Merge branch 'contextual-workflows' of github.com:Budibase/budibase into contextual-workflows
This commit is contained in:
commit
d2edf5ba62
|
@ -21,17 +21,25 @@ context("Create a workflow", () => {
|
||||||
// Add trigger
|
// Add trigger
|
||||||
cy.get("[data-cy=add-workflow-component]").click()
|
cy.get("[data-cy=add-workflow-component]").click()
|
||||||
cy.get("[data-cy=RECORD_SAVED]").click()
|
cy.get("[data-cy=RECORD_SAVED]").click()
|
||||||
cy.get(".budibase__input").select("dog")
|
cy.get("[data-cy=workflow-block-setup]").within(() => {
|
||||||
|
cy.get("select")
|
||||||
|
.first()
|
||||||
|
.select("dog")
|
||||||
|
})
|
||||||
|
|
||||||
// Create action
|
// Create action
|
||||||
cy.get("[data-cy=SAVE_RECORD]").click()
|
cy.get("[data-cy=SAVE_RECORD]").click()
|
||||||
cy.get(".budibase__input").select("dog")
|
cy.get("[data-cy=workflow-block-setup]").within(() => {
|
||||||
cy.get(".container input")
|
cy.get("select")
|
||||||
.first()
|
.first()
|
||||||
.type("goodboy")
|
.select("dog")
|
||||||
cy.get(".container input")
|
cy.get("input")
|
||||||
.eq(1)
|
.first()
|
||||||
.type("11")
|
.type("goodboy")
|
||||||
|
cy.get("input")
|
||||||
|
.eq(1)
|
||||||
|
.type("11")
|
||||||
|
})
|
||||||
|
|
||||||
// Save
|
// Save
|
||||||
cy.contains("Save Workflow").click()
|
cy.contains("Save Workflow").click()
|
||||||
|
@ -44,7 +52,6 @@ context("Create a workflow", () => {
|
||||||
|
|
||||||
it("should add record when a new record is added", () => {
|
it("should add record when a new record is added", () => {
|
||||||
cy.contains("backend").click()
|
cy.contains("backend").click()
|
||||||
|
|
||||||
cy.addRecord(["Rover", 15])
|
cy.addRecord(["Rover", 15])
|
||||||
cy.reload()
|
cy.reload()
|
||||||
cy.contains("goodboy").should("have.text", "goodboy")
|
cy.contains("goodboy").should("have.text", "goodboy")
|
||||||
|
|
|
@ -12,17 +12,6 @@
|
||||||
// Ensure any nullish modelId values get set to empty string so
|
// Ensure any nullish modelId values get set to empty string so
|
||||||
// that the select works
|
// that the select works
|
||||||
$: if (value?.modelId == null) value = { modelId: "" }
|
$: if (value?.modelId == null) value = { modelId: "" }
|
||||||
|
|
||||||
function setParsedValue(evt, field) {
|
|
||||||
const fieldSchema = model?.schema[field]
|
|
||||||
if (fieldSchema) {
|
|
||||||
if (fieldSchema.type === "number") {
|
|
||||||
value[field] = parseInt(evt.target.value)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
value[field] = evt.target.value
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="block-field">
|
<div class="block-field">
|
||||||
|
@ -49,12 +38,12 @@
|
||||||
<option value={option}>{option}</option>
|
<option value={option}>{option}</option>
|
||||||
{/each}
|
{/each}
|
||||||
</Select>
|
</Select>
|
||||||
{:else}
|
{:else if schema.type === "string"}
|
||||||
<BindableInput
|
<BindableInput
|
||||||
thin
|
thin
|
||||||
bind:value={value[field]}
|
bind:value={value[field]}
|
||||||
on:change={e => setParsedValue(e, field)}
|
|
||||||
label={field}
|
label={field}
|
||||||
|
type={schema.type}
|
||||||
{bindings} />
|
{bindings} />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container" data-cy="workflow-block-setup">
|
||||||
<div class="block-label">{block.name}</div>
|
<div class="block-label">{block.name}</div>
|
||||||
{#each inputs as [key, value]}
|
{#each inputs as [key, value]}
|
||||||
<div class="bb-margin-xl block-field">
|
<div class="bb-margin-xl block-field">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import { workflowStore, backendUiStore } from "builderStore"
|
import { workflowStore } from "builderStore"
|
||||||
import WorkflowBlockTagline from "./WorkflowBlockTagline.svelte"
|
import WorkflowBlockTagline from "./WorkflowBlockTagline.svelte"
|
||||||
|
|
||||||
export let onSelect
|
export let onSelect
|
||||||
|
@ -9,29 +9,12 @@
|
||||||
$: selected = $workflowStore.selectedBlock?.id === block.id
|
$: selected = $workflowStore.selectedBlock?.id === block.id
|
||||||
$: steps = $workflowStore.selectedWorkflow?.workflow?.definition?.steps ?? []
|
$: steps = $workflowStore.selectedWorkflow?.workflow?.definition?.steps ?? []
|
||||||
$: blockIdx = steps.findIndex(step => step.id === block.id)
|
$: blockIdx = steps.findIndex(step => step.id === block.id)
|
||||||
|
|
||||||
function selectBlock() {
|
|
||||||
onSelect(block)
|
|
||||||
}
|
|
||||||
|
|
||||||
function enrichInputs(inputs) {
|
|
||||||
let enrichedInputs = { ...inputs, enriched: {} }
|
|
||||||
const modelId = inputs.modelId || inputs.record?.modelId
|
|
||||||
if (modelId) {
|
|
||||||
enrichedInputs.enriched.model = $backendUiStore.models.find(
|
|
||||||
model => model._id === modelId
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return enrichedInputs
|
|
||||||
}
|
|
||||||
|
|
||||||
$: inputs = enrichInputs(block.inputs)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={`block ${block.type} hoverable`}
|
class={`block ${block.type} hoverable`}
|
||||||
class:selected
|
class:selected
|
||||||
on:click={selectBlock}>
|
on:click={() => onSelect(block)}>
|
||||||
<header>
|
<header>
|
||||||
{#if block.type === 'TRIGGER'}
|
{#if block.type === 'TRIGGER'}
|
||||||
<i class="ri-lightbulb-fill" />
|
<i class="ri-lightbulb-fill" />
|
||||||
|
@ -49,13 +32,13 @@
|
||||||
</header>
|
</header>
|
||||||
<hr />
|
<hr />
|
||||||
<p>
|
<p>
|
||||||
<WorkflowBlockTagline tagline={block.tagline} {inputs} />
|
<WorkflowBlockTagline {block} />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.block {
|
.block {
|
||||||
width: 320px;
|
width: 360px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
border-radius: var(--border-radius-m);
|
border-radius: var(--border-radius-m);
|
||||||
transition: 0.3s all ease;
|
transition: 0.3s all ease;
|
||||||
|
|
|
@ -1,19 +1,61 @@
|
||||||
<script>
|
<script>
|
||||||
import mustache from "mustache"
|
import mustache from "mustache"
|
||||||
|
import { get } from "lodash/fp"
|
||||||
|
import { backendUiStore } from "builderStore"
|
||||||
|
|
||||||
export let tagline
|
export let block
|
||||||
export let inputs
|
|
||||||
|
|
||||||
// Add bolt tags around inputs
|
$: inputs = enrichInputs(block.inputs)
|
||||||
$: boldTagline = tagline.replace(/{{/g, "<b>{{").replace(/}}/, "}}</b>")
|
$: tagline = formatTagline(block.tagline, block.schema, inputs)
|
||||||
|
$: html = (tagline || "")
|
||||||
|
.replace(/{{\s*/g, "<span>")
|
||||||
|
.replace(/\s*}}/g, "</span>")
|
||||||
|
|
||||||
// Fill in inputs with mustache
|
function enrichInputs(inputs) {
|
||||||
$: parsedTagline = mustache.render(boldTagline, { inputs })
|
let enrichedInputs = { ...inputs, enriched: {} }
|
||||||
|
const modelId = inputs.modelId || inputs.record?.modelId
|
||||||
|
if (modelId) {
|
||||||
|
enrichedInputs.enriched.model = $backendUiStore.models.find(
|
||||||
|
model => model._id === modelId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return enrichedInputs
|
||||||
|
}
|
||||||
|
|
||||||
// Wrap bound fields inside spans to highlight them
|
function formatTagline(tagline, schema, inputs) {
|
||||||
$: html = (parsedTagline || "")
|
// Add bold tags around inputs
|
||||||
.replace(/{{\s/g, "<span>")
|
let formattedTagline = tagline
|
||||||
.replace(/\s}}/g, "</span>")
|
.replace(/{{/g, "<b>{{")
|
||||||
|
.replace(/}}/, "}}</b>")
|
||||||
|
|
||||||
|
// Extract schema paths for any input bindings
|
||||||
|
const inputPaths = formattedTagline
|
||||||
|
.match(/{{\s*\S+\s*}}/g)
|
||||||
|
.map(x => x.replace(/[{}]/g, "").trim())
|
||||||
|
const schemaPaths = inputPaths.map(x => x.replace(/\./g, ".properties."))
|
||||||
|
|
||||||
|
// Replace any enum bindings with their pretty equivalents
|
||||||
|
schemaPaths.forEach((path, idx) => {
|
||||||
|
const prettyValues = get(`${path}.pretty`, schema)
|
||||||
|
if (prettyValues) {
|
||||||
|
const enumValues = get(`${path}.enum`, schema)
|
||||||
|
const inputPath = inputPaths[idx]
|
||||||
|
const value = get(inputPath, { inputs })
|
||||||
|
const valueIdx = enumValues.indexOf(value)
|
||||||
|
const prettyValue = prettyValues[valueIdx]
|
||||||
|
if (prettyValue == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
formattedTagline = formattedTagline.replace(
|
||||||
|
new RegExp(`{{\s*${inputPath}\s*}}`),
|
||||||
|
prettyValue
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Fill in bindings with mustache
|
||||||
|
return mustache.render(formattedTagline, { inputs })
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
@ -21,10 +63,15 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
div {
|
||||||
|
line-height: 1.25;
|
||||||
|
}
|
||||||
div :global(span) {
|
div :global(span) {
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
background-color: var(--purple-light);
|
background-color: var(--purple-light);
|
||||||
padding: var(--spacing-xs);
|
padding: var(--spacing-xs);
|
||||||
border-radius: var(--border-radius-m);
|
border-radius: var(--border-radius-m);
|
||||||
|
display: inline-block;
|
||||||
|
margin: 1px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue