Clean up and improve multi step form block

This commit is contained in:
Andrew Kingston 2023-12-12 20:22:48 +00:00
parent 01c8ef9f0f
commit 69ea28ad46
6 changed files with 104 additions and 113 deletions

View File

@ -465,8 +465,8 @@ const filterCategoryByContext = (component, context) => {
const { _component } = component
if (_component.endsWith("formblock")) {
if (
(component.actionType == "Create" && context.type === "schema") ||
(component.actionType == "View" && context.type === "form")
(component.actionType === "Create" && context.type === "schema") ||
(component.actionType === "View" && context.type === "form")
) {
return false
}
@ -474,20 +474,21 @@ const filterCategoryByContext = (component, context) => {
return true
}
// Enrich binding category information for certain components
const getComponentBindingCategory = (component, context, def) => {
let icon = def.icon
let category = component._instanceName
if (component._component.endsWith("formblock")) {
let contextCategorySuffix = {
form: "Fields",
schema: "Row",
if (context.type === "form") {
category = `${component._instanceName} - Fields`
icon = "Form"
} else if (context.type === "schema") {
category = `${component._instanceName} - Row`
icon = "Data"
}
category = `${component._instanceName} - ${
contextCategorySuffix[context.type]
}`
icon = context.type === "form" ? "Form" : "Data"
}
return {
icon,
category,

View File

@ -1289,15 +1289,14 @@ export const getFrontendStore = () => {
const settings = getComponentSettings(component._component)
const updatedSetting = settings.find(setting => setting.key === name)
// Can be a single string or array of strings
const resetFields = settings.filter(setting => {
return (
// Reset dependent fields
settings.forEach(setting => {
const needsReset =
name === setting.resetOn ||
(Array.isArray(setting.resetOn) && setting.resetOn.includes(name))
)
})
resetFields?.forEach(setting => {
component[setting.key] = null
if (needsReset) {
component[setting.key] = setting.defaultValue || null
}
})
if (

View File

@ -5,7 +5,7 @@
import { currentAsset, store } from "builderStore"
import { Helpers } from "@budibase/bbui"
import { writable } from "svelte/store"
import { buildMultiStepFormBlockButtonConfig } from "@budibase/frontend-core/src/utils/utils"
import { Utils } from "@budibase/frontend-core"
export let componentInstance
export let componentBindings
@ -20,18 +20,18 @@
setContext("multi-step-form-block", multiStepStore)
$: currentStep = $multiStepStore.currentStep
$: stepCount = value?.length || 0
$: multiStepStore.update(state => ({ ...state, stepCount }))
$: defaultButtonConfig = buildMultiStepFormBlockButtonConfig({
$: defaultProps = Utils.buildMultiStepFormBlockDefaultProps({
_id: componentInstance._id,
stepCount: stepCount,
currentStep: currentStep,
})
$: currentStep = $multiStepStore.currentStep
$: stepCount = value?.length || 0
$: multiStepStore.update(state => ({ ...state, stepCount }))
$: dataSource = getDatasourceForProvider($currentAsset, componentInstance)
$: emitCurrentStep(currentStep)
$: sectionName = getSectionName($multiStepStore)
$: stepConfigInstance = buildPseudoInstance(value[currentStep] || {})
$: stepInstance = buildPseudoInstance(value[currentStep], defaultProps)
$: stepDef = {
settings: [
{
@ -150,14 +150,15 @@
}
}
const buildPseudoInstance = ({ buttons, fields, title, desc }) => {
const buildPseudoInstance = (instance, defaultProps) => {
const { buttons, fields, title, desc } = instance || {}
return {
_id: Helpers.uuid(),
_component: "@budibase/standard-components/multistepformblockstep",
_instanceName: `Step ${currentStep + 1}`,
buttons: buttons || defaultButtonConfig,
title: title ?? defaultProps.title,
buttons: buttons || defaultProps.buttons,
fields,
title,
desc,
// Needed for field configuration
@ -169,7 +170,7 @@
<div class="nested-section">
<ComponentSettingsSection
includeHidden
componentInstance={stepConfigInstance}
componentInstance={stepInstance}
componentDefinition={stepDef}
onUpdateSetting={processUpdate}
showInstanceName={false}

View File

@ -6095,6 +6095,7 @@
},
{
"type": "static",
"suffix": "form",
"values": [
{
"label": "Value",

View File

@ -13,56 +13,6 @@
const { fetchDatasourceSchema } = getContext("sdk")
const component = getContext("component")
let schema
let formId
const getCurrentStep = () => {
if ($builderStore?.component?._id === $component.id) {
return $builderStore?.component.step
}
return 0
}
$: currentStep = getCurrentStep(
$builderStore?.component?._id,
componentInstance
)
$: fetchSchema(dataSource)
const getPropsForField = field => {
let fieldProps = field._component
? {
...field,
}
: {
field: field.name,
label: field.name,
placeholder: field.name,
_instanceName: field.name,
}
return fieldProps
}
const getDefaultFields = (fields, schema) => {
if (!schema) {
return []
}
let defaultFields = []
if (!fields || fields.length === 0) {
Object.values(schema)
.filter(field => !field.autocolumn)
.forEach(field => {
defaultFields.push({
name: field.name,
active: true,
})
})
}
return [...fields, ...defaultFields].filter(field => field.active)
}
const FieldTypeToComponentMap = {
string: "stringfield",
number: "numberfield",
@ -79,6 +29,35 @@
bb_reference: "bbreferencefield",
}
let schema
$: fetchSchema(dataSource)
$: enrichedSteps = enrichSteps(steps, schema, $component.id)
$: currentStep = getCurrentStep(
$builderStore?.component?._id,
componentInstance
)
const getCurrentStep = () => {
if ($builderStore?.component?._id === $component.id) {
return $builderStore?.component.step
}
return 0
}
const getPropsForField = field => {
return field._component
? {
...field,
}
: {
field: field.name,
label: field.name,
placeholder: field.name,
_instanceName: field.name,
}
}
const getComponentForField = field => {
const fieldSchemaName = field.field || field.name
if (!fieldSchemaName || !schema?.[fieldSchemaName]) {
@ -92,24 +71,37 @@
schema = (await fetchDatasourceSchema(dataSource)) || {}
}
$: stepProps = steps?.map((step, idx) => {
const { title, desc, fields, buttons } = step
return {
fields: getDefaultFields(fields || [], schema),
title,
desc,
buttons:
buttons ||
Utils.buildMultiStepFormBlockButtonConfig({
_id: $component.id,
stepCount: steps?.length ?? 0,
currentStep: idx,
}),
const getDefaultFields = (fields, schema) => {
if (fields?.length) {
return fields.filter(field => field.active)
}
})
return Object.values(schema || {})
.filter(field => !field.autocolumn)
.map(field => ({
name: field.name,
}))
}
const enrichSteps = (steps, schema, id) => {
const safeSteps = steps?.length ? steps : [{}]
return safeSteps.map((step, idx) => {
const { title, desc, fields, buttons } = step
const defaultProps = Utils.buildMultiStepFormBlockDefaultProps({
_id: id,
stepCount: safeSteps.length,
currentStep: idx,
})
return {
fields: getDefaultFields(fields || [], schema),
title: title ?? defaultProps.title,
desc,
buttons: buttons || defaultProps.buttons,
}
})
}
</script>
{#key stepProps}
{#key enrichedSteps}
<Block>
<BlockComponent
type="form"
@ -119,9 +111,8 @@
step: $builderStore.inBuilder === true ? currentStep + 1 : null,
}}
context="form"
bind:id={formId}
>
{#each steps || [] as step, idx ("step" + step._id)}
{#each enrichedSteps as step, idx}
<BlockComponent
type="formstep"
props={{ step: idx + 1, _instanceName: `Step ${idx + 1}` }}
@ -143,39 +134,32 @@
size: "shrink",
}}
>
<BlockComponent type="container">
<BlockComponent
type="heading"
props={{ text: stepProps?.[idx]?.title }}
/>
<BlockComponent type="container" order={0}>
<BlockComponent type="heading" props={{ text: step.title }} />
</BlockComponent>
<BlockComponent
type="text"
props={{ text: stepProps?.[idx]?.desc }}
/>
<BlockComponent type="fieldgroup">
{#each stepProps?.[idx]?.fields || [] as field, fieldIdx ("field_" + fieldIdx)}
{#if getComponentForField(field) && field.active}
<BlockComponent type="text" props={{ text: step.desc }} order={1} />
<BlockComponent type="fieldgroup" order={2}>
{#each step.fields as field, fieldIdx}
{#if getComponentForField(field)}
<BlockComponent
type={getComponentForField(field)}
props={getPropsForField(field)}
order={idx}
order={fieldIdx}
interactive
name={field?.field}
name={field.field}
/>
{/if}
{/each}
</BlockComponent>
<BlockComponent
type="buttongroup"
props={{ buttons: stepProps?.[idx]?.buttons }}
props={{ buttons: step.buttons }}
styles={{
normal: {
"margin-top": "16px",
},
}}
order={3}
/>
</BlockComponent>
</BlockComponent>

View File

@ -227,7 +227,7 @@ export const buildFormBlockButtonConfig = props => {
})
}
if (actionType == "Update" && showDeleteButton !== false) {
if (actionType === "Update" && showDeleteButton !== false) {
defaultButtons.push({
text: deleteText || "Delete",
_id: Helpers.uuid(),
@ -241,7 +241,7 @@ export const buildFormBlockButtonConfig = props => {
return defaultButtons
}
export const buildMultiStepFormBlockButtonConfig = props => {
export const buildMultiStepFormBlockDefaultProps = props => {
const { _id, stepCount, currentStep } = props || {}
// Sanity check
@ -249,6 +249,8 @@ export const buildMultiStepFormBlockButtonConfig = props => {
return
}
// Default the title to "Step X"
const title = `Step {{ [${_id}-form].[__currentStep] }}`
let buttons = []
// Add previous step button if we aren't the first step
@ -319,5 +321,8 @@ export const buildMultiStepFormBlockButtonConfig = props => {
})
}
return buttons
return {
buttons,
title,
}
}