]>
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 | } | |
88 | return this.pageStatus == "warn" | |
89 | ? "Partially Degraded Service" | |
90 | : "All Systems Operational"; | |
91 | }, | |
92 | uptime: function () { | |
93 | if (!this.heartbeat) { | |
94 | return 0; | |
95 | } | |
96 | const data = Object.values(this.heartbeat.uptimeList); | |
97 | const percent = data.reduce((a, b) => a + b, 0) / data.length || 0; | |
98 | return (percent * 100).toFixed(1); | |
99 | }, | |
100 | }, | |
101 | created() { | |
102 | this.item.url = `${this.item.url}/status/${this.dashboard}`; | |
103 | this.fetchStatus(); | |
104 | }, | |
105 | methods: { | |
106 | fetchStatus: function () { | |
107 | this.fetch(`/api/status-page/${this.dashboard}?cachebust=${Date.now()}`) | |
108 | .catch((e) => console.error(e)) | |
109 | .then((resp) => (this.incident = resp)); | |
110 | ||
111 | this.fetch(`/api/status-page/heartbeat/${this.dashboard}?cachebust=${Date.now()}`) | |
112 | .catch((e) => console.error(e)) | |
113 | .then((resp) => (this.heartbeat = resp)); | |
114 | }, | |
115 | }, | |
116 | }; | |
117 | </script> | |
118 | ||
119 | <style scoped lang="scss"> | |
120 | .status { | |
121 | font-size: 0.8rem; | |
122 | color: var(--text-title); | |
123 | ||
124 | &.good:before { | |
125 | background-color: #94e185; | |
126 | border-color: #78d965; | |
127 | box-shadow: 0 0 5px 1px #94e185; | |
128 | } | |
129 | ||
130 | &.warn:before { | |
131 | background-color: #f8a306; | |
132 | border-color: #e1b35e; | |
133 | box-shadow: 0 0 5px 1px #f8a306; | |
134 | } | |
135 | ||
136 | &.bad:before { | |
137 | background-color: #c9404d; | |
138 | border-color: #c42c3b; | |
139 | box-shadow: 0 0 5px 1px #c9404d; | |
140 | } | |
141 | ||
142 | &:before { | |
143 | content: " "; | |
144 | display: inline-block; | |
145 | width: 7px; | |
146 | height: 7px; | |
147 | margin-right: 10px; | |
148 | border: 1px solid #000; | |
149 | border-radius: 7px; | |
150 | } | |
151 | } | |
152 | </style> |