From 09b7fd4ad50c82cf17df464d3e151b6228fa578f Mon Sep 17 00:00:00 2001 From: attacker Date: Mon, 13 Jul 2026 04:20:10 +0800 Subject: [PATCH] =?UTF-8?q?refactor(i18n):=20U36=20=E5=85=A8=E9=87=8F=20JS?= =?UTF-8?q?X=20=E5=B1=9E=E6=80=A7=20+=20toast=20=E7=A1=AC=E7=BC=96?= =?UTF-8?q?=E7=A0=81=E4=B8=AD=E6=96=87=E6=B8=85=E9=9B=B6=20=E2=80=94=2020?= =?UTF-8?q?=20=E6=96=87=E4=BB=B6=2030=20=E5=A4=84=20=E2=86=92=200?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 清理 23 处 JSX 属性 (title/placeholder/label/description) + 7 处 toast 调用硬编码中文: - Deploy 模块 (AppRelease/DeployCredentials/PipelineManager/WorkspaceTermDialog/CredFormDialog/JobRoleCreateDialog/PipelineCreateDialog/AdvancedSettingsPanel) - Server 模块 (ServerForm) - System 模块 (LdapManagementSection/LiveMonitorDialog/SystemManager) - Audit 模块 (ActiveSessionsPanel/HistorySessionsPanel) - Monitor 模块 (AlertRulesTab/PrometheusDatasourceManager/SNMPMonitor) - AIOps 模块 (PredictiveCapacityTab) - Common/UI (TerminalLoadingOverlay/copy-button) 新增 25 翻译键 (common.connectingEllipsis/enteringWorkspace/connectingMonitor + deploy.* 11键 + server.jsonFormatPlaceholder + system.* 3键 + audit.* 2键 + monitor.* 3键 + aiops.aiAnalysisFailedToast + pipeline.subtitle) copy-button.tsx 从 import i18n → useTranslation() hook 3 组件新增 useTranslation hook (TerminalLoadingOverlay/WorkspaceTermDialog/LiveMonitorDialog/PredictiveCapacityTab) zh/en 7616→7640 +24 对齐, tsc -b=0, npm build✓ (17.25s), ESLint=0/43/0, go build=0, 17/17 测试通过 --- .../aiops/PredictiveCapacityTab.tsx | 4 +- .../common/TerminalLoadingOverlay.tsx | 6 ++- frontend/src/components/deploy/AppRelease.tsx | 4 +- .../components/deploy/DeployCredentials.tsx | 4 +- .../src/components/deploy/PipelineManager.tsx | 4 +- .../components/deploy/WorkspaceTermDialog.tsx | 4 +- .../credential-manager/CredFormDialog.tsx | 10 ++--- .../deploy-rbac/JobRoleCreateDialog.tsx | 2 +- .../pipeline-manager/PipelineCreateDialog.tsx | 4 +- .../pipeline-create/AdvancedSettingsPanel.tsx | 2 +- .../src/components/monitor/AlertRulesTab.tsx | 2 +- .../PrometheusDatasourceManager.tsx | 2 +- frontend/src/components/server/ServerForm.tsx | 2 +- .../system/LdapManagementSection.tsx | 4 +- .../components/system/LiveMonitorDialog.tsx | 4 +- .../src/components/system/SystemManager.tsx | 2 +- frontend/src/components/ui/copy-button.tsx | 19 +++++---- frontend/src/locales/en-US.json | 42 +++++++++++++++---- frontend/src/locales/zh-CN.json | 42 +++++++++++++++---- .../terminal-audit/ActiveSessionsPanel.tsx | 2 +- .../terminal-audit/HistorySessionsPanel.tsx | 2 +- frontend/src/pages/monitor/SNMPMonitor.tsx | 2 +- 22 files changed, 114 insertions(+), 55 deletions(-) diff --git a/frontend/src/components/aiops/PredictiveCapacityTab.tsx b/frontend/src/components/aiops/PredictiveCapacityTab.tsx index 66dd09c..3a54461 100644 --- a/frontend/src/components/aiops/PredictiveCapacityTab.tsx +++ b/frontend/src/components/aiops/PredictiveCapacityTab.tsx @@ -4,6 +4,7 @@ import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { toast } from 'sonner'; +import { useTranslation } from 'react-i18next'; import { aiApi } from '@/api'; import { buildCapacityInsightPrompt, type CapacityForecast } from './predictUtils'; import { AgentMarkdown, looksLikeMarkdown } from './AgentMarkdown'; @@ -15,6 +16,7 @@ export function PredictiveCapacityTab({ forecasts: CapacityForecast[]; loading: boolean; }) { + const { t } = useTranslation(); const [insight, setInsight] = useState(''); const [analyzing, setAnalyzing] = useState(false); @@ -28,7 +30,7 @@ export function PredictiveCapacityTab({ const res = await aiApi.chat([{ role: 'user', content: prompt }]); setInsight(res?.content || ''); } catch { - toast.error('AI 解读失败,请检查大模型配置或稍后重试'); + toast.error(t('aiops.aiAnalysisFailedToast')); } finally { setAnalyzing(false); } diff --git a/frontend/src/components/common/TerminalLoadingOverlay.tsx b/frontend/src/components/common/TerminalLoadingOverlay.tsx index 9c54fb3..14deed8 100644 --- a/frontend/src/components/common/TerminalLoadingOverlay.tsx +++ b/frontend/src/components/common/TerminalLoadingOverlay.tsx @@ -1,5 +1,6 @@ import { Loader2 } from 'lucide-react'; import { cn } from '@/lib/utils'; +import { useTranslation } from 'react-i18next'; interface TerminalLoadingOverlayProps { show: boolean; @@ -7,14 +8,15 @@ interface TerminalLoadingOverlayProps { className?: string; } -export function TerminalLoadingOverlay({ show, label = '连接中...', className }: TerminalLoadingOverlayProps) { +export function TerminalLoadingOverlay({ show, label, className }: TerminalLoadingOverlayProps) { + const { t } = useTranslation(); if (!show) return null; return (
- {label && {label}} + {label && {label || t('common.connectingEllipsis')}}
); diff --git a/frontend/src/components/deploy/AppRelease.tsx b/frontend/src/components/deploy/AppRelease.tsx index 034d3cd..f5d79f8 100644 --- a/frontend/src/components/deploy/AppRelease.tsx +++ b/frontend/src/components/deploy/AppRelease.tsx @@ -100,7 +100,7 @@ export function AppReleaseManager() { {/* 用户名(左上)与密码(左下)同列上下行,安全模式/域归右列 // Logan.Li */} -
+
- setRdpDomain(e.target.value)} placeholder="可选" + setRdpDomain(e.target.value)} placeholder={t('common.optional')} className="bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)] text-[var(--dg-text-primary)]" />
diff --git a/frontend/src/components/deploy/deploy-rbac/JobRoleCreateDialog.tsx b/frontend/src/components/deploy/deploy-rbac/JobRoleCreateDialog.tsx index 13a6bbd..ffc7dbc 100644 --- a/frontend/src/components/deploy/deploy-rbac/JobRoleCreateDialog.tsx +++ b/frontend/src/components/deploy/deploy-rbac/JobRoleCreateDialog.tsx @@ -89,7 +89,7 @@ export function JobRoleCreateDialog({ onPatternChange(e.target.value)} - placeholder="^cex-.* 或 ^api-server$" + placeholder={t('deploy.jobNamePatternHint')} className="h-8 text-sm font-mono dg-input" />

{patternHint}

diff --git a/frontend/src/components/deploy/pipeline-manager/PipelineCreateDialog.tsx b/frontend/src/components/deploy/pipeline-manager/PipelineCreateDialog.tsx index 0f142c4..66e6d1a 100644 --- a/frontend/src/components/deploy/pipeline-manager/PipelineCreateDialog.tsx +++ b/frontend/src/components/deploy/pipeline-manager/PipelineCreateDialog.tsx @@ -371,7 +371,7 @@ export function PipelineCreateDialog({ open, onOpenChange, onCreated }: Pipeline onValueChange={(v) => setNewGitCredentialId(v === '__none' ? '' : v)} > - + {t('deploy.notLinked')} @@ -396,7 +396,7 @@ export function PipelineCreateDialog({ open, onOpenChange, onCreated }: Pipeline onValueChange={(v) => setNewRegistryCredentialId(v === '__none' ? '' : v)} > - + 不关联 diff --git a/frontend/src/components/deploy/pipeline-manager/pipeline-create/AdvancedSettingsPanel.tsx b/frontend/src/components/deploy/pipeline-manager/pipeline-create/AdvancedSettingsPanel.tsx index 215262d..c3ef69d 100644 --- a/frontend/src/components/deploy/pipeline-manager/pipeline-create/AdvancedSettingsPanel.tsx +++ b/frontend/src/components/deploy/pipeline-manager/pipeline-create/AdvancedSettingsPanel.tsx @@ -106,7 +106,7 @@ export function AdvancedSettingsPanel({ onWatchBranchesChange(e.target.value)} - placeholder="监听分支,如 main, release/*" + placeholder={t('deploy.branchListenPlaceholder')} className="h-8 text-xs font-mono dg-input" /> )} diff --git a/frontend/src/components/monitor/AlertRulesTab.tsx b/frontend/src/components/monitor/AlertRulesTab.tsx index f609369..e14a00f 100644 --- a/frontend/src/components/monitor/AlertRulesTab.tsx +++ b/frontend/src/components/monitor/AlertRulesTab.tsx @@ -82,7 +82,7 @@ export function AlertRulesTab({ if (!ok) return; try { await alertApi.batchDeleteRules(selectedIds); - toast.success(`已删除 ${selectedIds.length} 条告警规则`); + toast.success(i18n.t('monitor.deletedRules', { count: selectedIds.length })); setSelectedIds([]); onReload(); } catch (error) { diff --git a/frontend/src/components/monitor/datasource/PrometheusDatasourceManager.tsx b/frontend/src/components/monitor/datasource/PrometheusDatasourceManager.tsx index 52415ea..6db3904 100644 --- a/frontend/src/components/monitor/datasource/PrometheusDatasourceManager.tsx +++ b/frontend/src/components/monitor/datasource/PrometheusDatasourceManager.tsx @@ -65,7 +65,7 @@ export default function PrometheusDatasourceManager() { const handleSetDefault = async (ds: PromDS) => { try { await setDefaultMutation.mutateAsync(ds.id); - toast.success(`已将「${ds.name}」设为默认数据源`); + toast.success(i18n.t('monitor.setDefaultDsSuccess', { name: ds.name })); } catch { toast.error(i18n.t('monitor.promDs2.deleteFailed')); } diff --git a/frontend/src/components/server/ServerForm.tsx b/frontend/src/components/server/ServerForm.tsx index fdbcaf8..ffd0186 100644 --- a/frontend/src/components/server/ServerForm.tsx +++ b/frontend/src/components/server/ServerForm.tsx @@ -396,7 +396,7 @@ export function ServerForm({
setFormData({ ...formData, tags: e.target.value })} className="bg-[var(--dg-bg-tertiary)] border-[var(--dg-border)] text-[var(--dg-text-primary)] placeholder:text-[var(--dg-text-muted)] font-mono text-sm" diff --git a/frontend/src/components/system/LdapManagementSection.tsx b/frontend/src/components/system/LdapManagementSection.tsx index ff9a1c8..ffe7720 100644 --- a/frontend/src/components/system/LdapManagementSection.tsx +++ b/frontend/src/components/system/LdapManagementSection.tsx @@ -288,7 +288,7 @@ export function LdapManagementSection(props: LdapManagementSectionProps) {
- setNewUser({ ...newUser, display_name: e.target.value })} placeholder="张三" className="dg-input" /> + setNewUser({ ...newUser, display_name: e.target.value })} placeholder={t('system.namePlaceholder')} className="dg-input" />
@@ -450,7 +450,7 @@ export function LdapManagementSection(props: LdapManagementSectionProps) {
- setEditLdapForm({ ...editLdapForm, title: e.target.value })} placeholder="运维工程师" className="dg-input" /> + setEditLdapForm({ ...editLdapForm, title: e.target.value })} placeholder={t('system.roleTitlePlaceholder')} className="dg-input" />
)} diff --git a/frontend/src/components/system/LiveMonitorDialog.tsx b/frontend/src/components/system/LiveMonitorDialog.tsx index 84401e8..59fdf08 100644 --- a/frontend/src/components/system/LiveMonitorDialog.tsx +++ b/frontend/src/components/system/LiveMonitorDialog.tsx @@ -1,5 +1,6 @@ // 终端审计实时监控 Dialog — 与 WebSSH 终端弹框一致的布局与适配 // Logan.Li import { useEffect, useRef, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { Terminal as XTerm } from 'xterm'; import { FitAddon } from 'xterm-addon-fit'; import 'xterm/css/xterm.css'; @@ -33,6 +34,7 @@ interface LiveMonitorProps { } export function LiveMonitorDialog({ open, onOpenChange, sessionId, sessionInfo }: LiveMonitorProps) { + const { t } = useTranslation(); const containerRef = useRef(null); const termRef = useRef(null); const fitRef = useRef(null); @@ -250,7 +252,7 @@ export function LiveMonitorDialog({ open, onOpenChange, sessionId, sessionInfo }
- +
diff --git a/frontend/src/components/system/SystemManager.tsx b/frontend/src/components/system/SystemManager.tsx index 448db0d..2ca03de 100644 --- a/frontend/src/components/system/SystemManager.tsx +++ b/frontend/src/components/system/SystemManager.tsx @@ -237,7 +237,7 @@ export function SystemManager() { const res = (await userApi.batchDelete(selectedUserIds)) as { message?: string; }; - toast.success(res?.message || `已删除 ${selectedUserIds.length} 个用户`); + toast.success(res?.message || t('system.batchDeleteUsers', { count: selectedUserIds.length })); setSelectedUserIds([]); await loadUsers(); } catch (error: unknown) { diff --git a/frontend/src/components/ui/copy-button.tsx b/frontend/src/components/ui/copy-button.tsx index 5b9256c..4252aa6 100644 --- a/frontend/src/components/ui/copy-button.tsx +++ b/frontend/src/components/ui/copy-button.tsx @@ -5,7 +5,7 @@ import { Button } from '@/components/ui/button'; import { useToast } from '@/hooks/use-toast'; import { copyToClipboard } from '@/utils/clipboard'; import { cn } from '@/lib/utils'; -import i18n from '@/i18n'; +import { useTranslation } from 'react-i18next'; export interface CopyButtonProps { text: string; @@ -22,14 +22,17 @@ export interface CopyButtonProps { export function CopyButton({ text, - label = '已复制', + label, children, className, size = 'sm', variant = 'outline', disabled, - title = '复制', + title, }: CopyButtonProps) { + const { t } = useTranslation(); + const resolvedLabel = label ?? t('common.copied'); + const resolvedTitle = title ?? t('common.copy'); const { toast } = useToast(); const [copied, setCopied] = useState(false); @@ -37,12 +40,12 @@ export function CopyButton({ const ok = await copyToClipboard(text); if (ok) { setCopied(true); - toast({ title: label }); + toast({ title: resolvedLabel }); setTimeout(() => setCopied(false), 2000); } else { toast({ - title: i18n.t('monitor.logPanel.copyFailed'), - description: i18n.t('common.copyManually'), + title: t('monitor.logPanel.copyFailed'), + description: t('common.copyManually'), variant: 'destructive', }); } @@ -61,8 +64,8 @@ export function CopyButton({ )} onClick={handleCopy} disabled={disabled || !text} - title={title} - aria-label={title} + title={resolvedTitle} + aria-label={resolvedTitle} > {copied ? ( diff --git a/frontend/src/locales/en-US.json b/frontend/src/locales/en-US.json index 4c420b3..beeff2b 100644 --- a/frontend/src/locales/en-US.json +++ b/frontend/src/locales/en-US.json @@ -516,7 +516,10 @@ "seconds": "sec", "copyManually": "Please manually select and copy", "scrollToTop": "Scroll to top", - "scrollToBottom": "Scroll to bottom" + "scrollToBottom": "Scroll to bottom", + "connectingEllipsis": "Connecting...", + "enteringWorkspace": "Entering workspace...", + "connectingMonitor": "Connecting to monitor..." }, "menu": { "dashboard": "Dashboard", @@ -1142,7 +1145,8 @@ "loadDirFailed": "Failed to load directory", "downloadFailed": "Download failed: ", "directory": "Directory" - } + }, + "jsonFormatPlaceholder": "JSON format, e.g. {\"key\":\"value\"}" }, "alert": { "stat": { @@ -1510,7 +1514,9 @@ } }, "reportTitle": "Terminal Session Audit Report", - "csvHeader": "Time,User,Command,Output Size,Session ID,Critical" + "csvHeader": "Time,User,Command,Output Size,Session ID,Critical", + "rdpRealtimeAudit": "RDP Real-time Audit", + "rdpHistoryReplay": "RDP History Replay" }, "deploy": { "pipeline": { @@ -2408,7 +2414,19 @@ "copyRef": "Copy Reference ID", "testConn": "Test Connection", "noTags": "No tags" - } + }, + "placeholderEnv": "Environment", + "placeholderStatus": "Status", + "noEnvConfig": "No environment configuration", + "clickEnvConfigHint": "Click \"Add Environment\" to create", + "rdpPassword": "Windows Password", + "rdpPasswordPlaceholder": "Windows login password", + "selectCredentialPlaceholder": "Select credential", + "dockerCredPlaceholder": "Docker credential", + "branchListenPlaceholder": "Listen branches, e.g. main, release/*", + "rdpUserRequired": "Please fill in RDP username", + "rdpPasswordRequired": "Please fill in RDP password", + "jobNamePatternHint": "^cex-.* or ^api-server$" }, "k8s": { "cluster": { @@ -5075,7 +5093,10 @@ "configDesc": "Configure Zabbix API connection to get host monitoring data", "directDb": "Direct DB Connection", "emptyDatasource": "No Zabbix data sources" - } + }, + "deletedRules": "Deleted {{count}} alert rules", + "setDefaultDsSuccess": "Set \"{{name}}\" as default datasource", + "collectSuccess": "{{name}} collection success" }, "task": { "cronJob": { @@ -6134,7 +6155,7 @@ }, "pipeline": { "title": "Pipelines", - "subtitle": "CI/CD Build · Deploy · Release All-in-One", + "subtitle": "CI/CD build, image packaging & dual-channel deployment", "pipelines": "Pipelines", "addPipeline": "New Pipeline", "editPipeline": "Edit Pipeline", @@ -7374,7 +7395,7 @@ "savingDot": "Saving...", "recordAllOps": "Record All Operations", "searchFilterHint": "Search filter (optional, use %s for username)", - "batchDeleteUsers": "Batch Delete Users", + "batchDeleteUsers": "Deleted {{count}} users", "forcePasswordComplexity": "Enforce Password Complexity", "systemVersion": "System Version", "saveConfig": "Save Configuration", @@ -7530,7 +7551,9 @@ "importSelected": "Import ({{count}})", "importAll": "Import All ({{count}})", "editLdapUserDesc": "Modify attributes of {{uid}}", - "permEffectTrailing": ", changes take effect after user re-login." + "permEffectTrailing": ", changes take effect after user re-login.", + "namePlaceholder": "John Doe", + "roleTitlePlaceholder": "DevOps Engineer" }, "aiops": { "title": "AIOps", @@ -8238,7 +8261,8 @@ "predictUtils": { "dailyCostHint": "Review {{scope}}today's high-cost services, pause non-essential resources or adjust auto-scaling", "monthlyBillHint": "Review {{scope}}this month's bill composition, optimize storage/CDN/compute, reduce over-budget quotas" - } + }, + "aiAnalysisFailedToast": "AI analysis failed, please check LLM config or try again later" }, "breadcrumb": { "dashboard": "Dashboard", diff --git a/frontend/src/locales/zh-CN.json b/frontend/src/locales/zh-CN.json index b186e63..f171d05 100644 --- a/frontend/src/locales/zh-CN.json +++ b/frontend/src/locales/zh-CN.json @@ -516,7 +516,10 @@ "seconds": "秒", "copyManually": "请手动选中内容后复制", "scrollToTop": "回到顶部", - "scrollToBottom": "回到底部" + "scrollToBottom": "回到底部", + "connectingEllipsis": "连接中...", + "enteringWorkspace": "正在进入工作区...", + "connectingMonitor": "正在连接监控..." }, "menu": { "dashboard": "仪表盘", @@ -1142,7 +1145,8 @@ "loadDirFailed": "加载目录失败", "downloadFailed": "下载失败: ", "directory": "目录" - } + }, + "jsonFormatPlaceholder": "JSON 格式,如 {\"key\":\"value\"}" }, "alert": { "stat": { @@ -1510,7 +1514,9 @@ } }, "reportTitle": "终端会话审计报告", - "csvHeader": "时间,用户,命令,输出大小,会话ID,高危" + "csvHeader": "时间,用户,命令,输出大小,会话ID,高危", + "rdpRealtimeAudit": "RDP 实时审计", + "rdpHistoryReplay": "RDP 历史回放" }, "deploy": { "pipeline": { @@ -2408,7 +2414,19 @@ "copyRef": "复制引用ID", "testConn": "测试连接", "noTags": "无标签" - } + }, + "placeholderEnv": "环境", + "placeholderStatus": "状态", + "noEnvConfig": "暂无环境配置", + "clickEnvConfigHint": "点击\"新增环境\"创建", + "rdpPassword": "Windows 密码", + "rdpPasswordPlaceholder": "Windows 登录密码", + "selectCredentialPlaceholder": "选择凭证", + "dockerCredPlaceholder": "Docker 凭证", + "branchListenPlaceholder": "监听分支,如 main, release/*", + "rdpUserRequired": "请填写 RDP 用户", + "rdpPasswordRequired": "请填写 RDP 密码", + "jobNamePatternHint": "^cex-.* 或 ^api-server$" }, "k8s": { "cluster": { @@ -5075,7 +5093,10 @@ "configDesc": "配置 Zabbix API 连接,获取主机监控数据", "directDb": "直连DB", "emptyDatasource": "暂无 Zabbix 数据源" - } + }, + "deletedRules": "已删除 {{count}} 条告警规则", + "setDefaultDsSuccess": "已将「{{name}}」设为默认数据源", + "collectSuccess": "{{name}} 采集成功" }, "task": { "cronJob": { @@ -6134,7 +6155,7 @@ }, "pipeline": { "title": "流水线", - "subtitle": "CI/CD 构建 · 部署 · 发布一体化", + "subtitle": "CI/CD 构建、镜像打包与双通道部署", "pipelines": "流水线列表", "addPipeline": "新建流水线", "editPipeline": "编辑流水线", @@ -7374,7 +7395,7 @@ "savingDot": "保存中...", "recordAllOps": "记录所有操作", "searchFilterHint": "搜索过滤器(可选,用 %s 代表用户名)", - "batchDeleteUsers": "批量删除用户", + "batchDeleteUsers": "已删除 {{count}} 个用户", "forcePasswordComplexity": "强制密码复杂度", "systemVersion": "系统版本", "saveConfig": "保存配置", @@ -7530,7 +7551,9 @@ "importSelected": "导入 ({{count}})", "importAll": "导入全部 ({{count}})", "editLdapUserDesc": "修改 {{uid}} 的属性", - "permEffectTrailing": ",修改后用户需重新登录生效。" + "permEffectTrailing": ",修改后用户需重新登录生效。", + "namePlaceholder": "张三", + "roleTitlePlaceholder": "运维工程师" }, "aiops": { "title": "AIOps 智能", @@ -8238,7 +8261,8 @@ "predictUtils": { "dailyCostHint": "检查{{scope}}今日高消费服务,暂停非必要资源或调整弹性伸缩策略", "monthlyBillHint": "复盘{{scope}}本月账单构成,优化存储/CDN/计算规格,必要时下调预算外资源配额" - } + }, + "aiAnalysisFailedToast": "AI 解读失败,请检查大模型配置或稍后重试" }, "breadcrumb": { "dashboard": "仪表盘", diff --git a/frontend/src/pages/audit/terminal-audit/ActiveSessionsPanel.tsx b/frontend/src/pages/audit/terminal-audit/ActiveSessionsPanel.tsx index ce3b644..b14d9c8 100644 --- a/frontend/src/pages/audit/terminal-audit/ActiveSessionsPanel.tsx +++ b/frontend/src/pages/audit/terminal-audit/ActiveSessionsPanel.tsx @@ -138,7 +138,7 @@ function RdpActiveSessionRow({ -
diff --git a/frontend/src/pages/audit/terminal-audit/HistorySessionsPanel.tsx b/frontend/src/pages/audit/terminal-audit/HistorySessionsPanel.tsx index f04c583..63ba724 100644 --- a/frontend/src/pages/audit/terminal-audit/HistorySessionsPanel.tsx +++ b/frontend/src/pages/audit/terminal-audit/HistorySessionsPanel.tsx @@ -290,7 +290,7 @@ export function HistorySessionsPanel() { {getStatusBadge(s.status)}
-