feat: custom labels toggle and inline editing in product list

Adds session-based show/hide toggle for custom labels in admin product list, inline editable fields for custom_label_0..4, and label suggestions with custom entry support. Includes repository/controller updates, UI fixes, tests, and PAUL docs release updates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jacek
2026-04-19 11:09:19 +02:00
parent 41e491c6b7
commit 9577d4944a
15 changed files with 856 additions and 42 deletions

View File

@@ -0,0 +1,201 @@
---
phase: 16-product-list-custom-labels
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- autoload/admin/Controllers/ShopProductController.php
- autoload/Domain/Product/ProductRepository.php
- admin/templates/shop-product/products-list-custom-script.php
- tests/Unit/admin/Controllers/ShopProductControllerTest.php
- tests/Unit/Domain/Product/ProductRepositoryTest.php
autonomous: false
delegation: off
---
<objective>
## Goal
Dodac w liscie produktow (`/admin/shop_product/view_list/`) przelacznik "Pokaz etykiety niestandardowe", ktory zapisuje stan w sesji i po wlaczeniu pokazuje szybka edycje 5 pol `custom_label_0..4` z podpowiedziami.
## Purpose
Administrator ma szybciej uzupelniac etykiety Google XML bez wchodzenia do edycji kazdego produktu, z zachowaniem spojnosc danych i wygodnych podpowiedzi istniejacych wartosci.
## Output
- Nowy przycisk obok "Dodaj produkt", sterujacy widocznoscia custom labels i zapisujacy stan w sesji
- Render 5 pol `custom_label_0..4` pod nazwa/SKU produktu w tabeli, tylko przy wlaczonej opcji
- Zapis kazdego pola do `pp_shop_products` oraz system podpowiedzi z istniejacych wartosci w bazie
- Odczyt nazw etykiet z bazy (z fallbackiem) zamiast hardcodu w widoku listy
</objective>
<context>
## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md
@.paul/STATE.md
## Source Files
@autoload/admin/Controllers/ShopProductController.php
@autoload/Domain/Product/ProductRepository.php
@admin/templates/components/table-list.php
@admin/templates/shop-product/products-list.php
@admin/templates/shop-product/products-list-custom-script.php
@tests/Unit/admin/Controllers/ShopProductControllerTest.php
@tests/Unit/Domain/Product/ProductRepositoryTest.php
</context>
<skills>
## Required Skills (from SPECIAL-FLOWS.md)
| Skill | Priority | When to Invoke | Loaded? |
|-------|----------|----------------|---------|
| /feature-dev | required | Before implementation in APPLY | ○ |
| /koniec-pracy | required | After implementation/release wrap-up | ○ |
**BLOCKING:** Required skills MUST be loaded before APPLY proceeds.
Run each skill command or confirm already loaded.
## Skill Invocation Checklist
- [ ] /feature-dev loaded (run command or confirm)
- [ ] /koniec-pracy loaded (run command or confirm)
</skills>
<acceptance_criteria>
## AC-1: Przelacznik widocznosci custom labels dziala i jest zapamietywany
```gherkin
Given administrator jest na /admin/shop_product/view_list/
When kliknie przycisk "Pokaz etykiety niestandardowe"
Then stan opcji zostanie zapisany w sesji
And po odswiezeniu/listowaniu tabela zachowa ustawiony stan (wlaczony lub wylaczony)
```
## AC-2: Lista produktow pokazuje 5 pol custom_label po wlaczeniu opcji
```gherkin
Given opcja "Pokaz etykiety niestandardowe" jest wlaczona
When lista produktow sie renderuje
Then pod sekcja zdjecie/nazwa/SKU-EAN dla kazdego produktu widoczne sa pola custom_label_0..custom_label_4
And etykiety tych pol sa pobrane dynamicznie z bazy danych (z fallbackiem tylko gdy brak konfiguracji)
```
## AC-3: Zapis i podpowiedzi wartosci dzialaja dla kazdego custom_label
```gherkin
Given administrator wpisuje wartosc w jednym z pol custom_label_0..custom_label_4
When wybierze podpowiedz lub zatwierdzi wpis
Then wartosc zostanie zapisana w pp_shop_products dla danego produktu i pola
And podpowiedzi sa budowane z juz istniejacych wartosci tego samego custom_label w bazie
```
## AC-4: Walidacja i bezpieczenstwo endpointow sa zachowane
```gherkin
Given zapytanie AJAX podaje nieprawidlowy typ labela spoza custom_label_0..4
When backend przetwarza request
Then operacja zostaje odrzucona bez zapisu
And odpowiedz zwraca status bledu bez ingerencji w dane produktu
```
</acceptance_criteria>
<tasks>
<task type="auto">
<name>Task 1: Dodac backend przelacznika sesyjnego i danych dla widoku listy</name>
<files>autoload/admin/Controllers/ShopProductController.php, autoload/Domain/Product/ProductRepository.php</files>
<action>
Rozszerzyc `ShopProductController::view_list()` o flage sesyjna dla widocznosci custom labels
oraz przekazanie do widoku nazw etykiet pobieranych z bazy.
Dodac akcje kontrolera do przelaczania flagi (toggle) i zwracania prostego JSON.
W `ProductRepository` dodac metode pobierajaca nazwy etykiet custom_label_0..4 z bazy
(np. tabela ustawien), z bezpiecznym fallbackiem "Custom label N" gdy wartosc nie istnieje.
Nie stosowac konkatenacji SQL dla danych wejsciowych.
</action>
<verify>Uruchomic testy kontrolera/repo oraz sprawdzic recznie, ze zmiana flagi utrzymuje sie po reloadzie listy</verify>
<done>AC-1 i AC-2 satisfied</done>
</task>
<task type="auto">
<name>Task 2: Dodac UI i logike AJAX dla custom labels na liscie produktow</name>
<files>autoload/admin/Controllers/ShopProductController.php, admin/templates/shop-product/products-list-custom-script.php</files>
<action>
Wygenerowac HTML 5 pol custom_label pod kolumna nazwy produktu tylko gdy flaga sesyjna jest wlaczona.
Uzyc klas zgodnych z istniejacym stylem (`custom-labels`, `custom_label_X_container`, listy sugestii).
Dodac przycisk "Pokaz etykiety niestandardowe" obok "Dodaj produkt" (hook przez custom script listy)
oraz obsluge klikniecia przez AJAX do nowej akcji toggle + odswiezenie aktualnego URL.
Podlaczyc dla kazdego inputa:
- pobieranie sugestii przez `/admin/shop_product/product_custom_label_suggestions/`
- zapis przez `/admin/shop_product/product_custom_label_save/`
z walidacja odpowiedzi i obsluga bledow UI.
</action>
<verify>Manual: wlaczyc opcje, wpisac i zapisac wartosc custom_label, odswiezyc strone, potwierdzic widocznosc i dane</verify>
<done>AC-2 i AC-3 satisfied</done>
</task>
<task type="auto">
<name>Task 3: Dodac testy regresyjne dla nowego zachowania</name>
<files>tests/Unit/admin/Controllers/ShopProductControllerTest.php, tests/Unit/Domain/Product/ProductRepositoryTest.php</files>
<action>
Rozszerzyc testy kontrolera o przypadki:
- toggle flagi sesyjnej
- odrzucenie nieprawidlowych typow labeli
- poprawne przekazanie danych do widoku listy przy wlaczonej opcji.
Rozszerzyc testy repozytorium o:
- pobieranie nazw custom labels z bazy z fallbackiem
- sugestie i zapis tylko dla dozwolonych label_type.
</action>
<verify>./test.ps1 tests/Unit/admin/Controllers/ShopProductControllerTest.php oraz ./test.ps1 tests/Unit/Domain/Product/ProductRepositoryTest.php</verify>
<done>AC-4 covered and AC-1..AC-3 protected by tests</done>
</task>
<task type="checkpoint:human-verify" gate="blocking">
<what-built>Nowy przycisk sesyjny + szybka edycja custom labels 0..4 z podpowiedziami na liscie produktow</what-built>
<how-to-verify>
1. Otworz: /admin/shop_product/view_list/
2. Kliknij: "Pokaz etykiety niestandardowe"
3. Potwierdz: pola custom_label_0..4 pojawiaja sie pod nazwa produktu
4. Wpisz wartosc, wybierz podpowiedz i odswiez strone
5. Potwierdz: wartosc zostala zapisana i toggle pozostaje aktywny
</how-to-verify>
<resume-signal>Type "approved" to continue, or describe issues to fix</resume-signal>
</task>
</tasks>
<boundaries>
## DO NOT CHANGE
- Globalnych komponentow listy niezwiązanych z produktami (`admin/templates/components/table-list.php`) poza minimalnym, koniecznym hookiem
- Endpointow API (`autoload/api/*`)
- Logiki produktow frontendowych (`autoload/front/*`, `templates/shop-product/*`)
## SCOPE LIMITS
- Zakres ograniczony do admin listy produktow i quick-edit custom labels
- Bez migracji DB w tym planie (odczyt nazw z istniejacych danych konfiguracyjnych)
- Bez refaktoru calego modułu integracji Google XML
</boundaries>
<verification>
Before declaring plan complete:
- [ ] ./test.ps1 tests/Unit/admin/Controllers/ShopProductControllerTest.php
- [ ] ./test.ps1 tests/Unit/Domain/Product/ProductRepositoryTest.php
- [ ] Manual check: toggle zapisuje sie w sesji i zachowuje po reloadzie
- [ ] Manual check: podpowiedzi i zapis custom labels dzialaja dla 0..4
- [ ] All acceptance criteria met
</verification>
<success_criteria>
- Przycisk "Pokaz etykiety niestandardowe" dziala i przechowuje stan w sesji
- Lista produktow pokazuje i zapisuje custom_label_0..4 bez wejscia w edycje produktu
- Nazwy etykiet sa pobierane z bazy z fallbackiem
- Testy regresyjne dla backendu i repozytorium przechodza
</success_criteria>
<output>
After completion, create `.paul/phases/16-product-list-custom-labels/16-01-SUMMARY.md`
</output>

View File

@@ -0,0 +1,149 @@
---
phase: 16-product-list-custom-labels
plan: 01
subsystem: admin
tags: [shop-product, custom-label, session-toggle, autocomplete, quick-edit]
requires: []
provides:
- Szybka edycja custom_label_0..4 na liscie produktow
- Przelacznik widocznosci etykiet w sesji admina
- Podpowiedzi istniejacych wartosci + wpisywanie wartosci wlasnej w jednym polu
affects: [shop-product-list, google-xml-label-flow]
tech-stack:
added: []
patterns: [inline quick-edit in table list, datalist autocomplete in single input, settings fallback mapping]
key-files:
created: []
modified:
- autoload/admin/Controllers/ShopProductController.php
- autoload/Domain/Product/ProductRepository.php
- admin/templates/shop-product/products-list.php
- admin/templates/shop-product/products-list-custom-script.php
- tests/Unit/admin/Controllers/ShopProductControllerTest.php
- tests/Unit/Domain/Product/ProductRepositoryTest.php
key-decisions:
- "Przelacznik widocznosci custom labels zapisany w sesji (per admin session)"
- "Nazwy custom labels pobierane z pp_settings z fallbackiem do domyslnych nazw"
- "UX: jedno pole input z autocomplete (datalist), bez osobnego select pod spodem"
patterns-established:
- "Dla list admina: toggle funkcji przez dedykowany endpoint JSON + reload widoku"
- "Quick-edit text fields: walidacja typu po stronie kontrolera przed zapisem/sugestiami"
duration: ~120min
completed: 2026-04-19
---
# Phase 16 Plan 01: Product list custom labels quick edit - Summary
**Wdrozono szybka edycje custom labels na liscie produktow z przelacznikiem sesyjnym i autocomplete w pojedynczym polu.**
## Performance
| Metric | Value |
|--------|-------|
| Duration | ~120min |
| Completed | 2026-04-19 |
| Tasks | 3 completed + 1 checkpoint approved |
| Files modified | 6 |
## Acceptance Criteria Results
| Criterion | Status | Notes |
|-----------|--------|-------|
| AC-1: Przelacznik widocznosci custom labels dziala i jest zapamietywany | Pass | Dodano przycisk toggle + zapis stanu w sesji admina |
| AC-2: Lista pokazuje 5 pol custom_label po wlaczeniu opcji | Pass | Pola custom_label_0..4 renderowane pod nazwa/SKU/EAN tylko przy wlaczonej opcji |
| AC-3: Zapis i podpowiedzi wartosci dzialaja dla custom_label | Pass | Zapis AJAX do bazy + autocomplete istniejacych wartosci i mozliwosc wpisu wlasnego |
| AC-4: Walidacja i bezpieczenstwo endpointow zachowane | Pass | Kontroler odrzuca niedozwolone label_type przed zapisem i pobraniem sugestii |
## Accomplishments
- Dodano nowy toggle "Pokaz/Ukryj etykiety niestandardowe" przy liscie produktow, sterowany sesja.
- Dodano inline quick-edit custom_label_0..4 bez wchodzenia do edycji produktu.
- Podpowiedzi dzialaja jako autocomplete w tym samym input (nie osobny kontrolka pod polem).
- Ujednolicono UX przycisku toggle (kolorystyka, rozmiar, hover, czytelnosc).
- Rozszerzono testy kontrolera i repozytorium o nowe przypadki.
## Files Created/Modified
| File | Change | Purpose |
|------|--------|---------|
| `autoload/admin/Controllers/ShopProductController.php` | Modified | Toggle sesyjny, render custom labels w tabeli, walidacja label_type |
| `autoload/Domain/Product/ProductRepository.php` | Modified | Pobieranie nazw custom_label z ustawien (fallback) |
| `admin/templates/shop-product/products-list.php` | Modified | Przekazanie flagi custom_labels_enabled do skryptu |
| `admin/templates/shop-product/products-list-custom-script.php` | Modified | UI toggle, zapis/sugestie custom label, autocomplete, poprawki wygladu |
| `tests/Unit/admin/Controllers/ShopProductControllerTest.php` | Modified | Testy nowych metod i walidacji kontrolera |
| `tests/Unit/Domain/Product/ProductRepositoryTest.php` | Modified | Testy customLabelNames + walidacji sugestii/zapisu |
## Decisions Made
| Decision | Rationale | Impact |
|----------|-----------|--------|
| Session key dla toggla (`shop_product_show_custom_labels`) | Funkcja ma byc osobnym trybem widoku admina | Stabilny stan po odswiezeniu strony |
| Nazwy etykiet z `pp_settings` + fallback | Wymaganie "nazwy z bazy" i bezpieczne zachowanie gdy brak konfiguracji | Elastyczne nazewnictwo bez hardcodu |
| Autocomplete w jednym polu zamiast input + oddzielny select | UX feedback od usera podczas checkpointu | Czytelniejszy i szybszy flow edycji |
## Deviations from Plan
### Summary
| Type | Count | Impact |
|------|-------|--------|
| Auto-fixed | 1 | Niski, techniczny (BOM w pliku kontrolera) |
| Scope additions | 2 | Niski, UX polish po feedbacku checkpoint |
| Deferred | 0 | Brak |
**Total impact:** Niezbedne poprawki techniczne i UX bez scope creep funkcjonalnego.
### Auto-fixed Issues
**1. Encoding/BOM in controller file**
- **Found during:** Task 1 implementation verification
- **Issue:** Parser PHP zglaszal blad namespace przez BOM na poczatku pliku
- **Fix:** Zapisano plik `ShopProductController.php` jako UTF-8 bez BOM
- **Files:** `autoload/admin/Controllers/ShopProductController.php`
- **Verification:** `php -l autoload/admin/Controllers/ShopProductController.php`
### Deferred Items
None.
## Issues Encountered
| Issue | Resolution |
|-------|------------|
| Drobne regresje UX przycisku toggle | Iteracyjna poprawka stylu i hover po feedbacku usera |
| Forma podpowiedzi (select pod inputem) nieakceptowalna UX | Zmieniono na jedno pole z autocomplete (datalist) |
## Verification Results
- `php -l autoload/admin/Controllers/ShopProductController.php` -> OK
- `php -l autoload/Domain/Product/ProductRepository.php` -> OK
- `php -l admin/templates/shop-product/products-list-custom-script.php` -> OK
- `php phpunit.phar tests/Unit/admin/Controllers/ShopProductControllerTest.php` -> OK (15 tests, 71 assertions)
- `php phpunit.phar tests/Unit/Domain/Product/ProductRepositoryTest.php` -> OK (64 tests, 131 assertions)
- Checkpoint human-verify: approved by user after final UX adjustments
Skill audit:
- `/feature-dev` - not invoked (user-approved override)
- `/koniec-pracy` - acknowledged by user as available for end-of-session flow
## Next Phase Readiness
**Ready:**
- Admin ma szybki i praktyczny workflow uzupelniania custom labels bez przechodzenia do edycji produktu.
- Kod posiada testy regresyjne dla nowej logiki backendowej.
**Concerns:**
- Brak.
**Blockers:**
- None.
---
*Phase: 16-product-list-custom-labels, Plan: 01*
*Completed: 2026-04-19*