Merge 1fdeea0c36
into 9f2cf28a76
This commit is contained in:
commit
470a1723e7
|
@ -78,7 +78,9 @@
|
|||
"tar": "~6.2.1",
|
||||
"tcp-ping": "~0.1.1",
|
||||
"thirty-two": "~1.0.2",
|
||||
"tippy.js": "^6.3.7",
|
||||
"tough-cookie": "~4.1.3",
|
||||
"vue3-calendar-heatmap": "^2.0.5",
|
||||
"ws": "^8.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -3083,7 +3085,6 @@
|
|||
"version": "2.10.2",
|
||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.10.2.tgz",
|
||||
"integrity": "sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ==",
|
||||
"dev": true,
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/popperjs"
|
||||
|
@ -13535,6 +13536,14 @@
|
|||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/tippy.js": {
|
||||
"version": "6.3.7",
|
||||
"resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz",
|
||||
"integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==",
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
|
@ -14393,6 +14402,18 @@
|
|||
"vue": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/vue3-calendar-heatmap": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/vue3-calendar-heatmap/-/vue3-calendar-heatmap-2.0.5.tgz",
|
||||
"integrity": "sha512-qvveNQlTS5Aw7AvRLs0zOyu3uP5iGJlXJAnkrkG2ElDdyQ8H1TJhQ8rL702CROjAg16ezIveUY10nCO7lqZ25w==",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"tippy.js": "^6.3.7",
|
||||
"vue": "^3.2.29"
|
||||
}
|
||||
},
|
||||
"node_modules/vuedraggable": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-4.1.0.tgz",
|
||||
|
|
|
@ -143,7 +143,9 @@
|
|||
"tar": "~6.2.1",
|
||||
"tcp-ping": "~0.1.1",
|
||||
"thirty-two": "~1.0.2",
|
||||
"tippy.js": "^6.3.7",
|
||||
"tough-cookie": "~4.1.3",
|
||||
"vue3-calendar-heatmap": "^2.0.5",
|
||||
"ws": "^8.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -76,20 +76,32 @@ router.get("/api/status-page/heartbeat/:slug", cache("1 minutes"), async (reques
|
|||
]);
|
||||
|
||||
for (let monitorID of monitorIDList) {
|
||||
// Calculating the percentage of uptime per day with the status count to show full year data
|
||||
let list = await R.getAll(`
|
||||
SELECT * FROM heartbeat
|
||||
SELECT
|
||||
strftime('%Y-%m-%d', time) AS day,
|
||||
(COUNT(CASE WHEN status = 1 THEN 1 END) * 100.0) / COUNT(status) AS percentage,
|
||||
(
|
||||
SELECT status
|
||||
FROM heartbeat AS sub
|
||||
WHERE strftime('%Y-%m-%d', sub.time) = strftime('%Y-%m-%d', main.time)
|
||||
GROUP BY status
|
||||
ORDER BY COUNT(*) DESC
|
||||
LIMIT 1
|
||||
) as status
|
||||
FROM heartbeat as main
|
||||
WHERE monitor_id = ?
|
||||
ORDER BY time DESC
|
||||
LIMIT 50
|
||||
GROUP BY day
|
||||
ORDER BY day DESC
|
||||
LIMIT 365
|
||||
`, [
|
||||
monitorID,
|
||||
]);
|
||||
|
||||
list = R.convertToBeans("heartbeat", list);
|
||||
heartbeatList[monitorID] = list.reverse().map(row => row.toPublicJSON());
|
||||
heartbeatList[monitorID] = list;
|
||||
|
||||
const uptimeCalculator = await UptimeCalculator.getUptimeCalculator(monitorID);
|
||||
uptimeList[`${monitorID}_24`] = uptimeCalculator.get24Hour().uptime;
|
||||
uptimeList[`${monitorID}_1y`] = uptimeCalculator.get1Year().uptime;
|
||||
}
|
||||
|
||||
response.json({
|
||||
|
|
|
@ -162,6 +162,16 @@ optgroup {
|
|||
background-color: #161B22;
|
||||
}
|
||||
|
||||
[data-tippy-root] {
|
||||
color: #333;
|
||||
font-size: small;
|
||||
font-weight: 600;
|
||||
background-color: #fff;
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
box-shadow: 2px 2px 2px #333;
|
||||
}
|
||||
|
||||
.btn-outline-normal {
|
||||
padding: 4px 10px;
|
||||
border: 1px solid #ced4da;
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
<template>
|
||||
<div ref="wrap">
|
||||
<div class="hp-bar-big">
|
||||
<CalendarHeatmap
|
||||
:style="{ fill: '#fff', fontSize: 'x-small' }"
|
||||
class="heatmap" :values="values" :end-date="endDate" no-data-text="Unknown" tooltip-unit="%"
|
||||
:range-color="['#ebedf0', '#C3D4CB', '#9ABAA7', '#72A182', '#49875E', '#216E39']" :max="100"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import dayjs from "dayjs";
|
||||
import { CalendarHeatmap } from "vue3-calendar-heatmap";
|
||||
|
||||
export default {
|
||||
components: { CalendarHeatmap },
|
||||
props: {
|
||||
/** ID of the monitor */
|
||||
monitorId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
// Getting the values in form of percentage
|
||||
values() {
|
||||
const data = this.$root.heartbeatList[this.monitorId]?.map(({ day, percentage }) => ({ date: day,
|
||||
count: percentage.toFixed(1) }));
|
||||
return data || [];
|
||||
},
|
||||
|
||||
endDate() {
|
||||
const date = dayjs().format("YYYY-MM-DD");
|
||||
return date;
|
||||
},
|
||||
},
|
||||
unmounted() {
|
||||
window.removeEventListener("resize", this.resize);
|
||||
},
|
||||
beforeMount() {
|
||||
if (this.heartbeatList === null) {
|
||||
if (!(this.monitorId in this.$root.heartbeatList)) {
|
||||
this.$root.heartbeatList[this.monitorId] = [];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
window.addEventListener("resize", this.resize);
|
||||
this.resize();
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Resize the heartbeat bar
|
||||
* @returns {void}
|
||||
*/
|
||||
resize() {
|
||||
if (this.$refs.wrap) {
|
||||
this.maxBeat = Math.floor(this.$refs.wrap.clientWidth / (this.beatWidth + this.beatMargin * 2));
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "../assets/vars.scss";
|
||||
|
||||
// This naming is an internal name for the package vue3-calendar-heatmap and it cannot be modified to kebab-case
|
||||
/* stylelint-disable */
|
||||
.vch__legend {
|
||||
display: inline-flex;
|
||||
padding: 0.25rem 0.5rem;
|
||||
gap: 1ch;
|
||||
align-items: center;
|
||||
}
|
||||
/* stylelint-enable */
|
||||
</style>
|
|
@ -33,12 +33,12 @@
|
|||
<template #item="monitor">
|
||||
<div class="item">
|
||||
<div class="row">
|
||||
<div class="col-9 col-md-8 small-padding">
|
||||
<div class="col-3 col-md-4 small-padding">
|
||||
<div class="info">
|
||||
<font-awesome-icon v-if="editMode" icon="arrows-alt-v" class="action drag me-3" />
|
||||
<font-awesome-icon v-if="editMode" icon="times" class="action remove me-3" @click="removeMonitor(group.index, monitor.index)" />
|
||||
|
||||
<Uptime :monitor="monitor.element" type="24" :pill="true" />
|
||||
<Uptime style="vertical-align: top;" :monitor="monitor.element" type="1y" :pill="true" />
|
||||
<a
|
||||
v-if="showLink(monitor)"
|
||||
:href="monitor.element.url"
|
||||
|
@ -48,7 +48,7 @@
|
|||
>
|
||||
{{ monitor.element.name }}
|
||||
</a>
|
||||
<p v-else class="item-name"> {{ monitor.element.name }} </p>
|
||||
<p v-else class="item-name" style="white-space: initial;"> {{ monitor.element.name }} </p>
|
||||
|
||||
<span
|
||||
title="Setting"
|
||||
|
@ -70,8 +70,8 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div :key="$root.userHeartbeatBar" class="col-3 col-md-4">
|
||||
<HeartbeatBar size="mid" :monitor-id="monitor.element.id" />
|
||||
<div :key="$root.userHeartbeatBar" class="col-9 col-md-8">
|
||||
<HeartbeatBarStatus :monitor-id="monitor.element.id" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -87,7 +87,7 @@
|
|||
<script>
|
||||
import MonitorSettingDialog from "./MonitorSettingDialog.vue";
|
||||
import Draggable from "vuedraggable";
|
||||
import HeartbeatBar from "./HeartbeatBar.vue";
|
||||
import HeartbeatBarStatus from "./HeartbeatBarStatus.vue";
|
||||
import Uptime from "./Uptime.vue";
|
||||
import Tag from "./Tag.vue";
|
||||
|
||||
|
@ -95,7 +95,7 @@ export default {
|
|||
components: {
|
||||
MonitorSettingDialog,
|
||||
Draggable,
|
||||
HeartbeatBar,
|
||||
HeartbeatBarStatus,
|
||||
Uptime,
|
||||
Tag,
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue