2026-05-22 10:04:24 -04:00
|
|
|
// screens-home.jsx
|
feat(home): restore launcher home page; move current home to Dashboard
The original first-version home page (big-button launcher with the
Dragonflight wordmark) is back at /. The Frame.io-style metrics +
recent-activity layout we've been treating as "home" is now the
Dashboard, reachable from the sidebar and from the launcher's
"Open dashboard" button.
- Renames existing Home → Dashboard (all the cards, sparklines, live
feed, job-queue, cluster mini-list are unchanged).
- New Home component: hero with the dragon-coiled-D logo (existing
img/dragon-logo.png), wordmark "DRAGONFLIGHT", a tag line, and 5
big tiles (Library, Recorders, Editor, Jobs, Settings) plus a
smaller Dashboard tile. Live cluster + recorder status pip at the
bottom mirrors what's in the topbar.
- The launcher pulls /metrics/home so the tile counts ("34 assets",
"0 live", "0 running") reflect reality.
2026-05-23 10:48:06 -04:00
|
|
|
//
|
|
|
|
|
// Two routes share this file:
|
|
|
|
|
//
|
ui: full audit pass (fixes #146, #147, #148, #149, #151, #152, #153, #154, #155)
Sweep of 9 web-ui audit findings from tracker #156. Issue #150 (modal
codec stubs) deferred per user request.
## #146 sweep em-dashes (186 to 0)
- Replace placeholder '—' with '·' across all jsx
- Convert ' — ' to ': ' or '. ' in copy where context permits
- Comment-only em-dashes converted to ASCII dash
- Sweep css files too (16 comments)
## #147 remove glassmorphism + accent gradients
- Strip 8 backdrop-filter declarations from styles-screens.css and
styles-asset.css. Only legit modal scrim in styles-modal.css remains.
- Replace .job-progress-fill gradient with solid var(--accent)
- Replace .monitor-tile.audio gradient with flat var(--bg-1)
## #148 extract Jobs inline styles to CSS
- Cut 19 inline style={{...}} blocks in screens-jobs.jsx to 1 (dynamic
width on progress bar). Live DOM was 487 inline-styled elements due
to per-row repetition; now ~0.
- Added job-row-kind, job-row-asset, job-row-node, job-row-time,
job-row-actions, job-row-status-* utility classes in styles-screens.css
## #149 sidebar IA reorganized
- Replace flat NAV_TREE + ADMIN_TREE with NAV_SECTIONS:
Workspace / Ingest / Operations / Admin
- Move Capture out of Ingest into Operations (it's a live-signal monitor,
not an ingest action)
- Drop the 0/N capture badge from nav (belongs in topbar)
- Add BETA badge to Editor
## #151 redesign Editor 'Coming Soon' bumper
- Replace fullscreen glassmorphism + gradient + glow overlay with a flat
beta banner across the top of the editor area
- New .editor-beta-banner CSS class (flat, accent-soft tint, no blur)
## #152 hide Tokens parody, restore real API token mgmt
- New top-level Tokens admin page wraps existing ApiTokensSection
- Old parody renamed to TokensParody, accessible at /tokens-parody route
- Add window-level df:nav event for cross-component routing
## #153 make Home actually useful
- New activity strip below the launcher grid: 'Recording now' tiles for
live recorders, 'Last 24 hours' tiles for newly created assets, plus
an attention strip when there are failed jobs or errored recorders
- Each item is clickable and routes to the relevant screen
## #154 aria-labels on icon-only buttons
- Projects + Library grid/list view toggles now have aria-label + title
## #155 page-header pattern
- Dashboard now renders a proper .page-header h1 with subtitle + alert
badge + cluster status pip
- Library toolbar-title promoted to h1 for screen-reader hierarchy
- Document Home/Library/Editor full-bleed exceptions in DESIGN.md
- Editor's chrome is the beta banner (covered by #151)
2026-05-28 19:50:07 -04:00
|
|
|
// • Home - the launcher. Big-button entry into each section of the MAM.
|
feat(home): restore launcher home page; move current home to Dashboard
The original first-version home page (big-button launcher with the
Dragonflight wordmark) is back at /. The Frame.io-style metrics +
recent-activity layout we've been treating as "home" is now the
Dashboard, reachable from the sidebar and from the launcher's
"Open dashboard" button.
- Renames existing Home → Dashboard (all the cards, sparklines, live
feed, job-queue, cluster mini-list are unchanged).
- New Home component: hero with the dragon-coiled-D logo (existing
img/dragon-logo.png), wordmark "DRAGONFLIGHT", a tag line, and 5
big tiles (Library, Recorders, Editor, Jobs, Settings) plus a
smaller Dashboard tile. Live cluster + recorder status pip at the
bottom mirrors what's in the topbar.
- The launcher pulls /metrics/home so the tile counts ("34 assets",
"0 live", "0 running") reflect reality.
2026-05-23 10:48:06 -04:00
|
|
|
//
|
2026-06-02 23:33:58 -04:00
|
|
|
// • Dashboard - the operations view. Rebuilt as a control-room status board.
|
|
|
|
|
|
|
|
|
|
// ─── DragonFlame ─────────────────────────────────────────────
|
|
|
|
|
// Canvas-based particle flame rendered behind the logo. Each particle rises
|
|
|
|
|
// from the base, fades as it climbs, and shifts hue from deep orange → yellow.
|
|
|
|
|
// Spectral shimmer is added via a secondary "spark" layer with lighter colors.
|
|
|
|
|
function DragonFlame() {
|
|
|
|
|
const canvasRef = React.useRef(null);
|
|
|
|
|
const rafRef = React.useRef(null);
|
|
|
|
|
|
|
|
|
|
React.useEffect(function() {
|
|
|
|
|
const canvas = canvasRef.current;
|
|
|
|
|
if (!canvas) return;
|
|
|
|
|
const ctx = canvas.getContext('2d');
|
|
|
|
|
|
|
|
|
|
// Particle pool
|
|
|
|
|
const W = 160, H = 200;
|
|
|
|
|
canvas.width = W;
|
|
|
|
|
canvas.height = H;
|
|
|
|
|
|
|
|
|
|
// Particle factory
|
|
|
|
|
function mkParticle(isSpark) {
|
|
|
|
|
const x = W * 0.5 + (Math.random() - 0.5) * (isSpark ? 30 : 50);
|
|
|
|
|
return {
|
|
|
|
|
x,
|
|
|
|
|
y: H - 10 - Math.random() * 20,
|
|
|
|
|
vx: (Math.random() - 0.5) * (isSpark ? 0.6 : 0.9),
|
|
|
|
|
vy: -(0.8 + Math.random() * (isSpark ? 2.2 : 1.6)),
|
|
|
|
|
life: 0,
|
|
|
|
|
maxLife: 50 + Math.random() * (isSpark ? 30 : 50),
|
|
|
|
|
size: isSpark ? 1 + Math.random() * 2 : 3 + Math.random() * 5,
|
|
|
|
|
spark: isSpark,
|
|
|
|
|
wobble: (Math.random() - 0.5) * 0.04,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const COUNT = 90, SPARK_COUNT = 30;
|
|
|
|
|
const particles = Array.from({ length: COUNT }, function() { return mkParticle(false); });
|
|
|
|
|
const sparks = Array.from({ length: SPARK_COUNT }, function() { return mkParticle(true); });
|
|
|
|
|
|
|
|
|
|
function reset(p) {
|
|
|
|
|
var n = mkParticle(p.spark);
|
|
|
|
|
Object.assign(p, n);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function draw() {
|
|
|
|
|
ctx.clearRect(0, 0, W, H);
|
|
|
|
|
|
|
|
|
|
// Draw glow base
|
|
|
|
|
const grad = ctx.createRadialGradient(W * 0.5, H - 5, 0, W * 0.5, H - 5, 55);
|
|
|
|
|
grad.addColorStop(0, 'rgba(255,120,0,0.18)');
|
|
|
|
|
grad.addColorStop(0.5, 'rgba(255,70,0,0.07)');
|
|
|
|
|
grad.addColorStop(1, 'transparent');
|
|
|
|
|
ctx.fillStyle = grad;
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.ellipse(W * 0.5, H - 5, 55, 30, 0, 0, Math.PI * 2);
|
|
|
|
|
ctx.fill();
|
|
|
|
|
|
|
|
|
|
// Update + draw each particle
|
|
|
|
|
var all = particles.concat(sparks);
|
|
|
|
|
all.forEach(function(p) {
|
|
|
|
|
p.life += 1;
|
|
|
|
|
if (p.life >= p.maxLife) { reset(p); return; }
|
|
|
|
|
|
|
|
|
|
var t = p.life / p.maxLife; // 0 → 1
|
|
|
|
|
// Gentle horizontal drift (wobble)
|
|
|
|
|
p.vx += p.wobble;
|
|
|
|
|
p.vx *= 0.98;
|
|
|
|
|
p.x += p.vx;
|
|
|
|
|
p.y += p.vy;
|
|
|
|
|
// Decelerate rise near end
|
|
|
|
|
p.vy *= 0.99;
|
|
|
|
|
|
|
|
|
|
var alpha = p.spark
|
|
|
|
|
? Math.sin(t * Math.PI) * 0.85
|
|
|
|
|
: (t < 0.2 ? t / 0.2 : 1 - (t - 0.2) / 0.8) * 0.7;
|
|
|
|
|
|
|
|
|
|
// Colour: deep orange (0°) → orange (20°) → yellow (50°) as t rises
|
|
|
|
|
var hue = p.spark
|
|
|
|
|
? 40 + t * 20 // sparks: golden yellow
|
|
|
|
|
: 10 + t * 45; // flame: orange→yellow
|
|
|
|
|
var sat = 100;
|
|
|
|
|
var lgt = p.spark ? 70 + t * 20 : 50 + t * 20;
|
|
|
|
|
|
|
|
|
|
ctx.save();
|
|
|
|
|
ctx.globalAlpha = alpha;
|
|
|
|
|
if (p.spark) {
|
|
|
|
|
// Sparks: small bright dots
|
|
|
|
|
ctx.fillStyle = 'hsl(' + hue + ',' + sat + '%,' + lgt + '%)';
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.arc(p.x, p.y, p.size * (1 - t * 0.5), 0, Math.PI * 2);
|
|
|
|
|
ctx.fill();
|
|
|
|
|
} else {
|
|
|
|
|
// Flame particles: soft blurred ellipses
|
|
|
|
|
var size = p.size * (1 - t * 0.6);
|
|
|
|
|
var g2 = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, size * 2.2);
|
|
|
|
|
g2.addColorStop(0, 'hsla(' + hue + ',' + sat + '%,' + lgt + '%,1)');
|
|
|
|
|
g2.addColorStop(0.4, 'hsla(' + (hue - 8) + ',' + sat + '%,' + (lgt - 10) + '%,0.5)');
|
|
|
|
|
g2.addColorStop(1, 'transparent');
|
|
|
|
|
ctx.fillStyle = g2;
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.ellipse(p.x, p.y, size * 2.2, size * 3.5, 0, 0, Math.PI * 2);
|
|
|
|
|
ctx.fill();
|
|
|
|
|
}
|
|
|
|
|
ctx.restore();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
rafRef.current = requestAnimationFrame(draw);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check reduced-motion preference
|
|
|
|
|
var mq = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)');
|
|
|
|
|
if (mq && mq.matches) {
|
|
|
|
|
// Static glow only
|
|
|
|
|
var sg = ctx.createRadialGradient(W * 0.5, H * 0.65, 0, W * 0.5, H * 0.65, 80);
|
|
|
|
|
sg.addColorStop(0, 'rgba(255,130,0,0.22)');
|
|
|
|
|
sg.addColorStop(0.6, 'rgba(255,70,0,0.08)');
|
|
|
|
|
sg.addColorStop(1, 'transparent');
|
|
|
|
|
ctx.fillStyle = sg;
|
|
|
|
|
ctx.fillRect(0, 0, W, H);
|
|
|
|
|
} else {
|
|
|
|
|
draw();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return function() {
|
|
|
|
|
if (rafRef.current) cancelAnimationFrame(rafRef.current);
|
feat(home): restore launcher home page; move current home to Dashboard
The original first-version home page (big-button launcher with the
Dragonflight wordmark) is back at /. The Frame.io-style metrics +
recent-activity layout we've been treating as "home" is now the
Dashboard, reachable from the sidebar and from the launcher's
"Open dashboard" button.
- Renames existing Home → Dashboard (all the cards, sparklines, live
feed, job-queue, cluster mini-list are unchanged).
- New Home component: hero with the dragon-coiled-D logo (existing
img/dragon-logo.png), wordmark "DRAGONFLIGHT", a tag line, and 5
big tiles (Library, Recorders, Editor, Jobs, Settings) plus a
smaller Dashboard tile. Live cluster + recorder status pip at the
bottom mirrors what's in the topbar.
- The launcher pulls /metrics/home so the tile counts ("34 assets",
"0 live", "0 running") reflect reality.
2026-05-23 10:48:06 -04:00
|
|
|
};
|
|
|
|
|
}, []);
|
|
|
|
|
|
2026-06-02 23:33:58 -04:00
|
|
|
return React.createElement('span', { className: 'launcher-logo-pulse' },
|
|
|
|
|
React.createElement('canvas', { ref: canvasRef })
|
feat(home): restore launcher home page; move current home to Dashboard
The original first-version home page (big-button launcher with the
Dragonflight wordmark) is back at /. The Frame.io-style metrics +
recent-activity layout we've been treating as "home" is now the
Dashboard, reachable from the sidebar and from the launcher's
"Open dashboard" button.
- Renames existing Home → Dashboard (all the cards, sparklines, live
feed, job-queue, cluster mini-list are unchanged).
- New Home component: hero with the dragon-coiled-D logo (existing
img/dragon-logo.png), wordmark "DRAGONFLIGHT", a tag line, and 5
big tiles (Library, Recorders, Editor, Jobs, Settings) plus a
smaller Dashboard tile. Live cluster + recorder status pip at the
bottom mirrors what's in the topbar.
- The launcher pulls /metrics/home so the tile counts ("34 assets",
"0 live", "0 running") reflect reality.
2026-05-23 10:48:06 -04:00
|
|
|
);
|
2026-06-02 23:33:58 -04:00
|
|
|
}
|