This commit is contained in:
Gerard Burns 2024-03-04 08:05:50 +00:00
parent 33f03f91f3
commit 2f90d7f431
6 changed files with 48 additions and 30 deletions

View File

@ -10,6 +10,7 @@
navigationStore, navigationStore,
selectedScreen, selectedScreen,
hoverStore, hoverStore,
componentTreeNodesStore,
} from "stores/builder" } from "stores/builder"
import ConfirmDialog from "components/common/ConfirmDialog.svelte" import ConfirmDialog from "components/common/ConfirmDialog.svelte"
import { import {
@ -130,6 +131,13 @@
error = event.error || "An unknown error occurred" error = event.error || "An unknown error occurred"
} else if (type === "select-component" && data.id) { } else if (type === "select-component" && data.id) {
componentStore.select(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") { } else if (type === "hover-component") {
hoverStore.hover(data.id, false) hoverStore.hover(data.id, false)
} else if (type === "update-prop") { } else if (type === "update-prop") {

View File

@ -4,12 +4,12 @@
selectedScreen, selectedScreen,
componentStore, componentStore,
selectedComponent, selectedComponent,
componentTreeNodesStore
} from "stores/builder" } from "stores/builder"
import { findComponent } from "helpers/components" import { findComponent } from "helpers/components"
import { goto, isActive } from "@roxi/routify" import { goto, isActive } from "@roxi/routify"
import { notifications } from "@budibase/bbui" import { notifications } from "@budibase/bbui"
import ConfirmDialog from "components/common/ConfirmDialog.svelte" import ConfirmDialog from "components/common/ConfirmDialog.svelte"
import componentTreeNodesStore from "stores/portal/componentTreeNodesStore"
let confirmDeleteDialog let confirmDeleteDialog
let confirmEjectDialog let confirmEjectDialog
@ -66,6 +66,7 @@
componentTreeNodesStore.expandNode(component._id) componentTreeNodesStore.expandNode(component._id)
}, },
["ArrowLeft"]: component => { ["ArrowLeft"]: component => {
componentStore.select(component._id)
componentTreeNodesStore.collapseNode(component._id) componentTreeNodesStore.collapseNode(component._id)
}, },
["Ctrl+ArrowRight"]: component => { ["Ctrl+ArrowRight"]: component => {
@ -83,6 +84,7 @@
expandChildren(component) expandChildren(component)
}, },
["Ctrl+ArrowLeft"]: component => { ["Ctrl+ArrowLeft"]: component => {
componentStore.select(component._id)
componentTreeNodesStore.collapseNode(component._id) componentTreeNodesStore.collapseNode(component._id)
const collapseChildren = component => { const collapseChildren = component => {

View File

@ -7,8 +7,8 @@
componentStore, componentStore,
userSelectedResourceMap, userSelectedResourceMap,
selectedComponent, selectedComponent,
selectedComponentPath,
hoverStore, hoverStore,
componentTreeNodesStore
} from "stores/builder" } from "stores/builder"
import { import {
findComponentPath, findComponentPath,
@ -17,7 +17,6 @@
} from "helpers/components" } from "helpers/components"
import { get } from "svelte/store" import { get } from "svelte/store"
import { dndStore } from "./dndStore" import { dndStore } from "./dndStore"
import componentTreeNodesStore from "stores/portal/componentTreeNodesStore"
export let components = [] export let components = []
export let level = 0 export let level = 0
@ -64,14 +63,11 @@
} }
} }
const isOpen = (component, selectedComponentPath, openNodes) => { const isOpen = (component, openNodes) => {
if (!component?._children?.length) { if (!component?._children?.length) {
return false return false
} }
if (selectedComponentPath.slice(0, -1).includes(component._id)) { return openNodes[`nodeOpen-${component._id}`] !== false
return true
}
return openNodes[`nodeOpen-${component._id}`]
} }
const isChildOfSelectedComponent = component => { const isChildOfSelectedComponent = component => {
@ -90,7 +86,7 @@
<!-- svelte-ignore a11y-click-events-have-key-events --> <!-- svelte-ignore a11y-click-events-have-key-events -->
<ul> <ul>
{#each filteredComponents || [] as component, index (component._id)} {#each filteredComponents || [] as component, index (component._id)}
{@const opened = isOpen(component, $selectedComponentPath, openNodes)} {@const opened = isOpen(component, openNodes)}
<li <li
on:click|stopPropagation={() => { on:click|stopPropagation={() => {
componentStore.select(component._id) componentStore.select(component._id)

View File

@ -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 => { const collapseNode = componentId => {
baseStore.update(openNodes => { baseStore.update(openNodes => {
openNodes[`nodeOpen-${componentId}`] = false openNodes[`nodeOpen-${componentId}`] = false
@ -30,6 +38,7 @@ const store = {
subscribe: baseStore.subscribe, subscribe: baseStore.subscribe,
toggleNode, toggleNode,
expandNode, expandNode,
expandNodes,
collapseNode, collapseNode,
} }

View File

@ -19,6 +19,7 @@ import {
appStore, appStore,
previewStore, previewStore,
tables, tables,
componentTreeNodesStore
} from "stores/builder/index" } from "stores/builder/index"
import { buildFormSchema, getSchemaForDatasource } from "dataBinding" import { buildFormSchema, getSchemaForDatasource } from "dataBinding"
import { import {
@ -29,7 +30,6 @@ import {
} from "constants/backend" } from "constants/backend"
import BudiStore from "./BudiStore" import BudiStore from "./BudiStore"
import { Utils } from "@budibase/frontend-core" import { Utils } from "@budibase/frontend-core"
import componentTreeNodesStore from "stores/portal/componentTreeNodesStore"
export const INITIAL_COMPONENTS_STATE = { export const INITIAL_COMPONENTS_STATE = {
components: {}, components: {},
@ -653,6 +653,16 @@ export class ComponentStore extends BudiStore {
this.update(state => { this.update(state => {
state.selectedScreenId = targetScreenId state.selectedScreenId = targetScreenId
state.selectedComponentId = newComponentId 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 return state
}) })
} }
@ -680,16 +690,16 @@ export class ComponentStore extends BudiStore {
// If we have siblings above us, choose the sibling or a descendant // If we have siblings above us, choose the sibling or a descendant
if (index > 0) { 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] const previousSibling = parent._children[index - 1]
if ( if (
previousSibling._children?.length && previousSibling._children?.length &&
componentTreeNodes[`nodeOpen-${previousSibling._id}`] componentTreeNodes[`nodeOpen-${previousSibling._id}`] !== false
) { ) {
let target = previousSibling let target = previousSibling
while ( while (
target._children?.length && target._children?.length &&
componentTreeNodes[`nodeOpen-${target._id}`] componentTreeNodes[`nodeOpen-${target._id}`] !== false
) { ) {
target = target._children[target._children.length - 1] target = target._children[target._children.length - 1]
} }
@ -720,11 +730,11 @@ export class ComponentStore extends BudiStore {
return navComponentId return navComponentId
} }
// If we have children, select first child // If we have children, select first child, and the node is not collapsed
if ( if (
component._children?.length && component._children?.length &&
(state.selectedComponentId === navComponentId || (state.selectedComponentId === navComponentId ||
componentTreeNodes[`nodeOpen-${component._id}`]) componentTreeNodes[`nodeOpen-${component._id}`] !== false)
) { ) {
return component._children[0]._id return component._children[0]._id
} else if (!parent) { } else if (!parent) {
@ -784,6 +794,7 @@ export class ComponentStore extends BudiStore {
await screenStore.patch(screen => { await screenStore.patch(screen => {
const componentId = component?._id const componentId = component?._id
const parent = findComponentParent(screen.props, componentId) const parent = findComponentParent(screen.props, componentId)
const componentTreeNodes = get(componentTreeNodesStore)
// Check we aren't right at the top of the tree // Check we aren't right at the top of the tree
const index = parent?._children.findIndex(x => x._id === componentId) const index = parent?._children.findIndex(x => x._id === componentId)
@ -803,7 +814,7 @@ export class ComponentStore extends BudiStore {
// sibling // sibling
const previousSibling = parent._children[index - 1] const previousSibling = parent._children[index - 1]
const definition = this.getDefinition(previousSibling._component) const definition = this.getDefinition(previousSibling._component)
if (definition.hasChildren) { if (definition.hasChildren && componentTreeNodes[`nodeOpen-${previousSibling._id}`] !== false) {
previousSibling._children.push(originalComponent) previousSibling._children.push(originalComponent)
} }
@ -829,6 +840,8 @@ export class ComponentStore extends BudiStore {
await screenStore.patch(screen => { await screenStore.patch(screen => {
const componentId = component?._id const componentId = component?._id
const parent = findComponentParent(screen.props, componentId) const parent = findComponentParent(screen.props, componentId)
const componentTreeNodes = get(componentTreeNodesStore)
// Sanity check parent is found // Sanity check parent is found
if (!parent?._children?.length) { 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 // Move below the next sibling if we are not the last sibling
if (index < parent._children.length) { 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 nextSibling = parent._children[index]
const definition = this.getDefinition(nextSibling._component) const definition = this.getDefinition(nextSibling._component)
if (definition.hasChildren) { if (definition.hasChildren && componentTreeNodes[`nodeOpen-${nextSibling._id}`] !== false) {
nextSibling._children.splice(0, 0, originalComponent) nextSibling._children.splice(0, 0, originalComponent)
} }
@ -1151,13 +1164,3 @@ export const selectedComponent = derived(
return clone return clone
} }
) )
export const selectedComponentPath = derived(
[componentStore, selectedScreen],
([$store, $selectedScreen]) => {
return findComponentPath(
$selectedScreen?.props,
$store.selectedComponentId
).map(component => component._id)
}
)

View File

@ -3,7 +3,6 @@ import { appStore } from "./app.js"
import { import {
componentStore, componentStore,
selectedComponent, selectedComponent,
selectedComponentPath,
} from "./components" } from "./components"
import { navigationStore } from "./navigation.js" import { navigationStore } from "./navigation.js"
import { themeStore } from "./theme.js" import { themeStore } from "./theme.js"
@ -30,8 +29,10 @@ import { integrations } from "./integrations"
import { sortedIntegrations } from "./sortedIntegrations" import { sortedIntegrations } from "./sortedIntegrations"
import { queries } from "./queries" import { queries } from "./queries"
import { flags } from "./flags" import { flags } from "./flags"
import componentTreeNodesStore from './componentTreeNodes';
export { export {
componentTreeNodesStore,
layoutStore, layoutStore,
appStore, appStore,
componentStore, componentStore,
@ -50,7 +51,6 @@ export {
isOnlyUser, isOnlyUser,
deploymentStore, deploymentStore,
selectedComponent, selectedComponent,
selectedComponentPath,
tables, tables,
views, views,
viewsV2, viewsV2,