dashboard: add missing dash-* CSS classes; cluster: add stat-row/stat-card CSS
The Dashboard page was rendering as plaintext because all .dash-* CSS classes (dash-section, dash-onair-*, dash-jobs-*, dash-cluster-*, dash-statusbar, etc.) were missing. Added them with the full dark-theme design-system styling matching the rest of the app. The Cluster page's .stat-row and .stat-card classes were also missing, causing node statistics (counts, CPU, GPUs, memory) to render unstyled. Added grid-based stat row and card styles.
This commit is contained in:
parent
4172b0d70a
commit
48d54a32cf
2 changed files with 551 additions and 0 deletions
|
|
@ -1019,6 +1019,38 @@
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
.stat-row {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
.stat-card {
|
||||
background: var(--bg-1);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--r-lg);
|
||||
padding: 14px 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
.stat-card .label {
|
||||
font-size: 10.5px;
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
color: var(--text-4);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
}
|
||||
.stat-card .value {
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
letter-spacing: -0.02em;
|
||||
color: var(--text-1);
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
/* ========== Settings ========== */
|
||||
.settings-nav {
|
||||
display: flex; flex-direction: column; gap: 2px;
|
||||
|
|
|
|||
|
|
@ -470,6 +470,525 @@
|
|||
text-align: right;
|
||||
}
|
||||
|
||||
/* ========== Dashboard page ========== */
|
||||
.page.dash {
|
||||
padding: 0 28px 12px;
|
||||
}
|
||||
|
||||
.dash-section {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.dash-section:last-child { margin-bottom: 0; }
|
||||
|
||||
.dash-sectionhead {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 16px 0 10px;
|
||||
position: relative;
|
||||
}
|
||||
.dash-sectionhead[data-accent=live] .dash-sectionhead-title { color: var(--live); }
|
||||
.dash-sectionhead[data-accent=danger] .dash-sectionhead-title { color: var(--danger); }
|
||||
.dash-sectionhead-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--text-1);
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
.dash-sectionhead-count {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
.dash-sectionhead-num {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: var(--text-2);
|
||||
}
|
||||
.dash-sectionhead-label {
|
||||
font-size: 11.5px;
|
||||
color: var(--text-3);
|
||||
}
|
||||
.dash-sectionhead-more {
|
||||
margin-left: auto;
|
||||
font-size: 11.5px;
|
||||
color: var(--text-3);
|
||||
background: none;
|
||||
border: 0;
|
||||
padding: 4px 6px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
transition: background 100ms, color 100ms;
|
||||
}
|
||||
.dash-sectionhead-more:hover {
|
||||
background: var(--bg-2);
|
||||
color: var(--text-1);
|
||||
}
|
||||
|
||||
/* On-air grid */
|
||||
.dash-onair-grid {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
.dash-onair-grid[data-count="1"] { grid-template-columns: 1fr; }
|
||||
.dash-onair-grid[data-count="2"] { grid-template-columns: 1fr 1fr; }
|
||||
.dash-onair-grid[data-count="3"] { grid-template-columns: 1fr 1fr 1fr; }
|
||||
.dash-onair-grid[data-count="4"] { grid-template-columns: 1fr 1fr; }
|
||||
|
||||
.dash-onair-tile {
|
||||
background: var(--bg-1);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--r-lg);
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
transition: border-color 120ms;
|
||||
}
|
||||
.dash-onair-tile:hover { border-color: var(--border-stronger); }
|
||||
|
||||
.dash-onair-video {
|
||||
position: relative;
|
||||
aspect-ratio: 16/9;
|
||||
background: var(--bg-2);
|
||||
overflow: hidden;
|
||||
}
|
||||
.dash-onair-rec-pip {
|
||||
position: absolute;
|
||||
top: 8px; left: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
font-size: 10.5px;
|
||||
font-weight: 600;
|
||||
color: white;
|
||||
background: var(--danger);
|
||||
padding: 2px 7px;
|
||||
border-radius: 4px;
|
||||
line-height: 1.3;
|
||||
}
|
||||
.dash-onair-rec-dot {
|
||||
width: 6px; height: 6px;
|
||||
border-radius: 50%;
|
||||
background: white;
|
||||
animation: dash-rec-pulse 1.5s ease-in-out infinite;
|
||||
}
|
||||
@keyframes dash-rec-pulse {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.3; }
|
||||
}
|
||||
.dash-onair-time {
|
||||
position: absolute;
|
||||
bottom: 8px; right: 8px;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 11px;
|
||||
color: white;
|
||||
background: rgba(0,0,0,0.65);
|
||||
padding: 2px 7px;
|
||||
border-radius: 4px;
|
||||
backdrop-filter: blur(4px);
|
||||
}
|
||||
.dash-onair-meta {
|
||||
padding: 10px 12px;
|
||||
}
|
||||
.dash-onair-name {
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: var(--text-1);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.dash-onair-sub {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
margin-top: 3px;
|
||||
font-size: 11.5px;
|
||||
color: var(--text-3);
|
||||
}
|
||||
.dash-onair-dot {
|
||||
color: var(--text-4);
|
||||
}
|
||||
.dash-onair-source,
|
||||
.dash-onair-res,
|
||||
.dash-onair-codec { font-family: var(--font-mono); font-size: 10.5px; }
|
||||
|
||||
/* Inline empty state */
|
||||
.dash-inline-empty {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 14px 14px;
|
||||
background: var(--bg-1);
|
||||
border: 1px dashed var(--border);
|
||||
border-radius: var(--r-md);
|
||||
color: var(--text-3);
|
||||
font-size: 12.5px;
|
||||
}
|
||||
.dash-inline-empty-cta {
|
||||
margin-left: auto;
|
||||
font-size: 11.5px;
|
||||
color: var(--accent);
|
||||
background: none;
|
||||
border: 0;
|
||||
padding: 4px 6px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.dash-inline-empty-cta:hover {
|
||||
background: var(--accent-soft);
|
||||
}
|
||||
|
||||
/* Up next strip */
|
||||
.dash-next-row {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
.dash-next-card {
|
||||
flex: 1;
|
||||
background: var(--bg-1);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--r-lg);
|
||||
overflow: hidden;
|
||||
transition: border-color 120ms;
|
||||
}
|
||||
.dash-next-card.imminent {
|
||||
border-color: var(--accent);
|
||||
}
|
||||
.dash-next-time {
|
||||
padding: 8px 12px 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
.dash-next-clock {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: var(--text-2);
|
||||
}
|
||||
.dash-next-rel {
|
||||
font-size: 10.5px;
|
||||
color: var(--accent-text);
|
||||
}
|
||||
.dash-next-body {
|
||||
padding: 4px 12px 10px;
|
||||
}
|
||||
.dash-next-name {
|
||||
font-size: 12.5px;
|
||||
font-weight: 500;
|
||||
color: var(--text-1);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.dash-next-sub {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
margin-top: 3px;
|
||||
font-size: 11px;
|
||||
color: var(--text-3);
|
||||
}
|
||||
|
||||
/* Attention section */
|
||||
.dash-attention {
|
||||
}
|
||||
.dash-attention-panel {
|
||||
background: var(--bg-1);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--r-lg);
|
||||
overflow: hidden;
|
||||
}
|
||||
.dash-attention-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 12px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
cursor: pointer;
|
||||
transition: background 100ms;
|
||||
}
|
||||
.dash-attention-row:last-child { border-bottom: 0; }
|
||||
.dash-attention-row.level-danger {
|
||||
border-left: 3px solid var(--danger);
|
||||
}
|
||||
.dash-attention-row.level-warning {
|
||||
border-left: 3px solid var(--warning);
|
||||
}
|
||||
.dash-attention-row:hover { background: var(--bg-2); }
|
||||
.dash-attention-icon {
|
||||
width: 24px; height: 24px;
|
||||
display: grid; place-items: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.dash-attention-title {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--text-1);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.dash-attention-detail {
|
||||
font-size: 11px;
|
||||
color: var(--text-3);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
flex: 1;
|
||||
}
|
||||
.dash-attention-arrow {
|
||||
flex-shrink: 0;
|
||||
color: var(--text-4);
|
||||
}
|
||||
.dash-attention-more {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 8px 12px;
|
||||
font-size: 11.5px;
|
||||
color: var(--text-3);
|
||||
cursor: pointer;
|
||||
justify-content: center;
|
||||
}
|
||||
.dash-attention-more:hover { color: var(--text-1); }
|
||||
|
||||
/* Two-column work + cluster grid */
|
||||
.dash-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 14px;
|
||||
}
|
||||
.dash-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* Job queue panel */
|
||||
.dash-jobs-panel {
|
||||
background: var(--bg-1);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--r-lg);
|
||||
overflow: hidden;
|
||||
}
|
||||
.dash-jobs-head {
|
||||
display: grid;
|
||||
grid-template-columns: 20px 1fr 1fr 1fr;
|
||||
gap: 6px;
|
||||
padding: 6px 12px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
color: var(--text-4);
|
||||
}
|
||||
.dash-jobs-row {
|
||||
display: grid;
|
||||
grid-template-columns: 20px 1fr 1fr 1fr;
|
||||
gap: 6px;
|
||||
padding: 7px 12px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
}
|
||||
.dash-jobs-row:last-child { border-bottom: 0; }
|
||||
.dash-jobs-statr { justify-content: center; }
|
||||
.dash-jobs-kind {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
color: var(--text-2);
|
||||
overflow: hidden;
|
||||
}
|
||||
.dash-jobs-kind span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.dash-jobs-asset {
|
||||
color: var(--text-1);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.dash-jobs-progress {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
.dash-jobs-bar {
|
||||
flex: 1;
|
||||
height: 4px;
|
||||
background: var(--bg-3);
|
||||
border-radius: 99px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.dash-jobs-bar-fill {
|
||||
height: 100%;
|
||||
background: var(--accent);
|
||||
border-radius: 99px;
|
||||
transition: width 300ms;
|
||||
}
|
||||
.dash-jobs-pct {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 10px;
|
||||
color: var(--text-3);
|
||||
min-width: 28px;
|
||||
text-align: right;
|
||||
}
|
||||
.dash-jobs-state {
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
color: var(--text-4);
|
||||
}
|
||||
.dash-jobs-state.done { color: var(--success); }
|
||||
.dash-jobs-state.failed { color: var(--danger); }
|
||||
|
||||
/* Cluster panel (dashboard) */
|
||||
.dash-cluster-panel {
|
||||
background: var(--bg-1);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--r-lg);
|
||||
overflow: hidden;
|
||||
}
|
||||
.dash-cluster-head {
|
||||
display: grid;
|
||||
grid-template-columns: 20px 1fr 1fr 1fr;
|
||||
gap: 6px;
|
||||
padding: 6px 12px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
color: var(--text-4);
|
||||
}
|
||||
.dash-cluster-row {
|
||||
display: grid;
|
||||
grid-template-columns: 20px 1fr 1fr 1fr;
|
||||
gap: 6px;
|
||||
padding: 7px 12px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
}
|
||||
.dash-cluster-row:last-child { border-bottom: 0; }
|
||||
.dash-cluster-row[data-online=false] { opacity: 0.55; }
|
||||
.dash-cluster-status { display: flex; align-items: center; }
|
||||
.dash-cluster-name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.dash-cluster-host {
|
||||
font-weight: 500;
|
||||
color: var(--text-1);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.dash-cluster-role {
|
||||
font-size: 9.5px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
color: var(--accent-text);
|
||||
background: var(--accent-soft);
|
||||
padding: 1px 5px;
|
||||
border-radius: 3px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.dash-cluster-metric {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
}
|
||||
.dash-cluster-bar {
|
||||
flex: 1;
|
||||
height: 4px;
|
||||
background: var(--bg-3);
|
||||
border-radius: 99px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.dash-cluster-bar-fill {
|
||||
height: 100%;
|
||||
border-radius: 99px;
|
||||
transition: width 200ms;
|
||||
}
|
||||
.dash-cluster-val {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 10.5px;
|
||||
color: var(--text-2);
|
||||
min-width: 32px;
|
||||
text-align: right;
|
||||
}
|
||||
.dash-cluster-val.muted { color: var(--text-4); }
|
||||
|
||||
/* Panel empty state */
|
||||
.dash-panel-empty {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
padding: 18px 12px;
|
||||
color: var(--text-3);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* Status bar */
|
||||
.dash-statusbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 10px 0 6px;
|
||||
border-top: 1px solid var(--border);
|
||||
margin-top: 6px;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 11px;
|
||||
}
|
||||
.dash-stat-pip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
}
|
||||
.dash-stat-pip[data-tone=live] .dash-pip-dot { background: var(--live); }
|
||||
.dash-stat-pip[data-tone=accent] .dash-pip-dot { background: var(--accent); }
|
||||
.dash-stat-pip[data-tone=warning] .dash-pip-dot { background: var(--warning); }
|
||||
.dash-stat-pip[data-tone=success] .dash-pip-dot { background: var(--success); }
|
||||
.dash-stat-pip[data-tone=idle] .dash-pip-dot { background: var(--text-4); }
|
||||
.dash-pip-dot {
|
||||
width: 6px; height: 6px;
|
||||
border-radius: 50%;
|
||||
background: var(--text-4);
|
||||
}
|
||||
.dash-pip-num {
|
||||
font-weight: 600;
|
||||
color: var(--text-2);
|
||||
}
|
||||
.dash-pip-label {
|
||||
color: var(--text-4);
|
||||
text-transform: lowercase;
|
||||
}
|
||||
.dash-statusbar-sep {
|
||||
color: var(--text-5, var(--text-4));
|
||||
opacity: 0.5;
|
||||
}
|
||||
.dash-statusbar-spacer { flex: 1; }
|
||||
.dash-statusbar-clock {
|
||||
color: var(--text-3);
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
/* ========== Empty states ========== */
|
||||
.dash-empty {
|
||||
padding: 16px 0;
|
||||
|
|
|
|||
Loading…
Reference in a new issue