Commit Graph

4 Commits

Author SHA1 Message Date
davidherran c3d196df03 feat: auto-optimize images on CMS upload via AssetBucketBrowser
Deploy to VPS / deploy (push) Has been cancelled
Enables the existing Sharp pipeline for all uploads — WebP conversion,
auto-orient, 2560px cap, content-hash filenames.  Upload toast now
shows compression savings percentage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-06 15:21:08 -05:00
davidherran 8ac372125a feat: dedicated 3D Models bucket in AssetBucketBrowser
Deploy to VPS / deploy (push) Has been cancelled
Add a "3D Models" bucket (path: models, accept: .glb/.gltf/.usdz)
to the cases scope. Previously 3D files were mixed into the Media
bucket at the root. Now they have their own tab with proper file
type hints and purple accent color matching the AR viewer UI.

- cases/media bucket no longer lists .glb/.gltf/.usdz in accept
- New bucketHint for models bucket warns on non-3D file uploads
- Network page 3D tab updated with purple accent + "3D Models"
  button label pointing to the dedicated bucket

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-06 15:15:44 -05:00
davidherran 778b35f15a feat: AssetBucketBrowser polish — bulk select, drag-move, rename in place
Deploy to VPS / deploy (push) Has been cancelled
The unified bucket browser graduated from "acceptable" to "actually
useful for bulk work". Editors can now manage dozens of files in a
single session without dragging each one through a modal.

NEW FEATURES (frontend)

1. BULK SELECTION
   - Click on a file when nothing's selected → opens it as before.
   - Click on the corner checkbox, or click the file once selection is
     active → toggle that one in/out.
   - Shift-click → range select between last anchor and current item.
   - Cmd/Ctrl-click → toggle without affecting others.
   - "Select all" toggle in the toolbar respects the search filter.

2. BULK ACTIONS TOOLBAR
   When at least one file is selected the toolbar morphs into:
     [N selected] [Delete] [Move to: Videos | Renders | …]
   Delete fires the new bulk DELETE endpoint with filePaths[], shows
   a single toast for the whole batch + per-file failure breakdown.
   Move iterates PATCH /api/assets per file (sequential, with a 'Moving…'
   indicator in the bucket helper bar).

3. DRAG TO MOVE BETWEEN BUCKETS
   Drag any file (or the whole selection if you started the drag from
   a selected file) onto another bucket tab. The tab highlights green
   with 'drop to move' while you hover. Drop fires the same per-file
   PATCH flow. No dialog, no friction.

4. RENAME IN PLACE
   Double-click a filename (in either grid or list view) → input opens
   in place. Enter saves, Escape cancels, blur saves. Sanitizes to
   safe characters. PATCH endpoint refuses to overwrite an existing
   file (returns 409, surfaced as a toast).

5. KEYBOARD HINT FOOTER
   Bottom-of-modal cheat sheet: Click / ⇧Click / ⌘Click / 2× click /
   drag onto another tab. So new editors don't have to discover the
   power-user features.

NEW BACKEND (src/app/api/assets/route.ts)

PATCH method
   { scope, slug, fromPath, toPath } → fs.renameSync.
   Used for both rename (same dir, new name) and move (different bucket).
   Refuses to overwrite an existing destination (409 conflict).
   Creates intermediate folders if needed.

DELETE extended
   Now accepts either { filePath: "x" } or { filePaths: ["a", "b"] }.
   Bulk path deletes one-by-one and returns per-file success/failure
   so the UI can show a precise toast.

REVIEWED FOR REGRESSIONS
- Single-file API still works — old { filePath } DELETE shape preserved.
- The 4 inline AssetManager call sites (network, news, applications,
  parts) use AssetBucketBrowser via the alias added in the previous
  commit; their integration is unchanged. Same props, same onSelect
  callback shape.
- Toast/Confirm calls go through the existing HqUiProvider mounted in
  hq-command/layout.tsx — no extra wiring.
2026-05-05 19:40:06 -05:00
davidherran 014a9eb094 refactor: unified AssetBucketBrowser replaces 4 inline AssetManagers
Deploy to VPS / deploy (push) Has been cancelled
Every HQ Command panel had its own ~210-line AssetManager component
copy-pasted into the page file. Same UI, same API, four diverging
implementations — and no consistent metaphor for "where does this file
go?". Editors had to think about subfolder names (videos/, renders/)
that the front-end implicitly expects.

ONE COMPONENT. CLEAR BUCKETS. SAME PATHS.

src/components/hq/AssetBucketBrowser.tsx — the single picker. Takes
scope + slug, shows bucket tabs (Media / Videos / Renders / etc.) and
maps each to the on-disk path the public site already reads from:

  cases:        Media (root) | Videos (/videos) | Renders (/renders)
  applications: Media (root) | Videos (/videos) | Renders (/renders)
  news:         Media (root)
  parts:        Media (root) | Renders (/renders)
  footage:      Hero Reel (root)
  branding:     Brand Assets (root)

Drop a file into the Videos tab → POSTs to /api/assets with path=videos
→ lands at /public/{scope}/{slug}/videos/<file> — exactly where
ApplicationClient.tsx and CaseStudyModal.tsx already look. Zero
front-end path changes, zero data migration.

UX upgrades the editor sees:
- Tabs make the bucket layout discoverable instead of buried in folder
  navigation. Each tab has its own description and accent colour.
- Soft-warning hints flag obvious mismatches ("Videos bucket usually
  holds .mp4 — this file may not display correctly") without blocking
  the upload.
- Search + grid/list views.
- Hover actions per file: copy URL, delete (with confirm).
- Persistent on-screen path (/{scope}/{slug}/{bucket}) so editors can
  always see the canonical location.

REPLACEMENT (4 page files)
- network/page.tsx:      719 → 513 lines (-206) — direct alias
- news/page.tsx:         484 → 313 lines (-171) — direct alias
- applications/page.tsx: 555 → 433 lines (-122) — adapter wraps the
  picker's onSelect into the markdown-syntax onInsert callback this
  panel uses. No call-site changes.
- parts/page.tsx:        413 → 320 lines  (-93) — direct alias

Net: -592 lines of duplicated UI, +560 lines of single shared component.
Future bucket-layout changes live in one file instead of four.

NO PATH/API CHANGES — /api/assets is unchanged. The on-disk layout is
unchanged. Existing assets keep rendering on the public site. Existing
DB rows (mediaFileName, galleryJson, videosJson, rendersJson) are
unaffected because we never moved files.
2026-05-05 08:55:20 -05:00