feat(media): reusable media management

Sprint 22.

- MediaAsset gains folder (flat) and MediaListParams gains folder/tag
  filters; MediaRepository.listFolders() derives the folder list from
  existing records
- upload validation: 10MB size cap, mime allow-list (jpeg/png/webp/gif/
  svg+xml/pdf), real error messages surfaced through MediaLibraryFacade
  instead of a generic swallowed string
- SVG uploads are sanitized (script tags and on*= attributes stripped)
  before storage
- raster images (excl. gif) are downscaled to a 2000px max dimension and
  re-encoded via canvas before storage - compression, not a crop UI
- tag editing (window.prompt, comma-separated) via
  MediaLibraryFacade.updateTags()
- MediaPickerComponent wired into Project Editor branding (logo, compact
  logo, favicon) alongside its existing category/product usage - confirmed
  no image fields exist on Static Pages or as a dedicated hero field to
  wire

docs/ADMIN.md updated with the new Sprint 22 section including the storage
abstraction note (MediaRepository was already the abstraction).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
sdarbinyan
2026-07-15 10:42:23 +04:00
parent 60c63a0d2a
commit 30afb5d778
14 changed files with 324 additions and 33 deletions

View File

@@ -32,12 +32,13 @@ Notify user: **from Sprint 20 (Categories) once product↔category link + admin
- Commit: `feat(admin): complete product management`
- Known trade-off: related-products picker sources from whatever page is currently loaded in `AdminProductsFacade.products()`, not a full catalog search — documented in ADMIN.md, fine at current mock scale.
## Sprint 22 — Media System hardening
- [ ] Folder support, tags, search in Media Manager
- [ ] Crop/resize/compression on upload, SVG + file-type validation
- [ ] Confirm reuse across category/product/logo/hero/static-page selectors
- [ ] Storage abstraction doc note (swap IndexedDB mock -> CDN later)
## Sprint 22 — Media System hardening ✅ done
- [x] Folder support (flat, filter-based), tags (edit + filter), search (already existed)
- [x] Resize/compression on upload (canvas downscale + re-encode, raster only) + SVG script-sanitization + file-type/size validation with real surfaced errors
- [x] Confirmed reuse: category images (20), product gallery (21), branding logo/compact-logo/favicon (22, newly wired). Static pages: no image fields (not a gap). Hero: no dedicated field exists.
- [x] Storage abstraction documented (`MediaRepository` abstract class was already the abstraction)
- Commit: `feat(media): reusable media management`
- Scoped down from ticket: no interactive crop UI (compression/resize only); folders are a flat tag, not a real folder entity/hierarchy.
## Sprint 23 — Orders (mock/local, flag backend gap)
- [ ] Orders model + local gateway (seed mock data)