mirror of
				https://github.com/louislam/uptime-kuma.git
				synced 2025-10-31 19:39:20 +08:00 
			
		
		
		
	Merge branch 'master' into clean-mobile-table
This commit is contained in:
		| @@ -16,6 +16,7 @@ module.exports = { | ||||
|         requireConfigFile: false, | ||||
|     }, | ||||
|     rules: { | ||||
|         "camelcase": "warn", | ||||
|         // override/add rules settings here, such as: | ||||
|         // 'vue/no-unused-vars': 'error' | ||||
|         "no-unused-vars": "warn", | ||||
|   | ||||
| @@ -6,7 +6,38 @@ The project was created with vite.js (vue3). Then I created a sub-directory call | ||||
|  | ||||
| The frontend code build into "dist" directory. The server uses "dist" as root. This is how production is working. | ||||
|  | ||||
| Your IDE should follow the config in ".editorconfig". The most special thing is I set it to 4 spaces indentation. I know 2 spaces indentation became a kind of standard nowadays for js, but my eyes is not so comfortable for this. In my opinion, there is no callback-hell nowadays, it is good to go back 4 spaces world again. | ||||
| # Can I create a pull request for Uptime Kuma? | ||||
|  | ||||
| Generally, if the pull request is working fine and it do not affect any existing logic, workflow and perfomance, I will merge to the master branch once it is tested. | ||||
|  | ||||
| If you are not sure, feel free to create an empty pull request draft first. | ||||
|  | ||||
| ## Pull Request Examples | ||||
|  | ||||
| ### ✅ High - Medium Priority | ||||
|  | ||||
| - Add a new notification | ||||
| - Add a chart | ||||
| - Fix a bug | ||||
|  | ||||
| ### *️⃣ Requires one more reviewer  | ||||
|  | ||||
| I do not have such knowledge to test it | ||||
|  | ||||
| - Add k8s supports  | ||||
|  | ||||
| ### *️⃣ Low Priority  | ||||
|  | ||||
| It chnaged my current workflow and require further studies. | ||||
|  | ||||
| - Change my release approach | ||||
|  | ||||
| ### ❌ Won't Merge | ||||
|  | ||||
| - Duplicated pull request | ||||
| - Buggy | ||||
| - Existing logic is completely modified or deleted | ||||
| - A function that is completely out of scope | ||||
|  | ||||
| # Project Styles | ||||
|  | ||||
| @@ -19,16 +50,27 @@ For example, recently, because I am not a python expert, I spent a 2 hours to re | ||||
| - All settings in frontend. | ||||
| - Easy to use | ||||
|  | ||||
| # Coding Styles | ||||
|  | ||||
| - Follow .editorconfig | ||||
| - Follow eslint | ||||
|  | ||||
| ## Name convention | ||||
|  | ||||
| - Javascript/Typescript: camelCaseType | ||||
| - SQLite: underscore_type | ||||
| - CSS/SCSS: dash-type | ||||
|  | ||||
| # Tools | ||||
| - Node.js >= 14 | ||||
| - Git | ||||
| - IDE that supports .editorconfig  (I am using Intellji Idea) | ||||
| - IDE that supports .editorconfig and eslint (I am using Intellji Idea) | ||||
| - A SQLite tool (I am using SQLite Expert Personal) | ||||
|  | ||||
| # Prepare the dev | ||||
| # Install dependencies  | ||||
|  | ||||
| ```bash | ||||
| npm install | ||||
| npm install --dev | ||||
| ``` | ||||
|  | ||||
| # Backend Dev | ||||
| @@ -39,7 +81,6 @@ npm run start-server | ||||
| # Or  | ||||
|  | ||||
| node server/server.js | ||||
|  | ||||
| ``` | ||||
|  | ||||
| It binds to 0.0.0.0:3001 by default. | ||||
| @@ -92,7 +133,8 @@ The data and socket logic in "src/mixins/socket.js" | ||||
|  | ||||
| # Database Migration | ||||
|  | ||||
| TODO | ||||
| 1. create `patch{num}.sql` in `./db/` | ||||
| 1. update `latestVersion` in `./server/database.js` | ||||
|  | ||||
| # Unit Test | ||||
|  | ||||
|   | ||||
							
								
								
									
										8140
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										8140
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -10,6 +10,9 @@ | ||||
|         "node": "14.*" | ||||
|     }, | ||||
|     "scripts": { | ||||
|         "lint:js": "eslint --ext \".js,.vue\" --ignore-path .gitignore .", | ||||
|         "lint:style": "stylelint \"**/*.{vue,css}\" --ignore-path .gitignore", | ||||
|         "lint": "npm run lint:js && npm run lint:style", | ||||
|         "dev": "vite --host", | ||||
|         "start": "npm run start-server", | ||||
|         "start-server": "node server/server.js", | ||||
| @@ -64,6 +67,7 @@ | ||||
|         "vue": "^3.2.2", | ||||
|         "vue-chart-3": "^0.5.7", | ||||
|         "vue-confirm-dialog": "^1.0.2", | ||||
|         "vue-i18n": "^9.1.7", | ||||
|         "vue-multiselect": "^3.0.0-alpha.2", | ||||
|         "vue-router": "^4.0.11", | ||||
|         "vue-toastification": "^2.0.0-rc.1" | ||||
|   | ||||
| @@ -1,8 +1,6 @@ | ||||
| const fs = require("fs"); | ||||
| const { sleep, debug, isDev } = require("../src/util"); | ||||
| const { R } = require("redbean-node"); | ||||
| const { setSetting, setting } = require("./util-server"); | ||||
| const knex = require("knex"); | ||||
|  | ||||
| class Database { | ||||
|  | ||||
|   | ||||
| @@ -4,7 +4,7 @@ | ||||
|             <div class="modal-content"> | ||||
|                 <div class="modal-header"> | ||||
|                     <h5 id="exampleModalLabel" class="modal-title"> | ||||
|                         Confirm | ||||
|                         {{ $t("Confirm") }} | ||||
|                     </h5> | ||||
|                     <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" /> | ||||
|                 </div> | ||||
| @@ -35,7 +35,7 @@ export default { | ||||
|         }, | ||||
|         yesText: { | ||||
|             type: String, | ||||
|             default: "Yes", | ||||
|             default: "Yes",     // TODO: No idea what to translate this | ||||
|         }, | ||||
|         noText: { | ||||
|             type: String, | ||||
|   | ||||
| @@ -6,12 +6,12 @@ | ||||
|  | ||||
|                 <div class="form-floating"> | ||||
|                     <input id="floatingInput" v-model="username" type="text" class="form-control" placeholder="Username"> | ||||
|                     <label for="floatingInput">Username</label> | ||||
|                     <label for="floatingInput">{{ $t("Username") }}</label> | ||||
|                 </div> | ||||
|  | ||||
|                 <div class="form-floating mt-3"> | ||||
|                     <input id="floatingPassword" v-model="password" type="password" class="form-control" placeholder="Password"> | ||||
|                     <label for="floatingPassword">Password</label> | ||||
|                     <label for="floatingPassword">{{ $t("Password") }}</label> | ||||
|                 </div> | ||||
|  | ||||
|                 <div class="form-check mb-3 mt-3 d-flex justify-content-center pe-4"> | ||||
| @@ -19,12 +19,12 @@ | ||||
|                         <input id="remember" v-model="$root.remember" type="checkbox" value="remember-me" class="form-check-input"> | ||||
|  | ||||
|                         <label class="form-check-label" for="remember"> | ||||
|                             Remember me | ||||
|                             {{ $t("Remember me") }} | ||||
|                         </label> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <button class="w-100 btn btn-primary" type="submit" :disabled="processing"> | ||||
|                     Login | ||||
|                     {{ $t("Login") }} | ||||
|                 </button> | ||||
|  | ||||
|                 <div v-if="res && !res.ok" class="alert alert-danger mt-3" role="alert"> | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| <template> | ||||
|     <div class="shadow-box list mb-4"> | ||||
|         <div v-if="Object.keys($root.monitorList).length === 0" class="text-center mt-3"> | ||||
|             No Monitors, please <router-link to="/add">add one</router-link>. | ||||
|             {{ $t("No Monitors, please") }} <router-link to="/add">{{ $t("add one") }}</router-link> | ||||
|         </div> | ||||
|  | ||||
|         <router-link v-for="(item, index) in sortedMonitorList" :key="index" :to="monitorURL(item.id)" class="item" :class="{ 'disabled': ! item.active }"> | ||||
|   | ||||
| @@ -5,17 +5,17 @@ | ||||
|                 <div class="modal-content"> | ||||
|                     <div class="modal-header"> | ||||
|                         <h5 id="exampleModalLabel" class="modal-title"> | ||||
|                             Setup Notification | ||||
|                             {{ $t("Setup Notification") }} | ||||
|                         </h5> | ||||
|                         <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" /> | ||||
|                     </div> | ||||
|                     <div class="modal-body"> | ||||
|                         <div class="mb-3"> | ||||
|                             <label for="type" class="form-label">Notification Type</label> | ||||
|                             <label for="type" class="form-label">{{ $t("Notification Type") }}</label> | ||||
|                             <select id="type" v-model="notification.type" class="form-select"> | ||||
|                                 <option value="telegram">Telegram</option> | ||||
|                                 <option value="webhook">Webhook</option> | ||||
|                                 <option value="smtp">Email (SMTP)</option> | ||||
|                                 <option value="smtp">{{ $t("Email") }} (SMTP)</option> | ||||
|                                 <option value="discord">Discord</option> | ||||
|                                 <option value="signal">Signal</option> | ||||
|                                 <option value="gotify">Gotify</option> | ||||
| @@ -31,7 +31,7 @@ | ||||
|                         </div> | ||||
|  | ||||
|                         <div class="mb-3"> | ||||
|                             <label for="name" class="form-label">Friendly Name</label> | ||||
|                             <label for="name" class="form-label">{{ $t("Friendly Name") }}</label> | ||||
|                             <input id="name" v-model="notification.name" type="text" class="form-control" required> | ||||
|                         </div> | ||||
|  | ||||
| @@ -407,13 +407,13 @@ | ||||
|                     </div> | ||||
|                     <div class="modal-footer"> | ||||
|                         <button v-if="id" type="button" class="btn btn-danger" :disabled="processing" @click="deleteConfirm"> | ||||
|                             Delete | ||||
|                             {{ $t("Delete") }} | ||||
|                         </button> | ||||
|                         <button type="button" class="btn btn-warning" :disabled="processing" @click="test"> | ||||
|                             Test | ||||
|                             {{ $t("Test") }} | ||||
|                         </button> | ||||
|                         <button type="submit" class="btn btn-primary" :disabled="processing"> | ||||
|                             Save | ||||
|                             {{ $t("Save") }} | ||||
|                         </button> | ||||
|                     </div> | ||||
|                 </div> | ||||
|   | ||||
| @@ -27,18 +27,18 @@ export default { | ||||
|  | ||||
|         text() { | ||||
|             if (this.status === 0) { | ||||
|                 return "Down" | ||||
|                 return this.$t("Down"); | ||||
|             } | ||||
|  | ||||
|             if (this.status === 1) { | ||||
|                 return "Up" | ||||
|                 return this.$t("Up"); | ||||
|             } | ||||
|  | ||||
|             if (this.status === 2) { | ||||
|                 return "Pending" | ||||
|                 return this.$t("Pending"); | ||||
|             } | ||||
|  | ||||
|             return "Unknown" | ||||
|             return this.$t("Unknown"); | ||||
|         }, | ||||
|     }, | ||||
| } | ||||
|   | ||||
							
								
								
									
										12
									
								
								src/languages/en.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/languages/en.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| export default { | ||||
|     languageName: "English", | ||||
|     checkEverySecond: "Check every {0} seconds.", | ||||
|     "Avg.": "Avg. ", | ||||
|     retriesDescription: "Maximum retries before the service is marked as down and a notification is sent", | ||||
|     ignoreTLSError: "Ignore TLS/SSL error for HTTPS websites", | ||||
|     upsideDownModeDescription: "Flip the status upside down. If the service is reachable, it is DOWN.", | ||||
|     maxRedirectDescription: "Maximum number of redirects to follow. Set to 0 to disable redirects.", | ||||
|     acceptedStatusCodesDescription: "Select status codes which are considered as a successful response.", | ||||
|     passwordNotMatchMsg: "The repeat password does not match.", | ||||
|     notificationDescription: "Please assign a notification to monitor(s) to get it to work.", | ||||
| } | ||||
							
								
								
									
										97
									
								
								src/languages/zh-HK.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								src/languages/zh-HK.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| export default { | ||||
|     languageName: "繁體中文 (香港)", | ||||
|     Settings: "設定", | ||||
|     Dashboard: "錶板", | ||||
|     "New Update": "有更新", | ||||
|     Language: "語言", | ||||
|     Appearance: "外觀", | ||||
|     Theme: "主題", | ||||
|     General: "一般", | ||||
|     Version: "版本", | ||||
|     "Check Update On GitHub": "到 Github 查看更新", | ||||
|     List: "列表", | ||||
|     Add: "新增", | ||||
|     "Add New Monitor": "新增監測器", | ||||
|     "Quick Stats": "綜合數據", | ||||
|     Up: "上線", | ||||
|     Down: "離線", | ||||
|     Pending: "待定", | ||||
|     Unknown: "不明", | ||||
|     Pause: "暫停", | ||||
|     Name: "名稱", | ||||
|     Status: "狀態", | ||||
|     DateTime: "日期時間", | ||||
|     Message: "內容", | ||||
|     "No important events": "沒有重要事件", | ||||
|     Resume: "恢復", | ||||
|     Edit: "編輯", | ||||
|     Delete: "刪除", | ||||
|     Current: "目前", | ||||
|     Uptime: "上線率", | ||||
|     "Cert Exp.": "証書期限", | ||||
|     days: "日", | ||||
|     day: "日", | ||||
|     "-day": "日", | ||||
|     hour: "小時", | ||||
|     "-hour": "小時", | ||||
|     checkEverySecond: "每 {0} 秒檢查一次", | ||||
|     "Avg.": "平均", | ||||
|     Response: "反應時間", | ||||
|     Ping: "反應時間", | ||||
|     "Monitor Type": "監測器類型", | ||||
|     Keyword: "關鍵字", | ||||
|     "Friendly Name": "名稱", | ||||
|     URL: "網址 URL", | ||||
|     Hostname: "Hostname", | ||||
|     Port: "Port", | ||||
|     "Heartbeat Interval": "檢查間距", | ||||
|     Retries: "重試數次確定為離線", | ||||
|     retriesDescription: "重試多少次後才判定為離線及傳送通知。如數值為 0 會即判定為離線及傳送通知。", | ||||
|     Advanced: "進階", | ||||
|     ignoreTLSError: "忽略 TLS/SSL 錯誤", | ||||
|     "Upside Down Mode": "反轉模式", | ||||
|     upsideDownModeDescription: "反轉狀態,如網址是可正常瀏覽,會被判定為 '離線/DOWN'", | ||||
|     "Max. Redirects": "跟隨重新導向 (Redirect) 的次數", | ||||
|     maxRedirectDescription: "設為 0 即不跟蹤", | ||||
|     "Accepted Status Codes": "接受為上線的 HTTP 狀態碼", | ||||
|     acceptedStatusCodesDescription: "可多選", | ||||
|     Save: "儲存", | ||||
|     Notifications: "通知", | ||||
|     "Not available, please setup.": "無法使用,需要設定", | ||||
|     "Setup Notification": "設定通知", | ||||
|     Light: "明亮", | ||||
|     Dark: "暗黑", | ||||
|     Auto: "自動", | ||||
|     "Theme - Heartbeat Bar": "監測器列表 狀態條外觀", | ||||
|     Normal: "一般", | ||||
|     Bottom: "下方", | ||||
|     None: "沒有", | ||||
|     Timezone: "時區", | ||||
|     "Search Engine Visibility": "是否允許搜尋器索引", | ||||
|     "Allow indexing": "允許索引", | ||||
|     "Discourage search engines from indexing site": "不建議搜尋器索引", | ||||
|     "Change Password": "變更密碼", | ||||
|     "Current Password": "目前密碼", | ||||
|     "New Password": "新密碼", | ||||
|     "Repeat New Password": "確認新密碼", | ||||
|     passwordNotMatchMsg: "密碼不一致", | ||||
|     "Update Password": "更新密碼", | ||||
|     "Disable Auth": "取消登入認証", | ||||
|     "Enable Auth": "開啟登入認証", | ||||
|     Logout: "登出", | ||||
|     notificationDescription: "新增後,你需要在監測器裡啟用。", | ||||
|     Leave: "離開", | ||||
|     "I understand, please disable": "我明白,請取消登入認証", | ||||
|     Confirm: "確認", | ||||
|     Yes: "是", | ||||
|     No: "否", | ||||
|     Username: "帳號", | ||||
|     Password: "密碼", | ||||
|     "Remember me": "記住我", | ||||
|     Login: "登入", | ||||
|     "No Monitors, please": "沒有監測器,請", | ||||
|     "add one": "新增", | ||||
|     "Notification Type": "通知類型", | ||||
|     "Email": "電郵", | ||||
|     "Test": "測試", | ||||
| } | ||||
| @@ -14,18 +14,18 @@ | ||||
|             </router-link> | ||||
|  | ||||
|             <a v-if="hasNewVersion" target="_blank" href="https://github.com/louislam/uptime-kuma/releases" class="btn btn-info me-3"> | ||||
|                 <font-awesome-icon icon="arrow-alt-circle-up" /> New Update | ||||
|                 <font-awesome-icon icon="arrow-alt-circle-up" /> {{ $t("New Update") }} | ||||
|             </a> | ||||
|  | ||||
|             <ul class="nav nav-pills"> | ||||
|                 <li class="nav-item"> | ||||
|                     <router-link to="/dashboard" class="nav-link"> | ||||
|                         <font-awesome-icon icon="tachometer-alt" /> Dashboard | ||||
|                         <font-awesome-icon icon="tachometer-alt" /> {{ $t("Dashboard") }} | ||||
|                     </router-link> | ||||
|                 </li> | ||||
|                 <li class="nav-item"> | ||||
|                     <router-link to="/settings" class="nav-link"> | ||||
|                         <font-awesome-icon icon="cog" /> Settings | ||||
|                         <font-awesome-icon icon="cog" /> {{ $t("Settings") }} | ||||
|                     </router-link> | ||||
|                 </li> | ||||
|             </ul> | ||||
| @@ -48,8 +48,8 @@ | ||||
|         <footer> | ||||
|             <div class="container-fluid"> | ||||
|                 Uptime Kuma - | ||||
|                 Version: {{ $root.info.version }} - | ||||
|                 <a href="https://github.com/louislam/uptime-kuma/releases" target="_blank" rel="noopener">Check Update On GitHub</a> | ||||
|                 {{ $t("Version") }}: {{ $root.info.version }} - | ||||
|                 <a href="https://github.com/louislam/uptime-kuma/releases" target="_blank" rel="noopener">{{ $t("Check Update On GitHub") }}</a> | ||||
|             </div> | ||||
|         </footer> | ||||
|  | ||||
| @@ -58,22 +58,22 @@ | ||||
|         <nav v-if="$root.isMobile" class="bottom-nav"> | ||||
|             <router-link to="/dashboard" class="nav-link"> | ||||
|                 <div><font-awesome-icon icon="tachometer-alt" /></div> | ||||
|                 Dashboard | ||||
|                 {{ $t("Dashboard") }} | ||||
|             </router-link> | ||||
|  | ||||
|             <router-link to="/list" class="nav-link"> | ||||
|                 <div><font-awesome-icon icon="list" /></div> | ||||
|                 List | ||||
|                 {{ $t("List") }} | ||||
|             </router-link> | ||||
|  | ||||
|             <router-link to="/add" class="nav-link"> | ||||
|                 <div><font-awesome-icon icon="plus" /></div> | ||||
|                 Add | ||||
|                 {{ $t("Add") }} | ||||
|             </router-link> | ||||
|  | ||||
|             <router-link to="/settings" class="nav-link"> | ||||
|                 <div><font-awesome-icon icon="cog" /></div> | ||||
|                 Settings | ||||
|                 {{ $t("Settings") }} | ||||
|             </router-link> | ||||
|         </nav> | ||||
|     </div> | ||||
|   | ||||
							
								
								
									
										20
									
								
								src/main.js
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								src/main.js
									
									
									
									
									
								
							| @@ -1,5 +1,6 @@ | ||||
| import "bootstrap"; | ||||
| import { createApp, h } from "vue"; | ||||
| import { createI18n } from "vue-i18n" | ||||
| import { createRouter, createWebHistory } from "vue-router"; | ||||
| import Toast from "vue-toastification"; | ||||
| import "vue-toastification/dist/index.css"; | ||||
| @@ -22,6 +23,9 @@ import List from "./pages/List.vue"; | ||||
|  | ||||
| import { appName } from "./util.ts"; | ||||
|  | ||||
| import en from "./languages/en"; | ||||
| import zhHK from "./languages/zh-HK"; | ||||
|  | ||||
| const routes = [ | ||||
|     { | ||||
|         path: "/", | ||||
| @@ -83,6 +87,19 @@ const router = createRouter({ | ||||
|     routes, | ||||
| }) | ||||
|  | ||||
| const languageList = { | ||||
|     en, | ||||
|     "zh-HK": zhHK, | ||||
| }; | ||||
|  | ||||
| const i18n = createI18n({ | ||||
|     locale: localStorage.locale || "en", | ||||
|     fallbackLocale: "en", | ||||
|     silentFallbackWarn: true, | ||||
|     silentTranslationWarn: true, | ||||
|     messages: languageList | ||||
| }); | ||||
|  | ||||
| const app = createApp({ | ||||
|     mixins: [ | ||||
|         socket, | ||||
| @@ -98,7 +115,8 @@ const app = createApp({ | ||||
|     render: () => h(App), | ||||
| }) | ||||
|  | ||||
| app.use(router) | ||||
| app.use(router); | ||||
| app.use(i18n); | ||||
|  | ||||
| const options = { | ||||
|     position: "bottom-right", | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
|         <div class="row"> | ||||
|             <div v-if="! $root.isMobile" class="col-12 col-md-5 col-xl-4"> | ||||
|                 <div> | ||||
|                     <router-link to="/add" class="btn btn-primary mb-3"><font-awesome-icon icon="plus" /> Add New Monitor</router-link> | ||||
|                     <router-link to="/add" class="btn btn-primary mb-3"><font-awesome-icon icon="plus" /> {{ $t("Add New Monitor") }}</router-link> | ||||
|                 </div> | ||||
|                 <MonitorList /> | ||||
|             </div> | ||||
|   | ||||
| @@ -2,50 +2,38 @@ | ||||
|     <transition name="slide-fade" appear> | ||||
|         <div v-if="$route.name === 'DashboardHome'"> | ||||
|             <h1 class="mb-3"> | ||||
|                 Quick Stats | ||||
|                 {{ $t("Quick Stats") }} | ||||
|             </h1> | ||||
|  | ||||
|             <div class="shadow-box big-padding text-center"> | ||||
|                 <div class="row"> | ||||
|                     <div class="col"> | ||||
|                         <h3>Up</h3> | ||||
|                         <h3>{{ $t("Up") }}</h3> | ||||
|                         <span class="num">{{ stats.up }}</span> | ||||
|                     </div> | ||||
|                     <div class="col"> | ||||
|                         <h3>Down</h3> | ||||
|                         <h3>{{ $t("Down") }}</h3> | ||||
|                         <span class="num text-danger">{{ stats.down }}</span> | ||||
|                     </div> | ||||
|                     <div class="col"> | ||||
|                         <h3>Unknown</h3> | ||||
|                         <h3>{{ $t("Unknown") }}</h3> | ||||
|                         <span class="num text-secondary">{{ stats.unknown }}</span> | ||||
|                     </div> | ||||
|                     <div class="col"> | ||||
|                         <h3>Pause</h3> | ||||
|                         <h3>{{ $t("Pause") }}</h3> | ||||
|                         <span class="num text-secondary">{{ stats.pause }}</span> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div v-if="false" class="row"> | ||||
|                     <div class="col-3"> | ||||
|                         <h3>Uptime</h3> | ||||
|                         <p>(24-hour)</p> | ||||
|                         <span class="num" /> | ||||
|                     </div> | ||||
|                     <div class="col-3"> | ||||
|                         <h3>Uptime</h3> | ||||
|                         <p>(30-day)</p> | ||||
|                         <span class="num" /> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|  | ||||
|             <div class="shadow-box table-shadow-box" style="overflow-x: scroll"> | ||||
|                 <table class="table table-borderless table-hover"> | ||||
|                     <thead> | ||||
|                         <tr> | ||||
|                             <th>Name</th> | ||||
|                             <th>Status</th> | ||||
|                             <th>DateTime</th> | ||||
|                             <th>Message</th> | ||||
|                             <th>{{ $t("Name") }}</th> | ||||
|                             <th>{{ $t("Status") }}</th> | ||||
|                             <th>{{ $t("DateTime") }}</th> | ||||
|                             <th>{{ $t("Message") }}</th> | ||||
|                         </tr> | ||||
|                     </thead> | ||||
|                     <tbody> | ||||
| @@ -58,7 +46,7 @@ | ||||
|  | ||||
|                         <tr v-if="importantHeartBeatList.length === 0"> | ||||
|                             <td colspan="4"> | ||||
|                                 No important events | ||||
|                                 {{ $t("No important events") }} | ||||
|                             </td> | ||||
|                         </tr> | ||||
|                     </tbody> | ||||
|   | ||||
| @@ -14,16 +14,16 @@ | ||||
|  | ||||
|             <div class="functions"> | ||||
|                 <button v-if="monitor.active" class="btn btn-light" @click="pauseDialog"> | ||||
|                     <font-awesome-icon icon="pause" /> Pause | ||||
|                     <font-awesome-icon icon="pause" /> {{ $t("Pause") }} | ||||
|                 </button> | ||||
|                 <button v-if="! monitor.active" class="btn btn-primary" @click="resumeMonitor"> | ||||
|                     <font-awesome-icon icon="play" /> Resume | ||||
|                     <font-awesome-icon icon="play" /> {{ $t("Resume") }} | ||||
|                 </button> | ||||
|                 <router-link :to=" '/edit/' + monitor.id " class="btn btn-secondary"> | ||||
|                     <font-awesome-icon icon="edit" /> Edit | ||||
|                     <font-awesome-icon icon="edit" /> {{ $t("Edit") }} | ||||
|                 </router-link> | ||||
|                 <button class="btn btn-danger" @click="deleteDialog"> | ||||
|                     <font-awesome-icon icon="trash" /> Delete | ||||
|                     <font-awesome-icon icon="trash" /> {{ $t("Delete") }} | ||||
|                 </button> | ||||
|             </div> | ||||
|  | ||||
| @@ -31,7 +31,7 @@ | ||||
|                 <div class="row"> | ||||
|                     <div class="col-md-8"> | ||||
|                         <HeartbeatBar :monitor-id="monitor.id" /> | ||||
|                         <span class="word">Check every {{ monitor.interval }} seconds.</span> | ||||
|                         <span class="word">{{ $t("checkEverySecond", [ monitor.interval ]) }}</span> | ||||
|                     </div> | ||||
|                     <div class="col-md-4 text-center"> | ||||
|                         <span class="badge rounded-pill" :class=" 'bg-' + status.color " style="font-size: 30px">{{ status.text }}</span> | ||||
| @@ -43,7 +43,7 @@ | ||||
|                 <div class="row"> | ||||
|                     <div class="col"> | ||||
|                         <h4>{{ pingTitle }}</h4> | ||||
|                         <p>(Current)</p> | ||||
|                         <p>({{ $t("Current") }})</p> | ||||
|                         <span class="num"> | ||||
|                             <a href="#" @click.prevent="showPingChartBox = !showPingChartBox"> | ||||
|                                 <CountUp :value="ping" /> | ||||
| @@ -51,26 +51,26 @@ | ||||
|                         </span> | ||||
|                     </div> | ||||
|                     <div class="col"> | ||||
|                         <h4>Avg. {{ pingTitle }}</h4> | ||||
|                         <p>(24-hour)</p> | ||||
|                         <h4>{{ $t("Avg.") }}{{ pingTitle }}</h4> | ||||
|                         <p>(24{{ $t("-hour") }})</p> | ||||
|                         <span class="num"><CountUp :value="avgPing" /></span> | ||||
|                     </div> | ||||
|                     <div class="col"> | ||||
|                         <h4>Uptime</h4> | ||||
|                         <p>(24-hour)</p> | ||||
|                         <h4>{{ $t("Uptime") }}</h4> | ||||
|                         <p>(24{{ $t("-hour") }})</p> | ||||
|                         <span class="num"><Uptime :monitor="monitor" type="24" /></span> | ||||
|                     </div> | ||||
|                     <div class="col"> | ||||
|                         <h4>Uptime</h4> | ||||
|                         <p>(30-day)</p> | ||||
|                         <h4>{{ $t("Uptime") }}</h4> | ||||
|                         <p>(30{{ $t("-day") }})</p> | ||||
|                         <span class="num"><Uptime :monitor="monitor" type="720" /></span> | ||||
|                     </div> | ||||
|  | ||||
|                     <div v-if="certInfo" class="col"> | ||||
|                         <h4>Cert Exp.</h4> | ||||
|                         <h4>{{ $t("Cert Exp.") }}</h4> | ||||
|                         <p>(<Datetime :value="certInfo.validTo" date-only />)</p> | ||||
|                         <span class="num"> | ||||
|                             <a href="#" @click.prevent="toggleCertInfoBox = !toggleCertInfoBox">{{ certInfo.daysRemaining }} days</a> | ||||
|                             <a href="#" @click.prevent="toggleCertInfoBox = !toggleCertInfoBox">{{ certInfo.daysRemaining }} {{ $t("days") }}</a> | ||||
|                         </span> | ||||
|                     </div> | ||||
|                 </div> | ||||
| @@ -132,9 +132,9 @@ | ||||
|                 <table class="table table-borderless table-hover"> | ||||
|                     <thead> | ||||
|                         <tr> | ||||
|                             <th>Status</th> | ||||
|                             <th>DateTime</th> | ||||
|                             <th>Message</th> | ||||
|                             <th>{{ $t("Status") }}</th> | ||||
|                             <th>{{ $t("DateTime") }}</th> | ||||
|                             <th>{{ $t("Message") }}</th> | ||||
|                         </tr> | ||||
|                     </thead> | ||||
|                     <tbody> | ||||
| @@ -146,7 +146,7 @@ | ||||
|  | ||||
|                         <tr v-if="importantHeartBeatList.length === 0"> | ||||
|                             <td colspan="3"> | ||||
|                                 No important events | ||||
|                                 {{ $t("No important events") }} | ||||
|                             </td> | ||||
|                         </tr> | ||||
|                     </tbody> | ||||
| @@ -209,10 +209,9 @@ export default { | ||||
|  | ||||
|         pingTitle() { | ||||
|             if (this.monitor.type === "http") { | ||||
|                 return "Response" | ||||
|                 return this.$t("Response"); | ||||
|             } | ||||
|  | ||||
|             return "Ping" | ||||
|             return this.$t("Ping"); | ||||
|         }, | ||||
|  | ||||
|         monitor() { | ||||
|   | ||||
| @@ -6,10 +6,10 @@ | ||||
|                 <div class="shadow-box"> | ||||
|                     <div class="row"> | ||||
|                         <div class="col-md-6"> | ||||
|                             <h2 class="mb-2">General</h2> | ||||
|                             <h2 class="mb-2">{{ $t("General") }}</h2> | ||||
|  | ||||
|                             <div class="my-3"> | ||||
|                                 <label for="type" class="form-label">Monitor Type</label> | ||||
|                                 <label for="type" class="form-label">{{ $t("Monitor Type") }}</label> | ||||
|                                 <select id="type" v-model="monitor.type" class="form-select" aria-label="Default select example"> | ||||
|                                     <option value="http"> | ||||
|                                         HTTP(s) | ||||
| @@ -21,23 +21,23 @@ | ||||
|                                         Ping | ||||
|                                     </option> | ||||
|                                     <option value="keyword"> | ||||
|                                         HTTP(s) - Keyword | ||||
|                                         HTTP(s) - {{ $t("Keyword") }} | ||||
|                                     </option> | ||||
|                                 </select> | ||||
|                             </div> | ||||
|  | ||||
|                             <div class="my-3"> | ||||
|                                 <label for="name" class="form-label">Friendly Name</label> | ||||
|                                 <label for="name" class="form-label">{{ $t("Friendly Name") }}</label> | ||||
|                                 <input id="name" v-model="monitor.name" type="text" class="form-control" required> | ||||
|                             </div> | ||||
|  | ||||
|                             <div v-if="monitor.type === 'http' || monitor.type === 'keyword' " class="my-3"> | ||||
|                                 <label for="url" class="form-label">URL</label> | ||||
|                                 <label for="url" class="form-label">{{ $t("URL") }}</label> | ||||
|                                 <input id="url" v-model="monitor.url" type="url" class="form-control" pattern="https?://.+" required> | ||||
|                             </div> | ||||
|  | ||||
|                             <div v-if="monitor.type === 'keyword' " class="my-3"> | ||||
|                                 <label for="keyword" class="form-label">Keyword</label> | ||||
|                                 <label for="keyword" class="form-label">{{ $t("Keyword") }}</label> | ||||
|                                 <input id="keyword" v-model="monitor.keyword" type="text" class="form-control" required> | ||||
|                                 <div class="form-text"> | ||||
|                                     Search keyword in plain html or JSON response and it is case-sensitive | ||||
| @@ -45,57 +45,57 @@ | ||||
|                             </div> | ||||
|  | ||||
|                             <div v-if="monitor.type === 'port' || monitor.type === 'ping' " class="my-3"> | ||||
|                                 <label for="hostname" class="form-label">Hostname</label> | ||||
|                                 <label for="hostname" class="form-label">{{ $t("Hostname") }}</label> | ||||
|                                 <input id="hostname" v-model="monitor.hostname" type="text" class="form-control" required> | ||||
|                             </div> | ||||
|  | ||||
|                             <div v-if="monitor.type === 'port' " class="my-3"> | ||||
|                                 <label for="port" class="form-label">Port</label> | ||||
|                                 <label for="port" class="form-label">{{ $t("Port") }}</label> | ||||
|                                 <input id="port" v-model="monitor.port" type="number" class="form-control" required min="0" max="65535" step="1"> | ||||
|                             </div> | ||||
|  | ||||
|                             <div class="my-3"> | ||||
|                                 <label for="interval" class="form-label">Heartbeat Interval (Every {{ monitor.interval }} seconds)</label> | ||||
|                                 <label for="interval" class="form-label">{{ $t("Heartbeat Interval") }} ({{ $t("checkEverySecond", [ monitor.interval ]) }})</label> | ||||
|                                 <input id="interval" v-model="monitor.interval" type="number" class="form-control" required min="20" step="1"> | ||||
|                             </div> | ||||
|  | ||||
|                             <div class="my-3"> | ||||
|                                 <label for="maxRetries" class="form-label">Retries</label> | ||||
|                                 <label for="maxRetries" class="form-label">{{ $t("Retries") }}</label> | ||||
|                                 <input id="maxRetries" v-model="monitor.maxretries" type="number" class="form-control" required min="0" step="1"> | ||||
|                                 <div class="form-text"> | ||||
|                                     Maximum retries before the service is marked as down and a notification is sent | ||||
|                                     {{ $t("retriesDescription") }} | ||||
|                                 </div> | ||||
|                             </div> | ||||
|  | ||||
|                             <h2 class="mt-5 mb-2">Advanced</h2> | ||||
|                             <h2 class="mt-5 mb-2">{{ $t("Advanced") }}</h2> | ||||
|  | ||||
|                             <div v-if="monitor.type === 'http' || monitor.type === 'keyword' " class="my-3 form-check"> | ||||
|                                 <input id="ignore-tls" v-model="monitor.ignoreTls" class="form-check-input" type="checkbox" value=""> | ||||
|                                 <label class="form-check-label" for="ignore-tls"> | ||||
|                                     Ignore TLS/SSL error for HTTPS websites | ||||
|                                     {{ $t("ignoreTLSError") }} | ||||
|                                 </label> | ||||
|                             </div> | ||||
|  | ||||
|                             <div class="my-3 form-check"> | ||||
|                                 <input id="upside-down" v-model="monitor.upsideDown" class="form-check-input" type="checkbox"> | ||||
|                                 <label class="form-check-label" for="upside-down"> | ||||
|                                     Upside Down Mode | ||||
|                                     {{ $t("Upside Down Mode") }} | ||||
|                                 </label> | ||||
|                                 <div class="form-text"> | ||||
|                                     Flip the status upside down. If the service is reachable, it is DOWN. | ||||
|                                     {{ $t("upsideDownModeDescription") }} | ||||
|                                 </div> | ||||
|                             </div> | ||||
|  | ||||
|                             <div v-if="monitor.type === 'http' || monitor.type === 'keyword' " class="my-3"> | ||||
|                                 <label for="maxRedirects" class="form-label">Max. Redirects</label> | ||||
|                                 <label for="maxRedirects" class="form-label">{{ $t("Max. Redirects") }}</label> | ||||
|                                 <input id="maxRedirects" v-model="monitor.maxredirects" type="number" class="form-control" required min="0" step="1"> | ||||
|                                 <div class="form-text"> | ||||
|                                     Maximum number of redirects to follow. Set to 0 to disable redirects. | ||||
|                                     {{ $t("maxRedirectDescription") }} | ||||
|                                 </div> | ||||
|                             </div> | ||||
|  | ||||
|                             <div v-if="monitor.type === 'http' || monitor.type === 'keyword' " class="my-3"> | ||||
|                                 <label for="acceptedStatusCodes" class="form-label">Accepted Status Codes</label> | ||||
|                                 <label for="acceptedStatusCodes" class="form-label">{{ $t("Accepted Status Codes") }}</label> | ||||
|  | ||||
|                                 <VueMultiselect | ||||
|                                     id="acceptedStatusCodes" | ||||
| @@ -112,21 +112,21 @@ | ||||
|                                 ></VueMultiselect> | ||||
|  | ||||
|                                 <div class="form-text"> | ||||
|                                     Select status codes which are considered as a successful response. | ||||
|                                     {{ $t("acceptedStatusCodesDescription") }} | ||||
|                                 </div> | ||||
|                             </div> | ||||
|  | ||||
|                             <div class="mt-5 mb-1"> | ||||
|                                 <button class="btn btn-primary" type="submit" :disabled="processing">Save</button> | ||||
|                                 <button class="btn btn-primary" type="submit" :disabled="processing">{{ $t("Save") }}</button> | ||||
|                             </div> | ||||
|                         </div> | ||||
|  | ||||
|                         <div class="col-md-6"> | ||||
|                             <div v-if="$root.isMobile" class="mt-3" /> | ||||
|  | ||||
|                             <h2 class="mb-2">Notifications</h2> | ||||
|                             <h2 class="mb-2">{{ $t("Notifications") }}</h2> | ||||
|                             <p v-if="$root.notificationList.length === 0"> | ||||
|                                 Not available, please setup. | ||||
|                                 {{ $t("Not available, please setup.") }} | ||||
|                             </p> | ||||
|  | ||||
|                             <div v-for="notification in $root.notificationList" :key="notification.id" class="form-check form-switch my-3"> | ||||
| @@ -134,12 +134,12 @@ | ||||
|  | ||||
|                                 <label class="form-check-label" :for=" 'notification' + notification.id"> | ||||
|                                     {{ notification.name }} | ||||
|                                     <a href="#" @click="$refs.notificationDialog.show(notification.id)">Edit</a> | ||||
|                                     <a href="#" @click="$refs.notificationDialog.show(notification.id)">{{ $t("Edit") }}</a> | ||||
|                                 </label> | ||||
|                             </div> | ||||
|  | ||||
|                             <button class="btn btn-primary me-2" type="button" @click="$refs.notificationDialog.show()"> | ||||
|                                 Setup Notification | ||||
|                                 {{ $t("Setup Notification") }} | ||||
|                             </button> | ||||
|                         </div> | ||||
|                     </div> | ||||
| @@ -175,7 +175,7 @@ export default { | ||||
|  | ||||
|     computed: { | ||||
|         pageName() { | ||||
|             return (this.isAdd) ? "Add New Monitor" : "Edit" | ||||
|             return this.$t((this.isAdd) ? "Add New Monitor" : "Edit"); | ||||
|         }, | ||||
|         isAdd() { | ||||
|             return this.$route.path === "/add"; | ||||
|   | ||||
| @@ -2,53 +2,63 @@ | ||||
|     <transition name="slide-fade" appear> | ||||
|         <div> | ||||
|             <h1 v-show="show" class="mb-3"> | ||||
|                 Settings | ||||
|                 {{ $t("Settings") }} | ||||
|             </h1> | ||||
|  | ||||
|             <div class="shadow-box"> | ||||
|                 <div class="row"> | ||||
|                     <div class="col-md-6"> | ||||
|                         <h2 class="mb-2">General</h2> | ||||
|                         <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> | ||||
|  | ||||
|                         <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> | ||||
|  | ||||
|                         <h2 class="mt-5 mb-2">{{ $t("General") }}</h2> | ||||
|                         <form class="mb-3" @submit.prevent="saveGeneral"> | ||||
|                             <div class="mb-3"> | ||||
|                                 <label for="timezone" class="form-label">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">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">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">Auto</label> | ||||
|                                     </div> | ||||
|                                 </div> | ||||
|                             </div> | ||||
|  | ||||
|                             <div class="mb-3"> | ||||
|                                 <label class="form-label">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">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">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">None</label> | ||||
|                                     </div> | ||||
|                                 </div> | ||||
|                             </div> | ||||
|  | ||||
|                             <div class="mb-3"> | ||||
|                                 <label for="timezone" class="form-label">Timezone</label> | ||||
|                                 <label for="timezone" class="form-label">{{ $t("Timezone") }}</label> | ||||
|                                 <select id="timezone" v-model="$root.userTimezone" class="form-select"> | ||||
|                                     <option value="auto"> | ||||
|                                         Auto: {{ guessTimezone }} | ||||
|                                         {{ $t("Auto") }}: {{ guessTimezone }} | ||||
|                                     </option> | ||||
|                                     <option v-for="(timezone, index) in timezoneList" :key="index" :value="timezone.value"> | ||||
|                                         {{ timezone.name }} | ||||
| @@ -57,65 +67,65 @@ | ||||
|                             </div> | ||||
|  | ||||
|                             <div class="mb-3"> | ||||
|                                 <label class="form-label">Search Engine Visibility</label> | ||||
|                                 <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"> | ||||
|                                         Allow indexing | ||||
|                                         {{ $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"> | ||||
|                                         Discourage search engines from indexing site | ||||
|                                         {{ $t("Discourage search engines from indexing site") }} | ||||
|                                     </label> | ||||
|                                 </div> | ||||
|                             </div> | ||||
|  | ||||
|                             <div> | ||||
|                                 <button class="btn btn-primary" type="submit"> | ||||
|                                     Save | ||||
|                                     {{ $t("Save") }} | ||||
|                                 </button> | ||||
|                             </div> | ||||
|                         </form> | ||||
|  | ||||
|                         <template v-if="loaded"> | ||||
|                             <template v-if="! settings.disableAuth"> | ||||
|                                 <h2 class="mt-5 mb-2">Change Password</h2> | ||||
|                                 <h2 class="mt-5 mb-2">{{ $t("Change Password") }}</h2> | ||||
|                                 <form class="mb-3" @submit.prevent="savePassword"> | ||||
|                                     <div class="mb-3"> | ||||
|                                         <label for="current-password" class="form-label">Current Password</label> | ||||
|                                         <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">New Password</label> | ||||
|                                         <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">Repeat New Password</label> | ||||
|                                         <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"> | ||||
|                                             The repeat password does not match. | ||||
|                                             {{ $t("passwordNotMatchMsg") }} | ||||
|                                         </div> | ||||
|                                     </div> | ||||
|  | ||||
|                                     <div> | ||||
|                                         <button class="btn btn-primary" type="submit"> | ||||
|                                             Update Password | ||||
|                                             {{ $t("Update Password") }} | ||||
|                                         </button> | ||||
|                                     </div> | ||||
|                                 </form> | ||||
|                             </template> | ||||
|  | ||||
|                             <h2 class="mt-5 mb-2">Advanced</h2> | ||||
|                             <h2 class="mt-5 mb-2">{{ $t("Advanced") }}</h2> | ||||
|  | ||||
|                             <div class="mb-3"> | ||||
|                                 <button v-if="settings.disableAuth" class="btn btn-outline-primary me-1" @click="enableAuth">Enable Auth</button> | ||||
|                                 <button v-if="! settings.disableAuth" class="btn btn-primary me-1" @click="confirmDisableAuth">Disable Auth</button> | ||||
|                                 <button v-if="! settings.disableAuth" class="btn btn-danger me-1" @click="$root.logout">Logout</button> | ||||
|                                 <button v-if="settings.disableAuth" class="btn btn-outline-primary me-1" @click="enableAuth">{{ $t("Enable Auth") }}</button> | ||||
|                                 <button v-if="! settings.disableAuth" class="btn btn-primary me-1" @click="confirmDisableAuth">{{ $t("Disable Auth") }}</button> | ||||
|                                 <button v-if="! settings.disableAuth" class="btn btn-danger me-1" @click="$root.logout">{{ $t("Logout") }}</button> | ||||
|                             </div> | ||||
|                         </template> | ||||
|                     </div> | ||||
| @@ -123,23 +133,23 @@ | ||||
|                     <div class="notification-list col-md-6"> | ||||
|                         <div v-if="$root.isMobile" class="mt-3" /> | ||||
|  | ||||
|                         <h2>Notifications</h2> | ||||
|                         <h2>{{ $t("Notifications") }}</h2> | ||||
|                         <p v-if="$root.notificationList.length === 0"> | ||||
|                             Not available, please setup. | ||||
|                             {{ $t("Not available, please setup.") }} | ||||
|                         </p> | ||||
|                         <p v-else> | ||||
|                             Please assign a notification to monitor(s) to get it to work. | ||||
|                             {{ $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)">Edit</a> | ||||
|                                 <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()"> | ||||
|                             Setup Notification | ||||
|                             {{ $t("Setup Notification") }} | ||||
|                         </button> | ||||
|                     </div> | ||||
|                 </div> | ||||
| @@ -147,10 +157,18 @@ | ||||
|  | ||||
|             <NotificationDialog ref="notificationDialog" /> | ||||
|  | ||||
|             <Confirm ref="confirmDisableAuth" btn-style="btn-danger" yes-text="I understand, please disable" no-text="Leave" @yes="disableAuth"> | ||||
|                 <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> | ||||
|             <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 === 'en' "> | ||||
|                     <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> | ||||
|  | ||||
|                 <template v-if="$i18n.locale === 'zh-HK' "> | ||||
|                     <p>你是否確認<strong>取消登入認証</strong>?</p> | ||||
|                     <p>這個功能是設計給已有<strong>第三方認証</strong>的用家,例如 Cloudflare Access。</p> | ||||
|                     <p>請小心使用。</p> | ||||
|                 </template> | ||||
|             </Confirm> | ||||
|         </div> | ||||
|     </transition> | ||||
| @@ -195,6 +213,10 @@ export default { | ||||
|         "password.repeatNewPassword"() { | ||||
|             this.invalidPassword = false; | ||||
|         }, | ||||
|  | ||||
|         "$i18n.locale"() { | ||||
|             localStorage.locale = this.$i18n.locale; | ||||
|         }, | ||||
|     }, | ||||
|  | ||||
|     mounted() { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user