mirror of
				https://github.com/louislam/uptime-kuma.git
				synced 2025-11-04 21:56:12 +08:00 
			
		
		
		
	WIP: Convert Settings to components
This commit is contained in:
		@@ -12,6 +12,7 @@ $dark-font-color2: #020b05;
 | 
			
		||||
$dark-bg: #0d1117;
 | 
			
		||||
$dark-bg2: #070a10;
 | 
			
		||||
$dark-border-color: #1d2634;
 | 
			
		||||
$dark-header-bg: #161b22;
 | 
			
		||||
 | 
			
		||||
$easing-in: cubic-bezier(0.54, 0.78, 0.55, 0.97);
 | 
			
		||||
$easing-out: cubic-bezier(0.25, 0.46, 0.45, 0.94);
 | 
			
		||||
 
 | 
			
		||||
@@ -137,7 +137,7 @@ export default {
 | 
			
		||||
    justify-content: space-between;
 | 
			
		||||
 | 
			
		||||
    .dark & {
 | 
			
		||||
        background-color: #161b22;
 | 
			
		||||
        background-color: $dark-header-bg;
 | 
			
		||||
        border-bottom: 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										25
									
								
								src/components/settings/About.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/components/settings/About.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="d-flex justify-content-center align-items-center">
 | 
			
		||||
        <div class="logo d-flex flex-column justify-content-center align-items-center">
 | 
			
		||||
            <object class="my-4" width="200" height="200" data="/icon.svg" />
 | 
			
		||||
            <div class="fs-4 fw-bold">Uptime Kuma</div>
 | 
			
		||||
            <div>{{ $t("Version") }}: {{ $root.info.version }}</div>
 | 
			
		||||
            <div class="my-1 update-link"><a href="https://github.com/louislam/uptime-kuma/releases" target="_blank" rel="noopener">{{ $t("Check Update On GitHub") }}</a></div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
.logo {
 | 
			
		||||
    margin: 4em 1em;
 | 
			
		||||
}
 | 
			
		||||
.update-link {
 | 
			
		||||
    font-size: 0.9em;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										149
									
								
								src/components/settings/Appearance.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								src/components/settings/Appearance.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,149 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div>
 | 
			
		||||
        <div class="my-4">
 | 
			
		||||
            <label for="language" class="form-label">
 | 
			
		||||
                {{ $t("Language") }}
 | 
			
		||||
            </label>
 | 
			
		||||
            <select id="language" v-model="$i18n.locale" class="form-select">
 | 
			
		||||
                <option
 | 
			
		||||
                    v-for="(lang, i) in $i18n.availableLocales"
 | 
			
		||||
                    :key="`Lang${i}`"
 | 
			
		||||
                    :value="lang"
 | 
			
		||||
                >
 | 
			
		||||
                    {{ $i18n.messages[lang].languageName }}
 | 
			
		||||
                </option>
 | 
			
		||||
            </select>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="my-4">
 | 
			
		||||
            <label for="timezone" class="form-label">{{ $t("Theme") }}</label>
 | 
			
		||||
            <div>
 | 
			
		||||
                <div
 | 
			
		||||
                    class="btn-group"
 | 
			
		||||
                    role="group"
 | 
			
		||||
                    aria-label="Basic checkbox toggle button group"
 | 
			
		||||
                >
 | 
			
		||||
                    <input
 | 
			
		||||
                        id="btncheck1"
 | 
			
		||||
                        v-model="$root.userTheme"
 | 
			
		||||
                        type="radio"
 | 
			
		||||
                        class="btn-check"
 | 
			
		||||
                        name="theme"
 | 
			
		||||
                        autocomplete="off"
 | 
			
		||||
                        value="light"
 | 
			
		||||
                    />
 | 
			
		||||
                    <label class="btn btn-outline-primary" for="btncheck1">
 | 
			
		||||
                        {{ $t("Light") }}
 | 
			
		||||
                    </label>
 | 
			
		||||
 | 
			
		||||
                    <input
 | 
			
		||||
                        id="btncheck2"
 | 
			
		||||
                        v-model="$root.userTheme"
 | 
			
		||||
                        type="radio"
 | 
			
		||||
                        class="btn-check"
 | 
			
		||||
                        name="theme"
 | 
			
		||||
                        autocomplete="off"
 | 
			
		||||
                        value="dark"
 | 
			
		||||
                    />
 | 
			
		||||
                    <label class="btn btn-outline-primary" for="btncheck2">
 | 
			
		||||
                        {{ $t("Dark") }}
 | 
			
		||||
                    </label>
 | 
			
		||||
 | 
			
		||||
                    <input
 | 
			
		||||
                        id="btncheck3"
 | 
			
		||||
                        v-model="$root.userTheme"
 | 
			
		||||
                        type="radio"
 | 
			
		||||
                        class="btn-check"
 | 
			
		||||
                        name="theme"
 | 
			
		||||
                        autocomplete="off"
 | 
			
		||||
                        value="auto"
 | 
			
		||||
                    />
 | 
			
		||||
                    <label class="btn btn-outline-primary" for="btncheck3">
 | 
			
		||||
                        {{ $t("Auto") }}
 | 
			
		||||
                    </label>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="my-4">
 | 
			
		||||
            <label class="form-label">{{ $t("Theme - Heartbeat Bar") }}</label>
 | 
			
		||||
            <div>
 | 
			
		||||
                <div
 | 
			
		||||
                    class="btn-group"
 | 
			
		||||
                    role="group"
 | 
			
		||||
                    aria-label="Basic checkbox toggle button group"
 | 
			
		||||
                >
 | 
			
		||||
                    <input
 | 
			
		||||
                        id="btncheck4"
 | 
			
		||||
                        v-model="$root.userHeartbeatBar"
 | 
			
		||||
                        type="radio"
 | 
			
		||||
                        class="btn-check"
 | 
			
		||||
                        name="heartbeatBarTheme"
 | 
			
		||||
                        autocomplete="off"
 | 
			
		||||
                        value="normal"
 | 
			
		||||
                    />
 | 
			
		||||
                    <label class="btn btn-outline-primary" for="btncheck4">
 | 
			
		||||
                        {{ $t("Normal") }}
 | 
			
		||||
                    </label>
 | 
			
		||||
 | 
			
		||||
                    <input
 | 
			
		||||
                        id="btncheck5"
 | 
			
		||||
                        v-model="$root.userHeartbeatBar"
 | 
			
		||||
                        type="radio"
 | 
			
		||||
                        class="btn-check"
 | 
			
		||||
                        name="heartbeatBarTheme"
 | 
			
		||||
                        autocomplete="off"
 | 
			
		||||
                        value="bottom"
 | 
			
		||||
                    />
 | 
			
		||||
                    <label class="btn btn-outline-primary" for="btncheck5">
 | 
			
		||||
                        {{ $t("Bottom") }}
 | 
			
		||||
                    </label>
 | 
			
		||||
 | 
			
		||||
                    <input
 | 
			
		||||
                        id="btncheck6"
 | 
			
		||||
                        v-model="$root.userHeartbeatBar"
 | 
			
		||||
                        type="radio"
 | 
			
		||||
                        class="btn-check"
 | 
			
		||||
                        name="heartbeatBarTheme"
 | 
			
		||||
                        autocomplete="off"
 | 
			
		||||
                        value="none"
 | 
			
		||||
                    />
 | 
			
		||||
                    <label class="btn btn-outline-primary" for="btncheck6">
 | 
			
		||||
                        {{ $t("None") }}
 | 
			
		||||
                    </label>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { setPageLocale } from "../../util-frontend";
 | 
			
		||||
export default {
 | 
			
		||||
    watch: {
 | 
			
		||||
        "$i18n.locale"() {
 | 
			
		||||
            localStorage.locale = this.$i18n.locale;
 | 
			
		||||
            setPageLocale();
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
@import "../../assets/vars.scss";
 | 
			
		||||
 | 
			
		||||
.btn-check:active + .btn-outline-primary,
 | 
			
		||||
.btn-check:checked + .btn-outline-primary,
 | 
			
		||||
.btn-check:hover + .btn-outline-primary {
 | 
			
		||||
    color: #fff;
 | 
			
		||||
 | 
			
		||||
    .dark & {
 | 
			
		||||
        color: #000;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dark {
 | 
			
		||||
    .list-group-item {
 | 
			
		||||
        background-color: $dark-bg2;
 | 
			
		||||
        color: $dark-font-color;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										213
									
								
								src/components/settings/Backup.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								src/components/settings/Backup.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,213 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div>
 | 
			
		||||
        <div class="my-4">
 | 
			
		||||
            <h4 class="mt-4 mb-2">{{ $t("Export Backup") }}</h4>
 | 
			
		||||
 | 
			
		||||
            <p>
 | 
			
		||||
                {{ $t("backupDescription") }} <br />
 | 
			
		||||
                ({{ $t("backupDescription2") }}) <br />
 | 
			
		||||
            </p>
 | 
			
		||||
 | 
			
		||||
            <div class="mb-2">
 | 
			
		||||
                <button class="btn btn-primary" @click="downloadBackup">
 | 
			
		||||
                    {{ $t("Export") }}
 | 
			
		||||
                </button>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <p>
 | 
			
		||||
                <strong>{{ $t("backupDescription3") }}</strong>
 | 
			
		||||
            </p>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div class="my-4">
 | 
			
		||||
            <h4 class="mt-4 mb-2">{{ $t("Import Backup") }}</h4>
 | 
			
		||||
 | 
			
		||||
            <label class="form-label">{{ $t("Options") }}:</label>
 | 
			
		||||
            <br />
 | 
			
		||||
            <div class="form-check form-check-inline">
 | 
			
		||||
                <input
 | 
			
		||||
                    id="radioKeep"
 | 
			
		||||
                    v-model="importHandle"
 | 
			
		||||
                    class="form-check-input"
 | 
			
		||||
                    type="radio"
 | 
			
		||||
                    name="radioImportHandle"
 | 
			
		||||
                    value="keep"
 | 
			
		||||
                />
 | 
			
		||||
                <label class="form-check-label" for="radioKeep">
 | 
			
		||||
                    {{ $t("Keep both") }}
 | 
			
		||||
                </label>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="form-check form-check-inline">
 | 
			
		||||
                <input
 | 
			
		||||
                    id="radioSkip"
 | 
			
		||||
                    v-model="importHandle"
 | 
			
		||||
                    class="form-check-input"
 | 
			
		||||
                    type="radio"
 | 
			
		||||
                    name="radioImportHandle"
 | 
			
		||||
                    value="skip"
 | 
			
		||||
                />
 | 
			
		||||
                <label class="form-check-label" for="radioSkip">
 | 
			
		||||
                    {{ $t("Skip existing") }}
 | 
			
		||||
                </label>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="form-check form-check-inline">
 | 
			
		||||
                <input
 | 
			
		||||
                    id="radioOverwrite"
 | 
			
		||||
                    v-model="importHandle"
 | 
			
		||||
                    class="form-check-input"
 | 
			
		||||
                    type="radio"
 | 
			
		||||
                    name="radioImportHandle"
 | 
			
		||||
                    value="overwrite"
 | 
			
		||||
                />
 | 
			
		||||
                <label class="form-check-label" for="radioOverwrite">
 | 
			
		||||
                    {{ $t("Overwrite") }}
 | 
			
		||||
                </label>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="form-text mb-2">
 | 
			
		||||
                {{ $t("importHandleDescription") }}
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div class="mb-2">
 | 
			
		||||
                <input
 | 
			
		||||
                    id="importBackup"
 | 
			
		||||
                    type="file"
 | 
			
		||||
                    class="form-control"
 | 
			
		||||
                    accept="application/json"
 | 
			
		||||
                />
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div class="input-group mb-2 justify-content-end">
 | 
			
		||||
                <button
 | 
			
		||||
                    type="button"
 | 
			
		||||
                    class="btn btn-outline-primary"
 | 
			
		||||
                    :disabled="processing"
 | 
			
		||||
                    @click="confirmImport"
 | 
			
		||||
                >
 | 
			
		||||
                    <div
 | 
			
		||||
                        v-if="processing"
 | 
			
		||||
                        class="spinner-border spinner-border-sm me-1"
 | 
			
		||||
                    ></div>
 | 
			
		||||
                    {{ $t("Import") }}
 | 
			
		||||
                </button>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div
 | 
			
		||||
                v-if="importAlert"
 | 
			
		||||
                class="alert alert-danger mt-3"
 | 
			
		||||
                style="padding: 6px 16px"
 | 
			
		||||
            >
 | 
			
		||||
                {{ importAlert }}
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <Confirm
 | 
			
		||||
            ref="confirmImport"
 | 
			
		||||
            btn-style="btn-danger"
 | 
			
		||||
            :yes-text="$t('Yes')"
 | 
			
		||||
            :no-text="$t('No')"
 | 
			
		||||
            @yes="importBackup"
 | 
			
		||||
        >
 | 
			
		||||
            {{ $t("confirmImportMsg") }}
 | 
			
		||||
        </Confirm>
 | 
			
		||||
    </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import Confirm from "../../components/Confirm.vue";
 | 
			
		||||
import dayjs from "dayjs";
 | 
			
		||||
import { useToast } from "vue-toastification";
 | 
			
		||||
 | 
			
		||||
const toast = useToast();
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
    components: {
 | 
			
		||||
        Confirm,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    data() {
 | 
			
		||||
        return {
 | 
			
		||||
            processing: false,
 | 
			
		||||
            importHandle: "skip",
 | 
			
		||||
            importAlert: null,
 | 
			
		||||
        };
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    methods: {
 | 
			
		||||
        confirmImport() {
 | 
			
		||||
            this.$refs.confirmImport.show();
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        downloadBackup() {
 | 
			
		||||
            let time = dayjs().format("YYYY_MM_DD-hh_mm_ss");
 | 
			
		||||
            let fileName = `Uptime_Kuma_Backup_${time}.json`;
 | 
			
		||||
            let monitorList = Object.values(this.$root.monitorList);
 | 
			
		||||
            let exportData = {
 | 
			
		||||
                version: this.$root.info.version,
 | 
			
		||||
                notificationList: this.$root.notificationList,
 | 
			
		||||
                monitorList: monitorList,
 | 
			
		||||
            };
 | 
			
		||||
            exportData = JSON.stringify(exportData, null, 4);
 | 
			
		||||
            let downloadItem = document.createElement("a");
 | 
			
		||||
            downloadItem.setAttribute(
 | 
			
		||||
                "href",
 | 
			
		||||
                "data:application/json;charset=utf-8," +
 | 
			
		||||
                    encodeURIComponent(exportData)
 | 
			
		||||
            );
 | 
			
		||||
            downloadItem.setAttribute("download", fileName);
 | 
			
		||||
            downloadItem.click();
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        importBackup() {
 | 
			
		||||
            this.processing = true;
 | 
			
		||||
            let uploadItem = document.getElementById("importBackup").files;
 | 
			
		||||
 | 
			
		||||
            if (uploadItem.length <= 0) {
 | 
			
		||||
                this.processing = false;
 | 
			
		||||
                return (this.importAlert = this.$t("alertNoFile"));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (uploadItem.item(0).type !== "application/json") {
 | 
			
		||||
                this.processing = false;
 | 
			
		||||
                return (this.importAlert = this.$t("alertWrongFileType"));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            let fileReader = new FileReader();
 | 
			
		||||
            fileReader.readAsText(uploadItem.item(0));
 | 
			
		||||
 | 
			
		||||
            fileReader.onload = (item) => {
 | 
			
		||||
                this.$root.uploadBackup(
 | 
			
		||||
                    item.target.result,
 | 
			
		||||
                    this.importHandle,
 | 
			
		||||
                    (res) => {
 | 
			
		||||
                        this.processing = false;
 | 
			
		||||
 | 
			
		||||
                        if (res.ok) {
 | 
			
		||||
                            toast.success(res.msg);
 | 
			
		||||
                        } else {
 | 
			
		||||
                            toast.error(res.msg);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                );
 | 
			
		||||
            };
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
@import "../../assets/vars.scss";
 | 
			
		||||
 | 
			
		||||
.dark {
 | 
			
		||||
    #importBackup {
 | 
			
		||||
        &::file-selector-button {
 | 
			
		||||
            color: $primary;
 | 
			
		||||
            background-color: $dark-bg;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &:hover:not(:disabled):not([readonly])::file-selector-button {
 | 
			
		||||
            color: $dark-font-color2;
 | 
			
		||||
            background-color: $primary;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										191
									
								
								src/components/settings/General.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								src/components/settings/General.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,191 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div>
 | 
			
		||||
        <form class="my-4" @submit.prevent="saveGeneral">
 | 
			
		||||
            <!-- Timezone -->
 | 
			
		||||
            <div class="mb-4">
 | 
			
		||||
                <label for="timezone" class="form-label">
 | 
			
		||||
                    {{ $t("Timezone") }}
 | 
			
		||||
                </label>
 | 
			
		||||
                <select id="timezone" v-model="$root.userTimezone" class="form-select">
 | 
			
		||||
                    <option value="auto">
 | 
			
		||||
                        {{ $t("Auto") }}: {{ guessTimezone }}
 | 
			
		||||
                    </option>
 | 
			
		||||
                    <option
 | 
			
		||||
                        v-for="(timezone, index) in timezoneList"
 | 
			
		||||
                        :key="index"
 | 
			
		||||
                        :value="timezone.value"
 | 
			
		||||
                    >
 | 
			
		||||
                        {{ timezone.name }}
 | 
			
		||||
                    </option>
 | 
			
		||||
                </select>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <!-- Search Engine -->
 | 
			
		||||
            <div class="mb-4">
 | 
			
		||||
                <label class="form-label">
 | 
			
		||||
                    {{ $t("Search Engine Visibility") }}
 | 
			
		||||
                </label>
 | 
			
		||||
 | 
			
		||||
                <div class="form-check">
 | 
			
		||||
                    <input
 | 
			
		||||
                        id="searchEngineIndexYes"
 | 
			
		||||
                        v-model="settings.searchEngineIndex"
 | 
			
		||||
                        class="form-check-input"
 | 
			
		||||
                        type="radio"
 | 
			
		||||
                        name="flexRadioDefault"
 | 
			
		||||
                        :value="true"
 | 
			
		||||
                        required
 | 
			
		||||
                    />
 | 
			
		||||
                    <label class="form-check-label" for="searchEngineIndexYes">
 | 
			
		||||
                        {{ $t("Allow indexing") }}
 | 
			
		||||
                    </label>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="form-check">
 | 
			
		||||
                    <input
 | 
			
		||||
                        id="searchEngineIndexNo"
 | 
			
		||||
                        v-model="settings.searchEngineIndex"
 | 
			
		||||
                        class="form-check-input"
 | 
			
		||||
                        type="radio"
 | 
			
		||||
                        name="flexRadioDefault"
 | 
			
		||||
                        :value="false"
 | 
			
		||||
                        required
 | 
			
		||||
                    />
 | 
			
		||||
                    <label class="form-check-label" for="searchEngineIndexNo">
 | 
			
		||||
                        {{ $t("Discourage search engines from indexing site") }}
 | 
			
		||||
                    </label>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <!-- Entry Page -->
 | 
			
		||||
            <div class="mb-4">
 | 
			
		||||
                <label class="form-label">{{ $t("Entry Page") }}</label>
 | 
			
		||||
 | 
			
		||||
                <div class="form-check">
 | 
			
		||||
                    <input
 | 
			
		||||
                        id="entryPageYes"
 | 
			
		||||
                        v-model="settings.entryPage"
 | 
			
		||||
                        class="form-check-input"
 | 
			
		||||
                        type="radio"
 | 
			
		||||
                        name="statusPage"
 | 
			
		||||
                        value="dashboard"
 | 
			
		||||
                        required
 | 
			
		||||
                    />
 | 
			
		||||
                    <label class="form-check-label" for="entryPageYes">
 | 
			
		||||
                        {{ $t("Dashboard") }}
 | 
			
		||||
                    </label>
 | 
			
		||||
                </div>
 | 
			
		||||
 | 
			
		||||
                <div class="form-check">
 | 
			
		||||
                    <input
 | 
			
		||||
                        id="entryPageNo"
 | 
			
		||||
                        v-model="settings.entryPage"
 | 
			
		||||
                        class="form-check-input"
 | 
			
		||||
                        type="radio"
 | 
			
		||||
                        name="statusPage"
 | 
			
		||||
                        value="statusPage"
 | 
			
		||||
                        required
 | 
			
		||||
                    />
 | 
			
		||||
                    <label class="form-check-label" for="entryPageNo">
 | 
			
		||||
                        {{ $t("Status Page") }}
 | 
			
		||||
                    </label>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <!-- Primary Base URL -->
 | 
			
		||||
            <div class="mb-4">
 | 
			
		||||
                <label class="form-label" for="primaryBaseURL">
 | 
			
		||||
                    {{ $t("Primary Base URL") }}
 | 
			
		||||
                </label>
 | 
			
		||||
 | 
			
		||||
                <div class="input-group mb-3">
 | 
			
		||||
                    <input
 | 
			
		||||
                        id="primaryBaseURL"
 | 
			
		||||
                        v-model="settings.primaryBaseURL"
 | 
			
		||||
                        class="form-control"
 | 
			
		||||
                        name="primaryBaseURL"
 | 
			
		||||
                        placeholder="https://"
 | 
			
		||||
                        pattern="https?://.+"
 | 
			
		||||
                    />
 | 
			
		||||
                    <button class="btn btn-outline-primary" type="button" @click="autoGetPrimaryBaseURL">
 | 
			
		||||
                        {{ $t("Auto Get") }}
 | 
			
		||||
                    </button>
 | 
			
		||||
                </div>
 | 
			
		||||
 | 
			
		||||
                <div class="form-text"></div>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <!-- Steam API Key -->
 | 
			
		||||
            <div class="mb-4">
 | 
			
		||||
                <label class="form-label" for="steamAPIKey">
 | 
			
		||||
                    {{ $t("Steam API Key") }}
 | 
			
		||||
                </label>
 | 
			
		||||
                <HiddenInput
 | 
			
		||||
                    id="steamAPIKey"
 | 
			
		||||
                    v-model="settings.steamAPIKey"
 | 
			
		||||
                />
 | 
			
		||||
                <div class="form-text">
 | 
			
		||||
                    {{ $t("steamApiKeyDescription") }}
 | 
			
		||||
                    <a href="https://steamcommunity.com/dev" target="_blank">
 | 
			
		||||
                        https://steamcommunity.com/dev
 | 
			
		||||
                    </a>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <!-- Save Button -->
 | 
			
		||||
            <div>
 | 
			
		||||
                <button class="btn btn-primary" type="submit">
 | 
			
		||||
                    {{ $t("Save") }}
 | 
			
		||||
                </button>
 | 
			
		||||
            </div>
 | 
			
		||||
        </form>
 | 
			
		||||
    </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import HiddenInput from "../../components/HiddenInput.vue";
 | 
			
		||||
import dayjs from "dayjs";
 | 
			
		||||
import utc from "dayjs/plugin/utc";
 | 
			
		||||
import timezone from "dayjs/plugin/timezone";
 | 
			
		||||
import { timezoneList } from "../../util-frontend";
 | 
			
		||||
dayjs.extend(utc);
 | 
			
		||||
dayjs.extend(timezone);
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
    components: {
 | 
			
		||||
        HiddenInput,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    data() {
 | 
			
		||||
        return {
 | 
			
		||||
            timezoneList: timezoneList(),
 | 
			
		||||
        };
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    computed: {
 | 
			
		||||
        settings() {
 | 
			
		||||
            return this.$parent.$parent.settings;
 | 
			
		||||
        },
 | 
			
		||||
        saveSettings() {
 | 
			
		||||
            return this.$parent.$parent.saveSettings;
 | 
			
		||||
        },
 | 
			
		||||
        settingsLoaded() {
 | 
			
		||||
            return this.$parent.$parent.settingsLoaded;
 | 
			
		||||
        },
 | 
			
		||||
        guessTimezone() {
 | 
			
		||||
            return dayjs.tz.guess();
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    methods: {
 | 
			
		||||
        saveGeneral() {
 | 
			
		||||
            localStorage.timezone = this.$root.userTimezone;
 | 
			
		||||
            this.saveSettings();
 | 
			
		||||
        },
 | 
			
		||||
        autoGetPrimaryBaseURL() {
 | 
			
		||||
            this.settings.primaryBaseURL = location.protocol + "//" + location.host;
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style></style>
 | 
			
		||||
							
								
								
									
										127
									
								
								src/components/settings/MonitorHistory.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								src/components/settings/MonitorHistory.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,127 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div>
 | 
			
		||||
        <div class="my-4">
 | 
			
		||||
            <label for="keepDataPeriodDays" class="form-label">
 | 
			
		||||
                {{
 | 
			
		||||
                    $t("clearDataOlderThan", [
 | 
			
		||||
                        settings.keepDataPeriodDays,
 | 
			
		||||
                    ])
 | 
			
		||||
                }}
 | 
			
		||||
            </label>
 | 
			
		||||
            <input
 | 
			
		||||
                id="keepDataPeriodDays"
 | 
			
		||||
                v-model="settings.keepDataPeriodDays"
 | 
			
		||||
                type="number"
 | 
			
		||||
                class="form-control"
 | 
			
		||||
                required
 | 
			
		||||
                min="1"
 | 
			
		||||
                step="1"
 | 
			
		||||
            />
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="my-4">
 | 
			
		||||
            <div class="my-3">
 | 
			
		||||
                <button class="btn btn-outline-info me-2" @click="shrinkDatabase">
 | 
			
		||||
                    {{ $t("Shrink Database") }} ({{ databaseSizeDisplay }})
 | 
			
		||||
                </button>
 | 
			
		||||
                <div class="form-text ms-2">{{ $t("shrinkDatabaseDescription") }}</div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <button
 | 
			
		||||
                class="btn btn-outline-danger me-2 mb-2"
 | 
			
		||||
                @click="confirmClearStatistics"
 | 
			
		||||
            >
 | 
			
		||||
                {{ $t("Clear all statistics") }}
 | 
			
		||||
            </button>
 | 
			
		||||
        </div>
 | 
			
		||||
        <Confirm
 | 
			
		||||
            ref="confirmClearStatistics"
 | 
			
		||||
            btn-style="btn-danger"
 | 
			
		||||
            :yes-text="$t('Yes')"
 | 
			
		||||
            :no-text="$t('No')"
 | 
			
		||||
            @yes="clearStatistics"
 | 
			
		||||
        >
 | 
			
		||||
            {{ $t("confirmClearStatisticsMsg") }}
 | 
			
		||||
        </Confirm>
 | 
			
		||||
    </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import Confirm from "../../components/Confirm.vue";
 | 
			
		||||
import { debug } from "../../util.ts";
 | 
			
		||||
import { useToast } from "vue-toastification";
 | 
			
		||||
 | 
			
		||||
const toast = useToast();
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
    components: {
 | 
			
		||||
        Confirm,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    data() {
 | 
			
		||||
        return {
 | 
			
		||||
            databaseSize: 0,
 | 
			
		||||
        };
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    computed: {
 | 
			
		||||
        settings() {
 | 
			
		||||
            return this.$parent.$parent.settings;
 | 
			
		||||
        },
 | 
			
		||||
        saveSettings() {
 | 
			
		||||
            return this.$parent.$parent.saveSettings;
 | 
			
		||||
        },
 | 
			
		||||
        settingsLoaded() {
 | 
			
		||||
            return this.$parent.$parent.settingsLoaded;
 | 
			
		||||
        },
 | 
			
		||||
        databaseSizeDisplay() {
 | 
			
		||||
            return (
 | 
			
		||||
                Math.round((this.databaseSize / 1024 / 1024) * 10) / 10 + " MB"
 | 
			
		||||
            );
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    mounted() {
 | 
			
		||||
        this.loadDatabaseSize();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    methods: {
 | 
			
		||||
        loadDatabaseSize() {
 | 
			
		||||
            debug("load database size");
 | 
			
		||||
            this.$root.getSocket().emit("getDatabaseSize", (res) => {
 | 
			
		||||
                if (res.ok) {
 | 
			
		||||
                    this.databaseSize = res.size;
 | 
			
		||||
                    debug("database size: " + res.size);
 | 
			
		||||
                } else {
 | 
			
		||||
                    debug(res);
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        shrinkDatabase() {
 | 
			
		||||
            this.$root.getSocket().emit("shrinkDatabase", (res) => {
 | 
			
		||||
                if (res.ok) {
 | 
			
		||||
                    this.loadDatabaseSize();
 | 
			
		||||
                    toast.success("Done");
 | 
			
		||||
                } else {
 | 
			
		||||
                    debug(res);
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        confirmClearStatistics() {
 | 
			
		||||
            this.$refs.confirmClearStatistics.show();
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        clearStatistics() {
 | 
			
		||||
            this.$root.clearStatistics((res) => {
 | 
			
		||||
                if (res.ok) {
 | 
			
		||||
                    this.$router.go();
 | 
			
		||||
                } else {
 | 
			
		||||
                    toast.error(res.msg);
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style></style>
 | 
			
		||||
							
								
								
									
										46
									
								
								src/components/settings/Notifications.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/components/settings/Notifications.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div>
 | 
			
		||||
        <div class="notification-list my-4">
 | 
			
		||||
            <p v-if="$root.notificationList.length === 0">
 | 
			
		||||
                {{ $t("Not available, please setup.") }}
 | 
			
		||||
            </p>
 | 
			
		||||
            <p v-else>
 | 
			
		||||
                {{ $t("notificationDescription") }}
 | 
			
		||||
            </p>
 | 
			
		||||
 | 
			
		||||
            <ul class="list-group mb-3" style="border-radius: 1rem;">
 | 
			
		||||
                <li v-for="(notification, index) in $root.notificationList" :key="index" class="list-group-item">
 | 
			
		||||
                    {{ notification.name }}<br>
 | 
			
		||||
                    <a href="#" @click="$refs.notificationDialog.show(notification.id)">{{ $t("Edit") }}</a>
 | 
			
		||||
                </li>
 | 
			
		||||
            </ul>
 | 
			
		||||
 | 
			
		||||
            <button class="btn btn-primary me-2" type="button" @click="$refs.notificationDialog.show()">
 | 
			
		||||
                {{ $t("Setup Notification") }}
 | 
			
		||||
            </button>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <NotificationDialog ref="notificationDialog" />
 | 
			
		||||
    </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import NotificationDialog from "../../components/NotificationDialog.vue";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
    components: {
 | 
			
		||||
        NotificationDialog
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
@import "../../assets/vars.scss";
 | 
			
		||||
 | 
			
		||||
.dark {
 | 
			
		||||
    .list-group-item {
 | 
			
		||||
        background-color: $dark-bg2;
 | 
			
		||||
        color: $dark-font-color;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										323
									
								
								src/components/settings/Security.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										323
									
								
								src/components/settings/Security.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,323 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div>
 | 
			
		||||
        <div v-if="settingsLoaded" class="my-4">
 | 
			
		||||
            <!-- Change Password -->
 | 
			
		||||
            <template v-if="!settings.disableAuth">
 | 
			
		||||
                <p>
 | 
			
		||||
                    {{ $t("Current User") }}: <strong>{{ username }}</strong>
 | 
			
		||||
                </p>
 | 
			
		||||
 | 
			
		||||
                <h5 class="my-4">{{ $t("Change Password") }}</h5>
 | 
			
		||||
                <form class="mb-3" @submit.prevent="savePassword">
 | 
			
		||||
                    <div class="mb-3">
 | 
			
		||||
                        <label for="current-password" class="form-label">
 | 
			
		||||
                            {{ $t("Current Password") }}
 | 
			
		||||
                        </label>
 | 
			
		||||
                        <input
 | 
			
		||||
                            id="current-password"
 | 
			
		||||
                            v-model="password.currentPassword"
 | 
			
		||||
                            type="password"
 | 
			
		||||
                            class="form-control"
 | 
			
		||||
                            required
 | 
			
		||||
                        />
 | 
			
		||||
                    </div>
 | 
			
		||||
 | 
			
		||||
                    <div class="mb-3">
 | 
			
		||||
                        <label for="new-password" class="form-label">
 | 
			
		||||
                            {{ $t("New Password") }}
 | 
			
		||||
                        </label>
 | 
			
		||||
                        <input
 | 
			
		||||
                            id="new-password"
 | 
			
		||||
                            v-model="password.newPassword"
 | 
			
		||||
                            type="password"
 | 
			
		||||
                            class="form-control"
 | 
			
		||||
                            required
 | 
			
		||||
                        />
 | 
			
		||||
                    </div>
 | 
			
		||||
 | 
			
		||||
                    <div class="mb-3">
 | 
			
		||||
                        <label for="repeat-new-password" class="form-label">
 | 
			
		||||
                            {{ $t("Repeat New Password") }}
 | 
			
		||||
                        </label>
 | 
			
		||||
                        <input
 | 
			
		||||
                            id="repeat-new-password"
 | 
			
		||||
                            v-model="password.repeatNewPassword"
 | 
			
		||||
                            type="password"
 | 
			
		||||
                            class="form-control"
 | 
			
		||||
                            :class="{ 'is-invalid': invalidPassword }"
 | 
			
		||||
                            required
 | 
			
		||||
                        />
 | 
			
		||||
                        <div class="invalid-feedback">
 | 
			
		||||
                            {{ $t("passwordNotMatchMsg") }}
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
 | 
			
		||||
                    <div>
 | 
			
		||||
                        <button class="btn btn-primary" type="submit">
 | 
			
		||||
                            {{ $t("Update Password") }}
 | 
			
		||||
                        </button>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </form>
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
            <div v-if="!$parent.$parent.settings.disableAuth" class="mt-5 mb-3">
 | 
			
		||||
                <h5 class="my-4">
 | 
			
		||||
                    {{ $t("Two Factor Authentication") }}
 | 
			
		||||
                </h5>
 | 
			
		||||
                <div class="mb-4">
 | 
			
		||||
                    <button
 | 
			
		||||
                        class="btn btn-primary me-2"
 | 
			
		||||
                        type="button"
 | 
			
		||||
                        @click="$refs.TwoFADialog.show()"
 | 
			
		||||
                    >
 | 
			
		||||
                        {{ $t("2FA Settings") }}
 | 
			
		||||
                    </button>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div class="my-4">
 | 
			
		||||
                <!-- Advanced -->
 | 
			
		||||
                <h5 class="my-4">{{ $t("Advanced") }}</h5>
 | 
			
		||||
 | 
			
		||||
                <div class="mb-4">
 | 
			
		||||
                    <button v-if="settings.disableAuth" class="btn btn-outline-primary me-2 mb-2" @click="enableAuth">{{ $t("Enable Auth") }}</button>
 | 
			
		||||
                    <button v-if="! settings.disableAuth" class="btn btn-primary me-2 mb-2" @click="confirmDisableAuth">{{ $t("Disable Auth") }}</button>
 | 
			
		||||
                    <button v-if="! settings.disableAuth" class="btn btn-danger me-2 mb-2" @click="$root.logout">{{ $t("Logout") }}</button>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <TwoFADialog ref="TwoFADialog" />
 | 
			
		||||
 | 
			
		||||
        <Confirm ref="confirmDisableAuth" btn-style="btn-danger" :yes-text="$t('I understand, please disable')" :no-text="$t('Leave')" @yes="disableAuth">
 | 
			
		||||
            <template v-if="$i18n.locale === 'es-ES' ">
 | 
			
		||||
                <p>Seguro que deseas <strong>deshabilitar la autenticación</strong>?</p>
 | 
			
		||||
                <p>Es para <strong>quien implementa autenticación de terceros</strong> ante Uptime Kuma como por ejemplo Cloudflare Access.</p>
 | 
			
		||||
                <p>Por favor usar con cuidado.</p>
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
            <template v-else-if="$i18n.locale === 'pt-BR' ">
 | 
			
		||||
                <p>Você tem certeza que deseja <strong>desativar a autenticação</strong>?</p>
 | 
			
		||||
                <p>Isso é para <strong>alguém que tem autenticação de terceiros</strong> na frente do 'UpTime Kuma' como o Cloudflare Access.</p>
 | 
			
		||||
                <p>Por favor, utilize isso com cautela.</p>
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
            <template v-else-if="$i18n.locale === 'zh-HK' ">
 | 
			
		||||
                <p>你是否確認<strong>取消登入認証</strong>?</p>
 | 
			
		||||
                <p>這個功能是設計給已有<strong>第三方認証</strong>的用家,例如 Cloudflare Access。</p>
 | 
			
		||||
                <p>請小心使用。</p>
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
            <template v-else-if="$i18n.locale === 'zh-CN' ">
 | 
			
		||||
                <p>是否确定 <strong>取消登录验证</strong>?</p>
 | 
			
		||||
                <p>这是为 <strong>有第三方认证</strong> 的用户提供的功能,如 Cloudflare Access</p>
 | 
			
		||||
                <p>请谨慎使用!</p>
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
            <template v-else-if="$i18n.locale === 'zh-TW' ">
 | 
			
		||||
                <p>你是否要<strong>取消登入驗證</strong>?</p>
 | 
			
		||||
                <p>此功能是設計給已有<strong>第三方認證</strong>的使用者,例如 Cloudflare Access。</p>
 | 
			
		||||
                <p>請謹慎使用。</p>
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
            <template v-else-if="$i18n.locale === 'de-DE' ">
 | 
			
		||||
                <p>Bist du sicher das du die <strong>Authentifizierung deaktivieren</strong> möchtest?</p>
 | 
			
		||||
                <p>Es ist für <strong>jemanden der eine externe Authentifizierung</strong> vor Uptime Kuma geschaltet hat, wie z.B. Cloudflare Access.</p>
 | 
			
		||||
                <p>Bitte mit Vorsicht nutzen.</p>
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
            <template v-else-if="$i18n.locale === 'sr' ">
 | 
			
		||||
                <p>Да ли сте сигурни да желите да <strong>искључите аутентификацију</strong>?</p>
 | 
			
		||||
                <p>То је за <strong>оне који имају додату аутентификацију</strong> испред Uptime Kuma као на пример Cloudflare Access.</p>
 | 
			
		||||
                <p>Молим Вас користите ово са пажњом.</p>
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
            <template v-else-if="$i18n.locale === 'sr-latn' ">
 | 
			
		||||
                <p>Da li ste sigurni da želite da <strong>isključite autentifikaciju</strong>?</p>
 | 
			
		||||
                <p>To je za <strong>one koji imaju dodatu autentifikaciju</strong> ispred Uptime Kuma kao na primer Cloudflare Access.</p>
 | 
			
		||||
                <p>Molim Vas koristite ovo sa pažnjom.</p>
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
            <template v-if="$i18n.locale === 'hr-HR' ">
 | 
			
		||||
                <p>Jeste li sigurni da želite <strong>isključiti autentikaciju</strong>?</p>
 | 
			
		||||
                <p>To je za <strong>korisnike koji imaju vanjsku autentikaciju stranice</strong> ispred Uptime Kume, poput usluge Cloudflare Access.</p>
 | 
			
		||||
                <p>Pažljivo koristite ovu opciju.</p>
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
            <template v-else-if="$i18n.locale === 'tr-TR' ">
 | 
			
		||||
                <p><strong>Şifreli girişi devre dışı bırakmak istediğinizden</strong>emin misiniz?</p>
 | 
			
		||||
                <p>Bu, Uptime Kuma'nın önünde Cloudflare Access gibi <strong>üçüncü taraf yetkilendirmesi olan</strong> kişiler içindir.</p>
 | 
			
		||||
                <p>Lütfen dikkatli kullanın.</p>
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
            <template v-else-if="$i18n.locale === 'ko-KR' ">
 | 
			
		||||
                <p>정말로 <strong>인증 기능을 끌까요</strong>?</p>
 | 
			
		||||
                <p>이 기능은 <strong>Cloudflare Access와 같은 서드파티 인증</strong>을 Uptime Kuma 앞에 둔 사용자를 위한 기능이에요.</p>
 | 
			
		||||
                <p>신중하게 사용하세요.</p>
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
            <template v-else-if="$i18n.locale === 'pl' ">
 | 
			
		||||
                <p>Czy na pewno chcesz <strong>wyłączyć autoryzację</strong>?</p>
 | 
			
		||||
                <p>Jest przeznaczony dla <strong>kogoś, kto ma autoryzację zewnętrzną</strong> przed Uptime Kuma, taką jak Cloudflare Access.</p>
 | 
			
		||||
                <p>Proszę używać ostrożnie.</p>
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
            <template v-else-if="$i18n.locale === 'et-EE' ">
 | 
			
		||||
                <p>Kas soovid <strong>lülitada autentimise välja</strong>?</p>
 | 
			
		||||
                <p>Kastuamiseks <strong>välise autentimispakkujaga</strong>, näiteks Cloudflare Access.</p>
 | 
			
		||||
                <p>Palun kasuta vastutustundlikult.</p>
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
            <template v-else-if="$i18n.locale === 'it-IT' ">
 | 
			
		||||
                <p>Si è certi di voler <strong>disabilitare l'autenticazione</strong>?</p>
 | 
			
		||||
                <p>È per <strong>chi ha l'autenticazione gestita da terze parti</strong> messa davanti ad Uptime Kuma, ad esempio Cloudflare Access.</p>
 | 
			
		||||
                <p>Utilizzare con attenzione.</p>
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
            <template v-else-if="$i18n.locale === 'id-ID' ">
 | 
			
		||||
                <p>Apakah Anda yakin ingin <strong>menonaktifkan autentikasi</strong>?</p>
 | 
			
		||||
                <p>Ini untuk <strong>mereka yang memiliki autentikasi pihak ketiga</strong> diletakkan di depan Uptime Kuma, misalnya akses Cloudflare.</p>
 | 
			
		||||
                <p>Gunakan dengan hati-hati.</p>
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
            <template v-else-if="$i18n.locale === 'ru-RU' ">
 | 
			
		||||
                <p>Вы уверены, что хотите <strong>отключить авторизацию</strong>?</p>
 | 
			
		||||
                <p>Это подходит для <strong>тех, у кого стоит другая авторизация</strong> перед открытием Uptime Kuma, например Cloudflare Access.</p>
 | 
			
		||||
                <p>Пожалуйста, используйте с осторожностью.</p>
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
            <template v-else-if="$i18n.locale === 'fa' ">
 | 
			
		||||
                <p>آیا مطمئن هستید که میخواهید <strong>احراز هویت را غیر فعال کنید</strong>?</p>
 | 
			
		||||
                <p>این ویژگی برای کسانی است که <strong> لایه امنیتی شخص ثالث دیگر بر روی این آدرس فعال کردهاند</strong>، مانند Cloudflare Access.</p>
 | 
			
		||||
                <p>لطفا از این امکان با دقت استفاده کنید.</p>
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
            <template v-else-if="$i18n.locale === 'bg-BG' ">
 | 
			
		||||
                <p>Сигурни ли сте, че желаете да <strong>изключите удостоверяването</strong>?</p>
 | 
			
		||||
                <p>Използва се в случаите, когато <strong>има настроен алтернативен метод за удостоверяване</strong> преди Uptime Kuma, например Cloudflare Access.</p>
 | 
			
		||||
                <p>Моля, използвайте с повишено внимание.</p>
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
            <template v-else-if="$i18n.locale === 'hu' ">
 | 
			
		||||
                <p>Biztos benne, hogy <strong>kikapcsolja a hitelesítést</strong>?</p>
 | 
			
		||||
                <p>Akkor érdemes, ha <strong>van 3rd-party hitelesítés</strong> az Uptime Kuma-t megelőzően mint a Cloudflare Access.</p>
 | 
			
		||||
                <p>Használja megfontoltan!</p>
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
            <template v-else-if="$i18n.locale === 'nb-NO' ">
 | 
			
		||||
                <p>Er du sikker på at du vil <strong>deaktiver autentisering</strong>?</p>
 | 
			
		||||
                <p>Dette er for <strong>de som har tredjepartsautorisering</strong> foran Uptime Kuma, for eksempel Cloudflare Access.</p>
 | 
			
		||||
                <p>Vennligst vær forsiktig.</p>
 | 
			
		||||
            </template>
 | 
			
		||||
 | 
			
		||||
            <!-- English (en) -->
 | 
			
		||||
            <template v-else>
 | 
			
		||||
                <p>Are you sure want to <strong>disable auth</strong>?</p>
 | 
			
		||||
                <p>It is for <strong>someone who have 3rd-party auth</strong> in front of Uptime Kuma such as Cloudflare Access.</p>
 | 
			
		||||
                <p>Please use it carefully.</p>
 | 
			
		||||
            </template>
 | 
			
		||||
        </Confirm>
 | 
			
		||||
    </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import Confirm from "../../components/Confirm.vue";
 | 
			
		||||
import TwoFADialog from "../../components/TwoFADialog.vue";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
    components: {
 | 
			
		||||
        Confirm,
 | 
			
		||||
        TwoFADialog
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    data() {
 | 
			
		||||
        return {
 | 
			
		||||
            username: "",
 | 
			
		||||
            invalidPassword: false,
 | 
			
		||||
            password: {
 | 
			
		||||
                currentPassword: "",
 | 
			
		||||
                newPassword: "",
 | 
			
		||||
                repeatNewPassword: "",
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    computed: {
 | 
			
		||||
        settings() {
 | 
			
		||||
            return this.$parent.$parent.settings;
 | 
			
		||||
        },
 | 
			
		||||
        saveSettings() {
 | 
			
		||||
            return this.$parent.$parent.saveSettings;
 | 
			
		||||
        },
 | 
			
		||||
        settingsLoaded() {
 | 
			
		||||
            return this.$parent.$parent.settingsLoaded;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    watch: {
 | 
			
		||||
        "password.repeatNewPassword"() {
 | 
			
		||||
            this.invalidPassword = false;
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    mounted() {
 | 
			
		||||
        this.loadUsername();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    methods: {
 | 
			
		||||
        savePassword() {
 | 
			
		||||
            if (this.password.newPassword !== this.password.repeatNewPassword) {
 | 
			
		||||
                this.invalidPassword = true;
 | 
			
		||||
            } else {
 | 
			
		||||
                this.$root
 | 
			
		||||
                    .getSocket()
 | 
			
		||||
                    .emit("changePassword", this.password, (res) => {
 | 
			
		||||
                        this.$root.toastRes(res);
 | 
			
		||||
                        if (res.ok) {
 | 
			
		||||
                            this.password.currentPassword = "";
 | 
			
		||||
                            this.password.newPassword = "";
 | 
			
		||||
                            this.password.repeatNewPassword = "";
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        loadUsername() {
 | 
			
		||||
            const jwtPayload = this.$root.getJWTPayload();
 | 
			
		||||
 | 
			
		||||
            if (jwtPayload) {
 | 
			
		||||
                this.username = jwtPayload.username;
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        disableAuth() {
 | 
			
		||||
            this.settings.disableAuth = true;
 | 
			
		||||
            this.saveSettings();
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        enableAuth() {
 | 
			
		||||
            this.settings.disableAuth = false;
 | 
			
		||||
            this.saveSettings();
 | 
			
		||||
            this.$root.storage().removeItem("token");
 | 
			
		||||
            location.reload();
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        confirmDisableAuth() {
 | 
			
		||||
            this.$refs.confirmDisableAuth.show();
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
@import "../../assets/vars.scss";
 | 
			
		||||
 | 
			
		||||
h5:after {
 | 
			
		||||
    content: "";
 | 
			
		||||
    display: block;
 | 
			
		||||
    width: 50%;
 | 
			
		||||
    padding-top: 8px;
 | 
			
		||||
    border-bottom: 1px solid $dark-border-color;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -307,4 +307,5 @@ export default {
 | 
			
		||||
    steamApiKeyDescription: "For monitoring a Steam Game Server you need a Steam Web-API key. You can register your API key here: ",
 | 
			
		||||
    "Current User": "Current User",
 | 
			
		||||
    recent: "Recent",
 | 
			
		||||
    shrinkDatabaseDescription: "Trigger database VACCUM for SQLite. If your database is created after 1.10.0, AUTO_VACCUM is already enabled and this action is not needed.",
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -188,8 +188,8 @@ main {
 | 
			
		||||
 | 
			
		||||
.dark {
 | 
			
		||||
    header {
 | 
			
		||||
        background-color: #161b22;
 | 
			
		||||
        border-bottom-color: #161b22 !important;
 | 
			
		||||
        background-color: $dark-header-bg;
 | 
			
		||||
        border-bottom-color: $dark-header-bg !important;
 | 
			
		||||
 | 
			
		||||
        span {
 | 
			
		||||
            color: #f0f6fc;
 | 
			
		||||
 
 | 
			
		||||
@@ -7,521 +7,90 @@
 | 
			
		||||
 | 
			
		||||
            <div class="shadow-box">
 | 
			
		||||
                <div class="row">
 | 
			
		||||
                    <div class="col-md-6">
 | 
			
		||||
                        <h2 class="mb-2">{{ $t("Appearance") }}</h2>
 | 
			
		||||
 | 
			
		||||
                        <div class="mb-3">
 | 
			
		||||
                            <label for="language" class="form-label">{{ $t("Language") }}</label>
 | 
			
		||||
                            <select id="language" v-model="$i18n.locale" class="form-select">
 | 
			
		||||
                                <option v-for="(lang, i) in $i18n.availableLocales" :key="`Lang${i}`" :value="lang">
 | 
			
		||||
                                    {{ $i18n.messages[lang].languageName }}
 | 
			
		||||
                                </option>
 | 
			
		||||
                            </select>
 | 
			
		||||
                    <div class="settings-menu">
 | 
			
		||||
                        <div v-for="(item, key) in subMenus"
 | 
			
		||||
                             :key="key"
 | 
			
		||||
                             class="menu-item"
 | 
			
		||||
                             :class="{ active: currentSubMenu == key }"
 | 
			
		||||
                             @click="currentSubMenu = key"
 | 
			
		||||
                        >
 | 
			
		||||
                            {{ item.title }}
 | 
			
		||||
                        </div>
 | 
			
		||||
 | 
			
		||||
                        <div class="mb-3">
 | 
			
		||||
                            <label for="timezone" class="form-label">{{ $t("Theme") }}</label>
 | 
			
		||||
 | 
			
		||||
                            <div>
 | 
			
		||||
                                <div class="btn-group" role="group" aria-label="Basic checkbox toggle button group">
 | 
			
		||||
                                    <input id="btncheck1" v-model="$root.userTheme" type="radio" class="btn-check" name="theme" autocomplete="off" value="light">
 | 
			
		||||
                                    <label class="btn btn-outline-primary" for="btncheck1">{{ $t("Light") }}</label>
 | 
			
		||||
 | 
			
		||||
                                    <input id="btncheck2" v-model="$root.userTheme" type="radio" class="btn-check" name="theme" autocomplete="off" value="dark">
 | 
			
		||||
                                    <label class="btn btn-outline-primary" for="btncheck2">{{ $t("Dark") }}</label>
 | 
			
		||||
 | 
			
		||||
                                    <input id="btncheck3" v-model="$root.userTheme" type="radio" class="btn-check" name="theme" autocomplete="off" value="auto">
 | 
			
		||||
                                    <label class="btn btn-outline-primary" for="btncheck3">{{ $t("Auto") }}</label>
 | 
			
		||||
                                </div>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
 | 
			
		||||
                        <div class="mb-3">
 | 
			
		||||
                            <label class="form-label">{{ $t("Theme - Heartbeat Bar") }}</label>
 | 
			
		||||
                            <div>
 | 
			
		||||
                                <div class="btn-group" role="group" aria-label="Basic checkbox toggle button group">
 | 
			
		||||
                                    <input id="btncheck4" v-model="$root.userHeartbeatBar" type="radio" class="btn-check" name="heartbeatBarTheme" autocomplete="off" value="normal">
 | 
			
		||||
                                    <label class="btn btn-outline-primary" for="btncheck4">{{ $t("Normal") }}</label>
 | 
			
		||||
 | 
			
		||||
                                    <input id="btncheck5" v-model="$root.userHeartbeatBar" type="radio" class="btn-check" name="heartbeatBarTheme" autocomplete="off" value="bottom">
 | 
			
		||||
                                    <label class="btn btn-outline-primary" for="btncheck5">{{ $t("Bottom") }}</label>
 | 
			
		||||
 | 
			
		||||
                                    <input id="btncheck6" v-model="$root.userHeartbeatBar" type="radio" class="btn-check" name="heartbeatBarTheme" autocomplete="off" value="none">
 | 
			
		||||
                                    <label class="btn btn-outline-primary" for="btncheck6">{{ $t("None") }}</label>
 | 
			
		||||
                                </div>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
 | 
			
		||||
                        <!-- General Settings -->
 | 
			
		||||
                        <h2 class="mt-5 mb-2">{{ $t("General") }}</h2>
 | 
			
		||||
 | 
			
		||||
                        <form class="mb-3" @submit.prevent="saveGeneral">
 | 
			
		||||
                            <!-- Timezone -->
 | 
			
		||||
                            <div class="mb-4">
 | 
			
		||||
                                <label for="timezone" class="form-label">{{ $t("Timezone") }}</label>
 | 
			
		||||
                                <select id="timezone" v-model="$root.userTimezone" class="form-select">
 | 
			
		||||
                                    <option value="auto">
 | 
			
		||||
                                        {{ $t("Auto") }}: {{ guessTimezone }}
 | 
			
		||||
                                    </option>
 | 
			
		||||
                                    <option v-for="(timezone, index) in timezoneList" :key="index" :value="timezone.value">
 | 
			
		||||
                                        {{ timezone.name }}
 | 
			
		||||
                                    </option>
 | 
			
		||||
                                </select>
 | 
			
		||||
                            </div>
 | 
			
		||||
 | 
			
		||||
                            <!-- Search Engine -->
 | 
			
		||||
                            <div class="mb-4">
 | 
			
		||||
                                <label class="form-label">{{ $t("Search Engine Visibility") }}</label>
 | 
			
		||||
 | 
			
		||||
                                <div class="form-check">
 | 
			
		||||
                                    <input id="searchEngineIndexYes" v-model="settings.searchEngineIndex" class="form-check-input" type="radio" name="flexRadioDefault" :value="true" required>
 | 
			
		||||
                                    <label class="form-check-label" for="searchEngineIndexYes">
 | 
			
		||||
                                        {{ $t("Allow indexing") }}
 | 
			
		||||
                                    </label>
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <div class="form-check">
 | 
			
		||||
                                    <input id="searchEngineIndexNo" v-model="settings.searchEngineIndex" class="form-check-input" type="radio" name="flexRadioDefault" :value="false" required>
 | 
			
		||||
                                    <label class="form-check-label" for="searchEngineIndexNo">
 | 
			
		||||
                                        {{ $t("Discourage search engines from indexing site") }}
 | 
			
		||||
                                    </label>
 | 
			
		||||
                                </div>
 | 
			
		||||
                            </div>
 | 
			
		||||
 | 
			
		||||
                            <!-- Entry Page -->
 | 
			
		||||
                            <div class="mb-4">
 | 
			
		||||
                                <label class="form-label">{{ $t("Entry Page") }}</label>
 | 
			
		||||
 | 
			
		||||
                                <div class="form-check">
 | 
			
		||||
                                    <input id="entryPageYes" v-model="settings.entryPage" class="form-check-input" type="radio" name="statusPage" value="dashboard" required>
 | 
			
		||||
                                    <label class="form-check-label" for="entryPageYes">
 | 
			
		||||
                                        {{ $t("Dashboard") }}
 | 
			
		||||
                                    </label>
 | 
			
		||||
                                </div>
 | 
			
		||||
 | 
			
		||||
                                <div class="form-check">
 | 
			
		||||
                                    <input id="entryPageNo" v-model="settings.entryPage" class="form-check-input" type="radio" name="statusPage" value="statusPage" required>
 | 
			
		||||
                                    <label class="form-check-label" for="entryPageNo">
 | 
			
		||||
                                        {{ $t("Status Page") }}
 | 
			
		||||
                                    </label>
 | 
			
		||||
                                </div>
 | 
			
		||||
                            </div>
 | 
			
		||||
 | 
			
		||||
                            <!-- Primary Base URL -->
 | 
			
		||||
                            <div class="mb-4">
 | 
			
		||||
                                <label class="form-label" for="primaryBaseURL">{{ $t("Primary Base URL") }}</label>
 | 
			
		||||
 | 
			
		||||
                                <div class="input-group mb-3">
 | 
			
		||||
                                    <input id="primaryBaseURL" v-model="settings.primaryBaseURL" class="form-control" name="primaryBaseURL" placeholder="https://" pattern="https?://.+">
 | 
			
		||||
                                    <button class="btn btn-outline-primary" type="button" @click="autoGetPrimaryBaseURL">{{ $t("Auto Get") }}</button>
 | 
			
		||||
                                </div>
 | 
			
		||||
 | 
			
		||||
                                <div class="form-text">
 | 
			
		||||
                                </div>
 | 
			
		||||
                            </div>
 | 
			
		||||
 | 
			
		||||
                            <!-- Steam API Key -->
 | 
			
		||||
                            <div class="mb-4">
 | 
			
		||||
                                <label class="form-label" for="steamAPIKey">{{ $t("Steam API Key") }}</label>
 | 
			
		||||
                                <HiddenInput id="steamAPIKey" v-model="settings.steamAPIKey" />
 | 
			
		||||
                                <div class="form-text">
 | 
			
		||||
                                    {{ $t("steamApiKeyDescription") }}<a href="https://steamcommunity.com/dev" target="_blank">https://steamcommunity.com/dev</a>
 | 
			
		||||
                                </div>
 | 
			
		||||
                            </div>
 | 
			
		||||
 | 
			
		||||
                            <!-- Monitor History -->
 | 
			
		||||
                            <div class="mb-4">
 | 
			
		||||
                                <h4 class="mt-4">{{ $t("Monitor History") }}</h4>
 | 
			
		||||
                                <div class="mt-2">
 | 
			
		||||
                                    <label for="keepDataPeriodDays" class="form-label">{{ $t("clearDataOlderThan", [ settings.keepDataPeriodDays ]) }}</label>
 | 
			
		||||
                                    <input id="keepDataPeriodDays" v-model="settings.keepDataPeriodDays" type="number" class="form-control" required min="1" step="1">
 | 
			
		||||
                                </div>
 | 
			
		||||
                            </div>
 | 
			
		||||
 | 
			
		||||
                            <!-- Save Button -->
 | 
			
		||||
                            <div>
 | 
			
		||||
                                <button class="btn btn-primary" type="submit">
 | 
			
		||||
                                    {{ $t("Save") }}
 | 
			
		||||
                                </button>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </form>
 | 
			
		||||
 | 
			
		||||
                        <template v-if="loaded">
 | 
			
		||||
                            <!-- Change Password -->
 | 
			
		||||
                            <template v-if="! settings.disableAuth">
 | 
			
		||||
                                <h2 class="mt-5 mb-2">{{ $t("Change Password") }}</h2>
 | 
			
		||||
                                <p>{{ $t("Current User") }}: <strong>{{ username }}</strong></p>
 | 
			
		||||
                                <form class="mb-3" @submit.prevent="savePassword">
 | 
			
		||||
                                    <div class="mb-3">
 | 
			
		||||
                                        <label for="current-password" class="form-label">{{ $t("Current Password") }}</label>
 | 
			
		||||
                                        <input id="current-password" v-model="password.currentPassword" type="password" class="form-control" required>
 | 
			
		||||
                                    </div>
 | 
			
		||||
 | 
			
		||||
                                    <div class="mb-3">
 | 
			
		||||
                                        <label for="new-password" class="form-label">{{ $t("New Password") }}</label>
 | 
			
		||||
                                        <input id="new-password" v-model="password.newPassword" type="password" class="form-control" required>
 | 
			
		||||
                                    </div>
 | 
			
		||||
 | 
			
		||||
                                    <div class="mb-3">
 | 
			
		||||
                                        <label for="repeat-new-password" class="form-label">{{ $t("Repeat New Password") }}</label>
 | 
			
		||||
                                        <input id="repeat-new-password" v-model="password.repeatNewPassword" type="password" class="form-control" :class="{ 'is-invalid' : invalidPassword }" required>
 | 
			
		||||
                                        <div class="invalid-feedback">
 | 
			
		||||
                                            {{ $t("passwordNotMatchMsg") }}
 | 
			
		||||
                                        </div>
 | 
			
		||||
                                    </div>
 | 
			
		||||
 | 
			
		||||
                                    <div>
 | 
			
		||||
                                        <button class="btn btn-primary" type="submit">
 | 
			
		||||
                                            {{ $t("Update Password") }}
 | 
			
		||||
                                        </button>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                </form>
 | 
			
		||||
                            </template>
 | 
			
		||||
 | 
			
		||||
                            <div v-if="! settings.disableAuth" class="mt-5 mb-3">
 | 
			
		||||
                                <h2 class="mb-2">
 | 
			
		||||
                                    {{ $t("Two Factor Authentication") }}
 | 
			
		||||
                                </h2>
 | 
			
		||||
                                <button class="btn btn-primary me-2" type="button" @click="$refs.TwoFADialog.show()">{{ $t("2FA Settings") }}</button>
 | 
			
		||||
                            </div>
 | 
			
		||||
 | 
			
		||||
                            <h2 class="mt-5 mb-2">{{ $t("Export Backup") }}</h2>
 | 
			
		||||
 | 
			
		||||
                            <p>
 | 
			
		||||
                                {{ $t("backupDescription") }} <br />
 | 
			
		||||
                                ({{ $t("backupDescription2") }}) <br />
 | 
			
		||||
                            </p>
 | 
			
		||||
 | 
			
		||||
                            <div class="mb-2">
 | 
			
		||||
                                <button class="btn btn-primary" @click="downloadBackup">{{ $t("Export") }}</button>
 | 
			
		||||
                            </div>
 | 
			
		||||
 | 
			
		||||
                            <p><strong>{{ $t("backupDescription3") }}</strong></p>
 | 
			
		||||
 | 
			
		||||
                            <h2 class="mt-5 mb-2">{{ $t("Import Backup") }}</h2>
 | 
			
		||||
 | 
			
		||||
                            <label class="form-label">{{ $t("Options") }}:</label>
 | 
			
		||||
                            <br>
 | 
			
		||||
                            <div class="form-check form-check-inline">
 | 
			
		||||
                                <input id="radioKeep" v-model="importHandle" class="form-check-input" type="radio" name="radioImportHandle" value="keep">
 | 
			
		||||
                                <label class="form-check-label" for="radioKeep">{{ $t("Keep both") }}</label>
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div class="form-check form-check-inline">
 | 
			
		||||
                                <input id="radioSkip" v-model="importHandle" class="form-check-input" type="radio" name="radioImportHandle" value="skip">
 | 
			
		||||
                                <label class="form-check-label" for="radioSkip">{{ $t("Skip existing") }}</label>
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div class="form-check form-check-inline">
 | 
			
		||||
                                <input id="radioOverwrite" v-model="importHandle" class="form-check-input" type="radio" name="radioImportHandle" value="overwrite">
 | 
			
		||||
                                <label class="form-check-label" for="radioOverwrite">{{ $t("Overwrite") }}</label>
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div class="form-text mb-2">
 | 
			
		||||
                                {{ $t("importHandleDescription") }}
 | 
			
		||||
                            </div>
 | 
			
		||||
 | 
			
		||||
                            <div class="mb-2">
 | 
			
		||||
                                <input id="importBackup" type="file" class="form-control" accept="application/json">
 | 
			
		||||
                            </div>
 | 
			
		||||
 | 
			
		||||
                            <div class="input-group mb-2 justify-content-end">
 | 
			
		||||
                                <button type="button" class="btn btn-outline-primary" :disabled="processing" @click="confirmImport">
 | 
			
		||||
                                    <div v-if="processing" class="spinner-border spinner-border-sm me-1"></div>
 | 
			
		||||
                                    {{ $t("Import") }}
 | 
			
		||||
                                </button>
 | 
			
		||||
                            </div>
 | 
			
		||||
 | 
			
		||||
                            <div v-if="importAlert" class="alert alert-danger mt-3" style="padding: 6px 16px;">
 | 
			
		||||
                                {{ importAlert }}
 | 
			
		||||
                            </div>
 | 
			
		||||
 | 
			
		||||
                            <!-- Advanced -->
 | 
			
		||||
                            <h2 class="mt-5 mb-2">{{ $t("Advanced") }}</h2>
 | 
			
		||||
 | 
			
		||||
                            <div class="mb-3">
 | 
			
		||||
                                <button v-if="settings.disableAuth" class="btn btn-outline-primary me-2 mb-2" @click="enableAuth">{{ $t("Enable Auth") }}</button>
 | 
			
		||||
                                <button v-if="! settings.disableAuth" class="btn btn-primary me-2 mb-2" @click="confirmDisableAuth">{{ $t("Disable Auth") }}</button>
 | 
			
		||||
                                <button v-if="! settings.disableAuth" class="btn btn-danger me-2 mb-2" @click="$root.logout">{{ $t("Logout") }}</button>
 | 
			
		||||
                                <button class="btn btn-outline-danger me-2 mb-2" @click="confirmClearStatistics">{{ $t("Clear all statistics") }}</button>
 | 
			
		||||
                                <button class="btn btn-info me-2 mb-2" @click="shrinkDatabase">{{ $t("Shrink Database") }} ({{ databaseSizeDisplay }})</button>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </template>
 | 
			
		||||
                    </div>
 | 
			
		||||
 | 
			
		||||
                    <div class="col-md-6">
 | 
			
		||||
                        <div v-if="$root.isMobile" class="mt-3" />
 | 
			
		||||
 | 
			
		||||
                        <!-- Notifications -->
 | 
			
		||||
                        <div class="notification-list ">
 | 
			
		||||
                            <h2>{{ $t("Notifications") }}</h2>
 | 
			
		||||
                            <p v-if="$root.notificationList.length === 0">
 | 
			
		||||
                                {{ $t("Not available, please setup.") }}
 | 
			
		||||
                            </p>
 | 
			
		||||
                            <p v-else>
 | 
			
		||||
                                {{ $t("notificationDescription") }}
 | 
			
		||||
                            </p>
 | 
			
		||||
 | 
			
		||||
                            <ul class="list-group mb-3" style="border-radius: 1rem;">
 | 
			
		||||
                                <li v-for="(notification, index) in $root.notificationList" :key="index" class="list-group-item">
 | 
			
		||||
                                    {{ notification.name }}<br>
 | 
			
		||||
                                    <a href="#" @click="$refs.notificationDialog.show(notification.id)">{{ $t("Edit") }}</a>
 | 
			
		||||
                                </li>
 | 
			
		||||
                            </ul>
 | 
			
		||||
 | 
			
		||||
                            <button class="btn btn-primary me-2" type="button" @click="$refs.notificationDialog.show()">
 | 
			
		||||
                                {{ $t("Setup Notification") }}
 | 
			
		||||
                            </button>
 | 
			
		||||
                    <div class="settings-content">
 | 
			
		||||
                        <div class="settings-content-header">
 | 
			
		||||
                            {{ subMenus[currentSubMenu].title }}
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div class="mx-3">
 | 
			
		||||
                            <component :is="subMenus[currentSubMenu].component" />
 | 
			
		||||
                        </div>
 | 
			
		||||
 | 
			
		||||
                        <!-- Info -->
 | 
			
		||||
                        <h2 class="mt-5">{{ $t("Info") }}</h2>
 | 
			
		||||
 | 
			
		||||
                        {{ $t("Version") }}: {{ $root.info.version }} <br />
 | 
			
		||||
                        <a href="https://github.com/louislam/uptime-kuma/releases" target="_blank" rel="noopener">{{ $t("Check Update On GitHub") }}</a>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <NotificationDialog ref="notificationDialog" />
 | 
			
		||||
            <TwoFADialog ref="TwoFADialog" />
 | 
			
		||||
 | 
			
		||||
            <Confirm ref="confirmDisableAuth" btn-style="btn-danger" :yes-text="$t('I understand, please disable')" :no-text="$t('Leave')" @yes="disableAuth">
 | 
			
		||||
                <template v-if="$i18n.locale === 'es-ES' ">
 | 
			
		||||
                    <p>Seguro que deseas <strong>deshabilitar la autenticación</strong>?</p>
 | 
			
		||||
                    <p>Es para <strong>quien implementa autenticación de terceros</strong> ante Uptime Kuma como por ejemplo Cloudflare Access.</p>
 | 
			
		||||
                    <p>Por favor usar con cuidado.</p>
 | 
			
		||||
                </template>
 | 
			
		||||
 | 
			
		||||
                <template v-else-if="$i18n.locale === 'pt-BR' ">
 | 
			
		||||
                    <p>Você tem certeza que deseja <strong>desativar a autenticação</strong>?</p>
 | 
			
		||||
                    <p>Isso é para <strong>alguém que tem autenticação de terceiros</strong> na frente do 'UpTime Kuma' como o Cloudflare Access.</p>
 | 
			
		||||
                    <p>Por favor, utilize isso com cautela.</p>
 | 
			
		||||
                </template>
 | 
			
		||||
 | 
			
		||||
                <template v-else-if="$i18n.locale === 'zh-HK' ">
 | 
			
		||||
                    <p>你是否確認<strong>取消登入認証</strong>?</p>
 | 
			
		||||
                    <p>這個功能是設計給已有<strong>第三方認証</strong>的用家,例如 Cloudflare Access。</p>
 | 
			
		||||
                    <p>請小心使用。</p>
 | 
			
		||||
                </template>
 | 
			
		||||
 | 
			
		||||
                <template v-else-if="$i18n.locale === 'zh-CN' ">
 | 
			
		||||
                    <p>是否确定 <strong>取消登录验证</strong>?</p>
 | 
			
		||||
                    <p>这是为 <strong>有第三方认证</strong> 的用户提供的功能,如 Cloudflare Access</p>
 | 
			
		||||
                    <p>请谨慎使用!</p>
 | 
			
		||||
                </template>
 | 
			
		||||
 | 
			
		||||
                <template v-else-if="$i18n.locale === 'zh-TW' ">
 | 
			
		||||
                    <p>你是否要<strong>取消登入驗證</strong>?</p>
 | 
			
		||||
                    <p>此功能是設計給已有<strong>第三方認證</strong>的使用者,例如 Cloudflare Access。</p>
 | 
			
		||||
                    <p>請謹慎使用。</p>
 | 
			
		||||
                </template>
 | 
			
		||||
 | 
			
		||||
                <template v-else-if="$i18n.locale === 'de-DE' ">
 | 
			
		||||
                    <p>Bist du sicher das du die <strong>Authentifizierung deaktivieren</strong> möchtest?</p>
 | 
			
		||||
                    <p>Es ist für <strong>jemanden der eine externe Authentifizierung</strong> vor Uptime Kuma geschaltet hat, wie z.B. Cloudflare Access.</p>
 | 
			
		||||
                    <p>Bitte mit Vorsicht nutzen.</p>
 | 
			
		||||
                </template>
 | 
			
		||||
 | 
			
		||||
                <template v-else-if="$i18n.locale === 'sr' ">
 | 
			
		||||
                    <p>Да ли сте сигурни да желите да <strong>искључите аутентификацију</strong>?</p>
 | 
			
		||||
                    <p>То је за <strong>оне који имају додату аутентификацију</strong> испред Uptime Kuma као на пример Cloudflare Access.</p>
 | 
			
		||||
                    <p>Молим Вас користите ово са пажњом.</p>
 | 
			
		||||
                </template>
 | 
			
		||||
 | 
			
		||||
                <template v-else-if="$i18n.locale === 'sr-latn' ">
 | 
			
		||||
                    <p>Da li ste sigurni da želite da <strong>isključite autentifikaciju</strong>?</p>
 | 
			
		||||
                    <p>To je za <strong>one koji imaju dodatu autentifikaciju</strong> ispred Uptime Kuma kao na primer Cloudflare Access.</p>
 | 
			
		||||
                    <p>Molim Vas koristite ovo sa pažnjom.</p>
 | 
			
		||||
                </template>
 | 
			
		||||
 | 
			
		||||
                <template v-if="$i18n.locale === 'hr-HR' ">
 | 
			
		||||
                    <p>Jeste li sigurni da želite <strong>isključiti autentikaciju</strong>?</p>
 | 
			
		||||
                    <p>To je za <strong>korisnike koji imaju vanjsku autentikaciju stranice</strong> ispred Uptime Kume, poput usluge Cloudflare Access.</p>
 | 
			
		||||
                    <p>Pažljivo koristite ovu opciju.</p>
 | 
			
		||||
                </template>
 | 
			
		||||
 | 
			
		||||
                <template v-else-if="$i18n.locale === 'tr-TR' ">
 | 
			
		||||
                    <p><strong>Şifreli girişi devre dışı bırakmak istediğinizden</strong>emin misiniz?</p>
 | 
			
		||||
                    <p>Bu, Uptime Kuma'nın önünde Cloudflare Access gibi <strong>üçüncü taraf yetkilendirmesi olan</strong> kişiler içindir.</p>
 | 
			
		||||
                    <p>Lütfen dikkatli kullanın.</p>
 | 
			
		||||
                </template>
 | 
			
		||||
 | 
			
		||||
                <template v-else-if="$i18n.locale === 'ko-KR' ">
 | 
			
		||||
                    <p>정말로 <strong>인증 기능을 끌까요</strong>?</p>
 | 
			
		||||
                    <p>이 기능은 <strong>Cloudflare Access와 같은 서드파티 인증</strong>을 Uptime Kuma 앞에 둔 사용자를 위한 기능이에요.</p>
 | 
			
		||||
                    <p>신중하게 사용하세요.</p>
 | 
			
		||||
                </template>
 | 
			
		||||
 | 
			
		||||
                <template v-else-if="$i18n.locale === 'pl' ">
 | 
			
		||||
                    <p>Czy na pewno chcesz <strong>wyłączyć autoryzację</strong>?</p>
 | 
			
		||||
                    <p>Jest przeznaczony dla <strong>kogoś, kto ma autoryzację zewnętrzną</strong> przed Uptime Kuma, taką jak Cloudflare Access.</p>
 | 
			
		||||
                    <p>Proszę używać ostrożnie.</p>
 | 
			
		||||
                </template>
 | 
			
		||||
 | 
			
		||||
                <template v-else-if="$i18n.locale === 'et-EE' ">
 | 
			
		||||
                    <p>Kas soovid <strong>lülitada autentimise välja</strong>?</p>
 | 
			
		||||
                    <p>Kastuamiseks <strong>välise autentimispakkujaga</strong>, näiteks Cloudflare Access.</p>
 | 
			
		||||
                    <p>Palun kasuta vastutustundlikult.</p>
 | 
			
		||||
                </template>
 | 
			
		||||
 | 
			
		||||
                <template v-else-if="$i18n.locale === 'it-IT' ">
 | 
			
		||||
                    <p>Si è certi di voler <strong>disabilitare l'autenticazione</strong>?</p>
 | 
			
		||||
                    <p>È per <strong>chi ha l'autenticazione gestita da terze parti</strong> messa davanti ad Uptime Kuma, ad esempio Cloudflare Access.</p>
 | 
			
		||||
                    <p>Utilizzare con attenzione.</p>
 | 
			
		||||
                </template>
 | 
			
		||||
 | 
			
		||||
                <template v-else-if="$i18n.locale === 'id-ID' ">
 | 
			
		||||
                    <p>Apakah Anda yakin ingin <strong>menonaktifkan autentikasi</strong>?</p>
 | 
			
		||||
                    <p>Ini untuk <strong>mereka yang memiliki autentikasi pihak ketiga</strong> diletakkan di depan Uptime Kuma, misalnya akses Cloudflare.</p>
 | 
			
		||||
                    <p>Gunakan dengan hati-hati.</p>
 | 
			
		||||
                </template>
 | 
			
		||||
 | 
			
		||||
                <template v-else-if="$i18n.locale === 'ru-RU' ">
 | 
			
		||||
                    <p>Вы уверены, что хотите <strong>отключить авторизацию</strong>?</p>
 | 
			
		||||
                    <p>Это подходит для <strong>тех, у кого стоит другая авторизация</strong> перед открытием Uptime Kuma, например Cloudflare Access.</p>
 | 
			
		||||
                    <p>Пожалуйста, используйте с осторожностью.</p>
 | 
			
		||||
                </template>
 | 
			
		||||
 | 
			
		||||
                <template v-else-if="$i18n.locale === 'fa' ">
 | 
			
		||||
                    <p>آیا مطمئن هستید که میخواهید <strong>احراز هویت را غیر فعال کنید</strong>?</p>
 | 
			
		||||
                    <p>این ویژگی برای کسانی است که <strong> لایه امنیتی شخص ثالث دیگر بر روی این آدرس فعال کردهاند</strong>، مانند Cloudflare Access.</p>
 | 
			
		||||
                    <p>لطفا از این امکان با دقت استفاده کنید.</p>
 | 
			
		||||
                </template>
 | 
			
		||||
 | 
			
		||||
                <template v-else-if="$i18n.locale === 'bg-BG' ">
 | 
			
		||||
                    <p>Сигурни ли сте, че желаете да <strong>изключите удостоверяването</strong>?</p>
 | 
			
		||||
                    <p>Използва се в случаите, когато <strong>има настроен алтернативен метод за удостоверяване</strong> преди Uptime Kuma, например Cloudflare Access.</p>
 | 
			
		||||
                    <p>Моля, използвайте с повишено внимание.</p>
 | 
			
		||||
                </template>
 | 
			
		||||
 | 
			
		||||
                <template v-else-if="$i18n.locale === 'hu' ">
 | 
			
		||||
                    <p>Biztos benne, hogy <strong>kikapcsolja a hitelesítést</strong>?</p>
 | 
			
		||||
                    <p>Akkor érdemes, ha <strong>van 3rd-party hitelesítés</strong> az Uptime Kuma-t megelőzően mint a Cloudflare Access.</p>
 | 
			
		||||
                    <p>Használja megfontoltan!</p>
 | 
			
		||||
                </template>
 | 
			
		||||
 | 
			
		||||
                <template v-else-if="$i18n.locale === 'nb-NO' ">
 | 
			
		||||
                    <p>Er du sikker på at du vil <strong>deaktiver autentisering</strong>?</p>
 | 
			
		||||
                    <p>Dette er for <strong>de som har tredjepartsautorisering</strong> foran Uptime Kuma, for eksempel Cloudflare Access.</p>
 | 
			
		||||
                    <p>Vennligst vær forsiktig.</p>
 | 
			
		||||
                </template>
 | 
			
		||||
 | 
			
		||||
                <!-- English (en) -->
 | 
			
		||||
                <template v-else>
 | 
			
		||||
                    <p>Are you sure want to <strong>disable auth</strong>?</p>
 | 
			
		||||
                    <p>It is for <strong>someone who have 3rd-party auth</strong> in front of Uptime Kuma such as Cloudflare Access.</p>
 | 
			
		||||
                    <p>Please use it carefully.</p>
 | 
			
		||||
                </template>
 | 
			
		||||
            </Confirm>
 | 
			
		||||
 | 
			
		||||
            <Confirm ref="confirmClearStatistics" btn-style="btn-danger" :yes-text="$t('Yes')" :no-text="$t('No')" @yes="clearStatistics">
 | 
			
		||||
                {{ $t("confirmClearStatisticsMsg") }}
 | 
			
		||||
            </Confirm>
 | 
			
		||||
            <Confirm ref="confirmImport" btn-style="btn-danger" :yes-text="$t('Yes')" :no-text="$t('No')" @yes="importBackup">
 | 
			
		||||
                {{ $t("confirmImportMsg") }}
 | 
			
		||||
            </Confirm>
 | 
			
		||||
        </div>
 | 
			
		||||
    </transition>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import HiddenInput from "../components/HiddenInput.vue";
 | 
			
		||||
import Confirm from "../components/Confirm.vue";
 | 
			
		||||
import dayjs from "dayjs";
 | 
			
		||||
import utc from "dayjs/plugin/utc";
 | 
			
		||||
import timezone from "dayjs/plugin/timezone";
 | 
			
		||||
import NotificationDialog from "../components/NotificationDialog.vue";
 | 
			
		||||
import TwoFADialog from "../components/TwoFADialog.vue";
 | 
			
		||||
import jwt_decode from "jwt-decode";
 | 
			
		||||
dayjs.extend(utc);
 | 
			
		||||
dayjs.extend(timezone);
 | 
			
		||||
import { markRaw } from "vue";
 | 
			
		||||
 | 
			
		||||
import { timezoneList, setPageLocale } from "../util-frontend";
 | 
			
		||||
import { useToast } from "vue-toastification";
 | 
			
		||||
import { debug } from "../util.ts";
 | 
			
		||||
 | 
			
		||||
const toast = useToast();
 | 
			
		||||
import Appearance from "../components/settings/Appearance.vue";
 | 
			
		||||
import General from "../components/settings/General.vue";
 | 
			
		||||
import Notifications from "../components/settings/Notifications.vue";
 | 
			
		||||
import MonitorHistory from "../components/settings/MonitorHistory.vue";
 | 
			
		||||
import Security from "../components/settings/Security.vue";
 | 
			
		||||
import Backup from "../components/settings/Backup.vue";
 | 
			
		||||
import About from "../components/settings/About.vue";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
    components: {
 | 
			
		||||
        NotificationDialog,
 | 
			
		||||
        TwoFADialog,
 | 
			
		||||
        Confirm,
 | 
			
		||||
        HiddenInput,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    data() {
 | 
			
		||||
        return {
 | 
			
		||||
            timezoneList: timezoneList(),
 | 
			
		||||
            guessTimezone: dayjs.tz.guess(),
 | 
			
		||||
            show: true,
 | 
			
		||||
            invalidPassword: false,
 | 
			
		||||
            password: {
 | 
			
		||||
                currentPassword: "",
 | 
			
		||||
                newPassword: "",
 | 
			
		||||
                repeatNewPassword: "",
 | 
			
		||||
            },
 | 
			
		||||
            settings: {
 | 
			
		||||
 | 
			
		||||
            show: true,
 | 
			
		||||
 | 
			
		||||
            settings: {},
 | 
			
		||||
            settingsLoaded: false,
 | 
			
		||||
 | 
			
		||||
            subMenus: {
 | 
			
		||||
                general: {
 | 
			
		||||
                    title: this.$t("General"),
 | 
			
		||||
                    component: markRaw(General),
 | 
			
		||||
                },
 | 
			
		||||
                appearance: {
 | 
			
		||||
                    title: this.$t("Appearance"),
 | 
			
		||||
                    component: markRaw(Appearance),
 | 
			
		||||
                },
 | 
			
		||||
                notifications: {
 | 
			
		||||
                    title: this.$t("Notifications"),
 | 
			
		||||
                    component: markRaw(Notifications),
 | 
			
		||||
                },
 | 
			
		||||
                monitorHistory: {
 | 
			
		||||
                    title: this.$t("Monitor History"),
 | 
			
		||||
                    component: markRaw(MonitorHistory),
 | 
			
		||||
                },
 | 
			
		||||
                security: {
 | 
			
		||||
                    title: this.$t("Security"),
 | 
			
		||||
                    component: markRaw(Security),
 | 
			
		||||
                },
 | 
			
		||||
                backup: {
 | 
			
		||||
                    title: this.$t("Backup"),
 | 
			
		||||
                    component: markRaw(Backup),
 | 
			
		||||
                },
 | 
			
		||||
                about: {
 | 
			
		||||
                    title: this.$t("About"),
 | 
			
		||||
                    component: markRaw(About),
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            loaded: false,
 | 
			
		||||
            importAlert: null,
 | 
			
		||||
            importHandle: "skip",
 | 
			
		||||
            processing: false,
 | 
			
		||||
            databaseSize: 0,
 | 
			
		||||
            currentSubMenu: "general",
 | 
			
		||||
        };
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    computed: {
 | 
			
		||||
        databaseSizeDisplay() {
 | 
			
		||||
            return Math.round(this.databaseSize / 1024 / 1024 * 10) / 10 + " MB";
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    watch: {
 | 
			
		||||
        "password.repeatNewPassword"() {
 | 
			
		||||
            this.invalidPassword = false;
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        "$i18n.locale"() {
 | 
			
		||||
            localStorage.locale = this.$i18n.locale;
 | 
			
		||||
            setPageLocale();
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    mounted() {
 | 
			
		||||
        this.loadUsername();
 | 
			
		||||
        this.loadSettings();
 | 
			
		||||
        this.loadDatabaseSize();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    methods: {
 | 
			
		||||
 | 
			
		||||
        saveGeneral() {
 | 
			
		||||
            localStorage.timezone = this.$root.userTimezone;
 | 
			
		||||
            this.saveSettings();
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        savePassword() {
 | 
			
		||||
            if (this.password.newPassword !== this.password.repeatNewPassword) {
 | 
			
		||||
                this.invalidPassword = true;
 | 
			
		||||
            } else {
 | 
			
		||||
                this.$root.getSocket().emit("changePassword", this.password, (res) => {
 | 
			
		||||
                    this.$root.toastRes(res);
 | 
			
		||||
                    if (res.ok) {
 | 
			
		||||
                        this.password.currentPassword = "";
 | 
			
		||||
                        this.password.newPassword = "";
 | 
			
		||||
                        this.password.repeatNewPassword = "";
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        loadUsername() {
 | 
			
		||||
            const jwtPayload = this.$root.getJWTPayload();
 | 
			
		||||
 | 
			
		||||
            if (jwtPayload) {
 | 
			
		||||
                this.username = jwtPayload.username;
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        loadSettings() {
 | 
			
		||||
            this.$root.getSocket().emit("getSettings", (res) => {
 | 
			
		||||
                this.settings = res.data;
 | 
			
		||||
@@ -538,7 +107,7 @@ export default {
 | 
			
		||||
                    this.settings.keepDataPeriodDays = 180;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                this.loaded = true;
 | 
			
		||||
                this.settingsLoaded = true;
 | 
			
		||||
            });
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
@@ -548,116 +117,6 @@ export default {
 | 
			
		||||
                this.loadSettings();
 | 
			
		||||
            });
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        confirmDisableAuth() {
 | 
			
		||||
            this.$refs.confirmDisableAuth.show();
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        confirmClearStatistics() {
 | 
			
		||||
            this.$refs.confirmClearStatistics.show();
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        confirmImport() {
 | 
			
		||||
            this.$refs.confirmImport.show();
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        disableAuth() {
 | 
			
		||||
            this.settings.disableAuth = true;
 | 
			
		||||
            this.saveSettings();
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        enableAuth() {
 | 
			
		||||
            this.settings.disableAuth = false;
 | 
			
		||||
            this.saveSettings();
 | 
			
		||||
            this.$root.storage().removeItem("token");
 | 
			
		||||
            location.reload();
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        downloadBackup() {
 | 
			
		||||
            let time = dayjs().format("YYYY_MM_DD-hh_mm_ss");
 | 
			
		||||
            let fileName = `Uptime_Kuma_Backup_${time}.json`;
 | 
			
		||||
            let monitorList = Object.values(this.$root.monitorList);
 | 
			
		||||
            let exportData = {
 | 
			
		||||
                version: this.$root.info.version,
 | 
			
		||||
                notificationList: this.$root.notificationList,
 | 
			
		||||
                monitorList: monitorList,
 | 
			
		||||
            };
 | 
			
		||||
            exportData = JSON.stringify(exportData, null, 4);
 | 
			
		||||
            let downloadItem = document.createElement("a");
 | 
			
		||||
            downloadItem.setAttribute("href", "data:application/json;charset=utf-8," + encodeURIComponent(exportData));
 | 
			
		||||
            downloadItem.setAttribute("download", fileName);
 | 
			
		||||
            downloadItem.click();
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        importBackup() {
 | 
			
		||||
            this.processing = true;
 | 
			
		||||
            let uploadItem = document.getElementById("importBackup").files;
 | 
			
		||||
 | 
			
		||||
            if (uploadItem.length <= 0) {
 | 
			
		||||
                this.processing = false;
 | 
			
		||||
                return this.importAlert = this.$t("alertNoFile");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (uploadItem.item(0).type !== "application/json") {
 | 
			
		||||
                this.processing = false;
 | 
			
		||||
                return this.importAlert = this.$t("alertWrongFileType");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            let fileReader = new FileReader();
 | 
			
		||||
            fileReader.readAsText(uploadItem.item(0));
 | 
			
		||||
 | 
			
		||||
            fileReader.onload = item => {
 | 
			
		||||
                this.$root.uploadBackup(item.target.result, this.importHandle, (res) => {
 | 
			
		||||
                    this.processing = false;
 | 
			
		||||
 | 
			
		||||
                    if (res.ok) {
 | 
			
		||||
                        toast.success(res.msg);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        toast.error(res.msg);
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
            };
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        clearStatistics() {
 | 
			
		||||
            this.$root.clearStatistics((res) => {
 | 
			
		||||
                if (res.ok) {
 | 
			
		||||
                    this.$router.go();
 | 
			
		||||
                } else {
 | 
			
		||||
                    toast.error(res.msg);
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        autoGetPrimaryBaseURL() {
 | 
			
		||||
            this.settings.primaryBaseURL = location.protocol + "//" + location.host;
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        shrinkDatabase() {
 | 
			
		||||
            this.$root.getSocket().emit("shrinkDatabase", (res) => {
 | 
			
		||||
                if (res.ok) {
 | 
			
		||||
                    this.loadDatabaseSize();
 | 
			
		||||
                    toast.success("Done");
 | 
			
		||||
                } else {
 | 
			
		||||
                    debug(res);
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        loadDatabaseSize() {
 | 
			
		||||
            debug("load database size");
 | 
			
		||||
            this.$root.getSocket().emit("getDatabaseSize", (res) => {
 | 
			
		||||
 | 
			
		||||
                if (res.ok) {
 | 
			
		||||
                    this.databaseSize = res.size;
 | 
			
		||||
                    debug("database size: " + res.size);
 | 
			
		||||
                } else {
 | 
			
		||||
                    debug(res);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -667,37 +126,8 @@ export default {
 | 
			
		||||
 | 
			
		||||
.shadow-box {
 | 
			
		||||
    padding: 20px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.btn-check:active + .btn-outline-primary,
 | 
			
		||||
.btn-check:checked + .btn-outline-primary,
 | 
			
		||||
.btn-check:hover + .btn-outline-primary {
 | 
			
		||||
    color: #fff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dark {
 | 
			
		||||
    .list-group-item {
 | 
			
		||||
        background-color: $dark-bg2;
 | 
			
		||||
        color: $dark-font-color;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .btn-check:active + .btn-outline-primary,
 | 
			
		||||
    .btn-check:checked + .btn-outline-primary,
 | 
			
		||||
    .btn-check:hover + .btn-outline-primary {
 | 
			
		||||
        color: #000;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #importBackup {
 | 
			
		||||
        &::file-selector-button {
 | 
			
		||||
            color: $primary;
 | 
			
		||||
            background-color: $dark-bg;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &:hover:not(:disabled):not([readonly])::file-selector-button {
 | 
			
		||||
            color: $dark-font-color2;
 | 
			
		||||
            background-color: $primary;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    min-height: calc(100vh - 155px);
 | 
			
		||||
    max-height: calc(100vh - 30px);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
footer {
 | 
			
		||||
@@ -707,4 +137,55 @@ footer {
 | 
			
		||||
    padding-bottom: 30px;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.settings-menu {
 | 
			
		||||
    flex: 0 0 auto;
 | 
			
		||||
    width: 300px;
 | 
			
		||||
 | 
			
		||||
    .menu-item {
 | 
			
		||||
        border-radius: 10px;
 | 
			
		||||
        margin: 0.5em;
 | 
			
		||||
        padding: 0.7em 1em;
 | 
			
		||||
        cursor: pointer;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .menu-item:hover {
 | 
			
		||||
        background: $highlight-white;
 | 
			
		||||
 | 
			
		||||
        .dark & {
 | 
			
		||||
            background: $dark-header-bg;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .menu-item.active {
 | 
			
		||||
        background: $highlight-white;
 | 
			
		||||
        border-left: 4px solid $primary;
 | 
			
		||||
        border-top-left-radius: 0;
 | 
			
		||||
        border-bottom-left-radius: 0;
 | 
			
		||||
 | 
			
		||||
        .dark & {
 | 
			
		||||
            background: $dark-header-bg;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.settings-content {
 | 
			
		||||
    flex: 0 0 auto;
 | 
			
		||||
    width: calc(100% - 300px);
 | 
			
		||||
 | 
			
		||||
    .settings-content-header {
 | 
			
		||||
        width: calc(100% + 20px);
 | 
			
		||||
        border-bottom: 1px solid #dee2e6;
 | 
			
		||||
        border-radius: 0 10px 0 0;
 | 
			
		||||
        margin-top: -20px;
 | 
			
		||||
        margin-right: -20px;
 | 
			
		||||
        padding: 12.5px 1em;
 | 
			
		||||
        font-size: 26px;
 | 
			
		||||
 | 
			
		||||
        .dark & {
 | 
			
		||||
            background: $dark-header-bg;
 | 
			
		||||
            border-bottom: 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user