Improve setting rendering and add dynamic section title
This commit is contained in:
parent
1bf556b4f2
commit
173a76dc52
|
@ -4,7 +4,6 @@
|
||||||
export let name
|
export let name
|
||||||
export let initiallyShow = false
|
export let initiallyShow = false
|
||||||
export let collapsible = true
|
export let collapsible = true
|
||||||
export let noPadding = false
|
|
||||||
|
|
||||||
let show = initiallyShow
|
let show = initiallyShow
|
||||||
|
|
||||||
|
@ -29,7 +28,6 @@
|
||||||
class="property-panel"
|
class="property-panel"
|
||||||
class:show={show || !collapsible}
|
class:show={show || !collapsible}
|
||||||
class:no-title={!name}
|
class:no-title={!name}
|
||||||
class:no-padding={noPadding}
|
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
@ -83,10 +81,6 @@
|
||||||
padding: var(--spacing-xl);
|
padding: var(--spacing-xl);
|
||||||
}
|
}
|
||||||
|
|
||||||
.property-panel.no-title.no-padding {
|
|
||||||
padding: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.show {
|
.show {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
|
@ -26,6 +26,7 @@ import FieldConfiguration from "./controls/FieldConfiguration/FieldConfiguration
|
||||||
import ButtonConfiguration from "./controls/ButtonConfiguration/ButtonConfiguration.svelte"
|
import ButtonConfiguration from "./controls/ButtonConfiguration/ButtonConfiguration.svelte"
|
||||||
import RelationshipFilterEditor from "./controls/RelationshipFilterEditor.svelte"
|
import RelationshipFilterEditor from "./controls/RelationshipFilterEditor.svelte"
|
||||||
import FormStepConfiguration from "./controls/FormStepConfiguration.svelte"
|
import FormStepConfiguration from "./controls/FormStepConfiguration.svelte"
|
||||||
|
import FormStepControls from "components/design/settings/controls/FormStepControls.svelte"
|
||||||
|
|
||||||
const componentMap = {
|
const componentMap = {
|
||||||
text: DrawerBindableInput,
|
text: DrawerBindableInput,
|
||||||
|
@ -53,6 +54,7 @@ const componentMap = {
|
||||||
fieldConfiguration: FieldConfiguration,
|
fieldConfiguration: FieldConfiguration,
|
||||||
buttonConfiguration: ButtonConfiguration,
|
buttonConfiguration: ButtonConfiguration,
|
||||||
stepConfiguration: FormStepConfiguration,
|
stepConfiguration: FormStepConfiguration,
|
||||||
|
formStepControls: FormStepControls,
|
||||||
columns: ColumnEditor,
|
columns: ColumnEditor,
|
||||||
"columns/basic": BasicColumnEditor,
|
"columns/basic": BasicColumnEditor,
|
||||||
"columns/grid": GridColumnEditor,
|
"columns/grid": GridColumnEditor,
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
import { getDatasourceForProvider } from "builderStore/dataBinding"
|
import { getDatasourceForProvider } from "builderStore/dataBinding"
|
||||||
import { currentAsset, store } from "builderStore"
|
import { currentAsset, store } from "builderStore"
|
||||||
import { Helpers } from "@budibase/bbui"
|
import { Helpers } from "@budibase/bbui"
|
||||||
import FormStepControls from "./FormStepControls.svelte"
|
|
||||||
import { writable } from "svelte/store"
|
import { writable } from "svelte/store"
|
||||||
import { buildMultiStepFormBlockButtonConfig } from "@budibase/frontend-core/src/utils/utils"
|
import { buildMultiStepFormBlockButtonConfig } from "@budibase/frontend-core/src/utils/utils"
|
||||||
|
|
||||||
|
@ -14,61 +13,70 @@
|
||||||
export let bindings
|
export let bindings
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
const multiStepStore = writable({
|
||||||
let stepState = [...(value || [])]
|
stepCount: value?.length ?? 0,
|
||||||
|
|
||||||
const stepStore = writable({
|
|
||||||
stepsCount: stepState?.length || 1,
|
|
||||||
currentStep: 0,
|
currentStep: 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
setContext("step-form-block", stepStore)
|
setContext("multi-step-form-block", multiStepStore)
|
||||||
|
|
||||||
$: ({ currentStep } = $stepStore)
|
$: currentStep = $multiStepStore.currentStep
|
||||||
$: if (stepState.length) {
|
$: stepCount = value?.length || 0
|
||||||
stepStore.update(state => ({
|
$: multiStepStore.update(state => ({ ...state, stepCount }))
|
||||||
...state,
|
|
||||||
stepsCount: stepState.length || 0,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
$: defaultButtonConfig = buildMultiStepFormBlockButtonConfig({
|
$: defaultButtonConfig = buildMultiStepFormBlockButtonConfig({
|
||||||
_id: componentInstance._id,
|
_id: componentInstance._id,
|
||||||
stepCount: value?.length,
|
stepCount: stepCount,
|
||||||
currentStep,
|
currentStep: currentStep,
|
||||||
})
|
})
|
||||||
|
$: dataSource = getDatasourceForProvider($currentAsset, componentInstance)
|
||||||
|
$: emitCurrentStep(currentStep)
|
||||||
|
$: sectionName = getSectionName($multiStepStore)
|
||||||
|
$: stepDef = {
|
||||||
|
settings: [
|
||||||
|
{
|
||||||
|
section: true,
|
||||||
|
name: sectionName,
|
||||||
|
settings: [
|
||||||
|
{
|
||||||
|
type: "formStepControls",
|
||||||
|
label: "Multi-steps",
|
||||||
|
key: "steps",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "Title",
|
||||||
|
key: "title",
|
||||||
|
nested: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
label: "Description",
|
||||||
|
key: "desc",
|
||||||
|
nested: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "fieldConfiguration",
|
||||||
|
key: "fields",
|
||||||
|
nested: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "buttonConfiguration",
|
||||||
|
label: "Buttons",
|
||||||
|
key: "buttons",
|
||||||
|
wide: true,
|
||||||
|
nested: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
// Step Definition Settings
|
const getSectionName = ({ stepCount, currentStep }) => {
|
||||||
let compSettings = [
|
if (stepCount <= 1) {
|
||||||
{
|
return "Details"
|
||||||
customType: "formStepControl",
|
}
|
||||||
label: "Multi-steps",
|
return `Details (Step ${currentStep + 1}/${stepCount})`
|
||||||
key: "steps",
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "text",
|
|
||||||
label: "Title",
|
|
||||||
key: "title",
|
|
||||||
nested: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "text",
|
|
||||||
label: "Description",
|
|
||||||
key: "desc",
|
|
||||||
nested: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "fieldConfiguration",
|
|
||||||
key: "fields",
|
|
||||||
nested: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "buttonConfiguration",
|
|
||||||
label: "Buttons",
|
|
||||||
key: "buttons",
|
|
||||||
wide: true,
|
|
||||||
nested: true,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
const emitCurrentStep = step => {
|
const emitCurrentStep = step => {
|
||||||
store.actions.preview.sendEvent("builder-meta", {
|
store.actions.preview.sendEvent("builder-meta", {
|
||||||
|
@ -79,70 +87,52 @@
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
$: dataSource = getDatasourceForProvider($currentAsset, componentInstance)
|
|
||||||
|
|
||||||
$: stepDef = {
|
|
||||||
component: "@budibase/standard-components/multistepformblock-step",
|
|
||||||
name: "Formblock step",
|
|
||||||
settings: compSettings,
|
|
||||||
}
|
|
||||||
|
|
||||||
const addStep = () => {
|
const addStep = () => {
|
||||||
const newStepIdx = currentStep + 1
|
const nextStep = currentStep + 1
|
||||||
|
dispatch("change", [
|
||||||
stepState = [
|
...value.slice(0, nextStep),
|
||||||
...stepState.slice(0, newStepIdx),
|
|
||||||
{},
|
{},
|
||||||
...stepState.slice(newStepIdx),
|
...value.slice(nextStep),
|
||||||
]
|
])
|
||||||
|
multiStepStore.update(state => ({
|
||||||
stepStore.update(state => ({
|
|
||||||
...state,
|
...state,
|
||||||
currentStep: newStepIdx,
|
currentStep: nextStep,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
dispatch("change", stepState)
|
|
||||||
emitCurrentStep(newStepIdx)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const removeStep = () => {
|
const removeStep = () => {
|
||||||
const clone = stepState.map(x => x)
|
dispatch("change", value.toSpliced(currentStep, 1))
|
||||||
clone.splice(currentStep, 1)
|
const newStep = Math.min(currentStep, stepCount - 2)
|
||||||
|
multiStepStore.update(state => ({
|
||||||
const targetStepIdx = Math.max(currentStep - 1, 0)
|
|
||||||
stepState = clone.map(x => x)
|
|
||||||
|
|
||||||
stepStore.update(state => ({
|
|
||||||
...state,
|
...state,
|
||||||
currentStep: targetStepIdx,
|
currentStep: newStep,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
dispatch("change", stepState)
|
|
||||||
emitCurrentStep(targetStepIdx)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const previousStep = () => {
|
const previousStep = () => {
|
||||||
const prevStepIdx = Math.max(currentStep - 1, 0)
|
const prevStepIdx = Math.max(currentStep - 1, 0)
|
||||||
stepStore.update(state => ({
|
multiStepStore.update(state => ({
|
||||||
...state,
|
...state,
|
||||||
currentStep: prevStepIdx,
|
currentStep: prevStepIdx,
|
||||||
}))
|
}))
|
||||||
emitCurrentStep(prevStepIdx)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const nextStep = () => {
|
const nextStep = () => {
|
||||||
const nextStepIdx = currentStep + 1
|
const nextStepIdx = currentStep + 1
|
||||||
stepStore.update(state => ({
|
multiStepStore.update(state => ({
|
||||||
...state,
|
...state,
|
||||||
currentStep: Math.min(nextStepIdx, stepState.length - 1),
|
currentStep: Math.min(nextStepIdx, value.length - 1),
|
||||||
}))
|
}))
|
||||||
emitCurrentStep(nextStepIdx)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateStep = (field, val) => {
|
const updateStep = (field, val) => {
|
||||||
stepState[currentStep] ||= {}
|
const newStep = {
|
||||||
stepState[currentStep][field.key] = val
|
...value[currentStep],
|
||||||
dispatch("change", stepState)
|
[field.key]: val,
|
||||||
|
}
|
||||||
|
let newValue = value.slice()
|
||||||
|
newValue[currentStep] = newStep
|
||||||
|
dispatch("change", newValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleStepAction = action => {
|
const handleStepAction = action => {
|
||||||
|
@ -158,9 +148,6 @@
|
||||||
break
|
break
|
||||||
case "previousStep":
|
case "previousStep":
|
||||||
previousStep()
|
previousStep()
|
||||||
break
|
|
||||||
default:
|
|
||||||
console.log("Nothing")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,32 +173,27 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$: stepConfigInstance = buildPseudoInstance(stepState?.[currentStep] || {})
|
$: stepConfigInstance = buildPseudoInstance(value[currentStep] || {})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<span class="settings-wrap">
|
<div class="nested-section">
|
||||||
<ComponentSettingsSection
|
<ComponentSettingsSection
|
||||||
includeHidden
|
includeHidden
|
||||||
componentInstance={stepConfigInstance}
|
componentInstance={stepConfigInstance}
|
||||||
componentDefinition={stepDef}
|
componentDefinition={stepDef}
|
||||||
onUpdateSetting={processUpdate}
|
onUpdateSetting={processUpdate}
|
||||||
getCustomComponent={type => {
|
|
||||||
const types = { formStepControl: FormStepControls }
|
|
||||||
return types[type]
|
|
||||||
}}
|
|
||||||
getCustomSectionTitle={section => {
|
|
||||||
console.log(section.name)
|
|
||||||
if (section.name === "Details" && stepState?.length > 0) {
|
|
||||||
return `Details (${currentStep}/${stepState?.length})`
|
|
||||||
}
|
|
||||||
return section.name
|
|
||||||
}}
|
|
||||||
showSectionTitle={false}
|
|
||||||
showInstanceName={false}
|
showInstanceName={false}
|
||||||
isScreen={false}
|
isScreen={false}
|
||||||
noPadding={true}
|
|
||||||
nested={true}
|
nested={true}
|
||||||
{bindings}
|
{bindings}
|
||||||
{componentBindings}
|
{componentBindings}
|
||||||
/>
|
/>
|
||||||
</span>
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.nested-section {
|
||||||
|
margin: 0 calc(-1 * var(--spacing-xl)) calc(-1 * var(--spacing-xl))
|
||||||
|
calc(-1 * var(--spacing-xl));
|
||||||
|
border-top: var(--border-light);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -2,15 +2,10 @@
|
||||||
import { createEventDispatcher, getContext } from "svelte"
|
import { createEventDispatcher, getContext } from "svelte"
|
||||||
import { ActionButton } from "@budibase/bbui"
|
import { ActionButton } from "@budibase/bbui"
|
||||||
|
|
||||||
const stepState = getContext("step-form-block")
|
const multiStepStore = getContext("multi-step-form-block")
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
$: ({ stepsCount, currentStep } = $stepState)
|
$: ({ stepCount, currentStep } = $multiStepStore)
|
||||||
|
|
||||||
const parseLastIdx = stepsCount => {
|
|
||||||
return Math.max(stepsCount - 1, 0)
|
|
||||||
}
|
|
||||||
$: lastIdx = parseLastIdx(stepsCount)
|
|
||||||
|
|
||||||
const stepAction = action => {
|
const stepAction = action => {
|
||||||
dispatch("change", {
|
dispatch("change", {
|
||||||
|
@ -19,7 +14,7 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if stepsCount === 1}
|
{#if stepCount === 1}
|
||||||
<ActionButton
|
<ActionButton
|
||||||
icon="MultipleAdd"
|
icon="MultipleAdd"
|
||||||
secondary
|
secondary
|
||||||
|
@ -43,7 +38,7 @@
|
||||||
<ActionButton
|
<ActionButton
|
||||||
size="S"
|
size="S"
|
||||||
secondary
|
secondary
|
||||||
disabled={currentStep === lastIdx}
|
disabled={currentStep === stepCount - 1}
|
||||||
icon="ChevronRight"
|
icon="ChevronRight"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
stepAction("nextStep")
|
stepAction("nextStep")
|
||||||
|
@ -53,7 +48,7 @@
|
||||||
size="S"
|
size="S"
|
||||||
secondary
|
secondary
|
||||||
icon="Close"
|
icon="Close"
|
||||||
disabled={stepsCount === 1}
|
disabled={stepCount === 1}
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
stepAction("removeStep")
|
stepAction("removeStep")
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -15,12 +15,9 @@
|
||||||
export let componentBindings
|
export let componentBindings
|
||||||
export let isScreen = false
|
export let isScreen = false
|
||||||
export let onUpdateSetting
|
export let onUpdateSetting
|
||||||
export let getCustomComponent
|
|
||||||
export let getCustomSectionTitle
|
|
||||||
export let showSectionTitle = true
|
export let showSectionTitle = true
|
||||||
export let includeHidden = false
|
export let includeHidden = false
|
||||||
export let tag
|
export let tag
|
||||||
export let noPadding = false
|
|
||||||
|
|
||||||
$: sections = getSections(
|
$: sections = getSections(
|
||||||
componentInstance,
|
componentInstance,
|
||||||
|
@ -133,30 +130,13 @@
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const resolveComponentByType = setting => {
|
|
||||||
if (setting.type) {
|
|
||||||
return getComponentForSetting(setting)
|
|
||||||
} else if (setting.customType && typeof getCustomComponent === "function") {
|
|
||||||
return getCustomComponent(setting.customType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const resolveSectionName = section => {
|
|
||||||
console.log(resolveSectionName)
|
|
||||||
if (typeof getCustomSectionTitle === "function") {
|
|
||||||
return getCustomSectionTitle(section)
|
|
||||||
} else {
|
|
||||||
return section.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const canRenderControl = (instance, setting, isScreen, includeHidden) => {
|
const canRenderControl = (instance, setting, isScreen, includeHidden) => {
|
||||||
// Prevent rendering on click setting for screens
|
// Prevent rendering on click setting for screens
|
||||||
if (setting?.type === "event" && isScreen) {
|
if (setting?.type === "event" && isScreen) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// Check we have a component to render for this setting
|
// Check we have a component to render for this setting
|
||||||
const control = resolveComponentByType(setting)
|
const control = getComponentForSetting(setting)
|
||||||
if (!control) {
|
if (!control) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -172,9 +152,8 @@
|
||||||
{#if section.visible}
|
{#if section.visible}
|
||||||
<DetailSummary
|
<DetailSummary
|
||||||
name={showSectionTitle ? section.name : ""}
|
name={showSectionTitle ? section.name : ""}
|
||||||
show={section.collapsed !== true}
|
|
||||||
{noPadding}
|
|
||||||
initiallyShow={section.collapsed !== true}
|
initiallyShow={section.collapsed !== true}
|
||||||
|
collapsible={section.name !== "General"}
|
||||||
>
|
>
|
||||||
{#if section.info}
|
{#if section.info}
|
||||||
<div class="section-info">
|
<div class="section-info">
|
||||||
|
@ -191,7 +170,7 @@
|
||||||
{#if setting.visible}
|
{#if setting.visible}
|
||||||
<PropertyControl
|
<PropertyControl
|
||||||
type={setting.type}
|
type={setting.type}
|
||||||
control={resolveComponentByType(setting)}
|
control={getComponentForSetting(setting)}
|
||||||
label={setting.label}
|
label={setting.label}
|
||||||
labelHidden={setting.labelHidden}
|
labelHidden={setting.labelHidden}
|
||||||
wide={setting.wide}
|
wide={setting.wide}
|
||||||
|
|
|
@ -6057,18 +6057,12 @@
|
||||||
"defaultValue": "Create"
|
"defaultValue": "Create"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Details",
|
"type": "stepConfiguration",
|
||||||
"section": true,
|
"key": "steps",
|
||||||
"settings": [
|
"nested": true,
|
||||||
{
|
"labelHidden": true,
|
||||||
"type": "stepConfiguration",
|
"resetOn": ["dataSource", "actionType"],
|
||||||
"key": "steps",
|
"defaultValue": [{}]
|
||||||
"nested": true,
|
|
||||||
"labelHidden": true,
|
|
||||||
"resetOn": ["dataSource", "actionType"],
|
|
||||||
"defaultValue": [{}]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"actions": [
|
"actions": [
|
||||||
|
|
|
@ -102,7 +102,7 @@
|
||||||
buttons ||
|
buttons ||
|
||||||
Utils.buildMultiStepFormBlockButtonConfig({
|
Utils.buildMultiStepFormBlockButtonConfig({
|
||||||
_id: $component.id,
|
_id: $component.id,
|
||||||
stepCount: steps?.length,
|
stepCount: steps?.length ?? 0,
|
||||||
currentStep: idx,
|
currentStep: idx,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue