]>
Commit | Line | Data |
---|---|---|
847d1ba3 A |
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 }}% | |
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 | } | |
5418c629 BW |
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; | |
847d1ba3 A |
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() { | |
59994bfe | 115 | /* eslint-disable */ |
847d1ba3 A |
116 | this.item.url = `${this.item.url}/status/${this.dashboard}`; |
117 | this.fetchStatus(); | |
118 | }, | |
119 | methods: { | |
120 | fetchStatus: function () { | |
5418c629 BW |
121 | const now = Date.now() |
122 | this.fetch(`/api/status-page/${this.dashboard}?cachebust=${now}`) | |
847d1ba3 A |
123 | .catch((e) => console.error(e)) |
124 | .then((resp) => (this.incident = resp)); | |
125 | ||
95d73348 | 126 | this.fetch( |
5418c629 | 127 | `/api/status-page/heartbeat/${this.dashboard}?cachebust=${now}` |
95d73348 | 128 | ) |
847d1ba3 A |
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> |