export class TreeNode {
constructor(parent, data) {// {{{
this.data = data
this.parent = parent
this.childrenFetched = false
this.children = null
this.sortChildren()
}// }}}
render() {// {{{
const nodeHTML = `
`
this.name()
const tmpl = document.createElement('template')
tmpl.innerHTML = nodeHTML
this.children = tmpl.content.querySelector('.children')
// data.NumChildren is set regardless of having fetched the children or not.
if (this.hasChildren()) {
const img = tmpl.content.querySelector('.expand-status img')
img.setAttribute('src', `/images/${_VERSION}/node_modules/@mdi/svg/svg/plus-box-outline.svg`)
img.addEventListener('click', event => this.toggleExpand(event))
} else
tmpl.content.querySelector('.expand-status').classList.add('leaf')
if (this.data.TypeIcon) {
const img = tmpl.content.querySelector('.icon img')
img.setAttribute('src', `/images/${_VERSION}/node_modules/@mdi/svg/svg/${this.data.TypeIcon}.svg`)
}
this.parent.appendChild(tmpl.content)
for (const c of this.data.Children || []) {
(new TreeNode(this.children, c)).render()
}
}// }}}
name() {// {{{
if (this.data.TypeName === 'root_node')
return 'Start'
return this.data.Name
}// }}}
hasChildren() {// {{{
return this.data.NumChildren > 0
}// }}}
sortChildren() {// {{{
this.data.Children.sort((a, b) => {
console.log(a.Name, b.Name)
if (a.TypeName < b.TypeName) return -1
if (a.TypeName > b.TypeName) return 1
if (a.Name < b.Name) return -1
if (a.Name > b.Name) return 1
return 0
})
}// }}}
toggleExpand(event) {// {{{
const node = event.target.closest('.node')
node?.classList.toggle('expanded')
const img = node?.classList.contains('expanded') ? 'minus-box-outline' : 'plus-box-outline'
event.target.setAttribute('src', `/images/${_VERSION}/node_modules/@mdi/svg/svg/${img}.svg`)
if (!this.childrenFetched && this.data.NumChildren > 0 && this.data.Children.length == 0) {
this.fetchChildren()
.then(data => {
this.childrenFetched = true
this.data.Children = data.Children
this.sortChildren()
for (const nodeData of this.data.Children) {
const node = new TreeNode(this.children, nodeData)
node.render()
}
})
.catch(err => {
alert(err)
console.error(err)
})
}
}// }}}
async fetchChildren() {// {{{
return new Promise((resolve, reject) => {
fetch(`/nodes/tree/${this.data.ID}?depth=2`)
.then(data => data.json())
.then(json => resolve(json))
.catch(err => reject(err))
})
}// }}}
}
// vim: foldmethod=marker