Custom WordPress plugin that replaces the default flat media library with a structured folder view. Features: hierarchical folders via custom taxonomy, sidebar folder tree, drag & drop, modal integration with Elementor/builders, bulk assign, upload auto-assign, toast notifications. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
9.3 KiB
9.3 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous
| phase | plan | type | wave | depends_on | files_modified | autonomous | ||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 04-polish-ux | 01 | execute | 1 |
|
|
true |
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
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
<acceptance_criteria>
AC-1: Bulk assign mediow do folderu
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)
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
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
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"
</acceptance_criteria>
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 grid2. "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)
<success_criteria>
- Wszystkie taski ukonczone
- Plugin gotowy jako MVP v0.1
- Wszystkie 4 fazy dzialaja razem
- UX jest plynny i profesjonalny </success_criteria>