Fix/automation update deletes relationship (#9468)
* Add padding to text field input * Apply padding to modal binding input * Support relationships in automation bindings * Trim automation field keys * Trim automation field name * Empty string check * Add checkbox for clearing relationships update row * Added state for automation field metadata * clearRelationships updateRow check * Padding tweak
This commit is contained in:
parent
ce924d5990
commit
919323b500
7 changed files with 99 additions and 20 deletions
|
@ -72,8 +72,19 @@
|
||||||
$: schemaFields = Object.values(schema || {})
|
$: schemaFields = Object.values(schema || {})
|
||||||
$: queryLimit = tableId?.includes("datasource") ? "∞" : "1000"
|
$: queryLimit = tableId?.includes("datasource") ? "∞" : "1000"
|
||||||
$: isTrigger = block?.type === "TRIGGER"
|
$: isTrigger = block?.type === "TRIGGER"
|
||||||
|
$: isUpdateRow = stepId === ActionStepID.UPDATE_ROW
|
||||||
|
|
||||||
const onChange = Utils.sequential(async (e, key) => {
|
const onChange = Utils.sequential(async (e, key) => {
|
||||||
|
if (e.detail?.tableId) {
|
||||||
|
const tableSchema = getSchemaForTable(e.detail.tableId, {
|
||||||
|
searchableSchema: true,
|
||||||
|
}).schema
|
||||||
|
if (isTestModal) {
|
||||||
|
testData.schema = tableSchema
|
||||||
|
} else {
|
||||||
|
block.inputs.schema = tableSchema
|
||||||
|
}
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
if (isTestModal) {
|
if (isTestModal) {
|
||||||
// Special case for webhook, as it requires a body, but the schema already brings back the body's contents
|
// Special case for webhook, as it requires a body, but the schema already brings back the body's contents
|
||||||
|
@ -293,9 +304,17 @@
|
||||||
<RowSelector
|
<RowSelector
|
||||||
{block}
|
{block}
|
||||||
value={inputData[key]}
|
value={inputData[key]}
|
||||||
on:change={e => onChange(e, key)}
|
meta={inputData["meta"] || {}}
|
||||||
|
on:change={e => {
|
||||||
|
if (e.detail?.key) {
|
||||||
|
onChange(e, e.detail.key)
|
||||||
|
} else {
|
||||||
|
onChange(e, key)
|
||||||
|
}
|
||||||
|
}}
|
||||||
{bindings}
|
{bindings}
|
||||||
{isTestModal}
|
{isTestModal}
|
||||||
|
{isUpdateRow}
|
||||||
/>
|
/>
|
||||||
{:else if value.customType === "webhookUrl"}
|
{:else if value.customType === "webhookUrl"}
|
||||||
<WebhookDisplay
|
<WebhookDisplay
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { tables } from "stores/backend"
|
import { tables } from "stores/backend"
|
||||||
import { Select } from "@budibase/bbui"
|
import { Select, Checkbox } 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"
|
||||||
|
@ -10,9 +10,11 @@
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
export let value
|
export let value
|
||||||
|
export let meta
|
||||||
export let bindings
|
export let bindings
|
||||||
export let block
|
export let block
|
||||||
export let isTestModal
|
export let isTestModal
|
||||||
|
export let isUpdateRow
|
||||||
|
|
||||||
$: parsedBindings = bindings.map(binding => {
|
$: parsedBindings = bindings.map(binding => {
|
||||||
let clone = Object.assign({}, binding)
|
let clone = Object.assign({}, binding)
|
||||||
|
@ -97,6 +99,17 @@
|
||||||
dispatch("change", value)
|
dispatch("change", value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onChangeSetting = (e, field) => {
|
||||||
|
let fields = {}
|
||||||
|
fields[field] = {
|
||||||
|
clearRelationships: e.detail,
|
||||||
|
}
|
||||||
|
dispatch("change", {
|
||||||
|
key: "meta",
|
||||||
|
fields,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 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: "" }
|
||||||
|
@ -124,21 +137,33 @@
|
||||||
{onChange}
|
{onChange}
|
||||||
/>
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
<svelte:component
|
<div>
|
||||||
this={isTestModal ? ModalBindableInput : DrawerBindableInput}
|
<svelte:component
|
||||||
placeholder={placeholders[schema.type]}
|
this={isTestModal ? ModalBindableInput : DrawerBindableInput}
|
||||||
panel={AutomationBindingPanel}
|
placeholder={placeholders[schema.type]}
|
||||||
value={Array.isArray(value[field])
|
panel={AutomationBindingPanel}
|
||||||
? value[field].join(" ")
|
value={Array.isArray(value[field])
|
||||||
: value[field]}
|
? value[field].join(" ")
|
||||||
on:change={e => onChange(e, field, schema.type)}
|
: value[field]}
|
||||||
label={field}
|
on:change={e => onChange(e, field, schema.type)}
|
||||||
type="string"
|
label={field}
|
||||||
bindings={parsedBindings}
|
type="string"
|
||||||
fillWidth={true}
|
bindings={parsedBindings}
|
||||||
allowJS={true}
|
fillWidth={true}
|
||||||
updateOnChange={false}
|
allowJS={true}
|
||||||
/>
|
updateOnChange={false}
|
||||||
|
/>
|
||||||
|
{#if isUpdateRow && schema.type === "link"}
|
||||||
|
<div class="checkbox-field">
|
||||||
|
<Checkbox
|
||||||
|
value={meta.fields?.[field]?.clearRelationships}
|
||||||
|
text={"Clear relationships if empty?"}
|
||||||
|
size={"S"}
|
||||||
|
on:change={e => onChangeSetting(e, field)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -155,4 +180,12 @@
|
||||||
.schema-fields :global(label) {
|
.schema-fields :global(label) {
|
||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
}
|
}
|
||||||
|
.checkbox-field {
|
||||||
|
padding-bottom: var(--spacing-s);
|
||||||
|
padding-left: 1px;
|
||||||
|
padding-top: var(--spacing-s);
|
||||||
|
}
|
||||||
|
.checkbox-field :global(label) {
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -58,7 +58,7 @@
|
||||||
entries = entries.filter(f => f.name !== originalName)
|
entries = entries.filter(f => f.name !== originalName)
|
||||||
}
|
}
|
||||||
value = entries.reduce((newVals, current) => {
|
value = entries.reduce((newVals, current) => {
|
||||||
newVals[current.name] = current.type
|
newVals[current.name.trim()] = current.type
|
||||||
return newVals
|
return newVals
|
||||||
}, {})
|
}, {})
|
||||||
dispatch("change", value)
|
dispatch("change", value)
|
||||||
|
|
|
@ -106,4 +106,8 @@
|
||||||
border: var(--border-light);
|
border: var(--border-light);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.control :global(.spectrum-Textfield-input) {
|
||||||
|
padding-right: 40px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -36,7 +36,13 @@
|
||||||
$: selectedSchema = selectedAutomation?.schema
|
$: selectedSchema = selectedAutomation?.schema
|
||||||
|
|
||||||
const onFieldsChanged = e => {
|
const onFieldsChanged = e => {
|
||||||
parameters.fields = e.detail
|
parameters.fields = Object.entries(e.detail || {}).reduce(
|
||||||
|
(acc, [key, value]) => {
|
||||||
|
acc[key.trim()] = value
|
||||||
|
return acc
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const setNew = () => {
|
const setNew = () => {
|
||||||
|
|
|
@ -51,6 +51,16 @@ export function cleanInputValues(inputs: Record<string, any>, schema: any) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//Check if input field should be a relationship and cast to array
|
||||||
|
for (let key in inputs.row) {
|
||||||
|
if (
|
||||||
|
inputs.schema?.[key]?.type === "link" &&
|
||||||
|
inputs.row[key] &&
|
||||||
|
typeof inputs.row[key] === "string"
|
||||||
|
) {
|
||||||
|
inputs.row[key] = JSON.parse(inputs.row[key])
|
||||||
|
}
|
||||||
|
}
|
||||||
return inputs
|
return inputs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,10 @@ export const definition: AutomationStepSchema = {
|
||||||
schema: {
|
schema: {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
|
meta: {
|
||||||
|
type: "object",
|
||||||
|
title: "Field settings",
|
||||||
|
},
|
||||||
row: {
|
row: {
|
||||||
type: "object",
|
type: "object",
|
||||||
customType: "row",
|
customType: "row",
|
||||||
|
@ -73,7 +77,10 @@ export async function run({ inputs, appId, emitter }: AutomationStepInput) {
|
||||||
|
|
||||||
// clear any undefined, null or empty string properties so that they aren't updated
|
// clear any undefined, null or empty string properties so that they aren't updated
|
||||||
for (let propKey of Object.keys(inputs.row)) {
|
for (let propKey of Object.keys(inputs.row)) {
|
||||||
if (inputs.row[propKey] == null || inputs.row[propKey] === "") {
|
if (
|
||||||
|
(inputs.row[propKey] == null || inputs.row[propKey] === "") &&
|
||||||
|
!inputs.meta?.fields?.[propKey]?.clearRelationships
|
||||||
|
) {
|
||||||
delete inputs.row[propKey]
|
delete inputs.row[propKey]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue