From ece564ea77ff2a953ee95c6021aaa74181aa7762 Mon Sep 17 00:00:00 2001 From: UNITRONIX <36471318+UNITRONIX@users.noreply.github.com> Date: Fri, 23 Oct 2026 11:20:03 +0200 Subject: [PATCH] feat(devices): manage rename and delete device tags Add scoped tag rename/delete APIs and Devices UI (Manage tags modal, context menu, edit/detail hints) so operators can retire or rename tags without editing every peer. Refs #470 Thanks: INSOLVE (Honorary); Marco Jakobs (@jacotec); MyNameisStitch (@MyNameisStitch); Redspin (@playerumpknow); muopc (@muopc) --- CHANGELOG.md | 3 + web-nodejs/lang/ar.json | 24 ++- web-nodejs/lang/cs.json | 24 ++- web-nodejs/lang/da.json | 24 ++- web-nodejs/lang/de.json | 24 ++- web-nodejs/lang/en.json | 20 ++ web-nodejs/lang/es.json | 24 ++- web-nodejs/lang/fi.json | 24 ++- web-nodejs/lang/fr.json | 24 ++- web-nodejs/lang/hi.json | 24 ++- web-nodejs/lang/hu.json | 24 ++- web-nodejs/lang/id.json | 24 ++- web-nodejs/lang/it.json | 24 ++- web-nodejs/lang/ja.json | 24 ++- web-nodejs/lang/ko.json | 24 ++- web-nodejs/lang/nb.json | 24 ++- web-nodejs/lang/nl.json | 24 ++- web-nodejs/lang/pl.json | 24 ++- web-nodejs/lang/pt.json | 24 ++- web-nodejs/lang/ro.json | 24 ++- web-nodejs/lang/sv.json | 24 ++- web-nodejs/lang/th.json | 24 ++- web-nodejs/lang/tr.json | 24 ++- web-nodejs/lang/uk.json | 24 ++- web-nodejs/lang/vi.json | 24 ++- web-nodejs/lang/zh-TW.json | 24 ++- web-nodejs/lang/zh.json | 24 ++- web-nodejs/public/css/device-detail.css | 6 + web-nodejs/public/css/devices.css | 68 ++++++ web-nodejs/public/js/deviceDetail.js | 3 +- web-nodejs/public/js/devices.js | 190 ++++++++++++++++- web-nodejs/routes/devices.routes.js | 129 +++++++++++ web-nodejs/services/tagManagementService.js | 200 ++++++++++++++++++ web-nodejs/tests/devices.routes.test.js | 138 +++++++++++- web-nodejs/tests/tagManagementService.test.js | 84 ++++++++ web-nodejs/views/devices.ejs | 3 + 36 files changed, 1388 insertions(+), 56 deletions(-) create mode 100644 web-nodejs/services/tagManagementService.js create mode 100644 web-nodejs/tests/tagManagementService.test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index a872876e..06bd3118 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ## [Unreleased] +### Added +- **Device tags management (#470):** Operators can rename or delete tags across all visible devices from Devices → Manage tags, unassign tags per device in Edit / Details / context menu, and matching dynamic group filters update on rename. Ships via panel update. + ### Changed - _(none yet)_ diff --git a/web-nodejs/lang/ar.json b/web-nodejs/lang/ar.json index 8820b885..ea7522d9 100644 --- a/web-nodejs/lang/ar.json +++ b/web-nodejs/lang/ar.json @@ -442,7 +442,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "إدارة الوسوم", + "manage_device_tags": "إدارة الوسوم", + "rename_tag": "إعادة تسمية الوسم", + "delete_tag": "حذف الوسم", + "rename_tag_prompt": "اسم الوسم الجديد", + "rename_tag_hint": "يعيد تسمية هذا الوسم على كل الأجهزة المرئية ويحدّث المجموعات الديناميكية المطابقة.", + "delete_tag_confirm": "إزالة الوسم \"{tag}\" من {count} جهاز/أجهزة؟ ستصبح المجموعات الديناميكية التي تستخدمه فارغة حتى التحديث.", + "tag_renamed": "تمت إعادة تسمية الوسم", + "tag_deleted": "تم حذف الوسم", + "tag_name_required": "اسم الوسم مطلوب", + "tag_rename_identical": "يجب أن يكون الاسم الجديد مختلفاً", + "tags_backend_unsupported": "وسوم الأجهزة غير مدعومة مع الخلفية الحالية", + "tags_manage_hint": "أعد تسمية الوسوم أو احذفها على كل الأجهزة المرئية. الإزالة من جهاز واحد تتم في التعديل أو التفاصيل.", + "tags_device_hint": "أزل وسماً هنا لإلغاء تعيينه من هذا الجهاز فقط. استخدم إدارة الوسوم لإعادة التسمية أو الحذف في كل مكان.", + "unassign_tag": "إزالة من هذا الجهاز", + "tag_device_one": "جهاز", + "tag_device_many": "أجهزة", + "tag_group_one": "مجموعة ديناميكية", + "tag_group_many": "مجموعات ديناميكية" }, "keys": { "title": "مفاتيح الخادم", @@ -1776,7 +1795,8 @@ "sessions_col_duration": "المدة", "sessions_active": "نشطة", "sessions_transport_punch": "مباشر / punch", - "sessions_transport_relay": "Relay" + "sessions_transport_relay": "Relay", + "tags_unassign_hint": "إزالة وسم هنا تلغي تعيينه من هذا الجهاز فقط. استخدم إدارة الوسوم في صفحة الأجهزة لإعادة التسمية أو الحذف في كل مكان." }, "inventory": { "title": "Inventory", diff --git a/web-nodejs/lang/cs.json b/web-nodejs/lang/cs.json index f222182c..fc3e4eb9 100644 --- a/web-nodejs/lang/cs.json +++ b/web-nodejs/lang/cs.json @@ -435,7 +435,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "Spravovat štítky", + "manage_device_tags": "Spravovat štítky", + "rename_tag": "Přejmenovat štítek", + "delete_tag": "Smazat štítek", + "rename_tag_prompt": "Nový název štítku", + "rename_tag_hint": "Přejmenuje tento štítek na všech viditelných zařízeních a aktualizuje odpovídající dynamické skupiny.", + "delete_tag_confirm": "Odebrat štítek \"{tag}\" z {count} zařízení? Dynamické skupiny používající tento štítek budou prázdné do aktualizace.", + "tag_renamed": "Štítek přejmenován", + "tag_deleted": "Štítek smazán", + "tag_name_required": "Název štítku je povinný", + "tag_rename_identical": "Nový název musí být jiný", + "tags_backend_unsupported": "Štítky zařízení nejsou s aktuálním backendem podporovány", + "tags_manage_hint": "Přejmenujte nebo smažte štítky na všech viditelných zařízeních. Odebrání z jednoho zařízení je v Upravit nebo Podrobnostech.", + "tags_device_hint": "Odeberte štítek zde, abyste jej odpojili jen od tohoto zařízení. Pro globální změnu použijte Spravovat štítky.", + "unassign_tag": "Odebrat z tohoto zařízení", + "tag_device_one": "zařízení", + "tag_device_many": "zařízení", + "tag_group_one": "dynamická skupina", + "tag_group_many": "dynamických skupin" }, "keys": { "title": "Klíče serveru", @@ -1769,7 +1788,8 @@ "sessions_col_duration": "Trvání", "sessions_active": "Aktivní", "sessions_transport_punch": "Přímé / punch", - "sessions_transport_relay": "Relay" + "sessions_transport_relay": "Relay", + "tags_unassign_hint": "Odebrání štítku zde jej odpojí jen od tohoto zařízení. Pro globální změnu použijte Spravovat štítky na stránce Zařízení." }, "inventory": { "title": "Inventář", diff --git a/web-nodejs/lang/da.json b/web-nodejs/lang/da.json index bf8e5a58..12f143bf 100644 --- a/web-nodejs/lang/da.json +++ b/web-nodejs/lang/da.json @@ -441,7 +441,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "Administrer tags", + "manage_device_tags": "Administrer tags", + "rename_tag": "Omdøb tag", + "delete_tag": "Slet tag", + "rename_tag_prompt": "Nyt tagnavn", + "rename_tag_hint": "Omdøber dette tag på alle synlige enheder og opdaterer matchende dynamiske grupper.", + "delete_tag_confirm": "Fjern tagget \"{tag}\" fra {count} enhed(er)? Dynamiske grupper der bruger det bliver tomme indtil opdatering.", + "tag_renamed": "Tag omdøbt", + "tag_deleted": "Tag slettet", + "tag_name_required": "Tagnavn er påkrævet", + "tag_rename_identical": "Det nye tagnavn skal være anderledes", + "tags_backend_unsupported": "Enhedstags understøttes ikke med den aktuelle backend", + "tags_manage_hint": "Omdøb eller slet tags på alle synlige enheder. Fjernelse fra én enhed sker under Rediger eller Detaljer.", + "tags_device_hint": "Fjern et tag her for kun at fjerne det fra denne enhed. Brug Administrer tags til at omdøbe eller slette overalt.", + "unassign_tag": "Fjern fra denne enhed", + "tag_device_one": "enhed", + "tag_device_many": "enheder", + "tag_group_one": "dynamisk gruppe", + "tag_group_many": "dynamiske grupper" }, "keys": { "title": "Servernøgler", @@ -1775,7 +1794,8 @@ "sessions_col_duration": "Varighed", "sessions_active": "Aktiv", "sessions_transport_punch": "Direkte / punch", - "sessions_transport_relay": "Relay" + "sessions_transport_relay": "Relay", + "tags_unassign_hint": "Fjernelse af et tag her fjerner det kun fra denne enhed. Brug Administrer tags på Enheder til at omdøbe eller slette overalt." }, "inventory": { "title": "Inventory", diff --git a/web-nodejs/lang/de.json b/web-nodejs/lang/de.json index c5011b2a..ca92e127 100644 --- a/web-nodejs/lang/de.json +++ b/web-nodejs/lang/de.json @@ -435,7 +435,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "Tags verwalten", + "manage_device_tags": "Tags verwalten", + "rename_tag": "Tag umbenennen", + "delete_tag": "Tag löschen", + "rename_tag_prompt": "Neuer Tagname", + "rename_tag_hint": "Benennt diesen Tag auf allen sichtbaren Geräten um und aktualisiert passende dynamische Gruppen.", + "delete_tag_confirm": "Tag \"{tag}\" von {count} Gerät(en) entfernen? Dynamische Gruppen mit diesem Tag bleiben bis zur Aktualisierung leer.", + "tag_renamed": "Tag umbenannt", + "tag_deleted": "Tag gelöscht", + "tag_name_required": "Tagname ist erforderlich", + "tag_rename_identical": "Der neue Tagname muss anders sein", + "tags_backend_unsupported": "Geräte-Tags werden mit dem aktuellen Backend nicht unterstützt", + "tags_manage_hint": "Tags auf allen sichtbaren Geräten umbenennen oder löschen. Entfernen von einem Gerät erfolgt in Bearbeiten oder Gerätedetails.", + "tags_device_hint": "Entfernen Sie einen Tag hier, um ihn nur von diesem Gerät zu lösen. Nutzen Sie Tags verwalten zum globalen Umbenennen oder Löschen.", + "unassign_tag": "Von diesem Gerät entfernen", + "tag_device_one": "Gerät", + "tag_device_many": "Geräte", + "tag_group_one": "dynamische Gruppe", + "tag_group_many": "dynamische Gruppen" }, "keys": { "title": "Dashboard", @@ -1769,7 +1788,8 @@ "sessions_col_duration": "Dauer", "sessions_active": "Aktiv", "sessions_transport_punch": "Direkt / Punch", - "sessions_transport_relay": "Relay" + "sessions_transport_relay": "Relay", + "tags_unassign_hint": "Das Entfernen eines Tags hier hebt die Zuweisung nur für dieses Gerät auf. Nutzen Sie Tags verwalten auf der Geräte-Seite zum globalen Umbenennen oder Löschen." }, "inventory": { "title": "Dashboard", diff --git a/web-nodejs/lang/en.json b/web-nodejs/lang/en.json index 98b29ecc..ac5e46b5 100644 --- a/web-nodejs/lang/en.json +++ b/web-nodejs/lang/en.json @@ -320,6 +320,25 @@ "access_policy": "Access Policy", "filter_by_tags": "Filter by tags", "no_tags": "No tags", + "manage_tags": "Manage tags", + "manage_device_tags": "Manage tags", + "rename_tag": "Rename tag", + "delete_tag": "Delete tag", + "rename_tag_prompt": "New tag name", + "rename_tag_hint": "Renames this tag on all devices you can see and updates matching dynamic groups.", + "delete_tag_confirm": "Remove tag \"{tag}\" from {count} device(s)? Dynamic groups that use this tag will become empty until updated.", + "tag_renamed": "Tag renamed", + "tag_deleted": "Tag deleted", + "tag_name_required": "Tag name is required", + "tag_rename_identical": "New tag name must be different", + "tags_backend_unsupported": "Device tags are not supported with the current backend", + "tags_manage_hint": "Rename or delete tags across all devices you can see. Removing a tag from one device is done in Edit or Device details.", + "tags_device_hint": "Remove a tag here to unassign it from this device only. Use Manage Tags to rename or delete a tag everywhere.", + "unassign_tag": "Remove from this device", + "tag_device_one": "device", + "tag_device_many": "devices", + "tag_group_one": "dynamic group", + "tag_group_many": "dynamic groups", "all_groups": "All groups", "create_group": "Create group", "manage_groups": "Manage Groups", @@ -1736,6 +1755,7 @@ "tag_placeholder": "Enter a tag name...", "add_tag": "Add", "tag_exists": "This tag already exists", + "tags_unassign_hint": "Removing a tag here unassigns it from this device only. Use Manage Tags on the Devices page to rename or delete a tag everywhere.", "notes": "Notes", "notes_placeholder": "Add notes about this device...", "danger_zone": "Danger Zone", diff --git a/web-nodejs/lang/es.json b/web-nodejs/lang/es.json index 2c825e09..4ce2754b 100644 --- a/web-nodejs/lang/es.json +++ b/web-nodejs/lang/es.json @@ -435,7 +435,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "Administrar etiquetas", + "manage_device_tags": "Administrar etiquetas", + "rename_tag": "Renombrar etiqueta", + "delete_tag": "Eliminar etiqueta", + "rename_tag_prompt": "Nuevo nombre de etiqueta", + "rename_tag_hint": "Renombra esta etiqueta en todos los dispositivos visibles y actualiza los grupos dinámicos coincidentes.", + "delete_tag_confirm": "¿Quitar la etiqueta \"{tag}\" de {count} dispositivo(s)? Los grupos dinámicos que la usan quedarán vacíos hasta actualizarlos.", + "tag_renamed": "Etiqueta renombrada", + "tag_deleted": "Etiqueta eliminada", + "tag_name_required": "El nombre de etiqueta es obligatorio", + "tag_rename_identical": "El nuevo nombre debe ser distinto", + "tags_backend_unsupported": "Las etiquetas de dispositivos no son compatibles con el backend actual", + "tags_manage_hint": "Renombre o elimine etiquetas en todos los dispositivos visibles. Quitar una etiqueta de un dispositivo se hace en Editar o Detalles.", + "tags_device_hint": "Quite una etiqueta aquí para desasignarla solo de este dispositivo. Use Administrar etiquetas para renombrar o eliminar en todas partes.", + "unassign_tag": "Quitar de este dispositivo", + "tag_device_one": "dispositivo", + "tag_device_many": "dispositivos", + "tag_group_one": "grupo dinámico", + "tag_group_many": "grupos dinámicos" }, "keys": { "title": "Panel", @@ -1769,7 +1788,8 @@ "sessions_col_duration": "Duración", "sessions_active": "Activa", "sessions_transport_punch": "Directo / punch", - "sessions_transport_relay": "Relay" + "sessions_transport_relay": "Relay", + "tags_unassign_hint": "Quitar una etiqueta aquí la desasigna solo de este dispositivo. Use Administrar etiquetas en Dispositivos para renombrar o eliminar en todas partes." }, "inventory": { "title": "Panel", diff --git a/web-nodejs/lang/fi.json b/web-nodejs/lang/fi.json index 7c9b0393..81ba741e 100644 --- a/web-nodejs/lang/fi.json +++ b/web-nodejs/lang/fi.json @@ -441,7 +441,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "Hallitse tageja", + "manage_device_tags": "Hallitse tageja", + "rename_tag": "Nimeä tagi uudelleen", + "delete_tag": "Poista tagi", + "rename_tag_prompt": "Uusi tagin nimi", + "rename_tag_hint": "Nimeää tämän tagin uudelleen kaikilla näkyvillä laitteilla ja päivittää vastaavat dynaamiset ryhmät.", + "delete_tag_confirm": "Poistetaanko tagi \"{tag}\" {count} laitteelta? Dynaamiset ryhmät, jotka käyttävät sitä, ovat tyhjiä päivitykseen asti.", + "tag_renamed": "Tagi nimetty uudelleen", + "tag_deleted": "Tagi poistettu", + "tag_name_required": "Tagin nimi on pakollinen", + "tag_rename_identical": "Uuden nimen on oltava eri", + "tags_backend_unsupported": "Laitetageja ei tueta nykyisellä backendillä", + "tags_manage_hint": "Nimeä uudelleen tai poista tageja kaikilta näkyviltä laitteilta. Poisto yhdeltä laitteelta tehdään Muokkaa- tai Tiedot-näkymässä.", + "tags_device_hint": "Poista tagi täällä irrottaaksesi sen vain tältä laitteelta. Käytä Hallitse tageja globaaliin uudelleennimeämiseen tai poistoon.", + "unassign_tag": "Poista tältä laitteelta", + "tag_device_one": "laite", + "tag_device_many": "laitetta", + "tag_group_one": "dynaaminen ryhmä", + "tag_group_many": "dynaamista ryhmää" }, "keys": { "title": "Palvelimen avaimet", @@ -1775,7 +1794,8 @@ "sessions_col_duration": "Kesto", "sessions_active": "Aktiivinen", "sessions_transport_punch": "Suora / punch", - "sessions_transport_relay": "Relay" + "sessions_transport_relay": "Relay", + "tags_unassign_hint": "Tagin poisto täällä irrottaa sen vain tältä laitteelta. Käytä Hallitse tageja Laitteet-sivulla globaaliin muutokseen." }, "inventory": { "title": "Inventory", diff --git a/web-nodejs/lang/fr.json b/web-nodejs/lang/fr.json index 44ca4bf3..b54a2be0 100644 --- a/web-nodejs/lang/fr.json +++ b/web-nodejs/lang/fr.json @@ -439,7 +439,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "Gérer les balises", + "manage_device_tags": "Gérer les balises", + "rename_tag": "Renommer la balise", + "delete_tag": "Supprimer la balise", + "rename_tag_prompt": "Nouveau nom de balise", + "rename_tag_hint": "Renomme cette balise sur tous les appareils visibles et met à jour les groupes dynamiques correspondants.", + "delete_tag_confirm": "Retirer la balise \"{tag}\" de {count} appareil(s) ? Les groupes dynamiques qui l’utilisent seront vides jusqu’à mise à jour.", + "tag_renamed": "Balise renommée", + "tag_deleted": "Balise supprimée", + "tag_name_required": "Le nom de balise est requis", + "tag_rename_identical": "Le nouveau nom doit être différent", + "tags_backend_unsupported": "Les balises d’appareils ne sont pas prises en charge avec le backend actuel", + "tags_manage_hint": "Renommez ou supprimez des balises sur tous les appareils visibles. Retirer une balise d’un appareil se fait dans Modifier ou Détails.", + "tags_device_hint": "Retirez une balise ici pour la désassigner de cet appareil uniquement. Utilisez Gérer les balises pour renommer ou supprimer partout.", + "unassign_tag": "Retirer de cet appareil", + "tag_device_one": "appareil", + "tag_device_many": "appareils", + "tag_group_one": "groupe dynamique", + "tag_group_many": "groupes dynamiques" }, "keys": { "title": "Tableau de bord", @@ -1786,7 +1805,8 @@ "sessions_col_duration": "Durée", "sessions_active": "Active", "sessions_transport_punch": "Direct / punch", - "sessions_transport_relay": "Relay" + "sessions_transport_relay": "Relay", + "tags_unassign_hint": "Retirer une balise ici la désassigne uniquement de cet appareil. Utilisez Gérer les balises sur la page Appareils pour renommer ou supprimer partout." }, "inventory": { "title": "Tableau de bord", diff --git a/web-nodejs/lang/hi.json b/web-nodejs/lang/hi.json index ef4aaf74..de7a4345 100644 --- a/web-nodejs/lang/hi.json +++ b/web-nodejs/lang/hi.json @@ -441,7 +441,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "टैग प्रबंधित करें", + "manage_device_tags": "टैग प्रबंधित करें", + "rename_tag": "टैग का नाम बदलें", + "delete_tag": "टैग हटाएँ", + "rename_tag_prompt": "नया टैग नाम", + "rename_tag_hint": "इस टैग का नाम सभी दिखाई देने वाले उपकरणों पर बदलता है और मेल खाते गतिशील समूह अपडेट करता है।", + "delete_tag_confirm": "टैग \"{tag}\" को {count} उपकरण(ों) से हटाएँ? इसे उपयोग करने वाले गतिशील समूह अपडेट तक खाली रहेंगे।", + "tag_renamed": "टैग का नाम बदला गया", + "tag_deleted": "टैग हटाया गया", + "tag_name_required": "टैग नाम आवश्यक है", + "tag_rename_identical": "नया नाम अलग होना चाहिए", + "tags_backend_unsupported": "वर्तमान बैकएंड के साथ उपकरण टैग समर्थित नहीं हैं", + "tags_manage_hint": "सभी दिखाई देने वाले उपकरणों पर टैग का नाम बदलें या हटाएँ। एक उपकरण से हटाना संपादन या विवरण में होता है।", + "tags_device_hint": "यहाँ टैग हटाकर केवल इस उपकरण से अनअसाइन करें। सर्वत्र बदलने के लिए टैग प्रबंधित करें उपयोग करें।", + "unassign_tag": "इस उपकरण से हटाएँ", + "tag_device_one": "उपकरण", + "tag_device_many": "उपकरण", + "tag_group_one": "गतिशील समूह", + "tag_group_many": "गतिशील समूह" }, "keys": { "title": "सर्वर कुंजी", @@ -1775,7 +1794,8 @@ "sessions_col_duration": "अवधि", "sessions_active": "सक्रिय", "sessions_transport_punch": "प्रत्यक्ष / punch", - "sessions_transport_relay": "Relay" + "sessions_transport_relay": "Relay", + "tags_unassign_hint": "यहाँ टैग हटाने से केवल इस उपकरण से अनअसाइन होता है। सर्वत्र बदलने के लिए उपकरण पृष्ठ पर टैग प्रबंधित करें उपयोग करें।" }, "inventory": { "title": "Inventory", diff --git a/web-nodejs/lang/hu.json b/web-nodejs/lang/hu.json index becef912..04fde3f0 100644 --- a/web-nodejs/lang/hu.json +++ b/web-nodejs/lang/hu.json @@ -441,7 +441,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "Címkék kezelése", + "manage_device_tags": "Címkék kezelése", + "rename_tag": "Címke átnevezése", + "delete_tag": "Címke törlése", + "rename_tag_prompt": "Új címkenév", + "rename_tag_hint": "Átnevezi ezt a címkét minden látható eszközön, és frissíti a megfelelő dinamikus csoportokat.", + "delete_tag_confirm": "Eltávolítja a(z) \"{tag}\" címkét {count} eszközről? A címkét használó dinamikus csoportok üresek maradnak a frissítésig.", + "tag_renamed": "Címke átnevezve", + "tag_deleted": "Címke törölve", + "tag_name_required": "A címkenév kötelező", + "tag_rename_identical": "Az új névnek különböznie kell", + "tags_backend_unsupported": "Az eszközcímkék nem támogatottak a jelenlegi backenddel", + "tags_manage_hint": "Nevezzen át vagy töröljön címkéket minden látható eszközön. Egy eszközről az Edit / Részletek alatt vehető le.", + "tags_device_hint": "Itt távolítsa el a címkét, hogy csak erről az eszközről legyen leválasztva. Globális műveletekhez használja a Címkék kezelése gombot.", + "unassign_tag": "Eltávolítás erről az eszközről", + "tag_device_one": "eszköz", + "tag_device_many": "eszköz", + "tag_group_one": "dinamikus csoport", + "tag_group_many": "dinamikus csoport" }, "keys": { "title": "Szerverkulcsok", @@ -1775,7 +1794,8 @@ "sessions_col_duration": "Időtartam", "sessions_active": "Aktív", "sessions_transport_punch": "Közvetlen / punch", - "sessions_transport_relay": "Relay" + "sessions_transport_relay": "Relay", + "tags_unassign_hint": "A címke eltávolítása itt csak erről az eszközről veszi le. Globális műveletekhez használja a Címkék kezelése gombot az Eszközök oldalon." }, "inventory": { "title": "Inventory", diff --git a/web-nodejs/lang/id.json b/web-nodejs/lang/id.json index 9ed7e9e4..1b9ee765 100644 --- a/web-nodejs/lang/id.json +++ b/web-nodejs/lang/id.json @@ -441,7 +441,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "Kelola tag", + "manage_device_tags": "Kelola tag", + "rename_tag": "Ganti nama tag", + "delete_tag": "Hapus tag", + "rename_tag_prompt": "Nama tag baru", + "rename_tag_hint": "Mengganti nama tag ini pada semua perangkat yang terlihat dan memperbarui grup dinamis yang cocok.", + "delete_tag_confirm": "Hapus tag \"{tag}\" dari {count} perangkat? Grup dinamis yang memakai tag ini akan kosong hingga diperbarui.", + "tag_renamed": "Tag diganti nama", + "tag_deleted": "Tag dihapus", + "tag_name_required": "Nama tag wajib diisi", + "tag_rename_identical": "Nama baru harus berbeda", + "tags_backend_unsupported": "Tag perangkat tidak didukung dengan backend saat ini", + "tags_manage_hint": "Ganti nama atau hapus tag di semua perangkat yang terlihat. Lepas dari satu perangkat lewat Edit atau Detail.", + "tags_device_hint": "Hapus tag di sini untuk melepasnya hanya dari perangkat ini. Gunakan Kelola tag untuk perubahan global.", + "unassign_tag": "Hapus dari perangkat ini", + "tag_device_one": "perangkat", + "tag_device_many": "perangkat", + "tag_group_one": "grup dinamis", + "tag_group_many": "grup dinamis" }, "keys": { "title": "Kunci Server", @@ -1775,7 +1794,8 @@ "sessions_col_duration": "Durasi", "sessions_active": "Aktif", "sessions_transport_punch": "Langsung / punch", - "sessions_transport_relay": "Relay" + "sessions_transport_relay": "Relay", + "tags_unassign_hint": "Menghapus tag di sini hanya melepasnya dari perangkat ini. Gunakan Kelola tag di halaman Perangkat untuk perubahan global." }, "inventory": { "title": "Inventory", diff --git a/web-nodejs/lang/it.json b/web-nodejs/lang/it.json index 0916328b..2fd45f87 100644 --- a/web-nodejs/lang/it.json +++ b/web-nodejs/lang/it.json @@ -435,7 +435,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "Gestisci tag", + "manage_device_tags": "Gestisci tag", + "rename_tag": "Rinomina tag", + "delete_tag": "Elimina tag", + "rename_tag_prompt": "Nuovo nome tag", + "rename_tag_hint": "Rinomina questo tag su tutti i dispositivi visibili e aggiorna i gruppi dinamici corrispondenti.", + "delete_tag_confirm": "Rimuovere il tag \"{tag}\" da {count} dispositivo/i? I gruppi dinamici che lo usano resteranno vuoti fino all’aggiornamento.", + "tag_renamed": "Tag rinominato", + "tag_deleted": "Tag eliminato", + "tag_name_required": "Il nome del tag è obbligatorio", + "tag_rename_identical": "Il nuovo nome deve essere diverso", + "tags_backend_unsupported": "I tag dei dispositivi non sono supportati con il backend attuale", + "tags_manage_hint": "Rinomina o elimina i tag su tutti i dispositivi visibili. Rimuovere un tag da un dispositivo si fa in Modifica o Dettagli.", + "tags_device_hint": "Rimuovi un tag qui per disassegnarlo solo da questo dispositivo. Usa Gestisci tag per rinominare o eliminare ovunque.", + "unassign_tag": "Rimuovi da questo dispositivo", + "tag_device_one": "dispositivo", + "tag_device_many": "dispositivi", + "tag_group_one": "gruppo dinamico", + "tag_group_many": "gruppi dinamici" }, "keys": { "title": "Chiavi del server", @@ -1769,7 +1788,8 @@ "sessions_col_duration": "Durata", "sessions_active": "Attiva", "sessions_transport_punch": "Diretto / punch", - "sessions_transport_relay": "Relay" + "sessions_transport_relay": "Relay", + "tags_unassign_hint": "Rimuovere un tag qui lo disassegna solo da questo dispositivo. Usa Gestisci tag nella pagina Dispositivi per rinominare o eliminare ovunque." }, "inventory": { "title": "Inventario", diff --git a/web-nodejs/lang/ja.json b/web-nodejs/lang/ja.json index 38b721d2..462090aa 100644 --- a/web-nodejs/lang/ja.json +++ b/web-nodejs/lang/ja.json @@ -435,7 +435,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "タグを管理", + "manage_device_tags": "タグを管理", + "rename_tag": "タグ名を変更", + "delete_tag": "タグを削除", + "rename_tag_prompt": "新しいタグ名", + "rename_tag_hint": "表示中のすべてのデバイスでこのタグ名を変更し、一致する動的グループを更新します。", + "delete_tag_confirm": "タグ \"{tag}\" を {count} 台のデバイスから削除しますか?このタグを使う動的グループは更新まで空になります。", + "tag_renamed": "タグ名を変更しました", + "tag_deleted": "タグを削除しました", + "tag_name_required": "タグ名は必須です", + "tag_rename_identical": "新しい名前は別である必要があります", + "tags_backend_unsupported": "現在のバックエンドではデバイスタグはサポートされていません", + "tags_manage_hint": "表示中のすべてのデバイスでタグを変更または削除します。1台からの解除は編集または詳細で行います。", + "tags_device_hint": "ここでタグを削除すると、このデバイスからのみ割り当てが解除されます。全体の変更にはタグを管理を使います。", + "unassign_tag": "このデバイスから削除", + "tag_device_one": "デバイス", + "tag_device_many": "デバイス", + "tag_group_one": "動的グループ", + "tag_group_many": "動的グループ" }, "keys": { "title": "サーバーキー", @@ -1769,7 +1788,8 @@ "sessions_col_duration": "所要時間", "sessions_active": "進行中", "sessions_transport_punch": "直接 / パンチ", - "sessions_transport_relay": "リレー" + "sessions_transport_relay": "リレー", + "tags_unassign_hint": "ここでタグを削除すると、このデバイスからのみ割り当てが解除されます。全体の変更にはデバイスページのタグを管理を使います。" }, "inventory": { "title": "Inventory", diff --git a/web-nodejs/lang/ko.json b/web-nodejs/lang/ko.json index 3747a7d2..c1434bfd 100644 --- a/web-nodejs/lang/ko.json +++ b/web-nodejs/lang/ko.json @@ -435,7 +435,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "태그 관리", + "manage_device_tags": "태그 관리", + "rename_tag": "태그 이름 바꾸기", + "delete_tag": "태그 삭제", + "rename_tag_prompt": "새 태그 이름", + "rename_tag_hint": "볼 수 있는 모든 장치에서 이 태그 이름을 바꾸고 일치하는 동적 그룹을 업데이트합니다.", + "delete_tag_confirm": "태그 \"{tag}\"을(를) {count}개 장치에서 제거할까요? 이 태그를 쓰는 동적 그룹은 업데이트될 때까지 비어 있습니다.", + "tag_renamed": "태그 이름이 바뀌었습니다", + "tag_deleted": "태그가 삭제되었습니다", + "tag_name_required": "태그 이름이 필요합니다", + "tag_rename_identical": "새 이름은 달라야 합니다", + "tags_backend_unsupported": "현재 백엔드에서는 장치 태그가 지원되지 않습니다", + "tags_manage_hint": "볼 수 있는 모든 장치에서 태그를 바꾸거나 삭제합니다. 한 장치에서 제거는 편집 또는 세부정보에서 합니다.", + "tags_device_hint": "여기서 태그를 제거하면 이 장치에서만 할당이 해제됩니다. 전역 변경은 태그 관리를 사용하세요.", + "unassign_tag": "이 장치에서 제거", + "tag_device_one": "장치", + "tag_device_many": "장치", + "tag_group_one": "동적 그룹", + "tag_group_many": "동적 그룹" }, "keys": { "title": "서버 키", @@ -1769,7 +1788,8 @@ "sessions_col_duration": "지속 시간", "sessions_active": "진행 중", "sessions_transport_punch": "직접 / 펀치", - "sessions_transport_relay": "릴레이" + "sessions_transport_relay": "릴레이", + "tags_unassign_hint": "여기서 태그를 제거하면 이 장치에서만 할당이 해제됩니다. 전역 변경은 장치 페이지의 태그 관리를 사용하세요." }, "inventory": { "title": "Inventory", diff --git a/web-nodejs/lang/nb.json b/web-nodejs/lang/nb.json index 4da9fa10..3a3ebf1d 100644 --- a/web-nodejs/lang/nb.json +++ b/web-nodejs/lang/nb.json @@ -441,7 +441,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "Administrer tagger", + "manage_device_tags": "Administrer tagger", + "rename_tag": "Gi tag nytt navn", + "delete_tag": "Slett tag", + "rename_tag_prompt": "Nytt tagnavn", + "rename_tag_hint": "Gir denne tagen nytt navn på alle synlige enheter og oppdaterer matchende dynamiske grupper.", + "delete_tag_confirm": "Fjern tagen \"{tag}\" fra {count} enhet(er)? Dynamiske grupper som bruker den blir tomme til de oppdateres.", + "tag_renamed": "Tag omdøpt", + "tag_deleted": "Tag slettet", + "tag_name_required": "Tagnavn er påkrevd", + "tag_rename_identical": "Det nye tagnavnet må være annerledes", + "tags_backend_unsupported": "Enhetstagger støttes ikke med gjeldende backend", + "tags_manage_hint": "Gi nytt navn eller slett tagger på alle synlige enheter. Fjerning fra én enhet gjøres i Rediger eller Detaljer.", + "tags_device_hint": "Fjern en tag her for å frakoble den kun fra denne enheten. Bruk Administrer tagger for global endring.", + "unassign_tag": "Fjern fra denne enheten", + "tag_device_one": "enhet", + "tag_device_many": "enheter", + "tag_group_one": "dynamisk gruppe", + "tag_group_many": "dynamiske grupper" }, "keys": { "title": "Servernøkler", @@ -1775,7 +1794,8 @@ "sessions_col_duration": "Varighet", "sessions_active": "Aktiv", "sessions_transport_punch": "Direkte / punch", - "sessions_transport_relay": "Relay" + "sessions_transport_relay": "Relay", + "tags_unassign_hint": "Fjerning av en tag her frakobler den kun fra denne enheten. Bruk Administrer tagger på Enheter for global endring." }, "inventory": { "title": "Inventory", diff --git a/web-nodejs/lang/nl.json b/web-nodejs/lang/nl.json index 709d170c..a1db8cfb 100644 --- a/web-nodejs/lang/nl.json +++ b/web-nodejs/lang/nl.json @@ -435,7 +435,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "Tags beheren", + "manage_device_tags": "Tags beheren", + "rename_tag": "Tag hernoemen", + "delete_tag": "Tag verwijderen", + "rename_tag_prompt": "Nieuwe tagnaam", + "rename_tag_hint": "Hernoemt deze tag op alle zichtbare apparaten en werkt bijpassende dynamische groepen bij.", + "delete_tag_confirm": "Tag \"{tag}\" van {count} apparaat/apparaten verwijderen? Dynamische groepen die deze tag gebruiken blijven leeg tot bijgewerkt.", + "tag_renamed": "Tag hernoemd", + "tag_deleted": "Tag verwijderd", + "tag_name_required": "Tagnaam is verplicht", + "tag_rename_identical": "Nieuwe tagnaam moet anders zijn", + "tags_backend_unsupported": "Apparaattags worden niet ondersteund met de huidige backend", + "tags_manage_hint": "Hernoem of verwijder tags op alle zichtbare apparaten. Verwijderen van één apparaat gebeurt in Bewerken of Details.", + "tags_device_hint": "Verwijder hier een tag om deze alleen van dit apparaat te ontkoppelen. Gebruik Tags beheren om overal te hernoemen of te verwijderen.", + "unassign_tag": "Van dit apparaat verwijderen", + "tag_device_one": "apparaat", + "tag_device_many": "apparaten", + "tag_group_one": "dynamische groep", + "tag_group_many": "dynamische groepen" }, "keys": { "title": "Serversleutels", @@ -1769,7 +1788,8 @@ "sessions_col_duration": "Duur", "sessions_active": "Actief", "sessions_transport_punch": "Direct / punch", - "sessions_transport_relay": "Relay" + "sessions_transport_relay": "Relay", + "tags_unassign_hint": "Een tag hier verwijderen ontkoppelt deze alleen van dit apparaat. Gebruik Tags beheren op Apparaten om overal te hernoemen of te verwijderen." }, "inventory": { "title": "Inventaris", diff --git a/web-nodejs/lang/pl.json b/web-nodejs/lang/pl.json index bf553197..a1c762fe 100644 --- a/web-nodejs/lang/pl.json +++ b/web-nodejs/lang/pl.json @@ -435,7 +435,26 @@ "group_commercialization_assign_existing": "Przypisz istniejący pakiet", "group_commercialization_create_new": "Utwórz nowy pakiet i przypisz", "group_commercialization_saved": "Pakiet przypisany do grupy", - "group_one_only": "Urządzenie może należeć tylko do jednej grupy" + "group_one_only": "Urządzenie może należeć tylko do jednej grupy", + "manage_tags": "Zarządzaj tagami", + "manage_device_tags": "Zarządzaj tagami", + "rename_tag": "Zmień nazwę tagu", + "delete_tag": "Usuń tag", + "rename_tag_prompt": "Nowa nazwa tagu", + "rename_tag_hint": "Zmienia nazwę tego tagu na wszystkich widocznych urządzeniach i aktualizuje pasujące grupy dynamiczne.", + "delete_tag_confirm": "Usunąć tag \"{tag}\" z {count} urządzeń? Grupy dynamiczne używające tego tagu będą puste do czasu aktualizacji.", + "tag_renamed": "Zmieniono nazwę tagu", + "tag_deleted": "Usunięto tag", + "tag_name_required": "Nazwa tagu jest wymagana", + "tag_rename_identical": "Nowa nazwa tagu musi być inna", + "tags_backend_unsupported": "Tagi urządzeń nie są obsługiwane w bieżącym backendzie", + "tags_manage_hint": "Zmieniaj nazwy lub usuwaj tagi na wszystkich widocznych urządzeniach. Usunięcie tagu z jednego urządzenia odbywa się w Edycji lub szczegółach urządzenia.", + "tags_device_hint": "Usuń tag tutaj, aby odpiąć go tylko od tego urządzenia. Użyj Zarządzaj tagami, aby zmienić nazwę lub usunąć tag wszędzie.", + "unassign_tag": "Usuń z tego urządzenia", + "tag_device_one": "urządzenie", + "tag_device_many": "urządzeń", + "tag_group_one": "grupa dynamiczna", + "tag_group_many": "grup dynamicznych" }, "keys": { "title": "Klucze serwera", @@ -1782,7 +1801,8 @@ "sessions_col_duration": "Czas", "sessions_active": "Aktywna", "sessions_transport_punch": "Bezpośrednie / punch", - "sessions_transport_relay": "Relay" + "sessions_transport_relay": "Relay", + "tags_unassign_hint": "Usunięcie tagu tutaj odłącza go tylko od tego urządzenia. Użyj Zarządzaj tagami na stronie Urządzenia, aby zmienić nazwę lub usunąć tag wszędzie." }, "inventory": { "title": "Inwentaryzacja", diff --git a/web-nodejs/lang/pt.json b/web-nodejs/lang/pt.json index 2358cbee..de9fcb8a 100644 --- a/web-nodejs/lang/pt.json +++ b/web-nodejs/lang/pt.json @@ -435,7 +435,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "Gerir etiquetas", + "manage_device_tags": "Gerir etiquetas", + "rename_tag": "Mudar nome da etiqueta", + "delete_tag": "Eliminar etiqueta", + "rename_tag_prompt": "Novo nome da etiqueta", + "rename_tag_hint": "Altera o nome desta etiqueta em todos os dispositivos visíveis e atualiza grupos dinâmicos correspondentes.", + "delete_tag_confirm": "Remover a etiqueta \"{tag}\" de {count} dispositivo(s)? Grupos dinâmicos que a usam ficarão vazios até serem atualizados.", + "tag_renamed": "Etiqueta renomeada", + "tag_deleted": "Etiqueta eliminada", + "tag_name_required": "O nome da etiqueta é obrigatório", + "tag_rename_identical": "O novo nome deve ser diferente", + "tags_backend_unsupported": "Etiquetas de dispositivos não são suportadas com o backend atual", + "tags_manage_hint": "Renomeie ou elimine etiquetas em todos os dispositivos visíveis. Remover de um dispositivo faz-se em Editar ou Detalhes.", + "tags_device_hint": "Remova uma etiqueta aqui para a desassociar apenas deste dispositivo. Use Gerir etiquetas para renomear ou eliminar em todo o lado.", + "unassign_tag": "Remover deste dispositivo", + "tag_device_one": "dispositivo", + "tag_device_many": "dispositivos", + "tag_group_one": "grupo dinâmico", + "tag_group_many": "grupos dinâmicos" }, "keys": { "title": "Chaves do servidor", @@ -1769,7 +1788,8 @@ "sessions_col_duration": "Duração", "sessions_active": "Ativa", "sessions_transport_punch": "Direto / punch", - "sessions_transport_relay": "Relay" + "sessions_transport_relay": "Relay", + "tags_unassign_hint": "Remover uma etiqueta aqui desassocia-a apenas deste dispositivo. Use Gerir etiquetas na página Dispositivos para renomear ou eliminar em todo o lado." }, "inventory": { "title": "Inventário", diff --git a/web-nodejs/lang/ro.json b/web-nodejs/lang/ro.json index 236267fb..b61e92a4 100644 --- a/web-nodejs/lang/ro.json +++ b/web-nodejs/lang/ro.json @@ -441,7 +441,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "Gestionează etichetele", + "manage_device_tags": "Gestionează etichetele", + "rename_tag": "Redenumește eticheta", + "delete_tag": "Șterge eticheta", + "rename_tag_prompt": "Nume nou pentru etichetă", + "rename_tag_hint": "Redenumește această etichetă pe toate dispozitivele vizibile și actualizează grupurile dinamice potrivite.", + "delete_tag_confirm": "Eliminați eticheta \"{tag}\" de pe {count} dispozitiv(e)? Grupurile dinamice care o folosesc vor fi goale până la actualizare.", + "tag_renamed": "Etichetă redenumită", + "tag_deleted": "Etichetă ștearsă", + "tag_name_required": "Numele etichetei este obligatoriu", + "tag_rename_identical": "Noul nume trebuie să fie diferit", + "tags_backend_unsupported": "Etichetele dispozitivelor nu sunt acceptate cu backend-ul curent", + "tags_manage_hint": "Redenumiți sau ștergeți etichete pe toate dispozitivele vizibile. Eliminarea de pe un dispozitiv se face în Editare sau Detalii.", + "tags_device_hint": "Eliminați o etichetă aici pentru a o dezasocia doar de acest dispozitiv. Folosiți Gestionează etichetele pentru redenumire/ștergere globală.", + "unassign_tag": "Elimină de pe acest dispozitiv", + "tag_device_one": "dispozitiv", + "tag_device_many": "dispozitive", + "tag_group_one": "grup dinamic", + "tag_group_many": "grupuri dinamice" }, "keys": { "title": "Cheile serverului", @@ -1775,7 +1794,8 @@ "sessions_col_duration": "Durată", "sessions_active": "Activă", "sessions_transport_punch": "Direct / punch", - "sessions_transport_relay": "Relay" + "sessions_transport_relay": "Relay", + "tags_unassign_hint": "Eliminarea unei etichete aici o dezasociază doar de acest dispozitiv. Folosiți Gestionează etichetele pe pagina Dispozitive pentru redenumire/ștergere globală." }, "inventory": { "title": "Inventory", diff --git a/web-nodejs/lang/sv.json b/web-nodejs/lang/sv.json index 5a23d457..19e911a6 100644 --- a/web-nodejs/lang/sv.json +++ b/web-nodejs/lang/sv.json @@ -441,7 +441,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "Hantera taggar", + "manage_device_tags": "Hantera taggar", + "rename_tag": "Byt namn på tagg", + "delete_tag": "Ta bort tagg", + "rename_tag_prompt": "Nytt taggnamn", + "rename_tag_hint": "Byter namn på denna tagg på alla synliga enheter och uppdaterar matchande dynamiska grupper.", + "delete_tag_confirm": "Ta bort taggen \"{tag}\" från {count} enhet(er)? Dynamiska grupper som använder den blir tomma tills de uppdateras.", + "tag_renamed": "Tagg omdöpt", + "tag_deleted": "Tagg borttagen", + "tag_name_required": "Taggnamn krävs", + "tag_rename_identical": "Det nya namnet måste vara annorlunda", + "tags_backend_unsupported": "Enhetstaggar stöds inte med aktuell backend", + "tags_manage_hint": "Byt namn på eller ta bort taggar på alla synliga enheter. Borttagning från en enhet görs i Redigera eller Detaljer.", + "tags_device_hint": "Ta bort en tagg här för att koppla bort den endast från denna enhet. Använd Hantera taggar för global ändring.", + "unassign_tag": "Ta bort från denna enhet", + "tag_device_one": "enhet", + "tag_device_many": "enheter", + "tag_group_one": "dynamisk grupp", + "tag_group_many": "dynamiska grupper" }, "keys": { "title": "Servernycklar", @@ -1775,7 +1794,8 @@ "sessions_col_duration": "Varaktighet", "sessions_active": "Aktiv", "sessions_transport_punch": "Direkt / punch", - "sessions_transport_relay": "Relay" + "sessions_transport_relay": "Relay", + "tags_unassign_hint": "Att ta bort en tagg här kopplar bort den endast från denna enhet. Använd Hantera taggar på Enheter för global ändring." }, "inventory": { "title": "Inventory", diff --git a/web-nodejs/lang/th.json b/web-nodejs/lang/th.json index 29f968d5..f0963907 100644 --- a/web-nodejs/lang/th.json +++ b/web-nodejs/lang/th.json @@ -441,7 +441,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "จัดการแท็ก", + "manage_device_tags": "จัดการแท็ก", + "rename_tag": "เปลี่ยนชื่อแท็ก", + "delete_tag": "ลบแท็ก", + "rename_tag_prompt": "ชื่อแท็กใหม่", + "rename_tag_hint": "เปลี่ยนชื่อแท็กนี้บนอุปกรณ์ที่มองเห็นทั้งหมด และอัปเดตกลุ่มไดนามิกที่ตรงกัน", + "delete_tag_confirm": "ลบแท็ก \"{tag}\" ออกจาก {count} อุปกรณ์หรือไม่ กลุ่มไดนามิกที่ใช้แท็กนี้จะว่างจนกว่าจะอัปเดต", + "tag_renamed": "เปลี่ยนชื่อแท็กแล้ว", + "tag_deleted": "ลบแท็กแล้ว", + "tag_name_required": "ต้องระบุชื่อแท็ก", + "tag_rename_identical": "ชื่อใหม่ต้องต่างจากเดิม", + "tags_backend_unsupported": "แท็กอุปกรณ์ไม่รองรับกับแบ็กเอนด์ปัจจุบัน", + "tags_manage_hint": "เปลี่ยนชื่อหรือลบแท็กบนอุปกรณ์ที่มองเห็นทั้งหมด การลบจากอุปกรณ์เดียวทำในแก้ไขหรือรายละเอียด", + "tags_device_hint": "ลบแท็กที่นี่เพื่อยกเลิกการกำหนดเฉพาะอุปกรณ์นี้ ใช้จัดการแท็กเพื่อเปลี่ยนชื่อหรือลบทั้งหมด", + "unassign_tag": "ลบออกจากอุปกรณ์นี้", + "tag_device_one": "อุปกรณ์", + "tag_device_many": "อุปกรณ์", + "tag_group_one": "กลุ่มไดนามิก", + "tag_group_many": "กลุ่มไดนามิก" }, "keys": { "title": "คีย์เซิร์ฟเวอร์", @@ -1775,7 +1794,8 @@ "sessions_col_duration": "ระยะเวลา", "sessions_active": "กำลังทำงาน", "sessions_transport_punch": "ตรง / punch", - "sessions_transport_relay": "Relay" + "sessions_transport_relay": "Relay", + "tags_unassign_hint": "ลบแท็กที่นี่จะยกเลิกการกำหนดเฉพาะอุปกรณ์นี้ ใช้จัดการแท็กในหน้าอุปกรณ์เพื่อเปลี่ยนชื่อหรือลบทั้งหมด" }, "inventory": { "title": "Inventory", diff --git a/web-nodejs/lang/tr.json b/web-nodejs/lang/tr.json index 1803d3d6..0b916b8b 100644 --- a/web-nodejs/lang/tr.json +++ b/web-nodejs/lang/tr.json @@ -441,7 +441,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "Etiketleri yönet", + "manage_device_tags": "Etiketleri yönet", + "rename_tag": "Etiketi yeniden adlandır", + "delete_tag": "Etiketi sil", + "rename_tag_prompt": "Yeni etiket adı", + "rename_tag_hint": "Bu etiketi görebildiğiniz tüm cihazlarda yeniden adlandırır ve eşleşen dinamik grupları günceller.", + "delete_tag_confirm": "\"{tag}\" etiketi {count} cihazdan kaldırılsın mı? Bu etiketi kullanan dinamik gruplar güncellenene kadar boş kalır.", + "tag_renamed": "Etiket yeniden adlandırıldı", + "tag_deleted": "Etiket silindi", + "tag_name_required": "Etiket adı gerekli", + "tag_rename_identical": "Yeni ad farklı olmalı", + "tags_backend_unsupported": "Cihaz etiketleri mevcut backend ile desteklenmiyor", + "tags_manage_hint": "Görünür tüm cihazlarda etiketleri yeniden adlandırın veya silin. Bir cihazdan kaldırma Düzenle veya Ayrıntılar’da yapılır.", + "tags_device_hint": "Burada bir etiketi kaldırarak yalnızca bu cihazdan ayırırsınız. Her yerde yeniden adlandırmak/silmek için Etiketleri yönet’i kullanın.", + "unassign_tag": "Bu cihazdan kaldır", + "tag_device_one": "cihaz", + "tag_device_many": "cihaz", + "tag_group_one": "dinamik grup", + "tag_group_many": "dinamik grup" }, "keys": { "title": "Sunucu Anahtarları", @@ -1775,7 +1794,8 @@ "sessions_col_duration": "Süre", "sessions_active": "Aktif", "sessions_transport_punch": "Doğrudan / punch", - "sessions_transport_relay": "Relay" + "sessions_transport_relay": "Relay", + "tags_unassign_hint": "Burada bir etiketi kaldırmak yalnızca bu cihazdan ayırır. Her yerde yeniden adlandırmak/silmek için Cihazlar sayfasındaki Etiketleri yönet’i kullanın." }, "inventory": { "title": "Inventory", diff --git a/web-nodejs/lang/uk.json b/web-nodejs/lang/uk.json index 9e1bff75..6171b1fc 100644 --- a/web-nodejs/lang/uk.json +++ b/web-nodejs/lang/uk.json @@ -441,7 +441,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "Керувати тегами", + "manage_device_tags": "Керувати тегами", + "rename_tag": "Перейменувати тег", + "delete_tag": "Видалити тег", + "rename_tag_prompt": "Нова назва тегу", + "rename_tag_hint": "Перейменовує цей тег на всіх видимих пристроях і оновлює відповідні динамічні групи.", + "delete_tag_confirm": "Видалити тег \"{tag}\" з {count} пристрою(їв)? Динамічні групи з цим тегом будуть порожніми до оновлення.", + "tag_renamed": "Тег перейменовано", + "tag_deleted": "Тег видалено", + "tag_name_required": "Назва тегу обов’язкова", + "tag_rename_identical": "Нова назва має відрізнятися", + "tags_backend_unsupported": "Теги пристроїв не підтримуються з поточним бекендом", + "tags_manage_hint": "Перейменовуйте або видаляйте теги на всіх видимих пристроях. Зняття з одного пристрою — в Редагуванні або Деталях.", + "tags_device_hint": "Видаліть тег тут, щоб відв’язати його лише від цього пристрою. Для глобальних змін використовуйте Керувати тегами.", + "unassign_tag": "Видалити з цього пристрою", + "tag_device_one": "пристрій", + "tag_device_many": "пристроїв", + "tag_group_one": "динамічна група", + "tag_group_many": "динамічних груп" }, "keys": { "title": "Ключі сервера", @@ -1775,7 +1794,8 @@ "sessions_col_duration": "Тривалість", "sessions_active": "Активна", "sessions_transport_punch": "Пряме / punch", - "sessions_transport_relay": "Relay" + "sessions_transport_relay": "Relay", + "tags_unassign_hint": "Видалення тегу тут відв’язує його лише від цього пристрою. Для глобальних змін використайте Керувати тегами на сторінці Пристрої." }, "inventory": { "title": "Inventory", diff --git a/web-nodejs/lang/vi.json b/web-nodejs/lang/vi.json index d07d828c..714f1c11 100644 --- a/web-nodejs/lang/vi.json +++ b/web-nodejs/lang/vi.json @@ -441,7 +441,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "Quản lý thẻ", + "manage_device_tags": "Quản lý thẻ", + "rename_tag": "Đổi tên thẻ", + "delete_tag": "Xóa thẻ", + "rename_tag_prompt": "Tên thẻ mới", + "rename_tag_hint": "Đổi tên thẻ này trên tất cả thiết bị bạn thấy và cập nhật nhóm động khớp.", + "delete_tag_confirm": "Gỡ thẻ \"{tag}\" khỏi {count} thiết bị? Nhóm động dùng thẻ này sẽ trống cho đến khi cập nhật.", + "tag_renamed": "Đã đổi tên thẻ", + "tag_deleted": "Đã xóa thẻ", + "tag_name_required": "Tên thẻ là bắt buộc", + "tag_rename_identical": "Tên mới phải khác", + "tags_backend_unsupported": "Thẻ thiết bị không được hỗ trợ với backend hiện tại", + "tags_manage_hint": "Đổi tên hoặc xóa thẻ trên tất cả thiết bị hiển thị. Gỡ khỏi một thiết bị trong Sửa hoặc Chi tiết.", + "tags_device_hint": "Gỡ thẻ tại đây chỉ bỏ gán khỏi thiết bị này. Dùng Quản lý thẻ để đổi tên/xóa toàn cục.", + "unassign_tag": "Gỡ khỏi thiết bị này", + "tag_device_one": "thiết bị", + "tag_device_many": "thiết bị", + "tag_group_one": "nhóm động", + "tag_group_many": "nhóm động" }, "keys": { "title": "Khóa máy chủ", @@ -1775,7 +1794,8 @@ "sessions_col_duration": "Thời lượng", "sessions_active": "Đang hoạt động", "sessions_transport_punch": "Trực tiếp / punch", - "sessions_transport_relay": "Relay" + "sessions_transport_relay": "Relay", + "tags_unassign_hint": "Gỡ thẻ tại đây chỉ bỏ gán khỏi thiết bị này. Dùng Quản lý thẻ trên trang Thiết bị để đổi tên/xóa toàn cục." }, "inventory": { "title": "Inventory", diff --git a/web-nodejs/lang/zh-TW.json b/web-nodejs/lang/zh-TW.json index 846cde1c..c5ff46c6 100644 --- a/web-nodejs/lang/zh-TW.json +++ b/web-nodejs/lang/zh-TW.json @@ -439,7 +439,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "管理標籤", + "manage_device_tags": "管理標籤", + "rename_tag": "重新命名標籤", + "delete_tag": "刪除標籤", + "rename_tag_prompt": "新標籤名稱", + "rename_tag_hint": "在您可見的所有裝置上重新命名此標籤,並更新相符的動態群組。", + "delete_tag_confirm": "從 {count} 台裝置移除標籤 \"{tag}\"?使用此標籤的動態群組在更新前將為空。", + "tag_renamed": "標籤已重新命名", + "tag_deleted": "標籤已刪除", + "tag_name_required": "標籤名稱為必填", + "tag_rename_identical": "新名稱必須不同", + "tags_backend_unsupported": "目前後端不支援裝置標籤", + "tags_manage_hint": "在您可見的所有裝置上重新命名或刪除標籤。從單一裝置移除請在編輯或詳細資料中操作。", + "tags_device_hint": "在此移除標籤僅取消本裝置的指派。全域重新命名或刪除請使用管理標籤。", + "unassign_tag": "從此裝置移除", + "tag_device_one": "台裝置", + "tag_device_many": "台裝置", + "tag_group_one": "個動態群組", + "tag_group_many": "個動態群組" }, "keys": { "title": "服務器密鑰", @@ -1786,7 +1805,8 @@ "sessions_col_duration": "時長", "sessions_active": "進行中", "sessions_transport_punch": "直連 / 打洞", - "sessions_transport_relay": "中繼" + "sessions_transport_relay": "中繼", + "tags_unassign_hint": "在此移除標籤僅取消本裝置的指派。全域重新命名或刪除請在裝置頁使用管理標籤。" }, "inventory": { "title": "資產清單", diff --git a/web-nodejs/lang/zh.json b/web-nodejs/lang/zh.json index b8c244b6..7c3eeb3c 100644 --- a/web-nodejs/lang/zh.json +++ b/web-nodejs/lang/zh.json @@ -435,7 +435,26 @@ "group_commercialization_assign_existing": "Assign existing package", "group_commercialization_create_new": "Create new package and assign", "group_commercialization_saved": "Package assigned to group", - "group_one_only": "A device can belong to only one group" + "group_one_only": "A device can belong to only one group", + "manage_tags": "管理标签", + "manage_device_tags": "管理标签", + "rename_tag": "重命名标签", + "delete_tag": "删除标签", + "rename_tag_prompt": "新标签名称", + "rename_tag_hint": "在您可见的所有设备上重命名此标签,并更新匹配的动态组。", + "delete_tag_confirm": "从 {count} 台设备移除标签 \"{tag}\"?使用此标签的动态组在更新前将为空。", + "tag_renamed": "标签已重命名", + "tag_deleted": "标签已删除", + "tag_name_required": "标签名称为必填项", + "tag_rename_identical": "新名称必须不同", + "tags_backend_unsupported": "当前后端不支持设备标签", + "tags_manage_hint": "在您可见的所有设备上重命名或删除标签。从单台设备移除请在编辑或详情中操作。", + "tags_device_hint": "在此移除标签仅取消本设备的分配。全局重命名或删除请使用管理标签。", + "unassign_tag": "从此设备移除", + "tag_device_one": "台设备", + "tag_device_many": "台设备", + "tag_group_one": "个动态组", + "tag_group_many": "个动态组" }, "keys": { "title": "服务器密钥", @@ -1769,7 +1788,8 @@ "sessions_col_duration": "时长", "sessions_active": "进行中", "sessions_transport_punch": "直连 / 打洞", - "sessions_transport_relay": "中继" + "sessions_transport_relay": "中继", + "tags_unassign_hint": "在此移除标签仅取消本设备的分配。全局重命名或删除请在设备页使用管理标签。" }, "inventory": { "title": "资产清单", diff --git a/web-nodejs/public/css/device-detail.css b/web-nodejs/public/css/device-detail.css index 6a10b5b4..794c4256 100644 --- a/web-nodejs/public/css/device-detail.css +++ b/web-nodejs/public/css/device-detail.css @@ -481,6 +481,12 @@ body.device-detail-open { TAGS TAB ═══════════════════════════════════════════════════════════════════════════ */ +.device-panel-tags-hint { + margin: 0 0 var(--space-sm, 0.5rem); + color: var(--text-tertiary, #8b949e); + font-size: var(--font-size-sm, 0.875rem); +} + .device-panel-tags-container { display: flex; flex-wrap: wrap; diff --git a/web-nodejs/public/css/devices.css b/web-nodejs/public/css/devices.css index 53a1034a..7817cbc6 100644 --- a/web-nodejs/public/css/devices.css +++ b/web-nodejs/public/css/devices.css @@ -434,6 +434,74 @@ border-color: var(--accent-blue) !important; } +.manage-tags-hint { + margin: 0 0 var(--space-md); +} + +.manage-tags-empty { + padding: var(--space-md); + color: var(--text-tertiary); + font-size: var(--font-size-sm); + text-align: center; +} + +.manage-tags-list { + list-style: none; + margin: 0; + padding: 0; + display: flex; + flex-direction: column; + gap: 8px; + max-height: min(50vh, 420px); + overflow-y: auto; +} + +.manage-tags-row { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + padding: 10px 12px; + border: 1px solid var(--border-primary); + border-radius: var(--radius-md); + background: var(--bg-secondary, transparent); +} + +.manage-tags-info { + display: flex; + flex-direction: column; + gap: 2px; + min-width: 0; +} + +.manage-tags-name { + font-weight: 600; + color: var(--text-primary); + word-break: break-word; +} + +.manage-tags-meta { + font-size: var(--font-size-sm); + color: var(--text-tertiary); +} + +.manage-tags-actions { + display: flex; + flex-shrink: 0; + gap: 6px; +} + +.manage-tags-actions .btn .material-icons { + font-size: 16px; +} + +.device-edit-tags-focus { + outline: 1px solid var(--accent-blue); + outline-offset: 4px; + border-radius: var(--radius-md); + padding: 8px; +} + /* ==================== Toolbar ==================== */ .devices-toolbar { diff --git a/web-nodejs/public/js/deviceDetail.js b/web-nodejs/public/js/deviceDetail.js index d1ef2fae..5f4ee3ba 100644 --- a/web-nodejs/public/js/deviceDetail.js +++ b/web-nodejs/public/js/deviceDetail.js @@ -840,12 +840,13 @@ const DeviceDetail = (function () { html += `