UI: globalny auto-init Select2 z wyszukiwarka dla selectow >4 opcji
- Nowy libraries/adspro-select2-autoinit.js (auto-init na document.ready + ajaxComplete debounce 150ms) - Wyszukiwarka odblokowana dla "Grupa reklam", "Kampania", "Klient" na /campaign_terms (data-adspro-select2="true") - Globalne style Select2 w layout/style.scss i style.css (uogolnione z .products-page) - Usuniety duplikat: blok CSS .products-page .select2-* i funkcja init_products_scope_select_search() w products PAUL: phase 10-select2-global-search complete (plan 10-01) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
## Current Position
|
## Current Position
|
||||||
|
|
||||||
Phase: 09-unit-pricing - Complete
|
Phase: 10-select2-global-search - Complete
|
||||||
Plan: 09-01 complete
|
Plan: 10-01 complete
|
||||||
Status: UNIFY complete. Loop closed - ready for next PLAN.
|
Status: UNIFY complete. Loop closed - ready for next PLAN.
|
||||||
Last activity: 2026-05-05T00:00:00Z - Unified .paul/phases/09-unit-pricing/09-01-SUMMARY.md
|
Last activity: 2026-05-16T13:40:00Z - Unified .paul/phases/10-select2-global-search/10-01-SUMMARY.md
|
||||||
|
|
||||||
## Loop Position
|
## Loop Position
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ PLAN --> APPLY --> UNIFY
|
|||||||
|
|
||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
Last session: 2026-05-05
|
Last session: 2026-05-16
|
||||||
Stopped at: Phase 09 complete
|
Stopped at: Phase 10 complete
|
||||||
Next action: Prepare next phase with $paul-plan (po uzupelnieniu PROJECT.md/ROADMAP.md lub wskazaniu kolejnego celu)
|
Next action: Prepare next phase with /paul:plan (po uzupelnieniu PROJECT.md/ROADMAP.md lub wskazaniu kolejnego celu)
|
||||||
Resume file: .paul/phases/09-unit-pricing/09-01-SUMMARY.md
|
Resume file: .paul/phases/10-select2-global-search/10-01-SUMMARY.md
|
||||||
|
|||||||
18
.paul/changelog/2026-05-16.md
Normal file
18
.paul/changelog/2026-05-16.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# 2026-05-16
|
||||||
|
|
||||||
|
## Co zrobiono
|
||||||
|
|
||||||
|
- [Phase 10, Plan 01] Globalny auto-init Select2 z polem wyszukiwania dla selectow >4 opcji
|
||||||
|
- Nowy modul `libraries/adspro-select2-autoinit.js` (auto-init na document.ready + ajaxComplete debounce 150ms)
|
||||||
|
- Wyszukiwarka odblokowana dla "Grupa reklam", "Kampania", "Klient" na /campaign_terms (opt-in `data-adspro-select2="true"`)
|
||||||
|
- Ujednolicony styl Select2 — globalne reguly w `layout/style.scss` i `layout/style.css`
|
||||||
|
- Usuniety duplikowany blok CSS .products-page .select2-* i funkcja init_products_scope_select_search() (~80 linii)
|
||||||
|
|
||||||
|
## Zmienione pliki
|
||||||
|
|
||||||
|
- `libraries/adspro-select2-autoinit.js` (nowy)
|
||||||
|
- `templates/site/layout-logged.php`
|
||||||
|
- `layout/style.scss`
|
||||||
|
- `layout/style.css`
|
||||||
|
- `templates/products/main_view.php`
|
||||||
|
- `templates/campaign_terms/main_view.php`
|
||||||
21
.paul/governance/governance_2026-05-16.jsonl
Normal file
21
.paul/governance/governance_2026-05-16.jsonl
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{"ts":"2026-05-16T13:32:28Z","tool":"Bash","cmd":"mkdir -p .paul/phases/10-select2-global-search\",\"description\":\"Create phase 10 directory\"},\"tool_response\":{\"stdout\":\"\",\"stderr\":\"\",\"interrupted\":false,\"isImage\":false,\"noOutputExp","cwd":"/c/visual studio code/projekty/adsPRO"}
|
||||||
|
{"ts":"2026-05-16T13:33:32Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\.paul\\\\phases\\\\10-select2-global-search\\\\10-01-PLAN.md","cwd":"/c/visual studio code/projekty/adsPRO"}
|
||||||
|
{"ts":"2026-05-16T13:33:38Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\.paul\\\\STATE.md","cwd":"/c/visual studio code/projekty/adsPRO"}
|
||||||
|
{"ts":"2026-05-16T13:35:05Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\libraries\\\\adspro-select2-autoinit.js","cwd":"/c/visual studio code/projekty/adsPRO"}
|
||||||
|
{"ts":"2026-05-16T13:35:13Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\templates\\\\site\\\\layout-logged.php","cwd":"/c/visual studio code/projekty/adsPRO"}
|
||||||
|
{"ts":"2026-05-16T13:35:25Z","tool":"Bash","cmd":"wc -l layout/style.scss; tail -3 layout/style.scss\",\"description\":\"Get scss end\"},\"tool_response\":{\"stdout\":\"3760 layout/style.scss\\n color: #000;\\r\\n justify-content: flex-start;\\r\\n","cwd":"/c/visual studio code/projekty/adsPRO"}
|
||||||
|
{"ts":"2026-05-16T13:36:00Z","tool":"Bash","cmd":"printf '%s' '.select2-container{width:100% !important}.select2-container--default .select2-selection--single{height:38px;border:1px solid #e2e8f0;border-radius:6px;background:#fff}.select2-container--","cwd":"/c/visual studio code/projekty/adsPRO"}
|
||||||
|
{"ts":"2026-05-16T13:36:14Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\templates\\\\products\\\\main_view.php","cwd":"/c/visual studio code/projekty/adsPRO"}
|
||||||
|
{"ts":"2026-05-16T13:36:20Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\templates\\\\products\\\\main_view.php","cwd":"/c/visual studio code/projekty/adsPRO"}
|
||||||
|
{"ts":"2026-05-16T13:36:25Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\templates\\\\products\\\\main_view.php","cwd":"/c/visual studio code/projekty/adsPRO"}
|
||||||
|
{"ts":"2026-05-16T13:36:32Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\templates\\\\campaign_terms\\\\main_view.php","cwd":"/c/visual studio code/projekty/adsPRO"}
|
||||||
|
{"ts":"2026-05-16T13:36:35Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\templates\\\\campaign_terms\\\\main_view.php","cwd":"/c/visual studio code/projekty/adsPRO"}
|
||||||
|
{"ts":"2026-05-16T13:36:38Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\templates\\\\campaign_terms\\\\main_view.php","cwd":"/c/visual studio code/projekty/adsPRO"}
|
||||||
|
{"ts":"2026-05-16T13:36:49Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\templates\\\\campaign_terms\\\\main_view.php","cwd":"/c/visual studio code/projekty/adsPRO"}
|
||||||
|
{"ts":"2026-05-16T13:36:53Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\templates\\\\campaign_terms\\\\main_view.php","cwd":"/c/visual studio code/projekty/adsPRO"}
|
||||||
|
{"ts":"2026-05-16T13:36:59Z","tool":"Bash","cmd":"php -l libraries/adspro-select2-autoinit.js 2>&1 | head -3; node --check libraries/adspro-select2-autoinit.js && echo \"JS OK\"\\nphp -l templates/products/main_view.php 2>&1 | tail -2\\nphp -l templa","cwd":"/c/visual studio code/projekty/adsPRO"}
|
||||||
|
{"ts":"2026-05-16T13:38:25Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\.paul\\\\STATE.md","cwd":"/c/visual studio code/projekty/adsPRO"}
|
||||||
|
{"ts":"2026-05-16T13:40:23Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\.paul\\\\phases\\\\10-select2-global-search\\\\10-01-SUMMARY.md","cwd":"/c/visual studio code/projekty/adsPRO"}
|
||||||
|
{"ts":"2026-05-16T13:40:35Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\.paul\\\\changelog\\\\2026-05-16.md","cwd":"/c/visual studio code/projekty/adsPRO"}
|
||||||
|
{"ts":"2026-05-16T13:40:41Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\adsPRO\\\\.paul\\\\STATE.md","cwd":"/c/visual studio code/projekty/adsPRO"}
|
||||||
|
{"ts":"2026-05-16T14:12:58Z","tool":"Bash","cmd":"git status; echo \"---\"; git log --oneline -5\",\"description\":\"Check status and recent commits\"},\"tool_response\":{\"stdout\":\"On branch main\\nYour branch is up to date with 'origin/main'.\\n\","cwd":"/c/visual studio code/projekty/adsPRO"}
|
||||||
264
.paul/phases/10-select2-global-search/10-01-PLAN.md
Normal file
264
.paul/phases/10-select2-global-search/10-01-PLAN.md
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
---
|
||||||
|
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
|
||||||
|
---
|
||||||
|
|
||||||
|
<objective>
|
||||||
|
## Goal
|
||||||
|
Globalny auto-init Select2 dla wszystkich `<select>` z >4 opcjami w aplikacji, ze spójnym stylem (jak na `/products`) i obsługą `allowClear` dla selectów z pustą opcją "- wszystkie / wybierz -". Usunięcie indywidualnych inicjalizacji Select2 tam, gdzie auto-init je zastąpi. Konkretny wyzwalacz: select "Grupa reklam" na `/campaign_terms`.
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
Spójny UX wyszukiwania w długich listach (kampanie, grupy reklam, klienci) bez konieczności pamiętania o ręcznym `$.fn.select2()` w każdym module. Eliminuje duplikację CSS i kodu init w poszczególnych szablonach.
|
||||||
|
|
||||||
|
## Output
|
||||||
|
- Nowy plik `libraries/adspro-select2-autoinit.js` (auto-init + helper window.adsproSelect2Init)
|
||||||
|
- Załączenie go w `templates/site/layout-logged.php` po `select2.full.min.js`
|
||||||
|
- Globalne style Select2 w `layout/style.scss` (uogólnione z `.products-page`)
|
||||||
|
- Usunięcie redundantnego init i CSS z `templates/products/main_view.php`
|
||||||
|
- Wywołanie helpera po AJAX w `templates/campaign_terms/main_view.php` (jako fallback dla dynamicznie ładowanych opcji)
|
||||||
|
</objective>
|
||||||
|
|
||||||
|
<context>
|
||||||
|
## 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
|
||||||
|
|
||||||
|
<clarifications>
|
||||||
|
- **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 `<select>` (campaign_terms). Dla statycznych selectów wystarcza `$(document).ready`.
|
||||||
|
</clarifications>
|
||||||
|
</context>
|
||||||
|
|
||||||
|
<acceptance_criteria>
|
||||||
|
|
||||||
|
## 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 `<select>` z więcej niż 4 opcjami w `<option>`
|
||||||
|
When DOM jest gotowy (lub po AJAX dla dynamicznych)
|
||||||
|
Then ten select jest zainicjalizowany jako Select2 z polem wyszukiwania
|
||||||
|
And selecty z `≤ 4` opcjami pozostają natywne (chyba że mają atrybut `data-adspro-select2="true"`)
|
||||||
|
And selecty z klasą `no-select2` lub atrybutem `data-adspro-select2="false"` są pomijane
|
||||||
|
```
|
||||||
|
|
||||||
|
## AC-3: AllowClear działa dla selectów z pustą opcją
|
||||||
|
```gherkin
|
||||||
|
Given Select2 jest zainicjalizowany na `<select>` którego pierwsza opcja ma value=""
|
||||||
|
When użytkownik wybrał wartość niepustą
|
||||||
|
Then widoczny jest przycisk X (clear)
|
||||||
|
When użytkownik kliknie X
|
||||||
|
Then wartość selecta wraca do "" i wyzwalany jest `change`
|
||||||
|
```
|
||||||
|
|
||||||
|
## AC-4: Styl spójny z dotychczasowym wyglądem /products
|
||||||
|
```gherkin
|
||||||
|
Given Select2 jest aktywny na dowolnej stronie layout-logged
|
||||||
|
Then wysokość selecta = 38px, border-radius 6px, kolor focusa #6690f4
|
||||||
|
And styl dropdown, search input, highlighted option = jak obecnie na /products
|
||||||
|
And nie ma duplikacji CSS w `templates/products/main_view.php` (block `.products-page .select2-*` usunięty)
|
||||||
|
```
|
||||||
|
|
||||||
|
## AC-5: Brak regresji indywidualnych Select2
|
||||||
|
```gherkin
|
||||||
|
Given dotychczasowe miejsca z ręcznym `$el.select2(...)` z własną konfiguracją (np. googleCategory z `data: cats`, placeholder, allowClear)
|
||||||
|
When strona się ładuje
|
||||||
|
Then nadal działają poprawnie (auto-init pomija już zainicjalizowane instancje przez sprawdzenie `$el.data('select2')`)
|
||||||
|
And `init_products_scope_select_search()` jest usunięte (zastąpione auto-initem), `update_delete_ad_group_button_state()` oraz `.trigger('change.select2')` nadal działają
|
||||||
|
```
|
||||||
|
|
||||||
|
</acceptance_criteria>
|
||||||
|
|
||||||
|
<tasks>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 1: Utworzyć moduł auto-init Select2</name>
|
||||||
|
<files>libraries/adspro-select2-autoinit.js</files>
|
||||||
|
<action>
|
||||||
|
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 `<option>` ma value === ""
|
||||||
|
* options.placeholder = tekst pierwszej pustej opcji (jeśli istnieje) lub atrybut `placeholder`
|
||||||
|
* options.language = 'pl' jeśli dostępne
|
||||||
|
* Wywołuje `$el.select2(options)`
|
||||||
|
* Ustawia `$el.data('adspro-select2-ready', true)`
|
||||||
|
3. Na `$(document).ready` wywołuje `window.adsproSelect2Init()`.
|
||||||
|
4. Podłącza globalny `$(document).ajaxComplete` z debounce ~150ms wywołującym `window.adsproSelect2Init()` (żeby pokryć selecty budowane po AJAX, np. terms_ad_group_id, products_campaign_id).
|
||||||
|
|
||||||
|
Avoid:
|
||||||
|
- Nie inicjalizować na DataTables length-select (`.dataTables_length select`).
|
||||||
|
- Nie nadpisywać istniejących instancji Select2.
|
||||||
|
- Nie używać MutationObserver (overkill — `ajaxComplete` wystarczy w tej aplikacji).
|
||||||
|
</action>
|
||||||
|
<verify>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'`.</verify>
|
||||||
|
<done>AC-2, AC-3 częściowo (silnik gotowy)</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 2: Załadować auto-init w layout i uogólnić CSS Select2</name>
|
||||||
|
<files>templates/site/layout-logged.php, layout/style.scss, layout/style.css</files>
|
||||||
|
<action>
|
||||||
|
1. W `templates/site/layout-logged.php` po linii `<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>` (linia ~35) dodać:
|
||||||
|
```html
|
||||||
|
<script src="/libraries/adspro-select2-autoinit.js"></script>
|
||||||
|
```
|
||||||
|
(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ć).
|
||||||
|
</action>
|
||||||
|
<verify>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.</verify>
|
||||||
|
<done>AC-2, AC-4</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 3: Usunąć redundantne Select2 w products i podłączyć helper w campaign_terms</name>
|
||||||
|
<files>templates/products/main_view.php, templates/campaign_terms/main_view.php</files>
|
||||||
|
<action>
|
||||||
|
**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 `<select id="terms_client_id" ...>` (~linia 9) żeby gwarantować init niezależnie od liczby opcji.
|
||||||
|
4. Dla `#terms_campaign_id` i `#terms_ad_group_id` w HTML (~linie 18, 24) dodać `data-adspro-select2="true"` — jawnie wymuszają Select2 nawet gdy chwilowo mają tylko placeholder.
|
||||||
|
|
||||||
|
Avoid:
|
||||||
|
- Nie zmieniać logiki `terms_storage_set/get`.
|
||||||
|
- Nie zmieniać struktury DataTables ani handlerów `change` na selectach.
|
||||||
|
- Nie usuwać innych stylów `.products-page *` poza blokiem Select2.
|
||||||
|
</action>
|
||||||
|
<verify>
|
||||||
|
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.
|
||||||
|
</verify>
|
||||||
|
<done>AC-1, AC-5</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
<task type="checkpoint:human-verify" gate="blocking">
|
||||||
|
<what-built>
|
||||||
|
Globalny auto-init Select2 + jednolity styl + wyszukiwarka w "Grupa reklam" na /campaign_terms.
|
||||||
|
</what-built>
|
||||||
|
<how-to-verify>
|
||||||
|
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.
|
||||||
|
</how-to-verify>
|
||||||
|
<resume-signal>Wpisz "approved" aby kontynuować lub opisz problemy do naprawy</resume-signal>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
</tasks>
|
||||||
|
|
||||||
|
<boundaries>
|
||||||
|
|
||||||
|
## 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 (`<select multiple>`) — auto-init obsługuje je tak samo (Select2 ma natywne wsparcie), ale nie dodajemy zaawansowanych opcji typu tagi.
|
||||||
|
- Brak nowych migracji DB, brak zmian w PHP poza ewentualnymi atrybutami HTML w templatach.
|
||||||
|
|
||||||
|
</boundaries>
|
||||||
|
|
||||||
|
<verification>
|
||||||
|
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
|
||||||
|
</verification>
|
||||||
|
|
||||||
|
<success_criteria>
|
||||||
|
- 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)
|
||||||
|
</success_criteria>
|
||||||
|
|
||||||
|
<output>
|
||||||
|
After completion, create `.paul/phases/10-select2-global-search/10-01-SUMMARY.md`
|
||||||
|
</output>
|
||||||
133
.paul/phases/10-select2-global-search/10-01-SUMMARY.md
Normal file
133
.paul/phases/10-select2-global-search/10-01-SUMMARY.md
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
---
|
||||||
|
phase: 10-select2-global-search
|
||||||
|
plan: 01
|
||||||
|
subsystem: ui
|
||||||
|
tags: [select2, jquery, ui, frontend, autoinit]
|
||||||
|
|
||||||
|
requires:
|
||||||
|
- phase: existing layout
|
||||||
|
provides: Select2 library already loaded via layout-logged.php
|
||||||
|
provides:
|
||||||
|
- Globalny auto-init Select2 dla wszystkich <select> >4 opcji w layout-logged
|
||||||
|
- Wyszukiwarka w selectach na /campaign_terms (klient, kampania, grupa reklam)
|
||||||
|
- Ujednolicony styl Select2 (poprzednio tylko .products-page)
|
||||||
|
affects: [wszystkie przyszle moduly UI uzywajace <select>]
|
||||||
|
|
||||||
|
tech-stack:
|
||||||
|
added: []
|
||||||
|
patterns:
|
||||||
|
- "Opt-in/opt-out atrybuty: data-adspro-select2=\"true|false\", klasa .no-select2"
|
||||||
|
- "Globalny ajaxComplete debounce do re-initu po dynamicznych zmianach DOM"
|
||||||
|
|
||||||
|
key-files:
|
||||||
|
created:
|
||||||
|
- libraries/adspro-select2-autoinit.js
|
||||||
|
modified:
|
||||||
|
- templates/site/layout-logged.php
|
||||||
|
- layout/style.scss
|
||||||
|
- layout/style.css
|
||||||
|
- templates/products/main_view.php
|
||||||
|
- templates/campaign_terms/main_view.php
|
||||||
|
|
||||||
|
key-decisions:
|
||||||
|
- "Globalny auto-init zamiast lokalnych init() w kazdym module"
|
||||||
|
- "Prog >4 opcji jako domyslny + opt-in atrybutem dla dynamicznych selectow"
|
||||||
|
- "AllowClear automatyczny gdy pierwsza option ma value=\"\""
|
||||||
|
|
||||||
|
patterns-established:
|
||||||
|
- "data-adspro-select2 attribute jako opt-in dla selectow ladowanych AJAX-em"
|
||||||
|
- "Globalne style Select2 w layout/style.scss (bez prefiksu .products-page)"
|
||||||
|
|
||||||
|
duration: ~20min
|
||||||
|
started: 2026-05-16T13:20:00Z
|
||||||
|
completed: 2026-05-16T13:40:00Z
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 10 Plan 01: Select2 global search Summary
|
||||||
|
|
||||||
|
**Globalny auto-init Select2 z polem wyszukiwania dla kazdego <select> z >4 opcjami; konkretnie odblokowane wyszukiwanie w "Grupa reklam" na /campaign_terms.**
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
| Metric | Value |
|
||||||
|
|--------|-------|
|
||||||
|
| Duration | ~20 min |
|
||||||
|
| Started | 2026-05-16T13:20:00Z |
|
||||||
|
| Completed | 2026-05-16T13:40:00Z |
|
||||||
|
| Tasks | 4 (3 auto + 1 checkpoint approved) |
|
||||||
|
| Files modified | 5 + 1 created |
|
||||||
|
|
||||||
|
## Acceptance Criteria Results
|
||||||
|
|
||||||
|
| Criterion | Status | Notes |
|
||||||
|
|-----------|--------|-------|
|
||||||
|
| AC-1: Select "Grupa reklam" ma wyszukiwarke | Pass | Potwierdzone przez user "approved" |
|
||||||
|
| AC-2: Auto-init dla selectow >4 opcji | Pass | Implementacja w libraries/adspro-select2-autoinit.js |
|
||||||
|
| AC-3: AllowClear dla selectow z pusta opcja | Pass | Wykrywane przez first_value === "" |
|
||||||
|
| AC-4: Styl spojny z dotychczasowym /products | Pass | Block .products-page .select2-* usuniety, style przeniesione do globalnego scope |
|
||||||
|
| AC-5: Brak regresji indywidualnych Select2 | Pass | $googleCategory.select2(...) zachowany; auto-init sprawdza $.data('select2') |
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
|
||||||
|
- Globalny moduł `adspro-select2-autoinit.js` z `window.adsproSelect2Init()` + auto-trigger na `document.ready` i `ajaxComplete` (debounce 150ms)
|
||||||
|
- Wyszukiwarka dla 3 selectów na `/campaign_terms` (klient, kampania, grupa reklam) — odblokowane przez `data-adspro-select2="true"`
|
||||||
|
- Eliminacja duplikacji: ~80 linii (CSS + funkcja init) usunięte z `templates/products/main_view.php`
|
||||||
|
- Globalne style Select2 (height 38, radius 6, focus #6690f4) w `layout/style.scss` i `layout/style.css`
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
|
||||||
|
| File | Change | Purpose |
|
||||||
|
|------|--------|---------|
|
||||||
|
| `libraries/adspro-select2-autoinit.js` | Created | Modul auto-init Select2 + helper window.adsproSelect2Init |
|
||||||
|
| `templates/site/layout-logged.php` | Modified | Podpiecie skryptu auto-init po Select2 |
|
||||||
|
| `layout/style.scss` | Modified | Globalne reguly Select2 (źródło) |
|
||||||
|
| `layout/style.css` | Modified | Globalne reguly Select2 (build) wstrzykniete przed sourceMappingURL |
|
||||||
|
| `templates/products/main_view.php` | Modified | Usuniety blok CSS .products-page .select2-* i funkcja init_products_scope_select_search() |
|
||||||
|
| `templates/campaign_terms/main_view.php` | Modified | data-adspro-select2="true" na 3 selectach + wywolania window.adsproSelect2Init() po AJAX |
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
| Decision | Rationale | Impact |
|
||||||
|
|----------|-----------|--------|
|
||||||
|
| Threshold >4 opcji | Krotsze listy nie potrzebuja wyszukiwarki | Selecty 2-4 opcji pozostaja natywne |
|
||||||
|
| Opt-in `data-adspro-select2="true"` dla AJAX | Dynamiczne selecty zaczynaja z 0-1 opcji | Wymusza init niezaleznie od chwilowej liczby opcji |
|
||||||
|
| Debounce 150ms na ajaxComplete | Multi-AJAX flow (load_campaigns -> load_ad_groups) | Jeden batch init zamiast wielu kolejnych |
|
||||||
|
| Zachowac `$googleCategory.select2(...)` w products | Wlasny placeholder, data: cats, allowClear | Auto-init pomija dzieki $.data('select2') check |
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
### Summary
|
||||||
|
|
||||||
|
| Type | Count | Impact |
|
||||||
|
|------|-------|--------|
|
||||||
|
| Auto-fixed | 0 | - |
|
||||||
|
| Scope additions | 0 | - |
|
||||||
|
| Deferred | 0 | - |
|
||||||
|
|
||||||
|
**Total impact:** Plan executed exactly as written.
|
||||||
|
|
||||||
|
### Deferred Items
|
||||||
|
|
||||||
|
None — plan executed exactly as written.
|
||||||
|
|
||||||
|
## Issues Encountered
|
||||||
|
|
||||||
|
| Issue | Resolution |
|
||||||
|
|-------|------------|
|
||||||
|
| `layout/style.css` jest minified single-line z sourceMappingURL na koncu | Wstrzykniecie nowych regul przed komentarzem sourceMappingURL via Python helper (zachowano BOM i mape) |
|
||||||
|
|
||||||
|
## Next Phase Readiness
|
||||||
|
|
||||||
|
**Ready:**
|
||||||
|
- Auto-init dziala na calym layout-logged — przyszle moduly z `<select>` >4 opcji dostana wyszukiwarke za darmo
|
||||||
|
- Wzorzec `data-adspro-select2="true"` dostepny dla dynamicznie ladowanych selectow
|
||||||
|
|
||||||
|
**Concerns:**
|
||||||
|
- Style globalne moga konfliktowac z innymi miejscami uzywajacymi Select2 (np. jconfirm-box, adspro-dialog-box maja juz swoje overrides — sprawdzic ewentualne kolizje w czasie rzeczywistego uzytkowania)
|
||||||
|
- Jezeli `layout/style.scss` zostanie przebudowane przez sass, blok `// === Select2 global overrides ===` zostanie zachowany w scss, ale .css wygenerowany ponownie zastapi wstrzykniety blok — przy nastepnym budowaniu trzeba zbudowac z scss
|
||||||
|
|
||||||
|
**Blockers:** None
|
||||||
|
|
||||||
|
---
|
||||||
|
*Phase: 10-select2-global-search, Plan: 01*
|
||||||
|
*Completed: 2026-05-16*
|
||||||
File diff suppressed because one or more lines are too long
@@ -3758,3 +3758,49 @@ table#products {
|
|||||||
color: #000;
|
color: #000;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// === Select2 global overrides (auto-init via libraries/adspro-select2-autoinit.js) ===
|
||||||
|
.select2-container {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
.select2-container--default .select2-selection--single {
|
||||||
|
height: 38px;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
.select2-container--default .select2-selection--single .select2-selection__rendered {
|
||||||
|
line-height: 36px;
|
||||||
|
padding-left: 12px;
|
||||||
|
padding-right: 36px;
|
||||||
|
color: #2d3748;
|
||||||
|
}
|
||||||
|
.select2-container--default .select2-selection--single .select2-selection__placeholder {
|
||||||
|
color: #6c757d;
|
||||||
|
}
|
||||||
|
.select2-container--default .select2-selection--single .select2-selection__arrow {
|
||||||
|
height: 36px;
|
||||||
|
right: 8px;
|
||||||
|
}
|
||||||
|
.select2-container--default.select2-container--focus .select2-selection--single {
|
||||||
|
border-color: #6690f4;
|
||||||
|
box-shadow: 0 0 0 3px rgba(102, 144, 244, 0.1);
|
||||||
|
}
|
||||||
|
.select2-dropdown {
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
.select2-search--dropdown .select2-search__field {
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
border-radius: 6px;
|
||||||
|
height: 34px;
|
||||||
|
padding: 0 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.select2-results__option {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.select2-container--default .select2-results__option--highlighted[aria-selected] {
|
||||||
|
background-color: #6690f4;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|||||||
153
libraries/adspro-select2-autoinit.js
Normal file
153
libraries/adspro-select2-autoinit.js
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
/**
|
||||||
|
* adsPRO — globalny auto-init Select2.
|
||||||
|
*
|
||||||
|
* Inicjalizuje Select2 na kazdym <select> z >4 opcjami (oraz na select z
|
||||||
|
* atrybutem data-adspro-select2="true"). Pomija .no-select2 i juz zainicjalizowane.
|
||||||
|
* Wlacza allowClear gdy pierwsza opcja ma value="".
|
||||||
|
*
|
||||||
|
* Helper: window.adsproSelect2Init($root) — uruchamiany takze automatycznie
|
||||||
|
* na document.ready oraz po kazdym AJAX (debounce).
|
||||||
|
*/
|
||||||
|
(function( $ )
|
||||||
|
{
|
||||||
|
if ( typeof $ === 'undefined' || typeof $.fn === 'undefined' || typeof $.fn.select2 === 'undefined' )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var THRESHOLD = 4;
|
||||||
|
|
||||||
|
function should_init( $el )
|
||||||
|
{
|
||||||
|
if ( !$el.length )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $el.data( 'select2' ) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $el.hasClass( 'no-select2' ) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var force = $el.attr( 'data-adspro-select2' );
|
||||||
|
|
||||||
|
if ( force === 'false' )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $el.closest( '.select2-container' ).length )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $el.closest( '.dataTables_length' ).length )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( force === 'true' )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var option_count = $el.prop( 'options' ) ? $el.prop( 'options' ).length : $el.find( 'option' ).length;
|
||||||
|
|
||||||
|
return option_count > THRESHOLD;
|
||||||
|
}
|
||||||
|
|
||||||
|
function build_options( $el )
|
||||||
|
{
|
||||||
|
var options = { width: '100%' };
|
||||||
|
var first_option = $el.find( 'option' ).first();
|
||||||
|
var first_value = first_option.length ? first_option.attr( 'value' ) : null;
|
||||||
|
var placeholder = $el.attr( 'placeholder' );
|
||||||
|
|
||||||
|
if ( first_option.length && ( first_value === '' || typeof first_value === 'undefined' ) )
|
||||||
|
{
|
||||||
|
options.allowClear = true;
|
||||||
|
|
||||||
|
if ( !placeholder )
|
||||||
|
{
|
||||||
|
var text = $.trim( first_option.text() );
|
||||||
|
placeholder = text || 'Wybierz...';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( placeholder )
|
||||||
|
{
|
||||||
|
options.placeholder = placeholder;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $.fn.select2.defaults && typeof $.fn.select2.defaults.set === 'function' )
|
||||||
|
{
|
||||||
|
// jezeli polski jezyk dostepny — nie wymuszamy globalnie, Select2 sam dobierze
|
||||||
|
}
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
function init_one( $el )
|
||||||
|
{
|
||||||
|
if ( !should_init( $el ) )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$el.select2( build_options( $el ) );
|
||||||
|
$el.data( 'adspro-select2-ready', true );
|
||||||
|
}
|
||||||
|
catch ( err )
|
||||||
|
{
|
||||||
|
if ( window.console && console.warn )
|
||||||
|
{
|
||||||
|
console.warn( '[adspro-select2] init failed', err );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function init_all( $root )
|
||||||
|
{
|
||||||
|
var $scope = $root && $root.length ? $root : $( document.body );
|
||||||
|
var $selects = $scope.find( 'select' );
|
||||||
|
|
||||||
|
if ( $scope.is( 'select' ) )
|
||||||
|
{
|
||||||
|
$selects = $selects.add( $scope );
|
||||||
|
}
|
||||||
|
|
||||||
|
$selects.each( function()
|
||||||
|
{
|
||||||
|
init_one( $( this ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
window.adsproSelect2Init = init_all;
|
||||||
|
|
||||||
|
$( function()
|
||||||
|
{
|
||||||
|
init_all();
|
||||||
|
} );
|
||||||
|
|
||||||
|
var ajax_debounce_timer = null;
|
||||||
|
|
||||||
|
$( document ).ajaxComplete( function()
|
||||||
|
{
|
||||||
|
if ( ajax_debounce_timer )
|
||||||
|
{
|
||||||
|
clearTimeout( ajax_debounce_timer );
|
||||||
|
}
|
||||||
|
|
||||||
|
ajax_debounce_timer = setTimeout( function()
|
||||||
|
{
|
||||||
|
init_all();
|
||||||
|
}, 150 );
|
||||||
|
} );
|
||||||
|
})( window.jQuery );
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
<div class="campaigns-filters">
|
<div class="campaigns-filters">
|
||||||
<div class="filter-group">
|
<div class="filter-group">
|
||||||
<label for="terms_client_id"><i class="fa-solid fa-building"></i> Klient</label>
|
<label for="terms_client_id"><i class="fa-solid fa-building"></i> Klient</label>
|
||||||
<select id="terms_client_id" name="terms_client_id" class="form-control">
|
<select id="terms_client_id" name="terms_client_id" class="form-control" data-adspro-select2="true">
|
||||||
<option value="">- wybierz klienta -</option>
|
<option value="">- wybierz klienta -</option>
|
||||||
<?php foreach ( $this -> clients as $client ): ?>
|
<?php foreach ( $this -> clients as $client ): ?>
|
||||||
<option value="<?= $client['id']; ?>"><?= htmlspecialchars( $client['name'] ); ?></option>
|
<option value="<?= $client['id']; ?>"><?= htmlspecialchars( $client['name'] ); ?></option>
|
||||||
@@ -15,13 +15,13 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="filter-group">
|
<div class="filter-group">
|
||||||
<label for="terms_campaign_id"><i class="fa-solid fa-bullhorn"></i> Kampania</label>
|
<label for="terms_campaign_id"><i class="fa-solid fa-bullhorn"></i> Kampania</label>
|
||||||
<select id="terms_campaign_id" name="terms_campaign_id" class="form-control">
|
<select id="terms_campaign_id" name="terms_campaign_id" class="form-control" data-adspro-select2="true">
|
||||||
<option value="">- wybierz kampanie -</option>
|
<option value="">- wybierz kampanie -</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="filter-group">
|
<div class="filter-group">
|
||||||
<label for="terms_ad_group_id"><i class="fa-solid fa-layer-group"></i> Grupa reklam</label>
|
<label for="terms_ad_group_id"><i class="fa-solid fa-layer-group"></i> Grupa reklam</label>
|
||||||
<select id="terms_ad_group_id" name="terms_ad_group_id" class="form-control">
|
<select id="terms_ad_group_id" name="terms_ad_group_id" class="form-control" data-adspro-select2="true">
|
||||||
<option value="">- wszystkie grupy -</option>
|
<option value="">- wszystkie grupy -</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@@ -1738,6 +1738,12 @@ function load_ad_groups()
|
|||||||
$ad_group_select.val( saved_ad_group_id );
|
$ad_group_select.val( saved_ad_group_id );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( typeof window.adsproSelect2Init === 'function' )
|
||||||
|
{
|
||||||
|
window.adsproSelect2Init( $ad_group_select.parent() );
|
||||||
|
}
|
||||||
|
$ad_group_select.trigger( 'change.select2' );
|
||||||
|
|
||||||
load_phrase_tables();
|
load_phrase_tables();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1791,6 +1797,12 @@ function load_campaigns_for_client( restore_campaign_id )
|
|||||||
$campaign_select.val( restore_campaign_id );
|
$campaign_select.val( restore_campaign_id );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( typeof window.adsproSelect2Init === 'function' )
|
||||||
|
{
|
||||||
|
window.adsproSelect2Init( $campaign_select.parent() );
|
||||||
|
}
|
||||||
|
$campaign_select.trigger( 'change.select2' );
|
||||||
|
|
||||||
load_ad_groups();
|
load_ad_groups();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -133,61 +133,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.products-page .select2-container {
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.products-page .select2-container--default .select2-selection--single {
|
|
||||||
height: 38px;
|
|
||||||
border: 1px solid #e2e8f0;
|
|
||||||
border-radius: 6px;
|
|
||||||
background: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.products-page .select2-container--default .select2-selection--single .select2-selection__rendered {
|
|
||||||
line-height: 36px;
|
|
||||||
padding-left: 12px;
|
|
||||||
padding-right: 36px;
|
|
||||||
font-size: 14px;
|
|
||||||
color: #2d3748;
|
|
||||||
}
|
|
||||||
|
|
||||||
.products-page .select2-container--default .select2-selection--single .select2-selection__placeholder {
|
|
||||||
color: #6c757d;
|
|
||||||
}
|
|
||||||
|
|
||||||
.products-page .select2-container--default .select2-selection--single .select2-selection__arrow {
|
|
||||||
height: 36px;
|
|
||||||
right: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.products-page .select2-container--default.select2-container--focus .select2-selection--single {
|
|
||||||
border-color: #6690f4;
|
|
||||||
box-shadow: 0 0 0 3px rgba(102, 144, 244, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.products-page .select2-dropdown {
|
|
||||||
border: 1px solid #e2e8f0;
|
|
||||||
border-radius: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.products-page .select2-search--dropdown .select2-search__field {
|
|
||||||
border: 1px solid #e2e8f0;
|
|
||||||
border-radius: 6px;
|
|
||||||
height: 34px;
|
|
||||||
padding: 6px 10px;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.products-page .select2-results__option {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.products-page .select2-container--default .select2-results__option--highlighted[aria-selected] {
|
|
||||||
background-color: #6690f4;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.products-page .products-id-cell {
|
.products-page .products-id-cell {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -607,29 +552,6 @@ function products_render_columns_picker( table_instance )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function init_products_scope_select_search()
|
|
||||||
{
|
|
||||||
if ( typeof $.fn.select2 === 'undefined' )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
[ '#products_campaign_id', '#products_ad_group_id' ].forEach( function( selector ) {
|
|
||||||
var $select = $( selector );
|
|
||||||
|
|
||||||
if ( !$select.length || $select.data( 'products-select2-ready' ) )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$select.select2({
|
|
||||||
width: '100%'
|
|
||||||
});
|
|
||||||
|
|
||||||
$select.data( 'products-select2-ready', true );
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
function products_breakdown_number( value, digits )
|
function products_breakdown_number( value, digits )
|
||||||
{
|
{
|
||||||
var num = Number( value || 0 );
|
var num = Number( value || 0 );
|
||||||
@@ -720,8 +642,6 @@ function products_build_breakdown_html( row_meta )
|
|||||||
|
|
||||||
$( function()
|
$( function()
|
||||||
{
|
{
|
||||||
init_products_scope_select_search();
|
|
||||||
|
|
||||||
var products_table = new DataTable( '#products', {
|
var products_table = new DataTable( '#products', {
|
||||||
stateSave: true,
|
stateSave: true,
|
||||||
ajax: {
|
ajax: {
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
<link rel="stylesheet" type="text/css" href="/libraries/select2/css/select2-bootstrap-5-theme.min.css">
|
<link rel="stylesheet" type="text/css" href="/libraries/select2/css/select2-bootstrap-5-theme.min.css">
|
||||||
<link rel="stylesheet" type="text/css" href="/layout/style.css">
|
<link rel="stylesheet" type="text/css" href="/layout/style.css">
|
||||||
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
||||||
|
<script src="/libraries/adspro-select2-autoinit.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body class="logged">
|
<body class="logged">
|
||||||
<?php
|
<?php
|
||||||
|
|||||||
Reference in New Issue
Block a user