mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-09-27 17:39:20 +08:00
Merge branch 'master' into customstatuspage
# Conflicts: # src/languages/de-DE.js
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<router-view />
|
||||
<router-view />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { setPageLocale } from "./util-frontend";
|
||||
export default {
|
||||
created() {
|
||||
setPageLocale();
|
||||
},
|
||||
created() {
|
||||
setPageLocale();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@@ -25,7 +25,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Modal } from "bootstrap"
|
||||
import { Modal } from "bootstrap";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@@ -42,19 +42,20 @@ export default {
|
||||
default: "No",
|
||||
},
|
||||
},
|
||||
emits: ["yes"],
|
||||
data: () => ({
|
||||
modal: null,
|
||||
}),
|
||||
mounted() {
|
||||
this.modal = new Modal(this.$refs.modal)
|
||||
this.modal = new Modal(this.$refs.modal);
|
||||
},
|
||||
methods: {
|
||||
show() {
|
||||
this.modal.show()
|
||||
this.modal.show();
|
||||
},
|
||||
yes() {
|
||||
this.$emit("yes");
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
@@ -57,6 +57,7 @@ export default {
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
data() {
|
||||
return {
|
||||
visibility: "password",
|
||||
|
@@ -5,7 +5,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
import { sleep } from "../util.ts"
|
||||
import { sleep } from "../util.ts";
|
||||
|
||||
export default {
|
||||
|
||||
@@ -25,12 +25,12 @@ export default {
|
||||
return {
|
||||
output: "",
|
||||
frameDuration: 30,
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
isNum() {
|
||||
return typeof this.value === "number"
|
||||
return typeof this.value === "number";
|
||||
},
|
||||
},
|
||||
|
||||
@@ -45,7 +45,7 @@ export default {
|
||||
} else {
|
||||
for (let i = 1; i < frames; i++) {
|
||||
this.output += step;
|
||||
await sleep(15)
|
||||
await sleep(15);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,5 +59,5 @@ export default {
|
||||
|
||||
methods: {},
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
@@ -4,12 +4,12 @@
|
||||
|
||||
<script>
|
||||
import dayjs from "dayjs";
|
||||
import relativeTime from "dayjs/plugin/relativeTime"
|
||||
import utc from "dayjs/plugin/utc"
|
||||
import timezone from "dayjs/plugin/timezone" // dependent on utc plugin
|
||||
dayjs.extend(utc)
|
||||
dayjs.extend(timezone)
|
||||
dayjs.extend(relativeTime)
|
||||
import relativeTime from "dayjs/plugin/relativeTime";
|
||||
import utc from "dayjs/plugin/utc";
|
||||
import timezone from "dayjs/plugin/timezone"; // dependent on utc plugin
|
||||
dayjs.extend(utc);
|
||||
dayjs.extend(timezone);
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@@ -29,5 +29,5 @@ export default {
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
@@ -38,7 +38,7 @@ export default {
|
||||
beatMargin: 4,
|
||||
move: false,
|
||||
maxBeat: -1,
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
||||
@@ -69,12 +69,12 @@ export default {
|
||||
if (start < 0) {
|
||||
// Add empty placeholder
|
||||
for (let i = start; i < 0; i++) {
|
||||
placeholders.push(0)
|
||||
placeholders.push(0);
|
||||
}
|
||||
start = 0;
|
||||
}
|
||||
|
||||
return placeholders.concat(this.beatList.slice(start))
|
||||
return placeholders.concat(this.beatList.slice(start));
|
||||
},
|
||||
|
||||
wrapStyle() {
|
||||
@@ -84,7 +84,7 @@ export default {
|
||||
return {
|
||||
padding: `${topBottom}px ${leftRight}px`,
|
||||
width: "100%",
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
barStyle() {
|
||||
@@ -94,12 +94,12 @@ export default {
|
||||
return {
|
||||
transition: "all ease-in-out 0.25s",
|
||||
transform: `translateX(${width}px)`,
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
return {
|
||||
transform: "translateX(0)",
|
||||
}
|
||||
};
|
||||
|
||||
},
|
||||
|
||||
@@ -109,7 +109,7 @@ export default {
|
||||
height: this.beatHeight + "px",
|
||||
margin: this.beatMargin + "px",
|
||||
"--hover-scale": this.hoverScale,
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
},
|
||||
@@ -120,7 +120,7 @@ export default {
|
||||
|
||||
setTimeout(() => {
|
||||
this.move = false;
|
||||
}, 300)
|
||||
}, 300);
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
@@ -162,15 +162,15 @@ export default {
|
||||
methods: {
|
||||
resize() {
|
||||
if (this.$refs.wrap) {
|
||||
this.maxBeat = Math.floor(this.$refs.wrap.clientWidth / (this.beatWidth + this.beatMargin * 2))
|
||||
this.maxBeat = Math.floor(this.$refs.wrap.clientWidth / (this.beatWidth + this.beatMargin * 2));
|
||||
}
|
||||
},
|
||||
|
||||
getBeatTitle(beat) {
|
||||
return `${this.$root.datetime(beat.time)}` + ((beat.msg) ? ` - ${beat.msg}` : ``);
|
||||
return `${this.$root.datetime(beat.time)}` + ((beat.msg) ? ` - ${beat.msg}` : "");
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -48,18 +48,19 @@ export default {
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
data() {
|
||||
return {
|
||||
visibility: "password",
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
model: {
|
||||
get() {
|
||||
return this.modelValue
|
||||
return this.modelValue;
|
||||
},
|
||||
set(value) {
|
||||
this.$emit("update:modelValue", value)
|
||||
this.$emit("update:modelValue", value);
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -74,5 +75,5 @@ export default {
|
||||
this.visibility = "password";
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
@@ -21,7 +21,7 @@
|
||||
|
||||
<router-link v-for="(item, index) in sortedMonitorList" :key="index" :to="monitorURL(item.id)" class="item" :class="{ 'disabled': ! item.active }">
|
||||
<div class="row">
|
||||
<div class="col-9 col-md-8 small-padding" :class="{ 'monitorItem': $root.userHeartbeatBar == 'bottom' || $root.userHeartbeatBar == 'none' }">
|
||||
<div class="col-9 col-md-8 small-padding" :class="{ 'monitor-item': $root.userHeartbeatBar == 'bottom' || $root.userHeartbeatBar == 'none' }">
|
||||
<div class="info">
|
||||
<Uptime :monitor="item" type="24" :pill="true" />
|
||||
{{ item.name }}
|
||||
@@ -172,7 +172,7 @@ export default {
|
||||
|
||||
.dark {
|
||||
.footer {
|
||||
// background-color: $dark-bg;
|
||||
// background-color: $dark-bg;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ export default {
|
||||
max-width: 15em;
|
||||
}
|
||||
|
||||
.monitorItem {
|
||||
.monitor-item {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
@@ -69,7 +69,6 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { Modal } from "bootstrap";
|
||||
import { ucfirst } from "../util.ts";
|
||||
|
||||
import Confirm from "./Confirm.vue";
|
||||
import NotificationFormList from "./notifications";
|
||||
|
@@ -24,7 +24,7 @@ import timezone from "dayjs/plugin/timezone";
|
||||
import "chartjs-adapter-dayjs";
|
||||
import { LineChart } from "vue-chart-3";
|
||||
import { useToast } from "vue-toastification";
|
||||
import { UP, DOWN, PENDING } from "../util.ts";
|
||||
import { DOWN } from "../util.ts";
|
||||
|
||||
dayjs.extend(utc);
|
||||
dayjs.extend(timezone);
|
||||
@@ -220,6 +220,7 @@ export default {
|
||||
if (newPeriod == "0") {
|
||||
newPeriod = null;
|
||||
this.heartbeatList = null;
|
||||
this.$root.storage().removeItem(`chart-period-${this.monitorId}`);
|
||||
} else {
|
||||
this.loading = true;
|
||||
|
||||
@@ -228,6 +229,7 @@ export default {
|
||||
toast.error(res.msg);
|
||||
} else {
|
||||
this.heartbeatList = res.data;
|
||||
this.$root.storage()[`chart-period-${this.monitorId}`] = newPeriod;
|
||||
}
|
||||
this.loading = false;
|
||||
});
|
||||
@@ -248,6 +250,12 @@ export default {
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
// Load chart period from storage if saved
|
||||
let period = this.$root.storage()[`chart-period-${this.monitorId}`];
|
||||
if (period != null) {
|
||||
this.chartPeriodHrs = Math.min(period, 6);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -278,7 +286,7 @@ export default {
|
||||
|
||||
.dropdown-item {
|
||||
border-radius: 0.3rem;
|
||||
padding: 2px 16px 4px 16px;
|
||||
padding: 2px 16px 4px;
|
||||
|
||||
.dark & {
|
||||
background: $dark-bg;
|
||||
@@ -286,6 +294,7 @@ export default {
|
||||
|
||||
.dark &:hover {
|
||||
background: $dark-font-color;
|
||||
color: $dark-font-color2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -25,7 +25,7 @@
|
||||
<label for="proxy-host" class="form-label">{{ $t("Proxy Server") }}</label>
|
||||
<div class="d-flex">
|
||||
<input id="proxy-host" v-model="proxy.host" type="text" class="form-control" required :placeholder="$t('Server Address')">
|
||||
<input v-model="proxy.port" type="number" class="form-control ms-2" style="width: 100px" required min="1" max="65535" :placeholder="$t('Port')">
|
||||
<input v-model="proxy.port" type="number" class="form-control ms-2" style="width: 100px;" required min="1" max="65535" :placeholder="$t('Port')">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@@ -145,7 +145,7 @@ export default {
|
||||
|
||||
.mobile {
|
||||
.item {
|
||||
padding: 13px 0 10px 0;
|
||||
padding: 13px 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -41,7 +41,7 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -49,7 +49,7 @@ export default {
|
||||
<style lang="scss" scoped>
|
||||
@import "../assets/vars.scss";
|
||||
|
||||
h5:after {
|
||||
h5::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 50%;
|
||||
|
@@ -46,7 +46,7 @@
|
||||
<input v-model="token" type="text" maxlength="6" class="form-control">
|
||||
<button class="btn btn-outline-primary" type="button" @click="verifyToken()">{{ $t("Verify Token") }}</button>
|
||||
</div>
|
||||
<p v-show="tokenValid" class="mt-2" style="color: green">{{ $t("tokenValidSettingsMsg") }}</p>
|
||||
<p v-show="tokenValid" class="mt-2" style="color: green;">{{ $t("tokenValidSettingsMsg") }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -22,33 +22,33 @@ export default {
|
||||
return Math.round(this.$root.uptimeList[key] * 10000) / 100 + "%";
|
||||
}
|
||||
|
||||
return this.$t("notAvailableShort")
|
||||
return this.$t("notAvailableShort");
|
||||
},
|
||||
|
||||
color() {
|
||||
if (this.lastHeartBeat.status === 0) {
|
||||
return "danger"
|
||||
return "danger";
|
||||
}
|
||||
|
||||
if (this.lastHeartBeat.status === 1) {
|
||||
return "primary"
|
||||
return "primary";
|
||||
}
|
||||
|
||||
if (this.lastHeartBeat.status === 2) {
|
||||
return "warning"
|
||||
return "warning";
|
||||
}
|
||||
|
||||
return "secondary"
|
||||
return "secondary";
|
||||
},
|
||||
|
||||
lastHeartBeat() {
|
||||
if (this.monitor.id in this.$root.lastHeartbeatList && this.$root.lastHeartbeatList[this.monitor.id]) {
|
||||
return this.$root.lastHeartbeatList[this.monitor.id]
|
||||
return this.$root.lastHeartbeatList[this.monitor.id];
|
||||
}
|
||||
|
||||
return {
|
||||
status: -1,
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
className() {
|
||||
@@ -59,7 +59,7 @@ export default {
|
||||
return "";
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
@@ -28,5 +28,5 @@ export default {
|
||||
this.$parent.notification.gotifyPriority = 8;
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="mattermost-webhook-url" class="form-label">{{ $t("Webhook URL") }}<span style="color:red;"><sup>*</sup></span></label>
|
||||
<label for="mattermost-webhook-url" class="form-label">{{ $t("Webhook URL") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||
<input id="mattermost-webhook-url" v-model="$parent.notification.mattermostWebhookUrl" type="text" class="form-control" required>
|
||||
<label for="mattermost-username" class="form-label">{{ $t("Username") }}</label>
|
||||
<input id="mattermost-username" v-model="$parent.notification.mattermostusername" type="text" class="form-control">
|
||||
@@ -11,7 +11,7 @@
|
||||
<label for="mattermost-channel" class="form-label">{{ $t("Channel Name") }}</label>
|
||||
<input id="mattermost-channel-name" v-model="$parent.notification.mattermostchannel" type="text" class="form-control">
|
||||
<div class="form-text">
|
||||
<span style="color:red;"><sup>*</sup></span>{{ $t("Required") }}
|
||||
<span style="color: red;"><sup>*</sup></span>{{ $t("Required") }}
|
||||
<i18n-t tag="p" keypath="aboutWebhooks" style="margin-top: 8px;">
|
||||
<a href="https://docs.mattermost.com/developer/webhooks-incoming.html" target="_blank">https://docs.mattermost.com/developer/webhooks-incoming.html</a>
|
||||
</i18n-t>
|
||||
|
34
src/components/notifications/OneBot.vue
Normal file
34
src/components/notifications/OneBot.vue
Normal file
@@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<div class="mb-3">
|
||||
<div class="mb-3">
|
||||
<label for="onebot-http-addr" class="form-label">{{ $t("onebotHttpAddress") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||
<input id="HttpUrl" v-model="$parent.notification.httpAddr" type="text" class="form-control" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="onebot-access-token" class="form-label">AccessToken<span style="color: red;"><sup>*</sup></span></label>
|
||||
<input id="HttpUrl" v-model="$parent.notification.accessToken" type="text" class="form-control" required>
|
||||
<div class="form-text">
|
||||
<p>{{ $t("onebotSafetyTips") }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="onebot-msg-type" class="form-label">{{ $t("onebotMessageType") }}</label>
|
||||
<select id="onebot-msg-type" v-model="$parent.notification.msgType" class="form-select">
|
||||
<option value="group">{{ $t("onebotGroupMessage") }}</option>
|
||||
<option value="private">{{ $t("onebotPrivateMessage") }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="onebot-reciever-id" class="form-label">{{ $t("onebotUserOrGroupId") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||
<input id="secretKey" v-model="$parent.notification.recieverId" type="text" class="form-control" required>
|
||||
</div>
|
||||
|
||||
<div class="form-text">
|
||||
<i18n-t tag="p" keypath="Read more:">
|
||||
<a href="https://github.com/botuniverse/onebot-11" target="_blank">https://github.com/botuniverse/onebot-11</a>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
19
src/components/notifications/PushDeer.vue
Normal file
19
src/components/notifications/PushDeer.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="pushdeer-key" class="form-label">{{ $t("PushDeer Key") }}</label>
|
||||
<HiddenInput id="pushdeer-key" v-model="$parent.notification.pushdeerKey" :required="true" autocomplete="one-time-code" placeholder="PDUxxxx"></HiddenInput>
|
||||
</div>
|
||||
|
||||
<i18n-t tag="p" keypath="More info on:" style="margin-top: 8px;">
|
||||
<a href="http://www.pushdeer.com/" rel="noopener noreferrer" target="_blank">http://www.pushdeer.com/</a>
|
||||
</i18n-t>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HiddenInput from "../HiddenInput.vue";
|
||||
export default {
|
||||
components: {
|
||||
HiddenInput,
|
||||
},
|
||||
};
|
||||
</script>
|
@@ -63,5 +63,5 @@ export default {
|
||||
components: {
|
||||
HiddenInput,
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
@@ -24,11 +24,13 @@ import AliyunSMS from "./AliyunSms.vue";
|
||||
import DingDing from "./DingDing.vue";
|
||||
import Bark from "./Bark.vue";
|
||||
import SerwerSMS from "./SerwerSMS.vue";
|
||||
import Stackfield from './Stackfield.vue';
|
||||
import Stackfield from "./Stackfield.vue";
|
||||
import WeCom from "./WeCom.vue";
|
||||
import GoogleChat from "./GoogleChat.vue";
|
||||
import Gorush from "./Gorush.vue";
|
||||
import Alerta from "./Alerta.vue";
|
||||
import OneBot from "./OneBot.vue";
|
||||
import PushDeer from "./PushDeer.vue";
|
||||
|
||||
/**
|
||||
* Manage all notification form.
|
||||
@@ -67,6 +69,8 @@ const NotificationFormList = {
|
||||
"GoogleChat": GoogleChat,
|
||||
"gorush": Gorush,
|
||||
"alerta": Alerta,
|
||||
"OneBot": OneBot,
|
||||
"PushDeer": PushDeer,
|
||||
};
|
||||
|
||||
export default NotificationFormList;
|
||||
|
@@ -44,6 +44,7 @@ export default {
|
||||
.logo {
|
||||
margin: 4em 1em;
|
||||
}
|
||||
|
||||
.update-link {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
@@ -69,7 +69,7 @@
|
||||
|
||||
<div class="mb-2">
|
||||
<input
|
||||
id="importBackup"
|
||||
id="import-backend"
|
||||
type="file"
|
||||
class="form-control"
|
||||
accept="application/json"
|
||||
@@ -94,7 +94,7 @@
|
||||
<div
|
||||
v-if="importAlert"
|
||||
class="alert alert-danger mt-3"
|
||||
style="padding: 6px 16px"
|
||||
style="padding: 6px 16px;"
|
||||
>
|
||||
{{ importAlert }}
|
||||
</div>
|
||||
@@ -159,7 +159,7 @@ export default {
|
||||
|
||||
importBackup() {
|
||||
this.processing = true;
|
||||
let uploadItem = document.getElementById("importBackup").files;
|
||||
let uploadItem = document.getElementById("import-backend").files;
|
||||
|
||||
if (uploadItem.length <= 0) {
|
||||
this.processing = false;
|
||||
@@ -198,7 +198,7 @@ export default {
|
||||
@import "../../assets/vars.scss";
|
||||
|
||||
.dark {
|
||||
#importBackup {
|
||||
#import-backend {
|
||||
&::file-selector-button {
|
||||
color: $primary;
|
||||
background-color: $dark-bg;
|
||||
|
@@ -189,4 +189,3 @@ export default {
|
||||
};
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
|
@@ -52,7 +52,7 @@
|
||||
|
||||
<script>
|
||||
import Confirm from "../../components/Confirm.vue";
|
||||
import { debug } from "../../util.ts";
|
||||
import { log } from "../../util.ts";
|
||||
import { useToast } from "vue-toastification";
|
||||
|
||||
const toast = useToast();
|
||||
@@ -91,13 +91,13 @@ export default {
|
||||
|
||||
methods: {
|
||||
loadDatabaseSize() {
|
||||
debug("load database size");
|
||||
log.debug("monitorhistory", "load database size");
|
||||
this.$root.getSocket().emit("getDatabaseSize", (res) => {
|
||||
if (res.ok) {
|
||||
this.databaseSize = res.size;
|
||||
debug("database size: " + res.size);
|
||||
log.debug("monitorhistory", "database size: " + res.size);
|
||||
} else {
|
||||
debug(res);
|
||||
log.debug("monitorhistory", res);
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -108,7 +108,7 @@ export default {
|
||||
this.loadDatabaseSize();
|
||||
toast.success("Done");
|
||||
} else {
|
||||
debug(res);
|
||||
log.debug("monitorhistory", res);
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -129,5 +129,3 @@ export default {
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
|
@@ -355,7 +355,7 @@ export default {
|
||||
<style lang="scss" scoped>
|
||||
@import "../../assets/vars.scss";
|
||||
|
||||
h5:after {
|
||||
h5::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 50%;
|
||||
|
@@ -343,7 +343,7 @@ export default {
|
||||
"No Monitors": "Няма монитори",
|
||||
"Untitled Group": "Група без заглавие",
|
||||
Services: "Услуги",
|
||||
Discard: "Премахни",
|
||||
Discard: "Отмени",
|
||||
Cancel: "Отмени",
|
||||
"Powered by": "Създадено чрез",
|
||||
serwersms: "SerwerSMS.pl",
|
||||
|
@@ -350,7 +350,7 @@ export default {
|
||||
serwersmsAPIPassword: "API Passwort",
|
||||
serwersmsPhoneNumber: "Telefonnummer",
|
||||
serwersmsSenderName: "Name des SMS-Absenders (über Kundenportal registriert)",
|
||||
"stackfield": "Stackfield",
|
||||
stackfield: "Stackfield",
|
||||
clicksendsms: "ClickSend SMS",
|
||||
apiCredentials: "API Zugangsdaten",
|
||||
smtpDkimSettings: "DKIM Einstellungen",
|
||||
@@ -362,6 +362,86 @@ export default {
|
||||
smtpDkimHashAlgo: "Hash-Algorithmus (Optional)",
|
||||
smtpDkimheaderFieldNames: "Zu validierende Header-Schlüssel (optional)",
|
||||
smtpDkimskipFields: "Zu ignorierende Header Schlüssel (optional)",
|
||||
PushByTechulus: "Push by Techulus",
|
||||
gorush: "Gorush",
|
||||
alerta: "Alerta",
|
||||
alertaApiEndpoint: "API Endpunkt",
|
||||
alertaEnvironment: "Umgebung",
|
||||
alertaApiKey: "API Schlüssel",
|
||||
alertaAlertState: "Alarmstatus",
|
||||
alertaRecoverState: "Wiederherstellungsstatus",
|
||||
deleteStatusPageMsg: "Bist du sicher, dass du diese Status-Seite löschen willst?",
|
||||
Proxies: "Proxies",
|
||||
default: "Standard",
|
||||
enabled: "Aktiviert",
|
||||
setAsDefault: "Als Standard setzen",
|
||||
deleteProxyMsg: "Bist du sicher, dass du diesen Proxy für alle Monitore löschen willst?",
|
||||
proxyDescription: "Proxies müssen einem Monitor zugewiesen werden, um zu funktionieren.",
|
||||
enableProxyDescription: "Dieser Proxy wird keinen Effekt auf Monitor-Anfragen haben, bis er aktiviert ist. Du kannst ihn temporär von allen Monitoren nach Aktivierungsstatus deaktivieren.",
|
||||
setAsDefaultProxyDescription: "Dieser Proxy wird standardmäßig für alle neuen Monitore aktiviert sein. Du kannst den Proxy immernoch für jeden Monitor einzeln deaktivieren.",
|
||||
"Certificate Chain": "Zertifikatskette",
|
||||
Valid: "Gültig",
|
||||
Invalid: "Ungültig",
|
||||
AccessKeyId: "AccessKey ID",
|
||||
SecretAccessKey: "AccessKey Secret",
|
||||
PhoneNumbers: "Telefonnummern",
|
||||
TemplateCode: "Vorlagencode",
|
||||
SignName: "Signaturname",
|
||||
"Sms template must contain parameters: ": "SMS Vorlage muss folgende Parameter enthalten: ",
|
||||
"Bark Endpoint": "Bark Endpunkt",
|
||||
WebHookUrl: "Webhook URL",
|
||||
SecretKey: "Geheimer Schlüssel",
|
||||
"For safety, must use secret key": "Zur Sicherheit muss ein geheimer Schlüssel verwendet werden",
|
||||
"Device Token": "Gerätetoken",
|
||||
Platform: "Platform",
|
||||
iOS: "iOS",
|
||||
Android: "Android",
|
||||
Huawei: "Huawei",
|
||||
High: "Hoch",
|
||||
Retry: "Wiederholungen",
|
||||
Topic: "Thema",
|
||||
"WeCom Bot Key": "WeCom Bot Schlüssel",
|
||||
"Setup Proxy": "Proxy einrichten",
|
||||
"Proxy Protocol": "Proxy Protokoll",
|
||||
"Proxy Server": "Proxy Server",
|
||||
"Proxy server has authentication": "Proxy server hat Authentifizierung",
|
||||
User: "Benutzer",
|
||||
Installed: "Installiert",
|
||||
"Not installed": "Nicht installiert",
|
||||
Running: "Läuft",
|
||||
"Not running": "Gestoppt",
|
||||
"Remove Token": "Token entfernen",
|
||||
Start: "Start",
|
||||
Stop: "Stop",
|
||||
"Uptime Kuma": "Uptime Kuma",
|
||||
"Add New Status Page": "Neue Status-Seite hinzufügen",
|
||||
Slug: "Slug",
|
||||
"Accept characters:": "Akzeptierte Zeichen:",
|
||||
startOrEndWithOnly: "Nur mit {0} anfangen und enden",
|
||||
"No consecutive dashes": "Keine aufeinanderfolgenden Bindestriche",
|
||||
Next: "Weiter",
|
||||
"The slug is already taken. Please choose another slug.": "Der Slug ist bereits in Verwendung. Bitte wähle einen anderen.",
|
||||
"No Proxy": "Kein Proxy",
|
||||
"HTTP Basic Auth": "HTTP Basisauthentifizierung",
|
||||
"New Status Page": "Neue Status-Seite",
|
||||
"Page Not Found": "Seite nicht gefunden",
|
||||
"Reverse Proxy": "Reverse Proxy",
|
||||
Backup: "Sicherung",
|
||||
About: "Über",
|
||||
wayToGetCloudflaredURL: "(Lade cloudflared von {0} herunter)",
|
||||
cloudflareWebsite: "Cloudflare Website",
|
||||
"Message:": "Nachricht:",
|
||||
"Don't know how to get the token? Please read the guide:": "Du weißt nicht, wie man den Token bekommt? Lies die Anleitung dazu:",
|
||||
"The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.": "Die aktuelle Verbindung kann unterbrochen werden, wenn du aktuell über Cloudflare Tunnel verbunden bist. Bist du sicher, dass du es stoppen willst? Gib zur Bestätigung dein aktuelles Passwort ein.",
|
||||
"Other Software": "Andere Software",
|
||||
"For example: nginx, Apache and Traefik.": "Zum Beispiel: nginx, Apache und Traefik.",
|
||||
"Please read": "Bitte lesen",
|
||||
"Subject:": "Betreff:",
|
||||
"Valid To:": "Gültig bis:",
|
||||
"Days Remaining:": "Tage verbleibend:",
|
||||
"Issuer:": "Aussteller:",
|
||||
"Fingerprint:": "Fingerabdruck:",
|
||||
"No status pages": "Keine Status-Seiten",
|
||||
Customize: "Anpassen",
|
||||
"Custom Footer": "Eigener Footer (Leerlassen für Standard)",
|
||||
"Custom CSS": "Eigenes CSS",
|
||||
|
@@ -445,4 +445,14 @@ export default {
|
||||
"Issuer:": "Issuer:",
|
||||
"Fingerprint:": "Fingerprint:",
|
||||
"No status pages": "No status pages",
|
||||
"Domain Name Expiry Notification": "Domain Name Expiry Notification",
|
||||
"Proxy": "Proxy",
|
||||
"Date Created": "Date Created",
|
||||
onebotHttpAddress: "OneBot HTTP Address",
|
||||
onebotMessageType: "OneBot Message Type",
|
||||
onebotGroupMessage: "Group",
|
||||
onebotPrivateMessage: "Private",
|
||||
onebotUserOrGroupId: "Group/User ID",
|
||||
onebotSafetyTips: "For safety, must set access token",
|
||||
"PushDeer Key": "PushDeer Key",
|
||||
};
|
||||
|
@@ -374,8 +374,8 @@ export default {
|
||||
serwersmsSenderName: "SMS Имя Отправителя (регистрированный через пользовательский портал)",
|
||||
stackfield: "Stackfield",
|
||||
smtpDkimSettings: "DKIM Настройки",
|
||||
smtpDkimDesc: "Please refer to the Nodemailer DKIM {0} for usage.",
|
||||
documentation: "документация",
|
||||
smtpDkimDesc: "Пожалуйста ознакомьтесь с {0} Nodemailer DKIM для использования.",
|
||||
documentation: "документацией",
|
||||
smtpDkimDomain: "Имя Домена",
|
||||
smtpDkimKeySelector: "Ключ",
|
||||
smtpDkimPrivateKey: "Приватный ключ",
|
||||
@@ -389,4 +389,12 @@ export default {
|
||||
alertaApiKey: "Ключ API",
|
||||
alertaAlertState: "Состояние алерта",
|
||||
alertaRecoverState: "Состояние восстановления",
|
||||
Proxies: "Прокси",
|
||||
default: "По умолчанию",
|
||||
enabled: "Включено",
|
||||
setAsDefault: "Установлено по умолчанию",
|
||||
deleteProxyMsg: "Вы действительно хотите удалить этот прокси для всех мониторов?",
|
||||
proxyDescription: "Прокси должны быть привязаны к монитору, чтобы работать.",
|
||||
enableProxyDescription: "Этот прокси не будет влиять на запросы монитора, пока не будет активирован. Вы можете контролировать временное отключение прокси для всех мониторов через статус активации.",
|
||||
setAsDefaultProxyDescription: "Этот прокси будет по умолчанию включен для новых мониторов. Вы всё ещё можете отдельно отключать прокси в каждом мониторе.",
|
||||
};
|
||||
|
@@ -449,4 +449,13 @@ export default {
|
||||
"Issuer:": "颁发者:",
|
||||
"Fingerprint:": "指纹:",
|
||||
"No status pages": "无状态页",
|
||||
"Domain Name Expiry Notification": "域名到期时通知",
|
||||
"Proxy": "代理",
|
||||
"Date Created": "创建于",
|
||||
onebotHttpAddress: "OneBot HTTP 地址",
|
||||
onebotMessageType: "OneBot 消息类型",
|
||||
onebotGroupMessage: "群聊",
|
||||
onebotPrivateMessage: "私聊",
|
||||
onebotUserOrGroupId: "群组/用户ID",
|
||||
onebotSafetyTips: "出于安全原因,请务必设置AccessToken",
|
||||
};
|
||||
|
@@ -3,5 +3,6 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {}
|
||||
export default {};
|
||||
</script>
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { io } from "socket.io-client";
|
||||
import { useToast } from "vue-toastification";
|
||||
import jwt_decode from "jwt-decode";
|
||||
import jwtDecode from "jwt-decode";
|
||||
import Favico from "favico.js";
|
||||
const toast = useToast();
|
||||
|
||||
@@ -266,7 +266,7 @@ export default {
|
||||
const jwtToken = this.$root.storage().token;
|
||||
|
||||
if (jwtToken && jwtToken !== "autoLogin") {
|
||||
return jwt_decode(jwtToken);
|
||||
return jwtDecode(jwtToken);
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
@@ -25,9 +25,9 @@ export default {
|
||||
MonitorList,
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
return {};
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@@ -118,6 +118,7 @@ export default {
|
||||
return 0;
|
||||
});
|
||||
|
||||
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
||||
this.heartBeatList = result;
|
||||
|
||||
return result;
|
||||
|
@@ -11,6 +11,6 @@ export default {
|
||||
components: {
|
||||
MonitorList,
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
@@ -92,7 +92,6 @@ export default {
|
||||
}
|
||||
|
||||
.info {
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
|
@@ -283,6 +283,7 @@ const toast = useToast();
|
||||
|
||||
const leavePageMsg = "Do you really want to leave? you have unsaved changes!";
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let feedInterval;
|
||||
|
||||
const favicon = new Favico({
|
||||
@@ -864,7 +865,7 @@ footer {
|
||||
|
||||
.incident, .customize {
|
||||
.content {
|
||||
&[contenteditable=true] {
|
||||
&[contenteditable="true"] {
|
||||
min-height: 60px;
|
||||
}
|
||||
}
|
||||
|
70
src/util.js
70
src/util.js
@@ -7,7 +7,7 @@
|
||||
// Backend uses the compiled file util.js
|
||||
// Frontend uses util.ts
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getMonitorRelativeURL = exports.genSecret = exports.getCryptoRandomInt = exports.getRandomInt = exports.getRandomArbitrary = exports.TimeLogger = exports.polyfill = exports.debug = exports.ucfirst = exports.sleep = exports.flipStatus = exports.STATUS_PAGE_PARTIAL_DOWN = exports.STATUS_PAGE_ALL_UP = exports.STATUS_PAGE_ALL_DOWN = exports.PENDING = exports.UP = exports.DOWN = exports.appName = exports.isDev = void 0;
|
||||
exports.getMonitorRelativeURL = exports.genSecret = exports.getCryptoRandomInt = exports.getRandomInt = exports.getRandomArbitrary = exports.TimeLogger = exports.polyfill = exports.log = exports.debug = exports.ucfirst = exports.sleep = exports.flipStatus = exports.STATUS_PAGE_PARTIAL_DOWN = exports.STATUS_PAGE_ALL_UP = exports.STATUS_PAGE_ALL_DOWN = exports.PENDING = exports.UP = exports.DOWN = exports.appName = exports.isDev = void 0;
|
||||
const _dayjs = require("dayjs");
|
||||
const dayjs = _dayjs;
|
||||
exports.isDev = process.env.NODE_ENV === "development";
|
||||
@@ -44,12 +44,60 @@ function ucfirst(str) {
|
||||
return firstLetter.toUpperCase() + str.substr(1);
|
||||
}
|
||||
exports.ucfirst = ucfirst;
|
||||
/**
|
||||
* @deprecated Use log.debug
|
||||
* @since https://github.com/louislam/uptime-kuma/pull/910
|
||||
* @param msg
|
||||
*/
|
||||
function debug(msg) {
|
||||
if (exports.isDev) {
|
||||
console.log(msg);
|
||||
}
|
||||
exports.log.log("", msg, "debug");
|
||||
}
|
||||
exports.debug = debug;
|
||||
class Logger {
|
||||
log(module, msg, level) {
|
||||
module = module.toUpperCase();
|
||||
level = level.toUpperCase();
|
||||
const now = new Date().toISOString();
|
||||
const formattedMessage = (typeof msg === "string") ? `${now} [${module}] ${level}: ${msg}` : msg;
|
||||
if (level === "INFO") {
|
||||
console.info(formattedMessage);
|
||||
}
|
||||
else if (level === "WARN") {
|
||||
console.warn(formattedMessage);
|
||||
}
|
||||
else if (level === "ERROR") {
|
||||
console.error(formattedMessage);
|
||||
}
|
||||
else if (level === "DEBUG") {
|
||||
if (exports.isDev) {
|
||||
console.debug(formattedMessage);
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.log(formattedMessage);
|
||||
}
|
||||
}
|
||||
info(module, msg) {
|
||||
this.log(module, msg, "info");
|
||||
}
|
||||
warn(module, msg) {
|
||||
this.log(module, msg, "warn");
|
||||
}
|
||||
error(module, msg) {
|
||||
this.log(module, msg, "error");
|
||||
}
|
||||
debug(module, msg) {
|
||||
this.log(module, msg, "debug");
|
||||
}
|
||||
exception(module, exception, msg) {
|
||||
let finalMessage = exception;
|
||||
if (msg) {
|
||||
finalMessage = `${msg}: ${exception}`;
|
||||
}
|
||||
this.log(module, finalMessage, "error");
|
||||
}
|
||||
}
|
||||
exports.log = new Logger();
|
||||
function polyfill() {
|
||||
/**
|
||||
* String.prototype.replaceAll() polyfill
|
||||
@@ -121,13 +169,6 @@ let getRandomBytes = ((typeof window !== 'undefined' && window.crypto)
|
||||
: function () {
|
||||
return require("crypto").randomBytes;
|
||||
})();
|
||||
/**
|
||||
* Returns a random integer between min (inclusive) and max (exclusive).
|
||||
* @param {number} min The minimum value.
|
||||
* @param {number} max The maximum value.
|
||||
*
|
||||
* Generated by Trelent
|
||||
*/
|
||||
function getCryptoRandomInt(min, max) {
|
||||
// synchronous version of: https://github.com/joepie91/node-random-number-csprng
|
||||
const range = max - min;
|
||||
@@ -158,13 +199,6 @@ function getCryptoRandomInt(min, max) {
|
||||
}
|
||||
}
|
||||
exports.getCryptoRandomInt = getCryptoRandomInt;
|
||||
/**
|
||||
* Generates a random string of length `length` from the characters in `chars`.
|
||||
* @param {number} length The number of characters to generate.
|
||||
* @param {string} chars A string containing all the possible characters to use for generating the random string.
|
||||
*
|
||||
* Generated by Trelent
|
||||
*/
|
||||
function genSecret(length = 64) {
|
||||
let secret = "";
|
||||
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
58
src/util.ts
58
src/util.ts
@@ -49,12 +49,66 @@ export function ucfirst(str: string) {
|
||||
return firstLetter.toUpperCase() + str.substr(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use log.debug
|
||||
* @since https://github.com/louislam/uptime-kuma/pull/910
|
||||
* @param msg
|
||||
*/
|
||||
export function debug(msg: any) {
|
||||
if (isDev) {
|
||||
console.log(msg);
|
||||
log.log("", msg, "debug");
|
||||
}
|
||||
|
||||
class Logger {
|
||||
log(module: string, msg: any, level: string) {
|
||||
module = module.toUpperCase();
|
||||
level = level.toUpperCase();
|
||||
|
||||
const now = new Date().toISOString();
|
||||
const formattedMessage = (typeof msg === "string") ? `${now} [${module}] ${level}: ${msg}` : msg;
|
||||
|
||||
if (level === "INFO") {
|
||||
console.info(formattedMessage);
|
||||
} else if (level === "WARN") {
|
||||
console.warn(formattedMessage);
|
||||
} else if (level === "ERROR") {
|
||||
console.error(formattedMessage);
|
||||
} else if (level === "DEBUG") {
|
||||
if (isDev) {
|
||||
console.debug(formattedMessage);
|
||||
}
|
||||
} else {
|
||||
console.log(formattedMessage);
|
||||
}
|
||||
}
|
||||
|
||||
info(module: string, msg: any) {
|
||||
this.log(module, msg, "info");
|
||||
}
|
||||
|
||||
warn(module: string, msg: any) {
|
||||
this.log(module, msg, "warn");
|
||||
}
|
||||
|
||||
error(module: string, msg: any) {
|
||||
this.log(module, msg, "error");
|
||||
}
|
||||
|
||||
debug(module: string, msg: any) {
|
||||
this.log(module, msg, "debug");
|
||||
}
|
||||
|
||||
exception(module: string, exception: any, msg: any) {
|
||||
let finalMessage = exception
|
||||
|
||||
if (msg) {
|
||||
finalMessage = `${msg}: ${exception}`
|
||||
}
|
||||
|
||||
this.log(module, finalMessage , "error");
|
||||
}
|
||||
}
|
||||
|
||||
export const log = new Logger();
|
||||
|
||||
declare global { interface String { replaceAll(str: string, newStr: string): string; } }
|
||||
|
||||
|
Reference in New Issue
Block a user