Add UptimeKuma Service component (#414)

*  Add UptimeKuma Service component

* 📝 Add custom services documentation

* Change await to fetch and use new API

*  Tri State logic from Uptime Kuma

* 📝 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>
pull/428/head^2
Adyanth H 2022-04-20 18:13:55 +05:30 committed by GitHub
parent 9c370d3c5e
commit 847d1ba3e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 167 additions and 0 deletions

View File

@ -179,3 +179,18 @@ You need to set the type to Emby, provide an api key and choose which stats to s
apikey: "MY-SUPER-SECRET-API-KEY"
libraryType: "music" #Choose which stats to show. Can be one of: music, series or movies.
```
## Uptime Kuma
Using the Uptime Kuma service you can display info about your instance uptime right on your Homer dashboard.
The 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).
```yaml
- name: "Uptime Kuma"
logo: "assets/tools/sample.png"
# subtitle: "A fancy self-hosted monitoring tool" # optional, if no subtitle is defined, Uptime Kuma incidents, if any, will be shown
url: "http://192.168.0.151:3001"
slug: "myCustomDashboard" # Defaults to "default" if not provided.
type: "UptimeKuma"
```

View File

@ -0,0 +1,152 @@
<template>
<Generic :item="item">
<template #content>
<p class="title is-4">{{ item.name }}</p>
<p class="subtitle is-6">
<template v-if="item.subtitle">
{{ item.subtitle }}
</template>
<template v-else-if="status">
{{ statusMessage }}
</template>
</p>
</template>
<template #indicator>
<div v-if="status" class="status" :class="status">
{{ uptime }}&percnt;
</div>
</template>
</Generic>
</template>
<script>
import service from "@/mixins/service.js";
import Generic from "./Generic.vue";
export default {
name: "UptimeKuma",
mixins: [service],
props: {
item: Object,
},
components: {
Generic,
},
data: () => ({
incident: null,
heartbeat: null,
}),
computed: {
dashboard: function () {
return this.item.slug ? this.item.slug : "default";
},
status: function () {
if (!this.incident) {
return "";
}
return this.incident.incident == null ? this.pageStatus : "bad";
},
lastHeartBeatList: function () {
let result = {};
for (let id in this.heartbeat.heartbeatList) {
let index = this.heartbeat.heartbeatList[id].length - 1;
result[id] = this.heartbeat.heartbeatList[id][index];
}
return result;
},
pageStatus: function () {
if (!this.heartbeat) {
return "";
}
if (Object.keys(this.heartbeat.heartbeatList).length === 0) {
return "";
}
let result = "good";
let hasUp = false;
for (let id in this.lastHeartBeatList) {
let beat = this.lastHeartBeatList[id];
if (beat.status == 1) {
hasUp = true;
} else {
result = "warn";
}
}
if (!hasUp) {
result = "bad";
}
return result;
},
statusMessage: function () {
if (!this.incident) {
return "";
}
if (this.incident.incident) {
return this.incident.incident.title;
}
return this.pageStatus == "warn"
? "Partially Degraded Service"
: "All Systems Operational";
},
uptime: function () {
if (!this.heartbeat) {
return 0;
}
const data = Object.values(this.heartbeat.uptimeList);
const percent = data.reduce((a, b) => a + b, 0) / data.length || 0;
return (percent * 100).toFixed(1);
},
},
created() {
this.item.url = `${this.item.url}/status/${this.dashboard}`;
this.fetchStatus();
},
methods: {
fetchStatus: function () {
this.fetch(`/api/status-page/${this.dashboard}?cachebust=${Date.now()}`)
.catch((e) => console.error(e))
.then((resp) => (this.incident = resp));
this.fetch(`/api/status-page/heartbeat/${this.dashboard}?cachebust=${Date.now()}`)
.catch((e) => console.error(e))
.then((resp) => (this.heartbeat = resp));
},
},
};
</script>
<style scoped lang="scss">
.status {
font-size: 0.8rem;
color: var(--text-title);
&.good:before {
background-color: #94e185;
border-color: #78d965;
box-shadow: 0 0 5px 1px #94e185;
}
&.warn:before {
background-color: #f8a306;
border-color: #e1b35e;
box-shadow: 0 0 5px 1px #f8a306;
}
&.bad:before {
background-color: #c9404d;
border-color: #c42c3b;
box-shadow: 0 0 5px 1px #c9404d;
}
&:before {
content: " ";
display: inline-block;
width: 7px;
height: 7px;
margin-right: 10px;
border: 1px solid #000;
border-radius: 7px;
}
}
</style>