forked from tsai/budibase
9 changed files with 292 additions and 13 deletions
@ -0,0 +1,113 @@ |
|||||
|
<script> |
||||
|
import { Input } from "@budibase/bbui" |
||||
|
|
||||
|
export let value = {} |
||||
|
$: fieldsArray = Object.entries(value).map(([name, type]) => ({ |
||||
|
name, |
||||
|
type, |
||||
|
})) |
||||
|
|
||||
|
let addNewName = "" |
||||
|
let addNewType = "string" |
||||
|
|
||||
|
function addField() { |
||||
|
if (!addNewName) return |
||||
|
if (value[addNewName.trim()]) { |
||||
|
addNewName = "" |
||||
|
return |
||||
|
} |
||||
|
const newValue = { ...value } |
||||
|
newValue[addNewName.trim()] = "string" |
||||
|
value = newValue |
||||
|
addNewName = "" |
||||
|
} |
||||
|
|
||||
|
function onInputEnter(e) { |
||||
|
if (e.key === "Enter") { |
||||
|
addField() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function removeField(name) { |
||||
|
const newValues = { ...value } |
||||
|
delete newValues[name] |
||||
|
value = newValues |
||||
|
} |
||||
|
|
||||
|
const fieldNameChanged = originalName => e => { |
||||
|
// reconstruct using fieldsArray, so field order is preserved |
||||
|
let entries = [...fieldsArray] |
||||
|
const newName = e.target.value |
||||
|
if (newName) { |
||||
|
entries.find(f => f.name === originalName).name = newName |
||||
|
} else { |
||||
|
entries = entries.filter(f => f.name !== originalName) |
||||
|
} |
||||
|
value = entries.reduce((newVals, current) => { |
||||
|
newVals[current.name] = current.type |
||||
|
return newVals |
||||
|
}, {}) |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<div class="root"> |
||||
|
{#each fieldsArray as field} |
||||
|
<i |
||||
|
class="remove-field ri-delete-bin-line" |
||||
|
on:click={() => removeField(field.name)} /> |
||||
|
<input |
||||
|
value={field.name} |
||||
|
on:change={fieldNameChanged(field.name)} |
||||
|
class="grid-field" /> |
||||
|
<select |
||||
|
value={field.type} |
||||
|
on:blur={e => (value[field.name] = e.target.value)} |
||||
|
class="grid-field"> |
||||
|
<option>string</option> |
||||
|
<option>number</option> |
||||
|
<option>boolean</option> |
||||
|
<option>datetime</option> |
||||
|
</select> |
||||
|
{/each} |
||||
|
<div class="new-field" on:keyup={onInputEnter}> |
||||
|
<Input |
||||
|
outline |
||||
|
small |
||||
|
bind:value={addNewName} |
||||
|
placeholder="Enter field name" /> |
||||
|
</div> |
||||
|
<!--button on:click={addField}>Add</button--> |
||||
|
</div> |
||||
|
|
||||
|
<style> |
||||
|
.root { |
||||
|
display: grid; |
||||
|
grid-template-columns: auto 1fr auto; |
||||
|
} |
||||
|
|
||||
|
.remove-field { |
||||
|
cursor: pointer; |
||||
|
color: var(--grey-6); |
||||
|
margin: auto 4px auto 0; |
||||
|
} |
||||
|
|
||||
|
.remove-field:hover { |
||||
|
color: var(--black); |
||||
|
} |
||||
|
|
||||
|
.new-field { |
||||
|
grid-column: 1 / span 3; |
||||
|
max-width: 100%; |
||||
|
} |
||||
|
|
||||
|
.grid-field { |
||||
|
min-width: 50px; |
||||
|
font-family: inherit; |
||||
|
font-size: inherit; |
||||
|
padding: 0.4em; |
||||
|
margin: 0 0 0.5em 0; |
||||
|
box-sizing: border-box; |
||||
|
border: 1px solid var(--grey-4); |
||||
|
border-radius: 0px; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,84 @@ |
|||||
|
<script> |
||||
|
import { Select, Label } from "@budibase/bbui" |
||||
|
import { automationStore } from "builderStore" |
||||
|
import SaveFields from "./SaveFields.svelte" |
||||
|
|
||||
|
// parameters.contextPath used in the client handler to determine which row to save |
||||
|
// this could be "data" or "data.parent", "data.parent.parent" etc |
||||
|
export let parameters |
||||
|
|
||||
|
let idFields |
||||
|
let schemaFields |
||||
|
|
||||
|
const automationSchema = automation => { |
||||
|
const schema = Object.entries( |
||||
|
automation.definition.trigger.inputs.fields |
||||
|
).map(([name, type]) => ({ name, type })) |
||||
|
|
||||
|
return { |
||||
|
name: automation.name, |
||||
|
_id: automation._id, |
||||
|
schema, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
$: automations = $automationStore.automations |
||||
|
.filter(a => a.definition.trigger && a.definition.trigger.stepId === "APP") |
||||
|
.map(automationSchema) |
||||
|
|
||||
|
$: selectedAutomation = |
||||
|
parameters && |
||||
|
parameters.automationId && |
||||
|
automations.find(a => a._id === parameters.automationId) |
||||
|
|
||||
|
const onFieldsChanged = e => { |
||||
|
parameters.fields = e.detail |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<div class="root"> |
||||
|
|
||||
|
{#if !automations || automations.length === 0} |
||||
|
<div class="cannot-use"> |
||||
|
You must have an automation that has an "App Action" trigger. |
||||
|
</div> |
||||
|
{:else} |
||||
|
<Label size="m" color="dark">Automation</Label> |
||||
|
<Select secondary bind:value={parameters.automationId}> |
||||
|
<option value="" /> |
||||
|
{#each automations as automation} |
||||
|
<option value={automation._id}>{automation.name}</option> |
||||
|
{/each} |
||||
|
</Select> |
||||
|
|
||||
|
{#if selectedAutomation} |
||||
|
<SaveFields |
||||
|
parameterFields={parameters.fields} |
||||
|
schemaFields={selectedAutomation.schema} |
||||
|
on:fieldschanged={onFieldsChanged} /> |
||||
|
{/if} |
||||
|
{/if} |
||||
|
</div> |
||||
|
|
||||
|
<style> |
||||
|
.root { |
||||
|
display: grid; |
||||
|
column-gap: var(--spacing-s); |
||||
|
row-gap: var(--spacing-s); |
||||
|
grid-template-columns: auto 1fr auto 1fr auto; |
||||
|
align-items: baseline; |
||||
|
} |
||||
|
|
||||
|
.root :global(> div:nth-child(2)) { |
||||
|
grid-column-start: 2; |
||||
|
grid-column-end: 6; |
||||
|
} |
||||
|
|
||||
|
.cannot-use { |
||||
|
color: var(--red); |
||||
|
font-size: var(--font-size-s); |
||||
|
text-align: center; |
||||
|
width: 70%; |
||||
|
margin: auto; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,10 @@ |
|||||
|
import API from "./api" |
||||
|
/** |
||||
|
* Executes an automation. Must have "App Action" trigger. |
||||
|
*/ |
||||
|
export const triggerAutomation = async (automationId, fields) => { |
||||
|
return await API.post({ |
||||
|
url: `/api/automations/${automationId}/trigger`, |
||||
|
body: { fields }, |
||||
|
}) |
||||
|
} |
||||
Loading…
Reference in new issue