aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAdyanth H <me@adyanth.dev>2022-04-20 18:13:55 +0530
committerGitHub <noreply@github.com>2022-04-20 08:43:55 -0400
commit847d1ba3e89b4a267c013126eaafa33a98ed9713 (patch)
tree52a3a82169c6d0b988c6d3f88c77f33cada0be67
parent9c370d3c5e25d1a5e3e04f6e146e35883e4ac2e3 (diff)
downloadhomer-847d1ba3e89b4a267c013126eaafa33a98ed9713.tar.gz
homer-847d1ba3e89b4a267c013126eaafa33a98ed9713.tar.zst
homer-847d1ba3e89b4a267c013126eaafa33a98ed9713.zip
Add UptimeKuma Service component (#414)
* :sparkles: Add UptimeKuma Service component * :memo: Add custom services documentation * Change await to fetch and use new API * :sparkles: Tri State logic from Uptime Kuma * :memo: Add and lint documentation * Remove erroneous logging Co-authored-by: Evan Steinkerchner <esteinkerchner@gmail.com> * Remove CORS warning Co-authored-by: Evan Steinkerchner <esteinkerchner@gmail.com> * Correct error level Co-authored-by: Evan Steinkerchner <esteinkerchner@gmail.com> * Correct error level Co-authored-by: Evan Steinkerchner <esteinkerchner@gmail.com> * Prevent caching of requests Co-authored-by: Evan Steinkerchner <esteinkerchner@gmail.com> * Prevent caching of requests Co-authored-by: Evan Steinkerchner <esteinkerchner@gmail.com> * Undo unrelated changes Co-authored-by: Evan Steinkerchner <esteinkerchner@gmail.com>
-rw-r--r--docs/customservices.md15
-rw-r--r--src/components/services/UptimeKuma.vue152
2 files changed, 167 insertions, 0 deletions
diff --git a/docs/customservices.md b/docs/customservices.md
index 509278f..709b16b 100644
--- a/docs/customservices.md
+++ b/docs/customservices.md
@@ -179,3 +179,18 @@ You need to set the type to Emby, provide an api key and choose which stats to s
179 apikey: "MY-SUPER-SECRET-API-KEY" 179 apikey: "MY-SUPER-SECRET-API-KEY"
180 libraryType: "music" #Choose which stats to show. Can be one of: music, series or movies. 180 libraryType: "music" #Choose which stats to show. Can be one of: music, series or movies.
181``` 181```
182
183## Uptime Kuma
184
185Using the Uptime Kuma service you can display info about your instance uptime right on your Homer dashboard.
186
187The following configuration is available for the UptimeKuma service. Needs v1.13.1 or later because of the change in APIs due to [multiple status pages support](https://github.com/louislam/uptime-kuma/releases/tag/1.13.1).
188
189```yaml
190- name: "Uptime Kuma"
191 logo: "assets/tools/sample.png"
192 # subtitle: "A fancy self-hosted monitoring tool" # optional, if no subtitle is defined, Uptime Kuma incidents, if any, will be shown
193 url: "http://192.168.0.151:3001"
194 slug: "myCustomDashboard" # Defaults to "default" if not provided.
195 type: "UptimeKuma"
196```
diff --git a/src/components/services/UptimeKuma.vue b/src/components/services/UptimeKuma.vue
new file mode 100644
index 0000000..5dd75f3
--- /dev/null
+++ b/src/components/services/UptimeKuma.vue
@@ -0,0 +1,152 @@
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>
23import service from "@/mixins/service.js";
24import Generic from "./Generic.vue";
25
26export 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>