#48 restructure. Screens in, user components out. _children static concept
This commit is contained in:
parent
f2221e32e2
commit
4e09043e3a
|
@ -21,12 +21,12 @@ $ : {
|
|||
|
||||
for(let el in htmlElements) {
|
||||
if(formControls[el].control.controlPosition === "Before Label") {
|
||||
_bb.insertComponent(
|
||||
_bb.insertChildren(
|
||||
_bb.props.formControls[el].control,
|
||||
htmlElements[el],
|
||||
htmlElements[el].childNodes.find(n => n.tagName === "LABEL"));
|
||||
} else {
|
||||
_bb.appendComponent(
|
||||
_bb.appendChildren(
|
||||
_bb.props.formControls[el].control,
|
||||
htmlElements[el]);
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ const SelectItem = (index) => {
|
|||
}
|
||||
|
||||
if(index >= 0)
|
||||
currentComponent = _bb.hydrateComponent(
|
||||
currentComponent = _bb.hydrateChildren(
|
||||
_bb.props.items[index].component, componentElement);
|
||||
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ let currentComponent;
|
|||
|
||||
$: {
|
||||
if(_bb && currentComponent) {
|
||||
_bb.hydrateComponent(testProps, currentComponent);
|
||||
_bb.hydrateChildren(testProps, currentComponent);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,9 +15,9 @@ import { defaultPagesObject } from "../userInterface/pagesParsing/defaultPagesOb
|
|||
import { buildPropsHierarchy } from "../userInterface/pagesParsing/buildPropsHierarchy"
|
||||
import api from "./api";
|
||||
import { isRootComponent, getExactComponent } from "../userInterface/pagesParsing/searchComponents";
|
||||
import { rename } from "../userInterface/pagesParsing/renameComponent";
|
||||
import { rename } from "../userInterface/pagesParsing/renameScreen";
|
||||
import {
|
||||
getComponentInfo, getNewComponentInfo
|
||||
getNewComponentInfo, getScreenInfo
|
||||
} from "../userInterface/pagesParsing/createProps";
|
||||
import {
|
||||
loadLibs, loadLibUrls, loadGeneratorLibs
|
||||
|
@ -36,12 +36,12 @@ export const getStore = () => {
|
|||
pages:defaultPagesObject(),
|
||||
mainUi:{},
|
||||
unauthenticatedUi:{},
|
||||
allComponents:[],
|
||||
components:[],
|
||||
currentFrontEndItem:null,
|
||||
currentComponentInfo:null,
|
||||
currentComponentIsNew:false,
|
||||
currentFrontEndType:"none",
|
||||
currentPageName: "",
|
||||
currentComponentProps:null,
|
||||
currentNodeIsNew: false,
|
||||
errors: [],
|
||||
activeNav: "database",
|
||||
|
@ -74,14 +74,14 @@ export const getStore = () => {
|
|||
store.saveLevel = saveLevel(store);
|
||||
store.deleteLevel = deleteLevel(store);
|
||||
store.setActiveNav = setActiveNav(store);
|
||||
store.saveDerivedComponent = saveDerivedComponent(store);
|
||||
store.saveScreen = saveScreen(store);
|
||||
store.refreshComponents = refreshComponents(store);
|
||||
store.addComponentLibrary = addComponentLibrary(store);
|
||||
store.renameDerivedComponent = renameDerivedComponent(store);
|
||||
store.deleteDerivedComponent = deleteDerivedComponent(store);
|
||||
store.setCurrentComponent = setCurrentComponent(store);
|
||||
store.renameScreen = renameScreen(store);
|
||||
store.deleteScreen = deleteScreen(store);
|
||||
store.setCurrentScreen = setCurrentScreen(store);
|
||||
store.setCurrentPage = setCurrentPage(store);
|
||||
store.createDerivedComponent = createDerivedComponent(store);
|
||||
store.createScreen = createScreen(store);
|
||||
store.removeComponentLibrary =removeComponentLibrary(store);
|
||||
store.addStylesheet = addStylesheet(store);
|
||||
store.removeStylesheet = removeStylesheet(store);
|
||||
|
@ -120,10 +120,9 @@ const initialise = (store, initial) => async () => {
|
|||
initial.hasAppPackage = true;
|
||||
initial.hierarchy = pkg.appDefinition.hierarchy;
|
||||
initial.accessLevels = pkg.accessLevels;
|
||||
initial.derivedComponents = values(pkg.derivedComponents);
|
||||
initial.generators = generatorsArray(pkg.rootComponents.generators);
|
||||
initial.allComponents = combineComponents(
|
||||
pkg.derivedComponents, pkg.rootComponents.components);
|
||||
initial.screens = values(pkg.screens);
|
||||
initial.generators = generatorsArray(pkg.components.generators);
|
||||
initial.components = values(pkg.components.components);
|
||||
initial.actions = values(pkg.appDefinition.actions);
|
||||
initial.triggers = pkg.appDefinition.triggers;
|
||||
|
||||
|
@ -175,17 +174,6 @@ const showFrontend = store => () => {
|
|||
})
|
||||
}
|
||||
|
||||
const combineComponents = (root, derived) => {
|
||||
const all = []
|
||||
for(let r in root) {
|
||||
all.push(root[r]);
|
||||
}
|
||||
for(let d in derived) {
|
||||
all.push(derived[d]);
|
||||
}
|
||||
return all;
|
||||
}
|
||||
|
||||
const newRecord = (store, useRoot) => () => {
|
||||
store.update(s => {
|
||||
s.currentNodeIsNew = true;
|
||||
|
@ -440,55 +428,50 @@ const setActiveNav = store => navName => {
|
|||
const createShadowHierarchy = hierarchy =>
|
||||
constructHierarchy(JSON.parse(JSON.stringify(hierarchy)));
|
||||
|
||||
const saveDerivedComponent = store => (derivedComponent) => {
|
||||
|
||||
const saveScreen = store => (screen) => {
|
||||
store.update(s => {
|
||||
|
||||
const components = pipe(s.allComponents, [
|
||||
filter(c => c.name !== derivedComponent.name),
|
||||
concat([derivedComponent])
|
||||
]);
|
||||
|
||||
const derivedComponents = pipe(s.derivedComponents, [
|
||||
filter(c => c.name !== derivedComponent.name),
|
||||
concat([derivedComponent])
|
||||
]);
|
||||
|
||||
s.allComponents = components;
|
||||
s.derivedComponents = derivedComponents;
|
||||
s.currentFrontEndItem = derivedComponent;
|
||||
s.currentComponentInfo = getComponentInfo(
|
||||
s.allComponents, derivedComponent.name);
|
||||
s.currentComponentIsNew = false;
|
||||
|
||||
api.post(`/_builder/api/${s.appname}/derivedcomponent`, derivedComponent)
|
||||
.then(() => savePackage(store, s));
|
||||
|
||||
return s;
|
||||
return _saveScreen(store, s, screen);
|
||||
})
|
||||
};
|
||||
|
||||
const createDerivedComponent = store => componentName => {
|
||||
const _saveScreen = (store, s, screen) => {
|
||||
const screens = pipe(s.screens, [
|
||||
filter(c => c.name !== screen.name),
|
||||
concat([screen])
|
||||
]);
|
||||
|
||||
s.screens = screens;
|
||||
s.currentFrontEndItem = screen;
|
||||
s.currentComponentInfo = getScreenInfo(
|
||||
s.components, screen);
|
||||
|
||||
api.post(`/_builder/api/${s.appname}/screen`, screen)
|
||||
.then(() => savePackage(store, s));
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
const createScreen = store => (screenName, layoutComponentName) => {
|
||||
store.update(s => {
|
||||
const newComponentInfo = getNewComponentInfo(
|
||||
s.allComponents, componentName);
|
||||
s.components, layoutComponentName, screenName);
|
||||
|
||||
s.currentFrontEndItem = newComponentInfo.component;
|
||||
s.currentComponentInfo = newComponentInfo;
|
||||
s.currentFrontEndType = "component";
|
||||
s.currentComponentIsNew = true;
|
||||
return s;
|
||||
s.currentFrontEndType = "screen";
|
||||
|
||||
return _saveScreen(store, s, newComponentInfo.component);
|
||||
});
|
||||
};
|
||||
|
||||
const createGeneratedComponents = store => components => {
|
||||
store.update(s => {
|
||||
s.allComponents = [...s.allComponents, ...components];
|
||||
s.derivedComponents = [...s.derivedComponents, ...components];
|
||||
s.components = [...s.components, ...components];
|
||||
s.screens = [...s.screens, ...components];
|
||||
|
||||
const doCreate = async () => {
|
||||
for(let c of components) {
|
||||
await api.post(`/_builder/api/${s.appname}/derivedcomponent`, c);
|
||||
await api.post(`/_builder/api/${s.appname}/screen`, c);
|
||||
}
|
||||
|
||||
await savePackage(store, s);
|
||||
|
@ -500,55 +483,56 @@ const createGeneratedComponents = store => components => {
|
|||
});
|
||||
};
|
||||
|
||||
const deleteDerivedComponent = store => name => {
|
||||
const deleteScreen = store => name => {
|
||||
store.update(s => {
|
||||
|
||||
const allComponents = pipe(s.allComponents, [
|
||||
const components = pipe(s.components, [
|
||||
filter(c => c.name !== name)
|
||||
]);
|
||||
|
||||
const derivedComponents = pipe(s.derivedComponents, [
|
||||
const screens = pipe(s.screens, [
|
||||
filter(c => c.name !== name)
|
||||
]);
|
||||
|
||||
s.allComponents = allComponents;
|
||||
s.derivedComponents = derivedComponents;
|
||||
s.components = components;
|
||||
s.screens = screens;
|
||||
if(s.currentFrontEndItem.name === name) {
|
||||
s.currentFrontEndItem = null;
|
||||
s.currentFrontEndType = "";
|
||||
}
|
||||
|
||||
api.delete(`/_builder/api/${s.appname}/derivedcomponent/${name}`);
|
||||
api.delete(`/_builder/api/${s.appname}/screen/${name}`);
|
||||
|
||||
return s;
|
||||
})
|
||||
}
|
||||
|
||||
const renameDerivedComponent = store => (oldname, newname) => {
|
||||
const renameScreen = store => (oldname, newname) => {
|
||||
store.update(s => {
|
||||
|
||||
const {
|
||||
allComponents, pages, error, changedComponents
|
||||
} = rename(s.pages, s.allComponents, oldname, newname);
|
||||
screens, pages, error, changedScreens
|
||||
} = rename(s.pages, s.screens, oldname, newname);
|
||||
|
||||
if(error) {
|
||||
// should really do something with this
|
||||
return s;
|
||||
}
|
||||
|
||||
s.allComponents = allComponents;
|
||||
s.screens = screens;
|
||||
s.pages = pages;
|
||||
if(s.currentFrontEndItem.name === oldname)
|
||||
s.currentFrontEndItem.name = newname;
|
||||
|
||||
const saveAllChanged = async () => {
|
||||
for(let cname of changedComponents) {
|
||||
const changedComponent = getExactComponent(allComponents, cname);
|
||||
await api.post(`/_builder/api/${s.appname}/derivedcomponent`, changedComponent);
|
||||
for(let screenName of changedScreens) {
|
||||
const changedScreen
|
||||
= getExactComponent(screens, screenName);
|
||||
await api.post(`/_builder/api/${s.appname}/screen`, changedScreen);
|
||||
}
|
||||
}
|
||||
|
||||
api.patch(`/_builder/api/${s.appname}/derivedcomponent`, {
|
||||
api.patch(`/_builder/api/${s.appname}/screen`, {
|
||||
oldname, newname
|
||||
})
|
||||
.then(() => saveAllChanged())
|
||||
|
@ -597,7 +581,7 @@ const addComponentLibrary = store => async lib => {
|
|||
componentsArray.push(components[c]);
|
||||
}
|
||||
|
||||
s.allComponents = pipe(s.allComponents, [
|
||||
s.components = pipe(s.components, [
|
||||
filter(c => !c.name.startsWith(`${lib}/`)),
|
||||
concat(componentsArray)
|
||||
]);
|
||||
|
@ -643,20 +627,20 @@ const removeStylesheet = store => stylesheet => {
|
|||
|
||||
const refreshComponents = store => async () => {
|
||||
|
||||
const components =
|
||||
await api.get(`/_builder/api/${db.appname}/rootcomponents`).then(r => r.json());
|
||||
const componentsAndGenerators =
|
||||
await api.get(`/_builder/api/${db.appname}/components`).then(r => r.json());
|
||||
|
||||
const rootComponents = pipe(components.components, [
|
||||
const components = pipe(componentsAndGenerators.components, [
|
||||
keys,
|
||||
map(k => ({...components[k], name:k}))
|
||||
map(k => ({...componentsAndGenerators[k], name:k}))
|
||||
]);
|
||||
|
||||
store.update(s => {
|
||||
s.allComponents = pipe(s.allComponents, [
|
||||
s.components = pipe(s.components, [
|
||||
filter(c => !isRootComponent(c)),
|
||||
concat(rootComponents)
|
||||
concat(components)
|
||||
]);
|
||||
s.generators = components.generators;
|
||||
s.generators = componentsAndGenerators.generators;
|
||||
return s;
|
||||
});
|
||||
};
|
||||
|
@ -668,8 +652,14 @@ const savePackage = (store, s) => {
|
|||
triggers:s.triggers,
|
||||
actions: keyBy("name")(s.actions),
|
||||
props: {
|
||||
main: buildPropsHierarchy(s.allComponents, s.pages.main.appBody),
|
||||
unauthenticated: buildPropsHierarchy(s.allComponents, s.pages.unauthenticated.appBody)
|
||||
main: buildPropsHierarchy(
|
||||
s.components,
|
||||
s.screens,
|
||||
s.pages.main.appBody),
|
||||
unauthenticated: buildPropsHierarchy(
|
||||
s.components,
|
||||
s.screens,
|
||||
s.pages.unauthenticated.appBody)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -682,13 +672,12 @@ const savePackage = (store, s) => {
|
|||
return api.post(`/_builder/api/${s.appname}/appPackage`, data);
|
||||
}
|
||||
|
||||
const setCurrentComponent = store => componentName => {
|
||||
const setCurrentScreen = store => screenName => {
|
||||
store.update(s => {
|
||||
const component = getExactComponent(s.allComponents, componentName);
|
||||
s.currentFrontEndItem = component;
|
||||
s.currentFrontEndType = "component";
|
||||
s.currentComponentIsNew = false;
|
||||
s.currentComponentInfo = getComponentInfo(s.allComponents, component.name);
|
||||
const screen = getExactComponent(s.screens, screenName);
|
||||
s.currentFrontEndItem = screen;
|
||||
s.currentFrontEndType = "screen";
|
||||
s.currentComponentInfo = getScreenInfo(s.components, screen);
|
||||
return s;
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,114 +0,0 @@
|
|||
<script>
|
||||
|
||||
import PropsView from "./PropsView.svelte";
|
||||
import IconButton from "../common/IconButton.svelte";
|
||||
import { getComponentInfo } from "./pagesParsing/createProps";
|
||||
import { store } from "../builderStore";
|
||||
import {
|
||||
cloneDeep,
|
||||
isUndefined
|
||||
} from "lodash/fp";
|
||||
import { fade, slide } from 'svelte/transition';
|
||||
|
||||
export let title = "";
|
||||
export let onGoBack = () => {};
|
||||
export let instanceProps = {};
|
||||
export let onPropsChanged = () => {};
|
||||
|
||||
|
||||
let editingSubComponentName;
|
||||
let editingSubComponentProps;
|
||||
let editingSubComponentArrayIndex;
|
||||
let editingSubComponentArrayPropName;
|
||||
let editingSubComponentTitle;
|
||||
let allComponents;
|
||||
|
||||
store.subscribe(s => {
|
||||
allComponents = s.allComponents;
|
||||
})
|
||||
|
||||
$: componentInfo = getComponentInfo(
|
||||
allComponents, instanceProps._component);
|
||||
|
||||
const onSubComponentGoBack = () => {
|
||||
editingSubComponentName = null;
|
||||
editingSubComponentProps = null;
|
||||
}
|
||||
|
||||
const onEditComponentProp = (propName, arrayIndex, arrayPropName) => {
|
||||
editingSubComponentName = propName;
|
||||
editingSubComponentTitle = isUndefined(arrayIndex)
|
||||
? propName
|
||||
: `${propName}[${arrayIndex}].${arrayPropName}`;
|
||||
editingSubComponentProps = isUndefined(arrayIndex)
|
||||
? instanceProps[propName]
|
||||
: instanceProps[propName][arrayIndex][arrayPropName];
|
||||
editingSubComponentArrayIndex = arrayIndex;
|
||||
editingSubComponentArrayPropName = arrayPropName;
|
||||
};
|
||||
|
||||
|
||||
const onSubComponentPropsChanged = (subProps) => {
|
||||
const newProps = cloneDeep(instanceProps);
|
||||
if(isUndefined(editingSubComponentArrayIndex)) {
|
||||
newProps[editingSubComponentName] = subProps;
|
||||
} else {
|
||||
newProps[editingSubComponentName]
|
||||
[editingSubComponentArrayIndex]
|
||||
[editingSubComponentArrayPropName] = subProps;
|
||||
}
|
||||
|
||||
instanceProps = newProps;
|
||||
onPropsChanged(newProps);
|
||||
}
|
||||
|
||||
|
||||
const propsChanged = newProps => {
|
||||
instanceProps = newProps;
|
||||
onPropsChanged(newProps);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<div>
|
||||
|
||||
<div class="title">
|
||||
<IconButton icon="chevron-left"
|
||||
on:click={onGoBack}/>
|
||||
<span>{title}</span>
|
||||
</div>
|
||||
|
||||
{#if editingSubComponentName}
|
||||
<div in:slide={{delay: 250, duration: 300}}
|
||||
out:fade>
|
||||
<svelte:self onPropsChanged={onSubComponentPropsChanged}
|
||||
onGoBack={onSubComponentGoBack}
|
||||
instanceProps={editingSubComponentProps}
|
||||
title={editingSubComponentTitle} />
|
||||
</div>
|
||||
{:else}
|
||||
<PropsView {instanceProps}
|
||||
{componentInfo}
|
||||
onPropsChanged={propsChanged}
|
||||
{onEditComponentProp} />
|
||||
{/if}
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.title {
|
||||
padding:3px;
|
||||
background-color: white;
|
||||
color: var(--secondary100);
|
||||
border-style:solid;
|
||||
border-width: 1px 0 0 0;
|
||||
border-color: var(--lightslate);
|
||||
}
|
||||
|
||||
.title > span {
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
|
@ -1,139 +0,0 @@
|
|||
<script>
|
||||
import {
|
||||
last
|
||||
} from "lodash/fp";
|
||||
import IconButton from "../common/IconButton.svelte";
|
||||
import ComponentSelector from "./ComponentSelector.svelte";
|
||||
import Button from "../common/Button.svelte";
|
||||
import ButtonGroup from "../common/ButtonGroup.svelte";
|
||||
import UIkit from "uikit";
|
||||
import {
|
||||
getComponentInfo
|
||||
} from "./pagesParsing/createProps";
|
||||
import { store } from "../builderStore";
|
||||
|
||||
const emptyProps = () => ({_component:""})
|
||||
|
||||
export let props = emptyProps();
|
||||
export let onValueChanged = () => {};
|
||||
export let onComponentChosen = () => {};
|
||||
export let onEdit = () => {};
|
||||
export let disabled = false;
|
||||
|
||||
const CHOOSE_COMPONENT = "choose_component";
|
||||
const CLEAR_COMPONENT = "clear_component";
|
||||
|
||||
let allComponents;
|
||||
let modalElement;
|
||||
let modalAction;
|
||||
|
||||
store.subscribe(s => {
|
||||
allComponents = s.allComponents;
|
||||
});
|
||||
|
||||
$: componentSelected = props._component.length > 0;
|
||||
$: shortName = last(props._component.split("/"));
|
||||
|
||||
const chooseComponent = () => {
|
||||
modalAction = CHOOSE_COMPONENT;
|
||||
showDialog();
|
||||
}
|
||||
|
||||
const clearComponent = () => {
|
||||
modalAction = CLEAR_COMPONENT;
|
||||
showDialog();
|
||||
}
|
||||
|
||||
const componentChosen = (component) => {
|
||||
const componentInfo = getComponentInfo(allComponents, component.name);
|
||||
props = componentInfo.fullProps;
|
||||
onValueChanged(props);
|
||||
onComponentChosen();
|
||||
hideDialog();
|
||||
}
|
||||
|
||||
const hideDialog = () => {
|
||||
UIkit.modal(modalElement).hide();
|
||||
}
|
||||
|
||||
const showDialog = () => {
|
||||
UIkit.modal(modalElement).show();
|
||||
}
|
||||
|
||||
const confirmClearComponent = () => {
|
||||
props = emptyProps();
|
||||
onValueChanged(emptyProps());
|
||||
hideDialog();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<div class="root uk-form-controls">
|
||||
<div class:selectedname={componentSelected}>
|
||||
{componentSelected ? shortName : "(none)"}
|
||||
</div>
|
||||
<div>
|
||||
{#if !disabled && componentSelected}
|
||||
<IconButton icon="edit"
|
||||
on:click={() => onEdit()}/>
|
||||
|
||||
<IconButton icon="trash"
|
||||
on:click={() => clearComponent()} />
|
||||
{:else if !disabled && !componentSelected}
|
||||
<IconButton icon="plus"
|
||||
on:click={() => chooseComponent()} />
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div bind:this={modalElement} uk-modal>
|
||||
<div class="uk-modal-dialog" uk-overflow-auto>
|
||||
|
||||
{#if modalAction === CHOOSE_COMPONENT}
|
||||
<div class="uk-modal-body">
|
||||
<ComponentSelector onComponentChosen={componentChosen}
|
||||
allowGenerators={false} />
|
||||
</div>
|
||||
{:else if modalAction === CLEAR_COMPONENT}
|
||||
<div class="uk-modal-body">
|
||||
Clear this component ?
|
||||
</div>
|
||||
<div class="uk-modal-footer">
|
||||
<ButtonGroup>
|
||||
<Button grouped
|
||||
on:click={hideDialog}
|
||||
color="secondary" >Cancel</Button>
|
||||
<Button grouped
|
||||
on:click={confirmClearComponent}>OK</Button>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
.root {
|
||||
display: grid;
|
||||
grid-template-columns: [name] 1fr [actions] auto;
|
||||
}
|
||||
|
||||
.root > div:nth-child(1) {
|
||||
grid-column-start: name;
|
||||
color: var(--secondary50);
|
||||
}
|
||||
|
||||
.root > div:nth-child(2) {
|
||||
grid-column-start: actions;
|
||||
}
|
||||
|
||||
.selectedname {
|
||||
font-weight: bold;
|
||||
color: var(--secondary);
|
||||
}
|
||||
|
||||
</style>
|
|
@ -5,17 +5,17 @@ import { store } from "../builderStore";
|
|||
|
||||
export let onComponentChosen = () => {};
|
||||
|
||||
let allComponents = [];
|
||||
let components = [];
|
||||
let phrase = "";
|
||||
|
||||
store.subscribe(s => {
|
||||
allComponents = s.allComponents;
|
||||
components = s.components;
|
||||
});
|
||||
|
||||
$: filteredComponents =
|
||||
!phrase
|
||||
? []
|
||||
: searchAllComponents(allComponents, phrase);
|
||||
: searchAllComponents(components, phrase);
|
||||
|
||||
</script>
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ export let onComponentChosen;
|
|||
export let onGeneratorChosen;
|
||||
export let allowGenerators;
|
||||
|
||||
let derivedComponents=[];
|
||||
let screens=[];
|
||||
let componentLibraries=[];
|
||||
|
||||
const addRootComponent = (c, all, isGenerator) => {
|
||||
|
@ -41,16 +41,16 @@ const addRootComponent = (c, all, isGenerator) => {
|
|||
store.subscribe(s => {
|
||||
|
||||
const newComponentLibraries = [];
|
||||
const newDerivedComponents = [];
|
||||
const newscreens = [];
|
||||
|
||||
for(let comp of sortBy(["name"])(s.allComponents)) {
|
||||
for(let comp of sortBy(["name"])(s.components)) {
|
||||
if(isRootComponent(comp)) {
|
||||
addRootComponent(
|
||||
comp,
|
||||
newComponentLibraries,
|
||||
false);
|
||||
} else {
|
||||
newDerivedComponents.push(comp);
|
||||
newscreens.push(comp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ store.subscribe(s => {
|
|||
true);
|
||||
}
|
||||
|
||||
derivedComponents = sortBy(["name"])(newDerivedComponents);
|
||||
screens = sortBy(["name"])(newscreens);
|
||||
componentLibraries = newComponentLibraries;
|
||||
});
|
||||
|
||||
|
@ -127,7 +127,7 @@ store.subscribe(s => {
|
|||
|
||||
<div class="library-container">
|
||||
|
||||
{#each derivedComponents as component}
|
||||
{#each screens as component}
|
||||
|
||||
<div class="component"
|
||||
on:click={() => onComponentChosen(component)}>
|
||||
|
|
|
@ -88,7 +88,7 @@ const expandFolder = folder => {
|
|||
}
|
||||
|
||||
const isComponentSelected = (type, current,c) =>
|
||||
type==="component"
|
||||
type==="screen"
|
||||
&& current
|
||||
&& current.name === c.name
|
||||
|
||||
|
@ -136,7 +136,7 @@ $: {
|
|||
|
||||
{#each componentsThisLevel as component}
|
||||
<div class="hierarchy-item component" class:selected={isComponentSelected($store.currentFrontEndType, $store.currentFrontEndItem, component.component)}
|
||||
on:click|stopPropagation={() => store.setCurrentComponent(component.component.name)}>
|
||||
on:click|stopPropagation={() => store.setCurrentScreen(component.component.name)}>
|
||||
<span>{@html getIcon("circle", "7")}</span>
|
||||
<span class="title">{component.title}</span>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
<script>
|
||||
import {
|
||||
isRootComponent
|
||||
} from "./pagesParsing/searchComponents"
|
||||
import { splitName } from "./pagesParsing/splitRootComponentName.js"
|
||||
import { store } from "../builderStore";
|
||||
import {
|
||||
groupBy, keys, find, sortBy
|
||||
} from "lodash/fp";
|
||||
import { pipe } from "../common/core";
|
||||
|
||||
let componentLibraries=[];
|
||||
|
||||
const addRootComponent = (c, all) => {
|
||||
const { libName } = splitName(c.name);
|
||||
let group = find(r => r.libName === libName)(all);
|
||||
|
||||
if(!group) {
|
||||
group = {
|
||||
libName,
|
||||
components: [],
|
||||
generators: []
|
||||
};
|
||||
|
||||
all.push(group);
|
||||
}
|
||||
|
||||
group.components.push(c)
|
||||
|
||||
};
|
||||
|
||||
const onComponentChosen = (component) => {
|
||||
|
||||
};
|
||||
|
||||
store.subscribe(s => {
|
||||
|
||||
const newComponentLibraries = [];
|
||||
|
||||
for(let comp of sortBy(["name"])(s.components)) {
|
||||
addRootComponent(
|
||||
comp,
|
||||
newComponentLibraries);
|
||||
}
|
||||
|
||||
componentLibraries = newComponentLibraries;
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<div class="root">
|
||||
{#each componentLibraries as lib}
|
||||
<div class="library-header">
|
||||
{lib.libName}
|
||||
</div>
|
||||
|
||||
<div class="library-container">
|
||||
|
||||
|
||||
<div class="inner-header">
|
||||
Components
|
||||
</div>
|
||||
|
||||
{#each lib.components as component}
|
||||
|
||||
<div class="component"
|
||||
on:click={() => onComponentChosen(component)}>
|
||||
<div class="name">
|
||||
{splitName(component.name).componentName}
|
||||
</div>
|
||||
<div class="description">
|
||||
{component.description}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/each}
|
||||
|
||||
</div>
|
||||
|
||||
{/each}
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<style>
|
||||
|
||||
.root {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.library-header {
|
||||
font-size: 1.1em;
|
||||
border-color: var(--primary25);
|
||||
border-width: 1px 0px;
|
||||
border-style: solid;
|
||||
background-color: var(--primary10);
|
||||
padding: 5px 0;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.library-container {
|
||||
padding: 0 0 10px 10px;
|
||||
flex: 1 1 auto;
|
||||
min-height: 0px;
|
||||
}
|
||||
|
||||
.inner-header {
|
||||
font-size: 0.9em;
|
||||
font-weight: bold;
|
||||
margin-top: 7px;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
.component {
|
||||
padding: 2px 0px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.component:hover {
|
||||
background-color: var(--lightslate);
|
||||
}
|
||||
|
||||
.component > .name {
|
||||
color: var(--secondary100);
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.component > .description {
|
||||
font-size: 0.8em;
|
||||
color: var(--secondary75);
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
</style>
|
|
@ -0,0 +1,79 @@
|
|||
<script>
|
||||
import EditComponentProps from "./EditComponentProps.svelte";
|
||||
import ComponentsList from "./ComponentsList.svelte";
|
||||
|
||||
let selected="properties";
|
||||
|
||||
const isSelected = tab =>
|
||||
selected === tab;
|
||||
|
||||
const selectTab = tab =>
|
||||
selected = tab;
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<div class="root">
|
||||
|
||||
<div class="switcher">
|
||||
|
||||
<button
|
||||
class:selected={selected==="properties"}
|
||||
on:click={() => selectTab("properties")}>
|
||||
Properties
|
||||
</button>
|
||||
|
||||
<button
|
||||
class:selected={selected==="components"}
|
||||
on:click={() => selectTab("components")}>
|
||||
Components
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
{#if selected==="properties"}
|
||||
<EditComponentProps />
|
||||
{/if}
|
||||
|
||||
{#if selected==="components"}
|
||||
<ComponentsList />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<style>
|
||||
|
||||
.root {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.switcher {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.switcher > button {
|
||||
display: inline-block;
|
||||
background-color: rgba(0,0,0,0);
|
||||
border-style: solid;
|
||||
border-color: var(--slate);
|
||||
margin: 5px;
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.switcher > .selected {
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.panel {
|
||||
flex: 1 1 auto;
|
||||
height: 0px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -24,7 +24,10 @@ store.subscribe(s => {
|
|||
]);
|
||||
appDefinition = {
|
||||
componentLibraries: s.loadLibraryUrls(),
|
||||
props: buildPropsHierarchy(s.allComponents, s.currentFrontEndItem),
|
||||
props: buildPropsHierarchy(
|
||||
s.components,
|
||||
s.screens,
|
||||
s.currentFrontEndItem),
|
||||
hierarchy: s.hierarchy,
|
||||
appRootPath: ""
|
||||
};
|
||||
|
|
|
@ -8,11 +8,10 @@ import Textbox from "../common/Textbox.svelte";
|
|||
import UIkit from "uikit";
|
||||
import { pipe } from "../common/core";
|
||||
import {
|
||||
getComponentInfo
|
||||
getScreenInfo
|
||||
} from "./pagesParsing/createProps";
|
||||
import Button from "../common/Button.svelte";
|
||||
import ButtonGroup from "../common/ButtonGroup.svelte";
|
||||
import ComponentInstanceEditor from "./ComponentInstanceEditor.svelte";
|
||||
|
||||
import {
|
||||
cloneDeep,
|
||||
|
@ -30,17 +29,11 @@ let name = "";
|
|||
let description = "";
|
||||
let tagsString = "";
|
||||
let nameInvalid = "";
|
||||
let componentDetailsExpanded = false;
|
||||
let componentInfo;
|
||||
let modalElement
|
||||
let propsValidationErrors = [];
|
||||
let editingComponentInstance;
|
||||
let editingComponentInstancePropName="";
|
||||
let editingComponentArrayIndex;
|
||||
let editingComponentArrayPropName;
|
||||
let editingComponentInstanceTitle;
|
||||
let originalName="";
|
||||
let allComponents;
|
||||
let components;
|
||||
let ignoreStore = false;
|
||||
|
||||
$: shortName = last(name.split("/"));
|
||||
|
@ -54,8 +47,7 @@ store.subscribe(s => {
|
|||
description = component.description;
|
||||
tagsString = join(", ")(component.tags);
|
||||
componentInfo = s.currentComponentInfo;
|
||||
componentDetailsExpanded = s.currentComponentIsNew;
|
||||
allComponents = s.allComponents;
|
||||
components = s.components;
|
||||
});
|
||||
|
||||
const save = () => {
|
||||
|
@ -73,12 +65,12 @@ const save = () => {
|
|||
map(s => s.trim())
|
||||
]);
|
||||
|
||||
store.saveDerivedComponent(component);
|
||||
store.saveScreen(component);
|
||||
|
||||
ignoreStore = false;
|
||||
// now do the rename
|
||||
if(name !== originalName) {
|
||||
store.renameDerivedComponent(originalName, name);
|
||||
store.renameScreen(originalName, name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,7 +79,7 @@ const deleteComponent = () => {
|
|||
}
|
||||
|
||||
const confirmDeleteComponent = () => {
|
||||
store.deleteDerivedComponent(component.name);
|
||||
store.deleteScreen(component.name);
|
||||
hideDialog();
|
||||
}
|
||||
|
||||
|
@ -99,7 +91,7 @@ const updateComponent = doChange => {
|
|||
const newComponent = cloneDeep(component);
|
||||
doChange(newComponent);
|
||||
component = newComponent;
|
||||
componentInfo = getComponentInfo(allComponents, newComponent);
|
||||
componentInfo = getScreenInfo(components, newComponent);
|
||||
}
|
||||
|
||||
const onPropsChanged = newProps => {
|
||||
|
@ -128,37 +120,6 @@ const showDialog = () => {
|
|||
UIkit.modal(modalElement).show();
|
||||
}
|
||||
|
||||
const onEditComponentProp = (propName, arrayIndex, arrayPropName) => {
|
||||
|
||||
editingComponentInstance = isUndefined(arrayIndex)
|
||||
? component.props[propName]
|
||||
: component.props[propName][arrayIndex][arrayPropName];
|
||||
editingComponentInstancePropName = propName;
|
||||
editingComponentInstanceTitle = isUndefined(arrayIndex)
|
||||
? propName
|
||||
: `${propName}[${arrayIndex}].${arrayPropName}`;
|
||||
|
||||
editingComponentArrayIndex = arrayIndex;
|
||||
editingComponentArrayPropName = arrayPropName;
|
||||
}
|
||||
|
||||
const componentInstanceCancelEdit = () => {
|
||||
editingComponentInstance = null;
|
||||
editingComponentInstancePropName = "";
|
||||
}
|
||||
|
||||
const componentInstancePropsChanged = (instanceProps) => {
|
||||
updateComponent(newComponent => {
|
||||
if(isUndefined(editingComponentArrayIndex)) {
|
||||
newComponent.props[editingComponentInstancePropName] = instanceProps;
|
||||
} else {
|
||||
newComponent.props[editingComponentInstancePropName]
|
||||
[editingComponentArrayIndex]
|
||||
[editingComponentArrayPropName] = instanceProps;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<div class="root">
|
||||
|
@ -177,53 +138,15 @@ const componentInstancePropsChanged = (instanceProps) => {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{#if editingComponentInstance}
|
||||
<div class="component-props-container">
|
||||
<ComponentInstanceEditor onGoBack={componentInstanceCancelEdit}
|
||||
title={editingComponentInstanceTitle}
|
||||
instanceProps={editingComponentInstance}
|
||||
onPropsChanged={componentInstancePropsChanged}/>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="component-props-container">
|
||||
|
||||
<div class="section-header padding" on:click={() => componentDetailsExpanded = !componentDetailsExpanded}>
|
||||
<span style="margin-right: 7px">Component Details</span>
|
||||
<IconButton icon={componentDetailsExpanded ? "chevron-down" : "chevron-right"}/>
|
||||
</div>
|
||||
|
||||
{#if componentDetailsExpanded}
|
||||
<div class="padding">
|
||||
<div class="info-text">
|
||||
<Textbox label="Name"
|
||||
infoText="use forward slash to store in subfolders"
|
||||
text={name}
|
||||
on:change={ev => name = ev.target.value}
|
||||
hasError={!!nameInvalid}/>
|
||||
<Textbox label="Description"
|
||||
on:change={ev => description = ev.target.value}
|
||||
text={description}/>
|
||||
<Textbox label="Tags"
|
||||
infoText="comma separated"
|
||||
on:change={ev => tagsString = ev.target.value}
|
||||
text={tagsString}/>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="section-header padding">
|
||||
<span>Properties</span>
|
||||
</div>
|
||||
|
||||
|
||||
<PropsView onValidate={onPropsValidate}
|
||||
{componentInfo}
|
||||
{onPropsChanged}
|
||||
{onEditComponentProp}/>
|
||||
{onPropsChanged} />
|
||||
|
||||
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -263,20 +186,13 @@ const componentInstancePropsChanged = (instanceProps) => {
|
|||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.padding {
|
||||
padding: 1rem 1rem 0rem 1rem;
|
||||
}
|
||||
|
||||
.info-text {
|
||||
color: var(--secondary100);
|
||||
font-size: .8rem !important;
|
||||
font-weight: bold;
|
||||
border-style: solid;
|
||||
border-width: 1px 0 0 0;
|
||||
border-color: var(--slate);
|
||||
}
|
||||
|
||||
.title {
|
||||
padding: 2rem 1rem 1rem 1rem;
|
||||
padding: 1rem;
|
||||
display: grid;
|
||||
grid-template-columns: [name] 1fr [actions] auto;
|
||||
color: var(--secondary100);
|
||||
|
@ -293,15 +209,6 @@ const componentInstancePropsChanged = (instanceProps) => {
|
|||
grid-column-start: actions;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: grid;
|
||||
grid-template-columns: [name] 1fr [actions] auto;
|
||||
color: var(--secondary50);
|
||||
font-size: .9rem;
|
||||
font-weight: bold;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.component-props-container {
|
||||
flex: 1 1 auto;
|
||||
overflow-y: auto;
|
|
@ -1,161 +0,0 @@
|
|||
<script>
|
||||
import { store } from "../builderStore";
|
||||
import { splitName } from "./pagesParsing/splitRootComponentName";
|
||||
import {
|
||||
getIndexNodes, getRecordNodes, getIndexSchema, pipe
|
||||
} from "../common/core";
|
||||
import {
|
||||
map, some, filter
|
||||
} from "lodash/fp";
|
||||
import Button from "../common/Button.svelte";
|
||||
import { componentDependencies } from "./pagesParsing/findDependencies";
|
||||
import { rename } from "./pagesParsing/renameComponent";
|
||||
import { getExactComponent } from "./pagesParsing/searchComponents";
|
||||
export let generator;
|
||||
export let onConfirmGenerate;
|
||||
|
||||
let libName;
|
||||
let componentName;
|
||||
let libs;
|
||||
let existingComponents;
|
||||
let _generator;
|
||||
let components;
|
||||
let generateParameter;
|
||||
let allGeneratedComponents;
|
||||
let selectedComponents = [];
|
||||
|
||||
store.subscribe(s => {
|
||||
libs = s.generatorLibraries;
|
||||
generateParameter = {
|
||||
indexes: getIndexNodes(s.hierarchy),
|
||||
records: getRecordNodes(s.hierarchy),
|
||||
helpers: {
|
||||
indexSchema: getIndexSchema(s.hierarchy)
|
||||
}
|
||||
}
|
||||
existingComponents = s.allComponents;
|
||||
});
|
||||
|
||||
const componentExists = name =>
|
||||
getExactComponent(existingComponents, name);
|
||||
|
||||
const componentsWithDependencies = () => {
|
||||
|
||||
const cmp = map(c => {
|
||||
const dependants = componentDependencies(
|
||||
{}, [...selectedComponents, ...existingComponents], c);
|
||||
const exists = componentExists(c.name);
|
||||
return {
|
||||
dependants: dependants.dependantComponents,
|
||||
component:c,
|
||||
error: exists ? "a component by this name already exists" : ""
|
||||
};
|
||||
})(allGeneratedComponents);
|
||||
components = cmp;
|
||||
}
|
||||
|
||||
$ : {
|
||||
if(generator && generator !== _generator) {
|
||||
_generator = generator;
|
||||
|
||||
const sp = splitName(generator.name);
|
||||
libName = sp.libName;
|
||||
componentName = sp.componentName;
|
||||
|
||||
allGeneratedComponents = libs[libName][componentName](generateParameter);
|
||||
selectedComponents =
|
||||
filter(c => !componentExists(c.name))(allGeneratedComponents);
|
||||
componentsWithDependencies();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const onSelectedChanged = component => ev => {
|
||||
const newselectedComponents = filter(c => c.name !== component.component.name)(
|
||||
selectedComponents);
|
||||
if(ev.target.checked) {
|
||||
newselectedComponents.push(component.component);
|
||||
}
|
||||
|
||||
selectedComponents = newselectedComponents;
|
||||
componentsWithDependencies();
|
||||
}
|
||||
|
||||
const onNameChanged = component => ev => {
|
||||
const newname = ev.target.value;
|
||||
const oldname = component.component.name;
|
||||
const result = rename({}, allGeneratedComponents, oldname, newname);
|
||||
component.error = result.error || "";
|
||||
allGeneratedComponents = [...result.allComponents];
|
||||
selectedComponents = map(s => {
|
||||
if(s.name === oldname) s.name = newname;
|
||||
return s;
|
||||
})(selectedComponents);
|
||||
componentsWithDependencies();
|
||||
}
|
||||
|
||||
const isComponentSelected = component =>
|
||||
some(c => c.name === component.component.name)(selectedComponents);
|
||||
|
||||
</script>
|
||||
|
||||
{#each components as c}
|
||||
|
||||
<div class="component">
|
||||
|
||||
<div class="uk-inline">
|
||||
<input type="checkbox"
|
||||
disabled={c.dependants.length > 0}
|
||||
class="uk-checkbox"
|
||||
checked={isComponentSelected(c)}
|
||||
on:change={onSelectedChanged(c)}>
|
||||
<input type="text"
|
||||
value={c.component.name}
|
||||
on:change={onNameChanged(c)}
|
||||
class="uk-input title {c.error ? 'uk-form-danger' : ''}">
|
||||
{#if isComponentSelected(c)}
|
||||
<span class="error">{c.error}</span>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="description">
|
||||
{c.component.description}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/each}
|
||||
|
||||
<div class="button-container">
|
||||
<Button on:click={() => onConfirmGenerate(selectedComponents)}>Add Components</Button>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<style>
|
||||
|
||||
.component {
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.component .title {
|
||||
width: 300px
|
||||
}
|
||||
|
||||
.component > .description {
|
||||
font-size: 0.8em;
|
||||
color: var(--secondary75);
|
||||
}
|
||||
|
||||
.button-container {
|
||||
text-align: right;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.error {
|
||||
font-size: 10pt;
|
||||
color: red;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -8,100 +8,126 @@ import Button from "../common/Button.svelte";
|
|||
import ButtonGroup from "../common/ButtonGroup.svelte";
|
||||
import { pipe } from "../common/core";
|
||||
import UIkit from "uikit";
|
||||
import {
|
||||
getNewComponentInfo
|
||||
} from "./pagesParsing/createProps";
|
||||
import { isRootComponent } from "./pagesParsing/searchComponents";
|
||||
import GeneratedComponents from "./GeneratedComponents.svelte";
|
||||
import { splitName } from "./pagesParsing/splitRootComponentName.js"
|
||||
|
||||
import {
|
||||
cloneDeep,
|
||||
join,
|
||||
split,
|
||||
map,
|
||||
keys,
|
||||
isUndefined
|
||||
find, filter, some, map, includes
|
||||
} from "lodash/fp";
|
||||
import { assign } from "lodash";
|
||||
|
||||
|
||||
|
||||
let componentSelectorModal;
|
||||
let generatorOptionsModal;
|
||||
let allComponents;
|
||||
let generator;
|
||||
|
||||
store.subscribe(s => {
|
||||
allComponents = s.allComponents;
|
||||
})
|
||||
|
||||
export const close = () => {
|
||||
UIkit.modal(componentSelectorModal).hide();
|
||||
if(generatorOptionsModal) UIkit.modal(generatorOptionsModal).hide();
|
||||
generator = null;
|
||||
}
|
||||
|
||||
export const show = () => {
|
||||
UIkit.modal(componentSelectorModal).show();
|
||||
}
|
||||
|
||||
const onComponentChosen = (c) => {
|
||||
store.createDerivedComponent(c.name);
|
||||
close();
|
||||
}
|
||||
let componentSelectorModal;
|
||||
let layoutComponents;
|
||||
let layoutComponent;
|
||||
let screens;
|
||||
let name="";
|
||||
let saveAttempted=false;
|
||||
|
||||
const onGeneratorChosen = (g) => {
|
||||
generator = g;
|
||||
store.subscribe(s => {
|
||||
|
||||
layoutComponents = pipe(s.components, [
|
||||
filter(c => includes("layout")(c.tags)),
|
||||
map(c => ({name:c.name, ...splitName(c.name)}))
|
||||
]);
|
||||
|
||||
layoutComponent = layoutComponent
|
||||
? find(c => c.name === layoutComponent.name)(layoutComponents)
|
||||
: layoutComponents[0];
|
||||
|
||||
screens = s.screens;
|
||||
});
|
||||
|
||||
const save = () => {
|
||||
saveAttempted = true;
|
||||
|
||||
const isValid = name.length > 0
|
||||
&& !screenNameExists(name)
|
||||
&& layoutComponent;
|
||||
|
||||
if(!isValid) return;
|
||||
|
||||
store.createScreen(name, layoutComponent.name);
|
||||
UIkit.modal(componentSelectorModal).hide();
|
||||
UIkit.modal(generatorOptionsModal).show();
|
||||
}
|
||||
|
||||
const onConfirmGenerate = (components) => {
|
||||
store.createGeneratedComponents(components);
|
||||
UIkit.modal(generatorOptionsModal).hide();
|
||||
generator = null;
|
||||
const cancel = () => {
|
||||
UIkit.modal(componentSelectorModal).hide();
|
||||
}
|
||||
|
||||
const screenNameExists = (name) =>
|
||||
some(s => s.name.toLowerCase() === name.toLowerCase())(screens)
|
||||
|
||||
</script>
|
||||
|
||||
<div bind:this={componentSelectorModal} id="new-component-modal" uk-modal>
|
||||
<div class="uk-modal-dialog" uk-overflow-auto>
|
||||
|
||||
<div class="uk-modal-header">
|
||||
<h1>New Component</h1>
|
||||
<h1>New Screen</h1>
|
||||
</div>
|
||||
|
||||
<div class="uk-modal-body">
|
||||
<ComponentSelector onComponentChosen={onComponentChosen}
|
||||
onGeneratorChosen={onGeneratorChosen}
|
||||
allowGenerators={true} />
|
||||
<div class="uk-modal-body uk-form-horizontal">
|
||||
<div class="uk-margin">
|
||||
<label class="uk-form-label">Name</label>
|
||||
<div class="uk-form-controls">
|
||||
<input class="uk-input uk-form-small"
|
||||
class:uk-form-danger={saveAttempted && (name.length === 0 || screenNameExists(name))}
|
||||
bind:value={name} >
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="uk-margin">
|
||||
<label class="uk-form-label">Layout Component</label>
|
||||
<div class="uk-form-controls">
|
||||
<select class="uk-select uk-form-small"
|
||||
bind:value={layoutComponent}
|
||||
class:uk-form-danger={saveAttempted && !layoutComponent}>
|
||||
{#each layoutComponents as comp}
|
||||
<option value={comp}>
|
||||
{comp.componentName} - {comp.libName}
|
||||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ButtonGroup style="float: right;">
|
||||
<Button color="primary" grouped on:click={save}>Create Screen</Button>
|
||||
<Button color="tertiary" grouped on:click={cancel}>Cancel</Button>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div bind:this={generatorOptionsModal} uk-modal>
|
||||
<div class="uk-modal-dialog" uk-overflow-auto>
|
||||
|
||||
{#if generator}
|
||||
|
||||
<div class="uk-modal-header">
|
||||
<h1>Generator - {generator ? generator.name : ""}</h1>
|
||||
</div>
|
||||
|
||||
<div class="uk-modal-body">
|
||||
<GeneratedComponents generator={generator}
|
||||
onConfirmGenerate={onConfirmGenerate} />
|
||||
</div>
|
||||
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<style>
|
||||
h1 {
|
||||
font-size:1.2em;
|
||||
}
|
||||
|
||||
.component-option {
|
||||
border-style: solid;
|
||||
border-color: var(--slate);
|
||||
border-width: 0 0 1px 0;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.component-option:hover {
|
||||
background-color: var(--lightslate);
|
||||
}
|
||||
|
||||
.component-name {
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
.lib-name {
|
||||
font-size: 9pt;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -20,7 +20,7 @@ store.subscribe(s => {
|
|||
page = s.pages[s.currentPageName];
|
||||
if(!page) return;
|
||||
title = page.index.title;
|
||||
components = pipe(s.allComponents, [
|
||||
components = pipe(s.components, [
|
||||
filter(s => !isRootComponent(s)),
|
||||
concat([notSeletedComponent])
|
||||
]);
|
||||
|
|
|
@ -1,120 +0,0 @@
|
|||
<script>
|
||||
import IconButton from "../common/IconButton.svelte";
|
||||
import {
|
||||
createArrayElementProps
|
||||
} from "./pagesParsing/createProps";
|
||||
import PropControl from "./PropControl.svelte";
|
||||
import {
|
||||
some,
|
||||
cloneDeep,
|
||||
} from "lodash/fp";
|
||||
import { validateProps } from "./pagesParsing/validateProps";
|
||||
|
||||
export let parentProps;
|
||||
export let propDef;
|
||||
export let onValueChanged;
|
||||
export let onValidate = () => {};
|
||||
export let onEditComponentProp = () => {};
|
||||
|
||||
let value = [];
|
||||
let elementDefinitionArray;
|
||||
let elementErrors = {};
|
||||
|
||||
$: {
|
||||
const elArray = [];
|
||||
for(let elProp in propDef.elementDefinition) {
|
||||
if(elProp === "_component") continue;
|
||||
elArray.push({
|
||||
...propDef.elementDefinition[elProp],
|
||||
____name: elProp
|
||||
});
|
||||
}
|
||||
elementDefinitionArray = elArray;
|
||||
value = parentProps[propDef.____name];
|
||||
}
|
||||
|
||||
const addElement = () => {
|
||||
const newElement = createArrayElementProps(
|
||||
propDef.____name,
|
||||
propDef.elementDefinition).props;
|
||||
|
||||
value = [...value, newElement];
|
||||
onValueChanged(value);
|
||||
}
|
||||
|
||||
const validate = (index, elementProps) => {
|
||||
elementErrors[index] = validateProps(
|
||||
propDef.elementDefinition, elementProps, [], true);
|
||||
onValidate(elementErrors[index]);
|
||||
return elementErrors[index].length === 0;
|
||||
}
|
||||
|
||||
const setProp = (index) => (name, propValue) => {
|
||||
const newValue = cloneDeep(value);
|
||||
const newProps = cloneDeep(newValue[index]);
|
||||
newProps[name] = propValue;
|
||||
newValue[index] = newProps;
|
||||
value = newValue;
|
||||
|
||||
if(validate(index, newProps))
|
||||
onValueChanged(newValue);
|
||||
|
||||
}
|
||||
|
||||
let fieldHasError = index => propName =>
|
||||
some(e => e.propName === propName)(elementErrors[index]);
|
||||
|
||||
const onEditComponent = (index, propName) => () => {
|
||||
onEditComponentProp(index, propName);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<div class="root">
|
||||
|
||||
|
||||
<div class="item-container">
|
||||
{#each value as item, index}
|
||||
|
||||
<div class="item-inner-container">
|
||||
{#each elementDefinitionArray as propDef}
|
||||
<PropControl setProp={setProp(index)}
|
||||
fieldHasError={fieldHasError(index)}
|
||||
{propDef}
|
||||
props={item}
|
||||
{index}
|
||||
onEditComponent={onEditComponent(index, propDef.____name)}
|
||||
disabled={false} />
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
{/each}
|
||||
|
||||
<div class="addelement-container"
|
||||
on:click={addElement}>
|
||||
<IconButton icon="plus"
|
||||
size="12"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<style>
|
||||
|
||||
.addelement-container {
|
||||
cursor: pointer;
|
||||
padding: 3px 0px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.addelement-container:hover {
|
||||
background-color: var(--primary25);
|
||||
}
|
||||
|
||||
|
||||
.item-container {
|
||||
padding-left: 3px;
|
||||
background: var(--secondary10);
|
||||
}
|
||||
|
||||
</style>
|
|
@ -3,8 +3,6 @@
|
|||
import Checkbox from "../common/Checkbox.svelte";
|
||||
import Textbox from "../common/Textbox.svelte";
|
||||
import Dropdown from "../common/Dropdown.svelte";
|
||||
import ComponentPropSelector from "./ComponentPropSelector.svelte";
|
||||
import PropArraySelector from "./PropArraySelector.svelte";
|
||||
import EventListSelector from "./EventListSelector.svelte";
|
||||
import StateBindingControl from "./StateBindingControl.svelte";
|
||||
|
||||
|
@ -15,7 +13,6 @@ export let propDef = {};
|
|||
export let props = {};
|
||||
export let disabled;
|
||||
export let index;
|
||||
export let onEditComponent = () => {};
|
||||
|
||||
$: isOdd = (index % 2 !== 0);
|
||||
|
||||
|
@ -28,32 +25,14 @@ const setComponentProp = (props) => {
|
|||
|
||||
<div class="root" >
|
||||
|
||||
{#if propDef.type === "component"}
|
||||
|
||||
<div class="prop-label">{propDef.____name}</div>
|
||||
<ComponentPropSelector label={propDef.____name}
|
||||
props={props[propDef.____name]}
|
||||
{disabled}
|
||||
onEdit={onEditComponent}
|
||||
onComponentChosen={onEditComponent}
|
||||
onValueChanged={setComponentProp}/>
|
||||
|
||||
{:else if propDef.type === "array"}
|
||||
|
||||
<div class="prop-label">{propDef.____name}</div>
|
||||
<PropArraySelector parentProps={props}
|
||||
{propDef}
|
||||
onValueChanged={setComponentProp}
|
||||
onEditComponentProp={onEditComponent} />
|
||||
|
||||
{:else if propDef.type === "event"}
|
||||
{#if propDef.type === "event"}
|
||||
|
||||
<div class="prop-label">{propDef.____name}</div>
|
||||
<EventListSelector parentProps={props}
|
||||
{propDef}
|
||||
onValueChanged={setComponentProp} />
|
||||
|
||||
{:else}
|
||||
{:else }
|
||||
|
||||
<div class="prop-label">{propDef.____name}</div>
|
||||
<StateBindingControl value={props[propDef.____name]}
|
||||
|
|
|
@ -1,27 +1,16 @@
|
|||
<script>
|
||||
|
||||
import {
|
||||
keys,
|
||||
map,
|
||||
some,
|
||||
includes,
|
||||
cloneDeep,
|
||||
isEqual,
|
||||
sortBy,
|
||||
filter,
|
||||
difference
|
||||
keys, map, some, includes,
|
||||
cloneDeep, isEqual, sortBy,
|
||||
filter, difference
|
||||
} from "lodash/fp";
|
||||
import { pipe } from "../common/core";
|
||||
import {
|
||||
getComponentInfo ,
|
||||
getInstanceProps
|
||||
} from "./pagesParsing/createProps";
|
||||
import { getExactComponent } from "./pagesParsing/searchComponents";
|
||||
import { getInstanceProps } from "./pagesParsing/createProps";
|
||||
import Checkbox from "../common/Checkbox.svelte";
|
||||
import Textbox from "../common/Textbox.svelte";
|
||||
import Dropdown from "../common/Dropdown.svelte";
|
||||
import { validateProps } from "./pagesParsing/validateProps";
|
||||
import ComponentPropSelector from "./ComponentPropSelector.svelte";
|
||||
import PropControl from "./PropControl.svelte";
|
||||
import IconButton from "../common/IconButton.svelte";
|
||||
|
||||
|
@ -30,17 +19,12 @@ export let onValidate = () => {};
|
|||
export let componentInfo;
|
||||
export let instanceProps = null;
|
||||
export let onPropsChanged = () => {};
|
||||
export let onEditComponentProp = () => {};
|
||||
|
||||
let errors = [];
|
||||
let props = {};
|
||||
let propsDefinitions = [];
|
||||
let inheritedPropsDefinitions = [];
|
||||
let inheritedExpanded = false;
|
||||
let isInstance = false;
|
||||
|
||||
const isPropInherited = name =>
|
||||
includes(name)(componentInfo.inheritedProps);
|
||||
|
||||
$: {
|
||||
if(componentInfo)
|
||||
|
@ -52,14 +36,6 @@ $: {
|
|||
|
||||
propsDefinitions = pipe(componentInfo.propsDefinition, [
|
||||
keys,
|
||||
filter(k => !isPropInherited(k)),
|
||||
map(k => ({...componentInfo.propsDefinition[k], ____name:k})),
|
||||
sortBy("____name")
|
||||
]);
|
||||
|
||||
inheritedPropsDefinitions = pipe(componentInfo.propsDefinition, [
|
||||
keys,
|
||||
filter(k => isPropInherited(k)),
|
||||
map(k => ({...componentInfo.propsDefinition[k], ____name:k})),
|
||||
sortBy("____name")
|
||||
]);
|
||||
|
@ -92,7 +68,7 @@ let setProp = (name, value) => {
|
|||
}
|
||||
|
||||
const validate = (finalProps) => {
|
||||
errors = validateProps(componentInfo.propsDefinition, finalProps, [], false);
|
||||
errors = validateProps(componentInfo.rootComponent, finalProps, [], false);
|
||||
onValidate(errors);
|
||||
return errors.length === 0;
|
||||
}
|
||||
|
@ -100,49 +76,26 @@ const validate = (finalProps) => {
|
|||
const fieldHasError = (propName) =>
|
||||
some(e => e.propName === propName)(errors);
|
||||
|
||||
const onEditComponent = (propName) => (arrayIndex, arrayPropName) => {
|
||||
onEditComponentProp(propName, arrayIndex, arrayPropName);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<div class="root">
|
||||
|
||||
<form class="uk-form-stacked">
|
||||
<form class="uk-form-stacked form-root">
|
||||
{#each propsDefinitions as propDef, index}
|
||||
|
||||
<div class="prop-container">
|
||||
|
||||
<PropControl {setProp}
|
||||
{fieldHasError}
|
||||
{propDef}
|
||||
{props}
|
||||
{index}
|
||||
onEditComponent={onEditComponent(propDef.____name)}
|
||||
disabled={false} />
|
||||
|
||||
</div>
|
||||
|
||||
{/each}
|
||||
|
||||
{#if inheritedPropsDefinitions.length > 0}
|
||||
<div class="inherited-title padding">
|
||||
<div>Inherited</div>
|
||||
<div>
|
||||
<IconButton icon={inheritedExpanded ? "chevron-down" : "chevron-right"}
|
||||
on:click={() => inheritedExpanded = !inheritedExpanded}/>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if inheritedExpanded}
|
||||
{#each inheritedPropsDefinitions as propDef, index}
|
||||
|
||||
<PropControl {setProp}
|
||||
{fieldHasError}
|
||||
{propDef}
|
||||
{props}
|
||||
{index}
|
||||
disabled={true} />
|
||||
|
||||
{/each}
|
||||
{/if}
|
||||
</form>
|
||||
|
||||
|
||||
|
@ -155,29 +108,17 @@ const onEditComponent = (propName) => (arrayIndex, arrayPropName) => {
|
|||
|
||||
.root {
|
||||
font-size:10pt;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.padding {
|
||||
padding: 0 10px;
|
||||
.form-root {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.inherited-title {
|
||||
padding: 1rem 1rem 1rem 1rem;
|
||||
display: grid;
|
||||
grid-template-columns: [name] 1fr [actions] auto;
|
||||
color: var(--secondary100);
|
||||
font-size: .9rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.inherited-title > div:nth-child(1) {
|
||||
grid-column-start: name;
|
||||
color: var(--secondary50);
|
||||
}
|
||||
|
||||
.inherited-title > div:nth-child(2) {
|
||||
grid-column-start: actions;
|
||||
color: var(--secondary100);
|
||||
.prop-container {
|
||||
flex: 1 1 auto;
|
||||
min-width: 250px;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -11,14 +11,14 @@ let addNewLib = "";
|
|||
let addNewStylesheet = "";
|
||||
let addComponentError = "";
|
||||
let modalElement;
|
||||
let allComponents;
|
||||
let components;
|
||||
|
||||
store.subscribe(s => {
|
||||
allComponents = s.allComponents;
|
||||
components = s.components;
|
||||
})
|
||||
|
||||
const removeLibrary = lib => {
|
||||
const dependencies = libraryDependencies(allComponents, lib);
|
||||
const dependencies = libraryDependencies(components, lib);
|
||||
if(dependencies.length > 0) return;
|
||||
store.removeComponentLibrary(lib);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
import ComponentsHierarchy from "./ComponentsHierarchy.svelte";
|
||||
import PagesList from "./PagesList.svelte"
|
||||
import EditComponent from "./EditComponent.svelte";
|
||||
import { store } from "../builderStore";
|
||||
import getIcon from "../common/icon";
|
||||
import { isComponent } from "./pagesParsing/searchComponents";
|
||||
|
@ -12,6 +11,7 @@ import NewComponent from "./NewComponent.svelte";
|
|||
import CurrentItemPreview from "./CurrentItemPreview.svelte";
|
||||
import SettingsView from "./SettingsView.svelte";
|
||||
import PageView from "./PageView.svelte";
|
||||
import ComponentsPaneSwitcher from "./ComponentsPaneSwitcher.svelte";
|
||||
|
||||
let newComponentPicker;
|
||||
const newComponent = () => {
|
||||
|
@ -32,7 +32,7 @@ const settings = () => {
|
|||
<div class="components-list-container">
|
||||
<div class="nav-group-header">
|
||||
<div>{@html getIcon("sidebar","18")}</div>
|
||||
<span class="components-nav-header">Components</span>
|
||||
<span class="components-nav-header">Screens</span>
|
||||
<div>
|
||||
<IconButton icon="settings"
|
||||
size="14px"
|
||||
|
@ -42,7 +42,7 @@ const settings = () => {
|
|||
</div>
|
||||
</div>
|
||||
<div class="nav-items-container">
|
||||
<ComponentsHierarchy components={$store.derivedComponents}/>
|
||||
<ComponentsHierarchy components={$store.screens}/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -58,17 +58,17 @@ const settings = () => {
|
|||
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{#if $store.currentFrontEndType === "component"}
|
||||
<div class="preview-pane">
|
||||
{#if $store.currentFrontEndType === "screen"}
|
||||
<CurrentItemPreview />
|
||||
{:else if $store.currentFrontEndType === "page"}
|
||||
<PageView />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if $store.currentFrontEndType === "component"}
|
||||
<div class="properties-pane">
|
||||
<EditComponent />
|
||||
{#if $store.currentFrontEndType === "screen"}
|
||||
<div class="components-pane">
|
||||
<ComponentsPaneSwitcher />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
|
@ -83,22 +83,25 @@ const settings = () => {
|
|||
|
||||
.root {
|
||||
display: grid;
|
||||
grid-template-columns: [uiNav] 250px [preview] auto [properties] 300px;
|
||||
grid-template-columns: 250px 1fr 300px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.ui-nav {
|
||||
grid-column-start: uiNav;
|
||||
grid-column: 1;
|
||||
background-color: var(--secondary5);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.properties-pane {
|
||||
grid-column-start: properties;
|
||||
.preview-pane {
|
||||
grid-column: 2;
|
||||
}
|
||||
|
||||
.components-pane {
|
||||
grid-column: 3;
|
||||
background-color: var(--secondary5);
|
||||
height: 100%;
|
||||
min-height: 0px;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,50 +2,46 @@ import {
|
|||
getComponentInfo, createProps, getInstanceProps
|
||||
} from "./createProps";
|
||||
|
||||
export const buildPropsHierarchy = (allComponents, baseComponent) => {
|
||||
export const buildPropsHierarchy = (components, screens, baseComponent) => {
|
||||
|
||||
const buildProps = (componentName, propsDefinition, derivedFromProps) => {
|
||||
const allComponents = [...components, ...screens];
|
||||
|
||||
const {props} = createProps(componentName, propsDefinition, derivedFromProps);
|
||||
props._component = componentName;
|
||||
const buildProps = (componentDefinition, derivedFromProps) => {
|
||||
|
||||
const {props} = createProps(componentDefinition, derivedFromProps);
|
||||
const propsDefinition = componentDefinition.props;
|
||||
props._component = componentDefinition.name;
|
||||
for(let propName in props) {
|
||||
if(propName === "_component") continue;
|
||||
|
||||
const propDef = propsDefinition[propName];
|
||||
if(!propDef) continue;
|
||||
if(propDef.type === "component") {
|
||||
if(propName === "_children") {
|
||||
|
||||
const subComponentProps = props[propName];
|
||||
const childrenProps = props[propName];
|
||||
|
||||
if(!subComponentProps._component) continue;
|
||||
if(!childrenProps
|
||||
|| childrenProps.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
props[propName] = [];
|
||||
|
||||
for(let child of childrenProps) {
|
||||
const propComponentInfo = getComponentInfo(
|
||||
allComponents, subComponentProps._component);
|
||||
allComponents, child._component);
|
||||
|
||||
const subComponentInstanceProps = getInstanceProps(
|
||||
propComponentInfo,
|
||||
subComponentProps
|
||||
child
|
||||
);
|
||||
|
||||
props[propName] = buildProps(
|
||||
props[propName].push(
|
||||
buildProps(
|
||||
propComponentInfo.rootComponent.name,
|
||||
propComponentInfo.propsDefinition,
|
||||
subComponentInstanceProps);
|
||||
|
||||
} else if(propDef.type === "array") {
|
||||
const propsArray = props[propName];
|
||||
const newPropsArray = [];
|
||||
let index = 0;
|
||||
for(let element of propsArray) {
|
||||
newPropsArray.push(
|
||||
buildProps(
|
||||
`${propName}#array_element#`,
|
||||
propDef.elementDefinition,
|
||||
element));
|
||||
index++;
|
||||
subComponentInstanceProps));
|
||||
}
|
||||
|
||||
props[propName] = newPropsArray;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,8 +54,7 @@ export const buildPropsHierarchy = (allComponents, baseComponent) => {
|
|||
const baseComponentInfo = getComponentInfo(allComponents, baseComponent);
|
||||
|
||||
return buildProps(
|
||||
baseComponentInfo.rootComponent.name,
|
||||
baseComponentInfo.propsDefinition,
|
||||
baseComponentInfo.rootComponent,
|
||||
baseComponentInfo.fullProps);
|
||||
|
||||
}
|
|
@ -1,44 +1,12 @@
|
|||
import {
|
||||
isString,
|
||||
isUndefined,
|
||||
find,
|
||||
keys,
|
||||
uniq,
|
||||
some,
|
||||
filter,
|
||||
reduce,
|
||||
cloneDeep,
|
||||
includes,
|
||||
last
|
||||
isString, isUndefined, find, keys, uniq,
|
||||
some, filter, reduce, cloneDeep, includes,last
|
||||
} from "lodash/fp";
|
||||
import { types, expandPropsDefinition } from "./types";
|
||||
import { types, expandComponentDefinition } from "./types";
|
||||
import { assign } from "lodash";
|
||||
import { pipe } from "../../common/core";
|
||||
import { isRootComponent } from "./searchComponents";
|
||||
|
||||
export const createPropDefinitionForDerived = (allComponents, componentName) => {
|
||||
|
||||
|
||||
const {propDef, derivedProps} = getComponentInfo(allComponents, componentName);
|
||||
|
||||
const hasDerivedProp = k => pipe(derivedProps, [
|
||||
keys,
|
||||
uniq,
|
||||
some(key => key === k)
|
||||
]);
|
||||
|
||||
return pipe(propDef, [
|
||||
keys,
|
||||
filter(k => !hasDerivedProp(k)),
|
||||
reduce((obj, k) => {
|
||||
obj[k] = propDef[k];
|
||||
return obj;
|
||||
}, {}),
|
||||
expandPropsDefinition
|
||||
])
|
||||
}
|
||||
|
||||
export const traverseForProps = getComponentInfo;
|
||||
import { ensureShardNameIsInShardMap } from "../../../../core/src/indexing/sharding";
|
||||
|
||||
export const getInstanceProps = (componentInfo, props) => {
|
||||
const finalProps = cloneDeep(componentInfo.fullProps);
|
||||
|
@ -50,47 +18,44 @@ export const getInstanceProps = (componentInfo, props) => {
|
|||
return finalProps;
|
||||
}
|
||||
|
||||
export const getNewComponentInfo = (allComponents, inherits) => {
|
||||
const parentcomponent = find(c => c.name === inherits)(allComponents);
|
||||
export const getNewComponentInfo = (components, rootComponent, name) => {
|
||||
const component = {
|
||||
name:"",
|
||||
name: name || "",
|
||||
description:"",
|
||||
inherits,
|
||||
props:{},
|
||||
tags:parentcomponent.tags
|
||||
props:{
|
||||
_component: rootComponent
|
||||
}
|
||||
};
|
||||
return getComponentInfo(
|
||||
allComponents,
|
||||
inherits,
|
||||
[component],
|
||||
{});
|
||||
components,
|
||||
component);
|
||||
}
|
||||
|
||||
|
||||
export const getComponentInfo = (allComponents, comp, stack=[], subComponentProps=null) => {
|
||||
const component = isString(comp)
|
||||
? find(c => c.name === comp)(allComponents)
|
||||
export const getScreenInfo = (components, screen) => {
|
||||
return getComponentInfo(
|
||||
components,
|
||||
screen);
|
||||
}
|
||||
|
||||
export const getComponentInfo = (components, comp) => {
|
||||
const targetComponent = isString(comp)
|
||||
? find(c => c.name === comp)(components)
|
||||
: comp;
|
||||
const cname = isString(comp) ? comp : comp.name;
|
||||
if(isRootComponent(component)) {
|
||||
subComponentProps = subComponentProps||{};
|
||||
const p = createProps(cname, component.props, subComponentProps);
|
||||
const rootProps = createProps(cname, component.props);
|
||||
const inheritedProps = [];
|
||||
const targetComponent = stack.length > 0
|
||||
? last(stack)
|
||||
: component;
|
||||
if(stack.length > 0) {
|
||||
|
||||
for(let prop in subComponentProps) {
|
||||
const hasProp = pipe(targetComponent.props, [
|
||||
keys,
|
||||
includes(prop)]);
|
||||
|
||||
if(!hasProp)
|
||||
inheritedProps.push(prop);
|
||||
}
|
||||
let component;
|
||||
let subComponent;
|
||||
if(isRootComponent(targetComponent)) {
|
||||
component = targetComponent;
|
||||
} else {
|
||||
subComponent = targetComponent;
|
||||
component = find(c => c.name === subComponent.props._component)(
|
||||
components);
|
||||
}
|
||||
|
||||
const subComponentProps = subComponent ? subComponent.props : {};
|
||||
const p = createProps(component, subComponentProps);
|
||||
const rootProps = createProps(component);
|
||||
|
||||
const unsetProps = pipe(p.props, [
|
||||
keys,
|
||||
filter(k => !includes(k)(keys(subComponentProps)) && k !== "_component")
|
||||
|
@ -100,8 +65,7 @@ export const getComponentInfo = (allComponents, comp, stack=[], subComponentProp
|
|||
fullProps._component = targetComponent.name;
|
||||
|
||||
return ({
|
||||
propsDefinition:expandPropsDefinition(component.props),
|
||||
inheritedProps,
|
||||
propsDefinition:expandComponentDefinition(component),
|
||||
rootDefaultProps: rootProps.props,
|
||||
unsetProps,
|
||||
fullProps: fullProps,
|
||||
|
@ -109,30 +73,25 @@ export const getComponentInfo = (allComponents, comp, stack=[], subComponentProp
|
|||
component: targetComponent,
|
||||
rootComponent: component
|
||||
});
|
||||
}
|
||||
return getComponentInfo(
|
||||
allComponents,
|
||||
component.inherits,
|
||||
[component, ...stack],
|
||||
{...component.props, ...subComponentProps});
|
||||
}
|
||||
|
||||
export const createProps = (componentName, propsDefinition, derivedFromProps) => {
|
||||
export const createProps = (componentDefinition, derivedFromProps) => {
|
||||
|
||||
const error = (propName, error) =>
|
||||
errors.push({propName, error});
|
||||
|
||||
const props = {
|
||||
_component: componentName
|
||||
_component: componentDefinition.name
|
||||
};
|
||||
|
||||
const errors = [];
|
||||
|
||||
if(!componentName)
|
||||
if(!componentDefinition.name)
|
||||
error("_component", "Component name not supplied");
|
||||
|
||||
for(let propDef in propsDefinition) {
|
||||
const parsedPropDef = parsePropDef(propsDefinition[propDef]);
|
||||
const propsDef = componentDefinition.props;
|
||||
for(let propDef in propsDef) {
|
||||
const parsedPropDef = parsePropDef(propsDef[propDef]);
|
||||
if(parsedPropDef.error)
|
||||
error(propDef, parsedPropDef.error);
|
||||
else
|
||||
|
@ -143,15 +102,16 @@ export const createProps = (componentName, propsDefinition, derivedFromProps) =>
|
|||
assign(props, derivedFromProps);
|
||||
}
|
||||
|
||||
if(componentDefinition.children !== false
|
||||
&& isUndefined(props._children)) {
|
||||
props._children = [];
|
||||
}
|
||||
|
||||
return ({
|
||||
props, errors
|
||||
});
|
||||
}
|
||||
|
||||
export const createArrayElementProps = (arrayPropName, elementDefinition) =>
|
||||
createProps(
|
||||
`#${arrayPropName}#array_element`,
|
||||
elementDefinition);
|
||||
|
||||
const parsePropDef = propDef => {
|
||||
const error = message => ({error:message, propDef});
|
||||
|
|
|
@ -5,7 +5,7 @@ import {
|
|||
} from "lodash/fp";
|
||||
import { isRootComponent } from "./searchComponents";
|
||||
|
||||
export const libraryDependencies = (allComponents, lib) => {
|
||||
export const libraryDependencies = (components, lib) => {
|
||||
|
||||
const componentDependsOnLibrary = comp => {
|
||||
if(isRootComponent(comp)) {
|
||||
|
@ -13,21 +13,24 @@ export const libraryDependencies = (allComponents, lib) => {
|
|||
return (libName === lib);
|
||||
}
|
||||
return componentDependsOnLibrary(
|
||||
find(c => c.name === comp.inherits)(allComponents)
|
||||
find(c => c.name === comp.props._component)(
|
||||
components)
|
||||
);
|
||||
}
|
||||
|
||||
return filter(c => !isRootComponent(c)
|
||||
&& componentDependsOnLibrary(c))(
|
||||
allComponents
|
||||
components
|
||||
);
|
||||
}
|
||||
|
||||
export const componentDependencies = (pages, allComponents, dependsOn) => {
|
||||
export const componentDependencies = (pages, screens, components, dependsOn) => {
|
||||
|
||||
const allComponents = [
|
||||
...cloneDeep(components),
|
||||
...cloneDeep(screens)];
|
||||
|
||||
pages = cloneDeep(pages);
|
||||
allComponents = cloneDeep(allComponents);
|
||||
const dependantComponents = [];
|
||||
const dependantPages = [];
|
||||
|
||||
|
@ -63,7 +66,7 @@ export const componentDependencies = (pages, allComponents, dependsOn) => {
|
|||
continue;
|
||||
}
|
||||
|
||||
if(component.inherits === dependsOn.name) {
|
||||
if(component.props._component === dependsOn.name) {
|
||||
dependantComponents.push(component);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { isRootComponent } from "./searchComponents";
|
||||
import { find } from "lodash/fp";
|
||||
|
||||
export const getRootComponent = (componentName, allComponents) => {
|
||||
const component = find(c => c.name === componentName)(allComponents);
|
||||
export const getRootComponent = (componentName, components) => {
|
||||
const component = find(c => c.name === componentName)(components);
|
||||
|
||||
if(isRootComponent(component)) return component;
|
||||
|
||||
return getRootComponent(component.inherits, allComponents);
|
||||
return getRootComponent(component.props._component, components);
|
||||
}
|
|
@ -2,18 +2,18 @@ import {
|
|||
isPlainObject, isArray, cloneDeep
|
||||
} from "lodash/fp";
|
||||
import {
|
||||
isRootComponent, getExactComponent
|
||||
getExactComponent
|
||||
} from "./searchComponents";
|
||||
|
||||
export const rename = (pages, allComponents, oldname, newname) => {
|
||||
export const rename = (pages, screens, oldname, newname) => {
|
||||
|
||||
pages = cloneDeep(pages);
|
||||
allComponents = cloneDeep(allComponents);
|
||||
const changedComponents = [];
|
||||
screens = cloneDeep(screens);
|
||||
const changedScreens = [];
|
||||
|
||||
const existingWithNewName = getExactComponent(allComponents, newname);
|
||||
const existingWithNewName = getExactComponent(screens, newname);
|
||||
if(existingWithNewName) return {
|
||||
allComponents, pages, error: "Component by that name already exists"
|
||||
components: screens, pages, error: "Component by that name already exists"
|
||||
};
|
||||
|
||||
const traverseProps = (props) => {
|
||||
|
@ -38,28 +38,24 @@ export const rename = (pages, allComponents, oldname, newname) => {
|
|||
}
|
||||
|
||||
|
||||
for(let component of allComponents) {
|
||||
|
||||
if(isRootComponent(component)) {
|
||||
continue;
|
||||
}
|
||||
for(let screen of screens) {
|
||||
|
||||
let hasEdited = false;
|
||||
|
||||
if(component.name === oldname) {
|
||||
component.name = newname;
|
||||
if(screen.name === oldname) {
|
||||
screen.name = newname;
|
||||
hasEdited = true;
|
||||
}
|
||||
|
||||
if(component.inherits === oldname) {
|
||||
component.inherits = newname;
|
||||
if(screen.props._component === oldname) {
|
||||
screen.props._component = newname;
|
||||
hasEdited = true;
|
||||
}
|
||||
|
||||
hasEdited = traverseProps(component.props) || hasEdited;
|
||||
hasEdited = traverseProps(screen.props) || hasEdited;
|
||||
|
||||
if(hasEdited && component.name !== newname)
|
||||
changedComponents.push(component.name);
|
||||
if(hasEdited && screen.name !== newname)
|
||||
changedScreens.push(screen.name);
|
||||
}
|
||||
|
||||
for(let pageName in pages) {
|
||||
|
@ -69,7 +65,7 @@ export const rename = (pages, allComponents, oldname, newname) => {
|
|||
}
|
||||
}
|
||||
|
||||
return {allComponents, pages, changedComponents};
|
||||
return {screens, pages, changedScreens};
|
||||
|
||||
|
||||
}
|
|
@ -11,14 +11,15 @@ import {
|
|||
|
||||
const normalString = s => (s||"").trim().toLowerCase();
|
||||
|
||||
export const isRootComponent = c => isComponent(c) && isUndefined(c.inherits);
|
||||
export const isRootComponent = c =>
|
||||
isComponent(c) && isUndefined(c.props._component);
|
||||
|
||||
export const isComponent = c => {
|
||||
const hasProp = (n) => !isUndefined(c[n]);
|
||||
return hasProp("name") && hasProp("props");
|
||||
}
|
||||
|
||||
export const searchAllComponents = (allComponents, phrase) => {
|
||||
export const searchAllComponents = (components, phrase) => {
|
||||
|
||||
const hasPhrase = (...vals) =>
|
||||
pipe(vals, [
|
||||
|
@ -31,35 +32,35 @@ export const searchAllComponents = (allComponents, phrase) => {
|
|||
if(isRootComponent(c)) return false;
|
||||
|
||||
const parent = getExactComponent(
|
||||
allComponents,
|
||||
c.inherits);
|
||||
components,
|
||||
c.props._component);
|
||||
|
||||
return componentMatches(parent);
|
||||
}
|
||||
|
||||
return filter(componentMatches)(allComponents);
|
||||
return filter(componentMatches)(components);
|
||||
}
|
||||
|
||||
export const getExactComponent = (allComponents, name) => {
|
||||
export const getExactComponent = (components, name) => {
|
||||
|
||||
const stringEquals = (s1, s2) =>
|
||||
normalString(s1) === normalString(s2);
|
||||
|
||||
return pipe(allComponents,[
|
||||
return pipe(components,[
|
||||
find(c => stringEquals(c.name, name))
|
||||
]);
|
||||
}
|
||||
|
||||
export const getAncestorProps = (allComponents, name, found=[]) => {
|
||||
export const getAncestorProps = (components, name, found=[]) => {
|
||||
const thisComponent = getExactComponent(
|
||||
allComponents, name);
|
||||
components, name);
|
||||
|
||||
if(isRootComponent(thisComponent))
|
||||
return [thisComponent.props, ...found];
|
||||
|
||||
return getAncestorProps(
|
||||
allComponents,
|
||||
thisComponent.inherits,
|
||||
components,
|
||||
thisComponent.props._component,
|
||||
[{...thisComponent.props},
|
||||
...found]);
|
||||
|
||||
|
|
|
@ -5,7 +5,8 @@ import {
|
|||
isArray,
|
||||
isObjectLike,
|
||||
isPlainObject,
|
||||
every
|
||||
every,
|
||||
isUndefined
|
||||
} from "lodash/fp";
|
||||
|
||||
import {
|
||||
|
@ -20,8 +21,7 @@ const defaultDef = typeName => () => ({
|
|||
type: typeName,
|
||||
required:false,
|
||||
default:types[typeName].default(),
|
||||
options: typeName === "options" ? [] : undefined,
|
||||
elementDefinition: typeName === "array" ? {} : undefined
|
||||
options: typeName === "options" ? [] : undefined
|
||||
});
|
||||
|
||||
const propType = (defaultValue, isOfType, defaultDefinition) => ({
|
||||
|
@ -42,18 +42,25 @@ const expandSingleProp = propDef => {
|
|||
}
|
||||
}
|
||||
|
||||
if(p.type === "array") {
|
||||
p.elementDefinition = expandPropsDefinition(p.elementDefinition);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
export const expandPropsDefinition = propsDefinition => {
|
||||
export const expandComponentDefinition = componentDefinition => {
|
||||
const expandedProps = {};
|
||||
for(let p in propsDefinition) {
|
||||
expandedProps[p] = expandSingleProp(propsDefinition[p]);
|
||||
const expandedComponent = {...componentDefinition};
|
||||
|
||||
for(let p in componentDefinition.props) {
|
||||
expandedProps[p] = expandSingleProp(
|
||||
componentDefinition.props[p]);
|
||||
}
|
||||
return expandedProps;
|
||||
|
||||
expandedComponent.props = expandedProps;
|
||||
|
||||
if(expandedComponent.children !== false) {
|
||||
expandedComponent.children = true;
|
||||
}
|
||||
|
||||
return expandedComponent;
|
||||
}
|
||||
|
||||
const isComponent = isObjectLike;
|
||||
|
@ -75,9 +82,7 @@ export const types = {
|
|||
string: propType(() => "", isString, defaultDef("string")),
|
||||
bool: propType(() => false, isBoolean, defaultDef("bool")),
|
||||
number: propType(() => 0, isNumber, defaultDef("number")),
|
||||
array: propType(() => [], isArray, defaultDef("array")),
|
||||
options: propType(() => "", isString, defaultDef("options")),
|
||||
component: propType(() => ({_component:""}), isComponent, defaultDef("component")),
|
||||
asset: propType(() => "", isString, defaultDef("asset")),
|
||||
event: propType(() => [], isEventList, defaultDef("event")),
|
||||
state: propType(() => emptyState(), isBound, defaultDef("state"))
|
||||
|
|
|
@ -14,9 +14,9 @@ export const validatePage = (page, getComponent) => {
|
|||
const errors = [];
|
||||
const error = message => errors.push(message);
|
||||
|
||||
const noIndex = !page.index || !page.index._component;
|
||||
const noIndex = !page.index;
|
||||
if(noIndex) {
|
||||
error("Must choose a component for your index.html");
|
||||
error("Page does not define an index member");
|
||||
}
|
||||
|
||||
if(!page.appBody
|
||||
|
@ -25,14 +25,18 @@ export const validatePage = (page, getComponent) => {
|
|||
error("App body must be set toa valid JSON file");
|
||||
}
|
||||
|
||||
/* Commenting this for now
|
||||
* index is a load of static members just now, but maybe useful
|
||||
for pageLayout props (which is just a pipe dream at time of writing)
|
||||
const indexHtmlErrors = noIndex
|
||||
? []
|
||||
: pipe(
|
||||
recursivelyValidate(page.index, getComponent), [
|
||||
map(e => `Index.html: ${e.error}`)
|
||||
]);
|
||||
*/
|
||||
|
||||
return [...errors, ...indexHtmlErrors];
|
||||
return errors;
|
||||
}
|
||||
|
||||
export const validatePages = (pages, getComponent) => {
|
||||
|
|
|
@ -23,14 +23,6 @@ const makeError = (errors, propName, stack) => (message) =>
|
|||
|
||||
export const recursivelyValidate = (rootProps, getComponent, stack=[]) => {
|
||||
|
||||
const getComponentPropsDefinition = componentName => {
|
||||
if(componentName.includes(":")) {
|
||||
const [parentComponent, arrayProp] = componentName.split(":");
|
||||
return getComponent(parentComponent)[arrayProp].elementDefinition;
|
||||
}
|
||||
return getComponent(componentName);
|
||||
}
|
||||
|
||||
if(!rootProps._component) {
|
||||
const errs = [];
|
||||
makeError(errs, "_component", stack)("Component is not set");
|
||||
|
@ -38,79 +30,56 @@ export const recursivelyValidate = (rootProps, getComponent, stack=[]) => {
|
|||
// this would break everything else anyway
|
||||
}
|
||||
|
||||
const propsDef = getComponentPropsDefinition(
|
||||
const componentDef = getComponent(
|
||||
rootProps._component);
|
||||
|
||||
const getPropsDefArray = (def) => pipe(def, [
|
||||
keys,
|
||||
map(k => def[k].name
|
||||
? expandPropDef(def[k])
|
||||
: ({
|
||||
...expandPropDef(def[k]),
|
||||
name:k }))
|
||||
]);
|
||||
|
||||
const propsDefArray = getPropsDefArray(propsDef);
|
||||
|
||||
const errors = validateProps(
|
||||
propsDef,
|
||||
componentDef,
|
||||
rootProps,
|
||||
stack,
|
||||
true);
|
||||
|
||||
const validateChildren = (_defArray, _props, _stack) => pipe(_defArray, [
|
||||
filter(d => d.type === "component"),
|
||||
map(d => recursivelyValidate(
|
||||
_props[d.name],
|
||||
getComponentPropsDefinition,
|
||||
[..._stack, d.name])),
|
||||
flatten
|
||||
const validateChildren = (_props, _stack) =>
|
||||
!_props._children
|
||||
? []
|
||||
: pipe(_props._children, [
|
||||
map(child => recursivelyValidate(
|
||||
child,
|
||||
getComponent,
|
||||
[..._stack, _props._children.indexOf(child)]))
|
||||
]);
|
||||
|
||||
const childErrors = validateChildren(
|
||||
propsDefArray, rootProps, stack);
|
||||
rootProps, stack);
|
||||
|
||||
const childArrayErrors = pipe(propsDefArray, [
|
||||
filter(d => d.type === "array"),
|
||||
map(d => pipe(rootProps[d.name], [
|
||||
map(elementProps => pipe(d.elementDefinition, [
|
||||
getPropsDefArray,
|
||||
arr => validateChildren(
|
||||
arr,
|
||||
elementProps,
|
||||
[...stack,
|
||||
`${d.name}[${indexOf(elementProps)(rootProps[d.name])}]`])
|
||||
]))
|
||||
]))
|
||||
]);
|
||||
|
||||
return flattenDeep([errors, ...childErrors, ...childArrayErrors]);
|
||||
return flattenDeep([errors, ...childErrors]);
|
||||
}
|
||||
|
||||
const expandPropDef = propDef => {
|
||||
const p = isString(propDef)
|
||||
const expandPropDef = propDef =>
|
||||
isString(propDef)
|
||||
? types[propDef].defaultDefinition()
|
||||
: propDef;
|
||||
if(p.type === "array" && isString(p.elementDefinition)) {
|
||||
p.elementDefinition = types[p.elementDefinition].defaultDefinition()
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
export const validateProps = (propsDefinition, props, stack=[], isFinal=true, isArrayElement=false) => {
|
||||
|
||||
export const validateProps = (componentDefinition, props, stack=[], isFinal=true) => {
|
||||
|
||||
const errors = [];
|
||||
|
||||
if(isFinal && !props._component && !isArrayElement) {
|
||||
if(isFinal && !props._component) {
|
||||
makeError(errors, "_component", stack)("Component is not set");
|
||||
return errors;
|
||||
// this would break everything else anyway
|
||||
}
|
||||
|
||||
for(let propDefName in propsDefinition) {
|
||||
const propsDefinition = componentDefinition.props;
|
||||
|
||||
for(let propDefName in props) {
|
||||
|
||||
if(propDefName === "_component") continue;
|
||||
if(propDefName === "_children") continue;
|
||||
if(propDefName === "_layout") continue;
|
||||
|
||||
const propDef = expandPropDef(propsDefinition[propDefName]);
|
||||
|
||||
|
@ -129,9 +98,7 @@ export const validateProps = (propsDefinition, props, stack=[], isFinal=true, is
|
|||
}
|
||||
|
||||
if(isBinding(propValue)) {
|
||||
if(propDef.type === "array"
|
||||
|| propDef.type === "component"
|
||||
|| propDef.type === "event") {
|
||||
if(propDef.type === "event") {
|
||||
error(`Cannot apply binding to type ${propDef.type}`);
|
||||
continue;
|
||||
}
|
||||
|
@ -141,22 +108,6 @@ export const validateProps = (propsDefinition, props, stack=[], isFinal=true, is
|
|||
continue;
|
||||
}
|
||||
|
||||
if(propDef.type === "array") {
|
||||
let index = 0;
|
||||
for(let arrayItem of propValue) {
|
||||
const arrayErrs = validateProps(
|
||||
propDef.elementDefinition,
|
||||
arrayItem,
|
||||
[...stack, `${propDefName}[${index}]`],
|
||||
isFinal,
|
||||
true
|
||||
)
|
||||
for(let arrErr of arrayErrs) {
|
||||
errors.push(arrErr);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
if(propDef.type === "options"
|
||||
&& propValue
|
||||
|
@ -170,33 +121,15 @@ export const validateProps = (propsDefinition, props, stack=[], isFinal=true, is
|
|||
return errors;
|
||||
}
|
||||
|
||||
export const validatePropsDefinition = (propsDefinition) => {
|
||||
const { errors } = createProps("dummy_component_name", propsDefinition);
|
||||
export const validateComponentDefinition = (componentDefinition) => {
|
||||
const { errors } = createProps(componentDefinition);
|
||||
|
||||
const propDefinitions = expandPropDef(componentDefinition.props);
|
||||
|
||||
// arrar props without elementDefinition
|
||||
pipe(propsDefinition, [
|
||||
pipe(propDefinitions, [
|
||||
keys,
|
||||
map(k => ({
|
||||
propDef:propsDefinition[k],
|
||||
propName:k
|
||||
})),
|
||||
filter(d => d.propDef.type === "array" && !d.propDef.elementDefinition),
|
||||
each(d => makeError(errors, d.propName)(`${d.propName} does not have a definition for it's item props`))
|
||||
]);
|
||||
|
||||
const arrayPropValidationErrors = pipe(propsDefinition, [
|
||||
keys,
|
||||
map(k => propsDefinition[k]),
|
||||
filter(d => d.type === "array" && d.elementDefinition),
|
||||
map(d => validatePropsDefinition(d.elementDefinition)),
|
||||
flatten
|
||||
]);
|
||||
|
||||
pipe(propsDefinition, [
|
||||
keys,
|
||||
map(k => ({
|
||||
propDef:propsDefinition[k],
|
||||
propDef:propDefinitions[k],
|
||||
propName:k
|
||||
})),
|
||||
filter(d => d.propDef.type === "options"
|
||||
|
@ -204,7 +137,7 @@ export const validatePropsDefinition = (propsDefinition) => {
|
|||
each(d => makeError(errors, d.propName)(`${d.propName} does not have any options`))
|
||||
]);
|
||||
|
||||
return [...errors, ...arrayPropValidationErrors]
|
||||
return errors;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { allComponents } from "./testData";
|
||||
import { componentsAndScreens } from "./testData";
|
||||
import {
|
||||
find
|
||||
} from "lodash/fp";
|
||||
|
@ -7,43 +7,25 @@ import { buildPropsHierarchy } from "../src/userInterface/pagesParsing/buildProp
|
|||
describe("buildPropsHierarchy", () => {
|
||||
|
||||
|
||||
it("should build a complex component with arrays and components", () => {
|
||||
it("should build a complex component children", () => {
|
||||
|
||||
const components = allComponents();
|
||||
const {components, screens} = componentsAndScreens();
|
||||
|
||||
const allprops = buildPropsHierarchy(
|
||||
components, "ButtonGroup");
|
||||
components, screens, "ButtonGroup");
|
||||
|
||||
expect(allprops._component).toEqual("budibase-components/div");
|
||||
|
||||
const primaryButtonProps = () => ({
|
||||
_component: "budibase-components/Button",
|
||||
css:"btn-primary",
|
||||
content: {_component:""},
|
||||
contentText: "",
|
||||
size:""
|
||||
_component: "budibase-components/Button"
|
||||
});
|
||||
|
||||
const headerButton = primaryButtonProps();
|
||||
expect(allprops.header).toEqual(headerButton);
|
||||
|
||||
const button1 = primaryButtonProps();
|
||||
button1.contentText = "Button 1";
|
||||
expect(allprops.children[0]).toEqual({
|
||||
_component: "children#array_element#",
|
||||
control: button1
|
||||
});
|
||||
|
||||
expect(allprops._children[0]).toEqual(button1);
|
||||
|
||||
const button2 = primaryButtonProps();
|
||||
button2.contentText = "Button 2";
|
||||
expect(allprops.children[1]).toEqual({
|
||||
_component: "children#array_element#",
|
||||
control: button2
|
||||
})
|
||||
|
||||
|
||||
|
||||
expect(allprops._children[1]).toEqual(button2)
|
||||
});
|
||||
|
||||
});
|
|
@ -1,12 +1,7 @@
|
|||
import {
|
||||
searchAllComponents,
|
||||
getExactComponent,
|
||||
getAncestorProps
|
||||
} from "../src/userInterface/pagesParsing/searchComponents";
|
||||
import {
|
||||
componentDependencies
|
||||
} from "../src/userInterface/pagesParsing/findDependencies";
|
||||
import { allComponents } from "./testData";
|
||||
import { componentsAndScreens } from "./testData";
|
||||
import { some, find } from "lodash/fp"
|
||||
|
||||
describe("component dependencies", () => {
|
||||
|
@ -19,37 +14,29 @@ describe("component dependencies", () => {
|
|||
|
||||
it("should include component that inheirts", () => {
|
||||
|
||||
const components = allComponents();
|
||||
const {components, screens} = componentsAndScreens();
|
||||
|
||||
const result = componentDependencies(
|
||||
{}, components, get(components, "budibase-components/TextBox"));
|
||||
{}, screens, components,
|
||||
get([...components, ...screens], "budibase-components/TextBox"));
|
||||
|
||||
expect(contains(result.dependantComponents, "common/SmallTextbox")).toBe(true);
|
||||
|
||||
});
|
||||
|
||||
it("should include component that nests", () => {
|
||||
const components = allComponents();
|
||||
const {components, screens} = componentsAndScreens();
|
||||
|
||||
const result = componentDependencies(
|
||||
{}, components, get(components, "PrimaryButton"));
|
||||
{}, screens, components,
|
||||
get([...components, ...screens], "budibase-components/Button"));
|
||||
|
||||
expect(contains(result.dependantComponents, "ButtonGroup")).toBe(true);
|
||||
|
||||
});
|
||||
|
||||
it("shouldinclude component that nests inside arrays", () => {
|
||||
const components = allComponents();
|
||||
|
||||
const result = componentDependencies(
|
||||
{}, components, get(components, "common/PasswordBox"));
|
||||
|
||||
expect(contains(result.dependantComponents, "ButtonGroup")).toBe(true);
|
||||
});
|
||||
|
||||
|
||||
it("should include components n page apbody", () => {
|
||||
const components = allComponents();
|
||||
const {components, screens} = componentsAndScreens();
|
||||
const pages = {
|
||||
main: {
|
||||
appBody: "PrimaryButton"
|
||||
|
@ -57,7 +44,8 @@ describe("component dependencies", () => {
|
|||
};
|
||||
|
||||
const result = componentDependencies(
|
||||
pages, components, get(components, "PrimaryButton"));
|
||||
pages, screens, components,
|
||||
get([...components, ...screens], "PrimaryButton"));
|
||||
|
||||
expect(result.dependantPages).toEqual(["main"]);
|
||||
});
|
||||
|
|
|
@ -10,46 +10,45 @@ import {
|
|||
|
||||
describe("createDefaultProps", () => {
|
||||
|
||||
it("should create a object with single string value, when default string field set", () => {
|
||||
const propDef = {
|
||||
const getcomponent = () => ({
|
||||
name:"some_component",
|
||||
props: {
|
||||
fieldName: {type:"string", default:"something"}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
const { props, errors } = createProps("some_component",propDef);
|
||||
it("should create a object with single string value, when default string field set", () => {
|
||||
|
||||
const { props, errors } = createProps(getcomponent());
|
||||
|
||||
expect(errors).toEqual([]);
|
||||
expect(props.fieldName).toBeDefined();
|
||||
expect(props.fieldName).toBe("something");
|
||||
expect(keys(props).length).toBe(2);
|
||||
expect(keys(props).length).toBe(3);
|
||||
});
|
||||
|
||||
it("should set component name", () => {
|
||||
const propDef = {
|
||||
fieldName: {type:"string", default:"something"}
|
||||
};
|
||||
|
||||
const { props, errors } = createProps("some_component",propDef);
|
||||
const { props, errors } = createProps(getcomponent());
|
||||
|
||||
expect(errors).toEqual([]);
|
||||
expect(props._component).toBe("some_component");
|
||||
});
|
||||
|
||||
it("should return error when component name not supplied", () => {
|
||||
const propDef = {
|
||||
fieldName: {type:"string", default:"something"}
|
||||
};
|
||||
const comp = getcomponent();
|
||||
comp.name = "";
|
||||
|
||||
const { errors } = createProps("",propDef);
|
||||
const { errors } = createProps(comp);
|
||||
|
||||
expect(errors.length).toEqual(1);
|
||||
});
|
||||
|
||||
it("should create a object with single blank string value, when no default", () => {
|
||||
const propDef = {
|
||||
fieldName: {type:"string"}
|
||||
};
|
||||
const comp = getcomponent();
|
||||
comp.props.fieldName = {type:"string"};
|
||||
|
||||
const { props, errors } = createProps("some_component",propDef);
|
||||
const { props, errors } = createProps(comp);
|
||||
|
||||
expect(errors).toEqual([]);
|
||||
expect(props.fieldName).toBeDefined();
|
||||
|
@ -57,11 +56,10 @@ describe("createDefaultProps", () => {
|
|||
});
|
||||
|
||||
it("should create a object with single blank string value, when prop definition is 'string' ", () => {
|
||||
const propDef = {
|
||||
fieldName: "string"
|
||||
};
|
||||
const comp = getcomponent();
|
||||
comp.props.fieldName = "string";
|
||||
|
||||
const { props, errors } = createProps("some_component",propDef);
|
||||
const { props, errors } = createProps(comp);
|
||||
|
||||
expect(errors).toEqual([]);
|
||||
expect(props.fieldName).toBeDefined();
|
||||
|
@ -69,11 +67,10 @@ describe("createDefaultProps", () => {
|
|||
});
|
||||
|
||||
it("should create a object with single fals value, when prop definition is 'bool' ", () => {
|
||||
const propDef = {
|
||||
isVisible: "bool"
|
||||
};
|
||||
const comp = getcomponent();
|
||||
comp.props.isVisible = "bool";
|
||||
|
||||
const { props, errors } = createProps("some_component",propDef);
|
||||
const { props, errors } = createProps(comp);
|
||||
|
||||
expect(errors).toEqual([]);
|
||||
expect(props.isVisible).toBeDefined();
|
||||
|
@ -81,35 +78,44 @@ describe("createDefaultProps", () => {
|
|||
});
|
||||
|
||||
it("should create a object with single 0 value, when prop definition is 'number' ", () => {
|
||||
const propDef = {
|
||||
width: "number"
|
||||
};
|
||||
|
||||
const { props, errors } = createProps("some_component",propDef);
|
||||
const comp = getcomponent();
|
||||
comp.props.width = "number";
|
||||
|
||||
const { props, errors } = createProps(comp);
|
||||
|
||||
expect(errors).toEqual([]);
|
||||
expect(props.width).toBeDefined();
|
||||
expect(props.width).toBe(0);
|
||||
});
|
||||
|
||||
it("should create a object with single empty array, when prop definition is 'array' ", () => {
|
||||
const propDef = {
|
||||
columns: "array"
|
||||
};
|
||||
it("should create a object with empty _children array, when children===true ", () => {
|
||||
const comp = getcomponent();
|
||||
comp.children = true;
|
||||
|
||||
const { props, errors } = createProps("some_component",propDef);
|
||||
const { props, errors } = createProps(comp);
|
||||
|
||||
expect(errors).toEqual([]);
|
||||
expect(props.columns).toBeDefined();
|
||||
expect(props.columns).toEqual([]);
|
||||
expect(props._children).toBeDefined();
|
||||
expect(props._children).toEqual([]);
|
||||
});
|
||||
|
||||
it("should create a object without _children array, when children===false ", () => {
|
||||
const comp = getcomponent();
|
||||
comp.children = false;
|
||||
|
||||
const { props, errors } = createProps(comp);
|
||||
|
||||
expect(errors).toEqual([]);
|
||||
expect(props._children).not.toBeDefined();
|
||||
});
|
||||
|
||||
it("should create a object with single empty array, when prop definition is 'event' ", () => {
|
||||
const propDef = {
|
||||
onClick: "event"
|
||||
};
|
||||
|
||||
const { props, errors } = createProps("some_component",propDef);
|
||||
const comp = getcomponent();
|
||||
comp.props.onClick = "event";
|
||||
|
||||
const { props, errors } = createProps(comp);
|
||||
|
||||
expect(errors).toEqual([]);
|
||||
expect(props.onClick).toBeDefined();
|
||||
|
@ -117,52 +123,72 @@ describe("createDefaultProps", () => {
|
|||
});
|
||||
|
||||
it("should create a object with empty state when prop def is 'state' ", () => {
|
||||
const propDef = {
|
||||
data: "state"
|
||||
};
|
||||
|
||||
const { props, errors } = createProps("some_component",propDef);
|
||||
const comp = getcomponent();
|
||||
comp.props.data = "state";
|
||||
|
||||
const { props, errors } = createProps(comp);
|
||||
|
||||
expect(errors).toEqual([]);
|
||||
expect(props.data[BB_STATE_BINDINGPATH]).toBeDefined();
|
||||
expect(props.data[BB_STATE_BINDINGPATH]).toBe("");
|
||||
});
|
||||
|
||||
it("should create a object with single empty component props, when prop definition is 'component' ", () => {
|
||||
const propDef = {
|
||||
content: "component"
|
||||
};
|
||||
it("should create a object children array when children == true ", () => {
|
||||
|
||||
const { props, errors } = createProps("some_component",propDef);
|
||||
const comp = getcomponent();
|
||||
comp.children = true;
|
||||
|
||||
const { props, errors } = createProps(comp);
|
||||
|
||||
expect(errors).toEqual([]);
|
||||
expect(props.content).toBeDefined();
|
||||
expect(props.content).toEqual({_component:""});
|
||||
expect(props._children).toBeDefined();
|
||||
expect(props._children).toEqual([]);
|
||||
});
|
||||
|
||||
it("should create a _children array when children not defined ", () => {
|
||||
|
||||
const comp = getcomponent();
|
||||
|
||||
const { props, errors } = createProps(comp);
|
||||
|
||||
expect(errors).toEqual([]);
|
||||
expect(props._children).toBeDefined();
|
||||
expect(props._children).toEqual([]);
|
||||
});
|
||||
|
||||
it("should not create _children array when children=false ", () => {
|
||||
|
||||
const comp = getcomponent();
|
||||
comp.children = false;
|
||||
|
||||
const { props, errors } = createProps(comp);
|
||||
|
||||
expect(errors).toEqual([]);
|
||||
expect(props._children).not.toBeDefined();
|
||||
});
|
||||
|
||||
it("should create an object with multiple prop names", () => {
|
||||
const propDef = {
|
||||
fieldName: "string",
|
||||
fieldLength: { type: "number", default: 500 }
|
||||
};
|
||||
|
||||
const { props, errors } = createProps("some_component",propDef);
|
||||
const comp = getcomponent();
|
||||
comp.props.fieldName = "string";
|
||||
comp.props.fieldLength = { type: "number", default: 500 };
|
||||
|
||||
const { props, errors } = createProps(comp);
|
||||
|
||||
expect(errors).toEqual([]);
|
||||
expect(props.fieldName).toBeDefined();
|
||||
expect(props.fieldName).toBe("");
|
||||
expect(props.fieldLength).toBeDefined();
|
||||
expect(props.fieldLength).toBe(500);
|
||||
expect(keys(props).length).toBe(3);
|
||||
})
|
||||
|
||||
it("should return error when invalid type", () => {
|
||||
const propDef = {
|
||||
fieldName: "invalid type name",
|
||||
fieldLength: { type: "invalid type name "}
|
||||
};
|
||||
const comp = getcomponent();
|
||||
comp.props.fieldName = "invalid type name";
|
||||
comp.props.fieldLength = { type: "invalid type name "};
|
||||
|
||||
const { errors } = createProps("some_component",propDef);
|
||||
const { errors } = createProps(comp);
|
||||
|
||||
expect(errors.length).toBe(2);
|
||||
expect(some(e => e.propName === "fieldName")(errors)).toBeTruthy();
|
||||
|
@ -170,11 +196,12 @@ describe("createDefaultProps", () => {
|
|||
});
|
||||
|
||||
it("should return error default value is not of declared type", () => {
|
||||
const propDef = {
|
||||
fieldName: {type:"string", default: 1}
|
||||
};
|
||||
|
||||
const { errors } = createProps("some_component",propDef);
|
||||
const comp = getcomponent();
|
||||
comp.props.fieldName = {type:"string", default: 1}
|
||||
|
||||
|
||||
const { errors } = createProps(comp);
|
||||
|
||||
expect(errors.length).toBe(1);
|
||||
expect(some(e => e.propName === "fieldName")(errors)).toBeTruthy();
|
||||
|
@ -186,11 +213,15 @@ describe("createDefaultProps", () => {
|
|||
fieldLength: { type: "number", default: 500}
|
||||
};
|
||||
|
||||
const comp = getcomponent();
|
||||
comp.props.fieldName = "string";
|
||||
comp.props.fieldLength = { type: "number", default: 500};
|
||||
|
||||
const derivedFrom = {
|
||||
fieldName: "surname"
|
||||
};
|
||||
|
||||
const { props, errors } = createProps("some_component",propDef, derivedFrom);
|
||||
const { props, errors } = createProps(comp, derivedFrom);
|
||||
|
||||
expect(errors.length).toBe(0);
|
||||
expect(props.fieldName).toBe("surname");
|
||||
|
|
|
@ -1,44 +1,50 @@
|
|||
import { expandPropsDefinition } from "../src/userInterface/pagesParsing/types";
|
||||
import { expandComponentDefinition } from "../src/userInterface/pagesParsing/types";
|
||||
|
||||
const propDef = {
|
||||
const componentDef = () => ({
|
||||
name: "comp",
|
||||
props: {
|
||||
label: "string",
|
||||
width: {type:"number"},
|
||||
color: {type:"string", required:true},
|
||||
child: "component",
|
||||
navitems: {
|
||||
type: "array",
|
||||
elementDefinition: {
|
||||
name: {type:"string"},
|
||||
height: "number"
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
describe("expandPropDefintion", () => {
|
||||
|
||||
it("should expand property defined as string, into default for that type", () => {
|
||||
|
||||
const result = expandPropsDefinition(propDef);
|
||||
const result = expandComponentDefinition(componentDef());
|
||||
|
||||
expect(result.label.type).toBe("string");
|
||||
expect(result.label.required).toBe(false);
|
||||
expect(result.props.label.type).toBe("string");
|
||||
expect(result.props.label.required).toBe(false);
|
||||
});
|
||||
|
||||
it("should add members to property defined as object, when members do not exist", () => {
|
||||
|
||||
const result = expandPropsDefinition(propDef);
|
||||
expect(result.width.required).toBe(false);
|
||||
const result = expandComponentDefinition(componentDef());
|
||||
expect(result.props.width.required).toBe(false);
|
||||
});
|
||||
|
||||
it("should not override existing memebers", () => {
|
||||
|
||||
const result = expandPropsDefinition(propDef);
|
||||
expect(result.color.required).toBe(true);
|
||||
const result = expandComponentDefinition(componentDef());
|
||||
expect(result.props.color.required).toBe(true);
|
||||
});
|
||||
|
||||
it("should also expand out elementdefinition of array", () => {
|
||||
const result = expandPropsDefinition(propDef);
|
||||
expect(result.navitems.elementDefinition.height.type).toBe("number");
|
||||
})
|
||||
it("should set children=true when not included", () => {
|
||||
const result = expandComponentDefinition(componentDef());
|
||||
expect(result.children).toBe(true);
|
||||
});
|
||||
|
||||
it("should not change children when specified", () => {
|
||||
const c = componentDef();
|
||||
c.children = false;
|
||||
const result = expandComponentDefinition(c);
|
||||
expect(result.children).toBe(false);
|
||||
|
||||
c.children = true;
|
||||
const result2 = expandComponentDefinition(c);
|
||||
expect(result2.children).toBe(true);
|
||||
});
|
||||
|
||||
})
|
|
@ -1,11 +1,12 @@
|
|||
import {
|
||||
getInstanceProps,
|
||||
getScreenInfo ,
|
||||
getComponentInfo
|
||||
} from "../src/userInterface/pagesParsing/createProps";
|
||||
import {
|
||||
keys, some
|
||||
keys, some, find
|
||||
} from "lodash/fp";
|
||||
import { allComponents } from "./testData";
|
||||
import { componentsAndScreens } from "./testData";
|
||||
|
||||
|
||||
|
||||
|
@ -13,7 +14,7 @@ describe("getComponentInfo", () => {
|
|||
|
||||
it("should return default props for root component", () => {
|
||||
const result = getComponentInfo(
|
||||
allComponents(),
|
||||
componentsAndScreens().components,
|
||||
"budibase-components/TextBox");
|
||||
|
||||
expect(result.errors).toEqual([]);
|
||||
|
@ -26,19 +27,10 @@ describe("getComponentInfo", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("should return no inherited for root component", () => {
|
||||
const result = getComponentInfo(
|
||||
allComponents(),
|
||||
"budibase-components/TextBox");
|
||||
|
||||
expect(result.inheritedProps).toEqual([]);
|
||||
|
||||
});
|
||||
|
||||
it("getInstanceProps should set supplied props on top of default props", () => {
|
||||
const result = getInstanceProps(
|
||||
getComponentInfo(
|
||||
allComponents(),
|
||||
componentsAndScreens().components,
|
||||
"budibase-components/TextBox"),
|
||||
{size:"small"});
|
||||
|
||||
|
@ -51,11 +43,18 @@ describe("getComponentInfo", () => {
|
|||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
it("should return correct props for derived component", () => {
|
||||
const result = getComponentInfo(
|
||||
allComponents(),
|
||||
"common/SmallTextbox");
|
||||
describe("getScreenInfo", () => {
|
||||
|
||||
const getScreen = (screens, name) =>
|
||||
find(s => s.name === name)(screens);
|
||||
|
||||
it("should return correct props for screen", () => {
|
||||
const {components, screens} = componentsAndScreens();
|
||||
const result = getScreenInfo(
|
||||
components,
|
||||
getScreen(screens, "common/SmallTextbox"));
|
||||
|
||||
expect(result.errors).toEqual([]);
|
||||
expect(result.fullProps).toEqual({
|
||||
|
@ -68,9 +67,10 @@ describe("getComponentInfo", () => {
|
|||
});
|
||||
|
||||
it("should return correct props for twice derived component", () => {
|
||||
const result = getComponentInfo(
|
||||
allComponents(),
|
||||
"common/PasswordBox");
|
||||
const {components, screens} = componentsAndScreens();
|
||||
const result = getScreenInfo(
|
||||
components,
|
||||
getScreen(screens, "common/PasswordBox"));
|
||||
|
||||
expect(result.errors).toEqual([]);
|
||||
expect(result.fullProps).toEqual({
|
||||
|
@ -82,19 +82,12 @@ describe("getComponentInfo", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("should list inheirted props as those that are defined in ancestor, derived components", () => {
|
||||
const result = getComponentInfo(
|
||||
allComponents(),
|
||||
"common/PasswordBox");
|
||||
|
||||
// size is inherited from SmallTextbox
|
||||
expect(result.inheritedProps).toEqual(["size"]);
|
||||
});
|
||||
|
||||
it("should list unset props as those that are only defined in root", () => {
|
||||
const result = getComponentInfo(
|
||||
allComponents(),
|
||||
"common/PasswordBox");
|
||||
const {components, screens} = componentsAndScreens();
|
||||
const result = getScreenInfo(
|
||||
components,
|
||||
getScreen(screens, "common/PasswordBox"));
|
||||
|
||||
expect(result.unsetProps).toEqual([
|
||||
"placeholder", "label"]);
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
import {
|
||||
searchAllComponents,
|
||||
getExactComponent,
|
||||
getAncestorProps
|
||||
} from "../src/userInterface/pagesParsing/searchComponents";
|
||||
import {
|
||||
rename
|
||||
} from "../src/userInterface/pagesParsing/renameComponent";
|
||||
import { allComponents } from "./testData";
|
||||
|
||||
describe("rename component", () => {
|
||||
it("should change the name of the component, duh", () => {
|
||||
|
||||
const components = allComponents();
|
||||
|
||||
const result = rename({}, components, "PrimaryButton", "MainButton");
|
||||
|
||||
const newComponent = getExactComponent(result.allComponents, "MainButton");
|
||||
const oldComponent = getExactComponent(result.allComponents, "Primary");
|
||||
expect(oldComponent).toBeUndefined();
|
||||
expect(newComponent).toBeDefined();
|
||||
expect(newComponent.name).toBe("MainButton");
|
||||
|
||||
});
|
||||
|
||||
it("should chnge name on inherits", () => {
|
||||
|
||||
const components = allComponents();
|
||||
|
||||
const result = rename({}, components, "common/SmallTextbox", "common/TinyTextbox");
|
||||
|
||||
const passwordTextbox = getExactComponent(result.allComponents, "common/PasswordBox");
|
||||
expect(passwordTextbox.inherits).toBe("common/TinyTextbox");
|
||||
|
||||
});
|
||||
|
||||
it("should change name of nested _components", () => {
|
||||
const components = allComponents();
|
||||
const result = rename({}, components, "PrimaryButton", "MainButton");
|
||||
|
||||
const buttonGroup = getExactComponent(result.allComponents, "ButtonGroup");
|
||||
expect(buttonGroup.props.header._component).toBe("MainButton");
|
||||
|
||||
});
|
||||
|
||||
it("should change name of nested _components inside arrays", () => {
|
||||
const components = allComponents();
|
||||
const result = rename({}, components, "PrimaryButton", "MainButton");
|
||||
|
||||
const buttonGroup = getExactComponent(result.allComponents, "ButtonGroup");
|
||||
expect(buttonGroup.props.children[0].control._component).toBe("MainButton");
|
||||
|
||||
});
|
||||
|
||||
|
||||
it("should change name of page appBody", () => {
|
||||
const components = allComponents();
|
||||
const pages = {
|
||||
main: {
|
||||
appBody: "PrimaryButton"
|
||||
}
|
||||
};
|
||||
|
||||
const result = rename(pages, components, "PrimaryButton", "MainButton");
|
||||
expect(result.pages.main.appBody).toBe("MainButton");
|
||||
|
||||
});
|
||||
|
||||
it("should return a list of changed components", () => {
|
||||
const components = allComponents();
|
||||
const result = rename({}, components, "PrimaryButton", "MainButton");
|
||||
|
||||
expect(result.changedComponents).toEqual(["ButtonGroup"]);
|
||||
|
||||
const result2 = rename({}, components, "common/SmallTextbox", "common/TinyTextBox");
|
||||
expect(result2.changedComponents).toEqual(["common/PasswordBox"]);
|
||||
|
||||
});
|
||||
})
|
|
@ -0,0 +1,61 @@
|
|||
import {
|
||||
getExactComponent
|
||||
} from "../src/userInterface/pagesParsing/searchComponents";
|
||||
import {
|
||||
rename
|
||||
} from "../src/userInterface/pagesParsing/renameScreen";
|
||||
import { componentsAndScreens } from "./testData";
|
||||
|
||||
describe("rename component", () => {
|
||||
it("should change the name of the component, duh", () => {
|
||||
|
||||
const {screens} = componentsAndScreens();
|
||||
|
||||
const result = rename({}, screens, "PrimaryButton", "MainButton");
|
||||
|
||||
const newComponent = getExactComponent(result.screens, "MainButton");
|
||||
const oldComponent = getExactComponent(result.screens, "Primary");
|
||||
expect(oldComponent).toBeUndefined();
|
||||
expect(newComponent).toBeDefined();
|
||||
expect(newComponent.name).toBe("MainButton");
|
||||
|
||||
});
|
||||
|
||||
/* this may be usefull if we have user defined components
|
||||
it("should change name of nested _components", () => {
|
||||
const {screens} = componentsAndScreens();
|
||||
const result = rename({}, screens, "PrimaryButton", "MainButton");
|
||||
|
||||
const buttonGroup = getExactComponent(result.screens, "ButtonGroup");
|
||||
expect(buttonGroup.props.header[0]._component).toBe("MainButton");
|
||||
|
||||
});
|
||||
*/
|
||||
|
||||
|
||||
it("should change name of page appBody", () => {
|
||||
const {screens} = componentsAndScreens();
|
||||
const pages = {
|
||||
main: {
|
||||
appBody: "PrimaryButton"
|
||||
}
|
||||
};
|
||||
|
||||
const result = rename(pages, screens, "PrimaryButton", "MainButton");
|
||||
expect(result.pages.main.appBody).toBe("MainButton");
|
||||
|
||||
});
|
||||
|
||||
/* this may be usefull if we have user defined components
|
||||
it("should return a list of changed components", () => {
|
||||
const {screens} = componentsAndScreens();
|
||||
const result = rename({}, screens, "PrimaryButton", "MainButton");
|
||||
|
||||
expect(result.changedScreens).toEqual(["ButtonGroup"]);
|
||||
|
||||
const result2 = rename({}, screens, "common/SmallTextbox", "common/TinyTextBox");
|
||||
expect(result2.changedScreens).toEqual(["Field"]);
|
||||
|
||||
});
|
||||
*/
|
||||
})
|
|
@ -3,42 +3,31 @@ import {
|
|||
getExactComponent,
|
||||
getAncestorProps
|
||||
} from "../src/userInterface/pagesParsing/searchComponents";
|
||||
import { allComponents } from "./testData";
|
||||
import { componentsAndScreens } from "./testData";
|
||||
|
||||
describe("searchAllComponents", () => {
|
||||
|
||||
it("should match derived component by name", () => {
|
||||
it("should match component by name", () => {
|
||||
|
||||
const results = searchAllComponents(
|
||||
allComponents(),
|
||||
"password"
|
||||
componentsAndScreens().components,
|
||||
"Textbox"
|
||||
);
|
||||
|
||||
expect(results.length).toBe(1);
|
||||
expect(results[0].name).toBe("common/PasswordBox");
|
||||
expect(results[0].name).toBe("budibase-components/TextBox");
|
||||
|
||||
});
|
||||
|
||||
it("should match derived component by tag", () => {
|
||||
it("should match component by tag", () => {
|
||||
|
||||
const results = searchAllComponents(
|
||||
allComponents(),
|
||||
"mask"
|
||||
componentsAndScreens().components,
|
||||
"record"
|
||||
);
|
||||
|
||||
expect(results.length).toBe(1);
|
||||
expect(results[0].name).toBe("common/PasswordBox");
|
||||
|
||||
});
|
||||
|
||||
it("should match component if ancestor matches", () => {
|
||||
|
||||
const results = searchAllComponents(
|
||||
allComponents(),
|
||||
"smalltext"
|
||||
);
|
||||
|
||||
expect(results.length).toBe(2);
|
||||
expect(results[0].name).toBe("budibase-components/RecordView");
|
||||
|
||||
});
|
||||
|
||||
|
@ -46,8 +35,9 @@ describe("searchAllComponents", () => {
|
|||
|
||||
describe("getExactComponent", () => {
|
||||
it("should get component by name", () => {
|
||||
const {components, screens} = componentsAndScreens();
|
||||
const result = getExactComponent(
|
||||
allComponents(),
|
||||
[...components, ...screens],
|
||||
"common/SmallTextbox"
|
||||
)
|
||||
|
||||
|
@ -56,8 +46,9 @@ describe("getExactComponent", () => {
|
|||
});
|
||||
|
||||
it("should return nothing when no result (should not fail)", () => {
|
||||
const {components, screens} = componentsAndScreens();
|
||||
const result = getExactComponent(
|
||||
allComponents(),
|
||||
[...components, ...screens],
|
||||
"bla/bla/bla"
|
||||
)
|
||||
|
||||
|
@ -71,29 +62,29 @@ describe("getAncestorProps", () => {
|
|||
it("should return props of root component", () => {
|
||||
|
||||
const result = getAncestorProps(
|
||||
allComponents(),
|
||||
componentsAndScreens().components,
|
||||
"budibase-components/TextBox"
|
||||
);
|
||||
|
||||
expect(result).toEqual([
|
||||
allComponents()[0].props
|
||||
componentsAndScreens().components[0].props
|
||||
]);
|
||||
|
||||
});
|
||||
|
||||
it("should return props of all ancestors and current component, in order", () => {
|
||||
it("should return props of inherited and current component, in order", () => {
|
||||
|
||||
const components = allComponents();
|
||||
const {components, screens} = componentsAndScreens();
|
||||
const allComponentsAndScreens = [...components, ...screens];
|
||||
|
||||
const result = getAncestorProps(
|
||||
components,
|
||||
allComponentsAndScreens,
|
||||
"common/PasswordBox"
|
||||
);
|
||||
|
||||
expect(result).toEqual([
|
||||
components[0].props,
|
||||
{...components[4].props},
|
||||
{...components[5].props}
|
||||
allComponentsAndScreens[0].props,
|
||||
{...allComponentsAndScreens[5].props}
|
||||
]);
|
||||
|
||||
});
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
|
||||
export const allComponents = () => ([
|
||||
export const componentsAndScreens = () => ({
|
||||
components: [
|
||||
{
|
||||
name: "budibase-components/TextBox",
|
||||
tags: ["Text", "input"],
|
||||
children: false,
|
||||
props: {
|
||||
size: {type:"options", options:["small", "medium", "large"]},
|
||||
isPassword: "bool",
|
||||
|
@ -13,10 +15,10 @@ export const allComponents = () => ([
|
|||
{
|
||||
name: "budibase-components/Button",
|
||||
tags: ["input"],
|
||||
children: true,
|
||||
props: {
|
||||
size: {type:"options", options:["small", "medium", "large"]},
|
||||
css: "string",
|
||||
content: "component",
|
||||
contentText: "string"
|
||||
}
|
||||
},
|
||||
|
@ -25,13 +27,6 @@ export const allComponents = () => ([
|
|||
tags: ["input"],
|
||||
props: {
|
||||
width: "number",
|
||||
header : "component",
|
||||
children: {
|
||||
type:"array",
|
||||
elementDefinition: {
|
||||
control: "component"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -40,59 +35,68 @@ export const allComponents = () => ([
|
|||
props: {
|
||||
data: "state"
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
screens: [
|
||||
{
|
||||
inherits:"budibase-components/TextBox",
|
||||
name: "common/SmallTextbox",
|
||||
props: {
|
||||
_component: "budibase-components/TextBox",
|
||||
size: "small"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
inherits:"common/SmallTextbox",
|
||||
name: "common/PasswordBox",
|
||||
tags: ["mask"],
|
||||
props: {
|
||||
isPassword: true
|
||||
_component: "budibase-components/TextBox",
|
||||
isPassword: true,
|
||||
size: "small"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
inherits:"budibase-components/Button",
|
||||
name:"PrimaryButton",
|
||||
props: {
|
||||
_component:"budibase-components/Button",
|
||||
css:"btn-primary"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
inherits:"budibase-components/div",
|
||||
name:"ButtonGroup",
|
||||
props: {
|
||||
|
||||
_component:"budibase-components/div",
|
||||
width: 100,
|
||||
header: {
|
||||
_component: "PrimaryButton"
|
||||
},
|
||||
children: [
|
||||
_children: [
|
||||
{
|
||||
control: {
|
||||
_component: "PrimaryButton",
|
||||
_component: "budibase-components/Button",
|
||||
contentText: "Button 1"
|
||||
}
|
||||
},
|
||||
{
|
||||
control: {
|
||||
_component: "PrimaryButton",
|
||||
_component: "budibase-components/Button",
|
||||
contentText: "Button 2"
|
||||
}
|
||||
},
|
||||
{
|
||||
control: {
|
||||
_component: "common/PasswordBox",
|
||||
}
|
||||
_component: "budibase-components/TextBox",
|
||||
isPassword: true,
|
||||
size: "small"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
])
|
||||
{
|
||||
name:"Field",
|
||||
props: {
|
||||
_component:"budibase-components/div",
|
||||
_children:[
|
||||
{
|
||||
_component: "common/SmallTextbox"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
]
|
||||
});
|
|
@ -6,21 +6,13 @@ import {
|
|||
const validPages = () => ({
|
||||
"main" : {
|
||||
"index" : {
|
||||
"_component": "testIndexHtml",
|
||||
"title": "My Cool App",
|
||||
"customScripts": [
|
||||
{"url": "MyCustomComponents.js"}
|
||||
]
|
||||
"title": "My Cool App"
|
||||
},
|
||||
"appBody" : "./main.app.json"
|
||||
},
|
||||
"unauthenticated" : {
|
||||
"index" : {
|
||||
"_component": "testIndexHtml",
|
||||
"title": "My Cool App - Login",
|
||||
"customScripts": [
|
||||
{"url": "MyCustomComponents.js"}
|
||||
]
|
||||
"title": "My Cool App - Login"
|
||||
},
|
||||
"appBody" : "./unauthenticated.app.json"
|
||||
},
|
||||
|
@ -29,12 +21,9 @@ const validPages = () => ({
|
|||
|
||||
const getComponent = name => ({
|
||||
testIndexHtml : {
|
||||
name: "testIndexHtml",
|
||||
props: {
|
||||
title: "string",
|
||||
customScripts: {
|
||||
type:"array",
|
||||
elementDefinition: {
|
||||
url: "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}[name])
|
||||
|
@ -53,11 +42,6 @@ describe("validate single page", () => {
|
|||
let page = validPages().main;
|
||||
delete page.index;
|
||||
expect(validatePage(page, getComponent).length).toEqual(1);
|
||||
|
||||
page.index = {title:"something"}; // no _component
|
||||
const noComponent = validatePage(page, getComponent);
|
||||
expect(noComponent.length).toEqual(1);
|
||||
|
||||
});
|
||||
|
||||
it("should return error when appBody is not set, or set incorrectly", () => {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {
|
||||
validatePropsDefinition,
|
||||
validateComponentDefinition,
|
||||
validateProps,
|
||||
recursivelyValidate
|
||||
} from "../src/userInterface/pagesParsing/validateProps";
|
||||
|
@ -11,61 +11,22 @@ import {
|
|||
// not that allot of this functionality is covered
|
||||
// in createDefaultProps - as validate props uses that.
|
||||
|
||||
describe("validatePropsDefinition", () => {
|
||||
describe("validateComponentDefinition", () => {
|
||||
|
||||
it("should recursively validate array props and return no errors when valid", () => {
|
||||
|
||||
const propsDef = {
|
||||
columns : {
|
||||
type: "array",
|
||||
elementDefinition: {
|
||||
width: "number",
|
||||
units: {
|
||||
type: "string",
|
||||
default: "px"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const errors = validatePropsDefinition(propsDef);
|
||||
|
||||
expect(errors).toEqual([]);
|
||||
|
||||
});
|
||||
|
||||
it("should recursively validate array props and return errors when invalid", () => {
|
||||
|
||||
const propsDef = {
|
||||
columns : {
|
||||
type: "array",
|
||||
elementDefinition: {
|
||||
width: "invlid type",
|
||||
units: {
|
||||
type: "string",
|
||||
default: "px"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const errors = validatePropsDefinition(propsDef);
|
||||
|
||||
expect(errors.length).toEqual(1);
|
||||
expect(errors[0].propName).toBe("width");
|
||||
|
||||
});
|
||||
|
||||
it("should return error when no options for options field", () => {
|
||||
|
||||
const propsDef = {
|
||||
const compDef = {
|
||||
name:"some_component",
|
||||
props: {
|
||||
size: {
|
||||
type: "options",
|
||||
options: []
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const errors = validatePropsDefinition(propsDef);
|
||||
const errors = validateComponentDefinition(compDef);
|
||||
|
||||
expect(errors.length).toEqual(1);
|
||||
expect(errors[0].propName).toBe("size");
|
||||
|
@ -74,14 +35,17 @@ describe("validatePropsDefinition", () => {
|
|||
|
||||
it("should not return error when options field has options", () => {
|
||||
|
||||
const propsDef = {
|
||||
const compDef = {
|
||||
name: "some_component",
|
||||
props: {
|
||||
size: {
|
||||
type: "options",
|
||||
options: ["small", "medium", "large"]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const errors = validatePropsDefinition(propsDef);
|
||||
const errors = validateComponentDefinition(compDef);
|
||||
|
||||
expect(errors).toEqual([]);
|
||||
|
||||
|
@ -89,30 +53,34 @@ describe("validatePropsDefinition", () => {
|
|||
|
||||
});
|
||||
|
||||
const validPropDef = {
|
||||
const validComponentDef = {
|
||||
name: "some_component",
|
||||
props: {
|
||||
size: {
|
||||
type: "options",
|
||||
options: ["small", "medium", "large"],
|
||||
default:"medium"
|
||||
},
|
||||
rowCount : "number",
|
||||
columns : {
|
||||
type: "array",
|
||||
elementDefinition: {
|
||||
rowCount : "number"
|
||||
}
|
||||
};
|
||||
|
||||
const childComponentDef = {
|
||||
name: "child_component",
|
||||
props: {
|
||||
width: "number",
|
||||
units: {
|
||||
type: "string",
|
||||
default: "px"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const validProps = () => {
|
||||
const { props } = createProps("some_component", validPropDef);
|
||||
props.columns.push(
|
||||
createProps("childcomponent", validPropDef.columns.elementDefinition).props);
|
||||
|
||||
const { props } = createProps(validComponentDef);
|
||||
props._children.push(
|
||||
createProps(childComponentDef));
|
||||
return props;
|
||||
}
|
||||
|
||||
|
@ -120,7 +88,7 @@ describe("validateProps", () => {
|
|||
|
||||
it("should have no errors with a big list of valid props", () => {
|
||||
|
||||
const errors = validateProps(validPropDef, validProps(), [], true);
|
||||
const errors = validateProps(validComponentDef, validProps(), [], true);
|
||||
expect(errors).toEqual([]);
|
||||
|
||||
});
|
||||
|
@ -129,7 +97,7 @@ describe("validateProps", () => {
|
|||
|
||||
const props = validProps();
|
||||
props.rowCount = "1";
|
||||
const errors = validateProps(validPropDef, props, [], true);
|
||||
const errors = validateProps(validComponentDef, props, [], true);
|
||||
expect(errors.length).toEqual(1);
|
||||
expect(errors[0].propName).toBe("rowCount");
|
||||
|
||||
|
@ -139,27 +107,17 @@ describe("validateProps", () => {
|
|||
|
||||
const props = validProps();
|
||||
props.size = "really_small";
|
||||
const errors = validateProps(validPropDef, props, [], true);
|
||||
const errors = validateProps(validComponentDef, props, [], true);
|
||||
expect(errors.length).toEqual(1);
|
||||
expect(errors[0].propName).toBe("size");
|
||||
|
||||
});
|
||||
|
||||
it("should return error with invalid array item", () => {
|
||||
|
||||
const props = validProps();
|
||||
props.columns[0].width = "seven";
|
||||
const errors = validateProps(validPropDef, props, [], true);
|
||||
expect(errors.length).toEqual(1);
|
||||
expect(errors[0].propName).toBe("width");
|
||||
|
||||
});
|
||||
|
||||
it("should not return error when has binding", () => {
|
||||
const props = validProps();
|
||||
props.columns[0].width = setBinding({path:"some_path"});
|
||||
props._children[0].width = setBinding({path:"some_path"});
|
||||
props.size = setBinding({path:"other path", fallback:"small"});
|
||||
const errors = validateProps(validPropDef, props, [], true);
|
||||
const errors = validateProps(validComponentDef, props, [], true);
|
||||
expect(errors.length).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
@ -167,64 +125,74 @@ describe("validateProps", () => {
|
|||
describe("recursivelyValidateProps", () => {
|
||||
|
||||
const rootComponent = {
|
||||
width: "number",
|
||||
child: "component",
|
||||
navitems: {
|
||||
type: "array",
|
||||
elementDefinition: {
|
||||
name: "string",
|
||||
icon: "component"
|
||||
}
|
||||
name: "rootComponent",
|
||||
children: true,
|
||||
props: {
|
||||
width: "number"
|
||||
}
|
||||
};
|
||||
|
||||
const todoListComponent = {
|
||||
showTitle: "bool",
|
||||
header: "component"
|
||||
name: "todoListComponent",
|
||||
props:{
|
||||
showTitle: "bool"
|
||||
}
|
||||
};
|
||||
|
||||
const headerComponent = {
|
||||
name: "headerComponent",
|
||||
props: {
|
||||
text: "string"
|
||||
}
|
||||
};
|
||||
|
||||
const iconComponent = {
|
||||
name: "iconComponent",
|
||||
props: {
|
||||
iconName: "string"
|
||||
}
|
||||
};
|
||||
|
||||
const navItemComponent = {
|
||||
name: "navItemComponent",
|
||||
props: {
|
||||
text: "string"
|
||||
}
|
||||
};
|
||||
|
||||
const getComponent = name => ({
|
||||
rootComponent,
|
||||
todoListComponent,
|
||||
headerComponent,
|
||||
iconComponent
|
||||
iconComponent,
|
||||
navItemComponent
|
||||
})[name];
|
||||
|
||||
const rootProps = () => ({
|
||||
_component: "rootComponent",
|
||||
width: 100,
|
||||
child: {
|
||||
_children: [{
|
||||
_component: "todoListComponent",
|
||||
showTitle: true,
|
||||
header: {
|
||||
_children : [
|
||||
{
|
||||
_component: "navItemComponent",
|
||||
text: "todos"
|
||||
},
|
||||
{
|
||||
_component: "headerComponent",
|
||||
text: "Your todo list"
|
||||
}
|
||||
},
|
||||
navitems: [
|
||||
{
|
||||
name: "Main",
|
||||
icon: {
|
||||
_component: "iconComponent",
|
||||
iconName:"fa fa-list"
|
||||
}
|
||||
iconName: "fa fa-list"
|
||||
},
|
||||
{
|
||||
name: "Settings",
|
||||
icon: {
|
||||
_component: "iconComponent",
|
||||
iconName:"fa fa-cog"
|
||||
}
|
||||
}
|
||||
]
|
||||
}]
|
||||
});
|
||||
|
||||
it("should return no errors for valid structure", () => {
|
||||
|
@ -245,38 +213,20 @@ describe("recursivelyValidateProps", () => {
|
|||
|
||||
it("should return error on first nested child component", () => {
|
||||
const root = rootProps();
|
||||
root.child.showTitle = "yeeeoooo";
|
||||
root._children[0].showTitle = "yeeeoooo";
|
||||
const result = recursivelyValidate(root, getComponent);
|
||||
expect(result.length).toBe(1);
|
||||
expect(result[0].stack).toEqual(["child"]);
|
||||
expect(result[0].stack).toEqual([0]);
|
||||
expect(result[0].propName).toBe("showTitle");
|
||||
});
|
||||
|
||||
it("should return error on second nested child component", () => {
|
||||
const root = rootProps();
|
||||
root.child.header.text = false;
|
||||
root._children[0]._children[0].text = false;
|
||||
const result = recursivelyValidate(root, getComponent);
|
||||
expect(result.length).toBe(1);
|
||||
expect(result[0].stack).toEqual(["child", "header"]);
|
||||
expect(result[0].stack).toEqual([0,0]);
|
||||
expect(result[0].propName).toBe("text");
|
||||
});
|
||||
|
||||
it("should return error on invalid array prop", () => {
|
||||
const root = rootProps();
|
||||
root.navitems[1].name = false;
|
||||
const result = recursivelyValidate(root, getComponent);
|
||||
expect(result.length).toBe(1);
|
||||
expect(result[0].propName).toBe("name");
|
||||
expect(result[0].stack).toEqual(["navitems[1]"]);
|
||||
});
|
||||
|
||||
it("should return error on invalid array child", () => {
|
||||
const root = rootProps();
|
||||
root.navitems[1].icon.iconName = false;
|
||||
const result = recursivelyValidate(root, getComponent);
|
||||
expect(result.length).toBe(1);
|
||||
expect(result[0].propName).toBe("iconName");
|
||||
expect(result[0].stack).toEqual(["navitems[1]", "icon"]);
|
||||
});
|
||||
|
||||
});
|
|
@ -15,20 +15,23 @@ import { isBound } from "./state/isState";
|
|||
|
||||
export const createApp = (componentLibraries, appDefinition, user) => {
|
||||
|
||||
const _initialiseComponent = (parentContext, hydrate) => (props, htmlElement, context, anchor=null) => {
|
||||
const _initialiseChildren = (parentContext, hydrate) => (childrenProps, htmlElement, context, anchor=null) => {
|
||||
|
||||
const {componentName, libName} = splitName(props._component);
|
||||
const childComponents = [];
|
||||
|
||||
for(let childProps of childrenProps) {
|
||||
const {componentName, libName} = splitName(childProps._component);
|
||||
|
||||
if(!componentName || !libName) return;
|
||||
|
||||
const {initialProps, bind} = setupBinding(
|
||||
store, props, coreApi,
|
||||
store, childProps, coreApi,
|
||||
context || parentContext, appDefinition.appRootPath);
|
||||
|
||||
|
||||
const componentProps = {
|
||||
...initialProps,
|
||||
_bb:bb(context || parentContext, props)
|
||||
_bb:bb(context || parentContext, childProps)
|
||||
};
|
||||
|
||||
const component = new (componentLibraries[libName][componentName])({
|
||||
|
@ -39,8 +42,10 @@ export const createApp = (componentLibraries, appDefinition, user) => {
|
|||
});
|
||||
|
||||
bind(component);
|
||||
childComponents.push(component);
|
||||
}
|
||||
|
||||
return component;
|
||||
return childComponents;
|
||||
}
|
||||
|
||||
const coreApi = createCoreApi(appDefinition, user);
|
||||
|
@ -86,10 +91,10 @@ export const createApp = (componentLibraries, appDefinition, user) => {
|
|||
}
|
||||
|
||||
const bb = (context, props) => ({
|
||||
hydrateComponent: _initialiseComponent(context, true),
|
||||
appendComponent: _initialiseComponent(context, false),
|
||||
insertComponent: (props, htmlElement, anchor, context) =>
|
||||
_initialiseComponent(context, false)(props, htmlElement, context, anchor),
|
||||
hydrateChildren: _initialiseChildren(context, true),
|
||||
appendChildren: _initialiseChildren(context, false),
|
||||
insertChildren: (props, htmlElement, anchor, context) =>
|
||||
_initialiseChildren(context, false)(props, htmlElement, context, anchor),
|
||||
store,
|
||||
relativeUrl,
|
||||
api,
|
||||
|
|
|
@ -34,8 +34,8 @@ export const loadBudibase = async (componentLibraries, props) => {
|
|||
}
|
||||
|
||||
const _app = createApp(componentLibraries, appDefinition, user);
|
||||
_app.hydrateComponent(
|
||||
props,
|
||||
_app.hydrateChildren(
|
||||
[props],
|
||||
document.body);
|
||||
|
||||
};
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,49 +1,46 @@
|
|||
main.svelte-15fmzor{height:100%;width:100%;font-family:"Roboto", Helvetica, Arial, sans-serif}
|
||||
.root.svelte-y7jhgd{height:100%;width:100%;display:flex;flex-direction:column}.top-nav.svelte-y7jhgd{flex:0 0 auto;height:25px;background:white;padding:5px;width:100%}.content.svelte-y7jhgd{flex:1 1 auto;width:100%;height:100px}.content.svelte-y7jhgd>div.svelte-y7jhgd{height:100%;width:100%}.topnavitem.svelte-y7jhgd{cursor:pointer;color:var(--secondary50);padding:0px 15px;font-weight:600;font-size:.9rem}.topnavitem.svelte-y7jhgd:hover{color:var(--secondary75);font-weight:600}.active.svelte-y7jhgd{color:var(--primary100);font-weight:900}
|
||||
.root.svelte-e4n7zy{position:fixed;margin:0 auto;text-align:center;top:20%;width:100%}.inner.svelte-e4n7zy{display:inline-block;margin:auto}.logo.svelte-e4n7zy{width:300px;margin-bottom:40px}.root.svelte-e4n7zy .option{width:250px}.app-link.svelte-e4n7zy{margin-top:10px;display:block}
|
||||
.root.svelte-y7jhgd{height:100%;width:100%;display:flex;flex-direction:column}.top-nav.svelte-y7jhgd{flex:0 0 auto;height:25px;background:white;padding:5px;width:100%}.content.svelte-y7jhgd{flex:1 1 auto;width:100%;height:100px}.content.svelte-y7jhgd>div.svelte-y7jhgd{height:100%;width:100%}.topnavitem.svelte-y7jhgd{cursor:pointer;color:var(--secondary50);padding:0px 15px;font-weight:600;font-size:.9rem}.topnavitem.svelte-y7jhgd:hover{color:var(--secondary75);font-weight:600}.active.svelte-y7jhgd{color:var(--primary100);font-weight:900}
|
||||
button.svelte-bxuckr{border-style:none;background-color:rgba(0,0,0,0);cursor:pointer;outline:none}button.svelte-bxuckr:hover{color:var(--hovercolor)}button.svelte-bxuckr:active{outline:none}
|
||||
.border-normal.svelte-vnon4v{border-radius:var(--borderradiusall)}.border-left.svelte-vnon4v{border-radius:var(--borderradius) 0 0 var(--borderradius)}.border-right.svelte-vnon4v{border-radius:0 var(--borderradius) var(--borderradius) 0}.border-middle.svelte-vnon4v{border-radius:0}button.svelte-vnon4v{border-style:solid;padding:7.5px 15px;cursor:pointer;margin:5px;border-radius:5px}.primary.svelte-vnon4v{background-color:var(--primary100);border-color:var(--primary100);color:var(--white)}.primary.svelte-vnon4v:hover{background-color:var(--primary75);border-color:var(--primary75)}.primary.svelte-vnon4v:active{background-color:var(--primarydark);border-color:var(--primarydark)}.primary-outline.svelte-vnon4v{background-color:var(--white);border-color:var(--primary100);color:var(--primary100)}.primary-outline.svelte-vnon4v:hover{background-color:var(--primary10)}.primary-outline.svelte-vnon4v:pressed{background-color:var(--primary25)}.secondary.svelte-vnon4v{background-color:var(--secondary100);border-color:var(--secondary100);color:var(--white)}.secondary.svelte-vnon4v:hover{background-color:var(--secondary75);border-color:var(--secondary75)}.secondary.svelte-vnon4v:pressed{background-color:var(--secondarydark);border-color:var(--secondarydark)}.secondary-outline.svelte-vnon4v{background-color:var(--white);border-color:var(--secondary100);color:var(--secondary100)}.secondary-outline.svelte-vnon4v:hover{background-color:var(--secondary10)}.secondary-outline.svelte-vnon4v:pressed{background-color:var(--secondary25)}.success.svelte-vnon4v{background-color:var(--success100);border-color:var(--success100);color:var(--white)}.success.svelte-vnon4v:hover{background-color:var(--success75);border-color:var(--success75)}.success.svelte-vnon4v:pressed{background-color:var(--successdark);border-color:var(--successdark)}.success-outline.svelte-vnon4v{background-color:var(--white);border-color:var(--success100);color:var(--success100)}.success-outline.svelte-vnon4v:hover{background-color:var(--success10)}.success-outline.svelte-vnon4v:pressed{background-color:var(--success25)}.deletion.svelte-vnon4v{background-color:var(--deletion100);border-color:var(--deletion100);color:var(--white)}.deletion.svelte-vnon4v:hover{background-color:var(--deletion75);border-color:var(--deletion75)}.deletion.svelte-vnon4v:pressed{background-color:var(--deletiondark);border-color:var(--deletiondark)}.deletion-outline.svelte-vnon4v{background-color:var(--white);border-color:var(--deletion100);color:var(--deletion100)}.deletion-outline.svelte-vnon4v:hover{background-color:var(--deletion10)}.deletion-outline.svelte-vnon4v:pressed{background-color:var(--deletion25)}
|
||||
.root.svelte-17zel0b{display:grid;grid-template-columns:250px 1fr 300px;height:100%;width:100%}.ui-nav.svelte-17zel0b{grid-column:1;background-color:var(--secondary5);height:100%}.preview-pane.svelte-17zel0b{grid-column:2}.components-pane.svelte-17zel0b{grid-column:3;background-color:var(--secondary5);min-height:0px;overflow-y:hidden}.pages-list-container.svelte-17zel0b{padding-top:2rem}.components-nav-header.svelte-17zel0b{font-size:.9rem}.nav-group-header.svelte-17zel0b{font-size:.9rem;padding-left:1rem}.nav-items-container.svelte-17zel0b{padding:1rem 1rem 0rem 1rem}.nav-group-header.svelte-17zel0b{display:grid;grid-template-columns:[icon] auto [title] 1fr [button] auto;padding:2rem 1rem 0rem 1rem;font-size:.9rem;font-weight:bold}.nav-group-header.svelte-17zel0b>div.svelte-17zel0b:nth-child(1){padding:0rem .5rem 0rem 0rem;vertical-align:bottom;grid-column-start:icon;margin-right:5px}.nav-group-header.svelte-17zel0b>span.svelte-17zel0b:nth-child(2){margin-left:5px;vertical-align:bottom;grid-column-start:title;margin-top:auto}.nav-group-header.svelte-17zel0b>div.svelte-17zel0b:nth-child(3){vertical-align:bottom;grid-column-start:button;cursor:pointer;color:var(--primary75)}.nav-group-header.svelte-17zel0b>div.svelte-17zel0b:nth-child(3):hover{color:var(--primary75)}
|
||||
.root.svelte-q8uz1n{height:100%;display:flex}.content.svelte-q8uz1n{flex:1 1 auto;height:100%;background-color:var(--white);margin:0}.nav.svelte-q8uz1n{flex:0 1 auto;width:300px;height:100%}
|
||||
.root.svelte-rjo9m0{display:grid;grid-template-columns:[uiNav] 250px [preview] auto [properties] 300px;height:100%;width:100%;overflow-y:auto}.ui-nav.svelte-rjo9m0{grid-column-start:uiNav;background-color:var(--secondary5);height:100%}.properties-pane.svelte-rjo9m0{grid-column-start:properties;background-color:var(--secondary5);height:100%;overflow-y:hidden}.pages-list-container.svelte-rjo9m0{padding-top:2rem}.components-nav-header.svelte-rjo9m0{font-size:.9rem}.nav-group-header.svelte-rjo9m0{font-size:.9rem;padding-left:1rem}.nav-items-container.svelte-rjo9m0{padding:1rem 1rem 0rem 1rem}.nav-group-header.svelte-rjo9m0{display:grid;grid-template-columns:[icon] auto [title] 1fr [button] auto;padding:2rem 1rem 0rem 1rem;font-size:.9rem;font-weight:bold}.nav-group-header.svelte-rjo9m0>div.svelte-rjo9m0:nth-child(1){padding:0rem .5rem 0rem 0rem;vertical-align:bottom;grid-column-start:icon;margin-right:5px}.nav-group-header.svelte-rjo9m0>span.svelte-rjo9m0:nth-child(2){margin-left:5px;vertical-align:bottom;grid-column-start:title;margin-top:auto}.nav-group-header.svelte-rjo9m0>div.svelte-rjo9m0:nth-child(3){vertical-align:bottom;grid-column-start:button;cursor:pointer;color:var(--primary75)}.nav-group-header.svelte-rjo9m0>div.svelte-rjo9m0:nth-child(3):hover{color:var(--primary75)}
|
||||
.root.svelte-117bbrk{padding-bottom:10px;padding-left:10px;font-size:.9rem;color:var(--secondary50);font-weight:bold}.hierarchy-item.svelte-117bbrk{cursor:pointer;padding:5px 0px}.hierarchy-item.svelte-117bbrk:hover{color:var(--secondary100)}.component.svelte-117bbrk{margin-left:5px}.selected.svelte-117bbrk{color:var(--primary100);font-weight:bold}.title.svelte-117bbrk{margin-left:10px}
|
||||
.uk-modal-dialog.svelte-91ta29{border-radius:.3rem}
|
||||
.root.svelte-1r2dipt{color:var(--secondary50);font-size:.9rem;font-weight:bold}.hierarchy-item.svelte-1r2dipt{cursor:pointer;padding:5px 0px}.hierarchy-item.svelte-1r2dipt:hover{color:var(--secondary)}.component.svelte-1r2dipt{margin-left:5px}.currentfolder.svelte-1r2dipt{color:var(--secondary100)}.selected.svelte-1r2dipt{color:var(--primary100);font-weight:bold}.title.svelte-1r2dipt{margin-left:10px}
|
||||
.root.svelte-r1aen3{height:100%;display:flex;flex-direction:column;border-style:solid;border-width:1px 0 0 0;border-color:var(--slate)}.title.svelte-r1aen3{padding:1rem;display:grid;grid-template-columns:[name] 1fr [actions] auto;color:var(--secondary100);font-size:.9rem;font-weight:bold}.title.svelte-r1aen3>div.svelte-r1aen3:nth-child(1){grid-column-start:name;color:var(--secondary100)}.title.svelte-r1aen3>div.svelte-r1aen3:nth-child(2){grid-column-start:actions}.component-props-container.svelte-r1aen3{flex:1 1 auto;overflow-y:auto}
|
||||
.section-container.svelte-yk1mmr{padding:15px;border-style:dotted;border-width:1px;border-color:var(--lightslate);border-radius:2px}.section-container.svelte-yk1mmr:nth-child(1){margin-bottom:15px}.row-text.svelte-yk1mmr{margin-right:15px;color:var(--primary100)}input.svelte-yk1mmr{margin-right:15px}p.svelte-yk1mmr>span.svelte-yk1mmr{margin-left:30px}.header.svelte-yk1mmr{display:grid;grid-template-columns:[title] 1fr [icon] auto}.header.svelte-yk1mmr>div.svelte-yk1mmr:nth-child(1){grid-column-start:title}.header.svelte-yk1mmr>div.svelte-yk1mmr:nth-child(2){grid-column-start:icon}
|
||||
.root.svelte-18ccx5u{display:flex;flex-direction:column}.library-header.svelte-18ccx5u{font-size:1.1em;border-color:var(--primary25);border-width:1px 0px;border-style:solid;background-color:var(--primary10);padding:5px 0;flex:0 0 auto}.library-container.svelte-18ccx5u{padding:0 0 10px 10px;flex:1 1 auto;min-height:0px}.inner-header.svelte-18ccx5u{font-size:0.9em;font-weight:bold;margin-top:7px;margin-bottom:3px}.component.svelte-18ccx5u{padding:2px 0px;cursor:pointer}.component.svelte-18ccx5u:hover{background-color:var(--lightslate)}.component.svelte-18ccx5u>.name.svelte-18ccx5u{color:var(--secondary100);display:inline-block}.component.svelte-18ccx5u>.description.svelte-18ccx5u{font-size:0.8em;color:var(--secondary75);display:inline-block;margin-left:10px}
|
||||
h1.svelte-11kb98w{font-size:1.2em}
|
||||
.component-container.svelte-12kdu9y{grid-row-start:middle;grid-column-start:middle;position:relative;overflow:hidden;padding-top:56.25%;margin:auto}.component-container.svelte-12kdu9y iframe.svelte-12kdu9y{border:0;height:100%;left:0;position:absolute;top:0;width:100%}
|
||||
h4.svelte-sqtlby{margin-top:20px}
|
||||
.root.svelte-wfv60d{height:100%;position:relative;padding:1.5rem}.actions-header.svelte-wfv60d{flex:0 1 auto}.node-view.svelte-wfv60d{overflow-y:auto;flex:1 1 auto}
|
||||
.root.svelte-1ersoxu{padding:15px}.help-text.svelte-1ersoxu{color:var(--slate);font-size:10pt}
|
||||
.items-root.svelte-19lmivt{display:flex;flex-direction:column;max-height:100%;height:100%;background-color:var(--secondary5)}.nav-group-header.svelte-19lmivt{display:grid;grid-template-columns:[icon] auto [title] 1fr [button] auto;padding:2rem 1rem 0rem 1rem;font-size:.9rem;font-weight:bold}.nav-group-header.svelte-19lmivt>div.svelte-19lmivt:nth-child(1){padding:0rem .7rem 0rem 0rem;vertical-align:bottom;grid-column-start:icon;margin-right:5px}.nav-group-header.svelte-19lmivt>div.svelte-19lmivt:nth-child(2){margin-left:5px;vertical-align:bottom;grid-column-start:title;margin-top:auto}.nav-group-header.svelte-19lmivt>div.svelte-19lmivt:nth-child(3){vertical-align:bottom;grid-column-start:button;cursor:pointer;color:var(--primary75)}.nav-group-header.svelte-19lmivt>div.svelte-19lmivt:nth-child(3):hover{color:var(--primary75)}.hierarchy-title.svelte-19lmivt{flex:auto 1 1}.hierarchy.svelte-19lmivt{display:flex;flex-direction:column;flex:1 0 auto;height:100px}.hierarchy-items-container.svelte-19lmivt{flex:1 1 auto;overflow-y:auto}
|
||||
.root.svelte-wfv60d{height:100%;position:relative;padding:1.5rem}.actions-header.svelte-wfv60d{flex:0 1 auto}.node-view.svelte-wfv60d{overflow-y:auto;flex:1 1 auto}
|
||||
.root.svelte-nd1yft{height:100%;position:relative;padding:1.5rem}
|
||||
.root.svelte-apja7r{height:100%;position:relative}.actions-header.svelte-apja7r{flex:0 1 auto}.node-view.svelte-apja7r{overflow-y:auto;flex:1 1 auto}
|
||||
.root.svelte-117bbrk{padding-bottom:10px;padding-left:10px;font-size:.9rem;color:var(--secondary50);font-weight:bold}.hierarchy-item.svelte-117bbrk{cursor:pointer;padding:5px 0px}.hierarchy-item.svelte-117bbrk:hover{color:var(--secondary100)}.component.svelte-117bbrk{margin-left:5px}.selected.svelte-117bbrk{color:var(--primary100);font-weight:bold}.title.svelte-117bbrk{margin-left:10px}
|
||||
h1.svelte-16jkjx9{font-size:1.2em}
|
||||
.root.svelte-1r2dipt{color:var(--secondary50);font-size:.9rem;font-weight:bold}.hierarchy-item.svelte-1r2dipt{cursor:pointer;padding:5px 0px}.hierarchy-item.svelte-1r2dipt:hover{color:var(--secondary)}.component.svelte-1r2dipt{margin-left:5px}.currentfolder.svelte-1r2dipt{color:var(--secondary100)}.selected.svelte-1r2dipt{color:var(--primary100);font-weight:bold}.title.svelte-1r2dipt{margin-left:10px}
|
||||
.uk-modal-dialog.svelte-vwwrf9{border-radius:.3rem}
|
||||
.root.svelte-1abif7s{height:100%;display:flex;flex-direction:column}.padding.svelte-1abif7s{padding:1rem 1rem 0rem 1rem}.info-text.svelte-1abif7s{color:var(--secondary100);font-size:.8rem !important;font-weight:bold}.title.svelte-1abif7s{padding:2rem 1rem 1rem 1rem;display:grid;grid-template-columns:[name] 1fr [actions] auto;color:var(--secondary100);font-size:.9rem;font-weight:bold}.title.svelte-1abif7s>div.svelte-1abif7s:nth-child(1){grid-column-start:name;color:var(--secondary100)}.title.svelte-1abif7s>div.svelte-1abif7s:nth-child(2){grid-column-start:actions}.section-header.svelte-1abif7s{display:grid;grid-template-columns:[name] 1fr [actions] auto;color:var(--secondary50);font-size:.9rem;font-weight:bold;vertical-align:middle}.component-props-container.svelte-1abif7s{flex:1 1 auto;overflow-y:auto}
|
||||
.root.svelte-1ersoxu{padding:15px}.help-text.svelte-1ersoxu{color:var(--slate);font-size:10pt}
|
||||
.section-container.svelte-yk1mmr{padding:15px;border-style:dotted;border-width:1px;border-color:var(--lightslate);border-radius:2px}.section-container.svelte-yk1mmr:nth-child(1){margin-bottom:15px}.row-text.svelte-yk1mmr{margin-right:15px;color:var(--primary100)}input.svelte-yk1mmr{margin-right:15px}p.svelte-yk1mmr>span.svelte-yk1mmr{margin-left:30px}.header.svelte-yk1mmr{display:grid;grid-template-columns:[title] 1fr [icon] auto}.header.svelte-yk1mmr>div.svelte-yk1mmr:nth-child(1){grid-column-start:title}.header.svelte-yk1mmr>div.svelte-yk1mmr:nth-child(2){grid-column-start:icon}
|
||||
.component-container.svelte-teqoiq{grid-row-start:middle;grid-column-start:middle;position:relative;overflow:hidden;padding-top:56.25%;margin:auto}.component-container.svelte-teqoiq iframe.svelte-teqoiq{border:0;height:100%;left:0;position:absolute;top:0;width:100%}
|
||||
.root.svelte-x3bf9z{display:flex}.root.svelte-x3bf9z:last-child{border-radius:0 var(--borderradius) var(--borderradius) 0}.root.svelte-x3bf9z:first-child{border-radius:var(--borderradius) 0 0 var(--borderradius)}.root.svelte-x3bf9z:not(:first-child):not(:last-child){border-radius:0}
|
||||
.edit-button.svelte-zm41av{cursor:pointer;color:var(--secondary25)}.title.svelte-zm41av{margin:3rem 0rem 0rem 0rem;font-weight:700}.table-content.svelte-zm41av{font-weight:500;font-size:.9rem}tr.svelte-zm41av:hover .edit-button.svelte-zm41av{color:var(--secondary75)}
|
||||
.dropdown-background.svelte-11ifkop{position:fixed;top:0;left:0;width:100vw;height:100vh}.root.svelte-11ifkop{cursor:pointer;z-index:1}.dropdown-content.svelte-11ifkop{position:absolute;background-color:var(--white);min-width:160px;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);z-index:1;font-weight:normal;border-style:solid;border-width:1px;border-color:var(--secondary10)}.dropdown-content.svelte-11ifkop:not(:focus){display:none}.action-row.svelte-11ifkop{padding:7px 10px;cursor:pointer}.action-row.svelte-11ifkop:hover{background-color:var(--primary100);color:var(--white)}
|
||||
.edit-button.svelte-lhfdtn{cursor:pointer;color:var(--secondary25)}tr.svelte-lhfdtn:hover .edit-button.svelte-lhfdtn{color:var(--secondary75)}.title.svelte-lhfdtn{margin:3rem 0rem 0rem 0rem;font-weight:700}.table-content.svelte-lhfdtn{font-weight:500;font-size:.9rem}
|
||||
.root.svelte-17ju2r{display:block;font-size:.9rem;width:100%;cursor:pointer;color:var(--secondary50);font-weight:500}.title.svelte-17ju2r{padding-top:.5rem;padding-right:.5rem}.title.svelte-17ju2r:hover{background-color:var(--secondary10)}.active.svelte-17ju2r{background-color:var(--primary10)}
|
||||
.library-header.svelte-chhyel{font-size:1.1em;border-color:var(--primary25);border-width:1px 0px;border-style:solid;background-color:var(--primary10);padding:5px 0}.library-container.svelte-chhyel{padding:0 0 10px 10px}.inner-header.svelte-chhyel{font-size:0.9em;font-weight:bold;margin-top:7px;margin-bottom:3px}.component.svelte-chhyel{padding:2px 0px;cursor:pointer}.component.svelte-chhyel:hover{background-color:var(--lightslate)}.component.svelte-chhyel>.name.svelte-chhyel{color:var(--secondary100);display:inline-block}.component.svelte-chhyel>.description.svelte-chhyel{font-size:0.8em;color:var(--secondary75);display:inline-block;margin-left:10px}
|
||||
.info-text.svelte-1gx0gkl{font-size:0.7rem;color:var(--secondary50)}
|
||||
.root.svelte-t6vms4{font-size:10pt;width:100%}.form-root.svelte-t6vms4{display:flex;flex-wrap:wrap}.prop-container.svelte-t6vms4{flex:1 1 auto;min-width:250px}
|
||||
.nav-item.svelte-1i5jqm7{padding:1.5rem 1rem 0rem 1rem;font-size:.9rem;font-weight:bold;cursor:pointer;flex:0 0 auto}.nav-item.svelte-1i5jqm7:hover{background-color:var(--primary10)}.active.svelte-1i5jqm7{background-color:var(--primary10)}
|
||||
.root.svelte-18xd5y3{height:100%;padding:2rem}.settings-title.svelte-18xd5y3{font-weight:700}.title.svelte-18xd5y3{margin:3rem 0rem 0rem 0rem;font-weight:700}.recordkey.svelte-18xd5y3{font-size:14px;font-weight:600;color:var(--primary100)}.fields-table.svelte-18xd5y3{margin:1rem 1rem 0rem 0rem;border-collapse:collapse}.add-field-button.svelte-18xd5y3{cursor:pointer}.edit-button.svelte-18xd5y3{cursor:pointer;color:var(--secondary25)}.edit-button.svelte-18xd5y3:hover{cursor:pointer;color:var(--secondary75)}th.svelte-18xd5y3{text-align:left}td.svelte-18xd5y3{padding:1rem 5rem 1rem 0rem;margin:0;font-size:14px;font-weight:500}.field-label.svelte-18xd5y3{font-size:14px;font-weight:500}thead.svelte-18xd5y3>tr.svelte-18xd5y3{border-width:0px 0px 1px 0px;border-style:solid;border-color:var(--secondary75);margin-bottom:20px}tbody.svelte-18xd5y3>tr.svelte-18xd5y3{border-width:0px 0px 1px 0px;border-style:solid;border-color:var(--primary10)}tbody.svelte-18xd5y3>tr.svelte-18xd5y3:hover{background-color:var(--primary10)}tbody.svelte-18xd5y3>tr:hover .edit-button.svelte-18xd5y3{color:var(--secondary75)}.index-container.svelte-18xd5y3{border-style:solid;border-width:0 0 1px 0;border-color:var(--secondary25);padding:10px;margin-bottom:5px}.index-label.svelte-18xd5y3{color:var(--slate)}.index-name.svelte-18xd5y3{font-weight:bold;color:var(--primary100)}.index-container.svelte-18xd5y3 code.svelte-18xd5y3{margin:0;display:inline;background-color:var(--primary10);color:var(--secondary100);padding:3px}.index-field-row.svelte-18xd5y3{margin:1rem 0rem 0rem 0rem}.no-indexes.svelte-18xd5y3{margin:1rem 0rem 0rem 0rem;font-family:var(--fontnormal);font-size:14px}
|
||||
.dropdown-background.svelte-11ifkop{position:fixed;top:0;left:0;width:100vw;height:100vh}.root.svelte-11ifkop{cursor:pointer;z-index:1}.dropdown-content.svelte-11ifkop{position:absolute;background-color:var(--white);min-width:160px;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);z-index:1;font-weight:normal;border-style:solid;border-width:1px;border-color:var(--secondary10)}.dropdown-content.svelte-11ifkop:not(:focus){display:none}.action-row.svelte-11ifkop{padding:7px 10px;cursor:pointer}.action-row.svelte-11ifkop:hover{background-color:var(--primary100);color:var(--white)}
|
||||
.root.svelte-17ju2r{display:block;font-size:.9rem;width:100%;cursor:pointer;color:var(--secondary50);font-weight:500}.title.svelte-17ju2r{padding-top:.5rem;padding-right:.5rem}.title.svelte-17ju2r:hover{background-color:var(--secondary10)}.active.svelte-17ju2r{background-color:var(--primary10)}
|
||||
.root.svelte-ehsf0i{display:block;font-size:.9rem;width:100%;cursor:pointer;font-weight:bold}.title.svelte-ehsf0i{font:var(--fontblack);padding-top:10px;padding-right:5px;padding-bottom:10px;color:var(--secondary100)}.title.svelte-ehsf0i:hover{background-color:var(--secondary10)}
|
||||
.edit-button.svelte-zm41av{cursor:pointer;color:var(--secondary25)}.title.svelte-zm41av{margin:3rem 0rem 0rem 0rem;font-weight:700}.table-content.svelte-zm41av{font-weight:500;font-size:.9rem}tr.svelte-zm41av:hover .edit-button.svelte-zm41av{color:var(--secondary75)}
|
||||
.edit-button.svelte-lhfdtn{cursor:pointer;color:var(--secondary25)}tr.svelte-lhfdtn:hover .edit-button.svelte-lhfdtn{color:var(--secondary75)}.title.svelte-lhfdtn{margin:3rem 0rem 0rem 0rem;font-weight:700}.table-content.svelte-lhfdtn{font-weight:500;font-size:.9rem}
|
||||
.root.svelte-wgyofl{padding:1.5rem;width:100%;align-items:right}
|
||||
.root.svelte-pq2tmv{height:100%;padding:15px}.allowed-records.svelte-pq2tmv{margin:20px 0px}.allowed-records.svelte-pq2tmv>span.svelte-pq2tmv{margin-right:30px}
|
||||
.info-text.svelte-1gx0gkl{font-size:0.7rem;color:var(--secondary50)}
|
||||
.library-header.svelte-chhyel{font-size:1.1em;border-color:var(--primary25);border-width:1px 0px;border-style:solid;background-color:var(--primary10);padding:5px 0}.library-container.svelte-chhyel{padding:0 0 10px 10px}.inner-header.svelte-chhyel{font-size:0.9em;font-weight:bold;margin-top:7px;margin-bottom:3px}.component.svelte-chhyel{padding:2px 0px;cursor:pointer}.component.svelte-chhyel:hover{background-color:var(--lightslate)}.component.svelte-chhyel>.name.svelte-chhyel{color:var(--secondary100);display:inline-block}.component.svelte-chhyel>.description.svelte-chhyel{font-size:0.8em;color:var(--secondary75);display:inline-block;margin-left:10px}
|
||||
.component.svelte-3sgo90{padding:5px 0}.component.svelte-3sgo90 .title.svelte-3sgo90{width:300px
|
||||
}.component.svelte-3sgo90>.description.svelte-3sgo90{font-size:0.8em;color:var(--secondary75)}.button-container.svelte-3sgo90{text-align:right;margin-top:20px}.error.svelte-3sgo90{font-size:10pt;color:red}
|
||||
.root.svelte-47ohpz{font-size:10pt}.padding.svelte-47ohpz{padding:0 10px}.inherited-title.svelte-47ohpz{padding:1rem 1rem 1rem 1rem;display:grid;grid-template-columns:[name] 1fr [actions] auto;color:var(--secondary100);font-size:.9rem;font-weight:bold}.inherited-title.svelte-47ohpz>div.svelte-47ohpz:nth-child(1){grid-column-start:name;color:var(--secondary50)}.inherited-title.svelte-47ohpz>div.svelte-47ohpz:nth-child(2){grid-column-start:actions;color:var(--secondary100)}
|
||||
.title.svelte-dhe1ge{padding:3px;background-color:white;color:var(--secondary100);border-style:solid;border-width:1px 0 0 0;border-color:var(--lightslate)}.title.svelte-dhe1ge>span.svelte-dhe1ge{margin-left:10px}
|
||||
.root.svelte-16sjty9{padding:2rem;border-radius:2rem}.uk-grid-small.svelte-16sjty9{padding:1rem}.option-container.svelte-16sjty9{border-style:dotted;border-width:1px;border-color:var(--primary75);padding:3px;margin-right:5px}
|
||||
.root.svelte-1hs1zh2{height:100%;padding:2rem}.settings-title.svelte-1hs1zh2{font-weight:700}.title.svelte-1hs1zh2{margin:3rem 0rem 0rem 0rem;font-weight:700}.recordkey.svelte-1hs1zh2{font-size:14px;font-weight:600;color:var(--primary100)}.fields-table.svelte-1hs1zh2{margin:1rem 1rem 0rem 0rem;border-collapse:collapse}.add-field-button.svelte-1hs1zh2{cursor:pointer}.edit-button.svelte-1hs1zh2{cursor:pointer;color:var(--secondary25)}.edit-button.svelte-1hs1zh2:hover{cursor:pointer;color:var(--secondary75)}th.svelte-1hs1zh2{text-align:left}td.svelte-1hs1zh2{padding:1rem 5rem 1rem 0rem;margin:0;font-size:14px;font-weight:500}.field-label.svelte-1hs1zh2{font-size:14px;font-weight:500}thead.svelte-1hs1zh2>tr.svelte-1hs1zh2{border-width:0px 0px 1px 0px;border-style:solid;border-color:var(--secondary75);margin-bottom:20px}tbody.svelte-1hs1zh2>tr.svelte-1hs1zh2{border-width:0px 0px 1px 0px;border-style:solid;border-color:var(--primary10)}tbody.svelte-1hs1zh2>tr.svelte-1hs1zh2:hover{background-color:var(--primary10)}tbody.svelte-1hs1zh2>tr:hover .edit-button.svelte-1hs1zh2{color:var(--secondary75)}.index-container.svelte-1hs1zh2{border-style:solid;border-width:0 0 1px 0;border-color:var(--secondary25);padding:10px;margin-bottom:5px}.index-label.svelte-1hs1zh2{color:var(--slate)}.index-name.svelte-1hs1zh2{font-weight:bold;color:var(--primary100)}.index-container.svelte-1hs1zh2 code.svelte-1hs1zh2{margin:0;display:inline;background-color:var(--primary10);color:var(--secondary100);padding:3px}.index-field-row.svelte-1hs1zh2{margin:1rem 0rem 0rem 0rem}.no-indexes.svelte-1hs1zh2{margin:1rem 0rem 0rem 0rem;font-family:var(--fontnormal);font-size:14px}
|
||||
input.svelte-9fre0g{margin-right:7px}
|
||||
.error-container.svelte-ole1mk{padding:10px;border-style:solid;border-color:var(--deletion100);border-radius:var(--borderradiusall);background:var(--deletion75)}.error-row.svelte-ole1mk{padding:5px 0px}
|
||||
textarea.svelte-di7k4b{padding:3px;margin-top:5px;margin-bottom:10px;background:var(--lightslate);color:var(--white);font-family:'Courier New', Courier, monospace;width:95%;height:100px;border-radius:5px}
|
||||
.root.svelte-1v0yya9{padding:1rem 1rem 0rem 1rem}.prop-label.svelte-1v0yya9{font-size:0.8rem;color:var(--secondary100);font-weight:bold}
|
||||
.root.svelte-ogh8o0{display:grid;grid-template-columns:[name] 1fr [actions] auto}.root.svelte-ogh8o0>div.svelte-ogh8o0:nth-child(1){grid-column-start:name;color:var(--secondary50)}.root.svelte-ogh8o0>div.svelte-ogh8o0:nth-child(2){grid-column-start:actions}.selectedname.svelte-ogh8o0{font-weight:bold;color:var(--secondary)}
|
||||
textarea.svelte-1kv2xk7{width:300px;height:200px}
|
||||
.error-container.svelte-ole1mk{padding:10px;border-style:solid;border-color:var(--deletion100);border-radius:var(--borderradiusall);background:var(--deletion75)}.error-row.svelte-ole1mk{padding:5px 0px}
|
||||
.root.svelte-16sjty9{padding:2rem;border-radius:2rem}.uk-grid-small.svelte-16sjty9{padding:1rem}.option-container.svelte-16sjty9{border-style:dotted;border-width:1px;border-color:var(--primary75);padding:3px;margin-right:5px}
|
||||
textarea.svelte-di7k4b{padding:3px;margin-top:5px;margin-bottom:10px;background:var(--lightslate);color:var(--white);font-family:'Courier New', Courier, monospace;width:95%;height:100px;border-radius:5px}
|
||||
.addelement-container.svelte-r1ft9p{cursor:pointer;padding:3px 0px;text-align:center}.addelement-container.svelte-r1ft9p:hover{background-color:var(--primary25);margin-top:5px}.control-container.svelte-r1ft9p{padding-left:3px;background:var(--secondary10)}.separator.svelte-r1ft9p{width:60%;margin:10px auto;border-style:solid;border-width:1px 0 0 0;border-color:var(--primary25)}
|
||||
.unbound-container.svelte-jubmd5{display:flex;margin:.5rem 0rem .5rem 0rem}.unbound-container.svelte-jubmd5>.svelte-jubmd5:nth-child(1){width:auto;flex:1 0 auto;font-size:0.8rem;color:var(--secondary100);border-radius:.2rem}.bound-header.svelte-jubmd5{display:flex}.bound-header.svelte-jubmd5>div.svelte-jubmd5:nth-child(1){flex:1 0 auto;width:30px;color:var(--secondary50);padding-left:5px}.binding-prop-label.svelte-jubmd5{color:var(--secondary50)}
|
||||
.addelement-container.svelte-199q8jr{cursor:pointer;padding:3px 0px;text-align:center}.addelement-container.svelte-199q8jr:hover{background-color:var(--primary25)}.item-container.svelte-199q8jr{padding-left:3px;background:var(--secondary10)}
|
||||
textarea.svelte-1kv2xk7{width:300px;height:200px}
|
||||
.type-selector-container.svelte-1b6pj9u{display:flex}.type-selector.svelte-1b6pj9u{border-color:var(--primary50);border-radius:2px;width:50px;flex:1 0 auto}
|
||||
.root.svelte-rj4q22{height:100%;display:flex;flex-direction:column}.switcher.svelte-rj4q22{flex:0 0 auto}.switcher.svelte-rj4q22>button.svelte-rj4q22{display:inline-block;background-color:rgba(0,0,0,0);border-style:solid;border-color:var(--slate);margin:5px;padding:5px;cursor:pointer}.switcher.svelte-rj4q22>.selected.svelte-rj4q22{background-color:red}.panel.svelte-rj4q22{flex:1 1 auto;height:0px;overflow-y:auto}
|
||||
|
||||
/*# sourceMappingURL=bundle.css.map */
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -6,12 +6,12 @@ const { resolve } = require("path");
|
|||
const send = require('koa-send');
|
||||
const {
|
||||
getPackageForBuilder,
|
||||
getRootComponents,
|
||||
getComponents,
|
||||
savePackage,
|
||||
getApps,
|
||||
saveDerivedComponent,
|
||||
renameDerivedComponent,
|
||||
deleteDerivedComponent,
|
||||
saveScreen,
|
||||
renameScreen,
|
||||
deleteScreen,
|
||||
componentLibraryInfo
|
||||
} = require("../utilities/builder");
|
||||
|
||||
|
@ -162,9 +162,9 @@ module.exports = (config, app) => {
|
|||
ctx.request.body);
|
||||
ctx.response.status = StatusCodes.OK;
|
||||
})
|
||||
.get("/_builder/api/:appname/rootcomponents", async (ctx) => {
|
||||
.get("/_builder/api/:appname/components", async (ctx) => {
|
||||
try {
|
||||
ctx.body = getRootComponents(
|
||||
ctx.body = getComponents(
|
||||
config,
|
||||
ctx.params.appname,
|
||||
ctx.query.lib);
|
||||
|
@ -194,26 +194,26 @@ module.exports = (config, app) => {
|
|||
ctx.body = info.generators;
|
||||
ctx.response.status = StatusCodes.OK;
|
||||
})
|
||||
.post("/_builder/api/:appname/derivedcomponent", async (ctx) => {
|
||||
await saveDerivedComponent(
|
||||
.post("/_builder/api/:appname/screen", async (ctx) => {
|
||||
await saveScreen(
|
||||
config,
|
||||
ctx.params.appname,
|
||||
ctx.request.body);
|
||||
ctx.response.status = StatusCodes.OK;
|
||||
})
|
||||
.patch("/_builder/api/:appname/derivedcomponent", async (ctx) => {
|
||||
await renameDerivedComponent(
|
||||
.patch("/_builder/api/:appname/screen", async (ctx) => {
|
||||
await renameScreen(
|
||||
config,
|
||||
ctx.params.appname,
|
||||
ctx.request.body.oldname,
|
||||
ctx.request.body.newname);
|
||||
ctx.response.status = StatusCodes.OK;
|
||||
})
|
||||
.delete("/_builder/api/:appname/derivedcomponent/*", async (ctx) => {
|
||||
.delete("/_builder/api/:appname/screen/*", async (ctx) => {
|
||||
const name = ctx.request.path.replace(
|
||||
`/_builder/api/${ctx.params.appname}/derivedcomponent/`, "");
|
||||
`/_builder/api/${ctx.params.appname}/screen/`, "");
|
||||
|
||||
await deleteDerivedComponent(
|
||||
await deleteScreen(
|
||||
config,
|
||||
ctx.params.appname,
|
||||
decodeURI(name));
|
||||
|
|
|
@ -5,8 +5,8 @@ const testPages = require("../appPackages/testApp/pages.json");
|
|||
const testComponents = require("../appPackages/testApp/customComponents/components.json");
|
||||
const testMoreComponents = require("../appPackages/testApp/moreCustomComponents/components.json");
|
||||
const statusCodes = require("../utilities/statusCodes");
|
||||
const derivedComponent1 = require("../appPackages/testApp/components/myTextBox.json");
|
||||
const derivedComponent2 = require("../appPackages/testApp/components/subfolder/otherTextBox.json");
|
||||
const screen1 = require("../appPackages/testApp/components/myTextBox.json");
|
||||
const screen2 = require("../appPackages/testApp/components/subfolder/otherTextBox.json");
|
||||
const { readJSON, pathExists, unlink } = require("fs-extra");
|
||||
|
||||
const app = require("./testApp")();
|
||||
|
@ -49,36 +49,36 @@ it("/apppackage should get pages", async () => {
|
|||
expect(body.pages).toEqual(testPages);
|
||||
});
|
||||
|
||||
it("/apppackage should get rootComponents", async () => {
|
||||
it("/apppackage should get components", async () => {
|
||||
|
||||
const {body} = await app.get("/_builder/api/testApp/appPackage")
|
||||
.expect(statusCodes.OK);
|
||||
|
||||
expect(body.rootComponents["./customComponents/textbox"]).toBeDefined();
|
||||
expect(body.rootComponents["./moreCustomComponents/textbox"]).toBeDefined();
|
||||
expect(body.components["./customComponents/textbox"]).toBeDefined();
|
||||
expect(body.components["./moreCustomComponents/textbox"]).toBeDefined();
|
||||
|
||||
expect(body.rootComponents["./customComponents/textbox"])
|
||||
expect(body.components["./customComponents/textbox"])
|
||||
.toEqual(testComponents.textbox);
|
||||
|
||||
expect(body.rootComponents["./moreCustomComponents/textbox"])
|
||||
expect(body.components["./moreCustomComponents/textbox"])
|
||||
.toEqual(testMoreComponents.textbox);
|
||||
});
|
||||
|
||||
it("/apppackage should get derivedComponents", async () => {
|
||||
it("/apppackage should get screens", async () => {
|
||||
|
||||
const {body} = await app.get("/_builder/api/testApp/appPackage")
|
||||
.expect(statusCodes.OK);
|
||||
|
||||
const expectedComponents = {
|
||||
"myTextBox" : {...derivedComponent1, name:"myTextBox"},
|
||||
"subfolder/otherTextBox": {...derivedComponent2, name:"subfolder/otherTextBox"}
|
||||
"myTextBox" : {...screen1, name:"myTextBox"},
|
||||
"subfolder/otherTextBox": {...screen2, name:"subfolder/otherTextBox"}
|
||||
};
|
||||
|
||||
expect(body.derivedComponents).toEqual(expectedComponents);
|
||||
expect(body.screens).toEqual(expectedComponents);
|
||||
});
|
||||
|
||||
it("should be able to create new derived component", async () => {
|
||||
const newDerivedComponent = {
|
||||
const newscreen = {
|
||||
name: "newTextBox",
|
||||
inherits: "./customComponents/textbox",
|
||||
props: {
|
||||
|
@ -86,17 +86,17 @@ it("should be able to create new derived component", async () => {
|
|||
}
|
||||
};
|
||||
|
||||
await app.post("/_builder/api/testApp/derivedcomponent", newDerivedComponent)
|
||||
await app.post("/_builder/api/testApp/screen", newscreen)
|
||||
.expect(statusCodes.OK);
|
||||
|
||||
const componentFile = "./appPackages/testApp/components/newTextBox.json";
|
||||
expect(await pathExists(componentFile)).toBe(true);
|
||||
expect(await readJSON(componentFile)).toEqual(newDerivedComponent);
|
||||
expect(await readJSON(componentFile)).toEqual(newscreen);
|
||||
|
||||
});
|
||||
|
||||
it("should be able to update derived component", async () => {
|
||||
const updatedDerivedComponent = {
|
||||
const updatedscreen = {
|
||||
name: "newTextBox",
|
||||
inherits: "./customComponents/textbox",
|
||||
props: {
|
||||
|
@ -104,15 +104,15 @@ it("should be able to update derived component", async () => {
|
|||
}
|
||||
};
|
||||
|
||||
await app.post("/_builder/api/testApp/derivedcomponent", updatedDerivedComponent)
|
||||
await app.post("/_builder/api/testApp/screen", updatedscreen)
|
||||
.expect(statusCodes.OK);
|
||||
|
||||
const componentFile = "./appPackages/testApp/components/newTextBox.json";
|
||||
expect(await readJSON(componentFile)).toEqual(updatedDerivedComponent);
|
||||
expect(await readJSON(componentFile)).toEqual(updatedscreen);
|
||||
});
|
||||
|
||||
it("should be able to rename derived component", async () => {
|
||||
await app.patch("/_builder/api/testApp/derivedcomponent", {
|
||||
await app.patch("/_builder/api/testApp/screen", {
|
||||
oldname: "newTextBox", newname: "anotherSubFolder/newTextBox"
|
||||
}).expect(statusCodes.OK);
|
||||
|
||||
|
@ -124,7 +124,7 @@ it("should be able to rename derived component", async () => {
|
|||
});
|
||||
|
||||
it("should be able to delete derived component", async () => {
|
||||
await app.delete("/_builder/api/testApp/derivedcomponent/anotherSubFolder/newTextBox")
|
||||
await app.delete("/_builder/api/testApp/screen/anotherSubFolder/newTextBox")
|
||||
.expect(statusCodes.OK);
|
||||
|
||||
const componentFile = "./appPackages/testApp/components/anotherSubFolder/newTextBox.json";
|
||||
|
|
|
@ -37,10 +37,10 @@ module.exports.getPackageForBuilder = async (config, appname) => {
|
|||
|
||||
pages,
|
||||
|
||||
rootComponents: await getRootComponents(appPath, pages),
|
||||
components: await getComponents(appPath, pages),
|
||||
|
||||
derivedComponents: keyBy("name")(
|
||||
await fetchDerivedComponents(appPath))
|
||||
screens: keyBy("name")(
|
||||
await fetchscreens(appPath))
|
||||
});
|
||||
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ module.exports.getApps = async (config, master) => {
|
|||
const componentPath = (appPath, name) =>
|
||||
join(appPath, "components", name + ".json");
|
||||
|
||||
module.exports.saveDerivedComponent = async (config, appname, component) => {
|
||||
module.exports.saveScreen = async (config, appname, component) => {
|
||||
const appPath = appPackageFolder(config, appname);
|
||||
const compPath = componentPath(appPath, component.name);
|
||||
await ensureDir(dirname(compPath));
|
||||
|
@ -70,7 +70,7 @@ module.exports.saveDerivedComponent = async (config, appname, component) => {
|
|||
{encoding:"utf8", flag:"w", spaces:2});
|
||||
}
|
||||
|
||||
module.exports.renameDerivedComponent = async (config, appname, oldName, newName) => {
|
||||
module.exports.renameScreen = async (config, appname, oldName, newName) => {
|
||||
const appPath = appPackageFolder(config, appname);
|
||||
|
||||
const oldComponentPath = componentPath(
|
||||
|
@ -85,7 +85,7 @@ module.exports.renameDerivedComponent = async (config, appname, oldName, newName
|
|||
newComponentPath);
|
||||
}
|
||||
|
||||
module.exports.deleteDerivedComponent = async (config, appname, name) => {
|
||||
module.exports.deleteScreen = async (config, appname, name) => {
|
||||
const appPath = appPackageFolder(config, appname);
|
||||
const componentFile = componentPath(appPath, name);
|
||||
await unlink(componentFile);
|
||||
|
@ -102,7 +102,7 @@ module.exports.componentLibraryInfo = async (config, appname, lib) => {
|
|||
};
|
||||
|
||||
|
||||
const getRootComponents = async (appPath, pages ,lib) => {
|
||||
const getComponents = async (appPath, pages ,lib) => {
|
||||
|
||||
let libs;
|
||||
if(!lib) {
|
||||
|
@ -131,7 +131,7 @@ const getRootComponents = async (appPath, pages ,lib) => {
|
|||
return {components, generators};
|
||||
}
|
||||
|
||||
const fetchDerivedComponents = async (appPath, relativePath = "") => {
|
||||
const fetchscreens = async (appPath, relativePath = "") => {
|
||||
|
||||
const currentDir = join(appPath, "components", relativePath);
|
||||
|
||||
|
@ -159,7 +159,7 @@ const fetchDerivedComponents = async (appPath, relativePath = "") => {
|
|||
|
||||
components.push(component);
|
||||
} else {
|
||||
const childComponents = await fetchDerivedComponents(
|
||||
const childComponents = await fetchscreens(
|
||||
appPath, join(relativePath, item)
|
||||
);
|
||||
|
||||
|
@ -172,4 +172,4 @@ const fetchDerivedComponents = async (appPath, relativePath = "") => {
|
|||
return components;
|
||||
}
|
||||
|
||||
module.exports.getRootComponents = getRootComponents;
|
||||
module.exports.getComponents = getComponents;
|
|
@ -33,7 +33,6 @@
|
|||
"description": "an html <button />",
|
||||
"props": {
|
||||
"contentText": { "type": "string", "default": "Button" },
|
||||
"contentComponent": "component",
|
||||
"className": {"type": "string", "default": "default"},
|
||||
"disabled": "bool",
|
||||
"onClick": "event",
|
||||
|
@ -71,8 +70,7 @@
|
|||
"formControls": {
|
||||
"type":"array",
|
||||
"elementDefinition": {
|
||||
"label": "string",
|
||||
"control":"component"
|
||||
"label": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -136,18 +134,11 @@
|
|||
"options": ["horizontal", "vertical"],
|
||||
"default":"horizontal"
|
||||
},
|
||||
"children": {
|
||||
"type":"array",
|
||||
"elementDefinition": {
|
||||
"control":"component"
|
||||
}
|
||||
},
|
||||
"width": {"type":"string","default":"auto"},
|
||||
"height": {"type":"string","default":"auto"},
|
||||
"containerClass":"string",
|
||||
"itemContainerClass":"string",
|
||||
"data": "state",
|
||||
"dataItemComponent": "component",
|
||||
"onLoad": "event"
|
||||
},
|
||||
"tags": ["div", "container", "layout", "panel"]
|
||||
|
@ -162,7 +153,6 @@
|
|||
"children": {
|
||||
"type":"array",
|
||||
"elementDefinition": {
|
||||
"component":"component",
|
||||
"gridColumnStart":"string",
|
||||
"gridColumnEnd":"string",
|
||||
"gridRowStart":"string",
|
||||
|
@ -220,7 +210,6 @@
|
|||
"description": "A stylable div with a component inside",
|
||||
"props" : {
|
||||
"text": "string",
|
||||
"component": "component",
|
||||
"containerClass": "string",
|
||||
"background": "string",
|
||||
"border": "string",
|
||||
|
@ -260,8 +249,7 @@
|
|||
"items": {
|
||||
"type": "array",
|
||||
"elementDefinition" : {
|
||||
"title": "string",
|
||||
"component": "component"
|
||||
"title": "string"
|
||||
}
|
||||
},
|
||||
"selectedItem":"string",
|
||||
|
@ -300,13 +288,11 @@
|
|||
"children": {
|
||||
"type":"array",
|
||||
"elementDefinition": {
|
||||
"component":"component",
|
||||
"className": "string"
|
||||
}
|
||||
},
|
||||
"className":"string",
|
||||
"data": "state",
|
||||
"dataItemComponent": "component",
|
||||
"onLoad": "event"
|
||||
},
|
||||
"tags": ["div", "container", "layout"]
|
||||
|
@ -370,16 +356,5 @@
|
|||
"className":"string"
|
||||
},
|
||||
"tags": []
|
||||
},
|
||||
"if": {
|
||||
"importPath": "if",
|
||||
"name": "If",
|
||||
"description": "An if condition.. if (CONDITION) THEN [display component A] ELSE [display component B]",
|
||||
"props" : {
|
||||
"condition": "string",
|
||||
"thenComponent":{"type":"component", "required":true},
|
||||
"elseComponent":"component"
|
||||
},
|
||||
"tags": []
|
||||
}
|
||||
}
|
|
@ -25338,7 +25338,7 @@ var app = (function () {
|
|||
|
||||
const bb = (bindings, context) => ({
|
||||
hydrateComponent: _initialiseComponent(context, true),
|
||||
appendComponent: _initialiseComponent(context, false),
|
||||
appendChildren: _initialiseComponent(context, false),
|
||||
insertComponent: (props, htmlElement, anchor, context) =>
|
||||
_initialiseComponent(context, false)(props, htmlElement, context, anchor),
|
||||
store,
|
||||
|
|
|
@ -43,18 +43,18 @@ $: {
|
|||
let index = 0;
|
||||
for(let child of _bb.props.children) {
|
||||
if(child.className) {
|
||||
_bb.hydrateComponent(
|
||||
child.component,
|
||||
_bb.hydrateChildren(
|
||||
child.children,
|
||||
staticHtmlElements[index]);
|
||||
} else {
|
||||
const anchor = getStaticAnchor(index);
|
||||
if(!anchor) {
|
||||
_bb.appendComponent(
|
||||
child.component,
|
||||
_bb.appendChildren(
|
||||
child.children,
|
||||
rootDiv);
|
||||
} else {
|
||||
_bb.insertComponent(
|
||||
child.component,
|
||||
_bb.insertChildren(
|
||||
child.children,
|
||||
rootDiv,
|
||||
anchor);
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ $: {
|
|||
if(hasData()) {
|
||||
let index = 0;
|
||||
for(let dataItem of data) {
|
||||
_bb.appendComponent(
|
||||
_bb.appendChildren(
|
||||
_bb.props.dataItemComponent,
|
||||
rootDiv,
|
||||
dataItem
|
||||
|
|
|
@ -16,7 +16,7 @@ $ : {
|
|||
|
||||
if(_bb && htmlElements) {
|
||||
for(let el in htmlElements) {
|
||||
_bb.hydrateComponent(
|
||||
_bb.hydrateChildren(
|
||||
_bb.props.formControls[el].control,
|
||||
htmlElements[el]
|
||||
);
|
||||
|
|
|
@ -22,7 +22,7 @@ let isInitilised = false;
|
|||
$ : {
|
||||
if(!isInitilised && _bb && htmlElements && Object.keys(htmlElements).length > 0) {
|
||||
for(let el in htmlElements) {
|
||||
_bb.hydrateComponent(
|
||||
_bb.hydrateChildren(
|
||||
_bb.props.children[el].component,
|
||||
htmlElements[el]
|
||||
);
|
||||
|
|
|
@ -32,10 +32,10 @@ $: {
|
|||
}
|
||||
|
||||
if(result) {
|
||||
currentComponent = _bb.hydrateComponent(
|
||||
currentComponent = _bb.hydrateChildren(
|
||||
_bb.props.thenComponent,element);
|
||||
} else if(elseComponent && elseComponent._component) {
|
||||
currentComponent = _bb.hydrateComponent(
|
||||
currentComponent = _bb.hydrateChildren(
|
||||
_bb.props.elseComponent,element);
|
||||
}
|
||||
|
||||
|
|
|
@ -53,8 +53,8 @@ $: {
|
|||
const onSelectItem = (index) => () => {
|
||||
selectedIndex = index;
|
||||
if(!components[index]) {
|
||||
const comp = _bb.hydrateComponent(
|
||||
_bb.props.items[index].component, componentElements[index]);
|
||||
const comp = _bb.hydrateChildren(
|
||||
_bb.props.items[index].children, componentElements[index]);
|
||||
components[index] = comp;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import {buildStyle} from "./buildStyle";
|
||||
import cssVars from "./cssVars";
|
||||
|
||||
export let component="";
|
||||
export let children="";
|
||||
export let text="";
|
||||
export let containerClass="";
|
||||
export let background="";
|
||||
|
@ -36,8 +36,8 @@ $: {
|
|||
cursor: onClick ? "pointer" : "none"
|
||||
});
|
||||
|
||||
if(_bb && component && componentElement && !componentInitialised) {
|
||||
_bb.hydrateComponent(_bb.props.component, componentElement);
|
||||
if(_bb && children && children.length > 0 && componentElement && !componentInitialised) {
|
||||
_bb.hydrateChildren(_bb.props.children, componentElement);
|
||||
componentInitialised = true;
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ const clickHandler = () => {
|
|||
use:cssVars={styleVars}
|
||||
bind:this={componentElement}
|
||||
on:click={clickHandler}>
|
||||
{component && component._component ? "" : text}
|
||||
{children && children.length === 0 ? "" : text}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -43,7 +43,7 @@ $: {
|
|||
}
|
||||
|
||||
for(let el in staticHtmlElements) {
|
||||
staticComponents[el] = _bb.hydrateComponent(
|
||||
staticComponents[el] = _bb.hydrateChildren(
|
||||
_bb.props.children[el].control,
|
||||
staticHtmlElements[el]
|
||||
);
|
||||
|
@ -61,7 +61,7 @@ $: {
|
|||
if(hasData()) {
|
||||
let index = 0;
|
||||
for(let d in dataBoundElements) {
|
||||
_bb.hydrateComponent(
|
||||
_bb.hydrateChildren(
|
||||
_bb.props.dataItemComponent,
|
||||
dataBoundElements[d],
|
||||
data[parseInt(d)]
|
||||
|
|
|
@ -13,7 +13,7 @@ let currentComponent;
|
|||
|
||||
$: {
|
||||
if(_bb && currentComponent) {
|
||||
_bb.hydrateComponent(testProps, currentComponent);
|
||||
_bb.hydrateChildren(testProps, currentComponent);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ const createClasses = (classes) => {
|
|||
|
||||
$:{
|
||||
if(_bb && contentComponentContainer && contentComponent._component)
|
||||
_bb.hydrateComponent(_bb.props.contentComponent, contentComponentContainer);
|
||||
_bb.hydrateChildren(_bb.props.contentComponent, contentComponentContainer);
|
||||
|
||||
cssVariables = {
|
||||
hoverColor, hoverBorder,
|
||||
|
|
Loading…
Reference in New Issue