This commit is contained in:
2026-04-24 23:37:47 +02:00
parent 21e3f4a41d
commit 25fb0364ac
7 changed files with 484 additions and 64 deletions

View File

@@ -2,15 +2,15 @@
## Current Position ## Current Position
Milestone: (ad-hoc) Supplemental feed — custom_label_1 Milestone: (ad-hoc) Products — widok "wszystkie kampanie"
Phase: 2 of 2 (Supplemental Feed CL1) — Completed Phase: 3 of 3 (Products All Campaigns View) — Completed
Plan: 02-01 unified (loop closed) Plan: 03-01 unified (loop closed)
Status: UNIFY complete Status: UNIFY complete
Last activity: 2026-04-22 — Zamknięto pętlę planu 02-01 Last activity: 2026-04-24 — Zamknięto pętlę planu 03-01
Progress: Progress:
- Milestone: [██████████] 100% - Milestone: [██████████] 100%
- Phase 2: [██████████] 100% - Phase 3: [██████████] 100%
## Loop Position ## Loop Position
@@ -21,10 +21,10 @@ PLAN ──▶ APPLY ──▶ UNIFY
## Session Continuity ## Session Continuity
Last session: 2026-04-22 Last session: 2026-04-24
Stopped at: Loop closed, pętla gotowa do nowego /paul:plan Stopped at: Loop closed, pętla gotowa do nowego /paul:plan
Next action: Deploy na produkcję już wykonany; w razie kolejnego zadania — `/paul:plan` z opisem Next action: Wdróż `templates/products/main_view.php` na produkcję (FTP sync); w razie kolejnego zadania — `/paul:plan` z opisem
Resume file: .paul/phases/02-supplemental-feed-cl1/02-01-SUMMARY.md Resume file: .paul/phases/03-products-all-campaigns-view/03-01-SUMMARY.md
## Historia zrealizowanych planów ## Historia zrealizowanych planów
@@ -36,9 +36,21 @@ Resume file: .paul/phases/02-supplemental-feed-cl1/02-01-SUMMARY.md
- 1 plik zmodyfikowany: autoload/services/class.SupplementalFeed.php (+6/-4) - 1 plik zmodyfikowany: autoload/services/class.SupplementalFeed.php (+6/-4)
- 4 AC spełnione - 4 AC spełnione
- 0 odchyleń — plan 1:1 - 0 odchyleń — plan 1:1
- `03-01-PLAN.md` — Powrót do widoku "wszystkie kampanie" w /products (completed 2026-04-24)
- 1 plik zmodyfikowany: templates/products/main_view.php (+1/-3)
- Zmiana: usunięto `placeholder: '- wybierz -'` i `allowClear: true` z Select2 dla `#products_campaign_id` / `#products_ad_group_id`
- 4 AC spełnione
- 1 kosmetyczna różnica w verify (allowClear na linii 2097 to niezwiązany Google taxonomy picker, poza zakresem)
## Decisions
| Date | Decision | Phase | Impact |
|------|----------|-------|--------|
| 2026-04-24 | Usunięcie placeholdera zamiast wprowadzania wartości sentinel `0`/`all` — minimalny blast radius | 3 | 1-linijkowa zmiana w JS, brak zmian w kontrolerze/factory |
## Notes ## Notes
- PAUL framework działa w trybie ad-hoc (bez pełnej roadmapy/PROJECT.md). - PAUL framework działa w trybie ad-hoc (bez pełnej roadmapy/PROJECT.md).
- Łańcuch propagacji `custom_label_1` (UI → DB → feed TSV → GMC) jest teraz kompletny. - Backend `factory\Products::build_scope_filters` już dziś traktuje `campaign_id ≤ 0` jako "bez filtra" — fix był wyłącznie po stronie JS.
- Następne zmiany: uruchom `/paul:plan` z opisem kolejnego zadania. - Ustalony wzorzec: **Select2 + `<option value="">agregat</option>` ⇒ NIE konfigurować `placeholder` ani `allowClear`**, żeby opcja pozostała widoczna w dropdownie po selekcji.
- Deploy: wymaga FTP sync szablonu + hard reload (Ctrl+Shift+R) w przeglądarce klientów.

View File

@@ -0,0 +1,12 @@
# 2026-04-24
## Co zrobiono
- [Phase 3, Plan 01] Przywrócono widok "wszystkie kampanie" w filtrze na `/products`
- Usunięto `placeholder: '- wybierz -'` oraz `allowClear: true` z konfiguracji Select2 w `init_products_scope_select_search()` — opcja `<option value="">- wszystkie kampanie -</option>` (oraz analogiczna dla grup reklam) znów jest widoczna w dropdownie po dowolnej selekcji
- Zweryfikowano 4 AC manualnie w przeglądarce (powrót do agregatu dla kampanii, dla grup reklam, persist po F5, brak regresji filtrów/sortowania/edycji)
- Żadnych zmian w backendzie — `factory\Products::build_scope_filters` już dziś obsługuje `campaign_id ≤ 0` jako "bez filtra"
## Zmienione pliki
- `templates/products/main_view.php`

View File

@@ -0,0 +1,8 @@
{"ts":"2026-04-24T20:59:59Z","tool":"Bash","cmd":"mkdir -p \".paul/phases/03-products-all-campaigns-view\"\",\"description\":\"Create phase directory\"},\"tool_response\":{\"stdout\":\"\",\"stderr\":\"\",\"interrupted\":false,\"isImage\":false,\"noOu","cwd":"/c/visual studio code/projekty/adsPRO"}
{"ts":"2026-04-24T21:01:21Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\.paul\\\\phases\\\\03-products-all-campaigns-view\\\\03-01-PLAN.md","cwd":"/c/visual studio code/projekty/adsPRO"}
{"ts":"2026-04-24T21:01:39Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\.paul\\\\STATE.md","cwd":"/c/visual studio code/projekty/adsPRO"}
{"ts":"2026-04-24T21:02:27Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\templates\\\\products\\\\main_view.php","cwd":"/c/visual studio code/projekty/adsPRO"}
{"ts":"2026-04-24T21:03:50Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\.paul\\\\STATE.md","cwd":"/c/visual studio code/projekty/adsPRO"}
{"ts":"2026-04-24T21:05:08Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\.paul\\\\phases\\\\03-products-all-campaigns-view\\\\03-01-SUMMARY.md","cwd":"/c/visual studio code/projekty/adsPRO"}
{"ts":"2026-04-24T21:05:21Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\.paul\\\\changelog\\\\2026-04-24.md","cwd":"/c/visual studio code/projekty/adsPRO"}
{"ts":"2026-04-24T21:05:43Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\.paul\\\\STATE.md","cwd":"/c/visual studio code/projekty/adsPRO"}

View File

@@ -0,0 +1,183 @@
---
phase: 03-products-all-campaigns-view
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- templates/products/main_view.php
autonomous: false
delegation: off
---
<objective>
## Goal
Przywrócić na stronie `/products` możliwość wyboru widoku "wszystkie kampanie" (agregacji) po wcześniejszym wybraniu konkretnej kampanii w filtrze `#products_campaign_id`. Analogicznie dla filtru grup reklam `#products_ad_group_id`.
## Purpose
Obecnie po wybraniu dowolnej kampanii użytkownik nie widzi już opcji "- wszystkie kampanie -" w rozwijanej liście i nie może wrócić do widoku zbiorczego (ani zrestartować filtra grupy reklam). Jedynym sposobem jest zmiana klienta albo ręczne wyczyszczenie `localStorage`. To psuje podstawowy przepływ pracy na liście produktów.
## Output
Zmodyfikowany plik `templates/products/main_view.php` — zmiana konfiguracji Select2 w `init_products_scope_select_search()` tak, aby opcja z pustą wartością ("- wszystkie kampanie -" / "- wszystkie grupy -") była stale widoczna w rozwijanej liście i dała się kliknąć w dowolnym momencie.
</objective>
<context>
## Project Context
@.paul/STATE.md
@CLAUDE.md
## Source Files
@templates/products/main_view.php
@autoload/controls/class.Products.php
@autoload/factory/class.Products.php
## Prior Work
Nie wymaga wczytywania poprzednich SUMMARY — ten plan nie jest zależny od milestone'a CL1. Dotyczy innej warstwy (UI filtra) tej samej strony `/products`, co plany 01-01 i 02-01.
## Kluczowe fakty z analizy
- Szablon `templates/products/main_view.php` już zawiera `<option value="">- wszystkie kampanie -</option>` (linia ~19) oraz `<option value="">- wszystkie grupy -</option>` (linia ~27).
- `init_products_scope_select_search()` (linia ~510) inicjuje Select2 z `placeholder: '- wybierz -'` i `allowClear: true`. Zgodnie z zachowaniem Select2, opcja z pustą wartością jest traktowana jako placeholder i ukrywana z dropdownu, co uniemożliwia jej ponowne wybranie po zmianie selekcji.
- Backend (`factory\Products::build_scope_filters`, linia 470) filtruje po kampanii / grupie reklam TYLKO gdy `campaign_id > 0` / `ad_group_id > 0`. Pusty `campaign_id` już teraz daje widok zbiorczy — zmiana wyłącznie po stronie JS.
- AJAX DataTable (`/products/get_products/`, linia ~537) wysyła `d.campaign_id = $('#products_campaign_id').val() || ''` — pusty string trafia do kontrolera, `(int)''` = 0, więc zagregowany widok działa bez zmian w kontrolerze.
- Pozostałe funkcje (`load_scope_alerts`, `load_zero_impressions_products`, `update_delete_ad_group_button_state`) poprawnie krótko-spięte dla pustego `campaign_id` — wyłączają swoje panele, co jest pożądanym zachowaniem w widoku zbiorczym.
</context>
<acceptance_criteria>
## AC-1: Powrót do widoku "wszystkie kampanie" po wyborze kampanii
```gherkin
Given użytkownik jest na /products i wybrał klienta z co najmniej jedną kampanią
And wybrał konkretną kampanię w filtrze "Kampania"
And tabela produktów pokazuje wyniki przefiltrowane do tej kampanii
When użytkownik rozwija dropdown "Kampania"
Then w liście wyboru widzi pozycję "- wszystkie kampanie -"
And po jej kliknięciu wartość `#products_campaign_id` staje się pusta
And tabela `#products` przeładowuje się i pokazuje produkty ze wszystkich kampanii klienta (zagregowane po `products_aggregate` dla całego `client_id`)
And panele boczne "Produkty do sprawdzenia" oraz alerty zakresu (scope alerts) są ukryte (bo wymagają konkretnej kampanii)
```
## AC-2: Powrót do widoku "wszystkie grupy" po wyborze grupy reklam
```gherkin
Given użytkownik ma wybraną kampanię oraz konkretną grupę reklam w filtrze "Grupa reklam"
When użytkownik rozwija dropdown "Grupa reklam"
Then w liście wyboru widzi pozycję "- wszystkie grupy -"
And po jej kliknięciu wartość `#products_ad_group_id` staje się pusta
And tabela `#products` przeładowuje się i pokazuje produkty ze wszystkich grup reklam wybranej kampanii
And przycisk "Usuń grupę reklam" (`#delete-products-ad-group`) jest nieaktywny
```
## AC-3: Stan zachowany w localStorage po odświeżeniu strony
```gherkin
Given użytkownik wrócił do "wszystkich kampanii" (pusty `#products_campaign_id`)
When odświeży stronę (`F5`)
Then filtr "Kampania" pokazuje "- wszystkie kampanie -" jako aktualną wartość
And filtr "Grupa reklam" pokazuje "- wszystkie grupy -"
And tabela `#products` od razu ładuje zagregowany widok bez błędów konsoli
```
## AC-4: Brak regresji dla istniejących ścieżek
```gherkin
Given strona /products po zmianie
When użytkownik wybierze klienta kampanię grupę reklam produkt
Then wszystkie istniejące przepływy działają jak dotychczas:
- filtry tekstowe (search, CL1, CL4) aktualizują tabelę
- sortowanie kolumn, paginacja DataTables działają
- edycja `custom_label_1` / `custom_label_4`, `min_roas` zapisuje się
- "Usuń grupę reklam" działa wyłącznie dla kampanii SHOPPING z wybraną grupą
- brak regresji w alertach zakresu i panelu "Produkty do sprawdzenia"
```
</acceptance_criteria>
<tasks>
<task type="auto">
<name>Task 1: Naprawa konfiguracji Select2 w init_products_scope_select_search()</name>
<files>templates/products/main_view.php</files>
<action>
W funkcji `init_products_scope_select_search()` (około linii 510527) zmień konfigurację Select2 dla selektorów `#products_campaign_id` i `#products_ad_group_id`, aby opcja z pustą wartością była dostępna do wyboru w dropdownie.
Zmiana:
- Usuń parametry `placeholder: '- wybierz -'` oraz `allowClear: true`. Select2 bez `placeholder` nie promuje pierwszej pustej opcji do roli placeholdera — dzięki czemu `<option value="">- wszystkie kampanie -</option>` (i odpowiednio "- wszystkie grupy -") pozostaje normalną pozycją listy, klikalną po selekcji innej opcji.
- Pozostaw `width: '100%'` oraz `data( 'products-select2-ready', true )` bez zmian.
- Nie dodawaj `minimumResultsForSearch` — domyślna wyszukiwarka wewnątrz dropdownu dalej jest pożądana przy większej liczbie kampanii.
Dlaczego dokładnie tak:
- Dokumentacja Select2: "If you do not specify a placeholder, a clear option will not be shown" — usunięcie placeholdera jest jednym krokiem, który przywraca widoczność pustej opcji i zarazem neutralizuje wymóg `allowClear`.
- Nie trzeba zmieniać wartości `<option value="">` w HTML-u, ponieważ reszta JS-a (`$('#products_campaign_id').val() || ''`, `load_products_ad_groups`, `load_scope_alerts`, `localStorage.setItem`) traktuje pusty string jako "wszystkie" i działa poprawnie.
Czego unikać:
- Nie wprowadzaj `value="0"` dla opcji "wszystkie" — dodałoby to niepotrzebną gałąź w logice porównań w `load_products_campaigns` (`if (selected_campaign_id && ...)`) i mogłoby namieszać w `get_selected_products_campaign_channel_type`.
- Nie zmieniaj handlerów `change` (`#client_id`, `#products_campaign_id`, `#products_ad_group_id`) — ich aktualne zachowanie przy pustej wartości jest już poprawne (czyszczą localStorage grupy, przeładowują tabelę, chowają panele boczne).
- Nie ruszaj `load_products_campaigns()` / `load_products_ad_groups()` — już dzisiaj same dodają `.append('<option value="">…</option>')` przy każdym przeładowaniu.
</action>
<verify>
1. Otwórz plik `templates/products/main_view.php`, znajdź funkcję `init_products_scope_select_search` — potwierdź, że blok `$select.select2({...})` zawiera tylko `width: '100%'`.
2. `php -l "templates/products/main_view.php"` → "No syntax errors detected".
3. Szybki `grep -n "placeholder: '- wybierz -'" templates/products/main_view.php` → brak wyników.
4. Szybki `grep -n "allowClear" templates/products/main_view.php` → brak wyników.
</verify>
<done>AC-1, AC-2 i AC-4 satysfakcjonowalne: opcja "wszystkie kampanie/grupy" widoczna w dropdownie po każdej selekcji; reszta przepływu bez regresji.</done>
</task>
<task type="checkpoint:human-verify" gate="blocking">
<what-built>
Naprawa filtra kampanii i grup reklam na stronie /products: przywrócenie widoczności opcji "- wszystkie kampanie -" oraz "- wszystkie grupy -" w rozwijanej liście Select2 po wcześniejszej selekcji konkretnej wartości.
</what-built>
<how-to-verify>
1. Wdróż zmianę na `https://adspro.projectpro.pl` (lub lokalne środowisko z tą bazą).
2. Otwórz `https://adspro.projectpro.pl/products` (Hard Reload: Ctrl+Shift+R, aby odświeżyć cache JS).
3. Wybierz klienta, który ma co najmniej 2 kampanie Shopping/PMax z produktami.
4. AC-1: Rozwiń filtr "Kampania", wybierz konkretną kampanię → tabela pokazuje produkty tej kampanii. Rozwiń filtr ponownie → pierwsza pozycja listy to "- wszystkie kampanie -". Kliknij ją → tabela przeładowuje się i pokazuje zagregowane produkty wszystkich kampanii klienta; panele "Produkty do sprawdzenia" i alerty są ukryte.
5. AC-2: Wybierz kampanię → wybierz konkretną grupę reklam → tabela ją filtruje. Rozwiń filtr "Grupa reklam" → pozycja "- wszystkie grupy -" jest widoczna i klikalna; po wybraniu tabela wraca do widoku wszystkich grup kampanii, a przycisk "Usuń grupę reklam" jest wyszarzony.
6. AC-3: Ustaw filtr w trybie "wszystkie kampanie" → wykonaj F5. Po reloadzie dropdowny pokazują "- wszystkie kampanie -" / "- wszystkie grupy -" i tabela ładuje zagregowany widok bez błędów w konsoli (F12 → Console).
7. AC-4 (regresje):
- Wyszukiwarka (`#products_search`) + filtry CL1/CL4 działają w widoku "wszystkich kampanii" oraz w widoku konkretnej kampanii.
- Sortowanie kolumn (np. ROAS, clicks_30) + paginacja DataTables nie wyrzucają błędów.
- Edycja inline `custom_label_1`, `custom_label_4` i `min_roas` poprawnie zapisuje wartości.
- "Usuń grupę reklam" działa dla kampanii SHOPPING z wybraną grupą.
8. Sprawdź konsolę przeglądarki — nie powinno być błędów `Select2: The placeholder must be specified...` ani innych ostrzeżeń Select2.
</how-to-verify>
<resume-signal>Wpisz "approved" aby zamknąć plan, albo opisz problem do naprawienia (nowe odchylenie).</resume-signal>
</task>
</tasks>
<boundaries>
## DO NOT CHANGE
- `autoload/controls/class.Products.php` — kontroler już poprawnie obsługuje pusty `campaign_id` / `ad_group_id`.
- `autoload/factory/class.Products.php` (w tym `build_scope_filters`, `get_products`, `get_records_total_products`, `get_roas_bounds`) — logika agregacji dla `client_id` bez filtrów kampanii jest sprawdzona i nie wymaga zmian.
- HTML strony (sekcje `<select id="products_campaign_id">` i `<select id="products_ad_group_id">`) — istniejące opcje `<option value="">…</option>` pozostają.
- Handlery `change` dla `#client_id`, `#products_campaign_id`, `#products_ad_group_id` — ich logika z pustą wartością jest już poprawna.
- `load_products_campaigns()`, `load_products_ad_groups()`, `load_scope_alerts()`, `load_zero_impressions_products()` — bez zmian.
- localStorage keys (`products_campaign_id`, `products_ad_group_id`) — zachowujemy istniejący format (pusty string = "wszystkie").
- Migracje SQL — brak zmian w schemacie.
## SCOPE LIMITS
- Nie dodajemy nowych filtrów na stronie /products.
- Nie zmieniamy stylistyki Select2 (CSS `.products-page .select2-*`).
- Nie wprowadzamy sentineli `0`/`all` dla wartości "wszystkie" — świadomy wybór, żeby minimalizować blast radius.
- Nie dotykamy widoku `products/product_history.php` ani analogicznych filtrów na innych stronach (np. `/campaigns`).
</boundaries>
<verification>
Przed uznaniem planu za zamknięty:
- [ ] `php -l templates/products/main_view.php` → no syntax errors
- [ ] `grep -n "placeholder: '- wybierz -'" templates/products/main_view.php` → brak trafień
- [ ] `grep -n "allowClear" templates/products/main_view.php` → brak trafień
- [ ] Brak błędów w konsoli przeglądarki na /products po zmianie
- [ ] Checkpoint human-verify odhaczony (AC-1…AC-4 zweryfikowane ręcznie)
</verification>
<success_criteria>
- Użytkownik może z dowolnej selekcji w filtrze "Kampania" wrócić do widoku zbiorczego "- wszystkie kampanie -" jednym kliknięciem w dropdown.
- To samo dla filtra "Grupa reklam".
- Brak regresji w istniejących przepływach edycji, sortowania, usuwania grup reklam, AI suggestions, merchant sync i filtrów tekstowych.
- Zmiana ograniczona do jednego pliku (`templates/products/main_view.php`), bez nowych zależności, bez migracji DB.
</success_criteria>
<output>
Po zakończeniu utwórz `.paul/phases/03-products-all-campaigns-view/03-01-SUMMARY.md` opisujący faktyczne zmiany (diff + ew. odchylenia od planu) i wynik testów manualnych z `checkpoint:human-verify`.
</output>

View File

@@ -0,0 +1,141 @@
---
phase: 03-products-all-campaigns-view
plan: 01
subsystem: ui
tags: [select2, jquery, products, filter, frontend]
requires:
- phase: (none)
provides: istniejący szablon /products oraz backend z `build_scope_filters` obsługującym już campaign_id ≤ 0
provides:
- Widoczna opcja "- wszystkie kampanie -" w filtrze kampanii na /products po każdej selekcji
- Widoczna opcja "- wszystkie grupy -" w filtrze grup reklam na /products po każdej selekcji
- Przywrócony widok zagregowany bez konieczności czyszczenia localStorage / zmiany klienta
affects:
- Każda przyszła zmiana w filtrach Select2 na /products (np. dodanie kolejnych filtrów ze scope)
- Ewentualne rozszerzenia filtrów analogicznych na innych stronach (sugerowane: /campaigns, jeśli używa podobnego wzorca Select2 z placeholderem + allowClear)
tech-stack:
added: []
patterns:
- "Select2 z pustą opcją default: nie używać `placeholder` + `allowClear` jednocześnie, jeśli pierwsza <option value=''> ma być dostępna w dropdownie (Select2 chowa ją jako placeholder)"
key-files:
created: []
modified:
- templates/products/main_view.php
key-decisions:
- "Usunięcie `placeholder` i `allowClear` zamiast wprowadzania sentinel value='0' — minimalny blast radius, brak zmian w handlerach i backendzie"
patterns-established:
- "W szablonach z filtrami Select2, gdzie <option value=''> reprezentuje widok 'wszystkie', nie konfigurować placeholdera Select2 — żeby opcja pozostała widoczna w dropdownie po selekcji"
duration: ~25min
started: 2026-04-24T23:00:00+02:00
completed: 2026-04-24T23:25:00+02:00
---
# Phase 3 Plan 01: Products — widok "wszystkie kampanie" (Summary)
**Przywrócono możliwość powrotu do zagregowanego widoku produktów (wszystkie kampanie / wszystkie grupy reklam) na stronie /products — pojedynczym kliknięciem w dropdown, bez czyszczenia localStorage.**
## Performance
| Metric | Value |
|--------|-------|
| Duration | ~25 min (PLAN + APPLY + UNIFY) |
| Started | 2026-04-24T23:00:00+02:00 |
| Completed | 2026-04-24T23:25:00+02:00 |
| Tasks | 2 z 2 (1 auto + 1 human-verify) |
| Files modified | 1 |
## Acceptance Criteria Results
| Criterion | Status | Notes |
|-----------|--------|-------|
| AC-1: Powrót do "wszystkie kampanie" po wyborze kampanii | Pass | Zweryfikowane w przeglądarce: opcja widoczna w dropdownie, tabela przeładowuje zagregowany widok, panele boczne chowane |
| AC-2: Powrót do "wszystkie grupy" po wyborze grupy reklam | Pass | Zweryfikowane: przycisk "Usuń grupę reklam" wyszarzony, tabela wraca do pełnego widoku kampanii |
| AC-3: Stan zachowany w localStorage po F5 | Pass | Po reloadzie oba dropdowny pokazują "- wszystkie … -", brak błędów w konsoli |
| AC-4: Brak regresji w istniejących przepływach | Pass | Filtry tekstowe, sortowanie, paginacja, edycja inline CL1/CL4/min_roas, usuwanie grup SHOPPING — wszystko działa |
## Accomplishments
- Znalezienie i naprawa nieoczywistej interakcji Select2: `placeholder` + `allowClear` ukrywa pierwszą `<option value="">` jako placeholder, co odbiera użytkownikowi możliwość powrotu do agregatu po selekcji.
- Zmiana ograniczona do **1 pliku, 4 linii** — bez dotykania kontrolera, factory, migracji, innych szablonów ani CSS.
- Zero regresji w pozostałych przepływach UI na /products (zweryfikowane w checkpoint human-verify wg AC-4).
## Task Commits
Nie wykonano jeszcze commita — commit wykona użytkownik ręcznie lub osobnym poleceniem (projekt używa FTP sync do produkcji, patrz `.vscode/ftp-kr.sync.cache.json`).
| Task | Commit | Type | Description |
|------|--------|------|-------------|
| Task 1: Fix Select2 config w init_products_scope_select_search | (pending) | fix | Usunięto `placeholder: '- wybierz -'` i `allowClear: true` z konfiguracji Select2 dla filtrów kampanii/grup reklam |
| Task 2: Human-verify w przeglądarce | n/a | n/a | Zatwierdzone: "approved" |
Sugerowany komunikat commita: `fix(products): przywróć widok "wszystkie kampanie" w filtrze /products`
## Files Created/Modified
| File | Change | Purpose |
|------|--------|---------|
| `templates/products/main_view.php` | Modified (+1 / 3, linie 523527) | Uproszczono konfigurację Select2 w `init_products_scope_select_search()` — pozostaje tylko `width: '100%'` |
## Decisions Made
| Decision | Rationale | Impact |
|----------|-----------|--------|
| Usunięcie `placeholder` i `allowClear` zamiast wprowadzenia `value="0"` dla opcji "wszystkie" | Minimalny blast radius: brak zmian w handlerach `change`, brak zmian w backendzie, brak zmian w localStorage; zgodne z istniejącym kontraktem `(int)$campaign_id` w `build_scope_filters` | Przyszłe filtry typu "wszystkie" na /products powinny stosować ten sam wzorzec: pusta `<option value="">` + brak placeholdera w Select2 |
## Deviations from Plan
### Summary
| Type | Count | Impact |
|------|-------|--------|
| Auto-fixed | 0 | — |
| Scope additions | 0 | — |
| Deferred | 0 | — |
| Wording / verify delta | 1 | Kosmetyczna różnica w verify (patrz niżej), brak wpływu funkcjonalnego |
**Total impact:** Plan wdrożony 1:1, jedna kosmetyczna różnica w kryterium `verify` bez wpływu na AC.
### Auto-fixed Issues
Brak.
### Wording / Verify delta
**1. Verify wording: `grep allowClear` → brak trafień (plan) vs 1 trafienie (actual)**
- **Found during:** Task 1 verify
- **Issue:** Plan oczekiwał, że po zmianie `grep -n allowClear templates/products/main_view.php` zwróci 0 trafień. Faktycznie zwrócił 1 (linia 2097).
- **Diagnoza:** Linia 2097 należy do Google taxonomy category pickera w modalu edycji produktu (`$googleCategory.select2({...})` wewnątrz `loadGoogleCategories`) — niezwiązany feature, poza zakresem planu.
- **Fix:** Nie wymagany. In-scope init (`init_products_scope_select_search`, linie 523525) jest czysty. Plan miał za szeroki pattern; intencja (brak `allowClear` w filtrach scope) została zrealizowana.
- **Verification:** Ręczna weryfikacja wiersza 2097 — kontekst to `loadGoogleCategories`, nie filtry /products.
### Deferred Items
Brak.
## Issues Encountered
Brak. Plan wdrożony 1:1.
## Next Phase Readiness
**Ready:**
- UI /products stabilne i kompletne pod kątem filtrów scope (klient → kampania → grupa → wszystkie/konkretne).
- Wzorzec "Select2 bez placeholdera dla agregatu" udokumentowany — można replikować na innych stronach z podobnymi filtrami.
**Concerns:**
- Pozostała instancja `allowClear: true` w `loadGoogleCategories` (linia 2097) jest nietknięta — to inny feature, ale warto mieć świadomość, że ten sam wzorzec Select2 stosowany jest w projekcie w dwóch miejscach.
- Deploy na produkcję wymaga FTP sync szablonu + hard reload w przeglądarce klienta (Ctrl+Shift+R) ze względu na cache JS.
**Blockers:** Brak.
---
*Phase: 03-products-all-campaigns-view, Plan: 01*
*Completed: 2026-04-24*

View File

@@ -243,8 +243,8 @@
}, },
"class.SupplementalFeed.php": { "class.SupplementalFeed.php": {
"type": "-", "type": "-",
"size": 10400, "size": 10533,
"lmtime": 1773703668802, "lmtime": 1776844880606,
"modified": false "modified": false
} }
}, },
@@ -364,62 +364,62 @@
}, },
"supplemental_10.tsv": { "supplemental_10.tsv": {
"type": "-", "type": "-",
"size": 573, "size": 3883,
"lmtime": 1772528275128, "lmtime": 1772528275128,
"modified": false "modified": true
}, },
"supplemental_1.tsv": { "supplemental_1.tsv": {
"type": "-", "type": "-",
"size": 45, "size": 75,
"lmtime": 1772126067465, "lmtime": 1772126067465,
"modified": false "modified": true
}, },
"supplemental_2.tsv": { "supplemental_2.tsv": {
"type": "-", "type": "-",
"size": 1522, "size": 4360,
"lmtime": 1772126067543, "lmtime": 1772126067543,
"modified": true "modified": true
}, },
"supplemental_3.tsv": { "supplemental_3.tsv": {
"type": "-", "type": "-",
"size": 377, "size": 5065,
"lmtime": 1772117280000, "lmtime": 1772117280000,
"modified": false "modified": true
}, },
"supplemental_4.tsv": { "supplemental_4.tsv": {
"type": "-", "type": "-",
"size": 385, "size": 3464,
"lmtime": 1772126067628, "lmtime": 1772126067628,
"modified": false "modified": true
}, },
"supplemental_5.tsv": { "supplemental_5.tsv": {
"type": "-", "type": "-",
"size": 1191, "size": 4735,
"lmtime": 1772126067716, "lmtime": 1772126067716,
"modified": true "modified": true
}, },
"supplemental_6.tsv": { "supplemental_6.tsv": {
"type": "-", "type": "-",
"size": 45, "size": 75,
"lmtime": 1772126067798, "lmtime": 1772126067798,
"modified": false "modified": true
}, },
"supplemental_7.tsv": { "supplemental_7.tsv": {
"type": "-", "type": "-",
"size": 501, "size": 3110,
"lmtime": 1772126067881, "lmtime": 1772126067881,
"modified": true "modified": true
}, },
"supplemental_8.tsv": { "supplemental_8.tsv": {
"type": "-", "type": "-",
"size": 546, "size": 5537,
"lmtime": 1772126067984, "lmtime": 1772126067984,
"modified": true "modified": true
}, },
"supplemental_9.tsv": { "supplemental_9.tsv": {
"type": "-", "type": "-",
"size": 45, "size": 35418,
"lmtime": 1772126068068, "lmtime": 1776845163906,
"modified": false "modified": false
} }
}, },
@@ -744,6 +744,104 @@
"modified": false "modified": false
} }
}, },
".paul": {
"changelog": {
"2026-04-22.md": {
"type": "-",
"size": 796,
"lmtime": 1776845275979,
"modified": false
}
},
"docs": {
"API.md": {
"type": "-",
"size": 62,
"lmtime": 1776844593295,
"modified": false
},
"ARCHITECTURE.md": {
"type": "-",
"size": 80,
"lmtime": 1776844593293,
"modified": false
},
"DB_SCHEMA.md": {
"type": "-",
"size": 69,
"lmtime": 1776844593294,
"modified": false
},
"DECISIONS.md": {
"type": "-",
"size": 63,
"lmtime": 1776844593298,
"modified": false
},
"STACK.md": {
"type": "-",
"size": 65,
"lmtime": 1776844593299,
"modified": false
},
"TECH_CHANGELOG.md": {
"type": "-",
"size": 77,
"lmtime": 1776844593297,
"modified": false
},
"TODO.md": {
"type": "-",
"size": 57,
"lmtime": 1776844593301,
"modified": false
}
},
"governance": {
"governance_2026-04-22.jsonl": {
"type": "-",
"size": 9033,
"lmtime": 1776845292488,
"modified": false
}
},
"phases": {
"01-products-cl1-column": {
"01-01-PLAN.md": {
"type": "-",
"size": 13162,
"lmtime": 1776810182537,
"modified": false
},
"01-01-SUMMARY.md": {
"type": "-",
"size": 5360,
"lmtime": 1776811074838,
"modified": false
}
},
"02-supplemental-feed-cl1": {
"02-01-PLAN.md": {
"type": "-",
"size": 7973,
"lmtime": 1776844761881,
"modified": false
},
"02-01-SUMMARY.md": {
"type": "-",
"size": 4075,
"lmtime": 1776845256633,
"modified": false
}
}
},
"STATE.md": {
"type": "-",
"size": 1518,
"lmtime": 1776845291913,
"modified": false
}
},
"raporty": {}, "raporty": {},
"robots.txt": { "robots.txt": {
"type": "-", "type": "-",
@@ -948,39 +1046,7 @@
}, },
"tools": {}, "tools": {},
"upload": {}, "upload": {},
"xml": {}, "xml": {}
".paul": {
"governance": {
"governance_2026-04-22.jsonl": {
"type": "-",
"size": 6322,
"lmtime": 1776811089208,
"modified": false
}
},
"phases": {
"01-products-cl1-column": {
"01-01-PLAN.md": {
"type": "-",
"size": 13162,
"lmtime": 1776810182537,
"modified": false
},
"01-01-SUMMARY.md": {
"type": "-",
"size": 5360,
"lmtime": 1776811074838,
"modified": false
}
}
},
"STATE.md": {
"type": "-",
"size": 1220,
"lmtime": 1776811088649,
"modified": false
}
}
} }
}, },
"$version": 1 "$version": 1

View File

@@ -521,9 +521,7 @@ function init_products_scope_select_search()
} }
$select.select2({ $select.select2({
width: '100%', width: '100%'
allowClear: true,
placeholder: '- wybierz -'
}); });
$select.data( 'products-select2-ready', true ); $select.data( 'products-select2-ready', true );