Update button actions and remove deprecated code
This commit is contained in:
parent
10f8e53305
commit
7e7219856d
|
@ -1,3 +1,4 @@
|
|||
import { cloneDeep } from "lodash/fp"
|
||||
import { get } from "svelte/store"
|
||||
import { backendUiStore, store } from "builderStore"
|
||||
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
|
||||
* provided by data provider components, such as lists or row detail components.
|
||||
* Gets all data provider components above a component.
|
||||
*/
|
||||
export const getBindableContexts = (rootComponent, componentId) => {
|
||||
export const getDataProviderComponents = (rootComponent, componentId) => {
|
||||
if (!rootComponent || !componentId) {
|
||||
return []
|
||||
}
|
||||
|
@ -28,43 +28,67 @@ export const getBindableContexts = (rootComponent, componentId) => {
|
|||
const path = findComponentPath(rootComponent, componentId)
|
||||
path.pop()
|
||||
|
||||
// Enrich components with their definitions
|
||||
const enriched = path.map(component => ({
|
||||
instance: component,
|
||||
definition: store.actions.components.getDefinition(component._component),
|
||||
}))
|
||||
// Filter by only data provider components
|
||||
return path.filter(component => {
|
||||
const def = 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 any components which provide data contexts
|
||||
const providers = enriched.filter(comp => comp.definition?.dataProvider)
|
||||
let contexts = []
|
||||
providers.forEach(({ definition, instance }) => {
|
||||
// Extract datasource from component instance
|
||||
const datasourceSetting = definition.settings.find(setting => {
|
||||
return setting.key === definition.datasourceSetting
|
||||
const datasourceSetting = def.settings.find(setting => {
|
||||
return setting.key === def.datasourceSetting
|
||||
})
|
||||
if (!datasourceSetting) {
|
||||
return
|
||||
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
|
||||
let datasource
|
||||
if (datasourceSetting.type === "datasource") {
|
||||
datasource = instance[datasourceSetting?.key]
|
||||
return component[datasourceSetting?.key]
|
||||
} else if (datasourceSetting.type === "table") {
|
||||
datasource = {
|
||||
tableId: instance[datasourceSetting?.key],
|
||||
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
|
||||
let contexts = []
|
||||
dataProviders.forEach(component => {
|
||||
const datasource = getDatasourceForProvider(component)
|
||||
if (!datasource) {
|
||||
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()
|
||||
|
||||
// Create bindable properties for each schema field
|
||||
keys.forEach(key => {
|
||||
const fieldSchema = schema[key]
|
||||
// Replace certain bindings with a new property to help display components
|
||||
|
@ -77,11 +101,12 @@ export const getBindableContexts = (rootComponent, componentId) => {
|
|||
|
||||
contexts.push({
|
||||
type: "context",
|
||||
runtimeBinding: `${instance._id}.${runtimeBoundKey}`,
|
||||
readableBinding: `${instance._instanceName}.${table.name}.${key}`,
|
||||
runtimeBinding: `${component._id}.${runtimeBoundKey}`,
|
||||
readableBinding: `${component._instanceName}.${table.name}.${key}`,
|
||||
fieldSchema,
|
||||
providerId: instance._id,
|
||||
providerId: component._id,
|
||||
tableId: datasource.tableId,
|
||||
field: key,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -115,26 +140,21 @@ export const getBindableComponents = rootComponent => {
|
|||
/**
|
||||
* Gets a schema for a datasource object.
|
||||
*/
|
||||
const getSchemaForDatasource = datasource => {
|
||||
export const getSchemaForDatasource = datasource => {
|
||||
let schema, table
|
||||
if (datasource) {
|
||||
const tables = get(backendUiStore).tables
|
||||
const { type } = datasource
|
||||
const table = tables.find(table => table._id === datasource.tableId)
|
||||
let schema
|
||||
table = tables.find(table => table._id === datasource.tableId)
|
||||
if (table) {
|
||||
if (type === "table") {
|
||||
schema = table.schema ?? {}
|
||||
schema = cloneDeep(table.schema)
|
||||
} else if (type === "view") {
|
||||
schema = table.views?.[datasource.name]?.schema ?? {}
|
||||
schema = cloneDeep(table.views?.[datasource.name]?.schema)
|
||||
} else if (type === "link") {
|
||||
schema = table.schema ?? {}
|
||||
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 }
|
||||
}
|
||||
|
@ -143,6 +163,9 @@ const getSchemaForDatasource = datasource => {
|
|||
* Converts a readable data binding into a runtime data binding
|
||||
*/
|
||||
export function readableToRuntimeBinding(bindableProperties, textWithBindings) {
|
||||
if (typeof textWithBindings !== "string") {
|
||||
return textWithBindings
|
||||
}
|
||||
const boundValues = textWithBindings.match(CAPTURE_VAR_INSIDE_MUSTACHE) || []
|
||||
let result = textWithBindings
|
||||
boundValues.forEach(boundValue => {
|
||||
|
@ -160,6 +183,9 @@ export function readableToRuntimeBinding(bindableProperties, textWithBindings) {
|
|||
* Converts a runtime data binding into a readable data binding
|
||||
*/
|
||||
export function runtimeToReadableBinding(bindableProperties, textWithBindings) {
|
||||
if (typeof textWithBindings !== "string") {
|
||||
return textWithBindings
|
||||
}
|
||||
const boundValues = textWithBindings.match(CAPTURE_VAR_INSIDE_MUSTACHE) || []
|
||||
let result = textWithBindings
|
||||
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>
|
||||
import { Select, Label } from "@budibase/bbui"
|
||||
import { store, backendUiStore, currentAsset } from "builderStore"
|
||||
import { getBindableProperties } from "builderStore/dataBinding"
|
||||
import { store, currentAsset } from "builderStore"
|
||||
import {
|
||||
getDataProviderComponents,
|
||||
getDatasourceForProvider,
|
||||
getSchemaForDatasource,
|
||||
} from "builderStore/dataBinding"
|
||||
|
||||
export let parameters
|
||||
|
||||
let idFields
|
||||
|
||||
$: bindableProperties = getBindableProperties(
|
||||
$: dataProviderComponents = getDataProviderComponents(
|
||||
$currentAsset.props,
|
||||
$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) {
|
||||
// Set rev ID
|
||||
parameters.revId = parameters.rowId.replace("_id", "_rev")
|
||||
|
||||
// Set table ID
|
||||
const idBinding = bindableProperties.find(
|
||||
prop =>
|
||||
prop.runtimeBinding ===
|
||||
parameters.rowId
|
||||
.replace("{{", "")
|
||||
.replace("}}", "")
|
||||
.trim()
|
||||
const providerComponent = dataProviderComponents.find(
|
||||
provider => provider._id === parameters.providerId
|
||||
)
|
||||
if (idBinding) {
|
||||
const { instance } = idBinding
|
||||
const component = $store.components[instance._component]
|
||||
const tableInfo = instance[component.context]
|
||||
if (tableInfo) {
|
||||
parameters.tableId =
|
||||
typeof tableInfo === "string" ? tableInfo : tableInfo.tableId
|
||||
const datasource = getDatasourceForProvider(providerComponent)
|
||||
const { table } = getSchemaForDatasource(datasource)
|
||||
if (table) {
|
||||
parameters.tableId = table._id
|
||||
}
|
||||
}
|
||||
|
||||
console.log(parameters)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="root">
|
||||
{#if idFields.length === 0}
|
||||
{#if dataProviderComponents.length === 0}
|
||||
<div class="cannot-use">
|
||||
Delete row can only be used within a component that provides data, such as
|
||||
a List
|
||||
|
@ -54,9 +39,9 @@
|
|||
<Label size="m" color="dark">Datasource</Label>
|
||||
<Select secondary bind:value={parameters.rowId}>
|
||||
<option value="" />
|
||||
{#each idFields as idField}
|
||||
<option value={`{{ ${idField.runtimeBinding} }}`}>
|
||||
{idField.instance._instanceName}
|
||||
{#each dataProviderComponents as provider}
|
||||
<option value={`{{ ${provider._id}._id }}`}>
|
||||
{provider._instanceName}
|
||||
</option>
|
||||
{/each}
|
||||
</Select>
|
||||
|
|
|
@ -1,77 +1,28 @@
|
|||
<script>
|
||||
import { Select, Label } from "@budibase/bbui"
|
||||
import { store, backendUiStore, currentAsset } from "builderStore"
|
||||
import { getBindableProperties } from "builderStore/dataBinding"
|
||||
import { store, currentAsset } from "builderStore"
|
||||
import {
|
||||
getDataProviderComponents,
|
||||
getDatasourceForProvider,
|
||||
getSchemaForDatasource,
|
||||
} from "builderStore/dataBinding"
|
||||
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
|
||||
|
||||
let idFields
|
||||
let schemaFields
|
||||
|
||||
$: bindableProperties = getBindableProperties(
|
||||
$: dataProviderComponents = getDataProviderComponents(
|
||||
$currentAsset.props,
|
||||
$store.selectedComponentId
|
||||
)
|
||||
|
||||
$: {
|
||||
if (parameters && parameters.contextPath) {
|
||||
schemaFields = schemaFromContextPath(parameters.contextPath)
|
||||
} else {
|
||||
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")
|
||||
$: providerComponent = dataProviderComponents.find(
|
||||
provider => provider._id === parameters.providerId
|
||||
)
|
||||
// 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
|
||||
}
|
||||
}
|
||||
$: schemaFields = getSchemaFields(providerComponent)
|
||||
|
||||
// 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 getSchemaFields = component => {
|
||||
const datasource = getDatasourceForProvider(component)
|
||||
const { schema } = getSchemaForDatasource(datasource)
|
||||
return Object.values(schema || {})
|
||||
}
|
||||
|
||||
const onFieldsChanged = e => {
|
||||
|
@ -80,19 +31,17 @@
|
|||
</script>
|
||||
|
||||
<div class="root">
|
||||
{#if idFields.length === 0}
|
||||
{#if !dataProviderComponents.length}
|
||||
<div class="cannot-use">
|
||||
Update row can only be used within a component that provides data, such as
|
||||
a List
|
||||
Save Row can only be used within a component that provides data, such as a
|
||||
Repeater
|
||||
</div>
|
||||
{:else}
|
||||
<Label size="m" color="dark">Datasource</Label>
|
||||
<Select secondary bind:value={parameters.contextPath}>
|
||||
<Select secondary bind:value={parameters.providerId}>
|
||||
<option value="" />
|
||||
{#each idFields as idField}
|
||||
<option value={idBindingToContextPath(idField.runtimeBinding)}>
|
||||
{idField.instance._instanceName}
|
||||
</option>
|
||||
{#each dataProviderComponents as provider}
|
||||
<option value={provider._id}>{provider._instanceName}</option>
|
||||
{/each}
|
||||
</Select>
|
||||
{/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 { routeStore } from "../store"
|
||||
import { routeStore, builderStore } from "../store"
|
||||
import { saveRow, deleteRow, triggerAutomation } from "../api"
|
||||
|
||||
const saveRowHandler = async (action, context) => {
|
||||
let draft = context[`${action.parameters.contextPath}_draft`]
|
||||
if (action.parameters.fields) {
|
||||
Object.entries(action.parameters.fields).forEach(([key, entry]) => {
|
||||
const { fields, providerId } = action.parameters
|
||||
if (providerId) {
|
||||
let draft = context[`${action.parameters.providerId}_draft`]
|
||||
if (fields) {
|
||||
Object.entries(fields).forEach(([key, entry]) => {
|
||||
draft[key] = enrichDataBinding(entry.value, context)
|
||||
})
|
||||
}
|
||||
await saveRow(draft)
|
||||
}
|
||||
}
|
||||
|
||||
const deleteRowHandler = async (action, context) => {
|
||||
const { tableId, revId, rowId } = action.parameters
|
||||
if (tableId && revId && rowId) {
|
||||
await deleteRow({
|
||||
tableId: enrichDataBinding(tableId, context),
|
||||
rowId: enrichDataBinding(rowId, context),
|
||||
revId: enrichDataBinding(revId, context),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const triggerAutomationHandler = async (action, context) => {
|
||||
const params = {}
|
||||
if (action.parameters.fields) {
|
||||
for (let field in action.parameters.fields) {
|
||||
params[field] = enrichDataBinding(
|
||||
action.parameters.fields[field].value,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
await triggerAutomation(action.parameters.automationId, params)
|
||||
}
|
||||
|
||||
const navigationHandler = action => {
|
||||
if (action.parameters.url) {
|
||||
routeStore.actions.navigate(action.parameters.url)
|
||||
}
|
||||
}
|
||||
|
||||
const handlerMap = {
|
||||
|
@ -48,6 +58,10 @@ const handlerMap = {
|
|||
* actions in the current 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"]])
|
||||
return async () => {
|
||||
for (let i = 0; i < handlers.length; i++) {
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
const getFormData = async context => {
|
||||
if (context) {
|
||||
const tableDefinition = await API.fetchTableDefinition(context.tableId)
|
||||
schema = tableDefinition.schema
|
||||
fields = Object.keys(schema)
|
||||
schema = tableDefinition?.schema
|
||||
fields = Object.keys(schema ?? {})
|
||||
|
||||
// Use the draft version for editing
|
||||
row = $dataContext[`${$dataContext.closestComponentId}_draft`]
|
||||
|
|
Loading…
Reference in New Issue