feat: unify operations health rail
This commit is contained in:
@@ -223,8 +223,9 @@ test('reconciles service identities with bound and identity-required vehicles',
|
|||||||
expect(screen.getByText('全部协议达到当前口径')).toBeInTheDocument();
|
expect(screen.getByText('全部协议达到当前口径')).toBeInTheDocument();
|
||||||
expect(screen.getByText('已绑定 1024 · 待绑定 11')).toBeInTheDocument();
|
expect(screen.getByText('已绑定 1024 · 待绑定 11')).toBeInTheDocument();
|
||||||
expect(screen.getByRole('heading', { name: '运行概览', level: 5 })).toBeInTheDocument();
|
expect(screen.getByRole('heading', { name: '运行概览', level: 5 })).toBeInTheDocument();
|
||||||
expect(screen.getByText('车辆总数 / 在线').closest('.v2-ops-metric')).toBeInTheDocument();
|
expect(screen.getByText('车辆总数 / 在线').closest('[role="listitem"]')).toHaveClass('is-secondary');
|
||||||
expect(screen.getByRole('list', { name: '运行健康指标' })).toHaveClass('v2-ops-metric-rail');
|
expect(screen.getByRole('list', { name: '运行健康指标' })).toHaveClass('v2-workspace-metric-list');
|
||||||
|
expect(screen.getByText('Kafka Lag').closest('.v2-workspace-metric-context')).toHaveClass('v2-workspace-metric-context');
|
||||||
expect(screen.getByText('全部正常')).toBeInTheDocument();
|
expect(screen.getByText('全部正常')).toBeInTheDocument();
|
||||||
expect(screen.getByText('运行时安全').closest('.semi-card')).toHaveClass('v2-ops-runtime');
|
expect(screen.getByText('运行时安全').closest('.semi-card')).toHaveClass('v2-ops-runtime');
|
||||||
expect(screen.getByText('协议来源就绪度').closest('.semi-card')).toHaveClass('v2-ops-sources');
|
expect(screen.getByText('协议来源就绪度').closest('.semi-card')).toHaveClass('v2-ops-sources');
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { SegmentedTabs } from '../shared/SegmentedTabs';
|
|||||||
import { VehicleCandidateList } from '../shared/VehicleCandidateList';
|
import { VehicleCandidateList } from '../shared/VehicleCandidateList';
|
||||||
import { WorkspaceCommandBar } from '../shared/WorkspaceCommandBar';
|
import { WorkspaceCommandBar } from '../shared/WorkspaceCommandBar';
|
||||||
import { WorkspaceFilterPanel } from '../shared/WorkspaceFilterPanel';
|
import { WorkspaceFilterPanel } from '../shared/WorkspaceFilterPanel';
|
||||||
|
import { WorkspaceMetricRail, type WorkspaceQueueMetricRailItem } from '../shared/WorkspaceMetricRail';
|
||||||
import { WorkspacePanelHeader } from '../shared/WorkspacePanelHeader';
|
import { WorkspacePanelHeader } from '../shared/WorkspacePanelHeader';
|
||||||
import { WorkspaceSideSheet } from '../shared/WorkspaceSideSheet';
|
import { WorkspaceSideSheet } from '../shared/WorkspaceSideSheet';
|
||||||
import { LIVE_QUERY_POLICY, QUERY_MEMORY } from '../queryPolicy';
|
import { LIVE_QUERY_POLICY, QUERY_MEMORY } from '../queryPolicy';
|
||||||
@@ -49,19 +50,6 @@ function number(value?: number, digits = 1) {
|
|||||||
return value == null || !Number.isFinite(value) ? '—' : value.toLocaleString('zh-CN', { maximumFractionDigits: digits });
|
return value == null || !Number.isFinite(value) ? '—' : value.toLocaleString('zh-CN', { maximumFractionDigits: digits });
|
||||||
}
|
}
|
||||||
|
|
||||||
function OpsMetric({ label, value, detail, tone = 'neutral' }: {
|
|
||||||
label: string;
|
|
||||||
value: string;
|
|
||||||
detail: string;
|
|
||||||
tone?: 'neutral' | 'success' | 'warning' | 'danger';
|
|
||||||
}) {
|
|
||||||
return <article className={`v2-ops-metric is-${tone}`} role="listitem">
|
|
||||||
<small>{label}</small>
|
|
||||||
<strong>{value}</strong>
|
|
||||||
<span>{detail}</span>
|
|
||||||
</article>;
|
|
||||||
}
|
|
||||||
|
|
||||||
function sourceOnlineRate(online: number, total: number, onlineRate?: number) {
|
function sourceOnlineRate(online: number, total: number, onlineRate?: number) {
|
||||||
if (onlineRate != null && Number.isFinite(onlineRate)) return Math.max(0, Math.min(100, onlineRate));
|
if (onlineRate != null && Number.isFinite(onlineRate)) return Math.max(0, Math.min(100, onlineRate));
|
||||||
return total > 0 ? Math.max(0, Math.min(100, (online / total) * 100)) : 0;
|
return total > 0 ? Math.max(0, Math.min(100, (online / total) * 100)) : 0;
|
||||||
@@ -457,6 +445,34 @@ export default function OperationsPage() {
|
|||||||
: healthIssueCount > 0
|
: healthIssueCount > 0
|
||||||
? `协议覆盖 ${sourceIssueCount} 项 · 链路运行 ${infrastructureIssueCount} 项`
|
? `协议覆盖 ${sourceIssueCount} 项 · 链路运行 ${infrastructureIssueCount} 项`
|
||||||
: '链路、写入与协议覆盖均正常';
|
: '链路、写入与协议覆盖均正常';
|
||||||
|
const healthMetrics: WorkspaceQueueMetricRailItem[] = [
|
||||||
|
{
|
||||||
|
label: '整体状态',
|
||||||
|
value: overallValue,
|
||||||
|
note: overallDetail,
|
||||||
|
tone: healthEvidencePending ? 'neutral' : readinessUnavailable || sourceErrorCount > 0 ? 'danger' : healthIssueCount > 0 ? 'warning' : 'success',
|
||||||
|
emphasis: 'primary'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '协议就绪 / 总数',
|
||||||
|
value: sources?.sources.length ? `${sourceHealthyCount} / ${sources.sources.length}` : readinessUnavailable ? '不可用' : '—',
|
||||||
|
note: readinessUnavailable ? '来源证据读取失败' : sourceIssueCount > 0 ? `${sourceIssueCount} 个协议需要处置` : sources?.sources.length ? '全部协议达到当前口径' : '等待协议覆盖证据',
|
||||||
|
tone: readinessUnavailable || sourceErrorCount > 0 ? 'danger' : sourceIssueCount > 0 ? 'warning' : sources?.sources.length ? 'success' : 'neutral',
|
||||||
|
emphasis: 'primary'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '车辆总数 / 在线',
|
||||||
|
value: sources ? `${sources.totalVehicles} / ${sources.onlineVehicles}` : '—',
|
||||||
|
note: sources ? `已绑定 ${sources.boundVehicles} · 待绑定 ${sources.identityRequiredVehicles}` : '档案与快照并集',
|
||||||
|
emphasis: 'secondary'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '活跃连接',
|
||||||
|
value: data?.activeConnections?.toLocaleString('zh-CN') ?? '—',
|
||||||
|
note: '网关实时连接',
|
||||||
|
emphasis: 'secondary'
|
||||||
|
}
|
||||||
|
];
|
||||||
const sortedLinks = useMemo(() => [...(data?.linkHealth ?? [])].sort((left, right) => {
|
const sortedLinks = useMemo(() => [...(data?.linkHealth ?? [])].sort((left, right) => {
|
||||||
const priority = { error: 0, warning: 1, ok: 2 } as Record<string, number>;
|
const priority = { error: 0, warning: 1, ok: 2 } as Record<string, number>;
|
||||||
return (priority[left.status] ?? 3) - (priority[right.status] ?? 3);
|
return (priority[left.status] ?? 3) - (priority[right.status] ?? 3);
|
||||||
@@ -519,18 +535,17 @@ export default function OperationsPage() {
|
|||||||
description="关键链路、基础设施与车辆覆盖的同一健康快照"
|
description="关键链路、基础设施与车辆覆盖的同一健康快照"
|
||||||
meta={<span className="v2-ops-overview-meta"><HealthTag status={overallStatus}>{!data ? '正在读取' : healthIssueCount > 0 ? `${healthIssueCount} 项需关注` : '全部正常'}</HealthTag><Typography.Text type="tertiary">15 秒自动刷新</Typography.Text></span>}
|
meta={<span className="v2-ops-overview-meta"><HealthTag status={overallStatus}>{!data ? '正在读取' : healthIssueCount > 0 ? `${healthIssueCount} 项需关注` : '全部正常'}</HealthTag><Typography.Text type="tertiary">15 秒自动刷新</Typography.Text></span>}
|
||||||
/>
|
/>
|
||||||
<section className="v2-ops-metric-rail" role="list" aria-label="运行健康指标">
|
<WorkspaceMetricRail
|
||||||
<OpsMetric label="整体状态" value={overallValue} detail={overallDetail} tone={healthEvidencePending ? 'neutral' : readinessUnavailable || sourceErrorCount > 0 ? 'danger' : healthIssueCount > 0 ? 'warning' : 'success'} />
|
variant="queue"
|
||||||
<OpsMetric
|
className="v2-ops-health-metric-rail"
|
||||||
label="协议就绪 / 总数"
|
ariaLabel="运行健康指标"
|
||||||
value={sources?.sources.length ? `${sourceHealthyCount} / ${sources.sources.length}` : readinessUnavailable ? '不可用' : '—'}
|
items={healthMetrics}
|
||||||
detail={readinessUnavailable ? '来源证据读取失败' : sourceIssueCount > 0 ? `${sourceIssueCount} 个协议需要处置` : sources?.sources.length ? '全部协议达到当前口径' : '等待协议覆盖证据'}
|
context={<span className={`v2-ops-health-kafka${data?.kafkaLag === 0 ? ' is-ok' : data ? ' is-warning' : ''}`}>
|
||||||
tone={readinessUnavailable || sourceErrorCount > 0 ? 'danger' : sourceIssueCount > 0 ? 'warning' : sources?.sources.length ? 'success' : 'neutral'}
|
<small>Kafka Lag</small>
|
||||||
|
<strong>{data?.kafkaLag?.toLocaleString('zh-CN') ?? '—'}</strong>
|
||||||
|
<em>{data?.kafkaLag === 0 ? '消费积压已回零' : data ? '存在待消费消息' : '等待消费证据'}</em>
|
||||||
|
</span>}
|
||||||
/>
|
/>
|
||||||
<OpsMetric label="车辆总数 / 在线" value={sources ? `${sources.totalVehicles} / ${sources.onlineVehicles}` : '—'} detail={sources ? `已绑定 ${sources.boundVehicles} · 待绑定 ${sources.identityRequiredVehicles}` : '档案与快照并集'} />
|
|
||||||
<OpsMetric label="活跃连接" value={data?.activeConnections?.toLocaleString('zh-CN') ?? '—'} detail="网关实时连接" />
|
|
||||||
<OpsMetric label="Kafka Lag" value={data?.kafkaLag?.toLocaleString('zh-CN') ?? '—'} detail={data?.kafkaLag === 0 ? '消费积压已回零' : data ? '存在待消费消息' : '等待消费证据'} tone={data?.kafkaLag === 0 ? 'success' : data ? 'warning' : 'neutral'} />
|
|
||||||
</section>
|
|
||||||
</Card>
|
</Card>
|
||||||
<Card className={`v2-ops-panel v2-ops-sources${sourceIssueCount || readinessUnavailable ? ' has-attention' : ''}`} bodyStyle={{ padding: 0 }}><WorkspacePanelHeader title="协议来源就绪度" description="优先展示覆盖不足的协议,并给出处置动作与验收口径" meta={<HealthTag status={readinessUnavailable ? 'error' : sourceIssueCount > 0 ? 'warning' : sources ? 'ok' : 'unknown'}>{readinessUnavailable ? '证据不可用' : sources ? sourceIssueCount > 0 ? `${sourceIssueCount} 个协议需关注` : `${sources.sources.length} 个协议正常` : '正在读取'}</HealthTag>} />{sources ? sortedSources.length ? <CardGroup className="v2-ops-source-list" type="grid" spacing={0}>{sortedSources.map((source) => {
|
<Card className={`v2-ops-panel v2-ops-sources${sourceIssueCount || readinessUnavailable ? ' has-attention' : ''}`} bodyStyle={{ padding: 0 }}><WorkspacePanelHeader title="协议来源就绪度" description="优先展示覆盖不足的协议,并给出处置动作与验收口径" meta={<HealthTag status={readinessUnavailable ? 'error' : sourceIssueCount > 0 ? 'warning' : sources ? 'ok' : 'unknown'}>{readinessUnavailable ? '证据不可用' : sources ? sourceIssueCount > 0 ? `${sourceIssueCount} 个协议需关注` : `${sources.sources.length} 个协议正常` : '正在读取'}</HealthTag>} />{sources ? sortedSources.length ? <CardGroup className="v2-ops-source-list" type="grid" spacing={0}>{sortedSources.map((source) => {
|
||||||
const onlineRate = sourceOnlineRate(source.online, source.total, source.onlineRate);
|
const onlineRate = sourceOnlineRate(source.online, source.total, source.onlineRate);
|
||||||
|
|||||||
@@ -322,15 +322,17 @@ describe('V2 production entry', () => {
|
|||||||
expect(workspaceStyles).toContain('grid-template-columns: repeat(2, minmax(0, 1fr));');
|
expect(workspaceStyles).toContain('grid-template-columns: repeat(2, minmax(0, 1fr));');
|
||||||
expect(workspaceStyles).toContain('Short landscape operations cockpit.');
|
expect(workspaceStyles).toContain('Short landscape operations cockpit.');
|
||||||
expect(workspaceStyles).toContain('grid-template-columns: minmax(196px, .42fr) minmax(0, 1fr);');
|
expect(workspaceStyles).toContain('grid-template-columns: minmax(196px, .42fr) minmax(0, 1fr);');
|
||||||
expect(workspaceStyles).toContain('.v2-ops-workspace.is-health .v2-ops-metric-rail {');
|
expect(workspaceStyles).toContain('.v2-ops-health-metric-rail.is-queue > .semi-card-body {');
|
||||||
expect(workspaceStyles).toContain('grid-template-columns: 1.12fr repeat(4, minmax(0, 1fr));');
|
expect(workspaceStyles).toContain('grid-template-columns: minmax(0, 1fr) 196px;');
|
||||||
expect(workspaceStyles).toContain('.v2-ops-workspace.is-diagnostic {');
|
expect(workspaceStyles).toContain('.v2-ops-workspace.is-diagnostic {');
|
||||||
expect(workspaceStyles).toContain('grid-template-columns: minmax(176px, .34fr) minmax(0, 1fr);');
|
expect(workspaceStyles).toContain('grid-template-columns: minmax(176px, .34fr) minmax(0, 1fr);');
|
||||||
expect(corePageSources.OperationsPage).toContain('<Checkbox');
|
expect(corePageSources.OperationsPage).toContain('<Checkbox');
|
||||||
expect(corePageSources.OperationsPage).toContain('<Input');
|
expect(corePageSources.OperationsPage).toContain('<Input');
|
||||||
expect(corePageSources.OperationsPage).toContain('<Card className="v2-source-diagnostic"');
|
expect(corePageSources.OperationsPage).toContain('<Card className="v2-source-diagnostic"');
|
||||||
expect(corePageSources.OperationsPage).toContain('<Card className="v2-ops-overview"');
|
expect(corePageSources.OperationsPage).toContain('<Card className="v2-ops-overview"');
|
||||||
expect(corePageSources.OperationsPage).toContain('<OpsMetric');
|
expect(corePageSources.OperationsPage).toContain("from '../shared/WorkspaceMetricRail'");
|
||||||
|
expect(corePageSources.OperationsPage).toContain('<WorkspaceMetricRail');
|
||||||
|
expect(corePageSources.OperationsPage).not.toContain('<OpsMetric');
|
||||||
expect(corePageSources.OperationsPage).toContain('<Card className="v2-ops-panel v2-ops-links"');
|
expect(corePageSources.OperationsPage).toContain('<Card className="v2-ops-panel v2-ops-links"');
|
||||||
expect(corePageSources.OperationsPage).toContain('<article className={`v2-ops-link-card');
|
expect(corePageSources.OperationsPage).toContain('<article className={`v2-ops-link-card');
|
||||||
expect(corePageSources.OperationsPage).not.toContain('<Card className={`v2-ops-link-card');
|
expect(corePageSources.OperationsPage).not.toContain('<Card className={`v2-ops-link-card');
|
||||||
@@ -578,6 +580,8 @@ describe('V2 production entry', () => {
|
|||||||
expect(corePageSources.AccessPage).toContain('<WorkspaceMetricRail');
|
expect(corePageSources.AccessPage).toContain('<WorkspaceMetricRail');
|
||||||
expect(corePageSources.AlertsPage).toContain("from '../shared/WorkspaceMetricRail'");
|
expect(corePageSources.AlertsPage).toContain("from '../shared/WorkspaceMetricRail'");
|
||||||
expect(corePageSources.AlertsPage).toContain('<WorkspaceMetricRail');
|
expect(corePageSources.AlertsPage).toContain('<WorkspaceMetricRail');
|
||||||
|
expect(corePageSources.OperationsPage).toContain("from '../shared/WorkspaceMetricRail'");
|
||||||
|
expect(corePageSources.OperationsPage).toContain('<WorkspaceMetricRail');
|
||||||
expect(corePageSources.HistoryPage).toContain('className="v2-history-result-meta"');
|
expect(corePageSources.HistoryPage).toContain('className="v2-history-result-meta"');
|
||||||
expect(corePageSources.AlertsPage).toContain('<Tag className={`v2-alert-severity');
|
expect(corePageSources.AlertsPage).toContain('<Tag className={`v2-alert-severity');
|
||||||
expect(corePageSources.AlertsPage).toContain('<Tag className={`v2-alert-status');
|
expect(corePageSources.AlertsPage).toContain('<Tag className={`v2-alert-status');
|
||||||
|
|||||||
@@ -937,52 +937,6 @@
|
|||||||
font-size: 8px;
|
font-size: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric-rail {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1.12fr repeat(4, minmax(0, 1fr));
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric,
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric:first-child {
|
|
||||||
min-width: 0;
|
|
||||||
min-height: 78px;
|
|
||||||
grid-column: auto;
|
|
||||||
border-top: 0;
|
|
||||||
border-right: 0;
|
|
||||||
border-left: 1px solid #e7edf4;
|
|
||||||
padding: 8px 9px 7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric:first-child {
|
|
||||||
border-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric small {
|
|
||||||
font-size: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric strong,
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric:first-child strong {
|
|
||||||
margin: 6px 0 5px;
|
|
||||||
font-size: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric:first-child strong {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric span {
|
|
||||||
font-size: 8px;
|
|
||||||
line-height: 1.3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric::after {
|
|
||||||
right: 9px;
|
|
||||||
left: 9px;
|
|
||||||
height: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-source-list.semi-card-group {
|
.v2-ops-workspace.is-health .v2-ops-source-list.semi-card-group {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
@@ -5293,75 +5247,6 @@
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.v2-ops-metric-rail {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1.2fr repeat(4, minmax(0, 1fr));
|
|
||||||
background: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-metric {
|
|
||||||
position: relative;
|
|
||||||
min-width: 0;
|
|
||||||
min-height: 112px;
|
|
||||||
padding: 17px 18px 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-metric + .v2-ops-metric {
|
|
||||||
border-left: 1px solid #e7edf4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-metric::after {
|
|
||||||
position: absolute;
|
|
||||||
right: 18px;
|
|
||||||
bottom: 0;
|
|
||||||
left: 18px;
|
|
||||||
height: 3px;
|
|
||||||
border-radius: 999px 999px 0 0;
|
|
||||||
background: #dce5ef;
|
|
||||||
content: "";
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-metric.is-success::after { background: var(--v2-green); }
|
|
||||||
.v2-ops-metric.is-warning::after { background: var(--v2-orange); }
|
|
||||||
.v2-ops-metric.is-danger::after { background: var(--v2-red); }
|
|
||||||
|
|
||||||
.v2-ops-metric small {
|
|
||||||
display: block;
|
|
||||||
overflow: hidden;
|
|
||||||
color: #6b7c92;
|
|
||||||
font-size: 11px;
|
|
||||||
font-weight: 600;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-metric strong {
|
|
||||||
display: block;
|
|
||||||
margin: 10px 0 8px;
|
|
||||||
overflow: hidden;
|
|
||||||
color: #20364f;
|
|
||||||
font-size: 24px;
|
|
||||||
font-variant-numeric: tabular-nums;
|
|
||||||
letter-spacing: -.025em;
|
|
||||||
line-height: 1;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-metric.is-success strong { color: #16835d; }
|
|
||||||
.v2-ops-metric.is-warning strong { color: #a66500; }
|
|
||||||
.v2-ops-metric.is-danger strong { color: #cf3f3b; }
|
|
||||||
|
|
||||||
.v2-ops-metric span {
|
|
||||||
display: block;
|
|
||||||
overflow: hidden;
|
|
||||||
color: #8390a2;
|
|
||||||
font-size: 10px;
|
|
||||||
line-height: 1.45;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-panel > .semi-card-body > .v2-workspace-panel-header {
|
.v2-ops-panel > .semi-card-body > .v2-workspace-panel-header {
|
||||||
min-height: 64px;
|
min-height: 64px;
|
||||||
border-bottom: 1px solid #e7edf4;
|
border-bottom: 1px solid #e7edf4;
|
||||||
@@ -5430,26 +5315,6 @@
|
|||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 900px) {
|
|
||||||
.v2-ops-metric-rail {
|
|
||||||
display: flex;
|
|
||||||
overflow-x: auto;
|
|
||||||
scroll-snap-type: x proximity;
|
|
||||||
scrollbar-width: thin;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-metric {
|
|
||||||
min-width: 190px;
|
|
||||||
flex: 0 0 190px;
|
|
||||||
scroll-snap-align: start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-metric:first-child {
|
|
||||||
min-width: 218px;
|
|
||||||
flex-basis: 218px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 680px) {
|
@media (max-width: 680px) {
|
||||||
.v2-ops-overview > .semi-card-body > .v2-workspace-panel-header {
|
.v2-ops-overview > .semi-card-body > .v2-workspace-panel-header {
|
||||||
min-height: 58px;
|
min-height: 58px;
|
||||||
@@ -5458,25 +5323,6 @@
|
|||||||
|
|
||||||
.v2-ops-overview-meta > .semi-typography { display: none; }
|
.v2-ops-overview-meta > .semi-typography { display: none; }
|
||||||
|
|
||||||
.v2-ops-metric {
|
|
||||||
min-width: 156px;
|
|
||||||
min-height: 96px;
|
|
||||||
flex-basis: 156px;
|
|
||||||
padding: 14px 13px 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-metric:first-child {
|
|
||||||
min-width: 184px;
|
|
||||||
flex-basis: 184px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-metric strong {
|
|
||||||
margin: 8px 0 7px;
|
|
||||||
font-size: 21px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-metric span { font-size: 10px; }
|
|
||||||
|
|
||||||
.v2-ops-link-card {
|
.v2-ops-link-card {
|
||||||
min-height: 72px;
|
min-height: 72px;
|
||||||
grid-template-columns: minmax(0, 1fr) auto;
|
grid-template-columns: minmax(0, 1fr) auto;
|
||||||
@@ -14595,21 +14441,6 @@
|
|||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.v2-ops-metric {
|
|
||||||
min-height: 100px;
|
|
||||||
padding: 14px 16px 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-metric::after {
|
|
||||||
right: 16px;
|
|
||||||
left: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-metric strong {
|
|
||||||
margin: 8px 0 7px;
|
|
||||||
font-size: 22px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-workspace.is-diagnostic {
|
.v2-ops-workspace.is-diagnostic {
|
||||||
display: flex;
|
display: flex;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
@@ -14724,49 +14555,6 @@
|
|||||||
min-height: 260px;
|
min-height: 260px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric-rail {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
||||||
overflow: visible;
|
|
||||||
scroll-snap-type: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric {
|
|
||||||
min-width: 0;
|
|
||||||
min-height: 78px;
|
|
||||||
flex: none;
|
|
||||||
border-top: 1px solid #e7edf4;
|
|
||||||
border-left: 0;
|
|
||||||
padding: 11px 12px 10px;
|
|
||||||
scroll-snap-align: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric:first-child {
|
|
||||||
min-width: 0;
|
|
||||||
min-height: 88px;
|
|
||||||
grid-column: 1 / -1;
|
|
||||||
border-top: 0;
|
|
||||||
padding-inline: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric:nth-child(even) {
|
|
||||||
border-right: 1px solid #e7edf4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric strong {
|
|
||||||
margin: 6px 0 5px;
|
|
||||||
font-size: 19px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric:first-child strong {
|
|
||||||
font-size: 22px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric::after {
|
|
||||||
right: 12px;
|
|
||||||
left: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-links .v2-ops-link-card {
|
.v2-ops-links .v2-ops-link-card {
|
||||||
min-height: 58px;
|
min-height: 58px;
|
||||||
grid-template-columns: minmax(0, 1fr) auto;
|
grid-template-columns: minmax(0, 1fr) auto;
|
||||||
@@ -14809,9 +14597,6 @@
|
|||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.v2-ops-metric {
|
|
||||||
min-height: 94px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -16443,6 +16228,35 @@
|
|||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.v2-ops-health-metric-rail.is-queue.semi-card {
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-health-metric-rail.is-queue > .semi-card-body {
|
||||||
|
grid-template-columns: minmax(0, 1fr) 196px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-health-metric-rail .v2-workspace-metric-list {
|
||||||
|
grid-template-columns: 1.25fr 1.05fr 1fr .9fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-health-metric-rail .v2-workspace-metric-list > span.is-primary.is-warning {
|
||||||
|
background: linear-gradient(145deg, #fff8ed 0%, #fffdf8 100%);
|
||||||
|
box-shadow: inset 0 -3px #e59a2f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-health-metric-rail .v2-workspace-metric-list > span.is-primary.is-warning > :is(small, strong) {
|
||||||
|
color: #9d5d0b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-health-kafka.is-ok strong {
|
||||||
|
color: #148459;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-health-kafka.is-warning strong {
|
||||||
|
color: #a76512;
|
||||||
|
}
|
||||||
|
|
||||||
.v2-reconcile-metric-rail {
|
.v2-reconcile-metric-rail {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
}
|
}
|
||||||
@@ -16474,6 +16288,27 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 900px) and (max-height: 480px) and (orientation: landscape) {
|
||||||
|
.v2-ops-health-metric-rail.is-queue > .semi-card-body {
|
||||||
|
min-height: 48px;
|
||||||
|
grid-template-columns: minmax(0, 1fr) 142px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-health-metric-rail .v2-workspace-metric-list > span {
|
||||||
|
min-height: 48px;
|
||||||
|
padding-block: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-health-metric-rail .v2-workspace-metric-list > span > strong {
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-ops-health-metric-rail .v2-workspace-metric-list > span > em {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 680px) {
|
@media (max-width: 680px) {
|
||||||
.v2-workspace-metric-rail.is-queue > .semi-card-body {
|
.v2-workspace-metric-rail.is-queue > .semi-card-body {
|
||||||
min-height: 56px;
|
min-height: 56px;
|
||||||
@@ -20418,52 +20253,6 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric-rail {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1.12fr repeat(4, minmax(0, 1fr));
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric,
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric:first-child {
|
|
||||||
min-width: 0;
|
|
||||||
min-height: 78px;
|
|
||||||
grid-column: auto;
|
|
||||||
border-top: 0;
|
|
||||||
border-right: 0;
|
|
||||||
border-left: 1px solid #e7edf4;
|
|
||||||
padding: 8px 9px 7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric:first-child {
|
|
||||||
border-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric small {
|
|
||||||
font-size: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric strong,
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric:first-child strong {
|
|
||||||
margin: 6px 0 5px;
|
|
||||||
font-size: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric:first-child strong {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric span {
|
|
||||||
font-size: 8px;
|
|
||||||
line-height: 1.3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-workspace.is-health .v2-ops-metric::after {
|
|
||||||
right: 9px;
|
|
||||||
left: 9px;
|
|
||||||
height: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v2-ops-workspace.is-diagnostic {
|
.v2-ops-workspace.is-diagnostic {
|
||||||
display: grid;
|
display: grid;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user