budibase/packages/client/src/state/stateManager.js

126 lines
3.1 KiB
JavaScript
Raw Normal View History

import {
isEventType,
eventHandlers,
EVENT_TYPE_MEMBER_NAME,
} from "./eventHandlers"
import { bbFactory } from "./bbComponentApi"
2020-05-29 15:06:10 +02:00
import mustache from "mustache"
2020-06-01 11:41:28 +02:00
import { get } from "svelte/store"
import { appStore } from "./store"
const doNothing = () => {}
doNothing.isPlaceholder = true
const isMetaProp = propName =>
propName === "_component" ||
propName === "_children" ||
propName === "_id" ||
propName === "_style" ||
propName === "_code" ||
2020-05-29 15:06:10 +02:00
propName === "_codeMeta" ||
propName === "_styles"
export const createStateManager = ({
componentLibraries,
onScreenSlotRendered,
routeTo,
}) => {
let handlerTypes = eventHandlers(routeTo)
let currentState
const getCurrentState = () => currentState
2020-05-30 01:14:41 +02:00
const bb = bbFactory({
2020-06-01 23:55:44 +02:00
store: appStore,
getCurrentState,
componentLibraries,
onScreenSlotRendered,
})
2020-05-30 01:14:41 +02:00
const setup = _setup({ handlerTypes, getCurrentState, bb, store: appStore })
return {
setup,
2020-06-01 22:26:32 +02:00
destroy: () => {},
getCurrentState,
2020-05-30 01:14:41 +02:00
store: appStore,
}
}
2020-06-01 11:41:28 +02:00
const _setup = ({ handlerTypes, getCurrentState, bb, store }) => node => {
const props = node.props
const context = node.context || {}
const initialProps = { ...props }
const currentStoreState = get(appStore)
for (let propName in props) {
if (isMetaProp(propName)) continue
2020-02-21 19:02:02 +01:00
const propValue = props[propName]
2020-06-01 22:26:32 +02:00
// A little bit of a hack - won't bind if the string doesn't start with {{
2020-06-01 11:41:28 +02:00
const isBound = typeof propValue === "string" && propValue.startsWith("{{")
2020-02-21 19:02:02 +01:00
2020-05-30 01:14:41 +02:00
if (isBound) {
2020-05-29 15:06:10 +02:00
initialProps[propName] = mustache.render(propValue, {
state: currentStoreState,
2020-06-01 11:41:28 +02:00
context,
2020-05-29 15:06:10 +02:00
})
2020-05-30 01:14:41 +02:00
if (!node.stateBound) {
node.stateBound = true
}
2020-05-29 15:06:10 +02:00
}
2020-02-21 19:02:02 +01:00
if (isEventType(propValue)) {
const handlersInfos = []
2020-02-21 19:02:02 +01:00
for (let event of propValue) {
const handlerInfo = {
2020-02-21 19:02:02 +01:00
handlerType: event[EVENT_TYPE_MEMBER_NAME],
parameters: event.parameters,
}
2020-05-29 15:06:10 +02:00
const resolvedParams = {}
for (let paramName in handlerInfo.parameters) {
const paramValue = handlerInfo.parameters[paramName]
2020-06-01 11:41:28 +02:00
resolvedParams[paramName] = () =>
mustache.render(paramValue, {
state: getCurrentState(),
context,
})
}
handlerInfo.parameters = resolvedParams
handlersInfos.push(handlerInfo)
}
2020-05-29 15:06:10 +02:00
if (handlersInfos.length === 0) {
initialProps[propName] = doNothing
} else {
initialProps[propName] = async context => {
for (let handlerInfo of handlersInfos) {
const handler = makeHandler(handlerTypes, handlerInfo)
await handler(context)
}
}
}
}
}
2020-05-30 01:14:41 +02:00
const setup = _setup({ handlerTypes, getCurrentState, bb, store })
initialProps._bb = bb(node, setup)
return initialProps
}
const makeHandler = (handlerTypes, handlerInfo) => {
const handlerType = handlerTypes[handlerInfo.handlerType]
2020-02-24 17:04:13 +01:00
return async context => {
const parameters = {}
2020-02-21 19:02:02 +01:00
for (let paramName in handlerInfo.parameters) {
parameters[paramName] = handlerInfo.parameters[paramName](context)
}
2020-02-24 17:04:13 +01:00
await handlerType.execute(parameters)
}
2020-02-23 23:07:28 +01:00
}