Commit graph

639 commits

Author SHA1 Message Date
claude
24820e921e polish: schedule past-time confirm, recorder name sanitization, asset detail player controls
- Schedule: if start_at is more than a minute in the past, confirm()
  before submitting (operator may want to fire immediately, but
  shouldn't do it accidentally)
- Recorders: generateClipName now sanitizes the recorder name so the
  S3 key / SMB path / ffmpeg arg stays clean — spaces become
  underscores, anything outside [A-Za-z0-9._-] is dropped, capped at 40
- Asset detail: audio mute + fullscreen buttons now key off streamUrl
  state (rather than videoRef.current which is null on first render)
  so they reliably appear when a stream is available
2026-05-23 04:12:42 +00:00
claude
47ad01d0b2 polish(projects,jobs,bins): row menus, real status bars, bulk retry
Projects:
- Per-row 3-dot menu in list view: Open / Rename / Delete (PATCH + DELETE)
- ProjectCard's bottom bar now shows real ready/in-flight/error counts
  for the project's assets instead of fake 70/20 segments
- After mutations, project list refreshes from /projects + recomputes
  asset counts client-side

Bins:
- GET /api/v1/bins now returns every bin across every project when
  no project_id is supplied; result rows include project_name + asset_count
- Asset right-click 'Move to bin' filters to bins in the same project as
  the asset and surfaces project_name as a tooltip

Jobs:
- 'Retry all failed' button in the header appears when there are
  failed jobs and POSTs /retry for each one in parallel
- Failed-row error message now clips with title= tooltip so 3KB
  ffmpeg stderr doesn't blow out the row layout

window.PROJECT_COLORS exposed for cross-screen access.
2026-05-23 04:09:13 +00:00
f474a77bcb feat(web-ui): style the asset right-click menu (.ctx-menu)
The AssetContextMenu in screens-library.jsx has shipped without
matching styles, so the menu rendered as raw HTML on the page. Adds
.ctx-menu / .ctx-header / .ctx-divider / .ctx-section-label / .ctx-empty
plus button + danger styles matching the existing .row-menu look.
2026-05-23 00:04:25 -04:00
claude
f186cdeacd polish(ui): wire dead buttons across asset detail, shell, containers, cluster
Asset detail:
- Download now fetches /assets/:id/hires presigned URL and triggers a
  named browser download instead of doing nothing
- More icon now opens a kebab menu (Copy ID, Delete permanently)
- Approve button removed (no backend); audio + fullscreen icons
  in the player controls now actually toggle mute / requestFullscreen

Shell:
- Sidebar Sign-out now POSTs /auth/logout + reloads (no-op when auth disabled, by design)
- Topbar Notifications bell removed (dead, no backend)
- Topbar search wired: typing + Enter routes to Library with the term
  pre-loaded into Library's own search box
- Cluster-healthy pip now polls /metrics/home every 30s so it reflects
  real online-vs-total instead of always showing green

Editor:
- Dead Export / Publish / Mark in / Mark out / Add to timeline / Step
  buttons are now visibly disabled with explanatory titles; a PREVIEW
  badge sits next to the sequence name so the WIP state is obvious

Containers / Cluster admin:
- Logs button opens a modal with the docker tail command + Copy button
  instead of a JS alert
- Restart now shows an inline toast (pending/ok/fail) instead of alerts
- Cluster Add Node / Drain / Logs replace alert() with a styled advice
  modal that supports multi-line commands + Copy
- Dead Cluster topology Graph/List tab toggle removed (only Graph is
  implemented anyway)
2026-05-23 04:04:08 +00:00
630dc75787 fix(web-ui): hide search wrapper (with dropdown) on narrow screens
Previously the responsive rule hid only .search, leaving the dropdown
positioned on its own wrapper. Target .search-wrap so input + results
both hide together.
2026-05-22 23:55:36 -04:00
899876c6cf feat(web-ui): style global search dropdown
Adds .search-wrap / .search-results / .search-result styles for the
new topbar command-palette dropdown. Per-kind pill colors distinguish
asset / project / recorder / job / user / nav results at a glance.
2026-05-22 23:55:14 -04:00
61d02d522b feat(web-ui): pass search-select handlers from App to Topbar
Wires onOpenAsset and onOpenProject through Topbar so that selecting
an asset/project from the global search opens the asset detail or
navigates to the project view. Adds openProjectFromAnywhere helper.
2026-05-22 23:53:19 -04:00
45c0e0f914 feat(web-ui): wire global search in topbar with results dropdown
Replaces the static topbar input with a working command-palette-style
search that queries ZAMPP_DATA across assets, projects, recorders,
jobs, users, and nav targets. Cmd/Ctrl+K focuses the input, arrow keys
move selection, Enter opens, Esc dismisses. Selecting an asset opens
the asset detail; project opens project view; other kinds navigate.
2026-05-22 23:52:49 -04:00
claude
992fbdfa20 fix(recorders,library): empty-capture handling + right-click context menu
Proxy failures ("moov atom not found"):
- root cause: failed/aborted SRT/RTMP recordings still uploaded 0-byte
  (or ftyp-only ~1KB) objects to S3, which ffmpeg can't probe
- worker proxy.js now bails on inputs < 4 KiB with a clear message
  before handing the file to ffmpeg
- capture-manager.stop() returns framesReceived + empty flag
- capture shutdown handler skips POST /assets entirely on empty
  sessions, instead calls new POST /assets/:id/mark-empty to flip
  the pre-created live asset to 'error' with a note

Library asset right-click menu:
- new AssetContextMenu component on screens-library.jsx; right-click
  any asset in grid or list view to open
- actions: Open, Rename, Move to bin (lists up to 10 bins), Remove
  from bin, Copy asset ID, Delete permanently (hard=true)
- viewport-aware positioning (won't clip past window edges)
- dismisses on outside click / contextmenu / scroll
- Library now refreshes via /assets after mutations; normalizeAsset
  exposed on window so the re-fetch shape matches boot
- ctx-menu styles in styles-rest.css
2026-05-23 03:52:30 +00:00
claude
9877ed351f fix(recorders): queue proxy on finalize + custom clip names
- POST /api/v1/assets: when transitioning from 'live' to 'processing'
  with a hi-res key but no proxy, queue a proxy job instead of just
  flipping status='ready'. Recorder-captured clips now get a proxy
  + thumbnail like upload-path assets do
- POST /api/v1/recorders/:id/start now accepts { clipName } in the body;
  operator-supplied name (sanitized to [A-Za-z0-9 ._-], capped at 80)
  overrides the auto-generated <recorder>_<timestamp> fallback
- RecorderRow gets a 'Clip name (optional)' input visible when stopped;
  Enter triggers Record, value sent on POST start, cleared on stop
- New POST /api/v1/assets/:id/generate-proxy and
  POST /api/v1/assets/backfill-proxies for one-shot cleanup of pre-fix
  clips that have a hi-res master but no proxy
2026-05-23 03:41:03 +00:00
claude
b128c9f5a9 fix(metrics): use real job_status enum values (queued/processing/complete) 2026-05-23 03:31:14 +00:00
claude
ef4c301149 feat(home,users): real metrics, working Users row actions + Groups CRUD
- Home: new /api/v1/metrics/home endpoint buckets last 24h of assets,
  jobs done/failed into hourly counts; sparklines now render real
  time-series instead of decorative sine waves
- Home stat cards are now clickable (route to relevant page) and the
  delta lines show real activity ("+N added in last 24h", "N completed")
- Home live-feed tiles use HlsPreview for recorders with a live_asset_id
- Users: row 3-dot menu is now a real popover with Rename / Reset
  password / Delete actions wired to PATCH /users/:id and DELETE
- Users: role is now an inline <select> that PATCHes immediately
- Users: Created column replaces fake 'last active' (no last_login
  tracking yet); group count is real
- Groups tab is now functional — list groups, create, expand to
  show + manage members (add/remove), delete; backed by existing
  /api/v1/groups CRUD
- Policies tab is now an honest 'coming soon' stub
- New icons: key, lock, edit; new .row-menu popover styles
2026-05-23 03:30:10 +00:00
claude
53196d38ce feat(scheduler): recorder scheduling — UI, CRUD, tick loop, recurrence
- New Ingest → Schedule page: upcoming/past/all tabs, status badges
  (pending / recording / completed / cancelled / failed), 10s
  auto-refresh, cancel/delete actions
- New Schedule modal: name, recorder dropdown, datetime-local start/end,
  recurrence (one-shot / daily / weekly), sensible defaults (+5min / +35min)
- Backend: migration 009 (recorder_schedules), routes/schedules.js
  (list/create/edit/cancel/delete), scheduler.js tick loop polling every
  15s; transitions trigger /recorders/:id/start and /stop via in-process
  HTTP so we reuse the full container orchestration path
- Recurring schedules: tick loop auto-queues the next occurrence on
  completion (daily = +24h, weekly = +7d)
- Sidebar + app.jsx route wired in, schedule-row table style added
2026-05-23 03:19:24 +00:00
claude
6398879b56 feat: SDK deployment UI, proxy encoding global settings, S3 env fallback
- Settings: drop AMPP tab, rename GPU/Transcoding → Proxy encoding
  with explicit 'applied to every ingested file' wording, expose
  CPU codec/preset options when GPU is off
- New Capture SDKs tab (Settings): upload Blackmagic / AJA / Deltacast
  SDK archives (.zip / .tar.gz) staged to /sdk/<vendor>/ inside mam-api;
  BMD is fully wired into the FFmpeg build pipeline, AJA + Deltacast
  staging-only pending FFmpeg patches
- mam-api: new /api/v1/sdk routes (multer upload, extract, list, delete);
  Dockerfile gets unzip+tar; docker-compose mounts /mnt/NVME/MAM/sdk:/sdk
- proxy worker now reads proxy-encoding settings from DB on every job,
  builds args for libx264 / NVENC / VAAPI, falls back to libx264 on
  hardware-encode failure
- settings GET /s3 falls back to S3_* env vars when DB is empty so the
  UI reflects what's actually wired (fixes 'not configured' false alarm)
2026-05-23 02:58:32 +00:00
dc0bd51648 docs: growing-files + Premiere panel quickstart 2026-05-22 19:16:34 -04:00
c3991a1e75 docs: growing-files + Premiere panel quickstart 2026-05-22 19:16:04 -04:00
328f7b4f31 feat: live HLS preview, proxy worker fixes, Settings tabs, growing-files + Premier panel
- worker/proxy: scale-to-even filter, analyzeduration 100M, skip images, hasAudio
- worker/promotion: SMB landing zone -> S3 on idle, queues proxy job, status='ready'
- web-ui screens-ingest: HlsPreview component replaces fake LiveStrip/FauxFrame
- web-ui screens-admin: functional Settings tabs (S3, GPU, Growing, SDI, AMPP)
- mam-api /settings/growing: GET/PUT growing-files config
- mam-api /assets/:id/live-path: SMB UNC/POSIX path for live growing assets
- capture-manager: GROWING_ENABLED -> write hires to /growing instead of S3 stream
- recorders.js: pass GROWING_ENABLED to capture container, bind /growing mount
- docker-compose: mount /mnt/NVME/MAM/wild-dragon-growing on mam-api + worker
- premiere-plugin: Mount Live button, Relink-to-HiRes, live->ready status poll
2026-05-22 19:12:53 -04:00
3fc8fbc230 add per-seat/per-stream/per-month strikethrough hero to Tokens page 2026-05-22 17:29:23 -04:00
ceceedf201 probe fallback: basic TCP/UDP connectivity when capture service is offline 2026-05-22 17:26:26 -04:00
4864db03f3 probe: fallback to basic TCP/UDP connectivity check when capture service is offline 2026-05-22 17:22:30 -04:00
8b57a9a35a expand codec list, add MXF container, remove proxy settings (fixed profile) 2026-05-22 17:20:01 -04:00
fa787bbe1e fix hover-to-play: remove status filter so any asset triggers stream fetch 2026-05-22 17:18:56 -04:00
0aa0922fd3 remove hardcoded recorders badge 2026-05-22 17:18:20 -04:00
1abf22623d feat: hover-to-play video preview on library asset cards
Fetches stream URL on hover after 350ms delay; renders muted autoplay
video overlay over the thumbnail. Supports both mp4 and HLS streams.
Only triggers for ready/live assets to avoid pointless API calls.
2026-05-22 16:58:11 -04:00
4afd0c7b21 feat: add /cluster/containers endpoint via Docker socket
Lists all containers on the local host; supports POST /containers/:id/restart.
Falls back to [] gracefully if Docker socket is unavailable.
2026-05-22 16:57:33 -04:00
6f2de45819 feat: wire real video playback via GET /assets/:id/stream
- Fetch stream URL on asset open; show <video> element for mp4/hls
- Use hls.js for live HLS streams (loaded via CDN in index.html)
- Sync video play/pause/seek/timeupdate to React state
- Show loading state while fetching stream, status message when unavailable
- Add Retry processing button for error-status assets
- totalMs derived from video metadata when available, falls back to parseDuration
2026-05-22 13:37:55 -04:00
e3c3d60103 index: add hls.js for live stream HLS playback 2026-05-22 13:31:57 -04:00
81324c8e52 shell: add Field component (used by modal-new-recorder, was missing from global scope) 2026-05-22 12:56:33 -04:00
bec58ab138 screens-asset: fix thumbGrad crash, parseDuration NaN, guard missing ACTIVITY 2026-05-22 12:49:33 -04:00
451bed834f screens-admin: wire all buttons — invite user, export CSV, cluster refresh, container logs/restart, node drain/remove 2026-05-22 12:27:02 -04:00
d00e1c666e screens-ingest: wire delete button on RecorderRow 2026-05-22 12:24:10 -04:00
ddb4cf0c51 feat: add POST /jobs/:id/retry endpoint for re-queuing failed BullMQ jobs 2026-05-22 12:18:53 -04:00
fea0f2962b fix: wire Jobs Retry (POST /jobs/:id/retry) and Delete (DELETE /jobs/:id) buttons 2026-05-22 12:18:23 -04:00
506ee2d695 fix: wire New Project button — modal + POST /projects + state refresh 2026-05-22 12:17:54 -04:00
88689a4eb2 fix: wire Library Upload button to navigate to Upload screen 2026-05-22 12:17:29 -04:00
dc269bec00 fix: make Settings S3 form functional — load from API, save & test 2026-05-22 12:08:10 -04:00
665ab5238d feat: live status polling in RecorderRow, immediate refresh on mount 2026-05-22 11:35:13 -04:00
bb508d3256 feat: add probe button to SRT/RTMP sources, fix node labels 2026-05-22 11:33:45 -04:00
994fd799d0 fix: stop endpoint handles missing/dead containers gracefully 2026-05-22 11:32:44 -04:00
6510871448 fix: implement real upload (XHR + S3 multipart) and fix SDI recorder device_index + manual fallback: modal-new-recorder.jsx 2026-05-22 11:10:01 -04:00
26399f8d0a fix: implement real upload (XHR + S3 multipart) and fix SDI recorder device_index + manual fallback: screens-ingest.jsx 2026-05-22 11:10:00 -04:00
529d14cb6b fix: SDI crash, monitors polling, home RAM fields, editor IN DEV splash, timecode, create recorder API: modal-new-recorder.jsx 2026-05-22 10:55:22 -04:00
fb44bd8aff fix: SDI crash, monitors polling, home RAM fields, editor IN DEV splash, timecode, create recorder API: screens-editor.jsx 2026-05-22 10:55:20 -04:00
24a1d57165 fix: SDI crash, monitors polling, home RAM fields, editor IN DEV splash, timecode, create recorder API: screens-ingest.jsx 2026-05-22 10:55:19 -04:00
48ee66e744 fix: SDI crash, monitors polling, home RAM fields, editor IN DEV splash, timecode, create recorder API: screens-home.jsx 2026-05-22 10:55:18 -04:00
0342aa0a5a fix admin screen: move data destructuring inside components, normalize field names: screens-admin.jsx 2026-05-22 10:15:42 -04:00
406f28c663 feat(ui): wire ingest screens to real API (recorders, capture devices): screens-ingest.jsx 2026-05-22 10:07:13 -04:00
835545e061 feat(ui): wire library, jobs, ingest, editor screens to live API data: screens-editor.jsx 2026-05-22 10:05:57 -04:00
1392e28a88 feat(ui): wire library, jobs, ingest, editor screens to live API data: screens-jobs.jsx 2026-05-22 10:05:56 -04:00
bc03ee866b feat(ui): wire library, jobs, ingest, editor screens to live API data: screens-library.jsx 2026-05-22 10:05:54 -04:00