diff --git a/packages/bbui/src/Actions/position_dropdown.js b/packages/bbui/src/Actions/position_dropdown.js index 2cb681670b..01555446d9 100644 --- a/packages/bbui/src/Actions/position_dropdown.js +++ b/packages/bbui/src/Actions/position_dropdown.js @@ -56,6 +56,8 @@ export default function positionDropdown(element, opts) { styles.left = anchorBounds.left + anchorBounds.width - elementBounds.width } else if (align === "right-outside") { styles.left = anchorBounds.right + offset + } else if (align === "left-outside") { + styles.left = anchorBounds.left - elementBounds.width - offset } else { styles.left = anchorBounds.left } diff --git a/packages/bbui/src/Drawer/Drawer.svelte b/packages/bbui/src/Drawer/Drawer.svelte index cd3fb0ccc0..18ac15dffa 100644 --- a/packages/bbui/src/Drawer/Drawer.svelte +++ b/packages/bbui/src/Drawer/Drawer.svelte @@ -21,7 +21,6 @@ } export function hide() { - console.log("CLOSE") if (!visible) { return } diff --git a/packages/bbui/src/Tabs/Tabs.svelte b/packages/bbui/src/Tabs/Tabs.svelte index 7184aedbaf..4cc22b226e 100644 --- a/packages/bbui/src/Tabs/Tabs.svelte +++ b/packages/bbui/src/Tabs/Tabs.svelte @@ -12,6 +12,7 @@ export let emphasized = false export let onTop = false export let size = "M" + export let beforeSwitch = null let thisSelected = undefined @@ -28,9 +29,14 @@ thisSelected = selected dispatch("select", thisSelected) } else if ($tab.title !== thisSelected) { - thisSelected = $tab.title - selected = $tab.title - dispatch("select", thisSelected) + if (typeof beforeSwitch == "function") { + const proceed = beforeSwitch($tab.title) + if (proceed) { + thisSelected = $tab.title + selected = $tab.title + dispatch("select", thisSelected) + } + } } if ($tab.title !== thisSelected) { tab.update(state => { diff --git a/packages/builder/src/builderStore/dataBinding.js b/packages/builder/src/builderStore/dataBinding.js index 467534284d..d6bc358d39 100644 --- a/packages/builder/src/builderStore/dataBinding.js +++ b/packages/builder/src/builderStore/dataBinding.js @@ -519,7 +519,7 @@ export const makeStateBinding = key => { readableBinding: `State.${key}`, category: "State", icon: "AutomatedSegment", - display: { name: key }, //no type + display: { name: key }, } } diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index e264dc099b..0da194dbec 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -69,6 +69,7 @@ const INITIAL_FRONTEND_STATE = { customTheme: {}, previewDevice: "desktop", highlightedSettingKey: null, + propertyFocus: null, builderSidePanel: false, // URL params @@ -1319,6 +1320,12 @@ export const getFrontendStore = () => { highlightedSettingKey: key, })) }, + propertyFocus: key => { + store.update(state => ({ + ...state, + propertyFocus: key, + })) + }, }, dnd: { start: component => { diff --git a/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte b/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte index 00a573c519..cd0aa1197f 100644 --- a/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte +++ b/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte @@ -37,7 +37,6 @@ import { TriggerStepID, ActionStepID } from "constants/backend/automations" import { onMount } from "svelte" import { cloneDeep } from "lodash/fp" - import CodeEditor from "components/common/CodeEditor/CodeEditor.svelte" export let block export let testData @@ -235,18 +234,19 @@ ? `steps[${idx - loopBlockCount}].${name}` : `steps.${idx - loopBlockCount}.${name}` const runtime = idx === 0 ? `trigger.${name}` : runtimeName + const categoryName = + idx === 0 + ? "Trigger outputs" + : isLoopBlock + ? "Loop Outputs" + : `Step ${idx - loopBlockCount} outputs` return { readableBinding: runtime, runtimeBinding: runtime, type: value.type, description: value.description, icon: bindingIcon, - category: - idx === 0 - ? "Trigger outputs" - : isLoopBlock - ? "Loop Outputs" - : `Step ${idx - loopBlockCount} outputs`, + category: categoryName, display: { type: value.type, name: name, diff --git a/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte b/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte index b355fe0537..c9f048db38 100644 --- a/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte +++ b/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte @@ -69,13 +69,15 @@ to: opts.end || editor.state.doc.length, insert: opts.value, }, - selection: { - anchor: opts.start + opts.value.length, - }, + selection: opts.cursor + ? { + anchor: opts.start + opts.value.length, + } + : undefined, }) } - // For handlebars only. Demo + // For handlebars only. const bindStyle = new MatchDecorator({ regexp: /{{[.\[\]\"#-\w\s\/]*}}/g, decoration: match => { @@ -117,7 +119,7 @@ ...completionKeymap, indentWithTab, ] - return buildKeymap + return baseMap } const buildBaseExtensions = () => { @@ -167,8 +169,6 @@ complete.push(foldGutter()) complete.push( EditorView.inputHandler.of((view, from, to, insert) => { - console.log({ view, from, to, insert }) - if (insert === "$") { let { text } = view.state.doc.lineAt(from) diff --git a/packages/builder/src/components/common/CodeEditor/index.js b/packages/builder/src/components/common/CodeEditor/index.js index 7f37a94881..cffeeeae0f 100644 --- a/packages/builder/src/components/common/CodeEditor/index.js +++ b/packages/builder/src/components/common/CodeEditor/index.js @@ -1,26 +1,14 @@ import { EditorView } from "@codemirror/view" -// import { insertCompletionText } from "@codemirror/autocomplete" import { getManifest } from "@budibase/string-templates" import sanitizeHtml from "sanitize-html" import { groupBy } from "lodash" -// Really just Javascript and Text export const EditorModes = { JS: { name: "javascript", json: false, match: /\$$/, }, - JSON: { - name: "javascript", - json: true, - }, - XML: { - name: "xml", - }, - SQL: { - name: "sql", - }, Handlebars: { name: "handlebars", base: "text/html", @@ -31,7 +19,6 @@ export const EditorModes = { }, } -// Get a generalised approach to constants in the dataBindings file? export const SECTIONS = { HB_HELPER: { name: "Helper", @@ -108,7 +95,7 @@ export const getDefaultTheme = opts => { color: "var(--ink)", }, "& .binding-wrap": { - color: "chartreuse", + color: "var(--spectrum-global-color-blue-700)", }, }, { dark } @@ -209,20 +196,15 @@ export const jsAutocomplete = baseCompletions => { let jsBinding = context.matchBefore(/\$\(\"[\s\w]*/) let options = baseCompletions || [] - if (!jsBinding) { - console.log("leaving") + if (jsBinding) { return { - from: context.pos, + from: jsBinding.from + 3, filter: true, options, } } - return { - from: jsBinding.from + 3, - filter: true, - options, - } + return null } return coreCompletion @@ -305,30 +287,27 @@ export const insertBinding = (view, from, to, text, mode) => { } export const bindingsToCompletions = (bindings, mode) => { - // REFACTOR OUT const bindingByCategory = groupBy(bindings, "category") - const categoryToIcon = bindings?.reduce((acc, ele) => { - if (ele.icon) { - acc[ele.category] = acc[ele.category] || ele.icon - } - return acc - }, {}) + const categoryMeta = bindings?.reduce((acc, ele) => { + acc[ele.category] = acc[ele.category] || {} - // REFACTOR OUT - const categoryToRank = bindings?.reduce((acc, ele) => { if (ele.icon) { - acc[ele.category] = acc[ele.category] || ele.display.rank + acc[ele.category]["icon"] = acc[ele.category]["icon"] || ele.icon + } + if (ele.display?.rank) { + acc[ele.category]["rank"] = acc[ele.category]["rank"] || ele.display.rank } return acc }, {}) const completions = Object.keys(bindingByCategory).reduce((comps, catKey) => { - // REFACTOR OUT + const { icon, rank } = categoryMeta[catKey] || {} + const bindindSectionHeader = buildSectionHeader( bindingByCategory.type, catKey, - categoryToIcon[catKey] || "", - categoryToRank[catKey] || 1 + icon || "", + typeof rank == "number" ? rank : 1 ) return [ diff --git a/packages/builder/src/components/common/bindings/BindingPanel.svelte b/packages/builder/src/components/common/bindings/BindingPanel.svelte index 3d4293767c..dfd116fe35 100644 --- a/packages/builder/src/components/common/bindings/BindingPanel.svelte +++ b/packages/builder/src/components/common/bindings/BindingPanel.svelte @@ -1,17 +1,13 @@ - -
- - -
-
- - -
+ + +
+ { + if (selectedMode == mode) { + return true + } - {#if sidebar} -
- -
- {/if} -
- - {#if allowJS} - + //Get the current mode value + const currentEditorValue = mode === "JavaScript" ? jsValue : hbsValue + if (currentEditorValue) { + targetMode = selectedMode + return false + } + return true + }} + > +
- - - JavaScript expressions are executed as functions, so ensure that - your expression returns a value. - +
+ {#if targetMode} +
+
+ + {`Switch to ${targetMode}?`} + + This will discard anything in your text +
+ + +
+
+
+ {/if} + +
+
{#if sidebar} @@ -270,32 +255,130 @@ {/if}
- {/if} -
- - -
- -
- + {#if allowJS} + +
+
+
+ {#if targetMode} +
+
+ + {`Switch to ${targetMode}?`} + + This will discard anything in your text +
+ + +
+
+
+ {/if} + + +
+ +
+ + {#if sidebar} +
+ +
+ {/if} +
+
+ {/if} +
+ + +
+
+
+
+ diff --git a/packages/builder/src/components/common/bindings/BindingPicker.svelte b/packages/builder/src/components/common/bindings/BindingPicker.svelte index 655d7ae991..1f4d5cd894 100644 --- a/packages/builder/src/components/common/bindings/BindingPicker.svelte +++ b/packages/builder/src/components/common/bindings/BindingPicker.svelte @@ -45,7 +45,6 @@ (!selectedCategory ? true : selectedCategory === category.name) ) }) - $: console.log(filteredCategories) $: filteredHelpers = helpers?.filter(helper => { return helper.label.match(searchRgx) || helper.description.match(searchRgx) }) diff --git a/packages/builder/src/components/common/bindings/DrawerBindableInput.svelte b/packages/builder/src/components/common/bindings/DrawerBindableInput.svelte index d664a9043d..f41b66bd77 100644 --- a/packages/builder/src/components/common/bindings/DrawerBindableInput.svelte +++ b/packages/builder/src/components/common/bindings/DrawerBindableInput.svelte @@ -4,6 +4,9 @@ readableToRuntimeBinding, runtimeToReadableBinding, } from "builderStore/dataBinding" + + import { store } from "builderStore" + import ClientBindingPanel from "components/common/bindings/ClientBindingPanel.svelte" import { createEventDispatcher, setContext } from "svelte" import { isJSBinding } from "@budibase/string-templates" @@ -20,6 +23,7 @@ export let allowHelpers = true export let updateOnChange = true export let drawerLeft + export let key const dispatch = createEventDispatcher() let bindingDrawer @@ -32,6 +36,7 @@ const saveBinding = () => { onChange(tempValue) + store.actions.settings.propertyFocus(null) onBlur() bindingDrawer.hide() } @@ -62,7 +67,13 @@ {updateOnChange} /> {#if !disabled} -
+
{ + store.actions.settings.propertyFocus(key) + bindingDrawer.show() + }} + >
{/if} diff --git a/packages/builder/src/components/design/settings/controls/PropertyControl.svelte b/packages/builder/src/components/design/settings/controls/PropertyControl.svelte index 30a05d4c6e..daa3f29592 100644 --- a/packages/builder/src/components/design/settings/controls/PropertyControl.svelte +++ b/packages/builder/src/components/design/settings/controls/PropertyControl.svelte @@ -21,6 +21,7 @@ export let componentBindings = [] export let nested = false export let highlighted = false + export let propertyFocus = false export let info = null $: nullishValue = value == null || value === "" @@ -72,6 +73,10 @@ if (highlighted) { store.actions.settings.highlight(null) } + // To fix focus 'affect' when property is target of a drawer other actions in the builder. + if (propertyFocus) { + store.actions.settings.propertyFocus(null) + } }) @@ -79,6 +84,7 @@ class="property-control" class:wide={!label || labelHidden} class:highlighted={highlighted && nullishValue} + class:property-focus={propertyFocus} > {#if label && !labelHidden}
@@ -125,6 +131,14 @@ background: var(--spectrum-global-color-gray-300); border-color: var(--spectrum-global-color-static-red-600); } + + .property-control.property-focus :global(input) { + border-color: var( + --spectrum-textfield-m-border-color-down, + var(--spectrum-alias-border-color-mouse-focus) + ); + } + .label { margin-top: 16px; transform: translateY(-50%); diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentKeyHandler.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentKeyHandler.svelte index 220c7c9015..e1b85b6f3f 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentKeyHandler.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentKeyHandler.svelte @@ -107,7 +107,6 @@ (inCodeEditor || ["input", "textarea"].indexOf(activeTag) !== -1) && e.key !== "Escape" ) { - console.log("KEY PRESS") return } // Key events are always for the selected component diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/ComponentSettingsSection.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/ComponentSettingsSection.svelte index 8fa0af45ed..78eecea76e 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/ComponentSettingsSection.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/ComponentSettingsSection.svelte @@ -140,6 +140,7 @@ nested={setting.nested} onChange={val => updateSetting(setting, val)} highlighted={$store.highlightedSettingKey === setting.key} + propertyFocus={$store.propertyFocus === setting.key} info={setting.info} props={{ // Generic settings