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 6aaab83895
commit d9f4c3a4b0
3 changed files with 75 additions and 26 deletions

View File

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

View File

@ -8,6 +8,7 @@ import {
} from "stores" } from "stores"
import { saveRow, deleteRow, executeQuery, triggerAutomation } from "api" import { saveRow, deleteRow, executeQuery, triggerAutomation } from "api"
import { ActionTypes } from "constants" import { ActionTypes } from "constants"
import { enrichDataBindings } from "./enrichDataBinding"
const saveRowHandler = async (action, context) => { const saveRowHandler = async (action, context) => {
const { fields, providerId, tableId } = action.parameters const { fields, providerId, tableId } = action.parameters
@ -25,7 +26,10 @@ const saveRowHandler = async (action, context) => {
if (tableId) { if (tableId) {
payload.tableId = tableId payload.tableId = tableId
} }
await saveRow(payload) const row = await saveRow(payload)
return {
row,
}
} }
const duplicateRowHandler = async (action, context) => { const duplicateRowHandler = async (action, context) => {
@ -178,11 +182,26 @@ export const enrichButtonActions = (actions, context) => {
return actions 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"]]) 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++) {
try { 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) const callback = async () => handlers[i](action, context)
// If this action is confirmable, show confirmation and await a // 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 // then execute the rest of the actions in the chain
const result = await callback() const result = await callback()
if (result !== false) { 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() await next()
} }
} }
@ -214,6 +241,8 @@ export const enrichButtonActions = (actions, context) => {
const result = await callback() const result = await callback()
if (result === false) { if (result === false) {
return return
} else {
buttonContext.push(result)
} }
} }
} catch (error) { } catch (error) {

View File

@ -32,35 +32,56 @@ export const enrichProps = (props, context) => {
data: context[context.closestComponentId], data: context[context.closestComponentId],
} }
// Enrich all data bindings in top level props // We want to exclude any button actions from enrichment at this stage.
let enrichedProps = enrichDataBindings(props, totalContext) // Extract top level button action settings.
let normalProps = { ...props }
// Enrich click actions if they exist let actionProps = {}
Object.keys(enrichedProps).forEach(prop => { Object.keys(normalProps).forEach(prop => {
if (prop?.toLowerCase().includes("onclick")) { if (prop?.toLowerCase().includes("onclick")) {
enrichedProps[prop] = enrichButtonActions( actionProps[prop] = normalProps[prop]
enrichedProps[prop], delete normalProps[prop]
totalContext
)
} }
}) })
// Enrich any click actions in conditions // Handle conditional UI separately after normal settings
if (enrichedProps._conditions) { let conditions = normalProps._conditions
enrichedProps._conditions.forEach(condition => { delete normalProps._conditions
if (condition.setting?.toLowerCase().includes("onclick")) {
condition.settingValue = enrichButtonActions(
condition.settingValue,
totalContext
)
// If there is an onclick function in here then it won't be serialised // Enrich all props except button actions
// properly, and therefore will not be updated properly. let enrichedProps = enrichDataBindings(normalProps, totalContext)
// The solution to this is add a rand which will ensure diffs happen
// every time. // Enrich button actions.
condition.rand = Math.random() // 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 return enrichedProps