Merge branch 'louislam:master' into bulgarian

This commit is contained in:
MrEddX
2022-08-14 07:20:37 +03:00
committed by GitHub
32 changed files with 1016 additions and 20 deletions

View File

@@ -0,0 +1,177 @@
<template>
<form @submit.prevent="submit">
<div ref="modal" class="modal fade" tabindex="-1" data-bs-backdrop="static">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 id="exampleModalLabel" class="modal-title">
{{ $t("Setup Docker Host") }}
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" />
</div>
<div class="modal-body">
<div class="mb-3">
<label for="docker-name" class="form-label">{{ $t("Friendly Name") }}</label>
<input id="docker-name" v-model="dockerHost.name" type="text" class="form-control" required>
</div>
<div class="mb-3">
<label for="docker-type" class="form-label">{{ $t("Connection Type") }}</label>
<select id="docker-type" v-model="dockerHost.dockerType" class="form-select">
<option v-for="type in connectionTypes" :key="type" :value="type">{{ $t(type) }}</option>
</select>
</div>
<div class="mb-3">
<label for="docker-daemon" class="form-label">{{ $t("Docker Daemon") }}</label>
<input id="docker-daemon" v-model="dockerHost.dockerDaemon" type="text" class="form-control" required>
<div class="form-text">
{{ $t("Examples") }}:
<ul>
<li>/var/run/docker.sock</li>
<li>tcp://localhost:2375</li>
</ul>
</div>
</div>
</div>
<div class="modal-footer">
<button v-if="id" type="button" class="btn btn-danger" :disabled="processing" @click="deleteConfirm">
{{ $t("Delete") }}
</button>
<button type="button" class="btn btn-warning" :disabled="processing" @click="test">
{{ $t("Test") }}
</button>
<button type="submit" class="btn btn-primary" :disabled="processing">
<div v-if="processing" class="spinner-border spinner-border-sm me-1"></div>
{{ $t("Save") }}
</button>
</div>
</div>
</div>
</div>
</form>
<Confirm ref="confirmDelete" btn-style="btn-danger" :yes-text="$t('Yes')" :no-text="$t('No')" @yes="deleteDockerHost">
{{ $t("deleteDockerHostMsg") }}
</Confirm>
</template>
<script lang="ts">
import { Modal } from "bootstrap";
import Confirm from "./Confirm.vue";
import { useToast } from "vue-toastification";
const toast = useToast();
export default {
components: {
Confirm,
},
props: {},
emits: [ "added" ],
data() {
return {
model: null,
processing: false,
id: null,
connectionTypes: [ "socket", "tcp" ],
dockerHost: {
name: "",
dockerDaemon: "",
dockerType: "",
// Do not set default value here, please scroll to show()
}
};
},
mounted() {
this.modal = new Modal(this.$refs.modal);
},
methods: {
deleteConfirm() {
this.modal.hide();
this.$refs.confirmDelete.show();
},
show(dockerHostID) {
if (dockerHostID) {
let found = false;
this.id = dockerHostID;
for (let n of this.$root.dockerHostList) {
if (n.id === dockerHostID) {
this.dockerHost = n;
found = true;
break;
}
}
if (!found) {
toast.error("Docker Host not found!");
}
} else {
this.id = null;
this.dockerHost = {
name: "",
dockerType: "socket",
dockerDaemon: "/var/run/docker.sock",
};
}
this.modal.show();
},
submit() {
this.processing = true;
this.$root.getSocket().emit("addDockerHost", this.dockerHost, this.id, (res) => {
this.$root.toastRes(res);
this.processing = false;
if (res.ok) {
this.modal.hide();
// Emit added event, doesn't emit edit.
if (! this.id) {
this.$emit("added", res.id);
}
}
});
},
test() {
this.processing = true;
this.$root.getSocket().emit("testDockerHost", this.dockerHost, (res) => {
this.$root.toastRes(res);
this.processing = false;
});
},
deleteDockerHost() {
this.processing = true;
this.$root.getSocket().emit("deleteDockerHost", this.id, (res) => {
this.$root.toastRes(res);
this.processing = false;
if (res.ok) {
this.modal.hide();
}
});
},
},
};
</script>
<style lang="scss" scoped>
@import "../assets/vars.scss";
.dark {
.modal-dialog .form-text, .modal-dialog p {
color: $dark-font-color;
}
}
</style>

