mirror of
				https://github.com/louislam/uptime-kuma.git
				synced 2025-11-04 13:46:13 +08:00 
			
		
		
		
	Move maintenance under /maintenance
				
					
				
			This commit is contained in:
		@@ -1,13 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="shadow-box mb-3" :style="boxStyle">
 | 
			
		||||
        <div class="list-header">
 | 
			
		||||
            <div class="search-wrapper float-start" style="margin-left: 5px;">
 | 
			
		||||
                <font-awesome-icon icon="filter" />
 | 
			
		||||
                <select v-model="selectedList" class="form-control" style="margin-left: 5px;">
 | 
			
		||||
                    <option value="monitor" selected>{{ $t('Monitors') }}</option>
 | 
			
		||||
                    <option value="maintenance">{{ $t('Maintenance') }}</option>
 | 
			
		||||
                </select>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="placeholder"></div>
 | 
			
		||||
            <div class="search-wrapper">
 | 
			
		||||
                <a v-if="searchText == ''" class="search-icon">
 | 
			
		||||
                    <font-awesome-icon icon="search" />
 | 
			
		||||
@@ -21,39 +15,13 @@
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="monitor-list" :class="{ scrollbar: scrollbar }">
 | 
			
		||||
            <div v-if="Object.keys($root.monitorList).length === 0 && selectedList === 'monitor'" class="text-center mt-3">
 | 
			
		||||
            <div v-if="Object.keys($root.monitorList).length === 0" class="text-center mt-3">
 | 
			
		||||
                {{ $t("No Monitors, please") }} <router-link to="/add">{{ $t("add one") }}</router-link>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div v-if="Object.keys($root.maintenanceList).length === 0 && selectedList === 'maintenance'" class="text-center mt-3">
 | 
			
		||||
                {{ $t("No Maintenance, please") }} <router-link to="/addMaintenance">{{ $t("add one") }}</router-link>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <template v-if="selectedList === 'maintenance'">
 | 
			
		||||
                <router-link
 | 
			
		||||
                    v-for="(item, index) in sortedMaintenanceList" :key="index" :to="maintenanceURL(item.id)"
 | 
			
		||||
                    class="item" :class="{ 'disabled': !$root.isActiveMaintenance(item.end_date) }"
 | 
			
		||||
                >
 | 
			
		||||
            <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">
 | 
			
		||||
                            <div class="info">
 | 
			
		||||
                                <Uptime :monitor="null" type="maintenance" :pill="true" />
 | 
			
		||||
                                {{ item.title }}
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </router-link>
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
            <template v-if="selectedList === 'monitor'">
 | 
			
		||||
                <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="{ 'monitor-item': $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 }}
 | 
			
		||||
@@ -62,10 +30,7 @@
 | 
			
		||||
                            <Tag v-for="tag in item.tags" :key="tag" :item="tag" :size="'sm'" />
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                        <div
 | 
			
		||||
                            v-show="$root.userHeartbeatBar == 'normal'" :key="$root.userHeartbeatBar"
 | 
			
		||||
                            class="col-3 col-md-4"
 | 
			
		||||
                        >
 | 
			
		||||
                    <div v-show="$root.userHeartbeatBar == 'normal'" :key="$root.userHeartbeatBar" class="col-3 col-md-4">
 | 
			
		||||
                        <HeartbeatBar size="small" :monitor-id="item.id" />
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
@@ -76,7 +41,6 @@
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </router-link>
 | 
			
		||||
            </template>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</template>
 | 
			
		||||
@@ -85,7 +49,7 @@
 | 
			
		||||
import HeartbeatBar from "../components/HeartbeatBar.vue";
 | 
			
		||||
import Tag from "../components/Tag.vue";
 | 
			
		||||
import Uptime from "../components/Uptime.vue";
 | 
			
		||||
import { getMaintenanceRelativeURL, getMonitorRelativeURL } from "../util.ts";
 | 
			
		||||
import { getMonitorRelativeURL } from "../util.ts";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
    components: {
 | 
			
		||||
@@ -102,7 +66,6 @@ export default {
 | 
			
		||||
    data() {
 | 
			
		||||
        return {
 | 
			
		||||
            searchText: "",
 | 
			
		||||
            selectedList: "monitor",
 | 
			
		||||
            windowTop: 0,
 | 
			
		||||
        };
 | 
			
		||||
    },
 | 
			
		||||
@@ -125,56 +88,6 @@ export default {
 | 
			
		||||
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        sortedMaintenanceList() {
 | 
			
		||||
            let result = Object.values(this.$root.maintenanceList);
 | 
			
		||||
 | 
			
		||||
            result.sort((m1, m2) => {
 | 
			
		||||
 | 
			
		||||
                if (this.$root.isActiveMaintenance(m1.end_date) !== this.$root.isActiveMaintenance(m2.end_date)) {
 | 
			
		||||
                    if (!this.$root.isActiveMaintenance(m2.end_date)) {
 | 
			
		||||
                        return -1;
 | 
			
		||||
                    }
 | 
			
		||||
                    if (!this.$root.isActiveMaintenance(m1.end_date)) {
 | 
			
		||||
                        return 1;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (this.$root.isActiveMaintenance(m1.end_date) && this.$root.isActiveMaintenance(m2.end_date)) {
 | 
			
		||||
                    if (Date.parse(m1.end_date) < Date.parse(m2.end_date)) {
 | 
			
		||||
                        return -1;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (Date.parse(m2.end_date) < Date.parse(m1.end_date)) {
 | 
			
		||||
                        return 1;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (!this.$root.isActiveMaintenance(m1.end_date) && !this.$root.isActiveMaintenance(m2.end_date)) {
 | 
			
		||||
                    if (Date.parse(m1.end_date) < Date.parse(m2.end_date)) {
 | 
			
		||||
                        return 1;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (Date.parse(m2.end_date) < Date.parse(m1.end_date)) {
 | 
			
		||||
                        return -1;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                return m1.title.localeCompare(m2.title);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            // Simple filter by search text
 | 
			
		||||
            // finds maintenance name
 | 
			
		||||
            if (this.searchText !== "") {
 | 
			
		||||
                const loweredSearchText = this.searchText.toLowerCase();
 | 
			
		||||
                result = result.filter(maintenance => {
 | 
			
		||||
                    return maintenance.title.toLowerCase().includes(loweredSearchText)
 | 
			
		||||
                        || maintenance.description.toLowerCase().includes(loweredSearchText);
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return result;
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        sortedMonitorList() {
 | 
			
		||||
            let result = Object.values(this.$root.monitorList);
 | 
			
		||||
 | 
			
		||||
@@ -240,9 +153,6 @@ export default {
 | 
			
		||||
        monitorURL(id) {
 | 
			
		||||
            return getMonitorRelativeURL(id);
 | 
			
		||||
        },
 | 
			
		||||
        maintenanceURL(id) {
 | 
			
		||||
            return getMaintenanceRelativeURL(id);
 | 
			
		||||
        },
 | 
			
		||||
        /** Clear the search bar */
 | 
			
		||||
        clearSearchText() {
 | 
			
		||||
            this.searchText = "";
 | 
			
		||||
@@ -319,11 +229,4 @@ export default {
 | 
			
		||||
    margin-top: 5px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.bg-maintenance {
 | 
			
		||||
    background-color: $maintenance;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
select {
 | 
			
		||||
    text-align: center;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
 
 | 
			
		||||
@@ -37,19 +37,32 @@
 | 
			
		||||
                            <div class="profile-pic">{{ $root.usernameFirstChar }}</div>
 | 
			
		||||
                            <font-awesome-icon icon="angle-down" />
 | 
			
		||||
                        </div>
 | 
			
		||||
 | 
			
		||||
                        <!-- Header's Dropdown Menu -->
 | 
			
		||||
                        <ul class="dropdown-menu">
 | 
			
		||||
                            <!-- Username -->
 | 
			
		||||
                            <li>
 | 
			
		||||
                                <i18n-t v-if="$root.username != null" tag="span" keypath="signedInDisp" class="dropdown-item-text">
 | 
			
		||||
                                    <strong>{{ $root.username }}</strong>
 | 
			
		||||
                                </i18n-t>
 | 
			
		||||
                                <span v-if="$root.username == null" class="dropdown-item-text">{{ $t("signedInDispDisabled") }}</span>
 | 
			
		||||
                            </li>
 | 
			
		||||
 | 
			
		||||
                            <li><hr class="dropdown-divider"></li>
 | 
			
		||||
 | 
			
		||||
                            <!-- Functions -->
 | 
			
		||||
                            <li>
 | 
			
		||||
                                <router-link to="/maintenance" class="dropdown-item" :class="{ active: $route.path.includes('manage-maintenance') }">
 | 
			
		||||
                                    <font-awesome-icon icon="wrench" /> {{ $t("Maintenance") }}
 | 
			
		||||
                                </router-link>
 | 
			
		||||
                            </li>
 | 
			
		||||
 | 
			
		||||
                            <li>
 | 
			
		||||
                                <router-link to="/settings" class="dropdown-item" :class="{ active: $route.path.includes('settings') }">
 | 
			
		||||
                                    <font-awesome-icon icon="cog" /> {{ $t("Settings") }}
 | 
			
		||||
                                </router-link>
 | 
			
		||||
                            </li>
 | 
			
		||||
 | 
			
		||||
                            <li v-if="$root.loggedIn && $root.socket.token !== 'autoLogin'">
 | 
			
		||||
                                <button class="dropdown-item" @click="$root.logout">
 | 
			
		||||
                                    <font-awesome-icon icon="sign-out-alt" />
 | 
			
		||||
@@ -77,7 +90,7 @@
 | 
			
		||||
 | 
			
		||||
        <!-- Mobile Only -->
 | 
			
		||||
        <div v-if="$root.isMobile" style="width: 100%; height: 60px;" />
 | 
			
		||||
        <nav v-if="$root.isMobile && $root.loggedIn" class="bottom-nav scroll">
 | 
			
		||||
        <nav v-if="$root.isMobile && $root.loggedIn" class="bottom-nav">
 | 
			
		||||
            <router-link to="/dashboard" class="nav-link">
 | 
			
		||||
                <div><font-awesome-icon icon="tachometer-alt" /></div>
 | 
			
		||||
                {{ $t("Dashboard") }}
 | 
			
		||||
@@ -93,11 +106,6 @@
 | 
			
		||||
                {{ $t("Add Monitor") }}
 | 
			
		||||
            </router-link>
 | 
			
		||||
 | 
			
		||||
            <router-link to="/addMaintenance" class="nav-link">
 | 
			
		||||
                <div><font-awesome-icon icon="wrench" /></div>
 | 
			
		||||
                {{ $t("Add Maintenance") }}
 | 
			
		||||
            </router-link>
 | 
			
		||||
 | 
			
		||||
            <router-link to="/settings" class="nav-link">
 | 
			
		||||
                <div><font-awesome-icon icon="cog" /></div>
 | 
			
		||||
                {{ $t("Settings") }}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,23 +2,7 @@
 | 
			
		||||
    <div class="container-fluid">
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            <div v-if="!$root.isMobile" class="col-12 col-md-5 col-xl-4">
 | 
			
		||||
                <div class="dropdown dropdown-create">
 | 
			
		||||
                    <button class="btn btn-primary mb-3 dropdown-toggle" type="button" data-bs-toggle="dropdown">
 | 
			
		||||
                        <font-awesome-icon icon="plus" /> {{ $t("Create") }}
 | 
			
		||||
                    </button>
 | 
			
		||||
                    <ul class="dropdown-menu dropdown-menu-end">
 | 
			
		||||
                        <li>
 | 
			
		||||
                            <button type="button" class="dropdown-item" @click="$router.push('/add')">
 | 
			
		||||
                                <font-awesome-icon icon="heartbeat" /> {{ $t("Monitor") }}
 | 
			
		||||
                            </button>
 | 
			
		||||
                        </li>
 | 
			
		||||
                        <li>
 | 
			
		||||
                            <button type="button" class="dropdown-item" @click="$router.push('/addMaintenance')">
 | 
			
		||||
                                <font-awesome-icon icon="wrench" /> {{ $t("Maintenance") }}
 | 
			
		||||
                            </button>
 | 
			
		||||
                        </li>
 | 
			
		||||
                    </ul>
 | 
			
		||||
                </div>
 | 
			
		||||
                <router-link to="/add" class="btn btn-primary mb-3"><font-awesome-icon icon="plus" /> {{ $t("Add New Monitor") }}</router-link>
 | 
			
		||||
                <MonitorList :scrollbar="true" />
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
@@ -45,8 +29,6 @@ export default {
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
@import "../assets/vars.scss";
 | 
			
		||||
 | 
			
		||||
.container-fluid {
 | 
			
		||||
    width: 98%;
 | 
			
		||||
}
 | 
			
		||||
@@ -55,22 +37,4 @@ export default {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    justify-content: end;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dark {
 | 
			
		||||
    .dropdown-create {
 | 
			
		||||
        ul {
 | 
			
		||||
            background-color: $dark-bg;
 | 
			
		||||
            border-color: $dark-bg2;
 | 
			
		||||
            border-width: 2px;
 | 
			
		||||
 | 
			
		||||
            li button {
 | 
			
		||||
                color: $dark-font-color;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            li button:hover {
 | 
			
		||||
                background-color: $dark-bg2;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
 
 | 
			
		||||
@@ -6,14 +6,12 @@
 | 
			
		||||
                <div class="shadow-box">
 | 
			
		||||
                    <div class="row">
 | 
			
		||||
                        <div class="col-md-6">
 | 
			
		||||
                            <h2 class="mb-2">{{ $t("General") }}</h2>
 | 
			
		||||
 | 
			
		||||
                            <!-- Title -->
 | 
			
		||||
                            <div class="my-3">
 | 
			
		||||
                                <label for="name" class="form-label">{{ $t("Title") }}</label>
 | 
			
		||||
                                <input
 | 
			
		||||
                                    id="name" v-model="maintenance.title" type="text" class="form-control"
 | 
			
		||||
                                    :placeholder="titlePlaceholder" required
 | 
			
		||||
                                    required
 | 
			
		||||
                                >
 | 
			
		||||
                            </div>
 | 
			
		||||
 | 
			
		||||
@@ -22,7 +20,6 @@
 | 
			
		||||
                                <label for="description" class="form-label">{{ $t("Description") }}</label>
 | 
			
		||||
                                <textarea
 | 
			
		||||
                                    id="description" v-model="maintenance.description" class="form-control"
 | 
			
		||||
                                    :placeholder="descriptionPlaceholder"
 | 
			
		||||
                                ></textarea>
 | 
			
		||||
                            </div>
 | 
			
		||||
 | 
			
		||||
@@ -54,8 +51,7 @@
 | 
			
		||||
 | 
			
		||||
                            <!-- Start Date Time -->
 | 
			
		||||
                            <div class="my-3">
 | 
			
		||||
                                <label for="start_date" class="form-label">{{ $t("Start of maintenance") }}
 | 
			
		||||
                                    ({{ $root.timezone }})</label>
 | 
			
		||||
                                <label for="start_date" class="form-label">{{ $t("Start Date") }}</label>
 | 
			
		||||
                                <input
 | 
			
		||||
                                    id="start_date" v-model="maintenance.start_date" :type="'datetime-local'"
 | 
			
		||||
                                    class="form-control" :class="{'dark-calendar': dark }" required
 | 
			
		||||
@@ -64,8 +60,7 @@
 | 
			
		||||
 | 
			
		||||
                            <!-- End Date Time -->
 | 
			
		||||
                            <div class="my-3">
 | 
			
		||||
                                <label for="end_date" class="form-label">{{ $t("Expected end of maintenance") }}
 | 
			
		||||
                                    ({{ $root.timezone }})</label>
 | 
			
		||||
                                <label for="end_date" class="form-label">{{ $t("End Date") }}</label>
 | 
			
		||||
                                <input
 | 
			
		||||
                                    id="end_date" v-model="maintenance.end_date" :type="'datetime-local'"
 | 
			
		||||
                                    class="form-control" :class="{'dark-calendar': dark }" required
 | 
			
		||||
@@ -79,14 +74,14 @@
 | 
			
		||||
                                    type="checkbox"
 | 
			
		||||
                                >
 | 
			
		||||
                                <label class="form-check-label" for="show-powered-by">{{
 | 
			
		||||
                                    $t("Show on all pages")
 | 
			
		||||
                                    $t("Show this Maintenance Message on ALL Status Pages")
 | 
			
		||||
                                }}</label>
 | 
			
		||||
                            </div>
 | 
			
		||||
 | 
			
		||||
                            <!-- Status pages to display maintenance info on -->
 | 
			
		||||
                            <div v-if="!showOnAllPages" class="my-3">
 | 
			
		||||
                                <label for="selected_status_pages" class="form-label">{{
 | 
			
		||||
                                    $t("Selected status pages")
 | 
			
		||||
                                    $t("Show this Maintenance Message on which Status Pages")
 | 
			
		||||
                                }}</label>
 | 
			
		||||
 | 
			
		||||
                                <VueMultiselect
 | 
			
		||||
@@ -155,25 +150,17 @@ export default {
 | 
			
		||||
    computed: {
 | 
			
		||||
 | 
			
		||||
        pageName() {
 | 
			
		||||
            return this.$t((this.isAdd) ? "Schedule maintenance" : "Edit");
 | 
			
		||||
            return this.$t((this.isAdd) ? "Schedule Maintenance" : "Edit Maintenance");
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        isAdd() {
 | 
			
		||||
            return this.$route.path === "/addMaintenance";
 | 
			
		||||
            return this.$route.path === "/add-maintenance";
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        isEdit() {
 | 
			
		||||
            return this.$route.path.startsWith("/editMaintenance");
 | 
			
		||||
            return this.$route.path.startsWith("/maintenance/edit");
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        titlePlaceholder() {
 | 
			
		||||
            return this.$t("maintenanceTitleExample");
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        descriptionPlaceholder() {
 | 
			
		||||
            return this.$t("maintenanceDescriptionExample");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
    watch: {
 | 
			
		||||
        "$route.fullPath"() {
 | 
			
		||||
@@ -281,7 +268,7 @@ export default {
 | 
			
		||||
                                toast.success(res.msg);
 | 
			
		||||
                                this.processing = false;
 | 
			
		||||
                                this.$root.getMaintenanceList();
 | 
			
		||||
                                this.$router.push("/dashboard/maintenance/" + res.maintenanceID);
 | 
			
		||||
                                this.$router.push("/maintenance/" + res.maintenanceID);
 | 
			
		||||
                            });
 | 
			
		||||
                        });
 | 
			
		||||
                    } else {
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
            </p>
 | 
			
		||||
 | 
			
		||||
            <div class="functions" style="margin-top: 10px;">
 | 
			
		||||
                <router-link :to=" '/editMaintenance/' + maintenance.id " class="btn btn-secondary">
 | 
			
		||||
                <router-link :to=" '/maintenance/edit/' + maintenance.id " class="btn btn-secondary">
 | 
			
		||||
                    <font-awesome-icon icon="edit" /> {{ $t("Edit") }}
 | 
			
		||||
                </router-link>
 | 
			
		||||
                <button class="btn btn-danger" @click="deleteDialog">
 | 
			
		||||
@@ -27,7 +27,7 @@
 | 
			
		||||
            </button>
 | 
			
		||||
            <br />
 | 
			
		||||
 | 
			
		||||
            <label for="selected_status_pages" class="form-label" style="margin-top: 20px;">{{ $t("Selected status pages") }}</label>
 | 
			
		||||
            <label for="selected_status_pages" class="form-label" style="margin-top: 20px;">{{ $t("Show this Maintenance Message on which Status Pages") }}</label>
 | 
			
		||||
            <br>
 | 
			
		||||
            <button v-for="statusPage in selectedStatusPages" :key="statusPage.id" class="btn btn-monitor" style="margin: 5px; cursor: auto; color: white; font-weight: 500;">
 | 
			
		||||
                {{ statusPage }}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										168
									
								
								src/pages/ManageMaintenance.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								src/pages/ManageMaintenance.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,168 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <transition name="slide-fade" appear>
 | 
			
		||||
        <div>
 | 
			
		||||
            <h1 class="mb-3">
 | 
			
		||||
                {{ $t("Maintenance") }}
 | 
			
		||||
            </h1>
 | 
			
		||||
 | 
			
		||||
            <div>
 | 
			
		||||
                <router-link to="/add-maintenance" class="btn btn-primary mb-3">
 | 
			
		||||
                    <font-awesome-icon icon="plus" /> {{ $t("Schedule Maintenance") }}
 | 
			
		||||
                </router-link>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div class="shadow-box">
 | 
			
		||||
                <span v-if="Object.keys(sortedMaintenanceList).length === 0" class="d-flex align-items-center justify-content-center my-3">
 | 
			
		||||
                    {{ $t("No maintenance") }}
 | 
			
		||||
                </span>
 | 
			
		||||
 | 
			
		||||
                <router-link
 | 
			
		||||
                    v-for="(item, index) in sortedMaintenanceList"
 | 
			
		||||
                    :key="index"
 | 
			
		||||
                    :to="maintenanceURL(item.id)"
 | 
			
		||||
                    class="item"
 | 
			
		||||
                    :class="{ 'disabled': !$root.isActiveMaintenance(item.end_date) }"
 | 
			
		||||
                >
 | 
			
		||||
                    <div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="info">
 | 
			
		||||
                        <div class="title">{{ item.title }}</div>
 | 
			
		||||
                        <div>{{ item.description }}</div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </router-link>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </transition>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { getResBaseURL } from "../util-frontend";
 | 
			
		||||
import { getMaintenanceRelativeURL } from "../util.ts";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
    components: {
 | 
			
		||||
    },
 | 
			
		||||
    data() {
 | 
			
		||||
        return {
 | 
			
		||||
        };
 | 
			
		||||
    },
 | 
			
		||||
    computed: {
 | 
			
		||||
        sortedMaintenanceList() {
 | 
			
		||||
            let result = Object.values(this.$root.maintenanceList);
 | 
			
		||||
 | 
			
		||||
            result.sort((m1, m2) => {
 | 
			
		||||
 | 
			
		||||
                if (this.$root.isActiveMaintenance(m1.end_date) !== this.$root.isActiveMaintenance(m2.end_date)) {
 | 
			
		||||
                    if (!this.$root.isActiveMaintenance(m2.end_date)) {
 | 
			
		||||
                        return -1;
 | 
			
		||||
                    }
 | 
			
		||||
                    if (!this.$root.isActiveMaintenance(m1.end_date)) {
 | 
			
		||||
                        return 1;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (this.$root.isActiveMaintenance(m1.end_date) && this.$root.isActiveMaintenance(m2.end_date)) {
 | 
			
		||||
                    if (Date.parse(m1.end_date) < Date.parse(m2.end_date)) {
 | 
			
		||||
                        return -1;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (Date.parse(m2.end_date) < Date.parse(m1.end_date)) {
 | 
			
		||||
                        return 1;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (!this.$root.isActiveMaintenance(m1.end_date) && !this.$root.isActiveMaintenance(m2.end_date)) {
 | 
			
		||||
                    if (Date.parse(m1.end_date) < Date.parse(m2.end_date)) {
 | 
			
		||||
                        return 1;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (Date.parse(m2.end_date) < Date.parse(m1.end_date)) {
 | 
			
		||||
                        return -1;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                return m1.title.localeCompare(m2.title);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            return result;
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
    mounted() {
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
    methods: {
 | 
			
		||||
        /**
 | 
			
		||||
         * Get the correct URL for the icon
 | 
			
		||||
         * @param {string} icon Path for icon
 | 
			
		||||
         * @returns {string} Correctly formatted path including port numbers
 | 
			
		||||
         */
 | 
			
		||||
        icon(icon) {
 | 
			
		||||
            if (icon === "/icon.svg") {
 | 
			
		||||
                return icon;
 | 
			
		||||
            } else {
 | 
			
		||||
                return getResBaseURL() + icon;
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        maintenanceURL(id) {
 | 
			
		||||
            return getMaintenanceRelativeURL(id);
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
    @import "../assets/vars.scss";
 | 
			
		||||
 | 
			
		||||
    .item {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        gap: 10px;
 | 
			
		||||
        text-decoration: none;
 | 
			
		||||
        border-radius: 10px;
 | 
			
		||||
        transition: all ease-in-out 0.15s;
 | 
			
		||||
        padding: 10px;
 | 
			
		||||
        min-height: 90px;
 | 
			
		||||
 | 
			
		||||
        &:hover {
 | 
			
		||||
            background-color: $highlight-white;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &.active {
 | 
			
		||||
            background-color: #cdf8f4;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $logo-width: 70px;
 | 
			
		||||
 | 
			
		||||
        .logo {
 | 
			
		||||
            width: $logo-width;
 | 
			
		||||
            height: $logo-width;
 | 
			
		||||
 | 
			
		||||
            // Better when the image is loading
 | 
			
		||||
            min-height: 1px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .info {
 | 
			
		||||
            .title {
 | 
			
		||||
                font-weight: bold;
 | 
			
		||||
                font-size: 20px;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            .slug {
 | 
			
		||||
                font-size: 14px;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .dark {
 | 
			
		||||
        .item {
 | 
			
		||||
            &:hover {
 | 
			
		||||
                background-color: $dark-bg2;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            &.active {
 | 
			
		||||
                background-color: $dark-bg2;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
</style>
 | 
			
		||||
@@ -15,6 +15,9 @@ import Entry from "./pages/Entry.vue";
 | 
			
		||||
import ManageStatusPage from "./pages/ManageStatusPage.vue";
 | 
			
		||||
import AddStatusPage from "./pages/AddStatusPage.vue";
 | 
			
		||||
import NotFound from "./pages/NotFound.vue";
 | 
			
		||||
import DockerHosts from "./components/settings/Docker.vue";
 | 
			
		||||
import MaintenanceDetails from "./pages/MaintenanceDetails.vue";
 | 
			
		||||
import ManageMaintenance from "./pages/ManageMaintenance.vue";
 | 
			
		||||
 | 
			
		||||
// Settings - Sub Pages
 | 
			
		||||
import Appearance from "./components/settings/Appearance.vue";
 | 
			
		||||
@@ -26,8 +29,6 @@ const Security = () => import("./components/settings/Security.vue");
 | 
			
		||||
import Proxies from "./components/settings/Proxies.vue";
 | 
			
		||||
import Backup from "./components/settings/Backup.vue";
 | 
			
		||||
import About from "./components/settings/About.vue";
 | 
			
		||||
import DockerHosts from "./components/settings/Docker.vue";
 | 
			
		||||
import MaintenanceDetails from "./pages/MaintenanceDetails.vue";
 | 
			
		||||
 | 
			
		||||
const routes = [
 | 
			
		||||
    {
 | 
			
		||||
@@ -64,28 +65,12 @@ const routes = [
 | 
			
		||||
                                    },
 | 
			
		||||
                                ],
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                path: "/dashboard/maintenance/:id",
 | 
			
		||||
                                component: EmptyLayout,
 | 
			
		||||
                                children: [
 | 
			
		||||
                                    {
 | 
			
		||||
                                        path: "",
 | 
			
		||||
                                        component: MaintenanceDetails,
 | 
			
		||||
                                    },
 | 
			
		||||
                                    {
 | 
			
		||||
                                        path: "/editMaintenance/:id",
 | 
			
		||||
                                        component: EditMaintenance,
 | 
			
		||||
                                    },
 | 
			
		||||
                                ],
 | 
			
		||||
                            },
 | 
			
		||||
 | 
			
		||||
                            {
 | 
			
		||||
                                path: "/add",
 | 
			
		||||
                                component: EditMonitor,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                path: "/addMaintenance",
 | 
			
		||||
                                component: EditMaintenance,
 | 
			
		||||
                            },
 | 
			
		||||
 | 
			
		||||
                        ],
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
@@ -146,6 +131,22 @@ const routes = [
 | 
			
		||||
                        path: "/add-status-page",
 | 
			
		||||
                        component: AddStatusPage,
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        path: "/maintenance",
 | 
			
		||||
                        component: ManageMaintenance,
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        path: "/maintenance/:id",
 | 
			
		||||
                        component: MaintenanceDetails,
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        path: "/add-maintenance",
 | 
			
		||||
                        component: EditMaintenance,
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        path: "/maintenance/edit/:id",
 | 
			
		||||
                        component: EditMaintenance,
 | 
			
		||||
                    },
 | 
			
		||||
                ],
 | 
			
		||||
            },
 | 
			
		||||
        ],
 | 
			
		||||
 
 | 
			
		||||
@@ -282,9 +282,9 @@ function getCryptoRandomInt(min, max) {
 | 
			
		||||
}
 | 
			
		||||
exports.getCryptoRandomInt = getCryptoRandomInt;
 | 
			
		||||
/**
 | 
			
		||||
 * Generate a secret
 | 
			
		||||
 * @param length Lenght of secret to generate
 | 
			
		||||
 * @returns
 | 
			
		||||
 * Generate a random alphanumeric string of fixed length
 | 
			
		||||
 * @param length Length of string to generate
 | 
			
		||||
 * @returns string
 | 
			
		||||
 */
 | 
			
		||||
function genSecret(length = 64) {
 | 
			
		||||
    let secret = "";
 | 
			
		||||
@@ -306,6 +306,6 @@ function getMonitorRelativeURL(id) {
 | 
			
		||||
}
 | 
			
		||||
exports.getMonitorRelativeURL = getMonitorRelativeURL;
 | 
			
		||||
function getMaintenanceRelativeURL(id) {
 | 
			
		||||
    return "/dashboard/maintenance/" + id;
 | 
			
		||||
    return "/maintenance/" + id;
 | 
			
		||||
}
 | 
			
		||||
exports.getMaintenanceRelativeURL = getMaintenanceRelativeURL;
 | 
			
		||||
 
 | 
			
		||||
@@ -340,5 +340,5 @@ export function getMonitorRelativeURL(id: string) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function getMaintenanceRelativeURL(id: string) {
 | 
			
		||||
    return "/dashboard/maintenance/" + id;
 | 
			
		||||
    return "/maintenance/" + id;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user