Dedupe and improve logic around selecting available datasources for saving and duplicating rows

This commit is contained in:
Andrew Kingston 2023-11-08 16:27:20 +00:00
parent bad79618c1
commit 883ac0d008
3 changed files with 97 additions and 105 deletions

View File

@ -2,27 +2,20 @@
import { Select, Label, Body, Checkbox, Input } from "@budibase/bbui"
import { store, currentAsset } from "builderStore"
import { tables, viewsV2 } from "stores/backend"
import {
getContextProviderComponents,
getSchemaForDatasourcePlus,
} from "builderStore/dataBinding"
import { getSchemaForDatasourcePlus } from "builderStore/dataBinding"
import SaveFields from "./SaveFields.svelte"
import { getDatasourceLikeProviders } from "components/design/settings/controls/ButtonActionEditor/actions/utils"
export let parameters
export let bindings = []
export let nested
$: formComponents = getContextProviderComponents(
$currentAsset,
$store.selectedComponentId,
"form"
)
$: schemaComponents = getContextProviderComponents(
$currentAsset,
$store.selectedComponentId,
"schema"
)
$: providerOptions = getProviderOptions(formComponents, schemaComponents)
$: schemaFields = getSchemaFields($currentAsset, parameters?.tableId)
$: providerOptions = getDatasourceLikeProviders({
asset: $currentAsset,
componentId: $store.selectedComponentId,
nested,
})
$: schemaFields = getSchemaFields(parameters?.tableId)
$: tableOptions = $tables.list.map(table => ({
label: table.name,
resourceId: table._id,
@ -33,44 +26,8 @@
}))
$: options = [...(tableOptions || []), ...(viewOptions || [])]
// Gets a context definition of a certain type from a component definition
const extractComponentContext = (component, contextType) => {
const def = store.actions.components.getDefinition(component?._component)
if (!def) {
return null
}
const contexts = Array.isArray(def.context) ? def.context : [def.context]
return contexts.find(context => context?.type === contextType)
}
// Gets options for valid context keys which provide valid data to submit
const getProviderOptions = (formComponents, schemaComponents) => {
const formContexts = formComponents.map(component => ({
component,
context: extractComponentContext(component, "form"),
}))
const schemaContexts = schemaComponents.map(component => ({
component,
context: extractComponentContext(component, "schema"),
}))
const allContexts = formContexts.concat(schemaContexts)
return allContexts.map(({ component, context }) => {
let runtimeBinding = component._id
if (context.suffix) {
runtimeBinding += `-${context.suffix}`
}
return {
label: component._instanceName,
value: runtimeBinding,
}
})
}
const getSchemaFields = (asset, tableId) => {
const { schema } = getSchemaForDatasourcePlus(tableId)
delete schema._id
delete schema._rev
const getSchemaFields = resourceId => {
const { schema } = getSchemaForDatasourcePlus(resourceId)
return Object.values(schema || {})
}

View File

@ -2,29 +2,19 @@
import { Select, Label, Body, Checkbox, Input } from "@budibase/bbui"
import { store, currentAsset } from "builderStore"
import { tables, viewsV2 } from "stores/backend"
import {
getContextProviderComponents,
getSchemaForDatasourcePlus,
} from "builderStore/dataBinding"
import { getSchemaForDatasourcePlus } from "builderStore/dataBinding"
import SaveFields from "./SaveFields.svelte"
import { getDatasourceLikeProviders } from "components/design/settings/controls/ButtonActionEditor/actions/utils"
export let parameters
export let bindings = []
export let nested
$: formComponents = getContextProviderComponents(
$currentAsset,
$store.selectedComponentId,
"form",
{ includeSelf: nested }
)
$: schemaComponents = getContextProviderComponents(
$currentAsset,
$store.selectedComponentId,
"schema",
{ includeSelf: nested }
)
$: providerOptions = getProviderOptions(formComponents, schemaComponents)
$: providerOptions = getDatasourceLikeProviders({
asset: $currentAsset,
componentId: $store.selectedComponentId,
nested,
})
$: schemaFields = getSchemaFields(parameters?.tableId)
$: tableOptions = $tables.list.map(table => ({
label: table.name,
@ -36,40 +26,6 @@
}))
$: options = [...(tableOptions || []), ...(viewOptions || [])]
// Gets a context definition of a certain type from a component definition
const extractComponentContext = (component, contextType) => {
const def = store.actions.components.getDefinition(component?._component)
if (!def) {
return null
}
const contexts = Array.isArray(def.context) ? def.context : [def.context]
return contexts.find(context => context?.type === contextType)
}
// Gets options for valid context keys which provide valid data to submit
const getProviderOptions = (formComponents, schemaComponents) => {
const formContexts = formComponents.map(component => ({
component,
context: extractComponentContext(component, "form"),
}))
const schemaContexts = schemaComponents.map(component => ({
component,
context: extractComponentContext(component, "schema"),
}))
const allContexts = formContexts.concat(schemaContexts)
return allContexts.map(({ component, context }) => {
let runtimeBinding = component._id
if (context.suffix) {
runtimeBinding += `-${context.suffix}`
}
return {
label: component._instanceName,
value: runtimeBinding,
}
})
}
const getSchemaFields = resourceId => {
const { schema } = getSchemaForDatasourcePlus(resourceId)
return Object.values(schema || {})

View File

@ -0,0 +1,79 @@
import { getContextProviderComponents } from "builderStore/dataBinding"
import { store } from "builderStore"
// Generates bindings for all components that provider "datasource like"
// contexts. This includes "form" contexts and "schema" contexts. This is used
// by various button actions as candidates for whole "row" objects.
// Some examples are saving rows or duplicating rows.
export const getDatasourceLikeProviders = ({ asset, componentId, nested }) => {
// Get all form context providers
const formComponents = getContextProviderComponents(
asset,
componentId,
"form",
{ includeSelf: nested }
)
// Get all schema context providers
const schemaComponents = getContextProviderComponents(
asset,
componentId,
"schema",
{ includeSelf: nested }
)
// Generate contexts for all form providers
const formContexts = formComponents.map(component => ({
component,
context: extractComponentContext(component, "form"),
}))
// Generate contexts for all schema providers
const schemaContexts = schemaComponents.map(component => ({
component,
context: extractComponentContext(component, "schema"),
}))
// Check for duplicate contexts by the same component. In this case, attempt
// to label contexts with their suffixes
schemaContexts.forEach(schemaContext => {
// Check if we have a form context for this component
const id = schemaContext.component._id
const existing = formContexts.find(x => x.component._id === id)
if (existing) {
if (existing.context.suffix) {
existing.readableSuffix = ` (${existing.context.suffix})`
}
if (schemaContext.context.suffix) {
schemaContext.readableSuffix = ` (${schemaContext.context.suffix})`
}
}
})
// Generate bindings for all contexts
const allContexts = formContexts.concat(schemaContexts)
return allContexts.map(({ component, context, readableSuffix }) => {
let readableBinding = component._instanceName
let runtimeBinding = component._id
if (context.suffix) {
runtimeBinding += `-${context.suffix}`
}
if (readableSuffix) {
readableBinding += readableSuffix
}
return {
label: readableBinding,
value: runtimeBinding,
}
})
}
// Gets a context definition of a certain type from a component definition
const extractComponentContext = (component, contextType) => {
const def = store.actions.components.getDefinition(component?._component)
if (!def) {
return null
}
const contexts = Array.isArray(def.context) ? def.context : [def.context]
return contexts.find(context => context?.type === contextType)
}