Merge commit '63c73915d33ccae0311f7f0e4a3002b4eb390a21'
This commit is contained in:
commit
fff4a361c9
|
@ -1,58 +1,12 @@
|
||||||
import {
|
|
||||||
split,
|
|
||||||
last
|
|
||||||
} from "lodash/fp";
|
|
||||||
import {writable} from "svelte/store";
|
import {writable} from "svelte/store";
|
||||||
import { $ } from "./core/common";
|
|
||||||
import {
|
|
||||||
setupBinding
|
|
||||||
} from "./state/stateBinding";
|
|
||||||
import { createCoreApi } from "./core";
|
import { createCoreApi } from "./core";
|
||||||
import { getStateOrValue } from "./state/getState";
|
import { getStateOrValue } from "./state/getState";
|
||||||
import { setState, setStateFromBinding } from "./state/setState";
|
import { setState, setStateFromBinding } from "./state/setState";
|
||||||
import { trimSlash } from "./common/trimSlash";
|
import { trimSlash } from "./common/trimSlash";
|
||||||
import { isBound } from "./state/isState";
|
import { isBound } from "./state/isState";
|
||||||
|
import { _initialiseChildren } from "./render/initialiseChildren";
|
||||||
|
|
||||||
export const createApp = (componentLibraries, appDefinition, user) => {
|
export const createApp = (componentLibraries, appDefinition, user, uiFunctions) => {
|
||||||
|
|
||||||
const _initialiseChildren = (parentContext, hydrate) => (childrenProps, htmlElement, context, anchor=null) => {
|
|
||||||
|
|
||||||
const childComponents = [];
|
|
||||||
|
|
||||||
if(hydrate) {
|
|
||||||
while (htmlElement.firstChild) {
|
|
||||||
htmlElement.removeChild(htmlElement.firstChild);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(let childProps of childrenProps) {
|
|
||||||
const {componentName, libName} = splitName(childProps._component);
|
|
||||||
|
|
||||||
if(!componentName || !libName) return;
|
|
||||||
|
|
||||||
const {initialProps, bind} = setupBinding(
|
|
||||||
store, childProps, coreApi,
|
|
||||||
context || parentContext, appDefinition.appRootPath);
|
|
||||||
|
|
||||||
|
|
||||||
const componentProps = {
|
|
||||||
...initialProps,
|
|
||||||
_bb:bb(context || parentContext, childProps)
|
|
||||||
};
|
|
||||||
|
|
||||||
const component = new (componentLibraries[libName][componentName])({
|
|
||||||
target: htmlElement,
|
|
||||||
props: componentProps,
|
|
||||||
hydrate:false,
|
|
||||||
anchor
|
|
||||||
});
|
|
||||||
|
|
||||||
bind(component);
|
|
||||||
childComponents.push(component);
|
|
||||||
}
|
|
||||||
|
|
||||||
return childComponents;
|
|
||||||
}
|
|
||||||
|
|
||||||
const coreApi = createCoreApi(appDefinition, user);
|
const coreApi = createCoreApi(appDefinition, user);
|
||||||
appDefinition.hierarchy = coreApi.templateApi.constructHierarchy(appDefinition.hierarchy);
|
appDefinition.hierarchy = coreApi.templateApi.constructHierarchy(appDefinition.hierarchy);
|
||||||
|
@ -85,7 +39,7 @@ export const createApp = (componentLibraries, appDefinition, user) => {
|
||||||
post: apiCall("POST"),
|
post: apiCall("POST"),
|
||||||
get: apiCall("GET"),
|
get: apiCall("GET"),
|
||||||
patch: apiCall("PATCH"),
|
patch: apiCall("PATCH"),
|
||||||
delete:apiCall("DELETE")
|
delete: apiCall("DELETE")
|
||||||
};
|
};
|
||||||
|
|
||||||
const safeCallEvent = (event, context) => {
|
const safeCallEvent = (event, context) => {
|
||||||
|
@ -96,11 +50,18 @@ export const createApp = (componentLibraries, appDefinition, user) => {
|
||||||
if(isFunction(event)) event(context);
|
if(isFunction(event)) event(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const initialiseChildrenParams = (parentContext, hydrate) => ({
|
||||||
|
bb, coreApi, store,
|
||||||
|
componentLibraries, appDefinition,
|
||||||
|
parentContext, hydrate, uiFunctions
|
||||||
|
});
|
||||||
|
|
||||||
const bb = (context, props) => ({
|
const bb = (context, props) => ({
|
||||||
hydrateChildren: _initialiseChildren(context, true),
|
hydrateChildren: _initialiseChildren(initialiseChildrenParams(context, true)),
|
||||||
appendChildren: _initialiseChildren(context, false),
|
appendChildren: _initialiseChildren(initialiseChildrenParams(context, false)),
|
||||||
insertChildren: (props, htmlElement, anchor, context) =>
|
insertChildren: (props, htmlElement, anchor, context) =>
|
||||||
_initialiseChildren(context, false)(props, htmlElement, context, anchor),
|
_initialiseChildren(initialiseChildrenParams(context, false))
|
||||||
|
(props, htmlElement, context, anchor),
|
||||||
store,
|
store,
|
||||||
relativeUrl,
|
relativeUrl,
|
||||||
api,
|
api,
|
||||||
|
@ -160,17 +121,3 @@ const buildBindings = (boundProps, boundArrays, contextBoundProps) => {
|
||||||
return bindings;
|
return bindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const splitName = fullname => {
|
|
||||||
const componentName = $(fullname, [
|
|
||||||
split("/"),
|
|
||||||
last
|
|
||||||
]);
|
|
||||||
|
|
||||||
const libName =fullname.substring(
|
|
||||||
0, fullname.length - componentName.length - 1);
|
|
||||||
|
|
||||||
return {libName, componentName};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import { createApp } from "./createApp";
|
import { createApp } from "./createApp";
|
||||||
import { trimSlash } from "./common/trimSlash";
|
import { trimSlash } from "./common/trimSlash";
|
||||||
|
|
||||||
export const loadBudibase = async ({componentLibraries, props, window, localStorage}) => {
|
export const loadBudibase = async ({
|
||||||
|
componentLibraries, props,
|
||||||
|
window, localStorage, uiFunctions }) => {
|
||||||
|
|
||||||
const appDefinition = window["##BUDIBASE_APPDEFINITION##"];
|
const appDefinition = window["##BUDIBASE_APPDEFINITION##"];
|
||||||
|
|
||||||
|
@ -33,7 +35,7 @@ export const loadBudibase = async ({componentLibraries, props, window, localStor
|
||||||
props = appDefinition.props;
|
props = appDefinition.props;
|
||||||
}
|
}
|
||||||
|
|
||||||
const _app = createApp(componentLibraries, appDefinition, user);
|
const _app = createApp(componentLibraries, appDefinition, user, uiFunctions);
|
||||||
_app.hydrateChildren(
|
_app.hydrateChildren(
|
||||||
[props],
|
[props],
|
||||||
window.document.body);
|
window.document.body);
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
import {
|
||||||
|
setupBinding
|
||||||
|
} from "../state/stateBinding";
|
||||||
|
import {
|
||||||
|
split,
|
||||||
|
last
|
||||||
|
} from "lodash/fp";
|
||||||
|
import { $ } from "../core/common";
|
||||||
|
import { renderComponent } from "./renderComponent";
|
||||||
|
|
||||||
|
export const _initialiseChildren = (initialiseOpts) =>
|
||||||
|
(childrenProps, htmlElement, context, anchor=null) => {
|
||||||
|
|
||||||
|
const { uiFunctions, bb, coreApi,
|
||||||
|
store, componentLibraries,
|
||||||
|
appDefinition, parentContext, hydrate } = initialiseOpts;
|
||||||
|
|
||||||
|
const childComponents = [];
|
||||||
|
|
||||||
|
if(hydrate) {
|
||||||
|
while (htmlElement.firstChild) {
|
||||||
|
htmlElement.removeChild(htmlElement.firstChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(let childProps of childrenProps) {
|
||||||
|
|
||||||
|
const {componentName, libName} = splitName(childProps._component);
|
||||||
|
|
||||||
|
if(!componentName || !libName) return;
|
||||||
|
|
||||||
|
const {initialProps, bind} = setupBinding(
|
||||||
|
store, childProps, coreApi,
|
||||||
|
context || parentContext, appDefinition.appRootPath);
|
||||||
|
|
||||||
|
/// here needs to go inside renderComponent ???
|
||||||
|
const componentProps = {
|
||||||
|
...initialProps,
|
||||||
|
_bb:bb(context || parentContext, childProps)
|
||||||
|
};
|
||||||
|
|
||||||
|
const componentConstructor = componentLibraries[libName][componentName];
|
||||||
|
|
||||||
|
const {component} = renderComponent({
|
||||||
|
componentConstructor,uiFunctions,
|
||||||
|
htmlElement, anchor,
|
||||||
|
parentContext, componentProps});
|
||||||
|
|
||||||
|
|
||||||
|
bind(component);
|
||||||
|
childComponents.push(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
return childComponents;
|
||||||
|
}
|
||||||
|
|
||||||
|
const splitName = fullname => {
|
||||||
|
const componentName = $(fullname, [
|
||||||
|
split("/"),
|
||||||
|
last
|
||||||
|
]);
|
||||||
|
|
||||||
|
const libName =fullname.substring(
|
||||||
|
0, fullname.length - componentName.length - 1);
|
||||||
|
|
||||||
|
return {libName, componentName};
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
|
||||||
|
export const renderComponent = ({
|
||||||
|
componentConstructor, uiFunctions,
|
||||||
|
htmlElement, anchor, parentContext,
|
||||||
|
componentProps}) => {
|
||||||
|
|
||||||
|
const func = uiFunctions[componentProps._id];
|
||||||
|
let component;
|
||||||
|
let componentContext;
|
||||||
|
const render = (context) => {
|
||||||
|
|
||||||
|
if(context) {
|
||||||
|
componentContext = {...componentContext};
|
||||||
|
componentContext.$parent = parentContext;
|
||||||
|
} else {
|
||||||
|
componentContext = parentContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
component = new componentConstructor({
|
||||||
|
target: htmlElement,
|
||||||
|
props: componentProps,
|
||||||
|
hydrate:false,
|
||||||
|
anchor
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if(func) {
|
||||||
|
func(render, parentContext);
|
||||||
|
} else {
|
||||||
|
render();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ({
|
||||||
|
context: componentContext,
|
||||||
|
component
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -15,6 +15,12 @@ import {
|
||||||
const doNothing = () => {};
|
const doNothing = () => {};
|
||||||
doNothing.isPlaceholder=true;
|
doNothing.isPlaceholder=true;
|
||||||
|
|
||||||
|
const isMetaProp = (propName) =>
|
||||||
|
propName === "_component"
|
||||||
|
|| propName === "_children"
|
||||||
|
|| propName === "_id"
|
||||||
|
|| propName === "_style";
|
||||||
|
|
||||||
export const setupBinding = (store, rootProps, coreApi, context, rootPath) => {
|
export const setupBinding = (store, rootProps, coreApi, context, rootPath) => {
|
||||||
|
|
||||||
const rootInitialProps = {...rootProps};
|
const rootInitialProps = {...rootProps};
|
||||||
|
@ -24,13 +30,12 @@ export const setupBinding = (store, rootProps, coreApi, context, rootPath) => {
|
||||||
const boundProps = [];
|
const boundProps = [];
|
||||||
const contextBoundProps = [];
|
const contextBoundProps = [];
|
||||||
const componentEventHandlers = [];
|
const componentEventHandlers = [];
|
||||||
const boundArrays = [];
|
|
||||||
|
|
||||||
for(let propName in props) {
|
for(let propName in props) {
|
||||||
|
|
||||||
if(propName === "_component") continue;
|
if(isMetaProp(propName)) continue;
|
||||||
|
|
||||||
const val = initialProps[propName];
|
const val = props[propName];
|
||||||
|
|
||||||
if(isBound(val) && takeStateFromStore(val)) {
|
if(isBound(val) && takeStateFromStore(val)) {
|
||||||
|
|
||||||
|
@ -76,21 +81,10 @@ export const setupBinding = (store, rootProps, coreApi, context, rootPath) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
initialProps[propName] = doNothing;
|
initialProps[propName] = doNothing;
|
||||||
} else if(Array.isArray(val)) {
|
}
|
||||||
const arrayOfBindings = [];
|
|
||||||
for(let element of val){
|
|
||||||
arrayOfBindings.push(getBindings(element, {...element}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boundArrays.push({
|
return {contextBoundProps, boundProps, componentEventHandlers, initialProps};
|
||||||
arrayOfBindings,
|
|
||||||
propName
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return {contextBoundProps, boundProps, componentEventHandlers, boundArrays, initialProps};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,8 +92,7 @@ export const setupBinding = (store, rootProps, coreApi, context, rootPath) => {
|
||||||
const bind = (rootBindings) => (component) => {
|
const bind = (rootBindings) => (component) => {
|
||||||
|
|
||||||
if(rootBindings.boundProps.length === 0
|
if(rootBindings.boundProps.length === 0
|
||||||
&& rootBindings.componentEventHandlers.length === 0
|
&& rootBindings.componentEventHandlers.length === 0) return;
|
||||||
&& rootBindings.boundArrays.length === 0) return;
|
|
||||||
|
|
||||||
const handlerTypes = eventHandlers(store, coreApi, rootPath);
|
const handlerTypes = eventHandlers(store, coreApi, rootPath);
|
||||||
|
|
||||||
|
@ -108,7 +101,7 @@ export const setupBinding = (store, rootProps, coreApi, context, rootPath) => {
|
||||||
|
|
||||||
const getPropsFromBindings = (s, bindings) => {
|
const getPropsFromBindings = (s, bindings) => {
|
||||||
|
|
||||||
const {boundProps, componentEventHandlers, boundArrays} = bindings;
|
const {boundProps, componentEventHandlers} = bindings;
|
||||||
const newProps = {...bindings.initialProps};
|
const newProps = {...bindings.initialProps};
|
||||||
|
|
||||||
for(let boundProp of boundProps) {
|
for(let boundProp of boundProps) {
|
||||||
|
@ -159,18 +152,6 @@ export const setupBinding = (store, rootProps, coreApi, context, rootPath) => {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(let boundArray of boundArrays) {
|
|
||||||
let index = 0;
|
|
||||||
if(!newProps[boundArray.propName])
|
|
||||||
newProps[boundArray.propName] = [];
|
|
||||||
for(let bindings of boundArray.arrayOfBindings){
|
|
||||||
newProps[boundArray.propName][index] = getPropsFromBindings(
|
|
||||||
s,
|
|
||||||
bindings);
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newProps;
|
return newProps;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -189,7 +170,6 @@ export const setupBinding = (store, rootProps, coreApi, context, rootPath) => {
|
||||||
initialProps:rootInitialProps,
|
initialProps:rootInitialProps,
|
||||||
bind:bind(bindings),
|
bind:bind(bindings),
|
||||||
boundProps:bindings.boundProps,
|
boundProps:bindings.boundProps,
|
||||||
boundArrays: bindings.boundArrays,
|
|
||||||
contextBoundProps: bindings.contextBoundProps
|
contextBoundProps: bindings.contextBoundProps
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
import { load } from "./testAppDef";
|
||||||
|
|
||||||
|
describe("controlFlow", () => {
|
||||||
|
|
||||||
|
it("should display simple div, with always true render function", async () => {
|
||||||
|
|
||||||
|
const {dom} = await load({
|
||||||
|
_component: "testlib/div",
|
||||||
|
className: "my-test-class",
|
||||||
|
_id: "always_render"
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(dom.window.document.body.children.length).toBe(1);
|
||||||
|
const child = dom.window.document.body.children[0];
|
||||||
|
expect(child.className).toBe("my-test-class");
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should not display div, with always false render function", async () => {
|
||||||
|
|
||||||
|
const {dom} = await load({
|
||||||
|
_component: "testlib/div",
|
||||||
|
className: "my-test-class",
|
||||||
|
_id: "never_render"
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(dom.window.document.body.children.length).toBe(0);
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should display 3 divs in a looped render function", async () => {
|
||||||
|
|
||||||
|
const {dom} = await load({
|
||||||
|
_component: "testlib/div",
|
||||||
|
className: "my-test-class",
|
||||||
|
_id: "three_clones"
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(dom.window.document.body.children.length).toBe(3);
|
||||||
|
|
||||||
|
const child0 = dom.window.document.body.children[0];
|
||||||
|
expect(child0.className).toBe("my-test-class");
|
||||||
|
|
||||||
|
const child1 = dom.window.document.body.children[1];
|
||||||
|
expect(child1.className).toBe("my-test-class");
|
||||||
|
|
||||||
|
const child2 = dom.window.document.body.children[2];
|
||||||
|
expect(child2.className).toBe("my-test-class");
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should display 3 div, in a looped render, as children", async () => {
|
||||||
|
const {dom} = await load({
|
||||||
|
_component: "testlib/div",
|
||||||
|
_children: [
|
||||||
|
{
|
||||||
|
_component: "testlib/div",
|
||||||
|
className: "my-test-class",
|
||||||
|
_id: "three_clones"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(dom.window.document.body.children.length).toBe(1);
|
||||||
|
|
||||||
|
const rootDiv = dom.window.document.body.children[0];
|
||||||
|
expect(rootDiv.children.length).toBe(3);
|
||||||
|
|
||||||
|
expect(rootDiv.children[0].className).toBe("my-test-class");
|
||||||
|
expect(rootDiv.children[1].className).toBe("my-test-class");
|
||||||
|
expect(rootDiv.children[2].className).toBe("my-test-class");
|
||||||
|
})
|
||||||
|
|
||||||
|
});
|
|
@ -74,59 +74,6 @@ describe("setupBinding", () => {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should update bound array props when updated ", () => {
|
|
||||||
|
|
||||||
const {component, store, props} = testSetup();
|
|
||||||
|
|
||||||
const {bind} = testSetupBinding(store, props, component);
|
|
||||||
bind(component);
|
|
||||||
|
|
||||||
store.update(s => {
|
|
||||||
s.FirstName = "Bobby";
|
|
||||||
s.LastName = "Thedog";
|
|
||||||
s.Customer = {
|
|
||||||
Name: "ACME inc",
|
|
||||||
Address: ""
|
|
||||||
};
|
|
||||||
s.addressToSet = "123 Main Street";
|
|
||||||
s.ArrayVal1 = "item 1 - version 1";
|
|
||||||
s.ArrayVal2 = "item 2 - version 1";
|
|
||||||
s.ArrayVal3 = "inner array item";
|
|
||||||
return s;
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.props.arrayWithInnerBinding[0].innerBound).toBe("item 1 - version 1");
|
|
||||||
expect(component.props.arrayWithInnerBinding[1].innerBound).toBe("item 2 - version 1");
|
|
||||||
expect(component.props.arrayWithInnerBinding[0].innerUnbound).toBe("not bound 1");
|
|
||||||
expect(component.props.arrayWithInnerBinding[1].innerUnbound).toBe("not bound 2");
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should update bound nested (2nd level) array props when updated ", () => {
|
|
||||||
|
|
||||||
const {component, store, props} = testSetup();
|
|
||||||
|
|
||||||
const {bind} = testSetupBinding(store, props, component);
|
|
||||||
bind(component);
|
|
||||||
|
|
||||||
store.update(s => {
|
|
||||||
s.FirstName = "Bobby";
|
|
||||||
s.LastName = "Thedog";
|
|
||||||
s.Customer = {
|
|
||||||
Name: "ACME inc",
|
|
||||||
Address: ""
|
|
||||||
};
|
|
||||||
s.addressToSet = "123 Main Street";
|
|
||||||
s.ArrayVal1 = "item 1 - version 1";
|
|
||||||
s.ArrayVal2 = "item 2 - version 1";
|
|
||||||
s.ArrayVal3 = "inner array item";
|
|
||||||
return s;
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.props.arrayWithInnerBinding[2].innerArray[0].innerInnerBound).toBe("inner array item");
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should update event handlers on state change", () => {
|
it("should update event handlers on state change", () => {
|
||||||
|
|
||||||
const {component, store, props} = testSetup();
|
const {component, store, props} = testSetup();
|
||||||
|
@ -235,23 +182,6 @@ const testSetup = () => {
|
||||||
path: "Customer.Address",
|
path: "Customer.Address",
|
||||||
value: binding("addressOverride", "", "event")
|
value: binding("addressOverride", "", "event")
|
||||||
})
|
})
|
||||||
],
|
|
||||||
arrayWithInnerBinding: [
|
|
||||||
{
|
|
||||||
innerBound: binding("ArrayVal1"),
|
|
||||||
innerUnbound: "not bound 1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
innerBound: binding("ArrayVal2"),
|
|
||||||
innerUnbound: "not bound 2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
innerArray: [
|
|
||||||
{
|
|
||||||
innerInnerBound: binding("ArrayVal3")
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,16 +3,32 @@ import { loadBudibase } from "../src/index";
|
||||||
|
|
||||||
export const load = async (props) => {
|
export const load = async (props) => {
|
||||||
const dom = new JSDOM(`<!DOCTYPE html><html><body></body><html>`);
|
const dom = new JSDOM(`<!DOCTYPE html><html><body></body><html>`);
|
||||||
|
autoAssignIds(props);
|
||||||
setAppDef(dom.window, props);
|
setAppDef(dom.window, props);
|
||||||
const app = await loadBudibase({
|
const app = await loadBudibase({
|
||||||
componentLibraries: allLibs(dom.window),
|
componentLibraries: allLibs(dom.window),
|
||||||
window: dom.window,
|
window: dom.window,
|
||||||
localStorage: createLocalStorage(),
|
localStorage: createLocalStorage(),
|
||||||
props
|
props,
|
||||||
|
uiFunctions
|
||||||
});
|
});
|
||||||
return {dom, app};
|
return {dom, app};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this happens for real by the builder...
|
||||||
|
// ..this only assigns _ids when missing
|
||||||
|
const autoAssignIds = (props, count=0) => {
|
||||||
|
if(!props._id) {
|
||||||
|
props._id = `auto_id_${count}`;
|
||||||
|
}
|
||||||
|
if(props._children) {
|
||||||
|
for(let child of props._children) {
|
||||||
|
count += 1;
|
||||||
|
autoAssignIds(child, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const setAppDef = (window, props) => {
|
const setAppDef = (window, props) => {
|
||||||
window["##BUDIBASE_APPDEFINITION##"] = ({
|
window["##BUDIBASE_APPDEFINITION##"] = ({
|
||||||
componentLibraries: [],
|
componentLibraries: [],
|
||||||
|
@ -87,5 +103,18 @@ const maketestlib = (window) => ({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const uiFunctions = ({
|
||||||
|
|
||||||
|
never_render : (render, parentContext) => {},
|
||||||
|
|
||||||
|
always_render : (render, parentContext) => {
|
||||||
|
render();
|
||||||
|
},
|
||||||
|
|
||||||
|
three_clones : (render, parentContext) => {
|
||||||
|
for(let i = 0; i<3; i++) {
|
||||||
|
render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue