From d893231c6d4046865f752b5c6d99a6dd623bbf27 Mon Sep 17 00:00:00 2001 From: Dorian Grasset Date: Wed, 14 Jan 2026 09:12:19 +0100 Subject: [PATCH] feat(maintenance): add quick duration buttons and pre-fill datetime fields (#6718) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Frank Elsinga --- config/vite.config.js | 3 + src/components/Uptime.vue | 6 +- src/components/settings/Notifications.vue | 4 +- src/lang/en.json | 10 +- src/pages/EditMaintenance.vue | 156 +++++++++++++++++++++- 5 files changed, 166 insertions(+), 13 deletions(-) diff --git a/config/vite.config.js b/config/vite.config.js index eaba9b342..91aa3cbcd 100644 --- a/config/vite.config.js +++ b/config/vite.config.js @@ -36,6 +36,9 @@ export default defineConfig({ srcDir: "src", filename: "serviceWorker.ts", strategies: "injectManifest", + injectManifest: { + maximumFileSizeToCacheInBytes: 3 * 1024 * 1024, // 3 MiB + }, }), ], css: { diff --git a/src/components/Uptime.vue b/src/components/Uptime.vue index c697ad6fc..22db8b6b9 100644 --- a/src/components/Uptime.vue +++ b/src/components/Uptime.vue @@ -85,12 +85,12 @@ export default { title() { if (this.type === "1y") { - return `1 ${this.$tc("year", 1)}`; + return this.$tc("years", 1, { n: 1 }); } if (this.type === "720") { - return `30 ${this.$tc("day", 30)}`; + return this.$tc("days", 30, { n: 30 }); } - return `24 ${this.$tc("hour", 24)}`; + return this.$tc("hours", 24, { n: 24 }); }, }, }; diff --git a/src/components/settings/Notifications.vue b/src/components/settings/Notifications.vue index 6ecae9d18..7af81165e 100644 --- a/src/components/settings/Notifications.vue +++ b/src/components/settings/Notifications.vue @@ -79,7 +79,7 @@ - - - + + @@ -511,6 +604,22 @@ export default { hasStatusPages() { return this.showOnAllPages || this.selectedStatusPages.length > 0; }, + + /** + * Calculate the current duration in minutes between start and end dates + * @returns {number|null} Duration in minutes, or null if dates are invalid + */ + currentDurationMinutes() { + if (!this.maintenance.dateRange?.[0] || !this.maintenance.dateRange?.[1]) { + return null; + } + const start = new Date(this.maintenance.dateRange[0]); + const end = new Date(this.maintenance.dateRange[1]); + if (isNaN(start.getTime()) || isNaN(end.getTime())) { + return null; + } + return Math.round((end.getTime() - start.getTime()) / 60000); + }, }, watch: { "$route.fullPath"() { @@ -570,6 +679,19 @@ export default { this.selectedStatusPages = []; if (this.isAdd) { + // Get current date/time in local timezone + const now = new Date(); + const oneHourLater = new Date(now.getTime() + 60 * 60000); + + const formatDateTime = (date) => { + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, "0"); + const day = String(date.getDate()).padStart(2, "0"); + const hours = String(date.getHours()).padStart(2, "0"); + const minutes = String(date.getMinutes()).padStart(2, "0"); + return `${year}-${month}-${day}T${hours}:${minutes}`; + }; + this.maintenance = { title: "", description: "", @@ -578,7 +700,7 @@ export default { cron: "30 3 * * *", durationMinutes: 60, intervalDay: 1, - dateRange: [], + dateRange: [formatDateTime(now), formatDateTime(oneHourLater)], timeRange: [ { hours: 2, @@ -591,7 +713,7 @@ export default { ], weekdays: [], daysOfMonth: [], - timezoneOption: null, + timezoneOption: "SAME_AS_SERVER", }; } else if (this.isEdit || this.isClone) { this.$root.getSocket().emit("getMaintenance", this.$route.params.id, (res) => { @@ -655,6 +777,30 @@ export default { } }, + /** + * Set quick duration for single maintenance + * Calculates end time based on start time + duration in minutes + * @param {number} minutes Duration in minutes + * @returns {void} + */ + setQuickDuration(minutes) { + if (!this.maintenance.dateRange[0]) { + this.$root.toastError(this.$t("Please set start time first")); + return; + } + + const startDate = new Date(this.maintenance.dateRange[0]); + const endDate = new Date(startDate.getTime() + minutes * 60000); + + const year = endDate.getFullYear(); + const month = String(endDate.getMonth() + 1).padStart(2, "0"); + const day = String(endDate.getDate()).padStart(2, "0"); + const hours = String(endDate.getHours()).padStart(2, "0"); + const mins = String(endDate.getMinutes()).padStart(2, "0"); + + this.maintenance.dateRange[1] = `${year}-${month}-${day}T${hours}:${mins}`; + }, + /** * Handle form submission - show confirmation if no monitors selected * @returns {void}