Add ability for components to provide example data context that they provide so that more bindings work with live eval

This commit is contained in:
Andrew Kingston 2024-02-16 13:25:41 +00:00
parent 461418390d
commit 5f6b846937
5 changed files with 75 additions and 3 deletions

View File

@ -69,8 +69,6 @@
return names
}
$: console.log(context)
const getBindingValue = binding => {
const hbs = `{{ ${binding.runtimeBinding} }}`
return processStringSync(hbs, context)

View File

@ -575,6 +575,15 @@
}
}
const getDataContext = () => {
const normalContext = get(context)
const additionalContext = ref?.getAdditionalDataContext?.()
return {
...normalContext,
...additionalContext,
}
}
onMount(() => {
// Register this component instance for external access
if ($appStore.isDevApp) {
@ -583,7 +592,7 @@
component: instance._component,
getSettings: () => cachedSettings,
getRawSettings: () => ({ ...staticSettings, ...dynamicSettings }),
getDataContext: () => get(context),
getDataContext: getDataContext,
reload: () => initialise(instance, true),
setEphemeralStyles: styles => (ephemeralStyles = styles),
state: store,

View File

@ -30,6 +30,7 @@
ActionTypes,
createContextStore,
Provider,
generateGoldenSample,
} = getContext("sdk")
let grid
@ -48,6 +49,19 @@
},
]
// Provide additional data context for live binding eval
export const getAdditionalDataContext = () => {
const rows = get(grid?.getContext()?.rows)
const goldenRow = generateGoldenSample(rows)
const id = [get(component).id]
return {
[id]: goldenRow,
eventContext: {
row: goldenRow,
},
}
}
// Parses columns to fix older formats
const getParsedColumns = columns => {
// If the first element has an active key all elements should be in the new format

View File

@ -28,6 +28,7 @@ import { ActionTypes } from "./constants"
import { fetchDatasourceSchema } from "./utils/schema.js"
import { getAPIKey } from "./utils/api.js"
import { enrichButtonActions } from "./utils/buttonActions.js"
import { generateGoldenSample } from "./utils/components.js"
import { processStringSync, makePropSafe } from "@budibase/string-templates"
import { fetchData, LuceneUtils, Constants } from "@budibase/frontend-core"
@ -65,6 +66,7 @@ export default {
processStringSync,
makePropSafe,
createContextStore,
generateGoldenSample,
// Components
Provider,

View File

@ -82,3 +82,52 @@ export const findComponentParent = (rootComponent, id, parentComponent) => {
}
return null
}
/**
* Util to check is a given value is "better" than another. "Betterness" is
* defined as presence and length.
*/
const isBetterSample = (newValue, oldValue) => {
// Prefer non-null values
if (oldValue == null && newValue != null) {
return true
}
// Don't change type
const oldType = typeof oldValue
const newType = typeof newValue
if (oldType !== newType) {
return false
}
// Prefer longer values
if (newType === "string" && newValue.length > oldValue.length) {
return true
}
if (
newType === "object" &&
Object.keys(newValue).length > Object.keys(oldValue).length
) {
return true
}
return false
}
/**
* Generates a best-case example object of the provided samples.
* The generated sample does not necessarily exist - it simply is a sample that
* contains "good" examples for every property of all the samples.
* The generate sample will have a value for all keys across all samples.
*/
export const generateGoldenSample = samples => {
let goldenSample = {}
samples?.forEach(sample => {
Object.keys(sample).forEach(key => {
if (isBetterSample(sample[key], goldenSample[key])) {
goldenSample[key] = sample[key]
}
})
})
return goldenSample
}