From 6f3ad884db24b131fda14a0b41cd3bd0602b337f Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 21 May 2020 21:40:16 +0100 Subject: [PATCH] workflow UI with DnD --- packages/builder/src/builderStore/index.js | 2 + .../src/builderStore/store/workflow.js | 34 + .../CreateEditModel/CreateEditModel.svelte | 4 +- packages/builder/src/flowy.css | 640 ++++++++++++++++++ packages/builder/src/global.css | 10 + packages/builder/src/index.html | 3 + packages/builder/src/main.js | 1 + .../workflow/BlockPanel/BlockPanel.svelte | 99 +++ .../workflow/BlockPanel/blockDefinitions.js | 54 ++ .../workflow/BlockPanel/index.js | 1 + .../WorkflowList/CreateWorkflowModal.svelte | 87 +++ .../workflow/WorkflowList/WorkflowList.svelte | 84 +++ .../workflow/WorkflowList/index.js | 1 + .../[application]/workflow/_layout.svelte | 47 ++ .../workflow/flowy/WorkflowBuilder.svelte | 43 ++ .../pages/[application]/workflow/flowy/apl.js | 0 .../pages/[application]/workflow/index.svelte | 5 + .../workflow/orchestrator/index.js | 38 ++ packages/client/src/render/screenRouter.js | 1 + .../src/Templates/indexDatatable.js | 80 --- .../src/Templates/recordForm.js | 149 ---- 21 files changed, 1152 insertions(+), 231 deletions(-) create mode 100644 packages/builder/src/builderStore/store/workflow.js create mode 100644 packages/builder/src/flowy.css create mode 100644 packages/builder/src/pages/[application]/workflow/BlockPanel/BlockPanel.svelte create mode 100644 packages/builder/src/pages/[application]/workflow/BlockPanel/blockDefinitions.js create mode 100644 packages/builder/src/pages/[application]/workflow/BlockPanel/index.js create mode 100644 packages/builder/src/pages/[application]/workflow/WorkflowList/CreateWorkflowModal.svelte create mode 100644 packages/builder/src/pages/[application]/workflow/WorkflowList/WorkflowList.svelte create mode 100644 packages/builder/src/pages/[application]/workflow/WorkflowList/index.js create mode 100644 packages/builder/src/pages/[application]/workflow/_layout.svelte create mode 100644 packages/builder/src/pages/[application]/workflow/flowy/WorkflowBuilder.svelte create mode 100644 packages/builder/src/pages/[application]/workflow/flowy/apl.js create mode 100644 packages/builder/src/pages/[application]/workflow/index.svelte create mode 100644 packages/builder/src/pages/[application]/workflow/orchestrator/index.js delete mode 100644 packages/materialdesign-components/src/Templates/indexDatatable.js delete mode 100644 packages/materialdesign-components/src/Templates/recordForm.js diff --git a/packages/builder/src/builderStore/index.js b/packages/builder/src/builderStore/index.js index 8ba017a7c8..dd6784c135 100644 --- a/packages/builder/src/builderStore/index.js +++ b/packages/builder/src/builderStore/index.js @@ -1,9 +1,11 @@ import { getStore } from "./store" import { getBackendUiStore } from "./store/backend" +import { getWorkflowStore } from "./store/workflow" import LogRocket from "logrocket" export const store = getStore() export const backendUiStore = getBackendUiStore() +export const workflowStore = getWorkflowStore() export const initialise = async () => { try { diff --git a/packages/builder/src/builderStore/store/workflow.js b/packages/builder/src/builderStore/store/workflow.js new file mode 100644 index 0000000000..b6aef38c72 --- /dev/null +++ b/packages/builder/src/builderStore/store/workflow.js @@ -0,0 +1,34 @@ +import { writable } from "svelte/store" +import api from "../api" + +export const getWorkflowStore = () => { + const INITIAL_WORKFLOW_STATE = { + workflows: [] + } + + const store = writable(INITIAL_WORKFLOW_STATE) + + store.actions = { + fetch: async instanceId => { + const WORKFLOWS_URL = `/api/${instanceId}/workflows`; + const workflowResponse = await api.get(WORKFLOWS_URL); + const json = await workflowResponse.json(); + store.update(state => { + state.workflows = json + return state + }) + }, + create: async ({ instanceId, name }) => { + const workflow = { name } + const CREATE_WORKFLOW_URL = `/api/${instanceId}/workflows`; + const response = await api.post(CREATE_WORKFLOW_URL, workflow) + const json = await response.json(); + store.update(state => { + state.workflows = state.workflows.concat(json.workflow) + return state + }) + }, + } + + return store +} \ No newline at end of file diff --git a/packages/builder/src/components/database/ModelDataTable/modals/CreateEditModel/CreateEditModel.svelte b/packages/builder/src/components/database/ModelDataTable/modals/CreateEditModel/CreateEditModel.svelte index 97bb799c45..bd302df5b7 100644 --- a/packages/builder/src/components/database/ModelDataTable/modals/CreateEditModel/CreateEditModel.svelte +++ b/packages/builder/src/components/database/ModelDataTable/modals/CreateEditModel/CreateEditModel.svelte @@ -35,7 +35,7 @@ } - +
{#if !showFieldView}

Create / Edit Model

@@ -43,7 +43,7 @@

Create / Edit Field

{/if} - +
{#if !showFieldView}

Settings

diff --git a/packages/builder/src/flowy.css b/packages/builder/src/flowy.css new file mode 100644 index 0000000000..647f404730 --- /dev/null +++ b/packages/builder/src/flowy.css @@ -0,0 +1,640 @@ +body, html { + margin: 0px; + padding: 0px; + overflow: hidden; + background-repeat: repeat; + background-size: 30px 30px; + background-color: #FBFBFB; + height: 100%; +} +#navigation { + height: 71px; + background-color: #FFF; + border: 1px solid #E8E8EF; + width: 100%; + display: table; + box-sizing: border-box; + position: fixed; + top: 0; + z-index: 9 +} +#back { + width: 40px; + height: 40px; + border-radius: 100px; + background-color: #F1F4FC; + text-align: center; + display: inline-block; + vertical-align: top; + margin-top: 12px; + margin-right: 10px +} +#back img { + margin-top: 13px; +} +#names { + display: inline-block; + vertical-align: top; +} +#title { + font-family: Roboto; + font-weight: 500; + font-size: 16px; + color: #393C44; + margin-bottom: 0px; +} +#subtitle { + font-family: Roboto; + color: #808292; + font-size: 14px; + margin-top: 5px; +} +#leftside { + display: inline-block; + vertical-align: middle; + margin-left: 20px; +} +#centerswitch { + position: absolute; + width: 222px; + left: 50%; + margin-left: -111px; + top: 15px; +} +#leftswitch { + border: 1px solid #E8E8EF; + background-color: #FBFBFB; + width: 111px; + height: 39px; + line-height: 39px; + border-radius: 5px 0px 0px 5px; + font-family: Roboto; + color: #393C44; + display: inline-block; + font-size: 14px; + text-align: center; +} +#rightswitch { + font-family: Roboto; + color: #808292; + border-radius: 0px 5px 5px 0px; + border: 1px solid #E8E8EF; + height: 39px; + width: 102px; + display: inline-block; + font-size: 14px; + line-height: 39px; + text-align: center; + margin-left: -5px; +} +#discard { + font-family: Roboto; + font-weight: 500; + font-size: 14px; + color: #A6A6B3; + width: 95px; + height: 38px; + border: 1px solid #E8E8EF; + border-radius: 5px; + text-align: center; + line-height: 38px; + display: inline-block; + vertical-align: top; + transition: all .2s cubic-bezier(.05,.03,.35,1); +} +#discard:hover { + cursor: pointer; + opacity: .7; +} +#publish { + font-family: Roboto; + font-weight: 500; + font-size: 14px; + color: #FFF; + background-color: #217CE8; + border-radius: 5px; + width: 143px; + height: 38px; + margin-left: 10px; + display: inline-block; + vertical-align: top; + text-align: center; + line-height: 38px; + margin-right: 20px; + transition: all .2s cubic-bezier(.05,.03,.35,1); +} +#publish:hover { + cursor: pointer; + opacity: .7; +} +#buttonsright { + float: right; + margin-top: 15px; +} +#leftcard { + width: 363px; + background-color: #FFF; + border: 1px solid #E8E8EF; + box-sizing: border-box; + padding-top: 85px; + padding-left: 20px; + height: 100%; + position: absolute; + z-index: 2; +} +#search input { + width: 318px; + height: 40px; + background-color: #FFF; + border: 1px solid #E8E8EF; + box-sizing: border-box; + box-shadow: 0px 2px 8px rgba(34,34,87,0.05); + border-radius: 5px; + text-indent: 35px; + font-family: Roboto; + font-size: 16px; +} +::-webkit-input-placeholder { /* Edge */ + color: #C9C9D5; +} + +:-ms-input-placeholder { /* Internet Explorer 10-11 */ + color: #C9C9D5 +} + +::placeholder { + color: #C9C9D5; +} +#search img { + position: absolute; + margin-top: 10px; + width: 18px; + margin-left: 12px; +} +#header { + font-size: 20px; + font-family: Roboto; + font-weight: bold; + color: #393C44; +} +#subnav { + border-bottom: 1px solid #E8E8EF; + width: calc(100% + 20px); + margin-left: -20px; + margin-top: 10px; +} +.navdisabled { + transition: all .3s cubic-bezier(.05,.03,.35,1); +} +.navdisabled:hover { + cursor: pointer; + opacity: .5; +} +.navactive { + color: #393C44!important; +} +#triggers { + margin-left: 20px; + font-family: Roboto; + font-weight: 500; + font-size: 14px; + text-align: center; + color: #808292; + width: calc(88% / 3); + height: 48px; + line-height: 48px; + display: inline-block; + float: left; +} +.navactive:after { + display: block; + content: ""; + width: 100%; + height: 4px; + background-color: #217CE8; + margin-top: -4px; +} +#actions { + display: inline-block; + font-family: Roboto; + font-weight: 500; + color: #808292; + font-size: 14px; + height: 48px; + line-height: 48px; + width: calc(88% / 3); + text-align: center; + float: left; +} +#loggers { + width: calc(88% / 3); + display: inline-block; + font-family: Roboto; + font-weight: 500; + color: #808292; + font-size: 14px; + height: 48px; + line-height: 48px; + text-align: center; +} +#footer { + position: absolute; + left: 0; + padding-left: 20px; + line-height: 40px; + bottom: 0; + width: 362px; + border: 1px solid #E8E8EF; + height: 67px; + box-sizing: border-box; + background-color: #FFF; + font-family: Roboto; + font-size: 14px; +} +#footer a { + text-decoration: none; + color: #393C44; + transition: all .2s cubic-bezier(.05,.03,.35,1); +} +#footer a:hover { + opacity: .5; +} +#footer span { + color: #808292; +} +#footer p { + display: inline-block; + color: #808292; +} +#footer img { + margin-left: 5px; + margin-right: 5px; +} +.blockelem:first-child { + margin-top: 20px +} +.blockelem { + padding-top: 10px; + width: 318px; + border: 1px solid transparent; + transition-property: box-shadow, height; + transition-duration: .2s; + transition-timing-function: cubic-bezier(.05,.03,.35,1); + border-radius: 5px; + box-shadow: 0px 0px 30px rgba(22, 33, 74, 0); + box-sizing: border-box; +} +.blockelem:hover { + box-shadow: 0px 4px 30px rgba(22, 33, 74, 0.08); + border-radius: 5px; + background-color: #FFF; + cursor: pointer; +} +.grabme, .blockico { + display: inline-block; +} +.grabme { + margin-top: 10px; + margin-left: 10px; + margin-bottom: -14px; + width: 15px; +} +#blocklist { + height: calc(100% - 220px); + overflow: auto; +} +#proplist { + height: calc(100% - 305px); + overflow: auto; + margin-top: -30px; + padding-top: 30px; +} +.blockin { + display: inline-block; + vertical-align: top; + margin-left: 12px; +} +.blockico { + width: 36px; + height: 36px; + background-color: #F1F4FC; + border-radius: 5px; + text-align: center; + white-space: nowrap; +} +.blockico span { + height: 100%; + width: 0px; + display: inline-block; + vertical-align: middle; +} +.blockico img { + vertical-align: middle; + margin-left: auto; + margin-right: auto; + display: inline-block; +} +.blocktext { + display: inline-block; + width: 220px; + vertical-align: top; + margin-left: 12px +} +.blocktitle { + margin: 0px!important; + padding: 0px!important; + font-family: Roboto; + font-weight: 500; + font-size: 16px; + color: #393C44; +} +.blockdesc { + margin-top: 5px; + font-family: Roboto; + color: #808292; + font-size: 14px; + line-height: 21px; +} +.blockdisabled { + background-color: #F0F2F9; + opacity: .5; +} +#closecard { + position: absolute; + margin-left: 340px; + background-color: #FFF; + border-radius: 0px 5px 5px 0px; + border-bottom: 1px solid #E8E8EF; + border-right: 1px solid #E8E8EF; + border-top: 1px solid #E8E8EF; + width: 53px; + height: 53px; + text-align: center; + z-index: 10; +} +#closecard img { + margin-top: 15px +} +#canvas { + border: 1px solid green; + position: absolute; + width: calc(100% - 361px); + height: calc(100% - 71px); + top: 71px; + left: 361px; + z-index: 0; + overflow: auto; +} +#propwrap { + position: absolute; + right: 0; + top: 0; + width: 311px; + height: 100%; + padding-left: 20px; + overflow: hidden; + z-index: -2; +} +#properties { + position: absolute; + height: 100%; + width: 311px; + background-color: #FFF; + right: -150px; + opacity: 0; + z-index: 2; + top: 0px; + box-shadow: -4px 0px 40px rgba(26, 26, 73, 0); + padding-left: 20px; + transition: all .25s cubic-bezier(.05,.03,.35,1); +} +.itson { + z-index: 2!important; +} +.expanded { + right: 0!important; + opacity: 1!important; + box-shadow: -4px 0px 40px rgba(26, 26, 73, 0.05); + z-index: 2; +} +#header2 { + font-size: 20px; + font-family: Roboto; + font-weight: bold; + color: #393C44; + margin-top: 101px; +} +#close { + margin-top: 100px; + position: absolute; + right: 20px; + z-index: 9999; + transition: all .25s cubic-bezier(.05,.03,.35,1); +} +#close:hover { + cursor: pointer; + opacity: .7; +} +#propswitch { + border-bottom: 1px solid #E8E8EF; + width: 331px; + margin-top: 10px; + margin-left: -20px; + margin-bottom: 30px; +} +#dataprop { + font-family: Roboto; + font-weight: 500; + font-size: 14px; + text-align: center; + color: #393C44; + width: calc(88% / 3); + height: 48px; + line-height: 48px; + display: inline-block; + float: left; + margin-left: 20px; +} +#dataprop:after { + display: block; + content: ""; + width: 100%; + height: 4px; + background-color: #217CE8; + margin-top: -4px; +} +#alertprop { + display: inline-block; + font-family: Roboto; + font-weight: 500; + color: #808292; + font-size: 14px; + height: 48px; + line-height: 48px; + width: calc(88% / 3); + text-align: center; + float: left; +} +#logsprop { + width: calc(88% / 3); + display: inline-block; + font-family: Roboto; + font-weight: 500; + color: #808292; + font-size: 14px; + height: 48px; + line-height: 48px; + text-align: center; +} +.inputlabel { + font-family: Roboto; + font-size: 14px; + color: #253134; +} +.dropme { + background-color: #FFF; + border-radius: 5px; + border: 1px solid #E8E8EF; + box-shadow: 0px 2px 8px rgba(34, 34, 87, 0.05); + font-family: Roboto; + font-size: 14px; + color: #253134; + text-indent: 20px; + height: 40px; + line-height: 40px; + width: 287px; + margin-bottom: 25px; +} +.dropme img { + margin-top: 17px; + float: right; + margin-right: 15px; +} +.checkus { + margin-bottom: 10px; +} +.checkus img { + display: inline-block; + vertical-align: middle; +} +.checkus p { + display: inline-block; + font-family: Roboto; + font-size: 14px; + vertical-align: middle; + margin-left: 10px; +} +#divisionthing { + height: 1px; + width: 100%; + background-color: #E8E8EF; + position: absolute; + right: 0px; + bottom: 80; +} +#removeblock { + border-radius: 5px; + position: absolute; + bottom: 20px; + font-family: Roboto; + font-size: 14px; + text-align: center; + width: 287px; + height: 38px; + line-height: 38px; + color: #253134; + border: 1px solid #E8E8EF; + transition: all .3s cubic-bezier(.05,.03,.35,1); +} +#removeblock:hover { + cursor: pointer; + opacity: .5; +} +.noselect { + -webkit-touch-callout: none; /* iOS Safari */ + -webkit-user-select: none; /* Safari */ + -khtml-user-select: none; /* Konqueror HTML */ + -moz-user-select: none; /* Old versions of Firefox */ + -ms-user-select: none; /* Internet Explorer/Edge */ + user-select: none; /* Non-prefixed version, currently + supported by Chrome, Opera and Firefox */ +} +.blockyname { + font-family: Roboto; + font-weight: 500; + color: #253134; + display: inline-block; + vertical-align: middle; + margin-left: 8px; + font-size: 16px; +} +.blockyleft img { + display: inline-block; + vertical-align: middle; +} +.blockyright { + display: inline-block; + float: right; + vertical-align: middle; + margin-right: 20px; + margin-top: 10px; + width: 28px; + height: 28px; + border-radius: 5px; + text-align: center; + background-color: #FFF; + transition: all .3s cubic-bezier(.05,.03,.35,1); + z-index: 10; +} +.blockyright:hover { + background-color: #F1F4FC; + cursor: pointer; +} +.blockyright img { + margin-top: 12px; +} +.blockyleft { + display: inline-block; + margin-left: 20px; +} +.blockydiv { + width: 100%; + height: 1px; + background-color: #E9E9EF; +} +.blockyinfo { + font-family: Roboto; + font-size: 14px; + color: #808292; + margin-top: 15px; + text-indent: 20px; + margin-bottom: 20px; +} +.blockyinfo span { + color: #253134; + font-weight: 500; + display: inline-block; + border-bottom: 1px solid #D3DCEA; + line-height: 20px; + text-indent: 0px; +} +.block { + background-color: #FFF; + margin-top: 0px!important; + box-shadow: 0px 4px 30px rgba(22, 33, 74, 0.05); +} +.selectedblock { + border: 2px solid #217CE8; + box-shadow: 0px 4px 30px rgba(22, 33, 74, 0.08); +} + +@media only screen and (max-width: 832px) { + #centerswitch { + display: none; + } +} +@media only screen and (max-width: 560px) { + #names { + display: none; + } +} \ No newline at end of file diff --git a/packages/builder/src/global.css b/packages/builder/src/global.css index 999415931a..08921f95d2 100644 --- a/packages/builder/src/global.css +++ b/packages/builder/src/global.css @@ -58,6 +58,16 @@ --background-button: #f9f9f9; --button-text: #0055ff; + + /* Budibase Styleguide Colors */ + --primary: #0055ff; + --secondary: #f1f4fc; + --color: #393c44; + --dark-grey: #808192; + --medium-grey: #e8e8ef; + --background: rgb(251, 251, 251); + --font: #393c44; + --coral: #eb5757; } html, body { diff --git a/packages/builder/src/index.html b/packages/builder/src/index.html index 23c5aaf6c0..65239c2e69 100644 --- a/packages/builder/src/index.html +++ b/packages/builder/src/index.html @@ -10,15 +10,18 @@ + + + \ No newline at end of file diff --git a/packages/builder/src/main.js b/packages/builder/src/main.js index eb1357fde2..f664629c66 100644 --- a/packages/builder/src/main.js +++ b/packages/builder/src/main.js @@ -1,4 +1,5 @@ import "./global.css" +import "./flowy.css"; import "./fonts.css" import "./budibase.css" import "/assets/roboto-v20-latin-ext_latin-300" diff --git a/packages/builder/src/pages/[application]/workflow/BlockPanel/BlockPanel.svelte b/packages/builder/src/pages/[application]/workflow/BlockPanel/BlockPanel.svelte new file mode 100644 index 0000000000..f66cdcc580 --- /dev/null +++ b/packages/builder/src/pages/[application]/workflow/BlockPanel/BlockPanel.svelte @@ -0,0 +1,99 @@ + + +
+
+ Blocks + Props +
+
+ {#each SUB_TABS as tab} + (selectedTab = tab.key)}> + {tab.name} + + {/each} +
+
+ {#each definitions as blockDefinition} +
+ +
+ +
+
+
+ + +
+
+

{blockDefinition.name}

+

{blockDefinition.description}

+
+
+
+ {/each} +
+
+ + diff --git a/packages/builder/src/pages/[application]/workflow/BlockPanel/blockDefinitions.js b/packages/builder/src/pages/[application]/workflow/BlockPanel/blockDefinitions.js new file mode 100644 index 0000000000..d13f317a2b --- /dev/null +++ b/packages/builder/src/pages/[application]/workflow/BlockPanel/blockDefinitions.js @@ -0,0 +1,54 @@ +const ACTIONS = { + SET_STATE: { + name: "Update UI", + icon: "", + description: "Update your User Interface with some data.", + type: "CLIENT", + }, + NAVIGATE: { + name: "Navigate", + icon: "", + description: "Navigate to another page.", + type: "CLIENT" + }, + CREATE_RECORD: { + name: "Save Record", + icon: "", + description: "Save a record to your database.", + type: "SERVER", + }, + DELETE_RECORD: { + description: "Delete a record from your database.", + icon: "", + name: "Delete Record", + type: "SERVER", + } +}; + +const TRIGGERS = { + CLICK: { + name: "Click", + icon: "", + description: "Trigger when you click on an element in the UI." + }, + LOAD: { + name: "Load", + icon: "", + description: "Trigger an element has finished loading." + }, + INPUT: { + name: "Input", + icon: "", + description: "Trigger when you type into an input box." + }, +}; + +const UTILITIES = { + +} + +export default { + ACTIONS, + TRIGGERS, + UTILITIES +} \ No newline at end of file diff --git a/packages/builder/src/pages/[application]/workflow/BlockPanel/index.js b/packages/builder/src/pages/[application]/workflow/BlockPanel/index.js new file mode 100644 index 0000000000..73ebcd6949 --- /dev/null +++ b/packages/builder/src/pages/[application]/workflow/BlockPanel/index.js @@ -0,0 +1 @@ +export { default as BlockPanel } from "./BlockPanel.svelte"; \ No newline at end of file diff --git a/packages/builder/src/pages/[application]/workflow/WorkflowList/CreateWorkflowModal.svelte b/packages/builder/src/pages/[application]/workflow/WorkflowList/CreateWorkflowModal.svelte new file mode 100644 index 0000000000..510b21704e --- /dev/null +++ b/packages/builder/src/pages/[application]/workflow/WorkflowList/CreateWorkflowModal.svelte @@ -0,0 +1,87 @@ + + +
+ + Create Workflow +
+
+ + +
+ + + diff --git a/packages/builder/src/pages/[application]/workflow/WorkflowList/WorkflowList.svelte b/packages/builder/src/pages/[application]/workflow/WorkflowList/WorkflowList.svelte new file mode 100644 index 0000000000..c611143f78 --- /dev/null +++ b/packages/builder/src/pages/[application]/workflow/WorkflowList/WorkflowList.svelte @@ -0,0 +1,84 @@ + + +
+
+ Workflows + +
+
    + {#each $workflowStore.workflows as workflow} +
  • + + {workflow.name} +
  • + {/each} +
+
+ + diff --git a/packages/builder/src/pages/[application]/workflow/WorkflowList/index.js b/packages/builder/src/pages/[application]/workflow/WorkflowList/index.js new file mode 100644 index 0000000000..18bd078eaa --- /dev/null +++ b/packages/builder/src/pages/[application]/workflow/WorkflowList/index.js @@ -0,0 +1 @@ +export { default as WorkflowList } from "./WorkflowList.svelte"; \ No newline at end of file diff --git a/packages/builder/src/pages/[application]/workflow/_layout.svelte b/packages/builder/src/pages/[application]/workflow/_layout.svelte new file mode 100644 index 0000000000..ec0a7d4ef9 --- /dev/null +++ b/packages/builder/src/pages/[application]/workflow/_layout.svelte @@ -0,0 +1,47 @@ + + +
+ +
+ +
+ +
+ + diff --git a/packages/builder/src/pages/[application]/workflow/flowy/WorkflowBuilder.svelte b/packages/builder/src/pages/[application]/workflow/flowy/WorkflowBuilder.svelte new file mode 100644 index 0000000000..0d596915c3 --- /dev/null +++ b/packages/builder/src/pages/[application]/workflow/flowy/WorkflowBuilder.svelte @@ -0,0 +1,43 @@ + + +
diff --git a/packages/builder/src/pages/[application]/workflow/flowy/apl.js b/packages/builder/src/pages/[application]/workflow/flowy/apl.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/builder/src/pages/[application]/workflow/index.svelte b/packages/builder/src/pages/[application]/workflow/index.svelte new file mode 100644 index 0000000000..766d9efaea --- /dev/null +++ b/packages/builder/src/pages/[application]/workflow/index.svelte @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/packages/builder/src/pages/[application]/workflow/orchestrator/index.js b/packages/builder/src/pages/[application]/workflow/orchestrator/index.js new file mode 100644 index 0000000000..5f037c07ff --- /dev/null +++ b/packages/builder/src/pages/[application]/workflow/orchestrator/index.js @@ -0,0 +1,38 @@ +import api from "builderStore/api"; + +class Orchestrator { + set strategy(strategy) { + this._stategy = strategy + } + + execute(workflow) { + this._strategy.execute(workflow); + } +} + +const ClientStrategy = { + execute: function(workflow) { + const block = workflow.next; + const EXECUTE_WORKFLOW_URL = `api/${workflow.instanceId}/workflows/${workflow._id}`; + + switch (block.type) { + case "CLIENT": + // fetch the workflow code from the server, then execute it here in the client + // catch any errors + // check against the conditions in the workflow + // if everything is fine, recurse + this.execute(workflow.next); + break; + case "SERVER": + // hit the server endpoint and wait for the response + // catch any errors + // check against the conditions in the workflow + // if everything is fine, recurse + await api.post() + break; + default: + break; + } + + } +} \ No newline at end of file diff --git a/packages/client/src/render/screenRouter.js b/packages/client/src/render/screenRouter.js index a45daca54f..f04df723a6 100644 --- a/packages/client/src/render/screenRouter.js +++ b/packages/client/src/render/screenRouter.js @@ -1,6 +1,7 @@ import regexparam from "regexparam" import { writable } from "svelte/store" +// TODO: refactor export const screenRouter = (screens, onScreenSelected, appRootPath) => { const makeRootedPath = url => { if (appRootPath) { diff --git a/packages/materialdesign-components/src/Templates/indexDatatable.js b/packages/materialdesign-components/src/Templates/indexDatatable.js deleted file mode 100644 index f242e7d8d6..0000000000 --- a/packages/materialdesign-components/src/Templates/indexDatatable.js +++ /dev/null @@ -1,80 +0,0 @@ -export default ({ indexes, helpers }) => - indexes.map(i => ({ - name: `Table based on view: ${i.name} `, - props: tableProps( - i, - helpers.indexSchema(i).filter(c => !excludedColumns.includes(c.name)) - ), - })) - -const excludedColumns = ["id", "key", "sortKey", "type", "isNew"] - -const tableProps = (index, indexSchema) => ({ - _component: "@budibase/materialdesign-components/Datatable", - _children: [ - { - _component: "@budibase/materialdesign-components/DatatableHead", - _children: [ - { - _component: "@budibase/materialdesign-components/DatatableRow", - isHeader: true, - _children: columnHeaders(indexSchema), - }, - ], - }, - { - _component: "@budibase/materialdesign-components/DatatableBody", - _children: [ - { - _code: rowCode(index), - _component: "@budibase/materialdesign-components/DatatableRow", - _children: dataCells(index, indexSchema), - }, - ], - }, - ], - onLoad: [ - { - "##eventHandlerType": "List Records", - parameters: { - indexKey: index.nodeKey(), - statePath: index.name, - }, - }, - ], -}) - -const columnHeaders = indexSchema => - indexSchema.map(col => ({ - _component: "@budibase/materialdesign-components/DatatableCell", - isHeader: true, - _children: [ - { - _component: "@budibase/standard-components/text", - type: "none", - text: col.name, - formattingTag: " - bold", - }, - ], - })) - -const dataCells = (index, indexSchema) => - indexSchema.map(col => ({ - _component: "@budibase/materialdesign-components/DatatableCell", - _children: [ - { - _component: "@budibase/standard-components/text", - type: "none", - text: `context.${dataItem(index)}.${col.name}`, - }, - ], - })) - -const dataItem = index => `${index.name}_item` -const dataCollection = index => `state.${index.name}` -const rowCode = index => - ` -if (!${dataCollection(index)}) return - -for (let ${dataItem(index)} of ${dataCollection(index)}) - render( { ${dataItem(index)} } )` diff --git a/packages/materialdesign-components/src/Templates/recordForm.js b/packages/materialdesign-components/src/Templates/recordForm.js deleted file mode 100644 index 38ab602a8e..0000000000 --- a/packages/materialdesign-components/src/Templates/recordForm.js +++ /dev/null @@ -1,149 +0,0 @@ -export default ({ records }) => - records.map(r => ({ - name: `Form for Record: ${r.nodeName()}`, - props: outerContainer(r), - })) - -const outerContainer = record => ({ - _component: "@budibase/standard-components/container", - _code: "", - type: "div", - onLoad: [ - { - "##eventHandlerType": "Get New Record", - parameters: { - collectionKey: record.collectionNodeKey(), - childRecordType: record.name, - statePath: record.name, - }, - }, - ], - _children: [ - heading(record), - ...record.fields.map(f => field(record, f)), - buttons(record), - ], -}) - -const heading = record => ({ - _component: "@budibase/materialdesign-components/H3", - text: capitalize(record.name), -}) - -const field = (record, f) => { - if (f.type === "bool") return checkbox(record, f) - if ( - f.type === "string" && - f.typeOptions && - f.typeOptions.values && - f.typeOptions.values.length > 0 - ) - return select(record, f) - return textField(record, f) -} - -const textField = (record, f) => ({ - _component: "@budibase/materialdesign-components/Textfield", - label: f.label, - variant: "filled", - disabled: false, - fullwidth: false, - colour: "primary", - maxLength: - f.typeOptions && f.typeOptions.maxLength ? f.typeOptions.maxLength : 0, - placeholder: f.label, - value: fieldValueBinding(record, f), -}) - -const checkbox = (record, f) => ({ - _component: "@budibase/materialdesign-components/Checkbox", - label: f.label, - checked: fieldValueBinding(record, f), -}) - -const select = (record, f) => ({ - _component: "@budibase/materialdesign-components/Select", - value: fieldValueBinding(record, f), - _children: f.typeOptions.values.map(val => ({ - _component: "@budibase/materialdesign-components/ListItem", - value: val, - text: val, - })), -}) - -const fieldValueBinding = (record, f) => `state.${record.name}.${f.name}` - -const capitalize = s => s.charAt(0).toUpperCase() + s.slice(1) - -const buttons = record => ({ - _component: "@budibase/standard-components/container", - borderWidth: "1px 0px 0px 0px", - borderColor: "lightgray", - borderStyle: "solid", - _styles: { - position: { - column: ["", ""], - row: ["", ""], - margin: ["", "", "", ""], - padding: ["30px", "", "", ""], - height: [""], - width: [""], - zindex: [""], - }, - layout: { - templaterows: [""], - templatecolumns: [""], - }, - }, - _children: [ - { - _component: "@budibase/materialdesign-components/Button", - onClick: [ - { - "##eventHandlerType": "Save Record", - parameters: { - statePath: `${record.name}`, - }, - }, - { - "##eventHandlerType": "Navigate To", - parameters: { - url: `/${record.name}s`, - }, - }, - ], - variant: "raised", - colour: "primary", - size: "medium", - text: `Save ${capitalize(record.name)}`, - }, - { - _component: "@budibase/materialdesign-components/Button", - _styles: { - position: { - row: ["", ""], - column: ["", ""], - padding: ["", "", "", ""], - margin: ["", "", "", "10px"], - width: [""], - height: [""], - zindex: [""], - }, - layout: { - templatecolumns: [""], - templaterows: [""], - }, - }, - onClick: [ - { - "##eventHandlerType": "Navigate To", - parameters: { - url: `/${record.name}s`, - }, - }, - ], - colour: "secondary", - text: "Cancel", - }, - ], -})