diff --git a/package-lock.json b/package-lock.json index eefd9d5a..5b961b90 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "uptime-kuma", - "version": "1.11.4", + "version": "1.12.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "uptime-kuma", - "version": "1.11.4", + "version": "1.12.1", "license": "MIT", "dependencies": { "@fortawesome/fontawesome-svg-core": "~1.2.36", @@ -29,6 +29,7 @@ "dayjs": "~1.10.7", "express": "~4.17.1", "express-basic-auth": "~1.2.0", + "favico.js": "^0.3.10", "form-data": "~4.0.0", "http-graceful-shutdown": "~3.1.5", "iconv-lite": "^0.6.3", @@ -6140,6 +6141,11 @@ "reusify": "^1.0.4" } }, + "node_modules/favico.js": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/favico.js/-/favico.js-0.3.10.tgz", + "integrity": "sha1-gFhuJ6EX8kqNUcGKmb3HFNQzkwE=" + }, "node_modules/fb-watchman": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", @@ -18240,6 +18246,11 @@ "reusify": "^1.0.4" } }, + "favico.js": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/favico.js/-/favico.js-0.3.10.tgz", + "integrity": "sha1-gFhuJ6EX8kqNUcGKmb3HFNQzkwE=" + }, "fb-watchman": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", diff --git a/package.json b/package.json index 9da73798..23f7acde 100644 --- a/package.json +++ b/package.json @@ -68,12 +68,13 @@ "chardet": "^1.3.0", "chart.js": "~3.6.0", "chartjs-adapter-dayjs": "~1.0.0", - "check-password-strength": "^2.0.3", + "check-password-strength": "^2.0.5", "command-exists": "~1.2.9", "compare-versions": "~3.6.0", "dayjs": "~1.10.7", "express": "~4.17.1", "express-basic-auth": "~1.2.0", + "favico.js": "^0.3.10", "form-data": "~4.0.0", "http-graceful-shutdown": "~3.1.5", "iconv-lite": "^0.6.3", diff --git a/src/languages/bg-BG.js b/src/languages/bg-BG.js index 66ce636f..1973aed1 100644 --- a/src/languages/bg-BG.js +++ b/src/languages/bg-BG.js @@ -361,4 +361,13 @@ export default { smtpDkimHashAlgo: "Хеш алгоритъм (по желание)", smtpDkimheaderFieldNames: "Хедър ключове за подписване (по желание)", smtpDkimskipFields: "Хедър ключове, които да не се подписват (по желание)", + PushByTechulus: "Push от Techulus", + GoogleChat: "Google Chat (Само за работното пространство на Google)", + gorush: "Gorush", + alerta: "Alerta", + alertaApiEndpoint: "Крайна точка на API", + alertaEnvironment: "Среда", + alertaApiKey: "API Ключ", + alertaAlertState: "Състояние на тревога", + alertaRecoverState: "Състояние на възстановяване", }; diff --git a/src/languages/hu.js b/src/languages/hu.js index 8b390dc4..06a324aa 100644 --- a/src/languages/hu.js +++ b/src/languages/hu.js @@ -362,4 +362,12 @@ export default { smtpDkimHashAlgo: "Hash algoritmus (nem kötelező)", smtpDkimheaderFieldNames: "Fejléc kulcsok a bejelentkezéshez (nem kötelező)", smtpDkimskipFields: "Fejléc kulcsok egyéb esetben (nem kötelező)", + PushByTechulus: "Techulus push", + gorush: "Gorush", + alerta: "Alerta", + alertaApiEndpoint: "API végpont", + alertaEnvironment: "Környezet", + alertaApiKey: "API kulcs", + alertaAlertState: "Figyelmeztetési állapot", + alertaRecoverState: "Visszaállási állapot", }; diff --git a/src/mixins/socket.js b/src/mixins/socket.js index 5dee6308..5d80293d 100644 --- a/src/mixins/socket.js +++ b/src/mixins/socket.js @@ -1,6 +1,7 @@ import { io } from "socket.io-client"; import { useToast } from "vue-toastification"; import jwt_decode from "jwt-decode"; +import Favico from "favico.js"; const toast = useToast(); let socket; @@ -11,6 +12,10 @@ const noSocketIOPages = [ "/" ]; +const favicon = new Favico({ + animation: "none" +}); + export default { data() { @@ -398,10 +403,50 @@ export default { return result; }, + + stats() { + let result = { + up: 0, + down: 0, + unknown: 0, + pause: 0, + }; + + for (let monitorID in this.$root.monitorList) { + let beat = this.$root.lastHeartbeatList[monitorID]; + let monitor = this.$root.monitorList[monitorID]; + + if (monitor && ! monitor.active) { + result.pause++; + } else if (beat) { + if (beat.status === 1) { + result.up++; + } else if (beat.status === 0) { + result.down++; + } else if (beat.status === 2) { + result.up++; + } else { + result.unknown++; + } + } else { + result.unknown++; + } + } + + return result; + }, }, watch: { + // Update Badge + "stats.down"(to, from) { + if (to !== from) { + favicon.badge(to); + console.log(to); + } + }, + // Reload the SPA if the server version is changed. "info.version"(to, from) { if (from && from !== to) { diff --git a/src/pages/DashboardHome.vue b/src/pages/DashboardHome.vue index 16d07983..6e8a5bbc 100644 --- a/src/pages/DashboardHome.vue +++ b/src/pages/DashboardHome.vue @@ -9,19 +9,19 @@

