mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-08-10 19:13:25 +08:00
Merge remote-tracking branch 'origin/master' into feat/badge-generator-placeholders
# Conflicts: # package-lock.json # package.json
This commit is contained in:
@@ -69,6 +69,7 @@
|
||||
.multiselect__content-wrapper {
|
||||
background-color: $dark-bg2;
|
||||
border-color: $dark-border-color;
|
||||
z-index: 150;
|
||||
}
|
||||
|
||||
.multiselect--above .multiselect__content-wrapper {
|
||||
|
@@ -104,7 +104,7 @@ export default {
|
||||
// We must check if there are any elements in monitorList to
|
||||
// prevent undefined errors if it hasn't been loaded yet
|
||||
if (this.$parent.editMode && ignoreSendUrl && Object.keys(this.$root.monitorList).length) {
|
||||
return this.$root.monitorList[monitor.element.id].type === "http" || this.$root.monitorList[monitor.element.id].type === "keyword";
|
||||
return this.$root.monitorList[monitor.element.id].type === "http" || this.$root.monitorList[monitor.element.id].type === "keyword" || this.$root.monitorList[monitor.element.id].type === "json-query";
|
||||
}
|
||||
return monitor.element.sendUrl && monitor.element.url && monitor.element.url !== "https://" && !this.editMode;
|
||||
},
|
||||
|
@@ -164,6 +164,7 @@ export default {
|
||||
"SMSManager": "SmsManager (smsmanager.cz)",
|
||||
"WeCom": "WeCom (企业微信群机器人)",
|
||||
"ServerChan": "ServerChan (Server酱)",
|
||||
"smsc": "SMSC",
|
||||
};
|
||||
|
||||
// Sort by notification name
|
||||
|
@@ -1,102 +0,0 @@
|
||||
<template>
|
||||
<div v-if="! (!plugin.installed && plugin.local)" class="plugin-item pt-4 pb-2">
|
||||
<div class="info">
|
||||
<h5>{{ plugin.fullName }}</h5>
|
||||
<p class="description">
|
||||
{{ plugin.description }}
|
||||
</p>
|
||||
<span class="version">{{ $t("Version") }}: {{ plugin.version }} <a v-if="plugin.repo" :href="plugin.repo" target="_blank">Repo</a></span>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button v-if="status === 'installing'" class="btn btn-primary" disabled>{{ $t("installing") }}</button>
|
||||
<button v-else-if="status === 'uninstalling'" class="btn btn-danger" disabled>{{ $t("uninstalling") }}</button>
|
||||
<button v-else-if="plugin.installed || status === 'installed'" class="btn btn-danger" @click="deleteConfirm">{{ $t("uninstall") }}</button>
|
||||
<button v-else class="btn btn-primary" @click="install">{{ $t("install") }}</button>
|
||||
</div>
|
||||
|
||||
<Confirm ref="confirmDelete" btn-style="btn-danger" :yes-text="$t('Yes')" :no-text="$t('No')" @yes="uninstall">
|
||||
{{ $t("confirmUninstallPlugin") }}
|
||||
</Confirm>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Confirm from "./Confirm.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Confirm,
|
||||
},
|
||||
props: {
|
||||
plugin: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
status: "",
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Show confirmation for deleting a tag
|
||||
*/
|
||||
deleteConfirm() {
|
||||
this.$refs.confirmDelete.show();
|
||||
},
|
||||
|
||||
install() {
|
||||
this.status = "installing";
|
||||
|
||||
this.$root.getSocket().emit("installPlugin", this.plugin.repo, this.plugin.name, (res) => {
|
||||
if (res.ok) {
|
||||
this.status = "";
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
this.plugin.installed = true;
|
||||
} else {
|
||||
this.$root.toastRes(res);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
uninstall() {
|
||||
this.status = "uninstalling";
|
||||
|
||||
this.$root.getSocket().emit("uninstallPlugin", this.plugin.name, (res) => {
|
||||
if (res.ok) {
|
||||
this.status = "";
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
this.plugin.installed = false;
|
||||
} else {
|
||||
this.$root.toastRes(res);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../assets/vars.scss";
|
||||
|
||||
.plugin-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-content: center;
|
||||
align-items: center;
|
||||
|
||||
.info {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 13px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.version {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
</style>
|
@@ -150,7 +150,7 @@ export default {
|
||||
// We must check if there are any elements in monitorList to
|
||||
// prevent undefined errors if it hasn't been loaded yet
|
||||
if (this.$parent.editMode && ignoreSendUrl && Object.keys(this.$root.monitorList).length) {
|
||||
return this.$root.monitorList[monitor.element.id].type === "http" || this.$root.monitorList[monitor.element.id].type === "keyword";
|
||||
return this.$root.monitorList[monitor.element.id].type === "http" || this.$root.monitorList[monitor.element.id].type === "keyword" || this.$root.monitorList[monitor.element.id].type === "json-query";
|
||||
}
|
||||
return monitor.element.sendUrl && monitor.element.url && monitor.element.url !== "https://" && !this.editMode;
|
||||
},
|
||||
|
43
src/components/notifications/SMSC.vue
Normal file
43
src/components/notifications/SMSC.vue
Normal file
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="smsc-login" class="form-label">{{ $t("API Username") }}</label>
|
||||
<i18n-t tag="div" class="form-text" keypath="wayToGetClickSendSMSToken">
|
||||
<a href="https://smsc.kz/" target="_blank">{{ $t("here") }}</a>
|
||||
</i18n-t>
|
||||
<input id="smsc-login" v-model="$parent.notification.smscLogin" type="text" class="form-control" required>
|
||||
<label for="smsc-key" class="form-label">{{ $t("API Key") }}</label>
|
||||
<HiddenInput id="smsc-key" v-model="$parent.notification.smscPassword" :required="true" autocomplete="new-password"></HiddenInput>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<div class="form-text">
|
||||
{{ $t("checkPrice", ['СМСЦ']) }}
|
||||
<a href="https://smsc.kz/tariffs/" target="_blank">https://smsc.kz/tariffs/</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="smsc-to-number" class="form-label">{{ $t("Recipient Number") }}</label>
|
||||
<input id="smsc-to-number" v-model="$parent.notification.smscToNumber" type="text" minlength="11" class="form-control" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="smsc-sender-name" class="form-label">{{ $t("From Name/Number") }}</label>
|
||||
<input id="smsc-sender-name" v-model="$parent.notification.smscSenderName" type="text" minlength="1" maxlength="15" class="form-control">
|
||||
<div class="form-text">{{ $t("Leave blank to use a shared sender number.") }}</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="smsc-platform" class="form-label">{{ $t("smscTranslit") }}</label><span style="color: red;"><sup>*</sup></span>
|
||||
<select id="smsc-platform" v-model="$parent.notification.smscTranslit" class="form-select">
|
||||
<option value="0">{{ $t("Default") }}</option>
|
||||
<option value="1">Translit</option>
|
||||
<option value="2">MpaHc/Ium</option>
|
||||
</select>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import HiddenInput from "../HiddenInput.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
HiddenInput,
|
||||
},
|
||||
};
|
||||
</script>
|
@@ -5,7 +5,18 @@
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="twilio-auth-token" class="form-label">{{ $t("Auth Token") }}</label>
|
||||
<label for="twilio-apikey-token" class="form-label">{{ $t("Api Key (optional)") }}</label>
|
||||
<input id="twilio-apikey-token" v-model="$parent.notification.twilioApiKey" type="text" class="form-control">
|
||||
<div class="form-text">
|
||||
<p>
|
||||
The API key is optional but recommended. You can provide either Account SID and AuthToken
|
||||
from the may TwilioConsole page or Account SID and the pair of Api Key and Api Key secret
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="twilio-auth-token" class="form-label">{{ $t("Auth Token / Api Key Secret") }}</label>
|
||||
<input id="twilio-auth-token" v-model="$parent.notification.twilioAuthToken" type="text" class="form-control" required>
|
||||
</div>
|
||||
|
||||
|
@@ -12,61 +12,97 @@
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="webhook-content-type" class="form-label">{{
|
||||
$t("Content Type")
|
||||
<label for="webhook-request-body" class="form-label">{{
|
||||
$t("Request Body")
|
||||
}}</label>
|
||||
<select
|
||||
id="webhook-content-type"
|
||||
id="webhook-request-body"
|
||||
v-model="$parent.notification.webhookContentType"
|
||||
class="form-select"
|
||||
required
|
||||
>
|
||||
<option value="json">application/json</option>
|
||||
<option value="form-data">multipart/form-data</option>
|
||||
<option value="json">{{ $t("webhookBodyPresetOption", ["application/json"]) }}</option>
|
||||
<option value="form-data">{{ $t("webhookBodyPresetOption", ["multipart/form-data"]) }}</option>
|
||||
<option value="custom">{{ $t("webhookBodyCustomOption") }}</option>
|
||||
</select>
|
||||
|
||||
<div class="form-text">
|
||||
<p>{{ $t("webhookJsonDesc", ['"application/json"']) }}</p>
|
||||
<i18n-t tag="p" keypath="webhookFormDataDesc">
|
||||
<template #multipart>"multipart/form-data"</template>
|
||||
<template #decodeFunction>
|
||||
<strong>json_decode($_POST['data'])</strong>
|
||||
</template>
|
||||
</i18n-t>
|
||||
<div v-if="$parent.notification.webhookContentType == 'json'">
|
||||
<p>{{ $t("webhookJsonDesc", ['"application/json"']) }}</p>
|
||||
</div>
|
||||
<div v-if="$parent.notification.webhookContentType == 'form-data'">
|
||||
<i18n-t tag="p" keypath="webhookFormDataDesc">
|
||||
<template #multipart>multipart/form-data"</template>
|
||||
<template #decodeFunction>
|
||||
<strong>json_decode($_POST['data'])</strong>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</div>
|
||||
<div v-if="$parent.notification.webhookContentType == 'custom'">
|
||||
<i18n-t tag="p" keypath="webhookCustomBodyDesc">
|
||||
<template #msg>
|
||||
<code>msg</code>
|
||||
</template>
|
||||
<template #heartbeat>
|
||||
<code>heartbeatJSON</code>
|
||||
</template>
|
||||
<template #monitor>
|
||||
<code>monitorJSON</code>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<textarea
|
||||
v-if="$parent.notification.webhookContentType == 'custom'"
|
||||
id="customBody"
|
||||
v-model="$parent.notification.webhookCustomBody"
|
||||
class="form-control"
|
||||
:placeholder="customBodyPlaceholder"
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<i18n-t
|
||||
tag="label"
|
||||
class="form-label"
|
||||
for="additionalHeaders"
|
||||
keypath="webhookAdditionalHeadersTitle"
|
||||
>
|
||||
</i18n-t>
|
||||
<div class="form-check form-switch">
|
||||
<input v-model="showAdditionalHeadersField" class="form-check-input" type="checkbox">
|
||||
<label class="form-check-label">{{ $t("webhookAdditionalHeadersTitle") }}</label>
|
||||
</div>
|
||||
<div class="form-text">
|
||||
<i18n-t tag="p" keypath="webhookAdditionalHeadersDesc"> </i18n-t>
|
||||
</div>
|
||||
<textarea
|
||||
v-if="showAdditionalHeadersField"
|
||||
id="additionalHeaders"
|
||||
v-model="$parent.notification.webhookAdditionalHeaders"
|
||||
class="form-control"
|
||||
:placeholder="headersPlaceholder"
|
||||
></textarea>
|
||||
<div class="form-text">
|
||||
<i18n-t tag="p" keypath="webhookAdditionalHeadersDesc"> </i18n-t>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
showAdditionalHeadersField: this.$parent.notification.webhookAdditionalHeaders != null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
headersPlaceholder() {
|
||||
return this.$t("Example:", [
|
||||
`
|
||||
{
|
||||
"HeaderName": "HeaderValue"
|
||||
"Authorization": "Authorization Token"
|
||||
}`,
|
||||
]);
|
||||
},
|
||||
customBodyPlaceholder() {
|
||||
return `Example:
|
||||
{
|
||||
"Title": "Uptime Kuma Alert - {{ monitorJSON['name'] }}",
|
||||
"Body": "{{ msg }}"
|
||||
}`;
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@@ -4,6 +4,7 @@ import AliyunSMS from "./AliyunSms.vue";
|
||||
import Apprise from "./Apprise.vue";
|
||||
import Bark from "./Bark.vue";
|
||||
import ClickSendSMS from "./ClickSendSMS.vue";
|
||||
import SMSC from "./SMSC.vue";
|
||||
import DingDing from "./DingDing.vue";
|
||||
import Discord from "./Discord.vue";
|
||||
import Feishu from "./Feishu.vue";
|
||||
@@ -61,6 +62,7 @@ const NotificationFormList = {
|
||||
"apprise": Apprise,
|
||||
"Bark": Bark,
|
||||
"clicksendsms": ClickSendSMS,
|
||||
"smsc": SMSC,
|
||||
"DingDing": DingDing,
|
||||
"discord": Discord,
|
||||
"Feishu": Feishu,
|
||||
|
@@ -1,57 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="mt-3">{{ remotePluginListMsg }}</div>
|
||||
<PluginItem v-for="plugin in remotePluginList" :key="plugin.id" :plugin="plugin" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PluginItem from "../PluginItem.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
PluginItem
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
remotePluginList: [],
|
||||
remotePluginListMsg: "",
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
pluginList() {
|
||||
return this.$parent.$parent.$parent.pluginList;
|
||||
},
|
||||
settings() {
|
||||
return this.$parent.$parent.$parent.settings;
|
||||
},
|
||||
saveSettings() {
|
||||
return this.$parent.$parent.$parent.saveSettings;
|
||||
},
|
||||
settingsLoaded() {
|
||||
return this.$parent.$parent.$parent.settingsLoaded;
|
||||
},
|
||||
},
|
||||
|
||||
async mounted() {
|
||||
this.loadList();
|
||||
},
|
||||
|
||||
methods: {
|
||||
loadList() {
|
||||
this.remotePluginListMsg = this.$t("Loading") + "...";
|
||||
|
||||
this.$root.getSocket().emit("getPluginList", (res) => {
|
||||
if (res.ok) {
|
||||
this.remotePluginList = res.pluginList;
|
||||
this.remotePluginListMsg = "";
|
||||
} else {
|
||||
this.remotePluginListMsg = this.$t("loadingError") + " " + res.msg;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
@@ -51,6 +51,9 @@
|
||||
"Ping": "Ping",
|
||||
"Monitor Type": "Monitor Type",
|
||||
"Keyword": "Keyword",
|
||||
"Invert Keyword": "Invert Keyword",
|
||||
"Expected Value": "Expected Value",
|
||||
"Json Query": "Json Query",
|
||||
"Friendly Name": "Friendly Name",
|
||||
"URL": "URL",
|
||||
"Hostname": "Hostname",
|
||||
@@ -195,8 +198,11 @@
|
||||
"Content Type": "Content Type",
|
||||
"webhookJsonDesc": "{0} is good for any modern HTTP servers such as Express.js",
|
||||
"webhookFormDataDesc": "{multipart} is good for PHP. The JSON will need to be parsed with {decodeFunction}",
|
||||
"webhookCustomBodyDesc": "Define a custom HTTP Body for the request. Template variables {msg}, {heartbeat}, {monitor} are accepted.",
|
||||
"webhookAdditionalHeadersTitle": "Additional Headers",
|
||||
"webhookAdditionalHeadersDesc": "Sets additional headers sent with the webhook.",
|
||||
"webhookAdditionalHeadersDesc": "Sets additional headers sent with the webhook. Each header should be defined as a JSON key/value.",
|
||||
"webhookBodyPresetOption": "Preset - {0}",
|
||||
"webhookBodyCustomOption": "Custom Body",
|
||||
"Webhook URL": "Webhook URL",
|
||||
"Application Token": "Application Token",
|
||||
"Server URL": "Server URL",
|
||||
@@ -518,6 +524,8 @@
|
||||
"passwordNotMatchMsg": "The repeat password does not match.",
|
||||
"notificationDescription": "Notifications must be assigned to a monitor to function.",
|
||||
"keywordDescription": "Search keyword in plain HTML or JSON response. The search is case-sensitive.",
|
||||
"invertKeywordDescription": "Look for the keyword to be absent rather than present.",
|
||||
"jsonQueryDescription": "Do a json Query against the response and check for expected value (Return value will get converted into string for comparison). Check out <a href='https://jsonata.org/'>jsonata.org</a> for the documentation about the query language. A playground can be found <a href='https://try.jsonata.org/'>here</a>.",
|
||||
"backupDescription": "You can backup all monitors and notifications into a JSON file.",
|
||||
"backupDescription2": "Note: history and event data is not included.",
|
||||
"backupDescription3": "Sensitive data such as notification tokens are included in the export file; please store export securely.",
|
||||
@@ -725,7 +733,8 @@
|
||||
"ntfyAuthenticationMethod": "Authentication Method",
|
||||
"ntfyUsernameAndPassword": "Username and Password",
|
||||
"twilioAccountSID": "Account SID",
|
||||
"twilioAuthToken": "Auth Token",
|
||||
"twilioApiKey": "Api Key (optional)",
|
||||
"twilioAuthToken": "Auth Token / Api Key Secret",
|
||||
"twilioFromNumber": "From Number",
|
||||
"twilioToNumber": "To Number",
|
||||
"Monitor Setting": "{0}'s Monitor Setting",
|
||||
@@ -756,5 +765,6 @@
|
||||
"Group": "Group",
|
||||
"Monitor Group": "Monitor Group",
|
||||
"noGroupMonitorMsg": "Not Available. Create a Group Monitor First.",
|
||||
"Close": "Close"
|
||||
"Close": "Close",
|
||||
"Request Body": "Request Body"
|
||||
}
|
||||
|
@@ -30,6 +30,9 @@ export default {
|
||||
theme() {
|
||||
// As entry can be status page now, set forceStatusPageTheme to true to use status page theme
|
||||
if (this.forceStatusPageTheme) {
|
||||
if (this.statusPageTheme === "auto") {
|
||||
return this.system;
|
||||
}
|
||||
return this.statusPageTheme;
|
||||
}
|
||||
|
||||
|
@@ -8,12 +8,20 @@
|
||||
<Tag v-for="tag in monitor.tags" :key="tag.id" :item="tag" :size="'sm'" />
|
||||
</div>
|
||||
<p class="url">
|
||||
<a v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'mp-health' " :href="monitor.url" target="_blank" rel="noopener noreferrer">{{ filterPassword(monitor.url) }}</a>
|
||||
<a v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'json-query' || monitor.type === 'mp-health' " :href="monitor.url" target="_blank" rel="noopener noreferrer">{{ filterPassword(monitor.url) }}</a>
|
||||
<span v-if="monitor.type === 'port'">TCP Port {{ monitor.hostname }}:{{ monitor.port }}</span>
|
||||
<span v-if="monitor.type === 'ping'">Ping: {{ monitor.hostname }}</span>
|
||||
<span v-if="monitor.type === 'keyword'">
|
||||
<br>
|
||||
<span>{{ $t("Keyword") }}:</span> <span class="keyword">{{ monitor.keyword }}</span>
|
||||
<span>{{ $t("Keyword") }}: </span>
|
||||
<span class="keyword">{{ monitor.keyword }}</span>
|
||||
<span v-if="monitor.invertKeyword" alt="Inverted keyword" class="keyword-inverted"> ↧</span>
|
||||
</span>
|
||||
<span v-if="monitor.type === 'json-query'">
|
||||
<br>
|
||||
<span>{{ $t("Json Query") }}:</span> <span class="keyword">{{ monitor.jsonPath }}</span>
|
||||
<br>
|
||||
<span>{{ $t("Expected Value") }}:</span> <span class="keyword">{{ monitor.expectedValue }}</span>
|
||||
</span>
|
||||
<span v-if="monitor.type === 'dns'">[{{ monitor.dns_resolve_type }}] {{ monitor.hostname }}
|
||||
<br>
|
||||
@@ -432,7 +440,7 @@ export default {
|
||||
translationPrefix = "Avg. ";
|
||||
}
|
||||
|
||||
if (this.monitor.type === "http" || this.monitor.type === "keyword") {
|
||||
if (this.monitor.type === "http" || this.monitor.type === "keyword" || this.monitor.type === "json-query") {
|
||||
return this.$t(translationPrefix + "Response");
|
||||
}
|
||||
|
||||
@@ -582,6 +590,10 @@ table {
|
||||
color: $dark-font-color;
|
||||
}
|
||||
|
||||
.keyword-inverted {
|
||||
color: $dark-font-color;
|
||||
}
|
||||
|
||||
.dropdown-clear-data {
|
||||
ul {
|
||||
background-color: $dark-bg;
|
||||
|
@@ -27,6 +27,9 @@
|
||||
<option value="keyword">
|
||||
HTTP(s) - {{ $t("Keyword") }}
|
||||
</option>
|
||||
<option value="json-query">
|
||||
HTTP(s) - {{ $t("Json Query") }}
|
||||
</option>
|
||||
<option value="grpc-keyword">
|
||||
gRPC(s) - {{ $t("Keyword") }}
|
||||
</option>
|
||||
@@ -97,7 +100,7 @@
|
||||
</div>
|
||||
|
||||
<!-- URL -->
|
||||
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'real-browser' " class="my-3">
|
||||
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'json-query' || monitor.type === 'real-browser' " class="my-3">
|
||||
<label for="url" class="form-label">{{ $t("URL") }}</label>
|
||||
<input id="url" v-model="monitor.url" type="url" class="form-control" pattern="https?://.+" required>
|
||||
</div>
|
||||
@@ -127,6 +130,31 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Invert keyword -->
|
||||
<div v-if="monitor.type === 'keyword' || monitor.type === 'grpc-keyword'" class="my-3 form-check">
|
||||
<input id="invert-keyword" v-model="monitor.invertKeyword" class="form-check-input" type="checkbox">
|
||||
<label class="form-check-label" for="invert-keyword">
|
||||
{{ $t("Invert Keyword") }}
|
||||
</label>
|
||||
<div class="form-text">
|
||||
{{ $t("invertKeywordDescription") }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Json Query -->
|
||||
<div v-if="monitor.type === 'json-query'" class="my-3">
|
||||
<label for="jsonPath" class="form-label">{{ $t("Json Query") }}</label>
|
||||
<input id="jsonPath" v-model="monitor.jsonPath" type="text" class="form-control" required>
|
||||
|
||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||
<div class="form-text" v-html="$t('jsonQueryDescription')">
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<label for="expectedValue" class="form-label">{{ $t("Expected Value") }}</label>
|
||||
<input id="expectedValue" v-model="monitor.expectedValue" type="text" class="form-control" required>
|
||||
</div>
|
||||
|
||||
<!-- Game -->
|
||||
<!-- GameDig only -->
|
||||
<div v-if="monitor.type === 'gamedig'" class="my-3">
|
||||
@@ -356,7 +384,7 @@
|
||||
|
||||
<h2 v-if="monitor.type !== 'push'" class="mt-5 mb-2">{{ $t("Advanced") }}</h2>
|
||||
|
||||
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' " class="my-3 form-check">
|
||||
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'json-query' " class="my-3 form-check">
|
||||
<input id="expiry-notification" v-model="monitor.expiryNotification" class="form-check-input" type="checkbox">
|
||||
<label class="form-check-label" for="expiry-notification">
|
||||
{{ $t("Certificate Expiry Notification") }}
|
||||
@@ -365,7 +393,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' " class="my-3 form-check">
|
||||
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'json-query' " class="my-3 form-check">
|
||||
<input id="ignore-tls" v-model="monitor.ignoreTls" class="form-check-input" type="checkbox" value="">
|
||||
<label class="form-check-label" for="ignore-tls">
|
||||
{{ $t("ignoreTLSError") }}
|
||||
@@ -457,7 +485,7 @@
|
||||
</button>
|
||||
|
||||
<!-- Proxies -->
|
||||
<div v-if="monitor.type === 'http' || monitor.type === 'keyword'">
|
||||
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'json-query'">
|
||||
<h2 class="mt-5 mb-2">{{ $t("Proxy") }}</h2>
|
||||
<p v-if="$root.proxyList.length === 0">
|
||||
{{ $t("Not available, please setup.") }}
|
||||
@@ -485,7 +513,7 @@
|
||||
</div>
|
||||
|
||||
<!-- HTTP Options -->
|
||||
<template v-if="monitor.type === 'http' || monitor.type === 'keyword' ">
|
||||
<template v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'json-query' ">
|
||||
<h2 class="mt-5 mb-2">{{ $t("HTTP Options") }}</h2>
|
||||
|
||||
<!-- Method -->
|
||||
@@ -1107,7 +1135,7 @@ message HealthCheckResponse {
|
||||
this.monitor.body = JSON.stringify(JSON.parse(this.monitor.body), null, 4);
|
||||
}
|
||||
|
||||
if (this.monitor.type && this.monitor.type !== "http" && this.monitor.type !== "keyword") {
|
||||
if (this.monitor.type && this.monitor.type !== "http" && (this.monitor.type !== "keyword" || this.monitor.type !== "json-query")) {
|
||||
this.monitor.httpBodyEncoding = null;
|
||||
}
|
||||
|
||||
|
@@ -116,12 +116,6 @@ export default {
|
||||
backup: {
|
||||
title: this.$t("Backup"),
|
||||
},
|
||||
/*
|
||||
Hidden for now: Unfortunately, after some test, I found that Playwright requires a lot of libraries to be installed on the Linux host in order to start Chrome or Firefox.
|
||||
It will be hard to install, so I hide this feature for now. But it still accessible via URL: /settings/plugins.
|
||||
plugins: {
|
||||
title: this.$tc("plugin", 2),
|
||||
},*/
|
||||
about: {
|
||||
title: this.$t("About"),
|
||||
},
|
||||
|
@@ -325,7 +325,7 @@
|
||||
</p>
|
||||
|
||||
<div class="refresh-info mb-2">
|
||||
<div>{{ $t("Last Updated") }}: <date-time :value="lastUpdateTime" /></div>
|
||||
<div>{{ $t("Last Updated") }}: {{ lastUpdateTimeDisplay }}</div>
|
||||
<div>{{ $tc("statusPageRefreshIn", [ updateCountdownText]) }}</div>
|
||||
</div>
|
||||
</footer>
|
||||
@@ -360,7 +360,6 @@ import DOMPurify from "dompurify";
|
||||
import Confirm from "../components/Confirm.vue";
|
||||
import PublicGroupList from "../components/PublicGroupList.vue";
|
||||
import MaintenanceTime from "../components/MaintenanceTime.vue";
|
||||
import DateTime from "../components/Datetime.vue";
|
||||
import { getResBaseURL } from "../util-frontend";
|
||||
import { STATUS_PAGE_ALL_DOWN, STATUS_PAGE_ALL_UP, STATUS_PAGE_MAINTENANCE, STATUS_PAGE_PARTIAL_DOWN, UP, MAINTENANCE } from "../util.ts";
|
||||
import Tag from "../components/Tag.vue";
|
||||
@@ -386,7 +385,6 @@ export default {
|
||||
Confirm,
|
||||
PrismEditor,
|
||||
MaintenanceTime,
|
||||
DateTime,
|
||||
Tag,
|
||||
VueMultiselect
|
||||
},
|
||||
@@ -583,6 +581,10 @@ export default {
|
||||
return "";
|
||||
}
|
||||
},
|
||||
|
||||
lastUpdateTimeDisplay() {
|
||||
return this.$root.datetime(this.lastUpdateTime);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
||||
|
@@ -19,7 +19,6 @@ import DockerHosts from "./components/settings/Docker.vue";
|
||||
import MaintenanceDetails from "./pages/MaintenanceDetails.vue";
|
||||
import ManageMaintenance from "./pages/ManageMaintenance.vue";
|
||||
import APIKeys from "./components/settings/APIKeys.vue";
|
||||
import Plugins from "./components/settings/Plugins.vue";
|
||||
|
||||
// Settings - Sub Pages
|
||||
import Appearance from "./components/settings/Appearance.vue";
|
||||
@@ -130,10 +129,6 @@ const routes = [
|
||||
path: "backup",
|
||||
component: Backup,
|
||||
},
|
||||
{
|
||||
path: "plugins",
|
||||
component: Plugins,
|
||||
},
|
||||
{
|
||||
path: "about",
|
||||
component: About,
|
||||
|
Reference in New Issue
Block a user