From a033562c4cf7b5f39a8f7fdcf8c7690ddb5ab4f7 Mon Sep 17 00:00:00 2001 From: DungTT Date: Mon, 25 May 2026 09:14:52 +0700 Subject: [PATCH] fix client --- web-client/src/main.jsx | 132 +------------------------------------- web-client/src/styles.css | 119 ++++------------------------------ 2 files changed, 17 insertions(+), 234 deletions(-) diff --git a/web-client/src/main.jsx b/web-client/src/main.jsx index a71c340..70dc390 100644 --- a/web-client/src/main.jsx +++ b/web-client/src/main.jsx @@ -20,7 +20,6 @@ import { Server, Settings, ShieldCheck, - TerminalSquare, Trash2, WifiOff, XCircle @@ -34,8 +33,6 @@ import { fetchApplicationManifest, fetchInstalledApps, fetchPackageApps, - fetchTaskComponents, - fetchTaskLogs, fetchTaskStatus, joinUrl, normalizeUrl, @@ -67,24 +64,6 @@ function saveSettings(settings) { window.localStorage.setItem(SETTINGS_KEY, JSON.stringify(settings)); } -function statusTone(status) { - if (status === 'success' || status === 'installed' || status === 'online') return 'success'; - if (status === 'running' || status === 'queued') return 'info'; - if (status === 'failed' || status === 'offline') return 'danger'; - if (status === 'update') return 'warning'; - return 'muted'; -} - -function formatDate(value) { - if (!value) return '-'; - const date = new Date(value); - if (Number.isNaN(date.getTime())) return value; - return new Intl.DateTimeFormat('vi-VN', { - dateStyle: 'short', - timeStyle: 'short' - }).format(date); -} - function getErrorMessage(error) { return error instanceof Error ? error.message : String(error || 'Có lỗi xảy ra'); } @@ -107,10 +86,6 @@ function App() { const [toast, setToast] = useState(null); const [busyAction, setBusyAction] = useState(''); const [activeTask, setActiveTask] = useState(null); - const [task, setTask] = useState(null); - const [taskLogs, setTaskLogs] = useState([]); - const [taskComponents, setTaskComponents] = useState([]); - const [taskStatus, setTaskStatus] = useState({ state: 'idle', message: '' }); const packageBaseUrl = settings.packageBaseUrl; const agentBaseUrl = settings.agentBaseUrl; @@ -235,24 +210,14 @@ function App() { }, [packageBaseUrl]); const loadTaskSnapshot = useCallback(async (taskId) => { - setTaskStatus({ state: 'loading', message: 'Đang cập nhật task' }); try { - const [nextTask, nextLogs, nextComponents] = await Promise.all([ - fetchTaskStatus(agentBaseUrl, taskId), - fetchTaskLogs(agentBaseUrl, taskId), - fetchTaskComponents(agentBaseUrl, taskId).catch(() => []) - ]); - setTask(nextTask); - setTaskLogs(nextLogs); - setTaskComponents(nextComponents); - setTaskStatus({ state: statusTone(nextTask.status), message: nextTask.status }); + const nextTask = await fetchTaskStatus(agentBaseUrl, taskId); if (TERMINAL_TASK_STATUSES.has(nextTask.status)) { await refreshAgent(); } return nextTask; - } catch (error) { - setTaskStatus({ state: 'danger', message: getErrorMessage(error) }); + } catch { return null; } }, [agentBaseUrl, refreshAgent]); @@ -265,17 +230,6 @@ function App() { appName: app.appName, queuedAt: new Date().toISOString() }); - setTask({ - taskId: queuedTask.taskId, - type: action, - appId: app.appId, - appName: app.appName, - status: queuedTask.status || 'queued', - progress: 0, - currentStep: 'queued' - }); - setTaskLogs([]); - setTaskComponents([]); }, []); const runAppAction = useCallback(async (action, app) => { @@ -618,14 +572,6 @@ function App() { status={detailStatus} packageBaseUrl={packageBaseUrl} /> - activeTask?.taskId && loadTaskSnapshot(activeTask.taskId)} - /> @@ -723,7 +669,7 @@ function AppDetailPanel({ app, detail, manifest, status, packageBaseUrl }) { const components = manifest?.components || []; return ( -
+

{app?.appName || 'App detail'}

@@ -775,78 +721,6 @@ function AppDetailPanel({ app, detail, manifest, status, packageBaseUrl }) { ); } -function TaskPanel({ activeTask, task, logs, components, status, onRefresh }) { - const progress = Math.max(0, Math.min(100, Number(task?.progress || 0))); - - return ( -
-
-
-

Task monitor

-

{activeTask?.taskId || 'Chưa có task'}

-
- -
- - {task ? ( - <> -
-
- {task.status} - {task.appName || task.appId} - {task.currentStep || '-'} -
- {progress}% -
-
-
-
- - {components.length > 0 && ( -
-
-
- {components.map((component) => ( -
-
- {component.componentId} - {component.currentStep || component.type} -
- {component.progress || 0}% -
- ))} -
- )} - -
-
-
-
- {logs.slice(-8).map((log, index) => ( -
- - {log.message} -
- ))} - {logs.length === 0 && ( -
{status.message || 'Đang chờ log.'}
- )} -
-
- - ) : ( -
Install, update hoặc remove để bắt đầu theo dõi.
- )} -
- ); -} - function Toast({ toast }) { const tone = toast.type === 'failure' ? 'danger' : toast.type; const Icon = tone === 'danger' ? AlertCircle : tone === 'success' ? CheckCircle2 : Activity; diff --git a/web-client/src/styles.css b/web-client/src/styles.css index bfe8f67..e94acce 100644 --- a/web-client/src/styles.css +++ b/web-client/src/styles.css @@ -541,6 +541,20 @@ code { overflow: auto; } +.side-stack > .panel:not(.app-detail-panel) { + flex-shrink: 0; +} + +.app-detail-panel { + flex: 1 1 360px; + overflow: auto; +} + +.app-detail-panel .component-list { + flex: 0 0 auto; + overflow: visible; +} + .page-filters { align-items: center; display: flex; @@ -879,104 +893,6 @@ tbody tr.selected-row td.action-col { white-space: nowrap; } -.task-summary { - align-items: center; - display: flex; - gap: 12px; - justify-content: space-between; - padding: 14px 16px 8px; -} - -.task-summary > div { - display: flex; - flex-direction: column; - gap: 6px; - min-width: 0; -} - -.task-summary strong { - color: #111827; - font-size: 13px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.task-summary small { - color: #64748b; - font-size: 12px; -} - -.task-summary > span { - color: #111827; - font-family: "Manrope", Arial, sans-serif; - font-size: 24px; - font-weight: 800; -} - -.progress-track { - background: #e2e8f0; - border-radius: 999px; - height: 8px; - margin: 0 16px 12px; - overflow: hidden; -} - -.progress-track div { - background: var(--primary); - border-radius: inherit; - height: 100%; - transition: width 0.18s ease; -} - -.task-components { - padding-top: 10px; -} - -.logs-box { - border-top: 1px solid #eef2f7; - display: flex; - flex-direction: column; - min-height: 0; - padding: 12px 16px 14px; -} - -.log-lines { - background: #111827; - border-radius: var(--radius); - color: #f8fafc; - display: flex; - flex-direction: column; - gap: 0; - margin-top: 8px; - max-height: 240px; - overflow: auto; - padding: 8px; -} - -.log-line { - display: grid; - gap: 8px; - grid-template-columns: 118px minmax(0, 1fr); - padding: 4px 2px; -} - -.log-line time { - color: #94a3b8; - font-size: 11px; -} - -.log-line span { - font-family: Consolas, "Liberation Mono", monospace; - font-size: 11px; - line-height: 1.45; - overflow-wrap: anywhere; -} - -.log-line.level-error span { - color: #fecaca; -} - .toast { align-items: center; background: #111827; @@ -1028,10 +944,6 @@ tbody tr.selected-row td.action-col { grid-template-columns: repeat(2, minmax(0, 1fr)); overflow: visible; } - - .task-panel { - grid-column: 1 / -1; - } } @media (max-width: 980px) { @@ -1126,7 +1038,4 @@ tbody tr.selected-row td.action-col { gap: 6px; } - .log-line { - grid-template-columns: 1fr; - } }