Tidy up data binding
This commit is contained in:
parent
bb46d1e139
commit
093d7f95b9
|
@ -24,7 +24,7 @@ import { cloneDeep, difference } from "lodash/fp"
|
||||||
* @returns {Array.<BindableProperty>}
|
* @returns {Array.<BindableProperty>}
|
||||||
*/
|
*/
|
||||||
export default function({ componentInstanceId, screen, components, tables }) {
|
export default function({ componentInstanceId, screen, components, tables }) {
|
||||||
const walkResult = walk({
|
const result = walk({
|
||||||
// cloning so we are free to mutate props (e.g. by adding _contexts)
|
// cloning so we are free to mutate props (e.g. by adding _contexts)
|
||||||
instance: cloneDeep(screen.props),
|
instance: cloneDeep(screen.props),
|
||||||
targetId: componentInstanceId,
|
targetId: componentInstanceId,
|
||||||
|
@ -33,13 +33,10 @@ export default function({ componentInstanceId, screen, components, tables }) {
|
||||||
})
|
})
|
||||||
|
|
||||||
return [
|
return [
|
||||||
...walkResult.bindableInstances
|
...result.bindableInstances
|
||||||
.filter(isInstanceInSharedContext(walkResult))
|
.filter(isInstanceInSharedContext(result))
|
||||||
.map(componentInstanceToBindable(walkResult)),
|
.map(componentInstanceToBindable),
|
||||||
|
...(result.target?._contexts.map(contextToBindables(tables)).flat() ?? []),
|
||||||
...(walkResult.target?._contexts
|
|
||||||
.map(contextToBindables(tables, walkResult))
|
|
||||||
.flat() ?? []),
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,26 +50,18 @@ const isInstanceInSharedContext = walkResult => i =>
|
||||||
|
|
||||||
// turns a component instance prop into binding expressions
|
// turns a component instance prop into binding expressions
|
||||||
// used by the UI
|
// used by the UI
|
||||||
const componentInstanceToBindable = walkResult => i => {
|
const componentInstanceToBindable = i => {
|
||||||
const lastContext =
|
|
||||||
i.instance._contexts.length &&
|
|
||||||
i.instance._contexts[i.instance._contexts.length - 1]
|
|
||||||
const contextParentPath = lastContext
|
|
||||||
? getParentPath(walkResult, lastContext)
|
|
||||||
: ""
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: "instance",
|
type: "instance",
|
||||||
instance: i.instance,
|
instance: i.instance,
|
||||||
// how the binding expression persists, and is used in the app at runtime
|
// how the binding expression persists, and is used in the app at runtime
|
||||||
runtimeBinding: `${contextParentPath}${i.instance._id}.${i.prop}`,
|
runtimeBinding: `${i.instance._id}`,
|
||||||
// how the binding exressions looks to the user of the builder
|
// how the binding exressions looks to the user of the builder
|
||||||
readableBinding: `${i.instance._instanceName}`,
|
readableBinding: `${i.instance._instanceName}`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const contextToBindables = (tables, walkResult) => context => {
|
const contextToBindables = tables => context => {
|
||||||
const contextParentPath = getParentPath(walkResult, context)
|
|
||||||
const tableId = context.table?.tableId ?? context.table
|
const tableId = context.table?.tableId ?? context.table
|
||||||
const table = tables.find(table => table._id === tableId)
|
const table = tables.find(table => table._id === tableId)
|
||||||
let schema =
|
let schema =
|
||||||
|
@ -98,7 +87,7 @@ const contextToBindables = (tables, walkResult) => context => {
|
||||||
fieldSchema,
|
fieldSchema,
|
||||||
instance: context.instance,
|
instance: context.instance,
|
||||||
// how the binding expression persists, and is used in the app at runtime
|
// how the binding expression persists, and is used in the app at runtime
|
||||||
runtimeBinding: `${contextParentPath}data.${runtimeBoundKey}`,
|
runtimeBinding: `${context.instance._id}.${runtimeBoundKey}`,
|
||||||
// how the binding expressions looks to the user of the builder
|
// how the binding expressions looks to the user of the builder
|
||||||
readableBinding: `${context.instance._instanceName}.${table.name}.${key}`,
|
readableBinding: `${context.instance._instanceName}.${table.name}.${key}`,
|
||||||
// table / view info
|
// table / view info
|
||||||
|
@ -118,20 +107,6 @@ const contextToBindables = (tables, walkResult) => context => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const getParentPath = (walkResult, context) => {
|
|
||||||
// describes the number of "parent" in the path
|
|
||||||
// clone array first so original array is not mtated
|
|
||||||
const contextParentNumber = [...walkResult.target._contexts]
|
|
||||||
.reverse()
|
|
||||||
.indexOf(context)
|
|
||||||
|
|
||||||
return (
|
|
||||||
new Array(contextParentNumber).fill("parent").join(".") +
|
|
||||||
// trailing . if has parents
|
|
||||||
(contextParentNumber ? "." : "")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const walk = ({ instance, targetId, components, tables, result }) => {
|
const walk = ({ instance, targetId, components, tables, result }) => {
|
||||||
if (!result) {
|
if (!result) {
|
||||||
result = {
|
result = {
|
||||||
|
|
|
@ -12,10 +12,7 @@ export function readableToRuntimeBinding(bindableProperties, textWithBindings) {
|
||||||
return boundValue === `{{ ${readableBinding} }}`
|
return boundValue === `{{ ${readableBinding} }}`
|
||||||
})
|
})
|
||||||
if (binding) {
|
if (binding) {
|
||||||
result = textWithBindings.replace(
|
result = result.replace(boundValue, `{{ ${binding.runtimeBinding} }}`)
|
||||||
boundValue,
|
|
||||||
`{{ ${binding.runtimeBinding} }}`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -46,7 +46,7 @@ export default `<html>
|
||||||
|
|
||||||
selectedComponentStyle = document.createElement('style');
|
selectedComponentStyle = document.createElement('style');
|
||||||
document.head.appendChild(selectedComponentStyle)
|
document.head.appendChild(selectedComponentStyle)
|
||||||
var selectedCss = '[data-bb-id="' + data.selectedComponentType + '-' + data.selectedComponentId + '"]' + '{border:2px solid #0055ff !important;}'
|
var selectedCss = '[data-bb-id="' + data.selectedComponentId + '"]' + '{border:2px solid #0055ff !important;}'
|
||||||
selectedComponentStyle.appendChild(document.createTextNode(selectedCss))
|
selectedComponentStyle.appendChild(document.createTextNode(selectedCss))
|
||||||
|
|
||||||
styles = document.createElement('style')
|
styles = document.createElement('style')
|
||||||
|
|
|
@ -30,14 +30,13 @@
|
||||||
// Extract component definition info
|
// Extract component definition info
|
||||||
const componentName = extractComponentName(definition._component)
|
const componentName = extractComponentName(definition._component)
|
||||||
const constructor = getComponentConstructor(componentName)
|
const constructor = getComponentConstructor(componentName)
|
||||||
const id = `${componentName}-${definition._id}`
|
|
||||||
const componentProps = extractValidProps(definition)
|
const componentProps = extractValidProps(definition)
|
||||||
const dataContext = getContext("data")
|
const dataContext = getContext("data")
|
||||||
const enrichedProps = dataContext.actions.enrichDataBindings(componentProps)
|
const enrichedProps = dataContext.actions.enrichDataBindings(componentProps)
|
||||||
const children = definition._children
|
const children = definition._children
|
||||||
|
|
||||||
// Set style context to be consumed by component
|
// Set contexts to be consumed by component
|
||||||
setContext("style", { ...definition._styles, id })
|
setContext("style", { ...definition._styles, id: definition._id })
|
||||||
$: console.log("Rendering: " + componentName)
|
$: console.log("Rendering: " + componentName)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
// Get current contexts
|
// Get current contexts
|
||||||
const dataContext = getContext("data")
|
const dataContext = getContext("data")
|
||||||
|
const { id } = getContext("style")
|
||||||
|
|
||||||
// Clone current context to this context
|
// Clone current context to this context
|
||||||
const newDataContext = createDataContextStore($dataContext)
|
const newDataContext = createDataContextStore($dataContext)
|
||||||
|
@ -14,7 +15,7 @@
|
||||||
// Add additional layer to context
|
// Add additional layer to context
|
||||||
let loaded = false
|
let loaded = false
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
newDataContext.actions.addContext(row)
|
newDataContext.actions.addContext(row, id)
|
||||||
loaded = true
|
loaded = true
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -3,7 +3,6 @@ import { enrichDataBinding } from "../utils"
|
||||||
import { cloneDeep } from "lodash/fp"
|
import { cloneDeep } from "lodash/fp"
|
||||||
|
|
||||||
const initialValue = {
|
const initialValue = {
|
||||||
parent: null,
|
|
||||||
data: null,
|
data: null,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,15 +11,12 @@ export const createDataContextStore = existingContext => {
|
||||||
const store = writable(initial)
|
const store = writable(initial)
|
||||||
|
|
||||||
// Adds a context layer to the data context tree
|
// Adds a context layer to the data context tree
|
||||||
const addContext = row => {
|
const addContext = (row, componentId) => {
|
||||||
store.update(state => {
|
store.update(state => {
|
||||||
if (state.data) {
|
if (row && componentId) {
|
||||||
state.parent = {
|
state[componentId] = row
|
||||||
parent: state.parent,
|
|
||||||
data: state.data,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
state.data = row
|
state.data = row
|
||||||
|
}
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue