diff --git a/static/css/notes2.css b/static/css/notes2.css
index 299b0af..7c7c224 100644
--- a/static/css/notes2.css
+++ b/static/css/notes2.css
@@ -6,6 +6,7 @@ html {
display: grid;
grid-template-areas: "tree crumbs" "tree sync" "tree name" "tree content" "tree blank";
grid-template-columns: min-content 1fr;
+ grid-template-rows: 64px 56px 48px min-content 1fr;
}
@media only screen and (max-width: 600px) {
#notes2 {
@@ -77,6 +78,7 @@ html {
#crumbs {
grid-area: crumbs;
display: grid;
+ align-items: center;
justify-items: center;
margin: 16px;
}
@@ -84,19 +86,14 @@ html {
grid-area: sync;
display: grid;
justify-items: center;
- justify-self: center;
width: 100%;
- max-width: 900px;
height: 56px;
position: relative;
}
-#sync-progress.hidden {
- visibility: hidden;
- opacity: 0;
- transition: visibility 0s 500ms, opacity 500ms linear;
-}
#sync-progress progress {
- width: calc(100% - 16px);
+ width: 100%;
+ padding: 0 7px;
+ max-width: 900px;
height: 16px;
border-radius: 4px;
}
@@ -121,11 +118,18 @@ html {
border-radius: 4px;
}
#sync-progress .count {
+ width: min-content;
+ white-space: nowrap;
margin-top: 0px;
color: #888;
position: absolute;
top: 22px;
}
+#sync-progress.hidden {
+ visibility: hidden;
+ opacity: 0;
+ transition: visibility 0s 500ms, opacity 500ms linear;
+}
.crumbs {
display: flex;
flex-wrap: wrap;
diff --git a/static/js/node.mjs b/static/js/node.mjs
index 4db59a0..8648057 100644
--- a/static/js/node.mjs
+++ b/static/js/node.mjs
@@ -385,9 +385,7 @@ export class Node {
if (this._children_fetched)
return this.Children
-
this.Children = await nodeStore.getTreeNodes(this.UUID, this.Level + 1)
-
this._children_fetched = true
// Children are sorted to allow for storing siblings befare and after.
@@ -403,6 +401,9 @@ export class Node {
this.Children[i]._parent = this
}
+ // Notify the tree that all children are fetched and ready to process.
+ _notes2.current.tree.fetchChildrenOn(this.UUID)
+
return this.Children
}//}}}
hasChildren() {//{{{
diff --git a/static/js/notes2.mjs b/static/js/notes2.mjs
index 3155043..9eb9503 100644
--- a/static/js/notes2.mjs
+++ b/static/js/notes2.mjs
@@ -29,10 +29,7 @@ export class Notes2 extends Component {
return html`
<${Tree} app=${this} key=${treeKey} startNode=${startNode} />
-
-
- <${NodeUI} app=${this} ref=${this.nodeUI} startNode=${startNode} />
-
+ <${NodeUI} app=${this} ref=${this.nodeUI} startNode=${startNode} />
`
}//}}}
getStartNode() {//{{{
@@ -84,6 +81,11 @@ class Tree extends Component {
this.expandedNodes = {} // keyed on UUID
this.treeDiv = createRef()
+ // childrenFetchedCallbacks is keyed on a UUID and each
+ // item is an array with callbacks called when a UUID has
+ // had all children fetched.
+ this.childrenFetchedCallbacks = {}
+
this.props.app.tree = this
this.populateFirstLevel()
@@ -113,6 +115,20 @@ class Tree extends Component {
this.setSelected(node)
}//}}}
+ fetchChildrenNotify(uuid, fn) {//{{{
+ if (this.childrenFetchedCallbacks[uuid] === undefined)
+ this.childrenFetchedCallbacks[uuid] = [fn]
+ else
+ this.childrenFetchedCallbacks[uuid].push(fn)
+ }//}}}
+ fetchChildrenOn(uuid) {//{{{
+ if (this.childrenFetchedCallbacks[uuid] === undefined)
+ return
+ for (const fn of this.childrenFetchedCallbacks[uuid])
+ fn(uuid)
+ delete this.childrenFetchedCallbacks[uuid]
+ }//}}}
+
populateFirstLevel(callback = null) {//{{{
nodeStore.get(ROOT_NODE)
.then(node => node.fetchChildren())
@@ -145,7 +161,7 @@ class Tree extends Component {
this.treeNodeComponents[node.UUID]?.current.forceUpdate()
if (!dontExpand)
- this.setNodeExpanded(node.UUID, true)
+ this.setNodeExpanded(node, true)
}//}}}
isSelected(node) {//{{{
return this.selectedNode?.UUID === node.UUID
@@ -155,7 +171,7 @@ class Tree extends Component {
const ancestry = await nodeStore.getNodeAncestry(node, [])
for (const i in ancestry) {
await nodeStore.node(ancestry[i].UUID).fetchChildren()
- this.setNodeExpanded(ancestry[i].UUID, true)
+ this.setNodeExpanded(ancestry[i], true)
}
// Already a top node, no need to expand anything.
@@ -163,17 +179,29 @@ class Tree extends Component {
return
// Start the chain of by expanding the top node.
- this.setNodeExpanded(ancestry[ancestry.length - 1].UUID, true)
+ this.setNodeExpanded(ancestry[ancestry.length - 1], 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
+ async setNodeExpanded(node, value) {//{{{
+ return new Promise((resolve, reject) => {
+ const work = uuid=>{
+ // Creating a default value if it doesn't exist already.
+ this.getNodeExpanded(uuid)
+ this.expandedNodes[uuid].value = value
+ resolve()
+ }
+
+ if (node.hasFetchedChildren()) {
+ work(node.UUID)
+ return
+ } else {
+ this.fetchChildrenNotify(node.UUID, uuid=>work(uuid))
+ }
+ })
}//}}}
getParentWithNextSibling(node) {//{{{
let currNode = node
@@ -190,17 +218,33 @@ class Tree extends Component {
return currNode
}//}}}
+ async recursiveExpand(node, state) {//{{{
+ if (state)
+ await this.setNodeExpanded(node, true)
+
+ for (const child of node.Children)
+ await this.recursiveExpand(child, state)
+
+ if (!state)
+ await this.setNodeExpanded(node, false)
+ }//}}}
+
async keyHandler(event) {//{{{
let handled = true
const n = this.selectedNode
const Space = ' '
switch (event.key) {
- // Space is toggling expansion.
+ // Space and enter is toggling expansion.
+ // Holding shift down does it recursively.
case Space:
case 'Enter':
const expanded = this.getNodeExpanded(n.UUID)
- this.setNodeExpanded(n.UUID, !expanded)
+ if (event.shiftKey) {
+ this.recursiveExpand(n, !expanded)
+ } else {
+ this.setNodeExpanded(n, !expanded)
+ }
break
case 'g':
@@ -249,7 +293,7 @@ class Tree extends Component {
const expanded = this.getNodeExpanded(n.UUID)
if (expanded && n.hasChildren()) {
- this.setNodeExpanded(n.UUID, false)
+ this.setNodeExpanded(n, false)
return
}
@@ -276,7 +320,7 @@ class Tree extends Component {
const expanded = this.getNodeExpanded(n.UUID)
if (!expanded && n.hasChildren()) {
- this.setNodeExpanded(n.UUID, true)
+ this.setNodeExpanded(n, true)
return
}
@@ -408,7 +452,7 @@ class TreeNode extends Component {
return html`
-
{ tree.setNodeExpanded(node.UUID, !tree.getNodeExpanded(node.UUID)) }}>${expandImg}
+
{ tree.setNodeExpanded(node, !tree.getNodeExpanded(node.UUID)) }}>${expandImg}
window._notes2.current.goToNode(node.UUID)}>${node.get('Name')}
${children}
`
diff --git a/static/less/notes2.less b/static/less/notes2.less
index 93b75cd..a2c0f81 100644
--- a/static/less/notes2.less
+++ b/static/less/notes2.less
@@ -19,6 +19,13 @@ html {
"tree blank"
;
grid-template-columns: min-content 1fr;
+ grid-template-rows:
+ 64px
+ 56px
+ 48px
+ min-content
+ 1fr;
+
@media only screen and (max-width: 600px) {
grid-template-areas:
@@ -46,6 +53,10 @@ html {
color: #ddd;
z-index: 100; // Over crumbs shadow
+ &:focus {
+ //background-color: #f0f;
+ }
+
#logo {
display: grid;
position: relative;
@@ -114,6 +125,7 @@ html {
#crumbs {
grid-area: crumbs;
display: grid;
+ align-items: center;
justify-items: center;
margin: 16px;
}
@@ -122,20 +134,15 @@ html {
grid-area: sync;
display: grid;
justify-items: center;
- justify-self: center;
+
width: 100%;
- max-width: 900px;
height: 56px;
position: relative;
- &.hidden {
- visibility: hidden;
- opacity: 0;
- transition: visibility 0s 500ms, opacity 500ms linear;
- }
-
progress {
- width: calc(100% - 16px);
+ width: 100%;
+ padding: 0 7px;
+ max-width: 900px;
height: 16px;
border-radius: 4px;
}
@@ -166,11 +173,20 @@ html {
}
.count {
+ width: min-content;
+ white-space: nowrap;
margin-top: 0px;
color: #888;
position: absolute;
top: 22px;
}
+
+ &.hidden {
+ visibility: hidden;
+ opacity: 0;
+ transition: visibility 0s 500ms, opacity 500ms linear;
+ }
+
}
.crumbs {