Merge pull request #8608 from Budibase/fix/form-block
Fix form block issues
This commit is contained in:
commit
abaa83d4ad
|
@ -23,14 +23,18 @@
|
||||||
export let bindings = []
|
export let bindings = []
|
||||||
export let nested
|
export let nested
|
||||||
|
|
||||||
$: showAvailableActions = !actions?.length
|
|
||||||
|
|
||||||
let actionQuery
|
let actionQuery
|
||||||
$: parsedQuery =
|
|
||||||
typeof actionQuery === "string" ? actionQuery.toLowerCase().trim() : ""
|
|
||||||
|
|
||||||
let selectedAction = actions?.length ? actions[0] : null
|
let selectedAction = actions?.length ? actions[0] : null
|
||||||
|
|
||||||
|
$: {
|
||||||
|
// Ensure parameters object is never null
|
||||||
|
if (selectedAction && !selectedAction.parameters) {
|
||||||
|
selectedAction.parameters = {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$: parsedQuery =
|
||||||
|
typeof actionQuery === "string" ? actionQuery.toLowerCase().trim() : ""
|
||||||
|
$: showAvailableActions = !actions?.length
|
||||||
$: mappedActionTypes = actionTypes.reduce((acc, action) => {
|
$: mappedActionTypes = actionTypes.reduce((acc, action) => {
|
||||||
let parsedName = action.name.toLowerCase().trim()
|
let parsedName = action.name.toLowerCase().trim()
|
||||||
if (parsedQuery.length && parsedName.indexOf(parsedQuery) < 0) {
|
if (parsedQuery.length && parsedName.indexOf(parsedQuery) < 0) {
|
||||||
|
@ -40,7 +44,6 @@
|
||||||
acc[action.type].push(action)
|
acc[action.type].push(action)
|
||||||
return acc
|
return acc
|
||||||
}, {})
|
}, {})
|
||||||
|
|
||||||
// These are ephemeral bindings which only exist while executing actions
|
// These are ephemeral bindings which only exist while executing actions
|
||||||
$: eventContexBindings = getEventContextBindings(
|
$: eventContexBindings = getEventContextBindings(
|
||||||
$currentAsset,
|
$currentAsset,
|
||||||
|
@ -50,9 +53,8 @@
|
||||||
selectedAction?.id
|
selectedAction?.id
|
||||||
)
|
)
|
||||||
$: allBindings = eventContexBindings.concat(bindings)
|
$: allBindings = eventContexBindings.concat(bindings)
|
||||||
|
|
||||||
// Assign a unique ID to each action
|
|
||||||
$: {
|
$: {
|
||||||
|
// Ensure each action has a unique ID
|
||||||
if (actions) {
|
if (actions) {
|
||||||
actions.forEach(action => {
|
actions.forEach(action => {
|
||||||
if (!action.id) {
|
if (!action.id) {
|
||||||
|
@ -61,13 +63,11 @@
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$: selectedActionComponent =
|
$: selectedActionComponent =
|
||||||
selectedAction &&
|
selectedAction &&
|
||||||
actionTypes.find(t => t.name === selectedAction[EVENT_TYPE_KEY])?.component
|
actionTypes.find(t => t.name === selectedAction[EVENT_TYPE_KEY])?.component
|
||||||
|
|
||||||
// Select the first action if we delete an action
|
|
||||||
$: {
|
$: {
|
||||||
|
// Select the first action if we delete an action
|
||||||
if (selectedAction && !actions?.includes(selectedAction)) {
|
if (selectedAction && !actions?.includes(selectedAction)) {
|
||||||
selectedAction = actions?.[0]
|
selectedAction = actions?.[0]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
<script>
|
<script>
|
||||||
import { Label, Body } from "@budibase/bbui"
|
import { Label } from "@budibase/bbui"
|
||||||
import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte"
|
import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte"
|
||||||
|
|
||||||
export let parameters
|
export let parameters
|
||||||
export let bindings = []
|
export let bindings = []
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Body size="S">Navigate To screen, or leave blank.</Body>
|
|
||||||
<br />
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
|
<span>
|
||||||
|
You can optionally navigate to another screen after closing the screen
|
||||||
|
modal.
|
||||||
|
</span>
|
||||||
<Label small>Screen</Label>
|
<Label small>Screen</Label>
|
||||||
<DrawerBindableInput
|
<DrawerBindableInput
|
||||||
title="Destination URL"
|
title="Destination URL"
|
||||||
|
@ -20,6 +22,9 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
span {
|
||||||
|
grid-column: 1 / 3;
|
||||||
|
}
|
||||||
.root {
|
.root {
|
||||||
display: grid;
|
display: grid;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
let structureLookupMap = {}
|
let structureLookupMap = {}
|
||||||
|
|
||||||
const registerBlockComponent = (id, order, parentId, instance) => {
|
const registerBlockComponent = (id, order, parentId, instance) => {
|
||||||
// Ensure child array exists
|
// Ensure child map exists
|
||||||
if (!structureLookupMap[parentId]) {
|
if (!structureLookupMap[parentId]) {
|
||||||
structureLookupMap[parentId] = {}
|
structureLookupMap[parentId] = {}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,14 @@
|
||||||
structureLookupMap[parentId][order] = instance
|
structureLookupMap[parentId][order] = instance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const unregisterBlockComponent = (order, parentId) => {
|
||||||
|
// Ensure child map exists
|
||||||
|
if (!structureLookupMap[parentId]) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delete structureLookupMap[parentId][order]
|
||||||
|
}
|
||||||
|
|
||||||
const eject = () => {
|
const eject = () => {
|
||||||
// Start the new structure with the root component
|
// Start the new structure with the root component
|
||||||
let definition = structureLookupMap[$component.id][0]
|
let definition = structureLookupMap[$component.id][0]
|
||||||
|
@ -73,6 +81,7 @@
|
||||||
// We register block components with their raw props so that we can eject
|
// We register block components with their raw props so that we can eject
|
||||||
// blocks later on
|
// blocks later on
|
||||||
registerComponent: registerBlockComponent,
|
registerComponent: registerBlockComponent,
|
||||||
|
unregisterComponent: unregisterBlockComponent,
|
||||||
})
|
})
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import { getContext } from "svelte"
|
import { getContext, onDestroy } from "svelte"
|
||||||
import { generate } from "shortid"
|
import { generate } from "shortid"
|
||||||
import { builderStore } from "../stores/builder.js"
|
import { builderStore } from "../stores/builder.js"
|
||||||
import Component from "components/Component.svelte"
|
import Component from "components/Component.svelte"
|
||||||
|
@ -41,6 +41,12 @@
|
||||||
block.registerComponent(id, order ?? 0, $component?.id, instance)
|
block.registerComponent(id, order ?? 0, $component?.id, instance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onDestroy(() => {
|
||||||
|
if ($builderStore.inBuilder) {
|
||||||
|
block.unregisterComponent(order ?? 0, $component?.id)
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Component {instance} isBlock>
|
<Component {instance} isBlock>
|
||||||
|
|
|
@ -1,242 +0,0 @@
|
||||||
<script>
|
|
||||||
import { getContext } from "svelte"
|
|
||||||
import BlockComponent from "../../BlockComponent.svelte"
|
|
||||||
import Block from "../../Block.svelte"
|
|
||||||
import Placeholder from "../Placeholder.svelte"
|
|
||||||
import { makePropSafe as safe } from "@budibase/string-templates"
|
|
||||||
|
|
||||||
export let actionType
|
|
||||||
export let dataSource
|
|
||||||
export let size
|
|
||||||
export let disabled
|
|
||||||
export let fields
|
|
||||||
export let labelPosition
|
|
||||||
export let title
|
|
||||||
export let showSaveButton
|
|
||||||
export let showDeleteButton
|
|
||||||
export let rowId
|
|
||||||
export let actionUrl
|
|
||||||
|
|
||||||
const { fetchDatasourceSchema } = getContext("sdk")
|
|
||||||
const FieldTypeToComponentMap = {
|
|
||||||
string: "stringfield",
|
|
||||||
number: "numberfield",
|
|
||||||
options: "optionsfield",
|
|
||||||
array: "multifieldselect",
|
|
||||||
boolean: "booleanfield",
|
|
||||||
longform: "longformfield",
|
|
||||||
datetime: "datetimefield",
|
|
||||||
attachment: "attachmentfield",
|
|
||||||
link: "relationshipfield",
|
|
||||||
json: "jsonfield",
|
|
||||||
barcodeqr: "codescanner",
|
|
||||||
}
|
|
||||||
|
|
||||||
let schema
|
|
||||||
let formId
|
|
||||||
let providerId
|
|
||||||
let repeaterId
|
|
||||||
|
|
||||||
$: fetchSchema(dataSource)
|
|
||||||
$: onSave = [
|
|
||||||
{
|
|
||||||
"##eventHandlerType": "Save Row",
|
|
||||||
parameters: {
|
|
||||||
providerId: formId,
|
|
||||||
tableId: dataSource?.tableId,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"##eventHandlerType": "Close Screen Modal",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"##eventHandlerType": "Navigate To",
|
|
||||||
parameters: {
|
|
||||||
url: actionUrl,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
$: onDelete = [
|
|
||||||
{
|
|
||||||
"##eventHandlerType": "Delete Row",
|
|
||||||
parameters: {
|
|
||||||
confirm: true,
|
|
||||||
tableId: dataSource?.tableId,
|
|
||||||
rowId: `{{ ${safe(repeaterId)}.${safe("_id")} }}`,
|
|
||||||
revId: `{{ ${safe(repeaterId)}.${safe("_rev")} }}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"##eventHandlerType": "Close Screen Modal",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"##eventHandlerType": "Navigate To",
|
|
||||||
parameters: {
|
|
||||||
url: actionUrl,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
$: filter = [
|
|
||||||
{
|
|
||||||
field: "_id",
|
|
||||||
operator: "equal",
|
|
||||||
type: "string",
|
|
||||||
value: !rowId ? `{{ ${safe("url")}.${safe("id")} }}` : rowId,
|
|
||||||
valueType: "Binding",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
$: dataProvider = `{{ literal ${safe(providerId)} }}`
|
|
||||||
$: renderDeleteButton = showDeleteButton && actionType === "Update"
|
|
||||||
$: renderSaveButton = showSaveButton && actionType !== "View"
|
|
||||||
$: renderButtons = renderDeleteButton || renderSaveButton
|
|
||||||
$: renderHeader = renderButtons || title
|
|
||||||
|
|
||||||
const fetchSchema = async () => {
|
|
||||||
schema = (await fetchDatasourceSchema(dataSource)) || {}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getComponentForField = field => {
|
|
||||||
if (!field || !schema?.[field]) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
const type = schema[field].type
|
|
||||||
return FieldTypeToComponentMap[type]
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<Block>
|
|
||||||
{#if fields?.length}
|
|
||||||
<BlockComponent
|
|
||||||
type="dataprovider"
|
|
||||||
context="provider"
|
|
||||||
bind:id={providerId}
|
|
||||||
props={{
|
|
||||||
dataSource,
|
|
||||||
filter,
|
|
||||||
limit: 1,
|
|
||||||
paginate: false,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<BlockComponent
|
|
||||||
type="repeater"
|
|
||||||
context="repeater"
|
|
||||||
bind:id={repeaterId}
|
|
||||||
props={{
|
|
||||||
dataProvider,
|
|
||||||
noRowsMessage: "We couldn't find a row to display",
|
|
||||||
direction: "column",
|
|
||||||
hAlign: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<BlockComponent
|
|
||||||
type="form"
|
|
||||||
props={{
|
|
||||||
actionType: actionType === "Create" ? "Create" : "Update",
|
|
||||||
dataSource,
|
|
||||||
size,
|
|
||||||
disabled: disabled || actionType === "View",
|
|
||||||
}}
|
|
||||||
styles={{
|
|
||||||
normal: {
|
|
||||||
width: "600px",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
context="form"
|
|
||||||
bind:id={formId}
|
|
||||||
>
|
|
||||||
<BlockComponent
|
|
||||||
type="container"
|
|
||||||
props={{
|
|
||||||
direction: "column",
|
|
||||||
hAlign: "stretch",
|
|
||||||
vAlign: "top",
|
|
||||||
gap: "M",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{#if renderHeader}
|
|
||||||
<BlockComponent
|
|
||||||
type="container"
|
|
||||||
props={{
|
|
||||||
direction: "row",
|
|
||||||
hAlign: "stretch",
|
|
||||||
vAlign: "center",
|
|
||||||
gap: "M",
|
|
||||||
wrap: true,
|
|
||||||
}}
|
|
||||||
order={0}
|
|
||||||
>
|
|
||||||
<BlockComponent
|
|
||||||
type="heading"
|
|
||||||
props={{ text: title || "" }}
|
|
||||||
order={0}
|
|
||||||
/>
|
|
||||||
{#if renderButtons}
|
|
||||||
<BlockComponent
|
|
||||||
type="container"
|
|
||||||
props={{
|
|
||||||
direction: "row",
|
|
||||||
hAlign: "stretch",
|
|
||||||
vAlign: "center",
|
|
||||||
gap: "M",
|
|
||||||
wrap: true,
|
|
||||||
}}
|
|
||||||
order={1}
|
|
||||||
>
|
|
||||||
{#if renderDeleteButton}
|
|
||||||
<BlockComponent
|
|
||||||
type="button"
|
|
||||||
props={{
|
|
||||||
text: "Delete",
|
|
||||||
onClick: onDelete,
|
|
||||||
quiet: true,
|
|
||||||
type: "secondary",
|
|
||||||
}}
|
|
||||||
order={0}
|
|
||||||
/>
|
|
||||||
{/if}
|
|
||||||
{#if renderSaveButton}
|
|
||||||
<BlockComponent
|
|
||||||
type="button"
|
|
||||||
props={{
|
|
||||||
text: "Save",
|
|
||||||
onClick: onSave,
|
|
||||||
type: "cta",
|
|
||||||
}}
|
|
||||||
order={1}
|
|
||||||
/>
|
|
||||||
{/if}
|
|
||||||
</BlockComponent>
|
|
||||||
{/if}
|
|
||||||
</BlockComponent>
|
|
||||||
{/if}
|
|
||||||
<BlockComponent
|
|
||||||
type="fieldgroup"
|
|
||||||
props={{ labelPosition }}
|
|
||||||
order={1}
|
|
||||||
>
|
|
||||||
{#each fields as field, idx}
|
|
||||||
{#if getComponentForField(field)}
|
|
||||||
<BlockComponent
|
|
||||||
type={getComponentForField(field)}
|
|
||||||
props={{
|
|
||||||
field,
|
|
||||||
label: field,
|
|
||||||
placeholder: field,
|
|
||||||
disabled,
|
|
||||||
}}
|
|
||||||
order={idx}
|
|
||||||
/>
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
</BlockComponent>
|
|
||||||
</BlockComponent>
|
|
||||||
</BlockComponent>
|
|
||||||
</BlockComponent>
|
|
||||||
</BlockComponent>
|
|
||||||
{:else}
|
|
||||||
<Placeholder
|
|
||||||
text="Choose your table and add some fields to your form to get started"
|
|
||||||
/>
|
|
||||||
{/if}
|
|
||||||
</Block>
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
<script>
|
||||||
|
import { getContext } from "svelte"
|
||||||
|
import BlockComponent from "components/BlockComponent.svelte"
|
||||||
|
import Block from "components/Block.svelte"
|
||||||
|
import { makePropSafe as safe } from "@budibase/string-templates"
|
||||||
|
import InnerFormBlock from "./InnerFormBlock.svelte"
|
||||||
|
|
||||||
|
export let actionType
|
||||||
|
export let dataSource
|
||||||
|
export let size
|
||||||
|
export let disabled
|
||||||
|
export let fields
|
||||||
|
export let labelPosition
|
||||||
|
export let title
|
||||||
|
export let showSaveButton
|
||||||
|
export let showDeleteButton
|
||||||
|
export let rowId
|
||||||
|
export let actionUrl
|
||||||
|
|
||||||
|
const { fetchDatasourceSchema } = getContext("sdk")
|
||||||
|
|
||||||
|
let schema
|
||||||
|
let providerId
|
||||||
|
let repeaterId
|
||||||
|
|
||||||
|
$: fetchSchema(dataSource)
|
||||||
|
$: dataProvider = `{{ literal ${safe(providerId)} }}`
|
||||||
|
$: filter = [
|
||||||
|
{
|
||||||
|
field: "_id",
|
||||||
|
operator: "equal",
|
||||||
|
type: "string",
|
||||||
|
value: !rowId ? `{{ ${safe("url")}.${safe("id")} }}` : rowId,
|
||||||
|
valueType: "Binding",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
// We could simply spread $$props into the inner form and append our
|
||||||
|
// additions, but that would create svelte warnings about unused props and
|
||||||
|
// make maintenance in future more confusing as we typically always have a
|
||||||
|
// proper mapping of schema settings to component exports, without having to
|
||||||
|
// search multiple files
|
||||||
|
$: innerProps = {
|
||||||
|
dataSource,
|
||||||
|
actionUrl,
|
||||||
|
actionType,
|
||||||
|
size,
|
||||||
|
disabled,
|
||||||
|
fields,
|
||||||
|
labelPosition,
|
||||||
|
title,
|
||||||
|
showSaveButton,
|
||||||
|
showDeleteButton,
|
||||||
|
schema,
|
||||||
|
repeaterId,
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchSchema = async () => {
|
||||||
|
schema = (await fetchDatasourceSchema(dataSource)) || {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Block>
|
||||||
|
{#if actionType === "Create"}
|
||||||
|
<BlockComponent
|
||||||
|
type="container"
|
||||||
|
props={{
|
||||||
|
direction: "column",
|
||||||
|
hAlign: "left",
|
||||||
|
vAlign: "stretch",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<InnerFormBlock {...innerProps} />
|
||||||
|
</BlockComponent>
|
||||||
|
{:else}
|
||||||
|
<BlockComponent
|
||||||
|
type="dataprovider"
|
||||||
|
context="provider"
|
||||||
|
bind:id={providerId}
|
||||||
|
props={{
|
||||||
|
dataSource,
|
||||||
|
filter,
|
||||||
|
limit: 1,
|
||||||
|
paginate: false,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<BlockComponent
|
||||||
|
type="repeater"
|
||||||
|
context="repeater"
|
||||||
|
bind:id={repeaterId}
|
||||||
|
props={{
|
||||||
|
dataProvider,
|
||||||
|
noRowsMessage: "We couldn't find a row to display",
|
||||||
|
direction: "column",
|
||||||
|
hAlign: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<InnerFormBlock {...innerProps} />
|
||||||
|
</BlockComponent>
|
||||||
|
</BlockComponent>
|
||||||
|
{/if}
|
||||||
|
</Block>
|
|
@ -0,0 +1,194 @@
|
||||||
|
<script>
|
||||||
|
import BlockComponent from "components/BlockComponent.svelte"
|
||||||
|
import Placeholder from "components/app/Placeholder.svelte"
|
||||||
|
import { makePropSafe as safe } from "@budibase/string-templates"
|
||||||
|
|
||||||
|
export let dataSource
|
||||||
|
export let actionUrl
|
||||||
|
export let actionType
|
||||||
|
export let size
|
||||||
|
export let disabled
|
||||||
|
export let fields
|
||||||
|
export let labelPosition
|
||||||
|
export let title
|
||||||
|
export let showSaveButton
|
||||||
|
export let showDeleteButton
|
||||||
|
export let schema
|
||||||
|
export let repeaterId
|
||||||
|
|
||||||
|
const FieldTypeToComponentMap = {
|
||||||
|
string: "stringfield",
|
||||||
|
number: "numberfield",
|
||||||
|
options: "optionsfield",
|
||||||
|
array: "multifieldselect",
|
||||||
|
boolean: "booleanfield",
|
||||||
|
longform: "longformfield",
|
||||||
|
datetime: "datetimefield",
|
||||||
|
attachment: "attachmentfield",
|
||||||
|
link: "relationshipfield",
|
||||||
|
json: "jsonfield",
|
||||||
|
barcodeqr: "codescanner",
|
||||||
|
}
|
||||||
|
|
||||||
|
let formId
|
||||||
|
|
||||||
|
$: onSave = [
|
||||||
|
{
|
||||||
|
"##eventHandlerType": "Save Row",
|
||||||
|
parameters: {
|
||||||
|
providerId: formId,
|
||||||
|
tableId: dataSource?.tableId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"##eventHandlerType": "Close Screen Modal",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"##eventHandlerType": "Navigate To",
|
||||||
|
parameters: {
|
||||||
|
url: actionUrl,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
$: onDelete = [
|
||||||
|
{
|
||||||
|
"##eventHandlerType": "Delete Row",
|
||||||
|
parameters: {
|
||||||
|
confirm: true,
|
||||||
|
tableId: dataSource?.tableId,
|
||||||
|
rowId: `{{ ${safe(repeaterId)}.${safe("_id")} }}`,
|
||||||
|
revId: `{{ ${safe(repeaterId)}.${safe("_rev")} }}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"##eventHandlerType": "Close Screen Modal",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"##eventHandlerType": "Navigate To",
|
||||||
|
parameters: {
|
||||||
|
url: actionUrl,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
$: renderDeleteButton = showDeleteButton && actionType === "Update"
|
||||||
|
$: renderSaveButton = showSaveButton && actionType !== "View"
|
||||||
|
$: renderButtons = renderDeleteButton || renderSaveButton
|
||||||
|
$: renderHeader = renderButtons || title
|
||||||
|
|
||||||
|
const getComponentForField = field => {
|
||||||
|
if (!field || !schema?.[field]) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const type = schema[field].type
|
||||||
|
return FieldTypeToComponentMap[type]
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if fields?.length}
|
||||||
|
<BlockComponent
|
||||||
|
type="form"
|
||||||
|
props={{
|
||||||
|
actionType: actionType === "Create" ? "Create" : "Update",
|
||||||
|
dataSource,
|
||||||
|
size,
|
||||||
|
disabled: disabled || actionType === "View",
|
||||||
|
}}
|
||||||
|
styles={{
|
||||||
|
normal: {
|
||||||
|
width: "600px",
|
||||||
|
"margin-left": "auto",
|
||||||
|
"margin-right": "auto",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
context="form"
|
||||||
|
bind:id={formId}
|
||||||
|
>
|
||||||
|
<BlockComponent
|
||||||
|
type="container"
|
||||||
|
props={{
|
||||||
|
direction: "column",
|
||||||
|
hAlign: "stretch",
|
||||||
|
vAlign: "top",
|
||||||
|
gap: "M",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{#if renderHeader}
|
||||||
|
<BlockComponent
|
||||||
|
type="container"
|
||||||
|
props={{
|
||||||
|
direction: "row",
|
||||||
|
hAlign: "stretch",
|
||||||
|
vAlign: "center",
|
||||||
|
gap: "M",
|
||||||
|
wrap: true,
|
||||||
|
}}
|
||||||
|
order={0}
|
||||||
|
>
|
||||||
|
<BlockComponent
|
||||||
|
type="heading"
|
||||||
|
props={{ text: title || "" }}
|
||||||
|
order={0}
|
||||||
|
/>
|
||||||
|
{#if renderButtons}
|
||||||
|
<BlockComponent
|
||||||
|
type="container"
|
||||||
|
props={{
|
||||||
|
direction: "row",
|
||||||
|
hAlign: "stretch",
|
||||||
|
vAlign: "center",
|
||||||
|
gap: "M",
|
||||||
|
wrap: true,
|
||||||
|
}}
|
||||||
|
order={1}
|
||||||
|
>
|
||||||
|
{#if renderDeleteButton}
|
||||||
|
<BlockComponent
|
||||||
|
type="button"
|
||||||
|
props={{
|
||||||
|
text: "Delete",
|
||||||
|
onClick: onDelete,
|
||||||
|
quiet: true,
|
||||||
|
type: "secondary",
|
||||||
|
}}
|
||||||
|
order={0}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
{#if renderSaveButton}
|
||||||
|
<BlockComponent
|
||||||
|
type="button"
|
||||||
|
props={{
|
||||||
|
text: "Save",
|
||||||
|
onClick: onSave,
|
||||||
|
type: "cta",
|
||||||
|
}}
|
||||||
|
order={1}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
</BlockComponent>
|
||||||
|
{/if}
|
||||||
|
</BlockComponent>
|
||||||
|
{/if}
|
||||||
|
<BlockComponent type="fieldgroup" props={{ labelPosition }} order={1}>
|
||||||
|
{#each fields as field, idx}
|
||||||
|
{#if getComponentForField(field)}
|
||||||
|
<BlockComponent
|
||||||
|
type={getComponentForField(field)}
|
||||||
|
props={{
|
||||||
|
field,
|
||||||
|
label: field,
|
||||||
|
placeholder: field,
|
||||||
|
disabled,
|
||||||
|
}}
|
||||||
|
order={idx}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
</BlockComponent>
|
||||||
|
</BlockComponent>
|
||||||
|
</BlockComponent>
|
||||||
|
{:else}
|
||||||
|
<Placeholder
|
||||||
|
text="Choose your table and add some fields to your form to get started"
|
||||||
|
/>
|
||||||
|
{/if}
|
|
@ -1,5 +1,5 @@
|
||||||
export { default as tableblock } from "./TableBlock.svelte"
|
export { default as tableblock } from "./TableBlock.svelte"
|
||||||
export { default as cardsblock } from "./CardsBlock.svelte"
|
export { default as cardsblock } from "./CardsBlock.svelte"
|
||||||
export { default as repeaterblock } from "./RepeaterBlock.svelte"
|
export { default as repeaterblock } from "./RepeaterBlock.svelte"
|
||||||
export { default as formblock } from "./FormBlock.svelte"
|
export { default as formblock } from "./form/FormBlock.svelte"
|
||||||
export { default as chartblock } from "./ChartBlock.svelte"
|
export { default as chartblock } from "./ChartBlock.svelte"
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
export let label
|
export let label
|
||||||
export let placeholder
|
export let placeholder
|
||||||
export let disabled = false
|
export let disabled = false
|
||||||
export let enableTime = false
|
export let enableTime = true
|
||||||
export let timeOnly = false
|
export let timeOnly = false
|
||||||
export let time24hr = false
|
export let time24hr = false
|
||||||
export let ignoreTimezones = false
|
export let ignoreTimezones = false
|
||||||
|
|
Loading…
Reference in New Issue