mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 02:16:05 +01:00 
			
		
		
		
	load initial tree from note cache
This commit is contained in:
		| @@ -1,30 +1,61 @@ | ||||
| "use strict"; | ||||
|  | ||||
| const sql = require('../../services/sql'); | ||||
| const optionService = require('../../services/options'); | ||||
| const treeService = require('../../services/tree'); | ||||
| const noteCache = require('../../services/note_cache/note_cache'); | ||||
|  | ||||
| function getNotesAndBranchesAndAttributes(noteIds) { | ||||
|     const notes = treeService.getNotesIncludingAscendants(noteIds); | ||||
|     noteIds = new Set(noteIds); | ||||
|     const collectedNoteIds = new Set(); | ||||
|     const collectedAttributeIds = new Set(); | ||||
|     const collectedBranchIds = new Set(); | ||||
|  | ||||
|     noteIds = new Set(notes.map(note => note.noteId)); | ||||
|     function collectEntityIds(note) { | ||||
|         if (collectedNoteIds.has(note.noteId)) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|     sql.fillNoteIdList(noteIds); | ||||
|         collectedNoteIds.add(note.noteId); | ||||
|  | ||||
|     // joining child note to filter out not completely synchronised notes which would then cause errors later | ||||
|     // cannot do that with parent because of root note's 'none' parent | ||||
|     const branches = sql.getRows(`  | ||||
|         SELECT  | ||||
|             branches.branchId, | ||||
|             branches.noteId, | ||||
|             branches.parentNoteId, | ||||
|             branches.notePosition, | ||||
|             branches.prefix, | ||||
|             branches.isExpanded | ||||
|         FROM param_list | ||||
|         JOIN branches ON param_list.paramId = branches.parentNoteId | ||||
|         JOIN notes AS child ON child.noteId = branches.noteId | ||||
|         WHERE branches.isDeleted = 0`); | ||||
|         for (const branch of note.parentBranches) { | ||||
|             collectedBranchIds.add(branch.branchId); | ||||
|  | ||||
|             collectEntityIds(branch.parentNote); | ||||
|         } | ||||
|  | ||||
|         for (const attr of note.ownedAttributes) { | ||||
|             collectedAttributeIds.add(attr.attributeId); | ||||
|  | ||||
|             if (attr.type === 'relation' && attr.name === 'template') { | ||||
|                 collectEntityIds(attr.targetNote); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     for (const noteId of noteIds) { | ||||
|         const note = noteCache.notes[noteId]; | ||||
|  | ||||
|         if (!note) { | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         collectEntityIds(note); | ||||
|     } | ||||
|  | ||||
|     const notes = []; | ||||
|  | ||||
|     for (const noteId of collectedNoteIds) { | ||||
|         const note = noteCache.notes[noteId]; | ||||
|  | ||||
|         notes.push({ | ||||
|             noteId: note.noteId, | ||||
|             title: note.title, | ||||
|             isProtected: note.isProtected, | ||||
|             type: note.type, | ||||
|             mime: note.mime, | ||||
|             isDeleted: note.isDeleted | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     const branches = []; | ||||
|  | ||||
|     if (noteIds.has('root')) { | ||||
|         branches.push({ | ||||
| @@ -37,39 +68,35 @@ function getNotesAndBranchesAndAttributes(noteIds) { | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     const attributes = sql.getRows(` | ||||
|         SELECT | ||||
|             attributes.attributeId, | ||||
|             attributes.noteId, | ||||
|             attributes.type, | ||||
|             attributes.name, | ||||
|             attributes.value, | ||||
|             attributes.position, | ||||
|             attributes.isInheritable | ||||
|         FROM param_list | ||||
|         JOIN attributes ON attributes.noteId = param_list.paramId  | ||||
|                         OR (attributes.type = 'relation' AND attributes.value = param_list.paramId) | ||||
|         WHERE attributes.isDeleted = 0`); | ||||
|     for (const branchId of collectedBranchIds) { | ||||
|         const branch = noteCache.branches[branchId]; | ||||
|  | ||||
|     // we don't really care about the direction of the relation | ||||
|     const missingTemplateNoteIds = attributes | ||||
|         .filter(attr => attr.type === 'relation' | ||||
|                 && attr.name === 'template' | ||||
|                 && !noteIds.has(attr.value)) | ||||
|         .map(attr => attr.value); | ||||
|  | ||||
|     if (missingTemplateNoteIds.length > 0) { | ||||
|         const templateData = getNotesAndBranchesAndAttributes(missingTemplateNoteIds); | ||||
|  | ||||
|         // there are going to be duplicates with simple concatenation, however: | ||||
|         // 1) shouldn't matter for the frontend which will update the entity twice | ||||
|         // 2) there shouldn't be many duplicates. There isn't that many templates | ||||
|         addArrays(notes, templateData.notes); | ||||
|         addArrays(branches, templateData.branches); | ||||
|         addArrays(attributes, templateData.attributes); | ||||
|         branches.push({ | ||||
|             branchId: branch.branchId, | ||||
|             noteId: branch.noteId, | ||||
|             parentNoteId: branch.parentNoteId, | ||||
|             notePosition: branch.notePosition, | ||||
|             prefix: branch.prefix, | ||||
|             isExpanded: branch.isExpanded | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     const attributes = []; | ||||
|  | ||||
|     for (const attributeId of collectedAttributeIds) { | ||||
|         const attribute = noteCache.attributes[attributeId]; | ||||
|  | ||||
|         attributes.push({ | ||||
|             attributeId: attribute.attributeId, | ||||
|             noteId: attribute.noteId, | ||||
|             type: attribute.type, | ||||
|             name: attribute.name, | ||||
|             value: attribute.value, | ||||
|             position: attribute.position, | ||||
|             isInheritable: attribute.isInheritable | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     // sorting in memory is faster | ||||
|     branches.sort((a, b) => a.notePosition - b.notePosition < 0 ? -1 : 1); | ||||
|     attributes.sort((a, b) => a.position - b.position < 0 ? -1 : 1); | ||||
|  | ||||
| @@ -80,35 +107,25 @@ function getNotesAndBranchesAndAttributes(noteIds) { | ||||
|     }; | ||||
| } | ||||
|  | ||||
| // should be fast based on https://stackoverflow.com/a/64826145/944162 | ||||
| // in this case it is assumed that target is potentially much larger than elementsToAdd | ||||
| function addArrays(target, elementsToAdd) { | ||||
|     while (elementsToAdd.length) { | ||||
|         target.push(elementsToAdd.shift()); | ||||
|     } | ||||
|  | ||||
|     return target; | ||||
| } | ||||
|  | ||||
| function getTree(req) { | ||||
|     const subTreeNoteId = req.query.subTreeNoteId || 'root'; | ||||
|     const collectedNoteIds = new Set(['root']); | ||||
|  | ||||
|     // FIXME: this query does not return ascendants of template notes | ||||
|     const noteIds = sql.getColumn(` | ||||
|         WITH RECURSIVE | ||||
|             treeWithDescendants(noteId, isExpanded) AS ( | ||||
|                 SELECT noteId, isExpanded FROM branches WHERE parentNoteId = ? AND isDeleted = 0 | ||||
|                 UNION | ||||
|                 SELECT branches.noteId, branches.isExpanded FROM branches | ||||
|                   JOIN treeWithDescendants ON branches.parentNoteId = treeWithDescendants.noteId | ||||
|                 WHERE treeWithDescendants.isExpanded = 1  | ||||
|                   AND branches.isDeleted = 0 | ||||
|             ) | ||||
|         SELECT noteId FROM treeWithDescendants`, [subTreeNoteId]); | ||||
|     function collect(parentNote) { | ||||
|         for (const childNote of parentNote.children || []) { | ||||
|             collectedNoteIds.add(childNote.noteId); | ||||
|  | ||||
|     noteIds.push(subTreeNoteId); | ||||
|             const childBranch = noteCache.getBranch(childNote.noteId, parentNote.noteId); | ||||
|  | ||||
|     return getNotesAndBranchesAndAttributes(noteIds); | ||||
|             if (childBranch.isExpanded) { | ||||
|                 collect(childBranch); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     collect(noteCache.notes[subTreeNoteId]); | ||||
|  | ||||
|     return getNotesAndBranchesAndAttributes(collectedNoteIds); | ||||
| } | ||||
|  | ||||
| function load(req) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user