diff --git a/static/js/node_store.mjs b/static/js/node_store.mjs index d29923f..c72445c 100644 --- a/static/js/node_store.mjs +++ b/static/js/node_store.mjs @@ -176,14 +176,32 @@ export class NodeStore { const nodeStore = trx.objectStore('nodes') const index = nodeStore.index('byParent') const req = index.getAll(storeParent) + + const hasChildrenPromises = [] req.onsuccess = (event) => { const nodes = [] for (const i in event.target.result) { const nodeData = event.target.result[i] const node = this.node(nodeData.UUID, nodeData, newLevel) + + // Look for the key of any children, a hopefully fast way + // to tell if any children exists at all and this node is a + // "folder". Needed quite early on for sorting. + const promise = new Promise((resolve, reject) => { + const countReq = index.getKey(nodeData.UUID) + countReq.onsuccess = event => { + node.setHasChildren(event.target.result !== undefined) + resolve() + } + }) + hasChildrenPromises.push(promise) nodes.push(node) } - resolve(nodes) + + Promise.all(hasChildrenPromises) + .then(() => { + resolve(nodes) + }) } req.onerror = (event) => reject(event.target.error) }) diff --git a/static/js/page_node.mjs b/static/js/page_node.mjs index d151f77..d3f3a6e 100644 --- a/static/js/page_node.mjs +++ b/static/js/page_node.mjs @@ -257,8 +257,15 @@ customElements.define('n2-nodeui', N2PageNodeUI) export class Node { static sort(a, b) {//{{{ - if (a.data.Name < b.data.Name) return -1 - if (a.data.Name > b.data.Name) return 0 + // Nodes with children ("folders") are sorted first. + if (a._has_children && !b._has_children) return -1 + if (!a._has_children && b._has_children) return 1 + + // Otherwise sort by lowercased name. + const an = a.data.Name.toLowerCase() + const bn = b.data.Name.toLowerCase() + if (an < bn) return -1 + if (an > bn) return 1 return 0 }//}}} static create(name, parentUUID) {// {{{ @@ -286,6 +293,7 @@ export class Node { this.ParentUUID = nodeData.ParentUUID this._children_fetched = false + this._has_children = null // this will be set by nodeStore.getTreeNodes this.Children = [] this.Ancestors = [] @@ -322,6 +330,7 @@ export class Node { this.Children.sort(Node.sort) const numChildren = this.Children.length + this.setHasChildren(numChildren > 0) for (let i = 0; i < numChildren; i++) { if (i > 0) this.Children[i]._sibling_before = this.Children[i - 1] @@ -336,8 +345,11 @@ export class Node { return this.Children }//}}} + setHasChildren(v) {// {{{ + this._has_children = v + }// }}} hasChildren() {//{{{ - return this.Children.length > 0 + return this._has_children }//}}} getSiblingBefore() {// {{{ return this._sibling_before diff --git a/static/js/tree.mjs b/static/js/tree.mjs index b672742..408e281 100644 --- a/static/js/tree.mjs +++ b/static/js/tree.mjs @@ -91,7 +91,11 @@ export class N2Tree extends CustomHTMLElement { } _mbus.dispatch('TREE_TRUNK_FETCHED') }) - .catch(e => { console.log(e); console.log(e.type, e.error); alert(e.error) }) + .catch(e => { + console.error(e) + console.log(e.type, e.error) + alert(e.error) + }) }//}}} getNodeExpanded(UUID) {//{{{ if (this.expandedNodes[UUID] === undefined) @@ -396,7 +400,7 @@ export class N2TreeNode extends CustomHTMLElement { this.render(true) }) - _mbus.subscribe(`NODE_EXPAND_${node.UUID}`, state => { + _mbus.subscribe(`NODE_EXPAND_${node.UUID}`, _state => { this.render(true) }) @@ -412,7 +416,7 @@ export class N2TreeNode extends CustomHTMLElement { return this // Fetch the next level of children if the parent tree node is expanded and our children thus will be visible. - const expanded = this.node.Children.length > 0 && this.tree.getNodeExpanded(this.node.UUID) + const expanded = this.node.hasChildren() && this.tree.getNodeExpanded(this.node.UUID) if (!this.children_populated && this.tree.getNodeExpanded(this.parent?.node.UUID)) { this.node.fetchChildren().then(() => this.children_populated = true) @@ -435,7 +439,7 @@ export class N2TreeNode extends CustomHTMLElement { } // The expand icon is only changed to not get a flickering when re-rendering. - if (this.node.Children.length === 0) + if (!this.node.hasChildren()) this.setImgSrc(this.elExpand, `/images/${window._VERSION}/leaf.svg`) else if (this.tree.getNodeExpanded(this.node.UUID)) this.setImgSrc(this.elExpand, `/images/${window._VERSION}/expanded.svg`)