Commit graph

44 commits

Author SHA1 Message Date
04508c847f fix: prepend folder prefix to filename before upload so AMPP can sort by folder 2026-05-02 23:39:50 -04:00
Claude
a32329abb2 Remove placement worker — buildS3Key already embeds prefix--filename for AMPP workflow 2026-05-02 11:29:32 -04:00
Claude
9ec0f91848 Simplify: single AMPP folder picker (repurpose S3 tree, remove separate input) 2026-04-30 21:57:05 -04:00
Claude
e55555d2b7 Fix AMPP picker: text input, path-based queuing, worker path resolution 2026-04-30 21:49:16 -04:00
4ee422a5e8 feat: AMPP folder picker UI — load folders, pick target, queue placement on upload 2026-04-30 17:57:00 -04:00
a07d2c0ae4 Add public/index.html
Speed display was wildly inaccurate during parallel multipart uploads. Fixed with monotonic byte tracking, 15s smoothing window, and cached speed values.
2026-04-12 13:44:54 -04:00
02f5583e96 chore: delete accidental hindex.html (filename typo during edit) 2026-04-12 13:39:20 -04:00
2e3ac69f97 fix: SpeedTracker uses monotonic bytes + 15s smoothing for accurate speed display
Speed display was wildly inaccurate during parallel multipart uploads because:
1. Parallel chunk progress events caused non-monotonic byte counts
2. The 5-second smoothing window was too short for bursty uploads
3. Speed dropped to near-zero between chunk boundaries

Fixes:
- Enforce monotonic byte tracking via _peak guard
- Extend sliding window from 5s to 15s
- Cache last good speed value for display continuity
- Require >= 1s of data before calculating (was 0.5s)
2026-04-12 13:34:03 -04:00
5113adb635 feat: add real-time upload speed monitor with ETA
Shows "XX% · Y.Y MB/s · ~Zm Zs" during uploads. Speed is smoothed
over a 5-second rolling window. Works for both small (single PUT)
and large (multipart chunked) uploads.
2026-04-09 22:08:33 -04:00
009530416f perf: reduce chunk size from 32MB to 8MB for better parallelism
A 46MB file now splits into 6 chunks (all 6 streams active) instead
of 2 chunks (4 streams idle). Better saturation of available bandwidth
on high-latency or constrained links.
2026-04-09 22:07:09 -04:00
f7d8ba14cf feat: presigned multipart upload for large files (browser-direct)
Large files (>32MB) now use presigned S3 multipart URLs via
/api/desktop/multipart/init, letting the browser PUT 32MB chunks
directly to S3 in 6 parallel streams. No data passes through Node.
Small files still use single presigned PUT. Updated HTTP mode
description to "HTTP multi-part upload".
2026-04-09 21:43:22 -04:00
6947e25230 fix: restore uploader + add chunked multipart for large files
Reverts accidental landing page overwrite. Files >32MB now use S3
multipart upload with 32MB chunks and 6 parallel streams per file.
Files <=32MB still use fast direct presigned PUT.
2026-04-09 21:32:06 -04:00
d06f96f208 fix: restore correct uploader with chunked multipart upload support 2026-04-09 21:29:31 -04:00
13349ce32e fix: restore correct uploader with chunked multipart upload support 2026-04-09 21:26:39 -04:00
97c4a4c779 fix: restore correct uploader with chunked multipart upload support 2026-04-09 21:26:12 -04:00
837d848c2e feat: chunked parallel multipart upload for large files
Files >32MB now use S3 multipart upload with 32MB chunks and 6 parallel
streams per file. Files <=32MB still use fast direct presigned PUT.
Fixes slow upload speeds for large files.
2026-04-09 21:22:23 -04:00
14aea6961e feat: chunked parallel multipart upload for large files
Files >32MB now use S3 multipart upload with 32MB chunks and 6 parallel
streams per file. Files <=32MB still use fast direct presigned PUT.
Fixes slow upload speeds for large files.
2026-04-09 21:21:22 -04:00
Zac
02b67f2b6a feat: enable Electron App download button with Windows/macOS links, remove "processed 6 at a time" text 2026-04-08 22:59:09 -04:00
84cf9cccbe Fix folder sorting, default selection, subfolder S3 keys, and HTTP mode description
Addresses feedback from Gavin (VPM):
- Sort folders alphabetically in both upload tree and admin tree views
- Auto-select VPM as default folder on login instead of Root
- Fix S3 key construction for nested folders: convert "/" to "--" so FLX
  correctly maps subfolders (e.g. Content/TEST - AMPP Demo now produces
  Content--TEST - AMPP Demo--file.ext instead of Content/TEST - AMPP Demo--file.ext)