{{ $t("Up") }}

- {{ stats.up }} + {{ $root.stats.up }}

{{ $t("Down") }}

- {{ stats.down }} + {{ $root.stats.down }}

{{ $t("Unknown") }}

- {{ stats.unknown }} + {{ $root.stats.unknown }}

{{ $t("pauseDashboardHome") }}

- {{ stats.pause }} + {{ $root.stats.pause }}
@@ -89,37 +89,6 @@ export default { }; }, computed: { - stats() { - let result = { - up: 0, - down: 0, - unknown: 0, - pause: 0, - }; - - for (let monitorID in this.$root.monitorList) { - let beat = this.$root.lastHeartbeatList[monitorID]; - let monitor = this.$root.monitorList[monitorID]; - - if (monitor && ! monitor.active) { - result.pause++; - } else if (beat) { - if (beat.status === 1) { - result.up++; - } else if (beat.status === 0) { - result.down++; - } else if (beat.status === 2) { - result.up++; - } else { - result.unknown++; - } - } else { - result.unknown++; - } - } - - return result; - }, importantHeartBeatList() { let result = []; diff --git a/src/pages/StatusPage.vue b/src/pages/StatusPage.vue index 69839ada..01974e32 100644 --- a/src/pages/StatusPage.vue +++ b/src/pages/StatusPage.vue @@ -220,12 +220,18 @@ import ImageCropUpload from "vue-image-crop-upload"; import { STATUS_PAGE_ALL_DOWN, STATUS_PAGE_ALL_UP, STATUS_PAGE_PARTIAL_DOWN, UP } from "../util.ts"; import { useToast } from "vue-toastification"; import dayjs from "dayjs"; +import Favico from "favico.js"; + const toast = useToast(); const leavePageMsg = "Do you really want to leave? you have unsaved changes!"; let feedInterval; +const favicon = new Favico({ + animation: "none" +}); + export default { components: { PublicGroupList, @@ -446,8 +452,25 @@ export default { // If editMode, it will use the data from websocket. if (! this.editMode) { axios.get("/api/status-page/heartbeat/" + this.slug).then((res) => { - this.$root.heartbeatList = res.data.heartbeatList; - this.$root.uptimeList = res.data.uptimeList; + const { heartbeatList, uptimeList } = res.data; + + this.$root.heartbeatList = heartbeatList; + this.$root.uptimeList = uptimeList; + + const heartbeatIds = Object.keys(heartbeatList); + const downMonitors = heartbeatIds.reduce((downMonitorsAmount, currentId) => { + const monitorHeartbeats = heartbeatList[currentId]; + const lastHeartbeat = monitorHeartbeats.at(-1); + + if (lastHeartbeat) { + return lastHeartbeat.status === 0 ? downMonitorsAmount + 1 : downMonitorsAmount; + } else { + return downMonitorsAmount; + } + }, 0); + + favicon.badge(downMonitors); + this.loadedData = true; }); }