mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-08-10 21:20:42 +08:00
Merge branch 'louislam:master' into italian-translation-update
This commit is contained in:
@@ -37,7 +37,7 @@
|
||||
<input id="name" v-model="notification.name" type="text" class="form-control" required>
|
||||
</div>
|
||||
|
||||
<Telegram v-if="notification.type === 'telegram'"></Telegram>
|
||||
<Telegram v-if="notification.type === 'telegram'" />
|
||||
|
||||
<!-- TODO: Convert all into vue components, but not an easy task. -->
|
||||
|
||||
@@ -65,49 +65,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="notification.type === 'smtp'">
|
||||
<div class="mb-3">
|
||||
<label for="hostname" class="form-label">Hostname</label>
|
||||
<input id="hostname" v-model="notification.smtpHost" type="text" class="form-control" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="port" class="form-label">Port</label>
|
||||
<input id="port" v-model="notification.smtpPort" type="number" class="form-control" required min="0" max="65535" step="1">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="form-check">
|
||||
<input id="secure" v-model="notification.smtpSecure" class="form-check-input" type="checkbox" value="">
|
||||
<label class="form-check-label" for="secure">
|
||||
Secure
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-text">
|
||||
Generally, true for 465, false for other ports.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="username" class="form-label">Username</label>
|
||||
<input id="username" v-model="notification.smtpUsername" type="text" class="form-control" autocomplete="false">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Password</label>
|
||||
<HiddenInput id="password" v-model="notification.smtpPassword" :required="true" autocomplete="one-time-code"></HiddenInput>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="from-email" class="form-label">From Email</label>
|
||||
<input id="from-email" v-model="notification.smtpFrom" type="email" class="form-control" required autocomplete="false">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="to-email" class="form-label">To Email</label>
|
||||
<input id="to-email" v-model="notification.smtpTo" type="email" class="form-control" required autocomplete="false">
|
||||
</div>
|
||||
</template>
|
||||
<SMTP v-if="notification.type === 'smtp'" />
|
||||
|
||||
<template v-if="notification.type === 'discord'">
|
||||
<div class="mb-3">
|
||||
@@ -437,8 +395,8 @@
|
||||
|
||||
<!-- DEPRECATED! Please create vue component in "./src/components/notifications/{notification name}.vue" -->
|
||||
|
||||
<div class="mb-3">
|
||||
<hr class="dropdown-divider">
|
||||
<div class="mb-3 mt-4">
|
||||
<hr class="dropdown-divider mb-4">
|
||||
|
||||
<div class="form-check form-switch">
|
||||
<input v-model="notification.isDefault" class="form-check-input" type="checkbox">
|
||||
@@ -456,6 +414,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button v-if="id" type="button" class="btn btn-danger" :disabled="processing" @click="deleteConfirm">
|
||||
{{ $t("Delete") }}
|
||||
@@ -481,19 +440,18 @@
|
||||
<script lang="ts">
|
||||
import { Modal } from "bootstrap"
|
||||
import { ucfirst } from "../util.ts"
|
||||
import axios from "axios";
|
||||
|
||||
import Confirm from "./Confirm.vue";
|
||||
import HiddenInput from "./HiddenInput.vue";
|
||||
import Telegram from "./notifications/Telegram.vue";
|
||||
import { useToast } from "vue-toastification"
|
||||
const toast = useToast();
|
||||
import SMTP from "./notifications/SMTP.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Confirm,
|
||||
HiddenInput,
|
||||
Telegram,
|
||||
SMTP,
|
||||
},
|
||||
props: {},
|
||||
data() {
|
||||
@@ -504,8 +462,8 @@ export default {
|
||||
notification: {
|
||||
name: "",
|
||||
type: null,
|
||||
gotifyPriority: 8,
|
||||
isDefault: false,
|
||||
// Do not set default value here, please scroll to show()
|
||||
},
|
||||
appriseInstalled: false,
|
||||
}
|
||||
@@ -558,9 +516,10 @@ export default {
|
||||
isDefault: false,
|
||||
}
|
||||
|
||||
// Default set to Telegram
|
||||
this.notification.type = "telegram"
|
||||
this.notification.gotifyPriority = 8
|
||||
// Set Default value here
|
||||
this.notification.type = "telegram";
|
||||
this.notification.gotifyPriority = 8;
|
||||
this.notification.smtpSecure = false;
|
||||
}
|
||||
|
||||
this.modal.show()
|
||||
|
75
src/components/notifications/SMTP.vue
Normal file
75
src/components/notifications/SMTP.vue
Normal file
@@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="hostname" class="form-label">{{ $t("Hostname") }}</label>
|
||||
<input id="hostname" v-model="$parent.notification.smtpHost" type="text" class="form-control" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="port" class="form-label">{{ $t("Port") }}</label>
|
||||
<input id="port" v-model="$parent.notification.smtpPort" type="number" class="form-control" required min="0" max="65535" step="1">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="secure" class="form-label">Secure</label>
|
||||
<select id="secure" v-model="$parent.notification.smtpSecure" class="form-select">
|
||||
<option :value="false">None / STARTTLS (25, 587)</option>
|
||||
<option :value="true">TLS (465)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="form-check">
|
||||
<input id="ignore-tls-error" v-model="$parent.notification.smtpIgnoreTLSError" class="form-check-input" type="checkbox" value="">
|
||||
<label class="form-check-label" for="ignore-tls-error">
|
||||
Ignore TLS Error
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="username" class="form-label">{{ $t("Username") }}</label>
|
||||
<input id="username" v-model="$parent.notification.smtpUsername" type="text" class="form-control" autocomplete="false">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">{{ $t("Password") }}</label>
|
||||
<HiddenInput id="password" v-model="$parent.notification.smtpPassword" :required="true" autocomplete="one-time-code"></HiddenInput>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="from-email" class="form-label">From Email</label>
|
||||
<input id="from-email" v-model="$parent.notification.smtpFrom" type="text" class="form-control" required autocomplete="false" placeholder=""Uptime Kuma" <example@kuma.pet>">
|
||||
<div class="form-text">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="to-email" class="form-label">To Email</label>
|
||||
<input id="to-email" v-model="$parent.notification.smtpTo" type="text" class="form-control" required autocomplete="false" placeholder="example2@kuma.pet, example3@kuma.pet">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="to-cc" class="form-label">CC</label>
|
||||
<input id="to-cc" v-model="$parent.notification.smtpCC" type="text" class="form-control" autocomplete="false">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="to-bcc" class="form-label">BCC</label>
|
||||
<input id="to-bcc" v-model="$parent.notification.smtpBCC" type="text" class="form-control" autocomplete="false">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HiddenInput from "../HiddenInput.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
HiddenInput,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
name: "smtp",
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
@@ -113,11 +113,19 @@ export default {
|
||||
"Create your admin account": "Erstelle dein Admin Konto",
|
||||
"Repeat Password": "Wiederhole das Passwort",
|
||||
"Resource Record Type": "Resource Record Type",
|
||||
"Import/Export Backup": "Import/Export Backup",
|
||||
"Export": "Export",
|
||||
"Import": "Import",
|
||||
respTime: "Antw. Zeit (ms)",
|
||||
notAvailableShort: "N/A",
|
||||
"Default enabled": "Standardmäßig aktiviert",
|
||||
"Also apply to existing monitors": "Auch für alle existierenden Monitore aktivieren",
|
||||
enableDefaultNotificationDescription: "Für jeden neuen Monitor wird diese Benachrichtigung standardmäßig aktiviert. Die Benachrichtigung kann weiterhin für jeden Monitor separat deaktiviert werden.",
|
||||
Create: "Erstellen",
|
||||
"Auto Get": "Auto Get"
|
||||
"Auto Get": "Auto Get",
|
||||
backupDescription: "Es können alle Monitore und alle Benachrichtigungen in einer JSON-Datei gesichert werden.",
|
||||
backupDescription2: "PS: Verlaufs- und Ereignisdaten sind nicht enthalten.",
|
||||
backupDescription3: "Sensible Daten wie Benachrichtigungstoken sind in der Exportdatei enthalten, bitte bewahre sie sorgfältig auf.",
|
||||
alertNoFile: "Bitte wähle eine Datei zum importieren aus.",
|
||||
alertWrongFileType: "Bitte wähle eine JSON Datei aus.",
|
||||
}
|
||||
|
@@ -111,6 +111,9 @@ export default {
|
||||
"Last Result": "Last Result",
|
||||
"Create your admin account": "Create your admin account",
|
||||
"Repeat Password": "Repeat Password",
|
||||
"Import/Export Backup": "Import/Export Backup",
|
||||
"Export": "Export",
|
||||
"Import": "Import",
|
||||
respTime: "Resp. Time (ms)",
|
||||
notAvailableShort: "N/A",
|
||||
"Default enabled": "Default enabled",
|
||||
@@ -119,5 +122,10 @@ export default {
|
||||
"Clear Data": "Clear Data",
|
||||
Events: "Events",
|
||||
Heartbeats: "Heartbeats",
|
||||
"Auto Get": "Auto Get"
|
||||
"Auto Get": "Auto Get",
|
||||
backupDescription: "You can backup all monitors and all notifications into a JSON file.",
|
||||
backupDescription2: "PS: History and event data is not included.",
|
||||
backupDescription3: "Sensitive data such as notification tokens is included in the export file, please keep it carefully.",
|
||||
alertNoFile: "Please select a file to import.",
|
||||
alertWrongFileType: "Please select a JSON file.",
|
||||
}
|
||||
|
@@ -254,6 +254,10 @@ export default {
|
||||
this.importantHeartbeatList = {}
|
||||
},
|
||||
|
||||
uploadBackup(uploadedJSON, callback) {
|
||||
socket.emit("uploadBackup", uploadedJSON, callback)
|
||||
},
|
||||
|
||||
clearEvents(monitorID, callback) {
|
||||
socket.emit("clearEvents", monitorID, callback)
|
||||
},
|
||||
|
@@ -120,6 +120,27 @@
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<h2 class="mt-5 mb-2">{{ $t("Import/Export Backup") }}</h2>
|
||||
|
||||
<p>
|
||||
{{ $t("backupDescription") }} <br />
|
||||
({{ $t("backupDescription2") }}) <br />
|
||||
</p>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<button class="btn btn-outline-primary" @click="downloadBackup">{{ $t("Export") }}</button>
|
||||
<button type="button" class="btn btn-outline-primary" :disabled="processing" @click="importBackup">
|
||||
<div v-if="processing" class="spinner-border spinner-border-sm me-1"></div>
|
||||
{{ $t("Import") }}
|
||||
</button>
|
||||
<input id="importBackup" type="file" class="form-control" accept="application/json">
|
||||
</div>
|
||||
<div v-if="importAlert" class="alert alert-danger mt-3" style="padding: 6px 16px;">
|
||||
{{ importAlert }}
|
||||
</div>
|
||||
|
||||
<p><strong>{{ $t("backupDescription3") }}</strong></p>
|
||||
|
||||
<h2 class="mt-5 mb-2">{{ $t("Advanced") }}</h2>
|
||||
|
||||
<div class="mb-3">
|
||||
@@ -275,6 +296,8 @@ export default {
|
||||
|
||||
},
|
||||
loaded: false,
|
||||
importAlert: null,
|
||||
processing: false,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -351,6 +374,52 @@ export default {
|
||||
this.$root.storage().removeItem("token");
|
||||
},
|
||||
|
||||
downloadBackup() {
|
||||
let time = dayjs().format("YYYY_MM_DD-hh_mm_ss");
|
||||
let fileName = `Uptime_Kuma_Backup_${time}.json`;
|
||||
let monitorList = Object.values(this.$root.monitorList);
|
||||
let exportData = {
|
||||
version: this.$root.info.version,
|
||||
notificationList: this.$root.notificationList,
|
||||
monitorList: monitorList,
|
||||
}
|
||||
exportData = JSON.stringify(exportData);
|
||||
let downloadItem = document.createElement("a");
|
||||
downloadItem.setAttribute("href", "data:application/json;charset=utf-8," + encodeURI(exportData));
|
||||
downloadItem.setAttribute("download", fileName);
|
||||
downloadItem.click();
|
||||
},
|
||||
|
||||
importBackup() {
|
||||
this.processing = true;
|
||||
let uploadItem = document.getElementById("importBackup").files;
|
||||
|
||||
if (uploadItem.length <= 0) {
|
||||
this.processing = false;
|
||||
return this.importAlert = this.$t("alertNoFile")
|
||||
}
|
||||
|
||||
if (uploadItem.item(0).type !== "application/json") {
|
||||
this.processing = false;
|
||||
return this.importAlert = this.$t("alertWrongFileType")
|
||||
}
|
||||
|
||||
let fileReader = new FileReader();
|
||||
fileReader.readAsText(uploadItem.item(0));
|
||||
|
||||
fileReader.onload = item => {
|
||||
this.$root.uploadBackup(item.target.result, (res) => {
|
||||
this.processing = false;
|
||||
|
||||
if (res.ok) {
|
||||
toast.success(res.msg);
|
||||
} else {
|
||||
toast.error(res.msg);
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
clearStatistics() {
|
||||
this.$root.clearStatistics((res) => {
|
||||
if (res.ok) {
|
||||
@@ -388,6 +457,18 @@ export default {
|
||||
.btn-check:hover + .btn-outline-primary {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
#importBackup {
|
||||
&::file-selector-button {
|
||||
color: $primary;
|
||||
background-color: $dark-bg;
|
||||
}
|
||||
|
||||
&:hover:not(:disabled):not([readonly])::file-selector-button {
|
||||
color: $dark-font-color2;
|
||||
background-color: $primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
footer {
|
||||
|
Reference in New Issue
Block a user