styling, bug fixes, client library state updates

This commit is contained in:
Martin McKeaveney 2020-05-29 16:06:23 +01:00
parent bba7b93b75
commit 385bcfe51f
11 changed files with 166 additions and 146 deletions

View File

@ -40,8 +40,13 @@ export default class Workflow {
block = block.next
}
// delete the block found
previous.next = block.next || {}
// delete the block matching your id
if (!block.next) {
delete previous.next
} else {
previous.next = block.next
}
}
createUiTree() {

View File

@ -1,14 +1,15 @@
<script>
import { onMount, getContext } from "svelte"
import { backendUiStore, workflowStore } from "builderStore"
import { notifier } from "@beyonk/svelte-notifications";
import { notifier } from "@beyonk/svelte-notifications"
import api from "builderStore/api"
import WorkflowBlockSetup from "./WorkflowBlockSetup.svelte"
import DeleteWorkflowModal from "./DeleteWorkflowModal.svelte"
const { open, close } = getContext("simple-modal")
$: workflow = $workflowStore.currentWorkflow && $workflowStore.currentWorkflow.workflow
$: workflow =
$workflowStore.currentWorkflow && $workflowStore.currentWorkflow.workflow
$: workflowBlock = $workflowStore.selectedWorkflowBlock
function deleteWorkflow() {
@ -23,7 +24,7 @@
function deleteWorkflowBlock() {
workflowStore.actions.deleteWorkflowBlock(workflowBlock)
notifier.info("Workflow block deleted.");
notifier.info("Workflow block deleted.")
}
</script>
@ -31,7 +32,6 @@
<header>
<span>Setup</span>
</header>
<div class="panel-body">
{#if workflowBlock}
<WorkflowBlockSetup {workflowBlock} />
<button
@ -40,6 +40,7 @@
Delete Block
</button>
{:else if $workflowStore.currentWorkflow}
<div class="panel-body">
<label class="uk-form-label">Workflow: {workflow.name}</label>
<div class="uk-margin">
<label class="uk-form-label">Name</label>
@ -54,19 +55,22 @@
<label class="uk-form-label">User Access</label>
Some User Access Stuff Here
</div>
<button
class="delete-workflow-button hoverable"
on:click={deleteWorkflow}>
</div>
<button class="delete-workflow-button hoverable" on:click={deleteWorkflow}>
Delete Workflow
</button>
{/if}
</div>
</section>
<style>
section {
display: flex;
flex-direction: column;
height: 100%;
}
.panel-body {
flex: 1;
}
header {

View File

@ -14,16 +14,10 @@
$: workflowLive = selectedWorkflow && selectedWorkflow.workflow.live
$: if (selectedWorkflow)
uiTree = selectedWorkflow ? selectedWorkflow.createUiTree() : []
$: uiTree = selectedWorkflow ? selectedWorkflow.createUiTree() : []
$: instanceId = $backendUiStore.selectedDatabase._id
function onDelete(block) {
// TODO finish
workflowStore.actions.deleteWorkflowBlock(block)
}
function onSelect(block) {
workflowStore.update(state => {
state.selectedWorkflowBlock = block
@ -44,7 +38,7 @@
</script>
<section>
<Flowchart blocks={uiTree} {onSelect} on:delete={onDelete} />
<Flowchart blocks={uiTree} {onSelect} />
<footer>
{#if selectedWorkflow}
<button

View File

@ -59,6 +59,11 @@
</section>
<style>
section {
display: flex;
flex-direction: column;
}
i {
color: #adaec4;
}
@ -70,6 +75,7 @@
ul {
list-style-type: none;
padding: 0;
flex: 1;
}
.live {

View File

@ -9,8 +9,7 @@
let definitions = []
</script>
<section>
<header>
<header>
<span
class="hoverable"
class:selected={selectedTab === 'WORKFLOWS'}
@ -25,13 +24,12 @@
Add
</span>
{/if}
</header>
{#if selectedTab === 'WORKFLOWS'}
</header>
{#if selectedTab === 'WORKFLOWS'}
<WorkflowList />
{:else if selectedTab === 'ADD'}
{:else if selectedTab === 'ADD'}
<BlockList />
{/if}
</section>
{/if}
<style>
header {

View File

@ -22,11 +22,6 @@
background: var(--background);
}
.nav {
padding: 20px;
height: 100%;
}
.root {
height: 100%;
display: flex;
@ -39,10 +34,9 @@
}
.nav {
padding: 20px;
overflow: auto;
flex: 0 1 auto;
width: 275px;
height: 100%;
border: 1px solid var(--medium-grey);
background: var(--white);
}

View File

@ -91,6 +91,25 @@ export const clientStrategy = {
if (block.actionId === "DELAY") {
await this.delay(block.args.time)
}
if (block.actionId === "FILTER") {
const { field, condition, value } = block.args;
switch (condition) {
case "=":
if (field !== value) return;
break;
case "!=":
if (field === value) return;
break;
case "gt":
if (field < value) return;
break;
case "lt":
if (field > value) return;
default:
return;
}
}
}
// this workflow block gets executed on the server

View File

@ -24,9 +24,8 @@ export const createApp = ({
routeTo,
appRootPath: frontendDefinition.appRootPath,
})
const getAttachChildrenParams = attachChildrenParams(stateManager)
screenSlotNode.props._children = [screen.props]
const initialiseChildParams = getAttachChildrenParams(screenSlotNode)
const initialiseChildParams = attachChildrenParams(stateManager, screenSlotNode)
attachChildren(initialiseChildParams)(screenSlotNode.rootElement, {
hydrate: true,
force: true,
@ -48,17 +47,13 @@ export const createApp = ({
routeTo(currentUrl || fallbackPath)
}
const attachChildrenParams = stateManager => {
const getInitialiseParams = treeNode => ({
const attachChildrenParams = (stateManager, treeNode) => ({
componentLibraries,
treeNode,
onScreenSlotRendered,
setupState: stateManager.setup,
getCurrentState: stateManager.getCurrentState,
})
return getInitialiseParams
}
});
let rootTreeNode
const pageStateManager = createStateManager({
@ -79,8 +74,7 @@ export const createApp = ({
_children: [page.props],
}
rootTreeNode.rootElement = target
const getInitialiseParams = attachChildrenParams(pageStateManager)
const initChildParams = getInitialiseParams(rootTreeNode)
const initChildParams = attachChildrenParams(pageStateManager, rootTreeNode)
attachChildren(initChildParams)(target, {
hydrate: true,

View File

@ -40,6 +40,13 @@ export const bbFactory = ({
delete: apiCall("DELETE"),
}
const safeCallEvent = (event, context) => {
const isFunction = obj =>
!!(obj && obj.constructor && obj.call && obj.apply)
if (isFunction(event)) event(context)
}
return (treeNode, setupState) => {
const attachParams = {
componentLibraries,
@ -53,7 +60,7 @@ export const bbFactory = ({
attachChildren: attachChildren(attachParams),
context: treeNode.context,
props: treeNode.props,
call: (event, context) => event(context),
call: safeCallEvent,
setStateFromBinding: (binding, value) =>
setStateFromBinding(store, binding, value),
setState: (path, value) => setState(store, path, value),

View File

@ -29,12 +29,8 @@ export const eventHandlers = (store, rootPath, routeTo) => {
return {
"Set State": handler(["path", "value"], setStateHandler),
"Load Record": handler(["recordKey", "statePath"], api.loadRecord),
"List Records": handler(["indexKey", "statePath"], api.listRecords),
"Save Record": handler(["statePath"], api.saveRecord),
"Navigate To": handler(["url"], param => routeTo(param && param.url)),
"Trigger Workflow": handler(["workflow"], api.triggerWorkflow),
Authenticate: handler(["username", "password"], api.authenticate),
"Trigger Workflow": handler(["workflow"], api.triggerWorkflow)
}
}

View File

@ -4,6 +4,7 @@ import {
EVENT_TYPE_MEMBER_NAME,
} from "./eventHandlers"
import { bbFactory } from "./bbComponentApi"
import { createTreeNode } from "../render/prepareRenderComponent"
import { getState } from "./getState"
import { attachChildren } from "../render/attachChildren"
import mustache from "mustache"
@ -34,16 +35,16 @@ export const createStateManager = ({
let currentState
// any nodes that have props that are bound to the store
let nodesBoundByProps = []
// let nodesBoundByProps = []
// any node whose children depend on code, that uses the store
let nodesWithCodeBoundChildren = []
// let nodesWithCodeBoundChildren = []
const getCurrentState = () => currentState
const registerBindings = _registerBindings(
nodesBoundByProps,
nodesWithCodeBoundChildren
)
// const registerBindings = _registerBindings(
// nodesBoundByProps,
// nodesWithCodeBoundChildren
// )
const bb = bbFactory({
store,
getCurrentState,
@ -52,14 +53,14 @@ export const createStateManager = ({
onScreenSlotRendered,
})
const setup = _setup(handlerTypes, getCurrentState, registerBindings, bb)
const setup = _setup(handlerTypes, getCurrentState, bb)
const unsubscribe = store.subscribe(
onStoreStateUpdated({
setCurrentState: s => (currentState = s),
setCurrentState: state => (currentState = state),
getCurrentState,
nodesWithCodeBoundChildren,
nodesBoundByProps,
// nodesWithCodeBoundChildren,
// nodesBoundByProps,
componentLibraries,
onScreenSlotRendered,
setupState: setup,
@ -77,91 +78,93 @@ export const createStateManager = ({
const onStoreStateUpdated = ({
setCurrentState,
getCurrentState,
nodesWithCodeBoundChildren,
// nodesBoundByProps,
componentLibraries,
onScreenSlotRendered,
setupState,
}) => state => {
setCurrentState(state)
// the original array gets changed by components' destroy()
// so we make a clone and check if they are still in the original
const nodesWithBoundChildren_clone = [...nodesWithCodeBoundChildren]
for (let node of nodesWithBoundChildren_clone) {
if (!nodesWithCodeBoundChildren.includes(node)) continue
attachChildren({
componentLibraries,
treeNode: node,
treeNode: createTreeNode(),
onScreenSlotRendered,
setupState,
getCurrentState,
})(node.rootElement, { hydrate: true, force: true })
}
})(document.querySelector("#app"), { hydrate: true, force: true })
// for (let node of nodesBoundByProps) {
// setNodeState(state, node)
// // the original array gets changed by components' destroy()
// // so we make a clone and check if they are still in the original
// const nodesWithBoundChildren_clone = [...nodesWithCodeBoundChildren]
// for (let node of nodesWithBoundChildren_clone) {
// if (!nodesWithCodeBoundChildren.includes(node)) continue
// attachChildren({
// componentLibraries,
// treeNode: node,
// onScreenSlotRendered,
// setupState,
// getCurrentState,
// })(node.rootElement, { hydrate: true, force: true })
// }
}
const _registerBindings = (nodesBoundByProps, nodesWithCodeBoundChildren) => (
node,
bindings
) => {
if (bindings.length > 0) {
node.bindings = bindings
nodesBoundByProps.push(node)
const onDestroy = () => {
nodesBoundByProps = nodesBoundByProps.filter(n => n === node)
node.onDestroy = node.onDestroy.filter(d => d === onDestroy)
}
node.onDestroy.push(onDestroy)
}
if (
node.props._children &&
node.props._children.filter(c => c._codeMeta && c._codeMeta.dependsOnStore)
.length > 0
) {
nodesWithCodeBoundChildren.push(node)
const onDestroy = () => {
nodesWithCodeBoundChildren = nodesWithCodeBoundChildren.filter(
n => n === node
)
node.onDestroy = node.onDestroy.filter(d => d === onDestroy)
}
node.onDestroy.push(onDestroy)
}
}
// const _registerBindings = (nodesBoundByProps, nodesWithCodeBoundChildren) => (
// node,
// bindings
// ) => {
// if (bindings.length > 0) {
// node.bindings = bindings
// nodesBoundByProps.push(node)
// const onDestroy = () => {
// nodesBoundByProps = nodesBoundByProps.filter(n => n === node)
// node.onDestroy = node.onDestroy.filter(d => d === onDestroy)
// }
// node.onDestroy.push(onDestroy)
// }
// if (
// node.props._children &&
// node.props._children.filter(c => c._codeMeta && c._codeMeta.dependsOnStore)
// .length > 0
// ) {
// nodesWithCodeBoundChildren.push(node)
// const onDestroy = () => {
// nodesWithCodeBoundChildren = nodesWithCodeBoundChildren.filter(
// n => n === node
// )
// node.onDestroy = node.onDestroy.filter(d => d === onDestroy)
// }
// node.onDestroy.push(onDestroy)
// }
// }
const setNodeState = (storeState, node) => {
if (!node.component) return
const newProps = { ...node.bindings.initialProps }
// const setNodeState = (storeState, node) => {
// if (!node.component) return
// const newProps = { ...node.bindings.initialProps }
for (let binding of node.bindings) {
const val = getState(storeState, binding.path, binding.fallback)
// for (let binding of node.bindings) {
// const val = getState(storeState, binding.path, binding.fallback)
if (val === undefined && newProps[binding.propName] !== undefined) {
delete newProps[binding.propName]
}
// if (val === undefined && newProps[binding.propName] !== undefined) {
// delete newProps[binding.propName]
// }
if (val !== undefined) {
newProps[binding.propName] = val
}
}
// if (val !== undefined) {
// newProps[binding.propName] = val
// }
// }
node.component.$set(newProps)
}
// node.component.$set(newProps)
// }
const _setup = (
handlerTypes,
getCurrentState,
registerBindings,
bb
) => node => {
console.log(node);
const props = node.props
const context = node.context || {}
const initialProps = { ...props }
const storeBoundProps = []
// const storeBoundProps = []
const currentStoreState = getCurrentState()
for (let propName in props) {
@ -249,9 +252,9 @@ const _setup = (
}
}
registerBindings(node, storeBoundProps)
// registerBindings(node, storeBoundProps)
const setup = _setup(handlerTypes, getCurrentState, registerBindings, bb)
const setup = _setup(handlerTypes, getCurrentState, bb)
initialProps._bb = bb(node, setup)
return initialProps