--- phase: 04-polish-ux plan: 01 type: execute wave: 1 depends_on: ["03-01"] files_modified: - wp-content/plugins/media-folder-pro/assets/js/folder-tree.js - wp-content/plugins/media-folder-pro/assets/js/media-filter.js - wp-content/plugins/media-folder-pro/assets/css/admin.css - wp-content/plugins/media-folder-pro/includes/class-ajax-handler.php - wp-content/plugins/media-folder-pro/media-folder-pro.php autonomous: true --- ## Goal Dopracowac UX pluginu: bulk przypisywanie mediow do folderow, dynamiczne countery, "Uncategorized" filtr, potwierdzenia operacji, stany puste, oraz drag & drop folderow miedzy soba w drzewku. ## Purpose Core features dzialaja — teraz potrzebny jest polish, ktory zamieni prototyp w uzyteczne narzedzie. Bez bulk operations i dobrych stanow pustych plugin bedzie frustrujacy w uzyciu. ## Output - Bulk select + assign do folderu - "Bez folderu" filtr (uncategorized media) - Drag & drop folderow (zmiana hierarchii) - Dynamiczne countery (live update) - Toast notifications zamiast alert() - Empty states i loading indicators ## Project Context @.paul/PROJECT.md @.paul/ROADMAP.md ## Prior Work @.paul/phases/03-media-modal/03-01-SUMMARY.md - Pelna integracja: sidebar tree + grid filter + modal dropdown + upload assign - 7 AJAX endpoints (create/rename/delete/move/get_folders/assign_media/upload_to_folder) - HTML5 D&D media→folders dziala, mfp-folder-changed event sync ## Source Files @wp-content/plugins/media-folder-pro/assets/js/folder-tree.js @wp-content/plugins/media-folder-pro/assets/js/media-filter.js @wp-content/plugins/media-folder-pro/assets/css/admin.css @wp-content/plugins/media-folder-pro/includes/class-ajax-handler.php @wp-content/plugins/media-folder-pro/media-folder-pro.php ## AC-1: Bulk assign mediow do folderu ```gherkin Given plugin aktywny, widok grid na upload.php When uzytkownik zaznacza wiele mediow (WP bulk select) i wybiera "Przenies do folderu" Then pojawia sie dropdown z folderami And po wyborze folderu wszystkie zaznaczone media zostaja przypisane And countery folderow aktualizuja sie ``` ## AC-2: Filtr "Bez folderu" (uncategorized) ```gherkin Given plugin aktywny, istnieja media bez przypisanego folderu When uzytkownik klika "Bez folderu" w drzewku sidebar Then grid pokazuje tylko media nieprzypisane do zadnego folderu ``` ## AC-3: Drag & drop folderow w drzewku ```gherkin Given plugin aktywny, istnieja foldery w drzewku When uzytkownik przeciaga folder na inny folder Then przeniesiony folder staje sie podfolderem docelowego And drzewko odswierza sie z nowa hierarchia And przenoszenie na root (poza drzewko) robi folder top-level ``` ## AC-4: Toast notifications i empty states ```gherkin Given plugin aktywny When uzytkownik wykonuje operacje (assign, create, delete, move) Then pojawia sie toast notification (nie alert()) z wynikiem And po zakonczeniu toast znika po 3 sekundach Given brak folderow w systemie When uzytkownik otwiera upload.php Then w sidebar widoczny jest empty state z CTA "Utworz pierwszy folder" ``` Task 1: Bulk assign + uncategorized filter + folder drag & drop wp-content/plugins/media-folder-pro/assets/js/folder-tree.js, wp-content/plugins/media-folder-pro/assets/js/media-filter.js, wp-content/plugins/media-folder-pro/assets/css/admin.css, wp-content/plugins/media-folder-pro/media-folder-pro.php 1. Bulk assign w media-filter.js: - Dodaj button "Przenies do folderu" do WP bulk actions bar - Hook na wp.media.view.AttachmentsBrowser lub na DOM (bulk select mode) - Metoda: po kliknieciu pokaz dropdown z folderami (reuse flattenFolders z modala) - Po wyborze folderu: zbierz IDs zaznaczonych mediow - Uzyj wp.media.frame selection lub querySelectorAll('.attachment.selected') - Wywolaj mfp_assign_media z tablica IDs - Po sukcesie: refreshTree() + odswierz grid 2. "Bez folderu" w folder-tree.js: - Dodaj pozycje "Bez folderu" pod "Wszystkie media" w sidebar - Klikniecie dispatcha 'mfp-folder-selected' z folderId: -1 - W media-filter.js: jesli folderId === -1, ustaw media_folder: -1 (MFP_Media_Query juz obsluguje -1 jako NOT EXISTS) - Dodaj ikone i styl (np. szary folder z ?) 3. Drag & drop folderow w folder-tree.js: - Na kazdym .mfp-folder__row: draggable="true" - dragstart: ustaw dataTransfer z type 'mfp-folder' + folder ID - Uzyj innego MIME type niz media drag (np. 'application/mfp-folder') - W drop handler: sprawdz typ danych - Jesli 'application/mfp-folder': to folder move → wywolaj mfp_move_folder - Jesli 'text/plain' (liczba): to media assign (istniejace zachowanie) - Drop na root area (poza folderami): new_parent_id = 0 (top-level) - Po sukcesie: refreshTree() - Wizualne: inny styl drop target dla folder-on-folder (np. zolty outline) 4. W admin.css: - Style dla "Bez folderu" linku - Style dla folder drag (rozny od media drag) - Style dla bulk assign dropdown/popup - .mfp-folder-drop-target (zolty, rozny od mfp-drop-target niebieski) 5. W media-folder-pro.php: - Dodaj i18n: 'uncategorized', 'moveToFolder', 'bulkAssigned' Avoid: Nie komplikowac bulk assign — prosty dropdown popup wystarczy. Avoid: Folder drag nie moze kolidowac z media drag — rozne dataTransfer types. - Zaznaczenie wielu mediow + bulk assign → przypisuje do wybranego folderu - "Bez folderu" klikalny, filtruje nieprzypisane media - Przeciaganie folderu na inny folder → zmiana hierarchii - Brak kolizji miedzy media drag a folder drag - Countery odswiezone po kazdej operacji AC-1 + AC-2 + AC-3 satisfied: bulk, uncategorized, folder D&D Task 2: Toast notifications + empty states + final polish wp-content/plugins/media-folder-pro/assets/js/folder-tree.js, wp-content/plugins/media-folder-pro/assets/js/media-filter.js, wp-content/plugins/media-folder-pro/assets/css/admin.css 1. System toast notifications: - Dodaj funkcje showToast(message, type) w folder-tree.js - type: 'success' (zielony), 'error' (czerwony), 'info' (niebieski) - Renderuj div.mfp-toast w prawym gornym rogu (fixed) - Auto-hide po 3s z CSS transition (fade out) - Wyeksportuj jako window.mfpToast(message, type) - Zamien WSZYSTKIE alert() i confirm() na: - alert() → showToast() - confirm() → natywny confirm() zostaje (jest OK dla destrukcji) 2. Zamien alert() w folder-tree.js: - createFolder success → toast 'Folder utworzony' - renameFolder success → toast 'Nazwa zmieniona' - deleteFolder success → toast 'Folder usuniety' - Errory → toast z type 'error' 3. Zamien alert() w media-filter.js: - assignMedia success → toast 'Media przypisane' - Errory → toast z type 'error' 4. Empty states w folder-tree.js: - Obecny empty state juz istnieje ("Kliknij + aby utworzyc...") - Ulepsz: dodaj ikone folderu, wieksza czcionka, przycisk CTA - Loading state: zamien '...' na spinner CSS (animated) 5. CSS w admin.css: - .mfp-toast: fixed position, right:20px, top:50px, z-index:10000 - .mfp-toast--success: zielone tlo - .mfp-toast--error: czerwone tlo - .mfp-toast--info: niebieskie tlo - Animacja: slide-in + fade-out - .mfp-empty ulepszone: ikona + CTA button - .mfp-spinner: CSS-only spinner (border animation) Avoid: Nie uzywac zewnetrznych bibliotek toast (np. toastr). Avoid: Nie zastepowac confirm() przy usuwaniu — potrzebne jest potwierdzenie. - Tworzenie folderu → toast "Folder utworzony" (zielony, 3s auto-hide) - Blad AJAX → toast z bledem (czerwony) - Brak folderow → empty state z ikona i CTA - Ladowanie folderow → spinner - Brak alert() w kodzie (oprocz confirm dla delete) - Brak JS errors w konsoli AC-4 satisfied: toast notifications i empty states ## DO NOT CHANGE - wp-content/plugins/elementor-pro/* - wp-content/plugins/media-folder-pro/includes/class-taxonomy.php - wp-content/plugins/media-folder-pro/includes/class-media-query.php - wp-content/plugins/media-folder-pro/assets/js/modal-integration.js (stabilna) ## SCOPE LIMITS - Brak keyboard navigation (nice-to-have, nie MVP) - Brak accessibility ARIA (nice-to-have, nie MVP) - Brak i18n .pot file (osobny task poza MVP) - Brak settings page (nie potrzebna w MVP) Before declaring plan complete: - [ ] Bulk select + assign dziala - [ ] "Bez folderu" filtruje uncategorized media - [ ] Folder drag & drop zmienia hierarchie - [ ] Toast notifications zamiast alert() - [ ] Empty state z CTA gdy brak folderow - [ ] Loading spinner podczas ladowania - [ ] Brak regresji: wszystkie Phase 1-3 features dzialaja - [ ] Brak JS errors w konsoli - [ ] Brak PHP errors/warnings - Wszystkie taski ukonczone - Plugin gotowy jako MVP v0.1 - Wszystkie 4 fazy dzialaja razem - UX jest plynny i profesjonalny After completion, create `.paul/phases/04-polish-ux/04-01-SUMMARY.md`