diff --git a/packages/bbui/src/Tabs/Tab.svelte b/packages/bbui/src/Tabs/Tab.svelte index 3644280edf..86f2c0ee52 100644 --- a/packages/bbui/src/Tabs/Tab.svelte +++ b/packages/bbui/src/Tabs/Tab.svelte @@ -8,11 +8,19 @@ const selected = getContext("tab") let tab let tabInfo + const setTabInfo = () => { - tabInfo = tab.getBoundingClientRect() - if ($selected.title === title) { - $selected.info = tabInfo - } + // If the tabs are being rendered inside a component which uses + // a svelte transition to enter, then this initial getBoundingClientRect + // will return an incorrect position. + // We just need to get this off the main thread to fix this, by using + // a 0ms timeout. + setTimeout(() => { + tabInfo = tab.getBoundingClientRect() + if ($selected.title === title) { + $selected.info = tabInfo + } + }, 0) } onMount(() => { diff --git a/packages/builder/src/builderStore/dataBinding.js b/packages/builder/src/builderStore/dataBinding.js index dc1e40e517..3389e20d40 100644 --- a/packages/builder/src/builderStore/dataBinding.js +++ b/packages/builder/src/builderStore/dataBinding.js @@ -7,11 +7,17 @@ import { } from "./storeUtils" import { store } from "builderStore" import { queries as queriesStores, tables as tablesStore } from "stores/backend" -import { makePropSafe } from "@budibase/string-templates" +import { + makePropSafe, + isJSBinding, + decodeJSBinding, + encodeJSBinding, +} from "@budibase/string-templates" import { TableNames } from "../constants" // Regex to match all instances of template strings const CAPTURE_VAR_INSIDE_TEMPLATE = /{{([^}]+)}}/g +const CAPTURE_VAR_INSIDE_JS = /\$\("([^")]+)"\)/g const CAPTURE_HBS_TEMPLATE = /{{[\S\s]*?}}/g /** @@ -430,6 +436,15 @@ function replaceBetween(string, start, end, replacement) { * utility function for the readableToRuntimeBinding and runtimeToReadableBinding. */ function bindingReplacement(bindableProperties, textWithBindings, convertTo) { + // Decide from base64 if using JS + const isJS = isJSBinding(textWithBindings) + if (isJS) { + textWithBindings = decodeJSBinding(textWithBindings) + } + + // Determine correct regex to find bindings to replace + const regex = isJS ? CAPTURE_VAR_INSIDE_JS : CAPTURE_VAR_INSIDE_TEMPLATE + const convertFrom = convertTo === "runtimeBinding" ? "readableBinding" : "runtimeBinding" if (typeof textWithBindings !== "string") { @@ -441,7 +456,7 @@ function bindingReplacement(bindableProperties, textWithBindings, convertTo) { .sort((a, b) => { return b.length - a.length }) - const boundValues = textWithBindings.match(CAPTURE_VAR_INSIDE_TEMPLATE) || [] + const boundValues = textWithBindings.match(regex) || [] let result = textWithBindings for (let boundValue of boundValues) { let newBoundValue = boundValue @@ -449,7 +464,7 @@ function bindingReplacement(bindableProperties, textWithBindings, convertTo) { // in the search, working from longest to shortest so always use best match first let searchString = newBoundValue for (let from of convertFromProps) { - if (shouldReplaceBinding(newBoundValue, from, convertTo)) { + if (isJS || shouldReplaceBinding(newBoundValue, from, convertTo)) { const binding = bindableProperties.find(el => el[convertFrom] === from) let idx do { @@ -472,6 +487,12 @@ function bindingReplacement(bindableProperties, textWithBindings, convertTo) { } result = result.replace(boundValue, newBoundValue) } + + // Re-encode to base64 if using JS + if (isJS) { + result = encodeJSBinding(result) + } + return result } diff --git a/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte b/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte index 36c295b94e..a3a2870a5e 100644 --- a/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte +++ b/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte @@ -194,6 +194,7 @@ value={inputData[key]} on:change={e => onChange(e, key)} {bindings} + allowJS={false} /> {/if} {:else if value.customType === "query"} @@ -259,6 +260,7 @@ value={inputData[key]} on:change={e => onChange(e, key)} {bindings} + allowJS={false} /> {/if} diff --git a/packages/builder/src/components/automation/SetupPanel/QueryParamSelector.svelte b/packages/builder/src/components/automation/SetupPanel/QueryParamSelector.svelte index 91dc369d80..7a4bda3047 100644 --- a/packages/builder/src/components/automation/SetupPanel/QueryParamSelector.svelte +++ b/packages/builder/src/components/automation/SetupPanel/QueryParamSelector.svelte @@ -39,6 +39,7 @@ type="string" {bindings} fillWidth={true} + allowJS={false} /> {/each} diff --git a/packages/builder/src/components/automation/SetupPanel/RowSelector.svelte b/packages/builder/src/components/automation/SetupPanel/RowSelector.svelte index 479b4bd46c..fc812e0289 100644 --- a/packages/builder/src/components/automation/SetupPanel/RowSelector.svelte +++ b/packages/builder/src/components/automation/SetupPanel/RowSelector.svelte @@ -110,6 +110,7 @@ type="string" {bindings} fillWidth={true} + allowJS={false} /> {/if} {/if} diff --git a/packages/builder/src/components/common/CodeMirrorEditor.svelte b/packages/builder/src/components/common/CodeMirrorEditor.svelte new file mode 100644 index 0000000000..e99fed0d41 --- /dev/null +++ b/packages/builder/src/components/common/CodeMirrorEditor.svelte @@ -0,0 +1,159 @@ + + + + +{#if label} +
+ +
+{/if} +
+