mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-06-19 18:56:48 +02:00
added heartbeat range
This commit is contained in:
parent
ad713eda4b
commit
493a5fdf69
8 changed files with 253 additions and 63 deletions
|
@ -1,12 +1,11 @@
|
||||||
exports.up = function (knex) {
|
exports.up = function (knex) {
|
||||||
return knex.schema
|
return knex.schema.alterTable("status_page", function (table) {
|
||||||
.alterTable("status_page", function (table) {
|
table.string("heartbeat_bar_range").defaultTo("auto");
|
||||||
table.integer("heartbeat_bar_range_days").defaultTo(90).unsigned();
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.down = function (knex) {
|
exports.down = function (knex) {
|
||||||
return knex.schema.alterTable("status_page", function (table) {
|
return knex.schema.alterTable("status_page", function (table) {
|
||||||
table.dropColumn("heartbeat_bar_range_days");
|
table.dropColumn("heartbeat_bar_range");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -409,7 +409,7 @@ class StatusPage extends BeanModel {
|
||||||
showPoweredBy: !!this.show_powered_by,
|
showPoweredBy: !!this.show_powered_by,
|
||||||
googleAnalyticsId: this.google_analytics_tag_id,
|
googleAnalyticsId: this.google_analytics_tag_id,
|
||||||
showCertificateExpiry: !!this.show_certificate_expiry,
|
showCertificateExpiry: !!this.show_certificate_expiry,
|
||||||
heartbeatBarRangeDays: this.heartbeat_bar_range_days || 90,
|
heartbeatBarRange: this.heartbeat_bar_range || "auto",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,7 +433,7 @@ class StatusPage extends BeanModel {
|
||||||
showPoweredBy: !!this.show_powered_by,
|
showPoweredBy: !!this.show_powered_by,
|
||||||
googleAnalyticsId: this.google_analytics_tag_id,
|
googleAnalyticsId: this.google_analytics_tag_id,
|
||||||
showCertificateExpiry: !!this.show_certificate_expiry,
|
showCertificateExpiry: !!this.show_certificate_expiry,
|
||||||
heartbeatBarRangeDays: this.heartbeat_bar_range_days || 90,
|
heartbeatBarRange: this.heartbeat_bar_range || "auto",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,14 +86,41 @@ router.get("/api/status-page/heartbeat/:slug", cache("1 minutes"), async (reques
|
||||||
|
|
||||||
// Get the status page to determine the heartbeat range
|
// Get the status page to determine the heartbeat range
|
||||||
let statusPage = await R.findOne("status_page", " id = ? ", [ statusPageID ]);
|
let statusPage = await R.findOne("status_page", " id = ? ", [ statusPageID ]);
|
||||||
let heartbeatRangeDays = (statusPage && statusPage.heartbeat_bar_range_days) ? statusPage.heartbeat_bar_range_days : 90;
|
let heartbeatRange = (statusPage && statusPage.heartbeat_bar_range) ? statusPage.heartbeat_bar_range : "auto";
|
||||||
|
|
||||||
// Calculate the date range for heartbeats
|
// Calculate the date range for heartbeats based on range setting
|
||||||
let dateFrom = new Date();
|
let dateFrom = new Date();
|
||||||
dateFrom.setDate(dateFrom.getDate() - heartbeatRangeDays);
|
if (heartbeatRange === "auto") {
|
||||||
|
// Auto mode: limit to last 100 beats (original behavior)
|
||||||
|
dateFrom = null;
|
||||||
|
} else if (heartbeatRange.endsWith("h")) {
|
||||||
|
// Hours
|
||||||
|
let hours = parseInt(heartbeatRange);
|
||||||
|
dateFrom.setHours(dateFrom.getHours() - hours);
|
||||||
|
} else if (heartbeatRange.endsWith("d")) {
|
||||||
|
// Days
|
||||||
|
let days = parseInt(heartbeatRange);
|
||||||
|
dateFrom.setDate(dateFrom.getDate() - days);
|
||||||
|
} else {
|
||||||
|
// Fallback to 90 days
|
||||||
|
dateFrom.setDate(dateFrom.getDate() - 90);
|
||||||
|
}
|
||||||
|
|
||||||
for (let monitorID of monitorIDList) {
|
for (let monitorID of monitorIDList) {
|
||||||
let list = await R.getAll(`
|
let list;
|
||||||
|
if (dateFrom === null) {
|
||||||
|
// Auto mode: use original logic with LIMIT 100
|
||||||
|
list = await R.getAll(`
|
||||||
|
SELECT * FROM heartbeat
|
||||||
|
WHERE monitor_id = ?
|
||||||
|
ORDER BY time DESC
|
||||||
|
LIMIT 100
|
||||||
|
`, [
|
||||||
|
monitorID,
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
// Time-based filtering
|
||||||
|
list = await R.getAll(`
|
||||||
SELECT * FROM heartbeat
|
SELECT * FROM heartbeat
|
||||||
WHERE monitor_id = ? AND time >= ?
|
WHERE monitor_id = ? AND time >= ?
|
||||||
ORDER BY time DESC
|
ORDER BY time DESC
|
||||||
|
@ -101,6 +128,7 @@ router.get("/api/status-page/heartbeat/:slug", cache("1 minutes"), async (reques
|
||||||
monitorID,
|
monitorID,
|
||||||
dateFrom.toISOString(),
|
dateFrom.toISOString(),
|
||||||
]);
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
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());
|
||||||
|
|
|
@ -165,7 +165,7 @@ module.exports.statusPageSocketHandler = (socket) => {
|
||||||
statusPage.custom_css = config.customCSS;
|
statusPage.custom_css = config.customCSS;
|
||||||
statusPage.show_powered_by = config.showPoweredBy;
|
statusPage.show_powered_by = config.showPoweredBy;
|
||||||
statusPage.show_certificate_expiry = config.showCertificateExpiry;
|
statusPage.show_certificate_expiry = config.showCertificateExpiry;
|
||||||
statusPage.heartbeat_bar_range_days = config.heartbeatBarRangeDays || 90;
|
statusPage.heartbeat_bar_range = config.heartbeatBarRange || "auto";
|
||||||
statusPage.modified_date = R.isoDateTime();
|
statusPage.modified_date = R.isoDateTime();
|
||||||
statusPage.google_analytics_tag_id = config.googleAnalyticsId;
|
statusPage.google_analytics_tag_id = config.googleAnalyticsId;
|
||||||
|
|
||||||
|
|
|
@ -5,19 +5,19 @@
|
||||||
v-for="(beat, index) in shortBeatList"
|
v-for="(beat, index) in shortBeatList"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="beat-hover-area"
|
class="beat-hover-area"
|
||||||
:class="{ 'empty': (beat === 0) }"
|
:class="{ 'empty': (beat === 0 || beat === null || beat.status === null) }"
|
||||||
:style="beatHoverAreaStyle"
|
:style="beatHoverAreaStyle"
|
||||||
:title="getBeatTitle(beat)"
|
:title="getBeatTitle(beat)"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="beat"
|
class="beat"
|
||||||
:class="{ 'empty': (beat === 0), 'down': (beat.status === 0), 'pending': (beat.status === 2), 'maintenance': (beat.status === 3) }"
|
:class="{ 'empty': (beat === 0 || beat === null || beat.status === null), 'down': (beat.status === 0), 'pending': (beat.status === 2), 'maintenance': (beat.status === 3) }"
|
||||||
:style="beatStyle"
|
:style="beatStyle"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="!$root.isMobile && size !== 'small' && beatList.length > 4 && $root.styleElapsedTime !== 'none'"
|
v-if="!$root.isMobile && size !== 'small' && shortBeatList.length > 4 && $root.styleElapsedTime !== 'none'"
|
||||||
class="d-flex justify-content-between align-items-center word" :style="timeStyle"
|
class="d-flex justify-content-between align-items-center word" :style="timeStyle"
|
||||||
>
|
>
|
||||||
<div>{{ timeSinceFirstBeat }}</div>
|
<div>{{ timeSinceFirstBeat }}</div>
|
||||||
|
@ -46,6 +46,11 @@ export default {
|
||||||
heartbeatList: {
|
heartbeatList: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: null,
|
default: null,
|
||||||
|
},
|
||||||
|
/** Heartbeat bar range */
|
||||||
|
heartbeatBarRange: {
|
||||||
|
type: String,
|
||||||
|
default: "auto",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@ -98,6 +103,12 @@ export default {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If heartbeat range is configured (not auto), aggregate by time periods
|
||||||
|
if (this.heartbeatBarRange && this.heartbeatBarRange !== "auto") {
|
||||||
|
return this.aggregatedBeatList;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Original logic for short time ranges
|
||||||
let placeholders = [];
|
let placeholders = [];
|
||||||
|
|
||||||
let start = this.beatList.length - this.maxBeat;
|
let start = this.beatList.length - this.maxBeat;
|
||||||
|
@ -117,6 +128,101 @@ export default {
|
||||||
return placeholders.concat(this.beatList.slice(start));
|
return placeholders.concat(this.beatList.slice(start));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
aggregatedBeatList() {
|
||||||
|
if (!this.beatList || !this.heartbeatBarRange || this.heartbeatBarRange === "auto") {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const now = dayjs();
|
||||||
|
const buckets = [];
|
||||||
|
|
||||||
|
// Parse the range to get total time and determine bucket size
|
||||||
|
let totalHours;
|
||||||
|
let bucketSize; // in hours
|
||||||
|
let totalBuckets = this.maxBeat || 50; // Use maxBeat to determine bucket count
|
||||||
|
|
||||||
|
if (this.heartbeatBarRange.endsWith("h")) {
|
||||||
|
totalHours = parseInt(this.heartbeatBarRange);
|
||||||
|
} else if (this.heartbeatBarRange.endsWith("d")) {
|
||||||
|
const days = parseInt(this.heartbeatBarRange);
|
||||||
|
totalHours = days * 24;
|
||||||
|
} else {
|
||||||
|
// Fallback
|
||||||
|
totalHours = 90 * 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate bucket size to fit the desired number of buckets
|
||||||
|
bucketSize = totalHours / totalBuckets;
|
||||||
|
|
||||||
|
// Create time buckets from oldest to newest
|
||||||
|
const startTime = now.subtract(totalHours, "hours");
|
||||||
|
|
||||||
|
for (let i = 0; i < totalBuckets; i++) {
|
||||||
|
let bucketStart;
|
||||||
|
let bucketEnd;
|
||||||
|
if (bucketSize < 1) {
|
||||||
|
// Handle sub-hour buckets (minutes)
|
||||||
|
const minutes = bucketSize * 60;
|
||||||
|
bucketStart = startTime.add(i * minutes, "minutes");
|
||||||
|
bucketEnd = bucketStart.add(minutes, "minutes");
|
||||||
|
} else {
|
||||||
|
// Handle hour+ buckets
|
||||||
|
bucketStart = startTime.add(i * bucketSize, "hours");
|
||||||
|
bucketEnd = bucketStart.add(bucketSize, "hours");
|
||||||
|
}
|
||||||
|
|
||||||
|
buckets.push({
|
||||||
|
start: bucketStart,
|
||||||
|
end: bucketEnd,
|
||||||
|
beats: [],
|
||||||
|
status: 1, // default to up
|
||||||
|
time: bucketEnd.toISOString()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Group heartbeats into buckets
|
||||||
|
this.beatList.forEach(beat => {
|
||||||
|
const beatTime = dayjs.utc(beat.time).local();
|
||||||
|
const bucket = buckets.find(b =>
|
||||||
|
(beatTime.isAfter(b.start) || beatTime.isSame(b.start)) &&
|
||||||
|
(beatTime.isBefore(b.end) || beatTime.isSame(b.end))
|
||||||
|
);
|
||||||
|
if (bucket) {
|
||||||
|
bucket.beats.push(beat);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Calculate status for each bucket
|
||||||
|
buckets.forEach(bucket => {
|
||||||
|
if (bucket.beats.length === 0) {
|
||||||
|
bucket.status = null; // no data - will be rendered as empty/grey
|
||||||
|
bucket.time = bucket.end.toISOString();
|
||||||
|
} else {
|
||||||
|
// If any beat is down, bucket is down
|
||||||
|
// If any beat is maintenance, bucket is maintenance
|
||||||
|
// Otherwise bucket is up
|
||||||
|
const hasDown = bucket.beats.some(b => b.status === 0);
|
||||||
|
const hasMaintenance = bucket.beats.some(b => b.status === 3);
|
||||||
|
|
||||||
|
if (hasDown) {
|
||||||
|
bucket.status = 0;
|
||||||
|
} else if (hasMaintenance) {
|
||||||
|
bucket.status = 3;
|
||||||
|
} else {
|
||||||
|
bucket.status = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the latest beat time in the bucket
|
||||||
|
const latestBeat = bucket.beats.reduce((latest, beat) =>
|
||||||
|
dayjs(beat.time).isAfter(dayjs(latest.time)) ? beat : latest
|
||||||
|
);
|
||||||
|
bucket.time = latestBeat.time;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return buckets;
|
||||||
|
},
|
||||||
|
|
||||||
wrapStyle() {
|
wrapStyle() {
|
||||||
let topBottom = (((this.beatHeight * this.hoverScale) - this.beatHeight) / 2);
|
let topBottom = (((this.beatHeight * this.hoverScale) - this.beatHeight) / 2);
|
||||||
let leftRight = (((this.beatWidth * this.hoverScale) - this.beatWidth) / 2);
|
let leftRight = (((this.beatWidth * this.hoverScale) - this.beatWidth) / 2);
|
||||||
|
@ -162,6 +268,14 @@ export default {
|
||||||
* @returns {object} The style object containing the CSS properties for positioning the time element.
|
* @returns {object} The style object containing the CSS properties for positioning the time element.
|
||||||
*/
|
*/
|
||||||
timeStyle() {
|
timeStyle() {
|
||||||
|
// For aggregated mode, don't use padding-based positioning
|
||||||
|
if (this.heartbeatBarRange && this.heartbeatBarRange !== "auto") {
|
||||||
|
return {
|
||||||
|
"margin-left": "0px",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Original logic for auto mode
|
||||||
return {
|
return {
|
||||||
"margin-left": this.numPadding * (this.beatWidth + this.beatHoverAreaPadding * 2) + "px",
|
"margin-left": this.numPadding * (this.beatWidth + this.beatHoverAreaPadding * 2) + "px",
|
||||||
};
|
};
|
||||||
|
@ -172,6 +286,22 @@ export default {
|
||||||
* @returns {string} The time elapsed in minutes or hours.
|
* @returns {string} The time elapsed in minutes or hours.
|
||||||
*/
|
*/
|
||||||
timeSinceFirstBeat() {
|
timeSinceFirstBeat() {
|
||||||
|
// For aggregated beats, calculate from the configured range
|
||||||
|
if (this.heartbeatBarRange && this.heartbeatBarRange !== "auto") {
|
||||||
|
if (this.heartbeatBarRange.endsWith("h")) {
|
||||||
|
const hours = parseInt(this.heartbeatBarRange);
|
||||||
|
return hours + "h";
|
||||||
|
} else if (this.heartbeatBarRange.endsWith("d")) {
|
||||||
|
const days = parseInt(this.heartbeatBarRange);
|
||||||
|
if (days < 2) {
|
||||||
|
return (days * 24) + "h";
|
||||||
|
} else {
|
||||||
|
return days + "d";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Original logic for auto mode
|
||||||
const firstValidBeat = this.shortBeatList.at(this.numPadding);
|
const firstValidBeat = this.shortBeatList.at(this.numPadding);
|
||||||
const minutes = dayjs().diff(dayjs.utc(firstValidBeat?.time), "minutes");
|
const minutes = dayjs().diff(dayjs.utc(firstValidBeat?.time), "minutes");
|
||||||
if (minutes > 60) {
|
if (minutes > 60) {
|
||||||
|
@ -267,6 +397,18 @@ export default {
|
||||||
* @returns {string} Beat title
|
* @returns {string} Beat title
|
||||||
*/
|
*/
|
||||||
getBeatTitle(beat) {
|
getBeatTitle(beat) {
|
||||||
|
if (beat === 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// For aggregated beats, show time range and status
|
||||||
|
if (beat.beats !== undefined && this.heartbeatBarRange && this.heartbeatBarRange !== "auto") {
|
||||||
|
const start = this.$root.datetime(beat.start);
|
||||||
|
const end = this.$root.datetime(beat.end);
|
||||||
|
const statusText = beat.status === 1 ? "Up" : beat.status === 0 ? "Down" : beat.status === 3 ? "Maintenance" : "No Data";
|
||||||
|
return `${start} - ${end}: ${statusText} (${beat.beats.length} checks)`;
|
||||||
|
}
|
||||||
|
|
||||||
return `${this.$root.datetime(beat.time)}` + ((beat.msg) ? ` - ${beat.msg}` : "");
|
return `${this.$root.datetime(beat.time)}` + ((beat.msg) ? ` - ${beat.msg}` : "");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div :key="$root.userHeartbeatBar" class="col-6">
|
<div :key="$root.userHeartbeatBar" class="col-6">
|
||||||
<HeartbeatBar size="mid" :monitor-id="monitor.element.id" />
|
<HeartbeatBar size="mid" :monitor-id="monitor.element.id" :heartbeat-bar-range="heartbeatBarRange" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -114,6 +114,11 @@ export default {
|
||||||
/** Should expiry be shown? */
|
/** Should expiry be shown? */
|
||||||
showCertificateExpiry: {
|
showCertificateExpiry: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
},
|
||||||
|
/** Heartbeat bar range */
|
||||||
|
heartbeatBarRange: {
|
||||||
|
type: String,
|
||||||
|
default: "auto",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
|
|
@ -376,13 +376,16 @@
|
||||||
"Refresh Interval": "Refresh Interval",
|
"Refresh Interval": "Refresh Interval",
|
||||||
"Refresh Interval Description": "The status page will do a full site refresh every {0} seconds",
|
"Refresh Interval Description": "The status page will do a full site refresh every {0} seconds",
|
||||||
"Heartbeat Bar Range": "Heartbeat Bar Range",
|
"Heartbeat Bar Range": "Heartbeat Bar Range",
|
||||||
|
"6 hours": "6 hours",
|
||||||
|
"12 hours": "12 hours",
|
||||||
|
"24 hours": "24 hours",
|
||||||
"7 days": "7 days",
|
"7 days": "7 days",
|
||||||
"30 days": "30 days",
|
"30 days": "30 days",
|
||||||
"60 days": "60 days",
|
"60 days": "60 days",
|
||||||
"90 days": "90 days",
|
"90 days": "90 days",
|
||||||
"180 days": "180 days",
|
"180 days": "180 days",
|
||||||
"365 days": "365 days",
|
"365 days": "365 days",
|
||||||
"How many days of heartbeat history to show in the status page": "How many days of heartbeat history to show in the status page",
|
"How much heartbeat history to show in the status page": "How much heartbeat history to show in the status page",
|
||||||
"Show Powered By": "Show Powered By",
|
"Show Powered By": "Show Powered By",
|
||||||
"Domain Names": "Domain Names",
|
"Domain Names": "Domain Names",
|
||||||
"signedInDisp": "Signed in as {0}",
|
"signedInDisp": "Signed in as {0}",
|
||||||
|
|
|
@ -44,16 +44,20 @@
|
||||||
|
|
||||||
<div class="my-3">
|
<div class="my-3">
|
||||||
<label for="heartbeat-bar-range" class="form-label">{{ $t("Heartbeat Bar Range") }}</label>
|
<label for="heartbeat-bar-range" class="form-label">{{ $t("Heartbeat Bar Range") }}</label>
|
||||||
<select id="heartbeat-bar-range" v-model="config.heartbeatBarRangeDays" class="form-select" data-testid="heartbeat-bar-range-select">
|
<select id="heartbeat-bar-range" v-model="config.heartbeatBarRange" class="form-select" data-testid="heartbeat-bar-range-select">
|
||||||
<option value="7">{{ $t("7 days") }}</option>
|
<option value="auto">{{ $t("Auto") }}</option>
|
||||||
<option value="30">{{ $t("30 days") }}</option>
|
<option value="6h">{{ $t("6 hours") }}</option>
|
||||||
<option value="60">{{ $t("60 days") }}</option>
|
<option value="12h">{{ $t("12 hours") }}</option>
|
||||||
<option value="90">{{ $t("90 days") }}</option>
|
<option value="24h">{{ $t("24 hours") }}</option>
|
||||||
<option value="180">{{ $t("180 days") }}</option>
|
<option value="7d">{{ $t("7 days") }}</option>
|
||||||
<option value="365">{{ $t("365 days") }}</option>
|
<option value="30d">{{ $t("30 days") }}</option>
|
||||||
|
<option value="60d">{{ $t("60 days") }}</option>
|
||||||
|
<option value="90d">{{ $t("90 days") }}</option>
|
||||||
|
<option value="180d">{{ $t("180 days") }}</option>
|
||||||
|
<option value="365d">{{ $t("365 days") }}</option>
|
||||||
</select>
|
</select>
|
||||||
<div class="form-text">
|
<div class="form-text">
|
||||||
{{ $t("How many days of heartbeat history to show in the status page") }}
|
{{ $t("How much heartbeat history to show in the status page") }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -343,7 +347,7 @@
|
||||||
👀 {{ $t("statusPageNothing") }}
|
👀 {{ $t("statusPageNothing") }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<PublicGroupList :edit-mode="enableEditMode" :show-tags="config.showTags" :show-certificate-expiry="config.showCertificateExpiry" />
|
<PublicGroupList :edit-mode="enableEditMode" :show-tags="config.showTags" :show-certificate-expiry="config.showCertificateExpiry" :heartbeat-bar-range="config.heartbeatBarRange" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<footer class="mt-5 mb-4">
|
<footer class="mt-5 mb-4">
|
||||||
|
@ -715,24 +719,27 @@ export default {
|
||||||
this.slug = "default";
|
this.slug = "default";
|
||||||
}
|
}
|
||||||
|
|
||||||
this.getData().then((res) => {
|
Promise.all([
|
||||||
this.config = res.data.config;
|
this.getData(),
|
||||||
|
this.editMode ? Promise.resolve() : this.loadHeartbeatData()
|
||||||
|
]).then(([configRes]) => {
|
||||||
|
this.config = configRes.data.config;
|
||||||
|
|
||||||
if (!this.config.domainNameList) {
|
if (!this.config.domainNameList) {
|
||||||
this.config.domainNameList = [];
|
this.config.domainNameList = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.config.heartbeatBarRangeDays) {
|
if (!this.config.heartbeatBarRange) {
|
||||||
this.config.heartbeatBarRangeDays = 90;
|
this.config.heartbeatBarRange = "auto";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.config.icon) {
|
if (this.config.icon) {
|
||||||
this.imgDataUrl = this.config.icon;
|
this.imgDataUrl = this.config.icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.incident = res.data.incident;
|
this.incident = configRes.data.incident;
|
||||||
this.maintenanceList = res.data.maintenanceList;
|
this.maintenanceList = configRes.data.maintenanceList;
|
||||||
this.$root.publicGroupList = res.data.publicGroupList;
|
this.$root.publicGroupList = configRes.data.publicGroupList;
|
||||||
|
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
|
|
||||||
|
@ -749,8 +756,6 @@ export default {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.updateHeartbeatList();
|
|
||||||
|
|
||||||
// Go to edit page if ?edit present
|
// Go to edit page if ?edit present
|
||||||
// null means ?edit present, but no value
|
// null means ?edit present, but no value
|
||||||
if (this.$route.query.edit || this.$route.query.edit === null) {
|
if (this.$route.query.edit || this.$route.query.edit === null) {
|
||||||
|
@ -784,13 +789,11 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the heartbeat list and update favicon if necessary
|
* Load heartbeat data from API
|
||||||
* @returns {void}
|
* @returns {Promise} Promise that resolves when data is loaded
|
||||||
*/
|
*/
|
||||||
updateHeartbeatList() {
|
loadHeartbeatData() {
|
||||||
// If editMode, it will use the data from websocket.
|
return axios.get("/api/status-page/heartbeat/" + this.slug).then((res) => {
|
||||||
if (! this.editMode) {
|
|
||||||
axios.get("/api/status-page/heartbeat/" + this.slug).then((res) => {
|
|
||||||
const { heartbeatList, uptimeList } = res.data;
|
const { heartbeatList, uptimeList } = res.data;
|
||||||
|
|
||||||
this.$root.heartbeatList = heartbeatList;
|
this.$root.heartbeatList = heartbeatList;
|
||||||
|
@ -814,6 +817,16 @@ export default {
|
||||||
this.lastUpdateTime = dayjs();
|
this.lastUpdateTime = dayjs();
|
||||||
this.updateUpdateTimer();
|
this.updateUpdateTimer();
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the heartbeat list and update favicon if necessary
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
updateHeartbeatList() {
|
||||||
|
// If editMode, it will use the data from websocket.
|
||||||
|
if (! this.editMode) {
|
||||||
|
this.loadHeartbeatData();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue