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 fa126bbc99..ae5866d12e 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
@@ -10,6 +10,7 @@
navigationStore,
selectedScreen,
hoverStore,
+ componentTreeNodesStore,
} from "stores/builder"
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
import {
@@ -130,6 +131,13 @@
error = event.error || "An unknown error occurred"
} else if (type === "select-component" && data.id) {
componentStore.select(data.id)
+
+ const componentPath = findComponentPath(
+ $selectedScreen?.props,
+ data.id
+ ).map(component => component._id)
+
+ componentTreeNodesStore.expandNodes(componentPath)
} else if (type === "hover-component") {
hoverStore.hover(data.id, false)
} else if (type === "update-prop") {
diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/ComponentKeyHandler.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/ComponentKeyHandler.svelte
index f6bbac39a5..df0d361290 100644
--- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/ComponentKeyHandler.svelte
+++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/ComponentKeyHandler.svelte
@@ -4,12 +4,12 @@
selectedScreen,
componentStore,
selectedComponent,
+ componentTreeNodesStore
} from "stores/builder"
import { findComponent } from "helpers/components"
import { goto, isActive } from "@roxi/routify"
import { notifications } from "@budibase/bbui"
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
- import componentTreeNodesStore from "stores/portal/componentTreeNodesStore"
let confirmDeleteDialog
let confirmEjectDialog
@@ -66,6 +66,7 @@
componentTreeNodesStore.expandNode(component._id)
},
["ArrowLeft"]: component => {
+ componentStore.select(component._id)
componentTreeNodesStore.collapseNode(component._id)
},
["Ctrl+ArrowRight"]: component => {
@@ -83,6 +84,7 @@
expandChildren(component)
},
["Ctrl+ArrowLeft"]: component => {
+ componentStore.select(component._id)
componentTreeNodesStore.collapseNode(component._id)
const collapseChildren = component => {
diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/ComponentTree.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/ComponentTree.svelte
index f24235ad07..b8e5720eea 100644
--- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/ComponentTree.svelte
+++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/ComponentTree.svelte
@@ -7,8 +7,8 @@
componentStore,
userSelectedResourceMap,
selectedComponent,
- selectedComponentPath,
hoverStore,
+ componentTreeNodesStore
} from "stores/builder"
import {
findComponentPath,
@@ -17,7 +17,6 @@
} from "helpers/components"
import { get } from "svelte/store"
import { dndStore } from "./dndStore"
- import componentTreeNodesStore from "stores/portal/componentTreeNodesStore"
export let components = []
export let level = 0
@@ -64,14 +63,11 @@
}
}
- const isOpen = (component, selectedComponentPath, openNodes) => {
+ const isOpen = (component, openNodes) => {
if (!component?._children?.length) {
return false
}
- if (selectedComponentPath.slice(0, -1).includes(component._id)) {
- return true
- }
- return openNodes[`nodeOpen-${component._id}`]
+ return openNodes[`nodeOpen-${component._id}`] !== false
}
const isChildOfSelectedComponent = component => {
@@ -90,7 +86,7 @@
{#each filteredComponents || [] as component, index (component._id)}
- {@const opened = isOpen(component, $selectedComponentPath, openNodes)}
+ {@const opened = isOpen(component, openNodes)}
- {
componentStore.select(component._id)
diff --git a/packages/builder/src/stores/portal/componentTreeNodesStore.js b/packages/builder/src/stores/builder/componentTreeNodes.js
similarity index 76%
rename from packages/builder/src/stores/portal/componentTreeNodesStore.js
rename to packages/builder/src/stores/builder/componentTreeNodes.js
index a6c07ae03b..f6d3a80c43 100644
--- a/packages/builder/src/stores/portal/componentTreeNodesStore.js
+++ b/packages/builder/src/stores/builder/componentTreeNodes.js
@@ -18,6 +18,14 @@ const expandNode = componentId => {
})
}
+const expandNodes = componentIds => {
+ baseStore.update(openNodes => {
+ const newNodes = Object.fromEntries(componentIds.map(id => ([`nodeOpen-${id}`, true])))
+
+ return { ...openNodes, ...newNodes };
+ })
+}
+
const collapseNode = componentId => {
baseStore.update(openNodes => {
openNodes[`nodeOpen-${componentId}`] = false
@@ -30,6 +38,7 @@ const store = {
subscribe: baseStore.subscribe,
toggleNode,
expandNode,
+ expandNodes,
collapseNode,
}
diff --git a/packages/builder/src/stores/builder/components.js b/packages/builder/src/stores/builder/components.js
index d7572dca60..6dc1a1c96b 100644
--- a/packages/builder/src/stores/builder/components.js
+++ b/packages/builder/src/stores/builder/components.js
@@ -19,6 +19,7 @@ import {
appStore,
previewStore,
tables,
+ componentTreeNodesStore
} from "stores/builder/index"
import { buildFormSchema, getSchemaForDatasource } from "dataBinding"
import {
@@ -29,7 +30,6 @@ import {
} from "constants/backend"
import BudiStore from "./BudiStore"
import { Utils } from "@budibase/frontend-core"
-import componentTreeNodesStore from "stores/portal/componentTreeNodesStore"
export const INITIAL_COMPONENTS_STATE = {
components: {},
@@ -653,6 +653,16 @@ export class ComponentStore extends BudiStore {
this.update(state => {
state.selectedScreenId = targetScreenId
state.selectedComponentId = newComponentId
+
+ const targetScreen = get(screenStore).screens.find(screen => screen.id === targetScreenId)
+
+ const componentPathIds = findComponentPath(
+ targetScreen?.props,
+ newComponentId
+ ).map(component => component._id)
+
+ componentTreeNodesStore.expandNodes(componentPathIds)
+
return state
})
}
@@ -680,16 +690,16 @@ export class ComponentStore extends BudiStore {
// If we have siblings above us, choose the sibling or a descendant
if (index > 0) {
- // If sibling before us accepts children, select a descendant
+ // If sibling before us accepts children, and is not collapsed, select a descendant
const previousSibling = parent._children[index - 1]
if (
previousSibling._children?.length &&
- componentTreeNodes[`nodeOpen-${previousSibling._id}`]
+ componentTreeNodes[`nodeOpen-${previousSibling._id}`] !== false
) {
let target = previousSibling
while (
target._children?.length &&
- componentTreeNodes[`nodeOpen-${target._id}`]
+ componentTreeNodes[`nodeOpen-${target._id}`] !== false
) {
target = target._children[target._children.length - 1]
}
@@ -720,11 +730,11 @@ export class ComponentStore extends BudiStore {
return navComponentId
}
- // If we have children, select first child
+ // If we have children, select first child, and the node is not collapsed
if (
component._children?.length &&
(state.selectedComponentId === navComponentId ||
- componentTreeNodes[`nodeOpen-${component._id}`])
+ componentTreeNodes[`nodeOpen-${component._id}`] !== false)
) {
return component._children[0]._id
} else if (!parent) {
@@ -784,6 +794,7 @@ export class ComponentStore extends BudiStore {
await screenStore.patch(screen => {
const componentId = component?._id
const parent = findComponentParent(screen.props, componentId)
+ const componentTreeNodes = get(componentTreeNodesStore)
// Check we aren't right at the top of the tree
const index = parent?._children.findIndex(x => x._id === componentId)
@@ -803,7 +814,7 @@ export class ComponentStore extends BudiStore {
// sibling
const previousSibling = parent._children[index - 1]
const definition = this.getDefinition(previousSibling._component)
- if (definition.hasChildren) {
+ if (definition.hasChildren && componentTreeNodes[`nodeOpen-${previousSibling._id}`] !== false) {
previousSibling._children.push(originalComponent)
}
@@ -829,6 +840,8 @@ export class ComponentStore extends BudiStore {
await screenStore.patch(screen => {
const componentId = component?._id
const parent = findComponentParent(screen.props, componentId)
+ const componentTreeNodes = get(componentTreeNodesStore)
+
// Sanity check parent is found
if (!parent?._children?.length) {
@@ -852,10 +865,10 @@ export class ComponentStore extends BudiStore {
// Move below the next sibling if we are not the last sibling
if (index < parent._children.length) {
- // If the next sibling has children, become the first child
+ // If the next sibling has children, and is not collapsed, become the first child
const nextSibling = parent._children[index]
const definition = this.getDefinition(nextSibling._component)
- if (definition.hasChildren) {
+ if (definition.hasChildren && componentTreeNodes[`nodeOpen-${nextSibling._id}`] !== false) {
nextSibling._children.splice(0, 0, originalComponent)
}
@@ -1151,13 +1164,3 @@ export const selectedComponent = derived(
return clone
}
)
-
-export const selectedComponentPath = derived(
- [componentStore, selectedScreen],
- ([$store, $selectedScreen]) => {
- return findComponentPath(
- $selectedScreen?.props,
- $store.selectedComponentId
- ).map(component => component._id)
- }
-)
diff --git a/packages/builder/src/stores/builder/index.js b/packages/builder/src/stores/builder/index.js
index bac9fb8826..ee2c36db38 100644
--- a/packages/builder/src/stores/builder/index.js
+++ b/packages/builder/src/stores/builder/index.js
@@ -3,7 +3,6 @@ import { appStore } from "./app.js"
import {
componentStore,
selectedComponent,
- selectedComponentPath,
} from "./components"
import { navigationStore } from "./navigation.js"
import { themeStore } from "./theme.js"
@@ -30,8 +29,10 @@ import { integrations } from "./integrations"
import { sortedIntegrations } from "./sortedIntegrations"
import { queries } from "./queries"
import { flags } from "./flags"
+import componentTreeNodesStore from './componentTreeNodes';
export {
+ componentTreeNodesStore,
layoutStore,
appStore,
componentStore,
@@ -50,7 +51,6 @@ export {
isOnlyUser,
deploymentStore,
selectedComponent,
- selectedComponentPath,
tables,
views,
viewsV2,