View File

@@ -2,9 +2,6 @@
<div class="mb-3">
<label for="Bark Endpoint" class="form-label">{{ $t("Bark Endpoint") }}<span style="color: red;"><sup>*</sup></span></label>
<input id="Bark Endpoint" v-model="$parent.notification.barkEndpoint" type="text" class="form-control" required>
<div class="form-text">
<p><span style="color: red;"><sup>*</sup></span>{{ $t("Required") }}</p>
</div>
<i18n-t tag="div" keypath="wayToGetTeamsURL" class="form-text">
<a
href="https://github.com/Finb/Bark"
@@ -12,4 +9,45 @@
>{{ $t("here") }}</a>
</i18n-t>
</div>
<div class="mb-3">
<label for="Bark Group" class="form-label">{{ $t("Bark Group") }}</label>
<input id="Bark Group" v-model="$parent.notification.barkGroup" type="text" class="form-control" required>
</div>
<div class="mb-3">
<label for="Bark Sound" class="form-label">{{ $t("Bark Sound") }}</label>
<select id="Bark Sound" v-model="$parent.notification.barkSound" class="form-select" required>
<option value="alarm">alarm</option>
<option value="anticipate">anticipate</option>
<option value="bell">bell</option>
<option value="birdsong">birdsong</option>
<option value="bloom">bloom</option>
<option value="calypso">calypso</option>
<option value="chime">chime</option>
<option value="choo">choo</option>
<option value="descent">descent</option>
<option value="electronic">electronic</option>
<option value="fanfare">fanfare</option>
<option value="glass">glass</option>
<option value="gotosleep">gotosleep</option>
<option value="healthnotification">healthnotification</option>
<option value="horn">horn</option>
<option value="ladder">ladder</option>
<option value="mailsent">mailsent</option>
<option value="minuet">minuet</option>
<option value="multiwayinvitation">multiwayinvitation</option>
<option value="newmail">newmail</option>
<option value="newsflash">newsflash</option>
<option value="noir">noir</option>
<option value="paymentsuccess">paymentsuccess</option>
<option value="shake">shake</option>
<option value="sherwoodforest">sherwoodforest</option>
<option value="silence">silence</option>
<option value="spell">spell</option>
<option value="suspense">suspense</option>
<option value="telegraph">telegraph</option>
<option value="tiptoes">tiptoes</option>
<option value="typewriters">typewriters</option>
<option value="update">update</option>
</select>
</div>
</template>

View File

@@ -0,0 +1,40 @@
<template>
<div class="mb-3">
<label for="homeAssistantUrl" class="form-label">{{ $t("Home Assistant URL") }}<span style="color: red;"><sup>*</sup></span></label>
<input id="homeAssistantUrl" v-model="$parent.notification.homeAssistantUrl" type="url" class="form-control" required>
</div>
<div class="mb-3">
<label for="longLivedAccessToken" class="form-label">{{ $t("Long-Lived Access Token") }}<span style="color: red;"><sup>*</sup></span></label>
<input id="longLivedAccessToken" v-model="$parent.notification.longLivedAccessToken" type="text" class="form-control" required>
<div class="form-text">
<p>{{ $t("Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ") }}</p>
</div>
</div>
<div class="mb-3">
<label for="notificationService" class="form-label">{{ $t("Notification Service") }}</label>
<input id="notificationService" v-model="$parent.notification.notificationService" type="text" :placeholder="$t('default: notify all devices')" class="form-control">
<div class="form-text">
<p>{{ $t("A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.") }}</p>
<p>{{ $t("Automations can optionally be triggered in Home Assistant:") }}</p>
<p>
{{ $t("Trigger type:") }} <code>Event</code><br />
{{ $t("Event type:") }} <code>call_service</code><br />
{{ $t("Event data:") }}
</p>
<pre>domain: notify
service: mobile_app_my_phone # change to your device name
service_data:
title: Uptime Kuma
data:
status: 0 # 0=down 1=up
# name: Optional Uptime Kuma Monitor Name to filter by</pre>
<p>
{{ $t("Then choose an action, for example switch the scene to where an RGB light is red.") }}
</p>
</div>
</div>
</template>

