Merge pull request #4390 from Budibase/feature/automation-data-types
Adding ability to toggle between Automation input types.
This commit is contained in:
commit
48d8aaea2a
|
@ -33,7 +33,7 @@ filterTests(['smoke', 'all'], () => {
|
||||||
cy.get(".spectrum-Button--cta").click()
|
cy.get(".spectrum-Button--cta").click()
|
||||||
})
|
})
|
||||||
cy.contains("Setup").click()
|
cy.contains("Setup").click()
|
||||||
cy.get(".spectrum-Picker-label").click()
|
cy.get(".spectrum-Picker-label").eq(1).click()
|
||||||
cy.contains("dog").click()
|
cy.contains("dog").click()
|
||||||
cy.get(".spectrum-Textfield-input")
|
cy.get(".spectrum-Textfield-input")
|
||||||
.first()
|
.first()
|
||||||
|
|
|
@ -57,6 +57,7 @@ const automationActions = store => ({
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
save: async automation => {
|
save: async automation => {
|
||||||
const response = await API.updateAutomation(automation)
|
const response = await API.updateAutomation(automation)
|
||||||
store.update(state => {
|
store.update(state => {
|
||||||
|
@ -130,6 +131,12 @@ const automationActions = store => ({
|
||||||
name: block.name,
|
name: block.name,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
toggleFieldControl: value => {
|
||||||
|
store.update(state => {
|
||||||
|
state.selectedBlock.rowControl = value
|
||||||
|
return state
|
||||||
|
})
|
||||||
|
},
|
||||||
deleteAutomationBlock: block => {
|
deleteAutomationBlock: block => {
|
||||||
store.update(state => {
|
store.update(state => {
|
||||||
const idx =
|
const idx =
|
||||||
|
|
|
@ -3,14 +3,8 @@
|
||||||
import Flowchart from "./FlowChart/FlowChart.svelte"
|
import Flowchart from "./FlowChart/FlowChart.svelte"
|
||||||
|
|
||||||
$: automation = $automationStore.selectedAutomation?.automation
|
$: automation = $automationStore.selectedAutomation?.automation
|
||||||
function onSelect(block) {
|
|
||||||
automationStore.update(state => {
|
|
||||||
state.selectedBlock = block
|
|
||||||
return state
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if automation}
|
{#if automation}
|
||||||
<Flowchart {automation} {onSelect} />
|
<Flowchart {automation} />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
|
|
||||||
export let automation
|
export let automation
|
||||||
export let onSelect
|
|
||||||
let testDataModal
|
let testDataModal
|
||||||
let blocks
|
let blocks
|
||||||
let confirmDeleteDialog
|
let confirmDeleteDialog
|
||||||
|
@ -45,7 +45,7 @@
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<div class="subtitle">
|
<div class="subtitle">
|
||||||
<Heading size="S">{automation.name}</Heading>
|
<Heading size="S">{automation.name}</Heading>
|
||||||
<div style="display:flex;">
|
<div style="display:flex; align-items: center;">
|
||||||
<div class="iconPadding">
|
<div class="iconPadding">
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<Icon
|
<Icon
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
animate:flip={{ duration: 500 }}
|
animate:flip={{ duration: 500 }}
|
||||||
in:fly|local={{ x: 500, duration: 1500 }}
|
in:fly|local={{ x: 500, duration: 1500 }}
|
||||||
>
|
>
|
||||||
<FlowItem {testDataModal} {onSelect} {block} />
|
<FlowItem {testDataModal} {block} />
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
Button,
|
Button,
|
||||||
StatusLight,
|
StatusLight,
|
||||||
ActionButton,
|
ActionButton,
|
||||||
|
Select,
|
||||||
notifications,
|
notifications,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import AutomationBlockSetup from "../../SetupPanel/AutomationBlockSetup.svelte"
|
import AutomationBlockSetup from "../../SetupPanel/AutomationBlockSetup.svelte"
|
||||||
|
@ -18,7 +19,6 @@
|
||||||
import ActionModal from "./ActionModal.svelte"
|
import ActionModal from "./ActionModal.svelte"
|
||||||
import { externalActions } from "./ExternalActions"
|
import { externalActions } from "./ExternalActions"
|
||||||
|
|
||||||
export let onSelect
|
|
||||||
export let block
|
export let block
|
||||||
export let testDataModal
|
export let testDataModal
|
||||||
let selected
|
let selected
|
||||||
|
@ -28,6 +28,10 @@
|
||||||
let setupToggled
|
let setupToggled
|
||||||
let blockComplete
|
let blockComplete
|
||||||
|
|
||||||
|
$: rowControl = $automationStore.selectedAutomation.automation.rowControl
|
||||||
|
$: showBindingPicker =
|
||||||
|
block.stepId === "CREATE_ROW" || block.stepId === "UPDATE_ROW"
|
||||||
|
|
||||||
$: testResult = $automationStore.selectedAutomation.testResults?.steps.filter(
|
$: testResult = $automationStore.selectedAutomation.testResults?.steps.filter(
|
||||||
step => (block.id ? step.id === block.id : step.stepId === block.stepId)
|
step => (block.id ? step.id === block.id : step.stepId === block.stepId)
|
||||||
)
|
)
|
||||||
|
@ -44,12 +48,6 @@
|
||||||
$automationStore.selectedAutomation?.automation?.definition?.steps.length +
|
$automationStore.selectedAutomation?.automation?.definition?.steps.length +
|
||||||
1
|
1
|
||||||
|
|
||||||
// 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(
|
$: hasCompletedInputs = Object.keys(
|
||||||
block.schema?.inputs?.properties || {}
|
block.schema?.inputs?.properties || {}
|
||||||
).every(x => block?.inputs[x])
|
).every(x => block?.inputs[x])
|
||||||
|
@ -64,6 +62,26 @@
|
||||||
notifications.error("Error saving notification")
|
notifications.error("Error saving notification")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function toggleFieldControl(evt) {
|
||||||
|
onSelect(block)
|
||||||
|
let rowControl
|
||||||
|
if (evt.detail === "Use values") {
|
||||||
|
rowControl = false
|
||||||
|
} else {
|
||||||
|
rowControl = true
|
||||||
|
}
|
||||||
|
automationStore.actions.toggleFieldControl(rowControl)
|
||||||
|
automationStore.actions.save(
|
||||||
|
$automationStore.selectedAutomation?.automation
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onSelect(block) {
|
||||||
|
await automationStore.update(state => {
|
||||||
|
state.selectedBlock = block
|
||||||
|
return state
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
@ -126,15 +144,33 @@
|
||||||
<Layout noPadding gap="S">
|
<Layout noPadding gap="S">
|
||||||
<div class="splitHeader">
|
<div class="splitHeader">
|
||||||
<ActionButton
|
<ActionButton
|
||||||
on:click={() => (setupToggled = !setupToggled)}
|
on:click={() => {
|
||||||
|
onSelect(block)
|
||||||
|
setupToggled = !setupToggled
|
||||||
|
}}
|
||||||
quiet
|
quiet
|
||||||
icon={setupToggled ? "ChevronDown" : "ChevronRight"}
|
icon={setupToggled ? "ChevronDown" : "ChevronRight"}
|
||||||
>
|
>
|
||||||
<Detail size="S">Setup</Detail>
|
<Detail size="S">Setup</Detail>
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
{#if !isTrigger}
|
{#if !isTrigger}
|
||||||
<div on:click={() => deleteStep()}>
|
<div class="block-options">
|
||||||
<Icon name="DeleteOutline" />
|
{#if showBindingPicker}
|
||||||
|
<div>
|
||||||
|
<Select
|
||||||
|
on:change={toggleFieldControl}
|
||||||
|
quiet
|
||||||
|
defaultValue="Use values"
|
||||||
|
autoWidth
|
||||||
|
value={rowControl ? "Use bindings" : "Use values"}
|
||||||
|
options={["Use values", "Use bindings"]}
|
||||||
|
placeholder={null}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
<div class="delete-padding" on:click={() => deleteStep()}>
|
||||||
|
<Icon name="DeleteOutline" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
@ -180,6 +216,13 @@
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.delete-padding {
|
||||||
|
padding-left: 30px;
|
||||||
|
}
|
||||||
|
.block-options {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
.center-items {
|
.center-items {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
@ -227,6 +227,7 @@
|
||||||
/>
|
/>
|
||||||
{:else if value.customType === "row"}
|
{:else if value.customType === "row"}
|
||||||
<RowSelector
|
<RowSelector
|
||||||
|
{block}
|
||||||
value={inputData[key]}
|
value={inputData[key]}
|
||||||
on:change={e => onChange(e, key)}
|
on:change={e => onChange(e, key)}
|
||||||
{bindings}
|
{bindings}
|
||||||
|
|
|
@ -1,26 +1,31 @@
|
||||||
<script>
|
<script>
|
||||||
import { tables } from "stores/backend"
|
import { tables } from "stores/backend"
|
||||||
import {
|
import { Select } from "@budibase/bbui"
|
||||||
Select,
|
|
||||||
Toggle,
|
|
||||||
DatePicker,
|
|
||||||
Multiselect,
|
|
||||||
TextArea,
|
|
||||||
} from "@budibase/bbui"
|
|
||||||
import DrawerBindableInput from "../../common/bindings/DrawerBindableInput.svelte"
|
import DrawerBindableInput from "../../common/bindings/DrawerBindableInput.svelte"
|
||||||
import AutomationBindingPanel from "../../common/bindings/ServerBindingPanel.svelte"
|
import AutomationBindingPanel from "../../common/bindings/ServerBindingPanel.svelte"
|
||||||
import { createEventDispatcher } from "svelte"
|
import { createEventDispatcher } from "svelte"
|
||||||
import ModalBindableInput from "components/common/bindings/ModalBindableInput.svelte"
|
|
||||||
import LinkedRowSelector from "components/common/LinkedRowSelector.svelte"
|
|
||||||
import { automationStore } from "builderStore"
|
import { automationStore } from "builderStore"
|
||||||
|
import RowSelectorTypes from "./RowSelectorTypes.svelte"
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
export let value
|
export let value
|
||||||
export let bindings
|
export let bindings
|
||||||
|
export let block
|
||||||
|
|
||||||
let table
|
let table
|
||||||
let schemaFields
|
let schemaFields
|
||||||
|
|
||||||
|
let placeholders = {
|
||||||
|
number: 10,
|
||||||
|
boolean: "true",
|
||||||
|
datetime: "2022-02-16T12:00:00.000Z ",
|
||||||
|
options: "1",
|
||||||
|
array: "1 2 3 4",
|
||||||
|
link: "ro_ta_123_456",
|
||||||
|
longform: "long form text",
|
||||||
|
}
|
||||||
|
$: rowControl = block.rowControl
|
||||||
$: {
|
$: {
|
||||||
table = $tables.list.find(table => table._id === value?.tableId)
|
table = $tables.list.find(table => table._id === value?.tableId)
|
||||||
schemaFields = Object.entries(table?.schema ?? {})
|
schemaFields = Object.entries(table?.schema ?? {})
|
||||||
|
@ -37,18 +42,48 @@
|
||||||
dispatch("change", value)
|
dispatch("change", value)
|
||||||
}
|
}
|
||||||
|
|
||||||
const onChange = (e, field) => {
|
const coerce = (value, type) => {
|
||||||
value[field] = e.detail
|
if (type === "boolean") {
|
||||||
|
if (typeof value === "boolean") {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
return value === "true"
|
||||||
|
}
|
||||||
|
if (type === "number") {
|
||||||
|
if (typeof value === "number") {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
return Number(value)
|
||||||
|
}
|
||||||
|
if (type === "options") {
|
||||||
|
return [value]
|
||||||
|
}
|
||||||
|
if (type === "array") {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
return value.split(",").map(x => x.trim())
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === "link") {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
return [value]
|
||||||
|
}
|
||||||
|
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
const onChange = (e, field, type) => {
|
||||||
|
value[field] = coerce(e.detail, type)
|
||||||
dispatch("change", value)
|
dispatch("change", value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure any nullish tableId values get set to empty string so
|
// Ensure any nullish tableId values get set to empty string so
|
||||||
// that the select works
|
// that the select works
|
||||||
$: if (value?.tableId == null) value = { tableId: "" }
|
$: if (value?.tableId == null) value = { tableId: "" }
|
||||||
|
|
||||||
function schemaHasOptions(schema) {
|
|
||||||
return !!schema.constraints?.inclusion?.length
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Select
|
<Select
|
||||||
|
@ -62,55 +97,46 @@
|
||||||
<div class="schema-fields">
|
<div class="schema-fields">
|
||||||
{#each schemaFields as [field, schema]}
|
{#each schemaFields as [field, schema]}
|
||||||
{#if !schema.autocolumn}
|
{#if !schema.autocolumn}
|
||||||
{#if schemaHasOptions(schema) && schema.type !== "array"}
|
{#if schema.type !== "attachment"}
|
||||||
<Select
|
|
||||||
on:change={e => onChange(e, field)}
|
|
||||||
label={field}
|
|
||||||
value={value[field]}
|
|
||||||
options={schema.constraints.inclusion}
|
|
||||||
/>
|
|
||||||
{:else if schema.type === "datetime"}
|
|
||||||
<DatePicker
|
|
||||||
label={field}
|
|
||||||
value={value[field]}
|
|
||||||
on:change={e => onChange(e, field)}
|
|
||||||
/>
|
|
||||||
{:else if schema.type === "boolean"}
|
|
||||||
<Toggle
|
|
||||||
text={field}
|
|
||||||
value={value[field]}
|
|
||||||
on:change={e => onChange(e, field)}
|
|
||||||
/>
|
|
||||||
{:else if schema.type === "array"}
|
|
||||||
<Multiselect
|
|
||||||
bind:value={value[field]}
|
|
||||||
label={field}
|
|
||||||
options={schema.constraints.inclusion}
|
|
||||||
/>
|
|
||||||
{:else if schema.type === "longform"}
|
|
||||||
<TextArea label={field} bind:value={value[field]} />
|
|
||||||
{:else if schema.type === "link"}
|
|
||||||
<LinkedRowSelector bind:linkedRows={value[field]} {schema} />
|
|
||||||
{:else if schema.type === "string" || schema.type === "number"}
|
|
||||||
{#if $automationStore.selectedAutomation.automation.testData}
|
{#if $automationStore.selectedAutomation.automation.testData}
|
||||||
<ModalBindableInput
|
{#if !rowControl}
|
||||||
value={value[field]}
|
<RowSelectorTypes
|
||||||
panel={AutomationBindingPanel}
|
{field}
|
||||||
label={field}
|
{schema}
|
||||||
type={value.customType}
|
{bindings}
|
||||||
on:change={e => onChange(e, field)}
|
{value}
|
||||||
{bindings}
|
{onChange}
|
||||||
/>
|
/>
|
||||||
|
{:else}
|
||||||
|
<DrawerBindableInput
|
||||||
|
placeholder={placeholders[schema.type]}
|
||||||
|
panel={AutomationBindingPanel}
|
||||||
|
value={Array.isArray(value[field])
|
||||||
|
? value[field].join(" ")
|
||||||
|
: value[field]}
|
||||||
|
on:change={e => onChange(e, field, schema.type)}
|
||||||
|
label={field}
|
||||||
|
type="string"
|
||||||
|
{bindings}
|
||||||
|
fillWidth={true}
|
||||||
|
allowJS={true}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
{:else if !rowControl}
|
||||||
|
<RowSelectorTypes {field} {schema} {bindings} {value} {onChange} />
|
||||||
{:else}
|
{:else}
|
||||||
<DrawerBindableInput
|
<DrawerBindableInput
|
||||||
|
placeholder={placeholders[schema.type]}
|
||||||
panel={AutomationBindingPanel}
|
panel={AutomationBindingPanel}
|
||||||
value={value[field]}
|
value={Array.isArray(value[field])
|
||||||
on:change={e => onChange(e, field)}
|
? value[field].join(" ")
|
||||||
|
: value[field]}
|
||||||
|
on:change={e => onChange(e, field, schema.type)}
|
||||||
label={field}
|
label={field}
|
||||||
type="string"
|
type="string"
|
||||||
{bindings}
|
{bindings}
|
||||||
fillWidth={true}
|
fillWidth={true}
|
||||||
allowJS={false}
|
allowJS={true}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
Toggle,
|
||||||
|
DatePicker,
|
||||||
|
Multiselect,
|
||||||
|
TextArea,
|
||||||
|
} from "@budibase/bbui"
|
||||||
|
import LinkedRowSelector from "components/common/LinkedRowSelector.svelte"
|
||||||
|
import DrawerBindableInput from "../../common/bindings/DrawerBindableInput.svelte"
|
||||||
|
import AutomationBindingPanel from "../../common/bindings/ServerBindingPanel.svelte"
|
||||||
|
|
||||||
|
export let onChange
|
||||||
|
export let field
|
||||||
|
export let schema
|
||||||
|
export let value
|
||||||
|
export let bindings
|
||||||
|
|
||||||
|
function schemaHasOptions(schema) {
|
||||||
|
return !!schema.constraints?.inclusion?.length
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if schemaHasOptions(schema) && schema.type !== "array"}
|
||||||
|
<Select
|
||||||
|
on:change={e => onChange(e, field)}
|
||||||
|
label={field}
|
||||||
|
value={value[field]}
|
||||||
|
options={schema.constraints.inclusion}
|
||||||
|
/>
|
||||||
|
{:else if schema.type === "datetime"}
|
||||||
|
<DatePicker
|
||||||
|
label={field}
|
||||||
|
value={value[field]}
|
||||||
|
on:change={e => onChange(e, field)}
|
||||||
|
/>
|
||||||
|
{:else if schema.type === "boolean"}
|
||||||
|
<Toggle
|
||||||
|
text={field}
|
||||||
|
value={value[field]}
|
||||||
|
on:change={e => onChange(e, field)}
|
||||||
|
/>
|
||||||
|
{:else if schema.type === "array"}
|
||||||
|
<Multiselect
|
||||||
|
bind:value={value[field]}
|
||||||
|
label={field}
|
||||||
|
options={schema.constraints.inclusion}
|
||||||
|
/>
|
||||||
|
{:else if schema.type === "longform"}
|
||||||
|
<TextArea label={field} bind:value={value[field]} />
|
||||||
|
{:else if schema.type === "link"}
|
||||||
|
<LinkedRowSelector bind:linkedRows={value[field]} {schema} />
|
||||||
|
{:else if schema.type === "string" || schema.type === "number"}
|
||||||
|
<DrawerBindableInput
|
||||||
|
panel={AutomationBindingPanel}
|
||||||
|
value={value[field]}
|
||||||
|
on:change={e => onChange(e, field)}
|
||||||
|
label={field}
|
||||||
|
type="string"
|
||||||
|
{bindings}
|
||||||
|
fillWidth={true}
|
||||||
|
allowJS={true}
|
||||||
|
/>
|
||||||
|
{/if}
|
Loading…
Reference in New Issue