diff --git a/lerna.json b/lerna.json
index dd7190c4b2..a1b8faab37 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,5 +1,5 @@
{
- "version": "0.9.125-alpha.7",
+ "version": "0.9.125-alpha.11",
"npmClient": "yarn",
"packages": [
"packages/*"
diff --git a/packages/auth/package.json b/packages/auth/package.json
index ec75651638..f99ac5c901 100644
--- a/packages/auth/package.json
+++ b/packages/auth/package.json
@@ -1,6 +1,6 @@
{
"name": "@budibase/auth",
- "version": "0.9.125-alpha.7",
+ "version": "0.9.125-alpha.11",
"description": "Authentication middlewares for budibase builder and apps",
"main": "src/index.js",
"author": "Budibase",
diff --git a/packages/auth/src/cache/user.js b/packages/auth/src/cache/user.js
index 669192a905..2b2693ca01 100644
--- a/packages/auth/src/cache/user.js
+++ b/packages/auth/src/cache/user.js
@@ -6,8 +6,10 @@ const EXPIRY_SECONDS = 3600
/**
* The default populate user function
*/
-const populateFromDB = (userId, tenantId) => {
- return getGlobalDB(tenantId).get(userId)
+const populateFromDB = async (userId, tenantId) => {
+ const user = await getGlobalDB(tenantId).get(userId)
+ user.budibaseAccess = true
+ return user
}
/**
diff --git a/packages/bbui/package.json b/packages/bbui/package.json
index f7e06046af..56c3903422 100644
--- a/packages/bbui/package.json
+++ b/packages/bbui/package.json
@@ -1,7 +1,7 @@
{
"name": "@budibase/bbui",
"description": "A UI solution used in the different Budibase projects.",
- "version": "0.9.125-alpha.7",
+ "version": "0.9.125-alpha.11",
"license": "AGPL-3.0",
"svelte": "src/index.js",
"module": "dist/bbui.es.js",
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/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 0000000000..1fbbe63e74
Binary files /dev/null and b/packages/builder/assets/integromat.png differ
diff --git a/packages/builder/assets/n8n.png b/packages/builder/assets/n8n.png
new file mode 100644
index 0000000000..b9dad93e5a
Binary files /dev/null and b/packages/builder/assets/n8n.png differ
diff --git a/packages/builder/assets/slack.svg b/packages/builder/assets/slack.svg
new file mode 100644
index 0000000000..adcae7e39d
--- /dev/null
+++ b/packages/builder/assets/slack.svg
@@ -0,0 +1,33 @@
+
+
+
\ No newline at end of file
diff --git a/packages/builder/assets/zapier.png b/packages/builder/assets/zapier.png
new file mode 100644
index 0000000000..3805331440
Binary files /dev/null and b/packages/builder/assets/zapier.png differ
diff --git a/packages/builder/cypress/integration/createAutomation.spec.js b/packages/builder/cypress/integration/createAutomation.spec.js
index e5040c3c45..0620a15e25 100644
--- a/packages/builder/cypress/integration/createAutomation.spec.js
+++ b/packages/builder/cypress/integration/createAutomation.spec.js
@@ -7,26 +7,42 @@ context("Create a automation", () => {
// https://on.cypress.io/interacting-with-elements
it("should create a automation", () => {
cy.createTestTableWithData()
-
+ cy.wait(2000)
cy.contains("Automate").click()
cy.get("[data-cy='new-screen'] > .spectrum-Icon").click()
- cy.get(".spectrum-Dialog-grid").within(() => {
+ cy.get(".modal-inner-wrapper").within(() => {
cy.get("input").type("Add Row")
+ cy.contains("Row Created").click()
+ cy.wait(500)
cy.get(".spectrum-Button--cta").click()
})
- // Add trigger
- cy.contains("Trigger").click()
- cy.contains("Row Created").click()
- cy.get(".setup").within(() => {
- cy.get(".spectrum-Picker-label").click()
- cy.contains("dog").click()
- })
+ // Setup trigger
+ cy.contains("Setup").click()
+ cy.get(".spectrum-Picker-label").click()
+ cy.wait(500)
+ cy.contains("dog").click()
// Create action
- cy.contains("Internal").click()
- cy.contains("Create Row").click()
- cy.get(".setup").within(() => {
+ cy.contains("Add Action").click()
+ cy.get(".modal-inner-wrapper").within(() => {
+ cy.wait(1000)
+ cy.contains("Create Row").trigger('mouseover').click().click()
+ cy.get(".spectrum-Button--cta").click()
+ })
+ cy.contains("Setup").click()
+ cy.get(".spectrum-Picker-label").click()
+ cy.contains("dog").click()
+ cy.get(".spectrum-Textfield-input")
+ .first()
+ .type("goodboy")
+ cy.get(".spectrum-Textfield-input")
+ .eq(1)
+ .type("11")
+
+ cy.contains("Run test").click()
+ cy.get(".modal-inner-wrapper").within(() => {
+ cy.wait(1000)
cy.get(".spectrum-Picker-label").click()
cy.contains("dog").click()
cy.get(".spectrum-Textfield-input")
@@ -35,19 +51,12 @@ context("Create a automation", () => {
cy.get(".spectrum-Textfield-input")
.eq(1)
.type("11")
+ cy.get(".spectrum-Textfield-input")
+ .eq(2)
+ .type("123456")
+ cy.get(".spectrum-Textfield-input")
+ .eq(3)
+ .type("123456")
})
-
- // Save
- cy.contains("Save Automation").click()
-
- // Activate Automation
- cy.get("[data-cy=activate-automation]").click()
- })
-
- it("should add row when a new row is added", () => {
- cy.contains("Data").click()
- cy.addRow(["Rover", 15])
- cy.reload()
- cy.contains("goodboy").should("have.text", "goodboy")
})
})
diff --git a/packages/builder/cypress/support/commands.js b/packages/builder/cypress/support/commands.js
index 261b840577..8bda515fbc 100644
--- a/packages/builder/cypress/support/commands.js
+++ b/packages/builder/cypress/support/commands.js
@@ -37,9 +37,8 @@ Cypress.Commands.add("createApp", name => {
cy.contains("Create app").click()
})
.then(() => {
- cy.get(".selected > .content", {
- timeout: 20000,
- }).should("be.visible")
+ cy.expandBudibaseConnection()
+ cy.get(".nav-item.selected > .content").should("be.visible")
})
})
@@ -83,6 +82,7 @@ Cypress.Commands.add("createTable", tableName => {
Cypress.Commands.add("addColumn", (tableName, columnName, type) => {
// Select Table
+ cy.selectTable(tableName)
cy.contains(".nav-item", tableName).click()
cy.contains("Create column").click()
@@ -161,3 +161,15 @@ Cypress.Commands.add("createScreen", (screenName, route) => {
cy.get(".spectrum-Button--cta").click()
})
})
+
+Cypress.Commands.add("expandBudibaseConnection", () => {
+ if (Cypress.$(".nav-item > .content > .opened").length === 0) {
+ // expand the Budibase DB connection string
+ cy.get(".icon.arrow").eq(0).click()
+ }
+})
+
+Cypress.Commands.add("selectTable", tableName => {
+ cy.expandBudibaseConnection()
+ cy.contains(".nav-item", tableName).click()
+})
diff --git a/packages/builder/package.json b/packages/builder/package.json
index 14b0d84795..ad74b263a7 100644
--- a/packages/builder/package.json
+++ b/packages/builder/package.json
@@ -1,6 +1,6 @@
{
"name": "@budibase/builder",
- "version": "0.9.125-alpha.7",
+ "version": "0.9.125-alpha.11",
"license": "AGPL-3.0",
"private": true,
"scripts": {
@@ -65,10 +65,10 @@
}
},
"dependencies": {
- "@budibase/bbui": "^0.9.125-alpha.7",
- "@budibase/client": "^0.9.125-alpha.7",
+ "@budibase/bbui": "^0.9.125-alpha.11",
+ "@budibase/client": "^0.9.125-alpha.11",
"@budibase/colorpicker": "1.1.2",
- "@budibase/string-templates": "^0.9.125-alpha.7",
+ "@budibase/string-templates": "^0.9.125-alpha.11",
"@sentry/browser": "5.19.1",
"@spectrum-css/page": "^3.0.1",
"@spectrum-css/vars": "^3.0.1",
diff --git a/packages/builder/src/builderStore/store/automation/Automation.js b/packages/builder/src/builderStore/store/automation/Automation.js
index a9dce88258..dcbb747e38 100644
--- a/packages/builder/src/builderStore/store/automation/Automation.js
+++ b/packages/builder/src/builderStore/store/automation/Automation.js
@@ -13,6 +13,10 @@ export default class Automation {
return this.automation.definition.trigger
}
+ addTestData(data) {
+ this.automation.testData = data
+ }
+
addBlock(block) {
// Make sure to add trigger if doesn't exist
if (!this.hasTrigger() && block.type === "TRIGGER") {
diff --git a/packages/builder/src/builderStore/store/automation/index.js b/packages/builder/src/builderStore/store/automation/index.js
index f8e7db04a0..db06ce1726 100644
--- a/packages/builder/src/builderStore/store/automation/index.js
+++ b/packages/builder/src/builderStore/store/automation/index.js
@@ -17,7 +17,6 @@ const automationActions = store => ({
state.blockDefinitions = {
TRIGGER: jsonResponses[1].trigger,
ACTION: jsonResponses[1].action,
- LOGIC: jsonResponses[1].logic,
}
// if previously selected find the new obj and select it
if (selected) {
@@ -80,9 +79,14 @@ const automationActions = store => ({
const { _id } = automation
return await api.post(`/api/automations/${_id}/trigger`)
},
- test: async ({ automation }) => {
+ test: async ({ automation }, testData) => {
const { _id } = automation
- return await api.post(`/api/automations/${_id}/test`)
+ const response = await api.post(`/api/automations/${_id}/test`, testData)
+ const json = await response.json()
+ store.update(state => {
+ state.selectedAutomation.testResults = json
+ return state
+ })
},
select: automation => {
store.update(state => {
@@ -91,6 +95,12 @@ const automationActions = store => ({
return state
})
},
+ addTestDataToAutomation: data => {
+ store.update(state => {
+ state.selectedAutomation.addTestData(data)
+ return state
+ })
+ },
addBlockToAutomation: block => {
store.update(state => {
const newBlock = state.selectedAutomation.addBlock(cloneDeep(block))
@@ -132,7 +142,6 @@ export const getAutomationStore = () => {
blockDefinitions: {
TRIGGER: [],
ACTION: [],
- LOGIC: [],
},
selectedAutomation: null,
}
diff --git a/packages/builder/src/components/automation/AutomationBuilder/AutomationBuilder.svelte b/packages/builder/src/components/automation/AutomationBuilder/AutomationBuilder.svelte
index 62faff3caa..7ce77a58e3 100644
--- a/packages/builder/src/components/automation/AutomationBuilder/AutomationBuilder.svelte
+++ b/packages/builder/src/components/automation/AutomationBuilder/AutomationBuilder.svelte
@@ -1,10 +1,8 @@
{#if automation}
-
{/if}
diff --git a/packages/builder/src/components/automation/AutomationBuilder/BlockList.svelte b/packages/builder/src/components/automation/AutomationBuilder/BlockList.svelte
deleted file mode 100644
index a04541cfad..0000000000
--- a/packages/builder/src/components/automation/AutomationBuilder/BlockList.svelte
+++ /dev/null
@@ -1,114 +0,0 @@
-
-
-
- {#each tabs as tab, idx}
-
-
onChangeTab(idx)}
- >
- {tab.label}
-
-
- {/each}
-
- (selectedIndex = null)}
- bind:this={popover}
- {anchor}
- align="left"
->
-
- {#each blocks as [stepId, blockDefinition]}
- addBlockToAutomation(stepId, blockDefinition)}
- />
- {/each}
-
-
-
-
-
-
-
diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte
new file mode 100644
index 0000000000..8820259e90
--- /dev/null
+++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ActionModal.svelte
@@ -0,0 +1,136 @@
+
+
+ {
+ blockComplete = true
+ addBlockToAutomation()
+ }}
+>
+ Select an app or event.
+
+ Apps
+
+
+ {#each Object.entries(external) as [idx, action]}
+
selectAction(action)}
+ >
+
+
+
+ {idx.charAt(0).toUpperCase() + idx.slice(1)}
+
+
+ {/each}
+
+
+ Actions
+
+
+ {#each Object.entries(internal) as [idx, action]}
+
selectAction(action)}
+ >
+
+
+
+ {action.name}
+
+
+ {/each}
+
+
+
+
+
diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/Arrow.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/Arrow.svelte
index 931490b197..5aec39abeb 100644
--- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/Arrow.svelte
+++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/Arrow.svelte
@@ -6,6 +6,7 @@
xmlns="http://www.w3.org/2000/svg"
>
diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ExternalActions.js b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ExternalActions.js
new file mode 100644
index 0000000000..843445a3c2
--- /dev/null
+++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ExternalActions.js
@@ -0,0 +1,11 @@
+import DiscordLogo from "assets/discord.svg"
+import ZapierLogo from "assets/zapier.png"
+import IntegromatLogo from "assets/integromat.png"
+import SlackLogo from "assets/slack.svg"
+
+export const externalActions = {
+ zapier: { name: "zapier", icon: ZapierLogo },
+ discord: { name: "discord", icon: DiscordLogo },
+ slack: { name: "slack", icon: SlackLogo },
+ integromat: { name: "integromat", icon: IntegromatLogo },
+}
diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowChart.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowChart.svelte
index e960271b87..53a5de3b51 100644
--- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowChart.svelte
+++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowChart.svelte
@@ -1,12 +1,25 @@
-{#if !blocks.length}Add a trigger to your automation to get started{/if}
-
- {#each blocks as block, idx (block.id)}
-
-
- {#if idx !== blocks.length - 1}
-
- {/if}
+
+
+
+
+
{automation.name}
+
+
deleteAutomation()} class="iconPadding">
+
+
+
{
+ testDataModal.show()
+ }}
+ icon="MultipleCheck"
+ size="S">Run test
+
+
- {/each}
-
+ {#each blocks as block, idx (block.id)}
+
+
+ {#if idx !== blocks.length - 1}
+
+
+
+ {/if}
+
+ {/each}
+
+
+
+
+
diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowItem.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowItem.svelte
index 439db62639..5898537dae 100644
--- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowItem.svelte
+++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowItem.svelte
@@ -1,86 +1,204 @@
onSelect(block)}
+ on:click={() => {
+ 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}
+
+
{
+ blockComplete = !blockComplete
+ }}
+ class="splitHeader"
+ >
+
+ {#if externalActions[block.stepId]}
+
+ {:else}
+
+ {/if}
+
+ {#if isTrigger}
+ When this happens:
+ {:else}
+ Do this:
+ {/if}
+
+ {block?.name?.toUpperCase() || ""}
+
+
+ {#if testResult}
+
resultsModal.show()}>
+ View response
+
+ {/if}
- {#if block.type !== "TRIGGER" || allowDeleteTrigger}
-
- {/if}
-
-
-
-
-
+
+ {#if !blockComplete}
+
+
+
+
+
+ {#if setupToggled}
+
+ {#if lastStep}
+
+ {/if}
+
+ {/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..7dfdff20a7
--- /dev/null
+++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ResultsModal.svelte
@@ -0,0 +1,114 @@
+
+
+
+
+
+ {#if isTrigger || testResult[0].outputs.success}
+
+
+
+ {:else}
+
+
+
+ {/if}
+
+
+
+ {
+ inputToggled = !inputToggled
+ }}
+ class="toggle splitHeader"
+ >
+
+
+ {#if inputToggled}
+
+ {:else}
+
+ {/if}
+
+
+ {#if inputToggled}
+
+
+
+ {/if}
+
+ {
+ outputToggled = !outputToggled
+ }}
+ class="toggle splitHeader"
+ >
+
+
+ {#if outputToggled}
+
+ {:else}
+
+ {/if}
+
+
+ {#if outputToggled}
+
+
+
+ {/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..d05c8fa326
--- /dev/null
+++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte
@@ -0,0 +1,88 @@
+
+
+ {
+ automationStore.actions.addTestDataToAutomation(testData)
+ automationStore.actions.test($automationStore.selectedAutomation, testData)
+ }}
+ cancelText="Cancel"
+>
+
+
+
+
+
+
+
+
+
diff --git a/packages/builder/src/components/automation/AutomationPanel/AutomationList.svelte b/packages/builder/src/components/automation/AutomationPanel/AutomationList.svelte
index f70366773a..79de4bfbe6 100644
--- a/packages/builder/src/components/automation/AutomationPanel/AutomationList.svelte
+++ b/packages/builder/src/components/automation/AutomationPanel/AutomationList.svelte
@@ -6,7 +6,6 @@
import EditAutomationPopover from "./EditAutomationPopover.svelte"
$: selectedAutomationId = $automationStore.selectedAutomation?.automation?._id
-
onMount(() => {
automationStore.actions.fetch()
})
diff --git a/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte b/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte
index dbcbc33db0..0c975eab18 100644
--- a/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte
+++ b/packages/builder/src/components/automation/AutomationPanel/AutomationPanel.svelte
@@ -2,7 +2,9 @@
import AutomationList from "./AutomationList.svelte"
import CreateAutomationModal from "./CreateAutomationModal.svelte"
import { Icon, Modal, Tabs, Tab } from "@budibase/bbui"
- let modal
+
+ export let modal
+ export let webhookModal
@@ -11,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..e774c366a5 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, Icon } 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,97 @@
name,
instanceId,
})
+ const newBlock = $automationStore.selectedAutomation.constructBlock(
+ "TRIGGER",
+ triggerVal.stepId,
+ triggerVal
+ )
+
+ automationStore.actions.addBlockToAutomation(newBlock)
+ if (triggerVal.stepId === "WEBHOOK") {
+ webhookModal.show
+ }
+
+ await automationStore.actions.save({
+ instanceId,
+ automation: $automationStore.selectedAutomation?.automation,
+ })
+
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/components/automation/SetupPanel/AutomationBlockSetup.svelte b/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte
index d1c5d104d3..f5bc2c04a8 100644
--- a/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte
+++ b/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte
@@ -2,8 +2,16 @@
import TableSelector from "./TableSelector.svelte"
import RowSelector from "./RowSelector.svelte"
import SchemaSetup from "./SchemaSetup.svelte"
- import { Button, Input, Select, Label } from "@budibase/bbui"
+ import {
+ Button,
+ Input,
+ Select,
+ Label,
+ ActionButton,
+ Drawer,
+ } from "@budibase/bbui"
import { automationStore } from "builderStore"
+ import { tables } from "stores/backend"
import WebhookDisplay from "../Shared/WebhookDisplay.svelte"
import DrawerBindableInput from "../../common/bindings/DrawerBindableInput.svelte"
import AutomationBindingPanel from "../../common/bindings/ServerBindingPanel.svelte"
@@ -12,15 +20,50 @@
import QueryParamSelector from "./QueryParamSelector.svelte"
import CronBuilder from "./CronBuilder.svelte"
import Editor from "components/integration/QueryEditor.svelte"
+ import { database } from "stores/backend"
+ import { debounce } from "lodash"
+ import ModalBindableInput from "components/common/bindings/ModalBindableInput.svelte"
+ import FilterDrawer from "components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterDrawer.svelte"
+ // need the client lucene builder to convert to the structure API expects
+ import { buildLuceneQuery } from "../../../../../client/src/utils/lucene"
export let block
export let webhookModal
- $: inputs = Object.entries(block.schema?.inputs?.properties || {})
+ export let testData
+ export let schemaProperties
+ export let isTestModal = false
+ let drawer
+ let tempFilters = lookForFilters(schemaProperties) || []
+ let fillWidth = true
+
$: stepId = block.stepId
$: bindings = getAvailableBindings(
- block,
+ block || $automationStore.selectedBlock,
$automationStore.selectedAutomation?.automation?.definition
)
+ $: instanceId = $database._id
+
+ $: inputData = testData ? testData : block.inputs
+ $: tableId = inputData ? inputData.tableId : null
+ $: table = tableId
+ ? $tables.list.find(table => table._id === inputData.tableId)
+ : { schema: {} }
+ $: schemaFields = table ? Object.values(table.schema) : []
+
+ const onChange = debounce(
+ async function (e, key) {
+ if (isTestModal) {
+ testData[key] = e.detail
+ } else {
+ block.inputs[key] = e.detail
+ await automationStore.actions.save({
+ instanceId,
+ automation: $automationStore.selectedAutomation?.automation,
+ })
+ }
+ },
+ isTestModal ? 0 : 800
+ )
function getAvailableBindings(block, automation) {
if (!block || !automation) {
@@ -52,64 +95,159 @@
}
return bindings
}
+
+ function lookForFilters(properties) {
+ console.log("testing")
+ if (!properties) {
+ return []
+ }
+ let filters
+ const inputs = testData ? testData : block.inputs
+ for (let [key, field] of properties) {
+ // need to look for the builder definition (keyed separately, see saveFilters)
+ const defKey = `${key}-def`
+ if (field.customType === "filters" && inputs?.[defKey]) {
+ filters = inputs[defKey]
+ break
+ }
+ }
+ return filters || []
+ }
+
+ function saveFilters(key) {
+ const filters = buildLuceneQuery(tempFilters)
+ const defKey = `${key}-def`
+ inputData[key] = filters
+ inputData[defKey] = tempFilters
+ onChange({ detail: filters }, key)
+ // need to store the builder definition in the automation
+ onChange({ detail: tempFilters }, defKey)
+ drawer.hide()
+ }
-
{block.name}
- {#each inputs as [key, value]}
+ {#each schemaProperties as [key, value]}
-
+
{#if value.type === "string" && value.enum}
{/each}
@@ -132,9 +270,7 @@
grid-gap: 5px;
}
- .block-label {
- font-weight: 600;
- font-size: var(--font-size-s);
- color: var(--grey-7);
+ .test :global(.drawer) {
+ width: 10000px !important;
}
diff --git a/packages/builder/src/components/automation/SetupPanel/CronBuilder.svelte b/packages/builder/src/components/automation/SetupPanel/CronBuilder.svelte
index 810e452742..1b410cd86a 100644
--- a/packages/builder/src/components/automation/SetupPanel/CronBuilder.svelte
+++ b/packages/builder/src/components/automation/SetupPanel/CronBuilder.svelte
@@ -1,7 +1,13 @@
-
+
diff --git a/packages/builder/src/components/automation/SetupPanel/RowSelector.svelte b/packages/builder/src/components/automation/SetupPanel/RowSelector.svelte
index 99f41908e7..3f390e0a4f 100644
--- a/packages/builder/src/components/automation/SetupPanel/RowSelector.svelte
+++ b/packages/builder/src/components/automation/SetupPanel/RowSelector.svelte
@@ -3,12 +3,25 @@
import { Select } from "@budibase/bbui"
import DrawerBindableInput from "../../common/bindings/DrawerBindableInput.svelte"
import AutomationBindingPanel from "../../common/bindings/ServerBindingPanel.svelte"
+ import { createEventDispatcher } from "svelte"
+ import ModalBindableInput from "components/common/bindings/ModalBindableInput.svelte"
+ import { automationStore } from "builderStore"
+
+ const dispatch = createEventDispatcher()
export let value
export let bindings
-
$: table = $tables.list.find(table => table._id === value?.tableId)
$: schemaFields = Object.entries(table?.schema ?? {})
+ const onChangeTable = e => {
+ value = { tableId: e.detail }
+ dispatch("change", value)
+ }
+
+ const onChange = (e, field) => {
+ value[field] = e.detail
+ dispatch("change", value)
+ }
// Ensure any nullish tableId values get set to empty string so
// that the select works
@@ -20,7 +33,8 @@
table.name}
getOptionValue={table => table._id}
@@ -32,19 +46,32 @@
{#if !schema.autocolumn}
{#if schemaHasOptions(schema)}
onChange(e, field)}
label={field}
- bind:value={value[field]}
+ value={value[field]}
options={schema.constraints.inclusion}
/>
{:else if schema.type === "string" || schema.type === "number"}
- (value[field] = e.detail)}
- label={field}
- type="string"
- {bindings}
- />
+ {#if $automationStore.selectedAutomation.automation.testData}
+ onChange(e, field)}
+ {bindings}
+ />
+ {:else}
+ onChange(e, field)}
+ label={field}
+ type="string"
+ {bindings}
+ fillWidth={true}
+ />
+ {/if}
{/if}
{/if}
{/each}
diff --git a/packages/builder/src/components/automation/SetupPanel/SchemaSetup.svelte b/packages/builder/src/components/automation/SetupPanel/SchemaSetup.svelte
index 1257563ff8..54f5b90164 100644
--- a/packages/builder/src/components/automation/SetupPanel/SchemaSetup.svelte
+++ b/packages/builder/src/components/automation/SetupPanel/SchemaSetup.svelte
@@ -1,5 +1,8 @@
@@ -68,7 +72,10 @@
/>
(value[field.name] = e.target.value)}
+ on:change={e => {
+ value[field.name] = e.target.value
+ dispatch("change", value)
+ }}
options={typeOptions}
/>
- import { automationStore } from "builderStore"
- import { database } from "stores/backend"
- import { notifications, Button, Modal, Heading, Toggle } from "@budibase/bbui"
- import AutomationBlockSetup from "./AutomationBlockSetup.svelte"
- import CreateWebookModal from "../Shared/CreateWebhookModal.svelte"
-
- let webhookModal
-
- $: instanceId = $database._id
- $: automation = $automationStore.selectedAutomation?.automation
- $: automationLive = automation?.live
-
- function setAutomationLive(live) {
- if (automationLive === live) {
- return
- }
- automation.live = live
- automationStore.actions.save({ instanceId, automation })
- if (live) {
- notifications.info(`Automation ${automation.name} enabled.`)
- } else {
- notifications.error(`Automation ${automation.name} disabled.`)
- }
- }
-
- async function testAutomation() {
- const result = await automationStore.actions.test({
- automation: $automationStore.selectedAutomation.automation,
- })
- if (result.status === 200) {
- notifications.success(
- `Automation ${automation.name} triggered successfully.`
- )
- } else {
- notifications.error(`Failed to trigger automation ${automation.name}.`)
- }
- }
-
- async function saveAutomation() {
- await automationStore.actions.save({
- instanceId,
- automation,
- })
- notifications.success(`Automation ${automation.name} saved.`)
- }
-
-
-
- Setup
- setAutomationLive(!automationLive)}
- dataCy="activate-automation"
- text="Live"
- />
-
-{#if $automationStore.selectedBlock}
-
-{:else if automation}
- {automation.name}
-
-{/if}
-
-
-
-
-
-
diff --git a/packages/builder/src/components/automation/SetupPanel/TableSelector.svelte b/packages/builder/src/components/automation/SetupPanel/TableSelector.svelte
index 4f9ac05a06..ceb28a37ca 100644
--- a/packages/builder/src/components/automation/SetupPanel/TableSelector.svelte
+++ b/packages/builder/src/components/automation/SetupPanel/TableSelector.svelte
@@ -1,11 +1,20 @@
table.name}
diff --git a/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte b/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte
index 42ea30dbb0..84c737eb67 100644
--- a/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte
+++ b/packages/builder/src/components/backend/DatasourceNavigator/DatasourceNavigator.svelte
@@ -9,7 +9,10 @@
import TableNavigator from "components/backend/TableNavigator/TableNavigator.svelte"
import ICONS from "./icons"
+ let openDataSources = []
+
function selectDatasource(datasource) {
+ toggleNode(datasource)
datasources.select(datasource._id)
$goto(`./datasource/${datasource._id}`)
}
@@ -19,6 +22,15 @@
$goto(`./datasource/${query.datasourceId}/${query._id}`)
}
+ function toggleNode(datasource) {
+ const isOpen = openDataSources.includes(datasource._id)
+ if (isOpen) {
+ openDataSources = openDataSources.filter(id => datasource._id !== id)
+ } else {
+ openDataSources = [...openDataSources, datasource._id]
+ }
+ }
+
onMount(() => {
datasources.fetch()
queries.fetch()
@@ -31,8 +43,11 @@
0}
text={datasource.name}
+ opened={openDataSources.includes(datasource._id)}
selected={$datasources.selected === datasource._id}
+ withArrow={true}
on:click={() => selectDatasource(datasource)}
+ on:iconClick={() => toggleNode(datasource)}
>
-
+ {#if openDataSources.includes(datasource._id)}
+
+ {/if}
{#each $queries.list.filter(query => query.datasourceId === datasource._id) as query}
onClickQuery(query)}
>
diff --git a/packages/builder/src/components/common/NavItem.svelte b/packages/builder/src/components/common/NavItem.svelte
index 977369299d..ec7994be84 100644
--- a/packages/builder/src/components/common/NavItem.svelte
+++ b/packages/builder/src/components/common/NavItem.svelte
@@ -1,5 +1,6 @@
{#if withArrow}
-
+
{/if}
diff --git a/packages/builder/src/components/common/bindings/DrawerBindableInput.svelte b/packages/builder/src/components/common/bindings/DrawerBindableInput.svelte
index ee2487a9d6..e5bfab583c 100644
--- a/packages/builder/src/components/common/bindings/DrawerBindableInput.svelte
+++ b/packages/builder/src/components/common/bindings/DrawerBindableInput.svelte
@@ -14,6 +14,7 @@
export let placeholder
export let label
export let disabled = false
+ export let fillWidth
const dispatch = createEventDispatcher()
let bindingDrawer
@@ -45,7 +46,7 @@
{/if}
-
+
Add the objects on the left to enrich your text.
diff --git a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte
index 494050f690..33ef0c6ea4 100644
--- a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte
+++ b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte
@@ -1,5 +1,5 @@
@@ -127,6 +127,7 @@
title={`Value for "${filter.field}"`}
value={filter.value}
placeholder="Value"
+ {panel}
{bindings}
on:change={event => (filter.value = event.detail)}
/>
diff --git a/packages/builder/src/pages/builder/_layout.svelte b/packages/builder/src/pages/builder/_layout.svelte
index 0dbabb31d2..4b296854b6 100644
--- a/packages/builder/src/pages/builder/_layout.svelte
+++ b/packages/builder/src/pages/builder/_layout.svelte
@@ -6,31 +6,35 @@
let loaded = false
$: multiTenancyEnabled = $admin.multiTenancy
- $: hasAdminUser = $admin?.checklist?.adminUser.checked
+ $: hasAdminUser = $admin?.checklist?.adminUser?.checked
$: tenantSet = $auth.tenantSet
+ $: cloud = $admin.cloud
onMount(async () => {
- await admin.init()
await auth.checkAuth()
+ await admin.init()
loaded = true
})
$: {
- const apiReady = $admin.loaded && $auth.loaded
- // if tenant is not set go to it
- if (loaded && apiReady && multiTenancyEnabled && !tenantSet) {
- $redirect("./auth/org")
- }
- // Force creation of an admin user if one doesn't exist
- else if (loaded && apiReady && !hasAdminUser) {
- $redirect("./admin")
+ // We should never see the org or admin user creation screens in the cloud
+ if (!cloud) {
+ const apiReady = $admin.loaded && $auth.loaded
+ // if tenant is not set go to it
+ if (loaded && apiReady && multiTenancyEnabled && !tenantSet) {
+ $redirect("./auth/org")
+ }
+ // Force creation of an admin user if one doesn't exist
+ else if (loaded && apiReady && !hasAdminUser) {
+ $redirect("./admin")
+ }
}
}
// Redirect to log in at any time if the user isn't authenticated
$: {
if (
loaded &&
- hasAdminUser &&
+ (hasAdminUser || cloud) &&
!$auth.user &&
!$isActive("./auth") &&
!$isActive("./invite")
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..841acb22c0 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,50 @@
-
+ {#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
-
-
diff --git a/packages/builder/src/pages/builder/auth/org.svelte b/packages/builder/src/pages/builder/auth/org.svelte
index 785cf05914..fea8831935 100644
--- a/packages/builder/src/pages/builder/auth/org.svelte
+++ b/packages/builder/src/pages/builder/auth/org.svelte
@@ -8,6 +8,7 @@
let tenantId = get(auth).tenantSet ? get(auth).tenantId : ""
$: multiTenancyEnabled = $admin.multiTenancy
+ $: cloud = $admin.cloud
async function setOrg() {
if (tenantId == null || tenantId === "") {
@@ -25,7 +26,7 @@
onMount(async () => {
await auth.checkQueryString()
- if (!multiTenancyEnabled) {
+ if (!multiTenancyEnabled || cloud) {
$goto("../")
} else {
admin.unload()
diff --git a/packages/builder/src/pages/builder/portal/_layout.svelte b/packages/builder/src/pages/builder/portal/_layout.svelte
index 3b8513b5a9..02f49bec5a 100644
--- a/packages/builder/src/pages/builder/portal/_layout.svelte
+++ b/packages/builder/src/pages/builder/portal/_layout.svelte
@@ -62,7 +62,7 @@
}
// add link to account portal if the user has access
- if ($auth?.user?.account) {
+ if ($auth?.user?.accountPortalAccess) {
menu = menu.concat([
{
title: "Account",
diff --git a/packages/cli/package.json b/packages/cli/package.json
index 2cc9a1aba3..1729e3003c 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -1,6 +1,6 @@
{
"name": "@budibase/cli",
- "version": "0.9.125-alpha.7",
+ "version": "0.9.125-alpha.11",
"description": "Budibase CLI, for developers, self hosting and migrations.",
"main": "src/index.js",
"bin": {
diff --git a/packages/client/package.json b/packages/client/package.json
index 9b60b1eddc..45499807ab 100644
--- a/packages/client/package.json
+++ b/packages/client/package.json
@@ -1,6 +1,6 @@
{
"name": "@budibase/client",
- "version": "0.9.125-alpha.7",
+ "version": "0.9.125-alpha.11",
"license": "MPL-2.0",
"module": "dist/budibase-client.js",
"main": "dist/budibase-client.js",
@@ -19,9 +19,9 @@
"dev:builder": "rollup -cw"
},
"dependencies": {
- "@budibase/bbui": "^0.9.125-alpha.7",
+ "@budibase/bbui": "^0.9.125-alpha.11",
"@budibase/standard-components": "^0.9.124",
- "@budibase/string-templates": "^0.9.125-alpha.7",
+ "@budibase/string-templates": "^0.9.125-alpha.11",
"regexparam": "^1.3.0",
"shortid": "^2.2.15",
"svelte-spa-router": "^3.0.5"
diff --git a/packages/client/yarn.lock b/packages/client/yarn.lock
index 5e6e414769..7815ac54f2 100644
--- a/packages/client/yarn.lock
+++ b/packages/client/yarn.lock
@@ -28,10 +28,10 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
-"@budibase/bbui@^0.9.125":
- version "0.9.125"
- resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.125.tgz#b1a85e38c884de5fa35de3a778be05f279dc8315"
- integrity sha512-amU8NTeuaUrulPQM6kXZbQznZ6fX8uMw7mhsn/23TonbDyHWGSZRJ6pIA2FYc+KOESK1fL62O4yzfQA0OIViNw==
+"@budibase/bbui@^0.9.125-alpha.11":
+ version "0.9.130"
+ resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.130.tgz#cad02a7aa16324eb7a056c5dc0162444fa917964"
+ integrity sha512-ULOC++363K8QEMasmsDmleF7AzjulFk/ZxGPlOJcVKJU8Bx5wG1uNFgTyJyGpmnbUWHd67eYUEettfH7I+VoOw==
dependencies:
"@adobe/spectrum-css-workflow-icons" "^1.2.1"
"@spectrum-css/actionbutton" "^1.0.1"
@@ -77,10 +77,10 @@
svelte-flatpickr "^3.1.0"
svelte-portal "^1.0.0"
-"@budibase/bbui@^0.9.125-alpha.5":
- version "0.9.128"
- resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.128.tgz#71a5e81b02a4f64baa6874bfa4b1d4fed8cc9f0b"
- integrity sha512-UCo9SRs1xsMQ0ClJOtNB7JeVF2+0iMVOfAZE7Rrf5d51W+1YeyM9b3BbfhxHRq1yeKLHrbdczerbTHQkmF1RwQ==
+"@budibase/bbui@^0.9.129":
+ version "0.9.129"
+ resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.129.tgz#989bf60d404772d4b308382faba7adac6518ec3e"
+ integrity sha512-U3uO9K3m7Ph5RQpzXx5IIy94s/KdU9Q8eJXFQwH6neYIKQk3OFo8br5px5C7lE38mtazqq9XvQy0f+MUarKk4A==
dependencies:
"@adobe/spectrum-css-workflow-icons" "^1.2.1"
"@spectrum-css/actionbutton" "^1.0.1"
@@ -155,11 +155,11 @@
year "^0.2.1"
"@budibase/standard-components@^0.9.124":
- version "0.9.125"
- resolved "https://registry.yarnpkg.com/@budibase/standard-components/-/standard-components-0.9.125.tgz#92244f009ce22f105694ca85fdc78923f8bcba11"
- integrity sha512-PjCJ39o0EMfrlMTUKDNHr+W1Vpz4saS5HKoOW0kigRvC7pwxnZuApB8uLryQ4hp4YCUelY30B4a7ps/JtYntDg==
+ version "0.9.129"
+ resolved "https://registry.yarnpkg.com/@budibase/standard-components/-/standard-components-0.9.129.tgz#f2cdead99b8f25177c4c291be3032fb9ffd1dac3"
+ integrity sha512-RYWBcrz4MGICg9neIPQ4CbU3WTTJoTofi2D4pwA+qvvN3uhqOCcFIZ3+yadZ5Akz2qwMztQ8WDvetowm2srZcA==
dependencies:
- "@budibase/bbui" "^0.9.125"
+ "@budibase/bbui" "^0.9.129"
"@spectrum-css/button" "^3.0.3"
"@spectrum-css/card" "^3.0.3"
"@spectrum-css/divider" "^1.0.3"
@@ -172,10 +172,10 @@
svelte-apexcharts "^1.0.2"
svelte-flatpickr "^3.1.0"
-"@budibase/string-templates@^0.9.125-alpha.5":
- version "0.9.128"
- resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-0.9.128.tgz#50ee46dc0d726d481bd5139cd0b38364649a8463"
- integrity sha512-4TzmnX2o5S2cts08ukB86El4wYm7cHuV2t6a7yDMGPe1mWeKP1WEtVF6rKhXEdbPTiotW8oYondOlgOP7DT9lA==
+"@budibase/string-templates@^0.9.125-alpha.11":
+ version "0.9.130"
+ resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-0.9.130.tgz#1be8affcba0dc8ff2b8044c65dd378dc76a165d0"
+ integrity sha512-DXO6Um18/k16i3hYilxvQ4RYNHhd29OJGbzjfQZ2v7z4Oin5y+WMZzpjX1hQS5g9f/CBbzu7qd7EHiz/n8gMqg==
dependencies:
"@budibase/handlebars-helpers" "^0.11.4"
dayjs "^1.10.4"
@@ -1272,7 +1272,12 @@ date.js@^0.3.1:
dependencies:
debug "~3.1.0"
-dayjs@^1.10.4, dayjs@^1.10.5:
+dayjs@^1.10.4:
+ version "1.10.7"
+ resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.7.tgz#2cf5f91add28116748440866a0a1d26f3a6ce468"
+ integrity sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig==
+
+dayjs@^1.10.5:
version "1.10.6"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.6.tgz#288b2aa82f2d8418a6c9d4df5898c0737ad02a63"
integrity sha512-AztC/IOW4L1Q41A86phW5Thhcrco3xuAA+YX/BLpLWWjRcTj5TOt/QImBLmCKlrF7u7k47arTnOyL6GnbG8Hvw==
diff --git a/packages/server/package.json b/packages/server/package.json
index c564e00d6e..c5642c72c7 100644
--- a/packages/server/package.json
+++ b/packages/server/package.json
@@ -1,7 +1,7 @@
{
"name": "@budibase/server",
"email": "hi@budibase.com",
- "version": "0.9.125-alpha.7",
+ "version": "0.9.125-alpha.11",
"description": "Budibase Web Server",
"main": "src/index.js",
"repository": {
@@ -49,7 +49,8 @@
"!src/automations/tests/**/*",
"!src/utilities/fileProcessor.js",
"!src/utilities/fileSystem/**/*",
- "!src/utilities/redis.js"
+ "!src/utilities/redis.js",
+ "!src/api/controllers/row/internalSearch.js"
],
"coverageReporters": [
"lcov",
@@ -63,9 +64,9 @@
"author": "Budibase",
"license": "AGPL-3.0-or-later",
"dependencies": {
- "@budibase/auth": "^0.9.125-alpha.7",
- "@budibase/client": "^0.9.125-alpha.7",
- "@budibase/string-templates": "^0.9.125-alpha.7",
+ "@budibase/auth": "^0.9.125-alpha.11",
+ "@budibase/client": "^0.9.125-alpha.11",
+ "@budibase/string-templates": "^0.9.125-alpha.11",
"@elastic/elasticsearch": "7.10.0",
"@koa/router": "8.0.0",
"@sendgrid/mail": "7.1.1",
diff --git a/packages/server/src/api/controllers/row/index.js b/packages/server/src/api/controllers/row/index.js
index a50afa77ea..1d003ebd18 100644
--- a/packages/server/src/api/controllers/row/index.js
+++ b/packages/server/src/api/controllers/row/index.js
@@ -113,6 +113,7 @@ exports.destroy = async function (ctx) {
exports.search = async ctx => {
const tableId = getTableId(ctx)
try {
+ ctx.status = 200
ctx.body = await pickApi(tableId).search(ctx)
} catch (err) {
ctx.throw(400, err)
diff --git a/packages/server/src/automations/actions.js b/packages/server/src/automations/actions.js
index ef77387a40..13f7c487c1 100644
--- a/packages/server/src/automations/actions.js
+++ b/packages/server/src/automations/actions.js
@@ -13,6 +13,7 @@ const zapier = require("./steps/zapier")
const integromat = require("./steps/integromat")
let filter = require("./steps/filter")
let delay = require("./steps/delay")
+let queryRow = require("./steps/queryRows")
const ACTION_IMPLS = {
SEND_EMAIL_SMTP: sendSmtpEmail.run,
@@ -26,6 +27,7 @@ const ACTION_IMPLS = {
SERVER_LOG: serverLog.run,
DELAY: delay.run,
FILTER: filter.run,
+ QUERY_ROWS: queryRow.run,
// these used to be lowercase step IDs, maintain for backwards compat
discord: discord.run,
slack: slack.run,
@@ -44,6 +46,7 @@ const ACTION_DEFINITIONS = {
SERVER_LOG: serverLog.definition,
DELAY: delay.definition,
FILTER: filter.definition,
+ QUERY_ROWS: queryRow.definition,
// these used to be lowercase step IDs, maintain for backwards compat
discord: discord.definition,
slack: slack.definition,
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..9706126438 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: "TableRowAddBottom",
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..26623d628b 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: "TableRowRemoveCenter",
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/queryRows.js b/packages/server/src/automations/steps/queryRows.js
new file mode 100644
index 0000000000..64b757418e
--- /dev/null
+++ b/packages/server/src/automations/steps/queryRows.js
@@ -0,0 +1,119 @@
+const rowController = require("../../api/controllers/row")
+const tableController = require("../../api/controllers/table")
+const { FieldTypes } = require("../../constants")
+
+const SortOrders = {
+ ASCENDING: "ascending",
+ DESCENDING: "descending",
+}
+
+const SortOrdersPretty = {
+ [SortOrders.ASCENDING]: "Ascending",
+ [SortOrders.DESCENDING]: "Descending",
+}
+
+exports.definition = {
+ description: "Query rows from the database",
+ icon: "Search",
+ 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"],
+ },
+ outputs: {
+ properties: {
+ rows: {
+ type: "array",
+ customType: "rows",
+ description: "The rows that were found",
+ },
+ success: {
+ type: "boolean",
+ description: "Whether the deletion was successful",
+ },
+ },
+ required: ["rows", "success"],
+ },
+ },
+}
+
+async function getTable(appId, tableId) {
+ const ctx = {
+ params: {
+ id: tableId,
+ },
+ appId,
+ }
+ await tableController.find(ctx)
+ return ctx.body
+}
+
+exports.run = async function ({ inputs, appId }) {
+ const { tableId, filters, sortColumn, sortOrder, limit } = inputs
+ const table = await getTable(appId, tableId)
+ let sortType = FieldTypes.STRING
+ if (table && table.schema && sortColumn) {
+ const fieldType = table.schema[sortColumn].type
+ sortType =
+ fieldType === FieldTypes.NUMBER ? FieldTypes.NUMBER : FieldTypes.STRING
+ }
+ const ctx = {
+ params: {
+ tableId,
+ },
+ request: {
+ body: {
+ sortOrder,
+ sortType,
+ sort: sortColumn,
+ query: filters || {},
+ limit,
+ },
+ },
+ appId,
+ }
+ try {
+ await rowController.search(ctx)
+ return {
+ rows: ctx.body ? ctx.body.rows : [],
+ success: ctx.status === 200,
+ }
+ } catch (err) {
+ return {
+ success: false,
+ response: err,
+ }
+ }
+}
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,
diff --git a/packages/server/src/automations/tests/queryRows.spec.js b/packages/server/src/automations/tests/queryRows.spec.js
new file mode 100644
index 0000000000..fca03f4e3b
--- /dev/null
+++ b/packages/server/src/automations/tests/queryRows.spec.js
@@ -0,0 +1,51 @@
+// lucene searching not supported in test due to use of PouchDB
+let rows = []
+jest.mock("../../api/controllers/row/internalSearch", () => ({
+ fullSearch: jest.fn(() => {
+ return {
+ rows,
+ }
+ }),
+ paginatedSearch: jest.fn(),
+}))
+const setup = require("./utilities")
+
+const NAME = "Test"
+
+describe("Test a query step automation", () => {
+ let table
+ let config = setup.getConfig()
+
+ beforeEach(async () => {
+ await config.init()
+ table = await config.createTable()
+ const row = {
+ name: NAME,
+ description: "original description",
+ tableId: table._id,
+ }
+ rows.push(await config.createRow(row))
+ rows.push(await config.createRow(row))
+ })
+
+ afterAll(setup.afterAll)
+
+ it("should be able to run the query step", async () => {
+ const inputs = {
+ tableId: table._id,
+ filters: {
+ equal: {
+ name: NAME,
+ },
+ },
+ sortColumn: "name",
+ sortOrder: "ascending",
+ limit: 10,
+ }
+ const res = await setup.runStep(setup.actions.QUERY_ROWS.stepId, inputs)
+ expect(res.success).toBe(true)
+ expect(res.rows).toBeDefined()
+ expect(res.rows.length).toBe(2)
+ expect(res.rows[0].name).toBe(NAME)
+ })
+})
\ No newline at end of file
diff --git a/packages/server/src/automations/triggerInfo/app.js b/packages/server/src/automations/triggerInfo/app.js
index 1c64795cf3..40d1531fa0 100644
--- a/packages/server/src/automations/triggerInfo/app.js
+++ b/packages/server/src/automations/triggerInfo/app.js
@@ -1,7 +1,7 @@
exports.definition = {
name: "App Action",
event: "app:trigger",
- icon: "ri-window-fill",
+ icon: "Apps",
tagline: "Automation fired from the frontend",
description: "Trigger an automation from an action inside your app",
stepId: "APP",
diff --git a/packages/server/src/automations/triggerInfo/cron.js b/packages/server/src/automations/triggerInfo/cron.js
index 31e79a4abf..9547da69fa 100644
--- a/packages/server/src/automations/triggerInfo/cron.js
+++ b/packages/server/src/automations/triggerInfo/cron.js
@@ -1,7 +1,7 @@
exports.definition = {
name: "Cron Trigger",
event: "cron:trigger",
- icon: "ri-timer-line",
+ icon: "Clock",
tagline: "Cron Trigger ({{inputs.cron}})",
description: "Triggers automation on a cron schedule.",
stepId: "CRON",
diff --git a/packages/server/src/automations/triggerInfo/rowDeleted.js b/packages/server/src/automations/triggerInfo/rowDeleted.js
index c7ead1fec4..7a7de13b11 100644
--- a/packages/server/src/automations/triggerInfo/rowDeleted.js
+++ b/packages/server/src/automations/triggerInfo/rowDeleted.js
@@ -1,7 +1,7 @@
exports.definition = {
name: "Row Deleted",
event: "row:delete",
- icon: "ri-delete-bin-line",
+ icon: "TableRowRemoveCenter",
tagline: "Row is deleted from {{inputs.enriched.table.name}}",
description: "Fired when a row is deleted from your database",
stepId: "ROW_DELETED",
diff --git a/packages/server/src/automations/triggerInfo/rowSaved.js b/packages/server/src/automations/triggerInfo/rowSaved.js
index 3a21a26878..d763ca0a8a 100644
--- a/packages/server/src/automations/triggerInfo/rowSaved.js
+++ b/packages/server/src/automations/triggerInfo/rowSaved.js
@@ -1,7 +1,7 @@
exports.definition = {
name: "Row Created",
event: "row:save",
- icon: "ri-save-line",
+ icon: "TableRowAddBottom",
tagline: "Row is added to {{inputs.enriched.table.name}}",
description: "Fired when a row is added to your database",
stepId: "ROW_SAVED",
diff --git a/packages/server/src/automations/triggerInfo/rowUpdated.js b/packages/server/src/automations/triggerInfo/rowUpdated.js
index 099ce0a6b2..182c7c810e 100644
--- a/packages/server/src/automations/triggerInfo/rowUpdated.js
+++ b/packages/server/src/automations/triggerInfo/rowUpdated.js
@@ -1,7 +1,7 @@
exports.definition = {
name: "Row Updated",
event: "row:update",
- icon: "ri-refresh-line",
+ icon: "Refresh",
tagline: "Row is updated in {{inputs.enriched.table.name}}",
description: "Fired when a row is updated in your database",
stepId: "ROW_UPDATED",
diff --git a/packages/server/src/automations/triggerInfo/webhook.js b/packages/server/src/automations/triggerInfo/webhook.js
index dd83031d8f..56e139311c 100644
--- a/packages/server/src/automations/triggerInfo/webhook.js
+++ b/packages/server/src/automations/triggerInfo/webhook.js
@@ -1,7 +1,7 @@
exports.definition = {
name: "Webhook",
event: "web:trigger",
- icon: "ri-global-line",
+ icon: "Send",
tagline: "Webhook endpoint is hit",
description: "Trigger an automation when a HTTP POST webhook is hit",
stepId: "WEBHOOK",
diff --git a/packages/server/yarn.lock b/packages/server/yarn.lock
index 115566194f..609839ee93 100644
--- a/packages/server/yarn.lock
+++ b/packages/server/yarn.lock
@@ -943,10 +943,10 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
-"@budibase/auth@^0.9.125-alpha.7":
- version "0.9.128"
- resolved "https://registry.yarnpkg.com/@budibase/auth/-/auth-0.9.128.tgz#6bb6c716b6647b7e9362e3faf12b191650ea0ad4"
- integrity sha512-WCcrtAXilT/4++7PdzyTYgrdVqZcKhUev3NcGrFQf7WbDhkVCuigWbb8Q01KXODjbs0BZC0RshVv/PxrgLbBQA==
+"@budibase/auth@^0.9.125-alpha.11":
+ version "0.9.130"
+ resolved "https://registry.yarnpkg.com/@budibase/auth/-/auth-0.9.130.tgz#04ff77b862e87e22b08ee7bebd5409ff479a2b35"
+ integrity sha512-wCgbnk8YvBtRQhmWd7w9UGNLL1ocJPHCq10652Dxm8nLnY0oAsgzVVoMsMULyTypfHiYtUEnOs7+JQ/nYa2zkA==
dependencies:
"@techpass/passport-openidconnect" "^0.3.0"
aws-sdk "^2.901.0"
@@ -1015,10 +1015,10 @@
svelte-flatpickr "^3.1.0"
svelte-portal "^1.0.0"
-"@budibase/bbui@^0.9.128":
- version "0.9.128"
- resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.128.tgz#71a5e81b02a4f64baa6874bfa4b1d4fed8cc9f0b"
- integrity sha512-UCo9SRs1xsMQ0ClJOtNB7JeVF2+0iMVOfAZE7Rrf5d51W+1YeyM9b3BbfhxHRq1yeKLHrbdczerbTHQkmF1RwQ==
+"@budibase/bbui@^0.9.130":
+ version "0.9.130"
+ resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.130.tgz#cad02a7aa16324eb7a056c5dc0162444fa917964"
+ integrity sha512-ULOC++363K8QEMasmsDmleF7AzjulFk/ZxGPlOJcVKJU8Bx5wG1uNFgTyJyGpmnbUWHd67eYUEettfH7I+VoOw==
dependencies:
"@adobe/spectrum-css-workflow-icons" "^1.2.1"
"@spectrum-css/actionbutton" "^1.0.1"
@@ -1064,14 +1064,14 @@
svelte-flatpickr "^3.1.0"
svelte-portal "^1.0.0"
-"@budibase/client@^0.9.125-alpha.7":
- version "0.9.128"
- resolved "https://registry.yarnpkg.com/@budibase/client/-/client-0.9.128.tgz#894f1e9c73cb10b30565e8828244f7ff04a34fce"
- integrity sha512-/CiijM5O/6yc5gtSAFBMP7eJE686QNX1FsCphpA89DjWdNEG5e2e0ZN9Z7AOTD90BUn7JXEAdvmqwDMGF5m8gg==
+"@budibase/client@^0.9.125-alpha.11":
+ version "0.9.130"
+ resolved "https://registry.yarnpkg.com/@budibase/client/-/client-0.9.130.tgz#efff68349667ad315cda2973d530cfe8a30b10d3"
+ integrity sha512-PJiOqEf7QF2/MS5CK9WkJl5JYSz/IBDQ1/H665V4Q1Kf5Y/hL+ymXaC5ztWPt6CZlo6dSoAZaD81h7zd6XeuYA==
dependencies:
- "@budibase/bbui" "^0.9.128"
- "@budibase/standard-components" "^0.9.128"
- "@budibase/string-templates" "^0.9.128"
+ "@budibase/bbui" "^0.9.130"
+ "@budibase/standard-components" "^0.9.130"
+ "@budibase/string-templates" "^0.9.130"
regexparam "^1.3.0"
shortid "^2.2.15"
svelte-spa-router "^3.0.5"
@@ -1122,12 +1122,12 @@
svelte-apexcharts "^1.0.2"
svelte-flatpickr "^3.1.0"
-"@budibase/standard-components@^0.9.128":
- version "0.9.128"
- resolved "https://registry.yarnpkg.com/@budibase/standard-components/-/standard-components-0.9.128.tgz#5d6e1dd751c6927dcf1ee515a6102bf73b315526"
- integrity sha512-fB6BOwk5uhPxW+U+TrIdD+zXU/l22S2YFcjXhaSpYVM+inzih9e+v2FVy2aW0Y85FdJ+MqT420o9EaolSF0p1w==
+"@budibase/standard-components@^0.9.130":
+ version "0.9.130"
+ resolved "https://registry.yarnpkg.com/@budibase/standard-components/-/standard-components-0.9.130.tgz#ed24eaafcca959e15c76b81e2340371d268ab131"
+ integrity sha512-hsLKnVciI+is6L42IDDcZ8sW/aLD0UyYLQd/hqMZT8WBf58908ujY3nwFZnxV30uwjSmiZeYCYmK3vbHDD0ljQ==
dependencies:
- "@budibase/bbui" "^0.9.128"
+ "@budibase/bbui" "^0.9.130"
"@spectrum-css/button" "^3.0.3"
"@spectrum-css/card" "^3.0.3"
"@spectrum-css/divider" "^1.0.3"
@@ -1140,10 +1140,10 @@
svelte-apexcharts "^1.0.2"
svelte-flatpickr "^3.1.0"
-"@budibase/string-templates@^0.9.125-alpha.7", "@budibase/string-templates@^0.9.128":
- version "0.9.128"
- resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-0.9.128.tgz#50ee46dc0d726d481bd5139cd0b38364649a8463"
- integrity sha512-4TzmnX2o5S2cts08ukB86El4wYm7cHuV2t6a7yDMGPe1mWeKP1WEtVF6rKhXEdbPTiotW8oYondOlgOP7DT9lA==
+"@budibase/string-templates@^0.9.125-alpha.11", "@budibase/string-templates@^0.9.130":
+ version "0.9.130"
+ resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-0.9.130.tgz#1be8affcba0dc8ff2b8044c65dd378dc76a165d0"
+ integrity sha512-DXO6Um18/k16i3hYilxvQ4RYNHhd29OJGbzjfQZ2v7z4Oin5y+WMZzpjX1hQS5g9f/CBbzu7qd7EHiz/n8gMqg==
dependencies:
"@budibase/handlebars-helpers" "^0.11.4"
dayjs "^1.10.4"
diff --git a/packages/string-templates/manifest.json b/packages/string-templates/manifest.json
index 02bd7f8a64..629bb2ebe3 100644
--- a/packages/string-templates/manifest.json
+++ b/packages/string-templates/manifest.json
@@ -1090,6 +1090,115 @@
"description": "Block helper that always renders the inverse block unless a
is less than or equal to b
.
\n"
}
},
+ "object": {
+ "extend": {
+ "args": [
+ "objects"
+ ],
+ "numArgs": 1,
+ "description": "Extend the context with the properties of other objects. A shallow merge is performed to avoid mutating the context.
\n"
+ },
+ "forIn": {
+ "args": [
+ "context",
+ "options"
+ ],
+ "numArgs": 2,
+ "description": "Block helper that iterates over the properties of an object, exposing each key and value on the context.
\n"
+ },
+ "forOwn": {
+ "args": [
+ "obj",
+ "options"
+ ],
+ "numArgs": 2,
+ "description": "Block helper that iterates over the own properties of an object, exposing each key and value on the context.
\n"
+ },
+ "toPath": {
+ "args": [
+ "prop"
+ ],
+ "numArgs": 1,
+ "description": "Take arguments and, if they are string or number, convert them to a dot-delineated object property path.
\n"
+ },
+ "get": {
+ "args": [
+ "prop",
+ "context",
+ "options"
+ ],
+ "numArgs": 3,
+ "description": "Use property paths (a.b.c
) to get a value or nested value from the context. Works as a regular helper or block helper.
\n"
+ },
+ "getObject": {
+ "args": [
+ "prop",
+ "context"
+ ],
+ "numArgs": 2,
+ "description": "Use property paths (a.b.c
) to get an object from the context. Differs from the get
helper in that this helper will return the actual object, including the given property key. Also, this helper does not work as a block helper.
\n"
+ },
+ "hasOwn": {
+ "args": [
+ "key",
+ "context"
+ ],
+ "numArgs": 2,
+ "description": "Return true if key
is an own, enumerable property of the given context
object.
\n"
+ },
+ "isObject": {
+ "args": [
+ "value"
+ ],
+ "numArgs": 1,
+ "description": "Return true if value
is an object.
\n"
+ },
+ "JSONparse": {
+ "args": [
+ "string"
+ ],
+ "numArgs": 1,
+ "description": "Parses the given string using JSON.parse
.
\n"
+ },
+ "JSONstringify": {
+ "args": [
+ "obj"
+ ],
+ "numArgs": 1,
+ "description": "Stringify an object using JSON.stringify
.
\n"
+ },
+ "merge": {
+ "args": [
+ "object",
+ "objects"
+ ],
+ "numArgs": 2,
+ "description": "Deeply merge the properties of the given objects
with the context object.
\n"
+ },
+ "parseJSON": {
+ "args": [
+ "string"
+ ],
+ "numArgs": 1,
+ "description": "Parses the given string using JSON.parse
.
\n"
+ },
+ "pick": {
+ "args": [
+ "properties",
+ "context",
+ "options"
+ ],
+ "numArgs": 3,
+ "description": "Pick properties from the context object.
\n"
+ },
+ "stringify": {
+ "args": [
+ "obj"
+ ],
+ "numArgs": 1,
+ "description": "Stringify an object using JSON.stringify
.
\n"
+ }
+ },
"date": {
"date": {
"args": [
diff --git a/packages/string-templates/package.json b/packages/string-templates/package.json
index 43b1f6f7d7..b97b796019 100644
--- a/packages/string-templates/package.json
+++ b/packages/string-templates/package.json
@@ -1,6 +1,6 @@
{
"name": "@budibase/string-templates",
- "version": "0.9.125-alpha.7",
+ "version": "0.9.125-alpha.11",
"description": "Handlebars wrapper for Budibase templating.",
"main": "src/index.cjs",
"module": "dist/bundle.mjs",
diff --git a/packages/string-templates/scripts/gen-collection-info.js b/packages/string-templates/scripts/gen-collection-info.js
index fcd3cb4923..29df10423f 100644
--- a/packages/string-templates/scripts/gen-collection-info.js
+++ b/packages/string-templates/scripts/gen-collection-info.js
@@ -11,7 +11,15 @@ const marked = require("marked")
*/
const DIRECTORY = fs.existsSync("node_modules") ? "." : ".."
-const COLLECTIONS = ["math", "array", "number", "url", "string", "comparison"]
+const COLLECTIONS = [
+ "math",
+ "array",
+ "number",
+ "url",
+ "string",
+ "comparison",
+ "object",
+]
const FILENAME = `${DIRECTORY}/manifest.json`
const outputJSON = {}
const ADDED_HELPERS = {
diff --git a/packages/worker/package.json b/packages/worker/package.json
index 59258e3886..89e86f6da9 100644
--- a/packages/worker/package.json
+++ b/packages/worker/package.json
@@ -1,7 +1,7 @@
{
"name": "@budibase/worker",
"email": "hi@budibase.com",
- "version": "0.9.125-alpha.7",
+ "version": "0.9.125-alpha.11",
"description": "Budibase background service",
"main": "src/index.js",
"repository": {
@@ -25,8 +25,8 @@
"author": "Budibase",
"license": "AGPL-3.0-or-later",
"dependencies": {
- "@budibase/auth": "^0.9.125-alpha.7",
- "@budibase/string-templates": "^0.9.125-alpha.7",
+ "@budibase/auth": "^0.9.125-alpha.11",
+ "@budibase/string-templates": "^0.9.125-alpha.11",
"@koa/router": "^8.0.0",
"@techpass/passport-openidconnect": "^0.3.0",
"aws-sdk": "^2.811.0",
diff --git a/packages/worker/src/api/controllers/global/users.js b/packages/worker/src/api/controllers/global/users.js
index 13959273cd..415808bf86 100644
--- a/packages/worker/src/api/controllers/global/users.js
+++ b/packages/worker/src/api/controllers/global/users.js
@@ -197,10 +197,10 @@ exports.getSelf = async ctx => {
// this will set the body
await exports.find(ctx)
- // append the account portal session information if present
- if (ctx.user.account) {
- ctx.body.account = ctx.user.account
- }
+ // forward session information not found in db
+ ctx.body.account = ctx.user.account
+ ctx.body.budibaseAccess = ctx.user.budibaseAccess
+ ctx.body.accountPortalAccess = ctx.user.accountPortalAccess
}
exports.updateSelf = async ctx => {
diff --git a/packages/worker/src/api/index.js b/packages/worker/src/api/index.js
index 03e782688e..e3cc6efbc4 100644
--- a/packages/worker/src/api/index.js
+++ b/packages/worker/src/api/index.js
@@ -84,7 +84,10 @@ router
.use(buildTenancyMiddleware(PUBLIC_ENDPOINTS, NO_TENANCY_ENDPOINTS))
// for now no public access is allowed to worker (bar health check)
.use((ctx, next) => {
- if (!ctx.isAuthenticated && !ctx.publicEndpoint) {
+ if (ctx.publicEndpoint) {
+ return next()
+ }
+ if (!ctx.isAuthenticated || !ctx.user.budibaseAccess) {
ctx.throw(403, "Unauthorized - no public worker access")
}
return next()