mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-12-18 12:14:41 -05:00
WIP
This commit is contained in:
parent
539683f8e9
commit
c1ccaa7a9f
2
package-lock.json
generated
2
package-lock.json
generated
@ -69,7 +69,7 @@
|
|||||||
"@vitejs/plugin-legacy": "~2.1.0",
|
"@vitejs/plugin-legacy": "~2.1.0",
|
||||||
"@vitejs/plugin-vue": "~3.1.0",
|
"@vitejs/plugin-vue": "~3.1.0",
|
||||||
"@vue/compiler-sfc": "~3.2.36",
|
"@vue/compiler-sfc": "~3.2.36",
|
||||||
"@vuepic/vue-datepicker": "^3.4.8",
|
"@vuepic/vue-datepicker": "~3.4.8",
|
||||||
"aedes": "^0.46.3",
|
"aedes": "^0.46.3",
|
||||||
"babel-plugin-rewire": "~1.2.0",
|
"babel-plugin-rewire": "~1.2.0",
|
||||||
"bootstrap": "5.1.3",
|
"bootstrap": "5.1.3",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
const { BeanModel } = require("redbean-node/dist/bean-model");
|
const { BeanModel } = require("redbean-node/dist/bean-model");
|
||||||
const { parseTimeObject, parseTimeFromTimeObject, isoToUTCDateTime, utcToISODateTime, SQL_DATETIME_FORMAT, utcToLocal, localToUTC } = require("../../src/util");
|
const { parseTimeObject, parseTimeFromTimeObject, utcToLocal, localToUTC } = require("../../src/util");
|
||||||
const { isArray } = require("chart.js/helpers");
|
const { isArray } = require("chart.js/helpers");
|
||||||
const { timeObjectToUTC, timeObjectToLocal } = require("../util-server");
|
const { timeObjectToUTC, timeObjectToLocal } = require("../util-server");
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ class Maintenance extends BeanModel {
|
|||||||
* @param {string} timezone If not specified, the timeRange will be in UTC
|
* @param {string} timezone If not specified, the timeRange will be in UTC
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
async toPublicJSON(timezone = null) {
|
async toPublicJSON() {
|
||||||
|
|
||||||
let dateRange = [];
|
let dateRange = [];
|
||||||
if (this.start_date) {
|
if (this.start_date) {
|
||||||
@ -22,21 +22,11 @@ class Maintenance extends BeanModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let timeRange = [];
|
let timeRange = [];
|
||||||
let startTime = parseTimeObject(this.start_time);
|
let startTime = timeObjectToLocal(parseTimeObject(this.start_time));
|
||||||
timeRange.push(startTime);
|
timeRange.push(startTime);
|
||||||
let endTime = parseTimeObject(this.end_time);
|
let endTime = timeObjectToLocal(parseTimeObject(this.end_time));
|
||||||
timeRange.push(endTime);
|
timeRange.push(endTime);
|
||||||
|
|
||||||
// Apply timezone offset
|
|
||||||
if (timezone) {
|
|
||||||
if (this.start_time) {
|
|
||||||
timeObjectToLocal(startTime, timezone);
|
|
||||||
}
|
|
||||||
if (this.end_time) {
|
|
||||||
timeObjectToLocal(endTime, timezone);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let obj = {
|
let obj = {
|
||||||
id: this.id,
|
id: this.id,
|
||||||
title: this.title,
|
title: this.title,
|
||||||
@ -70,18 +60,16 @@ class Maintenance extends BeanModel {
|
|||||||
return this.toPublicJSON(timezone);
|
return this.toPublicJSON(timezone);
|
||||||
}
|
}
|
||||||
|
|
||||||
static jsonToBean(bean, obj, timezone) {
|
static jsonToBean(bean, obj) {
|
||||||
if (obj.id) {
|
if (obj.id) {
|
||||||
bean.id = obj.id;
|
bean.id = obj.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply timezone offset to timeRange, as it cannot apply automatically.
|
// Apply timezone offset to timeRange, as it cannot apply automatically.
|
||||||
if (timezone) {
|
if (obj.timeRange[0]) {
|
||||||
if (obj.timeRange[0]) {
|
timeObjectToUTC(obj.timeRange[0]);
|
||||||
timeObjectToUTC(obj.timeRange[0], timezone);
|
if (obj.timeRange[1]) {
|
||||||
if (obj.timeRange[1]) {
|
timeObjectToUTC(obj.timeRange[1]);
|
||||||
timeObjectToUTC(obj.timeRange[1], timezone);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +106,7 @@ class Maintenance extends BeanModel {
|
|||||||
(maintenance_timeslot.start_date <= DATETIME('now')
|
(maintenance_timeslot.start_date <= DATETIME('now')
|
||||||
AND maintenance_timeslot.end_date >= DATETIME('now')
|
AND maintenance_timeslot.end_date >= DATETIME('now')
|
||||||
AND maintenance.active = 1)
|
AND maintenance.active = 1)
|
||||||
AND
|
OR
|
||||||
(maintenance.strategy = 'manual' AND active = 1)
|
(maintenance.strategy = 'manual' AND active = 1)
|
||||||
|
|
||||||
`;
|
`;
|
||||||
|
@ -40,6 +40,12 @@ class MaintenanceTimeslot extends BeanModel {
|
|||||||
bean.end_date = maintenance.end_date;
|
bean.end_date = maintenance.end_date;
|
||||||
bean.generated_next = true;
|
bean.generated_next = true;
|
||||||
await R.store(bean);
|
await R.store(bean);
|
||||||
|
} else if (maintenance.strategy === "recurring-interval") {
|
||||||
|
// TODO
|
||||||
|
} else if (maintenance.strategy === "recurring-weekday") {
|
||||||
|
// TODO
|
||||||
|
} else if (maintenance.strategy === "recurring-day-of-month") {
|
||||||
|
// TODO
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Unknown maintenance strategy");
|
throw new Error("Unknown maintenance strategy");
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ const apicache = require("../modules/apicache");
|
|||||||
const { UptimeKumaServer } = require("../uptime-kuma-server");
|
const { UptimeKumaServer } = require("../uptime-kuma-server");
|
||||||
const Maintenance = require("../model/maintenance");
|
const Maintenance = require("../model/maintenance");
|
||||||
const server = UptimeKumaServer.getInstance();
|
const server = UptimeKumaServer.getInstance();
|
||||||
const dayjs = require("dayjs");
|
|
||||||
const MaintenanceTimeslot = require("../model/maintenance_timeslot");
|
const MaintenanceTimeslot = require("../model/maintenance_timeslot");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,13 +13,13 @@ const MaintenanceTimeslot = require("../model/maintenance_timeslot");
|
|||||||
*/
|
*/
|
||||||
module.exports.maintenanceSocketHandler = (socket) => {
|
module.exports.maintenanceSocketHandler = (socket) => {
|
||||||
// Add a new maintenance
|
// Add a new maintenance
|
||||||
socket.on("addMaintenance", async (maintenance, timezone, callback) => {
|
socket.on("addMaintenance", async (maintenance, callback) => {
|
||||||
try {
|
try {
|
||||||
checkLogin(socket);
|
checkLogin(socket);
|
||||||
|
|
||||||
log.debug("maintenance", maintenance);
|
log.debug("maintenance", maintenance);
|
||||||
|
|
||||||
let bean = Maintenance.jsonToBean(R.dispense("maintenance"), maintenance, timezone);
|
let bean = Maintenance.jsonToBean(R.dispense("maintenance"), maintenance);
|
||||||
bean.user_id = socket.userID;
|
bean.user_id = socket.userID;
|
||||||
let maintenanceID = await R.store(bean);
|
let maintenanceID = await R.store(bean);
|
||||||
await MaintenanceTimeslot.generateTimeslot(bean);
|
await MaintenanceTimeslot.generateTimeslot(bean);
|
||||||
@ -42,7 +41,7 @@ module.exports.maintenanceSocketHandler = (socket) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Edit a maintenance
|
// Edit a maintenance
|
||||||
socket.on("editMaintenance", async (maintenance, timezone, callback) => {
|
socket.on("editMaintenance", async (maintenance, callback) => {
|
||||||
try {
|
try {
|
||||||
checkLogin(socket);
|
checkLogin(socket);
|
||||||
|
|
||||||
@ -52,7 +51,7 @@ module.exports.maintenanceSocketHandler = (socket) => {
|
|||||||
throw new Error("Permission denied.");
|
throw new Error("Permission denied.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Maintenance.jsonToBean(bean, maintenance, timezone);
|
Maintenance.jsonToBean(bean, maintenance);
|
||||||
|
|
||||||
await R.store(bean);
|
await R.store(bean);
|
||||||
await MaintenanceTimeslot.generateTimeslot(bean, null, true);
|
await MaintenanceTimeslot.generateTimeslot(bean, null, true);
|
||||||
@ -142,7 +141,7 @@ module.exports.maintenanceSocketHandler = (socket) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("getMaintenance", async (maintenanceID, timezone, callback) => {
|
socket.on("getMaintenance", async (maintenanceID, callback) => {
|
||||||
try {
|
try {
|
||||||
checkLogin(socket);
|
checkLogin(socket);
|
||||||
|
|
||||||
@ -155,7 +154,7 @@ module.exports.maintenanceSocketHandler = (socket) => {
|
|||||||
|
|
||||||
callback({
|
callback({
|
||||||
ok: true,
|
ok: true,
|
||||||
maintenance: await bean.toJSON(timezone),
|
maintenance: await bean.toJSON(),
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -648,8 +648,14 @@ module.exports.send403 = (res, msg = "") => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function timeObjectConvertTimezone(obj, timezone, timeObjectToUTC = true) {
|
function timeObjectConvertTimezone(obj, timezone, timeObjectToUTC = true) {
|
||||||
// e.g. +08:00
|
let offsetString;
|
||||||
let offsetString = dayjs().tz(timezone).format("Z");
|
|
||||||
|
if (timezone) {
|
||||||
|
offsetString = dayjs().tz(timezone).format("Z");
|
||||||
|
} else {
|
||||||
|
offsetString = dayjs().format("Z");
|
||||||
|
}
|
||||||
|
|
||||||
let hours = parseInt(offsetString.substring(1, 3));
|
let hours = parseInt(offsetString.substring(1, 3));
|
||||||
let minutes = parseInt(offsetString.substring(4, 6));
|
let minutes = parseInt(offsetString.substring(4, 6));
|
||||||
|
|
||||||
@ -680,10 +686,22 @@ function timeObjectConvertTimezone(obj, timezone, timeObjectToUTC = true) {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.timeObjectToUTC = (obj, timezone) => {
|
/**
|
||||||
|
*
|
||||||
|
* @param {object} obj
|
||||||
|
* @param {string} timezone
|
||||||
|
* @returns {object}
|
||||||
|
*/
|
||||||
|
module.exports.timeObjectToUTC = (obj, timezone = undefined) => {
|
||||||
return timeObjectConvertTimezone(obj, timezone, true);
|
return timeObjectConvertTimezone(obj, timezone, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.timeObjectToLocal = (obj, timezone) => {
|
/**
|
||||||
|
*
|
||||||
|
* @param {object} obj
|
||||||
|
* @param {string} timezone
|
||||||
|
* @returns {object}
|
||||||
|
*/
|
||||||
|
module.exports.timeObjectToLocal = (obj, timezone = undefined) => {
|
||||||
return timeObjectConvertTimezone(obj, timezone, false);
|
return timeObjectConvertTimezone(obj, timezone, false);
|
||||||
};
|
};
|
||||||
|
@ -630,4 +630,5 @@ export default {
|
|||||||
lastDay2: "2nd Last Day of Month",
|
lastDay2: "2nd Last Day of Month",
|
||||||
lastDay3: "3rd Last Day of Month",
|
lastDay3: "3rd Last Day of Month",
|
||||||
lastDay4: "4th Last Day of Month",
|
lastDay4: "4th Last Day of Month",
|
||||||
|
"No Maintenance": "No Maintenance",
|
||||||
};
|
};
|
||||||
|
@ -200,7 +200,8 @@
|
|||||||
:monthChangeOnScroll="false"
|
:monthChangeOnScroll="false"
|
||||||
:minDate="minDate"
|
:minDate="minDate"
|
||||||
:enableTimePicker="false"
|
:enableTimePicker="false"
|
||||||
:utc="true"
|
format="yyyy-MM-dd"
|
||||||
|
modelType="yyyy-MM-dd HH:mm:ss"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -356,9 +357,6 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
init() {
|
init() {
|
||||||
// Use browser's timezone!
|
|
||||||
let timezone = dayjs.tz.guess();
|
|
||||||
|
|
||||||
this.affectedMonitors = [];
|
this.affectedMonitors = [];
|
||||||
this.selectedStatusPages = [];
|
this.selectedStatusPages = [];
|
||||||
|
|
||||||
@ -381,7 +379,7 @@ export default {
|
|||||||
daysOfMonth: [],
|
daysOfMonth: [],
|
||||||
};
|
};
|
||||||
} else if (this.isEdit) {
|
} else if (this.isEdit) {
|
||||||
this.$root.getSocket().emit("getMaintenance", this.$route.params.id, timezone, (res) => {
|
this.$root.getSocket().emit("getMaintenance", this.$route.params.id, (res) => {
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
this.maintenance = res.maintenance;
|
this.maintenance = res.maintenance;
|
||||||
|
|
||||||
@ -440,11 +438,8 @@ export default {
|
|||||||
this.maintenance.end_date = this.$root.toUTC(this.maintenance.end_date);
|
this.maintenance.end_date = this.$root.toUTC(this.maintenance.end_date);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Use browser's timezone!
|
|
||||||
let timezone = dayjs.tz.guess();
|
|
||||||
|
|
||||||
if (this.isAdd) {
|
if (this.isAdd) {
|
||||||
this.$root.addMaintenance(this.maintenance, timezone, async (res) => {
|
this.$root.addMaintenance(this.maintenance, async (res) => {
|
||||||
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, () => {
|
||||||
@ -461,7 +456,7 @@ export default {
|
|||||||
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.$root.getSocket().emit("editMaintenance", this.maintenance, timezone, async (res) => {
|
this.$root.getSocket().emit("editMaintenance", this.maintenance, async (res) => {
|
||||||
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, () => {
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
<div class="shadow-box">
|
<div class="shadow-box">
|
||||||
<span v-if="Object.keys(sortedMaintenanceList).length === 0" class="d-flex align-items-center justify-content-center my-3">
|
<span v-if="Object.keys(sortedMaintenanceList).length === 0" class="d-flex align-items-center justify-content-center my-3">
|
||||||
{{ $t("No maintenance") }}
|
{{ $t("No Maintenance") }}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@ -34,9 +34,19 @@
|
|||||||
|
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<router-link v-if="false" :to="maintenanceURL(item.id)" class="btn btn-light">{{ $t("Details") }}</router-link>
|
<router-link v-if="false" :to="maintenanceURL(item.id)" class="btn btn-light">{{ $t("Details") }}</router-link>
|
||||||
|
|
||||||
|
<button v-if="item.active" class="btn btn-light" @click="pauseDialog">
|
||||||
|
<font-awesome-icon icon="pause" /> {{ $t("Pause") }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button v-if="!item.active" class="btn btn-primary" @click="resumeMaintenance">
|
||||||
|
<font-awesome-icon icon="play" /> {{ $t("Resume") }}
|
||||||
|
</button>
|
||||||
|
|
||||||
<router-link :to="'/maintenance/edit/' + item.id" class="btn btn-secondary">
|
<router-link :to="'/maintenance/edit/' + item.id" class="btn btn-secondary">
|
||||||
<font-awesome-icon icon="edit" /> {{ $t("Edit") }}
|
<font-awesome-icon icon="edit" /> {{ $t("Edit") }}
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|
||||||
<button class="btn btn-danger" @click="deleteDialog(item.id)">
|
<button class="btn btn-danger" @click="deleteDialog(item.id)">
|
||||||
<font-awesome-icon icon="trash" /> {{ $t("Delete") }}
|
<font-awesome-icon icon="trash" /> {{ $t("Delete") }}
|
||||||
</button>
|
</button>
|
||||||
@ -48,6 +58,10 @@
|
|||||||
<a href="https://github.com/louislam/uptime-kuma/wiki/Maintenance" target="_blank">Learn More</a>
|
<a href="https://github.com/louislam/uptime-kuma/wiki/Maintenance" target="_blank">Learn More</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<Confirm ref="confirmPause" :yes-text="$t('Yes')" :no-text="$t('No')" @yes="pauseMaintenance">
|
||||||
|
{{ $t("pauseMaintenanceMsg") }}
|
||||||
|
</Confirm>
|
||||||
|
|
||||||
<Confirm ref="confirmDelete" btn-style="btn-danger" :yes-text="$t('Yes')" :no-text="$t('No')" @yes="deleteMaintenance">
|
<Confirm ref="confirmDelete" btn-style="btn-danger" :yes-text="$t('Yes')" :no-text="$t('No')" @yes="deleteMaintenance">
|
||||||
{{ $t("deleteMaintenanceMsg") }}
|
{{ $t("deleteMaintenanceMsg") }}
|
||||||
</Confirm>
|
</Confirm>
|
||||||
@ -148,6 +162,33 @@ export default {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show dialog to confirm pause
|
||||||
|
*/
|
||||||
|
pauseDialog() {
|
||||||
|
this.$refs.confirmPause.show();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pause maintenance
|
||||||
|
*/
|
||||||
|
pauseMonitor() {
|
||||||
|
return;
|
||||||
|
this.$root.getSocket().emit("pauseMaintenance", selectedMaintenanceID, (res) => {
|
||||||
|
this.$root.toastRes(res);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resume maintenance
|
||||||
|
*/
|
||||||
|
resumeMaintenance() {
|
||||||
|
return;
|
||||||
|
this.$root.getSocket().emit("resumeMaintenance", selectedMaintenanceID, (res) => {
|
||||||
|
this.$root.toastRes(res);
|
||||||
|
});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
Loading…
Reference in New Issue
Block a user