Bug fixes for bindings panel and code editor
This commit is contained in:
parent
8e301902a3
commit
8a31cc2ff7
|
@ -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,12 @@
|
||||||
/>
|
/>
|
||||||
{:else if schema.type === "longform"}
|
{:else if schema.type === "longform"}
|
||||||
<TextArea
|
<TextArea
|
||||||
value={fieldData}
|
value={readableValue}
|
||||||
|
bindings={parsedBindings}
|
||||||
on:change={e =>
|
on:change={e =>
|
||||||
onChange({
|
onChange({
|
||||||
row: {
|
row: {
|
||||||
[field]: e.detail,
|
[field]: readableToRuntimeBinding(parsedBindings, e.detail),
|
||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
|
@ -144,11 +151,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>
|
||||||
|
|
|
@ -67,6 +67,10 @@
|
||||||
let targetMode = null
|
let targetMode = null
|
||||||
let expressionResult
|
let expressionResult
|
||||||
let evaluating = false
|
let evaluating = false
|
||||||
|
let mounted = false
|
||||||
|
|
||||||
|
// Value updates must be reprocessed to avoid timing issues
|
||||||
|
$: processUpdate(value, mounted)
|
||||||
|
|
||||||
$: useSnippets = allowSnippets && !$licensing.isFreePlan
|
$: useSnippets = allowSnippets && !$licensing.isFreePlan
|
||||||
$: editorModeOptions = getModeOptions(allowHBS, allowJS)
|
$: editorModeOptions = getModeOptions(allowHBS, allowJS)
|
||||||
|
@ -94,6 +98,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const processUpdate = value => {
|
||||||
|
if (!mounted) return
|
||||||
|
let isJS = value?.startsWith?.("{{ js ")
|
||||||
|
jsValue = isJS ? value : null
|
||||||
|
hbsValue = isJS ? null : value
|
||||||
|
}
|
||||||
|
|
||||||
const getHBSCompletions = bindingCompletions => {
|
const getHBSCompletions = bindingCompletions => {
|
||||||
return [
|
return [
|
||||||
hbAutocomplete([
|
hbAutocomplete([
|
||||||
|
@ -266,6 +277,8 @@
|
||||||
|
|
||||||
// Set the initial side panel
|
// Set the initial side panel
|
||||||
sidePanel = sidePanelOptions[0]
|
sidePanel = sidePanelOptions[0]
|
||||||
|
|
||||||
|
mounted = true
|
||||||
})
|
})
|
||||||
</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