From 84fb0dd9de5484583cfe9cd3c1f8b124de29fa86 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 6 Mar 2024 13:33:00 +0000 Subject: [PATCH] Add local state manipulation of snippets --- .../common/bindings/BindingPanel.svelte | 64 ++++++++++--- .../common/bindings/SnippetDrawer.svelte | 53 +++++++++++ .../common/bindings/SnippetSidePanel.svelte | 93 ++++++++++++------- .../builder/src/stores/builder/snippets.js | 9 +- packages/client/src/stores/derived/index.js | 1 + .../client/src/stores/derived/snippets.js | 6 ++ .../client/src/utils/enrichDataBinding.js | 26 ++---- 7 files changed, 177 insertions(+), 75 deletions(-) create mode 100644 packages/builder/src/components/common/bindings/SnippetDrawer.svelte create mode 100644 packages/client/src/stores/derived/snippets.js diff --git a/packages/builder/src/components/common/bindings/BindingPanel.svelte b/packages/builder/src/components/common/bindings/BindingPanel.svelte index 9efab620af..232aabc21c 100644 --- a/packages/builder/src/components/common/bindings/BindingPanel.svelte +++ b/packages/builder/src/components/common/bindings/BindingPanel.svelte @@ -34,15 +34,17 @@ const dispatch = createEventDispatcher() - export let bindings + export let bindings = [] export let value = "" - export let valid + export let valid = true + export let allowHBS = true export let allowJS = false export let allowHelpers = true export let allowSnippets = true export let context = null export let snippets = null export let autofocusEditor = false + export let placeholder = null const drawerContext = getContext("drawer") const Modes = { @@ -55,21 +57,26 @@ Snippets: "Code", } + let mode + let sidePanel let initialValueJS = value?.startsWith?.("{{ js ") - let mode = initialValueJS ? Modes.JavaScript : Modes.Text - let sidePanel = SidePanels.Bindings - let getCaretPosition - let insertAtPos let jsValue = initialValueJS ? value : null let hbsValue = initialValueJS ? null : value + let getCaretPosition + let insertAtPos let targetMode = null let expressionResult let drawerIsModal let evaluating = false $: drawerContext?.modal.subscribe(val => (drawerIsModal = val)) - $: editorModeOptions = allowJS ? [Modes.Text, Modes.JavaScript] : [Modes.Text] - $: sidePanelOptions = getSidePanelOptions(context, allowSnippets, mode) + $: editorModeOptions = getModeOptions(allowHBS, allowJS) + $: sidePanelOptions = getSidePanelOptions( + bindings, + context, + allowSnippets, + mode + ) $: enrichedBindings = enrichBindings(bindings, context, snippets) $: usingJS = mode === Modes.JavaScript $: editorMode = @@ -80,15 +87,30 @@ $: requestEval(runtimeExpression, context, snippets) $: bindingHelpers = new BindingHelpers(getCaretPosition, insertAtPos) $: { + // Ensure a valid side panel option is always selected if (!sidePanelOptions.includes(sidePanel)) { - sidePanel = SidePanels.Bindings + sidePanel = sidePanelOptions[0] } } - const getSidePanelOptions = (context, allowSnippets, mode) => { - let options = [SidePanels.Bindings] + const getModeOptions = (allowHBS, allowJS) => { + let options = [] + if (allowHBS) { + options.push(Modes.Text) + } + if (allowJS) { + options.push(Modes.JavaScript) + } + return options + } + + const getSidePanelOptions = (bindings, context, allowSnippets, mode) => { + let options = [] + if (bindings?.length) { + options.push(SidePanels.Bindings) + } if (context) { - options.unshift(SidePanels.Evaluation) + options.push(SidePanels.Evaluation) } if (allowSnippets && mode === Modes.JavaScript) { options.push(SidePanels.Snippets) @@ -197,6 +219,18 @@ } onMount(() => { + // Set the initial mode appropriately + const initialValueMode = initialValueJS ? Modes.JavaScript : Modes.Text + if (editorModeOptions.includes(initialValueMode)) { + mode = initialValueMode + } else { + mode = editorModeOptions[0] + } + + // Set the initial side panel + sidePanel = sidePanelOptions[0] + + // Determine if our initial value is valid valid = isValid(readableToRuntimeBinding(enrichedBindings, value)) }) @@ -254,7 +288,8 @@ ]), ]} autofocus={autofocusEditor} - placeholder="Add bindings by typing {{ or use the menu on the right" + placeholder={placeholder || + "Add bindings by typing {{ or use the menu on the right"} /> {:else if mode === Modes.JavaScript} {/if} {#if targetMode} diff --git a/packages/builder/src/components/common/bindings/SnippetDrawer.svelte b/packages/builder/src/components/common/bindings/SnippetDrawer.svelte new file mode 100644 index 0000000000..7e959053fa --- /dev/null +++ b/packages/builder/src/components/common/bindings/SnippetDrawer.svelte @@ -0,0 +1,53 @@ + + + + + {#if snippet} + + {/if} + + + + {#key key} + (code = e.detail)} + /> + {/key} + + diff --git a/packages/builder/src/components/common/bindings/SnippetSidePanel.svelte b/packages/builder/src/components/common/bindings/SnippetSidePanel.svelte index c1f3ca1531..592ca7cfcd 100644 --- a/packages/builder/src/components/common/bindings/SnippetSidePanel.svelte +++ b/packages/builder/src/components/common/bindings/SnippetSidePanel.svelte @@ -2,6 +2,7 @@ import { Input, Layout, Icon, Popover } from "@budibase/bbui" import CodeEditor from "components/common/CodeEditor/CodeEditor.svelte" import { EditorModes } from "components/common/CodeEditor" + import SnippetDrawer from "./SnippetDrawer.svelte" export let addSnippet export let snippets @@ -12,6 +13,8 @@ let popoverAnchor let hoveredSnippet let hideTimeout + let snippetDrawer + let editableSnippet $: filteredSnippets = getFilteredSnippets(snippets, search) @@ -60,9 +63,61 @@ search = "" } - const openSnippetModal = () => {} + const createSnippet = () => { + editableSnippet = null + snippetDrawer.show() + } + + const editSnippet = (e, snippet) => { + e.preventDefault() + e.stopPropagation() + editableSnippet = snippet + snippetDrawer.show() + } + + +
+ +
+ {#if searching} +
+ +
+ + {:else} +
Snippets
+ + + {/if} +
+
+ {#each filteredSnippets as snippet} +
showSnippet(snippet, e.target)} + on:mouseleave={hidePopover} + on:click={() => addSnippet(snippet)} + > + {snippet.name} + editSnippet(e, snippet)} + color="var(--spectrum-global-color-gray-700)" + /> +
+ {/each} +
+
+
+ -
- -
- {#if searching} -
- -
- - {:else} -
Snippets
- - - {/if} -
- -
- {#each filteredSnippets as snippet} -
showSnippet(snippet, e.target)} - on:mouseleave={hidePopover} - on:click={() => addSnippet(snippet)} - > - {snippet.name} -
- {/each} -
-
-
+