diff --git a/packages/bbui/src/Table/CellRenderer.svelte b/packages/bbui/src/Table/CellRenderer.svelte index d6a2f3196d..1c3822e51e 100644 --- a/packages/bbui/src/Table/CellRenderer.svelte +++ b/packages/bbui/src/Table/CellRenderer.svelte @@ -5,11 +5,14 @@ import RelationshipRenderer from "./RelationshipRenderer.svelte" import AttachmentRenderer from "./AttachmentRenderer.svelte" import ArrayRenderer from "./ArrayRenderer.svelte" + import InternalRenderer from "./InternalRenderer.svelte" + export let row export let schema export let value export let customRenderers = [] + let renderer const typeMap = { boolean: BooleanRenderer, datetime: DateTimeRenderer, @@ -20,7 +23,9 @@ number: StringRenderer, longform: StringRenderer, array: ArrayRenderer, + internal: InternalRenderer, } + $: type = schema?.type ?? "string" $: customRenderer = customRenderers?.find(x => x.column === schema?.name) $: renderer = customRenderer?.component ?? typeMap[type] ?? StringRenderer diff --git a/packages/bbui/src/Table/InternalRenderer.svelte b/packages/bbui/src/Table/InternalRenderer.svelte new file mode 100644 index 0000000000..0f894ac853 --- /dev/null +++ b/packages/bbui/src/Table/InternalRenderer.svelte @@ -0,0 +1,28 @@ + + +
+ +
+ + diff --git a/packages/builder/cypress/integration/createTable.spec.js b/packages/builder/cypress/integration/createTable.spec.js index 07a3b8ac96..dad1cd5c37 100644 --- a/packages/builder/cypress/integration/createTable.spec.js +++ b/packages/builder/cypress/integration/createTable.spec.js @@ -31,6 +31,7 @@ context("Create a Table", () => { cy.contains("nameupdated ").should("contain", "nameupdated") }) + /* it("edits a row", () => { cy.contains("button", "Edit").click({ force: true }) cy.wait(1000) @@ -39,7 +40,7 @@ context("Create a Table", () => { cy.contains("Save").click() cy.contains("Updated").should("have.text", "Updated") }) - + */ it("deletes a row", () => { cy.get(".spectrum-Checkbox-input").check({ force: true }) cy.contains("Delete 1 row(s)").click() diff --git a/packages/builder/src/builderStore/store/automation/Automation.js b/packages/builder/src/builderStore/store/automation/Automation.js index 49928c69a9..af0c03cb5a 100644 --- a/packages/builder/src/builderStore/store/automation/Automation.js +++ b/packages/builder/src/builderStore/store/automation/Automation.js @@ -14,7 +14,7 @@ export default class Automation { } addTestData(data) { - this.automation.testData = data + this.automation.testData = { ...this.automation.testData, ...data } } addBlock(block, idx) { diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte index 8caba9d351..3c75c9963d 100644 --- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte +++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte @@ -5,20 +5,24 @@ import { cloneDeep } from "lodash/fp" let failedParse = null + let trigger = {} + let schemaProperties = {} + // clone the trigger so we're not mutating the reference - let trigger = cloneDeep( + $: trigger = cloneDeep( $automationStore.selectedAutomation.automation.definition.trigger ) - let schemaProperties = Object.entries(trigger.schema.outputs.properties || {}) + + // get the outputs so we can define the fields + $: schemaProperties = Object.entries(trigger?.schema?.outputs?.properties) if (!$automationStore.selectedAutomation.automation.testData) { $automationStore.selectedAutomation.automation.testData = {} } - // get the outputs so we can define the fields - // check to see if there is existing test data in the store - $: testData = $automationStore.selectedAutomation.automation.testData + $: testData = $automationStore.selectedAutomation.automation.testData || {} + // Check the schema to see if required fields have been entered $: isError = !trigger.schema.outputs.required.every( required => testData[required] @@ -41,7 +45,6 @@ showConfirmButton={true} disabled={isError} onConfirm={() => { - automationStore.actions.addTestDataToAutomation(testData) automationStore.actions.test( $automationStore.selectedAutomation?.automation, testData @@ -53,7 +56,7 @@ >
{:else if value.customType === "webhookUrl"} - + onChange(e, key)} + value={inputData[key]} + /> {:else if value.customType === "triggerSchema"} onChange(e, key)} value={inputData[key]} /> {:else if value.customType === "code"} @@ -247,6 +266,10 @@
{/each} + + + + {#if stepId === "WEBHOOK"} {/if} diff --git a/packages/builder/src/components/automation/SetupPanel/RowSelector.svelte b/packages/builder/src/components/automation/SetupPanel/RowSelector.svelte index 1d54c86b4a..d1ab19761b 100644 --- a/packages/builder/src/components/automation/SetupPanel/RowSelector.svelte +++ b/packages/builder/src/components/automation/SetupPanel/RowSelector.svelte @@ -5,16 +5,29 @@ import AutomationBindingPanel from "../../common/bindings/ServerBindingPanel.svelte" import { createEventDispatcher } from "svelte" import ModalBindableInput from "components/common/bindings/ModalBindableInput.svelte" + import LinkedRowSelector from "components/common/LinkedRowSelector.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 ?? {}) + let table + let schemaFields + + $: { + table = $tables.list.find(table => table._id === value?.tableId) + schemaFields = Object.entries(table?.schema ?? {}) + // surface the schema so the user can see it in the json + schemaFields.map(([, schema]) => { + if (!schema.autocolumn && !value[schema.name]) { + value[schema.name] = "" + } + }) + } + const onChangeTable = e => { - value = { tableId: e.detail } + value["tableId"] = e.detail dispatch("change", value) } @@ -69,6 +82,8 @@ label={field} options={schema.constraints.inclusion} /> + {:else if schema.type === "link"} + {:else if schema.type === "string" || schema.type === "number"} {#if $automationStore.selectedAutomation.automation.testData} import { Icon } from "@budibase/bbui" import { automationStore } from "builderStore" - import { database } from "stores/backend" import WebhookDisplay from "./WebhookDisplay.svelte" import { ModalContent } from "@budibase/bbui" import { onMount, onDestroy } from "svelte" @@ -12,7 +11,6 @@ let schemaURL let propCount = 0 - $: instanceId = $database._id $: automation = $automationStore.selectedAutomation?.automation onMount(async () => { diff --git a/packages/builder/src/components/backend/DataTable/DataTable.svelte b/packages/builder/src/components/backend/DataTable/DataTable.svelte index 1cba1c31d9..f1d23e8f3d 100644 --- a/packages/builder/src/components/backend/DataTable/DataTable.svelte +++ b/packages/builder/src/components/backend/DataTable/DataTable.svelte @@ -16,11 +16,29 @@ import { Pagination } from "@budibase/bbui" let hideAutocolumns = true - + let schema $: isUsersTable = $tables.selected?._id === TableNames.USERS - $: schema = $tables.selected?.schema $: type = $tables.selected?.type $: isInternal = type !== "external" + $: { + schema = $tables.selected?.schema + + // Manually add these as we don't want them to be 'real' auto-columns + schema._id = { + type: "internal", + editable: false, + displayName: "ID", + autocolumn: true, + } + if (isInternal) { + schema._rev = { + type: "internal", + editable: false, + displayName: "Revision", + autocolumn: true, + } + } + } $: id = $tables.selected?._id $: search = searchTable(id) $: columnOptions = Object.keys($search.schema || {}) diff --git a/packages/server/src/automations/tests/automation.spec.js b/packages/server/src/automations/tests/automation.spec.js index 9444995ca1..b338b391c7 100644 --- a/packages/server/src/automations/tests/automation.spec.js +++ b/packages/server/src/automations/tests/automation.spec.js @@ -1,5 +1,12 @@ jest.mock("../../utilities/usageQuota") jest.mock("../thread") +jest.mock("../../utilities/redis", () => ({ + init: jest.fn(), + checkTestFlag: () => { + return false + }, +})) + jest.spyOn(global.console, "error") require("../../environment") diff --git a/packages/server/src/automations/triggerInfo/app.js b/packages/server/src/automations/triggerInfo/app.js index 40d1531fa0..b1b07e9d5b 100644 --- a/packages/server/src/automations/triggerInfo/app.js +++ b/packages/server/src/automations/triggerInfo/app.js @@ -22,6 +22,7 @@ exports.definition = { fields: { type: "object", description: "Fields submitted from the app frontend", + customType: "triggerSchema", }, }, required: ["fields"], diff --git a/packages/server/src/automations/triggers.js b/packages/server/src/automations/triggers.js index ae98f0e73a..e6c722ce3e 100644 --- a/packages/server/src/automations/triggers.js +++ b/packages/server/src/automations/triggers.js @@ -81,16 +81,20 @@ exports.externalTrigger = async function ( params, { getResponses } = {} ) { - if (automation.definition != null && automation.definition.trigger != null) { - if (automation.definition.trigger.stepId === "APP") { - // values are likely to be submitted as strings, so we shall convert to correct type - const coercedFields = {} - const fields = automation.definition.trigger.inputs.fields - for (let key of Object.keys(fields)) { - coercedFields[key] = coerce(params.fields[key], fields[key]) - } - params.fields = coercedFields + if ( + automation.definition != null && + automation.definition.trigger != null && + automation.definition.trigger.stepId === definitions.APP.stepId && + automation.definition.trigger.stepId === "APP" && + !checkTestFlag(automation._id) + ) { + // values are likely to be submitted as strings, so we shall convert to correct type + const coercedFields = {} + const fields = automation.definition.trigger.inputs.fields + for (let key of Object.keys(fields)) { + coercedFields[key] = coerce(params.fields[key], fields[key]) } + params.fields = coercedFields } const data = { automation, event: params } if (getResponses) {