diff options
-rw-r--r-- | docs/customservices.md | 12 | ||||
-rw-r--r-- | src/components/services/Immich.vue | 126 |
2 files changed, 138 insertions, 0 deletions
diff --git a/docs/customservices.md b/docs/customservices.md index 665c6f5..ca88d85 100644 --- a/docs/customservices.md +++ b/docs/customservices.md | |||
@@ -33,6 +33,7 @@ within Homer: | |||
33 | - [SABnzbd](#sabnzbd) | 33 | - [SABnzbd](#sabnzbd) |
34 | - [OctoPrint](#octoprint) | 34 | - [OctoPrint](#octoprint) |
35 | - [Tdarr](#tdarr) | 35 | - [Tdarr](#tdarr) |
36 | - [Immich](#immich) | ||
36 | 37 | ||
37 | If you experiencing any issue, please have a look to the [troubleshooting](troubleshooting.md) page. | 38 | If you experiencing any issue, please have a look to the [troubleshooting](troubleshooting.md) page. |
38 | 39 | ||
@@ -411,3 +412,14 @@ for transcoding on your Tdarr instance as well as the number of errored items. | |||
411 | type: "Tdarr" | 412 | type: "Tdarr" |
412 | checkInterval: 5000 # (Optional) Interval (in ms) for updating the queue & error counts | 413 | checkInterval: 5000 # (Optional) Interval (in ms) for updating the queue & error counts |
413 | ``` | 414 | ``` |
415 | |||
416 | ## Immich | ||
417 | |||
418 | The Immich service displays stats from your Immich server. | ||
419 | |||
420 | ```yaml | ||
421 | - name: "Immich" | ||
422 | type: "Immich" | ||
423 | apikey: "<--- Your api key --->" # administrator user | ||
424 | updateInterval: 5000 # (Optional) Interval (in ms) for updating the stats | ||
425 | ``` \ No newline at end of file | ||
diff --git a/src/components/services/Immich.vue b/src/components/services/Immich.vue new file mode 100644 index 0000000..e86ecd6 --- /dev/null +++ b/src/components/services/Immich.vue | |||
@@ -0,0 +1,126 @@ | |||
1 | <template> | ||
2 | <Generic :item="item"> | ||
3 | <template #indicator> | ||
4 | <div class="notifs"> | ||
5 | <strong v-if="users > 0" class="notif users" title="Users"> | ||
6 | {{ users }} | ||
7 | </strong> | ||
8 | <strong v-if="photos > 0" class="notif photos" title="Photos"> | ||
9 | {{ photos }} | ||
10 | </strong> | ||
11 | <strong v-if="videos > 0" class="notif videos" title="Videos"> | ||
12 | {{ videos }} | ||
13 | </strong> | ||
14 | <strong v-if="usage > 0" class="notif usage" title="Usage"> | ||
15 | {{ humanizeSize }} | ||
16 | </strong> | ||
17 | <strong | ||
18 | v-if="serverError" | ||
19 | class="notif errors" | ||
20 | title="Connection error to Immich API, check your url and apikey in config.yml" | ||
21 | >?</strong | ||
22 | > | ||
23 | </div> | ||
24 | </template> | ||
25 | </Generic> | ||
26 | </template> | ||
27 | |||
28 | <script> | ||
29 | import service from "@/mixins/service.js"; | ||
30 | import Generic from "./Generic.vue"; | ||
31 | |||
32 | export default { | ||
33 | name: "Immich", | ||
34 | mixins: [service], | ||
35 | props: { | ||
36 | item: Object, | ||
37 | }, | ||
38 | components: { | ||
39 | Generic, | ||
40 | }, | ||
41 | data: () => { | ||
42 | return { | ||
43 | users: null, | ||
44 | photos: null, | ||
45 | videos: null, | ||
46 | usage: null, | ||
47 | serverError: false, | ||
48 | }; | ||
49 | }, | ||
50 | created: function () { | ||
51 | const updateInterval = parseInt(this.item.updateInterval, 10) || 0; | ||
52 | if (updateInterval > 0) { | ||
53 | setInterval(() => this.fetchConfig(), updateInterval); | ||
54 | } | ||
55 | this.fetchConfig(); | ||
56 | }, | ||
57 | computed: { | ||
58 | humanizeSize: function () { | ||
59 | let bytes = this.usage; | ||
60 | if (Math.abs(bytes) < 1024) | ||
61 | return bytes + ' B'; | ||
62 | |||
63 | const units = ['KiB', 'MiB', 'GiB', 'TiB']; | ||
64 | let u = -1; | ||
65 | do { | ||
66 | bytes /= 1024; | ||
67 | ++u; | ||
68 | } while (Math.round(Math.abs(bytes) * 100) / 100 >= 1024 && u < units.length - 1); | ||
69 | |||
70 | return bytes.toFixed(2) + ' ' + units[u]; | ||
71 | }, | ||
72 | }, | ||
73 | methods: { | ||
74 | fetchConfig: function () { | ||
75 | const headers = { | ||
76 | "x-api-key": this.item.apikey, | ||
77 | }; | ||
78 | |||
79 | this.fetch(`/api/server-info/stats`, { headers }) | ||
80 | .then((stats) => { | ||
81 | this.photos = stats.photos; | ||
82 | this.videos = stats.videos; | ||
83 | this.usage = stats.usage; | ||
84 | this.users = stats.usageByUser.length; | ||
85 | }) | ||
86 | .catch((e) => { | ||
87 | console.error(e); | ||
88 | this.serverError = true; | ||
89 | }); | ||
90 | }, | ||
91 | }, | ||
92 | }; | ||
93 | </script> | ||
94 | |||
95 | <style scoped lang="scss"> | ||
96 | .notifs { | ||
97 | position: absolute; | ||
98 | color: white; | ||
99 | font-family: sans-serif; | ||
100 | top: 0.3em; | ||
101 | right: 0.5em; | ||
102 | .notif { | ||
103 | display: inline-block; | ||
104 | padding: 0.2em 0.35em; | ||
105 | border-radius: 0.25em; | ||
106 | position: relative; | ||
107 | margin-left: 0.3em; | ||
108 | font-size: 0.8em; | ||
109 | &.photos { | ||
110 | background-color: #4fb5d6; | ||
111 | } | ||
112 | |||
113 | &.videos { | ||
114 | background-color: #d08d2e; | ||
115 | } | ||
116 | |||
117 | &.usage { | ||
118 | background-color: #e51111; | ||
119 | } | ||
120 | |||
121 | &.users { | ||
122 | background-color: #8dd475; | ||
123 | } | ||
124 | } | ||
125 | } | ||
126 | </style> \ No newline at end of file | ||