From a321dab448d428aad7db918c8eea690ab61df947 Mon Sep 17 00:00:00 2001 From: Mikhail Chusavitin Date: Thu, 30 Jul 2026 18:21:09 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20=D1=82=D1=80=D0=B5=D1=82=D1=8C=D0=B5=20?= =?UTF-8?q?=D0=BC=D0=B5=D1=81=D1=82=D0=BE=20=D1=81=D0=B0=D0=BC=D0=BE=D0=BE?= =?UTF-8?q?=D1=82=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20ASSIGN?= =?UTF-8?q?ED=5FCATEGORIES=20+=20=D1=81=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=B2=20=D0=BE=D0=B4=D0=BD=D1=83=20=D1=84=D1=83?= =?UTF-8?q?=D0=BD=D0=BA=D1=86=D0=B8=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit applyConfigTypeToTabs() тоже пересобирал ASSIGNED_CATEGORIES из всех вкладок, включая "other", и вызывался прямо внутри applyServerSettings — из-за этого предыдущий фикс (два других места) перезатирался сразу же, и SYS всё ещё не появлялся во вкладке «Прочее». Свёл все 4 места пересчёта ASSIGNED_CATEGORIES в одну функцию computeAssignedCategories(), которая по определению исключает "other" — это устраняет класс бага целиком, а не по одному вхождению. Co-Authored-By: Claude Sonnet 5 --- web/templates/index.html | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/web/templates/index.html b/web/templates/index.html index 1c2dd24..b99276c 100644 --- a/web/templates/index.html +++ b/web/templates/index.html @@ -474,9 +474,17 @@ let TAB_CONFIG = { } }; -let ASSIGNED_CATEGORIES = Object.values(TAB_CONFIG) - .flatMap(t => t.categories) - .map(c => ciStr(c)); +// Categories belonging to any real tab (everything except "other"). +// "other" is defined as "whatever isn't in this set" — it must never +// contribute to it, or its own contents would exclude themselves. +function computeAssignedCategories() { + return Object.entries(TAB_CONFIG) + .filter(([key]) => key !== 'other') + .flatMap(([, t]) => t._allCategories || t.categories) + .map(c => ciStr(c)); +} + +let ASSIGNED_CATEGORIES = computeAssignedCategories(); // State let configUUID = '{{.ConfigUUID}}'; @@ -822,19 +830,16 @@ async function loadCategoriesFromAPI() { categoryOrderMap[ciStr(cat.code)] = cat.display_order; }); - // Build list of unassigned categories - const knownCodes = Object.values(TAB_CONFIG) - .flatMap(t => t.categories) - .map(c => ciStr(c)); + // Build list of unassigned categories (excludes "other" itself, so + // this stays correct even if it's re-run after "other" was already + // populated by a previous call). + const knownCodes = computeAssignedCategories(); const unassignedCategories = cats .filter(cat => !knownCodes.includes(ciStr(cat.code))) .sort((a, b) => a.display_order - b.display_order) .map(cat => cat.code); - // Rebuild ASSIGNED_CATEGORIES from known (non-"other") tabs before - // populating "other", so unassigned categories aren't immediately - // excluded from the "other" tab by their own assignment. ASSIGNED_CATEGORIES = knownCodes; // Update "other" tab with unassigned categories @@ -886,7 +891,7 @@ function applyServerSettings(settings) { // before restoring .other — otherwise categories already parked in // .other (e.g. by loadCategoriesFromAPI) get counted as "assigned" // and immediately excluded from the "other" tab again. - ASSIGNED_CATEGORIES = Object.values(TAB_CONFIG).flatMap(t => t.categories).map(c => ciStr(c)); + ASSIGNED_CATEGORIES = computeAssignedCategories(); TAB_CONFIG.other = otherTab || { categories: [], singleSelect: false, label: 'Other' }; } @@ -1398,11 +1403,10 @@ function applyConfigTypeToTabs() { } }); - // Rebuild assigned categories index using the full static list (_allCategories), - // not the filtered one — hidden categories still belong to their tab, not to Other. - ASSIGNED_CATEGORIES = Object.values(TAB_CONFIG) - .flatMap(t => t._allCategories || t.categories) - .map(c => ciStr(c)); + // Rebuild assigned categories index using the full static list + // (_allCategories), not the filtered one — hidden categories still + // belong to their tab, not to Other. + ASSIGNED_CATEGORIES = computeAssignedCategories(); } function updateTabVisibility() {