From 53a0c578ccaf20dc520834a49a29528f058abd79 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 11 Jul 2022 18:14:30 +0100 Subject: [PATCH 01/31] Fix drawer widths in automations section --- packages/bbui/src/Drawer/Drawer.svelte | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/bbui/src/Drawer/Drawer.svelte b/packages/bbui/src/Drawer/Drawer.svelte index af09b014d0..e1880d0ed4 100644 --- a/packages/bbui/src/Drawer/Drawer.svelte +++ b/packages/bbui/src/Drawer/Drawer.svelte @@ -82,6 +82,7 @@ } .fillWidth { + left: 260px !important; width: calc(100% - 260px) !important; } From bd5d4196924fc4a64dee8846d16006a14671329a Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 14 Jul 2022 15:19:42 +0100 Subject: [PATCH 02/31] Reduce state updates when selecting screens --- .../src/builderStore/store/frontend.js | 26 +++++++++++++++---- .../[screenId]/_components/AppPanel.svelte | 3 ++- .../_components/ScreenListPanel.svelte | 2 +- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index 16ae5ce215..b46516e875 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -61,6 +61,10 @@ const INITIAL_FRONTEND_STATE = { export const getFrontendStore = () => { const store = writable({ ...INITIAL_FRONTEND_STATE }) + store.subscribe(state => { + console.log("new state") + }) + store.actions = { reset: () => { store.set({ ...INITIAL_FRONTEND_STATE }) @@ -184,12 +188,24 @@ export const getFrontendStore = () => { }, screens: { select: screenId => { - store.update(state => { - let screens = state.screens - let screen = - screens.find(screen => screen._id === screenId) || screens[0] - if (!screen) return state + // Check this screen exists + const state = get(store) + const screen = state.screens.find(screen => screen._id === screenId) + console.log(screen) + if (!screen) { + return + } + // Check screen isn't already selected + if ( + state.selectedScreenId === screen._id && + state.selectedComponentId === screen.props?._id + ) { + return + } + + // Select new screen + store.update(state => { state.selectedScreenId = screen._id state.selectedComponentId = screen.props?._id return state diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPanel.svelte index d86e4a3c8d..76118cc9c8 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPanel.svelte @@ -17,7 +17,8 @@ getOptionValue={x => x._id} getOptionIcon={x => (x.routing.homeScreen ? "Home" : "WebPage")} getOptionColour={x => RoleUtils.getRoleColour(x.routing.roleId)} - bind:value={$store.selectedScreenId} + value={$store.selectedScreenId} + on:change={e => store.actions.screens.select(e.detail)} />
diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenListPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenListPanel.svelte index 40d9ab273d..ecb020b104 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenListPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenListPanel.svelte @@ -60,7 +60,7 @@ indentLevel={0} selected={$store.selectedScreenId === screen._id} text={screen.routing.route} - on:click={() => ($store.selectedScreenId = screen._id)} + on:click={() => store.actions.screens.select(screen._id)} color={RoleUtils.getRoleColour(screen.routing.roleId)} > From 172a5a8c252fd0597ed0544bc3fc9a1159c879fa Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 14 Jul 2022 15:29:06 +0100 Subject: [PATCH 03/31] Reduce state updates while saving screens --- .../src/builderStore/store/frontend.js | 29 ++++++++----------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index b46516e875..291057143d 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -177,15 +177,6 @@ export const getFrontendStore = () => { }) }, }, - routing: { - fetch: async () => { - const response = await API.fetchAppRoutes() - store.update(state => { - state.routes = response.routes - return state - }) - }, - }, screens: { select: screenId => { // Check this screen exists @@ -214,23 +205,27 @@ export const getFrontendStore = () => { save: async screen => { const creatingNewScreen = screen._id === undefined const savedScreen = await API.saveScreen(screen) + const routesResponse = await API.fetchAppRoutes() store.update(state => { + // Update screen object const idx = state.screens.findIndex(x => x._id === savedScreen._id) if (idx !== -1) { state.screens.splice(idx, 1, savedScreen) } else { state.screens.push(savedScreen) } + + // Select the new screen if creating a new one + if (creatingNewScreen) { + state.selectedScreenId = savedScreen._id + state.selectedComponentId = savedScreen.props._id + } + + // Update routes + state.routes = routesResponse.routes + return state }) - - // Refresh routes - await store.actions.routing.fetch() - - // Select the new screen if creating a new one - if (creatingNewScreen) { - store.actions.screens.select(savedScreen._id) - } return savedScreen }, delete: async screens => { From e3c2d57b0ed1bc64c45c9668dd5531e516da49e2 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 14 Jul 2022 15:31:45 +0100 Subject: [PATCH 04/31] Add screen patch store method and reduce state updates when deleting screens --- .../builder/src/builderStore/store/frontend.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index 291057143d..fd862dbc80 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -228,6 +228,14 @@ export const getFrontendStore = () => { }) return savedScreen }, + patch: async (screenId, patch) => { + const state = get(store) + const screen = state.screens.find(screen => screen._id === screenId) + if (!screen) { + return + } + return store.actions.screens.save({ ...screen, ...patch }) + }, delete: async screens => { const screensToDelete = Array.isArray(screens) ? screens : [screens] @@ -249,20 +257,24 @@ export const getFrontendStore = () => { promises.push(store.actions.links.delete(deleteUrls)) await Promise.all(promises) const deletedIds = screensToDelete.map(screen => screen._id) + const routesResponse = await API.fetchAppRoutes() store.update(state => { // Remove deleted screens from state state.screens = state.screens.filter(screen => { return !deletedIds.includes(screen._id) }) + // Deselect the current screen if it was deleted if (deletedIds.includes(state.selectedScreenId)) { state.selectedScreenId = null + state.selectedComponentId = null } + + // Update routing + state.routes = routesResponse.routes + return state }) - - // Refresh routes - await store.actions.routing.fetch() }, updateHomeScreen: async (screen, makeHomeScreen = true) => { let promises = [] From 0d2509a7f6f4c5f74e8350936598d175aa9fc277 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 14 Jul 2022 16:17:25 +0100 Subject: [PATCH 05/31] Update sequential helper to properly queue promises --- packages/frontend-core/src/utils/utils.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/frontend-core/src/utils/utils.js b/packages/frontend-core/src/utils/utils.js index afa88a0624..fc24aa67f1 100644 --- a/packages/frontend-core/src/utils/utils.js +++ b/packages/frontend-core/src/utils/utils.js @@ -5,13 +5,17 @@ * @return {Promise} a sequential version of the function */ export const sequential = fn => { - let promise + let queue = [] return async (...params) => { - if (promise) { - await promise + queue.push(async () => { + await fn(...params) + queue.pop() + if (queue.length) { + await queue[0]() + } + }) + if (queue.length === 1) { + await queue[0]() } - promise = fn(...params) - await promise - promise = null } } From 099bddab914c5010548637b249c0a63cf7bcbf1b Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 14 Jul 2022 16:17:40 +0100 Subject: [PATCH 06/31] Use patches when updating homescreens --- .../src/builderStore/store/frontend.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index fd862dbc80..a2d7fa78ed 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -21,6 +21,7 @@ import { } from "../componentUtils" import { Helpers } from "@budibase/bbui" import { DefaultAppTheme, LAYOUT_NAMES } from "../../constants" +import { Utils } from "@budibase/frontend-core" const INITIAL_FRONTEND_STATE = { apps: [], @@ -228,14 +229,16 @@ export const getFrontendStore = () => { }) return savedScreen }, - patch: async (screenId, patch) => { + patch: Utils.sequential(async (screenId, patchFn) => { const state = get(store) const screen = state.screens.find(screen => screen._id === screenId) if (!screen) { return } - return store.actions.screens.save({ ...screen, ...patch }) - }, + let clone = cloneDeep(screen) + patchFn(clone) + return await store.actions.screens.save(clone) + }), delete: async screens => { const screensToDelete = Array.isArray(screens) ? screens : [screens] @@ -291,14 +294,16 @@ export const getFrontendStore = () => { ) }) if (existingHomeScreen) { - existingHomeScreen.routing.homeScreen = false - promises.push(store.actions.screens.save(existingHomeScreen)) + const patchFn = screen => (screen.routing.homeScreen = false) + promises.push( + store.actions.screens.patch(existingHomeScreen._id, patchFn) + ) } } // Update the passed in screen - screen.routing.homeScreen = makeHomeScreen - promises.push(store.actions.screens.save(screen)) + const patchFn = screen => (screen.routing.homeScreen = makeHomeScreen) + promises.push(store.actions.screens.patch(screen._id, patchFn)) return await Promise.all(promises) }, removeCustomLayout: async screen => { From 99c3323390684fd134ff1121d21aba99f4a82590 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 14 Jul 2022 16:21:37 +0100 Subject: [PATCH 07/31] Use patch when detaching screen custom layouts --- .../builder/src/builderStore/store/frontend.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index a2d7fa78ed..6d836dad65 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -294,25 +294,27 @@ export const getFrontendStore = () => { ) }) if (existingHomeScreen) { - const patchFn = screen => (screen.routing.homeScreen = false) + const patch = screen => (screen.routing.homeScreen = false) promises.push( - store.actions.screens.patch(existingHomeScreen._id, patchFn) + store.actions.screens.patch(existingHomeScreen._id, patch) ) } } // Update the passed in screen - const patchFn = screen => (screen.routing.homeScreen = makeHomeScreen) - promises.push(store.actions.screens.patch(screen._id, patchFn)) + const patch = screen => (screen.routing.homeScreen = makeHomeScreen) + promises.push(store.actions.screens.patch(screen._id, patch)) return await Promise.all(promises) }, removeCustomLayout: async screen => { // Pull relevant settings from old layout, if required const layout = get(store).layouts.find(x => x._id === screen.layoutId) - screen.layoutId = null - screen.showNavigation = layout?.props.navigation !== "None" - screen.width = layout?.props.width || "Large" - await store.actions.screens.save(screen) + const patch = screen => { + screen.layoutId = null + screen.showNavigation = layout?.props.navigation !== "None" + screen.width = layout?.props.width || "Large" + } + await store.actions.screens.patch(screen._id, patch) }, }, preview: { From 56b255cfc908a2cbe5acaac457806aca2174b137 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 14 Jul 2022 16:24:16 +0100 Subject: [PATCH 08/31] Reduce state updates when selecting layouts --- .../src/builderStore/store/frontend.js | 19 ++++++++++++++++--- .../_components/LayoutListPanel.svelte | 2 +- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index 6d836dad65..53189b03f2 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -331,10 +331,23 @@ export const getFrontendStore = () => { }, layouts: { select: layoutId => { + // Check this layout exists + const state = get(store) + const layout = store.actions.layouts.find(layoutId) + if (!layout) { + return + } + + // Check layout isn't already selected + if ( + state.selectedLayoutId === layout._id && + state.selectedComponentId === layout.props?._id + ) { + return + } + + // Select new layout store.update(state => { - const layout = - store.actions.layouts.find(layoutId) || get(store).layouts[0] - if (!layout) return state.selectedLayoutId = layout._id state.selectedComponentId = layout.props?._id return state diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutListPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutListPanel.svelte index fd38f08ceb..cc895317fd 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutListPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/layouts/[layoutId]/_components/LayoutListPanel.svelte @@ -13,7 +13,7 @@ indentLevel={0} selected={$store.selectedLayoutId === layout._id} text={layout.name} - on:click={() => ($store.selectedLayoutId = layout._id)} + on:click={() => store.actions.layouts.select(layout._id)} > From fc927329896e043cd4b2365078a6595aa6294781 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 14 Jul 2022 16:26:18 +0100 Subject: [PATCH 09/31] Remove deprecated layout logic --- .../src/builderStore/store/frontend.js | 32 +------------------ 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index 53189b03f2..58092af31f 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -333,7 +333,7 @@ export const getFrontendStore = () => { select: layoutId => { // Check this layout exists const state = get(store) - const layout = store.actions.layouts.find(layoutId) + const layout = state.layouts.find(layout => layout._id === layoutId) if (!layout) { return } @@ -353,32 +353,6 @@ export const getFrontendStore = () => { return state }) }, - save: async layout => { - const creatingNewLayout = layout._id === undefined - const savedLayout = await API.saveLayout(layout) - store.update(state => { - const idx = state.layouts.findIndex(x => x._id === savedLayout._id) - if (idx !== -1) { - state.layouts.splice(idx, 1, savedLayout) - } else { - state.layouts.push(savedLayout) - } - return state - }) - - // Select layout if creating a new one - if (creatingNewLayout) { - store.actions.layouts.select(savedLayout._id) - } - return savedLayout - }, - find: layoutId => { - if (!layoutId) { - return get(mainLayout) - } - const storeContents = get(store) - return storeContents.layouts.find(layout => layout._id === layoutId) - }, delete: async layout => { if (!layout?._id) { return @@ -388,10 +362,6 @@ export const getFrontendStore = () => { layoutRev: layout._rev, }) store.update(state => { - // Select main layout if we deleted the selected layout - if (layout._id === state.selectedLayoutId) { - state.selectedLayoutId = get(mainLayout)._id - } state.layouts = state.layouts.filter(x => x._id !== layout._id) return state }) From 6368a2aaac9c19a887dbe4194d6b70251a37721e Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 14 Jul 2022 16:48:07 +0100 Subject: [PATCH 10/31] Use patch when creating new components --- .../src/builderStore/store/frontend.js | 82 +++++++++++-------- 1 file changed, 48 insertions(+), 34 deletions(-) diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index 58092af31f..675d97fabb 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -1,6 +1,6 @@ import { get, writable } from "svelte/store" import { cloneDeep } from "lodash/fp" -import { currentAsset, mainLayout, selectedComponent } from "builderStore" +import { currentAsset, selectedScreen, selectedComponent } from "builderStore" import { datasources, integrations, @@ -183,7 +183,6 @@ export const getFrontendStore = () => { // Check this screen exists const state = get(store) const screen = state.screens.find(screen => screen._id === screenId) - console.log(screen) if (!screen) { return } @@ -236,7 +235,10 @@ export const getFrontendStore = () => { return } let clone = cloneDeep(screen) - patchFn(clone) + const result = patchFn(clone) + if (result === false) { + return + } return await store.actions.screens.save(clone) }), delete: async screens => { @@ -420,48 +422,60 @@ export const getFrontendStore = () => { } }, create: async (componentName, presetProps) => { - const selected = get(selectedComponent) - const asset = get(currentAsset) - - // Create new component + const state = get(store) const componentInstance = store.actions.components.createInstance( componentName, presetProps ) - if (!componentInstance || !asset) { + if (!componentInstance) { return } - // Find parent node to attach this component to - let parentComponent - if (selected) { - // Use current screen or layout as parent if no component is selected - const definition = store.actions.components.getDefinition( - selected._component + // Create screen patch function + const patch = screen => { + // Find the selected component + const currentComponent = findComponent( + screen.props, + state.selectedComponentId ) - if (definition?.hasChildren) { - // Use selected component if it allows children - parentComponent = selected - } else { - // Otherwise we need to use the parent of this component - parentComponent = findComponentParent(asset?.props, selected._id) + if (!currentComponent) { + return false } - } else { - // Use screen or layout if no component is selected - parentComponent = asset?.props - } - // Attach component - if (!parentComponent) { - return - } - if (!parentComponent._children) { - parentComponent._children = [] - } - parentComponent._children.push(componentInstance) + // Find parent node to attach this component to + let parentComponent + if (currentComponent) { + // Use selected component as parent if one is selected + const definition = store.actions.components.getDefinition( + currentComponent._component + ) + if (definition?.hasChildren) { + // Use selected component if it allows children + parentComponent = currentComponent + } else { + // Otherwise we need to use the parent of this component + parentComponent = findComponentParent( + screen.props, + currentComponent._id + ) + } + } else { + // Use screen or layout if no component is selected + parentComponent = screen.props + } - // Save components and update UI - await store.actions.preview.saveSelected() + // Attach new component + if (!parentComponent) { + return false + } + if (!parentComponent._children) { + parentComponent._children = [] + } + parentComponent._children.push(componentInstance) + } + await store.actions.screens.patch(state.selectedScreenId, patch) + + // Select new component store.update(state => { state.selectedComponentId = componentInstance._id return state From 5a12e30f915e38085035538f3794a86a4457e7e7 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 14 Jul 2022 16:55:15 +0100 Subject: [PATCH 11/31] Use patch when deleting components --- .../src/builderStore/store/frontend.js | 51 +++++++++---------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index 675d97fabb..63c6073efd 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -431,7 +431,7 @@ export const getFrontendStore = () => { return } - // Create screen patch function + // Patch screen const patch = screen => { // Find the selected component const currentComponent = findComponent( @@ -492,39 +492,34 @@ export const getFrontendStore = () => { if (!component) { return } - const asset = get(currentAsset) - if (!asset) { - return - } + const state = get(store) + let parentId - // Fetch full definition - component = findComponent(asset.props, component._id) + // Patch screen + const patch = screen => { + // Check component exists + component = findComponent(screen.props, component._id) + if (!component) { + return false + } - // Ensure we aren't deleting the screen slot - if (component._component?.endsWith("/screenslot")) { - throw "You can't delete the screen slot" - } - - // Ensure we aren't deleting something that contains the screen slot - const screenslot = findComponentType( - component, - "@budibase/standard-components/screenslot" - ) - if (screenslot != null) { - throw "You can't delete a component that contains the screen slot" - } - - const parent = findComponentParent(asset.props, component._id) - if (parent) { + // Check component has a valid parent + const parent = findComponentParent(screen.props, component._id) + if (!parent) { + return false + } + parentId = parent._id parent._children = parent._children.filter( child => child._id !== component._id ) - store.update(state => { - state.selectedComponentId = parent._id - return state - }) } - await store.actions.preview.saveSelected() + await store.actions.screens.patch(state.selectedScreenId, patch) + + // Select the deleted component's parent + store.update(state => { + state.selectedComponentId = parentId + return state + }) }, copy: (component, cut = false, selectParent = true) => { const selectedAsset = get(currentAsset) From 5cdd37f6d8f488a0d02d43c7cf6066018f2d32ce Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 14 Jul 2022 17:55:35 +0100 Subject: [PATCH 12/31] Update cut+paste so cut doesn't actually remove the component from the tree and use new patch function --- .../src/builderStore/store/frontend.js | 76 +++++++++++-------- .../navigation/ComponentTree.svelte | 9 ++- 2 files changed, 52 insertions(+), 33 deletions(-) diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index 63c6073efd..e0ddd00bd8 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -534,13 +534,10 @@ export const getFrontendStore = () => { return state }) - // Remove the component from its parent if we're cutting + // Select the parent if cutting if (cut) { const parent = findComponentParent(selectedAsset.props, component._id) if (parent) { - parent._children = parent._children.filter( - child => child._id !== component._id - ) if (selectParent) { store.update(state => { state.selectedComponentId = parent._id @@ -551,23 +548,41 @@ export const getFrontendStore = () => { } }, paste: async (targetComponent, mode) => { - let promises = [] - store.update(state => { - // Stop if we have nothing to paste - if (!state.componentToPaste) { - return state + const state = get(store) + if (!state.componentToPaste) { + return + } + let newComponentId + + // Patch screen + const patch = screen => { + // Get up to date ref to target + targetComponent = findComponent(screen.props, targetComponent._id) + if (!targetComponent) { + return } const cut = state.componentToPaste.isCut - - // Clone the component to paste and make unique if copying - delete state.componentToPaste.isCut + const originalId = state.componentToPaste._id let componentToPaste = cloneDeep(state.componentToPaste) - if (cut) { - state.componentToPaste = null - } else { + delete componentToPaste.isCut + + // Make new component unique if copying + if (!cut) { makeComponentUnique(componentToPaste) } + newComponentId = componentToPaste._id + // Delete old component if cutting + if (cut) { + const parent = findComponentParent(screen.props, originalId) + if (parent?._children) { + parent._children = parent._children.filter( + component => component._id !== originalId + ) + } + } + + // Paste new component if (mode === "inside") { // Paste inside target component if chosen if (!targetComponent._children) { @@ -575,32 +590,29 @@ export const getFrontendStore = () => { } targetComponent._children.push(componentToPaste) } else { - // Otherwise find the parent so we can paste in the correct order - // in the parents child components - const selectedAsset = get(currentAsset) - if (!selectedAsset) { - return state - } + // Otherwise paste in the correct order in the parent's children const parent = findComponentParent( - selectedAsset.props, + screen.props, targetComponent._id ) - if (!parent) { - return state + if (!parent?._children) { + return false } - - // Insert the component in the correct position - const targetIndex = parent._children.indexOf(targetComponent) + const targetIndex = parent._children.findIndex(component => { + return component._id === targetComponent._id + }) const index = mode === "above" ? targetIndex : targetIndex + 1 - parent._children.splice(index, 0, cloneDeep(componentToPaste)) + parent._children.splice(index, 0, componentToPaste) } + } + await store.actions.screens.patch(state.selectedScreenId, patch) - // Save and select the new component - promises.push(store.actions.preview.saveSelected()) - state.selectedComponentId = componentToPaste._id + // Update state + store.update(state => { + delete state.componentToPaste + state.selectedComponentId = newComponentId return state }) - await Promise.all(promises) }, updateStyle: async (name, value) => { const selected = get(selectedComponent) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentTree.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentTree.svelte index cc7f70f2c5..6704027f35 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentTree.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentTree.svelte @@ -18,6 +18,13 @@ let closedNodes = {} + $: filteredComponents = components?.filter(component => { + return ( + !$store.componentToPaste?.isCut || + component._id !== $store.componentToPaste?._id + ) + }) + const dragover = (component, index) => e => { const mousePosition = e.offsetY / e.currentTarget.offsetHeight dndStore.actions.dragover({ @@ -91,7 +98,7 @@
    - {#each components || [] as component, index (component._id)} + {#each filteredComponents || [] as component, index (component._id)} {@const opened = isOpen(component, $selectedComponentPath, closedNodes)}
  • { From 587b385a47b7b545fb43b4e00f9a65688abbbc15 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 15 Jul 2022 08:22:06 +0100 Subject: [PATCH 13/31] Use patch for all component methods, add core component patch function, add component move functions to store --- .../src/builderStore/store/frontend.js | 189 ++++++++++++------ .../navigation/ComponentDropdownMenu.svelte | 36 +--- .../settings/ComponentSettingsSection.svelte | 4 +- 3 files changed, 131 insertions(+), 98 deletions(-) diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index e0ddd00bd8..aaf796fb9b 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -11,7 +11,6 @@ import { import { API } from "api" import analytics, { Events } from "analytics" import { - findComponentType, findComponentParent, findClosestMatchingComponent, findAllMatchingComponents, @@ -62,7 +61,21 @@ const INITIAL_FRONTEND_STATE = { export const getFrontendStore = () => { const store = writable({ ...INITIAL_FRONTEND_STATE }) - store.subscribe(state => { + const sequentialScreenPatch = Utils.sequential(async (patchFn, screenId) => { + const state = get(store) + const screen = state.screens.find(screen => screen._id === screenId) + if (!screen) { + return + } + let clone = cloneDeep(screen) + const result = patchFn(clone) + if (result === false) { + return + } + return await store.actions.screens.save(clone) + }) + + store.subscribe(() => { console.log("new state") }) @@ -228,19 +241,17 @@ export const getFrontendStore = () => { }) return savedScreen }, - patch: Utils.sequential(async (screenId, patchFn) => { - const state = get(store) - const screen = state.screens.find(screen => screen._id === screenId) - if (!screen) { + patch: async (patchFn, screenId) => { + // Default to the currently selected screen + if (!screenId) { + const state = get(store) + screenId = state.selectedScreenId + } + if (!screenId || !patchFn) { return } - let clone = cloneDeep(screen) - const result = patchFn(clone) - if (result === false) { - return - } - return await store.actions.screens.save(clone) - }), + return await sequentialScreenPatch(patchFn, screenId) + }, delete: async screens => { const screensToDelete = Array.isArray(screens) ? screens : [screens] @@ -282,7 +293,9 @@ export const getFrontendStore = () => { }) }, updateHomeScreen: async (screen, makeHomeScreen = true) => { - let promises = [] + if (!screen) { + return + } // Find any existing home screen for this role so we can remove it, // if we are setting this to be the new home screen @@ -297,16 +310,13 @@ export const getFrontendStore = () => { }) if (existingHomeScreen) { const patch = screen => (screen.routing.homeScreen = false) - promises.push( - store.actions.screens.patch(existingHomeScreen._id, patch) - ) + await store.actions.screens.patch(patch, existingHomeScreen._id) } } // Update the passed in screen const patch = screen => (screen.routing.homeScreen = makeHomeScreen) - promises.push(store.actions.screens.patch(screen._id, patch)) - return await Promise.all(promises) + await store.actions.screens.patch(patch, screen._id) }, removeCustomLayout: async screen => { // Pull relevant settings from old layout, if required @@ -316,14 +326,10 @@ export const getFrontendStore = () => { screen.showNavigation = layout?.props.navigation !== "None" screen.width = layout?.props.width || "Large" } - await store.actions.screens.patch(screen._id, patch) + await store.actions.screens.patch(patch, screen._id) }, }, preview: { - saveSelected: async () => { - const selectedAsset = get(currentAsset) - return await store.actions.screens.save(selectedAsset) - }, setDevice: device => { store.update(state => { state.previewDevice = device @@ -431,8 +437,8 @@ export const getFrontendStore = () => { return } - // Patch screen - const patch = screen => { + // Patch selected screen + await store.actions.screens.patch(screen => { // Find the selected component const currentComponent = findComponent( screen.props, @@ -472,8 +478,7 @@ export const getFrontendStore = () => { parentComponent._children = [] } parentComponent._children.push(componentInstance) - } - await store.actions.screens.patch(state.selectedScreenId, patch) + }) // Select new component store.update(state => { @@ -488,15 +493,34 @@ export const getFrontendStore = () => { return componentInstance }, + patch: async (patchFn, componentId, screenId) => { + // Use selected component by default + if (!componentId && !screenId) { + const state = get(store) + componentId = state.selectedComponentId + screenId = state.selectedScreenId + } + // Invalid if only a screen or component ID provided + if (!componentId || !screenId || !patchFn) { + return + } + const patchScreen = screen => { + let component = findComponent(screen.props, componentId) + if (!component) { + return false + } + return patchFn(component, screen) + } + await store.actions.screens.patch(patchScreen, screenId) + }, delete: async component => { if (!component) { return } - const state = get(store) let parentId // Patch screen - const patch = screen => { + await store.actions.screens.patch(screen => { // Check component exists component = findComponent(screen.props, component._id) if (!component) { @@ -512,8 +536,7 @@ export const getFrontendStore = () => { parent._children = parent._children.filter( child => child._id !== component._id ) - } - await store.actions.screens.patch(state.selectedScreenId, patch) + }) // Select the deleted component's parent store.update(state => { @@ -522,11 +545,6 @@ export const getFrontendStore = () => { }) }, copy: (component, cut = false, selectParent = true) => { - const selectedAsset = get(currentAsset) - if (!selectedAsset) { - return null - } - // Update store with copied component store.update(state => { state.componentToPaste = cloneDeep(component) @@ -536,7 +554,8 @@ export const getFrontendStore = () => { // Select the parent if cutting if (cut) { - const parent = findComponentParent(selectedAsset.props, component._id) + const screen = get(selectedScreen) + const parent = findComponentParent(screen?.props, component._id) if (parent) { if (selectParent) { store.update(state => { @@ -555,7 +574,7 @@ export const getFrontendStore = () => { let newComponentId // Patch screen - const patch = screen => { + await store.actions.screens.patch(screen => { // Get up to date ref to target targetComponent = findComponent(screen.props, targetComponent._id) if (!targetComponent) { @@ -604,8 +623,7 @@ export const getFrontendStore = () => { const index = mode === "above" ? targetIndex : targetIndex + 1 parent._children.splice(index, 0, componentToPaste) } - } - await store.actions.screens.patch(state.selectedScreenId, patch) + }) // Update state store.update(state => { @@ -614,39 +632,78 @@ export const getFrontendStore = () => { return state }) }, + moveUp: async component => { + await store.actions.screens.patch(screen => { + const componentId = component?._id + const parent = findComponentParent(screen.props, componentId) + if (!parent?._children?.length) { + return false + } + const currentIndex = parent._children.findIndex( + child => child._id === componentId + ) + if (currentIndex === 0) { + return false + } + const originalComponent = cloneDeep(parent._children[currentIndex]) + const newChildren = parent._children.filter( + component => component._id !== componentId + ) + newChildren.splice(currentIndex - 1, 0, originalComponent) + parent._children = newChildren + }) + }, + moveDown: async component => { + await store.actions.screens.patch(screen => { + const componentId = component?._id + const parent = findComponentParent(screen.props, componentId) + if (!parent?._children?.length) { + return false + } + const currentIndex = parent._children.findIndex( + child => child._id === componentId + ) + if (currentIndex === parent._children.length - 1) { + return false + } + const originalComponent = cloneDeep(parent._children[currentIndex]) + const newChildren = parent._children.filter( + component => component._id !== componentId + ) + newChildren.splice(currentIndex + 1, 0, originalComponent) + parent._children = newChildren + }) + }, updateStyle: async (name, value) => { - const selected = get(selectedComponent) - if (value == null || value === "") { - delete selected._styles.normal[name] - } else { - selected._styles.normal[name] = value - } - await store.actions.preview.saveSelected() + await store.actions.components.patch(component => { + if (value == null || value === "") { + delete component._styles.normal[name] + } else { + component._styles.normal[name] = value + } + }) }, updateCustomStyle: async style => { - const selected = get(selectedComponent) - selected._styles.custom = style - await store.actions.preview.saveSelected() + await store.actions.components.patch(component => { + component._styles.custom = style + }) }, updateConditions: async conditions => { - const selected = get(selectedComponent) - selected._conditions = conditions - await store.actions.preview.saveSelected() + await store.actions.components.patch(component => { + component._conditions = conditions + }) }, updateProp: async (name, value) => { - let component = get(selectedComponent) - if (!name || !component) { - return - } - if (component[name] === value) { - return - } - component[name] = value - store.update(state => { - state.selectedComponentId = component._id - return state + await store.actions.components.patch(component => { + if (!name || !component) { + return false + } + // Skip update if the value is the same + if (component[name] === value) { + return false + } + component[name] = value }) - await store.actions.preview.saveSelected() }, }, links: { diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentDropdownMenu.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentDropdownMenu.svelte index ae031e14bd..73159f1088 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentDropdownMenu.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentDropdownMenu.svelte @@ -19,43 +19,19 @@ // not show a context menu. $: showMenu = definition?.editable !== false && definition?.static !== true - const moveUpComponent = () => { - const asset = get(currentAsset) - const parent = findComponentParent(asset?.props, component._id) - if (!parent) { - return - } - const currentIndex = parent._children.indexOf(component) - if (currentIndex === 0) { - return - } + const moveUpComponent = async () => { try { - const newChildren = parent._children.filter(c => c !== component) - newChildren.splice(currentIndex - 1, 0, component) - parent._children = newChildren - store.actions.preview.saveSelected() + await store.actions.components.moveUp(component) } catch (error) { - notifications.error("Error saving screen") + notifications.error("Error moving component up") } } - const moveDownComponent = () => { - const asset = get(currentAsset) - const parent = findComponentParent(asset?.props, component._id) - if (!parent) { - return - } - const currentIndex = parent._children.indexOf(component) - if (currentIndex === parent._children.length - 1) { - return - } + const moveDownComponent = async () => { try { - const newChildren = parent._children.filter(c => c !== component) - newChildren.splice(currentIndex + 1, 0, component) - parent._children = newChildren - store.actions.preview.saveSelected() + await store.actions.components.moveDown(component) } catch (error) { - notifications.error("Error saving screen") + notifications.error("Error moving component down") } } 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 ba16c705f6..b10e6a68a1 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 @@ -29,13 +29,13 @@ ] } - const updateProp = Utils.sequential(async (key, value) => { + const updateProp = async (key, value) => { try { await store.actions.components.updateProp(key, value) } catch (error) { notifications.error("Error updating component prop") } - }) + } const canRenderControl = setting => { const control = getComponentForSetting(setting) From edfb0fa50dd18581e6ee977abb1de8c4edd420c3 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 15 Jul 2022 08:27:35 +0100 Subject: [PATCH 14/31] Ensure state never gets out of sync when saving app metadata by using server response to update state --- packages/builder/src/builderStore/index.js | 14 ++++---------- .../builder/src/builderStore/store/frontend.js | 16 ++++++++-------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/packages/builder/src/builderStore/index.js b/packages/builder/src/builderStore/index.js index 28ef1f4376..35c4587874 100644 --- a/packages/builder/src/builderStore/index.js +++ b/packages/builder/src/builderStore/index.js @@ -2,7 +2,6 @@ import { getFrontendStore } from "./store/frontend" import { getAutomationStore } from "./store/automation" import { getThemeStore } from "./store/theme" import { derived } from "svelte/store" -import { LAYOUT_NAMES } from "../constants" import { findComponent, findComponentPath } from "./componentUtils" import { RoleUtils } from "@budibase/frontend-core" @@ -28,6 +27,10 @@ export const selectedComponent = derived( } ) +// For legacy compatibility only, but with the new design UI this is just +// the selected screen +export const currentAsset = selectedScreen + export const sortedScreens = derived(store, $store => { return $store.screens.slice().sort((a, b) => { // Sort by role first @@ -66,12 +69,3 @@ export const selectedComponentPath = derived( ).map(component => component._id) } ) - -export const mainLayout = derived(store, $store => { - return $store.layouts?.find( - layout => layout._id === LAYOUT_NAMES.MASTER.PRIVATE - ) -}) - -// For compatibility -export const currentAsset = selectedScreen diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index aaf796fb9b..75cc4cd2cc 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -1,6 +1,6 @@ import { get, writable } from "svelte/store" import { cloneDeep } from "lodash/fp" -import { currentAsset, selectedScreen, selectedComponent } from "builderStore" +import { selectedScreen, selectedComponent } from "builderStore" import { datasources, integrations, @@ -155,12 +155,12 @@ export const getFrontendStore = () => { theme: { save: async theme => { const appId = get(store).appId - await API.saveAppMetadata({ + const app = await API.saveAppMetadata({ appId, metadata: { theme }, }) store.update(state => { - state.theme = theme + state.theme = app.theme return state }) }, @@ -168,12 +168,12 @@ export const getFrontendStore = () => { customTheme: { save: async customTheme => { const appId = get(store).appId - await API.saveAppMetadata({ + const app = await API.saveAppMetadata({ appId, metadata: { customTheme }, }) store.update(state => { - state.customTheme = customTheme + state.customTheme = app.customTheme return state }) }, @@ -181,12 +181,12 @@ export const getFrontendStore = () => { navigation: { save: async navigation => { const appId = get(store).appId - await API.saveAppMetadata({ + const app = await API.saveAppMetadata({ appId, metadata: { navigation }, }) store.update(state => { - state.navigation = navigation + state.navigation = app.navigation return state }) }, @@ -407,7 +407,7 @@ export const getFrontendStore = () => { } if (componentName.endsWith("/formstep")) { const parentForm = findClosestMatchingComponent( - get(currentAsset).props, + get(selectedScreen).props, get(selectedComponent)._id, component => component._component.endsWith("/form") ) From 66126531e3c05be647a8be665f5354cfa7b371e1 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 15 Jul 2022 08:39:31 +0100 Subject: [PATCH 15/31] Update screen settings to use patches --- .../src/builderStore/store/frontend.js | 8 +++++-- .../_components/ScreenSettingsPanel.svelte | 24 ++++++------------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index 75cc4cd2cc..71e422f8ae 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -309,13 +309,17 @@ export const getFrontendStore = () => { ) }) if (existingHomeScreen) { - const patch = screen => (screen.routing.homeScreen = false) + const patch = screen => { + screen.routing.homeScreen = false + } await store.actions.screens.patch(patch, existingHomeScreen._id) } } // Update the passed in screen - const patch = screen => (screen.routing.homeScreen = makeHomeScreen) + const patch = screen => { + screen.routing.homeScreen = makeHomeScreen + } await store.actions.screens.patch(patch, screen._id) }, removeCustomLayout: async screen => { diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel.svelte index 0d861d1cd8..c30c78d3b6 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel.svelte @@ -42,7 +42,7 @@ ) } - const setScreenSetting = (setting, value) => { + const setScreenSetting = async (setting, value) => { const { key, parser, validate } = setting // Parse value if required @@ -69,26 +69,16 @@ // Home screen changes need to be handled manually if (key === "routing.homeScreen") { - store.actions.screens.updateHomeScreen(get(selectedScreen), value) + console.log(value) + await store.actions.screens.updateHomeScreen(get(selectedScreen), value) return } - // Update screen object in store - // If there are 2 home screens after this change, remove this screen as a - // home screen - const screen = get(selectedScreen) - setWith(screen, key.split("."), value, Object) - const roleId = screen.routing.roleId - const homeScreens = get(store).screens.filter(screen => { - return screen.routing.roleId === roleId && screen.routing.homeScreen - }) - if (homeScreens.length > 1) { - screen.routing.homeScreen = false - } - - // Save new definition + // Update screen setting try { - store.actions.screens.save(screen) + await store.actions.screens.patch(screen => { + setWith(screen, key.split("."), value, Object) + }) } catch (error) { notifications.error("Error saving screen settings") } From aa1c0298bc868b41e65007b44862d4265974ea1b Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 15 Jul 2022 09:03:29 +0100 Subject: [PATCH 16/31] Move screen setting updates into store and use patches. Make screen settings generic --- .../src/builderStore/store/frontend.js | 59 +++++++++++-------- .../controls/ResetFieldsButton.svelte | 2 +- .../[screenId]/_components/AppPreview.svelte | 2 +- .../settings/ComponentSettingsSection.svelte | 9 ++- .../_components/ScreenSettingsPanel.svelte | 16 ++--- 5 files changed, 45 insertions(+), 43 deletions(-) diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index 71e422f8ae..0a12d348bc 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -292,35 +292,46 @@ export const getFrontendStore = () => { return state }) }, - updateHomeScreen: async (screen, makeHomeScreen = true) => { - if (!screen) { + updateSetting: async (screen, name, value) => { + if (!screen || !name) { return } - // Find any existing home screen for this role so we can remove it, - // if we are setting this to be the new home screen - if (makeHomeScreen) { - const roleId = screen.routing.roleId - let existingHomeScreen = get(store).screens.find(s => { - return ( - s.routing.roleId === roleId && - s.routing.homeScreen && - s._id !== screen._id - ) - }) - if (existingHomeScreen) { - const patch = screen => { - screen.routing.homeScreen = false - } - await store.actions.screens.patch(patch, existingHomeScreen._id) - } - } - - // Update the passed in screen + // Apply setting update const patch = screen => { - screen.routing.homeScreen = makeHomeScreen + if (!screen) { + return false + } + // Skip update if the value is the same + if (Helpers.deepGet(screen, name) === value) { + return false + } + Helpers.deepSet(screen, name, value) } await store.actions.screens.patch(patch, screen._id) + + // Ensure we don't have more than one home screen for this new role. + // This could happen after updating multiple different settings. + const state = get(store) + const updatedScreen = state.screens.find(s => s._id === screen._id) + if (!updatedScreen) { + return + } + const otherHomeScreens = state.screens.filter(s => { + return ( + s.routing.roleId === updatedScreen.routing.roleId && + s.routing.homeScreen && + s._id !== screen._id + ) + }) + if (otherHomeScreens.length) { + const patch = screen => { + screen.routing.homeScreen = false + } + for (let otherHomeScreen of otherHomeScreens) { + await store.actions.screens.patch(patch, otherHomeScreen._id) + } + } }, removeCustomLayout: async screen => { // Pull relevant settings from old layout, if required @@ -697,7 +708,7 @@ export const getFrontendStore = () => { component._conditions = conditions }) }, - updateProp: async (name, value) => { + updateSetting: async (name, value) => { await store.actions.components.patch(component => { if (!name || !component) { return false diff --git a/packages/builder/src/components/design/settings/controls/ResetFieldsButton.svelte b/packages/builder/src/components/design/settings/controls/ResetFieldsButton.svelte index e927526b92..16aaf91ce2 100644 --- a/packages/builder/src/components/design/settings/controls/ResetFieldsButton.svelte +++ b/packages/builder/src/components/design/settings/controls/ResetFieldsButton.svelte @@ -18,7 +18,7 @@ const dataSource = form?.dataSource const fields = makeDatasourceFormComponents(dataSource) try { - await store.actions.components.updateProp( + await store.actions.components.updateSetting( "_children", fields.map(field => field.json()) ) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte index e332f8e896..c15fa23ebe 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte @@ -138,7 +138,7 @@ $goto("./components") } } else if (type === "update-prop") { - await store.actions.components.updateProp(data.prop, data.value) + await store.actions.components.updateSetting(data.prop, data.value) } else if (type === "delete-component" && data.id) { confirmDeleteComponent(data.id) } else if (type === "duplicate-component" && data.id) { 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 b10e6a68a1..d8dc9bf066 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 @@ -5,7 +5,6 @@ import PropertyControl from "components/design/settings/controls/PropertyControl.svelte" import ResetFieldsButton from "components/design/settings/controls/ResetFieldsButton.svelte" import { getComponentForSetting } from "components/design/settings/componentSettings" - import { Utils } from "@budibase/frontend-core" export let componentDefinition export let componentInstance @@ -29,9 +28,9 @@ ] } - const updateProp = async (key, value) => { + const updateSetting = async (key, value) => { try { - await store.actions.components.updateProp(key, value) + await store.actions.components.updateSetting(key, value) } catch (error) { notifications.error("Error updating component prop") } @@ -84,7 +83,7 @@ label="Name" key="_instanceName" value={componentInstance._instanceName} - onChange={val => updateProp("_instanceName", val)} + onChange={val => updateSetting("_instanceName", val)} /> {/if} {#each section.settings as setting (setting.key)} @@ -97,7 +96,7 @@ value={componentInstance[setting.key]} defaultValue={setting.defaultValue} nested={setting.nested} - onChange={val => updateProp(setting.key, val)} + onChange={val => updateSetting(setting.key, val)} highlighted={$store.highlightedSettingKey === setting.key} props={{ // Generic settings diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel.svelte index c30c78d3b6..e6779d542c 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/screens/_components/ScreenSettingsPanel.svelte @@ -1,7 +1,7 @@ -{#if constructor && initialSettings && (visible || inSelectedPath)} +{#if constructor && initialSettings && (visible || inSelectedPath) && !builderHidden}
    { customTheme: window["##BUDIBASE_PREVIEW_CUSTOM_THEME##"], previewDevice: window["##BUDIBASE_PREVIEW_DEVICE##"], navigation: window["##BUDIBASE_PREVIEW_NAVIGATION##"], + hiddenComponentIds: window["##BUDIBASE_HIDDEN_COMPONENT_IDS##"], }) // Set app ID - this window flag is set by both the preview and the real diff --git a/packages/client/src/stores/builder.js b/packages/client/src/stores/builder.js index 94436b53b7..9d85eee022 100644 --- a/packages/client/src/stores/builder.js +++ b/packages/client/src/stores/builder.js @@ -17,6 +17,7 @@ const createBuilderStore = () => { previewDevice: "desktop", isDragging: false, navigation: null, + hiddenComponentIds: [], // Legacy - allow the builder to specify a layout layout: null, From f0e84b94f5fc28bb7cd141dabfe780766bb186c6 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 15 Jul 2022 12:01:07 +0100 Subject: [PATCH 21/31] Fix bug with sequential helper --- packages/frontend-core/src/utils/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend-core/src/utils/utils.js b/packages/frontend-core/src/utils/utils.js index fc24aa67f1..71688981a9 100644 --- a/packages/frontend-core/src/utils/utils.js +++ b/packages/frontend-core/src/utils/utils.js @@ -9,7 +9,7 @@ export const sequential = fn => { return async (...params) => { queue.push(async () => { await fn(...params) - queue.pop() + queue.shift() if (queue.length) { await queue[0]() } From d05564332ee896298d38980977168a892035292c Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 15 Jul 2022 12:27:48 +0100 Subject: [PATCH 22/31] Lint --- .../_components/navigation/ComponentDropdownMenu.svelte | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentDropdownMenu.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentDropdownMenu.svelte index 73159f1088..ed66c66c29 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentDropdownMenu.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/navigation/ComponentDropdownMenu.svelte @@ -1,8 +1,6 @@