From 50acb9957e81f75bb28747ad1434132c3c5cb752 Mon Sep 17 00:00:00 2001 From: Cees Bos Date: Wed, 19 Mar 2025 22:25:34 +0100 Subject: [PATCH 001/117] Add Linkding support --- docs/customservices.md | 22 +++++++++ src/components/services/Linkding.vue | 68 ++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 src/components/services/Linkding.vue diff --git a/docs/customservices.md b/docs/customservices.md index 7ddaaaa..8274546 100644 --- a/docs/customservices.md +++ b/docs/customservices.md @@ -25,6 +25,7 @@ within Homer: - [Immich](#immich) - [Jellystat](#jellystat) - [Lidarr, Prowlarr, Sonarr, Readarr and Radarr](#lidarr-prowlarr-sonarr-readarr-and-radarr) +- [Linkding](#linkding) - [Mealie](#mealie) - [Medusa](#medusa) - [Nextcloud](#nextcloud) @@ -276,6 +277,27 @@ If you are using an older version of Radarr or Sonarr which don't support the ne legacyApi: true ``` +## Linkding + +This integration makes it possible to query Linkding and list multiple results from Linkding. +Linkding has to be configured with CORS enabled. Linkding does not support that, but a reverse proxy in front can fix that. +For example if you use Traefik, documentation about that is here: https://doc.traefik.io/traefik/middlewares/http/headers/#cors-headers +Examples for various servers can be found at https://enable-cors.org/server.html. + +This integration supports at max 15 results from Linkding. But you can add it multiple times to you dashboard with different queries to retrieve what you need. + +```yaml + - name: "Linkding" + # Url to Linkding instance + url: https://ld.ceesbos.nl + token: "" + type: "Linkding" + # Maximum number of items returned by Linkding, minimal 1 and max 15 + limit: 10 + # query to do on Linkding. User #tagname to search for tags + query: "#ToDo #Homer" +``` + ## Mealie First off make sure to remove an existing `subtitle` as it will take precedence if set. diff --git a/src/components/services/Linkding.vue b/src/components/services/Linkding.vue new file mode 100644 index 0000000..840650a --- /dev/null +++ b/src/components/services/Linkding.vue @@ -0,0 +1,68 @@ + + + \ No newline at end of file From 37716c8d423aa8351423c5ab5f1d677c01f99ef3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20B=C3=A9langer?= <56379077+mbelangergit@users.noreply.github.com> Date: Wed, 19 Mar 2025 19:40:21 -0400 Subject: [PATCH 002/117] Fix typos in config-schema.json --- .schema/config-schema.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.schema/config-schema.json b/.schema/config-schema.json index eaea0b7..f751668 100644 --- a/.schema/config-schema.json +++ b/.schema/config-schema.json @@ -70,10 +70,10 @@ "properties": { "layout": { "enum": [ - "colums", + "columns", "list" ], - "description": "Layout of the dashboard, either 'column' or 'list'" + "description": "Layout of the dashboard, either 'columns' or 'list'" }, "colorTheme": { "enum": [ From e1fdb0069b67490553f99dfddb06dfb7bbc0f1d9 Mon Sep 17 00:00:00 2001 From: Cees Bos Date: Thu, 20 Mar 2025 18:27:59 +0100 Subject: [PATCH 003/117] Fix issues in Linkding integration revealed by code check in the pipeline --- src/components/services/Linkding.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/services/Linkding.vue b/src/components/services/Linkding.vue index 840650a..97aab9a 100644 --- a/src/components/services/Linkding.vue +++ b/src/components/services/Linkding.vue @@ -1,5 +1,5 @@ From 28ad80369ff4733d448cdf8bcb08010f3979b0f8 Mon Sep 17 00:00:00 2001 From: Molham Date: Sat, 19 Apr 2025 14:19:28 +0200 Subject: [PATCH 038/117] add support to dynamic interval time for polling the status --- docs/customservices.md | 3 ++- src/components/services/PiHole.vue | 8 ++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/customservices.md b/docs/customservices.md index fc6d318..ac77ba3 100644 --- a/docs/customservices.md +++ b/docs/customservices.md @@ -468,10 +468,11 @@ The following configuration is available for the PiHole service. - name: "Pi-hole" logo: "assets/tools/sample.png" # subtitle: "Network-wide Ad Blocking" # optional, if no subtitle is defined, PiHole statistics will be shown - url: "http://192.168.0.151/admin" + url: "http://192.168.0.151/admin" # For v6 API, do not include /admin in the URL apikey: "<---insert-api-key-here--->" # optional, needed if web interface is password protected type: "PiHole" apiVersion: 5 # optional, defaults to 5. Use 6 if your PiHole instance uses API v6 + checkInterval: 3000 # optional, defaults to 300000. interval in ms to check Pi-hole status ``` **Remarks:** diff --git a/src/components/services/PiHole.vue b/src/components/services/PiHole.vue index 004f382..9a20d42 100644 --- a/src/components/services/PiHole.vue +++ b/src/components/services/PiHole.vue @@ -68,8 +68,12 @@ export default { methods: { startStatusPolling: function () { this.fetchStatus(); - // Poll every 5 minutes - this.pollInterval = setInterval(this.fetchStatus, 300000); + // Set the interval to the checkInterval or default to 5 minutes + const interval = parseInt(this.item.checkInterval, 10) || 300000; + if (this.item.checkInterval < 1000) { + this.item.checkInterval = 1000; + } + this.pollInterval = setInterval(this.fetchStatus, interval); }, stopStatusPolling: function () { if (this.pollInterval) { From 4684b23a8c46a49c27960c00ee3b1f3583d1b63f Mon Sep 17 00:00:00 2001 From: Molham Date: Sat, 19 Apr 2025 14:46:18 +0200 Subject: [PATCH 039/117] better handle errors and set the subtitle as a message holder for errors --- src/components/services/PiHole.vue | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/components/services/PiHole.vue b/src/components/services/PiHole.vue index 9a20d42..a2b1ccf 100644 --- a/src/components/services/PiHole.vue +++ b/src/components/services/PiHole.vue @@ -42,7 +42,7 @@ export default { }), computed: { percentage: function () { - if (this.percent_blocked) { + if (typeof this.percent_blocked === 'number' && this.percent_blocked >= 0) { return this.percent_blocked.toFixed(1); } return ""; @@ -66,6 +66,11 @@ export default { } }, methods: { + handleError: function (error, status) { + console.error(error); + this.subtitle = error; + this.status = status; + }, startStatusPolling: function () { this.fetchStatus(); // Set the interval to the checkInterval or default to 5 minutes @@ -93,7 +98,7 @@ export default { } } } catch (e) { - console.error("Failed to load cached session:", e); + this.handleError(`Failed to load cached session: ${e}`, "error"); this.removeCacheSession(); } }, @@ -110,15 +115,14 @@ export default { method: 'DELETE' }); } catch (e) { - console.error("Failed to delete session:", e); + this.handleError(`Failed to delete session: ${e}`, "error"); } finally { this.removeCacheSession(); } }, authenticate: async function () { if (!this.item.apikey) { - console.error("API key is required for PiHole authentication"); - this.status = "disabled"; + this.handleError("API key is required for PiHole authentication", "disabled"); return false; } @@ -145,8 +149,7 @@ export default { } throw new Error("Invalid authentication response"); } catch (e) { - console.error("Authentication failed:", e); - this.status = "disabled"; + this.handleError(`Authentication failed: ${e}`, "disabled"); return false; } }, @@ -184,12 +187,11 @@ export default { throw new Error(`HTTP error: ${response.status}`); } } catch (e) { - console.error("Failed to fetch status:", e); - if (e.message.includes("HTTP error: 401") || e.message.includes("HTTP error: 403")) { + if (e.includes("HTTP error: 401") || e.includes("HTTP error: 403")) { this.removeCacheSession(); return this.retryWithDelay(); } - this.status = "disabled"; + this.handleError(`Failed to fetch status: ${e}`, "disabled"); this.removeCacheSession(); } }, @@ -214,8 +216,7 @@ export default { throw new Error(`HTTP error: ${response.status}`); } } catch (e) { - console.error("Failed to fetch v5 status:", e); - this.status = "error"; + this.handleError(`Failed to fetch v5 status: ${e}`, "error"); } }, } From 59b0ed76885fc07733e9cdb0814b9d3b25c0f69f Mon Sep 17 00:00:00 2001 From: Molham Date: Sat, 19 Apr 2025 14:48:10 +0200 Subject: [PATCH 040/117] set this.status after checking the response is OK --- src/components/services/PiHole.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/services/PiHole.vue b/src/components/services/PiHole.vue index a2b1ccf..353ccd0 100644 --- a/src/components/services/PiHole.vue +++ b/src/components/services/PiHole.vue @@ -170,11 +170,11 @@ export default { const url = `${this.endpoint}/${`api/stats/summary?sid=${encodeURIComponent(this.sessionId)}`.replace(/^\/+/, '')}`; const response = await fetch(url); - this.status = "enabled"; if (response.ok) { const result = await response.json(); if (result?.queries?.percent_blocked !== undefined) { + this.status = "enabled"; this.percent_blocked = result.queries.percent_blocked; this.retryCount = 0; } else { From 07207dca5521c7ff51982cfb3db22409b5439890 Mon Sep 17 00:00:00 2001 From: Molham Date: Sat, 19 Apr 2025 15:19:08 +0200 Subject: [PATCH 041/117] reset the api_v5 function to fetch the remote api with this.fetch --- src/components/services/PiHole.vue | 37 ++++++++++-------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/src/components/services/PiHole.vue b/src/components/services/PiHole.vue index 353ccd0..bb9afc0 100644 --- a/src/components/services/PiHole.vue +++ b/src/components/services/PiHole.vue @@ -42,7 +42,7 @@ export default { }), computed: { percentage: function () { - if (typeof this.percent_blocked === 'number' && this.percent_blocked >= 0) { + if (this.percent_blocked) { return this.percent_blocked.toFixed(1); } return ""; @@ -187,37 +187,24 @@ export default { throw new Error(`HTTP error: ${response.status}`); } } catch (e) { - if (e.includes("HTTP error: 401") || e.includes("HTTP error: 403")) { + if (e.message.includes("HTTP error: 401") || e.message.includes("HTTP error: 403")) { this.removeCacheSession(); return this.retryWithDelay(); } - this.handleError(`Failed to fetch status: ${e}`, "disabled"); + this.handleError(`Failed to fetch status: ${e.message || e}`, "disabled"); this.removeCacheSession(); } }, async fetchStatus_v5() { - try { - const params = {}; - if (this.item.apikey) { - params.auth = this.item.apikey; - } - const url = new URL(`${this.endpoint}/api.php`); - Object.keys(params).forEach(key => url.searchParams.append(key, params[key])); - - const response = await fetch(url); - this.status = response.status.toString(); - - if (response.ok) { - const result = await response.json(); - if (result?.ads_percentage_today !== undefined) { - this.percent_blocked = result.ads_percentage_today; - } - } else { - throw new Error(`HTTP error: ${response.status}`); - } - } catch (e) { - this.handleError(`Failed to fetch v5 status: ${e}`, "error"); - } + const authQueryParams = this.item.apikey + ? `?summaryRaw&auth=${this.item.apikey}` + : ""; + const result = await this.fetch(`/api.php${authQueryParams}`).catch((e) => + this.handleError(`Failed to fetch status: ${e}`, "disabled"), + ); + + this.status = result.status; + this.percent_blocked = result.ads_percentage_today; }, } }; From 9e314c960b2612163dd3320c347deebec4513e51 Mon Sep 17 00:00:00 2001 From: Molham Date: Sat, 19 Apr 2025 15:31:19 +0200 Subject: [PATCH 042/117] fix integration test --- src/components/services/PiHole.vue | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/components/services/PiHole.vue b/src/components/services/PiHole.vue index bb9afc0..afbc5c6 100644 --- a/src/components/services/PiHole.vue +++ b/src/components/services/PiHole.vue @@ -39,6 +39,8 @@ export default { retryCount: 0, maxRetries: 3, retryDelay: 5000, + localCheckInterval: 1000, // Default value or a fallback + pollInterval: null, }), computed: { percentage: function () { @@ -53,6 +55,8 @@ export default { }, created() { if (parseInt(this.item.apiVersion, 10) === 6) { + // Set the interval to the checkInterval or default to 5 minutes + this.localCheckInterval = parseInt(this.item.checkInterval, 10) || 300000; this.loadCachedSession(); this.startStatusPolling(); } else { @@ -73,12 +77,10 @@ export default { }, startStatusPolling: function () { this.fetchStatus(); - // Set the interval to the checkInterval or default to 5 minutes - const interval = parseInt(this.item.checkInterval, 10) || 300000; - if (this.item.checkInterval < 1000) { - this.item.checkInterval = 1000; + if (this.localCheckInterval < 1000) { + this.localCheckInterval = 1000; } - this.pollInterval = setInterval(this.fetchStatus, interval); + this.pollInterval = setInterval(this.fetchStatus, this.localCheckInterval); }, stopStatusPolling: function () { if (this.pollInterval) { From ad76093a389f799f029acba3b1d94afb21c55193 Mon Sep 17 00:00:00 2001 From: Molham Date: Sat, 19 Apr 2025 21:10:44 +0200 Subject: [PATCH 043/117] modify service.js mixin to accept one more parameter and return full response and use this.fetch in PiHole.vue --- src/components/services/PiHole.vue | 10 +++++++--- src/mixins/service.js | 6 +++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/components/services/PiHole.vue b/src/components/services/PiHole.vue index afbc5c6..1703bf3 100644 --- a/src/components/services/PiHole.vue +++ b/src/components/services/PiHole.vue @@ -169,10 +169,14 @@ export default { const authenticated = await this.authenticate(); if (!authenticated) return; } + const options = { + method: "GET", + headers: { + 'Content-Type': 'application/json' + } + }; + const response = await this.fetch(`api/stats/summary?sid=${encodeURIComponent(this.sessionId)}`, options, false, true); - const url = `${this.endpoint}/${`api/stats/summary?sid=${encodeURIComponent(this.sessionId)}`.replace(/^\/+/, '')}`; - const response = await fetch(url); - if (response.ok) { const result = await response.json(); if (result?.queries?.percent_blocked !== undefined) { diff --git a/src/mixins/service.js b/src/mixins/service.js index d52fc29..f1e77bf 100644 --- a/src/mixins/service.js +++ b/src/mixins/service.js @@ -12,7 +12,7 @@ export default { } }, methods: { - fetch: function (path, init, json = true) { + fetch: function (path, init, json = true, returnFullResponse = false) { let options = {}; if (this.proxy?.useCredentials) { @@ -58,6 +58,10 @@ export default { ); } + if (returnFullResponse) { + return response; + } + return json ? response.json() : response.text(); }); }, From 42f3a3ee71e236f6a3871febbafd8a11a83fae85 Mon Sep 17 00:00:00 2001 From: Molham Date: Sun, 20 Apr 2025 00:58:37 +0200 Subject: [PATCH 044/117] reset the mixin service.js and make use of the actual error message from the current service.js --- src/components/services/PiHole.vue | 27 ++++++++++----------------- src/mixins/service.js | 6 +----- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/src/components/services/PiHole.vue b/src/components/services/PiHole.vue index 1703bf3..654cd86 100644 --- a/src/components/services/PiHole.vue +++ b/src/components/services/PiHole.vue @@ -44,7 +44,7 @@ export default { }), computed: { percentage: function () { - if (this.percent_blocked) { + if (this.percent_blocked >= 0) { return this.percent_blocked.toFixed(1); } return ""; @@ -156,6 +156,7 @@ export default { } }, retryWithDelay: async function () { + console.log("Retrying authentication..."); if (this.retryCount < this.maxRetries) { this.retryCount++; await new Promise(resolve => setTimeout(resolve, this.retryDelay)); @@ -175,25 +176,17 @@ export default { 'Content-Type': 'application/json' } }; - const response = await this.fetch(`api/stats/summary?sid=${encodeURIComponent(this.sessionId)}`, options, false, true); + const response = await this.fetch(`api/stats/summary?sid=${encodeURIComponent(this.sessionId)}`); - if (response.ok) { - const result = await response.json(); - if (result?.queries?.percent_blocked !== undefined) { - this.status = "enabled"; - this.percent_blocked = result.queries.percent_blocked; - this.retryCount = 0; - } else { - throw new Error("Invalid response format"); - } - } else if (response.status === 401) { - this.removeCacheSession(); - return this.retryWithDelay(); - } else { - throw new Error(`HTTP error: ${response.status}`); + if (response?.queries?.percent_blocked === undefined) { + throw new Error("Invalid response format"); } + + this.status = "enabled"; + this.percent_blocked = response.queries.percent_blocked; + this.retryCount = 0; } catch (e) { - if (e.message.includes("HTTP error: 401") || e.message.includes("HTTP error: 403")) { + if (e.message.includes("401 error") || e.message.includes("403 error")) { this.removeCacheSession(); return this.retryWithDelay(); } diff --git a/src/mixins/service.js b/src/mixins/service.js index f1e77bf..d52fc29 100644 --- a/src/mixins/service.js +++ b/src/mixins/service.js @@ -12,7 +12,7 @@ export default { } }, methods: { - fetch: function (path, init, json = true, returnFullResponse = false) { + fetch: function (path, init, json = true) { let options = {}; if (this.proxy?.useCredentials) { @@ -58,10 +58,6 @@ export default { ); } - if (returnFullResponse) { - return response; - } - return json ? response.json() : response.text(); }); }, From 15f59b9e36aae7abf72ba1bd075a7e7617795c66 Mon Sep 17 00:00:00 2001 From: Molham Date: Sun, 20 Apr 2025 01:02:27 +0200 Subject: [PATCH 045/117] delete unused object --- src/components/services/PiHole.vue | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/components/services/PiHole.vue b/src/components/services/PiHole.vue index 654cd86..55656e9 100644 --- a/src/components/services/PiHole.vue +++ b/src/components/services/PiHole.vue @@ -170,12 +170,6 @@ export default { const authenticated = await this.authenticate(); if (!authenticated) return; } - const options = { - method: "GET", - headers: { - 'Content-Type': 'application/json' - } - }; const response = await this.fetch(`api/stats/summary?sid=${encodeURIComponent(this.sessionId)}`); if (response?.queries?.percent_blocked === undefined) { From 347a3d062b08fcfd54fd9aefe75ab435375efdf5 Mon Sep 17 00:00:00 2001 From: Molham Date: Wed, 30 Apr 2025 13:59:01 +0200 Subject: [PATCH 046/117] remove deleteing the session over the API call when leaving the page --- src/components/services/PiHole.vue | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/components/services/PiHole.vue b/src/components/services/PiHole.vue index 55656e9..8ca67b8 100644 --- a/src/components/services/PiHole.vue +++ b/src/components/services/PiHole.vue @@ -66,7 +66,6 @@ export default { beforeDestroy() { if (parseInt(this.item.apiVersion, 10) === 6) { this.stopStatusPolling(); - this.deleteSession(); } }, methods: { @@ -109,19 +108,6 @@ export default { this.sessionId = null; this.sessionExpiry = null; }, - deleteSession: async function () { - if (!this.sessionId) return; - - try { - await this.fetch(`/api/auth/session/${encodeURIComponent(this.sessionId)}`, { - method: 'DELETE' - }); - } catch (e) { - this.handleError(`Failed to delete session: ${e}`, "error"); - } finally { - this.removeCacheSession(); - } - }, authenticate: async function () { if (!this.item.apikey) { this.handleError("API key is required for PiHole authentication", "disabled"); From acb304adeca43500c04be6c1e5e8465ea0ed3e88 Mon Sep 17 00:00:00 2001 From: Bastien Wirtz Date: Sun, 4 May 2025 14:15:57 +0200 Subject: [PATCH 047/117] deps update --- package.json | 8 ++++---- pnpm-lock.yaml | 38 +++++++++++++++++++------------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index cec7286..54584ab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "homer", - "version": "25.04.1", + "version": "25.05.1", "type": "module", "scripts": { "dev": "vite", @@ -11,10 +11,10 @@ }, "dependencies": { "@fortawesome/fontawesome-free": "^6.7.2", - "bulma": "^1.0.3", + "bulma": "^1.0.4", "lodash.merge": "^4.6.2", "vue": "^3.5.13", - "yaml": "^2.7.0" + "yaml": "^2.7.1" }, "devDependencies": { "@eslint/js": "^9.21.0", @@ -30,7 +30,7 @@ "vite-plugin-pwa": "^0.21.1" }, "license": "Apache-2.0", - "packageManager": "pnpm@10.4.1+sha512.c753b6c3ad7afa13af388fa6d808035a008e30ea9993f58c6663e2bc5ff21679aa834db094987129aa4d488b86df57f7b634981b2f827cdcacc698cc0cfb88af", + "packageManager": "pnpm@10.10.0+sha512.d615db246fe70f25dcfea6d8d73dee782ce23e2245e3c4f6f888249fb568149318637dca73c2c5c8ef2a4ca0d5657fb9567188bfab47f566d1ee6ce987815c39", "pnpm": { "neverBuiltDependencies": [] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 24694e8..467bd5f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: specifier: ^6.7.2 version: 6.7.2 bulma: - specifier: ^1.0.3 - version: 1.0.3 + specifier: ^1.0.4 + version: 1.0.4 lodash.merge: specifier: ^4.6.2 version: 4.6.2 @@ -21,15 +21,15 @@ importers: specifier: ^3.5.13 version: 3.5.13 yaml: - specifier: ^2.7.0 - version: 2.7.0 + specifier: ^2.7.1 + version: 2.7.1 devDependencies: '@eslint/js': specifier: ^9.21.0 version: 9.21.0 '@vitejs/plugin-vue': specifier: ^5.2.1 - version: 5.2.1(vite@6.1.6(sass-embedded@1.85.0)(terser@5.39.0)(yaml@2.7.0))(vue@3.5.13) + version: 5.2.1(vite@6.1.6(sass-embedded@1.85.0)(terser@5.39.0)(yaml@2.7.1))(vue@3.5.13) '@vue/eslint-config-prettier': specifier: ^10.2.0 version: 10.2.0(eslint@9.21.0)(prettier@3.5.2) @@ -53,10 +53,10 @@ importers: version: 1.85.0 vite: specifier: ^6.1.6 - version: 6.1.6(sass-embedded@1.85.0)(terser@5.39.0)(yaml@2.7.0) + version: 6.1.6(sass-embedded@1.85.0)(terser@5.39.0)(yaml@2.7.1) vite-plugin-pwa: specifier: ^0.21.1 - version: 0.21.1(vite@6.1.6(sass-embedded@1.85.0)(terser@5.39.0)(yaml@2.7.0))(workbox-build@7.3.0)(workbox-window@7.3.0) + version: 0.21.1(vite@6.1.6(sass-embedded@1.85.0)(terser@5.39.0)(yaml@2.7.1))(workbox-build@7.3.0)(workbox-window@7.3.0) packages: @@ -1116,8 +1116,8 @@ packages: buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - bulma@1.0.3: - resolution: {integrity: sha512-9eVXBrXwlU337XUXBjIIq7i88A+tRbJYAjXQjT/21lwam+5tpvKF0R7dCesre9N+HV9c6pzCNEPKrtgvBBes2g==} + bulma@1.0.4: + resolution: {integrity: sha512-Ffb6YGXDiZYX3cqvSbHWqQ8+LkX6tVoTcZuVB3lm93sbAVXlO0D6QlOTMnV6g18gILpAXqkG2z9hf9z4hCjz2g==} call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} @@ -2523,8 +2523,8 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - yaml@2.7.0: - resolution: {integrity: sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==} + yaml@2.7.1: + resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==} engines: {node: '>= 14'} hasBin: true @@ -3480,9 +3480,9 @@ snapshots: '@types/trusted-types@2.0.7': {} - '@vitejs/plugin-vue@5.2.1(vite@6.1.6(sass-embedded@1.85.0)(terser@5.39.0)(yaml@2.7.0))(vue@3.5.13)': + '@vitejs/plugin-vue@5.2.1(vite@6.1.6(sass-embedded@1.85.0)(terser@5.39.0)(yaml@2.7.1))(vue@3.5.13)': dependencies: - vite: 6.1.6(sass-embedded@1.85.0)(terser@5.39.0)(yaml@2.7.0) + vite: 6.1.6(sass-embedded@1.85.0)(terser@5.39.0)(yaml@2.7.1) vue: 3.5.13 '@vue/compiler-core@3.5.13': @@ -3657,7 +3657,7 @@ snapshots: buffer-from@1.1.2: {} - bulma@1.0.3: {} + bulma@1.0.4: {} call-bind-apply-helpers@1.0.2: dependencies: @@ -4998,18 +4998,18 @@ snapshots: varint@6.0.0: {} - vite-plugin-pwa@0.21.1(vite@6.1.6(sass-embedded@1.85.0)(terser@5.39.0)(yaml@2.7.0))(workbox-build@7.3.0)(workbox-window@7.3.0): + vite-plugin-pwa@0.21.1(vite@6.1.6(sass-embedded@1.85.0)(terser@5.39.0)(yaml@2.7.1))(workbox-build@7.3.0)(workbox-window@7.3.0): dependencies: debug: 4.4.0 pretty-bytes: 6.1.1 tinyglobby: 0.2.12 - vite: 6.1.6(sass-embedded@1.85.0)(terser@5.39.0)(yaml@2.7.0) + vite: 6.1.6(sass-embedded@1.85.0)(terser@5.39.0)(yaml@2.7.1) workbox-build: 7.3.0 workbox-window: 7.3.0 transitivePeerDependencies: - supports-color - vite@6.1.6(sass-embedded@1.85.0)(terser@5.39.0)(yaml@2.7.0): + vite@6.1.6(sass-embedded@1.85.0)(terser@5.39.0)(yaml@2.7.1): dependencies: esbuild: 0.24.2 postcss: 8.5.3 @@ -5018,7 +5018,7 @@ snapshots: fsevents: 2.3.3 sass-embedded: 1.85.0 terser: 5.39.0 - yaml: 2.7.0 + yaml: 2.7.1 vue-eslint-parser@9.4.3(eslint@9.21.0): dependencies: @@ -5219,6 +5219,6 @@ snapshots: yallist@3.1.1: {} - yaml@2.7.0: {} + yaml@2.7.1: {} yocto-queue@0.1.0: {} From a5eeb1e44e5bc550f81ef95b8dd8f44075e1b326 Mon Sep 17 00:00:00 2001 From: Bastien Wirtz Date: Sun, 4 May 2025 15:12:06 +0200 Subject: [PATCH 048/117] feat(smart-cards): handle dynamic loading error --- src/assets/components/base.scss | 4 ++++ src/components/Service.vue | 10 ++++++---- src/components/services/OpenWeather.vue | 12 ++++++++---- src/components/services/_error.vue | 22 ++++++++++++++++++++++ 4 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 src/components/services/_error.vue diff --git a/src/assets/components/base.scss b/src/assets/components/base.scss index 87c7455..b88211e 100644 --- a/src/assets/components/base.scss +++ b/src/assets/components/base.scss @@ -55,6 +55,10 @@ background-color: var(--card-background); } } + .component-error .card { + border: 1px solid rgba(255, 33, 33, 0.664); + background-color: rgba(255, 58, 58, 0.24); + } .message { .message-body { diff --git a/src/components/Service.vue b/src/components/Service.vue index 405bf10..f250aae 100644 --- a/src/components/Service.vue +++ b/src/components/Service.vue @@ -5,7 +5,7 @@ From 1afa0afd00428f320fa8dd5108d5caee51e4f245 Mon Sep 17 00:00:00 2001 From: Bastien Wirtz Date: Sun, 4 May 2025 15:15:12 +0200 Subject: [PATCH 049/117] chore(lint): Apply lint --- src/components/services/DockerSocketProxy.vue | 28 ++++++-- src/components/services/PiHole.vue | 68 ++++++++++++------ src/components/services/Plex.vue | 70 +++++++++++-------- src/components/services/SABnzbd.vue | 3 +- 4 files changed, 109 insertions(+), 60 deletions(-) diff --git a/src/components/services/DockerSocketProxy.vue b/src/components/services/DockerSocketProxy.vue index ab33709..444f11a 100644 --- a/src/components/services/DockerSocketProxy.vue +++ b/src/components/services/DockerSocketProxy.vue @@ -2,16 +2,28 @@