feat(web): refine Semi UI history workspace
This commit is contained in:
68
design-qa.md
Normal file
68
design-qa.md
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
# Historical Data Semi UI Design QA
|
||||||
|
|
||||||
|
## Evidence
|
||||||
|
|
||||||
|
- Source visual truth: `/tmp/semi-ui-reference-1440.png` (accepted Semi UI workspace direction).
|
||||||
|
- Existing flow source: `/tmp/history-before-desktop.jpg` (historical data before this iteration).
|
||||||
|
- Implementation screenshot: `/tmp/history-after-desktop.jpg`.
|
||||||
|
- Responsive screenshots: `/tmp/history-after-1024.jpg`, `/tmp/history-after-mobile-sheet.jpg`.
|
||||||
|
- Full-view comparison: `/tmp/semi-history-design-comparison.jpg`.
|
||||||
|
- Same-route iteration comparison: `/tmp/history-before-after-comparison.jpg`.
|
||||||
|
- Requested desktop viewport: 1440 × 900. The embedded browser surface captured 1280 × 720; an additional exact 1024 × 768 capture was checked.
|
||||||
|
- Mobile viewport: 390 × 844.
|
||||||
|
- State: location history query for one vehicle, empty local result, desktop query collapsed; mobile filter sheet open.
|
||||||
|
|
||||||
|
## Full-view comparison
|
||||||
|
|
||||||
|
The implementation keeps the accepted product skeleton: persistent left navigation, white header, blue/gray visual hierarchy, restrained cards, compact controls, table-first workspace, and the same icon family. The historical-data workflow intentionally keeps its evidence table instead of copying the mileage-specific hero and mileage matrix.
|
||||||
|
|
||||||
|
The before/after comparison shows the material layout change: the applied query remains readable in the command rail while the full desktop filter panel can collapse, returning the vertical workspace to the historical detail table.
|
||||||
|
|
||||||
|
## Focused comparison
|
||||||
|
|
||||||
|
The mobile filter sheet was checked separately because its labels and controls are too small to assess reliably in the desktop comparison. At 390 × 844, the summary rail, date range, type/source selects, export action, and sticky reset/apply actions remain visible and touch-safe without horizontal overflow.
|
||||||
|
|
||||||
|
## Fidelity ledger
|
||||||
|
|
||||||
|
| Surface | Source evidence | Render evidence | Result |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| Typography | Compact Semi UI chrome with strong page/task titles and smaller utility copy | History title, command rail, metric values, panel title, filters and mobile sheet preserve the same hierarchy | Passed |
|
||||||
|
| Layout rhythm | Persistent navigation, 12–18px page gutters, one main data surface | Query rail, three metrics and the table align on one grid; collapsed state increases table height without adding another card family | Passed |
|
||||||
|
| Colors/tokens | White surfaces, cool gray canvas, blue primary, green healthy state | Existing shared tokens and Semi UI variants are reused; no new palette or gradient was introduced | Passed |
|
||||||
|
| Icons/assets | Supplied brand logo and Semi icon family | Brand assets are unchanged; filter, calendar, search, setting, export and more actions use the same Semi icon family | Passed |
|
||||||
|
| Copy/content | Query, range, data type/source and result actions are business-native | No business fields or routes were added or removed; the applied scope reuses existing query values | Passed |
|
||||||
|
| Responsive behavior | Dense desktop workspace with task-focused mobile disclosure | 1280 × 720, 1024 × 768 and 390 × 844 checks show no clipped primary action or horizontal page overflow | Passed |
|
||||||
|
| Interaction | Query controls should not compete with results after submission | Collapse/expand, apply/reset, mobile filter sheet and row/detail paths are covered by interaction tests | Passed |
|
||||||
|
|
||||||
|
## Above-the-fold copy diff
|
||||||
|
|
||||||
|
- Added visible control labels: `收起条件` and `修改条件`, required for the new query disclosure.
|
||||||
|
- Existing task title, description, status, query labels and result labels are preserved.
|
||||||
|
- No unapproved marketing copy, badge, module, navigation item or business claim was added.
|
||||||
|
|
||||||
|
## Comparison history
|
||||||
|
|
||||||
|
1. Earlier finding — P2: the desktop filter panel permanently occupied roughly 108px after a query, reducing the primary evidence-table viewport.
|
||||||
|
- Fix: added a lightweight desktop-only disclosure control and an applied-scope summary for time, category and source.
|
||||||
|
- Post-fix evidence: `/tmp/history-before-after-comparison.jpg`; the table begins materially higher while the query remains recoverable through `修改条件`.
|
||||||
|
2. Earlier finding — P2: mobile record quality relied on a small text indicator only.
|
||||||
|
- Fix: added a three-pixel semantic quality rail with selected-state override while retaining the existing quality label.
|
||||||
|
- Post-fix evidence: component test confirms semantic quality classes; no additional card height is introduced.
|
||||||
|
|
||||||
|
## Findings
|
||||||
|
|
||||||
|
- No actionable P0, P1 or P2 visual differences remain.
|
||||||
|
- P3 follow-up: Semi UI 2.101 still emits its existing `findDOMNode` StrictMode warning; it does not affect the rendered layout or interaction path in this iteration.
|
||||||
|
|
||||||
|
## Core interaction verification
|
||||||
|
|
||||||
|
- Desktop query collapse and re-open.
|
||||||
|
- Query submission collapses the desktop panel and preserves applied scope.
|
||||||
|
- Reset restores the full desktop query panel.
|
||||||
|
- Mobile filter sheet open, reset, apply and close.
|
||||||
|
- Historical trend, field settings, export task menu, pagination and row-detail interaction remain covered by the full test suite.
|
||||||
|
- Browser console contains no application exception or framework overlay; only the existing Semi UI StrictMode deprecation warning appears.
|
||||||
|
|
||||||
|
## Final result
|
||||||
|
|
||||||
|
final result: passed
|
||||||
@@ -139,7 +139,16 @@ test('clears stale rows, charts, and evidence as soon as the history scope chang
|
|||||||
}
|
}
|
||||||
expect(view.container.querySelector('.v2-history-discovery-shell')).toContainElement(screen.getByLabelText('历史数据查询操作'));
|
expect(view.container.querySelector('.v2-history-discovery-shell')).toContainElement(screen.getByLabelText('历史数据查询操作'));
|
||||||
expect(screen.getByLabelText('历史数据查询操作')).toHaveTextContent('遥测证据检索');
|
expect(screen.getByLabelText('历史数据查询操作')).toHaveTextContent('遥测证据检索');
|
||||||
expect(screen.getByLabelText('历史数据查询操作')).toHaveTextContent('上海时区');
|
expect(screen.getByLabelText('历史数据查询操作')).toHaveTextContent('07-16 00:00 – 07-16 05:00');
|
||||||
|
expect(screen.getByLabelText('历史数据查询操作')).toHaveTextContent('位置数据');
|
||||||
|
expect(screen.getByLabelText('历史数据查询操作')).toHaveTextContent('全部来源');
|
||||||
|
const desktopQueryToggle = screen.getByRole('button', { name: '收起查询条件' });
|
||||||
|
expect(desktopQueryToggle).toHaveAttribute('aria-expanded', 'true');
|
||||||
|
fireEvent.click(desktopQueryToggle);
|
||||||
|
expect(view.container.querySelector('.v2-history-discovery-shell')).toHaveAttribute('data-query-collapsed', 'true');
|
||||||
|
expect(screen.getByRole('button', { name: '修改查询条件' })).toHaveAttribute('aria-expanded', 'false');
|
||||||
|
fireEvent.click(screen.getByRole('button', { name: '修改查询条件' }));
|
||||||
|
expect(view.container.querySelector('.v2-history-discovery-shell')).toHaveAttribute('data-query-collapsed', 'false');
|
||||||
expect(view.container.querySelector('.v2-history-date-time-range.semi-datepicker')).toBeInTheDocument();
|
expect(view.container.querySelector('.v2-history-date-time-range.semi-datepicker')).toBeInTheDocument();
|
||||||
expect(screen.getByRole('group', { name: '快捷时间范围' })).toHaveClass('semi-button-group');
|
expect(screen.getByRole('group', { name: '快捷时间范围' })).toHaveClass('semi-button-group');
|
||||||
expect(screen.getByPlaceholderText('开始时间')).toHaveValue('2026-07-16 00:00');
|
expect(screen.getByPlaceholderText('开始时间')).toHaveValue('2026-07-16 00:00');
|
||||||
@@ -275,7 +284,7 @@ test('renders only selectable Semi history cards on mobile', async () => {
|
|||||||
|
|
||||||
const action = await screen.findByRole('button', { name: '查看 粤A移动历史 2026-07-16 04:00:00 数据详情' });
|
const action = await screen.findByRole('button', { name: '查看 粤A移动历史 2026-07-16 04:00:00 数据详情' });
|
||||||
expect(action).toHaveClass('semi-button', 'v2-history-mobile-action');
|
expect(action).toHaveClass('semi-button', 'v2-history-mobile-action');
|
||||||
expect(action.closest('.semi-card')).toHaveClass('v2-history-mobile-card');
|
expect(action.closest('.semi-card')).toHaveClass('v2-history-mobile-card', 'is-quality-normal');
|
||||||
expect(view.container.querySelector('.v2-history-data-table')).not.toBeInTheDocument();
|
expect(view.container.querySelector('.v2-history-data-table')).not.toBeInTheDocument();
|
||||||
expect(action).toHaveAttribute('aria-pressed', 'false');
|
expect(action).toHaveAttribute('aria-pressed', 'false');
|
||||||
expect(action).toHaveAttribute('aria-expanded', 'false');
|
expect(action).toHaveAttribute('aria-expanded', 'false');
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useMutation, useQuery, useQueryClient, type UseQueryResult } from '@tanstack/react-query';
|
import { useMutation, useQuery, useQueryClient, type UseQueryResult } from '@tanstack/react-query';
|
||||||
import { IconCalendar, IconChevronRight, IconClose, IconDownload, IconMapPin, IconMore, IconRefresh, IconSearch, IconSetting } from '@douyinfe/semi-icons';
|
import { IconCalendar, IconChevronRight, IconClose, IconDownload, IconFilter, IconMapPin, IconMore, IconRefresh, IconSearch, IconSetting } from '@douyinfe/semi-icons';
|
||||||
import { Button, Card, CardGroup, Checkbox, Descriptions, Dropdown, Empty, Input, Progress, Select, Spin, Table, Tag, Typography } from '@douyinfe/semi-ui';
|
import { Button, Card, CardGroup, Checkbox, Descriptions, Dropdown, Empty, Input, Progress, Select, Spin, Table, Tag, Typography } from '@douyinfe/semi-ui';
|
||||||
import { FormEvent, KeyboardEvent, useCallback, useEffect, useMemo, useState } from 'react';
|
import { FormEvent, KeyboardEvent, useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { useSearchParams } from 'react-router-dom';
|
import { useSearchParams } from 'react-router-dom';
|
||||||
@@ -369,6 +369,7 @@ export default function HistoryPage() {
|
|||||||
const [columnSettingsOpen, setColumnSettingsOpen] = useState(false);
|
const [columnSettingsOpen, setColumnSettingsOpen] = useState(false);
|
||||||
const [trendExpanded, setTrendExpanded] = useState(false);
|
const [trendExpanded, setTrendExpanded] = useState(false);
|
||||||
const [filtersCollapsed, setFiltersCollapsed] = useState(true);
|
const [filtersCollapsed, setFiltersCollapsed] = useState(true);
|
||||||
|
const [desktopQueryCollapsed, setDesktopQueryCollapsed] = useState(false);
|
||||||
const [exportJobsOpen, setExportJobsOpen] = useState(false);
|
const [exportJobsOpen, setExportJobsOpen] = useState(false);
|
||||||
const [toolsOpen, setToolsOpen] = useState(false);
|
const [toolsOpen, setToolsOpen] = useState(false);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -445,6 +446,7 @@ export default function HistoryPage() {
|
|||||||
const next = { ...draft, keywords: parsed.join(',') };
|
const next = { ...draft, keywords: parsed.join(',') };
|
||||||
setCriteria(next); setOffset(0);
|
setCriteria(next); setOffset(0);
|
||||||
setFiltersCollapsed(true);
|
setFiltersCollapsed(true);
|
||||||
|
setDesktopQueryCollapsed(true);
|
||||||
const url = new URLSearchParams({ keywords: next.keywords, category: next.category });
|
const url = new URLSearchParams({ keywords: next.keywords, category: next.category });
|
||||||
if (next.dateFrom) url.set('dateFrom', next.dateFrom);
|
if (next.dateFrom) url.set('dateFrom', next.dateFrom);
|
||||||
if (next.dateTo) url.set('dateTo', next.dateTo);
|
if (next.dateTo) url.set('dateTo', next.dateTo);
|
||||||
@@ -453,7 +455,7 @@ export default function HistoryPage() {
|
|||||||
};
|
};
|
||||||
const submit = (event: FormEvent) => { event.preventDefault(); applyDraft(); };
|
const submit = (event: FormEvent) => { event.preventDefault(); applyDraft(); };
|
||||||
const resetDraft = () => setDraft({ keywords: '', ...currentHistoryWindow(), category: 'location', protocol: '' });
|
const resetDraft = () => setDraft({ keywords: '', ...currentHistoryWindow(), category: 'location', protocol: '' });
|
||||||
const reset = () => { const next = { keywords: '', ...currentHistoryWindow(), category: 'location', protocol: '' }; setDraft(next); setCriteria(next); setOffset(0); setFiltersCollapsed(true); setSearchParams(preserveMonitorReturn(new URLSearchParams(), monitorReturn), { replace: true }); };
|
const reset = () => { const next = { keywords: '', ...currentHistoryWindow(), category: 'location', protocol: '' }; setDraft(next); setCriteria(next); setOffset(0); setFiltersCollapsed(true); setDesktopQueryCollapsed(false); setSearchParams(preserveMonitorReturn(new URLSearchParams(), monitorReturn), { replace: true }); };
|
||||||
const toggleMetric = (key: string) => setVisibleByCategory((current) => {
|
const toggleMetric = (key: string) => setVisibleByCategory((current) => {
|
||||||
const baseline = current[criteria.category] ?? allMetrics.filter((metric) => metric.defaultVisible).map((metric) => metric.key);
|
const baseline = current[criteria.category] ?? allMetrics.filter((metric) => metric.defaultVisible).map((metric) => metric.key);
|
||||||
const next = baseline.includes(key) ? baseline.filter((item) => item !== key) : [...baseline, key];
|
const next = baseline.includes(key) ? baseline.filter((item) => item !== key) : [...baseline, key];
|
||||||
@@ -471,6 +473,11 @@ export default function HistoryPage() {
|
|||||||
const page = Math.floor(offset / limit) + 1;
|
const page = Math.floor(offset / limit) + 1;
|
||||||
const summarySources = resultSummary?.sources?.join('、') || '—';
|
const summarySources = resultSummary?.sources?.join('、') || '—';
|
||||||
const summaryLoading = keywords.length > 0 && dataQuery.isFetching && !result;
|
const summaryLoading = keywords.length > 0 && dataQuery.isFetching && !result;
|
||||||
|
const appliedCategoryLabel = catalogQuery.data?.categories.find((item) => item.key === criteria.category)?.label
|
||||||
|
?? (criteria.category === 'raw' ? '原始报文' : criteria.category === 'mileage' ? '日里程' : '位置数据');
|
||||||
|
const appliedWindowLabel = criteria.dateFrom && criteria.dateTo
|
||||||
|
? `${criteria.dateFrom.replace('T', ' ').slice(5, 16)} – ${criteria.dateTo.replace('T', ' ').slice(5, 16)}`
|
||||||
|
: '时间待选择';
|
||||||
const historyMetrics: WorkspaceQueueMetricRailItem[] = [
|
const historyMetrics: WorkspaceQueueMetricRailItem[] = [
|
||||||
{
|
{
|
||||||
label: '结果行数',
|
label: '结果行数',
|
||||||
@@ -513,7 +520,7 @@ export default function HistoryPage() {
|
|||||||
|
|
||||||
return <div className="v2-history-page">
|
return <div className="v2-history-page">
|
||||||
<MonitorReturnBar />
|
<MonitorReturnBar />
|
||||||
<div className="v2-history-discovery-shell">
|
<div className="v2-history-discovery-shell" data-query-collapsed={!mobileLayout && desktopQueryCollapsed}>
|
||||||
<WorkspaceCommandBar
|
<WorkspaceCommandBar
|
||||||
className="v2-history-command-bar"
|
className="v2-history-command-bar"
|
||||||
ariaLabel="历史数据查询操作"
|
ariaLabel="历史数据查询操作"
|
||||||
@@ -521,7 +528,21 @@ export default function HistoryPage() {
|
|||||||
description="按车辆、时间和协议核验可追溯的历史数据"
|
description="按车辆、时间和协议核验可追溯的历史数据"
|
||||||
status={keywords.length ? `${keywords.length} 辆 · ${(result?.total ?? 0).toLocaleString('zh-CN')} 条` : '等待查询'}
|
status={keywords.length ? `${keywords.length} 辆 · ${(result?.total ?? 0).toLocaleString('zh-CN')} 条` : '等待查询'}
|
||||||
statusColor={keywords.length ? 'blue' : 'grey'}
|
statusColor={keywords.length ? 'blue' : 'grey'}
|
||||||
meta={<Typography.Text type="tertiary">上海时区 · 最多 5 台车辆</Typography.Text>}
|
meta={keywords.length ? <span className="v2-history-applied-scope" aria-label="已应用查询范围">
|
||||||
|
<span><IconCalendar />{appliedWindowLabel}</span>
|
||||||
|
<span>{appliedCategoryLabel}</span>
|
||||||
|
<span>{criteria.protocol || '全部来源'}</span>
|
||||||
|
</span> : <Typography.Text type="tertiary">上海时区 · 最多 5 台车辆</Typography.Text>}
|
||||||
|
actions={!mobileLayout ? <Button
|
||||||
|
className="v2-history-query-toggle"
|
||||||
|
theme="light"
|
||||||
|
type="tertiary"
|
||||||
|
icon={<IconFilter />}
|
||||||
|
aria-label={desktopQueryCollapsed ? '修改查询条件' : '收起查询条件'}
|
||||||
|
aria-expanded={!desktopQueryCollapsed}
|
||||||
|
aria-controls="v2-history-query-panel"
|
||||||
|
onClick={() => setDesktopQueryCollapsed((value) => !value)}
|
||||||
|
>{desktopQueryCollapsed ? '修改条件' : '收起条件'}</Button> : undefined}
|
||||||
/>
|
/>
|
||||||
{mobileLayout ? <div className="v2-history-mobile-discovery">
|
{mobileLayout ? <div className="v2-history-mobile-discovery">
|
||||||
<MobileFilterToggle
|
<MobileFilterToggle
|
||||||
@@ -582,7 +603,7 @@ export default function HistoryPage() {
|
|||||||
statusColor={keywords.length ? 'blue' : 'grey'}
|
statusColor={keywords.length ? 'blue' : 'grey'}
|
||||||
onToggle={() => setFiltersCollapsed((value) => !value)}
|
onToggle={() => setFiltersCollapsed((value) => !value)}
|
||||||
>
|
>
|
||||||
<form className={`v2-history-toolbar${filtersCollapsed ? ' is-mobile-collapsed' : ''}`} onSubmit={submit}>
|
<form id="v2-history-query-panel" className={`v2-history-toolbar${filtersCollapsed ? ' is-mobile-collapsed' : ''}`} onSubmit={submit}>
|
||||||
{historyFilterFields}
|
{historyFilterFields}
|
||||||
<div className="v2-history-toolbar-actions"><Button className="v2-primary-button" theme="solid" htmlType="submit" disabled={!parseHistoryKeywords(draft.keywords).length}>查询</Button><Button className="v2-secondary-button" theme="light" onClick={reset}>重置</Button>{!exportAllowed ? <Tag className="v2-history-permission-tag" color="grey" type="light" size="large">只读</Tag> : null}</div>
|
<div className="v2-history-toolbar-actions"><Button className="v2-primary-button" theme="solid" htmlType="submit" disabled={!parseHistoryKeywords(draft.keywords).length}>查询</Button><Button className="v2-secondary-button" theme="light" onClick={reset}>重置</Button>{!exportAllowed ? <Tag className="v2-history-permission-tag" color="grey" type="light" size="large">只读</Tag> : null}</div>
|
||||||
</form>
|
</form>
|
||||||
@@ -648,7 +669,7 @@ export default function HistoryPage() {
|
|||||||
onKeyDown={scrollHistoryTable}
|
onKeyDown={scrollHistoryTable}
|
||||||
>
|
>
|
||||||
{mobileLayout
|
{mobileLayout
|
||||||
? <div className="v2-history-mobile-list">{resultRows.map((row) => <Card key={row.id} className={`v2-history-mobile-card${selectedRow?.id === row.id ? ' is-selected' : ''}`} bodyStyle={{ padding: 0 }}><Button theme="borderless" type="tertiary" className="v2-history-mobile-action" aria-pressed={selectedRow?.id === row.id} aria-expanded={selectedRow?.id === row.id} aria-label={`查看 ${row.plate || row.vin} ${row.deviceTime} 数据详情`} onClick={() => selectRow(row)}><span className="v2-history-mobile-card-content"><header><span><strong>{row.plate || '未绑定车牌'}</strong><small>{row.vin}</small></span><span className={`v2-quality is-${row.quality}`}><i />{historyQualityLabel(row.quality)}</span></header><span className="v2-history-mobile-meta"><PlatformTime className="v2-history-time" value={row.deviceTime} /><ProtocolTag className="v2-history-protocol-tag" protocol={row.protocol} compact /></span>{isHealthyHistoryQuality(row.quality) ? null : <small className="v2-history-mobile-quality">{row.qualityReason || '平台未返回质量说明'}</small>}<dl>{visibleMetrics.slice(0, 4).map((metric) => <div key={metric.key}><dt>{metric.label}</dt><dd>{formatHistoryValue(row.values[metric.key], metric)}</dd></div>)}</dl><footer>查看完整详情<IconChevronRight /></footer></span></Button></Card>)}</div>
|
? <div className="v2-history-mobile-list">{resultRows.map((row) => <Card key={row.id} className={`v2-history-mobile-card is-quality-${row.quality}${selectedRow?.id === row.id ? ' is-selected' : ''}`} bodyStyle={{ padding: 0 }}><Button theme="borderless" type="tertiary" className="v2-history-mobile-action" aria-pressed={selectedRow?.id === row.id} aria-expanded={selectedRow?.id === row.id} aria-label={`查看 ${row.plate || row.vin} ${row.deviceTime} 数据详情`} onClick={() => selectRow(row)}><span className="v2-history-mobile-card-content"><header><span><strong>{row.plate || '未绑定车牌'}</strong><small>{row.vin}</small></span><span className={`v2-quality is-${row.quality}`}><i />{historyQualityLabel(row.quality)}</span></header><span className="v2-history-mobile-meta"><PlatformTime className="v2-history-time" value={row.deviceTime} /><ProtocolTag className="v2-history-protocol-tag" protocol={row.protocol} compact /></span>{isHealthyHistoryQuality(row.quality) ? null : <small className="v2-history-mobile-quality">{row.qualityReason || '平台未返回质量说明'}</small>}<dl>{visibleMetrics.slice(0, 4).map((metric) => <div key={metric.key}><dt>{metric.label}</dt><dd>{formatHistoryValue(row.values[metric.key], metric)}</dd></div>)}</dl><footer>查看完整详情<IconChevronRight /></footer></span></Button></Card>)}</div>
|
||||||
: resultRows.length ? <HistoryDataTable rows={resultRows} metrics={visibleMetrics} selectedRowID={selectedRow?.id} onSelect={selectRow} /> : null}
|
: resultRows.length ? <HistoryDataTable rows={resultRows} metrics={visibleMetrics} selectedRowID={selectedRow?.id} onSelect={selectRow} /> : null}
|
||||||
{dataQuery.isPending && keywords.length
|
{dataQuery.isPending && keywords.length
|
||||||
? <PanelLoading className="v2-history-loading" title="正在加载当前筛选范围的历史数据" description="按车辆、时间和协议整理可追溯证据。" />
|
? <PanelLoading className="v2-history-loading" title="正在加载当前筛选范围的历史数据" description="按车辆、时间和协议整理可追溯证据。" />
|
||||||
|
|||||||
@@ -8260,13 +8260,41 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.v2-history-mobile-list > .v2-history-mobile-card.semi-card {
|
.v2-history-mobile-list > .v2-history-mobile-card.semi-card {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
contain-intrinsic-size: auto 108px;
|
contain-intrinsic-size: auto 108px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.v2-history-mobile-list > .v2-history-mobile-card.semi-card::before {
|
||||||
|
position: absolute;
|
||||||
|
inset: 7px auto 7px 0;
|
||||||
|
z-index: 2;
|
||||||
|
width: 3px;
|
||||||
|
border-radius: 0 3px 3px 0;
|
||||||
|
background: #18a76f;
|
||||||
|
content: '';
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-mobile-list > .v2-history-mobile-card:is(.is-quality-warning, .is-quality-unknown).semi-card::before {
|
||||||
|
background: #ed9f31;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-mobile-list > .v2-history-mobile-card:is(.is-quality-error, .is-quality-critical).semi-card::before {
|
||||||
|
background: #e95a52;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-mobile-list > .v2-history-mobile-card.is-selected.semi-card::before {
|
||||||
|
inset-block: 0;
|
||||||
|
width: 4px;
|
||||||
|
border-radius: 0;
|
||||||
|
background: var(--v2-blue);
|
||||||
|
}
|
||||||
|
|
||||||
.v2-history-mobile-card-content {
|
.v2-history-mobile-card-content {
|
||||||
padding: 8px 9px;
|
padding: 8px 9px 8px 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.v2-history-mobile-card-content header strong {
|
.v2-history-mobile-card-content header strong {
|
||||||
@@ -15546,6 +15574,64 @@
|
|||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.v2-history-command-bar .v2-workspace-command-actions {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-applied-scope {
|
||||||
|
display: inline-flex;
|
||||||
|
min-width: 0;
|
||||||
|
align-items: center;
|
||||||
|
color: #64758b;
|
||||||
|
font-size: 10px;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-applied-scope > span {
|
||||||
|
display: inline-flex;
|
||||||
|
min-width: 0;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-applied-scope > span + span {
|
||||||
|
margin-left: 8px;
|
||||||
|
border-left: 1px solid #dce4ee;
|
||||||
|
padding-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-applied-scope > span:first-child {
|
||||||
|
max-width: min(28vw, 330px);
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-applied-scope .semi-icon {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
color: #6d91bf;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-query-toggle.semi-button {
|
||||||
|
height: 32px;
|
||||||
|
min-height: 32px;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
border-color: #d7e2ef;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #f7faff;
|
||||||
|
padding-inline: 10px;
|
||||||
|
color: #4f657e;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-query-toggle.semi-button:hover {
|
||||||
|
border-color: #b9cee9;
|
||||||
|
background: #edf5ff;
|
||||||
|
color: #1d64c5;
|
||||||
|
}
|
||||||
|
|
||||||
.v2-history-discovery-shell > .v2-history-filter-card.v2-workspace-filter-panel.semi-card {
|
.v2-history-discovery-shell > .v2-history-filter-card.v2-workspace-filter-panel.semi-card {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
@@ -15646,6 +15732,21 @@
|
|||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (min-width: 681px) {
|
||||||
|
.v2-history-discovery-shell[data-query-collapsed='true'],
|
||||||
|
.v2-history-discovery-shell[data-query-collapsed='true'] > .v2-history-command-bar {
|
||||||
|
border-radius: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-discovery-shell[data-query-collapsed='true'] > .v2-history-command-bar {
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-discovery-shell[data-query-collapsed='true'] > .v2-history-filter-card {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width: 1101px) {
|
@media (min-width: 1101px) {
|
||||||
.v2-history-discovery-shell .v2-history-toolbar {
|
.v2-history-discovery-shell .v2-history-toolbar {
|
||||||
grid-template-columns: minmax(220px, 1.05fr) minmax(400px, 1.85fr) minmax(112px, .55fr) minmax(126px, .6fr) auto;
|
grid-template-columns: minmax(220px, 1.05fr) minmax(400px, 1.85fr) minmax(112px, .55fr) minmax(126px, .6fr) auto;
|
||||||
@@ -15659,6 +15760,24 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (min-width: 681px) and (max-width: 980px) {
|
||||||
|
.v2-history-command-bar .v2-workspace-command-copy > .semi-typography:last-child {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-command-bar .v2-workspace-command-actions {
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-applied-scope > span:nth-child(n + 2) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v2-history-query-toggle.semi-button {
|
||||||
|
padding-inline: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.v2-history-time {
|
.v2-history-time {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
font-variant-numeric: tabular-nums;
|
font-variant-numeric: tabular-nums;
|
||||||
|
|||||||
Reference in New Issue
Block a user