| 
									
										
										
										
											2020-05-17 09:48:24 +02:00
										 |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const noteCache = require('./note_cache'); | 
					
						
							| 
									
										
										
										
											2020-11-23 22:52:48 +01:00
										 |  |  | const cls = require('../cls'); | 
					
						
							| 
									
										
										
										
											2020-06-04 00:04:57 +02:00
										 |  |  | const protectedSessionService = require('../protected_session'); | 
					
						
							| 
									
										
										
										
											2020-08-17 23:54:18 +02:00
										 |  |  | const log = require('../log'); | 
					
						
							| 
									
										
										
										
											2020-05-17 09:48:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-16 23:12:29 +02:00
										 |  |  | function isNotePathArchived(notePath) { | 
					
						
							|  |  |  |     const noteId = notePath[notePath.length - 1]; | 
					
						
							|  |  |  |     const note = noteCache.notes[noteId]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (note.isArchived) { | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (let i = 0; i < notePath.length - 1; i++) { | 
					
						
							|  |  |  |         const note = noteCache.notes[notePath[i]]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // this is going through parents so archived must be inheritable
 | 
					
						
							|  |  |  |         if (note.hasInheritableOwnedArchivedLabel) { | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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 | 
					
						
							|  |  |  |  * @return {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 = noteCache.notes[noteId]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-05 21:31:57 +02:00
										 |  |  |     if (!note) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-16 23:12:29 +02:00
										 |  |  |     for (const parentNote of note.parents) { | 
					
						
							|  |  |  |         if (isInAncestor(parentNote.noteId, ancestorNoteId)) { | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function getNoteTitle(childNoteId, parentNoteId) { | 
					
						
							|  |  |  |     const childNote = noteCache.notes[childNoteId]; | 
					
						
							|  |  |  |     const parentNote = noteCache.notes[parentNoteId]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-17 23:54:18 +02:00
										 |  |  |     if (!childNote) { | 
					
						
							|  |  |  |         log.info(`Cannot find note in cache for noteId ${childNoteId}`); | 
					
						
							|  |  |  |         return "[error fetching title]"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-16 23:12:29 +02:00
										 |  |  |     let title; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (childNote.isProtected) { | 
					
						
							|  |  |  |         title = protectedSessionService.isProtectedSessionAvailable() ? childNote.title : '[protected]'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         title = childNote.title; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-17 10:11:19 +02:00
										 |  |  |     const branch = parentNote ? noteCache.getBranch(childNote.noteId, parentNote.noteId) : null; | 
					
						
							| 
									
										
										
										
											2020-05-16 23:12:29 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return ((branch && branch.prefix) ? `${branch.prefix} - ` : '') + title; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function getNoteTitleArrayForPath(notePathArray) { | 
					
						
							|  |  |  |     const titles = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let parentNoteId = 'root'; | 
					
						
							|  |  |  |     let hoistedNotePassed = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (const noteId of notePathArray) { | 
					
						
							|  |  |  |         // start collecting path segment titles only after hoisted note
 | 
					
						
							|  |  |  |         if (hoistedNotePassed) { | 
					
						
							|  |  |  |             const title = getNoteTitle(noteId, parentNoteId); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             titles.push(title); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-23 22:52:48 +01:00
										 |  |  |         if (noteId === cls.getHoistedNoteId()) { | 
					
						
							| 
									
										
										
										
											2020-05-16 23:12:29 +02:00
										 |  |  |             hoistedNotePassed = true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         parentNoteId = noteId; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return titles; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function getNoteTitleForPath(notePathArray) { | 
					
						
							|  |  |  |     const titles = getNoteTitleArrayForPath(notePathArray); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return titles.join(' / '); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Returns notePath for noteId from cache. Note hoisting is respected. | 
					
						
							|  |  |  |  * Archived 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() | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function getSomePath(note, path = []) { | 
					
						
							|  |  |  |     if (note.noteId === 'root') { | 
					
						
							|  |  |  |         path.push(note.noteId); | 
					
						
							|  |  |  |         path.reverse(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-23 22:52:48 +01:00
										 |  |  |         if (!path.includes(cls.getHoistedNoteId())) { | 
					
						
							| 
									
										
										
										
											2020-05-16 23:12:29 +02:00
										 |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return path; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const parents = note.parents; | 
					
						
							|  |  |  |     if (parents.length === 0) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (const parentNote of parents) { | 
					
						
							|  |  |  |         const retPath = getSomePath(parentNote, path.concat([note.noteId])); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (retPath) { | 
					
						
							|  |  |  |             return retPath; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function getNotePath(noteId) { | 
					
						
							|  |  |  |     const note = noteCache.notes[noteId]; | 
					
						
							| 
									
										
										
										
											2020-08-28 23:20:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!note) { | 
					
						
							|  |  |  |         console.trace(`Cannot find note ${noteId} in cache.`); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-16 23:12:29 +02:00
										 |  |  |     const retPath = getSomePath(note); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (retPath) { | 
					
						
							|  |  |  |         const noteTitle = getNoteTitleForPath(retPath); | 
					
						
							|  |  |  |         const parentNote = note.parents[0]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return { | 
					
						
							|  |  |  |             noteId: noteId, | 
					
						
							| 
									
										
										
										
											2020-06-20 21:42:41 +02:00
										 |  |  |             branchId: noteCache.getBranch(noteId, parentNote.noteId).branchId, | 
					
						
							| 
									
										
										
										
											2020-05-16 23:12:29 +02:00
										 |  |  |             title: noteTitle, | 
					
						
							|  |  |  |             notePath: retPath, | 
					
						
							|  |  |  |             path: retPath.join('/') | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @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 = { | 
					
						
							| 
									
										
										
										
											2020-05-17 10:11:19 +02:00
										 |  |  |     getSomePath, | 
					
						
							| 
									
										
										
										
											2020-05-16 23:12:29 +02:00
										 |  |  |     getNotePath, | 
					
						
							| 
									
										
										
										
											2020-05-17 10:11:19 +02:00
										 |  |  |     getNoteTitle, | 
					
						
							| 
									
										
										
										
											2020-05-16 23:12:29 +02:00
										 |  |  |     getNoteTitleForPath, | 
					
						
							|  |  |  |     isAvailable, | 
					
						
							|  |  |  |     isArchived, | 
					
						
							|  |  |  |     isInAncestor, | 
					
						
							| 
									
										
										
										
											2020-09-15 16:46:03 +02:00
										 |  |  |     isNotePathArchived | 
					
						
							| 
									
										
										
										
											2020-05-16 23:12:29 +02:00
										 |  |  | }; |