Storing Node objects in NodeStore for single instance objects

This commit is contained in:
Magnus Åhall 2024-12-19 22:28:13 +01:00
parent d0150145ed
commit 41952df764
5 changed files with 187 additions and 68 deletions

View file

@ -8,7 +8,6 @@ const html = htm.bind(h)
export class Notes2 extends Component {
constructor() {//{{{
super()
this.tree = createRef()
this.nodeUI = createRef()
this.state = {
startNode: null,
@ -25,7 +24,7 @@ export class Notes2 extends Component {
return
return html`
<${Tree} ref=${this.tree} app=${this} startNode=${startNode} />
<${Tree} app=${this} startNode=${startNode} />
<div id="nodeui">
<${NodeUI} app=${this} ref=${this.nodeUI} startNode=${startNode} />
@ -56,10 +55,9 @@ export class Notes2 extends Component {
// New node is fetched in order to retrieve content and files.
// Such data is unnecessary to transfer for tree/navigational purposes.
nodeStore.get(nodeUUID).then(node => {
this.nodeUI.current.setNode(node)
//this.showPage('node')
})
const node = nodeStore.node(nodeUUID)
this.nodeUI.current.setNode(node)
this.tree.setSelected(node)
}//}}}
logout() {//{{{
localStorage.removeItem('session.UUID')
@ -73,7 +71,9 @@ class Tree extends Component {
this.treeNodes = {}
this.treeNodeComponents = {}
this.treeTrunk = []
this.selectedTreeNode = null
this.selectedNode = null
this.expandedNodes = {} // keyed on UUID
this.props.app.tree = this
this.populateFirstLevel()
@ -81,7 +81,7 @@ class Tree extends Component {
render({ app }) {//{{{
const renderedTreeTrunk = this.treeTrunk.map(node => {
this.treeNodeComponents[node.UUID] = createRef()
return html`<${TreeNode} key=${`treenode_${node.UUID}`} tree=${this} node=${node} ref=${this.treeNodeComponents[node.UUID]} selected=${node.UUID === app.startNode?.UUID} />`
return html`<${TreeNode} key=${`treenode_${node.UUID}`} tree=${this} node=${node} ref=${this.treeNodeComponents[node.UUID]} selected=${node.UUID === app.state.startNode?.UUID} />`
})
return html`
<div id="tree">
@ -98,7 +98,6 @@ class Tree extends Component {
this.treeNodes = {}
this.treeNodeComponents = {}
this.treeTrunk = []
this.selectedTreeNode = null
// A tree of nodes is built. This requires the list of nodes
// returned from the server to be sorted in such a way that
@ -125,14 +124,21 @@ class Tree extends Component {
.catch(e => { console.log(e); console.log(e.type, e.error); alert(e.error) })
}//}}}
setSelected(node) {//{{{
return // TODO
if (this.selectedTreeNode)
this.selectedTreeNode.selected.value = false
// The previously selected node, if any, needs to be rerendered
// to not retain its 'selected' class.
const prevUUID = this.selectedNode?.UUID
this.selectedNode = node
if (prevUUID)
this.treeNodeComponents[prevUUID]?.current.forceUpdate()
this.selectedTreeNode = this.treeNodeComponents[node.ID].current
this.selectedTreeNode.selected.value = true
this.selectedTreeNode.expanded.value = true
this.expandToTrunk(node.ID)
// And now the newly selected node is rerendered.
this.treeNodeComponents[node.UUID]?.current.forceUpdate()
// Expanding selected nodes... I don't know...
this.setNodeExpanded(node.UUID, true)
}//}}}
isSelected(node) {//{{{
return this.selectedNode?.UUID === node.UUID
}//}}}
crumbsUpdateNodes(node) {//{{{
console.log('crumbs', this.props.app.startNode.Crumbs)
@ -153,32 +159,41 @@ class Tree extends Component {
if (node !== undefined)
this.setSelected(node)
}//}}}
expandToTrunk(nodeUUID) {//{{{
let node = this.treeNodes[nodeUUID]
if (node === undefined)
return
node = this.treeNodes[node.ParentUUID]
while (node !== undefined) {
this.treeNodeComponents[node.UUID].current.expanded.value = true
node = this.treeNodes[node.ParentUUID]
async expandToTrunk(node) {//{{{
// Get all ancestors from a certain node up to the highest grandparent.
const ancestry = await nodeStore.getNodeAncestry(node, [])
for (const i in ancestry) {
await nodeStore.node(ancestry[i].UUID).fetchChildren()
this.setNodeExpanded(ancestry[i].UUID, true)
}
// Start the chain of by expanding the top node.
this.setNodeExpanded(ancestry[ancestry.length-1].UUID, true)
}//}}}
getNodeExpanded(UUID) {//{{{
if (this.expandedNodes[UUID] === undefined)
this.expandedNodes[UUID] = signal(false)
return this.expandedNodes[UUID].value
}//}}}
setNodeExpanded(UUID, value) {//{{{
// Creating a default value if it doesn't exist already.
this.getNodeExpanded(UUID)
this.expandedNodes[UUID].value = value
}//}}}
}
class TreeNode extends Component {
constructor(props) {//{{{
super(props)
this.selected = signal(props.selected)
this.expanded = signal(this.props.node._expanded)
this.children_populated = signal(false)
if (this.props.node.Level === 0)
if (this.props.node.Level === 0 || this.props.tree.getNodeExpanded(this.props.node.UUID))
this.fetchChildren()
}//}}}
render({ tree, node, parent }) {//{{{
// Fetch the next level of children if the parent tree node is expanded and our children thus will be visible.
if (!this.children_populated.value && parent?.expanded.value)
const selected = tree.isSelected(node) ? 'selected' : ''
if (!this.children_populated.value && tree.getNodeExpanded(parent?.props.node.UUID))
this.fetchChildren()
const children = node.Children.map(node => {
@ -190,25 +205,22 @@ class TreeNode extends Component {
if (node.Children.length === 0)
expandImg = html`<img src="/images/${window._VERSION}/leaf.svg" />`
else {
if (this.expanded.value)
if (tree.getNodeExpanded(node.UUID))
expandImg = html`<img src="/images/${window._VERSION}/expanded.svg" />`
else
expandImg = html`<img src="/images/${window._VERSION}/collapsed.svg" />`
}
const selected = (this.selected.value ? 'selected' : '')
return html`
<div class="node">
<div class="expand-toggle" onclick=${() => { this.expanded.value ^= true }}>${expandImg}</div>
<div class="expand-toggle" onclick=${() => { tree.setNodeExpanded(node.UUID, !tree.getNodeExpanded(node.UUID)) }}>${expandImg}</div>
<div class="name ${selected}" onclick=${() => window._notes2.current.goToNode(node.UUID)}>${node.get('Name')}</div>
<div class="children ${node.Children.length > 0 && this.expanded.value ? 'expanded' : 'collapsed'}">${children}</div>
<div class="children ${node.Children.length > 0 && tree.getNodeExpanded(node.UUID) ? 'expanded' : 'collapsed'}">${children}</div>
</div>`
}//}}}
fetchChildren() {//{{{
this.props.node.fetchChildren().then(() => {
this.children_populated.value = true
})
async fetchChildren() {//{{{
await this.props.node.fetchChildren()
this.children_populated.value = true
}//}}}
}