- Clarify HTTP mode note: "Files are processed 6 at a time" instead of
  "up to 6 concurrent files" which implied a total file limit

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 21:40:44 -04:00
Zac
ecdfe0f7cd Presigned direct-to-S3 uploads — bypass Node server entirely
Browser now uploads files directly to RustFS/S3 via presigned PUT URLs.
The Node server only generates signed URLs and tracks quota — file data
never touches the server. 6 concurrent file uploads.

Falls back to server-proxied PutObjectCommand upload if presigned fails.

Server changes:
- /api/presigned now checks folder permissions, quota, and blocked files
- /api/presigned/complete endpoint for post-upload quota tracking

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 01:08:55 -04:00
Zac
0f81cac6ec QOL improvements: folder search, user audit, admin folders fix, AMPP debug
- Add search/filter input to destination folder browser with 320px
  scrollable container
- Add User Audit button showing each user's visible pages, role,
  quota, and folder access permissions
- Fix admin Folders tab delete buttons (were broken due to
  JSON.stringify quote conflicts in innerHTML onclick handlers)
- Add more AMPP job name field fallbacks and debug logging to
  diagnose asset name display issue

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 01:03:28 -04:00
Zac
ad5f9a4186 Update HTTP mode description to reflect actual upload method
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 00:56:04 -04:00
Zac
d5192e8847 Replace chunked multipart upload with simple Upload class
The manual CreateMultipartUploadCommand/UploadPartCommand/CompleteMultipartUploadCommand
flow fails with RustFS due to non-standard XML responses (same issue as HeadBucketCommand).
Switch front-end to use /api/upload endpoint which uses @aws-sdk/lib-storage Upload class —
the same method that worked reliably in VPM-Uploader with RustFS.

Uses XMLHttpRequest for upload progress tracking.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 00:49:13 -04:00
Zac
ae4360e85a Fix S3 test (use HeadBucket like VPM-Uploader), replace UDP button with grayed Electron App 2026-04-07 00:30:28 -04:00
Zac
db25255472 Fix S3 save, remove UDP relay entirely, remove Extension tab 2026-04-07 00:26:43 -04:00
Zac
f3aa44104c Remove Extension tab, fix S3 save, update footer, add Electron uploader coming soon to UDP Relay 2026-04-07 00:21:31 -04:00
172250b279 fix: AMPP Monitor field mapping for Grassvalley API colon-namespaced keys
AMPP API returns keys like 'state:jobState', 'name:text', 'type:jobType',
'creator:id', 'created:dateTime', 'job:id' — not plain 'status', 'name',
etc. Frontend was falling back to 'Job' / 'Unknown' for every entry.

Updated field lookups to read colon-namespaced keys first, with fallbacks
for compatibility. Also added 'aborted' to the failed status detection.
2026-04-06 23:30:00 -04:00
8ec43c299e Add parallel chunked HTTP upload (Option 4 — Aspera-class speed)
Split files into 32 MB chunks, POST 6 concurrently to /api/upload/chunk,
server proxies each chunk as an S3 multipart part. Up to 4 files upload
in parallel simultaneously. Achieves Aspera-class throughput over plain
HTTP with no UDP port forwarding or custom protocols required.

Same approach used by MASV under the hood.

