This commit is contained in:
2026-09-18 17:45:27 +03:00
parent 52cd9a15e3
commit b2937fae17
3 changed files with 24 additions and 6 deletions

2
app.py
View File

@@ -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.09.18.1"
BUILD_VERSION = "2026.09.18.2"
# compatibility: BUILD_VERSION = "2026.08.26.1"
# compatibility: BUILD_VERSION = "2026.08.25.1"
# compatibility: BUILD_VERSION = "2026.08.24.15"

View File

@@ -996,6 +996,9 @@
}
async function refreshDrawerCache() {
// Do not patch/re-render Runtime data while the operator edits settings.
// The hourly server refresh keeps running; the browser catches up afterwards.
if (operatorSettingsEditingActive()) return;
if ((!state.open && !state.selectedId) || state.drawerRefreshBusy) return;
state.drawerRefreshBusy = true;
try {
@@ -1995,6 +1998,17 @@ function selectedGameIsFinished() {
return Boolean(state.selectedGame?.is_finished);
}
function operatorSettingsEditingActive() {
// BUILD144: settings are operator-owned UI state. Live match/schedule refresh
// may continue on the server, but must not rebuild the Runtime while an
// operator is typing into either Stat2TV settings or a full UI settings modal.
return Boolean(
state.settingsModal
|| document.querySelector(".hockey-settings-modal")
|| document.querySelector(".modal-settings-full")
);
}
function scheduleSelectedGamePoll(delay = 1000) {
stopSelectedGamePolling();
if (!state.selectedGameId || selectedGameIsFinished()) {
@@ -2022,6 +2036,7 @@ async function pollSelectedGame() {
|| !state.selectedGameId
|| !state.selectedId
|| state.open
|| operatorSettingsEditingActive()
|| selectedGameIsFinished()
) {
scheduleSelectedGamePoll(1000);
@@ -2498,6 +2513,10 @@ document.addEventListener("visibilitychange", () => {
const close = () => {
modal.remove();
state.settingsModal = null;
if (state.selectedGameId && !selectedGameIsFinished()) {
scheduleSelectedGamePoll(150);
}
if (state.selectedId) scheduleDrawerRefresh(250);
};
modal.querySelector("[data-settings-close]").addEventListener("click", close);
modal.querySelector(".hockey-settings-backdrop").addEventListener("click", close);

View File

@@ -13635,15 +13635,14 @@ function renderHockeyPenaltyDashboard(node, component, runtime) {
function runtimeVisibleTabs() {
const standings = getByPath(state.data, "hockey.standings") || {};
const schedule = getByPath(state.data, "hockey.schedule") || {};
const teamSchedule = getByPath(state.data, "hockey.team_schedule") || {};
const selectedGame = getByPath(state.data, "hockey.selected_game") || null;
const selectedTournament = getByPath(state.data, "hockey.selected_tournament") || null;
const hasSchedule = (Array.isArray(schedule.items) && schedule.items.length > 0)
|| (Array.isArray(teamSchedule.items) && teamSchedule.items.length > 0);
const visible = state.config.tabs.filter((tab) => {
if (tab.id === "standings") return Boolean(standings.available && Array.isArray(standings.variants) && standings.variants.length);
if (tab.id === "schedule") return hasSchedule;
// BUILD144: Schedule is navigation, not a data-availability indicator.
// Keep the tab visible even when the selected day has zero games or while
// the schedule cache is still loading; the component shows its empty state.
if (tab.id === "schedule") return true;
if (tab.id === "shootout") return Boolean(selectedGame && String(selectedTournament?.stage_key || "").toLowerCase() === "regular");
return true;
});