Merge pull request #3618 from Budibase/fix/block-context
Fixes for button actions, block contexts and nester data provider settings
This commit is contained in:
commit
32ea1da281
|
@ -61,7 +61,7 @@ export const getComponentBindableProperties = (asset, componentId) => {
|
||||||
/**
|
/**
|
||||||
* Gets all data provider components above a component.
|
* Gets all data provider components above a component.
|
||||||
*/
|
*/
|
||||||
export const getDataProviderComponents = (asset, componentId) => {
|
export const getContextProviderComponents = (asset, componentId, type) => {
|
||||||
if (!asset || !componentId) {
|
if (!asset || !componentId) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,18 @@ export const getDataProviderComponents = (asset, componentId) => {
|
||||||
// Filter by only data provider components
|
// Filter by only data provider components
|
||||||
return path.filter(component => {
|
return path.filter(component => {
|
||||||
const def = store.actions.components.getDefinition(component._component)
|
const def = store.actions.components.getDefinition(component._component)
|
||||||
return def?.context != null
|
if (!def?.context) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no type specified, return anything that exposes context
|
||||||
|
if (!type) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise only match components with the specific context type
|
||||||
|
const contexts = Array.isArray(def.context) ? def.context : [def.context]
|
||||||
|
return contexts.find(context => context.type === type) != null
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +154,7 @@ export const getDatasourceForProvider = (asset, component) => {
|
||||||
*/
|
*/
|
||||||
const getContextBindings = (asset, componentId) => {
|
const getContextBindings = (asset, componentId) => {
|
||||||
// Extract any components which provide data contexts
|
// Extract any components which provide data contexts
|
||||||
const dataProviders = getDataProviderComponents(asset, componentId)
|
const dataProviders = getContextProviderComponents(asset, componentId)
|
||||||
|
|
||||||
// Generate bindings for all matching components
|
// Generate bindings for all matching components
|
||||||
return getProviderContextBindings(asset, dataProviders)
|
return getProviderContextBindings(asset, dataProviders)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import { getDataProviderComponents } from "builderStore/dataBinding"
|
import { getContextProviderComponents } from "builderStore/dataBinding"
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Popover,
|
Popover,
|
||||||
|
@ -58,10 +58,13 @@
|
||||||
...query,
|
...query,
|
||||||
type: "query",
|
type: "query",
|
||||||
}))
|
}))
|
||||||
$: dataProviders = getDataProviderComponents(
|
$: contextProviders = getContextProviderComponents(
|
||||||
$currentAsset,
|
$currentAsset,
|
||||||
$store.selectedComponentId
|
$store.selectedComponentId
|
||||||
).map(provider => ({
|
)
|
||||||
|
$: dataProviders = contextProviders
|
||||||
|
.filter(component => component._component?.endsWith("/dataprovider"))
|
||||||
|
.map(provider => ({
|
||||||
label: provider._instanceName,
|
label: provider._instanceName,
|
||||||
name: provider._instanceName,
|
name: provider._instanceName,
|
||||||
providerId: provider._id,
|
providerId: provider._id,
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import { notifications } from "@budibase/bbui"
|
import { notifications } from "@budibase/bbui"
|
||||||
import EventEditor from "./EventEditor.svelte"
|
import EventEditor from "./EventEditor.svelte"
|
||||||
import { automationStore } from "builderStore"
|
import { automationStore } from "builderStore"
|
||||||
|
import { cloneDeep } from "lodash/fp"
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
|
@ -12,17 +13,23 @@
|
||||||
export let bindings
|
export let bindings
|
||||||
|
|
||||||
let drawer
|
let drawer
|
||||||
|
let tmpValue
|
||||||
|
|
||||||
|
const openDrawer = () => {
|
||||||
|
tmpValue = cloneDeep(value)
|
||||||
|
drawer.show()
|
||||||
|
}
|
||||||
|
|
||||||
const saveEventData = async () => {
|
const saveEventData = async () => {
|
||||||
// any automations that need created from event triggers
|
// any automations that need created from event triggers
|
||||||
const automationsToCreate = value.filter(
|
const automationsToCreate = tmpValue.filter(
|
||||||
action => action["##eventHandlerType"] === "Trigger Automation"
|
action => action["##eventHandlerType"] === "Trigger Automation"
|
||||||
)
|
)
|
||||||
for (let action of automationsToCreate) {
|
for (let action of automationsToCreate) {
|
||||||
await createAutomation(action.parameters)
|
await createAutomation(action.parameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch("change", value)
|
dispatch("change", tmpValue)
|
||||||
notifications.success("Component actions saved.")
|
notifications.success("Component actions saved.")
|
||||||
drawer.hide()
|
drawer.hide()
|
||||||
}
|
}
|
||||||
|
@ -54,11 +61,16 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ActionButton on:click={drawer.show}>Define actions</ActionButton>
|
<ActionButton on:click={openDrawer}>Define actions</ActionButton>
|
||||||
<Drawer bind:this={drawer} title={"Actions"}>
|
<Drawer bind:this={drawer} title={"Actions"}>
|
||||||
<svelte:fragment slot="description">
|
<svelte:fragment slot="description">
|
||||||
Define what actions to run.
|
Define what actions to run.
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
<Button cta slot="buttons" on:click={saveEventData}>Save</Button>
|
<Button cta slot="buttons" on:click={saveEventData}>Save</Button>
|
||||||
<EventEditor slot="body" bind:actions={value} eventType={name} {bindings} />
|
<EventEditor
|
||||||
|
slot="body"
|
||||||
|
bind:actions={tmpValue}
|
||||||
|
eventType={name}
|
||||||
|
{bindings}
|
||||||
|
/>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
import { store, currentAsset } from "builderStore"
|
import { store, currentAsset } from "builderStore"
|
||||||
import { tables } from "stores/backend"
|
import { tables } from "stores/backend"
|
||||||
import {
|
import {
|
||||||
getDataProviderComponents,
|
getContextProviderComponents,
|
||||||
getSchemaForDatasource,
|
getSchemaForDatasource,
|
||||||
} from "builderStore/dataBinding"
|
} from "builderStore/dataBinding"
|
||||||
import SaveFields from "./SaveFields.svelte"
|
import SaveFields from "./SaveFields.svelte"
|
||||||
|
@ -11,13 +11,54 @@
|
||||||
export let parameters
|
export let parameters
|
||||||
export let bindings = []
|
export let bindings = []
|
||||||
|
|
||||||
$: dataProviderComponents = getDataProviderComponents(
|
$: formComponents = getContextProviderComponents(
|
||||||
$currentAsset,
|
$currentAsset,
|
||||||
$store.selectedComponentId
|
$store.selectedComponentId,
|
||||||
|
"form"
|
||||||
)
|
)
|
||||||
|
$: schemaComponents = getContextProviderComponents(
|
||||||
|
$currentAsset,
|
||||||
|
$store.selectedComponentId,
|
||||||
|
"schema"
|
||||||
|
)
|
||||||
|
$: providerOptions = getProviderOptions(formComponents, schemaComponents)
|
||||||
$: schemaFields = getSchemaFields($currentAsset, parameters?.tableId)
|
$: schemaFields = getSchemaFields($currentAsset, parameters?.tableId)
|
||||||
$: tableOptions = $tables.list || []
|
$: tableOptions = $tables.list || []
|
||||||
|
|
||||||
|
// 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 getSchemaFields = (asset, tableId) => {
|
||||||
const { schema } = getSchemaForDatasource(asset, { type: "table", tableId })
|
const { schema } = getSchemaForDatasource(asset, { type: "table", tableId })
|
||||||
return Object.values(schema || {})
|
return Object.values(schema || {})
|
||||||
|
@ -39,10 +80,8 @@
|
||||||
<Label small>Data Source</Label>
|
<Label small>Data Source</Label>
|
||||||
<Select
|
<Select
|
||||||
bind:value={parameters.providerId}
|
bind:value={parameters.providerId}
|
||||||
options={dataProviderComponents}
|
options={providerOptions}
|
||||||
placeholder="None"
|
placeholder="None"
|
||||||
getOptionLabel={option => option._instanceName}
|
|
||||||
getOptionValue={option => option._id}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Label small>Table</Label>
|
<Label small>Table</Label>
|
||||||
|
|
Loading…
Reference in New Issue