Merge pull request #14370 from Budibase/dean-fixes
Binding Drawer and CodeEditor fixes
This commit is contained in:
commit
d7f00c981b
|
@ -70,6 +70,7 @@
|
||||||
|
|
||||||
// Stop unnecessary rendering
|
// Stop unnecessary rendering
|
||||||
const memoBlock = memo(block)
|
const memoBlock = memo(block)
|
||||||
|
const memoEnvVariables = memo($environment.variables)
|
||||||
|
|
||||||
const rowTriggers = [
|
const rowTriggers = [
|
||||||
TriggerStepID.ROW_UPDATED,
|
TriggerStepID.ROW_UPDATED,
|
||||||
|
@ -91,11 +92,20 @@
|
||||||
let insertAtPos, getCaretPosition
|
let insertAtPos, getCaretPosition
|
||||||
let stepLayouts = {}
|
let stepLayouts = {}
|
||||||
|
|
||||||
|
$: memoEnvVariables.set($environment.variables)
|
||||||
$: memoBlock.set(block)
|
$: memoBlock.set(block)
|
||||||
|
|
||||||
$: filters = lookForFilters(schemaProperties) || []
|
$: filters = lookForFilters(schemaProperties) || []
|
||||||
$: tempFilters = filters
|
$: tempFilters = filters
|
||||||
$: stepId = block.stepId
|
$: stepId = $memoBlock.stepId
|
||||||
$: bindings = getAvailableBindings(block, $selectedAutomation?.definition)
|
|
||||||
|
$: automationBindings = getAvailableBindings(
|
||||||
|
$memoBlock,
|
||||||
|
$selectedAutomation?.definition
|
||||||
|
)
|
||||||
|
$: environmentBindings = buildEnvironmentBindings($memoEnvVariables)
|
||||||
|
$: bindings = [...automationBindings, ...environmentBindings]
|
||||||
|
|
||||||
$: getInputData(testData, $memoBlock.inputs)
|
$: getInputData(testData, $memoBlock.inputs)
|
||||||
$: tableId = inputData ? inputData.tableId : null
|
$: tableId = inputData ? inputData.tableId : null
|
||||||
$: table = tableId
|
$: table = tableId
|
||||||
|
@ -110,7 +120,7 @@
|
||||||
{ allowLinks: true }
|
{ allowLinks: true }
|
||||||
)
|
)
|
||||||
$: queryLimit = tableId?.includes("datasource") ? "∞" : "1000"
|
$: queryLimit = tableId?.includes("datasource") ? "∞" : "1000"
|
||||||
$: isTrigger = block?.type === AutomationStepType.TRIGGER
|
$: isTrigger = $memoBlock?.type === AutomationStepType.TRIGGER
|
||||||
$: codeMode =
|
$: codeMode =
|
||||||
stepId === AutomationActionStepId.EXECUTE_BASH
|
stepId === AutomationActionStepId.EXECUTE_BASH
|
||||||
? EditorModes.Handlebars
|
? EditorModes.Handlebars
|
||||||
|
@ -119,13 +129,30 @@
|
||||||
disableWrapping: true,
|
disableWrapping: true,
|
||||||
})
|
})
|
||||||
$: editingJs = codeMode === EditorModes.JS
|
$: editingJs = codeMode === EditorModes.JS
|
||||||
$: requiredProperties = isTestModal ? [] : block.schema["inputs"].required
|
$: requiredProperties = isTestModal
|
||||||
|
? []
|
||||||
|
: $memoBlock.schema["inputs"].required
|
||||||
|
|
||||||
$: stepCompletions =
|
$: stepCompletions =
|
||||||
codeMode === EditorModes.Handlebars
|
codeMode === EditorModes.Handlebars
|
||||||
? [hbAutocomplete([...bindingsToCompletions(bindings, codeMode)])]
|
? [hbAutocomplete([...bindingsToCompletions(bindings, codeMode)])]
|
||||||
: []
|
: []
|
||||||
|
|
||||||
|
const buildEnvironmentBindings = () => {
|
||||||
|
if ($licensing.environmentVariablesEnabled) {
|
||||||
|
return getEnvironmentBindings().map(binding => {
|
||||||
|
return {
|
||||||
|
...binding,
|
||||||
|
display: {
|
||||||
|
...binding.display,
|
||||||
|
rank: 98,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
const getInputData = (testData, blockInputs) => {
|
const getInputData = (testData, blockInputs) => {
|
||||||
// Test data is not cloned for reactivity
|
// Test data is not cloned for reactivity
|
||||||
let newInputData = testData || cloneDeep(blockInputs)
|
let newInputData = testData || cloneDeep(blockInputs)
|
||||||
|
@ -151,9 +178,9 @@
|
||||||
|
|
||||||
// Store for any UX related data
|
// Store for any UX related data
|
||||||
const stepStore = writable({})
|
const stepStore = writable({})
|
||||||
$: currentStep = $stepStore?.[block.id]
|
$: stepState = $stepStore?.[block.id]
|
||||||
|
|
||||||
$: customStepLayouts($memoBlock, schemaProperties, currentStep)
|
$: customStepLayouts($memoBlock, schemaProperties, stepState)
|
||||||
|
|
||||||
const customStepLayouts = block => {
|
const customStepLayouts = block => {
|
||||||
if (
|
if (
|
||||||
|
@ -185,7 +212,6 @@
|
||||||
onChange: e => {
|
onChange: e => {
|
||||||
onChange({ ["revision"]: e.detail })
|
onChange({ ["revision"]: e.detail })
|
||||||
},
|
},
|
||||||
bindings,
|
|
||||||
updateOnChange: false,
|
updateOnChange: false,
|
||||||
forceModal: true,
|
forceModal: true,
|
||||||
},
|
},
|
||||||
|
@ -214,7 +240,6 @@
|
||||||
onChange: e => {
|
onChange: e => {
|
||||||
onChange({ [rowIdentifier]: e.detail })
|
onChange({ [rowIdentifier]: e.detail })
|
||||||
},
|
},
|
||||||
bindings,
|
|
||||||
updateOnChange: false,
|
updateOnChange: false,
|
||||||
forceModal: true,
|
forceModal: true,
|
||||||
},
|
},
|
||||||
|
@ -275,7 +300,7 @@
|
||||||
isUpdateRow: block.stepId === ActionStepID.UPDATE_ROW,
|
isUpdateRow: block.stepId === ActionStepID.UPDATE_ROW,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isTestModal && currentStep?.rowType === "oldRow") {
|
if (isTestModal && stepState?.rowType === "oldRow") {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
type: RowSelector,
|
type: RowSelector,
|
||||||
|
@ -722,22 +747,9 @@
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Environment bindings
|
|
||||||
if ($licensing.environmentVariablesEnabled) {
|
|
||||||
bindings = bindings.concat(
|
|
||||||
getEnvironmentBindings().map(binding => {
|
|
||||||
return {
|
|
||||||
...binding,
|
|
||||||
display: {
|
|
||||||
...binding.display,
|
|
||||||
rank: 98,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return bindings
|
return bindings
|
||||||
}
|
}
|
||||||
|
|
||||||
function lookForFilters(properties) {
|
function lookForFilters(properties) {
|
||||||
if (!properties) {
|
if (!properties) {
|
||||||
return []
|
return []
|
||||||
|
@ -770,7 +782,7 @@
|
||||||
drawer.hide()
|
drawer.hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
function canShowField(key, value) {
|
function canShowField(value) {
|
||||||
const dependsOn = value?.dependsOn
|
const dependsOn = value?.dependsOn
|
||||||
return !dependsOn || !!inputData[dependsOn]
|
return !dependsOn || !!inputData[dependsOn]
|
||||||
}
|
}
|
||||||
|
@ -829,6 +841,7 @@
|
||||||
<svelte:component
|
<svelte:component
|
||||||
this={config.type}
|
this={config.type}
|
||||||
{...config.props}
|
{...config.props}
|
||||||
|
{bindings}
|
||||||
on:change={config.props.onChange}
|
on:change={config.props.onChange}
|
||||||
/>
|
/>
|
||||||
</PropField>
|
</PropField>
|
||||||
|
@ -836,6 +849,7 @@
|
||||||
<svelte:component
|
<svelte:component
|
||||||
this={config.type}
|
this={config.type}
|
||||||
{...config.props}
|
{...config.props}
|
||||||
|
{bindings}
|
||||||
on:change={config.props.onChange}
|
on:change={config.props.onChange}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -13,6 +13,10 @@
|
||||||
import AutomationBindingPanel from "../../common/bindings/ServerBindingPanel.svelte"
|
import AutomationBindingPanel from "../../common/bindings/ServerBindingPanel.svelte"
|
||||||
import CodeEditor from "components/common/CodeEditor/CodeEditor.svelte"
|
import CodeEditor from "components/common/CodeEditor/CodeEditor.svelte"
|
||||||
import KeyValueBuilder from "components/integration/KeyValueBuilder.svelte"
|
import KeyValueBuilder from "components/integration/KeyValueBuilder.svelte"
|
||||||
|
import {
|
||||||
|
readableToRuntimeBinding,
|
||||||
|
runtimeToReadableBinding,
|
||||||
|
} from "dataBinding"
|
||||||
|
|
||||||
export let onChange
|
export let onChange
|
||||||
export let field
|
export let field
|
||||||
|
@ -30,6 +34,8 @@
|
||||||
return clone
|
return clone
|
||||||
})
|
})
|
||||||
|
|
||||||
|
$: readableValue = runtimeToReadableBinding(parsedBindings, fieldData)
|
||||||
|
|
||||||
let attachmentTypes = [
|
let attachmentTypes = [
|
||||||
FieldType.ATTACHMENTS,
|
FieldType.ATTACHMENTS,
|
||||||
FieldType.ATTACHMENT_SINGLE,
|
FieldType.ATTACHMENT_SINGLE,
|
||||||
|
@ -132,11 +138,11 @@
|
||||||
/>
|
/>
|
||||||
{:else if schema.type === "longform"}
|
{:else if schema.type === "longform"}
|
||||||
<TextArea
|
<TextArea
|
||||||
value={fieldData}
|
value={readableValue}
|
||||||
on:change={e =>
|
on:change={e =>
|
||||||
onChange({
|
onChange({
|
||||||
row: {
|
row: {
|
||||||
[field]: e.detail,
|
[field]: readableToRuntimeBinding(parsedBindings, e.detail),
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
|
@ -144,11 +150,11 @@
|
||||||
<span>
|
<span>
|
||||||
<div class="field-wrap json-field">
|
<div class="field-wrap json-field">
|
||||||
<CodeEditor
|
<CodeEditor
|
||||||
value={fieldData}
|
value={readableValue}
|
||||||
on:change={e => {
|
on:blur={e => {
|
||||||
onChange({
|
onChange({
|
||||||
row: {
|
row: {
|
||||||
[field]: e.detail,
|
[field]: readableToRuntimeBinding(parsedBindings, e.detail),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { Label } from "@budibase/bbui"
|
import { Label } from "@budibase/bbui"
|
||||||
import { onMount, createEventDispatcher } from "svelte"
|
import { onMount, createEventDispatcher, onDestroy } from "svelte"
|
||||||
import { FIND_ANY_HBS_REGEX } from "@budibase/string-templates"
|
import { FIND_ANY_HBS_REGEX } from "@budibase/string-templates"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -58,6 +58,64 @@
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
|
let textarea
|
||||||
|
let editor
|
||||||
|
let mounted = false
|
||||||
|
let isEditorInitialised = false
|
||||||
|
let queuedRefresh = false
|
||||||
|
|
||||||
|
// Theming!
|
||||||
|
let currentTheme = $themeStore?.theme
|
||||||
|
let isDark = !currentTheme.includes("light")
|
||||||
|
let themeConfig = new Compartment()
|
||||||
|
|
||||||
|
$: {
|
||||||
|
if (autofocus && isEditorInitialised) {
|
||||||
|
editor.focus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init when all elements are ready
|
||||||
|
$: if (mounted && !isEditorInitialised) {
|
||||||
|
isEditorInitialised = true
|
||||||
|
initEditor()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Theme change
|
||||||
|
$: if (mounted && isEditorInitialised && $themeStore?.theme) {
|
||||||
|
if (currentTheme != $themeStore?.theme) {
|
||||||
|
currentTheme = $themeStore?.theme
|
||||||
|
isDark = !currentTheme.includes("light")
|
||||||
|
|
||||||
|
// Issue theme compartment update
|
||||||
|
editor.dispatch({
|
||||||
|
effects: themeConfig.reconfigure([...(isDark ? [oneDark] : [])]),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait to try and gracefully replace
|
||||||
|
$: refresh(value, isEditorInitialised, mounted)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will refresh the editor contents only after
|
||||||
|
* it has been fully initialised
|
||||||
|
* @param value {string} the editor value
|
||||||
|
*/
|
||||||
|
const refresh = (value, initialised, mounted) => {
|
||||||
|
if (!initialised || !mounted) {
|
||||||
|
queuedRefresh = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (editor.state.doc.toString() !== value || queuedRefresh) {
|
||||||
|
editor.dispatch({
|
||||||
|
changes: { from: 0, to: editor.state.doc.length, insert: value },
|
||||||
|
})
|
||||||
|
queuedRefresh = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Export a function to expose caret position
|
// Export a function to expose caret position
|
||||||
export const getCaretPosition = () => {
|
export const getCaretPosition = () => {
|
||||||
const selection_range = editor.state.selection.ranges[0]
|
const selection_range = editor.state.selection.ranges[0]
|
||||||
|
@ -132,11 +190,6 @@
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Theming!
|
|
||||||
let currentTheme = $themeStore?.theme
|
|
||||||
let isDark = !currentTheme.includes("light")
|
|
||||||
let themeConfig = new Compartment()
|
|
||||||
|
|
||||||
const indentWithTabCustom = {
|
const indentWithTabCustom = {
|
||||||
key: "Tab",
|
key: "Tab",
|
||||||
run: view => {
|
run: view => {
|
||||||
|
@ -253,6 +306,11 @@
|
||||||
lineNumbers(),
|
lineNumbers(),
|
||||||
foldGutter(),
|
foldGutter(),
|
||||||
keymap.of(buildKeymap()),
|
keymap.of(buildKeymap()),
|
||||||
|
EditorView.domEventHandlers({
|
||||||
|
blur: () => {
|
||||||
|
dispatch("blur", editor.state.doc.toString())
|
||||||
|
},
|
||||||
|
}),
|
||||||
EditorView.updateListener.of(v => {
|
EditorView.updateListener.of(v => {
|
||||||
const docStr = v.state.doc?.toString()
|
const docStr = v.state.doc?.toString()
|
||||||
if (docStr === value) {
|
if (docStr === value) {
|
||||||
|
@ -266,11 +324,6 @@
|
||||||
return complete
|
return complete
|
||||||
}
|
}
|
||||||
|
|
||||||
let textarea
|
|
||||||
let editor
|
|
||||||
let mounted = false
|
|
||||||
let isEditorInitialised = false
|
|
||||||
|
|
||||||
const initEditor = () => {
|
const initEditor = () => {
|
||||||
const baseExtensions = buildBaseExtensions()
|
const baseExtensions = buildBaseExtensions()
|
||||||
|
|
||||||
|
@ -281,37 +334,13 @@
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
$: {
|
|
||||||
if (autofocus && isEditorInitialised) {
|
|
||||||
editor.focus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init when all elements are ready
|
|
||||||
$: if (mounted && !isEditorInitialised) {
|
|
||||||
isEditorInitialised = true
|
|
||||||
initEditor()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Theme change
|
|
||||||
$: if (mounted && isEditorInitialised && $themeStore?.theme) {
|
|
||||||
if (currentTheme != $themeStore?.theme) {
|
|
||||||
currentTheme = $themeStore?.theme
|
|
||||||
isDark = !currentTheme.includes("light")
|
|
||||||
|
|
||||||
// Issue theme compartment update
|
|
||||||
editor.dispatch({
|
|
||||||
effects: themeConfig.reconfigure([...(isDark ? [oneDark] : [])]),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
mounted = true
|
mounted = true
|
||||||
return () => {
|
})
|
||||||
if (editor) {
|
|
||||||
editor.destroy()
|
onDestroy(() => {
|
||||||
}
|
if (editor) {
|
||||||
|
editor.destroy()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
export let allowJS = true
|
export let allowJS = true
|
||||||
export let allowHelpers = true
|
export let allowHelpers = true
|
||||||
export let updateOnChange = true
|
export let updateOnChange = true
|
||||||
export let drawerLeft
|
|
||||||
export let type
|
export let type
|
||||||
export let schema
|
export let schema
|
||||||
|
|
||||||
|
@ -170,14 +169,7 @@
|
||||||
<Icon disabled={isJS} size="S" name="Close" />
|
<Icon disabled={isJS} size="S" name="Close" />
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<slot
|
<slot />
|
||||||
{label}
|
|
||||||
{disabled}
|
|
||||||
readonly={isJS}
|
|
||||||
value={isJS ? "(JavaScript function)" : readableValue}
|
|
||||||
{placeholder}
|
|
||||||
{updateOnChange}
|
|
||||||
/>
|
|
||||||
{/if}
|
{/if}
|
||||||
{#if !disabled && type !== "formula" && !disabled && !attachmentTypes.includes(type)}
|
{#if !disabled && type !== "formula" && !disabled && !attachmentTypes.includes(type)}
|
||||||
<div
|
<div
|
||||||
|
@ -195,7 +187,7 @@
|
||||||
on:drawerShow
|
on:drawerShow
|
||||||
bind:this={bindingDrawer}
|
bind:this={bindingDrawer}
|
||||||
title={title ?? placeholder ?? "Bindings"}
|
title={title ?? placeholder ?? "Bindings"}
|
||||||
left={drawerLeft}
|
forceModal={true}
|
||||||
>
|
>
|
||||||
<Button cta slot="buttons" on:click={saveBinding}>Save</Button>
|
<Button cta slot="buttons" on:click={saveBinding}>Save</Button>
|
||||||
<svelte:component
|
<svelte:component
|
||||||
|
|
Loading…
Reference in New Issue