Merge branch 'master' of git@github.com:lucasnz/uptime-kuma.git into ip-version

This commit is contained in:
lucas_nz 2023-10-15 09:07:56 +13:00
commit d79154ae1f
25 changed files with 48 additions and 544 deletions

View file

@ -65,8 +65,6 @@ log.debug("server", "Importing http-graceful-shutdown");
const gracefulShutdown = require("http-graceful-shutdown"); const gracefulShutdown = require("http-graceful-shutdown");
log.debug("server", "Importing prometheus-api-metrics"); log.debug("server", "Importing prometheus-api-metrics");
const prometheusAPIMetrics = require("prometheus-api-metrics"); const prometheusAPIMetrics = require("prometheus-api-metrics");
log.debug("server", "Importing compare-versions");
const compareVersions = require("compare-versions");
const { passwordStrength } = require("check-password-strength"); const { passwordStrength } = require("check-password-strength");
log.debug("server", "Importing 2FA Modules"); log.debug("server", "Importing 2FA Modules");
@ -91,9 +89,6 @@ log.debug("server", "Importing Notification");
const { Notification } = require("./notification"); const { Notification } = require("./notification");
Notification.init(); Notification.init();
log.debug("server", "Importing Proxy");
const { Proxy } = require("./proxy");
log.debug("server", "Importing Database"); log.debug("server", "Importing Database");
const Database = require("./database"); const Database = require("./database");
@ -1435,212 +1430,6 @@ let needSetup = false;
} }
}); });
socket.on("uploadBackup", async (uploadedJSON, importHandle, callback) => {
try {
checkLogin(socket);
let backupData = JSON.parse(uploadedJSON);
log.info("manage", `Importing Backup, User ID: ${socket.userID}, Version: ${backupData.version}`);
let notificationListData = backupData.notificationList;
let proxyListData = backupData.proxyList;
let monitorListData = backupData.monitorList;
let version17x = compareVersions.compare(backupData.version, "1.7.0", ">=");
// If the import option is "overwrite" it'll clear most of the tables, except "settings" and "user"
if (importHandle === "overwrite") {
// Stops every monitor first, so it doesn't execute any heartbeat while importing
for (let id in server.monitorList) {
let monitor = server.monitorList[id];
await monitor.stop();
}
await R.exec("DELETE FROM heartbeat");
await R.exec("DELETE FROM monitor_notification");
await R.exec("DELETE FROM monitor_tls_info");
await R.exec("DELETE FROM notification");
await R.exec("DELETE FROM monitor_tag");
await R.exec("DELETE FROM tag");
await R.exec("DELETE FROM monitor");
await R.exec("DELETE FROM proxy");
}
// Only starts importing if the backup file contains at least one notification
if (notificationListData.length >= 1) {
// Get every existing notification name and puts them in one simple string
let notificationNameList = await R.getAll("SELECT name FROM notification");
let notificationNameListString = JSON.stringify(notificationNameList);
for (let i = 0; i < notificationListData.length; i++) {
// Only starts importing the notification if the import option is "overwrite", "keep" or "skip" but the notification doesn't exists
if ((importHandle === "skip" && notificationNameListString.includes(notificationListData[i].name) === false) || importHandle === "keep" || importHandle === "overwrite") {
let notification = JSON.parse(notificationListData[i].config);
await Notification.save(notification, null, socket.userID);
}
}
}
// Only starts importing if the backup file contains at least one proxy
if (proxyListData && proxyListData.length >= 1) {
const proxies = await R.findAll("proxy");
// Loop over proxy list and save proxies
for (const proxy of proxyListData) {
const exists = proxies.find(item => item.id === proxy.id);
// Do not process when proxy already exists in import handle is skip and keep
if ([ "skip", "keep" ].includes(importHandle) && !exists) {
return;
}
// Save proxy as new entry if exists update exists one
await Proxy.save(proxy, exists ? proxy.id : undefined, proxy.userId);
}
}
// Only starts importing if the backup file contains at least one monitor
if (monitorListData.length >= 1) {
// Get every existing monitor name and puts them in one simple string
let monitorNameList = await R.getAll("SELECT name FROM monitor");
let monitorNameListString = JSON.stringify(monitorNameList);
for (let i = 0; i < monitorListData.length; i++) {
// Only starts importing the monitor if the import option is "overwrite", "keep" or "skip" but the notification doesn't exists
if ((importHandle === "skip" && monitorNameListString.includes(monitorListData[i].name) === false) || importHandle === "keep" || importHandle === "overwrite") {
// Define in here every new variable for monitors which where implemented after the first version of the Import/Export function (1.6.0)
// --- Start ---
// Define default values
let retryInterval = 0;
let timeout = monitorListData[i].timeout || (monitorListData[i].interval * 0.8); // fallback to old value
/*
Only replace the default value with the backup file data for the specific version, where it appears the first time
More information about that where "let version" will be defined
*/
if (version17x) {
retryInterval = monitorListData[i].retryInterval;
}
// --- End ---
let monitor = {
// Define the new variable from earlier here
name: monitorListData[i].name,
description: monitorListData[i].description,
type: monitorListData[i].type,
url: monitorListData[i].url,
method: monitorListData[i].method || "GET",
body: monitorListData[i].body,
headers: monitorListData[i].headers,
authMethod: monitorListData[i].authMethod,
basic_auth_user: monitorListData[i].basic_auth_user,
basic_auth_pass: monitorListData[i].basic_auth_pass,
authWorkstation: monitorListData[i].authWorkstation,
authDomain: monitorListData[i].authDomain,
timeout,
interval: monitorListData[i].interval,
retryInterval: retryInterval,
resendInterval: monitorListData[i].resendInterval || 0,
hostname: monitorListData[i].hostname,
maxretries: monitorListData[i].maxretries,
port: monitorListData[i].port,
keyword: monitorListData[i].keyword,
invertKeyword: monitorListData[i].invertKeyword,
ignoreTls: monitorListData[i].ignoreTls,
upsideDown: monitorListData[i].upsideDown,
maxredirects: monitorListData[i].maxredirects,
accepted_statuscodes: monitorListData[i].accepted_statuscodes,
dns_resolve_type: monitorListData[i].dns_resolve_type,
dns_resolve_server: monitorListData[i].dns_resolve_server,
notificationIDList: monitorListData[i].notificationIDList,
proxy_id: monitorListData[i].proxy_id || null,
};
if (monitorListData[i].pushToken) {
monitor.pushToken = monitorListData[i].pushToken;
}
let bean = R.dispense("monitor");
let notificationIDList = monitor.notificationIDList;
delete monitor.notificationIDList;
monitor.accepted_statuscodes_json = JSON.stringify(monitor.accepted_statuscodes);
delete monitor.accepted_statuscodes;
bean.import(monitor);
bean.user_id = socket.userID;
await R.store(bean);
// Only for backup files with the version 1.7.0 or higher, since there was the tag feature implemented
if (version17x) {
// Only import if the specific monitor has tags assigned
for (const oldTag of monitorListData[i].tags) {
// Check if tag already exists and get data ->
let tag = await R.findOne("tag", " name = ?", [
oldTag.name,
]);
let tagId;
if (!tag) {
// -> If it doesn't exist, create new tag from backup file
let beanTag = R.dispense("tag");
beanTag.name = oldTag.name;
beanTag.color = oldTag.color;
await R.store(beanTag);
tagId = beanTag.id;
} else {
// -> If it already exist, set tagId to value from database
tagId = tag.id;
}
// Assign the new created tag to the monitor
await R.exec("INSERT INTO monitor_tag (tag_id, monitor_id, value) VALUES (?, ?, ?)", [
tagId,
bean.id,
oldTag.value,
]);
}
}
await updateMonitorNotification(bean.id, notificationIDList);
// If monitor was active start it immediately, otherwise pause it
if (monitorListData[i].active === 1) {
await startMonitor(socket.userID, bean.id);
} else {
await pauseMonitor(socket.userID, bean.id);
}
}
}
await sendNotificationList(socket);
await server.sendMonitorList(socket);
}
callback({
ok: true,
msg: "successBackupRestored",
msgi18n: true,
});
} catch (e) {
callback({
ok: false,
msg: e.message,
});
}
});
socket.on("clearEvents", async (monitorID, callback) => { socket.on("clearEvents", async (monitorID, callback) => {
try { try {
checkLogin(socket); checkLogin(socket);

View file

@ -92,11 +92,9 @@
<script lang="ts"> <script lang="ts">
import { Modal } from "bootstrap"; import { Modal } from "bootstrap";
import { useToast } from "vue-toastification";
import dayjs from "dayjs"; import dayjs from "dayjs";
import Datepicker from "@vuepic/vue-datepicker"; import Datepicker from "@vuepic/vue-datepicker";
import CopyableInput from "./CopyableInput.vue"; import CopyableInput from "./CopyableInput.vue";
const toast = useToast();
export default { export default {
components: { components: {
@ -158,7 +156,7 @@ export default {
this.keymodal.show(); this.keymodal.show();
this.clearForm(); this.clearForm();
} else { } else {
toast.error(res.msg); this.$root.toastError(res.msg);
} }
}); });
}, },

View file

@ -62,8 +62,6 @@
<script lang="ts"> <script lang="ts">
import { Modal } from "bootstrap"; import { Modal } from "bootstrap";
import Confirm from "./Confirm.vue"; import Confirm from "./Confirm.vue";
import { useToast } from "vue-toastification";
const toast = useToast();
export default { export default {
components: { components: {
@ -120,7 +118,7 @@ export default {
} }
if (!found) { if (!found) {
toast.error("Docker Host not found!"); this.$root.toastError("Docker Host not found!");
} }
} else { } else {

View file

@ -35,7 +35,7 @@
</button> </button>
<div v-if="res && !res.ok" class="alert alert-danger mt-3" role="alert"> <div v-if="res && !res.ok" class="alert alert-danger mt-3" role="alert">
{{ res.msg }} {{ $t(res.msg) }}
</div> </div>
</form> </form>
</div> </div>

View file

@ -21,11 +21,8 @@ import { BarController, BarElement, Chart, Filler, LinearScale, LineController,
import "chartjs-adapter-dayjs-4"; import "chartjs-adapter-dayjs-4";
import dayjs from "dayjs"; import dayjs from "dayjs";
import { Line } from "vue-chartjs"; import { Line } from "vue-chartjs";
import { useToast } from "vue-toastification";
import { DOWN, PENDING, MAINTENANCE, log } from "../util.ts"; import { DOWN, PENDING, MAINTENANCE, log } from "../util.ts";
const toast = useToast();
Chart.register(LineController, BarController, LineElement, PointElement, TimeScale, BarElement, LinearScale, Tooltip, Filler); Chart.register(LineController, BarController, LineElement, PointElement, TimeScale, BarElement, LinearScale, Tooltip, Filler);
export default { export default {
@ -231,7 +228,7 @@ export default {
this.$root.getMonitorBeats(this.monitorId, newPeriod, (res) => { this.$root.getMonitorBeats(this.monitorId, newPeriod, (res) => {
if (!res.ok) { if (!res.ok) {
toast.error(res.msg); this.$root.toastError(res.msg);
} else { } else {
this.heartbeatList = res.data; this.heartbeatList = res.data;
this.$root.storage()[`chart-period-${this.monitorId}`] = newPeriod; this.$root.storage()[`chart-period-${this.monitorId}`] = newPeriod;

View file

@ -123,9 +123,7 @@ import Confirm from "./Confirm.vue";
import Tag from "./Tag.vue"; import Tag from "./Tag.vue";
import VueMultiselect from "vue-multiselect"; import VueMultiselect from "vue-multiselect";
import { colorOptions } from "../util-frontend"; import { colorOptions } from "../util-frontend";
import { useToast } from "vue-toastification";
import { getMonitorRelativeURL } from "../util.ts"; import { getMonitorRelativeURL } from "../util.ts";
const toast = useToast();
export default { export default {
components: { components: {
@ -320,7 +318,7 @@ export default {
for (let addId of this.addingMonitor) { for (let addId of this.addingMonitor) {
await this.addMonitorTagAsync(this.tag.id, addId, "").then((res) => { await this.addMonitorTagAsync(this.tag.id, addId, "").then((res) => {
if (!res.ok) { if (!res.ok) {
toast.error(res.msg); this.$root.toastError(res.msg);
editResult = false; editResult = false;
} }
}); });
@ -330,7 +328,7 @@ export default {
this.monitors.find(monitor => monitor.id === removeId)?.tags.forEach(async (monitorTag) => { this.monitors.find(monitor => monitor.id === removeId)?.tags.forEach(async (monitorTag) => {
await this.deleteMonitorTagAsync(this.tag.id, removeId, monitorTag.value).then((res) => { await this.deleteMonitorTagAsync(this.tag.id, removeId, monitorTag.value).then((res) => {
if (!res.ok) { if (!res.ok) {
toast.error(res.msg); this.$root.toastError(res.msg);
editResult = false; editResult = false;
} }
}); });

View file

@ -129,10 +129,8 @@
<script> <script>
import { Modal } from "bootstrap"; import { Modal } from "bootstrap";
import VueMultiselect from "vue-multiselect"; import VueMultiselect from "vue-multiselect";
import { useToast } from "vue-toastification";
import { colorOptions } from "../util-frontend"; import { colorOptions } from "../util-frontend";
import Tag from "../components/Tag.vue"; import Tag from "../components/Tag.vue";
const toast = useToast();
/** /**
* @typedef Tag * @typedef Tag
@ -262,7 +260,7 @@ export default {
if (res.ok) { if (res.ok) {
this.existingTags = res.tags; this.existingTags = res.tags;
} else { } else {
toast.error(res.msg); this.$root.toastError(res.msg);
} }
}); });
}, },
@ -399,7 +397,7 @@ export default {
let newTagResult; let newTagResult;
await this.addTagAsync(newTag).then((res) => { await this.addTagAsync(newTag).then((res) => {
if (!res.ok) { if (!res.ok) {
toast.error(res.msg); this.$root.toastError(res.msg);
newTagResult = false; newTagResult = false;
} }
newTagResult = res.tag; newTagResult = res.tag;
@ -424,7 +422,7 @@ export default {
// Assign tag to monitor // Assign tag to monitor
await this.addMonitorTagAsync(tagId, monitorId, newTag.value).then((res) => { await this.addMonitorTagAsync(tagId, monitorId, newTag.value).then((res) => {
if (!res.ok) { if (!res.ok) {
toast.error(res.msg); this.$root.toastError(res.msg);
newMonitorTagResult = false; newMonitorTagResult = false;
} }
newMonitorTagResult = true; newMonitorTagResult = true;
@ -440,7 +438,7 @@ export default {
let deleteMonitorTagResult; let deleteMonitorTagResult;
await this.deleteMonitorTagAsync(deleteTag.tag_id, deleteTag.monitor_id, deleteTag.value).then((res) => { await this.deleteMonitorTagAsync(deleteTag.tag_id, deleteTag.monitor_id, deleteTag.value).then((res) => {
if (!res.ok) { if (!res.ok) {
toast.error(res.msg); this.$root.toastError(res.msg);
deleteMonitorTagResult = false; deleteMonitorTagResult = false;
} }
deleteMonitorTagResult = true; deleteMonitorTagResult = true;

View file

@ -76,8 +76,6 @@
import { Modal } from "bootstrap"; import { Modal } from "bootstrap";
import Confirm from "./Confirm.vue"; import Confirm from "./Confirm.vue";
import VueQrcode from "vue-qrcode"; import VueQrcode from "vue-qrcode";
import { useToast } from "vue-toastification";
const toast = useToast();
export default { export default {
components: { components: {
@ -138,7 +136,7 @@ export default {
if (res.ok) { if (res.ok) {
this.uri = res.uri; this.uri = res.uri;
} else { } else {
toast.error(res.msg); this.$root.toastError(res.msg);
} }
}); });
}, },
@ -159,7 +157,7 @@ export default {
this.currentPassword = ""; this.currentPassword = "";
this.modal.hide(); this.modal.hide();
} else { } else {
toast.error(res.msg); this.$root.toastError(res.msg);
} }
}); });
}, },
@ -180,7 +178,7 @@ export default {
this.currentPassword = ""; this.currentPassword = "";
this.modal.hide(); this.modal.hide();
} else { } else {
toast.error(res.msg); this.$root.toastError(res.msg);
} }
}); });
}, },
@ -194,7 +192,7 @@ export default {
if (res.ok) { if (res.ok) {
this.tokenValid = res.valid; this.tokenValid = res.valid;
} else { } else {
toast.error(res.msg); this.$root.toastError(res.msg);
} }
}); });
}, },
@ -208,7 +206,7 @@ export default {
if (res.ok) { if (res.ok) {
this.twoFAStatus = res.status; this.twoFAStatus = res.status;
} else { } else {
toast.error(res.msg); this.$root.toastError(res.msg);
} }
}); });
}, },

View file

@ -58,8 +58,6 @@
<script> <script>
import HiddenInput from "../HiddenInput.vue"; import HiddenInput from "../HiddenInput.vue";
import axios from "axios"; import axios from "axios";
import { useToast } from "vue-toastification";
const toast = useToast();
export default { export default {
components: { components: {
@ -110,7 +108,7 @@ export default {
} }
} catch (error) { } catch (error) {
toast.error(error.message); this.$root.toastError(error.message);
} }
}, },

View file

@ -72,8 +72,6 @@
<script> <script>
import APIKeyDialog from "../../components/APIKeyDialog.vue"; import APIKeyDialog from "../../components/APIKeyDialog.vue";
import Confirm from "../Confirm.vue"; import Confirm from "../Confirm.vue";
import { useToast } from "vue-toastification";
const toast = useToast();
export default { export default {
components: { components: {
@ -109,11 +107,7 @@ export default {
*/ */
deleteKey() { deleteKey() {
this.$root.deleteAPIKey(this.selectedKeyID, (res) => { this.$root.deleteAPIKey(this.selectedKeyID, (res) => {
if (res.ok) { this.$root.toastRes(res);
toast.success(res.msg);
} else {
toast.error(res.msg);
}
}); });
}, },

View file

@ -1,232 +0,0 @@
<template>
<div>
<div class="my-4">
<div class="alert alert-warning" role="alert" style="border-radius: 15px;">
{{ $t("backupOutdatedWarning") }}<br />
<br />
{{ $t("backupRecommend") }}
</div>
<h4 class="mt-4 mb-2">{{ $t("Export Backup") }}</h4>
<p>
{{ $t("backupDescription") }} <br />
({{ $t("backupDescription2") }}) <br />
</p>
<div class="mb-2">
<button class="btn btn-primary" @click="downloadBackup">
{{ $t("Export") }}
</button>
</div>
<p>
<strong>{{ $t("backupDescription3") }}</strong>
</p>
</div>
<div class="my-4">
<h4 class="mt-4 mb-2">{{ $t("Import Backup") }}</h4>
<label class="form-label">{{ $t("Options") }}:</label>
<br />
<div class="form-check form-check-inline">
<input
id="radioKeep"
v-model="importHandle"
class="form-check-input"
type="radio"
name="radioImportHandle"
value="keep"
/>
<label class="form-check-label" for="radioKeep">
{{ $t("Keep both") }}
</label>
</div>
<div class="form-check form-check-inline">
<input
id="radioSkip"
v-model="importHandle"
class="form-check-input"
type="radio"
name="radioImportHandle"
value="skip"
/>
<label class="form-check-label" for="radioSkip">
{{ $t("Skip existing") }}
</label>
</div>
<div class="form-check form-check-inline">
<input
id="radioOverwrite"
v-model="importHandle"
class="form-check-input"
type="radio"
name="radioImportHandle"
value="overwrite"
/>
<label class="form-check-label" for="radioOverwrite">
{{ $t("Overwrite") }}
</label>
</div>
<div class="form-text mb-2">
{{ $t("importHandleDescription") }}
</div>
<div class="mb-2">
<input
id="import-backend"
type="file"
class="form-control"
accept="application/json"
/>
</div>
<div class="input-group mb-2 justify-content-end">
<button
type="button"
class="btn btn-outline-primary"
:disabled="processing"
@click="confirmImport"
>
<div
v-if="processing"
class="spinner-border spinner-border-sm me-1"
></div>
{{ $t("Import") }}
</button>
</div>
<div
v-if="importAlert"
class="alert alert-danger mt-3"
style="padding: 6px 16px;"
>
{{ importAlert }}
</div>
</div>
<Confirm
ref="confirmImport"
btn-style="btn-danger"
:yes-text="$t('Yes')"
:no-text="$t('No')"
@yes="importBackup"
>
{{ $t("confirmImportMsg") }}
</Confirm>
</div>
</template>
<script>
import Confirm from "../../components/Confirm.vue";
import dayjs from "dayjs";
import { useToast } from "vue-toastification";
const toast = useToast();
export default {
components: {
Confirm,
},
data() {
return {
processing: false,
importHandle: "skip",
importAlert: null,
};
},
methods: {
/**
* Show the confimation dialog confirming the configuration
* be imported
* @returns {void}
*/
confirmImport() {
this.$refs.confirmImport.show();
},
/**
* Download a backup of the configuration
* @returns {void}
*/
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, null, 4);
let downloadItem = document.createElement("a");
downloadItem.setAttribute(
"href",
"data:application/json;charset=utf-8," +
encodeURIComponent(exportData)
);
downloadItem.setAttribute("download", fileName);
downloadItem.click();
},
/**
* Import the specified backup file
* @returns {string|void} Error message
*/
importBackup() {
this.processing = true;
let uploadItem = document.getElementById("import-backend").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,
this.importHandle,
(res) => {
this.processing = false;
if (res.ok) {
toast.success(res.msg);
} else {
toast.error(res.msg);
}
}
);
};
},
},
};
</script>
<style lang="scss" scoped>
@import "../../assets/vars.scss";
.dark {
#import-backend {
&::file-selector-button {
color: $primary;
background-color: $dark-bg;
}
&:hover:not(:disabled):not([readonly])::file-selector-button {
color: $dark-font-color2;
background-color: $primary;
}
}
}
</style>

View file

@ -57,9 +57,6 @@
<script> <script>
import Confirm from "../../components/Confirm.vue"; import Confirm from "../../components/Confirm.vue";
import { log } from "../../util.ts"; import { log } from "../../util.ts";
import { useToast } from "vue-toastification";
const toast = useToast();
export default { export default {
components: { components: {
@ -118,7 +115,7 @@ export default {
this.$root.getSocket().emit("shrinkDatabase", (res) => { this.$root.getSocket().emit("shrinkDatabase", (res) => {
if (res.ok) { if (res.ok) {
this.loadDatabaseSize(); this.loadDatabaseSize();
toast.success("Done"); this.$root.toastSuccess("Done");
} else { } else {
log.debug("monitorhistory", res); log.debug("monitorhistory", res);
} }
@ -142,7 +139,7 @@ export default {
if (res.ok) { if (res.ok) {
this.$router.go(); this.$router.go();
} else { } else {
toast.error(res.msg); this.$root.toastError(res.msg);
} }
}); });
}, },

View file

@ -28,11 +28,9 @@
</template> </template>
<script> <script>
import { useToast } from "vue-toastification";
import TagEditDialog from "../../components/TagEditDialog.vue"; import TagEditDialog from "../../components/TagEditDialog.vue";
import Tag from "../Tag.vue"; import Tag from "../Tag.vue";
import Confirm from "../Confirm.vue"; import Confirm from "../Confirm.vue";
const toast = useToast();
export default { export default {
components: { components: {
@ -86,7 +84,7 @@ export default {
if (res.ok) { if (res.ok) {
this.tagsList = res.tags; this.tagsList = res.tags;
} else { } else {
toast.error(res.msg); this.$root.toastError(res.msg);
} }
}); });
}, },

View file

@ -342,7 +342,7 @@ export default {
* @returns {void} * @returns {void}
*/ */
toastSuccess(msg) { toastSuccess(msg) {
toast.success(msg); toast.success(this.$t(msg));
}, },
/** /**
@ -351,7 +351,7 @@ export default {
* @returns {void} * @returns {void}
*/ */
toastError(msg) { toastError(msg) {
toast.error(msg); toast.error(this.$t(msg));
}, },
/** /**

View file

@ -66,7 +66,7 @@ export default {
} else { } else {
if (res.msg.includes("UNIQUE constraint")) { if (res.msg.includes("UNIQUE constraint")) {
this.$root.toastError(this.$t("The slug is already taken. Please choose another slug.")); this.$root.toastError("The slug is already taken. Please choose another slug.");
} else { } else {
this.$root.toastRes(res); this.$root.toastRes(res);
} }

View file

@ -437,7 +437,7 @@ export default {
*/ */
testNotification() { testNotification() {
this.$root.getSocket().emit("testNotification", this.monitor.id); this.$root.getSocket().emit("testNotification", this.monitor.id);
toast.success("Test notification is requested."); this.$root.toastSuccess("Test notification is requested.");
}, },
/** /**
@ -498,11 +498,9 @@ export default {
*/ */
deleteMonitor() { deleteMonitor() {
this.$root.deleteMonitor(this.monitor.id, (res) => { this.$root.deleteMonitor(this.monitor.id, (res) => {
this.$root.toastRes(res);
if (res.ok) { if (res.ok) {
toast.success(res.msg);
this.$router.push("/dashboard"); this.$router.push("/dashboard");
} else {
toast.error(res.msg);
} }
}); });
}, },

View file

@ -246,14 +246,11 @@
</template> </template>
<script> <script>
import { useToast } from "vue-toastification";
import VueMultiselect from "vue-multiselect"; import VueMultiselect from "vue-multiselect";
import Datepicker from "@vuepic/vue-datepicker"; import Datepicker from "@vuepic/vue-datepicker";
import { timezoneList } from "../util-frontend"; import { timezoneList } from "../util-frontend";
import cronstrue from "cronstrue/i18n"; import cronstrue from "cronstrue/i18n";
const toast = useToast();
export default { export default {
components: { components: {
VueMultiselect, VueMultiselect,
@ -457,7 +454,7 @@ export default {
this.affectedMonitors.push(this.affectedMonitorsOptions.find(item => item.id === monitor.id)); this.affectedMonitors.push(this.affectedMonitorsOptions.find(item => item.id === monitor.id));
}); });
} else { } else {
toast.error(res.msg); this.$root.toastError(res.msg);
} }
}); });
@ -472,11 +469,11 @@ export default {
this.showOnAllPages = Object.values(res.statusPages).length === this.selectedStatusPagesOptions.length; this.showOnAllPages = Object.values(res.statusPages).length === this.selectedStatusPagesOptions.length;
} else { } else {
toast.error(res.msg); this.$root.toastError(res.msg);
} }
}); });
} else { } else {
toast.error(res.msg); this.$root.toastError(res.msg);
} }
}); });
} }
@ -490,7 +487,7 @@ export default {
this.processing = true; this.processing = true;
if (this.affectedMonitors.length === 0) { if (this.affectedMonitors.length === 0) {
toast.error(this.$t("atLeastOneMonitor")); this.$root.toastError(this.$t("atLeastOneMonitor"));
return this.processing = false; return this.processing = false;
} }
@ -499,14 +496,14 @@ export default {
if (res.ok) { if (res.ok) {
await this.addMonitorMaintenance(res.maintenanceID, async () => { await this.addMonitorMaintenance(res.maintenanceID, async () => {
await this.addMaintenanceStatusPage(res.maintenanceID, () => { await this.addMaintenanceStatusPage(res.maintenanceID, () => {
toast.success(res.msg); this.$root.toastRes(res);
this.processing = false; this.processing = false;
this.$root.getMaintenanceList(); this.$root.getMaintenanceList();
this.$router.push("/maintenance"); this.$router.push("/maintenance");
}); });
}); });
} else { } else {
toast.error(res.msg); this.$root.toastRes(res);
this.processing = false; this.processing = false;
} }
@ -524,7 +521,7 @@ export default {
}); });
} else { } else {
this.processing = false; this.processing = false;
toast.error(res.msg); this.$root.toastError(res.msg);
} }
}); });
} }
@ -539,7 +536,7 @@ export default {
async addMonitorMaintenance(maintenanceID, callback) { async addMonitorMaintenance(maintenanceID, callback) {
await this.$root.addMonitorMaintenance(maintenanceID, this.affectedMonitors, async (res) => { await this.$root.addMonitorMaintenance(maintenanceID, this.affectedMonitors, async (res) => {
if (!res.ok) { if (!res.ok) {
toast.error(res.msg); this.$root.toastError(res.msg);
} else { } else {
this.$root.getMonitorList(); this.$root.getMonitorList();
} }
@ -557,7 +554,7 @@ export default {
async addMaintenanceStatusPage(maintenanceID, callback) { async addMaintenanceStatusPage(maintenanceID, callback) {
await this.$root.addMaintenanceStatusPage(maintenanceID, (this.showOnAllPages) ? this.selectedStatusPagesOptions : this.selectedStatusPages, async (res) => { await this.$root.addMaintenanceStatusPage(maintenanceID, (this.showOnAllPages) ? this.selectedStatusPagesOptions : this.selectedStatusPages, async (res) => {
if (!res.ok) { if (!res.ok) {
toast.error(res.msg); this.$root.toastError(res.msg);
} else { } else {
this.$root.getMaintenanceList(); this.$root.getMaintenanceList();
} }

View file

@ -865,7 +865,7 @@ import { genSecret, isDev, MAX_INTERVAL_SECOND, MIN_INTERVAL_SECOND } from "../u
import { hostNameRegexPattern } from "../util-frontend"; import { hostNameRegexPattern } from "../util-frontend";
import { sleep } from "../util"; import { sleep } from "../util";
const toast = useToast(); const toast = useToast;
const pushTokenLength = 32; const pushTokenLength = 32;
@ -1190,7 +1190,7 @@ message HealthCheckResponse {
if (res.ok) { if (res.ok) {
this.gameList = res.gameList; this.gameList = res.gameList;
} else { } else {
toast.error(res.msg); this.$root.toastError(res.msg);
} }
}); });
} }
@ -1351,7 +1351,7 @@ message HealthCheckResponse {
this.monitor.timeout = ~~(this.monitor.interval * 8) / 10; this.monitor.timeout = ~~(this.monitor.interval * 8) / 10;
} }
} else { } else {
toast.error(res.msg); this.$root.toastError(res.msg);
} }
}); });
} }
@ -1445,7 +1445,7 @@ message HealthCheckResponse {
createdNewParent = true; createdNewParent = true;
this.monitor.parent = res.monitorID; this.monitor.parent = res.monitorID;
} else { } else {
toast.error(res.msg); this.$root.toastError(res.msg);
this.processing = false; this.processing = false;
return; return;
} }
@ -1461,17 +1461,14 @@ message HealthCheckResponse {
if (createdNewParent) { if (createdNewParent) {
this.startParentGroupMonitor(); this.startParentGroupMonitor();
} }
toast.success(res.msg);
this.processing = false; this.processing = false;
this.$root.getMonitorList(); this.$root.getMonitorList();
this.$router.push("/dashboard/" + res.monitorID); this.$router.push("/dashboard/" + res.monitorID);
} else { } else {
toast.error(res.msg);
this.processing = false; this.processing = false;
} }
this.$root.toastRes(res);
}); });
} else { } else {
await this.$refs.tagsManager.submit(this.monitor.id); await this.$refs.tagsManager.submit(this.monitor.id);

View file

@ -101,12 +101,8 @@ export default {
*/ */
deleteMaintenance() { deleteMaintenance() {
this.$root.deleteMaintenance(this.maintenance.id, (res) => { this.$root.deleteMaintenance(this.maintenance.id, (res) => {
if (res.ok) { this.$root.toastRes(res);
toast.success(res.msg); this.$router.push("/maintenance");
this.$router.push("/maintenance");
} else {
toast.error(res.msg);
}
}); });
}, },
}, },

