workflow UI with DnD
This commit is contained in:
parent
2965c2338d
commit
e659e69e86
|
@ -1,9 +1,11 @@
|
||||||
import { getStore } from "./store"
|
import { getStore } from "./store"
|
||||||
import { getBackendUiStore } from "./store/backend"
|
import { getBackendUiStore } from "./store/backend"
|
||||||
|
import { getWorkflowStore } from "./store/workflow"
|
||||||
import LogRocket from "logrocket"
|
import LogRocket from "logrocket"
|
||||||
|
|
||||||
export const store = getStore()
|
export const store = getStore()
|
||||||
export const backendUiStore = getBackendUiStore()
|
export const backendUiStore = getBackendUiStore()
|
||||||
|
export const workflowStore = getWorkflowStore()
|
||||||
|
|
||||||
export const initialise = async () => {
|
export const initialise = async () => {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -35,7 +35,7 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<heading>
|
<header>
|
||||||
{#if !showFieldView}
|
{#if !showFieldView}
|
||||||
<i class="ri-list-settings-line button--toggled" />
|
<i class="ri-list-settings-line button--toggled" />
|
||||||
<h3 class="budibase__title--3">Create / Edit Model</h3>
|
<h3 class="budibase__title--3">Create / Edit Model</h3>
|
||||||
|
@ -43,7 +43,7 @@
|
||||||
<i class="ri-file-list-line button--toggled" />
|
<i class="ri-file-list-line button--toggled" />
|
||||||
<h3 class="budibase__title--3">Create / Edit Field</h3>
|
<h3 class="budibase__title--3">Create / Edit Field</h3>
|
||||||
{/if}
|
{/if}
|
||||||
</heading>
|
</header>
|
||||||
{#if !showFieldView}
|
{#if !showFieldView}
|
||||||
<div class="padding">
|
<div class="padding">
|
||||||
<h4 class="budibase__label--big">Settings</h4>
|
<h4 class="budibase__label--big">Settings</h4>
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -58,6 +58,16 @@
|
||||||
|
|
||||||
--background-button: #f9f9f9;
|
--background-button: #f9f9f9;
|
||||||
--button-text: #0055ff;
|
--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 {
|
html, body {
|
||||||
|
|
|
@ -10,15 +10,18 @@
|
||||||
|
|
||||||
<link rel='icon' type='image/png' href='/_builder/favicon.png'>
|
<link rel='icon' type='image/png' href='/_builder/favicon.png'>
|
||||||
<link rel='stylesheet' href='/_builder/global.css'>
|
<link rel='stylesheet' href='/_builder/global.css'>
|
||||||
|
<link rel='stylesheet' href='/_builder/flowy.css'>
|
||||||
<link rel='stylesheet' href='/_builder/codemirror.css'>
|
<link rel='stylesheet' href='/_builder/codemirror.css'>
|
||||||
<link rel='stylesheet' href='/_builder/budibase.css'>
|
<link rel='stylesheet' href='/_builder/budibase.css'>
|
||||||
<link rel='stylesheet' href='/_builder/monokai.css'>
|
<link rel='stylesheet' href='/_builder/monokai.css'>
|
||||||
<link rel='stylesheet' href='/_builder/bundle.css'>
|
<link rel='stylesheet' href='/_builder/bundle.css'>
|
||||||
<link rel='stylesheet' href='/_builder/fonts.css'>
|
<link rel='stylesheet' href='/_builder/fonts.css'>
|
||||||
<link rel='stylesheet' href="/_builder/uikit.min.css">
|
<link rel='stylesheet' href="/_builder/uikit.min.css">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/alyssaxuu/flowy/flowy.min.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body id="app">
|
<body id="app">
|
||||||
|
<script src="https://cdn.jsdelivr.net/gh/alyssaxuu/flowy/flowy.min.js"></script>
|
||||||
<script src='/_builder/bundle.js'></script>
|
<script src='/_builder/bundle.js'></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -1,4 +1,5 @@
|
||||||
import "./global.css"
|
import "./global.css"
|
||||||
|
import "./flowy.css";
|
||||||
import "./fonts.css"
|
import "./fonts.css"
|
||||||
import "./budibase.css"
|
import "./budibase.css"
|
||||||
import "/assets/roboto-v20-latin-ext_latin-300"
|
import "/assets/roboto-v20-latin-ext_latin-300"
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
<script>
|
||||||
|
import { onMount } from "svelte"
|
||||||
|
import { backendUiStore } from "builderStore"
|
||||||
|
import api from "builderStore/api"
|
||||||
|
import blockDefinitions from "./blockDefinitions"
|
||||||
|
|
||||||
|
const SUB_TABS = [
|
||||||
|
{
|
||||||
|
name: "Triggers",
|
||||||
|
key: "TRIGGERS",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Actions",
|
||||||
|
key: "ACTIONS",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Utilities",
|
||||||
|
key: "UTILITIES",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
let selectedTab = "TRIGGERS"
|
||||||
|
let definitions = []
|
||||||
|
|
||||||
|
$: definitions = Object.values(blockDefinitions[selectedTab])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<header>
|
||||||
|
<span>Blocks</span>
|
||||||
|
<span>Props</span>
|
||||||
|
</header>
|
||||||
|
<div class="subtabs">
|
||||||
|
{#each SUB_TABS as tab}
|
||||||
|
<span
|
||||||
|
class="hoverable"
|
||||||
|
class:selected={tab.key === selectedTab}
|
||||||
|
on:click={() => (selectedTab = tab.key)}>
|
||||||
|
{tab.name}
|
||||||
|
</span>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
<div id="blocklist">
|
||||||
|
{#each definitions as blockDefinition}
|
||||||
|
<div class="blockelem create-flowy noselect">
|
||||||
|
<input
|
||||||
|
type="hidden"
|
||||||
|
name="blockelemtype"
|
||||||
|
class="blockelemtype"
|
||||||
|
value="1" />
|
||||||
|
<div class="grabme">
|
||||||
|
<!-- <img src="assets/grabme.svg" /> -->
|
||||||
|
</div>
|
||||||
|
<div class="blockin">
|
||||||
|
<div class="blockico">
|
||||||
|
<span />
|
||||||
|
<!-- <img src="assets/eye.svg" /> -->
|
||||||
|
</div>
|
||||||
|
<div class="blocktext">
|
||||||
|
<p class="blocktitle">{blockDefinition.name}</p>
|
||||||
|
<p class="blockdesc">{blockDefinition.description}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
header {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtabs {
|
||||||
|
margin-top: 27px;
|
||||||
|
display: grid;
|
||||||
|
grid-gap: 5px;
|
||||||
|
grid-auto-flow: column;
|
||||||
|
grid-auto-columns: 1fr 1fr 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtabs span {
|
||||||
|
text-align: center;
|
||||||
|
color: var(--font);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtabs span.selected {
|
||||||
|
border-bottom: 4px solid var(--primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtabs span:not(.selected) {
|
||||||
|
color: var(--dark-grey);
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -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
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
export { default as BlockPanel } from "./BlockPanel.svelte";
|
|
@ -0,0 +1,87 @@
|
||||||
|
<script>
|
||||||
|
import { store, backendUiStore, workflowStore } from "builderStore"
|
||||||
|
import api from "builderStore/api"
|
||||||
|
import ActionButton from "components/common/ActionButton.svelte"
|
||||||
|
|
||||||
|
export let onClosed
|
||||||
|
|
||||||
|
let name
|
||||||
|
|
||||||
|
$: valid = !!name
|
||||||
|
$: instanceId = $backendUiStore.selectedDatabase._id
|
||||||
|
$: appId = $store.appId
|
||||||
|
|
||||||
|
async function createWorkflow() {
|
||||||
|
await workflowStore.actions.create({
|
||||||
|
name,
|
||||||
|
instanceId,
|
||||||
|
})
|
||||||
|
onClosed()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<header>
|
||||||
|
<i class="ri-stackshare-line" />
|
||||||
|
Create Workflow
|
||||||
|
</header>
|
||||||
|
<div>
|
||||||
|
<label class="uk-form-label" for="form-stacked-text">Name</label>
|
||||||
|
<input class="uk-input" type="text" bind:value={name} />
|
||||||
|
</div>
|
||||||
|
<footer>
|
||||||
|
<a href="https://docs.budibase.com">
|
||||||
|
<i class="ri-information-line" />
|
||||||
|
Learn about workflows
|
||||||
|
</a>
|
||||||
|
<ActionButton alert on:click={onClosed}>Cancel</ActionButton>
|
||||||
|
<ActionButton disabled={!valid} on:click={createWorkflow}>Save</ActionButton>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
header {
|
||||||
|
font-size: 24px;
|
||||||
|
color: var(--font);
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header i {
|
||||||
|
margin-right: 10px;
|
||||||
|
font-size: 20px;
|
||||||
|
background: var(--secondary);
|
||||||
|
color: var(--dark-grey);
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
padding: 0 30px 30px 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
display: grid;
|
||||||
|
grid-auto-flow: column;
|
||||||
|
grid-gap: 5px;
|
||||||
|
grid-auto-columns: 3fr 1fr 1fr;
|
||||||
|
padding: 20px;
|
||||||
|
background: #fafafa;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a {
|
||||||
|
color: var(--primary);
|
||||||
|
font-size: 14px;
|
||||||
|
vertical-align: middle;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer i {
|
||||||
|
font-size: 20px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,84 @@
|
||||||
|
<script>
|
||||||
|
import Modal from "svelte-simple-modal"
|
||||||
|
import { onMount, getContext } from "svelte"
|
||||||
|
import { backendUiStore, workflowStore } from "builderStore";
|
||||||
|
import api from "builderStore/api"
|
||||||
|
import CreateWorkflowModal from "./CreateWorkflowModal.svelte";
|
||||||
|
|
||||||
|
|
||||||
|
const { open, close } = getContext("simple-modal")
|
||||||
|
|
||||||
|
function newWorkflow() {
|
||||||
|
open(
|
||||||
|
CreateWorkflowModal,
|
||||||
|
{
|
||||||
|
onClosed: close,
|
||||||
|
},
|
||||||
|
{ styleContent: { padding: "0" } }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
workflowStore.actions.fetch($backendUiStore.selectedDatabase._id);
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<header>
|
||||||
|
Workflows
|
||||||
|
<i on:click={newWorkflow} class="ri-add-circle-fill" />
|
||||||
|
</header>
|
||||||
|
<ul>
|
||||||
|
{#each $workflowStore.workflows as workflow}
|
||||||
|
<li class="workflow-item">
|
||||||
|
<i class="ri-stackshare-line" />
|
||||||
|
{workflow.name}
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
header {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: var(--dark-grey);
|
||||||
|
}
|
||||||
|
|
||||||
|
i:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workflow-item {
|
||||||
|
padding: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 3px;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workflow-item i {
|
||||||
|
font-size: 24px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workflow-item:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
background: var(--secondary);
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1 @@
|
||||||
|
export { default as WorkflowList } from "./WorkflowList.svelte";
|
|
@ -0,0 +1,47 @@
|
||||||
|
<script>
|
||||||
|
import { WorkflowList } from "./WorkflowList"
|
||||||
|
import { BlockPanel } from "./BlockPanel";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="root">
|
||||||
|
<div class="nav">
|
||||||
|
<WorkflowList />
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
<div class="nav">
|
||||||
|
<BlockPanel />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.content {
|
||||||
|
position: relative;
|
||||||
|
background: var(--background);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.root {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
background: #fafafa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
margin: 20px 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav {
|
||||||
|
overflow: auto;
|
||||||
|
flex: 0 1 auto;
|
||||||
|
width: 275px;
|
||||||
|
height: 100%;
|
||||||
|
border: 1px solid var(--medium-grey);
|
||||||
|
background: var(--white);
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,43 @@
|
||||||
|
<script>
|
||||||
|
import { onMount } from "svelte"
|
||||||
|
|
||||||
|
export let workflow = {}
|
||||||
|
|
||||||
|
let canvas
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
if (workflow.uiTree) {
|
||||||
|
flowy.import(workflow.uiTree);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
flowy(canvas, onGrab, onRelease);
|
||||||
|
})
|
||||||
|
|
||||||
|
function onGrab() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function onRelease() {
|
||||||
|
console.log("RELEASED!")
|
||||||
|
}
|
||||||
|
|
||||||
|
// function onGrab(block) {
|
||||||
|
// // When the user grabs a block
|
||||||
|
// }
|
||||||
|
// function onRelease() {
|
||||||
|
// // When the user releases a block
|
||||||
|
// console.log(flowy.output())
|
||||||
|
// }
|
||||||
|
// function onSnap(block, first, parent) {
|
||||||
|
// console.log(flowy.output())
|
||||||
|
// console.log(block, first, parent)
|
||||||
|
// // When a block snaps with another one
|
||||||
|
// }
|
||||||
|
// function onRearrange(block, parent) {
|
||||||
|
// console.log(block, parent)
|
||||||
|
// // When a block is rearranged
|
||||||
|
// }
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<section bind:this={canvas} class="canvas" />
|
|
@ -0,0 +1,5 @@
|
||||||
|
<script>
|
||||||
|
import WorkflowBuilder from "./flowy/WorkflowBuilder.svelte";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<WorkflowBuilder />
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
import regexparam from "regexparam"
|
import regexparam from "regexparam"
|
||||||
import { writable } from "svelte/store"
|
import { writable } from "svelte/store"
|
||||||
|
|
||||||
|
// TODO: refactor
|
||||||
export const screenRouter = (screens, onScreenSelected, appRootPath) => {
|
export const screenRouter = (screens, onScreenSelected, appRootPath) => {
|
||||||
const makeRootedPath = url => {
|
const makeRootedPath = url => {
|
||||||
if (appRootPath) {
|
if (appRootPath) {
|
||||||
|
|
|
@ -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: "<b> - 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)} } )`
|
|
|
@ -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",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
Loading…
Reference in New Issue