mirror of
				https://github.com/louislam/uptime-kuma.git
				synced 2025-11-04 13:46:13 +08:00 
			
		
		
		
	[WIP] Checking maintenance time using maintenance_timeslot table
This commit is contained in:
		
							
								
								
									
										46
									
								
								server/model/maintenance_timeslot.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								server/model/maintenance_timeslot.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
				
			|||||||
 | 
					const { BeanModel } = require("redbean-node/dist/bean-model");
 | 
				
			||||||
 | 
					const { R } = require("redbean-node");
 | 
				
			||||||
 | 
					const dayjs = require("dayjs");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MaintenanceTimeslot extends BeanModel {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async toPublicJSON() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async toJSON() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param {Maintenance} maintenance
 | 
				
			||||||
 | 
					     * @param {dayjs} startFrom (For recurring type only) Generate Timeslot from this date, if it is smaller than the current date, it will use the current date instead. As generating a passed timeslot is meaningless.
 | 
				
			||||||
 | 
					     * @param {boolean} removeExist Remove existing timeslot before create
 | 
				
			||||||
 | 
					     * @returns {Promise<void>}
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    static async generateTimeslot(maintenance, startFrom = null, removeExist = false) {
 | 
				
			||||||
 | 
					        if (!startFrom) {
 | 
				
			||||||
 | 
					            startFrom = dayjs();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (removeExist) {
 | 
				
			||||||
 | 
					            await R.exec("DELETE FROM maintenance_timeslot WHERE maintenance_id = ? ", [
 | 
				
			||||||
 | 
					                maintenance.id
 | 
				
			||||||
 | 
					            ]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (maintenance.strategy === "single") {
 | 
				
			||||||
 | 
					            let bean = R.dispense("maintenance_timeslot");
 | 
				
			||||||
 | 
					            bean.maintenance_id = maintenance.id;
 | 
				
			||||||
 | 
					            bean.start_date = maintenance.start_datetime;
 | 
				
			||||||
 | 
					            bean.end_date = maintenance.end_datetime;
 | 
				
			||||||
 | 
					            bean.generated_next = true;
 | 
				
			||||||
 | 
					            await R.store(bean);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            throw new Error("Unknown maintenance strategy");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = MaintenanceTimeslot;
 | 
				
			||||||
@@ -1105,7 +1105,17 @@ class Monitor extends BeanModel {
 | 
				
			|||||||
     * @returns {Promise<boolean>}
 | 
					     * @returns {Promise<boolean>}
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    static async isUnderMaintenance(monitorID) {
 | 
					    static async isUnderMaintenance(monitorID) {
 | 
				
			||||||
        const maintenance = await R.getRow("SELECT COUNT(*) AS count FROM monitor_maintenance mm JOIN maintenance ON mm.maintenance_id = maintenance.id WHERE mm.monitor_id = ? AND datetime(maintenance.start_date) <= datetime('now') AND datetime(maintenance.end_date) >= datetime('now') LIMIT 1", [ monitorID ]);
 | 
					        const maintenance = await R.getRow(`
 | 
				
			||||||
 | 
					            SELECT COUNT(*) AS count
 | 
				
			||||||
 | 
					            FROM monitor_maintenance mm
 | 
				
			||||||
 | 
					            JOIN maintenance
 | 
				
			||||||
 | 
					                ON mm.maintenance_id = maintenance.id
 | 
				
			||||||
 | 
					            JOIN maintenance_timeslot
 | 
				
			||||||
 | 
					                ON maintenance_timeslot.maintenance_id = maintenance.id
 | 
				
			||||||
 | 
					            WHERE mm.monitor_id = ?
 | 
				
			||||||
 | 
					                AND maintenance_timeslot.start_date <= DATETIME('now')
 | 
				
			||||||
 | 
					                AND maintenance_timeslot.end_date >= DATETIME('now')
 | 
				
			||||||
 | 
					            LIMIT 1`, [ monitorID ]);
 | 
				
			||||||
        return maintenance.count !== 0;
 | 
					        return maintenance.count !== 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -273,11 +273,11 @@ class StatusPage extends BeanModel {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            let maintenanceBeanList = R.convertToBeans("maintenance", await R.getAll(`
 | 
					            let maintenanceBeanList = R.convertToBeans("maintenance", await R.getAll(`
 | 
				
			||||||
                SELECT m.*
 | 
					                SELECT m.*
 | 
				
			||||||
            FROM maintenance m
 | 
					                FROM maintenance m, maintenance_status_page msp, maintenance_timeslot
 | 
				
			||||||
            JOIN maintenance_status_page msp
 | 
					                WHERE  msp.maintenance_id = m.id
 | 
				
			||||||
            ON msp.maintenance_id = m.id
 | 
					                AND maintenance_timeslot.maintenance.id = m.id
 | 
				
			||||||
            WHERE datetime(m.start_date) <= datetime('now')
 | 
					                AND maintenance_timeslot.start_date <= DATETIME('now')
 | 
				
			||||||
              AND datetime(m.end_date) >= datetime('now')
 | 
					                AND maintenance_timeslot.end_date >= DATETIME('now')
 | 
				
			||||||
                AND msp.status_page_id = ?
 | 
					                AND msp.status_page_id = ?
 | 
				
			||||||
                ORDER BY m.end_date
 | 
					                ORDER BY m.end_date
 | 
				
			||||||
            `, [ statusPageId ]));
 | 
					            `, [ statusPageId ]));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,7 @@ const server = UptimeKumaServer.getInstance();
 | 
				
			|||||||
const dayjs = require("dayjs");
 | 
					const dayjs = require("dayjs");
 | 
				
			||||||
const utc = require("dayjs/plugin/utc");
 | 
					const utc = require("dayjs/plugin/utc");
 | 
				
			||||||
let timezone = require("dayjs/plugin/timezone");
 | 
					let timezone = require("dayjs/plugin/timezone");
 | 
				
			||||||
 | 
					const MaintenanceTimeslot = require("../model/maintenance_timeslot");
 | 
				
			||||||
dayjs.extend(utc);
 | 
					dayjs.extend(utc);
 | 
				
			||||||
dayjs.extend(timezone);
 | 
					dayjs.extend(timezone);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -26,6 +27,7 @@ module.exports.maintenanceSocketHandler = (socket) => {
 | 
				
			|||||||
            let bean = Maintenance.jsonToBean(R.dispense("maintenance"), maintenance, timezone);
 | 
					            let bean = Maintenance.jsonToBean(R.dispense("maintenance"), maintenance, timezone);
 | 
				
			||||||
            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 server.sendMaintenanceList(socket);
 | 
					            await server.sendMaintenanceList(socket);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -57,6 +59,7 @@ module.exports.maintenanceSocketHandler = (socket) => {
 | 
				
			|||||||
            Maintenance.jsonToBean(bean, maintenance, timezone);
 | 
					            Maintenance.jsonToBean(bean, maintenance, timezone);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            await R.store(bean);
 | 
					            await R.store(bean);
 | 
				
			||||||
 | 
					            await MaintenanceTimeslot.generateTimeslot(bean, null, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            await server.sendMaintenanceList(socket);
 | 
					            await server.sendMaintenanceList(socket);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,7 +47,7 @@ export default {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (this.status === 3) {
 | 
					            if (this.status === 3) {
 | 
				
			||||||
                return this.$t("Maintenance");
 | 
					                return this.$t("statusMaintenance");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return this.$t("Unknown");
 | 
					            return this.$t("Unknown");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,7 @@ export default {
 | 
				
			|||||||
        uptime() {
 | 
					        uptime() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (this.type === "maintenance") {
 | 
					            if (this.type === "maintenance") {
 | 
				
			||||||
                return this.$t("Maintenance");
 | 
					                return this.$t("statusMaintenance");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let key = this.monitor.id + "_" + this.type;
 | 
					            let key = this.monitor.id + "_" + this.type;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,6 +10,7 @@ export default {
 | 
				
			|||||||
    maxRedirectDescription: "Maximum number of redirects to follow. Set to 0 to disable redirects.",
 | 
					    maxRedirectDescription: "Maximum number of redirects to follow. Set to 0 to disable redirects.",
 | 
				
			||||||
    acceptedStatusCodesDescription: "Select status codes which are considered as a successful response.",
 | 
					    acceptedStatusCodesDescription: "Select status codes which are considered as a successful response.",
 | 
				
			||||||
    Maintenance: "Maintenance",
 | 
					    Maintenance: "Maintenance",
 | 
				
			||||||
 | 
					    statusMaintenance: "Maintenance",
 | 
				
			||||||
    "Schedule maintenance": "Schedule maintenance",
 | 
					    "Schedule maintenance": "Schedule maintenance",
 | 
				
			||||||
    "Affected Monitors": "Affected Monitors",
 | 
					    "Affected Monitors": "Affected Monitors",
 | 
				
			||||||
    "Pick Affected Monitors...": "Pick Affected Monitors...",
 | 
					    "Pick Affected Monitors...": "Pick Affected Monitors...",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -380,4 +380,6 @@ export default {
 | 
				
			|||||||
    proxyDescription: "必須將代理伺服器指派給監測器才能運作。",
 | 
					    proxyDescription: "必須將代理伺服器指派給監測器才能運作。",
 | 
				
			||||||
    enableProxyDescription: "此代理伺服器在啟用前不會在監測器上生效,您可以藉由控制啟用狀態來暫時對所有的監測器停用代理伺服器。",
 | 
					    enableProxyDescription: "此代理伺服器在啟用前不會在監測器上生效,您可以藉由控制啟用狀態來暫時對所有的監測器停用代理伺服器。",
 | 
				
			||||||
    setAsDefaultProxyDescription: "預設情況下,新監測器將啟用此代理伺服器。您仍可分別停用各監測器的代理伺服器。",
 | 
					    setAsDefaultProxyDescription: "預設情況下,新監測器將啟用此代理伺服器。您仍可分別停用各監測器的代理伺服器。",
 | 
				
			||||||
 | 
					    Maintenance: "維護",
 | 
				
			||||||
 | 
					    statusMaintenance: "維護中",
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -588,7 +588,7 @@ export default {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                if (this.monitorList[monitorID].maintenance) {
 | 
					                if (this.monitorList[monitorID].maintenance) {
 | 
				
			||||||
                    result[monitorID] = {
 | 
					                    result[monitorID] = {
 | 
				
			||||||
                        text: this.$t("Maintenance"),
 | 
					                        text: this.$t("statusMaintenance"),
 | 
				
			||||||
                        color: "maintenance",
 | 
					                        color: "maintenance",
 | 
				
			||||||
                    };
 | 
					                    };
 | 
				
			||||||
                } else if (! lastHeartBeat) {
 | 
					                } else if (! lastHeartBeat) {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user