From 7c39cd89602b37e007b572bac3171e547f2d5dee Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+shamoon@users.noreply.github.com> Date: Tue, 11 Oct 2022 11:15:33 -0700 Subject: [PATCH 01/10] Private widget options API --- src/utils/config/api-response.js | 9 ++++++--- src/utils/config/config.js | 13 +++++++++++++ src/utils/config/service-helpers.js | 21 ++++++++++++++++++++- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/utils/config/api-response.js b/src/utils/config/api-response.js index 809927d1b..778877eb1 100644 --- a/src/utils/config/api-response.js +++ b/src/utils/config/api-response.js @@ -4,7 +4,7 @@ import path from "path"; import yaml from "js-yaml"; -import checkAndCopyConfig from "utils/config/config"; +import checkAndCopyConfig, { sanitizePrivateOptions } from "utils/config/config"; import { servicesFromConfig, servicesFromDocker, cleanServiceGroups } from "utils/config/service-helpers"; export async function bookmarksResponse() { @@ -38,9 +38,12 @@ export async function widgetsResponse() { if (!widgets) return []; // map easy to write YAML objects into easy to consume JS arrays - const widgetsArray = widgets.map((group) => ({ + const widgetsArray = widgets.map((group, index) => ({ type: Object.keys(group)[0], - options: { ...group[Object.keys(group)[0]] }, + options: { + index, + ...sanitizePrivateOptions(group[Object.keys(group)[0]]) + }, })); return widgetsArray; diff --git a/src/utils/config/config.js b/src/utils/config/config.js index 16861de81..1f6d13fcb 100644 --- a/src/utils/config/config.js +++ b/src/utils/config/config.js @@ -34,3 +34,16 @@ export function getSettings() { const fileContents = readFileSync(settingsYaml, "utf8"); return yaml.load(fileContents); } + +export function sanitizePrivateOptions(options, privateOnly = false) { + const privateOptions = ["url", "username", "password", "key"]; + const sanitizedOptions = {}; + Object.keys(options).forEach((key) => { + if (!privateOnly && !privateOptions.includes(key)) { + sanitizedOptions[key] = options[key]; + } else if (privateOnly && privateOptions.includes(key)) { + sanitizedOptions[key] = options[key]; + } + }); + return sanitizedOptions; +} \ No newline at end of file diff --git a/src/utils/config/service-helpers.js b/src/utils/config/service-helpers.js index 99ce34d1f..ba58b991d 100644 --- a/src/utils/config/service-helpers.js +++ b/src/utils/config/service-helpers.js @@ -5,7 +5,7 @@ import yaml from "js-yaml"; import Docker from "dockerode"; import * as shvl from "shvl"; -import checkAndCopyConfig from "utils/config/config"; +import checkAndCopyConfig, { sanitizePrivateOptions } from "utils/config/config"; import getDockerArguments from "utils/config/docker"; export async function servicesFromConfig() { @@ -166,3 +166,22 @@ export default async function getServiceWidget(group, service) { return false; } + +export async function getPrivateWidgetOptions(type, index) { + checkAndCopyConfig("widgets.yaml"); + + const widgetsYaml = path.join(process.cwd(), "config", "widgets.yaml"); + const fileContents = await fs.readFile(widgetsYaml, "utf8"); + const widgets = yaml.load(fileContents); + + if (!widgets) return []; + + const privateOptions = widgets.map((group, widgetIndex) => ({ + type: Object.keys(group)[0], + index: widgetIndex, + options: sanitizePrivateOptions(group[Object.keys(group)[0]], true), + })); + + return (type !== undefined && index !== undefined) ? privateOptions.find(o => o.type === type && o.index === parseInt(index, 10))?.options : privateOptions; +} + \ No newline at end of file From c1a55ff6d317910bd4284d339785dba9991c1c9d Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+shamoon@users.noreply.github.com> Date: Tue, 11 Oct 2022 11:16:03 -0700 Subject: [PATCH 02/10] Update glances to use private widget options API --- src/pages/api/widgets/glances.js | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/pages/api/widgets/glances.js b/src/pages/api/widgets/glances.js index 86992dd10..f4b7c010e 100644 --- a/src/pages/api/widgets/glances.js +++ b/src/pages/api/widgets/glances.js @@ -1,29 +1,17 @@ import { httpProxy } from "utils/proxy/http"; import createLogger from "utils/logger"; -import { getSettings } from "utils/config/config"; +import { getPrivateWidgetOptions } from "utils/config/service-helpers"; const logger = createLogger("glances"); export default async function handler(req, res) { - const { id } = req.query; + const { index } = req.query; - let errorMessage; - - let instanceID = "glances"; - if (id) { // multiple instances - instanceID = id; - } - const settings = getSettings(); - const instanceSettings = settings[instanceID]; - if (!instanceSettings) { - errorMessage = id ? `There is no glances section with id '${id}' in settings.yaml` : "There is no glances section in settings.yaml"; - logger.error(errorMessage); - return res.status(400).json({ error: errorMessage }); - } + const privateWidgetOptions = await getPrivateWidgetOptions("glances", index); - const url = instanceSettings?.url; + const url = privateWidgetOptions?.url; if (!url) { - errorMessage = "Missing Glances URL"; + const errorMessage = "Missing Glances URL"; logger.error(errorMessage); return res.status(400).json({ error: errorMessage }); } @@ -32,8 +20,8 @@ export default async function handler(req, res) { const headers = { "Accept-Encoding": "application/json" }; - if (instanceSettings.username && instanceSettings.password) { - headers.Authorization = `Basic ${Buffer.from(`${instanceSettings.username}:${instanceSettings.password}`).toString("base64")}` + if (privateWidgetOptions.username && privateWidgetOptions.password) { + headers.Authorization = `Basic ${Buffer.from(`${privateWidgetOptions.username}:${privateWidgetOptions.password}`).toString("base64")}` } const params = { method: "GET", headers }; From dced9188047f05750b019b3032682ce9789a961d Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+shamoon@users.noreply.github.com> Date: Tue, 11 Oct 2022 11:53:34 -0700 Subject: [PATCH 03/10] Update unifi_console to use private widget options --- .../widgets/unifi_console/unifi_console.jsx | 2 +- src/widgets/unifi/proxy.js | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/components/widgets/unifi_console/unifi_console.jsx b/src/components/widgets/unifi_console/unifi_console.jsx index 7427bd23c..889a517f1 100644 --- a/src/components/widgets/unifi_console/unifi_console.jsx +++ b/src/components/widgets/unifi_console/unifi_console.jsx @@ -10,7 +10,7 @@ export default function Widget({ options }) { // eslint-disable-next-line no-param-reassign options.type = "unifi_console"; - const { data: statsData, error: statsError } = useWidgetAPI(options, "stat/sites"); + const { data: statsData, error: statsError } = useWidgetAPI(options, "stat/sites", { index: options.index }); if (statsError || statsData?.error) { return ( diff --git a/src/widgets/unifi/proxy.js b/src/widgets/unifi/proxy.js index 53ee49f03..890c2c73c 100644 --- a/src/widgets/unifi/proxy.js +++ b/src/widgets/unifi/proxy.js @@ -3,8 +3,7 @@ import cache from "memory-cache"; import { formatApiCall } from "utils/proxy/api-helpers"; import { httpProxy } from "utils/proxy/http"; import { addCookieToJar, setCookieHeader } from "utils/proxy/cookie-jar"; -import { getSettings } from "utils/config/config"; -import getServiceWidget from "utils/config/service-helpers"; +import getServiceWidget, { getPrivateWidgetOptions } from "utils/config/service-helpers"; import createLogger from "utils/logger"; import widgets from "widgets/widgets"; @@ -15,13 +14,13 @@ const logger = createLogger(proxyName); async function getWidget(req) { const { group, service, type } = req.query; - + let widget = null; - if (type === "unifi_console") { - const settings = getSettings(); - widget = settings.unifi_console; + if (type === "unifi_console") { // info widget + const index = req.query?.query ? JSON.parse(req.query.query).index : undefined; + widget = await getPrivateWidgetOptions(type, index); if (!widget) { - logger.debug("There is no unifi_console section in settings.yaml"); + logger.debug("Error retrieving settings for this Unifi widget"); return null; } widget.type = "unifi"; From 48a09e5a99e80959ef494d7e4bbf0b5905c48dc8 Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+shamoon@users.noreply.github.com> Date: Tue, 11 Oct 2022 20:26:07 -0700 Subject: [PATCH 04/10] Refactor info widget sanitizing / privateOptions --- src/pages/api/widgets/glances.js | 2 +- src/utils/config/api-response.js | 28 +++++------ src/utils/config/config.js | 13 ----- src/utils/config/service-helpers.js | 23 +-------- src/utils/config/widget-helpers.js | 73 +++++++++++++++++++++++++++++ src/widgets/unifi/proxy.js | 3 +- 6 files changed, 89 insertions(+), 53 deletions(-) create mode 100644 src/utils/config/widget-helpers.js diff --git a/src/pages/api/widgets/glances.js b/src/pages/api/widgets/glances.js index f4b7c010e..5d4622b8d 100644 --- a/src/pages/api/widgets/glances.js +++ b/src/pages/api/widgets/glances.js @@ -1,6 +1,6 @@ import { httpProxy } from "utils/proxy/http"; import createLogger from "utils/logger"; -import { getPrivateWidgetOptions } from "utils/config/service-helpers"; +import { getPrivateWidgetOptions } from "utils/config/widget-helpers"; const logger = createLogger("glances"); diff --git a/src/utils/config/api-response.js b/src/utils/config/api-response.js index 778877eb1..5cc1127e3 100644 --- a/src/utils/config/api-response.js +++ b/src/utils/config/api-response.js @@ -4,8 +4,9 @@ import path from "path"; import yaml from "js-yaml"; -import checkAndCopyConfig, { sanitizePrivateOptions } from "utils/config/config"; +import checkAndCopyConfig from "utils/config/config"; import { servicesFromConfig, servicesFromDocker, cleanServiceGroups } from "utils/config/service-helpers"; +import { cleanWidgetGroups, widgetsFromConfig } from "utils/config/widget-helpers"; export async function bookmarksResponse() { checkAndCopyConfig("bookmarks.yaml"); @@ -29,24 +30,17 @@ export async function bookmarksResponse() { } export async function widgetsResponse() { - checkAndCopyConfig("widgets.yaml"); + let configuredWidgets; - const widgetsYaml = path.join(process.cwd(), "config", "widgets.yaml"); - const fileContents = await fs.readFile(widgetsYaml, "utf8"); - const widgets = yaml.load(fileContents); - - if (!widgets) return []; - - // map easy to write YAML objects into easy to consume JS arrays - const widgetsArray = widgets.map((group, index) => ({ - type: Object.keys(group)[0], - options: { - index, - ...sanitizePrivateOptions(group[Object.keys(group)[0]]) - }, - })); + try { + configuredWidgets = cleanWidgetGroups(await widgetsFromConfig()); + } catch (e) { + console.error("Failed to load widgets, please check widgets.yaml for errors or remove example entries."); + if (e) console.error(e); + configuredWidgets = []; + } - return widgetsArray; + return configuredWidgets; } export async function servicesResponse() { diff --git a/src/utils/config/config.js b/src/utils/config/config.js index 1f6d13fcb..0003c589d 100644 --- a/src/utils/config/config.js +++ b/src/utils/config/config.js @@ -33,17 +33,4 @@ export function getSettings() { const settingsYaml = join(process.cwd(), "config", "settings.yaml"); const fileContents = readFileSync(settingsYaml, "utf8"); return yaml.load(fileContents); -} - -export function sanitizePrivateOptions(options, privateOnly = false) { - const privateOptions = ["url", "username", "password", "key"]; - const sanitizedOptions = {}; - Object.keys(options).forEach((key) => { - if (!privateOnly && !privateOptions.includes(key)) { - sanitizedOptions[key] = options[key]; - } else if (privateOnly && privateOptions.includes(key)) { - sanitizedOptions[key] = options[key]; - } - }); - return sanitizedOptions; } \ No newline at end of file diff --git a/src/utils/config/service-helpers.js b/src/utils/config/service-helpers.js index ba58b991d..15740d22b 100644 --- a/src/utils/config/service-helpers.js +++ b/src/utils/config/service-helpers.js @@ -5,7 +5,7 @@ import yaml from "js-yaml"; import Docker from "dockerode"; import * as shvl from "shvl"; -import checkAndCopyConfig, { sanitizePrivateOptions } from "utils/config/config"; +import checkAndCopyConfig from "utils/config/config"; import getDockerArguments from "utils/config/docker"; export async function servicesFromConfig() { @@ -165,23 +165,4 @@ export default async function getServiceWidget(group, service) { } return false; -} - -export async function getPrivateWidgetOptions(type, index) { - checkAndCopyConfig("widgets.yaml"); - - const widgetsYaml = path.join(process.cwd(), "config", "widgets.yaml"); - const fileContents = await fs.readFile(widgetsYaml, "utf8"); - const widgets = yaml.load(fileContents); - - if (!widgets) return []; - - const privateOptions = widgets.map((group, widgetIndex) => ({ - type: Object.keys(group)[0], - index: widgetIndex, - options: sanitizePrivateOptions(group[Object.keys(group)[0]], true), - })); - - return (type !== undefined && index !== undefined) ? privateOptions.find(o => o.type === type && o.index === parseInt(index, 10))?.options : privateOptions; -} - \ No newline at end of file +} \ No newline at end of file diff --git a/src/utils/config/widget-helpers.js b/src/utils/config/widget-helpers.js new file mode 100644 index 000000000..c9bdd0fbb --- /dev/null +++ b/src/utils/config/widget-helpers.js @@ -0,0 +1,73 @@ +import { promises as fs } from "fs"; +import path from "path"; + +import yaml from "js-yaml"; + +import checkAndCopyConfig from "utils/config/config"; + +export async function widgetsFromConfig() { + checkAndCopyConfig("widgets.yaml"); + + const widgetsYaml = path.join(process.cwd(), "config", "widgets.yaml"); + const fileContents = await fs.readFile(widgetsYaml, "utf8"); + const widgets = yaml.load(fileContents); + + if (!widgets) return []; + + // map easy to write YAML objects into easy to consume JS arrays + const widgetsArray = widgets.map((group, index) => ({ + type: Object.keys(group)[0], + options: { + index, + ...group[Object.keys(group)[0]] + }, + })); + return widgetsArray; +} + +export async function cleanWidgetGroups(widgets) { + return widgets.map((widget, index) => { + const sanitizedOptions = widget.options; + const optionKeys = Object.keys(sanitizedOptions); + ["url", "username", "password", "key"].forEach((pO) => { + if (optionKeys.includes(pO)) { + delete sanitizedOptions[pO]; + } + }); + + return { + type: widget.type, + options: { + index, + ...sanitizedOptions + }, + } + }); +} + +export async function getPrivateWidgetOptions(type, widgetIndex) { + const widgets = await widgetsFromConfig(); + + const privateOptions = widgets.map((widget) => { + const { + index, + url, + username, + password, + key + } = widget.options; + + return { + type: widget.type, + options: { + index, + url, + username, + password, + key + }, + } + }); + + return (type !== undefined && widgetIndex !== undefined) ? privateOptions.find(o => o.type === type && o.options.index === parseInt(widgetIndex, 10))?.options : privateOptions; +} \ No newline at end of file diff --git a/src/widgets/unifi/proxy.js b/src/widgets/unifi/proxy.js index 890c2c73c..dc1c437b9 100644 --- a/src/widgets/unifi/proxy.js +++ b/src/widgets/unifi/proxy.js @@ -3,7 +3,8 @@ import cache from "memory-cache"; import { formatApiCall } from "utils/proxy/api-helpers"; import { httpProxy } from "utils/proxy/http"; import { addCookieToJar, setCookieHeader } from "utils/proxy/cookie-jar"; -import getServiceWidget, { getPrivateWidgetOptions } from "utils/config/service-helpers"; +import getServiceWidget from "utils/config/service-helpers"; +import { getPrivateWidgetOptions } from "utils/config/widget-helpers"; import createLogger from "utils/logger"; import widgets from "widgets/widgets"; From ce6a6ad723ac8bc4a478e8b7f7f41d144614d389 Mon Sep 17 00:00:00 2001 From: Paco Culebras <69261057+pacoculebras@users.noreply.github.com> Date: Sun, 16 Oct 2022 19:15:32 +0200 Subject: [PATCH 05/10] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2eeb6dc9f..1630d1bad 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ - Images built for AMD64 (x86_64), ARM64, ARMv7 and ARMv6 - Supports all Raspberry Pi's, most SBCs & Apple Silicon - Full i18n support with automatic language detection - - Translantions for Catalan, Chinese, Dutch, Finnish, French, German, Hebrew, Hungarian, Norwegian Bokmål, Polish, Portuguese, Portuguese (Brazil), Romainian, Russian, Spanish, Swedish and Yue + - Translations for Catalan, Chinese, Dutch, Finnish, French, German, Hebrew, Hungarian, Norwegian Bokmål, Polish, Portuguese, Portuguese (Brazil), Romainian, Russian, Spanish, Swedish and Yue - Want to help translate? [Join the Weblate project](https://hosted.weblate.org/engage/homepage/) - Service & Web Bookmarks - Docker Integration From a486cc46fa030e519308174838f3a310364f06b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Fern=C3=A1ndez=20S=C3=A1nchez?= Date: Wed, 12 Oct 2022 08:53:58 +0000 Subject: [PATCH 06/10] Translated using Weblate (Spanish) Currently translated at 100.0% (138 of 138 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/ --- public/locales/es/common.json | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/public/locales/es/common.json b/public/locales/es/common.json index 7335f88b0..25e153a16 100644 --- a/public/locales/es/common.json +++ b/public/locales/es/common.json @@ -178,28 +178,28 @@ "proxmox": { "mem": "Memoria", "cpu": "Procesador", - "lxc": "LXC", - "vms": "VMs" + "lxc": "Contenedores Linux", + "vms": "Máquinas Virtuales" }, "unifi": { - "up": "UP", - "users": "Users", - "uptime": "System Uptime", - "days": "Days", - "wan": "WAN", - "lan_users": "LAN Users", - "wlan_users": "WLAN Users", - "down": "DOWN", - "wait": "Please wait" + "up": "LEVANTADO", + "users": "Usuarios", + "uptime": "Tiempo de actividad", + "days": "Días", + "wan": "Red WAN", + "lan_users": "Usuarios LAN", + "wlan_users": "Usuarios WLAN", + "down": "CAÍDO", + "wait": "Espere por favor" }, "plex": { - "streams": "Active Streams", - "movies": "Movies", - "tv": "TV Shows" + "streams": "Transmisiones Activas", + "movies": "Peliculas", + "tv": "Programas TV" }, "glances": { - "cpu": "CPU", - "mem": "MEM", - "wait": "Please wait" + "cpu": "Procesador", + "mem": "Memoria", + "wait": "Espere por favor" } } From 472edbdcc6a786df4ffd879b3d350ddadbc7671e Mon Sep 17 00:00:00 2001 From: Nonoss117 Date: Wed, 12 Oct 2022 08:51:11 +0000 Subject: [PATCH 07/10] Translated using Weblate (French) Currently translated at 100.0% (138 of 138 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/fr/ --- public/locales/fr/common.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/locales/fr/common.json b/public/locales/fr/common.json index 2f49a82ea..b9e57dd38 100644 --- a/public/locales/fr/common.json +++ b/public/locales/fr/common.json @@ -198,8 +198,8 @@ "tv": "Séries TV" }, "glances": { - "cpu": "CPU", - "mem": "MEM", - "wait": "Please wait" + "cpu": "Cpu", + "mem": "Mém", + "wait": "Merci de patienter" } } From 8f8fa50e43f53de01825f3e72e4044aa58d3790b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?yahoo=EF=BD=9E=EF=BD=9E?= Date: Fri, 14 Oct 2022 07:29:40 +0000 Subject: [PATCH 08/10] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (138 of 138 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/zh_Hans/ --- public/locales/zh-CN/common.json | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/public/locales/zh-CN/common.json b/public/locales/zh-CN/common.json index 6592fb1e6..f0229a631 100644 --- a/public/locales/zh-CN/common.json +++ b/public/locales/zh-CN/common.json @@ -161,7 +161,7 @@ }, "mastodon": { "user_count": "用户", - "status_count": "Posts", + "status_count": "帖子", "domain_count": "域" }, "strelaysrv": { @@ -182,24 +182,24 @@ "vms": "VMs" }, "unifi": { - "users": "Users", - "uptime": "System Uptime", - "days": "Days", - "wan": "WAN", - "lan_users": "LAN Users", - "wlan_users": "WLAN Users", - "up": "UP", - "down": "DOWN", + "users": "用户", + "uptime": "系统运行时间", + "days": "天", + "wan": "广域网", + "lan_users": "局域网用户", + "wlan_users": "无线局域网用户", + "up": "向上", + "down": "向下", "wait": "请稍候" }, "plex": { - "streams": "Active Streams", - "movies": "Movies", - "tv": "TV Shows" + "streams": "活动流", + "movies": "电影", + "tv": "电视节目" }, "glances": { - "cpu": "CPU", - "mem": "MEM", - "wait": "Please wait" + "cpu": "处理器", + "mem": "内存", + "wait": "请稍等" } } From f8000756dc5a7a04656694f88e0ef5b97f02043a Mon Sep 17 00:00:00 2001 From: Serhan S Date: Sun, 16 Oct 2022 10:58:38 +0000 Subject: [PATCH 09/10] Translated using Weblate (German) Currently translated at 95.6% (132 of 138 strings) Translation: Homepage/Homepage Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/de/ --- public/locales/de/common.json | 36 +++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/public/locales/de/common.json b/public/locales/de/common.json index 3dbe8bebd..4512ad7b0 100644 --- a/public/locales/de/common.json +++ b/public/locales/de/common.json @@ -11,7 +11,7 @@ "total": "Gesamt", "free": "Frei", "used": "Gebraucht", - "load": "Belastung", + "load": "Last", "cpu": "CPU" }, "docker": { @@ -25,13 +25,13 @@ "playing": "Spielen", "transcoding": "Transcodierung", "bitrate": "Bitrate", - "no_active": "Keine aktive Streams" + "no_active": "Keine aktiven Streams" }, "tautulli": { "playing": "Spielen", "transcoding": "Transcodierung", "bitrate": "Bitrate", - "no_active": "Keine aktiven streamen" + "no_active": "Keine aktiven Streams" }, "rutorrent": { "active": "Aktiv", @@ -41,7 +41,7 @@ "sonarr": { "wanted": "Gesucht", "queued": "In Warteschlange", - "series": "Serie" + "series": "Serien" }, "radarr": { "wanted": "Gesucht", @@ -176,30 +176,30 @@ "failedLoginsLast24H": "fehlerhafte Anmeldungen (24h)" }, "proxmox": { - "mem": "MEM", + "mem": "RAM", "cpu": "CPU", "lxc": "LXC", "vms": "VMs" }, "unifi": { - "users": "Users", - "uptime": "System Uptime", - "days": "Days", + "users": "Benutzer", + "uptime": "System-Betriebszeit", + "days": "Tage", "wan": "WAN", - "lan_users": "LAN Users", - "wlan_users": "WLAN Users", - "up": "UP", - "down": "DOWN", - "wait": "Please wait" + "lan_users": "LAN Benutzer", + "wlan_users": "WLAN Benutzer", + "up": "SENDEN", + "down": "EMPFANGEN", + "wait": "Bitte warten" }, "plex": { - "streams": "Active Streams", - "movies": "Movies", - "tv": "TV Shows" + "streams": "Aktive Streams", + "movies": "Filme", + "tv": "TV Sendungen" }, "glances": { "cpu": "CPU", - "mem": "MEM", - "wait": "Please wait" + "mem": "RAM", + "wait": "Bitte warten" } } From 4ec8fc1350ccff5b1e44d28dfd9ff1a10bd492bd Mon Sep 17 00:00:00 2001 From: Ben Phelps Date: Mon, 17 Oct 2022 15:10:32 +0300 Subject: [PATCH 10/10] add changelog link to version --- src/components/version.jsx | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/components/version.jsx b/src/components/version.jsx index 522112191..bc142e925 100644 --- a/src/components/version.jsx +++ b/src/components/version.jsx @@ -31,7 +31,23 @@ export default function Version() { return (
- {version} ({revision.substring(0, 7)}, {formatDate(buildTime)}) + {version === "main" || version === "dev" || version === "nightly" ? ( + <> + {version} ({revision.substring(0, 7)}, {formatDate(buildTime)}) + + ) : ( + releaseData && + compareVersions(latestRelease.tag_name, version) > 0 && ( + + {version} ({revision.substring(0, 7)}, {formatDate(buildTime)}) + + ) + )} {version === "main" || version === "dev" || version === "nightly" ? null