Dynamically enrich button actions at runtime and provide additional ephemeral button action output context

This commit is contained in:
Andrew Kingston 2021-12-09 11:25:32 +00:00
parent 59ac6682ae
commit d9278dbc24
3 changed files with 75 additions and 26 deletions

View File

@ -27,7 +27,6 @@
actions,
selectedAction?.id
)
$: console.log(buttonContextBindings)
$: allBindings = buttonContextBindings.concat(bindings)
// Assign a unique ID to each action

View File

@ -8,6 +8,7 @@ import {
} from "stores"
import { saveRow, deleteRow, executeQuery, triggerAutomation } from "api"
import { ActionTypes } from "constants"
import { enrichDataBindings } from "./enrichDataBinding"
const saveRowHandler = async (action, context) => {
const { fields, providerId, tableId } = action.parameters
@ -25,7 +26,10 @@ const saveRowHandler = async (action, context) => {
if (tableId) {
payload.tableId = tableId
}
await saveRow(payload)
const row = await saveRow(payload)
return {
row,
}
}
const duplicateRowHandler = async (action, context) => {
@ -178,11 +182,26 @@ export const enrichButtonActions = (actions, context) => {
return actions
}
// Button context is built up as actions are executed.
// Inherit any previous button context which may have come from actions
// before a confirmable action since this breaks the chain.
let buttonContext = context.actions || []
const handlers = actions.map(def => handlerMap[def["##eventHandlerType"]])
return async () => {
for (let i = 0; i < handlers.length; i++) {
try {
const action = actions[i]
// Skip any non-existent action definitions
if (!handlers[i]) {
continue
}
// Built total context for this action
const totalContext = { ...context, actions: buttonContext }
// Get and enrich this button action with the total context
let action = actions[i]
action = enrichDataBindings(action, totalContext)
const callback = async () => handlers[i](action, context)
// If this action is confirmable, show confirmation and await a
@ -198,7 +217,15 @@ export const enrichButtonActions = (actions, context) => {
// then execute the rest of the actions in the chain
const result = await callback()
if (result !== false) {
const next = enrichButtonActions(actions.slice(i + 1), context)
// Generate a new total context to pass into the next enrichment
buttonContext.push(result)
const newContext = { ...context, actions: buttonContext }
// Enrich and call the next button action
const next = enrichButtonActions(
actions.slice(i + 1),
newContext
)
await next()
}
}
@ -214,6 +241,8 @@ export const enrichButtonActions = (actions, context) => {
const result = await callback()
if (result === false) {
return
} else {
buttonContext.push(result)
}
}
} catch (error) {

View File

@ -32,35 +32,56 @@ export const enrichProps = (props, context) => {
data: context[context.closestComponentId],
}
// Enrich all data bindings in top level props
let enrichedProps = enrichDataBindings(props, totalContext)
// Enrich click actions if they exist
Object.keys(enrichedProps).forEach(prop => {
// We want to exclude any button actions from enrichment at this stage.
// Extract top level button action settings.
let normalProps = { ...props }
let actionProps = {}
Object.keys(normalProps).forEach(prop => {
if (prop?.toLowerCase().includes("onclick")) {
enrichedProps[prop] = enrichButtonActions(
enrichedProps[prop],
totalContext
)
actionProps[prop] = normalProps[prop]
delete normalProps[prop]
}
})
// Enrich any click actions in conditions
if (enrichedProps._conditions) {
enrichedProps._conditions.forEach(condition => {
if (condition.setting?.toLowerCase().includes("onclick")) {
condition.settingValue = enrichButtonActions(
condition.settingValue,
totalContext
)
// Handle conditional UI separately after normal settings
let conditions = normalProps._conditions
delete normalProps._conditions
// If there is an onclick function in here then it won't be serialised
// properly, and therefore will not be updated properly.
// The solution to this is add a rand which will ensure diffs happen
// every time.
condition.rand = Math.random()
// Enrich all props except button actions
let enrichedProps = enrichDataBindings(normalProps, totalContext)
// Enrich button actions.
// Actions are enriched into a function at this stage, but actual data
// binding enrichment is done dynamically at runtime.
Object.keys(actionProps).forEach(prop => {
enrichedProps[prop] = enrichButtonActions(actionProps[prop], totalContext)
})
// Conditions
if (conditions?.length) {
let enrichedConditions = []
conditions.forEach(condition => {
if (condition.setting?.toLowerCase().includes("onclick")) {
// Copy and remove the setting value from the condition as it needs
// enriched separately
let toEnrich = { ...condition }
delete toEnrich.settingValue
// Join the condition back together
enrichedConditions.push({
...enrichDataBindings(toEnrich, totalContext),
settingValue: enrichButtonActions(
condition.settingValue,
totalContext
),
rand: Math.random(),
})
} else {
// Normal condition
enrichedConditions.push(enrichDataBindings(condition, totalContext))
}
})
enrichedProps._conditions = enrichedConditions
}
return enrichedProps