feat: replace UI with design system example pages wired to real API
Migrate all page components from the @cameleer/design-system v0.0.3 example UI, replacing mock data with real backend API hooks. This brings richer visuals (KpiStrip, GroupCard, RouteFlow, ProcessorTimeline, DateRangePicker, expandable rows) while preserving all existing API integration, auth, and routing infrastructure. Pages migrated: Dashboard, RoutesMetrics, RouteDetail, ExchangeDetail, AgentHealth, AgentInstance, OidcConfig, AuditLog, RBAC (Users/Groups/Roles). Also enhanced LayoutShell CommandPalette with real search data from catalog. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,13 @@
|
||||
/* Scrollable content area */
|
||||
.content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 20px 24px 40px;
|
||||
min-width: 0;
|
||||
background: var(--bg-body);
|
||||
}
|
||||
|
||||
/* Stat strip */
|
||||
.statStrip {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
@@ -5,13 +15,66 @@
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
/* Stat breakdown with colored dots */
|
||||
.breakdown {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
font-size: 11px;
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
.bpLive { color: var(--success); display: inline-flex; align-items: center; gap: 3px; }
|
||||
.bpStale { color: var(--warning); display: inline-flex; align-items: center; gap: 3px; }
|
||||
.bpDead { color: var(--error); display: inline-flex; align-items: center; gap: 3px; }
|
||||
|
||||
.routesSuccess { color: var(--success); }
|
||||
.routesWarning { color: var(--warning); }
|
||||
.routesError { color: var(--error); }
|
||||
|
||||
/* Scope breadcrumb trail */
|
||||
.scopeTrail {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 16px;
|
||||
gap: 6px;
|
||||
margin-bottom: 12px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.scopeLink {
|
||||
color: var(--amber);
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.scopeLink:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.scopeSep {
|
||||
color: var(--text-muted);
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.scopeCurrent {
|
||||
color: var(--text-primary);
|
||||
font-weight: 600;
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
/* Section header */
|
||||
.sectionTitle {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.sectionMeta {
|
||||
font-size: 11px;
|
||||
color: var(--text-muted);
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
/* Group cards grid */
|
||||
.groupGrid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
@@ -19,115 +82,131 @@
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* GroupCard meta strip */
|
||||
.groupGridSingle {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 14px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* Group meta row */
|
||||
.groupMeta {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
gap: 16px;
|
||||
font-size: 11px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.groupMeta strong {
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/* Instance table */
|
||||
.instanceTable {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.instanceTable thead tr {
|
||||
border-bottom: 1px solid var(--border-subtle);
|
||||
}
|
||||
|
||||
.instanceTable thead th {
|
||||
padding: 6px 8px;
|
||||
text-align: left;
|
||||
font-size: 11px;
|
||||
font-family: var(--font-mono);
|
||||
color: var(--text-secondary);
|
||||
font-weight: 600;
|
||||
color: var(--text-muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.thStatus {
|
||||
width: 24px;
|
||||
/* Alert banner in group footer */
|
||||
.alertBanner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 16px;
|
||||
background: var(--error-bg);
|
||||
font-size: 11px;
|
||||
color: var(--error);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.tdStatus {
|
||||
width: 24px;
|
||||
padding: 0 4px 0 8px;
|
||||
}
|
||||
|
||||
.instanceRow {
|
||||
cursor: pointer;
|
||||
transition: background 0.1s;
|
||||
border-bottom: 1px solid var(--border-subtle);
|
||||
}
|
||||
|
||||
.instanceRow:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.instanceRow:hover {
|
||||
background: var(--bg-hover);
|
||||
}
|
||||
|
||||
.instanceRow td {
|
||||
padding: 7px 8px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.instanceRowActive {
|
||||
background: var(--bg-selected, var(--bg-hover));
|
||||
.alertIcon {
|
||||
font-size: 14px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Instance fields */
|
||||
.instanceName {
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.instanceMeta {
|
||||
font-size: 11px;
|
||||
color: var(--text-muted);
|
||||
font-family: var(--font-mono);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.instanceError {
|
||||
font-size: 11px;
|
||||
color: var(--error);
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
.instanceHeartbeatDead {
|
||||
font-size: 11px;
|
||||
color: var(--error);
|
||||
font-family: var(--font-mono);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.instanceHeartbeatStale {
|
||||
font-size: 11px;
|
||||
color: var(--warning);
|
||||
font-family: var(--font-mono);
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.instanceLink {
|
||||
.instanceHeartbeatDead {
|
||||
color: var(--error);
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Detail panel content */
|
||||
.detailContent {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.detailRow {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: 12px;
|
||||
font-family: var(--font-body);
|
||||
padding: 4px 0;
|
||||
border-bottom: 1px solid var(--border-subtle);
|
||||
}
|
||||
|
||||
.detailLabel {
|
||||
color: var(--text-muted);
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
padding: 4px;
|
||||
margin-left: auto;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.instanceLink:hover {
|
||||
color: var(--text-primary);
|
||||
.detailProgress {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
width: 140px;
|
||||
}
|
||||
|
||||
.chartPanel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.chartTitle {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: var(--text-secondary);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.emptyChart {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 80px;
|
||||
background: var(--bg-surface-raised);
|
||||
border: 1px dashed var(--border-subtle);
|
||||
border-radius: var(--radius-md);
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
/* Event card (timeline panel) */
|
||||
.eventCard {
|
||||
margin-top: 20px;
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border-subtle);
|
||||
border-radius: var(--radius-lg);
|
||||
@@ -144,136 +223,4 @@
|
||||
justify-content: space-between;
|
||||
padding: 10px 16px;
|
||||
border-bottom: 1px solid var(--border-subtle);
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/* DetailPanel: Overview tab */
|
||||
|
||||
.overviewContent {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.overviewRow {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.detailList {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.detailRow {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
padding: 6px 0;
|
||||
border-bottom: 1px solid var(--border-subtle);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.detailRow:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.detailRow dt {
|
||||
color: var(--text-muted);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.detailRow dd {
|
||||
margin: 0;
|
||||
color: var(--text-primary);
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.metricsSection {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.metricLabel {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: var(--text-muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
/* DetailPanel: Performance tab */
|
||||
|
||||
.performanceContent {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.chartSection {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.chartLabel {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: var(--text-muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.emptyChart {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 80px;
|
||||
background: var(--bg-surface-raised);
|
||||
border: 1px dashed var(--border-subtle);
|
||||
border-radius: var(--radius-md);
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
/* Status breakdown in stat card */
|
||||
.statusBreakdown {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.statusLive { color: var(--success); }
|
||||
.statusStale { color: var(--warning); }
|
||||
.statusDead { color: var(--error); }
|
||||
|
||||
/* Scope trail */
|
||||
.scopeLabel {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
/* DetailPanel override */
|
||||
.detailPanelOverride {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
height: 100vh;
|
||||
z-index: 100;
|
||||
box-shadow: -4px 0 24px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.panelDivider {
|
||||
border-top: 1px solid var(--border-subtle);
|
||||
margin: 16px 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user