diff --git a/packages/builder/src/builderStore/dataBinding.js b/packages/builder/src/builderStore/dataBinding.js index 6eb6e6a0d8..7e82a40c41 100644 --- a/packages/builder/src/builderStore/dataBinding.js +++ b/packages/builder/src/builderStore/dataBinding.js @@ -105,11 +105,27 @@ export const getContextBindings = (rootComponent, componentId) => { return } - // Get schema and add _id and _rev fields for certain types - let { schema, table } = getSchemaForDatasource(datasource) + // Get schema and table for the datasource + const isForm = component._component.endsWith("/form") + let { schema, table } = getSchemaForDatasource(datasource, isForm) if (!schema || !table) { return } + + // Forms are an edge case. They can have a schema which will be exposed as + // bindable properties, but they can also have custom fields which we need + // to find and provide. + if (isForm) { + const formSchema = buildFormSchema(component) + console.log(formSchema) + Object.keys(formSchema).forEach(field => { + if (!schema[field]) { + schema[field] = formSchema[field] + } + }) + } + + // Add _id and _rev fields for certain types if (datasource.type === "table" || datasource.type === "link") { schema["_id"] = { type: "string" } schema["_rev"] = { type: "string " } @@ -177,7 +193,7 @@ export const getContextBindings = (rootComponent, componentId) => { /** * Gets a schema for a datasource object. */ -export const getSchemaForDatasource = datasource => { +export const getSchemaForDatasource = (datasource, isForm = false) => { let schema, table if (datasource) { const { type } = datasource @@ -191,6 +207,12 @@ export const getSchemaForDatasource = datasource => { if (table) { if (type === "view") { schema = cloneDeep(table.views?.[datasource.name]?.schema) + } else if (type === "query" && isForm) { + schema = {} + const params = table.parameters || [] + params.forEach(param => { + schema[param.name] = { ...param, type: "string" } + }) } else { schema = cloneDeep(table.schema) } @@ -199,6 +221,32 @@ export const getSchemaForDatasource = datasource => { return { schema, table } } +/** + * Builds a form schema given a form component. + * A form schema is a schema of all the fields nested anywhere within a form. + */ +const buildFormSchema = component => { + let schema = {} + if (!component) { + return schema + } + const def = store.actions.components.getDefinition(component._component) + const fieldSetting = def?.settings?.find( + setting => setting.key === "field" && setting.type.startsWith("field/") + ) + if (fieldSetting && component.field) { + const type = fieldSetting.type.split("field/")[1] + if (type) { + schema[component.field] = { name: component.field, type } + } + } + component._children?.forEach(child => { + const childSchema = buildFormSchema(child) + schema = { ...schema, ...childSchema } + }) + return schema +} + /** * utility function for the readableToRuntimeBinding and runtimeToReadableBinding. */ diff --git a/packages/builder/src/builderStore/store/screenTemplates/utils/commonComponents.js b/packages/builder/src/builderStore/store/screenTemplates/utils/commonComponents.js index d2757ec054..8c6bfe646b 100644 --- a/packages/builder/src/builderStore/store/screenTemplates/utils/commonComponents.js +++ b/packages/builder/src/builderStore/store/screenTemplates/utils/commonComponents.js @@ -169,7 +169,11 @@ export function makeTableFormComponents(tableId) { export function makeQueryFormComponents(queryId) { const queries = get(backendUiStore).queries - const schema = queries.find(query => query._id === queryId)?.schema ?? [] + const params = queries.find(query => query._id === queryId)?.parameters ?? [] + let schema = {} + params.forEach(param => { + schema[param.name] = { ...param, type: "string" } + }) return makeSchemaFormComponents(schema) } diff --git a/packages/builder/src/components/design/PropertiesPanel/SettingsView.svelte b/packages/builder/src/components/design/PropertiesPanel/SettingsView.svelte index 9f16578ce5..c3577e3259 100644 --- a/packages/builder/src/components/design/PropertiesPanel/SettingsView.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/SettingsView.svelte @@ -78,7 +78,7 @@ "field/longform": LongFormFieldSelect, "field/datetime": DateTimeFieldSelect, "field/attachment": AttachmentFieldSelect, - "field/relationship": RelationshipFieldSelect, + "field/link": RelationshipFieldSelect, } const getControl = type => { diff --git a/packages/client/src/utils/buttonActions.js b/packages/client/src/utils/buttonActions.js index 4b12823d2b..ba91f44f75 100644 --- a/packages/client/src/utils/buttonActions.js +++ b/packages/client/src/utils/buttonActions.js @@ -34,7 +34,7 @@ const deleteRowHandler = async (action, context) => { } const triggerAutomationHandler = async (action, context) => { - const { fields } = action.parameters() + const { fields } = action.parameters if (fields) { const params = {} for (let field in fields) { diff --git a/packages/standard-components/manifest.json b/packages/standard-components/manifest.json index 9e8652f450..b97c37c9f7 100644 --- a/packages/standard-components/manifest.json +++ b/packages/standard-components/manifest.json @@ -1282,7 +1282,7 @@ "styleable": true, "settings": [ { - "type": "field/relationship", + "type": "field/link", "label": "Field", "key": "field" }, diff --git a/packages/standard-components/src/forms/Form.svelte b/packages/standard-components/src/forms/Form.svelte index 31623d30f6..d65c851f43 100644 --- a/packages/standard-components/src/forms/Form.svelte +++ b/packages/standard-components/src/forms/Form.svelte @@ -133,7 +133,15 @@ } else { table = await API.fetchTableDefinition(datasource?.tableId) if (table) { - schema = table.schema || {} + if (datasource?.type === "query") { + schema = {} + const params = table.parameters || [] + params.forEach(param => { + schema[param.name] = { ...param, type: "string" } + }) + } else { + schema = table.schema || {} + } } } loaded = true