mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-08-21 20:02:29 +08:00
Merge branch 'louislam:master' into master
This commit is contained in:
@@ -21,7 +21,9 @@
|
||||
<div class="form-text">
|
||||
<ul>
|
||||
<li>{{ $t("Accept characters:") }} <mark>a-z</mark> <mark>0-9</mark> <mark>-</mark></li>
|
||||
<li>{{ $t("Start or end with") }} <mark>a-z</mark> <mark>0-9</mark> only</li>
|
||||
<i18n-t tag="li" keypath="startOrEndWithOnly">
|
||||
<mark>a-z</mark> <mark>0-9</mark>
|
||||
</i18n-t>
|
||||
<li>{{ $t("No consecutive dashes") }} <mark>--</mark></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@@ -170,6 +170,15 @@
|
||||
|
||||
<h2 v-if="monitor.type !== 'push'" class="mt-5 mb-2">{{ $t("Advanced") }}</h2>
|
||||
|
||||
<div class="my-3 form-check">
|
||||
<input id="expiry-notification" v-model="monitor.expiryNotification" class="form-check-input" type="checkbox">
|
||||
<label class="form-check-label" for="expiry-notification">
|
||||
{{ $t("Domain Name Expiry Notification") }}
|
||||
</label>
|
||||
<div class="form-text">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' " class="my-3 form-check">
|
||||
<input id="ignore-tls" v-model="monitor.ignoreTls" class="form-check-input" type="checkbox" value="">
|
||||
<label class="form-check-label" for="ignore-tls">
|
||||
@@ -254,31 +263,33 @@
|
||||
</button>
|
||||
|
||||
<!-- Proxies -->
|
||||
<h2 class="mt-5 mb-2">{{ $t("Proxies") }}</h2>
|
||||
<p v-if="$root.proxyList.length === 0">
|
||||
{{ $t("Not available, please setup.") }}
|
||||
</p>
|
||||
<div v-if="monitor.type === 'http' || monitor.type === 'keyword'">
|
||||
<h2 class="mt-5 mb-2">{{ $t("Proxy") }}</h2>
|
||||
<p v-if="$root.proxyList.length === 0">
|
||||
{{ $t("Not available, please setup.") }}
|
||||
</p>
|
||||
|
||||
<div v-if="$root.proxyList.length > 0" class="form-check form-switch my-3">
|
||||
<input id="proxy-disable" v-model="monitor.proxyId" :value="null" name="proxy" class="form-check-input" type="radio">
|
||||
<label class="form-check-label" for="proxy-disable">{{ $t("No Proxy") }}</label>
|
||||
<div v-if="$root.proxyList.length > 0" class="form-check my-3">
|
||||
<input id="proxy-disable" v-model="monitor.proxyId" :value="null" name="proxy" class="form-check-input" type="radio">
|
||||
<label class="form-check-label" for="proxy-disable">{{ $t("No Proxy") }}</label>
|
||||
</div>
|
||||
|
||||
<div v-for="proxy in $root.proxyList" :key="proxy.id" class="form-check my-3">
|
||||
<input :id="`proxy-${proxy.id}`" v-model="monitor.proxyId" :value="proxy.id" name="proxy" class="form-check-input" type="radio">
|
||||
|
||||
<label class="form-check-label" :for="`proxy-${proxy.id}`">
|
||||
{{ proxy.host }}:{{ proxy.port }} ({{ proxy.protocol }})
|
||||
<a href="#" @click="$refs.proxyDialog.show(proxy.id)">{{ $t("Edit") }}</a>
|
||||
</label>
|
||||
|
||||
<span v-if="proxy.default === true" class="badge bg-primary ms-2">{{ $t("default") }}</span>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-primary me-2" type="button" @click="$refs.proxyDialog.show()">
|
||||
{{ $t("Setup Proxy") }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-for="proxy in $root.proxyList" :key="proxy.id" class="form-check form-switch my-3">
|
||||
<input :id="`proxy-${proxy.id}`" v-model="monitor.proxyId" :value="proxy.id" name="proxy" class="form-check-input" type="radio">
|
||||
|
||||
<label class="form-check-label" :for="`proxy-${proxy.id}`">
|
||||
{{ proxy.host }}:{{ proxy.port }} ({{ proxy.protocol }})
|
||||
<a href="#" @click="$refs.proxyDialog.show(proxy.id)">{{ $t("Edit") }}</a>
|
||||
</label>
|
||||
|
||||
<span v-if="proxy.default === true" class="badge bg-primary ms-2">{{ $t("default") }}</span>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-primary me-2" type="button" @click="$refs.proxyDialog.show()">
|
||||
{{ $t("Setup Proxy") }}
|
||||
</button>
|
||||
|
||||
<!-- HTTP Options -->
|
||||
<template v-if="monitor.type === 'http' || monitor.type === 'keyword' ">
|
||||
<h2 class="mt-5 mb-2">{{ $t("HTTP Options") }}</h2>
|
||||
@@ -506,6 +517,7 @@ export default {
|
||||
notificationIDList: {},
|
||||
ignoreTls: false,
|
||||
upsideDown: false,
|
||||
expiryNotification: false,
|
||||
maxredirects: 10,
|
||||
accepted_statuscodes: ["200-299"],
|
||||
dns_resolve_type: "A",
|
||||
|
@@ -1,19 +1,45 @@
|
||||
<template>
|
||||
<div></div>
|
||||
<div>
|
||||
<StatusPage v-if="statusPageSlug" :override-slug="statusPageSlug" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from "axios";
|
||||
import StatusPage from "./StatusPage.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
StatusPage,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
statusPageSlug: null,
|
||||
};
|
||||
},
|
||||
async mounted() {
|
||||
let entryPage = (await axios.get("/api/entry-page")).data;
|
||||
|
||||
if (entryPage === "statusPage") {
|
||||
this.$router.push("/status");
|
||||
// There are only 2 cases that could come in here.
|
||||
// 1. Matched status Page domain name
|
||||
// 2. Vue Frontend Dev
|
||||
let res = (await axios.get("/api/entry-page")).data;
|
||||
|
||||
if (res.type === "statusPageMatchedDomain") {
|
||||
this.statusPageSlug = res.statusPageSlug;
|
||||
this.$root.forceStatusPageTheme = true;
|
||||
|
||||
} else if (res.type === "entryPage") { // Dev only. For production, the logic is in the server side
|
||||
const entryPage = res.entryPage;
|
||||
|
||||
if (entryPage === "statusPage") {
|
||||
this.$router.push("/status");
|
||||
} else {
|
||||
this.$router.push("/dashboard");
|
||||
}
|
||||
} else {
|
||||
this.$router.push("/dashboard");
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
};
|
||||
|
@@ -12,7 +12,7 @@
|
||||
<div class="shadow-box">
|
||||
<template v-if="$root.statusPageListLoaded">
|
||||
<span v-if="Object.keys($root.statusPageList).length === 0" class="d-flex align-items-center justify-content-center my-3">
|
||||
No status pages
|
||||
{{ $t("No status pages") }}
|
||||
</span>
|
||||
|
||||
<!-- use <a> instead of <router-link>, because the heartbeat won't load. -->
|
||||
|
@@ -121,6 +121,10 @@ export default {
|
||||
this.$root.getSocket().emit("getSettings", (res) => {
|
||||
this.settings = res.data;
|
||||
|
||||
if (this.settings.checkUpdate === undefined) {
|
||||
this.settings.checkUpdate = true;
|
||||
}
|
||||
|
||||
if (this.settings.searchEngineIndex === undefined) {
|
||||
this.settings.searchEngineIndex = false;
|
||||
}
|
||||
|
@@ -2,49 +2,61 @@
|
||||
<div v-if="loadedTheme" class="container mt-3">
|
||||
<!-- Sidebar for edit mode -->
|
||||
<div v-if="enableEditMode" class="sidebar">
|
||||
<div class="my-3">
|
||||
<label for="slug" class="form-label">{{ $t("Slug") }}</label>
|
||||
<div class="input-group">
|
||||
<span id="basic-addon3" class="input-group-text">/status/</span>
|
||||
<input id="slug" v-model="config.slug" type="text" class="form-control">
|
||||
<div class="sidebar-body">
|
||||
<div class="my-3">
|
||||
<label for="slug" class="form-label">{{ $t("Slug") }}</label>
|
||||
<div class="input-group">
|
||||
<span id="basic-addon3" class="input-group-text">/status/</span>
|
||||
<input id="slug" v-model="config.slug" type="text" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="my-3">
|
||||
<label for="title" class="form-label">{{ $t("Title") }}</label>
|
||||
<input id="title" v-model="config.title" type="text" class="form-control">
|
||||
</div>
|
||||
<div class="my-3">
|
||||
<label for="title" class="form-label">{{ $t("Title") }}</label>
|
||||
<input id="title" v-model="config.title" type="text" class="form-control">
|
||||
</div>
|
||||
|
||||
<div class="my-3">
|
||||
<label for="description" class="form-label">{{ $t("Description") }}</label>
|
||||
<textarea id="description" v-model="config.description" class="form-control"></textarea>
|
||||
</div>
|
||||
<div class="my-3">
|
||||
<label for="description" class="form-label">{{ $t("Description") }}</label>
|
||||
<textarea id="description" v-model="config.description" class="form-control"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="my-3 form-check form-switch">
|
||||
<input id="switch-theme" v-model="config.theme" class="form-check-input" type="checkbox" true-value="dark" false-value="light">
|
||||
<label class="form-check-label" for="switch-theme">{{ $t("Switch to Dark Theme") }}</label>
|
||||
</div>
|
||||
<div class="my-3 form-check form-switch">
|
||||
<input id="switch-theme" v-model="config.theme" class="form-check-input" type="checkbox" true-value="dark" false-value="light">
|
||||
<label class="form-check-label" for="switch-theme">{{ $t("Switch to Dark Theme") }}</label>
|
||||
</div>
|
||||
|
||||
<div class="my-3 form-check form-switch">
|
||||
<input id="showTags" v-model="config.showTags" class="form-check-input" type="checkbox">
|
||||
<label class="form-check-label" for="showTags">{{ $t("Show Tags") }}</label>
|
||||
</div>
|
||||
<div class="my-3 form-check form-switch">
|
||||
<input id="showTags" v-model="config.showTags" class="form-check-input" type="checkbox">
|
||||
<label class="form-check-label" for="showTags">{{ $t("Show Tags") }}</label>
|
||||
</div>
|
||||
|
||||
<div v-if="false" class="my-3">
|
||||
<label for="password" class="form-label">{{ $t("Password") }} <sup>Coming Soon</sup></label>
|
||||
<input id="password" v-model="config.password" disabled type="password" autocomplete="new-password" class="form-control">
|
||||
</div>
|
||||
<div v-if="false" class="my-3">
|
||||
<label for="password" class="form-label">{{ $t("Password") }} <sup>Coming Soon</sup></label>
|
||||
<input id="password" v-model="config.password" disabled type="password" autocomplete="new-password" class="form-control">
|
||||
</div>
|
||||
|
||||
<div v-if="false" class="my-3">
|
||||
<label for="cname" class="form-label">Domain Names <sup>Coming Soon</sup></label>
|
||||
<textarea id="cname" v-model="config.domanNames" rows="3" disabled class="form-control" :placeholder="domainNamesPlaceholder"></textarea>
|
||||
</div>
|
||||
<!-- Domain Name List -->
|
||||
<div class="my-3">
|
||||
<label class="form-label">
|
||||
Domain Names
|
||||
<font-awesome-icon icon="plus-circle" class="btn-add-domain action text-primary" @click="addDomainField" />
|
||||
</label>
|
||||
|
||||
<div class="danger-zone">
|
||||
<button class="btn btn-danger me-2" @click="deleteDialog">
|
||||
<font-awesome-icon icon="trash" />
|
||||
{{ $t("Delete") }}
|
||||
</button>
|
||||
<ul class="list-group domain-name-list">
|
||||
<li v-for="(domain, index) in config.domainNameList" :key="index" class="list-group-item">
|
||||
<input v-model="config.domainNameList[index]" type="text" class="no-bg domain-input" placeholder="example.com" />
|
||||
<font-awesome-icon icon="times" class="action remove ms-2 me-3 text-danger" @click="removeDomain(index)" />
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="danger-zone">
|
||||
<button class="btn btn-danger me-2" @click="deleteDialog">
|
||||
<font-awesome-icon icon="trash" />
|
||||
{{ $t("Delete") }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sidebar Footer -->
|
||||
@@ -55,7 +67,7 @@
|
||||
</button>
|
||||
|
||||
<button class="btn btn-danger me-2" @click="discard">
|
||||
<font-awesome-icon icon="save" />
|
||||
<font-awesome-icon icon="undo" />
|
||||
{{ $t("Discard") }}
|
||||
</button>
|
||||
</div>
|
||||
@@ -120,7 +132,7 @@
|
||||
|
||||
<!-- Incident Date -->
|
||||
<div class="date mt-3">
|
||||
{{ $t("Created") }}: {{ $root.datetime(incident.createdDate) }} ({{ dateFromNow(incident.createdDate) }})<br />
|
||||
{{ $t("Date Created") }}: {{ $root.datetime(incident.createdDate) }} ({{ dateFromNow(incident.createdDate) }})<br />
|
||||
<span v-if="incident.lastUpdatedDate">
|
||||
{{ $t("Last Updated") }}: {{ $root.datetime(incident.lastUpdatedDate) }} ({{ dateFromNow(incident.lastUpdatedDate) }})
|
||||
</span>
|
||||
@@ -259,6 +271,7 @@ const favicon = new Favico({
|
||||
});
|
||||
|
||||
export default {
|
||||
|
||||
components: {
|
||||
PublicGroupList,
|
||||
ImageCropUpload,
|
||||
@@ -278,6 +291,14 @@ export default {
|
||||
next();
|
||||
},
|
||||
|
||||
props: {
|
||||
overrideSlug: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
slug: null,
|
||||
@@ -294,7 +315,6 @@ export default {
|
||||
loadedData: false,
|
||||
baseURL: "",
|
||||
clickedEditButton: false,
|
||||
domainNamesPlaceholder: "domain1.com\ndomain2.com\n..."
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -389,6 +409,22 @@ export default {
|
||||
},
|
||||
watch: {
|
||||
|
||||
/**
|
||||
* If connected to the socket and logged in, request private data of this statusPage
|
||||
* @param connected
|
||||
*/
|
||||
"$root.loggedIn"(loggedIn) {
|
||||
if (loggedIn) {
|
||||
this.$root.getSocket().emit("getStatusPage", this.slug, (res) => {
|
||||
if (res.ok) {
|
||||
this.config = res.config;
|
||||
} else {
|
||||
toast.error(res.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Selected a monitor and add to the list.
|
||||
*/
|
||||
@@ -449,7 +485,7 @@ export default {
|
||||
this.baseURL = getResBaseURL();
|
||||
},
|
||||
async mounted() {
|
||||
this.slug = this.$route.params.slug;
|
||||
this.slug = this.overrideSlug || this.$route.params.slug;
|
||||
|
||||
if (!this.slug) {
|
||||
this.slug = "default";
|
||||
@@ -458,6 +494,10 @@ export default {
|
||||
axios.get("/api/status-page/" + this.slug).then((res) => {
|
||||
this.config = res.data.config;
|
||||
|
||||
if (!this.config.domainNameList) {
|
||||
this.config.domainNameList = [];
|
||||
}
|
||||
|
||||
if (this.config.icon) {
|
||||
this.imgDataUrl = this.config.icon;
|
||||
}
|
||||
@@ -575,6 +615,10 @@ export default {
|
||||
});
|
||||
},
|
||||
|
||||
addDomainField() {
|
||||
this.config.domainNameList.push("");
|
||||
},
|
||||
|
||||
discard() {
|
||||
location.href = "/status/" + this.slug;
|
||||
},
|
||||
@@ -657,6 +701,10 @@ export default {
|
||||
return dayjs.utc(date).fromNow();
|
||||
},
|
||||
|
||||
removeDomain(index) {
|
||||
this.config.domainNameList.splice(index, 1);
|
||||
},
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -705,9 +753,7 @@ h1 {
|
||||
top: 0;
|
||||
width: 300px;
|
||||
height: 100vh;
|
||||
padding: 15px 15px 68px 15px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
|
||||
border-right: 1px solid #ededed;
|
||||
|
||||
.danger-zone {
|
||||
@@ -715,13 +761,25 @@ h1 {
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
.sidebar-body {
|
||||
padding: 0 10px 10px 10px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
height: calc(100% - 70px);
|
||||
}
|
||||
|
||||
.sidebar-footer {
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 15px;
|
||||
position: absolute;
|
||||
border-top: 1px solid #ededed;
|
||||
border-right: 1px solid #ededed;
|
||||
padding: 10px;
|
||||
width: 300px;
|
||||
height: 70px;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
background-color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -808,7 +866,29 @@ footer {
|
||||
}
|
||||
|
||||
.sidebar-footer {
|
||||
border-right-color: $dark-border-color;
|
||||
border-top-color: $dark-border-color;
|
||||
background-color: $dark-header-bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.domain-name-list {
|
||||
li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 0 10px 10px;
|
||||
|
||||
.domain-input {
|
||||
flex-grow: 1;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
color: $dark-font-color;
|
||||
outline: none;
|
||||
|
||||
&::placeholder {
|
||||
color: #1d2634;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user