From 2a4cfa278b4e7ed0fb94b5d293263904f338434c Mon Sep 17 00:00:00 2001 From: pngwn Date: Fri, 24 Jan 2020 11:32:13 +0000 Subject: [PATCH] Implement updating of individual component props --- packages/builder/src/builderStore/store.js | 296 ++++++++++-------- .../builder/src/common/Icons/Image.svelte | 4 + .../builder/src/common/Icons/Input.svelte | 4 + packages/builder/src/common/Icons/index.js | 2 + .../ComponentHierarchyChildren.svelte | 24 ++ .../src/userInterface/ComponentPanel.svelte | 11 +- .../userInterface/ComponentsHierarchy.svelte | 38 ++- .../src/userInterface/ComponentsList.svelte | 80 ++++- .../userInterface/CurrentItemPreview.svelte | 12 +- .../src/userInterface/NewComponent.svelte | 1 - .../src/userInterface/PropsView.svelte | 6 +- .../userInterface/pagesParsing/createProps.js | 68 ++-- .../pagesParsing/validateProps.js | 90 +++--- packages/standard-components/src/Div.svelte | 3 +- 14 files changed, 385 insertions(+), 254 deletions(-) create mode 100644 packages/builder/src/common/Icons/Image.svelte create mode 100644 packages/builder/src/common/Icons/Input.svelte create mode 100644 packages/builder/src/userInterface/ComponentHierarchyChildren.svelte diff --git a/packages/builder/src/builderStore/store.js b/packages/builder/src/builderStore/store.js index cc074d450b..ce35cf1f29 100644 --- a/packages/builder/src/builderStore/store.js +++ b/packages/builder/src/builderStore/store.js @@ -1,8 +1,8 @@ import { - hierarchy as hierarchyFunctions, + hierarchy as hierarchyFunctions, } from "../../../core/src"; import { - filter, cloneDeep, sortBy, + filter, cloneDeep, sortBy, map, last, keys, concat, keyBy, find, isEmpty, reduce, values } from "lodash/fp"; @@ -10,16 +10,16 @@ import { pipe, getNode, validate, constructHierarchy, templateApi } from "../common/core"; -import {writable} from "svelte/store"; +import { writable } from "svelte/store"; import { defaultPagesObject } from "../userInterface/pagesParsing/defaultPagesObject" import { buildPropsHierarchy } from "../userInterface/pagesParsing/buildPropsHierarchy" import api from "./api"; import { isRootComponent, getExactComponent } from "../userInterface/pagesParsing/searchComponents"; import { rename } from "../userInterface/pagesParsing/renameScreen"; -import { - getNewComponentInfo, getScreenInfo +import { + getNewComponentInfo, getScreenInfo, getComponentInfo } from "../userInterface/pagesParsing/createProps"; -import { +import { loadLibs, loadLibUrls, loadGeneratorLibs } from "./loadComponentLibraries"; @@ -28,30 +28,30 @@ let appname = ""; export const getStore = () => { const initial = { - apps:[], - appname:"", + apps: [], + appname: "", hierarchy: {}, actions: [], triggers: [], - pages:defaultPagesObject(), - mainUi:{}, - unauthenticatedUi:{}, - components:[], - currentFrontEndItem:null, - currentComponentInfo:null, - currentFrontEndType:"none", + pages: defaultPagesObject(), + mainUi: {}, + unauthenticatedUi: {}, + components: [], + currentFrontEndItem: null, + currentComponentInfo: null, + currentFrontEndType: "none", currentPageName: "", - currentComponentProps:null, + currentComponentProps: null, currentNodeIsNew: false, errors: [], activeNav: "database", - isBackend:true, + isBackend: true, hasAppPackage: false, - accessLevels: {version:0, levels:[]}, + accessLevels: { version: 0, levels: [] }, currentNode: null, - libraries:null, - showSettings:false, - useAnalytics:true, + libraries: null, + showSettings: false, + useAnalytics: true, }; const store = writable(initial); @@ -82,7 +82,7 @@ export const getStore = () => { store.setCurrentScreen = setCurrentScreen(store); store.setCurrentPage = setCurrentPage(store); store.createScreen = createScreen(store); - store.removeComponentLibrary =removeComponentLibrary(store); + store.removeComponentLibrary = removeComponentLibrary(store); store.addStylesheet = addStylesheet(store); store.removeStylesheet = removeStylesheet(store); store.savePage = savePage(store); @@ -91,18 +91,21 @@ export const getStore = () => { store.showSettings = showSettings(store); store.useAnalytics = useAnalytics(store); store.createGeneratedComponents = createGeneratedComponents(store); + store.addChildComponent = addChildComponent(store); + store.selectComponent = selectComponent(store); + store.saveComponent = saveComponent(store); return store; -} +} export default getStore; const initialise = (store, initial) => async () => { - appname = window.location.hash - ? last(window.location.hash.substr(1).split("/")) - : ""; + appname = window.location.hash + ? last(window.location.hash.substr(1).split("/")) + : ""; - if(!appname) { + if (!appname) { initial.apps = await api.get(`/_builder/api/apps`).then(r => r.json()); initial.hasAppPackage = false; store.set(initial); @@ -110,7 +113,7 @@ const initialise = (store, initial) => async () => { } const pkg = await api.get(`/_builder/api/${appname}/appPackage`) - .then(r => r.json()); + .then(r => r.json()); initial.libraries = await loadLibs(appname, pkg); initial.generatorLibraries = await loadGeneratorLibs(appname, pkg); @@ -126,10 +129,10 @@ const initialise = (store, initial) => async () => { initial.actions = values(pkg.appDefinition.actions); initial.triggers = pkg.appDefinition.triggers; - if(!!initial.hierarchy && !isEmpty(initial.hierarchy)) { + if (!!initial.hierarchy && !isEmpty(initial.hierarchy)) { initial.hierarchy = constructHierarchy(initial.hierarchy); const shadowHierarchy = createShadowHierarchy(initial.hierarchy); - if(initial.currentNode !== null) + if (initial.currentNode !== null) initial.currentNode = getNode( shadowHierarchy, initial.currentNode.nodeId ); @@ -138,7 +141,7 @@ const initialise = (store, initial) => async () => { return initial; } -const generatorsArray = generators => +const generatorsArray = generators => pipe(generators, [ keys, filter(k => k !== "_lib"), @@ -179,12 +182,12 @@ const newRecord = (store, useRoot) => () => { s.currentNodeIsNew = true; const shadowHierarchy = createShadowHierarchy(s.hierarchy); parent = useRoot ? shadowHierarchy - : getNode( - shadowHierarchy, - s.currentNode.nodeId); + : getNode( + shadowHierarchy, + s.currentNode.nodeId); s.errors = []; s.currentNode = templateApi(shadowHierarchy) - .getNewRecordTemplate(parent, "", true); + .getNewRecordTemplate(parent, "", true); return s; }); } @@ -209,12 +212,12 @@ const newIndex = (store, useRoot) => () => { s.errors = []; const shadowHierarchy = createShadowHierarchy(s.hierarchy); parent = useRoot ? shadowHierarchy - : getNode( - shadowHierarchy, - s.currentNode.nodeId); + : getNode( + shadowHierarchy, + s.currentNode.nodeId); s.currentNode = templateApi(shadowHierarchy) - .getNewIndexTemplate(parent); + .getNewIndexTemplate(parent); return s; }); } @@ -224,7 +227,7 @@ const saveCurrentNode = (store) => () => { const errors = validate.node(s.currentNode); s.errors = errors; - if(errors.length > 0) { + if (errors.length > 0) { return s; } @@ -235,23 +238,23 @@ const saveCurrentNode = (store) => () => { s.hierarchy, s.currentNode.nodeId); let index = parentNode.children.length; - if(!!existingNode) { + if (!!existingNode) { // remove existing index = existingNode.parent().children.indexOf(existingNode); existingNode.parent().children = pipe(existingNode.parent().children, [ filter(c => c.nodeId !== existingNode.nodeId) ]); - } + } // should add node into existing hierarchy const cloned = cloneDeep(s.currentNode); templateApi(s.hierarchy).constructNode( - parentNode, + parentNode, cloned ); const newIndexOfchild = child => { - if(child === cloned) return index; + if (child === cloned) return index; const currentIndex = parentNode.children.indexOf(child); return currentIndex >= index ? currentIndex + 1 : currentIndex; } @@ -260,15 +263,15 @@ const saveCurrentNode = (store) => () => { sortBy(newIndexOfchild) ]); - if(!existingNode && s.currentNode.type === "record") { + if (!existingNode && s.currentNode.type === "record") { const defaultIndex = templateApi(s.hierarchy) - .getNewIndexTemplate(cloned.parent()); + .getNewIndexTemplate(cloned.parent()); defaultIndex.name = `all_${cloned.collectionName}`; defaultIndex.allowedRecordNodeIds = [cloned.nodeId]; } s.currentNodeIsNew = false; - + savePackage(store, s); return s; @@ -279,28 +282,28 @@ const importAppDefinition = store => appDefinition => { store.update(s => { s.hierarchy = appDefinition.hierarchy; s.currentNode = appDefinition.hierarchy.children.length > 0 - ? appDefinition.hierarchy.children[0] - : null; + ? appDefinition.hierarchy.children[0] + : null; s.actions = appDefinition.actions; s.triggers = appDefinition.triggers; - s.currentNodeIsNew = false; + s.currentNodeIsNew = false; return s; }); -} +} const deleteCurrentNode = store => () => { store.update(s => { const nodeToDelete = getNode(s.hierarchy, s.currentNode.nodeId); s.currentNode = hierarchyFunctions.isRoot(nodeToDelete.parent()) - ? find(n => n != s.currentNode) - (s.hierarchy.children) - : nodeToDelete.parent(); - if(hierarchyFunctions.isRecord(nodeToDelete)) { + ? find(n => n != s.currentNode) + (s.hierarchy.children) + : nodeToDelete.parent(); + if (hierarchyFunctions.isRecord(nodeToDelete)) { nodeToDelete.parent().children = filter(c => c.nodeId !== nodeToDelete.nodeId) - (nodeToDelete.parent().children); + (nodeToDelete.parent().children); } else { nodeToDelete.parent().indexes = filter(c => c.nodeId !== nodeToDelete.nodeId) - (nodeToDelete.parent().indexes); + (nodeToDelete.parent().indexes); } s.errors = []; savePackage(store, s); @@ -311,8 +314,8 @@ const deleteCurrentNode = store => () => { const saveField = databaseStore => (field) => { databaseStore.update(db => { db.currentNode.fields = filter(f => f.name !== field.name) - (db.currentNode.fields); - + (db.currentNode.fields); + templateApi(db.hierarchy).addField(db.currentNode, field); return db; }); @@ -322,21 +325,21 @@ const saveField = databaseStore => (field) => { const deleteField = databaseStore => field => { databaseStore.update(db => { db.currentNode.fields = filter(f => f.name !== field.name) - (db.currentNode.fields); + (db.currentNode.fields); return db; }); } -const saveAction = store => (newAction, isNew, oldAction=null) => { +const saveAction = store => (newAction, isNew, oldAction = null) => { store.update(s => { - const existingAction = isNew - ? null - : find(a => a.name === oldAction.name)(s.actions); - - if(existingAction) { + const existingAction = isNew + ? null + : find(a => a.name === oldAction.name)(s.actions); + + if (existingAction) { s.actions = pipe(s.actions, [ map(a => a === existingAction ? newAction : a) ]); @@ -348,7 +351,7 @@ const saveAction = store => (newAction, isNew, oldAction=null) => { }); } -const deleteAction = store => action => { +const deleteAction = store => action => { store.update(s => { s.actions = filter(a => a.name !== action.name)(s.actions); savePackage(store, s); @@ -356,14 +359,14 @@ const deleteAction = store => action => { }); } -const saveTrigger = store => (newTrigger, isNew, oldTrigger=null) => { +const saveTrigger = store => (newTrigger, isNew, oldTrigger = null) => { store.update(s => { - const existingTrigger = isNew - ? null - : find(a => a.name === oldTrigger.name)(s.triggers); - - if(existingTrigger) { + const existingTrigger = isNew + ? null + : find(a => a.name === oldTrigger.name)(s.triggers); + + if (existingTrigger) { s.triggers = pipe(s.triggers, [ map(a => a === existingTrigger ? newTrigger : a) ]); @@ -375,7 +378,7 @@ const saveTrigger = store => (newTrigger, isNew, oldTrigger=null) => { }); } -const deleteTrigger = store => trigger => { +const deleteTrigger = store => trigger => { store.update(s => { s.triggers = filter(t => t.name !== trigger.name)(s.triggers); return s; @@ -383,18 +386,18 @@ const deleteTrigger = store => trigger => { } const incrementAccessLevelsVersion = (s) => - s.accessLevels.version = (s.accessLevels.version || 0) + 1; + s.accessLevels.version = (s.accessLevels.version || 0) + 1; -const saveLevel = store => (newLevel, isNew, oldLevel=null) => { +const saveLevel = store => (newLevel, isNew, oldLevel = null) => { store.update(s => { const levels = s.accessLevels.levels; - const existingLevel = isNew - ? null - : find(a => a.name === oldLevel.name)(levels); - - if(existingLevel) { + const existingLevel = isNew + ? null + : find(a => a.name === oldLevel.name)(levels); + + if (existingLevel) { s.accessLevels.levels = pipe(levels, [ map(a => a === existingLevel ? newLevel : a) ]); @@ -425,7 +428,7 @@ const setActiveNav = store => navName => { }); } -const createShadowHierarchy = hierarchy => +const createShadowHierarchy = hierarchy => constructHierarchy(JSON.parse(JSON.stringify(hierarchy))); const saveScreen = store => (screen) => { @@ -448,7 +451,7 @@ const _saveScreen = (store, s, screen) => { api.post(`/_builder/api/${s.appname}/screen`, screen) .then(() => savePackage(store, s)); - return s; + return s; } const createScreen = store => (screenName, layoutComponentName) => { @@ -470,13 +473,13 @@ const createGeneratedComponents = store => components => { s.screens = [...s.screens, ...components]; const doCreate = async () => { - for(let c of components) { + for (let c of components) { await api.post(`/_builder/api/${s.appname}/screen`, c); } await savePackage(store, s); } - + doCreate(); return s; @@ -496,7 +499,7 @@ const deleteScreen = store => name => { s.components = components; s.screens = screens; - if(s.currentFrontEndItem.name === name) { + if (s.currentFrontEndItem.name === name) { s.currentFrontEndItem = null; s.currentFrontEndType = ""; } @@ -514,20 +517,20 @@ const renameScreen = store => (oldname, newname) => { screens, pages, error, changedScreens } = rename(s.pages, s.screens, oldname, newname); - if(error) { + if (error) { // should really do something with this return s; } s.screens = screens; s.pages = pages; - if(s.currentFrontEndItem.name === oldname) + if (s.currentFrontEndItem.name === oldname) s.currentFrontEndItem.name = newname; const saveAllChanged = async () => { - for(let screenName of changedScreens) { + for (let screenName of changedScreens) { const changedScreen - = getExactComponent(screens, screenName); + = getExactComponent(screens, screenName); await api.post(`/_builder/api/${s.appname}/screen`, changedScreen); } } @@ -535,10 +538,10 @@ const renameScreen = store => (oldname, newname) => { api.patch(`/_builder/api/${s.appname}/screen`, { oldname, newname }) - .then(() => saveAllChanged()) - .then(() => { - savePackage(store, s); - }); + .then(() => saveAllChanged()) + .then(() => { + savePackage(store, s); + }); return s; }) @@ -546,7 +549,7 @@ const renameScreen = store => (oldname, newname) => { const savePage = store => async page => { store.update(s => { - if(s.currentFrontEndType !== "page" || !s.currentPageName) { + if (s.currentFrontEndType !== "page" || !s.currentPageName) { return s; } @@ -558,26 +561,26 @@ const savePage = store => async page => { const addComponentLibrary = store => async lib => { - const response = - await api.get(`/_builder/api/${appname}/componentlibrary?lib=${encodeURI(lib)}`,undefined, false); + const response = + await api.get(`/_builder/api/${appname}/componentlibrary?lib=${encodeURI(lib)}`, undefined, false); const success = response.status === 200; - const error = response.status === 404 - ? `Could not find library ${lib}` - : success - ? "" - : response.statusText; - + const error = response.status === 404 + ? `Could not find library ${lib}` + : success + ? "" + : response.statusText; + const components = success - ? await response.json() - : []; + ? await response.json() + : []; store.update(s => { - if(success) { - + if (success) { + const componentsArray = []; - for(let c in components) { + for (let c in components) { componentsArray.push(components[c]); } @@ -592,18 +595,18 @@ const addComponentLibrary = store => async lib => { return s; }) - + } const removeComponentLibrary = store => lib => { store.update(s => { - - + + s.pages.componentLibraries = filter(l => l !== lib)( - s.pages.componentLibraries); + s.pages.componentLibraries); savePackage(store, s); - + return s; }) @@ -627,12 +630,12 @@ const removeStylesheet = store => stylesheet => { const refreshComponents = store => async () => { - const componentsAndGenerators = + const componentsAndGenerators = await api.get(`/_builder/api/${db.appname}/components`).then(r => r.json()); const components = pipe(componentsAndGenerators.components, [ keys, - map(k => ({...componentsAndGenerators[k], name:k})) + map(k => ({ ...componentsAndGenerators[k], name: k })) ]); store.update(s => { @@ -648,25 +651,25 @@ const refreshComponents = store => async () => { const savePackage = (store, s) => { const appDefinition = { - hierarchy:s.hierarchy, - triggers:s.triggers, + hierarchy: s.hierarchy, + triggers: s.triggers, actions: keyBy("name")(s.actions), props: { main: buildPropsHierarchy( - s.components, - s.screens, - s.pages.main.appBody), - unauthenticated: buildPropsHierarchy( - s.components, - s.screens, - s.pages.unauthenticated.appBody) + s.components, + s.screens, + s.pages.main.appBody), + unauthenticated: buildPropsHierarchy( + s.components, + s.screens, + s.pages.unauthenticated.appBody) } }; const data = { appDefinition, - accessLevels:s.accessLevels, - pages:s.pages, + accessLevels: s.accessLevels, + pages: s.pages, } return api.post(`/_builder/api/${s.appname}/appPackage`, data); @@ -689,3 +692,44 @@ const setCurrentPage = store => pageName => { return s; }) } + +const addChildComponent = store => component => { + + store.update(s => { + const newComponent = getNewComponentInfo( + s.components, component); + + const children = s.currentFrontEndItem.props._children; + + const component_definition = { + ...newComponent.fullProps, + _component: component, + name: component, + description: '', + location: (s.currentFrontEndItem.location ? s.currentFrontEndItem.location : []) + .concat(children && children.length || 0) + } + + s.currentFrontEndItem.props._children = + children ? + children.concat(component_definition) : + [component_definition]; + + return s; + }) +} + +const selectComponent = store => component => { + store.update(s => { + s.currentComponentInfo = getComponentInfo(s.components, component); + return s; + }) +} + +const saveComponent = store => component => { + store.update(s => { + s.currentComponentInfo = getComponentInfo(s.components, component); + console.log(s.currentFrontEndItem, s.screens) + return _saveScreen(store, s, s.currentFrontEndItem); + }) +} diff --git a/packages/builder/src/common/Icons/Image.svelte b/packages/builder/src/common/Icons/Image.svelte new file mode 100644 index 0000000000..8a07fedbdc --- /dev/null +++ b/packages/builder/src/common/Icons/Image.svelte @@ -0,0 +1,4 @@ + + + + diff --git a/packages/builder/src/common/Icons/Input.svelte b/packages/builder/src/common/Icons/Input.svelte new file mode 100644 index 0000000000..58c44466cf --- /dev/null +++ b/packages/builder/src/common/Icons/Input.svelte @@ -0,0 +1,4 @@ + + + + diff --git a/packages/builder/src/common/Icons/index.js b/packages/builder/src/common/Icons/index.js index 73f4500f7b..7ab39dfdd0 100644 --- a/packages/builder/src/common/Icons/index.js +++ b/packages/builder/src/common/Icons/index.js @@ -1,3 +1,5 @@ export { default as LayoutIcon } from './Layout.svelte'; export { default as PaintIcon } from './Paint.svelte'; export { default as TerminalIcon } from './Terminal.svelte'; +export { default as InputIcon } from './Input.svelte'; +export { default as ImageIcon } from './Image.svelte'; diff --git a/packages/builder/src/userInterface/ComponentHierarchyChildren.svelte b/packages/builder/src/userInterface/ComponentHierarchyChildren.svelte new file mode 100644 index 0000000000..fc9c664325 --- /dev/null +++ b/packages/builder/src/userInterface/ComponentHierarchyChildren.svelte @@ -0,0 +1,24 @@ + + +{#each components as component} + +{/each} diff --git a/packages/builder/src/userInterface/ComponentPanel.svelte b/packages/builder/src/userInterface/ComponentPanel.svelte index 2ab2ebf4c7..7dcfc32efe 100644 --- a/packages/builder/src/userInterface/ComponentPanel.svelte +++ b/packages/builder/src/userInterface/ComponentPanel.svelte @@ -43,7 +43,7 @@ $: shortName = last(name.split("/")); store.subscribe(s => { if(ignoreStore) return; - component = s.currentFrontEndItem; + component = s.currentComponentInfo.component; if(!component) return; originalName = component.name; name = component.name; @@ -68,7 +68,7 @@ const save = () => { map(s => s.trim()) ]); - store.saveScreen(component); + store.saveComponent(component); ignoreStore = false; // now do the rename @@ -92,14 +92,15 @@ const onPropsValidate = result => { const updateComponent = doChange => { const newComponent = cloneDeep(component); - doChange(newComponent); - component = newComponent; + + component = doChange(newComponent); + console.log(component, $store.screens[0].props._children[1]) componentInfo = getScreenInfo(components, newComponent); } const onPropsChanged = newProps => { updateComponent(newComponent => - assign(newComponent.props, newProps)); + assign(newComponent, newProps)) save(); } diff --git a/packages/builder/src/userInterface/ComponentsHierarchy.svelte b/packages/builder/src/userInterface/ComponentsHierarchy.svelte index 6afcd68477..9d0eeee740 100644 --- a/packages/builder/src/userInterface/ComponentsHierarchy.svelte +++ b/packages/builder/src/userInterface/ComponentsHierarchy.svelte @@ -1,4 +1,5 @@
- {#each subfolders as folder} + - {#each componentsThisLevel as component} -
store.setCurrentScreen(component.component.name)}> - + {component.title}
+ {#if component.component.props && component.component.props._children} + + {/if} {/each}
diff --git a/packages/builder/src/userInterface/ComponentsList.svelte b/packages/builder/src/userInterface/ComponentsList.svelte index 29aadae269..8f22e6acef 100644 --- a/packages/builder/src/userInterface/ComponentsList.svelte +++ b/packages/builder/src/userInterface/ComponentsList.svelte @@ -8,6 +8,7 @@ import { groupBy, keys, find, sortBy } from "lodash/fp"; import { pipe } from "../common/core"; +import { ImageIcon, InputIcon, LayoutIcon } from '../common/Icons/'; let componentLibraries=[]; @@ -29,9 +30,7 @@ const addRootComponent = (c, all) => { }; -const onComponentChosen = (component) => { - -}; +const onComponentChosen = store.addChildComponent; store.subscribe(s => { @@ -46,6 +45,8 @@ store.subscribe(s => { componentLibraries = newComponentLibraries; }); +let current_view = 'text'; +
@@ -55,22 +56,34 @@ store.subscribe(s => {
+ - -
- Components -
- - {#each lib.components as component} + {#each lib.components.filter(_ => true) as component}
onComponentChosen(component)}> + on:click={() => onComponentChosen(component.name)}>
{splitName(component.name).componentName}
-
+
{/each} @@ -113,8 +126,16 @@ store.subscribe(s => { } .component { - padding: 2px 0px; + padding: 0 15px; cursor: pointer; + border: 1px solid #ccc; + border-radius: 2px; + margin: 10px 0; + height: 40px; + box-sizing: border-box; + color: #163057; + display: flex; + align-items: center; } .component:hover { @@ -122,8 +143,11 @@ store.subscribe(s => { } .component > .name { - color: var(--secondary100); + color: #163057; display: inline-block; + font-size: 12px; + font-weight: bold; + opacity: 0.6; } .component > .description { @@ -133,6 +157,34 @@ store.subscribe(s => { margin-left: 10px; } +ul { + list-style: none; + display: flex; + padding: 0; +} +li { + margin-right: 20px; + background: none; + border-radius: 5px; + width: 48px; + height: 48px; +} + +li button { + width: 100%; + height: 100%; + background: none; + border: none; + border-radius: 5px; + padding: 12px; + outline: none; + cursor: pointer; +} + +.selected { + color: var(--button-text); + background: var(--background-button)!important; +} diff --git a/packages/builder/src/userInterface/CurrentItemPreview.svelte b/packages/builder/src/userInterface/CurrentItemPreview.svelte index 7e65057451..3c108e8902 100644 --- a/packages/builder/src/userInterface/CurrentItemPreview.svelte +++ b/packages/builder/src/userInterface/CurrentItemPreview.svelte @@ -17,7 +17,7 @@ let appDefinition = {}; store.subscribe(s => { hasComponent = !!s.currentFrontEndItem; - + stylesheetLinks = pipe(s.pages.stylesheets, [ map(s => ``), join("\n") @@ -25,8 +25,8 @@ store.subscribe(s => { appDefinition = { componentLibraries: s.loadLibraryUrls(), props: buildPropsHierarchy( - s.components, - s.screens, + s.components, + s.screens, s.currentFrontEndItem), hierarchy: s.hierarchy, appRootPath: "" @@ -45,7 +45,7 @@ store.subscribe(s => { title="componentPreview" srcdoc={ ` - + ${stylesheetLinks} \ No newline at end of file + diff --git a/packages/builder/src/userInterface/NewComponent.svelte b/packages/builder/src/userInterface/NewComponent.svelte index aef5b822c1..608097838c 100644 --- a/packages/builder/src/userInterface/NewComponent.svelte +++ b/packages/builder/src/userInterface/NewComponent.svelte @@ -29,7 +29,6 @@ let name=""; let saveAttempted=false; store.subscribe(s => { - console.log(s) layoutComponents = pipe(s.components, [ filter(c => c.container), map(c => ({name:c.name, ...splitName(c.name)})) diff --git a/packages/builder/src/userInterface/PropsView.svelte b/packages/builder/src/userInterface/PropsView.svelte index 80e742e220..b2e81d0ba3 100644 --- a/packages/builder/src/userInterface/PropsView.svelte +++ b/packages/builder/src/userInterface/PropsView.svelte @@ -25,7 +25,6 @@ let props = {}; let propsDefinitions = []; let isInstance = false; - $: { if(componentInfo) { @@ -46,7 +45,7 @@ $: { let setProp = (name, value) => { const newProps = cloneDeep(props); - let finalProps = isInstance ? newProps : cloneDeep(componentInfo.component.props); + let finalProps = isInstance ? newProps : cloneDeep(componentInfo.component.props ? componentInfo.component.props : componentInfo.component); if(!isInstance) { const nowSet = []; @@ -98,9 +97,6 @@ const fieldHasError = (propName) => - - -
diff --git a/packages/builder/src/userInterface/pagesParsing/createProps.js b/packages/builder/src/userInterface/pagesParsing/createProps.js index ccd7059a21..d0ed4f7402 100644 --- a/packages/builder/src/userInterface/pagesParsing/createProps.js +++ b/packages/builder/src/userInterface/pagesParsing/createProps.js @@ -1,6 +1,6 @@ import { isString, isUndefined, find, keys, uniq, - some, filter, reduce, cloneDeep, includes,last + some, filter, reduce, cloneDeep, includes, last } from "lodash/fp"; import { types, expandComponentDefinition } from "./types"; import { assign } from "lodash"; @@ -11,7 +11,7 @@ import { ensureShardNameIsInShardMap } from "../../../../core/src/indexing/shard export const getInstanceProps = (componentInfo, props) => { const finalProps = cloneDeep(componentInfo.fullProps); - for(let p in props) { + for (let p in props) { finalProps[p] = props[p]; } @@ -20,9 +20,9 @@ export const getInstanceProps = (componentInfo, props) => { export const getNewComponentInfo = (components, rootComponent, name) => { const component = { - name: name || "", - description:"", - props:{ + name: name || "", + description: "", + props: { _component: rootComponent } }; @@ -34,22 +34,22 @@ export const getNewComponentInfo = (components, rootComponent, name) => { export const getScreenInfo = (components, screen) => { return getComponentInfo( - components, + components, screen); } export const getComponentInfo = (components, comp) => { - const targetComponent = isString(comp) - ? find(c => c.name === comp)(components) - : comp; + const targetComponent = isString(comp) + ? find(c => c.name === comp)(components) + : comp; let component; let subComponent; - if(isRootComponent(targetComponent)) { + if (isRootComponent(targetComponent)) { component = targetComponent; } else { subComponent = targetComponent; - component = find(c => c.name === subComponent.props._component)( - components); + component = find(c => c.name === (subComponent.props ? subComponent.props._component : subComponent._component))( + components); } const subComponentProps = subComponent ? subComponent.props : {}; @@ -65,7 +65,7 @@ export const getComponentInfo = (components, comp) => { fullProps._component = targetComponent.name; return ({ - propsDefinition:expandComponentDefinition(component), + propsDefinition: expandComponentDefinition(component), rootDefaultProps: rootProps.props, unsetProps, fullProps: fullProps, @@ -78,7 +78,7 @@ export const getComponentInfo = (components, comp) => { export const createProps = (componentDefinition, derivedFromProps) => { const error = (propName, error) => - errors.push({propName, error}); + errors.push({ propName, error }); const props = { _component: componentDefinition.name @@ -86,24 +86,24 @@ export const createProps = (componentDefinition, derivedFromProps) => { const errors = []; - if(!componentDefinition.name) + if (!componentDefinition.name) error("_component", "Component name not supplied"); const propsDef = componentDefinition.props; - for(let propDef in propsDef) { + for (let propDef in propsDef) { const parsedPropDef = parsePropDef(propsDef[propDef]); - if(parsedPropDef.error) - error(propDef, parsedPropDef.error); - else + if (parsedPropDef.error) + error(propDef, parsedPropDef.error); + else props[propDef] = parsedPropDef; } - if(derivedFromProps) { + if (derivedFromProps) { assign(props, derivedFromProps); } - if(componentDefinition.children !== false - && isUndefined(props._children)) { + if (componentDefinition.children !== false + && isUndefined(props._children)) { props._children = []; } @@ -114,37 +114,37 @@ export const createProps = (componentDefinition, derivedFromProps) => { const parsePropDef = propDef => { - const error = message => ({error:message, propDef}); + const error = message => ({ error: message, propDef }); - if(isString(propDef)) { - if(!types[propDef]) + if (isString(propDef)) { + if (!types[propDef]) return error(`Do not recognise type ${propDef}`); - + return types[propDef].default(); } - if(!propDef.type) + if (!propDef.type) return error("Property Definition must declare a type"); - + const type = types[propDef.type]; - if(!type) + if (!type) return error(`Do not recognise type ${propDef.type}`); - if(isUndefined(propDef.default)) + if (isUndefined(propDef.default)) return type.default(propDef); - if(!type.isOfType(propDef.default)) + if (!type.isOfType(propDef.default)) return error(`${propDef.default} is not of type ${type}`); return propDef.default; } -export const arrayElementComponentName = (parentComponentName, arrayPropName) => +export const arrayElementComponentName = (parentComponentName, arrayPropName) => `${parentComponentName}:${arrayPropName}`; /* Allowed propDefOptions - type: string, bool, number, array - default: default value, when undefined -- required: field is required -*/ \ No newline at end of file +- required: field is required +*/ diff --git a/packages/builder/src/userInterface/pagesParsing/validateProps.js b/packages/builder/src/userInterface/pagesParsing/validateProps.js index dea08b093b..9f0f3ae11b 100644 --- a/packages/builder/src/userInterface/pagesParsing/validateProps.js +++ b/packages/builder/src/userInterface/pagesParsing/validateProps.js @@ -1,10 +1,10 @@ import { types } from "./types"; -import { - createProps, arrayElementComponentName +import { + createProps, arrayElementComponentName } from "./createProps"; import { isString } from "util"; -import { - includes, filter, map, keys, +import { + includes, filter, map, keys, flatten, flattenDeep, each, indexOf, isUndefined } from "lodash/fp"; @@ -18,12 +18,13 @@ const pipe = common.$; const makeError = (errors, propName, stack) => (message) => errors.push({ stack, - propName, - error:message}); + propName, + error: message + }); -export const recursivelyValidate = (rootProps, getComponent, stack=[]) => { +export const recursivelyValidate = (rootProps, getComponent, stack = []) => { - if(!rootProps._component) { + if (!rootProps._component) { const errs = []; makeError(errs, "_component", stack)("Component is not set"); return errs; @@ -40,34 +41,34 @@ export const recursivelyValidate = (rootProps, getComponent, stack=[]) => { stack, true); - const validateChildren = (_props, _stack) => - !_props._children - ? [] - : pipe(_props._children, [ - map(child => recursivelyValidate( - child, - getComponent, - [..._stack, _props._children.indexOf(child)])) - ]); + const validateChildren = (_props, _stack) => + !_props._children + ? [] + : pipe(_props._children, [ + map(child => recursivelyValidate( + child, + getComponent, + [..._stack, _props._children.indexOf(child)])) + ]); const childErrors = validateChildren( - rootProps, stack); + rootProps, stack); return flattenDeep([errors, ...childErrors]); } -const expandPropDef = propDef => +const expandPropDef = propDef => isString(propDef) - ? types[propDef].defaultDefinition() - : propDef; + ? types[propDef].defaultDefinition() + : propDef; -export const validateProps = (componentDefinition, props, stack=[], isFinal=true) => { +export const validateProps = (componentDefinition, props, stack = [], isFinal = true) => { const errors = []; - if(isFinal && !props._component) { + if (isFinal && !props._component) { makeError(errors, "_component", stack)("Component is not set"); return errors; // this would break everything else anyway @@ -75,44 +76,44 @@ export const validateProps = (componentDefinition, props, stack=[], isFinal=true const propsDefinition = componentDefinition.props; - for(let propDefName in props) { - - if(propDefName === "_component") continue; - if(propDefName === "_children") continue; - if(propDefName === "_layout") continue; + for (let propDefName in props) { + + const ignore = ['_component', "_children", '_layout', 'name', 'description', 'location']; + + if (ignore.includes(propDefName)) continue; const propDef = expandPropDef(propsDefinition[propDefName]); const type = types[propDef.type]; - const error = makeError(errors, propDefName, stack); + const error = makeError(errors, propDefName, stack); const propValue = props[propDefName]; // component declarations dont need to define al props. - if(!isFinal && isUndefined(propValue)) continue; + if (!isFinal && isUndefined(propValue)) continue; - if(isFinal && propDef.required && propValue) { + if (isFinal && propDef.required && propValue) { error(`Property ${propDefName} is required`); continue; - } + } - if(isBinding(propValue)) { - if(propDef.type === "event") { + if (isBinding(propValue)) { + if (propDef.type === "event") { error(`Cannot apply binding to type ${propDef.type}`); continue; } } - else if(!type.isOfType(propValue)) { + else if (!type.isOfType(propValue)) { error(`Property ${propDefName} is not of type ${propDef.type}. Actual value ${propValue}`) continue; } - - if(propDef.type === "options" - && propValue - && !isBinding(propValue) - && !includes(propValue)(propDef.options)) { + + if (propDef.type === "options" + && propValue + && !isBinding(propValue) + && !includes(propValue)(propDef.options)) { error(`Property ${propDefName} is not one of allowed options. Acutal value is ${propValue}`); } @@ -123,21 +124,20 @@ export const validateProps = (componentDefinition, props, stack=[], isFinal=true export const validateComponentDefinition = (componentDefinition) => { const { errors } = createProps(componentDefinition); - + const propDefinitions = expandPropDef(componentDefinition.props); pipe(propDefinitions, [ keys, map(k => ({ - propDef:propDefinitions[k], - propName:k + propDef: propDefinitions[k], + propName: k })), filter(d => d.propDef.type === "options" - && (!d.propDef.options || d.propDef.options.length === 0)), + && (!d.propDef.options || d.propDef.options.length === 0)), each(d => makeError(errors, d.propName)(`${d.propName} does not have any options`)) ]); return errors; } - diff --git a/packages/standard-components/src/Div.svelte b/packages/standard-components/src/Div.svelte index a586b29657..bb4b6d1d03 100644 --- a/packages/standard-components/src/Div.svelte +++ b/packages/standard-components/src/Div.svelte @@ -8,7 +8,7 @@ export let _bb; let rootDiv; $:{ if(_bb && rootDiv && _children && _children.length) - _bb.hydrateChildren(_children, theButton); + _bb.hydrateChildren(_children, rootDiv); } @@ -16,4 +16,3 @@ $:{
-