diff --git a/src/public/javascripts/services/load_results.js b/src/public/javascripts/services/load_results.js index 9ce1c5a51..c134de985 100644 --- a/src/public/javascripts/services/load_results.js +++ b/src/public/javascripts/services/load_results.js @@ -1,5 +1,7 @@ export class LoadResults { - constructor() { + constructor(treeCache) { + this.treeCache = treeCache; + this.noteIdToSourceId = {}; this.sourceIdToNoteIds = {}; @@ -25,14 +27,34 @@ export class LoadResults { this.branchIdToSourceId[branchId].push(sourceId); } + getBranches() { + + } + addNoteReordering(parentNoteId, sourceId) { } + getNoteReorderings() { + + } + addAttribute(attributeId, sourceId) { } + getAttributes() { + + } + + addNoteRevision(noteRevisionId, noteId, sourceId) { + + } + + hasNoteRevisionForNote(noteId) { + + } + getNoteIds() { return Object.keys(this.noteIdToSourceId); } diff --git a/src/public/javascripts/services/tree.js b/src/public/javascripts/services/tree.js index 39e0ba6fe..d081376a6 100644 --- a/src/public/javascripts/services/tree.js +++ b/src/public/javascripts/services/tree.js @@ -412,7 +412,7 @@ async function createNote(node, parentNoteId, target, extraOptions = {}) { await newParentNode.load(true); // force reload to show up new note - await appContext.getMainNoteTree().checkFolderStatus(newParentNode); + await appContext.getMainNoteTree().updateNode(newParentNode); } return {note, branch}; diff --git a/src/public/javascripts/services/tree_cache.js b/src/public/javascripts/services/tree_cache.js index b08ab56f5..9fbdf43d7 100644 --- a/src/public/javascripts/services/tree_cache.js +++ b/src/public/javascripts/services/tree_cache.js @@ -230,10 +230,11 @@ class TreeCache { return child.parentToBranch[parentNoteId]; } + // FIXME does not actually belong here async processSyncRows(syncRows) { const noteIdsToReload = []; - const loadResults = new LoadResults(); + const loadResults = new LoadResults(this); syncRows.filter(sync => sync.entityName === 'branches').forEach(sync => { noteIdsToReload.push(sync.parentNoteId); @@ -261,6 +262,11 @@ class TreeCache { loadResults.addAttribute(sync.entityId, sync.sourceId); }); + // missing reloading the relation target note + syncRows.filter(sync => sync.entityName === 'note_revisions').forEach(sync => { + loadResults.addNoteRevision(sync.entityId, sync.noteId, sync.sourceId); + }); + await this.reloadNotes(noteIdsToReload); const appContext = (await import('./app_context.js')).default; diff --git a/src/public/javascripts/widgets/attributes.js b/src/public/javascripts/widgets/attributes.js index cab4d6ad0..b18fb6c4d 100644 --- a/src/public/javascripts/widgets/attributes.js +++ b/src/public/javascripts/widgets/attributes.js @@ -88,11 +88,9 @@ class AttributesWidget extends StandardWidget { } } - syncDataListener({data}) { - if (data.find(sd => sd.entityName === 'attributes' && sd.noteId === this.tabContext.note.noteId)) { - // no need to invalidate attributes since the Attribute class listens to this as well - // (and is guaranteed to run first) - this.doRenderBody(); + entitiesReloadedListener({loadResults}) { + if (loadResults.getAttributes().find(attr => attr.type === 'relation' && attr.noteId === this.noteId)) { + this.refresh(); } } } diff --git a/src/public/javascripts/widgets/link_map.js b/src/public/javascripts/widgets/link_map.js index fd5ebc3fd..a003018c3 100644 --- a/src/public/javascripts/widgets/link_map.js +++ b/src/public/javascripts/widgets/link_map.js @@ -54,13 +54,9 @@ class LinkMapWidget extends StandardWidget { } } - syncDataListener({data}) { - if (data.find(sd => sd.entityName === 'attributes' && sd.noteId === this.tabContext.note.noteId)) { - // no need to invalidate attributes since the Attribute class listens to this as well - // (and is guaranteed to run first) - if (this.linkMapService) { - this.linkMapService.loadNotesAndRelations(); - } + entitiesReloadedListener({loadResults}) { + if (loadResults.getAttributes().find(attr => attr.type === 'relation' && (attr.noteId === this.noteId || attr.value === this.noteId))) { + this.refresh(); } } } diff --git a/src/public/javascripts/widgets/note_detail.js b/src/public/javascripts/widgets/note_detail.js index d5bfad04f..9c0fa13ab 100644 --- a/src/public/javascripts/widgets/note_detail.js +++ b/src/public/javascripts/widgets/note_detail.js @@ -220,9 +220,9 @@ export default class NoteDetailWidget extends TabAwareWidget { this.refresh(); } - entitiesReloadedListener(data) { - super.entitiesReloadedListener(data); - - return false; // stop propagation to children + entitiesReloadedListener({loadResults}) { + if (loadResults.isNoteReloaded(this.noteId, this.componentId)) { + this.refreshWithNote(this.note, this.notePath); + } } } \ No newline at end of file diff --git a/src/public/javascripts/widgets/note_revisions.js b/src/public/javascripts/widgets/note_revisions.js index fdbff4f17..d3159ecfe 100644 --- a/src/public/javascripts/widgets/note_revisions.js +++ b/src/public/javascripts/widgets/note_revisions.js @@ -55,6 +55,12 @@ class NoteRevisionsWidget extends StandardWidget { } } + entitiesReloadedListener({loadResults}) { + if (loadResults.hasNoteRevisionForNote(this.noteId)) { + this.refresh(); + } + } + syncDataListener({data}) { if (data.find(sd => sd.entityName === 'note_revisions' && sd.noteId === this.tabContext.note.noteId)) { this.refresh(); diff --git a/src/public/javascripts/widgets/note_tree.js b/src/public/javascripts/widgets/note_tree.js index 73abac935..007c7e786 100644 --- a/src/public/javascripts/widgets/note_tree.js +++ b/src/public/javascripts/widgets/note_tree.js @@ -331,7 +331,7 @@ export default class NoteTreeWidget extends TabAwareWidget { await parentNode.setExpanded(true, expandOpts); } - await this.checkFolderStatus(parentNode); + await this.updateNode(parentNode); let foundChildNode = this.findChildNode(parentNode, childNoteId); @@ -372,12 +372,16 @@ export default class NoteTreeWidget extends TabAwareWidget { return this.getNodeFromPath(notePath, true, expandOpts); } - async checkFolderStatus(node) { + async updateNode(node) { const note = await treeCache.getNote(node.data.noteId); + const branch = treeCache.getBranch(node.data.branchId); + node.data.isProtected = note.isProtected; + node.data.noteType = note.type; node.folder = note.type === 'search' || note.getChildNoteIds().length > 0; node.icon = await treeBuilder.getIcon(note); node.extraClasses = await treeBuilder.getExtraClasses(note); + node.title = (branch.prefix ? (branch.prefix + " - ") : "") + note.title; node.renderTitle(); } @@ -428,20 +432,93 @@ export default class NoteTreeWidget extends TabAwareWidget { } async entitiesReloadedListener({loadResults}) { - const activeNode = this.getActiveNode(); - const activateNotePath = activeNode ? await treeService.getNotePath(activeNode) : null; + const noteIdsToUpdate = new Set(); + const noteIdsToReload = new Set(); - for (const noteId of loadResults.getNoteIds()) { - for (const node of this.getNodesByNoteId(noteId)) { - const branch = treeCache.getBranch(node.data.branchId, true); + for (const attr of loadResults.getAttributes()) { + if (attr.type === 'label' && ['iconClass', 'cssClass'].includes(attr.name)) { + if (attr.isInheritable) { + noteIdsToReload.add(attr.noteId); + } + else { + noteIdsToUpdate.add(attr.noteId); + } + } + else if (attr.type === 'relation' && attr.name === 'template') { + // missing handling of things inherited from template + noteIdsToReload.add(attr.noteId); + } + } + + for (const branch of loadResults.getBranches()) { + for (const node of this.getNodesByBranchId(branch.branchId)) { + if (branch.isDeleted) { + if (node.isActive()) { + let newActive = node.getNextSibling(); + + if (!newActive) { + newActive = node.getPrevSibling(); + } + + if (!newActive) { + newActive = node.getParent(); + } + + await newActive.setActive(true, {noEvents: true}); + } - if (!branch) { node.remove(); } else { - await node.load(true); + noteIdsToUpdate.add(branch.noteId); + } + } - await this.checkFolderStatus(node); + if (!branch.isDeleted) { + for (const parentNode of this.getNodesByNoteId(branch.parentNoteId)) { + if (!parentNode.isLoaded()) { + continue; + } + + const found = parentNode.getChildren().find(child => child.data.noteId === branch.noteId); + + if (!found) { + noteIdsToReload.add(branch.parentNoteId); + } + } + } + } + + const activeNode = this.getActiveNode(); + const activateNotePath = activeNode ? await treeService.getNotePath(activeNode) : null; + + for (const noteId of noteIdsToReload) { + for (const node of this.getNodesByNoteId(noteId)) { + await node.load(true); + + await this.updateNode(node); + } + } + + for (const noteId of noteIdsToReload) { + for (const node of this.getNodesByNoteId(noteId)) { + await this.updateNode(node); + } + } + + for (const {parentNoteId} of loadResults.getNoteReorderings()) { + for (const node of this.getNodesByNoteId(parentNoteId)) { + if (node.isLoaded()) { + node.sortChildren((nodeA, nodeB) => { + const branchA = treeCache.branches[nodeA.data.branchId]; + const branchB = treeCache.branches[nodeB.data.branchId]; + + if (!branchA || !branchB) { + return 0; + } + + return branchA.notePosition - branchB.notePosition; + }); } } } @@ -500,20 +577,6 @@ export default class NoteTreeWidget extends TabAwareWidget { await server.put('branches/' + branchId + '/expanded/' + expandedNum); } - // async reloadNotesListener({noteIds, activateNotePath = null}) { - // if (noteIds.length === 0) { - // return; - // } - // - // await treeCache.reloadNotes(noteIds); - // - // if (!activateNotePath) { - // activateNotePath = appContext.getActiveTabNotePath(); - // } - // - // appContext.trigger('entitiesReloaded', { noteIds, activateNotePath }); - // } - async reloadTreeListener() { const notes = await treeService.loadTreeData(); diff --git a/src/public/javascripts/widgets/tab_aware_widget.js b/src/public/javascripts/widgets/tab_aware_widget.js index 2d261bba3..7e0de9da3 100644 --- a/src/public/javascripts/widgets/tab_aware_widget.js +++ b/src/public/javascripts/widgets/tab_aware_widget.js @@ -59,10 +59,4 @@ export default class TabAwareWidget extends BasicWidget { this.activeTabChanged(); } - - entitiesReloadedListener({loadResults}) { - if (loadResults.isNoteReloaded(this.noteId, this.componentId)) { - this.refreshWithNote(this.note, this.notePath); - } - } } \ No newline at end of file diff --git a/src/public/javascripts/widgets/what_links_here.js b/src/public/javascripts/widgets/what_links_here.js index ebe1b4c31..8f9a0a73c 100644 --- a/src/public/javascripts/widgets/what_links_here.js +++ b/src/public/javascripts/widgets/what_links_here.js @@ -49,6 +49,12 @@ class WhatLinksHereWidget extends StandardWidget { this.$body.empty().append($list); } + + entitiesReloadedListener({loadResults}) { + if (loadResults.getAttributes().find(attr => attr.type === 'relation' && attr.value === this.noteId)) { + this.refresh(); + } + } } export default WhatLinksHereWidget; \ No newline at end of file