From ee07aaa01dc25481247a8ae4539333c43f5ee8c8 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 2 Mar 2022 09:06:31 +0000 Subject: [PATCH 01/72] Don't set explicit height of tables when total row count is equal or less than the desired rows, to avoid tiny overflow due to horizontal scrollbars --- packages/bbui/src/Table/Table.svelte | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/packages/bbui/src/Table/Table.svelte b/packages/bbui/src/Table/Table.svelte index c9d7f12339..1d957b3f30 100644 --- a/packages/bbui/src/Table/Table.svelte +++ b/packages/bbui/src/Table/Table.svelte @@ -56,6 +56,7 @@ $: if (!loading) loaded = true $: fields = getFields(schema, showAutoColumns, autoSortColumns) $: rows = fields?.length ? data || [] : [] + $: totalRowCount = rows?.length || 0 $: visibleRowCount = getVisibleRowCount( loaded, height, @@ -63,7 +64,12 @@ rowCount, rowHeight ) - $: contentStyle = getContentStyle(visibleRowCount, rowCount, rowHeight) + $: heightStyle = getHeightStyle( + visibleRowCount, + rowCount, + totalRowCount, + rowHeight + ) $: sortedRows = sortRows(rows, sortColumn, sortOrder) $: gridStyle = getGridStyle(fields, schema, showEditColumn) $: showEditColumn = allowEditRows || allowSelectRows @@ -107,11 +113,16 @@ return Math.min(allRows, Math.ceil(height / rowHeight)) } - const getContentStyle = (visibleRows, rowCount, rowHeight) => { - if (!rowCount || !visibleRows) { + const getHeightStyle = ( + visibleRowCount, + rowCount, + totalRowCount, + rowHeight + ) => { + if (!rowCount || !visibleRowCount || totalRowCount <= rowCount) { return "" } - return `height: ${headerHeight + visibleRows * rowHeight}px;` + return `height: ${headerHeight + visibleRowCount * rowHeight}px;` } const getGridStyle = (fields, schema, showEditColumn) => { @@ -264,11 +275,11 @@ style={`--row-height: ${rowHeight}px; --header-height: ${headerHeight}px;`} > {#if !loaded} -
+
{:else} -
+
{#if fields.length}
{#if showEditColumn} From e411354538c2098e9e86954680fdb661724d6e3c Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 2 Mar 2022 17:45:01 +0000 Subject: [PATCH 02/72] Improve copy and paste to support keeping all data bindings valid --- .../src/builderStore/componentUtils.js | 61 +++++++++++++++++++ .../src/builderStore/store/frontend.js | 23 ++----- .../ComponentDropdownMenu.svelte | 6 +- packages/string-templates/src/index.cjs | 1 + packages/string-templates/src/index.js | 9 +++ packages/string-templates/src/index.mjs | 1 + 6 files changed, 79 insertions(+), 22 deletions(-) diff --git a/packages/builder/src/builderStore/componentUtils.js b/packages/builder/src/builderStore/componentUtils.js index 04a87998fe..557d83a00c 100644 --- a/packages/builder/src/builderStore/componentUtils.js +++ b/packages/builder/src/builderStore/componentUtils.js @@ -1,4 +1,10 @@ import { store } from "./index" +import { Helpers } from "@budibase/bbui" +import { + decodeJSBinding, + encodeJSBinding, + findAllBindings, +} from "@budibase/string-templates" /** * Recursively searches for a specific component ID @@ -161,3 +167,58 @@ export const getComponentSettings = componentType => { return settings } + +/** + * Randomises a components ID's, including all child component IDs, and also + * updates all data bindings to still be valid. + * This mutates the object in place. + * @param component the component to randomise + */ +export const makeComponentUnique = component => { + if (!component) { + return + } + + // Replace component ID + const oldId = component._id + const newId = Helpers.uuid() + component._id = newId + + if (component._children?.length) { + let children = JSON.stringify(component._children) + + // Replace all instances of this ID in child HBS bindings + children = children.replace(new RegExp(oldId, "g"), newId) + + // Replace all instances of this ID in child JS bindings + const bindings = findAllBindings(children) + bindings.forEach(binding => { + // JSON.stringify will have escaped double quotes, so we need + // to account for that + let sanitizedBinding = binding.replace(/\\"/g, '"') + + // Check if this is a valid JS binding + let js = decodeJSBinding(sanitizedBinding) + if (js != null) { + // Replace ID inside JS binding + js = js.replace(new RegExp(oldId, "g"), newId) + + // Create new valid JS binding + let newBinding = encodeJSBinding(js) + + // Replace escaped double quotes + newBinding = newBinding.replace(/"/g, '\\"') + + // Insert new JS back into binding. + // A single string replace here is better than a regex as + // the binding contains special characters, and we only need + // to replace a single instance. + children = children.replace(binding, newBinding) + } + }) + + // Recurse on all children + component._children = JSON.parse(children) + component._children.forEach(makeComponentUnique) + } +} diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index d8118c9c60..c8e4c85b06 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -24,9 +24,9 @@ import { findAllMatchingComponents, findComponent, getComponentSettings, + makeComponentUnique, } from "../componentUtils" import { Helpers } from "@budibase/bbui" -import { removeBindings } from "../dataBinding" const INITIAL_FRONTEND_STATE = { apps: [], @@ -490,37 +490,22 @@ export const getFrontendStore = () => { } } }, - paste: async (targetComponent, mode, preserveBindings = false) => { + paste: async (targetComponent, mode) => { let promises = [] store.update(state => { // Stop if we have nothing to paste if (!state.componentToPaste) { return state } - - // defines if this is a copy or a cut const cut = state.componentToPaste.isCut - // immediately need to remove bindings, currently these aren't valid when pasted - if (!cut && !preserveBindings) { - state.componentToPaste = removeBindings(state.componentToPaste, "") - } - - // Clone the component to paste - // Retain the same ID if cutting as things may be referencing this component + // Clone the component to paste and make unique if copying delete state.componentToPaste.isCut let componentToPaste = cloneDeep(state.componentToPaste) if (cut) { state.componentToPaste = null } else { - const randomizeIds = component => { - if (!component) { - return - } - component._id = Helpers.uuid() - component._children?.forEach(randomizeIds) - } - randomizeIds(componentToPaste) + makeComponentUnique(componentToPaste) } if (mode === "inside") { diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte index 0fcd43b58e..c8796fab25 100644 --- a/packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte @@ -61,7 +61,7 @@ const duplicateComponent = () => { storeComponentForCopy(false) - pasteComponent("below", true) + pasteComponent("below") } const deleteComponent = async () => { @@ -77,10 +77,10 @@ store.actions.components.copy(component, cut) } - const pasteComponent = (mode, preserveBindings = false) => { + const pasteComponent = mode => { try { // lives in store - also used by drag drop - store.actions.components.paste(component, mode, preserveBindings) + store.actions.components.paste(component, mode) } catch (error) { notifications.error("Error saving component") } diff --git a/packages/string-templates/src/index.cjs b/packages/string-templates/src/index.cjs index 5a84c45d78..9584374880 100644 --- a/packages/string-templates/src/index.cjs +++ b/packages/string-templates/src/index.cjs @@ -18,6 +18,7 @@ module.exports.processObject = templates.processObject module.exports.doesContainStrings = templates.doesContainStrings module.exports.doesContainString = templates.doesContainString module.exports.disableEscaping = templates.disableEscaping +module.exports.findAllBindings = templates.findAllBindings /** * Use vm2 to run JS scripts in a node env diff --git a/packages/string-templates/src/index.js b/packages/string-templates/src/index.js index eedd9423ee..76ad979670 100644 --- a/packages/string-templates/src/index.js +++ b/packages/string-templates/src/index.js @@ -322,3 +322,12 @@ module.exports.doesContainStrings = (template, strings) => { module.exports.doesContainString = (template, string) => { return exports.doesContainStrings(template, [string]) } + +/** + * Finds all regular (double bracketed) expressions inside a string. + * @param string the string to search + * @return {[]} all matching bindings + */ +module.exports.findAllBindings = string => { + return findDoubleHbsInstances(string) +} diff --git a/packages/string-templates/src/index.mjs b/packages/string-templates/src/index.mjs index f2cffdf378..a9745b3a34 100644 --- a/packages/string-templates/src/index.mjs +++ b/packages/string-templates/src/index.mjs @@ -18,6 +18,7 @@ export const processObject = templates.processObject export const doesContainStrings = templates.doesContainStrings export const doesContainString = templates.doesContainString export const disableEscaping = templates.disableEscaping +export const findAllBindings = templates.findAllBindings /** * Use polyfilled vm to run JS scripts in a browser Env From f2fbd3d1d0bb930c70f79c99f92718a65437eb46 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 2 Mar 2022 19:10:18 +0000 Subject: [PATCH 03/72] Rewrite screen wizard to make modals reusable and fix some edge case URL bugs --- .../store/screenTemplates/index.js | 7 +- .../ComponentDropdownMenu.svelte | 2 - .../ScreenDropdownMenu.svelte | 5 + .../NavigationPanel/NewScreenModal.svelte | 48 ++--- .../NavigationPanel/ScreenDetailsModal.svelte | 43 ++-- .../NavigationPanel/ScreenWizard.svelte | 200 +++++++++--------- 6 files changed, 143 insertions(+), 162 deletions(-) diff --git a/packages/builder/src/builderStore/store/screenTemplates/index.js b/packages/builder/src/builderStore/store/screenTemplates/index.js index 38ae434753..51496bdeb3 100644 --- a/packages/builder/src/builderStore/store/screenTemplates/index.js +++ b/packages/builder/src/builderStore/store/screenTemplates/index.js @@ -10,17 +10,18 @@ const allTemplates = tables => [ ] // Allows us to apply common behaviour to all create() functions -const createTemplateOverride = (frontendState, create) => () => { - const screen = create() +const createTemplateOverride = (frontendState, template) => () => { + const screen = template.create() screen.name = screen.props._id screen.routing.route = screen.routing.route.toLowerCase() + screen.template = template.id return screen } export default (frontendState, tables) => { const enrichTemplate = template => ({ ...template, - create: createTemplateOverride(frontendState, template.create), + create: createTemplateOverride(frontendState, template), }) const fromScratch = enrichTemplate(createFromScratchScreen) diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte index c8796fab25..df6be7e88f 100644 --- a/packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte @@ -73,13 +73,11 @@ } const storeComponentForCopy = (cut = false) => { - // lives in store - also used by drag drop store.actions.components.copy(component, cut) } const pasteComponent = mode => { try { - // lives in store - also used by drag drop store.actions.components.paste(component, mode) } catch (error) { notifications.error("Error saving component") diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte index 38ed79649e..47c9fb65b1 100644 --- a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte @@ -10,6 +10,8 @@ $: screen = $allScreens.find(screen => screen._id === screenId) + const duplicateScreen = () => {} + const deleteScreen = async () => { try { await store.actions.screens.delete(screen) @@ -25,6 +27,9 @@
+ + Duplicate + Delete diff --git a/packages/builder/src/components/design/NavigationPanel/NewScreenModal.svelte b/packages/builder/src/components/design/NavigationPanel/NewScreenModal.svelte index c48ba33efa..cd83d81235 100644 --- a/packages/builder/src/components/design/NavigationPanel/NewScreenModal.svelte +++ b/packages/builder/src/components/design/NavigationPanel/NewScreenModal.svelte @@ -10,39 +10,19 @@ ProgressCircle, } from "@budibase/bbui" import getTemplates from "builderStore/store/screenTemplates" - import { onDestroy } from "svelte" - import { createEventDispatcher } from "svelte" - - export let chooseModal - export let save + export let onConfirm + export let onCancel export let showProgressCircle = false - let selectedScreens = [] - const blankScreen = "createFromScratch" - const dispatch = createEventDispatcher() - function setScreens() { - dispatch("save", { - screens: selectedScreens, - }) - } + let selectedScreens = [] + let templates = getTemplates($store, $tables.list) $: blankSelected = selectedScreens?.length === 1 $: autoSelected = selectedScreens?.length > 0 && !blankSelected - let templates = getTemplates($store, $tables.list) - - const confirm = async () => { - if (autoSelected) { - setScreens() - await save() - } else { - setScreens() - chooseModal(1) - } - } const toggleScreenSelection = table => { if (selectedScreens.find(s => s.table === table.name)) { selectedScreens = selectedScreens.filter( @@ -56,25 +36,25 @@ } } - onDestroy(() => { - selectedScreens = [] - }) + const confirmScreenSelection = async () => { + await onConfirm(selectedScreens) + }
confirm()} + onConfirm={confirmScreenSelection} + {onCancel} disabled={!selectedScreens.length} size="L" > - Please select the screens you would like to add to your application. - Autogenerated screens come with CRUD functionality. - + + Please select the screens you would like to add to your application. + Autogenerated screens come with CRUD functionality. + Blank screen
{ if (!event.detail.startsWith("/")) { - url = "/" + event.detail + screenUrl = "/" + event.detail } - url = sanitizeUrl(url) - - if (routeExists(url, roleId)) { + screenUrl = sanitizeUrl(screenUrl) + if (routeExists(screenUrl)) { routeError = "This URL is already taken for this access role" } else { - routeError = "" + routeError = null } } - const routeExists = (url, roleId) => { - return $allScreens.some( + const routeExists = url => { + const roleId = get(selectedAccessRole) || "BASIC" + return get(allScreens).some( screen => screen.routing.route.toLowerCase() === url.toLowerCase() && screen.routing.roleId === roleId ) } - onDestroy(() => { - screenName = "" - url = "" - }) + const confirmScreenDetails = async () => { + await onConfirm({ + screenName, + screenUrl, + }) + } chooseModal(0)} - onConfirm={() => save()} + onConfirm={confirmScreenDetails} + {onCancel} cancelText={"Back"} - disabled={!screenName || !url || routeError} + disabled={!screenName || !screenUrl || routeError} >
diff --git a/packages/builder/src/components/design/NavigationPanel/ScreenWizard.svelte b/packages/builder/src/components/design/NavigationPanel/ScreenWizard.svelte index 144592035c..fd37490c53 100644 --- a/packages/builder/src/components/design/NavigationPanel/ScreenWizard.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ScreenWizard.svelte @@ -3,141 +3,137 @@ import NewScreenModal from "components/design/NavigationPanel/NewScreenModal.svelte" import sanitizeUrl from "builderStore/store/screenTemplates/utils/sanitizeUrl" import { Modal, notifications } from "@budibase/bbui" - import { store, selectedAccessRole, allScreens } from "builderStore" + import { store, selectedAccessRole } from "builderStore" import analytics, { Events } from "analytics" + import { get } from "svelte/store" - let newScreenModal - let navigationSelectionModal - let screenDetailsModal - let screenName = "" - let url = "" - let selectedScreens = [] + let pendingScreen let showProgressCircle = false - let routeError - let createdScreens = [] - $: roleId = $selectedAccessRole || "BASIC" + // Modal refs + let newScreenModal + let screenDetailsModal - const createScreens = async () => { - for (let screen of selectedScreens) { - let test = screen.create() - createdScreens.push(test) - analytics.captureEvent(Events.SCREEN.CREATED, { - template: screen.id || screen.name, - }) - } - } + // External handler to show the screen wizard + export const showModal = () => { + newScreenModal.show() - const save = async () => { - showProgressCircle = true - try { - await createScreens() - for (let screen of createdScreens) { - await saveScreens(screen) - } - await store.actions.routing.fetch() - selectedScreens = [] - createdScreens = [] - screenName = "" - url = "" - } catch (error) { - notifications.error("Error creating screens") - } + // Reset state when showing modal again + pendingScreen = null showProgressCircle = false } - const saveScreens = async draftScreen => { - let existingScreenCount = $store.screens.filter( - s => s.props._instanceName == draftScreen.props._instanceName - ).length - if (existingScreenCount > 0) { - let oldUrlArr = draftScreen.routing.route.split("/") - oldUrlArr[1] = `${oldUrlArr[1]}-${existingScreenCount + 1}` - draftScreen.routing.route = oldUrlArr.join("/") + // Creates an array of screens, checking and sanitising their URLs + const createScreens = async screens => { + if (!screens?.length) { + return } + showProgressCircle = true - let route = url ? sanitizeUrl(`${url}`) : draftScreen.routing.route - if (draftScreen) { - if (!route) { - routeError = "URL is required" - } else { - if (routeExists(route, roleId)) { - routeError = "This URL is already taken for this access role" - } else { - routeError = "" + try { + for (let screen of screens) { + // Check we aren't clashing with an existing URL + if (hasExistingUrl(screen.routing.route)) { + let suffix = 2 + let candidateUrl = makeCandidateUrl(screen, suffix) + while (hasExistingUrl(candidateUrl)) { + candidateUrl = makeCandidateUrl(screen, ++suffix) + } + screen.routing.route = candidateUrl } - } - if (routeError) return false + // Sanitise URL + screen.routing.route = sanitizeUrl(screen.routing.route) - if (screenName) { - draftScreen.props._instanceName = screenName - } + // Use the currently selected role + screen.routing.roleId = get(selectedAccessRole) || "BASIC" - draftScreen.routing.route = route - draftScreen.routing.roleId = roleId + // Create the screen + await store.actions.screens.save(screen) - await store.actions.screens.save(draftScreen) - if (draftScreen.props._instanceName.endsWith("List")) { - try { + // Analytics + if (screen.template) { + analytics.captureEvent(Events.SCREEN.CREATED, { + template: screen.template, + }) + } + + // Add link in layout for list screens + if (screen.props._instanceName.endsWith("List")) { await store.actions.components.links.save( - draftScreen.routing.route, - draftScreen.routing.route.split("/")[1] + screen.routing.route, + screen.routing.route.split("/")[1] ) - } catch (error) { - notifications.error("Error creating link to screen") } } + + // Refresh routing info since we have new screens + await store.actions.routing.fetch() + } catch (error) { + console.log(error) + notifications.error("Error creating screens") + } + + showProgressCircle = false + } + + // Checks if any screens exist in the store with the given route and + // currently selected role + const hasExistingUrl = url => { + const roleId = get(selectedAccessRole) || "BASIC" + const screens = get(store).screens.filter(s => s.routing.roleId === roleId) + return !!screens.find(s => s.routing?.route === url) + } + + // Constructs a candidate URL for a new screen, suffixing the base of the + // screen's URL with a given suffix. + // e.g. "/sales/:id" => "/sales-1/:id" + const makeCandidateUrl = (screen, suffix) => { + let url = screen.routing?.route || "" + if (url.startsWith("/")) { + url = url.slice(1) + } + if (!url.includes("/")) { + return `/${url}-${suffix}` + } else { + const split = url.split("/") + return `/${split[0]}-${suffix}/${split.join("/")}` } } - const routeExists = (route, roleId) => { - return $allScreens.some( - screen => - screen.routing.route.toLowerCase() === route.toLowerCase() && - screen.routing.roleId === roleId - ) - } - - export const showModal = () => { - newScreenModal.show() - } - - const setScreens = evt => { - selectedScreens = evt.detail.screens - } - - const chooseModal = index => { - /* - 0 = newScreenModal - 1 = screenDetailsModal - 2 = navigationSelectionModal - */ - if (index === 0) { - newScreenModal.show() - } else if (index === 1) { + // Handler for NewScreenModal + const confirmScreenSelection = async templates => { + // Handle template selection + if (templates?.length > 1) { + // Autoscreens, so create immediately + const screens = templates.map(template => template.create()) + await createScreens(screens) + } else { + // Empty screen, so proceed to the next modal + pendingScreen = templates[0].create() screenDetailsModal.show() - } else if (index === 2) { - navigationSelectionModal.show() } } + + // Handler for ScreenDetailsModal + const confirmScreenDetails = async ({ screenName, screenUrl }) => { + if (!pendingScreen) { + return + } + pendingScreen.props._instanceName = screenName + pendingScreen.routing.route = screenUrl + await createScreens([pendingScreen]) + } - + newScreenModal.show()} /> From f5ff71f9d1a41b53e5c78108073a22519bbc6c56 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 2 Mar 2022 19:26:43 +0000 Subject: [PATCH 04/72] Allow duplication of screens --- .../ScreenDropdownMenu.svelte | 57 +++++++++++++++++-- .../NavigationPanel/ScreenDetailsModal.svelte | 8 ++- .../NavigationPanel/ScreenWizard.svelte | 4 -- 3 files changed, 57 insertions(+), 12 deletions(-) diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte index 47c9fb65b1..33e4d89dda 100644 --- a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte @@ -2,15 +2,56 @@ import { goto } from "@roxi/routify" import { store, allScreens } from "builderStore" import ConfirmDialog from "components/common/ConfirmDialog.svelte" - import { ActionMenu, MenuItem, Icon, notifications } from "@budibase/bbui" + import { + ActionMenu, + MenuItem, + Icon, + Modal, + Helpers, + notifications, + } from "@budibase/bbui" + import ScreenDetailsModal from "../ScreenDetailsModal.svelte" + import sanitizeUrl from "builderStore/store/screenTemplates/utils/sanitizeUrl" + import analytics, { Events } from "analytics" + import { makeComponentUnique } from "builderStore/componentUtils" export let screenId let confirmDeleteDialog + let screenDetailsModal $: screen = $allScreens.find(screen => screen._id === screenId) - const duplicateScreen = () => {} + const duplicateScreen = () => { + screenDetailsModal.show() + } + + const createDuplicateScreen = async ({ screenName, screenUrl }) => { + // Create a dupe and ensure it is unique + let duplicateScreen = Helpers.cloneDeep(screen) + delete duplicateScreen._id + delete duplicateScreen._rev + makeComponentUnique(duplicateScreen.props) + + // Attach the new name and URL + duplicateScreen.routing.route = sanitizeUrl(screenUrl) + duplicateScreen.props._instanceName = screenName + + try { + // Create the screen + await store.actions.screens.save(duplicateScreen) + + // Analytics + if (screen.template) { + analytics.captureEvent(Events.SCREEN.CREATED, { + template: "createFromScratch", + }) + } + } catch (error) { + notifications.error("Error duplicating screen") + console.log(error) + } + } const deleteScreen = async () => { try { @@ -27,9 +68,7 @@
- - Duplicate - + Duplicate Delete @@ -40,3 +79,11 @@ okText="Delete Screen" onOk={deleteScreen} /> + + + + diff --git a/packages/builder/src/components/design/NavigationPanel/ScreenDetailsModal.svelte b/packages/builder/src/components/design/NavigationPanel/ScreenDetailsModal.svelte index 0fae114268..82b90be6a6 100644 --- a/packages/builder/src/components/design/NavigationPanel/ScreenDetailsModal.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ScreenDetailsModal.svelte @@ -7,15 +7,17 @@ export let onConfirm export let onCancel export let showProgressCircle = false + export let screenName + export let screenUrl - let screenName - let screenUrl let routeError + let touched = false const routeChanged = event => { if (!event.detail.startsWith("/")) { screenUrl = "/" + event.detail } + touched = true screenUrl = sanitizeUrl(screenUrl) if (routeExists(screenUrl)) { routeError = "This URL is already taken for this access role" @@ -48,7 +50,7 @@ onConfirm={confirmScreenDetails} {onCancel} cancelText={"Back"} - disabled={!screenName || !screenUrl || routeError} + disabled={!screenName || !screenUrl || routeError || !touched} > Date: Wed, 2 Mar 2022 19:52:10 +0000 Subject: [PATCH 05/72] Allow bulk deleting all screens under a route --- .../ComponentDropdownMenu.svelte | 0 .../ComponentTree.svelte | 2 +- .../LayoutDropdownMenu.svelte | 2 +- .../PathDropdownMenu.svelte | 78 +++++++++++++++++++ .../ComponentNavigationTree/PathTree.svelte | 5 +- .../ScreenDropdownMenu.svelte | 2 +- 6 files changed, 85 insertions(+), 4 deletions(-) rename packages/builder/src/components/design/NavigationPanel/{ => ComponentNavigationTree}/ComponentDropdownMenu.svelte (100%) create mode 100644 packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/PathDropdownMenu.svelte diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentDropdownMenu.svelte similarity index 100% rename from packages/builder/src/components/design/NavigationPanel/ComponentDropdownMenu.svelte rename to packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentDropdownMenu.svelte diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentTree.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentTree.svelte index c5dfd63cf9..d0095b2c0d 100644 --- a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentTree.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentTree.svelte @@ -1,7 +1,7 @@ + + +
+ +
+ + Delete all screens + +
+ + + +
+ Are you sure you want to delete all screens under the {path} route? +
+
The following screens will be deleted:
+
+ {#each screens as screen} +
{screen.route}
+ {/each} +
+
+
+ + diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/PathTree.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/PathTree.svelte index 841d8970f4..ee6de5c797 100644 --- a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/PathTree.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/PathTree.svelte @@ -8,6 +8,7 @@ import instantiateStore from "./dragDropStore" import ComponentTree from "./ComponentTree.svelte" import NavItem from "components/common/NavItem.svelte" + import PathDropdownMenu from "./PathDropdownMenu.svelte" import ScreenDropdownMenu from "./ScreenDropdownMenu.svelte" import { get } from "svelte/store" @@ -73,7 +74,9 @@ opened={routeOpened} {border} withArrow={route.subpaths} - /> + > + + {#if routeOpened} {#each filteredScreens as screen (screen.id)} diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte index 33e4d89dda..7d0b88c235 100644 --- a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte @@ -76,7 +76,7 @@ bind:this={confirmDeleteDialog} title="Confirm Deletion" body={"Are you sure you wish to delete this screen?"} - okText="Delete Screen" + okText="Delete screen" onOk={deleteScreen} /> From 530024bd632d6ad47d0bf066c0192c3ed5d8dc37 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 7 Mar 2022 08:16:55 +0000 Subject: [PATCH 06/72] Add component name to settings panel --- .../design/PropertiesPanel/ComponentSettingsSection.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/components/design/PropertiesPanel/ComponentSettingsSection.svelte b/packages/builder/src/components/design/PropertiesPanel/ComponentSettingsSection.svelte index f9fa56f739..88455fb003 100644 --- a/packages/builder/src/components/design/PropertiesPanel/ComponentSettingsSection.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/ComponentSettingsSection.svelte @@ -32,7 +32,7 @@ const customSections = settings.filter(setting => setting.section) return [ { - name: "General", + name: componentDefinition?.name || "General", info: componentDefinition?.info, settings: generalSettings, }, From 4c88a046fd7de958ac91ceea943bce5c87006c07 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 7 Mar 2022 10:41:52 +0000 Subject: [PATCH 07/72] Update confirm text button when duplicating screens --- .../ComponentNavigationTree/ScreenDropdownMenu.svelte | 1 + .../design/NavigationPanel/ScreenDetailsModal.svelte | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte index 7d0b88c235..3a5e60ae57 100644 --- a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte @@ -85,5 +85,6 @@ onConfirm={createDuplicateScreen} screenName={screen?.props._instanceName} screenUrl={screen?.routing.route} + confirmText="Duplicate" /> diff --git a/packages/builder/src/components/design/NavigationPanel/ScreenDetailsModal.svelte b/packages/builder/src/components/design/NavigationPanel/ScreenDetailsModal.svelte index 82b90be6a6..75977e51a2 100644 --- a/packages/builder/src/components/design/NavigationPanel/ScreenDetailsModal.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ScreenDetailsModal.svelte @@ -9,6 +9,7 @@ export let showProgressCircle = false export let screenName export let screenUrl + export let confirmText = "Continue" let routeError let touched = false @@ -46,7 +47,7 @@ Date: Mon, 7 Mar 2022 13:56:06 +0000 Subject: [PATCH 08/72] Add option to paste inside screens --- .../ScreenDropdownMenu.svelte | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte index 3a5e60ae57..972414ae0b 100644 --- a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ScreenDropdownMenu.svelte @@ -62,6 +62,14 @@ notifications.error("Error deleting screen") } } + + const pasteComponent = mode => { + try { + store.actions.components.paste(screen?.props, mode) + } catch (error) { + notifications.error("Error saving component") + } + } @@ -69,6 +77,13 @@
Duplicate + pasteComponent("inside")} + disabled={!$store.componentToPaste} + > + Paste inside + Delete From e84e4f98996ea8625f1daaf2fb1195d3cc4b201e Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 7 Mar 2022 14:05:26 +0000 Subject: [PATCH 09/72] Add duplicate action to settings bar --- .../design/AppPreview/CurrentItemPreview.svelte | 5 +++++ .../client/src/components/preview/SettingsBar.svelte | 10 ++++++++++ packages/client/src/stores/builder.js | 3 +++ 3 files changed, 18 insertions(+) diff --git a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte index 2a886fab0c..b0b7c16c68 100644 --- a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte +++ b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte @@ -159,6 +159,11 @@ await store.actions.components.updateProp(data.prop, data.value) } else if (type === "delete-component" && data.id) { confirmDeleteComponent(data.id) + } else if (type === "duplicate-component" && data.id) { + const rootComponent = get(currentAsset).props + const component = findComponent(rootComponent, data.id) + store.actions.components.copy(component) + await store.actions.components.paste(component) } else if (type === "preview-loaded") { // Wait for this event to show the client library if intelligent // loading is supported diff --git a/packages/client/src/components/preview/SettingsBar.svelte b/packages/client/src/components/preview/SettingsBar.svelte index a4e3ca4d72..c5ad8bef6c 100644 --- a/packages/client/src/components/preview/SettingsBar.svelte +++ b/packages/client/src/components/preview/SettingsBar.svelte @@ -146,6 +146,15 @@
{/if} {/each} + { + builderStore.actions.duplicateComponent( + $builderStore.selectedComponent._id + ) + }} + title="Duplicate component" + /> { @@ -153,6 +162,7 @@ $builderStore.selectedComponent._id ) }} + title="Delete component" />
{/if} diff --git a/packages/client/src/stores/builder.js b/packages/client/src/stores/builder.js index 719909b538..27c8bbe2a2 100644 --- a/packages/client/src/stores/builder.js +++ b/packages/client/src/stores/builder.js @@ -62,6 +62,9 @@ const createBuilderStore = () => { deleteComponent: id => { dispatchEvent("delete-component", { id }) }, + duplicateComponent: id => { + dispatchEvent("duplicate-component", { id }) + }, notifyLoaded: () => { dispatchEvent("preview-loaded") }, From 8131bae496687e6d9fbba82fd19d8d39065c8089 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 8 Mar 2022 08:46:07 +0000 Subject: [PATCH 10/72] Update cypress tests for different button casing --- packages/builder/cypress/support/commands.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/builder/cypress/support/commands.js b/packages/builder/cypress/support/commands.js index ede1038a58..699cf1fbf0 100644 --- a/packages/builder/cypress/support/commands.js +++ b/packages/builder/cypress/support/commands.js @@ -247,7 +247,7 @@ Cypress.Commands.add("createScreen", (screenName, route) => { cy.get("[aria-label=AddCircle]").click() cy.get(".spectrum-Modal").within(() => { cy.get(".item").contains("Blank").click() - cy.get(".spectrum-Button").contains("Add Screens").click({ force: true }) + cy.get(".spectrum-Button").contains("Add screens").click({ force: true }) cy.wait(500) }) cy.get(".spectrum-Dialog-grid").within(() => { @@ -265,7 +265,7 @@ Cypress.Commands.add("createAutogeneratedScreens", screenNames => { for (let i = 0; i < screenNames.length; i++) { cy.get(".item").contains(screenNames[i]).click() } - cy.get(".spectrum-Button").contains("Add Screens").click({ force: true }) + cy.get(".spectrum-Button").contains("Add screens").click({ force: true }) cy.wait(4000) }) From d8cb5bfd246f82704def4276f3bafc9a7953e62a Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 8 Mar 2022 14:14:57 +0000 Subject: [PATCH 11/72] Fix screen renaming when same route already exists --- packages/builder/cypress.json | 2 +- .../src/components/design/NavigationPanel/ScreenWizard.svelte | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/builder/cypress.json b/packages/builder/cypress.json index edad1f39d3..3e4d4c4d1b 100644 --- a/packages/builder/cypress.json +++ b/packages/builder/cypress.json @@ -1,6 +1,6 @@ { "baseUrl": "http://localhost:4100", - "video": false, + "video": true, "projectId": "bmbemn", "env": { "PORT": "4100", diff --git a/packages/builder/src/components/design/NavigationPanel/ScreenWizard.svelte b/packages/builder/src/components/design/NavigationPanel/ScreenWizard.svelte index 76ee253e00..c30241868a 100644 --- a/packages/builder/src/components/design/NavigationPanel/ScreenWizard.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ScreenWizard.svelte @@ -93,7 +93,7 @@ return `/${url}-${suffix}` } else { const split = url.split("/") - return `/${split[0]}-${suffix}/${split.join("/")}` + return `/${split[0]}-${suffix}/${split.slice(1).join("/")}` } } From 5bef8849ca041c10baf349e89d681b0ff25cf0e7 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 8 Mar 2022 14:45:47 +0000 Subject: [PATCH 12/72] Remove cypress video flag again --- packages/builder/cypress.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/cypress.json b/packages/builder/cypress.json index 3e4d4c4d1b..edad1f39d3 100644 --- a/packages/builder/cypress.json +++ b/packages/builder/cypress.json @@ -1,6 +1,6 @@ { "baseUrl": "http://localhost:4100", - "video": true, + "video": false, "projectId": "bmbemn", "env": { "PORT": "4100", From 990442b45e06614344ff728f26b25e1a1954720b Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 8 Mar 2022 17:57:36 +0000 Subject: [PATCH 13/72] Add optional chaining to all current asset references to account for nullish values --- packages/builder/src/builderStore/dataBinding.js | 4 ++-- packages/builder/src/builderStore/index.js | 2 +- packages/builder/src/builderStore/store/frontend.js | 4 ++-- .../ComponentNavigationTree/ComponentDropdownMenu.svelte | 4 ++-- .../ButtonActionEditor/actions/S3Upload.svelte | 2 +- .../PropertyControls/DataProviderSelect.svelte | 2 +- .../PropertiesPanel/PropertyControls/FormFieldSelect.svelte | 2 +- .../PropertiesPanel/PropertyControls/ResetFieldsButton.svelte | 2 +- .../app/[application]/design/[assetType]/_layout.svelte | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/builder/src/builderStore/dataBinding.js b/packages/builder/src/builderStore/dataBinding.js index 5b9bebcbf5..41174a9d9d 100644 --- a/packages/builder/src/builderStore/dataBinding.js +++ b/packages/builder/src/builderStore/dataBinding.js @@ -126,7 +126,7 @@ export const getDatasourceForProvider = (asset, component) => { if (dataProviderSetting) { const settingValue = component[dataProviderSetting.key] const providerId = extractLiteralHandlebarsID(settingValue) - const provider = findComponent(asset.props, providerId) + const provider = findComponent(asset?.props, providerId) return getDatasourceForProvider(asset, provider) } @@ -458,7 +458,7 @@ export const getSchemaForDatasource = (asset, datasource, options) => { // Determine the entity which backs this datasource. // "provider" datasources are those targeting another data provider if (type === "provider") { - const component = findComponent(asset.props, datasource.providerId) + const component = findComponent(asset?.props, datasource.providerId) const source = getDatasourceForProvider(asset, component) return getSchemaForDatasource(asset, source, options) } diff --git a/packages/builder/src/builderStore/index.js b/packages/builder/src/builderStore/index.js index 5181e756c6..82556c74cf 100644 --- a/packages/builder/src/builderStore/index.js +++ b/packages/builder/src/builderStore/index.js @@ -25,7 +25,7 @@ export const selectedComponent = derived( if (!$currentAsset || !$store.selectedComponentId) { return null } - return findComponent($currentAsset.props, $store.selectedComponentId) + return findComponent($currentAsset?.props, $store.selectedComponentId) } ) diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index c8e4c85b06..fd29414e3c 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -400,11 +400,11 @@ export const getFrontendStore = () => { parentComponent = selected } else { // Otherwise we need to use the parent of this component - parentComponent = findComponentParent(asset.props, selected._id) + parentComponent = findComponentParent(asset?.props, selected._id) } } else { // Use screen or layout if no component is selected - parentComponent = asset.props + parentComponent = asset?.props } // Attach component diff --git a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentDropdownMenu.svelte b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentDropdownMenu.svelte index df6be7e88f..75601084a0 100644 --- a/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentDropdownMenu.svelte +++ b/packages/builder/src/components/design/NavigationPanel/ComponentNavigationTree/ComponentDropdownMenu.svelte @@ -21,7 +21,7 @@ const moveUpComponent = () => { const asset = get(currentAsset) - const parent = findComponentParent(asset.props, component._id) + const parent = findComponentParent(asset?.props, component._id) if (!parent) { return } @@ -41,7 +41,7 @@ const moveDownComponent = () => { const asset = get(currentAsset) - const parent = findComponentParent(asset.props, component._id) + const parent = findComponentParent(asset?.props, component._id) if (!parent) { return } diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/S3Upload.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/S3Upload.svelte index 76cccf58c5..2e374f165f 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/S3Upload.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/S3Upload.svelte @@ -5,7 +5,7 @@ export let parameters - $: components = findAllMatchingComponents($currentAsset.props, component => + $: components = findAllMatchingComponents($currentAsset?.props, component => component._component.endsWith("s3upload") ) diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/DataProviderSelect.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/DataProviderSelect.svelte index d7118fd3ec..a5b7a08255 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/DataProviderSelect.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/DataProviderSelect.svelte @@ -10,7 +10,7 @@ const dispatch = createEventDispatcher() const getValue = component => `{{ literal ${makePropSafe(component._id)} }}` - $: path = findComponentPath($currentAsset.props, $store.selectedComponentId) + $: path = findComponentPath($currentAsset?.props, $store.selectedComponentId) $: providers = path.filter(c => c._component?.endsWith("/dataprovider")) // Set initial value to closest data provider diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FormFieldSelect.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FormFieldSelect.svelte index 94a542480f..1f08c56ff5 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FormFieldSelect.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FormFieldSelect.svelte @@ -12,7 +12,7 @@ export let type $: form = findClosestMatchingComponent( - $currentAsset.props, + $currentAsset?.props, componentInstance._id, component => component._component === "@budibase/standard-components/form" ) diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ResetFieldsButton.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ResetFieldsButton.svelte index a76a93d7f6..e927526b92 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ResetFieldsButton.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ResetFieldsButton.svelte @@ -11,7 +11,7 @@ const resetFormFields = async () => { const form = findClosestMatchingComponent( - $currentAsset.props, + $currentAsset?.props, componentInstance._id, component => component._component.endsWith("/form") ) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[assetType]/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/design/[assetType]/_layout.svelte index dc565e5f39..97697c7449 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[assetType]/_layout.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[assetType]/_layout.svelte @@ -135,7 +135,7 @@ if (asset?._id) { url += `/${asset._id}` if (componentId) { - const componentPath = findComponentPath(asset.props, componentId) + const componentPath = findComponentPath(asset?.props, componentId) const componentURL = componentPath .slice(1) .map(comp => comp._id) From ce984348a0da93a4c8bf38d9498bc7d46b167b5a Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Wed, 9 Mar 2022 16:08:55 +0100 Subject: [PATCH 14/72] fixing enrichment of relationships in patch call --- packages/server/src/api/controllers/row/internal.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/server/src/api/controllers/row/internal.js b/packages/server/src/api/controllers/row/internal.js index 068a485a8a..9ddd6328b5 100644 --- a/packages/server/src/api/controllers/row/internal.js +++ b/packages/server/src/api/controllers/row/internal.js @@ -83,7 +83,11 @@ exports.patch = async ctx => { const isUserTable = tableId === InternalTables.USER_METADATA let oldRow try { - oldRow = await db.get(inputs._id) + let dbTable = await db.get(tableId) + oldRow = await outputProcessing( + dbTable, + await findRow(ctx, tableId, inputs._id) + ) } catch (err) { if (isUserTable) { // don't include the rev, it'll be the global rev From 0b7919cd3d8029a572e59e049af6b0fbdc2b7bb1 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 10 Mar 2022 10:18:03 +0000 Subject: [PATCH 15/72] Update date filtering to only use a between statement when 2 dates are provided --- packages/server/src/integrations/base/sql.ts | 23 ++++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/packages/server/src/integrations/base/sql.ts b/packages/server/src/integrations/base/sql.ts index ffa405f016..f4ebc02098 100644 --- a/packages/server/src/integrations/base/sql.ts +++ b/packages/server/src/integrations/base/sql.ts @@ -27,11 +27,8 @@ function parse(input: any) { if (typeof input !== "string") { return input } - if (input === MAX_ISO_DATE) { - return new Date(8640000000000000) - } - if (input === MIN_ISO_DATE) { - return new Date(-8640000000000000) + if (input === MAX_ISO_DATE || input === MIN_ISO_DATE) { + return null } if (isIsoDateString(input)) { return new Date(input) @@ -130,11 +127,19 @@ class InternalBuilder { } if (filters.range) { iterate(filters.range, (key, value) => { - if (!value.high || !value.low) { - return + if (value.low && value.high) { + // Use a between operator if we have 2 valid range values + const fnc = allOr ? "orWhereBetween" : "whereBetween" + query = query[fnc](key, [value.low, value.high]) + } else if (value.low) { + // Use just a single greater than operator if we only have a low + const fnc = allOr ? "orWhere" : "where" + query = query[fnc](key, ">", value.low) + } else if (value.high) { + // Use just a single less than operator if we only have a high + const fnc = allOr ? "orWhere" : "where" + query = query[fnc](key, "<", value.high) } - const fnc = allOr ? "orWhereBetween" : "whereBetween" - query = query[fnc](key, [value.low, value.high]) }) } if (filters.equal) { From 42cbdcd92354ca7fa24cc00c0c54ae9fd837f81b Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 10 Mar 2022 11:54:15 +0000 Subject: [PATCH 16/72] Add css print styles to ensure multi-page print is possible --- packages/client/src/components/ClientApp.svelte | 8 ++++++++ packages/client/src/components/app/Layout.svelte | 16 ++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/packages/client/src/components/ClientApp.svelte b/packages/client/src/components/ClientApp.svelte index e8ed7e9538..9a14f72ec8 100644 --- a/packages/client/src/components/ClientApp.svelte +++ b/packages/client/src/components/ClientApp.svelte @@ -226,4 +226,12 @@ border: 1px solid var(--spectrum-global-color-gray-300); border-radius: 4px; } + + @media print { + #spectrum-root, + #clip-root, + #app-root { + overflow: visible !important; + } + } diff --git a/packages/client/src/components/app/Layout.svelte b/packages/client/src/components/app/Layout.svelte index 600d295cba..a801ea4b46 100644 --- a/packages/client/src/components/app/Layout.svelte +++ b/packages/client/src/components/app/Layout.svelte @@ -427,4 +427,20 @@ height: var(--height); z-index: 998; } + + /* Print styles */ + @media print { + .layout, + .main-wrapper { + overflow: visible !important; + } + .nav-wrapper { + display: none !important; + } + .layout { + flex-direction: column !important; + justify-content: flex-start !important; + align-items: stretch !important; + } + } From c4a35021876e9e7b4fd8d838179b5042a0e8fccc Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 10 Mar 2022 11:56:31 +0000 Subject: [PATCH 17/72] Add comment for consistency --- packages/client/src/components/ClientApp.svelte | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/client/src/components/ClientApp.svelte b/packages/client/src/components/ClientApp.svelte index 9a14f72ec8..27767862ab 100644 --- a/packages/client/src/components/ClientApp.svelte +++ b/packages/client/src/components/ClientApp.svelte @@ -227,6 +227,7 @@ border-radius: 4px; } + /* Print styles */ @media print { #spectrum-root, #clip-root, From 8bac9d43b4e5f9ad25a1b016b08c89b1a1b139d2 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 15 Mar 2022 11:42:12 +0000 Subject: [PATCH 18/72] Revert locks to develop --- packages/client/yarn.lock | 35 ++++++++++++--------------- packages/server/yarn.lock | 50 +++++++++++++++++++-------------------- packages/worker/yarn.lock | 16 ++++++------- 3 files changed, 48 insertions(+), 53 deletions(-) diff --git a/packages/client/yarn.lock b/packages/client/yarn.lock index d29d01df08..8eb1682af8 100644 --- a/packages/client/yarn.lock +++ b/packages/client/yarn.lock @@ -28,13 +28,13 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@budibase/bbui@^1.0.89", "@budibase/bbui@^1.0.89-alpha.0": - version "1.0.89" - resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-1.0.89.tgz#f6fc913b49a64fc0db81b0bdded57b497bc37b41" - integrity sha512-ShJA+3aLHY2u/815TBt3Smiyw/RoYDjWAI9dB2ny4EZcNHeKsTpF1tPnvmOj7vgHKZliSt8+nHaqGCaX5hBvVg== +"@budibase/bbui@^1.0.85": + version "1.0.85" + resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-1.0.85.tgz#b4f4415f2acfe3f2891413545c5338a250522576" + integrity sha512-gxRu48r39b/FLaDIaU89xuPnIjr76b9HoKqx7vgNWyiwaNh6IyyA0LtHRTLj7r2/sLjDCTjYXTVBqDkcmbANpw== dependencies: "@adobe/spectrum-css-workflow-icons" "^1.2.1" - "@budibase/string-templates" "^1.0.89" + "@budibase/string-templates" "^1.0.85" "@spectrum-css/actionbutton" "^1.0.1" "@spectrum-css/actiongroup" "^1.0.1" "@spectrum-css/avatar" "^3.0.2" @@ -80,12 +80,12 @@ svelte-flatpickr "^3.2.3" svelte-portal "^1.0.0" -"@budibase/frontend-core@^1.0.89-alpha.0": - version "1.0.89" - resolved "https://registry.yarnpkg.com/@budibase/frontend-core/-/frontend-core-1.0.89.tgz#18426895df2e4220bb328b76882b0aa915d8cda0" - integrity sha512-yQMgPnZuWSNmwOGwvUr5uI3h4SuAltc4hovxzQ2Tcnl8YmR6/f4ZgPpz2DgcnQg3aEAGFqvx0wRJDiovr/K7Kg== +"@budibase/frontend-core@^1.0.85": + version "1.0.85" + resolved "https://registry.yarnpkg.com/@budibase/frontend-core/-/frontend-core-1.0.85.tgz#f44d97016edc54d4bd6a10a6066f9d0f8d5b5a45" + integrity sha512-dTHnmWrr87wuulxLsyR7g2hlSOxKtMuDAOXsDZe8drGCiD7gdbSgcYPckJ9dC4XxRJ/rKZN0AZ1tZdRoH7Tx6g== dependencies: - "@budibase/bbui" "^1.0.89" + "@budibase/bbui" "^1.0.85" lodash "^4.17.21" svelte "^3.46.2" @@ -114,10 +114,10 @@ to-gfm-code-block "^0.1.1" year "^0.2.1" -"@budibase/string-templates@^1.0.89", "@budibase/string-templates@^1.0.89-alpha.0": - version "1.0.89" - resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-1.0.89.tgz#21d9fc2825f787e1d57472aee413c0d541d09274" - integrity sha512-oaKEepiEoPTISjBAFceq37HQfXL8bs+gKF/IL9RIdXjTzD21Tj7JA7Q3/Lp2NUoIrpy7C7NJ4DMxpeD5/HVcXg== +"@budibase/string-templates@^1.0.85": + version "1.0.85" + resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-1.0.85.tgz#1119ddb28bb3a512a894d4f20b9982cc65911cc7" + integrity sha512-buU5+rMRXFTQZlG9M3e+uPuaJ57OXE3pSPt/H0mo/8l7Bs5O1Xs9p8O6k2YvTkvQueJeqfwbL9QbztxPmCK9xQ== dependencies: "@budibase/handlebars-helpers" "^0.11.8" dayjs "^1.10.4" @@ -868,12 +868,7 @@ csso@^4.2.0: dependencies: css-tree "^1.1.2" -dayjs@^1.10.4: - version "1.11.0" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.0.tgz#009bf7ef2e2ea2d5db2e6583d2d39a4b5061e805" - integrity sha512-JLC809s6Y948/FuCZPm5IX8rRhQwOiyMb2TfVVQEixG7P8Lm/gt5S7yoQZmC8x1UehI9Pb7sksEt4xx14m+7Ug== - -dayjs@^1.10.5: +dayjs@^1.10.4, dayjs@^1.10.5: version "1.10.8" resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.8.tgz#267df4bc6276fcb33c04a6735287e3f429abec41" integrity sha512-wbNwDfBHHur9UOzNUjeKUOJ0fCb0a52Wx0xInmQ7Y8FstyajiV1NmK1e00cxsr9YrE9r7yAChE0VvpuY5Rnlow== diff --git a/packages/server/yarn.lock b/packages/server/yarn.lock index 3e71029869..8aa64db0c2 100644 --- a/packages/server/yarn.lock +++ b/packages/server/yarn.lock @@ -995,10 +995,10 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@budibase/backend-core@^1.0.89-alpha.0": - version "1.0.89" - resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.89.tgz#0cfeb43d59ef7e0fa42fac6a241519ba7f59a654" - integrity sha512-XKV0s+FMDzS0kSWAo07OdEN1+NsidR1irCQRXPlxVYF+NE34vqcA+AmJerjjA8V3uMPAdTyzJGxklLW/gjED/w== +"@budibase/backend-core@^1.0.84": + version "1.0.84" + resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.84.tgz#9fb01669129838419c57f1723e9274cb4bb9dfd5" + integrity sha512-8hqRxSHO8A46f/hyzcqCdlku05yXBVEea1/FJdkoEDoCPhbuv04VHQ/f/dwkWctQ/oL8fm8MHpCA4ApyO7bnJA== dependencies: "@techpass/passport-openidconnect" "^0.3.0" aws-sdk "^2.901.0" @@ -1068,13 +1068,13 @@ svelte-flatpickr "^3.2.3" svelte-portal "^1.0.0" -"@budibase/bbui@^1.0.89": - version "1.0.89" - resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-1.0.89.tgz#f6fc913b49a64fc0db81b0bdded57b497bc37b41" - integrity sha512-ShJA+3aLHY2u/815TBt3Smiyw/RoYDjWAI9dB2ny4EZcNHeKsTpF1tPnvmOj7vgHKZliSt8+nHaqGCaX5hBvVg== +"@budibase/bbui@^1.0.84": + version "1.0.84" + resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-1.0.84.tgz#8bf2f3d93aaf71ae353f93b10cb34e06c99d8176" + integrity sha512-GO2qXq5wJ00YCdgl93fP1y9eLwAbX0fpt9WVqNYWcgUzAMkeQAOPr7S0ud05GwLZPo736exxqh6RzSwo5H73sg== dependencies: "@adobe/spectrum-css-workflow-icons" "^1.2.1" - "@budibase/string-templates" "^1.0.89" + "@budibase/string-templates" "^1.0.84" "@spectrum-css/actionbutton" "^1.0.1" "@spectrum-css/actiongroup" "^1.0.1" "@spectrum-css/avatar" "^3.0.2" @@ -1120,14 +1120,14 @@ svelte-flatpickr "^3.2.3" svelte-portal "^1.0.0" -"@budibase/client@^1.0.89-alpha.0": - version "1.0.89" - resolved "https://registry.yarnpkg.com/@budibase/client/-/client-1.0.89.tgz#14ffcd1f97c1f73904544624d0ab2ea62a82c278" - integrity sha512-SsnzXldCRJuGYafWFn0KhHQa0htUECLEdVJbYpuE9DgJT8sEeQLRLMvprAbgi+63GoLs5QmxD2c5qiSY8UicCg== +"@budibase/client@^1.0.84": + version "1.0.84" + resolved "https://registry.yarnpkg.com/@budibase/client/-/client-1.0.84.tgz#7d29cd03a3611fb580ced1bb911b45e73a8c7832" + integrity sha512-sZC3/7KQXPHS/jDyeTiPKK8Ri81JgtgInIfEvpd45V5jeg5kNo0L1m37xZgQEzQCqSqr47veM6WN7Kl3WYZr0g== dependencies: - "@budibase/bbui" "^1.0.89" - "@budibase/frontend-core" "^1.0.89" - "@budibase/string-templates" "^1.0.89" + "@budibase/bbui" "^1.0.84" + "@budibase/frontend-core" "^1.0.84" + "@budibase/string-templates" "^1.0.84" "@spectrum-css/button" "^3.0.3" "@spectrum-css/card" "^3.0.3" "@spectrum-css/divider" "^1.0.3" @@ -1147,12 +1147,12 @@ svelte-flatpickr "^3.1.0" svelte-spa-router "^3.0.5" -"@budibase/frontend-core@^1.0.89": - version "1.0.89" - resolved "https://registry.yarnpkg.com/@budibase/frontend-core/-/frontend-core-1.0.89.tgz#18426895df2e4220bb328b76882b0aa915d8cda0" - integrity sha512-yQMgPnZuWSNmwOGwvUr5uI3h4SuAltc4hovxzQ2Tcnl8YmR6/f4ZgPpz2DgcnQg3aEAGFqvx0wRJDiovr/K7Kg== +"@budibase/frontend-core@^1.0.84": + version "1.0.84" + resolved "https://registry.yarnpkg.com/@budibase/frontend-core/-/frontend-core-1.0.84.tgz#d21594ddb521b79e2ac1b5322903887268f8a9aa" + integrity sha512-v6vTIVq8p+1ytnCWckYUqzzJ4Ylo6DF4C/pi2x5UrZxZuU7tQPMYGktHGQOouosHoGoZXsnPXJooeFHy43j0OQ== dependencies: - "@budibase/bbui" "^1.0.89" + "@budibase/bbui" "^1.0.84" lodash "^4.17.21" svelte "^3.46.2" @@ -1199,10 +1199,10 @@ svelte-apexcharts "^1.0.2" svelte-flatpickr "^3.1.0" -"@budibase/string-templates@^1.0.89", "@budibase/string-templates@^1.0.89-alpha.0": - version "1.0.89" - resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-1.0.89.tgz#21d9fc2825f787e1d57472aee413c0d541d09274" - integrity sha512-oaKEepiEoPTISjBAFceq37HQfXL8bs+gKF/IL9RIdXjTzD21Tj7JA7Q3/Lp2NUoIrpy7C7NJ4DMxpeD5/HVcXg== +"@budibase/string-templates@^1.0.84": + version "1.0.84" + resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-1.0.84.tgz#66669e9898ed20c6be2c46a5eb19d55003eb6bcb" + integrity sha512-6Tv/TfGkmr3uBwNdZ3eKAPKwdsRTZbuQ+02puH+EcJK2leCerINo1SpAHf1BOmjQJynKeslKpSkUiisRVerMEg== dependencies: "@budibase/handlebars-helpers" "^0.11.8" dayjs "^1.10.4" diff --git a/packages/worker/yarn.lock b/packages/worker/yarn.lock index 8c7d61f81b..50c407ad15 100644 --- a/packages/worker/yarn.lock +++ b/packages/worker/yarn.lock @@ -286,10 +286,10 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@budibase/backend-core@^1.0.89-alpha.0": - version "1.0.89" - resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.89.tgz#0cfeb43d59ef7e0fa42fac6a241519ba7f59a654" - integrity sha512-XKV0s+FMDzS0kSWAo07OdEN1+NsidR1irCQRXPlxVYF+NE34vqcA+AmJerjjA8V3uMPAdTyzJGxklLW/gjED/w== +"@budibase/backend-core@^1.0.84": + version "1.0.84" + resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.84.tgz#9fb01669129838419c57f1723e9274cb4bb9dfd5" + integrity sha512-8hqRxSHO8A46f/hyzcqCdlku05yXBVEea1/FJdkoEDoCPhbuv04VHQ/f/dwkWctQ/oL8fm8MHpCA4ApyO7bnJA== dependencies: "@techpass/passport-openidconnect" "^0.3.0" aws-sdk "^2.901.0" @@ -335,10 +335,10 @@ to-gfm-code-block "^0.1.1" year "^0.2.1" -"@budibase/string-templates@^1.0.89-alpha.0": - version "1.0.89" - resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-1.0.89.tgz#21d9fc2825f787e1d57472aee413c0d541d09274" - integrity sha512-oaKEepiEoPTISjBAFceq37HQfXL8bs+gKF/IL9RIdXjTzD21Tj7JA7Q3/Lp2NUoIrpy7C7NJ4DMxpeD5/HVcXg== +"@budibase/string-templates@^1.0.84": + version "1.0.84" + resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-1.0.84.tgz#66669e9898ed20c6be2c46a5eb19d55003eb6bcb" + integrity sha512-6Tv/TfGkmr3uBwNdZ3eKAPKwdsRTZbuQ+02puH+EcJK2leCerINo1SpAHf1BOmjQJynKeslKpSkUiisRVerMEg== dependencies: "@budibase/handlebars-helpers" "^0.11.8" dayjs "^1.10.4" From 1c104d6fa580306d15468c9ca9966b2ec3f9b3d2 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 15 Mar 2022 11:52:54 +0000 Subject: [PATCH 19/72] Add test cases for SQL range filtering changes --- .../server/src/integrations/tests/sql.spec.js | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/packages/server/src/integrations/tests/sql.spec.js b/packages/server/src/integrations/tests/sql.spec.js index 6ef82f0113..c2e65c56b7 100644 --- a/packages/server/src/integrations/tests/sql.spec.js +++ b/packages/server/src/integrations/tests/sql.spec.js @@ -187,4 +187,55 @@ describe("SQL query builder", () => { sql: `select * from (select * from \`${TABLE_NAME}\` limit ?) as \`${TABLE_NAME}\`` }) }) + + it("should use greater than when only low range specified", () => { + const date = new Date() + const query = sql._query(generateReadJson({ + filters: { + range: { + property: { + low: date, + } + } + } + })) + expect(query).toEqual({ + bindings: [date, limit], + sql: `select * from (select * from "${TABLE_NAME}" where "${TABLE_NAME}"."property" > $1 limit $2) as "${TABLE_NAME}"` + }) + }) + + it("should use less than when only high range specified", () => { + const date = new Date() + const query = sql._query(generateReadJson({ + filters: { + range: { + property: { + high: date, + } + } + } + })) + expect(query).toEqual({ + bindings: [date, limit], + sql: `select * from (select * from "${TABLE_NAME}" where "${TABLE_NAME}"."property" < $1 limit $2) as "${TABLE_NAME}"` + }) + }) + + it("should use greater than when only low range specified", () => { + const date = new Date() + const query = sql._query(generateReadJson({ + filters: { + range: { + property: { + low: date, + } + } + } + })) + expect(query).toEqual({ + bindings: [date, limit], + sql: `select * from (select * from "${TABLE_NAME}" where "${TABLE_NAME}"."property" > $1 limit $2) as "${TABLE_NAME}"` + }) + }) }) From ab0de4b23359b629fd95b84980bc1d3c40867e70 Mon Sep 17 00:00:00 2001 From: Maurits Lourens Date: Wed, 16 Mar 2022 21:01:47 +0100 Subject: [PATCH 20/72] set text-overflow on binding panel items --- .../builder/src/components/common/bindings/BindingPanel.svelte | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/builder/src/components/common/bindings/BindingPanel.svelte b/packages/builder/src/components/common/bindings/BindingPanel.svelte index 076ef529fe..3aa1bd35bd 100644 --- a/packages/builder/src/components/common/bindings/BindingPanel.svelte +++ b/packages/builder/src/components/common/bindings/BindingPanel.svelte @@ -238,6 +238,9 @@ border: var(--border-light); transition: background-color 130ms ease-in-out, color 130ms ease-in-out, border-color 130ms ease-in-out; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } li:not(:last-of-type) { margin-bottom: var(--spacing-s); From a4405891d47e780daf2e198f2509fc825d733713 Mon Sep 17 00:00:00 2001 From: Maurits Lourens Date: Wed, 16 Mar 2022 21:05:45 +0100 Subject: [PATCH 21/72] set word-wrap to break word, so the text spreads on multiple lines --- .../src/components/common/bindings/BindingPanel.svelte | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/builder/src/components/common/bindings/BindingPanel.svelte b/packages/builder/src/components/common/bindings/BindingPanel.svelte index 3aa1bd35bd..f05f935226 100644 --- a/packages/builder/src/components/common/bindings/BindingPanel.svelte +++ b/packages/builder/src/components/common/bindings/BindingPanel.svelte @@ -238,9 +238,7 @@ border: var(--border-light); transition: background-color 130ms ease-in-out, color 130ms ease-in-out, border-color 130ms ease-in-out; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; + word-wrap: break-word; } li:not(:last-of-type) { margin-bottom: var(--spacing-s); From 8cd921f834784a6316c61e2ab21e57cb683742ae Mon Sep 17 00:00:00 2001 From: Maurits Lourens Date: Fri, 18 Mar 2022 14:35:06 +0100 Subject: [PATCH 22/72] fetch the table which contains info about the primaryDisplay --- packages/client/src/components/app/forms/Form.svelte | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/client/src/components/app/forms/Form.svelte b/packages/client/src/components/app/forms/Form.svelte index f0000233e6..8e2e0b2510 100644 --- a/packages/client/src/components/app/forms/Form.svelte +++ b/packages/client/src/components/app/forms/Form.svelte @@ -17,6 +17,7 @@ let table $: fetchSchema(dataSource) + $: fetchTable(dataSource) // Returns the closes data context which isn't a built in context const getInitialValues = (type, dataSource, context) => { @@ -74,6 +75,16 @@ } } + const fetchTable = async dataSource => { + if (dataSource?.tableId) { + try { + table = await API.fetchTableDefinition(dataSource.tableId) + } catch (error) { + table = null + } + } + } + $: initialValues = getInitialValues(actionType, dataSource, $context) $: resetKey = Helpers.hashString( JSON.stringify(initialValues) + JSON.stringify(schema) From 103bb254376bcfa1e75086dc4a778845bb56a7c8 Mon Sep 17 00:00:00 2001 From: Maurits Lourens Date: Fri, 18 Mar 2022 16:45:33 +0100 Subject: [PATCH 23/72] don't sent searchableSchema to getSchemaForDatasource --- .../PropertyControls/FilterEditor/FilterEditor.svelte | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterEditor.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterEditor.svelte index 25c39d9f79..2cb35a9cf5 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterEditor.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterEditor.svelte @@ -18,9 +18,7 @@ let tempValue = value || [] $: dataSource = getDatasourceForProvider($currentAsset, componentInstance) - $: schema = getSchemaForDatasource($currentAsset, dataSource, { - searchableSchema: true, - })?.schema + $: schema = getSchemaForDatasource($currentAsset, dataSource)?.schema $: schemaFields = Object.values(schema || {}) const saveFilter = async () => { From c79ec57a5d922a6e533fe787a07fa81de948a98b Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 18 Mar 2022 19:52:11 +0000 Subject: [PATCH 24/72] Add initial work on horizontally scrollable component tree with automatic scrolling --- .../src/components/common/NavItem.svelte | 75 ++++++++++--------- .../ComponentTree.svelte | 10 +++ .../ComponentNavigationTree/PathTree.svelte | 8 ++ .../ComponentNavigationTree/index.svelte | 7 +- .../FrontendNavigatePane.svelte | 66 +++++++++++++--- .../design/[assetType]/_layout.svelte | 2 - 6 files changed, 118 insertions(+), 50 deletions(-) diff --git a/packages/builder/src/components/common/NavItem.svelte b/packages/builder/src/components/common/NavItem.svelte index d2074b69b1..c653f4739a 100644 --- a/packages/builder/src/components/common/NavItem.svelte +++ b/packages/builder/src/components/common/NavItem.svelte @@ -15,6 +15,7 @@ export let iconColor const dispatch = createEventDispatcher() + let textRef function onIconClick(event) { event.stopPropagation() @@ -26,49 +27,58 @@ class="nav-item" class:border class:selected - style={`padding-left: ${indentLevel * 14}px`} + style={`padding-left: ${20 + indentLevel * 14}px`} {draggable} on:dragend on:dragstart on:dragover on:drop on:click + on:mouseover={() => { + const size = textRef.getBoundingClientRect() + dispatch("mouseover", size.width) + }} ondragover="return false" ondragenter="return false" > -
- {#if withArrow} -
- -
- {/if} + {#if withArrow} +
+ +
+ {/if} - - {#if iconText} -
- {iconText} -
- {:else if icon} -
- -
- {/if} -
{text}
- {#if withActions} -
- -
- {/if} -
+ + {#if iconText} +
+ {iconText} +
+ {:else if icon} +
+ +
+ {/if} +
{text}
+ {#if withActions} +
+ +
+ {/if}
diff --git a/packages/builder/src/components/design/NavigationPanel/FrontendNavigatePane.svelte b/packages/builder/src/components/design/NavigationPanel/FrontendNavigatePane.svelte index a5045d8e9f..12282323ee 100644 --- a/packages/builder/src/components/design/NavigationPanel/FrontendNavigatePane.svelte +++ b/packages/builder/src/components/design/NavigationPanel/FrontendNavigatePane.svelte @@ -1,5 +1,5 @@ - -
-