diff --git a/docs/superpowers/specs/2026-08-31-pivot-stronicowanie-sortowanie-design.md b/docs/superpowers/specs/2026-08-31-pivot-stronicowanie-sortowanie-design.md new file mode 100644 index 000000000..c71549c33 --- /dev/null +++ b/docs/superpowers/specs/2026-08-31-pivot-stronicowanie-sortowanie-design.md @@ -0,0 +1,163 @@ +# Tabela krzyżowa: stronicowanie i sortowanie + +Data: 2026-08-31 +Branch: `feat-pivot-stronicowanie-sortowanie` + +## Problem + +Tabela krzyżowa (`postac=pivot` na `/zapytanie/`, `report_type=pivot` +w multiseeku) renderuje **wszystkie** wiersze macierzy naraz. Przy +`pivot_row=autor` to ~2000 wierszy na jednej stronie — nieużywalne. + +Brakuje też jakiegokolwiek sterowania kolejnością: `_labels()` sortuje +alfabetycznie po etykiecie (albo malejąco po roku dla `rok`/`koszyk_pk`) +i to jedyna dostępna kolejność. Typowe pytanie użytkownika brzmi „kto ma +najwięcej prac" — dziś wymaga eksportu do XLSX i posortowania w Excelu. + +## Zakres + +1. Stronicowanie wierszy macierzy — **obie** ścieżki wejścia (multiseek + „precyzyjne" i `/zapytanie/` DjangoQL), bo obie renderują ten sam + partial `multiseek/report-body-pivot.html`. +2. Sortowanie wierszy: po etykiecie (dzisiejsze, domyślne) albo po sumie + wiersza (RAZEM), oba kierunki. + +Poza zakresem: sortowanie kolumn (kolumn jest z definicji mało — bramka +`PIVOT_MAX_CELLS` i tak by nie przepuściła szerokiej macierzy), sortowanie +po konkretnej kolumnie, stronicowanie kolumn. + +## Rozważone podejścia + +| | Opis | Werdykt | +|---|---|---| +| A | Sortuj + stronicuj **już zbudowaną** macierz w pamięci | **wybrane** | +| B | `LIMIT/OFFSET` na kluczach wierszy w SQL-u | odrzucone | +| C | Sortowanie/stronicowanie po stronie klienta (DataTables) | odrzucone | + +**B** wymagałoby drugiego przebiegu po zbiorze, żeby policzyć sumy kolumn +i sumę całkowitą (te muszą obejmować cały dataset, nie widoczną stronę), +a przy wymiarze idącym przez `autorzy__` płaciłoby ten sam drogi JOIN +dwa razy. Bramka `PIVOT_MAX_PAIRS` i tak ogranicza rozmiar tego, co wchodzi +do RAM-u, więc oszczędność pamięci byłaby iluzoryczna. + +**C** przeczy sednu zgłoszenia: 2000 wierszy nadal poleciałoby do +przeglądarki. Strona musi też działać bez JS (partial ma `