chore: snapshot workflow migration progress
This commit is contained in:
@@ -34,6 +34,32 @@ const EMPTY_FORM = {
|
||||
lighting_only: false,
|
||||
shadow_catcher_enabled: false,
|
||||
camera_orbit: true,
|
||||
workflow_input_schema_text: '[]',
|
||||
}
|
||||
|
||||
function stringifyWorkflowInputSchema(value: unknown): string {
|
||||
try {
|
||||
return JSON.stringify(Array.isArray(value) ? value : [], null, 2)
|
||||
} catch {
|
||||
return '[]'
|
||||
}
|
||||
}
|
||||
|
||||
function parseWorkflowInputSchemaText(rawValue: unknown): unknown[] {
|
||||
const text = typeof rawValue === 'string' ? rawValue.trim() : ''
|
||||
if (!text) return []
|
||||
|
||||
let parsed: unknown
|
||||
try {
|
||||
parsed = JSON.parse(text)
|
||||
} catch {
|
||||
throw new Error('Workflow input schema must be valid JSON')
|
||||
}
|
||||
|
||||
if (!Array.isArray(parsed)) {
|
||||
throw new Error('Workflow input schema must be a JSON array')
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
|
||||
export default function RenderTemplateTable() {
|
||||
@@ -43,7 +69,7 @@ export default function RenderTemplateTable() {
|
||||
const [addFile, setAddFile] = useState<File | null>(null)
|
||||
const [cloneBlendFrom, setCloneBlendFrom] = useState<string>('')
|
||||
const [editingId, setEditingId] = useState<string | null>(null)
|
||||
const [editDraft, setEditDraft] = useState<Partial<RenderTemplate>>({})
|
||||
const [editDraft, setEditDraft] = useState<(Partial<RenderTemplate> & { workflow_input_schema_text?: string })>({})
|
||||
const fileInputRef = useRef<HTMLInputElement>(null)
|
||||
const reuploadRef = useRef<HTMLInputElement>(null)
|
||||
const [reuploadId, setReuploadId] = useState<string | null>(null)
|
||||
@@ -75,6 +101,7 @@ export default function RenderTemplateTable() {
|
||||
fd.append('lighting_only', String(form.lighting_only))
|
||||
fd.append('shadow_catcher_enabled', String(form.shadow_catcher_enabled))
|
||||
fd.append('camera_orbit', String(form.camera_orbit))
|
||||
fd.append('workflow_input_schema', JSON.stringify(parseWorkflowInputSchemaText(form.workflow_input_schema_text)))
|
||||
return createRenderTemplate(fd)
|
||||
},
|
||||
onSuccess: () => {
|
||||
@@ -85,7 +112,7 @@ export default function RenderTemplateTable() {
|
||||
setCloneBlendFrom('')
|
||||
setShowAdd(false)
|
||||
},
|
||||
onError: (e: any) => toast.error(e.response?.data?.detail || 'Failed to create template'),
|
||||
onError: (e: any) => toast.error(e.response?.data?.detail || e.message || 'Failed to create template'),
|
||||
})
|
||||
|
||||
const updateMut = useMutation({
|
||||
@@ -96,7 +123,7 @@ export default function RenderTemplateTable() {
|
||||
qc.invalidateQueries({ queryKey: ['render-templates'] })
|
||||
setEditingId(null)
|
||||
},
|
||||
onError: (e: any) => toast.error(e.response?.data?.detail || 'Failed to update'),
|
||||
onError: (e: any) => toast.error(e.response?.data?.detail || e.message || 'Failed to update'),
|
||||
})
|
||||
|
||||
const deleteMut = useMutation({
|
||||
@@ -128,6 +155,7 @@ export default function RenderTemplateTable() {
|
||||
shadow_catcher_enabled: t.shadow_catcher_enabled,
|
||||
camera_orbit: t.camera_orbit,
|
||||
output_type_ids: t.output_type_ids ?? [],
|
||||
workflow_input_schema: t.workflow_input_schema ?? [],
|
||||
}),
|
||||
onSuccess: () => {
|
||||
toast.success('Template duplicated')
|
||||
@@ -147,13 +175,19 @@ export default function RenderTemplateTable() {
|
||||
lighting_only: t.lighting_only,
|
||||
shadow_catcher_enabled: t.shadow_catcher_enabled,
|
||||
camera_orbit: t.camera_orbit,
|
||||
workflow_input_schema_text: stringifyWorkflowInputSchema(t.workflow_input_schema),
|
||||
is_active: t.is_active,
|
||||
})
|
||||
}
|
||||
|
||||
function saveEdit() {
|
||||
if (!editingId) return
|
||||
updateMut.mutate({ id: editingId, data: editDraft as Record<string, unknown> })
|
||||
const data: Record<string, unknown> = { ...editDraft }
|
||||
if (Object.prototype.hasOwnProperty.call(editDraft, 'workflow_input_schema_text')) {
|
||||
data.workflow_input_schema = parseWorkflowInputSchemaText(editDraft.workflow_input_schema_text)
|
||||
delete data.workflow_input_schema_text
|
||||
}
|
||||
updateMut.mutate({ id: editingId, data })
|
||||
}
|
||||
|
||||
// Render the edit form grid (shared between edit-row and add-row)
|
||||
@@ -174,6 +208,9 @@ export default function RenderTemplateTable() {
|
||||
if (field === 'lighting_only') return editDraft.lighting_only ?? t!.lighting_only
|
||||
if (field === 'shadow_catcher_enabled') return editDraft.shadow_catcher_enabled ?? t!.shadow_catcher_enabled
|
||||
if (field === 'camera_orbit') return editDraft.camera_orbit ?? t!.camera_orbit
|
||||
if (field === 'workflow_input_schema_text') {
|
||||
return editDraft.workflow_input_schema_text ?? stringifyWorkflowInputSchema(t!.workflow_input_schema)
|
||||
}
|
||||
if (field === 'is_active') return editDraft.is_active ?? t!.is_active
|
||||
return (editDraft as any)[field] ?? (t as any)[field]
|
||||
}
|
||||
@@ -381,7 +418,27 @@ export default function RenderTemplateTable() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Row 4: Active + Save/Cancel */}
|
||||
<div className="mt-4">
|
||||
<label className="block text-xs font-medium text-content-muted mb-1">
|
||||
Workflow Input Schema (JSON)
|
||||
</label>
|
||||
<textarea
|
||||
className="input-sm w-full min-h-36 font-mono text-xs"
|
||||
value={String(val('workflow_input_schema_text') ?? '[]')}
|
||||
onChange={(e) => set('workflow_input_schema_text', e.target.value)}
|
||||
placeholder='[{"key":"studio_variant","label":"Studio Variant","type":"select","options":[{"value":"default","label":"Default"}]}]'
|
||||
/>
|
||||
<p className="mt-1 text-xs text-content-muted">
|
||||
Defines additional `resolve_template` node inputs for this .blend template.
|
||||
</p>
|
||||
<p className="mt-1 text-xs text-content-muted">
|
||||
Matching variants can be bound inside the template via markers like
|
||||
`template-input:studio_variant=warm` or a `template_input=studio_variant=warm`
|
||||
custom property on collections, objects, or worlds.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Row 5: Active + Save/Cancel */}
|
||||
<div className="flex items-center justify-between mt-4 pt-3 border-t border-border-light">
|
||||
{isEdit ? (
|
||||
<label className="flex items-center gap-2">
|
||||
|
||||
Reference in New Issue
Block a user