diff --git a/drizzle/migrate/package.json b/drizzle/migrate/package.json
index 35772f216..20eaa11ff 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"
diff --git a/package.json b/package.json
index 3724f70c2..0ec53e668 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": {
@@ -233,4 +233,4 @@
]
}
}
-}
\ No newline at end of file
+}
diff --git a/public/locales/cn/common.json b/public/locales/cn/common.json
index 7115fbb72..13a736080 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 7210ffadc..9e3c1673a 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 eaab4b3d9..32b5e93db 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 065f41b13..814bcdbfa 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 4d700fe75..af0834cb1 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 7cb274d47..af6f64a58 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 a43767043..1d4f442ab 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 3f3b132c9..e05f3c470 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/en/modules/smart-home/entity-state.json b/public/locales/en/modules/smart-home/entity-state.json
new file mode 100644
index 000000000..e477757df
--- /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/public/locales/es/common.json b/public/locales/es/common.json
index 4dff3f768..6a2ffe27e 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 2260ecdf9..868684af7 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": "Restreint"
}
\ No newline at end of file
diff --git a/public/locales/he/common.json b/public/locales/he/common.json
index 735b7eead..81f1f1869 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 70d34cfad..8a843849e 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 3affb1371..c2ef87e55 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 83bca3a24..ae1523ab8 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 95f6d9eb4..8bb6ce7ed 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 409e5d444..1073a2306 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 ed31ad643..0f6284982 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 387c33c16..3d4508036 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 3b7787e17..97911405f 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 28b0288a2..200c27260 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 1fc22fd99..e8c70c589 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 fe14bc03d..18e17c952 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,11 +45,13 @@
"seeMore": "Zobacz więcej...",
"position": {
"left": "Lewo",
- "center": "",
+ "center": "Wyśrodkowany",
"right": "Prawo"
},
"attributes": {
"width": "Szerokość",
"height": "Wysokość"
- }
+ },
+ "public": "Publiczna",
+ "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 841cb2881..79445aae3 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 e3ba8e24a..7cbf4cf41 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 3deca86e3..93f560112 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 84b043ebb..e800018db 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 e21bbb299..324001ae2 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 4cdb44fa8..eb91bd053 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 5eccbe96a..af1ad0e11 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": {
diff --git a/public/locales/pt/common.json b/public/locales/pt/common.json
index 8ca0efcd8..da2117089 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,11 +45,13 @@
"seeMore": "Veja mais...",
"position": {
"left": "Esquerda",
- "center": "",
+ "center": "Centralizado",
"right": "Certo"
},
"attributes": {
"width": "Largura",
"height": "Altura"
- }
+ },
+ "public": "Público",
+ "restricted": "Restrito"
}
\ 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 471f0a8d0..ade865ce1 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 b6fde0d77..075ce5239 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 a48a95c33..41de25796 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/pt/modules/torrents-status.json b/public/locales/pt/modules/torrents-status.json
index 8089d44ba..6c1fab563 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 80053d146..f2a5ab396 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 8f8a32ec9..66581d72c 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 b81fe732e..7e080aceb 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"
}
diff --git a/public/locales/ru/common.json b/public/locales/ru/common.json
index 182197bbd..2bdeb1d73 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 86fc75c7a..d44fa489e 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 453f0a86d..a7955df42 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 1abe2496b..7f1ac4da8 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 b5a11df3b..f6637c055 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 768963087..da824cb33 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 97c5e820b..f983c3e62 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 c9c722329..9c5236d49 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 3b0e1e56f..e4143d0fc 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 c37ea6b9d..33ff8cfbd 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
diff --git a/public/site.webmanifest b/public/site.webmanifest
index 96dae66d5..cb12a1e1b 100644
--- a/public/site.webmanifest
+++ b/public/site.webmanifest
@@ -1,4 +1,6 @@
{
+ "name": "Homarr",
+ "start_url": "/",
"display": "standalone",
"icons": [
{
diff --git a/scripts/run.sh b/scripts/run.sh
index ba017d05e..4623c6078 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=$!
diff --git a/src/components/Dashboard/Modals/EditAppModal/Tabs/GeneralTab/GeneralTab.tsx b/src/components/Dashboard/Modals/EditAppModal/Tabs/GeneralTab/GeneralTab.tsx
index 2d7637751..3e7806159 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 (
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 632a2cefa..eb021a94c 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/components/layout/Templates/BoardLayout.tsx b/src/components/layout/Templates/BoardLayout.tsx
index a8bc1439f..3e82ea775 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',
},
}}
/>
diff --git a/src/pages/board/[slug]/customize.tsx b/src/pages/board/[slug]/customize.tsx
index a83ecf33c..5234f9d84 100644
--- a/src/pages/board/[slug]/customize.tsx
+++ b/src/pages/board/[slug]/customize.tsx
@@ -229,7 +229,7 @@ export default function CustomizationPage({
)}
-
+
diff --git a/src/server/api/root.ts b/src/server/api/root.ts
index 23ddd6044..f6aed4aac 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 000000000..b977bcb11
--- /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 000000000..6ee8418b4
--- /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 000000000..de3f3ffc0
--- /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 ff186c616..910e30220 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 086edcae5..298983b33 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 000000000..262f9816e
--- /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 68a3c5039..6c624ca5d 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 39d775896..9219d8ae2 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/notebook/NotebookEditor.tsx b/src/widgets/notebook/NotebookEditor.tsx
index 63ca61310..a9faf7f2d 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();
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 000000000..ef3846517
--- /dev/null
+++ b/src/widgets/smart-home/entity-state/entity-state.widget.tsx
@@ -0,0 +1,98 @@
+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,
+ refetchInterval: 2 * 60 * 1000
+ }
+ );
+
+ 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;