More work on special pages

This commit is contained in:
Magnus Åhall 2026-06-16 06:54:10 +02:00
parent da7999fb24
commit 15bd742ef7
3 changed files with 158 additions and 69 deletions

View file

@ -15,6 +15,8 @@ export class NodeStore {
this.sendQueue = null
this.nodesHistory = null
this.files = null
this.initializeSpecialNodes()
}//}}}
initializeDB() {//{{{
return new Promise((resolve, reject) => {
@ -86,9 +88,11 @@ export class NodeStore {
}
})
}//}}}
purgeCache() {//{{{
this.nodes = {}
}//}}}
initializeSpecialNodes() {// {{{
this.nodes[ROOT_NODE] = new Node({ UUID: ROOT_NODE, Name: 'Start', Special: true }, -1)
this.nodes[DELETED_NODE] = new Node({ UUID: DELETED_NODE, Name: 'Deleted nodes', Special: true }, -1)
this.nodes[ORPHANED_NODE] = new Node({ UUID: ORPHANED_NODE, Name: 'Orphaned nodes', Special: true }, -1)
}// }}}
node(uuid, dataIfUndefined, newLevel) {//{{{
let n = this.nodes[uuid]
@ -244,14 +248,9 @@ export class NodeStore {
return new Promise((resolve, reject) => {
switch (uuid) {
case ROOT_NODE:
const rootNode = new Node({ UUID: ROOT_NODE, Name: 'Start', Special: true }, -1)
this.nodes[ROOT_NODE] = rootNode
resolve(rootNode)
return
case DELETED_NODE:
const deletedNode = new Node({ UUID: DELETED_NODE, Name: 'Deleted nodes', Special: true }, -1)
this.nodes[DELETED_NODE] = deletedNode
resolve(deletedNode)
case ORPHANED_NODE:
resolve(this.nodes[uuid])
return
}
@ -261,73 +260,78 @@ export class NodeStore {
let nodeStore = suppliedNodestore
if (nodeStore === undefined) {
trx = this.db.transaction('nodes', 'readonly')
nodeStore = trx.objectStore('nodes')
}
const getRequest = nodeStore.get(uuid)
getRequest.onsuccess = (event) => {
// Node not found in IndexedDB.
if (event.target.result === undefined) {
reject("No such node")
return
trx = this.db.transaction('nodes', 'readonly')
nodeStore = trx.objectStore('nodes')
}
const node = this.node(uuid, event.target.result, -1)
resolve(node)
}
})
}//}}}
getNodeAncestry(node, accumulated) {//{{{
return new Promise((resolve, reject) => {
if (accumulated === undefined)
accumulated = []
const nodeParentIndex = this.db
.transaction('nodes', 'readonly')
.objectStore('nodes')
const getRequest = nodeStore.get(uuid)
if (node.UUID === ROOT_NODE || node.ParentUUID === ROOT_NODE) {
resolve(accumulated)
return
}
getRequest.onsuccess = (event) => {
// Node not found in IndexedDB.
if (event.target.result === undefined) {
reject("No such node")
return
}
const node = this.node(uuid, event.target.result, -1)
resolve(node)
}
})
}//}}}
getNodeAncestry(node, accumulated) {//{{{
return new Promise((resolve, reject) => {
if (accumulated === undefined)
accumulated = []
if (node.UUID === DELETED_NODE || node.ParentUUID === DELETED_NODE) {
resolve(accumulated)
return
}
const nodeParentIndex = this.db
.transaction('nodes', 'readonly')
.objectStore('nodes')
const getRequest = nodeParentIndex.get(node.ParentUUID)
getRequest.onsuccess = (event) => {
// Node not found in IndexedDB.
// Not expected to happen.
const parentNodeData = event.target.result
if (parentNodeData === undefined) {
reject("No such node")
if (node.UUID === ROOT_NODE || node.ParentUUID === ROOT_NODE) {
resolve(accumulated)
return
}
const parentNode = this.node(parentNodeData.UUID, parentNodeData, -1)
this.getNodeAncestry(parentNode, accumulated.concat(parentNode))
.then(accumulated => resolve(accumulated))
}
})
if (node.UUID === DELETED_NODE || node.ParentUUID === DELETED_NODE) {
resolve(accumulated)
return
}
}//}}}
newTransaction(objectStore, mode) {// {{{
return this.db.transaction(objectStore, mode)
}// }}}
if (node.UUID === ORPHANED_NODE || node.ParentUUID === ORPHANED_NODE) {
resolve(accumulated)
return
}
nodeCount() {//{{{
return new Promise((resolve, reject) => {
const t = this.db.transaction('nodes', 'readwrite')
const nodeStore = t.objectStore('nodes')
const countReq = nodeStore.count()
countReq.onsuccess = event => {
resolve(event.target.result)
}
})
}//}}}
const getRequest = nodeParentIndex.get(node.ParentUUID)
getRequest.onsuccess = (event) => {
// Node not found in IndexedDB.
// Not expected to happen.
const parentNodeData = event.target.result
if (parentNodeData === undefined) {
reject("No such node")
return
}
const parentNode = this.node(parentNodeData.UUID, parentNodeData, -1)
this.getNodeAncestry(parentNode, accumulated.concat(parentNode))
.then(accumulated => resolve(accumulated))
}
})
}//}}}
newTransaction(objectStore, mode) {// {{{
return this.db.transaction(objectStore, mode)
}// }}}
nodeCount() {//{{{
return new Promise((resolve, reject) => {
const t = this.db.transaction('nodes', 'readwrite')
const nodeStore = t.objectStore('nodes')
const countReq = nodeStore.count()
countReq.onsuccess = event => {
resolve(event.target.result)
}
})
}//}}}
}
class SimpleNodeStore {

View file

@ -1,4 +1,4 @@
import { ROOT_NODE, ORPHANED_NODE , DELETED_NODE} from 'node_store'
import { ROOT_NODE, ORPHANED_NODE, DELETED_NODE } from 'node_store'
import { Node } from 'node'
import { CustomHTMLElement } from './lib/custom_html_element.mjs'
import { Color, Solver } from './lib/css_colorize.mjs'
@ -161,11 +161,22 @@ export class N2Sidebar extends CustomHTMLElement {
const deletednode = await nodeStore.get(DELETED_NODE)
const deletedtreenode = new SpecialNodeDeleted(this, deletednode, null)
const orphanednode = await nodeStore.get(ORPHANED_NODE)
const orphanedtreenode = new SpecialNodeOrphaned(this, orphanednode, null)
startnode._sibling_after = deletednode
deletednode._sibling_before = startnode
deletednode._sibling_after = orphanednode
orphanednode._sibling_before = deletednode
this.treeNodeComponents[startnode.UUID] = starttreenode
this.treeNodeComponents[deletednode.UUID] = deletedtreenode
this.treeNodeComponents[orphanednode.UUID] = orphanedtreenode
this.elTreenodes.appendChild(await starttreenode.render())
this.elTreenodes.appendChild(await deletedtreenode.render())
this.elTreenodes.appendChild(await orphanedtreenode.render())
// Notify the application that the initial tree is rendered (with children)
// and that initial node selection can take place. App will check URL to
@ -677,11 +688,16 @@ export class N2TreeNode extends CustomHTMLElement {
if (this.node.UUID === ROOT_NODE)
this.setImgSrc(this.elExpand, `/images/${window._VERSION}/icon_home.svg`)
else if (this.node.UUID === '00000000-0000-0000-0000-000000000002') {
else if (this.node.UUID === DELETED_NODE) {
this.setImgSrc(this.elExpand, `/images/${window._VERSION}/leaf_deleted.svg`)
this.elExpand.classList.add('deleted')
}
else if (this.node.UUID === ORPHANED_NODE) {
this.setImgSrc(this.elExpand, `/images/${window._VERSION}/leaf_orphaned.svg`)
this.elExpand.classList.add('deleted')
}
else if (!this.node.hasChildren())
this.setImgSrc(this.elExpand, `/images/${window._VERSION}/leaf.svg`)
else if (this.sidebar.getNodeExpanded(this.node.UUID))
@ -724,8 +740,16 @@ class SpecialNodeDeleted extends N2TreeNode {
}//}}}
}
class SpecialNodeOrphaned extends N2TreeNode {
constructor(sidebar, node, parent) {//{{{
super(sidebar, node, parent)
this.removeAttribute('draggable')
}//}}}
}
customElements.define('n2-sidebar', N2Sidebar)
customElements.define('n2-treenode', N2TreeNode)
customElements.define('n2-specialnodedeleted', SpecialNodeDeleted)
customElements.define('n2-specialnodeorphaned', SpecialNodeOrphaned)
// vim: foldmethod=marker