- server.js: Add /api/upload/initiate, /chunk, /complete, /abort endpoints
- public/index.html: Replace single-PUT uploadHTTP() with parallel chunked version
2026-04-06 23:22:51 -04:00
a3d1446060 fix: add missing UDP Relay admin tab button and HTTP/UDP mode toggle buttons on upload page 2026-04-06 22:46:52 -04:00
42fead82aa fix: split relay URL into internal + public for browser clients
The relay container is reached internally via docker service name
(http://dragon-wind-relay:3001) but browsers need the public address.
Previously the internal URL was sent to clients causing UDP uploads to fail.

- Add publicRelayUrl field to relay config (server + admin UI)
- /api/udp/session now returns publicRelayUrl to browser clients
- Internal relayUrl still used for server-side health checks
- Falls back to internal URL if public not set

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 22:02:14 -04:00
9e1e25ac97 fix: web GUI upload Content-Type mismatch with presigned URL
Same fix as the Chrome extension — the web GUI's uploadHTTP() was using
item.file.type (browser-determined MIME) instead of presigned.contentType
(server-signed MIME). For broadcast formats like MXF, R3D, BRAW where
the browser returns empty or generic types, this causes an S3 signature
mismatch and the PUT fails.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 21:56:03 -04:00
fa206ba21a fix: AMPP monitor duplicate ID, not-configured UX, and auto-refresh
- Fix duplicate id="ampp-status" collision between the monitor page and
  admin AMPP panel — admin panel now uses id="ampp-cfg-status" so the
  monitor status messages are no longer silently hijacked
- AMPP monitor now shows a clear "not configured" card with a direct
  button to Admin → AMPP instead of a cryptic error when the API key
  hasn't been entered yet
- Improve job field mapping to handle AMPP response variations
  (jobStatus, displayName, jobType, results array vs items array)
- Add 30-second auto-refresh while on the Monitor tab; timer is cleared
  when navigating away to avoid ghost requests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 21:32:09 -04:00
08c138ca46 Fix extension icons and AMPP autofill
- Generate missing chrome-extension/images/ icons (16, 48, 128px)
  that were absent from repo, causing 'Could not load manifest' error
- Fix AMPP API key field: add readonly+onfocus to block Bitwarden/browser autofill

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 21:05:46 -04:00
017d73f48c Fix S3 config form: autofill, region default, secret field
- Add readonly+onfocus trick to prevent browser autofilling secret key with garbage
- Set region value="us-east-1" so it always has a real default, not just placeholder
- loadS3Config always clears secret field and sets contextual placeholder
- Secret hint now clearly shows saved vs not-saved state

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 20:39:22 -04:00
d0525eb718 Fix extension 404, simplify UDP/relay UI
- Add chrome-extension/ to Dockerfile COPY (was missing, caused 404 on download)
- Remove UDP Relay tab from admin panel (relay is server-side, no user config needed)
- Remove upload mode toggle buttons, replace with clean inline status bar
- Extension panel: drop relay port-forwarding note, simplify to 'extension required' message
- UDP hint shown inline only when extension is detected in browser

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 20:32:25 -04:00
b393eca960 Redesign folder UI, VPM branding, and auto theme
- Replace chip-pill folder selector with clean vertical tree list
- VPM text wordmark replaces vpm-logo.png in login + header (no PNG/invert hack)
- Wild Dragon logo/icon retained only on favicon and splash animation
- Auto-detect prefers-color-scheme on first load (no longer defaults to dark)
- System theme changes update UI if user hasn't manually toggled
- Remove dragon icon from login card and app header

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 20:26:51 -04:00
c03b7ef491 Add per-user upload quotas/permissions and share link system
- Per-user quota tracking (MB limit + uploadedBytes counter)
- Per-user allowed folders restriction (empty = all folders allowed)
- Admin permissions modal: quota config, folder checkboxes, usage reset
- Share links: create tokenized upload URLs with expiry, max-uses, folder
- Public share.html upload page (no auth required) with drag-drop + progress
- Backend routes: GET/PUT /api/users/:u/permissions, POST .../quota/reset
- Backend routes: GET/POST /api/sharelinks, DELETE .../token, GET /share/:token
- migrateData() ensures existing user records gain new fields on startup
- Frontend JS: loadUsers quota column, openPermissions modal, loadShareLinks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 19:58:29 -04:00
12441b7bf4 feat: VPM branding + Built by footer
- Added VPM logo (vpm-logo.png) to login card and header left side
  (subtle, opacity 50%, auto-inverted in light mode)
- Footer at bottom of app: "Built by Zac Gaetano & Wild Dragon LLC
  · In partnership with Broadcast Management Group"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 19:41:07 -04:00
cde70d386d fix: extension download using wrong auth header (Authorization vs x-auth-token)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 21:25:46 -04:00
e2c6db7113 fix: S3 generic compat, nav tab reliability, single logo
S3:
- Endpoint is now optional (leave blank = AWS S3, custom = MinIO/R2/Backblaze/etc.)
- forcePathStyle only applied when a custom endpoint is set (harmless on AWS)
- initS3() no longer requires endpoint to be present
- Updated form hint to explain AWS vs generic S3 usage

Nav tabs:
- Switched admin tab active-state matching from fragile array-index to data-tab attribute
- Added user-select:none to prevent text selection on click for both nav and admin tabs
- Admin tabs now flex-wrap for narrow viewports

Logo:
- Removed wilddragon-logo.png wordmark from splash, login, and header
- Single dragon-icon.png used throughout — no CSS invert hack needed
- Cleaner header: icon + "Dragon Wind" badge only

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 20:42:21 -04:00
895145e1ed feat: Chrome extension download + install guide in admin panel
- GET /api/extension/download — streams chrome-extension/ as a .zip using archiver
- Admin → 🧩 Extension tab with:
  - One-click download button (fetches zip via auth'd API, triggers browser save)
  - 5-step install guide: unzip, chrome://extensions, developer mode, load unpacked, configure
  - UDP port-forwarding reminder note
- Added archiver dependency to package.json

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 20:33:56 -04:00
155c821ef8 feat: AMPP configuration in admin settings
- GET/PUT /api/ampp/config — store base URL + API key in db.json (no restart needed)
- POST /api/ampp/test — authenticate against AMPP token endpoint and report result
- Refactored AMPP_BASE/AMPP_API_KEY constants to dynamic getAmppBase()/getAmppApiKey()
  functions so live config changes take effect immediately
- Admin → AMPP tab: base URL field, masked API key field, Test Connection + Save buttons
- Cached token invalidated automatically on config save

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 20:22:51 -04:00
6b6efc61ba feat: Wild Dragon branding — splash animation + logo assets
- Full cinematic splash screen with animated dragon GIF, 18 wind streaks,
  pulsing glow rings, shimmer subtitle, and accelerating progress bar
- Wild Dragon wordmark (wilddragon-logo.png) in header and login, CSS-inverted for dark mode
- Dragon circular icon (dragon-icon.png) in header and login card
- Dragon animation GIF (dragon-anim.gif) as splash hero
- Blue (#1e4bd8) primary accent matching Wild Dragon brand; orange reserved for UDP mode

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 20:19:57 -04:00
641701edf8 feat: Dragon Wind v1.0 — dual-mode broadcast uploader
- Full VPM Uploader feature set (auth, users, folders, AMPP monitor)
- HTTP upload via presigned S3 URLs with XHR progress tracking
- UDP upload mode with relay server (WebRTC DataChannel + HTTP fallback)
- S3 Admin settings with live Test Connection (upload+delete verify)
- UDP Relay Admin settings with health check
- Standalone UDP relay server (Node.js + Docker) with multipart S3 assembly
- Chrome Extension (Manifest v3): popup, background, content script
- Dynamic S3 client — reconfigures on save without restart
- Dark/light theme, full AMPP job monitor
- docker-compose.yml with dragon-wind + udp-relay services

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 20:05:34 -04:00