Wskaźnik offline: ramka zamiast belki + naprawa cyklicznego migania

Dwa zgłoszenia z kiosku (2026-07-31):

1. BELKA ZASŁANIAŁA DANE ALS. Pełnoekranowy pasek u góry zajmował pas
   ekranu i obcinał dane informacyjne w iframe. Zastąpiony cienką pulsującą
   RAMKĄ wokół całego ekranu (pointer-events: none, niczego nie zakrywa)
   plus małą plakietką w rogu. Z daleka widoczna równie dobrze.

2. WSKAŹNIK MIGAŁ zamiast świecić ciągle. disconnectedSince było resetowane
   przy KAŻDEJ nieudanej próbie reconnectu, nie tylko przy przejściu
   połączone->rozłączone — przy odstępie ponowień > 10 s (backoff dochodzi
   do 30 s) licznik ciszy zerował się co próbę i wskaźnik cyklicznie znikał
   i wracał. Teraz znacznik początku przerwy ustawiany wyłącznie przy
   przejściu ze stanu połączonego.

   Kontekst zgłoszenia: strona działa jeszcze przeciw STAREMU LuPortowi,
   który nie ma kanału zbiorczego ani uwierzytelniania WS — połączenie pada
   ciągle (oczekiwane do czasu wdrożenia; potem wstaje bez zmian), a błąd
   zamieniał tę ciągłą przerwę w miganie.

Testy: scenariusz 7 próbkuje wskaźnik co 500 ms przez 90 s ciągłej awarii
i wymaga 100% aktywnych próbek — z błędem aktywnych było 51/182 (72% czasu
zgaszony; dokładnie zgłoszone "pojawia się i znika"). Fałszywy WebSocket
odrzuca teraz połączenia jak przeglądarka (onclose po nieudanej próbie),
więc długa przerwa z ponowieniami jest testowalna. 11/11 scenariuszy PASS,
mutacja poprawki wywraca scenariusz 7.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-31 08:16:36 +02:00
parent d97d139d52
commit 89155c3f2a
4 changed files with 118 additions and 58 deletions
+54 -32
View File
@@ -145,43 +145,56 @@
text-shadow: 0 0 24px rgba(255, 0, 0, 0.6);
}
/* ── OFFLINE BANNER ──────────────────────────── */
/* Widoczna z daleka informacja o utracie łączności z LuPort.
POMARAŃCZOWA, nie czerwona — czerwień jest zarezerwowana dla alarmów
maszyn; ten pasek mówi „ekran może pokazywać nieświeży obraz",
a nie „maszyna stoi". Poprzednia wersja tej strony traciła połączenia
PO CICHU (patrz README, sekcja Historia) — ten pasek jest wprost
wnioskiem z tamtej awarii: utrata łączności ma być widoczna z hali,
a nie odkrywana po fakcie. */
#offline-banner {
/* ── OFFLINE INDICATOR ───────────────────────── */
/* Widoczna z daleka informacja o utracie łączności z LuPort — CIENKA
pulsująca RAMKA wokół całego ekranu plus mała plakietka w rogu.
Wcześniejsza pełnoekranowa belka u góry zasłaniała dane ALS
w iframe (zgłoszone 2026-07-31) — ramka niczego nie zakrywa,
a z daleka widać ją równie dobrze. POMARAŃCZOWA, nie czerwona:
czerwień jest zarezerwowana dla alarmów maszyn; ramka mówi „ekran
może pokazywać nieświeży obraz", a nie „maszyna stoi". Utrata
łączności MA być widoczna z hali — poprzednia wersja strony traciła
połączenia po cichu (README, Historia). */
#offline-indicator {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 9998;
background: #7a4a00;
color: #ffd9a0;
border-bottom: 3px solid #ffaa33;
padding: 10px 24px;
text-align: center;
font-size: clamp(16px, 2vw, 28px);
font-weight: 700;
letter-spacing: 0.05em;
}
#offline-banner.active {
#offline-indicator.active {
display: block;
animation: offlineBlink 2s step-start infinite;
}
@keyframes offlineBlink {
#offline-frame {
position: fixed;
inset: 0;
border: 6px solid #ffaa33;
pointer-events: none;
z-index: 9998;
animation: offlinePulse 2s ease-in-out infinite;
}
@keyframes offlinePulse {
0%,
100% {
background: #7a4a00;
border-color: #ffaa33;
box-shadow: inset 0 0 20px rgba(255, 170, 51, 0.25);
}
50% {
background: #9a5e00;
border-color: #7a4a00;
box-shadow: inset 0 0 6px rgba(255, 170, 51, 0.1);
}
}
#offline-chip {
position: fixed;
top: 10px;
right: 12px;
background: #7a4a00;
color: #ffd9a0;
border: 1px solid #ffaa33;
border-radius: 6px;
padding: 4px 12px;
font-size: 14px;
font-weight: 700;
letter-spacing: 0.05em;
pointer-events: none;
z-index: 9999;
}
/* ── STATUS BAR ──────────────────────────────── */
#status-bar {
@@ -222,7 +235,10 @@
<div id="machines-grid"></div>
</div>
<div id="offline-banner">⚠ BRAK POŁĄCZENIA Z LUPORT — DANE MOGĄ BYĆ NIEAKTUALNE ⚠</div>
<div id="offline-indicator">
<div id="offline-frame"></div>
<div id="offline-chip">⚠ OFFLINE — dane mogą być nieaktualne</div>
</div>
<!-- Ten element MUSI istnieć w DOM. Poprzednia wersja miała go
zakomentowanego, a refreshStatus() dalej po niego sięgał — TypeError
@@ -369,8 +385,14 @@
};
ws.onclose = () => {
// Znacznik początku przerwy ustawiany WYŁĄCZNIE przy przejściu
// połączone->rozłączone. Reset przy każdej NIEUDANEJ próbie
// reconnectu (jak wcześniej) zerował licznik ciszy co próbę i przy
// odstępie ponowień > 10 s wskaźnik offline cyklicznie znikał
// i wracał (zgłoszone 2026-07-31: „pasek pojawia się i znika") —
// zamiast świecić ciągle przez całą przerwę.
if (wsConnected) disconnectedSince = Date.now();
wsConnected = false;
disconnectedSince = Date.now();
clearTimeout(stableTimer);
refreshStatus();
reconnectTimer = setTimeout(connect, nextReconnectDelay());
@@ -482,11 +504,11 @@
: "WS: rozłączono — ponawiam…";
}
const banner = document.getElementById("offline-banner");
if (banner) {
const indicator = document.getElementById("offline-indicator");
if (indicator) {
const offlineLongEnough =
!wsConnected && Date.now() - disconnectedSince > OFFLINE_BANNER_AFTER_MS;
banner.classList.toggle("active", offlineLongEnough && !DEBUG_ALARM);
indicator.classList.toggle("active", offlineLongEnough && !DEBUG_ALARM);
}
}