feat: focus operations review queue
This commit is contained in:
@@ -82,9 +82,14 @@ test('renders reconciliation queue, loads evidence on demand and records review
|
|||||||
expect(screen.queryByText('先选择一辆车')).not.toBeInTheDocument();
|
expect(screen.queryByText('先选择一辆车')).not.toBeInTheDocument();
|
||||||
expect(screen.getByText('质量问题队列').closest('.semi-card')).toHaveClass('v2-reconcile-center');
|
expect(screen.getByText('质量问题队列').closest('.semi-card')).toHaveClass('v2-reconcile-center');
|
||||||
expect(screen.getByText('质量问题队列').closest('.v2-workspace-panel-header')).toHaveClass('v2-reconcile-heading');
|
expect(screen.getByText('质量问题队列').closest('.v2-workspace-panel-header')).toHaveClass('v2-reconcile-heading');
|
||||||
expect(document.querySelector('.v2-reconcile-kpi-card small')?.textContent).toBe('待复核');
|
const reconciliationMetrics = screen.getByRole('list', { name: '差异处置队列概览' });
|
||||||
expect(document.querySelectorAll('.v2-reconcile-kpi-card')).toHaveLength(4);
|
expect(reconciliationMetrics.closest('.semi-card')).toHaveClass('v2-workspace-metric-rail', 'v2-reconcile-metric-rail');
|
||||||
expect(screen.getByText('SLA 超时').closest('.semi-card')).toHaveClass('v2-reconcile-kpi-card', 'is-sla', 'is-overdue');
|
expect(within(reconciliationMetrics).getAllByRole('listitem')).toHaveLength(4);
|
||||||
|
expect(within(reconciliationMetrics).getByText('待复核').closest('[role="listitem"]')).toHaveClass('is-primary');
|
||||||
|
expect(within(reconciliationMetrics).getByText('SLA 超时').closest('[role="listitem"]')).toHaveClass('is-danger');
|
||||||
|
expect(within(reconciliationMetrics).getByText('已自动恢复').closest('[role="listitem"]')).toHaveClass('is-secondary', 'is-success');
|
||||||
|
expect(screen.getByText('当前筛选').closest('.v2-workspace-metric-context')).toHaveTextContent('1');
|
||||||
|
expect(document.querySelectorAll('.v2-reconcile-kpi-card')).toHaveLength(0);
|
||||||
expect(screen.queryByText('活跃问题', { exact: true })).not.toBeInTheDocument();
|
expect(screen.queryByText('活跃问题', { exact: true })).not.toBeInTheDocument();
|
||||||
expect(screen.queryByText('近 30 天趋势')).not.toBeInTheDocument();
|
expect(screen.queryByText('近 30 天趋势')).not.toBeInTheDocument();
|
||||||
const trendButton = screen.getByRole('button', { name: '30 天趋势' });
|
const trendButton = screen.getByRole('button', { name: '30 天趋势' });
|
||||||
@@ -169,6 +174,7 @@ test('renders only the compact mobile reconciliation surface and defers secondar
|
|||||||
|
|
||||||
const toolbar = document.querySelector('.v2-reconcile-toolbar');
|
const toolbar = document.querySelector('.v2-reconcile-toolbar');
|
||||||
expect(toolbar).toHaveClass('is-mobile-collapsed');
|
expect(toolbar).toHaveClass('is-mobile-collapsed');
|
||||||
|
expect(screen.getByRole('button', { name: /修改筛选差异:活跃差异 · 1 条/ })).toBeInTheDocument();
|
||||||
fireEvent.click(screen.getByRole('button', { name: /修改筛选差异/ }));
|
fireEvent.click(screen.getByRole('button', { name: /修改筛选差异/ }));
|
||||||
expect(toolbar).not.toHaveClass('is-mobile-collapsed');
|
expect(toolbar).not.toHaveClass('is-mobile-collapsed');
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { InlineError } from '../shared/AsyncState';
|
|||||||
import { MobileFilterToggle } from '../shared/MobileFilterToggle';
|
import { MobileFilterToggle } from '../shared/MobileFilterToggle';
|
||||||
import { PlatformTime } from '../shared/PlatformTime';
|
import { PlatformTime } from '../shared/PlatformTime';
|
||||||
import { TablePagination } from '../shared/TablePagination';
|
import { TablePagination } from '../shared/TablePagination';
|
||||||
|
import { WorkspaceMetricRail } from '../shared/WorkspaceMetricRail';
|
||||||
import { WorkspacePanelHeader } from '../shared/WorkspacePanelHeader';
|
import { WorkspacePanelHeader } from '../shared/WorkspacePanelHeader';
|
||||||
import { WorkspaceSideSheet } from '../shared/WorkspaceSideSheet';
|
import { WorkspaceSideSheet } from '../shared/WorkspaceSideSheet';
|
||||||
import { detailTriggerRow } from '../shared/detailTriggerRow';
|
import { detailTriggerRow } from '../shared/detailTriggerRow';
|
||||||
@@ -312,7 +313,7 @@ export default function ReconciliationCenter() {
|
|||||||
const totalPages = Math.max(1, Math.ceil((page?.total ?? 0) / pageSize));
|
const totalPages = Math.max(1, Math.ceil((page?.total ?? 0) / pageSize));
|
||||||
const issueRows = page?.items ?? [];
|
const issueRows = page?.items ?? [];
|
||||||
const activeFilterCount = Number(Boolean(deferredKeyword)) + Number(severity !== 'all') + Number(ruleCode !== 'all');
|
const activeFilterCount = Number(Boolean(deferredKeyword)) + Number(severity !== 'all') + Number(ruleCode !== 'all');
|
||||||
const filterSummary = `${status === 'active' ? '活跃差异' : statusLabel(status)}${activeFilterCount ? ` · 另 ${activeFilterCount} 项` : ''}`;
|
const filterSummary = `${status === 'active' ? '活跃差异' : statusLabel(status)} · ${(page?.total ?? 0).toLocaleString('zh-CN')} 条${activeFilterCount ? ` · 另 ${activeFilterCount} 项` : ''}`;
|
||||||
const selectedIssue = detail.data ?? issueRows.find((item) => item.id === selectedID);
|
const selectedIssue = detail.data ?? issueRows.find((item) => item.id === selectedID);
|
||||||
const detailPanel = selectedID && detail.isPending
|
const detailPanel = selectedID && detail.isPending
|
||||||
? <Card className="v2-reconcile-detail is-sheet" bodyStyle={{ padding: 0 }}><div className="v2-reconcile-detail-loading" role="status"><Spin size="middle" tip="正在读取差异证据…" /></div></Card>
|
? <Card className="v2-reconcile-detail is-sheet" bodyStyle={{ padding: 0 }}><div className="v2-reconcile-detail-loading" role="status"><Spin size="middle" tip="正在读取差异证据…" /></div></Card>
|
||||||
@@ -350,14 +351,39 @@ export default function ReconciliationCenter() {
|
|||||||
</>}
|
</>}
|
||||||
/>
|
/>
|
||||||
{summary.isError ? <InlineError message={summary.error.message} onRetry={() => summary.refetch()} /> : null}
|
{summary.isError ? <InlineError message={summary.error.message} onRetry={() => summary.refetch()} /> : null}
|
||||||
<div className="v2-reconcile-overview">
|
<WorkspaceMetricRail
|
||||||
<div className="v2-reconcile-kpis">
|
variant="queue"
|
||||||
<Card className="v2-reconcile-kpi-card is-priority" bodyStyle={{ padding: 0 }}><small>待复核</small><strong>{data?.pending.toLocaleString('zh-CN') ?? '—'}</strong><span>活跃问题 {data?.active.toLocaleString('zh-CN') ?? '—'}</span></Card>
|
className="v2-reconcile-metric-rail"
|
||||||
<Card className={`v2-reconcile-kpi-card is-sla${data?.overSla ? ' is-overdue' : ''}`} bodyStyle={{ padding: 0 }}><small>SLA 超时</small><strong>{data?.overSla.toLocaleString('zh-CN') ?? '—'}</strong><span>{data?.overSla ? '超过 24 小时,优先复核' : '当前没有超时差异'}</span></Card>
|
ariaLabel="差异处置队列概览"
|
||||||
<Card className="v2-reconcile-kpi-card" bodyStyle={{ padding: 0 }}><small>已确认来源</small><strong>{data?.confirmed.toLocaleString('zh-CN') ?? '—'}</strong><span>保留为活跃差异</span></Card>
|
items={[
|
||||||
<Card className="v2-reconcile-kpi-card" bodyStyle={{ padding: 0 }}><small>已自动恢复</small><strong>{data?.recovered.toLocaleString('zh-CN') ?? '—'}</strong><span>规则已不再命中</span></Card>
|
{
|
||||||
</div>
|
label: '待复核',
|
||||||
</div>
|
value: data?.pending.toLocaleString('zh-CN') ?? '—',
|
||||||
|
note: `活跃 ${data?.active.toLocaleString('zh-CN') ?? '—'} 项`,
|
||||||
|
tone: 'primary'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'SLA 超时',
|
||||||
|
value: data?.overSla.toLocaleString('zh-CN') ?? '—',
|
||||||
|
note: data?.overSla ? '超过 24 小时' : '当前无超时',
|
||||||
|
tone: data?.overSla ? 'danger' : 'success'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '已确认来源',
|
||||||
|
value: data?.confirmed.toLocaleString('zh-CN') ?? '—',
|
||||||
|
note: '保留活跃差异',
|
||||||
|
emphasis: 'secondary'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '已自动恢复',
|
||||||
|
value: data?.recovered.toLocaleString('zh-CN') ?? '—',
|
||||||
|
note: '规则不再命中',
|
||||||
|
tone: 'success',
|
||||||
|
emphasis: 'secondary'
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
context={<span aria-live="polite"><small>当前筛选</small><strong>{(page?.total ?? 0).toLocaleString('zh-CN')}</strong><em>按严重程度、最近发现时间排序</em></span>}
|
||||||
|
/>
|
||||||
<div className="v2-reconcile-layout">
|
<div className="v2-reconcile-layout">
|
||||||
<div className="v2-reconcile-main">
|
<div className="v2-reconcile-main">
|
||||||
<MobileFilterToggle
|
<MobileFilterToggle
|
||||||
@@ -387,10 +413,6 @@ export default function ReconciliationCenter() {
|
|||||||
...(data?.byRule.map((item) => ({ value: item.name, label: `${ruleLabel(item.name)} · ${item.count}` })) ?? [])
|
...(data?.byRule.map((item) => ({ value: item.name, label: `${ruleLabel(item.name)} · ${item.count}` })) ?? [])
|
||||||
]} />
|
]} />
|
||||||
</div>
|
</div>
|
||||||
<div className="v2-reconcile-result-bar" aria-live="polite">
|
|
||||||
<span><strong>{(page?.total ?? 0).toLocaleString('zh-CN')}</strong> 个符合条件的问题</span>
|
|
||||||
<span>按严重程度、最近发现时间排序</span>
|
|
||||||
</div>
|
|
||||||
{issues.isError ? <InlineError message={issues.error.message} onRetry={() => issues.refetch()} /> : null}
|
{issues.isError ? <InlineError message={issues.error.message} onRetry={() => issues.refetch()} /> : null}
|
||||||
<div
|
<div
|
||||||
className="v2-reconcile-table-wrap is-scroll-region"
|
className="v2-reconcile-table-wrap is-scroll-region"
|
||||||
|
|||||||
@@ -462,6 +462,11 @@ describe('V2 production entry', () => {
|
|||||||
expect(workspaceMetricRailSource).toContain("import { Card, CardGroup } from '@douyinfe/semi-ui'");
|
expect(workspaceMetricRailSource).toContain("import { Card, CardGroup } from '@douyinfe/semi-ui'");
|
||||||
expect(workspaceMetricRailSource).toContain('<Card className={className}');
|
expect(workspaceMetricRailSource).toContain('<Card className={className}');
|
||||||
expect(workspaceMetricRailSource).toContain('<CardGroup className={secondaryClassName}');
|
expect(workspaceMetricRailSource).toContain('<CardGroup className={secondaryClassName}');
|
||||||
|
expect(workspaceMetricRailSource).toContain("variant: 'queue'");
|
||||||
|
expect(workspaceMetricRailSource).toContain('className={`v2-workspace-metric-rail is-queue');
|
||||||
|
expect(reconciliationSource).toContain('<WorkspaceMetricRail');
|
||||||
|
expect(reconciliationSource).toContain('variant="queue"');
|
||||||
|
expect(reconciliationSource).not.toContain('v2-reconcile-kpi-card');
|
||||||
expect(corePageSources.MonitorPage).toContain('<Input');
|
expect(corePageSources.MonitorPage).toContain('<Input');
|
||||||
expect(corePageSources.MonitorPage).toContain('<Select');
|
expect(corePageSources.MonitorPage).toContain('<Select');
|
||||||
expect(corePageSources.MonitorPage).toContain('<WorkspaceSideSheet');
|
expect(corePageSources.MonitorPage).toContain('<WorkspaceSideSheet');
|
||||||
@@ -504,7 +509,9 @@ describe('V2 production entry', () => {
|
|||||||
expect(reconciliationSource).toContain('<RadioGroup');
|
expect(reconciliationSource).toContain('<RadioGroup');
|
||||||
expect(reconciliationSource).toContain('<Select');
|
expect(reconciliationSource).toContain('<Select');
|
||||||
expect(reconciliationSource).toContain('<Card className="v2-reconcile-center"');
|
expect(reconciliationSource).toContain('<Card className="v2-reconcile-center"');
|
||||||
expect(reconciliationSource).toContain('<Card className="v2-reconcile-kpi-card');
|
expect(reconciliationSource).toContain('<WorkspaceMetricRail');
|
||||||
|
expect(reconciliationSource).toContain('variant="queue"');
|
||||||
|
expect(reconciliationSource).not.toContain('v2-reconcile-kpi-card');
|
||||||
expect(reconciliationSource).toContain('v2-reconcile-trend');
|
expect(reconciliationSource).toContain('v2-reconcile-trend');
|
||||||
expect(reconciliationSource).toContain('<Card className={`v2-reconcile-detail');
|
expect(reconciliationSource).toContain('<Card className={`v2-reconcile-detail');
|
||||||
expect(reconciliationSource).toContain('<WorkspaceSideSheet');
|
expect(reconciliationSource).toContain('<WorkspaceSideSheet');
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen, within } from '@testing-library/react';
|
||||||
import { describe, expect, it } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
import { WorkspaceMetricRail } from './WorkspaceMetricRail';
|
import { WorkspaceMetricRail } from './WorkspaceMetricRail';
|
||||||
|
|
||||||
@@ -23,4 +23,29 @@ describe('WorkspaceMetricRail', () => {
|
|||||||
expect(view.container.querySelectorAll('.test-card.semi-card')).toHaveLength(3);
|
expect(view.container.querySelectorAll('.test-card.semi-card')).toHaveLength(3);
|
||||||
expect(screen.getByLabelText('车辆数:20;当前授权范围')).toHaveClass('is-vehicles');
|
expect(screen.getByLabelText('车辆数:20;当前授权范围')).toHaveClass('is-vehicles');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('renders a list-first queue variant inside one Semi card', () => {
|
||||||
|
const view = render(<WorkspaceMetricRail
|
||||||
|
variant="queue"
|
||||||
|
ariaLabel="处置队列概览"
|
||||||
|
className="queue-metrics"
|
||||||
|
items={[
|
||||||
|
{ label: '待复核', value: '1,347', note: '活跃问题', tone: 'primary' },
|
||||||
|
{ label: 'SLA 超时', value: '1,206', note: '超过 24 小时', tone: 'danger' },
|
||||||
|
{ label: '已确认', value: '0', emphasis: 'secondary' },
|
||||||
|
{ label: '已恢复', value: '704', emphasis: 'secondary', tone: 'success' }
|
||||||
|
]}
|
||||||
|
context={<span>当前筛选 <strong>1,347</strong> 条</span>}
|
||||||
|
/>);
|
||||||
|
|
||||||
|
const rail = view.container.querySelector('.v2-workspace-metric-rail');
|
||||||
|
expect(rail).toHaveClass('semi-card', 'is-queue', 'queue-metrics');
|
||||||
|
const list = screen.getByRole('list', { name: '处置队列概览' });
|
||||||
|
expect(within(list).getAllByRole('listitem')).toHaveLength(4);
|
||||||
|
expect(within(list).getByText('待复核').closest('[role="listitem"]')).toHaveClass('is-primary');
|
||||||
|
expect(within(list).getByText('SLA 超时').closest('[role="listitem"]')).toHaveClass('is-danger');
|
||||||
|
expect(within(list).getByText('已恢复').closest('[role="listitem"]')).toHaveClass('is-secondary', 'is-success');
|
||||||
|
expect(view.container.querySelector('.v2-workspace-metric-context')).toHaveTextContent('当前筛选 1,347 条');
|
||||||
|
expect(view.container.querySelectorAll('.semi-card')).toHaveLength(1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,15 +8,15 @@ export type WorkspaceMetricRailItem = {
|
|||||||
className?: string;
|
className?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function WorkspaceMetricRail({
|
export type WorkspaceQueueMetricRailItem = {
|
||||||
ariaLabel,
|
label: string;
|
||||||
primary,
|
value: ReactNode;
|
||||||
secondary,
|
note?: ReactNode;
|
||||||
className,
|
tone?: 'neutral' | 'primary' | 'success' | 'warning' | 'danger';
|
||||||
cardClassName,
|
emphasis?: 'primary' | 'secondary';
|
||||||
secondaryClassName,
|
};
|
||||||
primaryValueClassName
|
|
||||||
}: {
|
type WorkspaceSummaryMetricRailProps = {
|
||||||
ariaLabel: string;
|
ariaLabel: string;
|
||||||
primary: WorkspaceMetricRailItem;
|
primary: WorkspaceMetricRailItem;
|
||||||
secondary: WorkspaceMetricRailItem[];
|
secondary: WorkspaceMetricRailItem[];
|
||||||
@@ -24,7 +24,47 @@ export function WorkspaceMetricRail({
|
|||||||
cardClassName: string;
|
cardClassName: string;
|
||||||
secondaryClassName: string;
|
secondaryClassName: string;
|
||||||
primaryValueClassName?: string;
|
primaryValueClassName?: string;
|
||||||
}) {
|
};
|
||||||
|
|
||||||
|
type WorkspaceQueueMetricRailProps = {
|
||||||
|
variant: 'queue';
|
||||||
|
ariaLabel: string;
|
||||||
|
className: string;
|
||||||
|
items: WorkspaceQueueMetricRailItem[];
|
||||||
|
context?: ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function WorkspaceMetricRail(props: WorkspaceSummaryMetricRailProps | WorkspaceQueueMetricRailProps) {
|
||||||
|
if ('items' in props) {
|
||||||
|
return <Card className={`v2-workspace-metric-rail is-queue ${props.className}`} bodyStyle={{ padding: 0 }}>
|
||||||
|
<div className="v2-workspace-metric-list" role="list" aria-label={props.ariaLabel}>
|
||||||
|
{props.items.map((item, index) => {
|
||||||
|
const toneClassName = `is-${item.tone ?? 'neutral'}`;
|
||||||
|
const emphasisClassName = `is-${item.emphasis ?? (index < 2 ? 'primary' : 'secondary')}`;
|
||||||
|
return <span
|
||||||
|
className={toneClassName === emphasisClassName ? toneClassName : `${toneClassName} ${emphasisClassName}`}
|
||||||
|
role="listitem"
|
||||||
|
key={item.label}
|
||||||
|
>
|
||||||
|
<small>{item.label}</small>
|
||||||
|
<strong>{item.value}</strong>
|
||||||
|
{item.note ? <em>{item.note}</em> : null}
|
||||||
|
</span>;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
{props.context ? <div className="v2-workspace-metric-context">{props.context}</div> : null}
|
||||||
|
</Card>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
ariaLabel,
|
||||||
|
primary,
|
||||||
|
secondary,
|
||||||
|
className,
|
||||||
|
cardClassName,
|
||||||
|
secondaryClassName,
|
||||||
|
primaryValueClassName
|
||||||
|
} = props;
|
||||||
const cardClass = (item: WorkspaceMetricRailItem, primaryCard = false) => [
|
const cardClass = (item: WorkspaceMetricRailItem, primaryCard = false) => [
|
||||||
cardClassName,
|
cardClassName,
|
||||||
primaryCard ? 'is-primary' : '',
|
primaryCard ? 'is-primary' : '',
|
||||||
|
|||||||
@@ -16180,6 +16180,207 @@
|
|||||||
min-width: 908px;
|
min-width: 908px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Shared Semi UI queue metrics.
|
||||||
|
* Keep operational evidence in one compact rail so the result list remains
|
||||||
|
* the visual and interaction focus.
|
||||||
|
*/
|
||||||
|
.v2-workspace-metric-rail.is-queue.semi-card {
|
||||||
|
overflow: hidden;
|
||||||
|
border: 0;
|
||||||
|
border-bottom: 1px solid #e1e8f0;
|
||||||
|
border-radius: 0;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-rail.is-queue > .semi-card-body {
|
||||||
|
display: grid;
|
||||||
|
min-height: 58px;
|
||||||
|
grid-template-columns: minmax(0, 1fr) 218px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-list {
|
||||||
|
display: grid;
|
||||||
|
min-width: 0;
|
||||||
|
grid-template-columns: 1.15fr 1.15fr .9fr .9fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-list > span {
|
||||||
|
display: grid;
|
||||||
|
min-width: 0;
|
||||||
|
min-height: 58px;
|
||||||
|
grid-template-columns: auto minmax(0, 1fr);
|
||||||
|
grid-template-rows: auto auto;
|
||||||
|
align-content: center;
|
||||||
|
column-gap: 10px;
|
||||||
|
padding: 7px 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-list > span + span {
|
||||||
|
border-left: 1px solid #e5ebf2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-list > span > small {
|
||||||
|
grid-column: 1;
|
||||||
|
color: #78879a;
|
||||||
|
font-size: 9px;
|
||||||
|
font-weight: 650;
|
||||||
|
line-height: 14px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-list > span > strong {
|
||||||
|
grid-column: 1;
|
||||||
|
color: #243950;
|
||||||
|
font-size: 21px;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
line-height: 24px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-list > span > em {
|
||||||
|
align-self: center;
|
||||||
|
grid-column: 2;
|
||||||
|
grid-row: 1 / 3;
|
||||||
|
overflow: hidden;
|
||||||
|
color: #8a97a8;
|
||||||
|
font-size: 9px;
|
||||||
|
font-style: normal;
|
||||||
|
line-height: 14px;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-list > span.is-secondary > strong {
|
||||||
|
font-size: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-list > span.is-primary {
|
||||||
|
background: linear-gradient(145deg, #edf5ff 0%, #f8fbff 100%);
|
||||||
|
box-shadow: inset 0 -3px #1f6feb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-list > span.is-primary > :is(small, strong) {
|
||||||
|
color: #155fc5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-list > span.is-danger {
|
||||||
|
background: linear-gradient(145deg, #fff 0%, #fff8f7 100%);
|
||||||
|
box-shadow: inset 0 -3px #e2554f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-list > span.is-danger > :is(small, strong) {
|
||||||
|
color: #c2413d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-list > span.is-success > :is(small, strong) {
|
||||||
|
color: #148459;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-list > span.is-warning > :is(small, strong) {
|
||||||
|
color: #a76512;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-context {
|
||||||
|
display: flex;
|
||||||
|
min-width: 0;
|
||||||
|
align-items: center;
|
||||||
|
border-left: 1px solid #e5ebf2;
|
||||||
|
background: #fbfcfe;
|
||||||
|
padding: 7px 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-context > span {
|
||||||
|
display: grid;
|
||||||
|
min-width: 0;
|
||||||
|
grid-template-columns: auto 1fr;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 1px 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-context small {
|
||||||
|
color: #8491a2;
|
||||||
|
font-size: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-context strong {
|
||||||
|
color: #2f5f9b;
|
||||||
|
font-size: 18px;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-context em {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
overflow: hidden;
|
||||||
|
color: #929eac;
|
||||||
|
font-size: 8px;
|
||||||
|
font-style: normal;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-metric-rail {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 681px) {
|
||||||
|
.v2-reconcile-heading.v2-workspace-panel-header {
|
||||||
|
min-height: 62px;
|
||||||
|
padding-block: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-toolbar {
|
||||||
|
padding-block: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
.v2-workspace-metric-rail.is-queue > .semi-card-body {
|
||||||
|
grid-template-columns: minmax(0, 1fr) 180px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-list > span {
|
||||||
|
column-gap: 6px;
|
||||||
|
padding-inline: 9px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 680px) {
|
||||||
|
.v2-workspace-metric-rail.is-queue > .semi-card-body {
|
||||||
|
min-height: 56px;
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-list {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-list > span {
|
||||||
|
min-height: 56px;
|
||||||
|
grid-template-columns: auto minmax(0, 1fr);
|
||||||
|
column-gap: 8px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-list > span.is-secondary {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-list > span > strong {
|
||||||
|
font-size: 19px;
|
||||||
|
line-height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-list > span > em {
|
||||||
|
font-size: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-workspace-metric-context {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.v2-reconcile-issue-cell > span {
|
.v2-reconcile-issue-cell > span {
|
||||||
display: flex;
|
display: flex;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
@@ -21899,10 +22100,35 @@
|
|||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-detail-sidesheet .v2-workspace-config-summary {
|
||||||
|
min-height: 104px;
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-detail-sidesheet .v2-workspace-config-summary > span:last-child {
|
||||||
|
min-height: 38px;
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
grid-template-columns: auto auto minmax(0, 1fr);
|
||||||
|
align-items: baseline;
|
||||||
|
align-content: center;
|
||||||
|
column-gap: 8px;
|
||||||
|
padding-block: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-detail-sidesheet .v2-workspace-config-summary > span:last-child :is(small, strong, em) {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
.v2-reconcile-detail-sidesheet .v2-workspace-config-summary > span:first-child strong,
|
.v2-reconcile-detail-sidesheet .v2-workspace-config-summary > span:first-child strong,
|
||||||
.v2-reconcile-detail-sidesheet .v2-workspace-config-summary > span:nth-child(2) strong {
|
.v2-reconcile-detail-sidesheet .v2-workspace-config-summary > span:nth-child(2) strong {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.v2-reconcile-detail-sidesheet .v2-workspace-config-summary > span:last-child strong {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 900px) and (max-height: 480px) and (orientation: landscape) {
|
@media (max-width: 900px) and (max-height: 480px) and (orientation: landscape) {
|
||||||
|
|||||||
Reference in New Issue
Block a user