feat: migrate jobs.html to wd-* design system
This commit is contained in:
parent
6e43ab30c2
commit
33d2a4004d
1 changed files with 61 additions and 61 deletions
|
|
@ -5,7 +5,7 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
<title>Jobs — Dragonflight</title>
|
||||
<link rel="stylesheet" href="css/common.css">
|
||||
<link rel="stylesheet" href="/dist/app.css">
|
||||
<style>
|
||||
/* ── page layout ─────────────────────────────────────────── */
|
||||
.page-body {
|
||||
|
|
@ -357,77 +357,77 @@
|
|||
</head>
|
||||
<body>
|
||||
|
||||
<div class="shell">
|
||||
<div class="wd-shell" style="display:flex;min-height:100vh;">
|
||||
|
||||
<!-- ── Sidebar ─────────────────────────────────────────── -->
|
||||
<nav class="sidebar" aria-label="Main navigation">
|
||||
<div class="sidebar-brand">
|
||||
<img src="img/dragon-logo.png?v=1" alt="Dragonflight" class="sidebar-logo">
|
||||
<span class="sidebar-brand-name">Dragonflight</span>
|
||||
<nav class="wd-sidebar" aria-label="Main navigation">
|
||||
<div class="wd-sidebar-header">
|
||||
<img src="img/dragon-logo.png?v=1" alt="Dragonflight" style="width:18px;height:18px;">
|
||||
<span class="wd-sidebar-brand">Dragonflight</span>
|
||||
</div>
|
||||
<nav class="sidebar-nav">
|
||||
<a href="home.html" class="nav-item">
|
||||
<div class="wd-sidebar-nav">
|
||||
<a href="home.html" class="wd-nav-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M2 7l6-5 6 5v7a1 1 0 0 1-1 1h-3v-5H6v5H3a1 1 0 0 1-1-1z"/></svg>
|
||||
Home
|
||||
</a>
|
||||
<a href="index.html" class="nav-item">
|
||||
<a href="index.html" class="wd-nav-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="1" y="1" width="6" height="6" rx="1"/><rect x="9" y="1" width="6" height="6" rx="1"/><rect x="1" y="9" width="6" height="6" rx="1"/><rect x="9" y="9" width="6" height="6" rx="1"/></svg>
|
||||
Library
|
||||
</a>
|
||||
<a href="projects.html" class="nav-item">
|
||||
<a href="projects.html" class="wd-nav-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M1 4a1 1 0 0 1 1-1h4l2 2h5a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1z"/></svg>
|
||||
Projects
|
||||
</a>
|
||||
<a href="upload.html" class="nav-item">
|
||||
<a href="upload.html" class="wd-nav-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M8 11V3M5 6l3-3 3 3"/><path d="M2 13h12"/></svg>
|
||||
Ingest
|
||||
</a>
|
||||
<a href="recorders.html" class="nav-item">
|
||||
<a href="recorders.html" class="wd-nav-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="1" y="4" width="10" height="8" rx="1"/><path d="M11 7l4-2v6l-4-2"/></svg>
|
||||
Recorders
|
||||
</a>
|
||||
<a href="capture.html" class="nav-item">
|
||||
<a href="capture.html" class="wd-nav-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="8" cy="8" r="3"/><circle cx="8" cy="8" r="6.5"/></svg>
|
||||
Capture
|
||||
</a>
|
||||
<a href="jobs.html" class="nav-item active">
|
||||
<a href="jobs.html" class="wd-nav-item is-active">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M2 4h12M2 8h8M2 12h5"/></svg>
|
||||
Jobs
|
||||
</a>
|
||||
<a href="editor.html" class="nav-item">
|
||||
<a href="editor.html" class="wd-nav-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M2 13l1.5-3.5L11 2l3 3-7.5 7.5L3 14zM10 3l3 3"/></svg>
|
||||
Editor
|
||||
</a>
|
||||
<div class="sidebar-section-label">Admin</div>
|
||||
<a href="users.html" class="nav-item">
|
||||
<div class="wd-sidebar-section">Admin</div>
|
||||
<a href="users.html" class="wd-nav-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="6" cy="5" r="2.5"/><path d="M1 13c0-2.8 2.2-5 5-5s5 2.2 5 5"/><circle cx="12" cy="5" r="2"/><path d="M15 12c0-1.9-1.3-3.5-3-4"/></svg>
|
||||
Users
|
||||
</a>
|
||||
<a href="tokens.html" class="nav-item">
|
||||
<a href="tokens.html" class="wd-nav-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="6" cy="10" r="3.5"/><path d="M8.7 7.3L13 3M11.5 3.5l1.5 1.5M13.5 2.5l1 1"/></svg>
|
||||
Tokens
|
||||
</a>
|
||||
<a href="containers.html" class="nav-item">
|
||||
<a href="containers.html" class="wd-nav-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="1" y="5" width="14" height="4" rx="1"/><rect x="1" y="10" width="14" height="4" rx="1"/><path d="M4 7h1M4 12h1"/></svg>
|
||||
Containers
|
||||
</a>
|
||||
<a href="cluster.html" class="nav-item">
|
||||
<a href="cluster.html" class="wd-nav-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="8" cy="8" r="2"/><circle cx="2" cy="3" r="1.5"/><circle cx="14" cy="3" r="1.5"/><circle cx="2" cy="13" r="1.5"/><circle cx="14" cy="13" r="1.5"/><path d="M3.1 4.1L6.5 6.5M12.9 4.1L9.5 6.5M3.1 11.9L6.5 9.5M12.9 11.9L9.5 9.5"/></svg>
|
||||
Cluster
|
||||
</a>
|
||||
<a href="settings.html" class="nav-item">
|
||||
<a href="settings.html" class="wd-nav-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="8" cy="8" r="2.5"/><path d="M8 1v1.5M8 13.5V15M1 8h1.5M13.5 8H15M2.9 2.9l1.1 1.1M12 12l1.1 1.1M2.9 13.1L4 12M12 4l1.1-1.1"/></svg>
|
||||
Settings
|
||||
</a>
|
||||
</nav>
|
||||
<div class="sidebar-footer">
|
||||
<div class="sidebar-user">
|
||||
<div class="sidebar-user-avatar" id="userAvatar">?</div>
|
||||
<div class="sidebar-user-info">
|
||||
<div class="sidebar-user-name" id="userName">—</div>
|
||||
<div class="sidebar-user-role" id="userRole"></div>
|
||||
</div>
|
||||
<div class="wd-sidebar-footer">
|
||||
<div class="wd-sidebar-user">
|
||||
<div class="wd-sidebar-user-avatar" id="userAvatar">?</div>
|
||||
<div class="wd-sidebar-user-info">
|
||||
<div class="wd-sidebar-user-name" id="userName">—</div>
|
||||
<div class="wd-sidebar-user-role" id="userRole"></div>
|
||||
</div>
|
||||
<button class="btn btn-ghost" id="logoutBtn" title="Sign out" style="padding:0;width:24px;height:24px;flex-shrink:0;">
|
||||
<button class="wd-btn wd-btn--ghost wd-btn--sm wd-btn--icon wd-sidebar-user-logout" id="logoutBtn" title="Sign out">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" width="14" height="14"><path d="M10 8H3M6 5l-3 3 3 3"/><path d="M7 3h5a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1H7"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -435,15 +435,15 @@
|
|||
</nav>
|
||||
|
||||
<!-- ── Main area ────────────────────────────────────────── -->
|
||||
<div class="main">
|
||||
<div style="flex:1;display:flex;flex-direction:column;">
|
||||
|
||||
<!-- Topbar -->
|
||||
<header class="topbar">
|
||||
<div class="topbar-left">
|
||||
<header class="wd-topbar">
|
||||
<div class="wd-topbar-left">
|
||||
<span class="page-title">Jobs</span>
|
||||
</div>
|
||||
<div class="topbar-right">
|
||||
<button class="btn btn-ghost btn-sm" id="btn-clear-done" onclick="clearCompleted()">
|
||||
<div class="wd-topbar-right">
|
||||
<button class="wd-btn wd-btn--ghost wd-btn--sm" id="btn-clear-done" onclick="clearCompleted()">
|
||||
Clear completed
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -491,7 +491,7 @@
|
|||
|
||||
<div class="spacer"></div>
|
||||
|
||||
<select class="form-select type-select" id="type-filter" onchange="renderJobs()">
|
||||
<select class="wd-select type-select" id="type-filter" onchange="renderJobs()">
|
||||
<option value="">All types</option>
|
||||
<option value="transcode">Transcode</option>
|
||||
<option value="proxy">Proxy</option>
|
||||
|
|
@ -516,20 +516,20 @@
|
|||
</div><!-- /shell -->
|
||||
|
||||
<!-- ── Job detail slide panel ─────────────────────────────── -->
|
||||
<div class="slide-overlay" id="detail-overlay" onclick="closeDetail()"></div>
|
||||
<div class="slide-panel" id="detail-panel" role="dialog" aria-label="Job detail">
|
||||
<div class="slide-panel-header">
|
||||
<span class="slide-panel-title" id="detail-title">Job Detail</span>
|
||||
<button class="btn btn-ghost btn-sm" onclick="closeDetail()" aria-label="Close" style="padding:0;width:28px;height:28px;">
|
||||
<div class="wd-slide-overlay" id="detail-overlay" onclick="closeDetail()"></div>
|
||||
<div class="wd-slide-panel" id="detail-panel" role="dialog" aria-label="Job detail">
|
||||
<div class="wd-slide-panel-header">
|
||||
<span class="wd-slide-panel-title" id="detail-title">Job Detail</span>
|
||||
<button class="wd-btn wd-btn--ghost wd-btn--sm" onclick="closeDetail()" aria-label="Close" style="padding:0;width:28px;height:28px;">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M3 3l10 10M13 3L3 13"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="slide-panel-body job-detail-panel" id="detail-body">
|
||||
<div class="wd-slide-panel-body job-detail-panel" id="detail-body">
|
||||
<!-- populated by openDetail() -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="toast-container" class="toast-container"></div>
|
||||
<div id="toast-container" class="wd-toast-container"></div>
|
||||
|
||||
<script>
|
||||
/* ────────────────────────────────────────────────────────
|
||||
|
|
@ -645,15 +645,15 @@ function renderJobs() {
|
|||
completed: 'No completed jobs', failed: 'No failed jobs'
|
||||
};
|
||||
area.innerHTML = `
|
||||
<div class="empty-state">
|
||||
<div class="empty-icon">
|
||||
<div class="wd-empty">
|
||||
<div class="wd-empty-icon">
|
||||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none">
|
||||
<rect x="4" y="6" width="24" height="20" rx="2" stroke="var(--border-strong)" stroke-width="1.5"/>
|
||||
<path d="M9 12h14M9 17h10M9 22h6" stroke="var(--border-strong)" stroke-width="1.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="empty-title">${labels[currentFilter] || 'No jobs'}</div>
|
||||
<div class="empty-desc">Jobs appear here when assets are processed.</div>
|
||||
<div class="wd-empty-title">${labels[currentFilter] || 'No jobs'}</div>
|
||||
<div class="wd-empty-body">Jobs appear here when assets are processed.</div>
|
||||
</div>`;
|
||||
return;
|
||||
}
|
||||
|
|
@ -699,7 +699,7 @@ function renderRow(job) {
|
|||
const dur = formatDuration(job.started_at, job.completed_at || job.failed_at);
|
||||
|
||||
const retryBtn = (job.status === 'failed' && job.asset_id)
|
||||
? `<button class="btn btn-ghost" style="font-size:var(--text-xs);padding:4px 10px;color:var(--status-green)" onclick="retryJob('${escHtml(job.asset_id)}', event)" title="Re-queue asset processing">Retry</button>`
|
||||
? `<button class="wd-btn wd-btn--ghost" style="font-size:var(--text-xs);padding:4px 10px;color:var(--status-green)" onclick="retryJob('${escHtml(job.asset_id)}', event)" title="Re-queue asset processing">Retry</button>`
|
||||
: '';
|
||||
|
||||
tr.innerHTML = `
|
||||
|
|
@ -721,9 +721,9 @@ function renderRow(job) {
|
|||
</td>
|
||||
<td class="time-cell">${dur}</td>
|
||||
<td>
|
||||
<button class="btn btn-ghost" style="font-size:var(--text-xs);padding:4px 10px" onclick="openDetail('${escHtml(job.id)}')">Details</button>
|
||||
<button class="wd-btn wd-btn--ghost" style="font-size:var(--text-xs);padding:4px 10px" onclick="openDetail('${escHtml(job.id)}')">Details</button>
|
||||
${retryBtn}
|
||||
<button class="btn btn-ghost" style="font-size:var(--text-xs);padding:4px 10px;color:var(--signal-bad)" onclick="killJob('${escHtml(job.id)}', event)" title="Remove this job from the queue">Kill</button>
|
||||
<button class="wd-btn wd-btn--ghost" style="font-size:var(--text-xs);padding:4px 10px;color:var(--signal-bad)" onclick="killJob('${escHtml(job.id)}', event)" title="Remove this job from the queue">Kill</button>
|
||||
</td>`;
|
||||
|
||||
return tr;
|
||||
|
|
@ -753,13 +753,13 @@ async function retryJob(assetId, ev) {
|
|||
|
||||
function statusBadge(status) {
|
||||
const map = {
|
||||
active: '<span class="badge badge-recording">Active</span>',
|
||||
waiting: '<span class="badge badge-idle">Waiting</span>',
|
||||
completed: '<span class="badge badge-ready">Done</span>',
|
||||
failed: '<span class="badge badge-error">Failed</span>',
|
||||
delayed: '<span class="badge badge-processing">Delayed</span>'
|
||||
active: '<span class="wd-badge wd-badge--bad">Active</span>',
|
||||
waiting: '<span class="wd-badge wd-badge--idle">Waiting</span>',
|
||||
completed: '<span class="wd-badge wd-badge--good">Done</span>',
|
||||
failed: '<span class="wd-badge wd-badge--bad">Failed</span>',
|
||||
delayed: '<span class="wd-badge wd-badge--warn">Delayed</span>'
|
||||
};
|
||||
return map[status] || `<span class="badge badge-idle">${escHtml(status || 'Unknown')}</span>`;
|
||||
return map[status] || `<span class="wd-badge wd-badge--idle">${escHtml(status || 'Unknown')}</span>`;
|
||||
}
|
||||
|
||||
/* ────────────────────────────────────────────────────────
|
||||
|
|
@ -819,7 +819,7 @@ function openDetail(jobId) {
|
|||
|
||||
${job.status === 'failed' && job.asset_id ? `
|
||||
<div class="panel-section">
|
||||
<button class="btn btn-secondary btn-sm" onclick="retryJob('${escHtml(job.asset_id)}', event); closeDetail();">
|
||||
<button class="wd-btn wd-btn--secondary wd-btn--sm" onclick="retryJob('${escHtml(job.asset_id)}', event); closeDetail();">
|
||||
Retry — re-queue processing
|
||||
</button>
|
||||
</div>` : ''}
|
||||
|
|
@ -841,13 +841,13 @@ function openDetail(jobId) {
|
|||
<div class="log-block">${escHtml(JSON.stringify(job, null, 2))}</div>
|
||||
</div>`;
|
||||
|
||||
document.getElementById('detail-panel').classList.add('open');
|
||||
document.getElementById('detail-overlay').classList.add('open');
|
||||
document.getElementById('detail-panel').classList.add('is-open');
|
||||
document.getElementById('detail-overlay').classList.add('is-open');
|
||||
}
|
||||
|
||||
function closeDetail() {
|
||||
document.getElementById('detail-panel').classList.remove('open');
|
||||
document.getElementById('detail-overlay').classList.remove('open');
|
||||
document.getElementById('detail-panel').classList.remove('is-open');
|
||||
document.getElementById('detail-overlay').classList.remove('is-open');
|
||||
}
|
||||
|
||||
/* ────────────────────────────────────────────────────────
|
||||
|
|
@ -894,7 +894,7 @@ function formatDuration(start, end) {
|
|||
|
||||
function toast(msg, type = 'success') {
|
||||
const el = document.createElement('div');
|
||||
el.className = `toast ${type === 'error' ? 'toast-error' : ''}`;
|
||||
el.className = `wd-toast ${type === 'error' ? 'wd-toast--error' : 'wd-toast--success'}`;
|
||||
el.textContent = msg;
|
||||
document.getElementById('toast-container').appendChild(el);
|
||||
requestAnimationFrame(() => el.classList.add('show'));
|
||||
|
|
|
|||
Loading…
Reference in a new issue