From 50b7063811d69d54ed7e94fe4ffa6c1b82a47e0c Mon Sep 17 00:00:00 2001 From: zadam Date: Thu, 21 Oct 2021 22:52:52 +0200 Subject: [PATCH] display properly relations in note map even if they are not in the subtree, closes #2251 --- src/becca/entities/note.js | 4 +-- src/public/app/widgets/note_map.js | 37 ++++++++++++++++++++++-- src/routes/api/note_map.js | 45 +++++++++++++++++++++++++----- 3 files changed, 75 insertions(+), 11 deletions(-) diff --git a/src/becca/entities/note.js b/src/becca/entities/note.js index 6a9a1d784..91abb37c6 100644 --- a/src/becca/entities/note.js +++ b/src/becca/entities/note.js @@ -764,8 +764,8 @@ class Note extends AbstractEntity { } /** @return {String[]} */ - getSubtreeNoteIds() { - return this.getSubtreeNotes().map(note => note.noteId); + getSubtreeNoteIds(includeArchived = true) { + return this.getSubtreeNotes(includeArchived).map(note => note.noteId); } getDescendantNoteIds() { diff --git a/src/public/app/widgets/note_map.js b/src/public/app/widgets/note_map.js index 8e596a9c5..2c2e08f14 100644 --- a/src/public/app/widgets/note_map.js +++ b/src/public/app/widgets/note_map.js @@ -332,9 +332,9 @@ export default class NoteMapWidget extends NoteContextAwareWidget { if (this.widgetMode === 'ribbon') { setTimeout(() => { - const node = this.nodes.find(node => node.id === this.noteId); + const subGraphNoteIds = this.getSubGraphConnectedToCurrentNote(data); - this.graph.centerAt(node.x, node.y, 500); + this.graph.zoomToFit(400, 50, node => subGraphNoteIds.has(node.id)); }, 1000); } else if (this.widgetMode === 'type') { @@ -344,6 +344,39 @@ export default class NoteMapWidget extends NoteContextAwareWidget { } } + getSubGraphConnectedToCurrentNote(data) { + function getGroupedLinksBySource(links) { + const map = {}; + + for (const link of links) { + const key = link.source.id; + map[key] = map[key] || []; + map[key].push(link); + } + + return map; + } + + const linksBySource = getGroupedLinksBySource(data.links); + + const subGraphNoteIds = new Set(); + + function traverseGraph(noteId) { + if (subGraphNoteIds.has(noteId)) { + return; + } + + subGraphNoteIds.add(noteId); + + for (const link of linksBySource[noteId] || []) { + traverseGraph(link.target.id); + } + } + + traverseGraph(this.noteId); + return subGraphNoteIds; + } + cleanup() { this.$container.html(''); } diff --git a/src/routes/api/note_map.js b/src/routes/api/note_map.js index 433cb6791..9437e13f5 100644 --- a/src/routes/api/note_map.js +++ b/src/routes/api/note_map.js @@ -24,23 +24,54 @@ function buildDescendantCountMap() { return noteIdToCountMap; } +function getNeighbors(note, depth) { + if (depth === 0) { + return []; + } + + const retNoteIds = []; + + for (const relation of note.getRelations()) { + if (['relationMapLink', 'template', 'image'].includes(relation.name)) { + continue; + } + + const targetNote = relation.getTargetNote(); + retNoteIds.push(targetNote.noteId); + + for (const noteId of getNeighbors(targetNote, depth - 1)) { + retNoteIds.push(noteId); + } + } + + return retNoteIds; +} + function getLinkMap(req) { const mapRootNote = becca.getNote(req.params.noteId); // if the map root itself has ignore (journal typically) then there wouldn't be anything to display so // we'll just ignore it const ignoreExcludeFromNoteMap = mapRootNote.hasLabel('excludeFromNoteMap'); - const noteIds = new Set(); + const noteIds = new Set( + mapRootNote.getSubtreeNotes(false) + .filter(note => ignoreExcludeFromNoteMap || !note.hasLabel('excludeFromNoteMap')) + .map(note => note.noteId) + ); - const notes = mapRootNote.getSubtreeNotes(false) - .filter(note => ignoreExcludeFromNoteMap || !note.hasLabel('excludeFromNoteMap')) - .map(note => [ + for (const noteId of getNeighbors(mapRootNote, 3)) { + noteIds.add(noteId); + } + + const notes = Array.from(noteIds).map(noteId => { + const note = becca.getNote(noteId); + + return [ note.noteId, note.isContentAvailable() ? note.title : '[protected]', note.type - ]); - - notes.forEach(([noteId]) => noteIds.add(noteId)); + ]; + }); const links = Object.values(becca.attributes).filter(rel => { if (rel.type !== 'relation' || rel.name === 'relationMapLink' || rel.name === 'template') {