From 2f76060c39ba5dcf2b3d0b8fc2b0205bdf6623a8 Mon Sep 17 00:00:00 2001 From: Admin Date: Sun, 19 Jul 2026 18:47:35 +0000 Subject: [PATCH] feat: complete all page components - Dashboard: system stats with cards - Tasks: task management table with filters - Scripts: script management grid - Logs: execution log viewer - Interconnect: node management - Terminal: xterm.js integration - Settings: theme and site config - Login: authentication page --- web/package.json | 5 +- web/pnpm-lock.yaml | 40 ++++-- web/src/api/endpoints.ts | 64 +++++++++ web/src/api/hooks.ts | 166 ++++++++++++++++++++++++ web/src/api/types.ts | 103 +++++++++++++++ web/src/pages/Dashboard.tsx | 187 +++++++++++++++++++++------ web/src/pages/Interconnect.tsx | 176 ++++++++++++++++++++++++- web/src/pages/Login.tsx | 153 ++++++++++++++++++++++ web/src/pages/Logs.tsx | 138 +++++++++++++++++++- web/src/pages/Scripts.tsx | 163 ++++++++++++++++++++++- web/src/pages/Settings.tsx | 138 +++++++++++++++++++- web/src/pages/Tasks.tsx | 230 ++++++++++++++++++++++++++++++++- web/src/pages/Terminal.tsx | 142 +++++++++++++++++++- web/src/routeTree.gen.ts | 69 ++++++---- 14 files changed, 1684 insertions(+), 90 deletions(-) create mode 100644 web/src/api/endpoints.ts create mode 100644 web/src/api/hooks.ts create mode 100644 web/src/api/types.ts create mode 100644 web/src/pages/Login.tsx diff --git a/web/package.json b/web/package.json index fd5d955..eca4072 100644 --- a/web/package.json +++ b/web/package.json @@ -13,7 +13,8 @@ "@tanstack/react-router": "^1.120.0", "@tanstack/react-table": "^8.21.0", "@xterm/xterm": "^5.5.0", - "framer-motion": "^12.0.0", + "@xterm/addon-fit": "^0.10.0", + "framer-motion": "^11.15.0", "lucide-react": "^0.525.0", "react": "^19.2.7", "react-dom": "^19.2.7", @@ -31,4 +32,4 @@ "typescript": "^5.9.0", "vite": "^8.1.5" } -} +} \ No newline at end of file diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index c63e1b7..bf727d5 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -17,12 +17,15 @@ importers: '@tanstack/react-table': specifier: ^8.21.0 version: 8.21.3(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@xterm/addon-fit': + specifier: ^0.10.0 + version: 0.10.0(@xterm/xterm@5.5.0) '@xterm/xterm': specifier: ^5.5.0 version: 5.5.0 framer-motion: - specifier: ^12.0.0 - version: 12.42.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^11.15.0 + version: 11.18.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7) lucide-react: specifier: ^0.525.0 version: 0.525.0(react@19.2.7) @@ -286,6 +289,11 @@ packages: babel-plugin-react-compiler: optional: true + '@xterm/addon-fit@0.10.0': + resolution: {integrity: sha512-UFYkDm4HUahf2lnEyHvio51TNGiLK66mqP2JoATy7hRZeXaGMRDr00JiSF7m63vR5WKATF605yEggJKsw0JpMQ==} + peerDependencies: + '@xterm/xterm': ^5.0.0 + '@xterm/xterm@5.5.0': resolution: {integrity: sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==} @@ -399,8 +407,8 @@ packages: fraction.js@5.3.4: resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==} - framer-motion@12.42.2: - resolution: {integrity: sha512-5XY9luDiu0oHfHBjpDthFMh0ES+122w6p/papSJBweMkO8Sn+PW2QaEgRblQBpWFnuvZS5qvarpt/hO2pjGmnw==} + framer-motion@11.18.2: + resolution: {integrity: sha512-5F5Och7wrvtLVElIpclDT0CBzMVg3dL22B64aZwHtsIY8RB4mXICLrkajK4G9R+ieSAGcgrLeae2SeUTg2pr6w==} peerDependencies: '@emotion/is-prop-valid': '*' react: ^18.0.0 || ^19.0.0 @@ -515,11 +523,11 @@ packages: peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 - motion-dom@12.42.2: - resolution: {integrity: sha512-5gIMWLp/PycBtJRJWRgjxke5n8dlvkSn2DrYW+tr3XcqAZY1xZh6BJyooJXCM8wdfM7wfMjkBJNLge1CKPUIRA==} + motion-dom@11.18.1: + resolution: {integrity: sha512-g76KvA001z+atjfxczdRtw/RXOM3OMSdd1f4DL77qCTF/+avrRJiawSG4yDibEQ215sr9kpinSlX2pCTJ9zbhw==} - motion-utils@12.39.0: - resolution: {integrity: sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ==} + motion-utils@11.18.1: + resolution: {integrity: sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA==} nanoid@3.3.16: resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==} @@ -875,6 +883,10 @@ snapshots: '@rolldown/pluginutils': 1.0.1 vite: 8.1.5(@types/node@22.20.1) + '@xterm/addon-fit@0.10.0(@xterm/xterm@5.5.0)': + dependencies: + '@xterm/xterm': 5.5.0 + '@xterm/xterm@5.5.0': {} autoprefixer@10.5.4(postcss@8.5.19): @@ -965,10 +977,10 @@ snapshots: fraction.js@5.3.4: {} - framer-motion@12.42.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + framer-motion@11.18.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7): dependencies: - motion-dom: 12.42.2 - motion-utils: 12.39.0 + motion-dom: 11.18.1 + motion-utils: 11.18.1 tslib: 2.8.1 optionalDependencies: react: 19.2.7 @@ -1042,11 +1054,11 @@ snapshots: dependencies: react: 19.2.7 - motion-dom@12.42.2: + motion-dom@11.18.1: dependencies: - motion-utils: 12.39.0 + motion-utils: 11.18.1 - motion-utils@12.39.0: {} + motion-utils@11.18.1: {} nanoid@3.3.16: {} diff --git a/web/src/api/endpoints.ts b/web/src/api/endpoints.ts new file mode 100644 index 0000000..74dd868 --- /dev/null +++ b/web/src/api/endpoints.ts @@ -0,0 +1,64 @@ +import { request } from './index' +import type { MonitorStats, Task, Script, EnvVar, LogEntry, InterconnectNode, User, Settings } from './types' + +// Auth +export const login = (username: string, password: string) => + request<{ token: string }>('/auth/login', { + method: 'POST', + body: JSON.stringify({ username, password }) + }) + +export const logout = () => request('/auth/logout', { method: 'POST' }) +export const getCurrentUser = () => request('/auth/me') + +// Dashboard +export const getStats = () => request('/stats') +export const getSentence = () => request<{ content: string; author: string }>('/sentence') +export const getTaskStats = () => request<{ total: number; running: number; scheduled: number }>('/taskstats') + +// Tasks +export const getTasks = (params?: { status?: string; tag?: string }) => { + const query = new URLSearchParams(params as any).toString() + return request(`/tasks${query ? '?' + query : ''}`) +} + +export const getTask = (id: number) => request(`/tasks/${id}`) +export const createTask = (data: Partial) => request('/tasks', { method: 'POST', body: JSON.stringify(data) }) +export const updateTask = (id: number, data: Partial) => request(`/tasks/${id}`, { method: 'PUT', body: JSON.stringify(data) }) +export const deleteTask = (id: number) => request(`/tasks/${id}`, { method: 'DELETE' }) +export const executeTask = (id: number) => request(`/execute/task/${id}`, { method: 'POST' }) +export const getTags = () => request('/tasks/tags') + +// Scripts +export const getScripts = () => request('/scripts') +export const getScript = (id: number) => request