From 21dcde44a15354f060fad5f6c0e95f8187be8be0 Mon Sep 17 00:00:00 2001 From: Meier Lukas Date: Wed, 15 Nov 2023 06:39:40 +0100 Subject: [PATCH 01/13] =?UTF-8?q?=F0=9F=90=9B=20Notebook=20edit=20button?= =?UTF-8?q?=20placed=20above=20edit=20mode=20settings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/widgets/notebook/NotebookEditor.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/widgets/notebook/NotebookEditor.tsx b/src/widgets/notebook/NotebookEditor.tsx index 63ca613107e..a9faf7f2df7 100644 --- a/src/widgets/notebook/NotebookEditor.tsx +++ b/src/widgets/notebook/NotebookEditor.tsx @@ -52,6 +52,7 @@ import StarterKit from '@tiptap/starter-kit'; import { useSession } from 'next-auth/react'; import { useTranslation } from 'next-i18next'; import { Dispatch, SetStateAction, useState } from 'react'; +import { useEditModeStore } from '~/components/Dashboard/Views/useEditModeStore'; import { useConfigContext } from '~/config/provider'; import { useConfigStore } from '~/config/store'; import { api } from '~/utils/api'; @@ -62,9 +63,10 @@ import { INotebookWidget } from './NotebookWidgetTile'; export function Editor({ widget }: { widget: INotebookWidget }) { const [content, setContent] = useState(widget.properties.content); const [toSaveContent, setToSaveContent] = useState(content); + const isEditMode = useEditModeStore((x) => x.enabled); const { data: sessionData } = useSession(); - const enabled = !!sessionData?.user.isAdmin; + const enabled = !!sessionData?.user.isAdmin && !isEditMode; const [isEditing, setIsEditing] = useState(false); const { config, name: configName } = useConfigContext(); From f7ab929bcba85fa88ae340198f910f9bb58804a4 Mon Sep 17 00:00:00 2001 From: Meier Lukas Date: Wed, 15 Nov 2023 06:44:07 +0100 Subject: [PATCH 02/13] =?UTF-8?q?=F0=9F=90=9B=20Link=20to=20definition=20o?= =?UTF-8?q?f=20screen=20sized=20for=20edit=20mode=20notification=20wrong?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../layout/Templates/BoardLayout.tsx | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/components/layout/Templates/BoardLayout.tsx b/src/components/layout/Templates/BoardLayout.tsx index a8bc1439f56..3e82ea7759e 100644 --- a/src/components/layout/Templates/BoardLayout.tsx +++ b/src/components/layout/Templates/BoardLayout.tsx @@ -2,17 +2,13 @@ import { Button, Global, Text, Title, Tooltip, clsx } from '@mantine/core'; import { useHotkeys, useWindowEvent } from '@mantine/hooks'; import { openContextModal } from '@mantine/modals'; import { hideNotification, showNotification } from '@mantine/notifications'; -import { - IconApps, - IconEditCircle, - IconEditCircleOff, - IconSettings -} from '@tabler/icons-react'; +import { IconApps, IconEditCircle, IconEditCircleOff, IconSettings } from '@tabler/icons-react'; import Consola from 'consola'; import { useSession } from 'next-auth/react'; import { Trans, useTranslation } from 'next-i18next'; import Link from 'next/link'; import { useRouter } from 'next/router'; +import { env } from 'process'; import { useEditModeStore } from '~/components/Dashboard/Views/useEditModeStore'; import { useNamedWrapperColumnCount } from '~/components/Dashboard/Wrappers/gridstack/store'; import { BoardHeadOverride } from '~/components/layout/Meta/BoardHeadOverride'; @@ -20,7 +16,6 @@ import { HeaderActionButton } from '~/components/layout/header/ActionButton'; import { useConfigContext } from '~/config/provider'; import { api } from '~/utils/api'; -import { env } from 'process'; import { MainLayout } from './MainLayout'; type BoardLayoutProps = { @@ -32,10 +27,7 @@ export const BoardLayout = ({ children }: BoardLayoutProps) => { const { data: session } = useSession(); return ( - } - > + }> {children} @@ -135,7 +127,7 @@ const ToggleEditModeButton = () => { ), @@ -205,7 +197,7 @@ const BackgroundImage = () => { backgroundPosition: 'center center', backgroundSize: config?.settings.customization.backgroundImageSize ?? 'cover', backgroundRepeat: config?.settings.customization.backgroundImageRepeat ?? 'no-repeat', - backgroundAttachment: config?.settings.customization.backgroundImageAttachment ?? 'fixed' + backgroundAttachment: config?.settings.customization.backgroundImageAttachment ?? 'fixed', }, }} /> From 34074b1c9246e56c1665d3e9a9a7a25402a23e70 Mon Sep 17 00:00:00 2001 From: Meier Lukas Date: Wed, 15 Nov 2023 06:48:23 +0100 Subject: [PATCH 03/13] =?UTF-8?q?=F0=9F=90=9B=20Migrate=20package.json=20h?= =?UTF-8?q?as=20no=20license=20field?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- drizzle/migrate/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/drizzle/migrate/package.json b/drizzle/migrate/package.json index 35772f2169e..20eaa11ff78 100644 --- a/drizzle/migrate/package.json +++ b/drizzle/migrate/package.json @@ -1,4 +1,5 @@ { + "license": "MIT", "description": "This package.json is used for the migration script the dependencies are only installed within the Dockerfile.", "scripts": { "db:migrate": "ts-node ./migrate.ts" From a30d6f6f7b09aca866a96db316b226f729e755de Mon Sep 17 00:00:00 2001 From: No-Maines-Land Date: Wed, 15 Nov 2023 01:03:38 -0500 Subject: [PATCH 04/13] Update GeneralTab.tsx --- .../Dashboard/Modals/EditAppModal/Tabs/GeneralTab/GeneralTab.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/Dashboard/Modals/EditAppModal/Tabs/GeneralTab/GeneralTab.tsx b/src/components/Dashboard/Modals/EditAppModal/Tabs/GeneralTab/GeneralTab.tsx index 2d763775143..3e7806159b3 100644 --- a/src/components/Dashboard/Modals/EditAppModal/Tabs/GeneralTab/GeneralTab.tsx +++ b/src/components/Dashboard/Modals/EditAppModal/Tabs/GeneralTab/GeneralTab.tsx @@ -24,7 +24,6 @@ export const GeneralTab = ({ form, openTab }: GeneralTabProps) => { t('general.internalAddress.troubleshoot.lines.enablePings'), t('general.internalAddress.troubleshoot.lines.wget'), t('general.internalAddress.troubleshoot.lines.iframe'), - t('general.internalAddress.troubleshoot.lines.clearCache'), ]; return ( From da7c1114384b895d894c681848ec4cd603fd4776 Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Sat, 18 Nov 2023 14:42:47 +0000 Subject: [PATCH 05/13] Allow custom nextauth port (#1663) --- scripts/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/run.sh b/scripts/run.sh index ba017d05e6f..4623c60787a 100644 --- a/scripts/run.sh +++ b/scripts/run.sh @@ -1,7 +1,7 @@ #!/bin/sh echo "Exporting hostname..." -export NEXTAUTH_URL_INTERNAL="http://$HOSTNAME:7575" +export NEXTAUTH_URL_INTERNAL="http://$HOSTNAME:${PORT:-7575}" echo "Migrating database..." cd ./migrate; yarn db:migrate & PID=$! From 5aefd0962f8757a4357d015a4353a1f4a109eaa2 Mon Sep 17 00:00:00 2001 From: Thomas Camlong Date: Sat, 18 Nov 2023 15:43:46 +0100 Subject: [PATCH 06/13] New Crowdin updates (#1641) --- public/locales/cn/common.json | 4 +- public/locales/cn/layout/modals/about.json | 2 +- public/locales/cr/common.json | 4 +- public/locales/cs/common.json | 4 +- .../locales/cs/modules/torrents-status.json | 2 +- public/locales/da/common.json | 4 +- public/locales/de/common.json | 4 +- public/locales/el/common.json | 4 +- public/locales/es/common.json | 4 +- public/locales/fr/common.json | 4 +- public/locales/he/common.json | 4 +- .../customization/page-appearance.json | 22 +++--- public/locales/he/tools/docker.json | 2 +- public/locales/hr/common.json | 4 +- public/locales/hu/common.json | 4 +- public/locales/it/common.json | 4 +- public/locales/ja/common.json | 4 +- public/locales/ko/common.json | 4 +- public/locales/lv/common.json | 4 +- public/locales/nl/common.json | 4 +- public/locales/no/common.json | 4 +- public/locales/pl/common.json | 4 +- public/locales/pt/common.json | 4 +- public/locales/pt/layout/modals/about.json | 8 +-- .../locales/pt/modules/dns-hole-summary.json | 4 +- public/locales/pt/modules/notebook.json | 72 +++++++++---------- public/locales/ru/common.json | 4 +- public/locales/sk/common.json | 4 +- public/locales/sl/common.json | 4 +- public/locales/sv/common.json | 4 +- public/locales/tr/common.json | 4 +- .../customization/page-appearance.json | 4 +- .../customization/shade-selector.json | 2 +- public/locales/tw/common.json | 4 +- public/locales/uk/common.json | 4 +- public/locales/vi/common.json | 4 +- 36 files changed, 140 insertions(+), 86 deletions(-) diff --git a/public/locales/cn/common.json b/public/locales/cn/common.json index 7115fbb7228..13a7360808f 100644 --- a/public/locales/cn/common.json +++ b/public/locales/cn/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "宽度", "height": "高度" - } + }, + "public": "公开", + "restricted": "限制" } \ No newline at end of file diff --git a/public/locales/cn/layout/modals/about.json b/public/locales/cn/layout/modals/about.json index 7210ffadca8..9e3c1673a47 100644 --- a/public/locales/cn/layout/modals/about.json +++ b/public/locales/cn/layout/modals/about.json @@ -5,7 +5,7 @@ "key": "快捷键", "action": "操作", "keybinds": "热键绑定", - "translators": "翻译 ({{count}})", + "translators": "翻译者 ({{count}})", "translatorsDescription": "感谢这些人,Homarr 现已支持 {{languages}} 种语言!想要帮助将 Homarr 翻译成您的语言吗?请阅读此处了解如何执行此操作 。", "contributors": "贡献者 ({{count}})", "contributorsDescription": "这些人构建了让 homarr 工作的代码!想帮助建造 Homarr 吗?请阅读此处了解如何操作", diff --git a/public/locales/cr/common.json b/public/locales/cr/common.json index eaab4b3d924..32b5e93db51 100644 --- a/public/locales/cr/common.json +++ b/public/locales/cr/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "crwdns3910:0crwdne3910:0", "height": "crwdns3912:0crwdne3912:0" - } + }, + "public": "crwdns4034:0crwdne4034:0", + "restricted": "crwdns4036:0crwdne4036:0" } \ No newline at end of file diff --git a/public/locales/cs/common.json b/public/locales/cs/common.json index 065f41b13ac..814bcdbfa3b 100644 --- a/public/locales/cs/common.json +++ b/public/locales/cs/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "", "height": "" - } + }, + "public": "", + "restricted": "" } \ No newline at end of file diff --git a/public/locales/cs/modules/torrents-status.json b/public/locales/cs/modules/torrents-status.json index 4d700fe7591..af0834cb12e 100644 --- a/public/locales/cs/modules/torrents-status.json +++ b/public/locales/cs/modules/torrents-status.json @@ -36,7 +36,7 @@ "footer": { "error": "", "lastUpdated": "Naposledy aktualizováno před {{time}}", - "ratioGlobal": "Globální poměr", + "ratioGlobal": "Obecný poměr", "ratioWithFilter": "Filtrovaný poměr" }, "table": { diff --git a/public/locales/da/common.json b/public/locales/da/common.json index 7cb274d47f7..af6f64a58bf 100644 --- a/public/locales/da/common.json +++ b/public/locales/da/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "Bredde", "height": "Højde" - } + }, + "public": "Offentlig", + "restricted": "Begrænset" } \ No newline at end of file diff --git a/public/locales/de/common.json b/public/locales/de/common.json index a4376704339..1d4f442ab5d 100644 --- a/public/locales/de/common.json +++ b/public/locales/de/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "Breite", "height": "Höhe" - } + }, + "public": "Öffentlich sichtbar", + "restricted": "Eingeschränkt" } \ No newline at end of file diff --git a/public/locales/el/common.json b/public/locales/el/common.json index 3f3b132c9a1..e05f3c470da 100644 --- a/public/locales/el/common.json +++ b/public/locales/el/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "Πλάτος", "height": "Ύψος" - } + }, + "public": "Δημόσιο", + "restricted": "Περιορισμένη πρόσβαση" } \ No newline at end of file diff --git a/public/locales/es/common.json b/public/locales/es/common.json index 4dff3f76849..6a2ffe27eac 100644 --- a/public/locales/es/common.json +++ b/public/locales/es/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "Ancho", "height": "Alto" - } + }, + "public": "Pública", + "restricted": "Restringido" } \ No newline at end of file diff --git a/public/locales/fr/common.json b/public/locales/fr/common.json index 2260ecdf9c2..fe57b120406 100644 --- a/public/locales/fr/common.json +++ b/public/locales/fr/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "Largeur", "height": "Hauteur" - } + }, + "public": "Public", + "restricted": "" } \ No newline at end of file diff --git a/public/locales/he/common.json b/public/locales/he/common.json index 735b7eead2e..81f1f1869ab 100644 --- a/public/locales/he/common.json +++ b/public/locales/he/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "רוחב", "height": "גובה" - } + }, + "public": "ציבורי", + "restricted": "מוגבל" } \ No newline at end of file diff --git a/public/locales/he/settings/customization/page-appearance.json b/public/locales/he/settings/customization/page-appearance.json index 70d34cfad15..8a843849e23 100644 --- a/public/locales/he/settings/customization/page-appearance.json +++ b/public/locales/he/settings/customization/page-appearance.json @@ -19,26 +19,26 @@ "label": "רקע" }, "backgroundImageAttachment": { - "label": "", + "label": "צירוף תמונת רקע", "options": { - "fixed": "", - "scroll": "" + "fixed": "קבוע - הרקע נשאר באותו מיקום (מומלץ)", + "scroll": "גלילה - גלילה ברקע עם העכבר" } }, "backgroundImageSize": { - "label": "", + "label": "גודל תמונת רקע", "options": { - "cover": "", - "contain": "" + "cover": "כיסוי - קנה מידה קטן ככל האפשר של התמונה כדי לכסות את כל החלון על ידי חיתוך שטח מוגזם. (מוּמלָץ)", + "contain": "מכיל - קנה מידה גדול ככל האפשר של התמונה בתוך המיכל שלה מבלי לחתוך או למתוח את התמונה." } }, "backgroundImageRepeat": { - "label": "", + "label": "צירוף תמונת רקע", "options": { - "repeat": "", - "no-repeat": "", - "repeat-x": "", - "repeat-y": "" + "repeat": "חזור - התמונה חוזרת על עצמה ככל שנדרש כדי לכסות את כל אזור ציור תמונת הרקע.", + "no-repeat": "ללא חזרה - התמונה אינה חוזרת על עצמה וייתכן שלא תמלא את כל החלל (מומלץ)", + "repeat-x": "חזור X - זהה ל'חזרה' אבל רק על הציר האופקי.", + "repeat-y": "חזור Y - זהה ל'חזרה' אבל רק על הציר האנכי." } }, "customCSS": { diff --git a/public/locales/he/tools/docker.json b/public/locales/he/tools/docker.json index 3affb1371bf..c2ef87e55fd 100644 --- a/public/locales/he/tools/docker.json +++ b/public/locales/he/tools/docker.json @@ -2,7 +2,7 @@ "title": "דוקר", "alerts": { "notConfigured": { - "text": "" + "text": "למופע ה-Homarr שלך לא הוגדר Docker או שהוא נכשל באחזור קונטיינרים. אנא עיין בתיעוד כיצד להגדיר את האינטגרציה." } }, "modals": { diff --git a/public/locales/hr/common.json b/public/locales/hr/common.json index 83bca3a2497..ae1523ab89b 100644 --- a/public/locales/hr/common.json +++ b/public/locales/hr/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "Širina", "height": "Visina" - } + }, + "public": "Javno", + "restricted": "" } \ No newline at end of file diff --git a/public/locales/hu/common.json b/public/locales/hu/common.json index 95f6d9eb426..8bb6ce7ed76 100644 --- a/public/locales/hu/common.json +++ b/public/locales/hu/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "Szélesség", "height": "Magasság" - } + }, + "public": "Nyilvános", + "restricted": "Korlátozott" } \ No newline at end of file diff --git a/public/locales/it/common.json b/public/locales/it/common.json index 409e5d44485..1073a230699 100644 --- a/public/locales/it/common.json +++ b/public/locales/it/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "Larghezza", "height": "Altezza" - } + }, + "public": "Pubblico", + "restricted": "Limitato" } \ No newline at end of file diff --git a/public/locales/ja/common.json b/public/locales/ja/common.json index ed31ad64312..0f6284982d7 100644 --- a/public/locales/ja/common.json +++ b/public/locales/ja/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "幅", "height": "高さ" - } + }, + "public": "公開", + "restricted": "" } \ No newline at end of file diff --git a/public/locales/ko/common.json b/public/locales/ko/common.json index 387c33c1605..3d45080366a 100644 --- a/public/locales/ko/common.json +++ b/public/locales/ko/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "너비", "height": "높이" - } + }, + "public": "공개", + "restricted": "" } \ No newline at end of file diff --git a/public/locales/lv/common.json b/public/locales/lv/common.json index 3b7787e1746..97911405f05 100644 --- a/public/locales/lv/common.json +++ b/public/locales/lv/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "Platums", "height": "Augstums" - } + }, + "public": "Publisks", + "restricted": "" } \ No newline at end of file diff --git a/public/locales/nl/common.json b/public/locales/nl/common.json index 28b0288a2ab..200c27260ba 100644 --- a/public/locales/nl/common.json +++ b/public/locales/nl/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "Breedte", "height": "Hoogte" - } + }, + "public": "Openbaar", + "restricted": "" } \ No newline at end of file diff --git a/public/locales/no/common.json b/public/locales/no/common.json index 1fc22fd9924..e8c70c58937 100644 --- a/public/locales/no/common.json +++ b/public/locales/no/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "Bredde", "height": "Høyde" - } + }, + "public": "Offentlig", + "restricted": "" } \ No newline at end of file diff --git a/public/locales/pl/common.json b/public/locales/pl/common.json index fe14bc03ddf..b4fee4d41bf 100644 --- a/public/locales/pl/common.json +++ b/public/locales/pl/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "Szerokość", "height": "Wysokość" - } + }, + "public": "Publiczna", + "restricted": "" } \ No newline at end of file diff --git a/public/locales/pt/common.json b/public/locales/pt/common.json index 8ca0efcd8c2..41ce8280885 100644 --- a/public/locales/pt/common.json +++ b/public/locales/pt/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "Largura", "height": "Altura" - } + }, + "public": "Público", + "restricted": "" } \ No newline at end of file diff --git a/public/locales/pt/layout/modals/about.json b/public/locales/pt/layout/modals/about.json index 471f0a8d0a3..ade865ce10c 100644 --- a/public/locales/pt/layout/modals/about.json +++ b/public/locales/pt/layout/modals/about.json @@ -5,10 +5,10 @@ "key": "Tecla de atalho", "action": "Ação", "keybinds": "Ligações de teclas", - "translators": "", - "translatorsDescription": "", - "contributors": "", - "contributorsDescription": "", + "translators": "Tradutores ({{count}})", + "translatorsDescription": "Graças a essas pessoas, o Homarr está disponível em {{languages}} idiomas! Quer ajudar a traduzir o Homarr para seu idioma? Veja como fazer isso aqui.", + "contributors": "Colaboradores ({{count}})", + "contributorsDescription": "Essas pessoas criaram o código que faz o homarr funcionar! Quer ajudar a construir o Homarr? Veja como fazer isso aqui", "actions": { "toggleTheme": "Alternar o modo claro/escuro", "focusSearchBar": "Foco na barra de pesquisa", diff --git a/public/locales/pt/modules/dns-hole-summary.json b/public/locales/pt/modules/dns-hole-summary.json index b6fde0d7745..075ce5239d7 100644 --- a/public/locales/pt/modules/dns-hole-summary.json +++ b/public/locales/pt/modules/dns-hole-summary.json @@ -21,8 +21,8 @@ "metrics": { "domainsOnAdlist": "Domínios em adlists", "queriesToday": "Consultas hoje", - "queriesBlockedTodayPercentage": "", - "queriesBlockedToday": "" + "queriesBlockedTodayPercentage": "Bloqueado hoje", + "queriesBlockedToday": "Bloqueado hoje" } } } diff --git a/public/locales/pt/modules/notebook.json b/public/locales/pt/modules/notebook.json index a48a95c3330..41de2579678 100644 --- a/public/locales/pt/modules/notebook.json +++ b/public/locales/pt/modules/notebook.json @@ -8,7 +8,7 @@ "label": "Mostrar a barra de ferramentas para ajudá-lo a escrever markdown" }, "allowReadOnlyCheck": { - "label": "" + "label": "Permitir a verificação no modo de leitura" }, "content": { "label": "O conteúdo do notebook" @@ -17,43 +17,43 @@ }, "card": { "controls": { - "bold": "", - "italic": "", - "strikethrough": "", - "underline": "", - "colorText": "", - "colorHighlight": "", - "code": "", - "clear": "", - "heading": "", - "align": "", - "blockquote": "", - "horizontalLine": "", - "bulletList": "", - "orderedList": "", - "checkList": "", - "increaseIndent": "", - "decreaseIndent": "", - "link": "", - "unlink": "", - "image": "", - "addTable": "", - "deleteTable": "", - "colorCell": "", - "mergeCell": "", - "addColumnLeft": "", - "addColumnRight": "", - "deleteColumn": "", - "addRowTop": "", - "addRowBelow": "", - "deleteRow": "" + "bold": "Negrito", + "italic": "Itálico", + "strikethrough": "Riscar", + "underline": "Sublinhar", + "colorText": "Cor do texto", + "colorHighlight": "Texto colorido em destaque", + "code": "Código", + "clear": "Limpar formatação", + "heading": "Cabeçalho {{level}}", + "align": "Alinhar texto: {{position}}", + "blockquote": "Bloco de Citação", + "horizontalLine": "Linha horizontal", + "bulletList": "Lista de marcadores", + "orderedList": "Lista ordenada", + "checkList": "Lista de verificação", + "increaseIndent": "Aumentar recuo", + "decreaseIndent": "Diminuir recuo", + "link": "Link", + "unlink": "Remover link", + "image": "Incorporar imagem", + "addTable": "Adicionar tabela", + "deleteTable": "Excluir tabela", + "colorCell": "Cor da Célula", + "mergeCell": "Ativar/desativar mesclagem de células", + "addColumnLeft": "Adicionar coluna antes", + "addColumnRight": "Adicionar coluna depois", + "deleteColumn": "Excluir coluna", + "addRowTop": "Adicionar linha antes", + "addRowBelow": "Adicionar linha depois", + "deleteRow": "Excluir linha" }, "modals": { - "clearColor": "", - "source": "", - "widthPlaceholder": "", - "columns": "", - "rows": "" + "clearColor": "Limpar cor", + "source": "Fonte", + "widthPlaceholder": "Valor em % ou pixels", + "columns": "Colunas", + "rows": "Linhas" } } } \ No newline at end of file diff --git a/public/locales/ru/common.json b/public/locales/ru/common.json index 182197bbd83..2bdeb1d73a1 100644 --- a/public/locales/ru/common.json +++ b/public/locales/ru/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "Ширина", "height": "Высота" - } + }, + "public": "Публичный", + "restricted": "" } \ No newline at end of file diff --git a/public/locales/sk/common.json b/public/locales/sk/common.json index 86fc75c7a49..d44fa489e40 100644 --- a/public/locales/sk/common.json +++ b/public/locales/sk/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "Šírka", "height": "Výška" - } + }, + "public": "Verejné", + "restricted": "" } \ No newline at end of file diff --git a/public/locales/sl/common.json b/public/locales/sl/common.json index 453f0a86da2..a7955df4295 100644 --- a/public/locales/sl/common.json +++ b/public/locales/sl/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "Širina", "height": "Višina" - } + }, + "public": "Javna stran", + "restricted": "" } \ No newline at end of file diff --git a/public/locales/sv/common.json b/public/locales/sv/common.json index 1abe2496b00..7f1ac4da8de 100644 --- a/public/locales/sv/common.json +++ b/public/locales/sv/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "Bredd", "height": "Höjd" - } + }, + "public": "Publik", + "restricted": "" } \ No newline at end of file diff --git a/public/locales/tr/common.json b/public/locales/tr/common.json index b5a11df3bf3..f6637c05578 100644 --- a/public/locales/tr/common.json +++ b/public/locales/tr/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "Genişlik", "height": "Yükseklik" - } + }, + "public": "Herkese açık", + "restricted": "Sınırlı" } \ No newline at end of file diff --git a/public/locales/tr/settings/customization/page-appearance.json b/public/locales/tr/settings/customization/page-appearance.json index 7689630872f..da824cb33bd 100644 --- a/public/locales/tr/settings/customization/page-appearance.json +++ b/public/locales/tr/settings/customization/page-appearance.json @@ -21,7 +21,7 @@ "backgroundImageAttachment": { "label": "Arkaplan resim ekle", "options": { - "fixed": "Düzeltildi - Arka plan aynı konumda kalıyor (tavsiye edilen)", + "fixed": "Sabit - Arka plan aynı konumda kalır (önerilir)", "scroll": "Kaydırma - Arka plan farenizle kaydırılır" } }, @@ -36,7 +36,7 @@ "label": "Arkaplan resim ekle", "options": { "repeat": "Tekrarla - Resim, arka plan görüntü alanının tamamını kapsayacak şekilde gerektiği kadar tekrarlanır.", - "no-repeat": "", + "no-repeat": "Tekrarsız - Resim tekrarlanmaz ve tüm alanı doldurmayabilir (önerilir)", "repeat-x": "Tekrarla X - 'Tekrarla' ile aynıdır ancak yalnızca yatay eksende.", "repeat-y": "Tekrar Y - 'Tekrarla' ile aynıdır, ancak yalnızca dikey eksende." } diff --git a/public/locales/tr/settings/customization/shade-selector.json b/public/locales/tr/settings/customization/shade-selector.json index 97c5e820bcc..f983c3e623d 100644 --- a/public/locales/tr/settings/customization/shade-selector.json +++ b/public/locales/tr/settings/customization/shade-selector.json @@ -1,3 +1,3 @@ { - "label": "Gölge" + "label": "Gölge " } \ No newline at end of file diff --git a/public/locales/tw/common.json b/public/locales/tw/common.json index c9c72232953..9c5236d49cd 100644 --- a/public/locales/tw/common.json +++ b/public/locales/tw/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "寬度", "height": "高度" - } + }, + "public": "公開", + "restricted": "受到限制" } \ No newline at end of file diff --git a/public/locales/uk/common.json b/public/locales/uk/common.json index 3b0e1e56f8e..e4143d0fc3c 100644 --- a/public/locales/uk/common.json +++ b/public/locales/uk/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "Ширина", "height": "Висота" - } + }, + "public": "Публічний", + "restricted": "" } \ No newline at end of file diff --git a/public/locales/vi/common.json b/public/locales/vi/common.json index c37ea6b9db2..33ff8cfbd19 100644 --- a/public/locales/vi/common.json +++ b/public/locales/vi/common.json @@ -51,5 +51,7 @@ "attributes": { "width": "Chiều rộng", "height": "Chiều cao" - } + }, + "public": "Công khai", + "restricted": "" } \ No newline at end of file From eadfa4a10ffa2702a723b5fb43bf49fc5ef6ef55 Mon Sep 17 00:00:00 2001 From: Meier Lukas Date: Sat, 18 Nov 2023 22:11:29 +0100 Subject: [PATCH 07/13] =?UTF-8?q?=E2=9C=A8=20Add=20support=20for=20install?= =?UTF-8?q?ation=20in=20address=20bar=20(#1675)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/site.webmanifest | 2 ++ 1 file changed, 2 insertions(+) diff --git a/public/site.webmanifest b/public/site.webmanifest index 96dae66d5e9..cb12a1e1b64 100644 --- a/public/site.webmanifest +++ b/public/site.webmanifest @@ -1,4 +1,6 @@ { + "name": "Homarr", + "start_url": "/", "display": "standalone", "icons": [ { From fe63c03372b20da00c0d65ce722b2e438540b1e6 Mon Sep 17 00:00:00 2001 From: Thomas Camlong Date: Tue, 21 Nov 2023 18:33:18 +0100 Subject: [PATCH 08/13] =?UTF-8?q?=F0=9F=8C=90=20New=20Crowdin=20updates=20?= =?UTF-8?q?(#1682)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/locales/fr/common.json | 2 +- public/locales/pl/common.json | 6 ++--- public/locales/pl/layout/modals/add-app.json | 10 ++++----- public/locales/pl/modules/calendar.json | 2 +- public/locales/pl/modules/dashdot.json | 4 ++-- public/locales/pl/modules/notebook.json | 4 ++-- .../locales/pl/modules/torrents-status.json | 4 ++-- .../customization/page-appearance.json | 22 +++++++++---------- public/locales/pl/tools/docker.json | 2 +- 9 files changed, 28 insertions(+), 28 deletions(-) diff --git a/public/locales/fr/common.json b/public/locales/fr/common.json index fe57b120406..868684af75f 100644 --- a/public/locales/fr/common.json +++ b/public/locales/fr/common.json @@ -53,5 +53,5 @@ "height": "Hauteur" }, "public": "Public", - "restricted": "" + "restricted": "Restreint" } \ No newline at end of file diff --git a/public/locales/pl/common.json b/public/locales/pl/common.json index b4fee4d41bf..18e17c952c1 100644 --- a/public/locales/pl/common.json +++ b/public/locales/pl/common.json @@ -1,7 +1,7 @@ { "save": "Zapisz", "apply": "Zastosuj", - "insert": "", + "insert": "Wstaw", "about": "O programie", "cancel": "Anuluj", "close": "Zamknij", @@ -45,7 +45,7 @@ "seeMore": "Zobacz więcej...", "position": { "left": "Lewo", - "center": "", + "center": "Wyśrodkowany", "right": "Prawo" }, "attributes": { @@ -53,5 +53,5 @@ "height": "Wysokość" }, "public": "Publiczna", - "restricted": "" + "restricted": "Ograniczone" } \ No newline at end of file diff --git a/public/locales/pl/layout/modals/add-app.json b/public/locales/pl/layout/modals/add-app.json index 841cb288147..79445aae346 100644 --- a/public/locales/pl/layout/modals/add-app.json +++ b/public/locales/pl/layout/modals/add-app.json @@ -20,11 +20,11 @@ "lines": { "nothingAfterPort": "W większości, jeśli nie we wszystkich przypadkach, nie należy wprowadzać żadnej ścieżki po porcie. (Nawet '/admin' dla pihole lub '/web' dla plex)", "protocolCheck": "Zawsze upewnij się, że adres URL jest poprzedzony przez http lub https, i upewnij się, że używasz odpowiedniego adresu.", - "preferIP": "", - "enablePings": "", - "wget": "", - "iframe": "", - "clearCache": "" + "preferIP": "Zalecane jest użycie bezpośredniego adresu IP maszyny lub kontenera, z którym próbujesz się komunikować.", + "enablePings": "Sprawdź, czy adres IP jest prawidłowy, włączając polecenia ping. Dostosuj tablicę -> Układ -> Włącz pingi. Na kafelkach aplikacji pojawi się mała czerwona lub zielona dymka, a najechanie na nią spowoduje wyświetlenie kodu odpowiedzi (w większości przypadków oczekiwana jest zielona dymka z kodem 200).", + "wget": "Aby mieć pewność, że homarr będzie mógł komunikować się z innymi aplikacjami, wykonaj wget/curl/ping IP:port aplikacji.", + "iframe": "Jeśli chodzi o ramki iframe, powinny one zawsze używać tego samego protokołu (http/s), co Homarr.", + "clearCache": "Niektóre informacje są rejestrowane w pamięci podręcznej, więc integracja może nie działać, jeśli nie wyczyścisz pamięci podręcznej w ogólnych opcjach Homarr." }, "footer": "Aby uzyskać więcej informacji na temat rozwiązywania problemów, skontaktuj się z nami na naszym {{discord}}." } diff --git a/public/locales/pl/modules/calendar.json b/public/locales/pl/modules/calendar.json index e3ba8e24a06..7cbf4cf4175 100644 --- a/public/locales/pl/modules/calendar.json +++ b/public/locales/pl/modules/calendar.json @@ -3,7 +3,7 @@ "name": "Kalendarz", "description": "Wyświetla kalendarz z nadchodzącymi wydaniami, z obsługiwanych integracji.", "settings": { - "title": "Ustawienia dla widżetu Kalendarz", + "title": "Ustawienia dla widżetu Kalendarza", "radarrReleaseType": { "label": "Rodzaj premiery w Radarr", "data": { diff --git a/public/locales/pl/modules/dashdot.json b/public/locales/pl/modules/dashdot.json index 3deca86e371..93f56011272 100644 --- a/public/locales/pl/modules/dashdot.json +++ b/public/locales/pl/modules/dashdot.json @@ -1,6 +1,6 @@ { "descriptor": { - "name": "Dash.", + "name": "Dach.", "description": "Wyświetla wykresy zewnętrznego Dash. Instancja wewnątrz Homarr.", "settings": { "title": "Ustawienia dla widgetu Dash.", @@ -82,7 +82,7 @@ } }, "card": { - "title": "Dash.", + "title": "Dach.", "errors": { "noService": "Nie znaleziono usługi Dash. Proszę dodać ją do pulpitu Homarra lub ustawić adres URL usługi Dash. w opcjach modułu", "noInformation": "Nie można uzyskać informacji z dash. - używasz najnowszej wersji?", diff --git a/public/locales/pl/modules/notebook.json b/public/locales/pl/modules/notebook.json index 84b043ebb6c..e800018dbb3 100644 --- a/public/locales/pl/modules/notebook.json +++ b/public/locales/pl/modules/notebook.json @@ -8,7 +8,7 @@ "label": "Pokaż pasek narzędzi ułatwiający pisanie w markdown" }, "allowReadOnlyCheck": { - "label": "" + "label": "Zezwalaj na sprawdzanie w trybie tylko do odczytu" }, "content": { "label": "Zawartość notatnika" @@ -39,7 +39,7 @@ "image": "Osadź obraz", "addTable": "Dodaj tabelę", "deleteTable": "Usuń tabelę", - "colorCell": "", + "colorCell": "Kolor Komórki", "mergeCell": "Przełączanie scalania komórek", "addColumnLeft": "Dodaj kolumnę przed", "addColumnRight": "Dodaj kolumnę po", diff --git a/public/locales/pl/modules/torrents-status.json b/public/locales/pl/modules/torrents-status.json index e21bbb299d7..324001ae2eb 100644 --- a/public/locales/pl/modules/torrents-status.json +++ b/public/locales/pl/modules/torrents-status.json @@ -11,10 +11,10 @@ "label": "Wyświetlanie ukończonych torrentów" }, "displayActiveTorrents": { - "label": "" + "label": "Wyświetl aktywne torrenty" }, "speedLimitOfActiveTorrents": { - "label": "" + "label": "Prędkość wysyłania pozwalająca uznać torrent za aktywny (kB/s)" }, "displayStaleTorrents": { "label": "Wyświetlanie nieaktualnych torrentów" diff --git a/public/locales/pl/settings/customization/page-appearance.json b/public/locales/pl/settings/customization/page-appearance.json index 4cdb44fa86b..eb91bd053a6 100644 --- a/public/locales/pl/settings/customization/page-appearance.json +++ b/public/locales/pl/settings/customization/page-appearance.json @@ -19,26 +19,26 @@ "label": "Tło" }, "backgroundImageAttachment": { - "label": "", + "label": "Ustawienie obrazu tła", "options": { - "fixed": "", - "scroll": "" + "fixed": "Fixed – Tło pozostaje w tej samej pozycji (zalecane)", + "scroll": "Scroll - Tło przewija się za pomocą myszy" } }, "backgroundImageSize": { - "label": "", + "label": "Rozmiar obrazu tła", "options": { - "cover": "", - "contain": "" + "cover": "Cover — skaluje obraz do najmniejszego możliwego rozmiaru, aby pokryć całe okno poprzez przycięcie nadmiernej przestrzeni. (Zalecana)", + "contain": "Contain — skaluje obraz do największego możliwego rozmiaru w jego kontenerze, bez przycinania i rozciągania obrazu." } }, "backgroundImageRepeat": { - "label": "", + "label": "Ustawienie obrazu tła", "options": { - "repeat": "", - "no-repeat": "", - "repeat-x": "", - "repeat-y": "" + "repeat": "Repeat — obraz jest powtarzany tak często, jak to konieczne, aby pokryć cały obszar obrazu tła.", + "no-repeat": "No repeat — obraz nie jest powtarzany i może nie wypełniać całej przestrzeni (zalecane)", + "repeat-x": "Repeat X — to samo co „Powtórz”, ale tylko na osi poziomej.", + "repeat-y": "Repeat Y — to samo co „Powtórz”, ale tylko w osi pionowej." } }, "customCSS": { diff --git a/public/locales/pl/tools/docker.json b/public/locales/pl/tools/docker.json index 5eccbe96adb..af1ad0e110f 100644 --- a/public/locales/pl/tools/docker.json +++ b/public/locales/pl/tools/docker.json @@ -2,7 +2,7 @@ "title": "Docker", "alerts": { "notConfigured": { - "text": "" + "text": "Twoja instancja Homarr nie ma skonfigurowanego Dockera lub nie była w stanie pobrać listę kontenerów. Sprawdź dokumentację, aby dowiedzieć się, jak skonfigurować integrację." } }, "modals": { From 5a8a378a2ecddef31d20f1ed6092d936d92ab05f Mon Sep 17 00:00:00 2001 From: Tagaishi Date: Tue, 21 Nov 2023 18:34:01 +0100 Subject: [PATCH 09/13] =?UTF-8?q?=F0=9F=90=9B=20Affix=20overlapping=20cust?= =?UTF-8?q?om=20CSS=20box=20(#1687)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/board/[slug]/customize.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/board/[slug]/customize.tsx b/src/pages/board/[slug]/customize.tsx index a83ecf33cd8..5234f9d8424 100644 --- a/src/pages/board/[slug]/customize.tsx +++ b/src/pages/board/[slug]/customize.tsx @@ -229,7 +229,7 @@ export default function CustomizationPage({ )} - + From 7f46fafbb94c1f08a73ff440f8aafea7ba2f00f5 Mon Sep 17 00:00:00 2001 From: Thomas Camlong Date: Thu, 23 Nov 2023 21:43:18 +0100 Subject: [PATCH 10/13] =?UTF-8?q?=F0=9F=8C=90=20New=20Crowdin=20updates=20?= =?UTF-8?q?(#1692)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/locales/pt/common.json | 8 +++---- .../locales/pt/modules/torrents-status.json | 12 +++++----- .../pt/settings/customization/general.json | 2 +- .../customization/page-appearance.json | 22 +++++++++---------- public/locales/pt/tools/docker.json | 6 ++--- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/public/locales/pt/common.json b/public/locales/pt/common.json index 41ce8280885..da21170896f 100644 --- a/public/locales/pt/common.json +++ b/public/locales/pt/common.json @@ -1,7 +1,7 @@ { "save": "Salvar", - "apply": "", - "insert": "", + "apply": "Aplicar", + "insert": "Inserir", "about": "Sobre", "cancel": "Cancelar", "close": "Fechar", @@ -45,7 +45,7 @@ "seeMore": "Veja mais...", "position": { "left": "Esquerda", - "center": "", + "center": "Centralizado", "right": "Certo" }, "attributes": { @@ -53,5 +53,5 @@ "height": "Altura" }, "public": "Público", - "restricted": "" + "restricted": "Restrito" } \ No newline at end of file diff --git a/public/locales/pt/modules/torrents-status.json b/public/locales/pt/modules/torrents-status.json index 8089d44ba7b..6c1fab56358 100644 --- a/public/locales/pt/modules/torrents-status.json +++ b/public/locales/pt/modules/torrents-status.json @@ -11,10 +11,10 @@ "label": "Mostrar torrentes completas" }, "displayActiveTorrents": { - "label": "" + "label": "Exibir torrents ativos" }, "speedLimitOfActiveTorrents": { - "label": "" + "label": "Velocidade de upload para considerar um torrent como ativo (kB/s)" }, "displayStaleTorrents": { "label": "Exibição de torrentes envelhecidas" @@ -27,8 +27,8 @@ "description": "Quando a opção \"is whitelist\" estiver marcada, ela funcionará como uma lista de permissões. Se não estiver marcada, será uma lista negra. Não fará nada quando estiver vazia" }, "displayRatioWithFilter": { - "label": "", - "info": "" + "label": "Exibir proporção da lista de torrents filtrados", + "info": "Se estiver desativado, somente a proporção global será exibida. A proporção global ainda usará os rótulos se estiver definida" } } }, @@ -36,8 +36,8 @@ "footer": { "error": "Erro", "lastUpdated": "Última actualização {{time}} atrás", - "ratioGlobal": "", - "ratioWithFilter": "" + "ratioGlobal": "Proporção global", + "ratioWithFilter": "Proporção com filtro" }, "table": { "header": { diff --git a/public/locales/pt/settings/customization/general.json b/public/locales/pt/settings/customization/general.json index 80053d14692..f2a5ab396bd 100644 --- a/public/locales/pt/settings/customization/general.json +++ b/public/locales/pt/settings/customization/general.json @@ -22,7 +22,7 @@ "description": "Configure o Homarr para usuários com deficiência ou incapacitados" }, "access": { - "name": "", + "name": "Acesso", "description": "Configure quem tem acesso ao seu quadro" } } diff --git a/public/locales/pt/settings/customization/page-appearance.json b/public/locales/pt/settings/customization/page-appearance.json index 8f8a32ec957..66581d72cc5 100644 --- a/public/locales/pt/settings/customization/page-appearance.json +++ b/public/locales/pt/settings/customization/page-appearance.json @@ -19,26 +19,26 @@ "label": "Antecedentes" }, "backgroundImageAttachment": { - "label": "", + "label": "Anexo de imagem de fundo", "options": { - "fixed": "", - "scroll": "" + "fixed": "Fixado - O plano de fundo permanece na mesma posição (recomendado)", + "scroll": "Rolagem - O plano de fundo rola com seu mouse" } }, "backgroundImageSize": { - "label": "", + "label": "Tamanho da imagem de fundo", "options": { - "cover": "", - "contain": "" + "cover": "Capa - Dimensiona a imagem o menor possível para cobrir toda a janela cortando o espaço excessivo. (recomendado)", + "contain": "Conter - Dimensiona a imagem o máximo possível dentro de seu contêiner, sem cortar ou esticar a imagem." } }, "backgroundImageRepeat": { - "label": "", + "label": "Anexo de imagem de fundo", "options": { - "repeat": "", - "no-repeat": "", - "repeat-x": "", - "repeat-y": "" + "repeat": "Repetir - A imagem é repetida o quanto for necessário para cobrir toda a área de pintura da imagem de fundo.", + "no-repeat": "Sem repetição - A imagem não se repete e pode não preencher todo o espaço (recomendado)", + "repeat-x": "Repetir X - O mesmo que 'Repetir', mas apenas no eixo horizontal.", + "repeat-y": "Repetir Y - O mesmo que 'Repetir', mas apenas no eixo vertical." } }, "customCSS": { diff --git a/public/locales/pt/tools/docker.json b/public/locales/pt/tools/docker.json index b81fe732ed0..7e080aceb65 100644 --- a/public/locales/pt/tools/docker.json +++ b/public/locales/pt/tools/docker.json @@ -2,16 +2,16 @@ "title": "Docker", "alerts": { "notConfigured": { - "text": "" + "text": "Sua instância do Homarr não possui o Docker configurado ou falhou em buscar contêineres. Por favor, verifique a documentação sobre como configurar a integração." } }, "modals": { "selectBoard": { - "title": "Escolha uma placa", + "title": "Escolha um quadro", "text": "Escolha o quadro em que deseja adicionar os aplicativos para os contêineres do Docker selecionados.", "form": { "board": { - "label": "Diretoria" + "label": "Quadro" }, "submit": "Adicionar aplicativos" } From 312e2c8297e5daf521ca7088a37293b001fa37e2 Mon Sep 17 00:00:00 2001 From: Manuel <30572287+manuel-rw@users.noreply.github.com> Date: Thu, 23 Nov 2023 21:44:05 +0100 Subject: [PATCH 11/13] =?UTF-8?q?=E2=9C=A8=20#698=20homeassistant=20widget?= =?UTF-8?q?=20(#1658)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- .../en/modules/smart-home/entity-state.json | 17 ++++ .../InputElements/IntegrationSelector.tsx | 5 + src/server/api/root.ts | 3 +- .../api/routers/smart-home/entity-state.ts | 53 ++++++++++ .../server/sdk/homeassistant/HomeAssistant.ts | 41 ++++++++ .../sdk/homeassistant/models/EntityState.ts | 12 +++ src/tools/server/translation-namespaces.ts | 1 + src/tools/shared/strings.ts | 6 ++ src/tools/singleton/HomeAssistantSingleton.ts | 20 ++++ src/types/app.ts | 5 +- src/widgets/index.ts | 2 + .../entity-state/entity-state.widget.tsx | 97 +++++++++++++++++++ 13 files changed, 261 insertions(+), 3 deletions(-) create mode 100644 public/locales/en/modules/smart-home/entity-state.json create mode 100644 src/server/api/routers/smart-home/entity-state.ts create mode 100644 src/tools/server/sdk/homeassistant/HomeAssistant.ts create mode 100644 src/tools/server/sdk/homeassistant/models/EntityState.ts create mode 100644 src/tools/singleton/HomeAssistantSingleton.ts create mode 100644 src/widgets/smart-home/entity-state/entity-state.widget.tsx diff --git a/package.json b/package.json index 3724f70c2ea..7fbaf97074b 100644 --- a/package.json +++ b/package.json @@ -233,4 +233,4 @@ ] } } -} \ No newline at end of file +} diff --git a/public/locales/en/modules/smart-home/entity-state.json b/public/locales/en/modules/smart-home/entity-state.json new file mode 100644 index 00000000000..e477757df73 --- /dev/null +++ b/public/locales/en/modules/smart-home/entity-state.json @@ -0,0 +1,17 @@ +{ + "entityNotFound": "Entity not found", + "descriptor": { + "name": "Home Assistant entity", + "description": "Current state of an entity in Home Assistant", + "settings": { + "title": "Entity state", + "entityId": { + "label": "Entity ID", + "info": "Unique entity ID in Home Assistant. Copy by clicking on entity > Click on cog icon > Click on copy button at 'Entity ID'. Some custom entities may not be supported." + }, + "displayName": { + "label": "Display name" + } + } + } +} \ No newline at end of file diff --git a/src/components/Dashboard/Modals/EditAppModal/Tabs/IntegrationTab/Components/InputElements/IntegrationSelector.tsx b/src/components/Dashboard/Modals/EditAppModal/Tabs/IntegrationTab/Components/InputElements/IntegrationSelector.tsx index 632a2cefacf..eb021a94c88 100644 --- a/src/components/Dashboard/Modals/EditAppModal/Tabs/IntegrationTab/Components/InputElements/IntegrationSelector.tsx +++ b/src/components/Dashboard/Modals/EditAppModal/Tabs/IntegrationTab/Components/InputElements/IntegrationSelector.tsx @@ -183,4 +183,9 @@ export const availableIntegrations = [ image: 'https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/adguard-home.png', label: 'AdGuard Home', }, + { + value: 'homeAssistant', + image: 'https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons@master/png/home-assistant.png', + label: 'Home Assistant' + } ] as const satisfies Readonly; diff --git a/src/server/api/root.ts b/src/server/api/root.ts index 23ddd6044d5..f6aed4aac07 100644 --- a/src/server/api/root.ts +++ b/src/server/api/root.ts @@ -1,5 +1,4 @@ import { createTRPCRouter } from '~/server/api/trpc'; - import { appRouter } from './routers/app'; import { boardRouter } from './routers/board'; import { calendarRouter } from './routers/calendar'; @@ -16,6 +15,7 @@ import { notebookRouter } from './routers/notebook'; import { overseerrRouter } from './routers/overseerr'; import { passwordRouter } from './routers/password'; import { rssRouter } from './routers/rss'; +import { smartHomeEntityStateRouter } from './routers/smart-home/entity-state'; import { timezoneRouter } from './routers/timezone'; import { usenetRouter } from './routers/usenet/router'; import { userRouter } from './routers/user'; @@ -47,6 +47,7 @@ export const rootRouter = createTRPCRouter({ boards: boardRouter, password: passwordRouter, notebook: notebookRouter, + smartHomeEntityState: smartHomeEntityStateRouter }); // export type definition of API diff --git a/src/server/api/routers/smart-home/entity-state.ts b/src/server/api/routers/smart-home/entity-state.ts new file mode 100644 index 00000000000..b977bcb11ee --- /dev/null +++ b/src/server/api/routers/smart-home/entity-state.ts @@ -0,0 +1,53 @@ +import { TRPCError } from '@trpc/server'; + +import { ZodError, z } from 'zod'; + + +import { createTRPCRouter, protectedProcedure } from '../../trpc'; + +import { findAppProperty } from '~/tools/client/app-properties'; +import { getConfig } from '~/tools/config/getConfig'; +import { HomeAssistantSingleton } from '~/tools/singleton/HomeAssistantSingleton'; + +export const smartHomeEntityStateRouter = createTRPCRouter({ + retrieveStatus: protectedProcedure + .input( + z.object({ + configName: z.string(), + entityId: z.string().regex(/^[A-Za-z0-9-_\.]+$/) + }) + ) + .query(async ({ input }) => { + const config = getConfig(input.configName); + + const instances = config.apps.filter((app) => app.integration?.type == 'homeAssistant'); + + for (var instance of instances) { + const url = new URL(instance.url); + const client = HomeAssistantSingleton.getOrSet(url, findAppProperty(instance, 'apiKey')); + const state = await client.getEntityState(input.entityId); + + if (!state.success) { + if (!(state.error instanceof ZodError)) { + continue; + } + // Consola.error('Unable to handle entity state: ', state.error); + throw new TRPCError({ + code: 'NOT_IMPLEMENTED', + message: `Unable to handle Home Assistant entity state. This may be due to malformed response or unknown entity type. Check log for details` + }); + } + + if(!state.data) { + throw new TRPCError({ + code: 'INTERNAL_SERVER_ERROR', + message: `Home Assistant: Unable to connect to app '${instance.id}'. Check logs for details` + }); + } + + return state.data; + } + + return null; + }), +}); diff --git a/src/tools/server/sdk/homeassistant/HomeAssistant.ts b/src/tools/server/sdk/homeassistant/HomeAssistant.ts new file mode 100644 index 00000000000..6ee8418b448 --- /dev/null +++ b/src/tools/server/sdk/homeassistant/HomeAssistant.ts @@ -0,0 +1,41 @@ +import Consola from 'consola'; +import { appendPath } from '~/tools/shared/strings'; +import { entityStateSchema } from './models/EntityState'; + +export class HomeAssistant { + public readonly basePath: URL; + private readonly token: string; + + constructor(url: URL, token: string) { + if (!url.pathname.endsWith('/')) { + url.pathname += "/"; + } + url.pathname += 'api'; + this.basePath = url; + this.token = token; + } + + async getEntityState(entityId: string) { + try { + const response = await fetch(appendPath(this.basePath, `/states/${entityId}`), { + headers: { + 'Authorization': `Bearer ${this.token}` + } + }); + const body = await response.json(); + if (!response.ok) { + return { + success: false as const, + error: body + }; + } + return entityStateSchema.safeParseAsync(body); + } catch (err) { + Consola.error(`Failed to fetch from '${this.basePath}': ${err}`); + return { + success: false as const, + error: err + }; + } + } +} diff --git a/src/tools/server/sdk/homeassistant/models/EntityState.ts b/src/tools/server/sdk/homeassistant/models/EntityState.ts new file mode 100644 index 00000000000..de3f3ffc0f4 --- /dev/null +++ b/src/tools/server/sdk/homeassistant/models/EntityState.ts @@ -0,0 +1,12 @@ +import { z } from 'zod'; + + +export const entityStateSchema = z.object({ + attributes: z.record(z.union([z.string(), z.number(), z.boolean()])), + entity_id: z.string(), + last_changed: z.string().pipe(z.coerce.date()), + last_updated: z.string().pipe(z.coerce.date()), + state: z.string(), +}); + +export type EntityState = z.infer; diff --git a/src/tools/server/translation-namespaces.ts b/src/tools/server/translation-namespaces.ts index ff186c61628..910e3022094 100644 --- a/src/tools/server/translation-namespaces.ts +++ b/src/tools/server/translation-namespaces.ts @@ -29,6 +29,7 @@ export const boardNamespaces = [ 'modules/dns-hole-controls', 'modules/bookmark', 'modules/notebook', + 'modules/smart-home/entity-state', 'widgets/error-boundary', 'widgets/draggable-list', 'widgets/location', diff --git a/src/tools/shared/strings.ts b/src/tools/shared/strings.ts index 086edcae564..298983b33f3 100644 --- a/src/tools/shared/strings.ts +++ b/src/tools/shared/strings.ts @@ -12,3 +12,9 @@ export const trimStringEnding = (original: string, toTrimIfExists: string[]) => export const firstUpperCase = (str: string) => { return str.charAt(0).toUpperCase() + str.slice(1); }; + +export const appendPath = (url: URL, path: string) => { + const newUrl = new URL(url); + newUrl.pathname += path; + return newUrl; +} diff --git a/src/tools/singleton/HomeAssistantSingleton.ts b/src/tools/singleton/HomeAssistantSingleton.ts new file mode 100644 index 00000000000..262f9816e77 --- /dev/null +++ b/src/tools/singleton/HomeAssistantSingleton.ts @@ -0,0 +1,20 @@ +import { HomeAssistant } from '../server/sdk/homeassistant/HomeAssistant'; + +export class HomeAssistantSingleton { + private static _instances: HomeAssistant[] = []; + + public static getOrSet(url: URL, token: string): HomeAssistant { + const match = this._instances.find( + (instance) => + instance.basePath.hostname === url.hostname && instance.basePath.port === url.port + ); + + if (!match) { + const instance = new HomeAssistant(url, token); + this._instances.push(instance); + return instance; + } + + return match; + } +} diff --git a/src/types/app.ts b/src/types/app.ts index 68a3c5039e2..6c624ca5d8b 100644 --- a/src/types/app.ts +++ b/src/types/app.ts @@ -1,4 +1,5 @@ import { Icon, IconKey, IconPassword, IconUser } from '@tabler/icons-react'; + import { Property } from 'csstype'; import { TileBaseType } from './tile'; @@ -55,7 +56,8 @@ export type IntegrationType = | 'jellyfin' | 'nzbGet' | 'pihole' - | 'adGuardHome'; + | 'adGuardHome' + | 'homeAssistant'; export type AppIntegrationType = { type: IntegrationType | null; @@ -97,6 +99,7 @@ export const integrationFieldProperties: { plex: ['apiKey'], pihole: ['apiKey'], adGuardHome: ['username', 'password'], + homeAssistant: ['apiKey'] }; export type IntegrationFieldDefinitionType = { diff --git a/src/widgets/index.ts b/src/widgets/index.ts index 39d77589667..9219d8ae28a 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -11,6 +11,7 @@ import mediaRequestsStats from './media-requests/MediaRequestStatsTile'; import mediaServer from './media-server/MediaServerTile'; import notebook from './notebook/NotebookWidgetTile'; import rss from './rss/RssWidgetTile'; +import smartHomeEntityState from './smart-home/entity-state/entity-state.widget'; import torrent from './torrent/TorrentTile'; import usenet from './useNet/UseNetTile'; import videoStream from './video/VideoStreamTile'; @@ -34,4 +35,5 @@ export default { 'dns-hole-controls': dnsHoleControls, bookmark, notebook, + 'smart-home/entity-state': smartHomeEntityState }; diff --git a/src/widgets/smart-home/entity-state/entity-state.widget.tsx b/src/widgets/smart-home/entity-state/entity-state.widget.tsx new file mode 100644 index 00000000000..ac497d3b363 --- /dev/null +++ b/src/widgets/smart-home/entity-state/entity-state.widget.tsx @@ -0,0 +1,97 @@ +import { Center, Loader, Stack, Text, Tooltip } from '@mantine/core'; +import { IconAlertHexagon, IconBinaryTree, IconExclamationMark } from '@tabler/icons-react'; +import { useTranslation } from 'react-i18next'; +import { useConfigContext } from '~/config/provider'; +import { api } from '~/utils/api'; +import { defineWidget } from '~/widgets/helper'; +import { WidgetLoading } from '~/widgets/loading'; +import { IWidget } from '~/widgets/widgets'; + +const definition = defineWidget({ + id: 'smart-home/entity-state', + icon: IconBinaryTree, + options: { + entityId: { + type: 'text', + defaultValue: 'sun.sun', + info: true, + }, + displayName: { + type: 'text', + defaultValue: 'Sun', + }, + }, + gridstack: { + minWidth: 1, + minHeight: 1, + maxWidth: 12, + maxHeight: 12, + }, + component: EntityStateTile, +}); + +export type ISmartHomeEntityStateWidget = IWidget<(typeof definition)['id'], typeof definition>; + +interface SmartHomeEntityStateWidgetProps { + widget: ISmartHomeEntityStateWidget; +} + +function EntityStateTile({ widget }: SmartHomeEntityStateWidgetProps) { + const { t } = useTranslation('modules/smart-home/entity-state'); + const { name: configName } = useConfigContext(); + + const { data, isInitialLoading, isLoading, isError, error } = + api.smartHomeEntityState.retrieveStatus.useQuery( + { + configName: configName!, + entityId: widget.properties.entityId, + }, + { + enabled: !!configName, + } + ); + + let dataComponent = null; + + if (isError) { + dataComponent = ( + + + + ); + } + + if (!dataComponent && isInitialLoading) { + dataComponent = ; + } + + if (!dataComponent && !data) { + dataComponent = ( + + + + ); + } + + if (!dataComponent) { + dataComponent = ( + + {data?.state} + {isLoading && } + + ); + } + + return ( +
+ + + {widget.properties.displayName} + + {dataComponent} + +
+ ); +} + +export default definition; From 5522abdfb6705f077f4e31558914055a08cdb3db Mon Sep 17 00:00:00 2001 From: Manuel <30572287+manuel-rw@users.noreply.github.com> Date: Thu, 23 Nov 2023 21:46:51 +0100 Subject: [PATCH 12/13] =?UTF-8?q?=F0=9F=94=96=20Increase=20version=20(#169?= =?UTF-8?q?9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7fbaf97074b..0ec53e668de 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "homarr", - "version": "0.14.1", + "version": "0.14.2", "description": "Homarr - A homepage for your server.", "license": "MIT", "repository": { From dfcb899013479ed80bb255f78b4b29f3d5a5508b Mon Sep 17 00:00:00 2001 From: Manuel <30572287+manuel-rw@users.noreply.github.com> Date: Thu, 23 Nov 2023 22:21:34 +0100 Subject: [PATCH 13/13] =?UTF-8?q?=E2=9C=A8=20Stale=20time=20for=20entity?= =?UTF-8?q?=20state=20(#1702)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/widgets/smart-home/entity-state/entity-state.widget.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widgets/smart-home/entity-state/entity-state.widget.tsx b/src/widgets/smart-home/entity-state/entity-state.widget.tsx index ac497d3b363..ef384651796 100644 --- a/src/widgets/smart-home/entity-state/entity-state.widget.tsx +++ b/src/widgets/smart-home/entity-state/entity-state.widget.tsx @@ -48,6 +48,7 @@ function EntityStateTile({ widget }: SmartHomeEntityStateWidgetProps) { }, { enabled: !!configName, + refetchInterval: 2 * 60 * 1000 } );