Update button actions and remove deprecated code
This commit is contained in:
parent
cbe6459a9c
commit
d94473bca5
|
@ -1,3 +1,4 @@
|
||||||
|
import { cloneDeep } from "lodash/fp"
|
||||||
import { get } from "svelte/store"
|
import { get } from "svelte/store"
|
||||||
import { backendUiStore, store } from "builderStore"
|
import { backendUiStore, store } from "builderStore"
|
||||||
import { findAllMatchingComponents, findComponentPath } from "./storeUtils"
|
import { findAllMatchingComponents, findComponentPath } from "./storeUtils"
|
||||||
|
@ -15,10 +16,9 @@ export const getBindableProperties = (rootComponent, componentId) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all bindable data contexts. These are fields of schemas of data contexts
|
* Gets all data provider components above a component.
|
||||||
* provided by data provider components, such as lists or row detail components.
|
|
||||||
*/
|
*/
|
||||||
export const getBindableContexts = (rootComponent, componentId) => {
|
export const getDataProviderComponents = (rootComponent, componentId) => {
|
||||||
if (!rootComponent || !componentId) {
|
if (!rootComponent || !componentId) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
@ -28,43 +28,67 @@ export const getBindableContexts = (rootComponent, componentId) => {
|
||||||
const path = findComponentPath(rootComponent, componentId)
|
const path = findComponentPath(rootComponent, componentId)
|
||||||
path.pop()
|
path.pop()
|
||||||
|
|
||||||
// Enrich components with their definitions
|
// Filter by only data provider components
|
||||||
const enriched = path.map(component => ({
|
return path.filter(component => {
|
||||||
instance: component,
|
const def = store.actions.components.getDefinition(component._component)
|
||||||
definition: store.actions.components.getDefinition(component._component),
|
return def?.dataProvider
|
||||||
}))
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a datasource object for a certain data provider component
|
||||||
|
*/
|
||||||
|
export const getDatasourceForProvider = component => {
|
||||||
|
const def = store.actions.components.getDefinition(component?._component)
|
||||||
|
if (!def) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract datasource from component instance
|
||||||
|
const datasourceSetting = def.settings.find(setting => {
|
||||||
|
return setting.key === def.datasourceSetting
|
||||||
|
})
|
||||||
|
if (!datasourceSetting) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
// There are different types of setting which can be a datasource, for
|
||||||
|
// example an actual datasource object, or a table ID string.
|
||||||
|
// Convert the datasource setting into a proper datasource object so that
|
||||||
|
// we can use it properly
|
||||||
|
if (datasourceSetting.type === "datasource") {
|
||||||
|
return component[datasourceSetting?.key]
|
||||||
|
} else if (datasourceSetting.type === "table") {
|
||||||
|
return {
|
||||||
|
tableId: component[datasourceSetting?.key],
|
||||||
|
type: "table",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all bindable data contexts. These are fields of schemas of data contexts
|
||||||
|
* provided by data provider components, such as lists or row detail components.
|
||||||
|
*/
|
||||||
|
export const getBindableContexts = (rootComponent, componentId) => {
|
||||||
|
const dataProviders = getDataProviderComponents(rootComponent, componentId)
|
||||||
|
|
||||||
// Extract any components which provide data contexts
|
// Extract any components which provide data contexts
|
||||||
const providers = enriched.filter(comp => comp.definition?.dataProvider)
|
|
||||||
let contexts = []
|
let contexts = []
|
||||||
providers.forEach(({ definition, instance }) => {
|
dataProviders.forEach(component => {
|
||||||
// Extract datasource from component instance
|
const datasource = getDatasourceForProvider(component)
|
||||||
const datasourceSetting = definition.settings.find(setting => {
|
|
||||||
return setting.key === definition.datasourceSetting
|
|
||||||
})
|
|
||||||
if (!datasourceSetting) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// There are different types of setting which can be a datasource, for
|
|
||||||
// example an actual datasource object, or a table ID string.
|
|
||||||
// Convert the datasource setting into a proper datasource object so that
|
|
||||||
// we can use it properly
|
|
||||||
let datasource
|
|
||||||
if (datasourceSetting.type === "datasource") {
|
|
||||||
datasource = instance[datasourceSetting?.key]
|
|
||||||
} else if (datasourceSetting.type === "table") {
|
|
||||||
datasource = {
|
|
||||||
tableId: instance[datasourceSetting?.key],
|
|
||||||
type: "table",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!datasource) {
|
if (!datasource) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const { schema, table } = getSchemaForDatasource(datasource)
|
// Get schema and add _id and _rev fields
|
||||||
|
let { schema, table } = getSchemaForDatasource(datasource)
|
||||||
|
schema["_id"] = { type: "string" }
|
||||||
|
schema["_rev"] = { type: "string " }
|
||||||
const keys = Object.keys(schema).sort()
|
const keys = Object.keys(schema).sort()
|
||||||
|
|
||||||
|
// Create bindable properties for each schema field
|
||||||
keys.forEach(key => {
|
keys.forEach(key => {
|
||||||
const fieldSchema = schema[key]
|
const fieldSchema = schema[key]
|
||||||
// Replace certain bindings with a new property to help display components
|
// Replace certain bindings with a new property to help display components
|
||||||
|
@ -77,11 +101,12 @@ export const getBindableContexts = (rootComponent, componentId) => {
|
||||||
|
|
||||||
contexts.push({
|
contexts.push({
|
||||||
type: "context",
|
type: "context",
|
||||||
runtimeBinding: `${instance._id}.${runtimeBoundKey}`,
|
runtimeBinding: `${component._id}.${runtimeBoundKey}`,
|
||||||
readableBinding: `${instance._instanceName}.${table.name}.${key}`,
|
readableBinding: `${component._instanceName}.${table.name}.${key}`,
|
||||||
fieldSchema,
|
fieldSchema,
|
||||||
providerId: instance._id,
|
providerId: component._id,
|
||||||
tableId: datasource.tableId,
|
tableId: datasource.tableId,
|
||||||
|
field: key,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -115,27 +140,22 @@ export const getBindableComponents = rootComponent => {
|
||||||
/**
|
/**
|
||||||
* Gets a schema for a datasource object.
|
* Gets a schema for a datasource object.
|
||||||
*/
|
*/
|
||||||
const getSchemaForDatasource = datasource => {
|
export const getSchemaForDatasource = datasource => {
|
||||||
const tables = get(backendUiStore).tables
|
let schema, table
|
||||||
const { type } = datasource
|
if (datasource) {
|
||||||
const table = tables.find(table => table._id === datasource.tableId)
|
const tables = get(backendUiStore).tables
|
||||||
let schema
|
const { type } = datasource
|
||||||
if (table) {
|
table = tables.find(table => table._id === datasource.tableId)
|
||||||
if (type === "table") {
|
if (table) {
|
||||||
schema = table.schema ?? {}
|
if (type === "table") {
|
||||||
} else if (type === "view") {
|
schema = cloneDeep(table.schema)
|
||||||
schema = table.views?.[datasource.name]?.schema ?? {}
|
} else if (type === "view") {
|
||||||
} else if (type === "link") {
|
schema = cloneDeep(table.views?.[datasource.name]?.schema)
|
||||||
schema = table.schema ?? {}
|
} else if (type === "link") {
|
||||||
|
schema = cloneDeep(table.schema)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (schema) {
|
|
||||||
// Add ID and rev fields for any valid datasources
|
|
||||||
schema["_id"] = { type: "string" }
|
|
||||||
schema["_rev"] = { type: "string " }
|
|
||||||
} else {
|
|
||||||
schema = {}
|
|
||||||
}
|
|
||||||
return { schema, table }
|
return { schema, table }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,6 +163,9 @@ const getSchemaForDatasource = datasource => {
|
||||||
* Converts a readable data binding into a runtime data binding
|
* Converts a readable data binding into a runtime data binding
|
||||||
*/
|
*/
|
||||||
export function readableToRuntimeBinding(bindableProperties, textWithBindings) {
|
export function readableToRuntimeBinding(bindableProperties, textWithBindings) {
|
||||||
|
if (typeof textWithBindings !== "string") {
|
||||||
|
return textWithBindings
|
||||||
|
}
|
||||||
const boundValues = textWithBindings.match(CAPTURE_VAR_INSIDE_MUSTACHE) || []
|
const boundValues = textWithBindings.match(CAPTURE_VAR_INSIDE_MUSTACHE) || []
|
||||||
let result = textWithBindings
|
let result = textWithBindings
|
||||||
boundValues.forEach(boundValue => {
|
boundValues.forEach(boundValue => {
|
||||||
|
@ -160,6 +183,9 @@ export function readableToRuntimeBinding(bindableProperties, textWithBindings) {
|
||||||
* Converts a runtime data binding into a readable data binding
|
* Converts a runtime data binding into a readable data binding
|
||||||
*/
|
*/
|
||||||
export function runtimeToReadableBinding(bindableProperties, textWithBindings) {
|
export function runtimeToReadableBinding(bindableProperties, textWithBindings) {
|
||||||
|
if (typeof textWithBindings !== "string") {
|
||||||
|
return textWithBindings
|
||||||
|
}
|
||||||
const boundValues = textWithBindings.match(CAPTURE_VAR_INSIDE_MUSTACHE) || []
|
const boundValues = textWithBindings.match(CAPTURE_VAR_INSIDE_MUSTACHE) || []
|
||||||
let result = textWithBindings
|
let result = textWithBindings
|
||||||
boundValues.forEach(boundValue => {
|
boundValues.forEach(boundValue => {
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
<script>
|
|
||||||
import { Select, Label } from "@budibase/bbui"
|
|
||||||
import { backendUiStore } from "builderStore"
|
|
||||||
import SaveFields from "./SaveFields.svelte"
|
|
||||||
|
|
||||||
export let parameters
|
|
||||||
|
|
||||||
const tableFields = tableId => {
|
|
||||||
const table = $backendUiStore.tables.find(m => m._id === tableId)
|
|
||||||
return Object.keys(table.schema).map(k => ({
|
|
||||||
name: k,
|
|
||||||
type: table.schema[k].type,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
$: schemaFields =
|
|
||||||
parameters && parameters.tableId ? tableFields(parameters.tableId) : []
|
|
||||||
|
|
||||||
const onFieldsChanged = e => {
|
|
||||||
parameters.fields = e.detail
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="root">
|
|
||||||
<Label size="m" color="dark">Table</Label>
|
|
||||||
<Select secondary bind:value={parameters.tableId}>
|
|
||||||
<option value="" />
|
|
||||||
{#each $backendUiStore.tables as table}
|
|
||||||
<option value={table._id}>{table.name}</option>
|
|
||||||
{/each}
|
|
||||||
</Select>
|
|
||||||
|
|
||||||
{#if parameters.tableId}
|
|
||||||
<SaveFields
|
|
||||||
parameterFields={parameters.fields}
|
|
||||||
{schemaFields}
|
|
||||||
on:fieldschanged={onFieldsChanged} />
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.root {
|
|
||||||
display: grid;
|
|
||||||
column-gap: var(--spacing-s);
|
|
||||||
row-gap: var(--spacing-s);
|
|
||||||
grid-template-columns: auto 1fr auto 1fr auto;
|
|
||||||
align-items: baseline;
|
|
||||||
}
|
|
||||||
.root :global(> div:nth-child(2)) {
|
|
||||||
grid-column-start: 2;
|
|
||||||
grid-column-end: 6;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,51 +1,36 @@
|
||||||
<script>
|
<script>
|
||||||
import { Select, Label } from "@budibase/bbui"
|
import { Select, Label } from "@budibase/bbui"
|
||||||
import { store, backendUiStore, currentAsset } from "builderStore"
|
import { store, currentAsset } from "builderStore"
|
||||||
import { getBindableProperties } from "builderStore/dataBinding"
|
import {
|
||||||
|
getDataProviderComponents,
|
||||||
|
getDatasourceForProvider,
|
||||||
|
getSchemaForDatasource,
|
||||||
|
} from "builderStore/dataBinding"
|
||||||
|
|
||||||
export let parameters
|
export let parameters
|
||||||
|
|
||||||
let idFields
|
$: dataProviderComponents = getDataProviderComponents(
|
||||||
|
|
||||||
$: bindableProperties = getBindableProperties(
|
|
||||||
$currentAsset.props,
|
$currentAsset.props,
|
||||||
$store.selectedComponentId
|
$store.selectedComponentId
|
||||||
)
|
)
|
||||||
$: idFields = bindableProperties.filter(
|
|
||||||
bindable =>
|
|
||||||
bindable.type === "context" && bindable.runtimeBinding.endsWith("._id")
|
|
||||||
)
|
|
||||||
$: {
|
$: {
|
||||||
|
// Automatically set rev and table ID based on row ID
|
||||||
if (parameters.rowId) {
|
if (parameters.rowId) {
|
||||||
// Set rev ID
|
|
||||||
parameters.revId = parameters.rowId.replace("_id", "_rev")
|
parameters.revId = parameters.rowId.replace("_id", "_rev")
|
||||||
|
const providerComponent = dataProviderComponents.find(
|
||||||
// Set table ID
|
provider => provider._id === parameters.providerId
|
||||||
const idBinding = bindableProperties.find(
|
|
||||||
prop =>
|
|
||||||
prop.runtimeBinding ===
|
|
||||||
parameters.rowId
|
|
||||||
.replace("{{", "")
|
|
||||||
.replace("}}", "")
|
|
||||||
.trim()
|
|
||||||
)
|
)
|
||||||
if (idBinding) {
|
const datasource = getDatasourceForProvider(providerComponent)
|
||||||
const { instance } = idBinding
|
const { table } = getSchemaForDatasource(datasource)
|
||||||
const component = $store.components[instance._component]
|
if (table) {
|
||||||
const tableInfo = instance[component.context]
|
parameters.tableId = table._id
|
||||||
if (tableInfo) {
|
|
||||||
parameters.tableId =
|
|
||||||
typeof tableInfo === "string" ? tableInfo : tableInfo.tableId
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(parameters)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
{#if idFields.length === 0}
|
{#if dataProviderComponents.length === 0}
|
||||||
<div class="cannot-use">
|
<div class="cannot-use">
|
||||||
Delete row can only be used within a component that provides data, such as
|
Delete row can only be used within a component that provides data, such as
|
||||||
a List
|
a List
|
||||||
|
@ -54,9 +39,9 @@
|
||||||
<Label size="m" color="dark">Datasource</Label>
|
<Label size="m" color="dark">Datasource</Label>
|
||||||
<Select secondary bind:value={parameters.rowId}>
|
<Select secondary bind:value={parameters.rowId}>
|
||||||
<option value="" />
|
<option value="" />
|
||||||
{#each idFields as idField}
|
{#each dataProviderComponents as provider}
|
||||||
<option value={`{{ ${idField.runtimeBinding} }}`}>
|
<option value={`{{ ${provider._id}._id }}`}>
|
||||||
{idField.instance._instanceName}
|
{provider._instanceName}
|
||||||
</option>
|
</option>
|
||||||
{/each}
|
{/each}
|
||||||
</Select>
|
</Select>
|
||||||
|
|
|
@ -1,77 +1,28 @@
|
||||||
<script>
|
<script>
|
||||||
import { Select, Label } from "@budibase/bbui"
|
import { Select, Label } from "@budibase/bbui"
|
||||||
import { store, backendUiStore, currentAsset } from "builderStore"
|
import { store, currentAsset } from "builderStore"
|
||||||
import { getBindableProperties } from "builderStore/dataBinding"
|
import {
|
||||||
|
getDataProviderComponents,
|
||||||
|
getDatasourceForProvider,
|
||||||
|
getSchemaForDatasource,
|
||||||
|
} from "builderStore/dataBinding"
|
||||||
import SaveFields from "./SaveFields.svelte"
|
import SaveFields from "./SaveFields.svelte"
|
||||||
|
|
||||||
// parameters.contextPath used in the client handler to determine which row to save
|
|
||||||
// this could be "data" or "data.parent", "data.parent.parent" etc
|
|
||||||
export let parameters
|
export let parameters
|
||||||
|
|
||||||
let idFields
|
$: dataProviderComponents = getDataProviderComponents(
|
||||||
let schemaFields
|
|
||||||
|
|
||||||
$: bindableProperties = getBindableProperties(
|
|
||||||
$currentAsset.props,
|
$currentAsset.props,
|
||||||
$store.selectedComponentId
|
$store.selectedComponentId
|
||||||
)
|
)
|
||||||
|
$: providerComponent = dataProviderComponents.find(
|
||||||
|
provider => provider._id === parameters.providerId
|
||||||
|
)
|
||||||
|
$: schemaFields = getSchemaFields(providerComponent)
|
||||||
|
|
||||||
$: {
|
const getSchemaFields = component => {
|
||||||
if (parameters && parameters.contextPath) {
|
const datasource = getDatasourceForProvider(component)
|
||||||
schemaFields = schemaFromContextPath(parameters.contextPath)
|
const { schema } = getSchemaForDatasource(datasource)
|
||||||
} else {
|
return Object.values(schema || {})
|
||||||
schemaFields = []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const idBindingToContextPath = id => id.substring(0, id.length - 4)
|
|
||||||
const contextPathToId = path => `${path}._id`
|
|
||||||
|
|
||||||
$: {
|
|
||||||
idFields = bindableProperties.filter(
|
|
||||||
bindable =>
|
|
||||||
bindable.type === "context" && bindable.runtimeBinding.endsWith("._id")
|
|
||||||
)
|
|
||||||
// ensure contextPath is always defaulted - there is usually only one option
|
|
||||||
if (idFields.length > 0 && !parameters.contextPath) {
|
|
||||||
parameters.contextPath = idBindingToContextPath(
|
|
||||||
idFields[0].runtimeBinding
|
|
||||||
)
|
|
||||||
parameters = parameters
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// just wraps binding in {{ ... }}
|
|
||||||
const toBindingExpression = bindingPath => `{{ ${bindingPath} }}`
|
|
||||||
|
|
||||||
// finds the selected idBinding, then reads the table/view
|
|
||||||
// from the component instance that it belongs to.
|
|
||||||
// then returns the field names for that schema
|
|
||||||
const schemaFromContextPath = contextPath => {
|
|
||||||
if (!contextPath) return []
|
|
||||||
|
|
||||||
const idBinding = bindableProperties.find(
|
|
||||||
prop => prop.runtimeBinding === contextPathToId(contextPath)
|
|
||||||
)
|
|
||||||
if (!idBinding) return []
|
|
||||||
|
|
||||||
const { instance } = idBinding
|
|
||||||
|
|
||||||
const component = $store.components[instance._component]
|
|
||||||
|
|
||||||
// component.context is the name of the prop that holds the tableId
|
|
||||||
const tableInfo = instance[component.context]
|
|
||||||
const tableId =
|
|
||||||
typeof tableInfo === "string" ? tableInfo : tableInfo.tableId
|
|
||||||
|
|
||||||
if (!tableInfo) return []
|
|
||||||
|
|
||||||
const table = $backendUiStore.tables.find(m => m._id === tableId)
|
|
||||||
parameters.tableId = tableId
|
|
||||||
return Object.keys(table.schema).map(k => ({
|
|
||||||
name: k,
|
|
||||||
type: table.schema[k].type,
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const onFieldsChanged = e => {
|
const onFieldsChanged = e => {
|
||||||
|
@ -80,19 +31,17 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
{#if idFields.length === 0}
|
{#if !dataProviderComponents.length}
|
||||||
<div class="cannot-use">
|
<div class="cannot-use">
|
||||||
Update row can only be used within a component that provides data, such as
|
Save Row can only be used within a component that provides data, such as a
|
||||||
a List
|
Repeater
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<Label size="m" color="dark">Datasource</Label>
|
<Label size="m" color="dark">Datasource</Label>
|
||||||
<Select secondary bind:value={parameters.contextPath}>
|
<Select secondary bind:value={parameters.providerId}>
|
||||||
<option value="" />
|
<option value="" />
|
||||||
{#each idFields as idField}
|
{#each dataProviderComponents as provider}
|
||||||
<option value={idBindingToContextPath(idField.runtimeBinding)}>
|
<option value={provider._id}>{provider._instanceName}</option>
|
||||||
{idField.instance._instanceName}
|
|
||||||
</option>
|
|
||||||
{/each}
|
{/each}
|
||||||
</Select>
|
</Select>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -1,127 +0,0 @@
|
||||||
<script>
|
|
||||||
import { Select, Label } from "@budibase/bbui"
|
|
||||||
import { store, backendUiStore, currentAsset } from "builderStore"
|
|
||||||
import { getBindableProperties } from "builderStore/dataBinding"
|
|
||||||
import SaveFields from "./SaveFields.svelte"
|
|
||||||
|
|
||||||
export let parameters
|
|
||||||
|
|
||||||
$: bindableProperties = getBindableProperties(
|
|
||||||
$currentAsset.props,
|
|
||||||
$store.selectedComponentId
|
|
||||||
)
|
|
||||||
|
|
||||||
let idFields
|
|
||||||
let rowId
|
|
||||||
$: {
|
|
||||||
idFields = bindableProperties.filter(
|
|
||||||
bindable =>
|
|
||||||
bindable.type === "context" && bindable.runtimeBinding.endsWith("._id")
|
|
||||||
)
|
|
||||||
// ensure rowId is always defaulted - there is usually only one option
|
|
||||||
if (idFields.length > 0 && !parameters._id) {
|
|
||||||
rowId = idFields[0].runtimeBinding
|
|
||||||
parameters = parameters
|
|
||||||
} else if (!rowId && parameters._id) {
|
|
||||||
rowId = parameters._id
|
|
||||||
.replace("{{", "")
|
|
||||||
.replace("}}", "")
|
|
||||||
.trim()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$: parameters._id = `{{ ${rowId} }}`
|
|
||||||
|
|
||||||
// just wraps binding in {{ ... }}
|
|
||||||
const toBindingExpression = bindingPath => `{{ ${bindingPath} }}`
|
|
||||||
|
|
||||||
// finds the selected idBinding, then reads the table/view
|
|
||||||
// from the component instance that it belongs to.
|
|
||||||
// then returns the field names for that schema
|
|
||||||
const schemaFromIdBinding = rowId => {
|
|
||||||
if (!rowId) return []
|
|
||||||
|
|
||||||
const idBinding = bindableProperties.find(
|
|
||||||
prop => prop.runtimeBinding === rowId
|
|
||||||
)
|
|
||||||
if (!idBinding) return []
|
|
||||||
|
|
||||||
const { instance } = idBinding
|
|
||||||
|
|
||||||
const component = $store.components[instance._component]
|
|
||||||
|
|
||||||
// component.context is the name of the prop that holds the tableId
|
|
||||||
const tableInfo = instance[component.context]
|
|
||||||
|
|
||||||
if (!tableInfo) return []
|
|
||||||
|
|
||||||
const table = $backendUiStore.tables.find(m => m._id === tableInfo.tableId)
|
|
||||||
parameters.tableId = tableInfo.tableId
|
|
||||||
return Object.keys(table.schema).map(k => ({
|
|
||||||
name: k,
|
|
||||||
type: table.schema[k].type,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
let schemaFields
|
|
||||||
$: {
|
|
||||||
if (parameters && rowId) {
|
|
||||||
schemaFields = schemaFromIdBinding(rowId)
|
|
||||||
} else {
|
|
||||||
schemaFields = []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const onFieldsChanged = e => {
|
|
||||||
parameters.fields = e.detail
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="root">
|
|
||||||
{#if idFields.length === 0}
|
|
||||||
<div class="cannot-use">
|
|
||||||
Update row can only be used within a component that provides data, such as
|
|
||||||
a List
|
|
||||||
</div>
|
|
||||||
{:else}
|
|
||||||
<Label size="m" color="dark">Row Id</Label>
|
|
||||||
<Select secondary bind:value={rowId}>
|
|
||||||
<option value="" />
|
|
||||||
{#each idFields as idField}
|
|
||||||
<option value={idField.runtimeBinding}>
|
|
||||||
{idField.readableBinding}
|
|
||||||
</option>
|
|
||||||
{/each}
|
|
||||||
</Select>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if rowId}
|
|
||||||
<SaveFields
|
|
||||||
parameterFields={parameters.fields}
|
|
||||||
{schemaFields}
|
|
||||||
on:fieldschanged={onFieldsChanged} />
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.root {
|
|
||||||
display: grid;
|
|
||||||
column-gap: var(--spacing-s);
|
|
||||||
row-gap: var(--spacing-s);
|
|
||||||
grid-template-columns: auto 1fr auto 1fr auto;
|
|
||||||
align-items: baseline;
|
|
||||||
}
|
|
||||||
|
|
||||||
.root :global(> div:nth-child(2)) {
|
|
||||||
grid-column-start: 2;
|
|
||||||
grid-column-end: 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cannot-use {
|
|
||||||
color: var(--red);
|
|
||||||
font-size: var(--font-size-s);
|
|
||||||
text-align: center;
|
|
||||||
width: 70%;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,39 +1,49 @@
|
||||||
|
import { get } from "svelte/store"
|
||||||
import { enrichDataBinding } from "./enrichDataBinding"
|
import { enrichDataBinding } from "./enrichDataBinding"
|
||||||
import { routeStore } from "../store"
|
import { routeStore, builderStore } from "../store"
|
||||||
import { saveRow, deleteRow, triggerAutomation } from "../api"
|
import { saveRow, deleteRow, triggerAutomation } from "../api"
|
||||||
|
|
||||||
const saveRowHandler = async (action, context) => {
|
const saveRowHandler = async (action, context) => {
|
||||||
let draft = context[`${action.parameters.contextPath}_draft`]
|
const { fields, providerId } = action.parameters
|
||||||
if (action.parameters.fields) {
|
if (providerId) {
|
||||||
Object.entries(action.parameters.fields).forEach(([key, entry]) => {
|
let draft = context[`${action.parameters.providerId}_draft`]
|
||||||
draft[key] = enrichDataBinding(entry.value, context)
|
if (fields) {
|
||||||
})
|
Object.entries(fields).forEach(([key, entry]) => {
|
||||||
|
draft[key] = enrichDataBinding(entry.value, context)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
await saveRow(draft)
|
||||||
}
|
}
|
||||||
await saveRow(draft)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const deleteRowHandler = async (action, context) => {
|
const deleteRowHandler = async (action, context) => {
|
||||||
const { tableId, revId, rowId } = action.parameters
|
const { tableId, revId, rowId } = action.parameters
|
||||||
await deleteRow({
|
if (tableId && revId && rowId) {
|
||||||
tableId: enrichDataBinding(tableId, context),
|
await deleteRow({
|
||||||
rowId: enrichDataBinding(rowId, context),
|
tableId: enrichDataBinding(tableId, context),
|
||||||
revId: enrichDataBinding(revId, context),
|
rowId: enrichDataBinding(rowId, context),
|
||||||
})
|
revId: enrichDataBinding(revId, context),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const triggerAutomationHandler = async (action, context) => {
|
const triggerAutomationHandler = async (action, context) => {
|
||||||
const params = {}
|
const params = {}
|
||||||
for (let field in action.parameters.fields) {
|
if (action.parameters.fields) {
|
||||||
params[field] = enrichDataBinding(
|
for (let field in action.parameters.fields) {
|
||||||
action.parameters.fields[field].value,
|
params[field] = enrichDataBinding(
|
||||||
context
|
action.parameters.fields[field].value,
|
||||||
)
|
context
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
await triggerAutomation(action.parameters.automationId, params)
|
await triggerAutomation(action.parameters.automationId, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
const navigationHandler = action => {
|
const navigationHandler = action => {
|
||||||
routeStore.actions.navigate(action.parameters.url)
|
if (action.parameters.url) {
|
||||||
|
routeStore.actions.navigate(action.parameters.url)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handlerMap = {
|
const handlerMap = {
|
||||||
|
@ -48,6 +58,10 @@ const handlerMap = {
|
||||||
* actions in the current context.
|
* actions in the current context.
|
||||||
*/
|
*/
|
||||||
export const enrichButtonActions = (actions, context) => {
|
export const enrichButtonActions = (actions, context) => {
|
||||||
|
// Prevent button actions in the builder preview
|
||||||
|
if (get(builderStore).inBuilder) {
|
||||||
|
return () => {}
|
||||||
|
}
|
||||||
const handlers = actions.map(def => handlerMap[def["##eventHandlerType"]])
|
const handlers = actions.map(def => handlerMap[def["##eventHandlerType"]])
|
||||||
return async () => {
|
return async () => {
|
||||||
for (let i = 0; i < handlers.length; i++) {
|
for (let i = 0; i < handlers.length; i++) {
|
||||||
|
|
|
@ -28,8 +28,8 @@
|
||||||
const getFormData = async context => {
|
const getFormData = async context => {
|
||||||
if (context) {
|
if (context) {
|
||||||
const tableDefinition = await API.fetchTableDefinition(context.tableId)
|
const tableDefinition = await API.fetchTableDefinition(context.tableId)
|
||||||
schema = tableDefinition.schema
|
schema = tableDefinition?.schema
|
||||||
fields = Object.keys(schema)
|
fields = Object.keys(schema ?? {})
|
||||||
|
|
||||||
// Use the draft version for editing
|
// Use the draft version for editing
|
||||||
row = $dataContext[`${$dataContext.closestComponentId}_draft`]
|
row = $dataContext[`${$dataContext.closestComponentId}_draft`]
|
||||||
|
|
Loading…
Reference in New Issue