feat(dashboard): lazy routes, Needs-you strip, URL state, exact numbers
- Workspace, SettingsHub, SessionDetail and the Workflow sub-tab are lazy (main bundle 2,166 kB -> ~920 kB), wrapped in RouteErrorBoundary: a stale chunk after a self-update reloads once (vite:preloadError too), any other error shows a Reload panel instead of a blank page. - Live refresh: lib/throttle.ts + hooks/useLiveRefresh.ts replace trailing debounces that froze under a steady event stream; refresh skips hidden tabs and refetches after a WebSocket reconnect. Monitor loads only while shown, with one batched GET /api/agents?session_ids= instead of N+1; a failing endpoint is an inline error, not a blank Dashboard. - NeedsYouStrip on Monitor and above Analytics. Tabs, filters, page, sort and search live in the URL (Dashboard, Sessions, Activity, SessionDetail). - Sessions: tool / workspace / date-range filters, CSV/JSON export (formula-neutralised), focusable row links, Open in workspace (the dead /run links are gone), stale responses dropped, error + Retry. - Fixes: "NaNs" durations, 30/7-day charts skipping idle days, weekday labels west of UTC (now averages), cache hit rate denominator, billable tokens vs cache reads, exact tool-call counts, "To" date = end of day, invalid ?from= no longer throws, recent list no longer shrinks to 15, stable message keys, transcript switch races. - Light-theme-unreadable bg-black code panels and dark-only DAG fills use tokens; status configs and chart colours use theme tokens; Health tab and other literals translated. - Server (additive): GET /api/agents?session_ids=, GET /api/sessions awaiting=1&from=&to=, stats tool_call_count/distinct_tool_count, event rows carry session/agent labels.
This commit is contained in:
@@ -1,10 +1,17 @@
|
||||
{
|
||||
"title": "Luồng hoạt động",
|
||||
"subtitle": "Luồng thời gian thực của mọi sự kiện Agent",
|
||||
"paused": "(đã tạm dừng - {{count}} mục đệm)",
|
||||
"paused": "(đã tạm dừng — {{count}} sự kiện mới)",
|
||||
"resume": "Tiếp tục",
|
||||
"pause": "Tạm dừng",
|
||||
"noActivity": "Chưa có hoạt động",
|
||||
"noActivityDesc": "Sự kiện sẽ được phát trực tiếp tại đây khi các Agent Claude Code làm việc.",
|
||||
"viewSession": "Phiên"
|
||||
"viewSession": "Phiên",
|
||||
"exportCsv": "CSV",
|
||||
"exportJson": "JSON",
|
||||
"failedLoad": "Không thể tải sự kiện",
|
||||
"newEvents_one": "{{count}} sự kiện mới — về mới nhất",
|
||||
"newEvents_other": "{{count}} sự kiện mới — về mới nhất",
|
||||
"firstPage": "Trang đầu",
|
||||
"lastPage": "Trang cuối"
|
||||
}
|
||||
|
||||
@@ -50,5 +50,8 @@
|
||||
"noSessionTrendData": "Chưa có dữ liệu xu hướng phiên.",
|
||||
"last7Days": "7 ngày gần nhất",
|
||||
"less": "Ít",
|
||||
"more": "Nhiều"
|
||||
"more": "Nhiều",
|
||||
"tokensExCacheReads": "Token (trừ đọc cache)",
|
||||
"cacheReadsSub": "+{{reads}} token đọc cache · tỉ lệ trúng {{pct}}%",
|
||||
"avgPerWeekday30d": "Trung bình theo thứ trong tuần, 30 ngày qua"
|
||||
}
|
||||
|
||||
@@ -18,5 +18,94 @@
|
||||
"failedConnect": "Không thể kết nối máy chủ",
|
||||
"failedLoad": "Không thể tải dữ liệu",
|
||||
"activeTrend": " đang hoạt động",
|
||||
"totalTrend": " trong phiên hoạt động"
|
||||
"totalTrend": " trong phiên hoạt động",
|
||||
"tabs": {
|
||||
"label": "Các chế độ xem tổng quan",
|
||||
"analytics": "Phân tích",
|
||||
"monitor": "Giám sát",
|
||||
"health": "Sức khỏe hệ thống"
|
||||
},
|
||||
"collapseSubagents": "Thu gọn subagent",
|
||||
"expandSubagents": "Mở rộng subagent",
|
||||
"needsYou": {
|
||||
"title": "Cần bạn xử lý",
|
||||
"since": "đang chờ {{ago}}"
|
||||
},
|
||||
"health": {
|
||||
"runtime": "Môi trường chạy",
|
||||
"cores_one": "{{count}} lõi",
|
||||
"cores_other": "{{count}} lõi",
|
||||
"uptime": "Thời gian chạy",
|
||||
"cpu": "CPU (1/5/15 phút)",
|
||||
"nodeRss": "Bộ nhớ Node (RSS)",
|
||||
"hostMemory": "Bộ nhớ máy",
|
||||
"hostMemoryTip": "Bộ nhớ máy: đã dùng {{pct}}%\n{{used}} / {{total}}",
|
||||
"heap": "Heap V8",
|
||||
"heapTip": "Heap V8: đã dùng {{pct}}%\n{{used}} / giới hạn {{limit}}\nĐã cấp phát: {{allocated}}\nNgoài heap: {{external}}",
|
||||
"storage": "Lưu trữ",
|
||||
"writeVelocityTip": "Tốc độ ghi (sự kiện):\n5 phút: {{m5}}\n15 phút: {{m15}}\n1 giờ: {{h1}}",
|
||||
"database": "Cơ sở dữ liệu",
|
||||
"recordsTip": "Phân bố bản ghi\n\nPhiên: {{sessions}} ({{sessPct}}%)\nAgent: {{agents}} ({{agentPct}}%)\nSự kiện: {{events}} ({{eventPct}}%)\n\nTổng: {{total}} bản ghi",
|
||||
"total": "tổng",
|
||||
"sessions": "Phiên",
|
||||
"agents": "Agent",
|
||||
"events": "Sự kiện",
|
||||
"score": "Điểm sức khỏe",
|
||||
"formula": "Công thức",
|
||||
"formulaTip": "Công thức chỉ số tổng hợp:\n0.4 × Tỉ lệ thành công ({{success}}%)\n+ 0.25 × Trúng cache ({{cache}}%)\n+ 0.25 × (100 − Tỉ lệ lỗi) ({{noError}}%)\n+ 0.10 × (100 − Heap%) ({{noHeap}}%)\n= {{score}}",
|
||||
"scoreTip": "Điểm: {{score}} / 100\n\n• Tỉ lệ thành công (40%): {{success}}%\n• Trúng cache (25%): {{cache}}%\n• Tránh lỗi (25%): {{noError}}%\n• Sức khỏe bộ nhớ (10%): {{noHeap}}%",
|
||||
"cache": "Cache",
|
||||
"cacheTip": "Tỉ lệ trúng cache: {{pct}}%\nTrúng: {{hits}}\nTrượt: {{misses}}",
|
||||
"errors": "Lỗi",
|
||||
"errorsTip": "Tỉ lệ lỗi: {{pct}}%\n<5% = tốt, 5–15% = cảnh báo, >15% = nghiêm trọng",
|
||||
"compact": "Nén",
|
||||
"compactTip": "Số lần nén transcript: {{count}}\nThu gọn cửa sổ ngữ cảnh bằng cách tóm tắt các lượt.",
|
||||
"saved": "Tiết kiệm",
|
||||
"savedTip": "Token thu hồi: {{tokens}}\nĐược giải phóng nhờ nén.",
|
||||
"tokenUsage": "Sử dụng token",
|
||||
"totalSuffix": "tổng {{value}}",
|
||||
"modelTip": "{{model}}\nĐầu vào: {{input}}\nĐầu ra: {{output}}\nĐọc cache: {{cacheRead}}\nTỉ trọng: {{pct}}%",
|
||||
"noModelData": "Chưa có dữ liệu mô hình",
|
||||
"concurrency": "Đồng thời",
|
||||
"intervals_one": "{{count}} khoảng",
|
||||
"intervals_other": "{{count}} khoảng",
|
||||
"concurrencyTip": "Đỉnh: {{peak}} phiên song song\nKhoảng có hoạt động: {{active}}\nTrung bình: {{avg}}",
|
||||
"noConcurrencyData": "Chưa có dữ liệu đồng thời",
|
||||
"peak": "Đỉnh",
|
||||
"peakTip": "Đỉnh: {{count}} phiên chạy cùng lúc.",
|
||||
"active": "Hoạt động",
|
||||
"activeTip": "{{active}} trên {{total}} khoảng có phiên hoạt động.",
|
||||
"avg": "TB",
|
||||
"avgTip": "Mức đồng thời trung bình trên mọi khoảng.",
|
||||
"toolUsage": "Sử dụng công cụ",
|
||||
"top": "top {{count}}",
|
||||
"invocationsTip_one": "{{tool}}: {{formatted}} lần gọi",
|
||||
"invocationsTip_other": "{{tool}}: {{formatted}} lần gọi",
|
||||
"noToolData": "Chưa có dữ liệu công cụ",
|
||||
"subagentEffectiveness": "Hiệu quả subagent",
|
||||
"defaultType": "mặc định",
|
||||
"effectivenessTip": "{{type}}\nThành công: {{pct}}%\nTổng: {{total}} · OK: {{ok}} · Lỗi: {{errors}}",
|
||||
"noSubagentData": "Chưa có dữ liệu subagent",
|
||||
"integration": "Tích hợp",
|
||||
"hooksActive": "Đang hoạt động",
|
||||
"hookTip": "Đường dẫn: {{path}}\nTrạng thái: {{status}}",
|
||||
"connected": "Đã kết nối",
|
||||
"disconnected": "Mất kết nối",
|
||||
"noHooks": "Chưa đăng ký hook dự án nào",
|
||||
"wsTip": "Kết nối WebSocket: {{count}}\nGiao thức: RFC 6455",
|
||||
"wsActive": "WebSocket đang hoạt động",
|
||||
"connections_one": "{{count}} kết nối",
|
||||
"connections_other": "{{count}} kết nối",
|
||||
"platform": "Nền tảng",
|
||||
"journalMode": "Chế độ journal",
|
||||
"synchronous": "Đồng bộ",
|
||||
"autoVacuum": "Tự dọn dẹp",
|
||||
"foreignKeys": "Khóa ngoại",
|
||||
"busyTimeout": "Thời gian chờ khóa"
|
||||
},
|
||||
"errorBoundary": {
|
||||
"title": "Đã xảy ra lỗi",
|
||||
"body": "Không thể tải trang này. Tải lại thường sẽ khắc phục — ví dụ sau khi dashboard vừa được cập nhật.",
|
||||
"reload": "Tải lại"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,14 @@
|
||||
"noEvents": "Chưa có sự kiện được ghi nhận.",
|
||||
"conversation": "Hội thoại",
|
||||
"timeline": "Dòng thời gian ({{shown}}/{{total}})",
|
||||
"transcriptNotFound": "Không tìm thấy bản ghi hội thoại cho agent này. Tệp transcript có thể bị thiếu hoặc chưa được liên kết."
|
||||
"transcriptNotFound": "Không tìm thấy bản ghi hội thoại cho agent này. Tệp transcript có thể bị thiếu hoặc chưa được liên kết.",
|
||||
"back": "Quay lại",
|
||||
"collapseSubagents": "Thu gọn subagent",
|
||||
"expandSubagents": "Mở rộng subagent",
|
||||
"dashboardRun": {
|
||||
"title": "Một pane trên dashboard đang chạy phiên này",
|
||||
"body": "Mở pane trong workspace để gửi tiếp, xem đầu ra hoặc dừng nó."
|
||||
}
|
||||
},
|
||||
"toolBadgeTitle": "Ghi lại bởi {{tool}}",
|
||||
"menu": {
|
||||
@@ -45,5 +52,109 @@
|
||||
"inWorkspace": "Mở trong workspace của nó",
|
||||
"copyId": "Sao chép ID session",
|
||||
"copyFolder": "Sao chép đường dẫn thư mục"
|
||||
},
|
||||
"exportCsv": "CSV",
|
||||
"exportJson": "JSON",
|
||||
"filterDirectory": "Lọc theo thư mục",
|
||||
"allDirectories": "Tất cả thư mục",
|
||||
"sortLabel": "Sắp xếp phiên",
|
||||
"sortTimeDesc": "Theo thời gian (mới nhất)",
|
||||
"sortTimeAsc": "Theo thời gian (cũ nhất)",
|
||||
"sortDurationDesc": "Theo thời lượng (dài nhất)",
|
||||
"sortDurationAsc": "Theo thời lượng (ngắn nhất)",
|
||||
"sortPriceDesc": "Theo chi phí (cao nhất)",
|
||||
"sortPriceAsc": "Theo chi phí (thấp nhất)",
|
||||
"descending": "Giảm dần",
|
||||
"ascending": "Tăng dần",
|
||||
"filterTool": "Lọc theo công cụ AI",
|
||||
"allTools": "Mọi công cụ AI",
|
||||
"filterWorkspace": "Lọc theo workspace",
|
||||
"allWorkspaces": "Mọi workspace",
|
||||
"dateFrom": "Từ",
|
||||
"dateTo": "Đến",
|
||||
"clearFilters": "Xóa bộ lọc",
|
||||
"failedList": "Không thể tải danh sách phiên",
|
||||
"tableRegion": "Bảng phiên",
|
||||
"openInWorkspace": "Mở trong workspace",
|
||||
"openInWorkspaceTitle": "Một pane trên dashboard đang chạy phiên này — mở nó",
|
||||
"remoteSourceBadgeTitle": "Được thu thập từ máy từ xa",
|
||||
"datePicker": {
|
||||
"placeholder": "Chọn ngày và giờ",
|
||||
"clear": "Xóa ngày",
|
||||
"prevMonth": "Tháng trước",
|
||||
"nextMonth": "Tháng sau",
|
||||
"time": "Giờ"
|
||||
},
|
||||
"conversation": {
|
||||
"failedLoad": "Không thể tải transcript",
|
||||
"transcript": "Transcript",
|
||||
"messages_one": "{{count}} tin nhắn",
|
||||
"messages_other": "{{count}} tin nhắn",
|
||||
"refresh": "Làm mới hội thoại",
|
||||
"loadingHistory": "Đang tải lịch sử…",
|
||||
"scrollForOlder": "Cuộn lên để xem tin nhắn cũ hơn",
|
||||
"loading": "Đang tải hội thoại…",
|
||||
"empty": "Không tìm thấy bản ghi hội thoại.",
|
||||
"emptyBody": "Siêu dữ liệu của phiên này đã được nhập, nhưng tệp transcript không còn trên đĩa. Claude Code tự động xóa transcript của phiên không hoạt động sau một thời gian lưu giữ (cleanupPeriodDays, mặc định 30 ngày), nên các hội thoại cũ có thể đã mất. Các phiên được nhập từ nay sẽ được chụp lại và giữ nguyên ngay cả khi Claude Code xóa bản gốc.",
|
||||
"newMessages": "Tin nhắn mới",
|
||||
"systemReminder": "Nhắc nhở hệ thống",
|
||||
"persistedOutput": "Đầu ra đã lưu",
|
||||
"taskNotification": "Thông báo tác vụ",
|
||||
"thinking": "Suy nghĩ",
|
||||
"chars_one": "{{formatted}} ký tự",
|
||||
"chars_other": "{{formatted}} ký tự",
|
||||
"sender": {
|
||||
"user": "Người dùng",
|
||||
"assistant": "Trợ lý",
|
||||
"orchestrator": "Agent chính",
|
||||
"system": "Hệ thống",
|
||||
"tool": "Công cụ"
|
||||
},
|
||||
"lines_one": "{{count}} dòng",
|
||||
"lines_other": "{{count}} dòng",
|
||||
"copyCode": "Sao chép mã",
|
||||
"copy": "Sao chép",
|
||||
"tool": {
|
||||
"inputTruncated": "Đầu vào (bị cắt bớt)",
|
||||
"command": "Lệnh",
|
||||
"newFile": "Tệp mới",
|
||||
"replaceAll": "thay tất cả",
|
||||
"removed": "Đã xóa",
|
||||
"added": "Đã thêm",
|
||||
"pattern": "Mẫu",
|
||||
"path": "Đường dẫn",
|
||||
"glob": "Glob",
|
||||
"input": "Đầu vào",
|
||||
"empty": "trống",
|
||||
"error": "Lỗi",
|
||||
"output": "Đầu ra",
|
||||
"statusError": "lỗi",
|
||||
"statusOk": "ok",
|
||||
"statusPending": "đang chờ"
|
||||
}
|
||||
},
|
||||
"overview": {
|
||||
"agent": "Agent",
|
||||
"running": "đang chạy",
|
||||
"events": "Sự kiện",
|
||||
"perMin": "{{rate}}/phút",
|
||||
"toolCalls": "Lần gọi công cụ",
|
||||
"unique": "{{count}} loại",
|
||||
"subagents": "Subagent",
|
||||
"plusMain_one": "+{{count}} chính",
|
||||
"plusMain_other": "+{{count}} chính",
|
||||
"compactions": "Lần nén",
|
||||
"errors": "Lỗi",
|
||||
"duration": "Thời lượng",
|
||||
"topTools": "Công cụ dùng nhiều",
|
||||
"distinctTotal": "tổng {{count}}",
|
||||
"noToolCalls": "Chưa có lần gọi công cụ nào.",
|
||||
"contextCompaction": "Nén ngữ cảnh",
|
||||
"runs_one": "{{count}} lần chạy",
|
||||
"runs_other": "{{count}} lần chạy",
|
||||
"noSubagents": "Phiên này không có subagent.",
|
||||
"tokenFlow": "Luồng token",
|
||||
"total": "tổng {{value}}",
|
||||
"eventMix": "Cơ cấu sự kiện"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,6 +204,15 @@
|
||||
"outcomeAbandoned": "Phiên dừng mà không có Stop sạch và cũng không có lỗi rõ ràng - thường là đóng giữa chừng.",
|
||||
"outcomeFallback": "Trạng thái cuối của các phiên trong phạm vi, được tính từ sự kiện hook cuối quan sát được."
|
||||
}
|
||||
},
|
||||
"legendItems": {
|
||||
"sessions": "Phiên",
|
||||
"mainAgent": "Agent chính",
|
||||
"subagentTypes": "Loại subagent",
|
||||
"compactions": "Lần nén",
|
||||
"completed": "Hoàn thành",
|
||||
"error": "Lỗi",
|
||||
"abandoned": "Bị bỏ dở"
|
||||
}
|
||||
},
|
||||
"drillIn": {
|
||||
@@ -230,7 +239,9 @@
|
||||
"noEvents": "Không có sự kiện cho phiên này.",
|
||||
"showingOf": "Đang hiển thị 100 / {{total}} sự kiện",
|
||||
"sessionInfo": " phiên - hoạt động {{from}}%-{{to}} thời lượng phiên",
|
||||
"sortedByCompaction": " phiên (sắp theo số lần nén ngữ cảnh)"
|
||||
"sortedByCompaction": " phiên (sắp theo số lần nén ngữ cảnh)",
|
||||
"openSession": "Mở phiên",
|
||||
"openInWorkspace": "Mở trong workspace"
|
||||
},
|
||||
"lanes": {
|
||||
"title": "Tỉ lệ pass các node pipeline",
|
||||
@@ -316,5 +327,7 @@
|
||||
"sessions_one": "{{count}} phiên",
|
||||
"sessions_other": "{{count}} phiên",
|
||||
"pluginBreakdown": "{{skills}} skill được dùng · {{skillCalls}} lần gọi skill · {{mcpCalls}} lần gọi tool MCP"
|
||||
}
|
||||
},
|
||||
"selectedNode": "Đang chọn:",
|
||||
"clearSelection": "Bỏ chọn"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user