View File

@@ -10,6 +10,7 @@ import Feishu from "./Feishu.vue";
import GoogleChat from "./GoogleChat.vue";
import Gorush from "./Gorush.vue";
import Gotify from "./Gotify.vue";
import HomeAssistant from "./HomeAssistant.vue";
import Line from "./Line.vue";
import LineNotify from "./LineNotify.vue";
import LunaSea from "./LunaSea.vue";
@@ -54,6 +55,7 @@ const NotificationFormList = {
"GoogleChat": GoogleChat,
"gorush": Gorush,
"gotify": Gotify,
"HomeAssistant": HomeAssistant,
"line": Line,
"LineNotify": LineNotify,
"lunasea": LunaSea,

View File

@@ -0,0 +1,48 @@
<template>
<div>
<div class="dockerHost-list my-4">
<p v-if="$root.dockerHostList.length === 0">
{{ $t("Not available, please setup.") }}
</p>
<ul class="list-group mb-3" style="border-radius: 1rem;">
<li v-for="(dockerHost, index) in $root.dockerHostList" :key="index" class="list-group-item">
{{ dockerHost.name }}<br>
<a href="#" @click="$refs.dockerHostDialog.show(dockerHost.id)">{{ $t("Edit") }}</a>
</li>
</ul>
<button class="btn btn-primary me-2" type="button" @click="$refs.dockerHostDialog.show()">
{{ $t("Setup Docker Host") }}
</button>
</div>
<DockerHostDialog ref="dockerHostDialog" />
</div>
</template>
<script>
import DockerHostDialog from "../../components/DockerHostDialog.vue";
export default {
components: {
DockerHostDialog,
},
data() {
return {};
},
computed: {
settings() {
return this.$parent.$parent.$parent.settings;
},
saveSettings() {
return this.$parent.$parent.$parent.saveSettings;
},
settingsLoaded() {
return this.$parent.$parent.$parent.settingsLoaded;
},
}
};
</script>

View File

@@ -165,7 +165,10 @@ export default {
Pink: "Pink",
"Search...": "Suchen...",
"Heartbeat Retry Interval": "Überprüfungsintervall",
"Resend Notification if Down X times consequently": "Benachrichtigung erneut senden, wenn Inaktiv X mal hintereinander",
retryCheckEverySecond: "Alle {0} Sekunden neu versuchen",
resendEveryXTimes: "Erneut versenden alle {0} mal",
resendDisabled: "Erneut versenden deaktiviert",
"Import Backup": "Backup importieren",
"Export Backup": "Backup exportieren",
"Avg. Ping": "Durchschn. Ping",

View File

@@ -2,6 +2,8 @@ export default {
languageName: "English",
checkEverySecond: "Check every {0} seconds",
retryCheckEverySecond: "Retry every {0} seconds",
resendEveryXTimes: "Resend every {0} times",
resendDisabled: "Resend disabled",
retriesDescription: "Maximum retries before the service is marked as down and a notification is sent",
ignoreTLSError: "Ignore TLS/SSL error for HTTPS websites",
upsideDownModeDescription: "Flip the status upside down. If the service is reachable, it is DOWN.",
@@ -72,6 +74,7 @@ export default {
"Heartbeat Interval": "Heartbeat Interval",
Retries: "Retries",
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
"Resend Notification if Down X times consequently": "Resend Notification if Down X times consequently",
Advanced: "Advanced",
"Upside Down Mode": "Upside Down Mode",
"Max. Redirects": "Max. Redirects",
@@ -408,6 +411,8 @@ export default {
SignName: "SignName",
"Sms template must contain parameters: ": "Sms template must contain parameters: ",
"Bark Endpoint": "Bark Endpoint",
"Bark Group": "Bark Group",
"Bark Sound": "Bark Sound",
WebHookUrl: "WebHookUrl",
SecretKey: "SecretKey",
"For safety, must use secret key": "For safety, must use secret key",
@@ -467,6 +472,7 @@ export default {
"Domain Name Expiry Notification": "Domain Name Expiry Notification",
Proxy: "Proxy",
"Date Created": "Date Created",
HomeAssistant: "Home Assistant",
onebotHttpAddress: "OneBot HTTP Address",
onebotMessageType: "OneBot Message Type",
onebotGroupMessage: "Group",
@@ -479,6 +485,12 @@ export default {
"Domain Names": "Domain Names",
signedInDisp: "Signed in as {0}",
signedInDispDisabled: "Auth Disabled.",
RadiusSecret: "Radius Secret",
RadiusSecretDescription: "Shared Secret between client and server",
RadiusCalledStationId: "Called Station Id",
RadiusCalledStationIdDescription: "Identifier of the called device",
RadiusCallingStationId: "Calling Station Id",
RadiusCallingStationIdDescription: "Identifier of the calling device",
"Certificate Expiry Notification": "Certificate Expiry Notification",
"API Username": "API Username",
"API Key": "API Key",
@@ -487,7 +499,7 @@ export default {
"Leave blank to use a shared sender number.": "Leave blank to use a shared sender number.",
"Octopush API Version": "Octopush API Version",
"Legacy Octopush-DM": "Legacy Octopush-DM",
"endpoint": "endpoint",
endpoint: "endpoint",
octopushAPIKey: "\"API key\" from HTTP API credentials in control panel",
octopushLogin: "\"Login\" from HTTP API credentials in control panel",
promosmsLogin: "API Login Name",
@@ -531,9 +543,19 @@ export default {
"Coming Soon": "Coming Soon",
wayToGetClickSendSMSToken: "You can get API Username and API Key from {0} .",
"Connection String": "Connection String",
"Query": "Query",
Query: "Query",
settingsCertificateExpiry: "TLS Certificate Expiry",
certificationExpiryDescription: "HTTPS Monitors trigger notification when TLS certificate expires in:",
"Setup Docker Host": "Setup Docker Host",
"Connection Type": "Connection Type",
"Docker Daemon": "Docker Daemon",
deleteDockerHostMsg: "Are you sure want to delete this docker host for all monitors?",
socket: "Socket",
tcp: "TCP / HTTP",
"Docker Container": "Docker Container",
"Container Name / ID": "Container Name / ID",
"Docker Host": "Docker Host",
"Docker Hosts": "Docker Hosts",
"ntfy Topic": "ntfy Topic",
"Domain": "Domain",
"Workstation": "Workstation",

View File

@@ -404,6 +404,8 @@ export default {
TemplateCode: "TemplateCode",
SignName: "SignName",
"Bark Endpoint": "Bark 接入点",
"Bark Group": "Bark 群组",
"Bark Sound": "Bark 铃声",
"Device Token": "Apple Device Token",
Platform: "平台",
iOS: "iOS",

View File

@@ -408,6 +408,8 @@ export default {
SignName: "SignName",
"Sms template must contain parameters: ": "Sms 範本必須包含參數:",
"Bark Endpoint": "Bark 端點",
"Bark Group": "Bark 群組",
"Bark Sound": "Bark 鈴聲",
WebHookUrl: "WebHookUrl",
SecretKey: "SecretKey",
"For safety, must use secret key": "為了安全起見,必須使用秘密金鑰",

View File

@@ -39,6 +39,7 @@ export default {
uptimeList: { },
tlsInfoList: {},
notificationList: [],
dockerHostList: [],
statusPageListLoaded: false,
statusPageList: [],
proxyList: [],
@@ -147,6 +148,10 @@ export default {
});
});
socket.on("dockerHostList", (data) => {
this.dockerHostList = data;
});
socket.on("heartbeat", (data) => {
if (! (data.monitorID in this.heartbeatList)) {
this.heartbeatList[data.monitorID] = [];

View File

@@ -27,6 +27,9 @@
<option value="dns">
DNS
</option>
<option value="docker">
{{ $t("Docker Container") }}
</option>
</optgroup>
<optgroup label="Passive Monitor Type">
@@ -48,6 +51,9 @@
<option value="postgres">
PostgreSQL
</option>
<option value="radius">
Radius
</option>
</optgroup>
</select>
</div>
@@ -84,8 +90,8 @@
</div>
<!-- Hostname -->
<!-- TCP Port / Ping / DNS / Steam / MQTT only -->
<div v-if="monitor.type === 'port' || monitor.type === 'ping' || monitor.type === 'dns' || monitor.type === 'steam' || monitor.type === 'mqtt'" class="my-3">
<!-- TCP Port / Ping / DNS / Steam / MQTT / Radius only -->
<div v-if="monitor.type === 'port' || monitor.type === 'ping' || monitor.type === 'dns' || monitor.type === 'steam' || monitor.type === 'mqtt' || monitor.type === 'radius'" class="my-3">
<label for="hostname" class="form-label">{{ $t("Hostname") }}</label>
<input id="hostname" v-model="monitor.hostname" type="text" class="form-control" :pattern="`${ipRegexPattern}|${hostnameRegexPattern}`" required>
</div>
@@ -141,6 +147,34 @@
</div>
</template>
<!-- Docker Container Name / ID -->
<!-- For Docker Type -->
<div v-if="monitor.type === 'docker'" class="my-3">
<label for="docker_container" class="form-label">{{ $t("Container Name / ID") }}</label>
<input id="docker_container" v-model="monitor.docker_container" type="text" class="form-control" required>
</div>
<!-- Docker Host -->
<!-- For Docker Type -->
<div v-if="monitor.type === 'docker'" class="my-3">
<h2 class="mb-2">{{ $t("Docker Host") }}</h2>
<p v-if="$root.dockerHostList.length === 0">
{{ $t("Not available, please setup.") }}
</p>
<div v-else class="mb-3">
<label for="docker-host" class="form-label">{{ $t("Docker Host") }}</label>
<select id="docket-host" v-model="monitor.docker_host" class="form-select">
<option v-for="host in $root.dockerHostList" :key="host.id" :value="host.id">{{ host.name }}</option>
</select>
<a href="#" @click="$refs.dockerHostDialog.show(monitor.docker_host)">{{ $t("Edit") }}</a>
</div>
<button class="btn btn-primary me-2" type="button" @click="$refs.dockerHostDialog.show()">
{{ $t("Setup Docker Host") }}
</button>
</div>
<!-- MQTT -->
<!-- For MQTT Type -->
<template v-if="monitor.type === 'mqtt'">
@@ -171,6 +205,36 @@
</div>
</template>
<template v-if="monitor.type === 'radius'">
<div class="my-3">
<label for="radius_username" class="form-label">Radius {{ $t("Username") }}</label>
<input id="radius_username" v-model="monitor.radiusUsername" type="text" class="form-control" required />
</div>
<div class="my-3">
<label for="radius_password" class="form-label">Radius {{ $t("Password") }}</label>
<input id="radius_password" v-model="monitor.radiusPassword" type="password" class="form-control" required />
</div>
<div class="my-3">
<label for="radius_secret" class="form-label">{{ $t("RadiusSecret") }}</label>
<input id="radius_secret" v-model="monitor.radiusSecret" type="password" class="form-control" required />
<div class="form-text"> {{ $t( "RadiusSecretDescription") }} </div>
</div>
<div class="my-3">
<label for="radius_called_station_id" class="form-label">{{ $t("RadiusCalledStationId") }}</label>
<input id="radius_called_station_id" v-model="monitor.radiusCalledStationId" type="text" class="form-control" required />
<div class="form-text"> {{ $t( "RadiusCalledStationIdDescription") }} </div>
</div>
<div class="my-3">
<label for="radius_calling_station_id" class="form-label">{{ $t("RadiusCallingStationId") }}</label>
<input id="radius_calling_station_id" v-model="monitor.radiusCallingStationId" type="text" class="form-control" required />
<div class="form-text"> {{ $t( "RadiusCallingStationIdDescription") }} </div>
</div>
</template>
<!-- SQL Server and PostgreSQL -->
<template v-if="monitor.type === 'sqlserver' || monitor.type === 'postgres'">
<div class="my-3">
@@ -211,6 +275,15 @@
<input id="retry-interval" v-model="monitor.retryInterval" type="number" class="form-control" required min="20" step="1">
</div>
<div class="my-3">
<label for="resend-interval" class="form-label">
{{ $t("Resend Notification if Down X times consequently") }}
<span v-if="monitor.resendInterval > 0">({{ $t("resendEveryXTimes", [ monitor.resendInterval ]) }})</span>
<span v-else>({{ $t("resendDisabled") }})</span>
</label>
<input id="resend-interval" v-model="monitor.resendInterval" type="number" class="form-control" required min="0" step="1">
</div>
<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">
@@ -424,6 +497,7 @@
</form>
<NotificationDialog ref="notificationDialog" @added="addedNotification" />
<DockerHostDialog ref="dockerHostDialog" @added="addedDockerHost" />
<ProxyDialog ref="proxyDialog" @added="addedProxy" />
</div>
</transition>
@@ -434,6 +508,7 @@ import VueMultiselect from "vue-multiselect";
import { useToast } from "vue-toastification";
import CopyableInput from "../components/CopyableInput.vue";
import NotificationDialog from "../components/NotificationDialog.vue";
import DockerHostDialog from "../components/DockerHostDialog.vue";
import ProxyDialog from "../components/ProxyDialog.vue";
import TagsManager from "../components/TagsManager.vue";
import { genSecret, isDev } from "../util.ts";
@@ -445,6 +520,7 @@ export default {
ProxyDialog,
CopyableInput,
NotificationDialog,
DockerHostDialog,
TagsManager,
VueMultiselect,
},
@@ -593,6 +669,7 @@ export default {
method: "GET",
interval: 60,
retryInterval: this.interval,
resendInterval: 0,
maxretries: 0,
notificationIDList: {},
ignoreTls: false,
@@ -602,6 +679,8 @@ export default {
accepted_statuscodes: [ "200-299" ],
dns_resolve_type: "A",
dns_resolve_server: "1.1.1.1",
docker_container: "",
docker_host: null,
proxyId: null,
mqttUsername: "",
mqttPassword: "",
@@ -729,6 +808,12 @@ export default {
addedProxy(id) {
this.monitor.proxyId = id;
},
// Added a Docker Host Event
// Enable it if the Docker Host is added in EditMonitor.vue
addedDockerHost(id) {
this.monitor.docker_host = id;
}
},
};
</script>

View File

@@ -89,6 +89,9 @@ export default {
"monitor-history": {
title: this.$t("Monitor History"),
},
"docker-hosts": {
title: this.$t("Docker Hosts"),
},
security: {
title: this.$t("Security"),
},

View File

@@ -25,6 +25,7 @@ const Security = () => import("./components/settings/Security.vue");
import Proxies from "./components/settings/Proxies.vue";
import Backup from "./components/settings/Backup.vue";
import About from "./components/settings/About.vue";
import DockerHosts from "./components/settings/Docker.vue";
const routes = [
{
@@ -95,6 +96,10 @@ const routes = [
path: "monitor-history",
component: MonitorHistory,
},
{
path: "docker-hosts",
component: DockerHosts,
},
{
path: "security",
component: Security,