Initial commit
This commit is contained in:
parent
3167fcdc76
commit
cb2a19620b
|
@ -44,7 +44,9 @@
|
|||
align-items: stretch;
|
||||
border-bottom: var(--border-light);
|
||||
}
|
||||
|
||||
.property-group-container:last-child {
|
||||
border-bottom: 0px;
|
||||
}
|
||||
.property-group-name {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
|
|
|
@ -93,6 +93,40 @@ const INITIAL_FRONTEND_STATE = {
|
|||
tourNodes: null,
|
||||
}
|
||||
|
||||
export const updateComponentSetting = (name, value) => {
|
||||
return component => {
|
||||
if (!name || !component) {
|
||||
return false
|
||||
}
|
||||
// Skip update if the value is the same
|
||||
if (component[name] === value) {
|
||||
return false
|
||||
}
|
||||
|
||||
const settings = getComponentSettings(component._component)
|
||||
const updatedSetting = settings.find(setting => setting.key === name)
|
||||
|
||||
if (
|
||||
updatedSetting?.type === "dataSource" ||
|
||||
updatedSetting?.type === "table"
|
||||
) {
|
||||
const { schema } = getSchemaForDatasource(null, value)
|
||||
const columnNames = Object.keys(schema || {})
|
||||
const multifieldKeysToSelectAll = settings
|
||||
.filter(setting => {
|
||||
return setting.type === "multifield" && setting.selectAllFields
|
||||
})
|
||||
.map(setting => setting.key)
|
||||
|
||||
multifieldKeysToSelectAll.forEach(key => {
|
||||
component[key] = columnNames
|
||||
})
|
||||
}
|
||||
|
||||
component[name] = value
|
||||
}
|
||||
}
|
||||
|
||||
export const getFrontendStore = () => {
|
||||
const store = writable({ ...INITIAL_FRONTEND_STATE })
|
||||
let websocket
|
||||
|
@ -111,13 +145,18 @@ export const getFrontendStore = () => {
|
|||
}
|
||||
let clone = cloneDeep(screen)
|
||||
const result = patchFn(clone)
|
||||
console.log("sequentialScreenPatch ", result)
|
||||
if (result === false) {
|
||||
return
|
||||
}
|
||||
return await store.actions.screens.save(clone)
|
||||
return
|
||||
//return await store.actions.screens.save(clone)
|
||||
})
|
||||
|
||||
store.actions = {
|
||||
tester: (name, value) => {
|
||||
return updateComponentSetting(name, value)
|
||||
},
|
||||
reset: () => {
|
||||
store.set({ ...INITIAL_FRONTEND_STATE })
|
||||
websocket?.disconnect()
|
||||
|
@ -825,6 +864,7 @@ export const getFrontendStore = () => {
|
|||
},
|
||||
patch: async (patchFn, componentId, screenId) => {
|
||||
// Use selected component by default
|
||||
console.log("front end patch")
|
||||
if (!componentId || !screenId) {
|
||||
const state = get(store)
|
||||
componentId = componentId || state.selectedComponentId
|
||||
|
@ -834,6 +874,7 @@ export const getFrontendStore = () => {
|
|||
return
|
||||
}
|
||||
const patchScreen = screen => {
|
||||
// findComponent looks in the tree not comp.settings[0]
|
||||
let component = findComponent(screen.props, componentId)
|
||||
if (!component) {
|
||||
return false
|
||||
|
@ -842,6 +883,18 @@ export const getFrontendStore = () => {
|
|||
}
|
||||
await store.actions.screens.patch(patchScreen, screenId)
|
||||
},
|
||||
// Temporary
|
||||
customPatch: async (patchFn, componentId, screenId) => {
|
||||
console.log("patchUpdate :")
|
||||
if (!componentId || !screenId) {
|
||||
const state = get(store)
|
||||
componentId = componentId || state.selectedComponentId
|
||||
screenId = screenId || state.selectedScreenId
|
||||
}
|
||||
if (!componentId || !screenId || !patchFn) {
|
||||
return
|
||||
}
|
||||
},
|
||||
delete: async component => {
|
||||
if (!component) {
|
||||
return
|
||||
|
@ -1207,37 +1260,9 @@ export const getFrontendStore = () => {
|
|||
})
|
||||
},
|
||||
updateSetting: async (name, value) => {
|
||||
await store.actions.components.patch(component => {
|
||||
if (!name || !component) {
|
||||
return false
|
||||
}
|
||||
// Skip update if the value is the same
|
||||
if (component[name] === value) {
|
||||
return false
|
||||
}
|
||||
|
||||
const settings = getComponentSettings(component._component)
|
||||
const updatedSetting = settings.find(setting => setting.key === name)
|
||||
|
||||
if (
|
||||
updatedSetting?.type === "dataSource" ||
|
||||
updatedSetting?.type === "table"
|
||||
) {
|
||||
const { schema } = getSchemaForDatasource(null, value)
|
||||
const columnNames = Object.keys(schema || {})
|
||||
const multifieldKeysToSelectAll = settings
|
||||
.filter(setting => {
|
||||
return setting.type === "multifield" && setting.selectAllFields
|
||||
})
|
||||
.map(setting => setting.key)
|
||||
|
||||
multifieldKeysToSelectAll.forEach(key => {
|
||||
component[key] = columnNames
|
||||
})
|
||||
}
|
||||
|
||||
component[name] = value
|
||||
})
|
||||
await store.actions.components.patch(
|
||||
updateComponentSetting(name, value)
|
||||
)
|
||||
},
|
||||
requestEjectBlock: componentId => {
|
||||
store.actions.preview.sendEvent("eject-block", componentId)
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
<!-- FormBlockFieldSettingsPopover -->
|
||||
<script>
|
||||
import { Icon, Popover, Layout } from "@budibase/bbui"
|
||||
import { store } from "builderStore"
|
||||
import { cloneDeep } from "lodash/fp"
|
||||
|
||||
import ComponentSettingsSection from "../../../../../pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/ComponentSettingsSection.svelte"
|
||||
|
||||
export let anchor
|
||||
export let field
|
||||
|
||||
export let componentBindings
|
||||
export let bindings
|
||||
export let parent
|
||||
|
||||
let popover
|
||||
|
||||
$: sudoComponentInstance = buildSudoInstance(field)
|
||||
$: componentDef = store.actions.components.getDefinition(field._component)
|
||||
$: parsedComponentDef = processComponentDefinitionSettings(componentDef)
|
||||
|
||||
const buildSudoInstance = instance => {
|
||||
let clone = cloneDeep(instance)
|
||||
|
||||
// only do this IF necessary
|
||||
const instanceCheck = store.actions.components.createInstance(
|
||||
clone._component,
|
||||
{
|
||||
_instanceName: instance.displayName,
|
||||
field: instance.name, //Must be fixed
|
||||
label: instance.displayName,
|
||||
placeholder: instance.displayName,
|
||||
},
|
||||
{} //?
|
||||
)
|
||||
|
||||
// mutating on load would achieve this.
|
||||
// Would need to replace the entire config at this point
|
||||
// console.log(instanceCheck)
|
||||
|
||||
return instanceCheck
|
||||
}
|
||||
|
||||
// Ensures parent bindings are pushed down
|
||||
// Confirm this
|
||||
const processComponentDefinitionSettings = componentDef => {
|
||||
const clone = cloneDeep(componentDef)
|
||||
clone.settings.forEach(setting => {
|
||||
if (setting.type === "text") {
|
||||
setting.nested = true
|
||||
}
|
||||
})
|
||||
return clone
|
||||
}
|
||||
|
||||
// Current core update setting fn
|
||||
const updateSetting = async (setting, value) => {
|
||||
console.log("Custom Save Setting", setting, value)
|
||||
console.log("The parent", parent)
|
||||
|
||||
//updateBlockFieldSetting in frontend?
|
||||
const nestedFieldInstance = cloneDeep(sudoComponentInstance)
|
||||
|
||||
// Parse the current fields on load and check for unbuilt instances
|
||||
// This is icky
|
||||
let parentFieldsSettings = parent.fields.find(
|
||||
pSetting => pSetting.name === nestedFieldInstance.field
|
||||
)
|
||||
|
||||
//In this scenario it may be best to extract
|
||||
store.actions.tester(setting.key, value)(nestedFieldInstance) //mods the internal val
|
||||
|
||||
parentFieldsSettings = cloneDeep(nestedFieldInstance)
|
||||
|
||||
console.log("UPDATED nestedFieldInstance", nestedFieldInstance)
|
||||
|
||||
//Overwrite all the fields
|
||||
await store.actions.components.updateSetting("fields", parent.fields)
|
||||
|
||||
/*
|
||||
ignore/disabled _instanceName > this will be handled in the new header field.
|
||||
ignore/disabled field > this should be populated and hidden.
|
||||
*/
|
||||
}
|
||||
</script>
|
||||
|
||||
<Icon
|
||||
name="Settings"
|
||||
hoverable
|
||||
size="S"
|
||||
on:click={() => {
|
||||
popover.show()
|
||||
}}
|
||||
/>
|
||||
|
||||
<Popover bind:this={popover} {anchor} align="left-outside">
|
||||
<Layout noPadding>
|
||||
<!--
|
||||
property-group-container - has a border, is there a scenario where it doesnt render?
|
||||
|
||||
FormBlock Default behaviour.
|
||||
|
||||
validation: field.validation,
|
||||
field: field.name,
|
||||
label: field.displayName,
|
||||
placeholder: field.displayName,
|
||||
|
||||
Block differences
|
||||
_instanceName:
|
||||
Filtered as it has been moved to own area.
|
||||
field:
|
||||
Fixed - not visible.
|
||||
|
||||
componentBindings
|
||||
These appear to be removed/invalid
|
||||
|
||||
Bindings
|
||||
{bindings} - working
|
||||
{componentBindings}
|
||||
componentdefinition.settings[x].nested needs to be true
|
||||
Are these appropriate for the form block
|
||||
|
||||
FormBlock will have to pull the settings from fields:[]
|
||||
|
||||
Frontend Store > updateSetting: async (name, value)
|
||||
Performs a patch for the component settings change
|
||||
|
||||
PropertyControl
|
||||
Would this behaviour require a flag?
|
||||
highlighted={$store.highlightedSettingKey === setting.key}
|
||||
propertyFocus={$store.propertyFocus === setting.key}
|
||||
|
||||
Mode filtering of fields
|
||||
Create
|
||||
Update
|
||||
View > do we filter fields here or disable them?
|
||||
Default value?? Makes no sense
|
||||
|
||||
Drawer actions
|
||||
CRUD - how to persist to the correct location?
|
||||
Its just not a thing now
|
||||
- Validation
|
||||
- Bindings
|
||||
- Custom options.
|
||||
|
||||
** Options source - should this be shaped too?
|
||||
Schema,
|
||||
Datasource
|
||||
Custom
|
||||
-->
|
||||
|
||||
<ComponentSettingsSection
|
||||
componentInstance={sudoComponentInstance}
|
||||
componentDefinition={parsedComponentDef}
|
||||
isScreen={false}
|
||||
{bindings}
|
||||
{componentBindings}
|
||||
onUpdateSetting={updateSetting}
|
||||
/>
|
||||
</Layout>
|
||||
</Popover>
|
|
@ -1,45 +1,125 @@
|
|||
<script>
|
||||
import { Button, ActionButton, Drawer } from "@budibase/bbui"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
import ColumnDrawer from "./ColumnDrawer.svelte"
|
||||
import { cloneDeep } from "lodash/fp"
|
||||
import { generate } from "shortid"
|
||||
import {
|
||||
getDatasourceForProvider,
|
||||
getSchemaForDatasource,
|
||||
} from "builderStore/dataBinding"
|
||||
import { currentAsset } from "builderStore"
|
||||
import SettingsList from "../SettingsList.svelte"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
import { store, selectedScreen } from "builderStore"
|
||||
import {
|
||||
getBindableProperties,
|
||||
getComponentBindableProperties,
|
||||
} from "builderStore/dataBinding"
|
||||
|
||||
import EditFieldPopover from "./EditFieldPopover.svelte"
|
||||
|
||||
export let componentInstance
|
||||
export let value = []
|
||||
export let value
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
let drawer
|
||||
let boundValue
|
||||
// Dean - From the inner form block - make a util
|
||||
const FieldTypeToComponentMap = {
|
||||
string: "stringfield",
|
||||
number: "numberfield",
|
||||
bigint: "bigintfield",
|
||||
options: "optionsfield",
|
||||
array: "multifieldselect",
|
||||
boolean: "booleanfield",
|
||||
longform: "longformfield",
|
||||
datetime: "datetimefield",
|
||||
attachment: "attachmentfield",
|
||||
link: "relationshipfield",
|
||||
json: "jsonfield",
|
||||
barcodeqr: "codescanner",
|
||||
}
|
||||
|
||||
// Dean - From the inner form block - make a util
|
||||
const getComponentForField = field => {
|
||||
if (!field || !schema?.[field]) {
|
||||
return null
|
||||
}
|
||||
const type = schema[field].type
|
||||
return FieldTypeToComponentMap[type]
|
||||
}
|
||||
|
||||
let fieldConfigList
|
||||
|
||||
$: text = getText(value)
|
||||
$: convertOldColumnFormat(value)
|
||||
$: datasource = getDatasourceForProvider($currentAsset, componentInstance)
|
||||
$: schema = getSchema($currentAsset, datasource)
|
||||
$: options = Object.keys(schema || {})
|
||||
$: sanitisedValue = getValidColumns(value, options)
|
||||
$: sanitisedValue = getValidColumns(convertOldFieldFormat(value), options)
|
||||
$: updateBoundValue(sanitisedValue)
|
||||
|
||||
const getText = value => {
|
||||
if (!value?.length) {
|
||||
return "All fields"
|
||||
$: fieldConfigList.forEach(column => {
|
||||
if (!column.id) {
|
||||
column.id = generate()
|
||||
}
|
||||
let text = `${value.length} field`
|
||||
if (value.length !== 1) {
|
||||
text += "s"
|
||||
}
|
||||
return text
|
||||
})
|
||||
|
||||
$: bindings = getBindableProperties(
|
||||
$selectedScreen,
|
||||
$store.selectedComponentId
|
||||
)
|
||||
$: console.log("bindings ", bindings)
|
||||
|
||||
$: componentBindings = getComponentBindableProperties(
|
||||
$selectedScreen,
|
||||
$store.selectedComponentId
|
||||
)
|
||||
$: console.log("componentBindings ", componentBindings)
|
||||
|
||||
// Builds unused ones only
|
||||
const buildListOptions = (schema, selected) => {
|
||||
let schemaClone = cloneDeep(schema)
|
||||
selected.forEach(val => {
|
||||
delete schemaClone[val.name]
|
||||
})
|
||||
|
||||
return Object.keys(schemaClone)
|
||||
.filter(key => !schemaClone[key].autocolumn)
|
||||
.map(key => {
|
||||
const col = schemaClone[key]
|
||||
return {
|
||||
name: key,
|
||||
displayName: key,
|
||||
id: generate(),
|
||||
active: typeof col.active != "boolean" ? !value : col.active,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const convertOldColumnFormat = oldColumns => {
|
||||
if (typeof oldColumns?.[0] === "string") {
|
||||
value = oldColumns.map(field => ({ name: field, displayName: field }))
|
||||
/*
|
||||
SUPPORT
|
||||
- ["FIELD1", "FIELD2"...]
|
||||
"fields": [ "First Name", "Last Name" ]
|
||||
|
||||
- [{name: "FIELD1", displayName: "FIELD1"}, ... only the currentlyadded fields]
|
||||
* [{name: "FIELD1", displayName: "FIELD1", active: true|false}, all currently available fields]
|
||||
*/
|
||||
|
||||
$: unconfigured = buildListOptions(schema, fieldConfigList)
|
||||
|
||||
const convertOldFieldFormat = fields => {
|
||||
let formFields
|
||||
if (typeof fields?.[0] === "string") {
|
||||
formFields = fields.map(field => ({
|
||||
name: field,
|
||||
displayName: field,
|
||||
active: true,
|
||||
}))
|
||||
} else {
|
||||
formFields = fields
|
||||
}
|
||||
return (formFields || []).map(field => {
|
||||
return {
|
||||
...field,
|
||||
active: typeof field?.active != "boolean" ? true : field?.active,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getSchema = (asset, datasource) => {
|
||||
|
@ -55,7 +135,7 @@
|
|||
}
|
||||
|
||||
const updateBoundValue = value => {
|
||||
boundValue = cloneDeep(value)
|
||||
fieldConfigList = cloneDeep(value)
|
||||
}
|
||||
|
||||
const getValidColumns = (columns, options) => {
|
||||
|
@ -75,29 +155,32 @@
|
|||
})
|
||||
}
|
||||
|
||||
const open = () => {
|
||||
updateBoundValue(sanitisedValue)
|
||||
drawer.show()
|
||||
let listOptions
|
||||
$: if (fieldConfigList) {
|
||||
listOptions = [...fieldConfigList, ...unconfigured].map(column => {
|
||||
const type = getComponentForField(column.name)
|
||||
const _component = `@budibase/standard-components/${type}`
|
||||
|
||||
return { ...column, _component } //only necessary if it doesnt exist
|
||||
})
|
||||
console.log(listOptions)
|
||||
}
|
||||
|
||||
const save = () => {
|
||||
dispatch("change", getValidColumns(boundValue, options))
|
||||
drawer.hide()
|
||||
const listUpdated = e => {
|
||||
const parsedColumns = getValidColumns(e.detail, options)
|
||||
dispatch("change", parsedColumns)
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="field-configuration">
|
||||
<ActionButton on:click={open}>{text}</ActionButton>
|
||||
<SettingsList
|
||||
value={listOptions}
|
||||
on:change={listUpdated}
|
||||
rightButton={EditFieldPopover}
|
||||
rightProps={{ componentBindings, bindings, parent: componentInstance }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Drawer bind:this={drawer} title="Form Fields">
|
||||
<svelte:fragment slot="description">
|
||||
Configure the fields in your form.
|
||||
</svelte:fragment>
|
||||
<Button cta slot="buttons" on:click={save}>Save</Button>
|
||||
<ColumnDrawer slot="body" bind:columns={boundValue} {options} {schema} />
|
||||
</Drawer>
|
||||
|
||||
<style>
|
||||
.field-configuration :global(.spectrum-ActionButton) {
|
||||
width: 100%;
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
<script>
|
||||
import { Toggle, Icon } from "@budibase/bbui"
|
||||
import { dndzone } from "svelte-dnd-action"
|
||||
import { flip } from "svelte/animate"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
|
||||
export let value = []
|
||||
export let showHandle = true
|
||||
export let rightButton
|
||||
export let rightProps = {}
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const flipDurationMs = 150
|
||||
let dragDisabled = false
|
||||
let listOptions = [...value]
|
||||
let anchors = {}
|
||||
|
||||
const updateColumnOrder = e => {
|
||||
listOptions = e.detail.items
|
||||
}
|
||||
|
||||
const handleFinalize = e => {
|
||||
updateColumnOrder(e)
|
||||
dispatch("change", listOptions)
|
||||
dragDisabled = false
|
||||
}
|
||||
|
||||
// This is optional and should be moved.
|
||||
const onToggle = item => {
|
||||
return e => {
|
||||
console.log(`${item.name} toggled: ${e.detail}`)
|
||||
item.active = e.detail
|
||||
dispatch("change", listOptions)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<ul
|
||||
class="list-wrap"
|
||||
use:dndzone={{
|
||||
items: listOptions,
|
||||
flipDurationMs,
|
||||
dropTargetStyle: { outline: "none" },
|
||||
dragDisabled,
|
||||
}}
|
||||
on:finalize={handleFinalize}
|
||||
on:consider={updateColumnOrder}
|
||||
>
|
||||
{#each listOptions as item (item.id)}
|
||||
<li
|
||||
animate:flip={{ duration: flipDurationMs }}
|
||||
bind:this={anchors[item.id]}
|
||||
>
|
||||
<div class="left-content">
|
||||
{#if showHandle}
|
||||
<div
|
||||
class="handle"
|
||||
aria-label="drag-handle"
|
||||
style={dragDisabled ? "cursor: grab" : "cursor: grabbing"}
|
||||
>
|
||||
<Icon name="DragHandle" size="XL" />
|
||||
</div>
|
||||
{/if}
|
||||
<!-- slot - left action -->
|
||||
<Toggle on:change={onToggle(item)} text="" value={item.active} thin />
|
||||
{item.name}
|
||||
</div>
|
||||
<!-- slot - right action -->
|
||||
<div class="right-content">
|
||||
{#if rightButton}
|
||||
<svelte:component
|
||||
this={rightButton}
|
||||
anchor={anchors[item.id]}
|
||||
field={item}
|
||||
componentBindings={rightProps.componentBindings}
|
||||
bindings={rightProps.bindings}
|
||||
parent={rightProps.parent}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
|
||||
<style>
|
||||
.list-wrap {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
border-radius: 4px;
|
||||
background-color: var(
|
||||
--spectrum-table-background-color,
|
||||
var(--spectrum-global-color-gray-50)
|
||||
);
|
||||
border: 1px solid
|
||||
var(--spectrum-table-border-color, var(--spectrum-alias-border-color-mid));
|
||||
}
|
||||
.list-wrap > li {
|
||||
background-color: var(
|
||||
--spectrum-table-background-color,
|
||||
var(--spectrum-global-color-gray-50)
|
||||
);
|
||||
transition: background-color ease-in-out 130ms;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid
|
||||
var(--spectrum-table-border-color, var(--spectrum-alias-border-color-mid));
|
||||
}
|
||||
.list-wrap > li:hover {
|
||||
background-color: var(
|
||||
--spectrum-table-row-background-color-hover,
|
||||
var(--spectrum-alias-highlight-hover)
|
||||
);
|
||||
}
|
||||
.list-wrap > li:first-child {
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
.list-wrap > li:last-child {
|
||||
border-top-left-radius: var(--spectrum-table-regular-border-radius);
|
||||
border-top-right-radius: var(--spectrum-table-regular-border-radius);
|
||||
}
|
||||
.left-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.list-wrap li {
|
||||
padding-left: var(--spacing-s);
|
||||
padding-right: var(--spacing-s);
|
||||
}
|
||||
</style>
|
|
@ -13,11 +13,16 @@
|
|||
export let bindings
|
||||
export let componentBindings
|
||||
export let isScreen = false
|
||||
export let onUpdateSetting
|
||||
|
||||
$: sections = getSections(componentInstance, componentDefinition, isScreen)
|
||||
|
||||
const getSections = (instance, definition, isScreen) => {
|
||||
const settings = definition?.settings ?? []
|
||||
console.log(
|
||||
"ComponentSettingsSection::definition?.settings",
|
||||
definition?.settings
|
||||
)
|
||||
const generalSettings = settings.filter(setting => !setting.section)
|
||||
const customSections = settings.filter(setting => setting.section)
|
||||
let sections = [
|
||||
|
@ -46,19 +51,23 @@
|
|||
}
|
||||
|
||||
const updateSetting = async (setting, value) => {
|
||||
try {
|
||||
await store.actions.components.updateSetting(setting.key, value)
|
||||
if (typeof onUpdateSetting === "function") {
|
||||
onUpdateSetting(setting, value)
|
||||
} else {
|
||||
try {
|
||||
await store.actions.components.updateSetting(setting.key, value)
|
||||
|
||||
// Send event if required
|
||||
if (setting.sendEvents) {
|
||||
analytics.captureEvent(Events.COMPONENT_UPDATED, {
|
||||
name: componentInstance._component,
|
||||
setting: setting.key,
|
||||
value,
|
||||
})
|
||||
// Send event if required
|
||||
if (setting.sendEvents) {
|
||||
analytics.captureEvent(Events.COMPONENT_UPDATED, {
|
||||
name: componentInstance._component,
|
||||
setting: setting.key,
|
||||
value,
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
notifications.error("Error updating component prop")
|
||||
}
|
||||
} catch (error) {
|
||||
notifications.error("Error updating component prop")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,10 +138,13 @@
|
|||
{/if}
|
||||
{#each section.settings as setting (setting.key)}
|
||||
{#if setting.visible}
|
||||
<!-- DEAN - Remove fieldConfiguration label config -->
|
||||
<PropertyControl
|
||||
type={setting.type}
|
||||
control={getComponentForSetting(setting)}
|
||||
label={setting.label}
|
||||
label={setting.type != "fieldConfiguration"
|
||||
? setting.label
|
||||
: undefined}
|
||||
labelHidden={setting.labelHidden}
|
||||
key={setting.key}
|
||||
value={componentInstance[setting.key]}
|
||||
|
|
|
@ -5106,22 +5106,6 @@
|
|||
"key": "title",
|
||||
"nested": true
|
||||
},
|
||||
{
|
||||
"type": "select",
|
||||
"label": "Size",
|
||||
"key": "size",
|
||||
"options": [
|
||||
{
|
||||
"label": "Medium",
|
||||
"value": "spectrum--medium"
|
||||
},
|
||||
{
|
||||
"label": "Large",
|
||||
"value": "spectrum--large"
|
||||
}
|
||||
],
|
||||
"defaultValue": "spectrum--medium"
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"label": "Empty text",
|
||||
|
@ -5133,45 +5117,6 @@
|
|||
"invert": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"section": true,
|
||||
"name": "Fields",
|
||||
"settings": [
|
||||
{
|
||||
"type": "fieldConfiguration",
|
||||
"label": "Fields",
|
||||
"key": "fields",
|
||||
"selectAllFields": true
|
||||
},
|
||||
{
|
||||
"type": "select",
|
||||
"label": "Field labels",
|
||||
"key": "labelPosition",
|
||||
"defaultValue": "left",
|
||||
"options": [
|
||||
{
|
||||
"label": "Left",
|
||||
"value": "left"
|
||||
},
|
||||
{
|
||||
"label": "Above",
|
||||
"value": "above"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"label": "Disabled",
|
||||
"key": "disabled",
|
||||
"defaultValue": false,
|
||||
"dependsOn": {
|
||||
"setting": "actionType",
|
||||
"value": "View",
|
||||
"invert": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"section": true,
|
||||
"name": "Buttons",
|
||||
|
@ -5241,6 +5186,61 @@
|
|||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"section": true,
|
||||
"name": "Fields",
|
||||
"settings": [
|
||||
{
|
||||
"type": "select",
|
||||
"label": "Align labels",
|
||||
"key": "labelPosition",
|
||||
"defaultValue": "left",
|
||||
"options": [
|
||||
{
|
||||
"label": "Left",
|
||||
"value": "left"
|
||||
},
|
||||
{
|
||||
"label": "Above",
|
||||
"value": "above"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "select",
|
||||
"label": "Size",
|
||||
"key": "size",
|
||||
"options": [
|
||||
{
|
||||
"label": "Medium",
|
||||
"value": "spectrum--medium"
|
||||
},
|
||||
{
|
||||
"label": "Large",
|
||||
"value": "spectrum--large"
|
||||
}
|
||||
],
|
||||
"defaultValue": "spectrum--medium"
|
||||
},
|
||||
{
|
||||
"type": "fieldConfiguration",
|
||||
"label": "Fields",
|
||||
"key": "fields",
|
||||
"selectAllFields": true
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"label": "Disabled",
|
||||
"key": "disabled",
|
||||
"defaultValue": false,
|
||||
"dependsOn": {
|
||||
"setting": "actionType",
|
||||
"value": "View",
|
||||
"invert": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"context": [
|
||||
|
|
|
@ -24,14 +24,20 @@
|
|||
const { fetchDatasourceSchema } = getContext("sdk")
|
||||
|
||||
const convertOldFieldFormat = fields => {
|
||||
if (typeof fields?.[0] === "string") {
|
||||
return fields.map(field => ({ name: field, displayName: field }))
|
||||
}
|
||||
|
||||
return fields
|
||||
return typeof fields?.[0] === "string"
|
||||
? fields.map(field => ({
|
||||
name: field,
|
||||
displayName: field,
|
||||
active: true,
|
||||
}))
|
||||
: fields
|
||||
}
|
||||
|
||||
//All settings need to derive from the block config now
|
||||
|
||||
// Parse the fields here too. Not present means false.
|
||||
const getDefaultFields = (fields, schema) => {
|
||||
let formFields
|
||||
if (schema && (!fields || fields.length === 0)) {
|
||||
const defaultFields = []
|
||||
|
||||
|
@ -41,13 +47,20 @@
|
|||
defaultFields.push({
|
||||
name: field.name,
|
||||
displayName: field.name,
|
||||
active: true,
|
||||
})
|
||||
})
|
||||
|
||||
return defaultFields
|
||||
formFields = [...defaultFields]
|
||||
} else {
|
||||
formFields = (fields || []).map(field => {
|
||||
return {
|
||||
...field,
|
||||
active: typeof field?.active != "boolean" ? true : field?.active,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return fields
|
||||
return formFields.filter(field => field.active)
|
||||
}
|
||||
|
||||
let schema
|
||||
|
@ -56,7 +69,6 @@
|
|||
|
||||
$: formattedFields = convertOldFieldFormat(fields)
|
||||
$: fieldsOrDefault = getDefaultFields(formattedFields, schema)
|
||||
|
||||
$: fetchSchema(dataSource)
|
||||
$: dataProvider = `{{ literal ${safe(providerId)} }}`
|
||||
$: filter = [
|
||||
|
|
|
@ -197,22 +197,24 @@
|
|||
{/if}
|
||||
</BlockComponent>
|
||||
{/if}
|
||||
<BlockComponent type="fieldgroup" props={{ labelPosition }} order={1}>
|
||||
{#each fields as field, idx}
|
||||
{#if getComponentForField(field.name)}
|
||||
<BlockComponent
|
||||
type={getComponentForField(field.name)}
|
||||
props={{
|
||||
validation: field.validation,
|
||||
field: field.name,
|
||||
label: field.displayName,
|
||||
placeholder: field.displayName,
|
||||
}}
|
||||
order={idx}
|
||||
/>
|
||||
{/if}
|
||||
{/each}
|
||||
</BlockComponent>
|
||||
{#key fields}
|
||||
<BlockComponent type="fieldgroup" props={{ labelPosition }} order={1}>
|
||||
{#each fields as field, idx}
|
||||
{#if getComponentForField(field.name)}
|
||||
<BlockComponent
|
||||
type={getComponentForField(field.name)}
|
||||
props={{
|
||||
validation: field.validation,
|
||||
field: field.name,
|
||||
label: field.displayName,
|
||||
placeholder: field.displayName,
|
||||
}}
|
||||
order={idx}
|
||||
/>
|
||||
{/if}
|
||||
{/each}
|
||||
</BlockComponent>
|
||||
{/key}
|
||||
</BlockComponent>
|
||||
</BlockComponent>
|
||||
{:else}
|
||||
|
|
Loading…
Reference in New Issue