diff --git a/app.py b/app.py index fbe78b6..a9094de 100644 --- a/app.py +++ b/app.py @@ -29,7 +29,7 @@ from ui_builder import install_ui_builder from khl_site.khl_data_center import APP as khl_site_app BASE_DIR = Path(__file__).resolve().parent -BUILD_VERSION = "2026.08.27.1" +BUILD_VERSION = "2026.08.27.2" # compatibility: BUILD_VERSION = "2026.08.26.1" # compatibility: BUILD_VERSION = "2026.08.25.1" # compatibility: BUILD_VERSION = "2026.08.24.15" diff --git a/ui_builder/manager.py b/ui_builder/manager.py index 2732703..6541df9 100644 --- a/ui_builder/manager.py +++ b/ui_builder/manager.py @@ -574,7 +574,7 @@ class UIBuilderManager: "description": str(selector.get("description") or "")[:300], "group_id": group_id if group_id in valid_group_ids else "", "button_id": button_id if button_id in valid_button_ids else "", - "style": "select" if str(selector.get("style") or "segments") == "select" else "segments", + "style": str(selector.get("style") or "segments") if str(selector.get("style") or "segments") in {"segments", "select", "periods"} else "segments", "options": options, "default_value": default_value, "sort_order": int(selector.get("sort_order") if str(selector.get("sort_order", "")).lstrip("-").isdigit() else selector_index * 10), diff --git a/ui_builder/static/app.js b/ui_builder/static/app.js index c8a8017..9af7586 100644 --- a/ui_builder/static/app.js +++ b/ui_builder/static/app.js @@ -2494,7 +2494,7 @@ function startCustomTooltips() { description: String(selector?.description || "").slice(0, 300), group_id: String(selector?.group_id || "").slice(0, 48), button_id: String(selector?.button_id || "").slice(0, 48), - style: String(selector?.style || "segments") === "select" ? "select" : "segments", + style: ["select", "periods"].includes(String(selector?.style || "segments")) ? String(selector.style) : "segments", options: fallbackOptions, default_value: defaultValue, sort_order: Number.isFinite(Number(selector?.sort_order)) ? Number(selector.sort_order) : index * 10, @@ -8824,7 +8824,7 @@ function openHockeyPrematchButtonsEditor() { let activeEditorSection = "buttons"; if (activeEditorGroupId === "__ungrouped") activeEditorGroupId = ""; if (activeEditorGroupId && !draftGroups.some((group) => group.id === activeEditorGroupId)) activeEditorGroupId = draftGroups[0]?.id || ""; - const collapsedEditorGroups = new Set(); + const collapsedEditorGroups = new Set(["", ...draftGroups.map((group) => String(group.id || ""))]); const groupButtons = (groupId) => draft .filter((button) => String(button.group_id || "") === String(groupId || "")) @@ -8875,9 +8875,12 @@ function openHockeyPrematchButtonsEditor() { - - - + + ${selector.style === "periods" + ? ` + ` + : ` + `} `; @@ -9112,6 +9115,9 @@ function openHockeyPrematchButtonsEditor() { activeEditorGroupId = String(selector.group_id || ""); collapsedEditorGroups.delete(activeEditorGroupId); renderEditor(); + } else if (field === "style") { + if (selector.style === "periods") selector.default_value = "1"; + renderEditor(); } }); }); @@ -9233,11 +9239,57 @@ function hockeyMatchRuntimeValues() { return values && typeof values === "object" ? values : {}; } +function quickPanelPeriodLabel(value) { + const key = String(value || "").toLowerCase(); + if (key === "1" || key === "2" || key === "3") return key; + if (key === "ot") return "ОТ"; + const match = key.match(/^ot(\d+)$/); + return match ? `ОТ${match[1]}` : String(value || ""); +} + +function quickPanelSelectorRuntimeOptions(selector) { + if (String(selector?.style || "") !== "periods") return Array.isArray(selector?.options) ? selector.options : []; + const control = getByPath(state.data, "hockey.game_control") || {}; + const tournament = getByPath(state.data, "hockey.selected_tournament") || {}; + const stage = String(control?.stage || tournament?.stage_key || "").toLowerCase(); + const raw = Array.isArray(control?.period_options) ? control.period_options : []; + let options = raw + .map((item) => ({ value: String(item?.value || ""), label: quickPanelPeriodLabel(item?.value) })) + .filter((item) => { + if (["1", "2", "3"].includes(item.value)) return true; + if (stage === "playoff") return /^ot\d+$/.test(item.value); + return item.value === "ot"; + }); + if (!options.length) { + options = [ + { value: "1", label: "1" }, + { value: "2", label: "2" }, + { value: "3", label: "3" }, + ]; + if (stage === "playoff") { + const current = String(control?.current_period || "").toLowerCase().match(/^ot(\d+)$/); + const count = Math.max(2, Number(current?.[1] || 0) + 1); + for (let number = 1; number <= count; number += 1) options.push({ value: `ot${number}`, label: `ОТ${number}` }); + } else { + options.push({ value: "ot", label: "ОТ" }); + } + } + const seen = new Set(); + return options.filter((item) => { + if (!item.value || seen.has(item.value)) return false; + seen.add(item.value); + return true; + }); +} + function quickPanelSelectorValue(selector) { + const options = quickPanelSelectorRuntimeOptions(selector); const values = hockeyMatchRuntimeValues(); const stored = String(values[`panel.${selector.id}.value`] ?? ""); - if (selector.options.some((option) => option.value === stored)) return stored; - return selector.default_value || selector.options[0]?.value || ""; + if (options.some((option) => option.value === stored)) return stored; + const configuredDefault = String(selector?.default_value || ""); + if (options.some((option) => option.value === configuredDefault)) return configuredDefault; + return options[0]?.value || ""; } async function hockeyRefreshQuickPanelMapping() { @@ -9355,16 +9407,18 @@ function hockeyScoreDockMarkup() { } function quickPanelSelectorMarkup(selector) { + const options = quickPanelSelectorRuntimeOptions(selector); const current = quickPanelSelectorValue(selector); const tooltip = selector.description || selector.label; if (selector.style === "select") { - return ``; + return ``; } - return `