View file

@ -81,8 +81,6 @@ import { getResBaseURL } from "../util-frontend";
import { getMaintenanceRelativeURL } from "../util.ts"; import { getMaintenanceRelativeURL } from "../util.ts";
import Confirm from "../components/Confirm.vue"; import Confirm from "../components/Confirm.vue";
import MaintenanceTime from "../components/MaintenanceTime.vue"; import MaintenanceTime from "../components/MaintenanceTime.vue";
import { useToast } from "vue-toastification";
const toast = useToast();
export default { export default {
components: { components: {
@ -159,11 +157,9 @@ export default {
*/ */
deleteMaintenance() { deleteMaintenance() {
this.$root.deleteMaintenance(this.selectedMaintenanceID, (res) => { this.$root.deleteMaintenance(this.selectedMaintenanceID, (res) => {
this.$root.toastRes(res);
if (res.ok) { if (res.ok) {
toast.success(res.msg);
this.$router.push("/maintenance"); this.$router.push("/maintenance");
} else {
toast.error(res.msg);
} }
}); });
}, },

View file

@ -113,9 +113,6 @@ export default {
proxies: { proxies: {
title: this.$t("Proxies"), title: this.$t("Proxies"),
}, },
backup: {
title: this.$t("Backup"),
},
about: { about: {
title: this.$t("About"), title: this.$t("About"),
}, },

View file

@ -46,9 +46,6 @@
</template> </template>
<script> <script>
import { useToast } from "vue-toastification";
const toast = useToast();
export default { export default {
data() { data() {
return { return {
@ -79,7 +76,7 @@ export default {
this.processing = true; this.processing = true;
if (this.password !== this.repeatPassword) { if (this.password !== this.repeatPassword) {
toast.error(this.$t("PasswordsDoNotMatch")); this.$root.toastError("PasswordsDoNotMatch");
this.processing = false; this.processing = false;
return; return;
} }

View file

@ -179,7 +179,7 @@ export default {
}, },
test() { test() {
toast.error("not implemented"); this.$root.toastError("not implemented");
} }
}, },
}; };

View file

@ -614,7 +614,7 @@ export default {
} }
} else { } else {
toast.error(res.msg); this.$root.toastError(res.msg);
} }
}); });
} }
@ -869,7 +869,7 @@ export default {
this.enableEditMode = false; this.enableEditMode = false;
location.href = "/manage-status-page"; location.href = "/manage-status-page";
} else { } else {
toast.error(res.msg); this.$root.toastError(res.msg);
} }
}); });
}, },
@ -959,7 +959,7 @@ export default {
*/ */
postIncident() { postIncident() {
if (this.incident.title === "" || this.incident.content === "") { if (this.incident.title === "" || this.incident.content === "") {
toast.error(this.$t("Please input title and content")); this.$root.toastError("Please input title and content");
return; return;
} }
@ -969,7 +969,7 @@ export default {
this.enableEditIncidentMode = false; this.enableEditIncidentMode = false;
this.incident = res.incident; this.incident = res.incident;
} else { } else {
toast.error(res.msg); this.$root.toastError(res.msg);
} }
}); });

View file

@ -30,7 +30,6 @@ import Tags from "./components/settings/Tags.vue";
import MonitorHistory from "./components/settings/MonitorHistory.vue"; import MonitorHistory from "./components/settings/MonitorHistory.vue";
const Security = () => import("./components/settings/Security.vue"); const Security = () => import("./components/settings/Security.vue");
import Proxies from "./components/settings/Proxies.vue"; import Proxies from "./components/settings/Proxies.vue";
import Backup from "./components/settings/Backup.vue";
import About from "./components/settings/About.vue"; import About from "./components/settings/About.vue";
const routes = [ const routes = [
@ -126,10 +125,6 @@ const routes = [
path: "proxies", path: "proxies",
component: Proxies, component: Proxies,
}, },
{
path: "backup",
component: Backup,
},
{ {
path: "about", path: "about",
component: About, component: About,