Compare commits

...

5 commits

Author SHA1 Message Date
Zandor Smith
8e489b184b
Merge 9977dd2246 into 8a432ac937 2024-11-12 18:00:25 +00:00
Ionys
8a432ac937
fix(status page): Make sure the group deletion is correctly handled when groupIDList is empty (#5340)
Some checks failed
Auto Test / check-linters (push) Has been cancelled
Auto Test / armv7-simple-test (18, ARMv7) (push) Has been cancelled
Auto Test / armv7-simple-test (20, ARMv7) (push) Has been cancelled
Auto Test / e2e-test (push) Has been cancelled
CodeQL / Analyze (push) Has been cancelled
Merge Conflict Labeler / Labeling (push) Has been cancelled
validate / json-yaml-validate (push) Has been cancelled
validate / validate (push) Has been cancelled
Auto Test / auto-test (18, ARM64) (push) Has been cancelled
Auto Test / auto-test (18, macos-latest) (push) Has been cancelled
Auto Test / auto-test (18, ubuntu-latest) (push) Has been cancelled
Auto Test / auto-test (18, windows-latest) (push) Has been cancelled
Auto Test / auto-test (20, ARM64) (push) Has been cancelled
Auto Test / auto-test (20, macos-latest) (push) Has been cancelled
Auto Test / auto-test (20, ubuntu-latest) (push) Has been cancelled
Auto Test / auto-test (20, windows-latest) (push) Has been cancelled
2024-11-12 19:00:09 +01:00
Zandor Smith
9977dd2246
Merge branch 'master' into feature/status-page-offline-monitors-group 2024-07-22 23:17:54 +02:00
Zandor Smith
f5e1df7dae
Fix linting issues. 2024-04-18 21:26:00 +02:00
Zandor Smith
1dd6e61269
Status Page: Display offline monitors at the top of the statuspage. 2024-04-18 21:03:34 +02:00
3 changed files with 58 additions and 6 deletions

View file

@ -220,6 +220,9 @@ module.exports.statusPageSocketHandler = (socket) => {
// Delete groups that are not in the list // Delete groups that are not in the list
log.debug("socket", "Delete groups that are not in the list"); log.debug("socket", "Delete groups that are not in the list");
if (groupIDList.length === 0) {
await R.exec("DELETE FROM `group` WHERE status_page_id = ?", [ statusPage.id ]);
} else {
const slots = groupIDList.map(() => "?").join(","); const slots = groupIDList.map(() => "?").join(",");
const data = [ const data = [
@ -227,6 +230,7 @@ module.exports.statusPageSocketHandler = (socket) => {
statusPage.id statusPage.id
]; ];
await R.exec(`DELETE FROM \`group\` WHERE id NOT IN (${slots}) AND status_page_id = ?`, data); await R.exec(`DELETE FROM \`group\` WHERE id NOT IN (${slots}) AND status_page_id = ?`, data);
}
const server = UptimeKumaServer.getInstance(); const server = UptimeKumaServer.getInstance();

View file

@ -953,6 +953,8 @@
"cellsyntSplitLongMessages": "Split long messages into up to 6 parts. 153 x 6 = 918 characters.", "cellsyntSplitLongMessages": "Split long messages into up to 6 parts. 153 x 6 = 918 characters.",
"max 15 digits": "max 15 digits", "max 15 digits": "max 15 digits",
"max 11 alphanumeric characters": "max 11 alphanumeric characters", "max 11 alphanumeric characters": "max 11 alphanumeric characters",
"offlineMonitor": "Offline Monitor",
"offlineMonitors": "Offline Monitors",
"Community String": "Community String", "Community String": "Community String",
"snmpCommunityStringHelptext": "This string functions as a password to authenticate and control access to SNMP-enabled devices. Match it with your SNMP device's configuration.", "snmpCommunityStringHelptext": "This string functions as a password to authenticate and control access to SNMP-enabled devices. Match it with your SNMP device's configuration.",
"OID (Object Identifier)": "OID (Object Identifier)", "OID (Object Identifier)": "OID (Object Identifier)",

View file

@ -322,6 +322,30 @@
</div> </div>
</div> </div>
<div v-if="$root.downMonitors?.length > 0" class="mb-4">
<div class="mb-5">
<h2 class="group-title">
{{ $t($root.downMonitors.length === 1 ? "offlineMonitor" : "offlineMonitors") }}
</h2>
<div class="shadow-box monitor-list mt-4 position-relative">
<div v-for="monitor in $root.downMonitors" :key="monitor.id" class="item">
<div class="row">
<div class="col-9 col-md-8 small-padding">
<div class="info">
<Uptime :monitor="monitor" type="24" :pill="true" />
{{ monitor.name }}
</div>
</div>
<div :key="$root.userHeartbeatBar" class="col-3 col-md-4">
<HeartbeatBar size="mid" :monitor-id="monitor.id" />
</div>
</div>
</div>
</div>
</div>
</div>
<div class="mb-4"> <div class="mb-4">
<div v-if="$root.publicGroupList.length === 0 && loadedData" class="text-center"> <div v-if="$root.publicGroupList.length === 0 && loadedData" class="text-center">
<!-- 👀 Nothing here, please add a group or a monitor. --> <!-- 👀 Nothing here, please add a group or a monitor. -->
@ -383,6 +407,8 @@ import { getResBaseURL } from "../util-frontend";
import { STATUS_PAGE_ALL_DOWN, STATUS_PAGE_ALL_UP, STATUS_PAGE_MAINTENANCE, STATUS_PAGE_PARTIAL_DOWN, UP, MAINTENANCE } from "../util.ts"; import { STATUS_PAGE_ALL_DOWN, STATUS_PAGE_ALL_UP, STATUS_PAGE_MAINTENANCE, STATUS_PAGE_PARTIAL_DOWN, UP, MAINTENANCE } from "../util.ts";
import Tag from "../components/Tag.vue"; import Tag from "../components/Tag.vue";
import VueMultiselect from "vue-multiselect"; import VueMultiselect from "vue-multiselect";
import Uptime from "../components/Uptime.vue";
import HeartbeatBar from "../components/HeartbeatBar.vue";
const toast = useToast(); const toast = useToast();
dayjs.extend(duration); dayjs.extend(duration);
@ -399,6 +425,8 @@ const favicon = new Favico({
export default { export default {
components: { components: {
HeartbeatBar,
Uptime,
PublicGroupList, PublicGroupList,
ImageCropUpload, ImageCropUpload,
Confirm, Confirm,
@ -777,6 +805,8 @@ export default {
this.$root.heartbeatList = heartbeatList; this.$root.heartbeatList = heartbeatList;
this.$root.uptimeList = uptimeList; this.$root.uptimeList = uptimeList;
this.$root.downMonitors = this.downMonitors();
const heartbeatIds = Object.keys(heartbeatList); const heartbeatIds = Object.keys(heartbeatList);
const downMonitors = heartbeatIds.reduce((downMonitorsAmount, currentId) => { const downMonitors = heartbeatIds.reduce((downMonitorsAmount, currentId) => {
const monitorHeartbeats = heartbeatList[currentId]; const monitorHeartbeats = heartbeatList[currentId];
@ -798,6 +828,22 @@ export default {
} }
}, },
downMonitors() {
let result = [];
for (const id in this.$root.publicMonitorList) {
const monitor = this.$root.publicMonitorList[id];
const heartbeats = this.$root.heartbeatList[monitor.id];
const lastHeartbeat = heartbeats.at(-1);
if (!lastHeartbeat || lastHeartbeat.status !== 0) {
continue;
}
result.push(monitor);
}
return result;
},
/** /**
* Setup timer to display countdown to refresh * Setup timer to display countdown to refresh
* @returns {void} * @returns {void}