From e8cc21481ac326b7ddc0790835d2df0542c5a87f Mon Sep 17 00:00:00 2001 From: Werner Kramer Date: Wed, 29 May 2024 14:14:42 +0200 Subject: [PATCH] Generate schema and ui schema from workflow properties --- src/components/workflows/WorkflowsControl.vue | 43 ++++++++-- src/components/workflows/workflowUtils.ts | 82 +++++++++++++++++++ 2 files changed, 120 insertions(+), 5 deletions(-) create mode 100644 src/components/workflows/workflowUtils.ts diff --git a/src/components/workflows/WorkflowsControl.vue b/src/components/workflows/WorkflowsControl.vue index 3ac94f77..aa15b087 100644 --- a/src/components/workflows/WorkflowsControl.vue +++ b/src/components/workflows/WorkflowsControl.vue @@ -105,6 +105,7 @@ import { WorkflowType, useWorkflowsStore, } from '@/stores/workflows' +import { generateDefaultUISchema, generateJsonSchema } from './workflowUtils' interface Props { secondaryWorkflows: SecondaryWorkflowGroupItem[] | null @@ -280,17 +281,49 @@ function toValue( const formSchema = asyncComputed(async () => { if (!currentWorkflow.value) return undefined - return getJson(`${currentWorkflow.value.secondaryWorkflowId}.schema.json`) + return getSchema(`${currentWorkflow.value.secondaryWorkflowId}.schema.json`) }) + const formUISchema = asyncComputed(async () => { if (!currentWorkflow.value) return undefined - return getJson(`${currentWorkflow.value.secondaryWorkflowId}.ui-schema.json`) + return getUISchema( + `${currentWorkflow.value.secondaryWorkflowId}.ui-schema.json`, + ) }) -async function getJson(file: string) { +async function getUISchema(file: string) { + try { + const schema = await getFile(file) + return schema.json() + } catch (error) { + const workflowProperties = currentWorkflow.value?.properties + if (workflowProperties !== undefined) + return generateDefaultUISchema(workflowProperties) + } +} + +async function getSchema(file: string) { + try { + const schema = await getFile(file) + return schema.json() + } catch (error) { + const workflowProperties = currentWorkflow.value?.properties + if (workflowProperties !== undefined) + return generateJsonSchema(workflowProperties) + } +} + +async function getFile(file: string) { const url = getResourcesStaticUrl(file) - const data = await fetch(url) - return data.json() + try { + const response = await fetch(url) + if (!response.ok) { + throw new Error(`Failed to fetch ${url}`) + } + return response + } catch (error) { + throw new Error(`Failed to fetch ${url}`) + } } function onFormChange(event: any) { diff --git a/src/components/workflows/workflowUtils.ts b/src/components/workflows/workflowUtils.ts new file mode 100644 index 00000000..ebea0d5c --- /dev/null +++ b/src/components/workflows/workflowUtils.ts @@ -0,0 +1,82 @@ +import { SecondaryWorkflowProperties } from '@deltares/fews-pi-requests' + +/** + * Generates a JSON schema based on an array of SecondaryWorkflowProperty objects. + * @param properties An array of SecondaryWorkflowProperty objects. + * @returns The generated JSON schema. + */ +export function generateJsonSchema(properties: SecondaryWorkflowProperties[]) { + const schema: any = { + type: 'object', + properties: {}, + } + + properties.forEach((property) => { + let type = 'string' + switch (property.type) { + case 'dateTime': + type = 'string' + break + case 'float': + case 'double': + case 'int': + type = 'number' + break + case 'string': + break + } + + schema.properties[property.key] = { + type, + } + }) + + return schema +} + +/** + * Generates a default UI schema based on an array of SecondaryWorkflowProperty objects. + * @param properties An array of SecondaryWorkflowProperty objects. + * @returns The generated default UI schema. + */ +export function generateDefaultUISchema( + properties: SecondaryWorkflowProperties[], +) { + const uiSchema: any = { + type: 'VerticalLayout', + elements: [], + } + + properties.forEach((property) => { + if (property.editable === false) return + const element: any = { + type: 'Control', + scope: `#/properties/${property.key}`, + } + + switch (property.type) { + case 'dateTime': + element.options = { + format: 'date-time', + } + break + case 'float': + case 'double': + case 'int': + element.options = { + placeholder: property.description, + format: 'number', + } + break + case 'string': + element.options = { + placeholder: property.description, + } + break + } + + uiSchema.elements.push(element) + }) + + return uiSchema +}