diff --git a/web/src/api/files.ts b/web/src/api/files.ts new file mode 100644 index 0000000..5f56a54 --- /dev/null +++ b/web/src/api/files.ts @@ -0,0 +1,49 @@ +import type { ApiResponse } from '@/types/jobs' +import apiClient from '@/api/client' +import type { FileResponse, ListFilesResponse, UploadSessionResponse, InitUploadRequest, FolderResponse, CreateFolderRequest } from '@/types/files' + +export function listFiles(params?: { folder_id?: number; page?: number; page_size?: number; search?: string }): Promise> { + return apiClient.get('/files', { params }) +} + +export function getFile(id: number): Promise> { + return apiClient.get(`/files/${id}`) +} + +export function deleteFile(id: number): Promise> { + return apiClient.delete(`/files/${id}`) +} + +export function downloadFileUrl(id: number): string { + return `/api/v1/files/${id}/download` +} + +export function initUpload(data: InitUploadRequest): Promise> { + return apiClient.post('/files/uploads', data) +} + +export function uploadChunk(sessionId: number, chunkIndex: number, chunk: Blob): Promise> { + const formData = new FormData() + formData.append('chunk', chunk) + return apiClient.put(`/files/uploads/${sessionId}/chunks/${chunkIndex}`, formData) +} + +export function completeUpload(sessionId: number): Promise> { + return apiClient.post(`/files/uploads/${sessionId}/complete`) +} + +export function cancelUpload(sessionId: number): Promise> { + return apiClient.post(`/files/uploads/${sessionId}/cancel`) +} + +export function listFolders(params?: { parent_id?: number | null }): Promise> { + return apiClient.get('/files/folders', { params }) +} + +export function createFolder(data: CreateFolderRequest): Promise> { + return apiClient.post('/files/folders', data) +} + +export function deleteFolder(id: number): Promise> { + return apiClient.delete(`/files/folders/${id}`) +} diff --git a/web/src/api/tasks.ts b/web/src/api/tasks.ts new file mode 100644 index 0000000..35b0d15 --- /dev/null +++ b/web/src/api/tasks.ts @@ -0,0 +1,15 @@ +import type { ApiResponse } from '@/types/jobs' +import apiClient from '@/api/client' +import type { ApplicationListResponse, CreateTaskRequest, TaskListResponse } from '@/types/tasks' + +export function getApplications(params?: { page?: number; page_size?: number }): Promise> { + return apiClient.get('/applications', { params }) +} + +export function createTask(data: CreateTaskRequest): Promise> { + return apiClient.post('/tasks', data) +} + +export function listTasks(params?: { page?: number; page_size?: number; status?: string }): Promise> { + return apiClient.get('/tasks', { params }) +} diff --git a/web/src/types/files.ts b/web/src/types/files.ts new file mode 100644 index 0000000..9e2c414 --- /dev/null +++ b/web/src/types/files.ts @@ -0,0 +1,56 @@ +export interface FileResponse { + id: number + name: string + folder_id?: number | null + sha256: string + size: number + mime_type: string + folder_path?: string + user_id?: number | null + created_at: string + updated_at: string +} + +export interface ListFilesResponse { + files?: FileResponse[] + total?: number + page?: number + page_size?: number +} + +export interface FolderResponse { + id: number + name: string + parent_id?: number | null + path: string + file_count: number + subfolder_count: number + created_at: string +} + +export interface CreateFolderRequest { + name: string + parent_id?: number | null +} + +export interface UploadSessionResponse { + id: number + file_name: string + file_size: number + sha256: string + chunk_size: number + total_chunks: number + status: string + uploaded_chunks?: number[] + created_at?: string + expires_at?: string +} + +export interface InitUploadRequest { + file_name: string + file_size: number + sha256: string + chunk_size?: number + mime_type?: string + folder_id?: number | null +} diff --git a/web/src/types/tasks.ts b/web/src/types/tasks.ts new file mode 100644 index 0000000..cff37e8 --- /dev/null +++ b/web/src/types/tasks.ts @@ -0,0 +1,91 @@ +export interface ParameterSchema { + name: string + label?: string + type: string + required?: boolean + default?: string + options?: string[] + description?: string +} + +export interface Application { + id: number + name: string + description?: string + icon?: string + category?: string + script_template: string + parameters?: ParameterSchema[] | null + scope?: string + created_by?: number + created_at: string + updated_at: string +} + +export interface ApplicationListResponse { + applications?: Application[] + total?: number + page?: number + page_size?: number +} + +export interface CreateTaskRequest { + app_id: number + task_name?: string + values?: Record + partition?: string + cpus?: number + job_name?: string + memory_per_node?: number + nodes?: string + tasks?: number + cpus_per_task?: number + file_ids?: number[] +} + +export interface TaskResponse { + id: number + task_name: string + app_id: number + app_name: string + status: string + current_step: string + retry_count: number + slurm_job_id: number | null + work_dir: string + error_message: string + created_at: string + updated_at: string + partition?: string + cpus?: number | null + memory_per_node?: number | null + memory_per_cpu?: number | null + time_limit?: number | null + qos?: string + job_name?: string + nodes?: string + tasks?: number | null + cpus_per_task?: number | null + constraints?: string + reservation?: string + account?: string + nice?: number | null + mail_type?: string + mail_user?: string + standard_output?: string + standard_error?: string + standard_input?: string + required_nodes?: string + excluded_nodes?: string + begin_time?: number | null + deadline?: number | null + array?: string + dependency?: string + requeue?: boolean + kill_on_node_fail?: boolean +} + +export interface TaskListResponse { + items?: TaskResponse[] + total?: number +}