add admin media library with image management and block picker integration

- Schema: alt, caption, tags fields on images table with metadata changeset
- Context: list_images with filters, find_usages, used_image_ids, delete_with_cleanup
- Admin UI: /admin/media with grid view, upload, filters, detail panel, metadata editing
- Block editor: :image field type for image_text and content_body blocks
- Page renderer: image_id resolution with legacy URL fallback
- Mobile: bottom sheet detail panel with slide-up animation
- CSS: uses correct --t-* admin theme tokens, admin-badge colour variants

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jamey
2026-02-27 22:20:51 +00:00
parent a039c8d53c
commit 847b5f3e5e
15 changed files with 1828 additions and 17 deletions

View File

@@ -9,7 +9,7 @@
- Image optimization pipeline (AVIF/WebP/JPEG responsive variants)
- Shop pages (home, collections, products, cart, about, contact, error, delivery, privacy, terms)
- Mobile-first design with bottom navigation
- 1309 tests passing, 100% PageSpeed score
- 1398 tests passing, 100% PageSpeed score
- SQLite production tuning (IMMEDIATE transactions, mmap, WAL journal limit)
- Variant selector with color swatches and size buttons
- Session-based cart with real variant data (add/remove/quantity, cross-tab sync)
@@ -30,7 +30,7 @@
Ordered by dependency level — admin shell chain first (unblocks most downstream work).
Plans: [admin-redesign.md](docs/plans/admin-redesign.md) | [admin-font-loading.md](docs/plans/admin-font-loading.md) | [setup-wizard.md](docs/plans/setup-wizard.md) | [setup-and-launch.md](docs/plans/setup-and-launch.md) | [setup-auto-confirm.md](docs/plans/setup-auto-confirm.md) | [email-settings.md](docs/plans/email-settings.md) | [search.md](docs/plans/search.md) | [products-refactor.md](/home/jamey/.claude/plans/snug-roaming-zebra.md) | [shipping-sync.md](docs/plans/shipping-sync.md) | [printful-integration.md](docs/plans/printful-integration.md) | [provider-strategy.md](docs/plans/provider-strategy.md) | [css-migration.md](docs/plans/css-migration.md) | [analytics-v2.md](docs/plans/analytics-v2.md) | [page-builder.md](docs/plans/page-builder.md)
Plans: [admin-redesign.md](docs/plans/admin-redesign.md) | [admin-font-loading.md](docs/plans/admin-font-loading.md) | [setup-wizard.md](docs/plans/setup-wizard.md) | [setup-and-launch.md](docs/plans/setup-and-launch.md) | [setup-auto-confirm.md](docs/plans/setup-auto-confirm.md) | [email-settings.md](docs/plans/email-settings.md) | [search.md](docs/plans/search.md) | [products-refactor.md](/home/jamey/.claude/plans/snug-roaming-zebra.md) | [shipping-sync.md](docs/plans/shipping-sync.md) | [printful-integration.md](docs/plans/printful-integration.md) | [provider-strategy.md](docs/plans/provider-strategy.md) | [css-migration.md](docs/plans/css-migration.md) | [analytics-v2.md](docs/plans/analytics-v2.md) | [page-builder.md](docs/plans/page-builder.md) | [media-library.md](docs/plans/media-library.md)
| # | Task | Depends on | Est | Status |
|---|------|------------|-----|--------|
@@ -137,6 +137,11 @@ Plans: [admin-redesign.md](docs/plans/admin-redesign.md) | [admin-font-loading.m
| ~~83~~ | ~~`LegalPages` module — generate accurate privacy, delivery, and terms content from settings + provider + shipping data~~ | — | 2.5h | done |
| ~~84~~ | ~~Wire `LegalPages` into `Content` LiveView — replace `PreviewData` calls, add tests~~ | 83 | 45m | done |
| 85 | Page editor integration — "Regenerate" button, auto-regenerate on settings change, customised vs auto label | 83, 19 | 1.5h | planned |
| | **Media library** ([plan](docs/plans/media-library.md)) | | | |
| ~~93~~ | ~~Schema + context — alt/caption/tags on images, media type, find_usages, orphan detection~~ | — | 1.5h | done |
| ~~94~~ | ~~Admin media library UI — grid, filters, upload, detail panel, orphan management~~ | 93 | 2.5h | done |
| ~~95~~ | ~~Image picker for page builder — `:image` field type, image_id resolution in renderer~~ | 94 | 2h | done |
| 96 | Polish — theme editor alt text, full modal picker, orphan cleanup on ref removal | 95 | 1h | planned |
| | **Platform site** | | | |
| 73 | Platform/marketing site — brochure, pricing, sign-up | — | TBD | planned |
| 74 | Separation of concerns: platform site vs AGPL open source core | 73 | TBD | planned |
@@ -457,8 +462,25 @@ See: [plan](docs/plans/shipping-sync.md) for implementation details
See: [docs/plans/analytics-v2.md](docs/plans/analytics-v2.md) for v2 plan
### Media Library
**Status:** Complete — Stages 1-3 done, stage 4 (polish) planned
Admin media library at `/admin/media` with image grid, type/search/orphan filters, upload with alt text, detail panel (metadata editing, usage tracking, delete with protection). Image schema extended with `alt`, `caption`, `tags` fields and `"media"` type. `find_usages/1` scans product_images, theme settings, favicon variants, and page blocks. `delete_with_cleanup/1` refuses deletion of in-use images and cleans up disk variants. `:image` field type in block editor with image preview and ID input. Page renderer resolves `image_id` to responsive variant URLs, falling back to legacy `image_url`/`image_src` strings. Alt text backfill mix task. 1398 tests.
**Key files:**
- `lib/berrypod/media.ex` — extended context (list, update_metadata, find_usages, used_image_ids, delete_with_cleanup)
- `lib/berrypod/media/image.ex` — alt/caption/tags fields, media type, metadata_changeset
- `lib/berrypod_web/live/admin/media.ex` — admin media library LiveView
- `lib/berrypod_web/components/block_editor_components.ex``:image` field type
- `lib/berrypod_web/page_renderer.ex` — image_id resolution helpers
- `lib/mix/tasks/berrypod/backfill_alt_text.ex` — one-time backfill task
- `test/berrypod/media_test.exs` — 36 tests (17 new)
- `test/berrypod_web/live/admin/media_test.exs` — 11 tests
See: [docs/plans/media-library.md](docs/plans/media-library.md) for full plan
### Page Editor
**Status:** In progress — Stage 7b of 9 complete, 1326 tests
**Status:** In progress — Stage 8 of 9 complete, 1370 tests
Database-driven page builder. Every page is a flat list of blocks stored as JSON — add, remove, reorder, and edit blocks on any page. One generic renderer for all pages (no page-specific render functions). Portable blocks (hero, featured_products, image_text, etc.) work on any page. Page-specific blocks (product_hero, cart_items, etc.) are restricted to their native page. Block data loaders dynamically load data based on which blocks are on the page. ETS-cached page definitions. Mobile-first admin editor with live preview, undo/redo, accessible reordering (no drag-and-drop), inline settings forms, and "reset to defaults". CSS-driven page layout (not renderer-driven).
@@ -471,8 +493,8 @@ Database-driven page builder. Every page is a flat list of blocks stored as JSON
6. ~~Admin editor — page list + block management~~ ✅ (`660fda9`)
7. ~~Admin editor — inline block settings editing~~ ✅ (`3f97742`)
7b. ~~SettingsField struct + repeater field type for info_card items~~ ✅ (`6fbd654`)
8. **Next →** Live preview — split layout with real-time preview
9. Undo/redo + polish — history stacks, keyboard shortcuts, animations
8. ~~Live page editor sidebar — collapsible sidebar on shop pages, backdrop dismiss, portable content block~~ ✅ (`a039c8d`)
9. **Next →** Undo/redo + polish — history stacks, keyboard shortcuts, animations
**Key files created:**
- `lib/berrypod/pages.ex` — context (CRUD + cache + load_block_data)
@@ -482,7 +504,12 @@ Database-driven page builder. Every page is a flat list of blocks stored as JSON
- `test/berrypod/pages_test.exs` — 34 tests
- `test/berrypod_web/page_renderer_test.exs` — 18 tests
- `lib/berrypod/pages/settings_field.ex` — typed struct for settings schema fields
- `lib/berrypod/pages/block_editor.ex` — pure functions for block manipulation
- `lib/berrypod_web/components/block_editor_components.ex` — shared editor UI components
- `lib/berrypod_web/page_editor_hook.ex` — on_mount hook for live page editing on shop pages
- `test/berrypod_web/live/admin/pages_test.exs` — 42 tests
- `test/berrypod/pages/block_editor_test.exs` — 26 tests
- `test/berrypod_web/page_editor_hook_test.exs` — 13 tests
See: [docs/plans/page-builder.md](docs/plans/page-builder.md) for full plan