mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 03:29:02 +01:00 
			
		
		
		
	refactoring of "some path" WIP
This commit is contained in:
		
							parent
							
								
									7aa26580ba
								
							
						
					
					
						commit
						a1d4e062ed
					
				| @ -24,49 +24,12 @@ function isNotePathArchived(notePath) { | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * This assumes that note is available. "archived" note means that there isn't a single non-archived note-path | ||||
|  * leading to this note. | ||||
|  * | ||||
|  * @param noteId | ||||
|  */ | ||||
| function isArchived(noteId) { | ||||
|     const notePath = getSomePath(noteId); | ||||
| 
 | ||||
|     return isNotePathArchived(notePath); | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @param {string} noteId | ||||
|  * @param {string} ancestorNoteId | ||||
|  * @returns {boolean} - true if given noteId has ancestorNoteId in any of its paths (even archived) | ||||
|  */ | ||||
| function isInAncestor(noteId, ancestorNoteId) { | ||||
|     if (ancestorNoteId === 'root' || ancestorNoteId === noteId) { | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     const note = becca.notes[noteId]; | ||||
| 
 | ||||
|     if (!note) { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     for (const parentNote of note.parents) { | ||||
|         if (isInAncestor(parentNote.noteId, ancestorNoteId)) { | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| function getNoteTitle(childNoteId, parentNoteId) { | ||||
|     const childNote = becca.notes[childNoteId]; | ||||
|     const parentNote = becca.notes[parentNoteId]; | ||||
| 
 | ||||
|     if (!childNote) { | ||||
|         log.info(`Cannot find note in cache for noteId '${childNoteId}'`); | ||||
|         log.info(`Cannot find note '${childNoteId}'`); | ||||
|         return "[error fetching title]"; | ||||
|     } | ||||
| 
 | ||||
| @ -119,86 +82,15 @@ function getNoteTitleForPath(notePathArray) { | ||||
|     return titles.join(' / '); | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Returns notePath for noteId. Note hoisting is respected. | ||||
|  * Archived (and hidden) notes are also returned, but non-archived paths are preferred if available | ||||
|  * - this means that archived paths is returned only if there's no non-archived path | ||||
|  * - you can check whether returned path is archived using isArchived | ||||
|  * | ||||
|  * @param {BNote} note | ||||
|  * @param {string[]} path | ||||
|  */ | ||||
| function getSomePath(note, path = []) { | ||||
|     // first try to find note within hoisted note, otherwise take any existing note path
 | ||||
|     return getSomePathInner(note, path, true) | ||||
|         || getSomePathInner(note, path, false); | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @param {BNote} note | ||||
|  * @param {string[]} parentPath | ||||
|  * @param {boolean} respectHoisting | ||||
|  * @returns {string[]|false} | ||||
|  */ | ||||
| function getSomePathInner(note, parentPath, respectHoisting) { | ||||
|     const childPath = [...parentPath, note.noteId]; | ||||
|     if (note.isRoot()) { | ||||
|         childPath.reverse(); | ||||
| 
 | ||||
|         if (respectHoisting && !childPath.includes(cls.getHoistedNoteId())) { | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         return childPath; | ||||
|     } | ||||
| 
 | ||||
|     const parents = note.parents; | ||||
|     if (parents.length === 0) { | ||||
|         console.log(`Note '${note.noteId}' - '${note.title}' has no parents.`); | ||||
| 
 | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     const completeNotePaths = parents.map(parentNote => getSomePathInner(parentNote, childPath, respectHoisting)); | ||||
| 
 | ||||
|     if (completeNotePaths.length === 0) { | ||||
|         return false; | ||||
|     } else if (completeNotePaths.length === 1) { | ||||
|         return completeNotePaths[0]; | ||||
|     } else { | ||||
|         completeNotePaths.sort((a, b) => { | ||||
|             if (a.isInHoistedSubTree !== b.isInHoistedSubTree) { | ||||
|                 return a.isInHoistedSubTree ? -1 : 1; | ||||
|             } else if (a.isSearch !== b.isSearch) { | ||||
|                 return a.isSearch ? 1 : -1; | ||||
|             } else if (a.isArchived !== b.isArchived) { | ||||
|                 return a.isArchived ? 1 : -1; | ||||
|             } else if (a.isHidden !== b.isHidden) { | ||||
|                 return a.isHidden ? 1 : -1; | ||||
|             } else { | ||||
|                 return a.notePath.length - b.notePath.length; | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         // if there are multiple valid paths, take the shortest one
 | ||||
|         const shortestNotePath = completeNotePaths.reduce((shortestPath, nextPath) => | ||||
|             nextPath.length < shortestPath.length | ||||
|                 ? nextPath | ||||
|                 : shortestPath, completeNotePaths[0]); | ||||
| 
 | ||||
|         return shortestNotePath; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| function getNotePath(noteId) { | ||||
|     const note = becca.notes[noteId]; | ||||
| 
 | ||||
|     if (!note) { | ||||
|         console.trace(`Cannot find note '${noteId}' in cache.`); | ||||
|         console.trace(`Cannot find note '${noteId}'.`); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     const retPath = getSomePath(note); | ||||
|     const retPath = note.getBestNotePath(); | ||||
| 
 | ||||
|     if (retPath) { | ||||
|         const noteTitle = getNoteTitleForPath(retPath); | ||||
| @ -223,23 +115,9 @@ function getNotePath(noteId) { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @param noteId | ||||
|  * @returns {boolean} - true if note exists (is not deleted) and is available in current note hoisting | ||||
|  */ | ||||
| function isAvailable(noteId) { | ||||
|     const notePath = getNotePath(noteId); | ||||
| 
 | ||||
|     return !!notePath; | ||||
| } | ||||
| 
 | ||||
| module.exports = { | ||||
|     getSomePath, | ||||
|     getNotePath, | ||||
|     getNoteTitle, | ||||
|     getNoteTitleForPath, | ||||
|     isAvailable, | ||||
|     isArchived, | ||||
|     isInAncestor, | ||||
|     isNotePathArchived | ||||
| }; | ||||
|  | ||||
| @ -748,6 +748,21 @@ class BNote extends AbstractBeccaEntity { | ||||
|         return this.hasAttribute('label', 'archived'); | ||||
|     } | ||||
| 
 | ||||
|     areAllNotePathsArchived() { | ||||
|         // there's a slight difference between note being itself archived and all its note paths being archived
 | ||||
|         // - note is archived when it itself has an archived label or inherits it
 | ||||
|         // - note does not have or inherit archived label, but each note paths contains a note with (non-inheritable)
 | ||||
|         //   archived label
 | ||||
| 
 | ||||
|         const bestNotePathRecord = this.getSortedNotePathRecords()[0]; | ||||
| 
 | ||||
|         if (!bestNotePathRecord) { | ||||
|             throw new Error(`No note path available for note '${this.noteId}'`); | ||||
|         } | ||||
| 
 | ||||
|         return bestNotePathRecord.isArchived; | ||||
|     } | ||||
| 
 | ||||
|     hasInheritableArchivedLabel() { | ||||
|         for (const attr of this.getAttributes()) { | ||||
|             if (attr.name === 'archived' && attr.type === LABEL && attr.isInheritable) { | ||||
|  | ||||
| @ -404,7 +404,7 @@ async function findSimilarNotes(noteId) { | ||||
|         let score = computeScore(candidateNote); | ||||
| 
 | ||||
|         if (score >= 1.5) { | ||||
|             const notePath = beccaService.getSomePath(candidateNote); | ||||
|             const notePath = candidateNote.getBestNotePath(); | ||||
| 
 | ||||
|             // this takes care of note hoisting
 | ||||
|             if (!notePath) { | ||||
|  | ||||
| @ -3,14 +3,14 @@ | ||||
| const sql = require('../../services/sql'); | ||||
| const protectedSessionService = require('../../services/protected_session'); | ||||
| const noteService = require('../../services/notes'); | ||||
| const beccaService = require('../../becca/becca_service'); | ||||
| const becca = require("../../becca/becca"); | ||||
| 
 | ||||
| function getRecentChanges(req) { | ||||
|     const {ancestorNoteId} = req.params; | ||||
| 
 | ||||
|     let recentChanges = []; | ||||
| 
 | ||||
|     const noteRevisions = sql.getRows(` | ||||
|     const noteRevisionRows = sql.getRows(` | ||||
|         SELECT  | ||||
|             notes.noteId, | ||||
|             notes.isDeleted AS current_isDeleted, | ||||
| @ -24,16 +24,18 @@ function getRecentChanges(req) { | ||||
|             note_revisions | ||||
|             JOIN notes USING(noteId)`);
 | ||||
| 
 | ||||
|     for (const noteRevision of noteRevisions) { | ||||
|         if (beccaService.isInAncestor(noteRevision.noteId, ancestorNoteId)) { | ||||
|             recentChanges.push(noteRevision); | ||||
|     for (const noteRevisionRow of noteRevisionRows) { | ||||
|         const note = becca.getNote(noteRevisionRow.noteId); | ||||
| 
 | ||||
|         if (note?.hasAncestor(ancestorNoteId)) { | ||||
|             recentChanges.push(noteRevisionRow); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // now we need to also collect date points not represented in note revisions:
 | ||||
|     // 1. creation for all notes (dateCreated)
 | ||||
|     // 2. deletion for deleted notes (dateModified)
 | ||||
|     const notes = sql.getRows(` | ||||
|     const noteRows = sql.getRows(` | ||||
|             SELECT | ||||
|                 notes.noteId, | ||||
|                 notes.isDeleted AS current_isDeleted, | ||||
| @ -57,9 +59,11 @@ function getRecentChanges(req) { | ||||
|             FROM notes | ||||
|             WHERE notes.isDeleted = 1`);
 | ||||
| 
 | ||||
|     for (const note of notes) { | ||||
|         if (beccaService.isInAncestor(note.noteId, ancestorNoteId)) { | ||||
|             recentChanges.push(note); | ||||
|     for (const noteRow of noteRows) { | ||||
|         const note = becca.getNote(noteRow.noteId); | ||||
| 
 | ||||
|         if (note?.hasAncestor(ancestorNoteId)) { | ||||
|             recentChanges.push(noteRow); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -24,7 +24,7 @@ class NoteFlatTextExp extends Expression { | ||||
|          */ | ||||
|         function searchDownThePath(note, tokens, path) { | ||||
|             if (tokens.length === 0) { | ||||
|                 const retPath = beccaService.getSomePath(note, path); | ||||
|                 const retPath = this.getNotePath(note, path); | ||||
| 
 | ||||
|                 if (retPath) { | ||||
|                     const noteId = retPath[retPath.length - 1]; | ||||
| @ -131,6 +131,17 @@ class NoteFlatTextExp extends Expression { | ||||
|         return resultNoteSet; | ||||
|     } | ||||
| 
 | ||||
|     getNotePath(note, path) { | ||||
|         if (path.length === 0) { | ||||
|             return note.getBestNotePath(); | ||||
|         } else { | ||||
|             const closestNoteId = path[0]; | ||||
|             const closestNoteBestNotePath = becca.getNote(closestNoteId).getBestNotePathString(); | ||||
| 
 | ||||
|             return [...closestNoteBestNotePath, ...path.slice(1)]; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Returns noteIds which have at least one matching tokens | ||||
|      * | ||||
|  | ||||
| @ -157,7 +157,7 @@ function findResultsWithExpression(expression, searchContext) { | ||||
|     const searchResults = noteSet.notes | ||||
|         .filter(note => !note.isDeleted) | ||||
|         .map(note => { | ||||
|             const notePathArray = executionContext.noteIdToNotePath[note.noteId] || beccaService.getSomePath(note); | ||||
|             const notePathArray = executionContext.noteIdToNotePath[note.noteId] || note.getBestNotePath(); | ||||
| 
 | ||||
|             if (!notePathArray) { | ||||
|                 throw new Error(`Can't find note path for note ${JSON.stringify(note.getPojo())}`); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 zadam
						zadam