fix: lint

This commit is contained in:
Mats Stottmeister 2025-06-11 21:40:16 +02:00
parent e6ce7e7a61
commit 7064932c16
No known key found for this signature in database
4 changed files with 65 additions and 55 deletions

View file

@ -10,4 +10,4 @@ exports.down = function (knex) {
return knex.schema.alterTable("monitor_group", function (table) { return knex.schema.alterTable("monitor_group", function (table) {
table.dropColumn("daily_view"); table.dropColumn("daily_view");
}); });
}; };

View file

@ -142,7 +142,7 @@ router.get("/api/status-page/heartbeat-daily/:slug", cache("5 minutes"), async (
for (let monitor of monitorData) { for (let monitor of monitorData) {
const monitorID = monitor.monitor_id; const monitorID = monitor.monitor_id;
const useDailyView = monitor.daily_view; const useDailyView = monitor.daily_view;
dailyViewSettings[monitorID] = useDailyView; dailyViewSettings[monitorID] = useDailyView;
if (useDailyView) { if (useDailyView) {
@ -173,7 +173,7 @@ router.get("/api/status-page/heartbeat-daily/:slug", cache("5 minutes"), async (
// Determine overall status for the day based on majority // Determine overall status for the day based on majority
if (row.maintenance_beats > 0) { if (row.maintenance_beats > 0) {
status = 3; // Maintenance status = 3; // Maintenance
} else if (row.down_beats > row.up_beats / 2) { } else if (row.down_beats > row.up_beats / 2) {
status = 0; // Down if more than 50% down status = 0; // Down if more than 50% down
} else if (row.up_beats > 0) { } else if (row.up_beats > 0) {
status = 1; // Up status = 1; // Up
@ -200,15 +200,15 @@ router.get("/api/status-page/heartbeat-daily/:slug", cache("5 minutes"), async (
}); });
heartbeatList[monitorID] = processedData; heartbeatList[monitorID] = processedData;
// Calculate uptime based only on actual daily data (not including missing days) // Calculate uptime based only on actual daily data (not including missing days)
if (processedData.length > 0) { if (processedData.length > 0) {
// Get recent data (last 30 days worth of actual data) // Get recent data (last 30 days worth of actual data)
const recentData = processedData.slice(-30); const recentData = processedData.slice(-30);
let totalUp = 0; let totalUp = 0;
let totalDown = 0; let totalDown = 0;
recentData.forEach(day => { recentData.forEach(day => {
if (day.dailyStats) { if (day.dailyStats) {
// Convert strings to numbers to avoid concatenation // Convert strings to numbers to avoid concatenation
@ -216,7 +216,7 @@ router.get("/api/status-page/heartbeat-daily/:slug", cache("5 minutes"), async (
totalDown += parseInt(day.dailyStats.down) || 0; totalDown += parseInt(day.dailyStats.down) || 0;
} }
}); });
const totalChecks = totalUp + totalDown; const totalChecks = totalUp + totalDown;
uptimeList[`${monitorID}_24`] = totalChecks > 0 ? (totalUp / totalChecks) : 0; uptimeList[`${monitorID}_24`] = totalChecks > 0 ? (totalUp / totalChecks) : 0;
} else { } else {
@ -235,7 +235,7 @@ router.get("/api/status-page/heartbeat-daily/:slug", cache("5 minutes"), async (
list = R.convertToBeans("heartbeat", list); list = R.convertToBeans("heartbeat", list);
heartbeatList[monitorID] = list.reverse().map(row => row.toPublicJSON()); heartbeatList[monitorID] = list.reverse().map(row => row.toPublicJSON());
const uptimeCalculator = await UptimeCalculator.getUptimeCalculator(monitorID); const uptimeCalculator = await UptimeCalculator.getUptimeCalculator(monitorID);
uptimeList[`${monitorID}_24`] = uptimeCalculator.get24Hour().uptime; uptimeList[`${monitorID}_24`] = uptimeCalculator.get24Hour().uptime;
} }

View file

@ -11,12 +11,12 @@
> >
<div <div
class="beat daily-beat" class="beat daily-beat"
:class="{ :class="{
'empty': (beat === 0), 'empty': (beat === 0),
'missing': (beat.missing || beat.status === -1), 'missing': (beat.missing || beat.status === -1),
'down': (beat.status === 0), 'down': (beat.status === 0),
'pending': (beat.status === 2), 'pending': (beat.status === 2),
'maintenance': (beat.status === 3) 'maintenance': (beat.status === 3)
}" }"
:style="getBeatStyle(beat)" :style="getBeatStyle(beat)"
/> />
@ -178,8 +178,10 @@ export default {
*/ */
timeSinceFirstBeat() { timeSinceFirstBeat() {
const firstValidBeat = this.shortBeatList.at(this.numPadding); const firstValidBeat = this.shortBeatList.at(this.numPadding);
if (!firstValidBeat || !firstValidBeat.date) return ""; if (!firstValidBeat || !firstValidBeat.date) {
return "";
}
const days = dayjs().diff(dayjs(firstValidBeat.date), "days"); const days = dayjs().diff(dayjs(firstValidBeat.date), "days");
if (days > 30) { if (days > 30) {
return Math.floor(days / 30) + "mo"; return Math.floor(days / 30) + "mo";
@ -194,10 +196,12 @@ export default {
*/ */
timeSinceLastBeat() { timeSinceLastBeat() {
const lastValidBeat = this.shortBeatList.at(-1); const lastValidBeat = this.shortBeatList.at(-1);
if (!lastValidBeat || !lastValidBeat.date) return ""; if (!lastValidBeat || !lastValidBeat.date) {
return "";
}
const days = dayjs().diff(dayjs(lastValidBeat.date), "days"); const days = dayjs().diff(dayjs(lastValidBeat.date), "days");
if (days === 0) { if (days === 0) {
return this.$t("Today"); return this.$t("Today");
} else if (days === 1) { } else if (days === 1) {
@ -273,31 +277,37 @@ export default {
* @returns {string} Beat title * @returns {string} Beat title
*/ */
getBeatTitle(beat) { getBeatTitle(beat) {
if (!beat || beat === 0) return ""; if (!beat || beat === 0) {
return "";
}
// Handle missing data // Handle missing data
if (beat.missing || beat.status === -1) { if (beat.missing || beat.status === -1) {
const date = beat.date || beat.time.split(' ')[0]; const date = beat.date || beat.time.split(" ")[0];
return `${date}\nNo data available`; return `${date}\nNo data available`;
} }
const date = beat.date || beat.time.split(' ')[0]; const date = beat.date || beat.time.split(" ")[0];
const uptime = Math.round(beat.uptime * 100); const uptime = Math.round(beat.uptime * 100);
const stats = beat.dailyStats; const stats = beat.dailyStats;
let tooltip = `${date}\nUptime: ${uptime}%`; let tooltip = `${date}\nUptime: ${uptime}%`;
if (stats) { if (stats) {
tooltip += `\nUp: ${stats.up}, Down: ${stats.down}`; tooltip += `\nUp: ${stats.up}, Down: ${stats.down}`;
if (stats.pending > 0) tooltip += `, Pending: ${stats.pending}`; if (stats.pending > 0) {
if (stats.maintenance > 0) tooltip += `, Maintenance: ${stats.maintenance}`; tooltip += `, Pending: ${stats.pending}`;
}
if (stats.maintenance > 0) {
tooltip += `, Maintenance: ${stats.maintenance}`;
}
tooltip += `\nTotal checks: ${stats.total}`; tooltip += `\nTotal checks: ${stats.total}`;
} }
if (beat.ping) { if (beat.ping) {
tooltip += `\nAvg ping: ${beat.ping}ms`; tooltip += `\nAvg ping: ${beat.ping}ms`;
} }
return tooltip; return tooltip;
}, },
@ -329,23 +339,23 @@ export default {
*/ */
generateCompleteTimeline(actualData) { generateCompleteTimeline(actualData) {
const timeline = []; const timeline = [];
const today = dayjs().startOf('day'); const today = dayjs().startOf("day");
const startDate = today.subtract(90, 'day'); // 3 months back const startDate = today.subtract(90, "day"); // 3 months back
// Create a map of existing data by date for quick lookup // Create a map of existing data by date for quick lookup
const dataMap = {}; const dataMap = {};
actualData.forEach(beat => { actualData.forEach(beat => {
if (beat && beat.date) { if (beat && beat.date) {
const dateKey = dayjs(beat.date).format('YYYY-MM-DD'); const dateKey = dayjs(beat.date).format("YYYY-MM-DD");
dataMap[dateKey] = beat; dataMap[dateKey] = beat;
} }
}); });
// Generate complete timeline from startDate to today // Generate complete timeline from startDate to today
for (let i = 0; i <= 90; i++) { for (let i = 0; i <= 90; i++) {
const currentDate = startDate.add(i, 'day'); const currentDate = startDate.add(i, "day");
const dateKey = currentDate.format('YYYY-MM-DD'); const dateKey = currentDate.format("YYYY-MM-DD");
if (dataMap[dateKey]) { if (dataMap[dateKey]) {
// Use actual data if available // Use actual data if available
timeline.push(dataMap[dateKey]); timeline.push(dataMap[dateKey]);
@ -354,7 +364,7 @@ export default {
timeline.push({ timeline.push({
status: -1, // Special status for missing data status: -1, // Special status for missing data
date: dateKey, date: dateKey,
time: dateKey + ' 00:00:00', time: dateKey + " 00:00:00",
uptime: 0, uptime: 0,
ping: 0, ping: 0,
missing: true, missing: true,
@ -368,7 +378,7 @@ export default {
}); });
} }
} }
return timeline; return timeline;
}, },
@ -429,23 +439,23 @@ export default {
// Daily beats get special styling // Daily beats get special styling
&.daily-beat { &.daily-beat {
border: 1px solid rgba(0, 0, 0, 0.1); border: 1px solid rgba(0, 0, 0, 0.1);
&.down { &.down {
border-color: darken($danger, 10%); border-color: darken($danger, 10%);
} }
&.pending { &.pending {
border-color: darken($warning, 10%); border-color: darken($warning, 10%);
} }
&.maintenance { &.maintenance {
border-color: darken($maintenance, 10%); border-color: darken($maintenance, 10%);
} }
&:not(.empty):not(.down):not(.pending):not(.maintenance):not(.missing) { &:not(.empty):not(.down):not(.pending):not(.maintenance):not(.missing) {
border-color: darken($primary, 10%); border-color: darken($primary, 10%);
} }
&.missing { &.missing {
border-color: transparent; border-color: transparent;
} }
@ -458,31 +468,31 @@ export default {
.hp-bar-big .beat.empty { .hp-bar-big .beat.empty {
background-color: #848484; background-color: #848484;
} }
.hp-bar-big .beat.missing { .hp-bar-big .beat.missing {
background-color: #555555; background-color: #555555;
opacity: 0.6; opacity: 0.6;
} }
.hp-bar-big .beat.daily-beat { .hp-bar-big .beat.daily-beat {
border-color: rgba(255, 255, 255, 0.2); border-color: rgba(255, 255, 255, 0.2);
&.down { &.down {
border-color: lighten($danger, 10%); border-color: lighten($danger, 10%);
} }
&.pending { &.pending {
border-color: lighten($warning, 10%); border-color: lighten($warning, 10%);
} }
&.maintenance { &.maintenance {
border-color: lighten($maintenance, 10%); border-color: lighten($maintenance, 10%);
} }
&:not(.empty):not(.down):not(.pending):not(.maintenance):not(.missing) { &:not(.empty):not(.down):not(.pending):not(.maintenance):not(.missing) {
border-color: lighten($primary, 10%); border-color: lighten($primary, 10%);
} }
&.missing { &.missing {
border-color: transparent; border-color: transparent;
} }
@ -506,4 +516,4 @@ export default {
background-color: #333; background-color: #333;
} }
} }
</style> </style>

View file

@ -773,7 +773,7 @@ export default {
if (! this.editMode) { if (! this.editMode) {
// Fetch mixed data based on per-monitor daily view settings // Fetch mixed data based on per-monitor daily view settings
axios.get("/api/status-page/heartbeat-daily/" + this.slug).then((res) => { axios.get("/api/status-page/heartbeat-daily/" + this.slug).then((res) => {
const { heartbeatList, uptimeList, dailyViewSettings, hasMixedData } = res.data; const { heartbeatList, uptimeList, dailyViewSettings } = res.data;
// Store both regular and daily data appropriately // Store both regular and daily data appropriately
this.$root.heartbeatList = {}; this.$root.heartbeatList = {};
@ -785,12 +785,12 @@ export default {
if (dailyViewSettings[monitorId]) { if (dailyViewSettings[monitorId]) {
// This monitor uses daily view // This monitor uses daily view
this.$root.dailyHeartbeatList[monitorId] = heartbeatList[monitorId]; this.$root.dailyHeartbeatList[monitorId] = heartbeatList[monitorId];
// Set up lastHeartbeatList for uptime color calculation // Set up lastHeartbeatList for uptime color calculation
if (heartbeatList[monitorId] && heartbeatList[monitorId].length > 0) { if (heartbeatList[monitorId] && heartbeatList[monitorId].length > 0) {
const lastDailyBeat = heartbeatList[monitorId][heartbeatList[monitorId].length - 1]; const lastDailyBeat = heartbeatList[monitorId][heartbeatList[monitorId].length - 1];
// Create a minimal heartbeat list with just the last beat for color calculation // Create a minimal heartbeat list with just the last beat for color calculation
this.$root.heartbeatList[monitorId] = [lastDailyBeat]; this.$root.heartbeatList[monitorId] = [ lastDailyBeat ];
} }
} else { } else {
// This monitor uses regular view // This monitor uses regular view