From 1497f3f680fc9419a654208a776d4039c026959e Mon Sep 17 00:00:00 2001 From: Maurits Lourens Date: Mon, 26 Jul 2021 23:48:59 +0200 Subject: [PATCH 01/38] delete component using the keyboard --- .../design/AppPreview/CurrentItemPreview.svelte | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte index 607061013d..a6d186817c 100644 --- a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte +++ b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte @@ -103,8 +103,7 @@ } else if (type === "update-prop") { store.actions.components.updateProp(data.prop, data.value) } else if (type === "delete-component" && data.id) { - idToDelete = data.id - confirmDeleteDialog.show() + confirmDeleteComponent(data.id) } else if (type === "preview-loaded") { // Wait for this event to show the client library if intelligent // loading is supported @@ -113,8 +112,19 @@ console.warning(`Client sent unknown event type: ${type}`) } }) + + iframe.contentWindow.addEventListener("keydown", event => { + if ((event.key === "Delete" || event.key === "Backspace") && selectedComponentId) { + confirmDeleteComponent(selectedComponentId); + } + }) }) + const confirmDeleteComponent = (componentId) => { + idToDelete = componentId + confirmDeleteDialog.show() + } + const deleteComponent = () => { store.actions.components.delete({ _id: idToDelete }) idToDelete = null From 7173be59c6e7f16d81c353affa672e3e1016ea50 Mon Sep 17 00:00:00 2001 From: Maurits Lourens Date: Mon, 26 Jul 2021 23:53:11 +0200 Subject: [PATCH 02/38] remove event listeners prevents memory leaks --- .../design/AppPreview/CurrentItemPreview.svelte | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte index a6d186817c..7c0be0e067 100644 --- a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte +++ b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte @@ -1,5 +1,5 @@
{#if withArrow} -
+
{/if} From 378760074fe2054041f202699af4689b6e1eb88d Mon Sep 17 00:00:00 2001 From: Maurits Lourens Date: Tue, 31 Aug 2021 15:46:30 +0200 Subject: [PATCH 04/38] only show delete confirmation when no input or textarea is focussed --- .../AppPreview/CurrentItemPreview.svelte | 57 ++++++++++--------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte index 7c0be0e067..dc7cebbb5f 100644 --- a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte +++ b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte @@ -95,39 +95,42 @@ { once: true } ) - // Add listener for events sent by cliebt library in preview - iframe.contentWindow.addEventListener("bb-event", event => { - const { type, data } = event.detail - if (type === "select-component" && data.id) { - store.actions.components.select({ _id: data.id }) - } else if (type === "update-prop") { - store.actions.components.updateProp(data.prop, data.value) - } else if (type === "delete-component" && data.id) { - confirmDeleteComponent(data.id) - } else if (type === "preview-loaded") { - // Wait for this event to show the client library if intelligent - // loading is supported - loading = false - } else { - console.warning(`Client sent unknown event type: ${type}`) - } - }) - - iframe.contentWindow.addEventListener("keydown", event => { - if ((event.key === "Delete" || event.key === "Backspace") && selectedComponentId) { - confirmDeleteComponent(selectedComponentId); - } - }) + // Add listener for events sent by client library in preview + iframe.contentWindow.addEventListener("bb-event", handleBudibaseEvent) + iframe.contentWindow.addEventListener("keydown", handleKeydownEvent) }) // remove all iframe event listeners on component destroy onDestroy(() => { - iframe.contentWindow.removeEventListener("ready") - iframe.contentWindow.removeEventListener("error") - iframe.contentWindow.removeEventListener("bb-event") - iframe.contentWindow.removeEventListener("keydown") + iframe.contentWindow.removeEventListener("bb-event", handleBudibaseEvent) + iframe.contentWindow.removeEventListener("keydown", handleKeydownEvent) }) + const handleBudibaseEvent = event => { + const { type, data } = event.detail + if (type === "select-component" && data.id) { + store.actions.components.select({ _id: data.id }) + } else if (type === "update-prop") { + store.actions.components.updateProp(data.prop, data.value) + } else if (type === "delete-component" && data.id) { + confirmDeleteComponent(data.id) + } else if (type === "preview-loaded") { + // Wait for this event to show the client library if intelligent + // loading is supported + loading = false + } else { + console.warning(`Client sent unknown event type: ${type}`) + } + }; + + const handleKeydownEvent = event => { + if ((event.key === "Delete" || event.key === "Backspace") && + selectedComponentId && + ['input', 'textarea'].indexOf(iframe.contentWindow.document.activeElement?.tagName.toLowerCase()) === -1) { + confirmDeleteComponent(selectedComponentId); + } + } + const confirmDeleteComponent = (componentId) => { idToDelete = componentId confirmDeleteDialog.show() From 432d876dff7a38674ab91e764c0bc3fdf910391b Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 14 Sep 2021 17:49:01 +0100 Subject: [PATCH 05/38] Backbone of query definition. --- .../server/src/automations/steps/queryRows.js | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 packages/server/src/automations/steps/queryRows.js diff --git a/packages/server/src/automations/steps/queryRows.js b/packages/server/src/automations/steps/queryRows.js new file mode 100644 index 0000000000..8b01bd9755 --- /dev/null +++ b/packages/server/src/automations/steps/queryRows.js @@ -0,0 +1,74 @@ +//const rowController = require("../../api/controllers/row") + +const SortOrders = { + ASCENDING: "ascending", + DESCENDING: "descending", +} + +const SortOrdersPretty = { + [SortOrders.ASCENDING]: "Ascending", + [SortOrders.DESCENDING]: "Descending", +} + +exports.definition = { + description: "Query rows from the database", + icon: "ri-search-line", + name: "Query rows", + tagline: "Query rows from {{inputs.enriched.table.name}} table", + type: "ACTION", + stepId: "QUERY_ROWS", + internal: true, + inputs: {}, + schema: { + inputs: { + properties: { + tableId: { + type: "string", + customType: "table", + title: "Table", + }, + filters: { + type: "object", + customType: "filters", + title: "Filtering", + }, + sortColumn: { + type: "string", + title: "Sort Column", + customType: "column", + }, + sortOrder: { + type: "string", + title: "Sort Order", + enum: Object.values(SortOrders), + pretty: Object.values(SortOrdersPretty), + }, + limit: { + type: "number", + title: "Limit", + }, + }, + required: ["tableId", "filters"], + }, + outputs: { + properties: { + row: { + type: "array", + customType: "rows", + description: "The rows that were found", + }, + success: { + type: "boolean", + description: "Whether the deletion was successful", + }, + }, + required: ["rows", "success"], + }, + }, +} + +exports.run = async function ({ inputs, appId }) { + console.log(inputs) + console.log(appId) + // TODO: use the search controller +} From 4869ecbf3a6608401b719448ea5eefbbc4dc3988 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Wed, 1 Sep 2021 15:23:40 +0100 Subject: [PATCH 06/38] add splash screen to automation --- .../FlowChart/FlowChart.svelte | 6 --- .../AutomationPanel/AutomationPanel.svelte | 3 +- .../app/[application]/automate/_layout.svelte | 50 ++++++++++++++++++- .../app/[application]/automate/index.svelte | 10 ---- 4 files changed, 50 insertions(+), 19 deletions(-) diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowChart.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowChart.svelte index e960271b87..16ef04a7ca 100644 --- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowChart.svelte +++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowChart.svelte @@ -19,7 +19,6 @@ } -{#if !blocks.length}Add a trigger to your automation to get started{/if}
{#each blocks as block, idx (block.id)}
diff --git a/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte b/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte index dbcbc33db0..b2773ae455 100644 --- a/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte +++ b/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte @@ -2,7 +2,8 @@ import AutomationList from "./AutomationList.svelte" import CreateAutomationModal from "./CreateAutomationModal.svelte" import { Icon, Modal, Tabs, Tab } from "@budibase/bbui" - let modal + + export let modal
diff --git a/packages/builder/src/pages/builder/app/[application]/automate/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/automate/_layout.svelte index d1aaeb0240..bc04548d8f 100644 --- a/packages/builder/src/pages/builder/app/[application]/automate/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/automate/_layout.svelte @@ -1,22 +1,51 @@
- + {#if automation} + + {:else} +
+
+ + + + + You have no automations + Let's fix that. Call the bots! + + +
+
+ {/if}
{#if $automationStore.selectedAutomation}
{/if} + + +
diff --git a/packages/builder/src/pages/builder/app/[application]/automate/index.svelte b/packages/builder/src/pages/builder/app/[application]/automate/index.svelte index d48bd36e59..e5dea10e0b 100644 --- a/packages/builder/src/pages/builder/app/[application]/automate/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/automate/index.svelte @@ -15,13 +15,3 @@ } }) - -Create your first automation to get started - - From fd4c1c992972284a5bcce09a4453cfa21704b386 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Thu, 2 Sep 2021 14:25:01 +0100 Subject: [PATCH 07/38] Add triggers to setup modal --- .../AutomationPanel/AutomationPanel.svelte | 3 +- .../CreateAutomationModal.svelte | 91 ++++++++++++++----- .../app/[application]/automate/_layout.svelte | 9 +- 3 files changed, 77 insertions(+), 26 deletions(-) diff --git a/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte b/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte index b2773ae455..0c975eab18 100644 --- a/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte +++ b/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte @@ -4,6 +4,7 @@ import { Icon, Modal, Tabs, Tab } from "@budibase/bbui" export let modal + export let webhookModal
@@ -12,7 +13,7 @@
- +
diff --git a/packages/builder/src/components/automation/AutomationPanel/CreateAutomationModal.svelte b/packages/builder/src/components/automation/AutomationPanel/CreateAutomationModal.svelte index dfcfc2ab95..43bb2ff777 100644 --- a/packages/builder/src/components/automation/AutomationPanel/CreateAutomationModal.svelte +++ b/packages/builder/src/components/automation/AutomationPanel/CreateAutomationModal.svelte @@ -3,12 +3,14 @@ import { database } from "stores/backend" import { automationStore } from "builderStore" import { notifications } from "@budibase/bbui" - import { Icon, Input, ModalContent } from "@budibase/bbui" + import { Input, ModalContent, Layout, Body } from "@budibase/bbui" import analytics from "analytics" let name + let selectedTrigger + let triggerVal + export let webhookModal - $: valid = !!name $: instanceId = $database._id async function createAutomation() { @@ -16,41 +18,84 @@ name, instanceId, }) + const newBlock = await $automationStore.selectedAutomation.constructBlock( + "TRIGGER", + triggerVal.stepId, + triggerVal + ) + automationStore.actions.addBlockToAutomation(newBlock) + if (triggerVal.stepId === "WEBHOOK") { + webhookModal.show() + } + notifications.success(`Automation ${name} created.`) $goto(`./${$automationStore.selectedAutomation.automation._id}`) analytics.captureEvent("Automation Created", { name }) } + $: triggers = Object.entries($automationStore.blockDefinitions.TRIGGER) + + const selectTrigger = trigger => { + triggerVal = trigger + selectedTrigger = trigger.name + } + Please name your automation, then select a trigger. Every automation must + start with a trigger. + - - - Learn about automations - + + + Triggers + +
+ {#each triggers as [idx, trigger]} +
selectTrigger(trigger)} + > +
+ + + {trigger.name} +
+
+ {/each} +
+
diff --git a/packages/builder/src/pages/builder/app/[application]/automate/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/automate/_layout.svelte index bc04548d8f..0d0582a34e 100644 --- a/packages/builder/src/pages/builder/app/[application]/automate/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/automate/_layout.svelte @@ -4,14 +4,16 @@ import AutomationPanel from "components/automation/AutomationPanel/AutomationPanel.svelte" import SetupPanel from "components/automation/SetupPanel/SetupPanel.svelte" import CreateAutomationModal from "components/automation/AutomationPanel/CreateAutomationModal.svelte" + import CreateWebhookModal from "components/automation/shared/CreateWebhookModal.svelte" $: automation = $automationStore.selectedAutomation?.automation let modal + let webhookModal
{#if automation} @@ -44,7 +46,10 @@
{/if} - + + + +
From 7fd79d3d4edee2b6ccde29e795bf75c9c7b02813 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Mon, 6 Sep 2021 14:31:55 +0100 Subject: [PATCH 08/38] Update flow chart styling and event handling --- .../bbui/src/ActionButton/ActionButton.svelte | 5 + .../AutomationBuilder.svelte | 1 - .../AutomationBuilder/FlowChart/Arrow.svelte | 1 + .../FlowChart/FlowChart.svelte | 80 +++++-- .../FlowChart/FlowItem.svelte | 224 ++++++++++++++---- .../FlowChart/TestDataModal.svelte | 12 + .../CreateAutomationModal.svelte | 31 ++- .../SetupPanel/AutomationBlockSetup.svelte | 8 +- .../automate/[automation]/_layout.svelte | 15 -- 9 files changed, 273 insertions(+), 104 deletions(-) create mode 100644 packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte delete mode 100644 packages/builder/src/pages/builder/app/[application]/automate/[automation]/_layout.svelte diff --git a/packages/bbui/src/ActionButton/ActionButton.svelte b/packages/bbui/src/ActionButton/ActionButton.svelte index 83f71d385b..b518ac3d92 100644 --- a/packages/bbui/src/ActionButton/ActionButton.svelte +++ b/packages/bbui/src/ActionButton/ActionButton.svelte @@ -12,6 +12,7 @@ export let dataCy = null export let size = "M" export let active = false + export let fullWidth = false function longPress(element) { if (!longPressable) return @@ -40,6 +41,7 @@ class:spectrum-ActionButton--quiet={quiet} class:spectrum-ActionButton--emphasized={emphasized} class:is-selected={selected} + class:fullWidth class="spectrum-ActionButton spectrum-ActionButton--size{size}" class:active {disabled} @@ -71,6 +73,9 @@ diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowItem.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowItem.svelte index 439db62639..d36204897e 100644 --- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowItem.svelte +++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowItem.svelte @@ -1,21 +1,83 @@
onSelect(block)} > -
- {#if block.type === "TRIGGER"} - - When this happens... - {:else if block.type === "ACTION"} - - Do this... - {:else if block.type === "LOGIC"} - - Only continue if... - {/if} -
- {#if block.type === "TRIGGER"}Trigger{:else}Step {blockIdx + 1}{/if} +
+
+ + + +
+ When this happens: + + {block.name.toUpperCase()} +
- {#if block.type !== "TRIGGER" || allowDeleteTrigger} -
- {/if} -
-
-

- -

+
+ +
+ +
+
{ + if (!setupComplete) { + setupToggled = !setupToggled + } + }} + class="toggle" + > + {#if setupToggled} + + {:else} + + {/if} + Setup +
+
deleteStep()}> + +
+
+ + {#if setupToggled} + + {#if block.inputs[schemaKey]} + + {/if} + {/if} +
+
+ + +
+ +
{ + if (setupComplete) { + testToggled = !testToggled + } + }} + class="toggle" + > + {#if testToggled} + + {:else} + + {/if} + Test +
+ {#if testToggled} + Add test data + + {/if} +
+
+ + + + + + + + + + + +
diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte new file mode 100644 index 0000000000..31139fdc9e --- /dev/null +++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte @@ -0,0 +1,12 @@ + + + + test + diff --git a/packages/builder/src/components/automation/AutomationPanel/CreateAutomationModal.svelte b/packages/builder/src/components/automation/AutomationPanel/CreateAutomationModal.svelte index 43bb2ff777..799cd930dd 100644 --- a/packages/builder/src/components/automation/AutomationPanel/CreateAutomationModal.svelte +++ b/packages/builder/src/components/automation/AutomationPanel/CreateAutomationModal.svelte @@ -3,7 +3,7 @@ import { database } from "stores/backend" import { automationStore } from "builderStore" import { notifications } from "@budibase/bbui" - import { Input, ModalContent, Layout, Body } from "@budibase/bbui" + import { Input, ModalContent, Layout, Body, Icon } from "@budibase/bbui" import analytics from "analytics" let name @@ -18,17 +18,18 @@ name, instanceId, }) - const newBlock = await $automationStore.selectedAutomation.constructBlock( + const newBlock = $automationStore.selectedAutomation.constructBlock( "TRIGGER", triggerVal.stepId, triggerVal ) + automationStore.actions.addBlockToAutomation(newBlock) if (triggerVal.stepId === "WEBHOOK") { webhookModal.show() } - notifications.success(`Automation ${name} created.`) + $goto(`./${$automationStore.selectedAutomation.automation._id}`) analytics.captureEvent("Automation Created", { name }) } @@ -56,16 +57,16 @@ Triggers -
+
{#each triggers as [idx, trigger]}
selectTrigger(trigger)} > -
- - +
+ + {trigger.name}
@@ -76,13 +77,21 @@ diff --git a/packages/builder/src/pages/builder/app/[application]/automate/[automation]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/automate/[automation]/_layout.svelte deleted file mode 100644 index 3be71a1bbe..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/automate/[automation]/_layout.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - - From 09cab87a86cc71cb897ffad5f25fec86fd8b7ed4 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Tue, 7 Sep 2021 14:32:43 +0100 Subject: [PATCH 09/38] Add new actions modal and integration with flowchart --- packages/builder/assets/discord.svg | 10 ++ packages/builder/assets/integromat.png | Bin 0 -> 26614 bytes packages/builder/assets/slack.svg | 33 ++++ packages/builder/assets/zapier.png | Bin 0 -> 12359 bytes .../FlowChart/ActionModal.svelte | 140 +++++++++++++++++ .../FlowChart/FlowItem.svelte | 147 ++++++++++-------- .../app/[application]/automate/_layout.svelte | 19 --- packages/server/src/automations/steps/bash.js | 2 +- .../server/src/automations/steps/createRow.js | 2 +- .../server/src/automations/steps/delay.js | 2 +- .../server/src/automations/steps/deleteRow.js | 2 +- .../src/automations/steps/executeQuery.js | 2 +- .../src/automations/steps/executeScript.js | 2 +- .../server/src/automations/steps/filter.js | 2 +- .../src/automations/steps/outgoingWebhook.js | 2 +- .../src/automations/steps/sendSmtpEmail.js | 2 +- .../server/src/automations/steps/serverLog.js | 2 +- .../server/src/automations/steps/updateRow.js | 2 +- 18 files changed, 275 insertions(+), 96 deletions(-) create mode 100644 packages/builder/assets/discord.svg create mode 100644 packages/builder/assets/integromat.png create mode 100644 packages/builder/assets/slack.svg create mode 100644 packages/builder/assets/zapier.png create mode 100644 packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte diff --git a/packages/builder/assets/discord.svg b/packages/builder/assets/discord.svg new file mode 100644 index 0000000000..3efe1ec110 --- /dev/null +++ b/packages/builder/assets/discord.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/packages/builder/assets/integromat.png b/packages/builder/assets/integromat.png new file mode 100644 index 0000000000000000000000000000000000000000..1fbbe63e7444ce8a7959293880d85b72d1ae7724 GIT binary patch literal 26614 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

*@J)kRGmkxaj;U0uin&yZC+8s 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 literal 0 HcmV?d00001 diff --git a/packages/builder/assets/slack.svg b/packages/builder/assets/slack.svg new file mode 100644 index 0000000000..c37dc5eb49 --- /dev/null +++ b/packages/builder/assets/slack.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/builder/assets/zapier.png b/packages/builder/assets/zapier.png new file mode 100644 index 0000000000000000000000000000000000000000..38053314401f390e840df558ba8cda5a3826714d GIT binary patch literal 12359 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 + import { ModalContent, Layout, Detail, Body, Icon } from "@budibase/bbui" + import { automationStore } from "builderStore" + import DiscordLogo from "assets/discord.svg" + import ZapierLogo from "assets/zapier.png" + import IntegromatLogo from "assets/integromat.png" + import SlackLogo from "assets/integromat.png" + + let selectedAction + let actionVal + export let blockComplete + + let externalActionsPredicate = [ + { name: "zapier", logo: ZapierLogo }, + { name: "discord", logo: DiscordLogo }, + { name: "slack", logo: SlackLogo }, + { name: "integromat", logo: IntegromatLogo }, + ] + let actions = Object.entries($automationStore.blockDefinitions.ACTION) + + const externalActions = actions.reduce((acc, elm) => { + const [k, v] = elm + if (externalActionsPredicate.some(pred => pred.name === k)) { + acc[k] = v + } + return acc + }, {}) + + const internalActions = actions.reduce((acc, elm) => { + const [k, v] = elm + if (!externalActionsPredicate.some(pred => pred.name === k)) { + acc[k] = v + } + return acc + }, {}) + + const selectAction = action => { + actionVal = action + selectedAction = action.name + } + + function addBlockToAutomation() { + const newBlock = $automationStore.selectedAutomation.constructBlock( + "ACTION", + actionVal.stepId, + actionVal + ) + automationStore.actions.addBlockToAutomation(newBlock) + } + + + { + blockComplete = true + addBlockToAutomation() + }} +> + Select an app or event. + + Apps + +

+ {#each Object.entries(externalActions) as [idx, action]} +
selectAction(action)} + > +
+ val.name === idx).logo} + alt="zapier" + /> + + {idx.charAt(0).toUpperCase() + idx.slice(1)} +
+
+ {/each} +
+ + Actions + +
+ {#each Object.entries(internalActions) as [idx, action]} +
selectAction(action)} + > +
+ + + {action.name} +
+
+ {/each} +
+ + + + diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowItem.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowItem.svelte index d36204897e..cca59345ee 100644 --- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowItem.svelte +++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowItem.svelte @@ -10,6 +10,7 @@ Button, ActionButton, notifications, + StatusLight, } from "@budibase/bbui" import AutomationBlockSetup from "../../SetupPanel/AutomationBlockSetup.svelte" import CreateWebhookModal from "components/automation/shared/CreateWebhookModal.svelte" @@ -25,6 +26,7 @@ let testDataModal let actionModal let setupComplete + let blockComplete let testToggled $: setupToggled = !setupComplete || false @@ -83,92 +85,105 @@
onSelect(block)} + on:click={() => { + blockComplete = false + onSelect(block) + }} >
-
- - - -
- When this happens: +
+
+ + + +
+ When this happens: - {block.name.toUpperCase()} + {block?.name?.toUpperCase() || ""} +
+ {#if blockComplete} + + {/if}
- -
- -
+ {#if !blockComplete} + +
+ +
+
{ + if (!setupComplete) { + setupToggled = !setupToggled + } + }} + class="toggle" + > + {#if setupToggled} + + {:else} + + {/if} + Setup +
+
deleteStep()}> + +
+
+ + {#if setupToggled} + + {#if block.inputs[schemaKey]} + + {/if} + {/if} +
+
+ + +
+
{ - if (!setupComplete) { - setupToggled = !setupToggled + if (setupComplete) { + testToggled = !testToggled } }} class="toggle" > - {#if setupToggled} + {#if testToggled} {:else} {/if} - Setup + Test
-
deleteStep()}> - -
-
- - {#if setupToggled} - - {#if block.inputs[schemaKey]} - Add test data + {/if} - {/if} - -
- - -
- -
{ - if (setupComplete) { - testToggled = !testToggled - } - }} - class="toggle" - > - {#if testToggled} - - {:else} - - {/if} - Test -
- {#if testToggled} - Add test data - - {/if} -
-
+
+
+ {/if} - + @@ -185,7 +200,7 @@ display: flex; align-items: center; } - .setup { + .splitHeader { display: flex; justify-content: space-between; } diff --git a/packages/builder/src/pages/builder/app/[application]/automate/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/automate/_layout.svelte index 0d0582a34e..5123e50bc6 100644 --- a/packages/builder/src/pages/builder/app/[application]/automate/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/automate/_layout.svelte @@ -2,7 +2,6 @@ import { Heading, Body, Layout, Button, Modal } from "@budibase/bbui" import { automationStore } from "builderStore" import AutomationPanel from "components/automation/AutomationPanel/AutomationPanel.svelte" - import SetupPanel from "components/automation/SetupPanel/SetupPanel.svelte" import CreateAutomationModal from "components/automation/AutomationPanel/CreateAutomationModal.svelte" import CreateWebhookModal from "components/automation/shared/CreateWebhookModal.svelte" $: automation = $automationStore.selectedAutomation?.automation @@ -40,11 +39,6 @@
{/if}
- {#if $automationStore.selectedAutomation} -
- -
- {/if} @@ -82,19 +76,6 @@ gap: var(--spacing-l); overflow: hidden; } - - .setup { - padding: var(--spectrum-global-dimension-size-200); - border-left: var(--border-light); - display: flex; - flex-direction: column; - justify-content: flex-start; - align-items: stretch; - gap: var(--spacing-l); - background-color: var(--background); - overflow-y: auto; - } - .centered { top: 0; bottom: 0; diff --git a/packages/server/src/automations/steps/bash.js b/packages/server/src/automations/steps/bash.js index 6c44c1bbbb..2be6ad7db3 100644 --- a/packages/server/src/automations/steps/bash.js +++ b/packages/server/src/automations/steps/bash.js @@ -4,7 +4,7 @@ const { processStringSync } = require("@budibase/string-templates") exports.definition = { name: "Bash Scripting", tagline: "Execute a bash command", - icon: "ri-terminal-box-line", + icon: "JourneyEvent", description: "Run a bash script", type: "ACTION", internal: true, diff --git a/packages/server/src/automations/steps/createRow.js b/packages/server/src/automations/steps/createRow.js index e3c90fb15b..6bb5e3c42e 100644 --- a/packages/server/src/automations/steps/createRow.js +++ b/packages/server/src/automations/steps/createRow.js @@ -6,7 +6,7 @@ const usage = require("../../utilities/usageQuota") exports.definition = { name: "Create Row", tagline: "Create a {{inputs.enriched.table.name}} row", - icon: "ri-save-3-line", + icon: "SaveFloppy", description: "Add a row to your database", type: "ACTION", internal: true, diff --git a/packages/server/src/automations/steps/delay.js b/packages/server/src/automations/steps/delay.js index 899d8f8401..ad59df54c5 100644 --- a/packages/server/src/automations/steps/delay.js +++ b/packages/server/src/automations/steps/delay.js @@ -2,7 +2,7 @@ let { wait } = require("../../utilities") exports.definition = { name: "Delay", - icon: "ri-time-line", + icon: "Clock", tagline: "Delay for {{inputs.time}} milliseconds", description: "Delay the automation until an amount of time has passed", stepId: "DELAY", diff --git a/packages/server/src/automations/steps/deleteRow.js b/packages/server/src/automations/steps/deleteRow.js index 10f39d2d0c..4e014ccc20 100644 --- a/packages/server/src/automations/steps/deleteRow.js +++ b/packages/server/src/automations/steps/deleteRow.js @@ -4,7 +4,7 @@ const usage = require("../../utilities/usageQuota") exports.definition = { description: "Delete a row from your database", - icon: "ri-delete-bin-line", + icon: "DeleteOutline", name: "Delete Row", tagline: "Delete a {{inputs.enriched.table.name}} row", type: "ACTION", diff --git a/packages/server/src/automations/steps/executeQuery.js b/packages/server/src/automations/steps/executeQuery.js index d5799a8f7d..2ca0b21449 100644 --- a/packages/server/src/automations/steps/executeQuery.js +++ b/packages/server/src/automations/steps/executeQuery.js @@ -4,7 +4,7 @@ const { buildCtx } = require("./utils") exports.definition = { name: "External Data Connector", tagline: "Execute Data Connector", - icon: "ri-database-2-line", + icon: "Data", description: "Execute a query in an external data connector", type: "ACTION", stepId: "EXECUTE_QUERY", diff --git a/packages/server/src/automations/steps/executeScript.js b/packages/server/src/automations/steps/executeScript.js index 70298b9f8f..c56dfbd4e9 100644 --- a/packages/server/src/automations/steps/executeScript.js +++ b/packages/server/src/automations/steps/executeScript.js @@ -4,7 +4,7 @@ const { buildCtx } = require("./utils") exports.definition = { name: "JS Scripting", tagline: "Execute JavaScript Code", - icon: "ri-terminal-box-line", + icon: "Code", description: "Run a piece of JavaScript code in your automation", type: "ACTION", internal: true, diff --git a/packages/server/src/automations/steps/filter.js b/packages/server/src/automations/steps/filter.js index 84bdc10c1d..80d3198cba 100644 --- a/packages/server/src/automations/steps/filter.js +++ b/packages/server/src/automations/steps/filter.js @@ -18,7 +18,7 @@ exports.PrettyFilterConditions = PrettyFilterConditions exports.definition = { name: "Filter", tagline: "{{inputs.field}} {{inputs.condition}} {{inputs.value}}", - icon: "ri-git-branch-line", + icon: "Branch2", description: "Filter any automations which do not meet certain conditions", type: "LOGIC", internal: true, diff --git a/packages/server/src/automations/steps/outgoingWebhook.js b/packages/server/src/automations/steps/outgoingWebhook.js index ea0f0ce6be..6194e1052b 100644 --- a/packages/server/src/automations/steps/outgoingWebhook.js +++ b/packages/server/src/automations/steps/outgoingWebhook.js @@ -20,7 +20,7 @@ const BODY_REQUESTS = [RequestType.POST, RequestType.PUT, RequestType.PATCH] exports.definition = { name: "Outgoing webhook", tagline: "Send a {{inputs.requestMethod}} request", - icon: "ri-send-plane-line", + icon: "Send", description: "Send a request of specified method to a URL", type: "ACTION", internal: true, diff --git a/packages/server/src/automations/steps/sendSmtpEmail.js b/packages/server/src/automations/steps/sendSmtpEmail.js index 552c9b4d36..9e4b5a6a3c 100644 --- a/packages/server/src/automations/steps/sendSmtpEmail.js +++ b/packages/server/src/automations/steps/sendSmtpEmail.js @@ -3,7 +3,7 @@ const { sendSmtpEmail } = require("../../utilities/workerRequests") exports.definition = { description: "Send an email using SMTP", tagline: "Send SMTP email to {{inputs.to}}", - icon: "ri-mail-open-line", + icon: "Email", name: "Send Email (SMTP)", type: "ACTION", internal: true, diff --git a/packages/server/src/automations/steps/serverLog.js b/packages/server/src/automations/steps/serverLog.js index 82e7d073e3..b88a731d56 100644 --- a/packages/server/src/automations/steps/serverLog.js +++ b/packages/server/src/automations/steps/serverLog.js @@ -7,7 +7,7 @@ exports.definition = { name: "Backend log", tagline: "Console log a value in the backend", - icon: "ri-server-line", + icon: "Monitoring", description: "Logs the given text to the server (using console.log)", type: "ACTION", internal: true, diff --git a/packages/server/src/automations/steps/updateRow.js b/packages/server/src/automations/steps/updateRow.js index 961f75dee7..ac5eb16fcd 100644 --- a/packages/server/src/automations/steps/updateRow.js +++ b/packages/server/src/automations/steps/updateRow.js @@ -4,7 +4,7 @@ const automationUtils = require("../automationUtils") exports.definition = { name: "Update Row", tagline: "Update a {{inputs.enriched.table.name}} row", - icon: "ri-refresh-line", + icon: "Refresh", description: "Update a row in your database", type: "ACTION", internal: true, From 0fadf104e257823d232dfc9d9da1c9409b535f67 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Thu, 9 Sep 2021 12:00:37 +0100 Subject: [PATCH 10/38] save automation on change / delete / create --- .../FlowChart/FlowChart.svelte | 51 +++++-- .../FlowChart/FlowItem.svelte | 124 ++++++------------ .../FlowChart/ResultsModal.svelte | 58 ++++++++ .../FlowChart/TestDataModal.svelte | 18 ++- .../CreateAutomationModal.svelte | 8 +- .../SetupPanel/AutomationBlockSetup.svelte | 57 ++++++-- .../automation/SetupPanel/CronBuilder.svelte | 11 +- .../automation/SetupPanel/RowSelector.svelte | 20 ++- .../automation/SetupPanel/SchemaSetup.svelte | 6 + .../SetupPanel/TableSelector.svelte | 9 ++ .../automate/[automation]/_layout.svelte | 15 +++ .../app/[application]/automate/_layout.svelte | 2 +- 12 files changed, 262 insertions(+), 117 deletions(-) create mode 100644 packages/builder/src/components/automation/AutomationBuilder/FlowChart/ResultsModal.svelte create mode 100644 packages/builder/src/pages/builder/app/[application]/automate/[automation]/_layout.svelte diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowChart.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowChart.svelte index de89ebbb12..2398d2754a 100644 --- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowChart.svelte +++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowChart.svelte @@ -1,16 +1,18 @@
@@ -32,26 +57,23 @@ style="display:flex; color: var(--spectrum-global-color-gray-400);" > - + deleteAutomation()} class="iconPadding"> - + testAutomation()} + icon="MultipleCheck" + size="S">Run test
-
- {#if published} - Automation is published{:else} - Automation is not published{/if} -
{#each blocks as block, idx (block.id)}
{#if idx !== blocks.length - 1} @@ -97,6 +119,7 @@ } .iconPadding { + cursor: pointer; display: flex; padding-right: var(--spacing-m); } diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowItem.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowItem.svelte index cca59345ee..bc2ded8870 100644 --- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowItem.svelte +++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowItem.svelte @@ -8,77 +8,52 @@ Detail, Modal, Button, - ActionButton, - notifications, StatusLight, } from "@budibase/bbui" import AutomationBlockSetup from "../../SetupPanel/AutomationBlockSetup.svelte" import CreateWebhookModal from "components/automation/shared/CreateWebhookModal.svelte" import TestDataModal from "./TestDataModal.svelte" + import ResultsModal from "./ResultsModal.svelte" + import ActionModal from "./ActionModal.svelte" import { database } from "stores/backend" export let onSelect export let block - let selected let webhookModal let testDataModal let actionModal - let setupComplete + let resultsModal + let setupToggled let blockComplete - let testToggled - - $: setupToggled = !setupComplete || false - $: instanceId = $database._id - $: schemaKey = Object.keys(block.schema?.inputs?.properties || {}) + + $: isTrigger = block.type === "TRIGGER" $: selected = $automationStore.selectedBlock?.id === block.id $: steps = $automationStore.selectedAutomation?.automation?.definition?.steps ?? [] $: blockIdx = steps.findIndex(step => step.id === block.id) - $: allowDeleteTrigger = !steps.length + $: lastStep = !isTrigger && blockIdx + 1 === steps.length - function deleteStep() { + // Logic for hiding / showing the add button.first we check if it has a child + // then we check to see whether its inputs have been commpleted + $: disableAddButton = isTrigger + ? $automationStore.selectedAutomation?.automation?.definition?.steps + .length > 0 + : !isTrigger && steps.length - blockIdx > 1 + $: hasCompletedInputs = Object.keys( + block.schema?.inputs?.properties || {} + ).every(x => block?.inputs[x]) + + async function deleteStep() { automationStore.actions.deleteAutomationBlock(block) - } - - async function testAutomation() { - const result = await automationStore.actions.trigger({ - automation: $automationStore.selectedAutomation.automation, - }) - if (result.status === 200) { - notifications.success( - `Automation ${$automationStore.selectedAutomation.automation.name} triggered successfully.` - ) - } else { - notifications.error( - `Failed to trigger automation ${$automationStore.selectedAutomation.automation.name}.` - ) - } - return result - } - - async function saveAutomation() { await automationStore.actions.save({ instanceId, - automation: $automationStore.selectedAutomation.automation, + automation: $automationStore.selectedAutomation?.automation, }) - notifications.success( - `Automation ${$automationStore.selectedAutomation.automation.name} saved.` - ) - } - - function onContinue() { - const testResult = testAutomation() - const saveResult = saveAutomation() - - if (testResult && saveResult) { - setupComplete = true - testToggled = true - } } @@ -108,8 +83,12 @@ {block?.name?.toUpperCase() || ""}
- {#if blockComplete} - + {#if !blockComplete} + resultsModal.show()}> + View response + {/if}
@@ -120,9 +99,7 @@
{ - if (!setupComplete) { - setupToggled = !setupToggled - } + setupToggled = !setupToggled }} class="toggle" > @@ -133,55 +110,38 @@ {/if} Setup
-
deleteStep()}> - -
+ {#if !isTrigger} +
deleteStep()}> + +
+ {/if}
{#if setupToggled} - {#if block.inputs[schemaKey]} - testDataModal.show()} cta + >Test Automation {/if} - {/if} - -
- - -
- -
{ - if (setupComplete) { - testToggled = !testToggled - } - }} - class="toggle" - > - {#if testToggled} - - {:else} - - {/if} - Test -
- {#if testToggled} - Add test data Add Action {/if}
{/if} + + + + diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ResultsModal.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ResultsModal.svelte new file mode 100644 index 0000000000..cbfd5ad432 --- /dev/null +++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ResultsModal.svelte @@ -0,0 +1,58 @@ + + + +
+
{ + inputToggled = !inputToggled + }} + class="toggle" + > + {#if inputToggled} + + {:else} + + {/if} + Input +
+
+ +
+
{ + outputToggled = !outputToggled + }} + class="toggle" + > + {#if outputToggled} + + {:else} + + {/if} + Output +
+
+
+ + diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte index 31139fdc9e..9de0265dc9 100644 --- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte +++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte @@ -1,5 +1,10 @@ - test +
+ > + +