update
This commit is contained in:
@@ -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.
|
||||||
|
|||||||
12
.paul/changelog/2026-04-24.md
Normal file
12
.paul/changelog/2026-04-24.md
Normal 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`
|
||||||
8
.paul/governance/governance_2026-04-24.jsonl
Normal file
8
.paul/governance/governance_2026-04-24.jsonl
Normal 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"}
|
||||||
183
.paul/phases/03-products-all-campaigns-view/03-01-PLAN.md
Normal file
183
.paul/phases/03-products-all-campaigns-view/03-01-PLAN.md
Normal 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 510–527) 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>
|
||||||
141
.paul/phases/03-products-all-campaigns-view/03-01-SUMMARY.md
Normal file
141
.paul/phases/03-products-all-campaigns-view/03-01-SUMMARY.md
Normal 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 523–527) | 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 523–525) 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*
|
||||||
168
.vscode/ftp-kr.sync.cache.json
vendored
168
.vscode/ftp-kr.sync.cache.json
vendored
@@ -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
|
||||||
|
|||||||
@@ -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 );
|
||||||
|
|||||||
Reference in New Issue
Block a user