From abce57379d22518ddb2e1bb2007029251e48af6c Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Tue, 27 Feb 2024 00:32:05 -0800 Subject: [PATCH 1/7] Documentation: fix repository typo (#3013) --- .github/workflows/repo-maintenance.yml | 12 ++++++------ CONTRIBUTING.md | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/repo-maintenance.yml b/.github/workflows/repo-maintenance.yml index d1f7e4fdd..7cf47c51b 100644 --- a/.github/workflows/repo-maintenance.yml +++ b/.github/workflows/repo-maintenance.yml @@ -42,17 +42,17 @@ jobs: This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new discussion for related concerns. - See our [contributing guidelines](https://github.com/gethomepage/homepage/blob/main/CONTRIBUTING.md#automatic-respoistory-maintenance) for more details. + See our [contributing guidelines](https://github.com/gethomepage/homepage/blob/main/CONTRIBUTING.md#automatic-repository-maintenance) for more details. pr-comment: > This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new discussion for related concerns. - See our [contributing guidelines](https://github.com/gethomepage/homepage/blob/main/CONTRIBUTING.md#automatic-respoistory-maintenance) for more details. + See our [contributing guidelines](https://github.com/gethomepage/homepage/blob/main/CONTRIBUTING.md#automatic-repository-maintenance) for more details. discussion-comment: > This discussion has been automatically locked since there has not been any recent activity after it was closed. Please open a new discussion for related concerns. - See our [contributing guidelines](https://github.com/gethomepage/homepage/blob/main/CONTRIBUTING.md#automatic-respoistory-maintenance) for more details. + See our [contributing guidelines](https://github.com/gethomepage/homepage/blob/main/CONTRIBUTING.md#automatic-repository-maintenance) for more details. close-answered-discussions: name: 'Close Answered Discussions' runs-on: ubuntu-latest @@ -92,7 +92,7 @@ jobs: }`; const commentVariables = { discussion: discussion.id, - body: 'This discussion has been automatically closed because it was marked as answered. See our [contributing guidelines](https://github.com/gethomepage/homepage/blob/main/CONTRIBUTING.md#automatic-respoistory-maintenance) for more details.', + body: 'This discussion has been automatically closed because it was marked as answered. See our [contributing guidelines](https://github.com/gethomepage/homepage/blob/main/CONTRIBUTING.md#automatic-repository-maintenance) for more details.', } await github.graphql(addCommentMutation, commentVariables) @@ -182,7 +182,7 @@ jobs: }`; const commentVariables = { discussion: discussion.id, - body: 'This discussion has been automatically closed due to inactivity. See our [contributing guidelines](https://github.com/gethomepage/homepage/blob/main/CONTRIBUTING.md#automatic-respoistory-maintenance) for more details.', + body: 'This discussion has been automatically closed due to inactivity. See our [contributing guidelines](https://github.com/gethomepage/homepage/blob/main/CONTRIBUTING.md#automatic-repository-maintenance) for more details.', } await github.graphql(addCommentMutation, commentVariables); @@ -260,7 +260,7 @@ jobs: }`; const commentVariables = { discussion: discussion.id, - body: 'This discussion has been automatically closed due to lack of community support. See our [contributing guidelines](https://github.com/gethomepage/homepage/blob/main/CONTRIBUTING.md#automatic-respoistory-maintenance) for more details.', + body: 'This discussion has been automatically closed due to lack of community support. See our [contributing guidelines](https://github.com/gethomepage/homepage/blob/main/CONTRIBUTING.md#automatic-repository-maintenance) for more details.', } await github.graphql(addCommentMutation, commentVariables); diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7dfb6a6d4..48f2818da 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -52,7 +52,7 @@ By contributing, you agree that your contributions will be licensed under its GN This document was adapted from the open-source contribution guidelines for [Facebook's Draft](https://github.com/facebook/draft-js/blob/main/CONTRIBUTING.md) -# Automatic Respoistory Maintenance +# Automatic Respository Maintenance The homepage team appreciates all effort and interest from the community in filing bug reports, creating feature requests, sharing ideas and helping other community members. That said, in an effort to keep the repository organized and managebale the project uses automatic handling of certain areas: From 68e4b98ddbb27e61cb132c2ba304752ee3be2928 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Wed, 28 Feb 2024 01:46:06 -0800 Subject: [PATCH 2/7] Fix: support cyrillic characters in quicklaunch (#3020) --- src/pages/index.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 39ac6cf29..b5aac8a96 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -225,7 +225,7 @@ function Home({ initialSettings }) { if (e.target.tagName === "BODY" || e.target.id === "inner_wrapper") { if ( (e.key.length === 1 && - e.key.match(/(\w|\s|[à-ü]|[À-Ü])/g) && + e.key.match(/(\w|\s|[à-ü]|[À-Ü]|[\w\u0430-\u044f])/gi) && !(e.altKey || e.ctrlKey || e.metaKey || e.shiftKey)) || e.key.match(/([à-ü]|[À-Ü])/g) || // accented characters may require modifier keys (e.key === "v" && (e.ctrlKey || e.metaKey)) From e92ccc30ba87adc21a1db3f6f9bf8f99c93142d4 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Wed, 28 Feb 2024 11:44:32 -0800 Subject: [PATCH 3/7] Fix: only log errors directly if exist --- src/pages/api/config/[path].js | 2 +- src/pages/api/docker/stats/[...service].js | 2 +- src/pages/api/docker/status/[...service].js | 2 +- src/pages/api/kubernetes/stats/[...service].js | 2 +- src/pages/api/kubernetes/status/[...service].js | 2 +- src/pages/api/services/proxy.js | 4 ++-- src/pages/api/widgets/kubernetes.js | 2 +- src/pages/index.jsx | 2 +- src/utils/config/service-helpers.js | 2 +- src/utils/proxy/http.js | 4 ++-- src/widgets/audiobookshelf/proxy.js | 2 +- src/widgets/gamedig/proxy.js | 2 +- src/widgets/minecraft/proxy.js | 2 +- src/widgets/pyload/proxy.js | 2 +- 14 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/pages/api/config/[path].js b/src/pages/api/config/[path].js index 7f3b6a079..6cb04698f 100644 --- a/src/pages/api/config/[path].js +++ b/src/pages/api/config/[path].js @@ -28,7 +28,7 @@ export default async function handler(req, res) { res.setHeader("Content-Type", mimeType); return res.status(200).send(fileContent); } catch (error) { - logger.error(error); + if (error) logger.error(error); return res.status(500).end("Internal Server Error"); } } diff --git a/src/pages/api/docker/stats/[...service].js b/src/pages/api/docker/stats/[...service].js index 715e51881..e92bad7ce 100644 --- a/src/pages/api/docker/stats/[...service].js +++ b/src/pages/api/docker/stats/[...service].js @@ -80,7 +80,7 @@ export default async function handler(req, res) { error: "not found", }); } catch (e) { - logger.error(e); + if (e) logger.error(e); return res.status(500).send({ error: { message: e?.message ?? "Unknown error" }, }); diff --git a/src/pages/api/docker/status/[...service].js b/src/pages/api/docker/status/[...service].js index 96c6bea60..f9dc640bb 100644 --- a/src/pages/api/docker/status/[...service].js +++ b/src/pages/api/docker/status/[...service].js @@ -108,7 +108,7 @@ export default async function handler(req, res) { status: "not found", }); } catch (e) { - logger.error(e); + if (e) logger.error(e); return res.status(500).send({ error: { message: e?.message ?? "Unknown error" }, }); diff --git a/src/pages/api/kubernetes/stats/[...service].js b/src/pages/api/kubernetes/stats/[...service].js index 90a67becd..b1bf83450 100644 --- a/src/pages/api/kubernetes/stats/[...service].js +++ b/src/pages/api/kubernetes/stats/[...service].js @@ -106,7 +106,7 @@ export default async function handler(req, res) { stats, }); } catch (e) { - logger.error(e); + if (e) logger.error(e); res.status(500).send({ error: "unknown error", }); diff --git a/src/pages/api/kubernetes/status/[...service].js b/src/pages/api/kubernetes/status/[...service].js index 1ca191261..f771d69df 100644 --- a/src/pages/api/kubernetes/status/[...service].js +++ b/src/pages/api/kubernetes/status/[...service].js @@ -59,7 +59,7 @@ export default async function handler(req, res) { status, }); } catch (e) { - logger.error(e); + if (e) logger.error(e); res.status(500).send({ error: "unknown error", }); diff --git a/src/pages/api/services/proxy.js b/src/pages/api/services/proxy.js index 80856419a..be4a96a67 100644 --- a/src/pages/api/services/proxy.js +++ b/src/pages/api/services/proxy.js @@ -71,8 +71,8 @@ export default async function handler(req, res) { logger.debug("Unknown proxy service type: %s", type); return res.status(403).json({ error: "Unkown proxy service type" }); - } catch (ex) { - logger.error(ex); + } catch (e) { + if (e) logger.error(e); return res.status(500).send({ error: "Unexpected error" }); } } diff --git a/src/pages/api/widgets/kubernetes.js b/src/pages/api/widgets/kubernetes.js index b55b02d73..0859212fa 100644 --- a/src/pages/api/widgets/kubernetes.js +++ b/src/pages/api/widgets/kubernetes.js @@ -94,7 +94,7 @@ export default async function handler(req, res) { nodes: Object.entries(nodeMap).map(([name, node]) => ({ name, ...node })), }); } catch (e) { - logger.error("exception %s", e); + if (e) logger.error(e); return res.status(500).send({ error: "unknown error", }); diff --git a/src/pages/index.jsx b/src/pages/index.jsx index b5aac8a96..b62f9ab2d 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -65,7 +65,7 @@ export async function getStaticProps() { }, }; } catch (e) { - if (logger) { + if (logger && e) { logger.error(e); } return { diff --git a/src/utils/config/service-helpers.js b/src/utils/config/service-helpers.js index 9f9979150..77c9a673c 100644 --- a/src/utils/config/service-helpers.js +++ b/src/utils/config/service-helpers.js @@ -325,7 +325,7 @@ export async function servicesFromKubernetes() { return mappedServiceGroups; } catch (e) { - logger.error(e); + if (e) logger.error(e); throw e; } } diff --git a/src/utils/proxy/http.js b/src/utils/proxy/http.js index 1755dd936..ff34ce0d6 100644 --- a/src/utils/proxy/http.js +++ b/src/utils/proxy/http.js @@ -44,7 +44,7 @@ function handleRequest(requestor, url, params) { // zlib errors responseContent.on("error", (e) => { - logger.error(e); + if (e) logger.error(e); responseContent = response; // fallback }); response.pipe(responseContent); @@ -112,7 +112,7 @@ export async function httpProxy(url, params = {}) { constructedUrl.port ? `:${constructedUrl.port}` : "", constructedUrl.pathname, ); - logger.error(err); + if (err) logger.error(err); return [500, "application/json", { error: { message: err?.message ?? "Unknown error", url, rawError: err } }, null]; } } diff --git a/src/widgets/audiobookshelf/proxy.js b/src/widgets/audiobookshelf/proxy.js index c4dba5cdb..9701c1feb 100644 --- a/src/widgets/audiobookshelf/proxy.js +++ b/src/widgets/audiobookshelf/proxy.js @@ -63,7 +63,7 @@ export default async function audiobookshelfProxyHandler(req, res) { return res.status(200).send(libraryStats); } catch (e) { - logger.error(e.message); + if (e) logger.error(e); return res.status(500).send({ error: { message: e.message } }); } } diff --git a/src/widgets/gamedig/proxy.js b/src/widgets/gamedig/proxy.js index 0029834c5..8a7e55c5a 100644 --- a/src/widgets/gamedig/proxy.js +++ b/src/widgets/gamedig/proxy.js @@ -28,7 +28,7 @@ export default async function gamedigProxyHandler(req, res) { ping: serverData.ping, }); } catch (e) { - logger.error(e); + if (e) logger.error(e); res.status(200).send({ online: false, diff --git a/src/widgets/minecraft/proxy.js b/src/widgets/minecraft/proxy.js index 7aeedfb99..f7bac9d45 100644 --- a/src/widgets/minecraft/proxy.js +++ b/src/widgets/minecraft/proxy.js @@ -18,7 +18,7 @@ export default async function minecraftProxyHandler(req, res) { players: pingResponse.players, }); } catch (e) { - logger.error(e); + if (e) logger.error(e); res.status(200).send({ version: undefined, online: false, diff --git a/src/widgets/pyload/proxy.js b/src/widgets/pyload/proxy.js index 802a67c6c..4d7cd1168 100644 --- a/src/widgets/pyload/proxy.js +++ b/src/widgets/pyload/proxy.js @@ -103,7 +103,7 @@ export default async function pyloadProxyHandler(req, res) { } } } catch (e) { - logger.error(e); + if (e) logger.error(e); return res.status(500).send({ error: { message: `Error communicating with Pyload API: ${e.toString()}` } }); } From f0910a9e8b43e2bb007f4adb140584327d30afef Mon Sep 17 00:00:00 2001 From: russkinz <68681047+russkinz@users.noreply.github.com> Date: Thu, 29 Feb 2024 09:32:27 +1300 Subject: [PATCH 4/7] Documentation: fix openwrt docs (#3016) --------- Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com> --- docs/widgets/services/openwrt.md | 38 ++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/docs/widgets/services/openwrt.md b/docs/widgets/services/openwrt.md index c1c3ee94d..3759d2b0c 100644 --- a/docs/widgets/services/openwrt.md +++ b/docs/widgets/services/openwrt.md @@ -26,29 +26,35 @@ In order for homepage to access the OpenWRT RPC endpoints you will need to [crea Create an ACL named `homepage.json` in `/usr/share/rpcd/acl.d/`, the following permissions will suffice: -``` +```json { - "homepage": { - "description": "Homepage widget", - "read": { - "ubus": { - "network.interface.wan": ["status"], - "network.interface.lan": ["status"], - "network.device": ["status"] - "system": ["info"] - } - }, - } + "homepage": { + "description": "Homepage widget", + "read": { + "ubus": { + "network.interface.wan": ["status"], + "network.interface.lan": ["status"], + "network.device": ["status"], + "system": ["info"] + } + } + } } ``` -Then add a user that will use that ACL in `/etc/config/rpc`: +Create a `crypt(5)` password hash using the following command in the OpenWRT shell: + +```sh +uhttpd -m "" +``` -```config login +Then add a user that will use the ACL and hashed password in `/etc/config/rpcd`: + +``` +config login option username 'homepage' - option password '' + option password '' list read homepage - list write '*' ``` This username and password will be used in Homepage's services.yaml to grant access. From 5892d7407c7c300ee857db44d9ef657d769c86cc Mon Sep 17 00:00:00 2001 From: RoboMagus <68224306+RoboMagus@users.noreply.github.com> Date: Thu, 29 Feb 2024 16:34:26 +0100 Subject: [PATCH 5/7] Fix: docker status labels colors (#3028) --------- Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com> --- src/components/services/status.jsx | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/components/services/status.jsx b/src/components/services/status.jsx index e0f74210f..606570d2c 100644 --- a/src/components/services/status.jsx +++ b/src/components/services/status.jsx @@ -16,24 +16,25 @@ export default function Status({ service, style }) { colorClass = "text-rose-500/80"; } else if (data) { if (data.status?.includes("running")) { - if (data.health === "starting") { - statusTitle = t("docker.starting"); - colorClass = "text-blue-500/80"; - } - - if (data.health === "unhealthy") { - statusTitle = t("docker.unhealthy"); - colorClass = "text-orange-400/50 dark:text-orange-400/80"; - } + colorClass = "text-emerald-500/80"; if (!data.health) { statusLabel = data.status.replace("running", t("docker.running")); } else { statusLabel = data.health === "healthy" ? t("docker.healthy") : data.health; + + if (data.health === "starting") { + statusLabel = t("docker.starting"); + colorClass = "text-blue-500/80"; + } + + if (data.health === "unhealthy") { + statusLabel = t("docker.unhealthy"); + colorClass = "text-orange-400/50 dark:text-orange-400/80"; + } } statusTitle = statusLabel; - colorClass = "text-emerald-500/80"; } if (data.status === "not found" || data.status === "exited" || data.status?.startsWith("partial")) { @@ -41,6 +42,7 @@ export default function Status({ service, style }) { else if (data.status === "exited") statusLabel = t("docker.exited"); else statusLabel = data.status.replace("partial", t("docker.partial")); colorClass = "text-orange-400/50 dark:text-orange-400/80"; + statusTitle = statusLabel; } } @@ -52,7 +54,9 @@ export default function Status({ service, style }) { return (
{style !== "dot" ? ( From 9ba8f3193dec3b75748e96e0320f26a4be6dd8de Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Thu, 29 Feb 2024 07:40:09 -0800 Subject: [PATCH 6/7] Minor status refactoring --- src/components/services/status.jsx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/components/services/status.jsx b/src/components/services/status.jsx index 606570d2c..3a6f3b330 100644 --- a/src/components/services/status.jsx +++ b/src/components/services/status.jsx @@ -7,12 +7,11 @@ export default function Status({ service, style }) { const { data, error } = useSWR(`/api/docker/status/${service.container}/${service.server || ""}`); let statusLabel = t("docker.unknown"); - let statusTitle = ""; let backgroundClass = "px-1.5 py-0.5 bg-theme-500/10 dark:bg-theme-900/50"; let colorClass = "text-black/20 dark:text-white/40 "; if (error) { - statusTitle = t("docker.error"); + statusLabel = t("docker.error"); colorClass = "text-rose-500/80"; } else if (data) { if (data.status?.includes("running")) { @@ -33,8 +32,6 @@ export default function Status({ service, style }) { colorClass = "text-orange-400/50 dark:text-orange-400/80"; } } - - statusTitle = statusLabel; } if (data.status === "not found" || data.status === "exited" || data.status?.startsWith("partial")) { @@ -42,14 +39,12 @@ export default function Status({ service, style }) { else if (data.status === "exited") statusLabel = t("docker.exited"); else statusLabel = data.status.replace("partial", t("docker.partial")); colorClass = "text-orange-400/50 dark:text-orange-400/80"; - statusTitle = statusLabel; } } if (style === "dot") { colorClass = colorClass.replace(/text-/g, "bg-").replace(/\/\d\d/g, ""); backgroundClass = "p-4 hover:bg-theme-500/10 dark:hover:bg-theme-900/20"; - statusTitle = statusLabel; } return ( @@ -57,7 +52,7 @@ export default function Status({ service, style }) { className={`w-auto text-center overflow-hidden ${backgroundClass} rounded-b-[3px] docker-status docker-status-${statusLabel .toLowerCase() .replace(" ", "-")}`} - title={statusTitle} + title={statusLabel} > {style !== "dot" ? (
{statusLabel}
From b4263531cb8ce35c39d90ae0c2a6104383345b57 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Thu, 29 Feb 2024 23:42:33 -0800 Subject: [PATCH 7/7] Fix: info widget gaps (#3038) --- src/components/widgets/widget/container.jsx | 4 ++-- src/pages/index.jsx | 18 +++++++----------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/components/widgets/widget/container.jsx b/src/components/widgets/widget/container.jsx index 442aa0842..c9240dd3b 100644 --- a/src/components/widgets/widget/container.jsx +++ b/src/components/widgets/widget/container.jsx @@ -16,7 +16,7 @@ export function getAllClasses(options, additionalClassNames = "") { } return classNames( - "flex flex-col justify-center ml-2 mr-2", + "flex flex-col justify-center", "mt-2 m:mb-0 rounded-md shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 dark:bg-white/5 p-2 pl-3 pr-3", additionalClassNames, ); @@ -24,7 +24,7 @@ export function getAllClasses(options, additionalClassNames = "") { let widgetAlignedClasses = "flex flex-col max-w:full sm:basis-auto self-center grow-0 flex-wrap"; if (options?.style?.isRightAligned) { - widgetAlignedClasses = "flex flex-col justify-center first:ml-auto ml-2 mr-2 "; + widgetAlignedClasses = "flex flex-col justify-center"; } return classNames(widgetAlignedClasses, additionalClassNames); diff --git a/src/pages/index.jsx b/src/pages/index.jsx index b62f9ab2d..10b2f6d5a 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -161,10 +161,10 @@ function Index({ initialSettings, fallback }) { const headerStyles = { boxed: - "m-6 mb-0 sm:m-9 sm:mb-0 rounded-md shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 dark:bg-white/5 p-3", - underlined: "m-6 mb-0 sm:m-9 sm:mb-1 border-b-2 pb-4 border-theme-800 dark:border-theme-200/50", - clean: "m-6 mb-0 sm:m-9 sm:mb-0", - boxedWidgets: "m-6 mb-0 sm:m-9 sm:mb-0 sm:mt-1", + "m-5 mb-0 sm:m-9 sm:mb-0 rounded-md shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 dark:bg-white/5 p-3", + underlined: "m-5 mb-0 sm:m-9 sm:mb-1 border-b-2 pb-4 border-theme-800 dark:border-theme-200/50", + clean: "m-5 mb-0 sm:m-9 sm:mb-0", + boxedWidgets: "m-5 mb-0 sm:m-9 sm:mb-0 sm:mt-1", }; function Home({ initialSettings }) { @@ -282,7 +282,7 @@ function Home({ initialSettings }) { return ( <> {tabs.length > 0 && ( -
+
    -
    +
    {widgets && ( <> {widgets @@ -436,7 +432,7 @@ function Home({ initialSettings }) { id="information-widgets-right" className={classNames( "m-auto flex flex-wrap grow sm:basis-auto justify-between md:justify-end", - headerStyle === "boxedWidgets" ? "sm:ml-4" : "sm:ml-2", + "m-auto flex flex-wrap grow sm:basis-auto justify-between md:justify-end gap-x-2", )} > {widgets