fix: remove duplicate endpoints.ts, fix Login imports
- Remove web/src/api/endpoints.ts (redundant with index.ts) - Fix Login.tsx to use useLogin hook - Simplify Dockerfile (use CI-built artifacts)
This commit is contained in:
+3
-23
@@ -1,28 +1,8 @@
|
|||||||
# Build stage
|
# Production stage - only needs nginx and built files
|
||||||
FROM node:22-alpine AS builder
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Install pnpm
|
|
||||||
RUN corepack enable && corepack prepare pnpm@9 --activate
|
|
||||||
|
|
||||||
# Copy package files
|
|
||||||
COPY web/package.json web/pnpm-lock.yaml ./
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
RUN pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
# Copy source
|
|
||||||
COPY web/ ./
|
|
||||||
|
|
||||||
# Build
|
|
||||||
RUN pnpm build
|
|
||||||
|
|
||||||
# Production stage
|
|
||||||
FROM nginx:alpine
|
FROM nginx:alpine
|
||||||
|
|
||||||
# Copy built files
|
# Copy built files (from CI artifact or local build)
|
||||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
COPY web/dist /usr/share/nginx/html
|
||||||
|
|
||||||
# Copy nginx config
|
# Copy nginx config
|
||||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
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<void>('/auth/logout', { method: 'POST' })
|
|
||||||
export const getCurrentUser = () => request<User>('/auth/me')
|
|
||||||
|
|
||||||
// Dashboard
|
|
||||||
export const getStats = () => request<MonitorStats>('/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<Task[]>(`/tasks${query ? '?' + query : ''}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getTask = (id: number) => request<Task>(`/tasks/${id}`)
|
|
||||||
export const createTask = (data: Partial<Task>) => request<Task>('/tasks', { method: 'POST', body: JSON.stringify(data) })
|
|
||||||
export const updateTask = (id: number, data: Partial<Task>) => request<Task>(`/tasks/${id}`, { method: 'PUT', body: JSON.stringify(data) })
|
|
||||||
export const deleteTask = (id: number) => request<void>(`/tasks/${id}`, { method: 'DELETE' })
|
|
||||||
export const executeTask = (id: number) => request<void>(`/execute/task/${id}`, { method: 'POST' })
|
|
||||||
export const getTags = () => request<string[]>('/tasks/tags')
|
|
||||||
|
|
||||||
// Scripts
|
|
||||||
export const getScripts = () => request<Script[]>('/scripts')
|
|
||||||
export const getScript = (id: number) => request<Script>(`/scripts/${id}`)
|
|
||||||
export const createScript = (data: Partial<Script>) => request<Script>('/scripts', { method: 'POST', body: JSON.stringify(data) })
|
|
||||||
export const updateScript = (id: number, data: Partial<Script>) => request<Script>(`/scripts/${id}`, { method: 'PUT', body: JSON.stringify(data) })
|
|
||||||
export const deleteScript = (id: number) => request<void>(`/scripts/${id}`, { method: 'DELETE' })
|
|
||||||
|
|
||||||
// Env
|
|
||||||
export const getEnvs = () => request<EnvVar[]>('/env')
|
|
||||||
export const getEnv = (id: number) => request<EnvVar>(`/env/${id}`)
|
|
||||||
export const createEnv = (data: Partial<EnvVar>) => request<EnvVar>('/env', { method: 'POST', body: JSON.stringify(data) })
|
|
||||||
export const updateEnv = (id: number, data: Partial<EnvVar>) => request<EnvVar>(`/env/${id}`, { method: 'PUT', body: JSON.stringify(data) })
|
|
||||||
export const deleteEnv = (id: number) => request<void>(`/env/${id}`, { method: 'DELETE' })
|
|
||||||
|
|
||||||
// Logs
|
|
||||||
export const getLogs = (params?: { task_id?: number; status?: string; page?: number }) => {
|
|
||||||
const query = new URLSearchParams(params as any).toString()
|
|
||||||
return request<LogEntry[]>(`/logs${query ? '?' + query : ''}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Interconnect
|
|
||||||
export const getNodes = () => request<InterconnectNode[]>('/interconnect/nodes')
|
|
||||||
export const getNode = (id: string) => request<InterconnectNode>(`/interconnect/nodes/${id}`)
|
|
||||||
export const createNode = (data: Partial<InterconnectNode>) => request<InterconnectNode>('/interconnect/nodes', { method: 'POST', body: JSON.stringify(data) })
|
|
||||||
export const updateNode = (id: string, data: Partial<InterconnectNode>) => request<InterconnectNode>(`/interconnect/nodes/${id}`, { method: 'PUT', body: JSON.stringify(data) })
|
|
||||||
export const deleteNode = (id: string) => request<void>(`/interconnect/nodes/${id}`, { method: 'DELETE' })
|
|
||||||
|
|
||||||
// Settings
|
|
||||||
export const getSettings = () => request<Settings>('/settings')
|
|
||||||
export const updateSettings = (data: Partial<Settings>) => request<Settings>('/settings', { method: 'PUT', body: JSON.stringify(data) })
|
|
||||||
|
|
||||||
// Monitor
|
|
||||||
export const getMonitor = () => request<MonitorStats>('/monitor')
|
|
||||||
+7
-10
@@ -1,27 +1,24 @@
|
|||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { useNavigate } from '@tanstack/react-router'
|
import { useNavigate } from '@tanstack/react-router'
|
||||||
import { login } from '@/api/endpoints'
|
import { useLogin } from '@/api/hooks'
|
||||||
import { Lock, User, AlertCircle } from 'lucide-react'
|
import { Lock, User, AlertCircle } from 'lucide-react'
|
||||||
|
|
||||||
export default function Login() {
|
export default function Login() {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
const loginMutation = useLogin()
|
||||||
const [username, setUsername] = useState('')
|
const [username, setUsername] = useState('')
|
||||||
const [password, setPassword] = useState('')
|
const [password, setPassword] = useState('')
|
||||||
const [error, setError] = useState('')
|
const [error, setError] = useState('')
|
||||||
const [loading, setLoading] = useState(false)
|
|
||||||
|
|
||||||
const handleSubmit = async (e: React.FormEvent) => {
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
setError('')
|
setError('')
|
||||||
setLoading(true)
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await login(username, password)
|
await loginMutation.mutateAsync({ username, password })
|
||||||
navigate({ to: '/' })
|
navigate({ to: '/' })
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
setError(err.message || 'Login failed')
|
setError(err.message || 'Login failed')
|
||||||
} finally {
|
|
||||||
setLoading(false)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +127,7 @@ export default function Login() {
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={loading}
|
disabled={loginMutation.isPending}
|
||||||
style={{
|
style={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
padding: 12,
|
padding: 12,
|
||||||
@@ -140,11 +137,11 @@ export default function Login() {
|
|||||||
color: 'white',
|
color: 'white',
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight: 500,
|
fontWeight: 500,
|
||||||
cursor: loading ? 'not-allowed' : 'pointer',
|
cursor: loginMutation.isPending ? 'not-allowed' : 'pointer',
|
||||||
opacity: loading ? 0.7 : 1,
|
opacity: loginMutation.isPending ? 0.7 : 1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{loading ? 'Signing in...' : 'Sign In'}
|
{loginMutation.isPending ? 'Signing in...' : 'Sign In'}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user