From 0c6a3e4ef1e52f387e171422958f1572b3d421f1 Mon Sep 17 00:00:00 2001 From: lingniu Date: Sat, 18 Jul 2026 07:19:19 +0800 Subject: [PATCH] refine Semi UI alert workspace --- .../apps/web/src/v2/pages/AlertsPage.test.tsx | 13 +- .../apps/web/src/v2/pages/AlertsPage.tsx | 38 +- .../apps/web/src/v2/styles/workspace.css | 360 +++++++++++------- 3 files changed, 256 insertions(+), 155 deletions(-) diff --git a/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.test.tsx b/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.test.tsx index d13ac562..5258af81 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.test.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.test.tsx @@ -71,10 +71,10 @@ test('loads only event dependencies on the default alert tab', async () => { expect(mocks.alertRulesV2).toHaveBeenCalledTimes(1); expect(mocks.metricCatalog).not.toHaveBeenCalled(); expect(mocks.alertNotificationsV2).toHaveBeenCalledTimes(1); - expect(mocks.alertNotificationsV2.mock.calls[0][0].toString()).toBe('unreadOnly=true&limit=100'); + expect(mocks.alertNotificationsV2.mock.calls[0][0].toString()).toBe('unreadOnly=true&limit=1'); }); -test('loads one full notification query on a direct notifications entry', async () => { +test('loads a paginated notification page and an independent unread total on direct entry', async () => { mocks.alertNotificationsV2.mockResolvedValue({ items: [], total: 0, limit: 100, offset: 0 }); const client = new QueryClient({ defaultOptions: { queries: { retry: false } } }); const view = render(); @@ -84,12 +84,17 @@ test('loads one full notification query on a direct notifications entry', async expect(view.container.querySelector('.v2-alert-notifications')).toHaveClass('semi-card'); expect(screen.getByRole('heading', { level: 5, name: '站内通知' })).toBeInTheDocument(); expect(view.container.querySelector('.v2-alert-notification-empty.semi-empty')).toBeInTheDocument(); + expect(view.container.querySelector('.v2-alert-notification-pagination')).toBeInTheDocument(); + expect(screen.getByRole('combobox', { name: '每页通知数' })).toBeInTheDocument(); expect(view.container.querySelector('.v2-alert-channel-card.semi-card')).toBeInTheDocument(); expect(view.container.querySelector('.v2-alert-channel-descriptions.semi-descriptions')).toBeInTheDocument(); expect(mocks.alertRulesV2).not.toHaveBeenCalled(); expect(mocks.metricCatalog).not.toHaveBeenCalled(); - expect(mocks.alertNotificationsV2).toHaveBeenCalledTimes(1); - expect(mocks.alertNotificationsV2.mock.calls[0][0].toString()).toBe('limit=100'); + expect(mocks.alertNotificationsV2).toHaveBeenCalledTimes(2); + expect(mocks.alertNotificationsV2.mock.calls.map(([params]) => params.toString())).toEqual(expect.arrayContaining([ + 'unreadOnly=true&limit=1', + 'limit=20&offset=0' + ])); }); test('ends notification mutation feedback with a visible retryable error instead of a silent pending state', async () => { diff --git a/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.tsx b/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.tsx index 7339c010..c84026ec 100644 --- a/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.tsx +++ b/vehicle-data-platform/apps/web/src/v2/pages/AlertsPage.tsx @@ -4,7 +4,7 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { FormEvent, useEffect, useMemo, useState } from 'react'; import { Link, useSearchParams } from 'react-router-dom'; import { api } from '../../api/client'; -import type { AlertEvent, AlertNotification, AlertQuery, AlertRule, AlertRuleInput, AlertStatus, MetricDefinition, Page } from '../../api/types'; +import type { AlertEvent, AlertQuery, AlertRule, AlertRuleInput, AlertStatus, MetricDefinition, Page } from '../../api/types'; import { actionLabels, alertValue, canAct, formatAlertTime, operatorLabels, ruleCondition, severityLabels, statusLabels, thresholdText } from '../domain/alert'; import { InlineError, PanelEmpty, PanelLoading } from '../shared/AsyncState'; import { MetricActionButton } from '../shared/MetricActionButton'; @@ -373,23 +373,30 @@ function RulesWorkspace({ rules, metrics }: { rules: AlertRule[]; metrics: Metri ; } -type NotificationsQuery = { - data?: Page; - error: Error | null; - isError: boolean; - isPending: boolean; - refetch: () => unknown; -}; - -function NotificationsWorkspace({ editable, notifications }: { editable: boolean; notifications: NotificationsQuery }) { +function NotificationsWorkspace({ editable }: { editable: boolean }) { const queryClient = useQueryClient(); + const [offset, setOffset] = useState(0); + const [limit, setLimit] = useState(20); + const notifications = useQuery({ + queryKey: ['alert-notifications-v2', 'all', limit, offset], + queryFn: ({ signal }) => api.alertNotificationsV2(new URLSearchParams({ limit: String(limit), offset: String(offset) }), signal), + staleTime: 5_000, + gcTime: QUERY_MEMORY.highVolumeGcTime + }); const read = useMutation({ mutationFn: api.readAlertNotificationsV2, onSuccess: async () => { await Promise.all([queryClient.invalidateQueries({ queryKey: ['alert-notifications-v2'] }), queryClient.invalidateQueries({ queryKey: ['alert-summary-v2'] })]); } }); const items = notifications.data?.items ?? []; - return !item.read)} onClick={() => read.mutate(items.filter((item) => !item.read).map((item) => item.id))}>{read.isPending ? '正在更新' : '全部标为已读'} : 只读} />{notifications.isError ? notifications.refetch()} /> : null}{read.isError ? : null} + const total = notifications.data?.total ?? 0; + const totalPages = Math.max(1, Math.ceil(total / limit)); + const page = Math.floor(offset / limit) + 1; + useEffect(() => { + if (offset > 0 && offset >= total && !notifications.isPending) setOffset(Math.max(0, (totalPages - 1) * limit)); + }, [limit, notifications.isPending, offset, total, totalPages]); + return !item.read)} onClick={() => read.mutate(items.filter((item) => !item.read).map((item) => item.id))}>{read.isPending ? '正在更新' : '本页全部已读'} : 只读} />{notifications.isError ? notifications.refetch()} /> : null}{read.isError ? : null}
{notifications.isPending ?
: items.length ? {items.map((item) => {item.title}} headerExtraContent={{item.read ? '已读' : '未读'}} headerLine bodyStyle={{ padding: 0 }}>

{item.content}

{formatAlertTime(item.createdAt)}{editable && !item.read ? : null}
)}
: !notifications.isError ? } title="暂无站内通知" description="告警触发或状态变更后,通知会在这里形成可追溯记录。" /> : null}
+
setOffset((next - 1) * limit)} pageSize={limit} pageSizeLabel="每页通知数" onPageSizeChange={(next) => { setLimit(next); setOffset(0); }} pageSizeOptions={[{ value: 20, label: '20 条/页' }, { value: 50, label: '50 条/页' }]} />
外部通知通道} headerLine bodyStyle={{ padding: 0 }}>预留 · 未启用 }, { key: '邮件(Email)', value: 预留 · 未启用 }, @@ -406,13 +413,10 @@ export default function AlertsPage() { const [filters, setFilterState] = useState(initialFilters); const [eventDraft, setEventDraft] = useState(initialFilters); const rules = useQuery({ queryKey: ['alert-rules-v2'], queryFn: ({ signal }) => api.alertRulesV2(signal), staleTime: 30_000, gcTime: QUERY_MEMORY.summaryGcTime, enabled: activeTab !== 'notifications' }); const metrics = useQuery({ queryKey: ['metric-catalog-v2'], queryFn: ({ signal }) => api.metricCatalog(signal), staleTime: 300_000, enabled: activeTab === 'rules' }); - const notices = useQuery({ queryKey: ['alert-notifications-v2', 'unread'], queryFn: ({ signal }) => api.alertNotificationsV2(new URLSearchParams({ unreadOnly: 'true', limit: '100' }), signal), staleTime: 5_000, gcTime: QUERY_MEMORY.summaryGcTime, enabled: activeTab !== 'notifications' }); - const notifications = useQuery({ queryKey: ['alert-notifications-v2', 'all'], queryFn: ({ signal }) => api.alertNotificationsV2(new URLSearchParams({ limit: '100' }), signal), staleTime: 5_000, gcTime: QUERY_MEMORY.summaryGcTime, enabled: activeTab === 'notifications' }); - const unread = activeTab === 'notifications' - ? notifications.data?.items.filter((item) => !item.read).length ?? notices.data?.total ?? 0 - : notices.data?.total ?? 0; + const notices = useQuery({ queryKey: ['alert-notifications-v2', 'unread'], queryFn: ({ signal }) => api.alertNotificationsV2(new URLSearchParams({ unreadOnly: 'true', limit: '1' }), signal), staleTime: 5_000, gcTime: QUERY_MEMORY.summaryGcTime }); + const unread = notices.data?.total ?? 0; const setTab = (next: Tab) => { setTabState(next); const copy = new URLSearchParams(params); copy.set('tab', next); setParams(copy, { replace: true }); }; const setFilters = (next: Filters) => { setFilterState(next); const copy = new URLSearchParams(); if (tab !== 'events') copy.set('tab', tab); Object.entries(next).forEach(([key, value]) => { if (value) copy.set(key, value); }); setParams(copy, { replace: true }); }; const tabs = [{ key: 'events' as const, label: '告警事件', icon: }, ...(admin ? [{ key: 'rules' as const, label: '规则配置' }] : []), { key: 'notifications' as const, label: '站内通知', icon: , count: unread || undefined }]; - return
{operator ? '可处置事件' : '只读查看'}{unread ? `${unread.toLocaleString('zh-CN')} 条未读` : '通知已读'}
{activeTab !== 'notifications' && rules.isError ? rules.refetch()} /> : null}{activeTab === 'rules' && metrics.isError ? metrics.refetch()} /> : null}{activeTab === 'events' ? : activeTab === 'rules' ? : }
; + return
{operator ? '可处置事件' : '只读查看'}{unread ? `${unread.toLocaleString('zh-CN')} 条未读` : '通知已读'}
{activeTab !== 'notifications' && rules.isError ? rules.refetch()} /> : null}{activeTab === 'rules' && metrics.isError ? metrics.refetch()} /> : null}{activeTab === 'events' ? : activeTab === 'rules' ? : }
; } diff --git a/vehicle-data-platform/apps/web/src/v2/styles/workspace.css b/vehicle-data-platform/apps/web/src/v2/styles/workspace.css index 5da195fd..6c1677ab 100644 --- a/vehicle-data-platform/apps/web/src/v2/styles/workspace.css +++ b/vehicle-data-platform/apps/web/src/v2/styles/workspace.css @@ -6589,42 +6589,42 @@ * command rail and reserves the remaining height for the operational list. */ .v2-alert-page { - gap: 9px; - padding: 12px 18px 16px; + gap: 12px; + padding: 14px 18px 18px; background: #f6f8fb; } .v2-alert-navigation { display: flex; - min-height: 46px; + min-height: 52px; flex: 0 0 auto; align-items: center; justify-content: space-between; gap: 14px; overflow: hidden; border: 1px solid #dce4ed; - border-radius: 10px; + border-radius: 12px; background: #fff; - padding: 4px 8px 4px 4px; - box-shadow: 0 3px 12px rgba(31, 53, 80, .04); + padding: 5px 10px 5px 5px; + box-shadow: 0 5px 18px rgba(31, 53, 80, .045); } .v2-alert-navigation .v2-alert-tabs.v2-segmented-tabs { width: auto; - min-height: 36px; + min-height: 40px; flex: 0 1 auto; - grid-auto-columns: minmax(126px, 1fr); + grid-auto-columns: minmax(136px, 1fr); border: 0; - border-radius: 7px; + border-radius: 9px; background: #f2f5f9; padding: 3px; box-shadow: none; } .v2-alert-navigation .v2-alert-tabs.v2-segmented-tabs > .semi-button { - min-height: 32px; - border-radius: 6px; - font-size: 12px; + min-height: 34px; + border-radius: 7px; + font-size: 13px; } .v2-alert-navigation-meta { @@ -6638,13 +6638,13 @@ .v2-alert-navigation-meta > .semi-typography { color: #7d899a; - font-size: 11px; + font-size: 12px; } .v2-alert-navigation-meta > .semi-tag { - min-height: 24px; + min-height: 26px; border-radius: 6px; - font-size: 10px; + font-size: 11px; } .v2-alert-filter-card.semi-card, @@ -6655,8 +6655,8 @@ .v2-alert-rule-editor.semi-card, .v2-alert-notifications.semi-card { border-color: #dce4ed; - border-radius: 9px; - box-shadow: 0 3px 14px rgba(31, 53, 80, .045); + border-radius: 12px; + box-shadow: 0 5px 18px rgba(31, 53, 80, .045); } .v2-alert-filter-card.semi-card { @@ -6668,33 +6668,35 @@ } .v2-alert-filter.v2-alert-filter-primary { - min-height: 60px; + min-height: 70px; grid-template-columns: minmax(250px, 1.45fr) minmax(122px, .62fr) minmax(136px, .68fr) auto auto auto; - gap: 8px; - padding: 9px 11px; + gap: 10px; + padding: 11px 13px; } .v2-alert-filter.v2-alert-filter-primary label { - gap: 4px; - font-size: 10px; + gap: 5px; + color: #66778e; + font-size: 11px; + font-weight: 600; } .v2-alert-filter.v2-alert-filter-primary label > div, .v2-alert-filter.v2-alert-filter-primary .semi-select, .v2-alert-filter.v2-alert-filter-primary .semi-input-wrapper, .v2-alert-filter.v2-alert-filter-primary > .semi-button { - min-height: 34px; - border-radius: 7px; + min-height: 38px; + border-radius: 8px; } .v2-alert-filter.v2-alert-filter-primary .semi-input, .v2-alert-filter.v2-alert-filter-primary .semi-select-selection-text, .v2-alert-filter.v2-alert-filter-primary > .semi-button { - font-size: 12px; + font-size: 13px; } .v2-alert-context-card.semi-card { - min-height: 64px; + min-height: 76px; flex: 0 0 auto; overflow: hidden; } @@ -6702,54 +6704,54 @@ .v2-alert-context-card > .semi-card-body { display: grid; height: 100%; - grid-template-columns: minmax(0, 1fr) 278px; + grid-template-columns: minmax(0, 1fr) 300px; } .v2-alert-context-card .v2-alert-kpis, .v2-alert-context-card .v2-alert-kpis .v2-metric-action-content { - min-height: 64px; + min-height: 76px; } .v2-alert-context-card .v2-alert-kpis small { - font-size: 10px; + font-size: 11px; } .v2-alert-context-card .v2-alert-kpis strong { - margin-top: 5px; - font-size: 19px; + margin-top: 7px; + font-size: 22px; } .v2-alert-context-card .v2-alert-secondary-states { - padding: 6px; - gap: 4px; + padding: 8px; + gap: 6px; } .v2-alert-context-card .v2-alert-secondary-states > .semi-button { - border-radius: 6px; - padding: 5px 6px; + border-radius: 8px; + padding: 7px 8px; } .v2-alert-context-card .v2-alert-secondary-states span { - font-size: 9px; + font-size: 10px; } .v2-alert-context-card .v2-alert-secondary-states b { - font-size: 14px; + font-size: 16px; } .v2-alert-workspace { min-height: 0; flex: 1 1 0; - gap: 9px; + gap: 12px; } .v2-alert-workspace.is-inspector-open { - grid-template-columns: minmax(680px, 1fr) 370px; + grid-template-columns: minmax(680px, 1fr) 390px; } .v2-alert-table-card > .semi-card-body > .v2-workspace-panel-header { - min-height: 48px; - padding: 7px 12px; + min-height: 54px; + padding: 8px 14px; } .v2-alert-table-card .v2-workspace-panel-copy { @@ -6757,18 +6759,18 @@ } .v2-alert-table-card .v2-workspace-panel-copy > h5.semi-typography { - font-size: 14px; + font-size: 15px; } .v2-alert-table-card .v2-workspace-panel-copy > .semi-typography { color: #8793a4; - font-size: 9px; + font-size: 10px; } .v2-alert-table-card .v2-workspace-panel-actions > .semi-button { - min-height: 30px; - border-radius: 6px; - font-size: 11px; + min-height: 34px; + border-radius: 8px; + font-size: 12px; } .v2-alert-table-scroll { @@ -6789,26 +6791,28 @@ } .v2-alert-table-scroll .v2-alert-event-table.semi-table-wrapper .semi-table-thead > .semi-table-row > .semi-table-row-head { - height: 38px; + height: 42px; background: #f7f9fc; - font-size: 10px; -} - -.v2-alert-table-scroll .v2-alert-event-table.semi-table-wrapper .semi-table-tbody > .semi-table-row > .semi-table-row-cell { - height: 46px; - padding: 6px 9px; + color: #5e7087; font-size: 11px; } +.v2-alert-table-scroll .v2-alert-event-table.semi-table-wrapper .semi-table-tbody > .semi-table-row > .semi-table-row-cell { + height: 52px; + padding: 7px 10px; + color: #47586e; + font-size: 12px; +} + .v2-alert-table-card > .semi-card-body > footer { - min-height: 42px; - padding: 5px 10px; + min-height: 46px; + padding: 6px 12px; } .v2-alert-table-card > .semi-card-body > footer button, .v2-alert-table-card > .semi-card-body > footer select { - height: 28px; - font-size: 11px; + height: 32px; + font-size: 12px; } .v2-alert-inspector.semi-card { @@ -6823,16 +6827,16 @@ } .v2-alert-inspector > .semi-card-body > .v2-alert-inspector-heading { - min-height: 58px; - padding: 8px 11px; + min-height: 64px; + padding: 10px 13px; } .v2-alert-inspector-content { min-height: 0; flex: 1 1 auto; - gap: 0; + gap: 10px; overflow: auto; - padding: 0 10px 10px; + padding: 10px; } .v2-alert-inspector-content > .v2-alert-detail-card.semi-card { @@ -6841,22 +6845,20 @@ } .v2-alert-detail-card.semi-card { - border-width: 0 0 1px; - border-color: #e4e9f0; - border-radius: 0; - background: transparent; - box-shadow: none; + overflow: hidden; + border: 1px solid #dfe6ef; + border-radius: 10px; + background: #fff; + box-shadow: 0 3px 12px rgba(31, 53, 80, .035); } .v2-alert-detail-card > .semi-card-header { - min-height: 40px; - border-bottom: 0; - padding: 0 2px; + min-height: 44px; + border-bottom: 1px solid #e8edf3; + padding: 0 12px; } .v2-alert-detail-card > .semi-card-body { - border: 1px solid #e1e7ef; - border-radius: 7px; background: #fff; } @@ -6866,19 +6868,19 @@ } .v2-alert-inspector > .semi-card-body > .v2-alert-links { - min-height: 46px; - padding: 6px 10px; + min-height: 50px; + padding: 7px 10px; } .v2-alert-inspector > .semi-card-body > .v2-alert-links a { - min-height: 32px; + min-height: 34px; } .v2-alert-rules { min-height: 0; flex: 1 1 0; - grid-template-columns: minmax(300px, 340px) minmax(600px, 1fr); - gap: 9px; + grid-template-columns: minmax(320px, 350px) minmax(620px, 1fr); + gap: 12px; } .v2-alert-rule-list.semi-card, @@ -6915,40 +6917,80 @@ .v2-alert-rule-list > .semi-card-body > .v2-alert-rule-list-heading, .v2-alert-rule-editor-form > .v2-alert-rule-editor-heading { - min-height: 56px; - padding: 8px 12px; + min-height: 60px; + padding: 9px 14px; } .v2-alert-rule-item.semi-button { - min-height: 68px; - padding: 8px 11px; + min-height: 74px; + padding: 10px 13px; } .v2-alert-rule-copy > small { - margin-top: 5px; + margin-top: 6px; } .v2-alert-rule-templates { - padding: 11px 12px; + grid-template-columns: minmax(0, 1fr); + align-items: stretch; + gap: 9px; + padding: 13px 14px 14px; +} + +.v2-alert-rule-templates > div { + gap: 3px; +} + +.v2-alert-rule-templates > nav { + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 10px; } .v2-alert-template-card.semi-button { - min-height: 72px; - padding: 9px; + min-height: 94px; + padding: 11px; +} + +.v2-alert-template-card.semi-button .semi-button-content { + grid-template-columns: 38px minmax(0, 1fr); + align-content: center; + row-gap: 7px; +} + +.v2-alert-template-card .v2-alert-template-icon { + grid-row: 1 / span 2; +} + +.v2-alert-template-card .v2-alert-template-copy { + grid-column: 2; +} + +.v2-alert-template-card .v2-alert-template-copy small { + display: -webkit-box; + white-space: normal; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; +} + +.v2-alert-template-card .semi-tag { + max-width: 100%; + grid-column: 2; + justify-self: start; + font-size: 9px; } .v2-rule-form-grid { - gap: 11px 13px; - padding: 13px 14px 16px; + gap: 13px 15px; + padding: 16px 16px 18px; } .v2-alert-rule-editor-form > footer { position: sticky; z-index: 3; bottom: 0; - min-height: 56px; + min-height: 60px; background: rgba(255, 255, 255, .97); - padding: 8px 14px; + padding: 9px 16px; backdrop-filter: blur(10px); } @@ -6963,24 +7005,40 @@ height: 100%; min-height: 0; max-height: none; - grid-template-rows: 54px minmax(0, 1fr) auto; + grid-template-rows: 60px minmax(0, 1fr) 48px auto; overflow: hidden; } .v2-alert-notifications > .semi-card-body > .v2-workspace-panel-header { - min-height: 54px; - padding: 8px 12px; + min-height: 60px; + padding: 10px 14px; } .v2-alert-notification-list { min-height: 0; overflow: auto; - padding: 9px; + padding: 12px; } .v2-alert-notification-cards.semi-card-group { grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 9px; + gap: 11px; +} + +.v2-alert-notification-card.semi-card { + content-visibility: auto; + contain-intrinsic-size: auto 132px; +} + +.v2-alert-notification-pagination { + display: flex; + min-height: 48px; + align-items: center; + justify-content: space-between; + gap: 12px; + border-top: 1px solid #e4eaf1; + background: #fff; + padding: 6px 12px; } .v2-alert-channel-card.semi-card { @@ -6990,12 +7048,12 @@ } .v2-alert-channel-card > .semi-card-header { - min-height: 34px; - padding: 0 12px; + min-height: 38px; + padding: 0 14px; } .v2-alert-channel-descriptions.semi-descriptions { - padding: 5px 9px 8px; + padding: 6px 11px 9px; } .v2-alert-channel-descriptions table { @@ -7011,14 +7069,14 @@ .v2-alert-channel-descriptions tr { display: flex; min-width: 0; - min-height: 32px; + min-height: 34px; align-items: center; justify-content: space-between; gap: 6px; border: 1px solid #e4e9f0; border-radius: 6px; background: #fafbfd; - padding: 4px 7px; + padding: 5px 8px; } .v2-alert-channel-descriptions .semi-descriptions-item { @@ -7031,6 +7089,15 @@ padding-right: 0; } +.v2-alert-channel-descriptions .semi-descriptions-key, +.v2-alert-channel-descriptions .semi-descriptions-value { + font-size: 10px; +} + +.v2-alert-channel-descriptions .semi-tag { + font-size: 9px; +} + @media (max-width: 1180px) and (min-width: 681px) { .v2-alert-filter.v2-alert-filter-primary { grid-template-columns: minmax(220px, 1fr) 120px 130px auto auto auto; @@ -7061,9 +7128,9 @@ @media (max-width: 680px) { .v2-alert-page { - gap: 8px; + gap: 10px; overflow: auto; - padding: 8px 7px 16px; + padding: 9px 8px 16px; } .v2-alert-page.is-events { @@ -7077,23 +7144,23 @@ position: sticky; z-index: 8; top: 0; - min-height: 46px; - border-radius: 9px; - padding: 3px; + min-height: 50px; + border-radius: 11px; + padding: 4px; } .v2-alert-navigation .v2-alert-tabs.v2-segmented-tabs { position: static; width: 100%; - min-height: 38px; + min-height: 42px; grid-auto-columns: minmax(104px, 1fr); overflow-x: auto; } .v2-alert-navigation .v2-alert-tabs.v2-segmented-tabs > .semi-button { - min-height: 32px; + min-height: 36px; padding-inline: 7px; - font-size: 10px; + font-size: 11px; } .v2-alert-navigation-meta { @@ -7108,7 +7175,7 @@ min-height: 0; grid-template-columns: 1fr 1fr; gap: 8px; - padding: 9px; + padding: 10px; } .v2-alert-filter.v2-alert-filter-primary label:first-child { @@ -7124,7 +7191,7 @@ } .v2-alert-context-card.semi-card { - min-height: 94px; + min-height: 104px; } .v2-alert-context-card > .semi-card-body { @@ -7132,14 +7199,14 @@ } .v2-alert-context-card .v2-alert-kpis { - height: 58px; - min-height: 58px; + height: 64px; + min-height: 64px; grid-template-columns: repeat(4, minmax(0, 1fr)); } .v2-alert-context-card .v2-alert-kpis .v2-metric-action, .v2-alert-context-card .v2-alert-kpis .v2-metric-action-content { - min-height: 58px; + min-height: 64px; } .v2-alert-context-card .v2-alert-kpis .v2-metric-action { @@ -7157,32 +7224,32 @@ } .v2-alert-context-card .v2-alert-kpis small { - font-size: 8px; + font-size: 9px; } .v2-alert-context-card .v2-alert-kpis strong { margin-top: 0; - font-size: 16px; + font-size: 18px; } .v2-alert-context-card .v2-alert-secondary-states { - min-height: 34px; + min-height: 40px; border-top: 1px solid #e4e9f0; border-left: 0; padding: 3px 4px; } .v2-alert-context-card .v2-alert-secondary-states > .semi-button { - min-height: 30px; + min-height: 34px; padding: 2px 5px; } .v2-alert-context-card .v2-alert-secondary-states span { - font-size: 8px; + font-size: 9px; } .v2-alert-context-card .v2-alert-secondary-states b { - font-size: 12px; + font-size: 13px; } .v2-alert-page.is-events .v2-alert-workspace { @@ -7236,8 +7303,8 @@ } .v2-alert-mobile-list { - gap: 6px; - padding: 6px; + gap: 8px; + padding: 8px; } .v2-alert-mobile-list > .v2-alert-mobile-card.semi-card { @@ -7246,11 +7313,11 @@ } .v2-alert-mobile-card-content { - padding: 8px 9px; + padding: 10px 11px; } .v2-alert-mobile-card-content header > strong { - font-size: 13px; + font-size: 14px; } .v2-alert-mobile-card-content header > span { @@ -7259,19 +7326,19 @@ .v2-alert-mobile-card-content .v2-alert-severity.semi-tag, .v2-alert-mobile-card-content .v2-alert-status.semi-tag { - height: 20px; - min-height: 20px; - border-radius: 5px; - padding-inline: 5px; - font-size: 8px; + height: 22px; + min-height: 22px; + border-radius: 6px; + padding-inline: 6px; + font-size: 9px; } .v2-alert-mobile-card-content p { - margin: 4px 0 5px; + margin: 6px 0 7px; overflow: hidden; color: #405168; - font-size: 11px; - line-height: 14px; + font-size: 12px; + line-height: 16px; text-overflow: ellipsis; white-space: nowrap; } @@ -7279,13 +7346,13 @@ .v2-alert-mobile-card-content dl { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0; - padding-top: 6px; + padding-top: 7px; } .v2-alert-mobile-card-content dl > div { display: block; min-width: 0; - min-height: 28px; + min-height: 32px; padding: 0 5px; } @@ -7299,7 +7366,7 @@ .v2-alert-mobile-card-content dt { overflow: hidden; - font-size: 8px; + font-size: 9px; text-overflow: ellipsis; white-space: nowrap; } @@ -7308,8 +7375,8 @@ min-width: 0; margin: 3px 0 0; overflow: hidden; - font-size: 9px; - line-height: 12px; + font-size: 10px; + line-height: 13px; text-align: left; text-overflow: ellipsis; white-space: nowrap; @@ -7361,10 +7428,35 @@ flex: none; } + .v2-alert-notifications > .semi-card-body { + grid-template-rows: 58px minmax(320px, 1fr) 76px auto; + } + .v2-alert-notification-cards.semi-card-group { grid-template-columns: 1fr; } + .v2-alert-notification-pagination { + min-height: 76px; + align-items: stretch; + justify-content: center; + flex-direction: column; + gap: 7px; + padding: 8px 10px; + } + + .v2-alert-notification-pagination .v2-table-pagination-info { + width: 100%; + } + + .v2-alert-notification-pagination .v2-table-pagination-controls { + width: 100%; + } + + .v2-alert-notification-pagination .v2-table-pagination { + flex: 1 1 auto; + } + .v2-alert-channel-descriptions tbody { display: table-row-group; }