From 76fbdefeaa380e0f11deea0299fe28c47a65444b Mon Sep 17 00:00:00 2001 From: migatu Date: Fri, 24 Jul 2026 17:22:48 +0200 Subject: [PATCH] =?UTF-8?q?feat(prezentacja):=20klikni=C4=99cie=20powi?= =?UTF-8?q?=C4=99ksza=20kosmogram=20na=20pe=C5=82ne=20okno=20(PRE-25)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ósma wskazówka partnerów, jako małe QoL przed PRE-22. Koło rysujemy w kolumnie tekstu, więc na mniejszym ekranie glify i stopnie robią się nieczytelne. Kliknięcie rozciąga wykres na całe okno, ponowne wraca do strony. SVG skaluje się bez utraty jakości, więc nie potrzeba drugiej wersji rysunku ani biblioteki. Wyjście z powiększenia na trzy sposoby: klik w wykres, klik w tło, Esc. Dostępne też z klawiatury (Enter/Spacja, focus-visible), bo inaczej obejrzenie szczegółów wymagałoby myszy. Dwie decyzje warte odnotowania: 1. WARSTWA. z-index 1100 CELOWO pomiędzy: ponad kontrolkami Leafleta (1000), ale PONIŻEJ okna postępu (1200). Gdy trwa pisanie horoskopu, log operacji ma zostać na wierzchu. Test pilnuje tej nierówności, bo to jedyna liczba tutaj, którą łatwo zmienić bez zastanowienia i zepsuć coś niewidocznego na oko. 2. ROZMIAR. Koło jest kwadratowe, więc ograniczamy je KRÓTSZYM bokiem okna (min(96vw, 92vh)) — inaczej na szerokim ekranie wystawałoby w pionie. Skrypt podpięty globalnie w base.html i osłonięty sprawdzeniem, czy koło w ogóle jest na stronie — zadziała też na przyszłej zakładce „Skompiluj" bez zmian. Przy powiększeniu blokujemy przewijanie strony pod spodem. Weryfikacja na żywej aplikacji, pomiarami w DOM: po kliknięciu .wheel-fig ma position:fixed, display:flex, z-index:1100; SVG rośnie z 460×460 do 662×653 przy oknie 1280×720, visibility visible; body dostaje overflow:hidden. Ponowne kliknięcie wraca do 460×460 i zdejmuje klasę. Zrzutu ekranu stanu powiększonego NIE mam — panel przeglądarki zaciął się w trakcie (puste klatki, viewport raportowany jako 0×0), więc opieram się na pomiarach i testach. Testy: 10 nowych. Całość: prezentacja 87 passed, logika 265 / 1 skip. Co-Authored-By: Claude Opus 4.8 --- docs/astrololo_wymagania.xlsx | Bin 36969 -> 37303 bytes services/presentation/app/static/styles.css | 18 +++++ services/presentation/app/static/wheelzoom.js | 60 ++++++++++++++++ services/presentation/app/templates/base.html | 3 + services/presentation/tests/test_wheelzoom.py | 64 ++++++++++++++++++ 5 files changed, 145 insertions(+) create mode 100644 services/presentation/app/static/wheelzoom.js create mode 100644 services/presentation/tests/test_wheelzoom.py diff --git a/docs/astrololo_wymagania.xlsx b/docs/astrololo_wymagania.xlsx index c7bb6d5977d1843145a729627904be61911e958f..7935e61a98edc863ce1a0c50811a174445f55397 100644 GIT binary patch delta 9193 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 m#!c-+k|U>(29| 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 y|BL_# + {# Powiększanie kosmogramu (PRE-25) — globalnie, bo koło pojawi się też na + zakładce „Skompiluj"; skrypt sam sprawdza, czy jest co powiększać. #} +
diff --git a/services/presentation/tests/test_wheelzoom.py b/services/presentation/tests/test_wheelzoom.py new file mode 100644 index 0000000..66faf8b --- /dev/null +++ b/services/presentation/tests/test_wheelzoom.py @@ -0,0 +1,64 @@ +"""Powiększanie kosmogramu na pełne okno (PRE-25). + +Test strukturalny, jak przy pozostałych rzeczach żyjących w JS/CSS. Osobno +pilnujemy warstwy nakładki: to jedyna liczba w tym pliku, którą łatwo zmienić +bez zastanowienia i zepsuć coś, czego się nie widzi na pierwszy rzut oka. +""" +import pathlib +import re + +APP = pathlib.Path(__file__).resolve().parents[1] / "app" +JS = (APP / "static" / "wheelzoom.js").read_text(encoding="utf-8") +CSS = (APP / "static" / "styles.css").read_text(encoding="utf-8") +BASE = (APP / "templates" / "base.html").read_text(encoding="utf-8") + + +def test_script_is_loaded_globally(): + """Ładowane w base.html, bo koło pojawi się też na zakładce Skompiluj.""" + assert "wheelzoom.js" in BASE + + +def test_toggles_on_click(): + assert "addEventListener('click'" in JS + assert "classList.toggle" in JS + + +def test_closes_with_escape(): + assert "'Escape'" in JS + + +def test_reachable_from_keyboard(): + """Bez tego jedyny sposób na obejrzenie szczegółów wykresu wymagałby myszy.""" + assert "tabindex" in JS + assert "'Enter'" in JS + + +def test_page_scroll_is_locked_while_zoomed(): + """Inaczej przewijanie „przecieka" na treść pod spodem, której i tak nie widać.""" + assert "wheel-zoom-open" in JS + assert re.search(r"body\.wheel-zoom-open\s*\{[^}]*overflow:\s*hidden", CSS) + + +def test_zoomed_layer_sits_above_map_but_below_progress(): + """Warstwy: kontrolki Leafleta 1000 < kosmogram < okno postępu 1200. + Gdy trwa pisanie horoskopu, log operacji ma zostać na wierzchu.""" + zoom = re.search(r"\.wheel-fig\.zoomed\s*\{[^}]*z-index:\s*(\d+)", CSS) + progress = re.search(r"\.progress-overlay\s*\{[^}]*z-index:\s*(\d+)", CSS) + assert zoom and progress, "nie znaleziono warstw w CSS" + assert 1000 < int(zoom.group(1)) < int(progress.group(1)) + + +def test_zoomed_wheel_is_bounded_by_shorter_window_side(): + """Koło jest kwadratowe — ograniczamy je krótszym bokiem okna, inaczej na + szerokim ekranie wystawałoby w pionie.""" + block = re.search(r"\.wheel-fig\.zoomed svg\.wheel\s*\{[^}]*\}", CSS) + assert block and "vh" in block.group(0) and "vw" in block.group(0) + + +def test_cursor_signals_the_affordance(): + assert "zoom-in" in CSS and "zoom-out" in CSS + + +def test_does_nothing_without_a_wheel(): + """Na zakładkach bez kosmogramu skrypt ma po prostu wyjść.""" + assert "if (!figures.length) return;" in JS -- 2.52.0