make alerts live, more hooks, app notifications
This commit is contained in:
parent
6f0a84dd38
commit
7a3b368399
|
@ -38,6 +38,7 @@
|
|||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@beyonk/svelte-notifications": "^2.0.3",
|
||||
"@budibase/client": "^0.0.32",
|
||||
"@nx-js/compiler-util": "^2.0.0",
|
||||
"codemirror": "^5.51.0",
|
||||
|
|
|
@ -152,7 +152,7 @@ export default {
|
|||
{
|
||||
find: "builderStore",
|
||||
replacement: path.resolve(projectRootDir, "src/builderStore"),
|
||||
},
|
||||
}
|
||||
],
|
||||
customResolver,
|
||||
}),
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
import AppNotification, {
|
||||
showAppNotification,
|
||||
} from "components/common/AppNotification.svelte"
|
||||
import { NotificationDisplay } from '@beyonk/svelte-notifications'
|
||||
|
||||
|
||||
function showErrorBanner() {
|
||||
showAppNotification({
|
||||
|
@ -24,8 +26,7 @@
|
|||
$basepath = "/_builder"
|
||||
</script>
|
||||
|
||||
<AppNotification />
|
||||
|
||||
<NotificationDisplay />
|
||||
<Modal>
|
||||
<Router {routes} />
|
||||
</Modal>
|
||||
|
|
|
@ -77,7 +77,8 @@
|
|||
}
|
||||
|
||||
.budibase__input {
|
||||
width: 250px;
|
||||
width: 100%;
|
||||
max-width: 250px;
|
||||
height: 35px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #DBDBDB;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import mustache from "mustache"
|
||||
// TODO: tidy up import
|
||||
import blockDefinitions from "../../../pages/[application]/workflow/WorkflowPanel/blockDefinitions"
|
||||
import { generate } from "shortid"
|
||||
|
||||
/**
|
||||
* Class responsible for the traversing of the workflow definition.
|
||||
|
@ -14,7 +15,10 @@ export default class Workflow {
|
|||
addBlock(block) {
|
||||
let node = this.workflow.definition
|
||||
while (node.next) node = node.next
|
||||
node.next = block
|
||||
node.next = {
|
||||
id: generate(),
|
||||
...block
|
||||
}
|
||||
}
|
||||
|
||||
updateBlock(updatedBlock, id) {
|
||||
|
@ -70,7 +74,7 @@ export default class Workflow {
|
|||
type: block.type,
|
||||
params: block.params,
|
||||
args,
|
||||
heading: block.actionId,
|
||||
heading: definition.actionId,
|
||||
body: mustache.render(tagline, args),
|
||||
})
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ const workflowActions = store => ({
|
|||
},
|
||||
deleteWorkflowBlock: block => {
|
||||
store.update(state => {
|
||||
state.currentWorkflow.deleteBlock(block._id)
|
||||
state.currentWorkflow.deleteBlock(block.id)
|
||||
state.selectedWorkflowBlock = null
|
||||
return state
|
||||
})
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
$: {
|
||||
events = Object.keys(component)
|
||||
// TODO: use real events
|
||||
.filter(propName => ["onChange", "onClick", "onLoad"].includes(propName))
|
||||
.map(propName => ({
|
||||
name: propName,
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
EVENT_TYPE_MEMBER_NAME,
|
||||
allHandlers,
|
||||
} from "components/common/eventHandlers"
|
||||
import { store } from "builderStore"
|
||||
import { store, workflowStore } from "builderStore"
|
||||
import StateBindingOptions from "../PropertyCascader/StateBindingOptions.svelte"
|
||||
import { ArrowDownIcon } from "components/common/Icons/"
|
||||
|
||||
|
@ -22,18 +22,26 @@
|
|||
<div class="handler-option">
|
||||
<span>{parameter.name}</span>
|
||||
<div class="handler-input">
|
||||
<Input on:change={onChange} value={parameter.value} />
|
||||
<button on:click={() => (isOpen = !isOpen)}>
|
||||
<div class="icon" style={`transform: rotate(${isOpen ? 0 : 90}deg);`}>
|
||||
<ArrowDownIcon size={36} />
|
||||
</div>
|
||||
</button>
|
||||
{#if isOpen}
|
||||
<StateBindingOptions
|
||||
onSelect={option => {
|
||||
onChange(option)
|
||||
isOpen = false
|
||||
}} />
|
||||
{#if parameter.name === 'workflow'}
|
||||
<select class="budibase__input" {onChange} value={parameter.value}>
|
||||
{#each $workflowStore.workflows as workflow}
|
||||
<option value={workflow._id}>{workflow.name}</option>
|
||||
{/each}
|
||||
</select>
|
||||
{:else}
|
||||
<Input on:change={onChange} value={parameter.value} />
|
||||
<button on:click={() => (isOpen = !isOpen)}>
|
||||
<div class="icon" style={`transform: rotate(${isOpen ? 0 : 90}deg);`}>
|
||||
<ArrowDownIcon size={36} />
|
||||
</div>
|
||||
</button>
|
||||
{#if isOpen}
|
||||
<StateBindingOptions
|
||||
onSelect={option => {
|
||||
onChange(option)
|
||||
isOpen = false
|
||||
}} />
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -56,11 +56,10 @@
|
|||
on:click={() => $goto(`/settings`)}>
|
||||
<SettingsIcon />
|
||||
</span>
|
||||
<span
|
||||
class:active={false}
|
||||
class="topnavitemright"
|
||||
on:click={() => (location = `/${application}`)}>
|
||||
<PreviewIcon />
|
||||
<span class:active={false} class="topnavitemright">
|
||||
<a href={`/${application}`} target="_blank">
|
||||
<PreviewIcon />
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -84,6 +83,11 @@
|
|||
flex-direction: column;
|
||||
}
|
||||
|
||||
a {
|
||||
text-transform: none;
|
||||
color: var(--ink-lighter);
|
||||
}
|
||||
|
||||
.top-nav {
|
||||
flex: 0 0 auto;
|
||||
height: 60px;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script>
|
||||
import { store, backendUiStore, workflowStore } from "builderStore"
|
||||
import { notifier } from '@beyonk/svelte-notifications'
|
||||
import api from "builderStore/api"
|
||||
import ActionButton from "components/common/ActionButton.svelte"
|
||||
|
||||
|
@ -16,6 +17,7 @@
|
|||
workflow: $workflowStore.currentWorkflow.workflow,
|
||||
})
|
||||
onClosed()
|
||||
notifier.danger("Workflow deleted.")
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
<script>
|
||||
import { onMount, getContext } from "svelte"
|
||||
import { backendUiStore, workflowStore } from "builderStore"
|
||||
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
|
||||
$: workflow = $workflowStore.currentWorkflow && $workflowStore.currentWorkflow.workflow
|
||||
$: workflowBlock = $workflowStore.selectedWorkflowBlock
|
||||
|
||||
function deleteWorkflow() {
|
||||
|
@ -21,8 +22,8 @@
|
|||
}
|
||||
|
||||
function deleteWorkflowBlock() {
|
||||
// TODO: implement, need to put IDs against workflow blocks
|
||||
workflowStore.actions.deleteWorkflowBlock(workflowBlock)
|
||||
notifier.info("Workflow block deleted.");
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { backendUiStore } from "builderStore"
|
||||
import { backendUiStore, store } from "builderStore"
|
||||
|
||||
export let workflowBlock
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
|||
$: workflowParams = workflowBlock.params
|
||||
? Object.entries(workflowBlock.params)
|
||||
: []
|
||||
$: components = Object.values($store.components).filter(comp => comp.name)
|
||||
// $: workflowArgs = workflowBlock.args ? Object.keys(workflowBlock.args) : []
|
||||
</script>
|
||||
|
||||
|
@ -18,7 +19,15 @@
|
|||
<div class="uk-margin block-field">
|
||||
<label class="uk-form-label">{parameter}</label>
|
||||
<div class="uk-form-controls">
|
||||
{#if type === 'number'}
|
||||
{#if Array.isArray(type)}
|
||||
<select
|
||||
class="budibase__input"
|
||||
bind:value={workflowBlock.args[parameter]}>
|
||||
{#each type as option}
|
||||
<option value={option}>{option}</option>
|
||||
{/each}
|
||||
</select>
|
||||
{:else if type === 'number'}
|
||||
<input
|
||||
type="number"
|
||||
class="budibase__input"
|
||||
|
@ -32,11 +41,11 @@
|
|||
{/each}
|
||||
</select>
|
||||
{:else if type === 'component'}
|
||||
<!-- <select>
|
||||
{#each $store.components as question}
|
||||
<option value={question}>{question.text}</option>
|
||||
<select class="budibase__input">
|
||||
{#each components as component}
|
||||
<option value={component.id}>{component.name}</option>
|
||||
{/each}
|
||||
</select> -->
|
||||
</select>
|
||||
{:else if type === 'string'}
|
||||
<input
|
||||
type="text"
|
||||
|
|
|
@ -1,17 +1,23 @@
|
|||
<script>
|
||||
import { onMount } from "svelte"
|
||||
import { workflowStore, backendUiStore } from "builderStore"
|
||||
import { notifier } from "@beyonk/svelte-notifications"
|
||||
import Flowchart from "./svelte-flows/Flowchart.svelte"
|
||||
import api from "builderStore/api"
|
||||
|
||||
let canvas
|
||||
let workflow
|
||||
let selectedWorkflow
|
||||
let uiTree
|
||||
let instanceId = $backendUiStore.selectedDatabase._id
|
||||
|
||||
$: workflow = $workflowStore.currentWorkflow
|
||||
// TODO: better naming
|
||||
$: selectedWorkflow = $workflowStore.currentWorkflow
|
||||
|
||||
$: if (workflow) uiTree = workflow ? workflow.createUiTree() : []
|
||||
$: workflowLive = selectedWorkflow && selectedWorkflow.workflow.live
|
||||
|
||||
$: if (selectedWorkflow)
|
||||
uiTree = selectedWorkflow ? selectedWorkflow.createUiTree() : []
|
||||
|
||||
$: instanceId = $backendUiStore.selectedDatabase._id
|
||||
|
||||
function onDelete(block) {
|
||||
// TODO finish
|
||||
|
@ -24,17 +30,37 @@
|
|||
return state
|
||||
})
|
||||
}
|
||||
|
||||
function setWorkflowLive(live) {
|
||||
const { workflow } = selectedWorkflow
|
||||
workflow.live = live
|
||||
workflowStore.actions.save({ instanceId, workflow })
|
||||
if (live) {
|
||||
notifier.info(`Workflow ${workflow.name} enabled.`)
|
||||
} else {
|
||||
notifier.danger(`Workflow ${workflow.name} disabled.`)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<section>
|
||||
<Flowchart blocks={uiTree} {onSelect} on:delete={onDelete} />
|
||||
<footer>
|
||||
<button class="stop-button hoverable">
|
||||
<i class="ri-stop-fill" />
|
||||
</button>
|
||||
<button class="play-button hoverable">
|
||||
<i class="ri-play-fill" />
|
||||
</button>
|
||||
{#if selectedWorkflow}
|
||||
<button
|
||||
class:highlighted={workflowLive}
|
||||
class:hoverable={workflowLive}
|
||||
class="stop-button hoverable">
|
||||
<i class="ri-stop-fill" on:click={() => setWorkflowLive(false)} />
|
||||
</button>
|
||||
<button
|
||||
class:highlighted={!workflowLive}
|
||||
class:hoverable={!workflowLive}
|
||||
class="play-button hoverable"
|
||||
on:click={() => setWorkflowLive(true)}>
|
||||
<i class="ri-play-fill" />
|
||||
</button>
|
||||
{/if}
|
||||
</footer>
|
||||
</section>
|
||||
|
||||
|
@ -61,11 +87,11 @@
|
|||
margin-right: 24px;
|
||||
}
|
||||
|
||||
.play-button:hover {
|
||||
.play-button.highlighted {
|
||||
background: var(--primary);
|
||||
}
|
||||
|
||||
.stop-button:hover {
|
||||
.stop-button.highlighted {
|
||||
background: var(--coral);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<svg
|
||||
width="9"
|
||||
height="75"
|
||||
viewBox="0 0 9 75"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.0625 70H9L4.5 75L0 70H3.9375V65H5.0625V70Z" fill="#ADAEC4" />
|
||||
<rect x="4" width="1" height="65" fill="#ADAEC4" />
|
||||
</svg>
|
After Width: | Height: | Size: 241 B |
|
@ -1,5 +1,6 @@
|
|||
<script>
|
||||
import FlowItem from "./FlowItem.svelte"
|
||||
import Arrow from "./Arrow.svelte";
|
||||
|
||||
export let blocks = []
|
||||
export let onSelect
|
||||
|
@ -9,7 +10,7 @@
|
|||
{#each blocks as block, idx}
|
||||
<FlowItem {onSelect} {block} />
|
||||
{#if idx !== blocks.length - 1}
|
||||
<i class="ri-arrow-down-line" />
|
||||
<Arrow />
|
||||
{/if}
|
||||
{/each}
|
||||
</section>
|
||||
|
|
|
@ -1,16 +1,27 @@
|
|||
<script>
|
||||
import { fade } from "svelte/transition"
|
||||
|
||||
export let onSelect
|
||||
export let block
|
||||
|
||||
function selectBlock() {
|
||||
onSelect(block)
|
||||
}
|
||||
|
||||
console.log(block)
|
||||
</script>
|
||||
|
||||
<div class={`${block.type} hoverable`} on:click={selectBlock}>
|
||||
<header>{block.heading}</header>
|
||||
<div transition:fade class={`${block.type} hoverable`} on:click={selectBlock}>
|
||||
<header>
|
||||
{#if block.type === 'TRIGGER'}
|
||||
<i class="ri-lightbulb-fill" />
|
||||
When this happens...
|
||||
{:else if block.type === 'ACTION'}
|
||||
<i class="ri-flashlight-fill" />
|
||||
Do this...
|
||||
{:else if block.type === 'LOGIC'}
|
||||
<i class="ri-pause-fill" />
|
||||
Only continue if...
|
||||
{/if}
|
||||
</header>
|
||||
<hr />
|
||||
<p>
|
||||
{@html block.body}
|
||||
|
@ -21,7 +32,6 @@
|
|||
div {
|
||||
width: 320px;
|
||||
padding: 20px;
|
||||
margin-bottom: 60px;
|
||||
border-radius: 5px;
|
||||
transition: 0.3s all;
|
||||
box-shadow: 0 4px 30px 0 rgba(57, 60, 68, 0.08);
|
||||
|
@ -30,6 +40,18 @@
|
|||
color: var(--white);
|
||||
}
|
||||
|
||||
header {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
header i {
|
||||
font-size: 20px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.ACTION {
|
||||
background-color: var(--white);
|
||||
color: var(--font);
|
||||
|
|
|
@ -52,16 +52,21 @@
|
|||
grid-gap: 5px;
|
||||
grid-auto-flow: column;
|
||||
grid-auto-columns: 1fr 1fr 1fr;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.subtabs span {
|
||||
transition: 0.3s all;
|
||||
text-align: center;
|
||||
color: var(--font);
|
||||
color: var(--dark-grey);
|
||||
font-weight: 500;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.subtabs span.selected {
|
||||
border-bottom: 4px solid var(--primary);
|
||||
background: var(--dark-grey);
|
||||
color: var(--white);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.subtabs span:not(.selected) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script>
|
||||
import { store, backendUiStore, workflowStore } from "builderStore"
|
||||
import { notifier } from '@beyonk/svelte-notifications'
|
||||
import api from "builderStore/api"
|
||||
import ActionButton from "components/common/ActionButton.svelte"
|
||||
|
||||
|
@ -17,6 +18,7 @@
|
|||
instanceId,
|
||||
})
|
||||
onClosed()
|
||||
notifier.success(`Workflow ${name} created.`)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script>
|
||||
import Modal from "svelte-simple-modal"
|
||||
import { notifier } from "@beyonk/svelte-notifications";
|
||||
import { onMount, getContext } from "svelte"
|
||||
import { backendUiStore, workflowStore } from "builderStore"
|
||||
import api from "builderStore/api"
|
||||
|
@ -8,7 +9,7 @@
|
|||
const { open, close } = getContext("simple-modal")
|
||||
|
||||
$: currentWorkflowId =
|
||||
$workflowStore.currentWorkflow && $workflowStore.currentWorkflow._id
|
||||
$workflowStore.currentWorkflow && $workflowStore.currentWorkflow.workflow._id
|
||||
|
||||
function newWorkflow() {
|
||||
open(
|
||||
|
@ -24,12 +25,14 @@
|
|||
workflowStore.actions.fetch($backendUiStore.selectedDatabase._id)
|
||||
})
|
||||
|
||||
function saveWorkflow() {
|
||||
async function saveWorkflow() {
|
||||
const workflow = $workflowStore.currentWorkflow.workflow
|
||||
// TODO: Clean up args
|
||||
workflowStore.actions.save({
|
||||
await workflowStore.actions.save({
|
||||
instanceId: $backendUiStore.selectedDatabase._id,
|
||||
workflow: $workflowStore.currentWorkflow.workflow,
|
||||
workflow
|
||||
})
|
||||
notifier.success(`Workflow ${workflow.name} saved.`);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -82,7 +85,7 @@
|
|||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 3px;
|
||||
height: 40px;
|
||||
height: 32px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,17 +5,6 @@
|
|||
import api from "builderStore/api"
|
||||
import blockDefinitions from "./blockDefinitions"
|
||||
|
||||
const WORKFLOW_TABS = [
|
||||
{
|
||||
name: "Workflows",
|
||||
key: "WORKFLOWS",
|
||||
},
|
||||
{
|
||||
name: "Add",
|
||||
key: "ADD",
|
||||
},
|
||||
]
|
||||
|
||||
let selectedTab = "WORKFLOWS"
|
||||
let definitions = []
|
||||
</script>
|
||||
|
@ -57,15 +46,4 @@
|
|||
span:not(.selected) {
|
||||
color: var(--dark-grey);
|
||||
}
|
||||
|
||||
.delete-workflow-button {
|
||||
font-family: Roboto;
|
||||
width: 100%;
|
||||
border: solid 1px #f2f2f2;
|
||||
border-radius: 2px;
|
||||
background: var(--white);
|
||||
height: 32px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -2,7 +2,7 @@ const ACTION = {
|
|||
SET_STATE: {
|
||||
name: "Update UI State",
|
||||
tagline: "Update <b>{{path}}</b> to <b>{{value}}</b>",
|
||||
icon: "",
|
||||
icon: "ri-refresh-line",
|
||||
description: "Update your User Interface with some data.",
|
||||
environment: "CLIENT",
|
||||
params: {
|
||||
|
@ -38,8 +38,8 @@ const ACTION = {
|
|||
},
|
||||
},
|
||||
FIND_RECORD: {
|
||||
description: "Delete a record from your database.",
|
||||
icon: "ri-delete-bin-line",
|
||||
description: "Find a record in your database.",
|
||||
icon: "ri-search-line",
|
||||
name: "Find Record",
|
||||
environment: "SERVER",
|
||||
params: {
|
||||
|
@ -59,7 +59,7 @@ const ACTION = {
|
|||
},
|
||||
SEND_EMAIL: {
|
||||
description: "Send an email.",
|
||||
tagline: "Send email to {{to}}",
|
||||
tagline: "Send email to <b>{{to}}</b>",
|
||||
icon: "ri-mail-open-fill",
|
||||
name: "Send Email",
|
||||
environment: "SERVER",
|
||||
|
@ -73,9 +73,9 @@ const ACTION = {
|
|||
}
|
||||
|
||||
const TRIGGER = {
|
||||
SAVE_RECORD: {
|
||||
RECORD_SAVED: {
|
||||
name: "Record Saved",
|
||||
icon: "ri-delete-bin-line",
|
||||
icon: "ri-save-line",
|
||||
tagline: "Record is added to {{model}}",
|
||||
description: "Save a record to your database.",
|
||||
environment: "SERVER",
|
||||
|
@ -83,39 +83,72 @@ const TRIGGER = {
|
|||
model: "model",
|
||||
},
|
||||
},
|
||||
RECORD_DELETED: {
|
||||
name: "Record Deleted",
|
||||
icon: "ri-delete-bin-line",
|
||||
tagline: "Record is deleted from <b>{{model}}</b>",
|
||||
description: "Fired when a record is deleted from your database.",
|
||||
environment: "SERVER",
|
||||
params: {
|
||||
model: "model"
|
||||
},
|
||||
},
|
||||
CLICK: {
|
||||
name: "Click",
|
||||
icon: "ri-cursor-line",
|
||||
tagline: "{{component}} is clicked",
|
||||
description: "Trigger when you click on an element in the UI.",
|
||||
environment: "CLIENT",
|
||||
params: {
|
||||
component: "component"
|
||||
}
|
||||
},
|
||||
LOAD: {
|
||||
name: "Load",
|
||||
icon: "ri-loader-line",
|
||||
tagline: "{{component}} is loaded",
|
||||
description: "Trigger an element has finished loading.",
|
||||
environment: "CLIENT",
|
||||
params: {
|
||||
component: "component"
|
||||
}
|
||||
},
|
||||
INPUT: {
|
||||
name: "Input",
|
||||
icon: "ri-text",
|
||||
description: "Trigger when you environment into an input box.",
|
||||
tagline: "Text entered into {{component}",
|
||||
description: "Trigger when you type into an input box.",
|
||||
environment: "CLIENT",
|
||||
params: {
|
||||
component: "component"
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
const LOGIC = {
|
||||
FILTER: {
|
||||
name: "Filter",
|
||||
tagline: "{{key}} {{condition}} {{value}}",
|
||||
tagline: "{{field}} <b>{{condition}}</b> {{value}}",
|
||||
icon: "ri-git-branch-line",
|
||||
description: "Filter any workflows which do not meet certain conditions.",
|
||||
environment: "CLIENT",
|
||||
params: {
|
||||
if: "string",
|
||||
field: "string",
|
||||
condition: [
|
||||
"equals"
|
||||
],
|
||||
value: "string"
|
||||
},
|
||||
},
|
||||
DELAY: {
|
||||
name: "Delay",
|
||||
icon: "ri-git-branch-line",
|
||||
icon: "ri-time-fill",
|
||||
tagline: "Delay for <b>{{time}}</b> milliseconds",
|
||||
description: "Delay the workflow until an amount of time has passed.",
|
||||
environment: "CLIENT",
|
||||
params: {
|
||||
time: "number",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import get from "lodash/fp/get"
|
||||
|
||||
/**
|
||||
* The workflow orhestrator is a class responsible for executing workflows.
|
||||
* The workflow orchestrator is a class responsible for executing workflows.
|
||||
* It relies on the strategy pattern, which allows composable behaviour to be
|
||||
* passed into its execute() function. This allows custom execution behaviour based
|
||||
* on where the orchestrator is run.
|
||||
|
@ -30,6 +30,7 @@ export default class Orchestrator {
|
|||
|
||||
// Execute a workflow from a running budibase app
|
||||
export const clientStrategy = {
|
||||
delay: ms => new Promise(resolve => setTimeout(resolve, ms)),
|
||||
context: {},
|
||||
bindContextArgs: function(args, api) {
|
||||
const mappedArgs = { ...args }
|
||||
|
@ -80,6 +81,10 @@ export const clientStrategy = {
|
|||
SET_STATE: block.args,
|
||||
}
|
||||
}
|
||||
|
||||
if (block.actionId === "DELAY") {
|
||||
await this.delay(block.args.time)
|
||||
}
|
||||
}
|
||||
|
||||
// this workflow block gets executed on the server
|
||||
|
@ -102,6 +107,6 @@ export const clientStrategy = {
|
|||
console.log("workflowContext", this.context)
|
||||
|
||||
// TODO: clean this up, don't pass all those args
|
||||
this.run({ workflow: workflow.next, instanceId, api })
|
||||
await this.run({ workflow: workflow.next, instanceId, api })
|
||||
},
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue