Bug fixes for bindings panel and code editor

This commit is contained in:
Dean 2024-08-13 11:07:00 +01:00
parent 8e301902a3
commit 8a31cc2ff7
4 changed files with 96 additions and 55 deletions

View File

@ -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),
}, },
}) })
}} }}

View File

@ -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>

View File

@ -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>

View File

@ -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