217555025f
frontend/src/pages/WorkflowEditor.tsx: full React Flow editor with custom nodes (Input/Convert/Render/FFmpeg/Output), config sidepanel, node palette with drag-drop, new workflow dialog. frontend/src/api/workflows.ts: workflow CRUD API client. @xyflow/react added to package.json dependencies. Route /workflows + sidebar link for admin+pm. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
81 lines
2.1 KiB
TypeScript
81 lines
2.1 KiB
TypeScript
import api from './client'
|
|
|
|
export interface WorkflowDefinition {
|
|
id: string
|
|
name: string
|
|
output_type_id: string | null
|
|
config: WorkflowConfig
|
|
is_active: boolean
|
|
created_at: string
|
|
}
|
|
|
|
export interface WorkflowConfig {
|
|
type: 'still' | 'turntable' | 'multi_angle' | 'custom'
|
|
params: WorkflowParams
|
|
nodes?: WorkflowNode[]
|
|
}
|
|
|
|
export interface WorkflowParams {
|
|
render_engine?: 'cycles' | 'eevee'
|
|
samples?: number
|
|
resolution?: [number, number]
|
|
fps?: number
|
|
duration_s?: number
|
|
angles?: number[]
|
|
}
|
|
|
|
export interface WorkflowNode {
|
|
id: string
|
|
type: string
|
|
position: { x: number; y: number }
|
|
data: Record<string, unknown>
|
|
}
|
|
|
|
export interface WorkflowCreate {
|
|
name: string
|
|
output_type_id?: string | null
|
|
config: WorkflowConfig
|
|
is_active?: boolean
|
|
}
|
|
|
|
export interface WorkflowRun {
|
|
id: string
|
|
workflow_def_id: string | null
|
|
order_line_id: string | null
|
|
celery_task_id: string | null
|
|
status: 'pending' | 'running' | 'completed' | 'failed'
|
|
started_at: string | null
|
|
completed_at: string | null
|
|
error_message: string | null
|
|
created_at: string
|
|
node_results: WorkflowNodeResult[]
|
|
}
|
|
|
|
export interface WorkflowNodeResult {
|
|
id: string
|
|
node_name: string
|
|
status: string
|
|
output: Record<string, unknown> | null
|
|
log: string | null
|
|
duration_s: number | null
|
|
created_at: string
|
|
}
|
|
|
|
export const getWorkflows = (): Promise<WorkflowDefinition[]> =>
|
|
api.get('/workflows').then(r => r.data)
|
|
|
|
export const getWorkflow = (id: string): Promise<WorkflowDefinition> =>
|
|
api.get(`/workflows/${id}`).then(r => r.data)
|
|
|
|
export const createWorkflow = (data: WorkflowCreate): Promise<WorkflowDefinition> =>
|
|
api.post('/workflows', data).then(r => r.data)
|
|
|
|
export const updateWorkflow = (id: string, data: Partial<WorkflowCreate>): Promise<WorkflowDefinition> =>
|
|
api.put(`/workflows/${id}`, data).then(r => r.data)
|
|
|
|
export const deleteWorkflow = (id: string): Promise<void> =>
|
|
api.delete(`/workflows/${id}`).then(() => undefined)
|
|
|
|
export const getWorkflowRuns = (workflowId: string): Promise<WorkflowRun[]> =>
|
|
api.get(`/workflows/${workflowId}/runs`).then(r => r.data)
|