]> git.immae.eu Git - github/bastienwirtz/homer.git/blob - src/components/services/UptimeKuma.vue
Adds total count for VMs.
[github/bastienwirtz/homer.git] / src / components / services / UptimeKuma.vue
1 <template>
2 <Generic :item="item">
3 <template #content>
4 <p class="title is-4">{{ item.name }}</p>
5 <p class="subtitle is-6">
6 <template v-if="item.subtitle">
7 {{ item.subtitle }}
8 </template>
9 <template v-else-if="status">
10 {{ statusMessage }}
11 </template>
12 </p>
13 </template>
14 <template #indicator>
15 <div v-if="status" class="status" :class="status">
16 {{ uptime }}&percnt;
17 </div>
18 </template>
19 </Generic>
20 </template>
21
22 <script>
23 import service from "@/mixins/service.js";
24 import Generic from "./Generic.vue";
25
26 export default {
27 name: "UptimeKuma",
28 mixins: [service],
29 props: {
30 item: Object,
31 },
32 components: {
33 Generic,
34 },
35 data: () => ({
36 incident: null,
37 heartbeat: null,
38 }),
39 computed: {
40 dashboard: function () {
41 return this.item.slug ? this.item.slug : "default";
42 },
43 status: function () {
44 if (!this.incident) {
45 return "";
46 }
47 return this.incident.incident == null ? this.pageStatus : "bad";
48 },
49 lastHeartBeatList: function () {
50 let result = {};
51
52 for (let id in this.heartbeat.heartbeatList) {
53 let index = this.heartbeat.heartbeatList[id].length - 1;
54 result[id] = this.heartbeat.heartbeatList[id][index];
55 }
56
57 return result;
58 },
59 pageStatus: function () {
60 if (!this.heartbeat) {
61 return "";
62 }
63 if (Object.keys(this.heartbeat.heartbeatList).length === 0) {
64 return "";
65 }
66 let result = "good";
67 let hasUp = false;
68 for (let id in this.lastHeartBeatList) {
69 let beat = this.lastHeartBeatList[id];
70 if (beat.status == 1) {
71 hasUp = true;
72 } else {
73 result = "warn";
74 }
75 }
76 if (!hasUp) {
77 result = "bad";
78 }
79 return result;
80 },
81 statusMessage: function () {
82 if (!this.incident) {
83 return "";
84 }
85 if (this.incident.incident) {
86 return this.incident.incident.title;
87 }
88
89 let message = "";
90 switch (this.pageStatus) {
91 case "good":
92 message = "All Systems Operational";
93 break;
94 case "warn":
95 message = "Partially Degraded Service";
96 break;
97 case "bad":
98 message = "Degraded Service";
99 break;
100 default:
101 message = "Unknown service status";
102 }
103 return message;
104 },
105 uptime: function () {
106 if (!this.heartbeat) {
107 return 0;
108 }
109 const data = Object.values(this.heartbeat.uptimeList);
110 const percent = data.reduce((a, b) => a + b, 0) / data.length || 0;
111 return (percent * 100).toFixed(1);
112 },
113 },
114 created() {
115 /* eslint-disable */
116 this.item.url = `${this.item.url}/status/${this.dashboard}`;
117 this.fetchStatus();
118 },
119 methods: {
120 fetchStatus: function () {
121 const now = Date.now()
122 this.fetch(`/api/status-page/${this.dashboard}?cachebust=${now}`)
123 .catch((e) => console.error(e))
124 .then((resp) => (this.incident = resp));
125
126 this.fetch(
127 `/api/status-page/heartbeat/${this.dashboard}?cachebust=${now}`
128 )
129 .catch((e) => console.error(e))
130 .then((resp) => (this.heartbeat = resp));
131 },
132 },
133 };
134 </script>
135
136 <style scoped lang="scss">
137 .status {
138 font-size: 0.8rem;
139 color: var(--text-title);
140
141 &.good:before {
142 background-color: #94e185;
143 border-color: #78d965;
144 box-shadow: 0 0 5px 1px #94e185;
145 }
146
147 &.warn:before {
148 background-color: #f8a306;
149 border-color: #e1b35e;
150 box-shadow: 0 0 5px 1px #f8a306;
151 }
152
153 &.bad:before {
154 background-color: #c9404d;
155 border-color: #c42c3b;
156 box-shadow: 0 0 5px 1px #c9404d;
157 }
158
159 &:before {
160 content: " ";
161 display: inline-block;
162 width: 7px;
163 height: 7px;
164 margin-right: 10px;
165 border: 1px solid #000;
166 border-radius: 7px;
167 }
168 }
169 </style>