---
phase: 10-select2-global-search
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- libraries/adspro-select2-autoinit.js
- templates/site/layout-logged.php
- layout/style.scss
- layout/style.css
- templates/products/main_view.php
- templates/campaign_terms/main_view.php
autonomous: false
delegation: off
---
## Goal
Globalny auto-init Select2 dla wszystkich `
## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md
@.paul/STATE.md
@.paul/codebase/architecture.md
## Source Files
@templates/site/layout-logged.php
@templates/products/main_view.php
@templates/campaign_terms/main_view.php
@layout/style.scss
- **Zakres** — Globalny czy lokalny?
→ Odpowiedź: Globalny auto-init w layout; usunąć dotychczasowe indywidualne inicjalizacje gdzie auto-init je pokryje (zostawiamy specjalne przypadki jak googleCategory z `data` API i własnym placeholderem).
- **Styl/UX** — allowClear i jednolity styl jak na /products?
→ Odpowiedź: Tak — allowClear włączony dla selectów z pustą opcją (value="") oraz styl uogólniony z `.products-page` na cały layout.
- **Dynamika** — sposób obsługi dynamicznie ładowanych opcji?
→ Odpowiedź: Mniej problemów = minimalna zmiana. Auto-init oferuje helper `window.adsproSelect2Init($root)` wywoływany po AJAX-budowanym `
## AC-1: Select "Grupa reklam" na /campaign_terms ma wyszukiwarkę
```gherkin
Given użytkownik jest na /campaign_terms i wybrał klienta + kampanię (załadowane >4 grupy reklam)
When kliknie w select "Grupa reklam"
Then otwiera się dropdown Select2 z polem wyszukiwania
And wpisanie fragmentu nazwy filtruje listę
And wybór grupy działa identycznie jak wcześniej (load_search_terms / load_negative)
```
## AC-2: Globalny auto-init pokrywa wszystkie selecty z >4 opcjami
```gherkin
Given dowolna podstrona w layout-logged ma `Task 1: Utworzyć moduł auto-init Select2libraries/adspro-select2-autoinit.js
Utworzyć nowy plik z modułem auto-init. Wymagania:
1. Sprawdza `typeof $.fn.select2 !== 'undefined'` przed działaniem.
2. Eksportuje `window.adsproSelect2Init($root)`:
- `$root` opcjonalny (domyślnie `$(document.body)`)
- Wyszukuje `select` w `$root` filtrując:
* pomija `select[multiple]` z natywną logiką jeśli ma `data-adspro-select2="false"` (multiple jest OK domyślnie)
* pomija `.no-select2` lub `[data-adspro-select2="false"]`
* pomija jeśli `$el.data('select2')` już istnieje (już zainicjalizowane)
* pomija jeśli select jest w `.select2-container` (wewnątrz Select2 wyświetlacza)
* pomija jeśli rodzic ma klasę `.dataTables_length` (długość strony DataTables — krótka lista)
* Inicjalizuje gdy: `select.options.length > 4` LUB ma atrybut `data-adspro-select2="true"`
- Dla każdego pasującego selecta:
* options.width = '100%'
* options.allowClear = true jeśli pierwsza `Plik istnieje, `node -c` lub `php -r "echo file_exists('libraries/adspro-select2-autoinit.js') ? 'OK' : 'FAIL';"` zwraca OK; w przeglądarce DevTools → `typeof window.adsproSelect2Init === 'function'`.AC-2, AC-3 częściowo (silnik gotowy)Task 2: Załadować auto-init w layout i uogólnić CSS Select2templates/site/layout-logged.php, layout/style.scss, layout/style.css
1. W `templates/site/layout-logged.php` po linii `` (linia ~35) dodać:
```html
```
(Uwaga: w pliku są dwa źródła select2 — local i CDN. Auto-init dorzucamy raz, po obu.)
2. W `layout/style.scss` dodać nową sekcję `// === Select2 global overrides ===` z regułami zaadaptowanymi z `templates/products/main_view.php` linie 136-189. Selektory globalne (BEZ prefiksu `.products-page`):
- `.select2-container` width 100%
- `.select2-container--default .select2-selection--single` (height 38, border #e2e8f0, radius 6, bg #fff)
- `.select2-selection__rendered` (line-height 36, padding 12/36, color #2d3748)
- `.select2-selection__placeholder` (#6c757d)
- `.select2-selection__arrow` (height 36, right 8)
- `.select2-container--focus .select2-selection--single` (border #6690f4, shadow rgba(102,144,244,.1))
- `.select2-dropdown` (border #e2e8f0, radius 6)
- `.select2-search--dropdown .select2-search__field` (border, radius, height 34, font 14)
- `.select2-results__option` (font 14)
- `.select2-container--default .select2-results__option--highlighted[aria-selected]` (bg #6690f4, color #fff)
3. Skompilować SCSS do `layout/style.css` (lub dopisać te same reguły bezpośrednio do `layout/style.css` jeśli SCSS nie jest auto-budowane w projekcie — sprawdzić nagłówek pliku style.css czy ma marker auto-generated). Jeżeli style.css jest commitowane ręcznie, dopisać identyczny blok CSS na końcu pliku style.css.
Avoid:
- Nie usuwać żadnych innych istniejących reguł z style.scss/style.css.
- Nie zmieniać kolejności ładowania Select2 CSS (local + CDN — obecny stan zachować).
Po odświeżeniu dowolnej strony layout-logged: w DevTools `$('.select2-container').length > 0` na stronach z natywnymi selectami z >4 opcjami; computed style selecta = height 38px.AC-2, AC-4Task 3: Usunąć redundantne Select2 w products i podłączyć helper w campaign_termstemplates/products/main_view.php, templates/campaign_terms/main_view.php
**W `templates/products/main_view.php`:**
1. Usunąć blok CSS `.products-page .select2-*` (linie ~136-189) — zastąpiony przez globalne reguły z Task 2.
2. Usunąć funkcję `init_products_scope_select_search()` (linie ~610-631) ORAZ jej wywołanie w linii ~723.
- Jeśli wywołanie jest częścią innego bloku, zostawić sąsiednie linie nietknięte; tylko skreślić wywołanie funkcji.
3. NIE ruszać `$googleCategory.select2({...})` w linii ~2414 (ma własny `data:`, `placeholder`, `allowClear` — auto-init go pominie bo będzie już zainicjalizowany przed/po; dodać przed tym wywołaniem klasę `no-select2` na `$googleCategory` LUB zostawić — auto-init nie nadpisuje istniejących instancji, więc bezpiecznie).
4. Zachować wszystkie `$x.trigger('change.select2')` (linie ~1112, 1133, 1159, 1178) — nadal aktualne.
**W `templates/campaign_terms/main_view.php`:**
1. W funkcji `load_campaigns()` po linii `$campaign_select.val( restore_campaign_id );` (~1791) i ogólnie po wszystkich append() w success: dodać:
```js
if ( typeof window.adsproSelect2Init === 'function' ) window.adsproSelect2Init( $campaign_select.parent() );
$campaign_select.trigger( 'change.select2' );
```
2. W funkcji `load_ad_groups()` po pętli `ad_groups.forEach` (po ~1738): analogicznie dla `$ad_group_select`.
3. Dla `#terms_client_id` (jeśli ma >4 opcji od razu po PHP render) auto-init z `$(document).ready` go pokryje — nie trzeba zmian; ale dla pewności dodać atrybut `data-adspro-select2="true"` w `
1. Strona `/products` — wybór kampanii i grupy reklam działa, wyszukiwarka obecna, wygląd niezmieniony.
2. Strona `/campaign_terms` — po wyborze klienta + kampanii select "Grupa reklam" otwiera dropdown z wyszukiwarką; filtrowanie po wpisaniu fragmentu działa; wybór wczytuje termy.
3. `git diff templates/products/main_view.php` pokazuje usunięcie bloków CSS i funkcji init.
AC-1, AC-5
Globalny auto-init Select2 + jednolity styl + wyszukiwarka w "Grupa reklam" na /campaign_terms.
1. Otwórz `https://adspro.projectpro.pl/campaign_terms`.
2. Wybierz klienta, potem kampanię — poczekaj na załadowanie grup reklam.
3. Kliknij select "Grupa reklam" → powinien pokazać się dropdown Select2 z polem wyszukiwania na górze.
4. Wpisz fragment nazwy grupy — lista filtruje się na żywo.
5. Wybierz grupę → tabela "Search terms" / "Negative" przeładowuje się jak wcześniej.
6. Kliknij X (jeśli pierwsza opcja "- wszystkie grupy -") → wraca do "- wszystkie grupy -".
7. Przejdź na `/products` — sprawdź że wybór kampanii i grupy reklam nadal działa (regresja).
8. Przejdź na kilka innych podstron (/campaigns, /clients, /feeds) — sprawdź czy żaden select nie wygląda zepsuto.
9. Sprawdź w DevTools console: brak błędów JS po załadowaniu strony i po zmianach w selectach.
Wpisz "approved" aby kontynuować lub opisz problemy do naprawy
## DO NOT CHANGE
- `libraries/select2/**` — biblioteka Select2 (nie modyfikujemy źródeł).
- Logika AJAX endpointów `/campaign_terms/*` i `/products/*` (tylko frontend).
- `$googleCategory.select2(...)` w `products/main_view.php` (~2414) — działa z własną konfiguracją.
- Inne miejsca używające `.trigger('change.select2')` — zachować.
- Backend (controls/factory/services) — bez zmian.
## SCOPE LIMITS
- Tylko layout-logged (panel zalogowanego użytkownika). Nie ruszamy layout-unlogged (`/login` itp.).
- Nie wprowadzamy nowych bibliotek ani nie aktualizujemy wersji Select2.
- Nie zmieniamy multi-select (`
Before declaring plan complete:
- [ ] Plik `libraries/adspro-select2-autoinit.js` istnieje i jest podłączony w layout-logged.php
- [ ] Globalne style Select2 w `layout/style.css`
- [ ] Blok `.products-page .select2-*` usunięty z `templates/products/main_view.php`
- [ ] Funkcja `init_products_scope_select_search()` i jej wywołanie usunięte
- [ ] `data-adspro-select2="true"` na 3 selectach w `templates/campaign_terms/main_view.php`
- [ ] `window.adsproSelect2Init(...)` wywoływane po load_campaigns/load_ad_groups w campaign_terms
- [ ] Brak błędów JS w konsoli na /campaign_terms i /products
- [ ] Checkpoint human-verify zaakceptowany
- Wszystkie zadania ukończone
- Wszystkie kryteria akceptacji spełnione
- Brak regresji wizualnej/funkcjonalnej na /products
- Wyszukiwarka działa na /campaign_terms → Grupa reklam (i na każdym innym selecie z >4 opcjami w layout-logged)