mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 10:26:08 +01:00 
			
		
		
		
	refactoring of "some path" WIP
This commit is contained in:
		| @@ -120,7 +120,7 @@ function getNoteTitleForPath(notePathArray) { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Returns notePath for noteId from cache. Note hoisting is respected. | ||||
|  * 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 | ||||
| @@ -136,20 +136,20 @@ function getSomePath(note, path = []) { | ||||
|  | ||||
| /** | ||||
|  * @param {BNote} note | ||||
|  * @param {string[]} path | ||||
|  * @param {boolean}respectHoisting | ||||
|  * @param {string[]} parentPath | ||||
|  * @param {boolean} respectHoisting | ||||
|  * @returns {string[]|false} | ||||
|  */ | ||||
| function getSomePathInner(note, path, respectHoisting) { | ||||
| function getSomePathInner(note, parentPath, respectHoisting) { | ||||
|     const childPath = [...parentPath, note.noteId]; | ||||
|     if (note.isRoot()) { | ||||
|         const foundPath = [...path, note.noteId]; | ||||
|         foundPath.reverse(); | ||||
|         childPath.reverse(); | ||||
|  | ||||
|         if (respectHoisting && !foundPath.includes(cls.getHoistedNoteId())) { | ||||
|         if (respectHoisting && !childPath.includes(cls.getHoistedNoteId())) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         return foundPath; | ||||
|         return childPath; | ||||
|     } | ||||
|  | ||||
|     const parents = note.parents; | ||||
| @@ -159,15 +159,35 @@ function getSomePathInner(note, path, respectHoisting) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     for (const parentNote of parents) { | ||||
|         const retPath = getSomePathInner(parentNote, [...path, note.noteId], respectHoisting); | ||||
|  | ||||
|         if (retPath) { | ||||
|             return retPath; | ||||
|         } | ||||
|     } | ||||
|     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) { | ||||
|   | ||||
| @@ -12,6 +12,7 @@ const TaskContext = require("../../services/task_context"); | ||||
| const dayjs = require("dayjs"); | ||||
| const utc = require('dayjs/plugin/utc'); | ||||
| const eventService = require("../../services/events"); | ||||
| const froca = require("../../public/app/services/froca.js"); | ||||
| dayjs.extend(utc); | ||||
|  | ||||
| const LABEL = 'label'; | ||||
| @@ -1150,6 +1151,8 @@ class BNote extends AbstractBeccaEntity { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Gives all possible note paths leading to this note. Paths containing search note are ignored (could form cycles) | ||||
|      * | ||||
|      * @returns {string[][]} - array of notePaths (each represented by array of noteIds constituting the particular note path) | ||||
|      */ | ||||
|     getAllNotePaths() { | ||||
| @@ -1157,18 +1160,73 @@ class BNote extends AbstractBeccaEntity { | ||||
|             return [['root']]; | ||||
|         } | ||||
|  | ||||
|         const notePaths = []; | ||||
|         const parentNotes = this.getParentNotes(); | ||||
|         let notePaths = []; | ||||
|  | ||||
|         for (const parentNote of this.getParentNotes()) { | ||||
|             for (const parentPath of parentNote.getAllNotePaths()) { | ||||
|                 parentPath.push(this.noteId); | ||||
|                 notePaths.push(parentPath); | ||||
|         if (parentNotes.length === 1) { // optimization for most common case | ||||
|             notePaths = parentNotes[0].getAllNotePaths(); | ||||
|         } else { | ||||
|             notePaths = parentNotes.flatMap(parentNote => parentNote.getAllNotePaths()); | ||||
|         } | ||||
|  | ||||
|         for (const notePath of notePaths) { | ||||
|             notePath.push(this.noteId); | ||||
|         } | ||||
|  | ||||
|         return notePaths; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param {string} [hoistedNoteId='root'] | ||||
|      * @return {{isArchived: boolean, isInHoistedSubTree: boolean, notePath: string[], isHidden: boolean}[]} | ||||
|      */ | ||||
|     getSortedNotePathRecords(hoistedNoteId = 'root') { | ||||
|         const isHoistedRoot = hoistedNoteId === 'root'; | ||||
|  | ||||
|         const notePaths = this.getAllNotePaths().map(path => ({ | ||||
|             notePath: path, | ||||
|             isInHoistedSubTree: isHoistedRoot || path.includes(hoistedNoteId), | ||||
|             isArchived: path.some(noteId => froca.notes[noteId].isArchived), | ||||
|             isHidden: path.includes('_hidden') | ||||
|         })); | ||||
|  | ||||
|         notePaths.sort((a, b) => { | ||||
|             if (a.isInHoistedSubTree !== b.isInHoistedSubTree) { | ||||
|                 return a.isInHoistedSubTree ? -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; | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         return notePaths; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns note path considered to be the "best" | ||||
|      * | ||||
|      * @param {string} [hoistedNoteId='root'] | ||||
|      * @return {string[]} array of noteIds constituting the particular note path | ||||
|      */ | ||||
|     getBestNotePath(hoistedNoteId = 'root') { | ||||
|         return this.getSortedNotePathRecords(hoistedNoteId)[0]?.notePath; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns note path considered to be the "best" | ||||
|      * | ||||
|      * @param {string} [hoistedNoteId='root'] | ||||
|      * @return {string} serialized note path (e.g. 'root/a1h315/js725h') | ||||
|      */ | ||||
|     getBestNotePathString(hoistedNoteId = 'root') { | ||||
|         const notePath = this.getBestNotePath(hoistedNoteId); | ||||
|  | ||||
|         return notePath?.join("/"); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return boolean - true if there's no non-hidden path, note is not cloned to the visible tree | ||||
|      */ | ||||
|   | ||||
| @@ -247,6 +247,11 @@ class FNote { | ||||
|         return this.__filterAttrs(this.__getCachedAttributes([]), type, name); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param {string[]} path | ||||
|      * @return {FAttribute[]} | ||||
|      * @private | ||||
|      */ | ||||
|     __getCachedAttributes(path) { | ||||
|         // notes/clones cannot form tree cycles, it is possible to create attribute inheritance cycle via templates | ||||
|         // when template instance is a parent of template itself | ||||
| @@ -299,63 +304,49 @@ class FNote { | ||||
|         return this.noteId === 'root'; | ||||
|     } | ||||
|  | ||||
|     getAllNotePaths(encounteredNoteIds = null) { | ||||
|     /** | ||||
|      * Gives all possible note paths leading to this note. Paths containing search note are ignored (could form cycles) | ||||
|      * | ||||
|      * @returns {string[][]} - array of notePaths (each represented by array of noteIds constituting the particular note path) | ||||
|      */ | ||||
|     getAllNotePaths() { | ||||
|         if (this.noteId === 'root') { | ||||
|             return [['root']]; | ||||
|         } | ||||
|  | ||||
|         if (!encounteredNoteIds) { | ||||
|             encounteredNoteIds = new Set(); | ||||
|         } | ||||
|  | ||||
|         encounteredNoteIds.add(this.noteId); | ||||
|  | ||||
|         const parentNotes = this.getParentNotes(); | ||||
|         let paths; | ||||
|         let notePaths = []; | ||||
|  | ||||
|         if (parentNotes.length === 1) { // optimization for the most common case | ||||
|             if (encounteredNoteIds.has(parentNotes[0].noteId)) { | ||||
|                 return []; | ||||
|             } | ||||
|             else { | ||||
|                 paths = parentNotes[0].getAllNotePaths(encounteredNoteIds); | ||||
|             } | ||||
|         } | ||||
|         else { | ||||
|             paths = []; | ||||
|  | ||||
|             for (const parentNote of parentNotes) { | ||||
|                 if (encounteredNoteIds.has(parentNote.noteId)) { | ||||
|                     continue; | ||||
|         if (parentNotes.length === 1) { // optimization for most common case | ||||
|             notePaths = parentNotes[0].getAllNotePaths(); | ||||
|         } else { | ||||
|             notePaths = parentNotes.flatMap(parentNote => parentNote.getAllNotePaths()); | ||||
|         } | ||||
|  | ||||
|                 const newSet = new Set(encounteredNoteIds); | ||||
|  | ||||
|                 paths.push(...parentNote.getAllNotePaths(newSet)); | ||||
|             } | ||||
|         for (const notePath of notePaths) { | ||||
|             notePath.push(this.noteId); | ||||
|         } | ||||
|  | ||||
|         for (const path of paths) { | ||||
|             path.push(this.noteId); | ||||
|         return notePaths; | ||||
|     } | ||||
|  | ||||
|         return paths; | ||||
|     } | ||||
|     /** | ||||
|      * @param {string} [hoistedNoteId='root'] | ||||
|      * @return {{isArchived: boolean, isInHoistedSubTree: boolean, notePath: string[], isHidden: boolean}[]} | ||||
|      */ | ||||
|     getSortedNotePathRecords(hoistedNoteId = 'root') { | ||||
|         const isHoistedRoot = hoistedNoteId === 'root'; | ||||
|  | ||||
|     getSortedNotePaths(hoistedNotePath = 'root') { | ||||
|         const notePaths = this.getAllNotePaths().map(path => ({ | ||||
|             notePath: path, | ||||
|             isInHoistedSubTree: path.includes(hoistedNotePath), | ||||
|             isArchived: path.find(noteId => froca.notes[noteId].isArchived), | ||||
|             isSearch: path.find(noteId => froca.notes[noteId].type === 'search'), | ||||
|             isInHoistedSubTree: isHoistedRoot || path.includes(hoistedNoteId), | ||||
|             isArchived: path.some(noteId => froca.notes[noteId].isArchived), | ||||
|             isHidden: path.includes('_hidden') | ||||
|         })); | ||||
|  | ||||
|         notePaths.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) { | ||||
| @@ -368,6 +359,28 @@ class FNote { | ||||
|         return notePaths; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns note path considered to be the "best" | ||||
|      * | ||||
|      * @param {string} [hoistedNoteId='root'] | ||||
|      * @return {string[]} array of noteIds constituting the particular note path | ||||
|      */ | ||||
|     getBestNotePath(hoistedNoteId = 'root') { | ||||
|         return this.getSortedNotePathRecords(hoistedNoteId)[0]?.notePath; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns note path considered to be the "best" | ||||
|      * | ||||
|      * @param {string} [hoistedNoteId='root'] | ||||
|      * @return {string} serialized note path (e.g. 'root/a1h315/js725h') | ||||
|      */ | ||||
|     getBestNotePathString(hoistedNoteId = 'root') { | ||||
|         const notePath = this.getBestNotePath(hoistedNoteId); | ||||
|  | ||||
|         return notePath?.join("/"); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return boolean - true if there's no non-hidden path, note is not cloned to the visible tree | ||||
|      */ | ||||
| @@ -391,6 +404,13 @@ class FNote { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param {FAttribute[]} attributes | ||||
|      * @param {string} type | ||||
|      * @param {string} name | ||||
|      * @return {FAttribute[]} | ||||
|      * @private | ||||
|      */ | ||||
|     __filterAttrs(attributes, type, name) { | ||||
|         this.__validateTypeName(type, name); | ||||
|  | ||||
| @@ -527,7 +547,9 @@ class FNote { | ||||
|      * @returns {boolean} true if note has an attribute with given type and name (including inherited) | ||||
|      */ | ||||
|     hasAttribute(type, name) { | ||||
|         return !!this.getAttribute(type, name); | ||||
|         const attributes = this.getAttributes(); | ||||
|  | ||||
|         return attributes.some(attr => attr.name === name && attr.type === type); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -227,7 +227,7 @@ async function cloneNoteToBranch(childNoteId, parentBranchId, prefix) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| async function cloneNoteToNote(childNoteId, parentNoteId, prefix) { | ||||
| async function cloneNoteToParentNote(childNoteId, parentNoteId, prefix) { | ||||
|     const resp = await server.put(`notes/${childNoteId}/clone-to-note/${parentNoteId}`, { | ||||
|         prefix: prefix | ||||
|     }); | ||||
| @@ -254,5 +254,5 @@ export default { | ||||
|     moveNodeUpInHierarchy, | ||||
|     cloneNoteAfter, | ||||
|     cloneNoteToBranch, | ||||
|     cloneNoteToNote, | ||||
|     cloneNoteToParentNote, | ||||
| }; | ||||
|   | ||||
| @@ -2,7 +2,6 @@ import server from "./server.js"; | ||||
| import appContext from "../components/app_context.js"; | ||||
| import utils from './utils.js'; | ||||
| import noteCreateService from './note_create.js'; | ||||
| import treeService from './tree.js'; | ||||
| import froca from "./froca.js"; | ||||
|  | ||||
| // this key needs to have this value, so it's hit by the tooltip | ||||
| @@ -188,7 +187,8 @@ function initNoteAutocomplete($el, options) { | ||||
|                 templateNoteId: templateNoteId | ||||
|             }); | ||||
|  | ||||
|             suggestion.notePath = treeService.getSomeNotePath(note); | ||||
|             const hoistedNoteId = appContext.tabManager.getActiveContext()?.hoistedNoteId; | ||||
|             suggestion.notePath = note.getBestNotePathString(hoistedNoteId); | ||||
|         } | ||||
|  | ||||
|         $el.setSelectedNotePath(suggestion.notePath); | ||||
|   | ||||
| @@ -4,6 +4,7 @@ import froca from "./froca.js"; | ||||
| import utils from "./utils.js"; | ||||
| import attributeRenderer from "./attribute_renderer.js"; | ||||
| import noteContentRenderer from "./note_content_renderer.js"; | ||||
| import appContext from "../components/app_context.js"; | ||||
|  | ||||
| function setupGlobalTooltip() { | ||||
|     $(document).on("mouseenter", "a", mouseEnterHandler); | ||||
| @@ -83,13 +84,14 @@ async function renderTooltip(note) { | ||||
|         return '<div>Note has been deleted.</div>'; | ||||
|     } | ||||
|  | ||||
|     const someNotePath = treeService.getSomeNotePath(note); | ||||
|     const hoistedNoteId = appContext.tabManager.getActiveContext()?.hoistedNoteId; | ||||
|     const bestNotePath = note.getBestNotePathString(hoistedNoteId); | ||||
|  | ||||
|     if (!someNotePath) { | ||||
|     if (!bestNotePath) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     let content = `<h5 class="note-tooltip-title">${(await treeService.getNoteTitleWithPathAsSuffix(someNotePath)).prop('outerHTML')}</h5>`; | ||||
|     let content = `<h5 class="note-tooltip-title">${(await treeService.getNoteTitleWithPathAsSuffix(bestNotePath)).prop('outerHTML')}</h5>`; | ||||
|  | ||||
|     const {$renderedAttributes} = await attributeRenderer.renderNormalAttributes(note); | ||||
|  | ||||
|   | ||||
| @@ -79,14 +79,10 @@ async function resolveNotePathToSegments(notePath, hoistedNoteId = 'root', logEr | ||||
|                         You can ignore this message as it is mostly harmless.`); | ||||
|                 } | ||||
|  | ||||
|                 const someNotePath = getSomeNotePath(child, hoistedNoteId); | ||||
|                 const bestNotePath = child.getBestNotePath(hoistedNoteId); | ||||
|  | ||||
|                 if (someNotePath) { // in case it's root the path may be empty | ||||
|                     const pathToRoot = someNotePath.split("/").reverse().slice(1); | ||||
|  | ||||
|                     if (!pathToRoot.includes("root")) { | ||||
|                         pathToRoot.push('root'); | ||||
|                     } | ||||
|                 if (bestNotePath) { | ||||
|                     const pathToRoot = bestNotePath.reverse().slice(1); | ||||
|  | ||||
|                     for (const noteId of pathToRoot) { | ||||
|                         effectivePathSegments.push(noteId); | ||||
| @@ -109,31 +105,17 @@ async function resolveNotePathToSegments(notePath, hoistedNoteId = 'root', logEr | ||||
|     else { | ||||
|         const note = await froca.getNote(getNoteIdFromNotePath(notePath)); | ||||
|  | ||||
|         const someNotePathSegments = getSomeNotePathSegments(note, hoistedNoteId); | ||||
|         const bestNotePath = note.getBestNotePath(hoistedNoteId); | ||||
|  | ||||
|         if (!someNotePathSegments) { | ||||
|             throw new Error(`Did not find any path segments for ${note.toString()}, hoisted note ${hoistedNoteId}`); | ||||
|         if (!bestNotePath) { | ||||
|             throw new Error(`Did not find any path segments for '${note.toString()}', hoisted note '${hoistedNoteId}'`); | ||||
|         } | ||||
|  | ||||
|         // if there isn't actually any note path with hoisted note then return the original resolved note path | ||||
|         return someNotePathSegments.includes(hoistedNoteId) ? someNotePathSegments : effectivePathSegments; | ||||
|         return bestNotePath.includes(hoistedNoteId) ? bestNotePath : effectivePathSegments; | ||||
|     } | ||||
| } | ||||
|  | ||||
| function getSomeNotePathSegments(note, hoistedNotePath = 'root') { | ||||
|     utils.assertArguments(note); | ||||
|  | ||||
|     const notePaths = note.getSortedNotePaths(hoistedNotePath); | ||||
|  | ||||
|     return notePaths.length > 0 ? notePaths[0].notePath : null; | ||||
| } | ||||
|  | ||||
| function getSomeNotePath(note, hoistedNotePath = 'root') { | ||||
|     const notePath = getSomeNotePathSegments(note, hoistedNotePath); | ||||
|  | ||||
|     return notePath === null ? null : notePath.join('/'); | ||||
| } | ||||
|  | ||||
| ws.subscribeToMessages(message => { | ||||
|    if (message.type === 'openNote') { | ||||
|        appContext.tabManager.activateOrOpenNote(message.noteId); | ||||
| @@ -311,16 +293,6 @@ function isNotePathInAddress() { | ||||
|         || (notePath === '' && !!ntxId); | ||||
| } | ||||
|  | ||||
| function parseNotePath(notePath) { | ||||
|     let noteIds = notePath.split('/'); | ||||
|  | ||||
|     if (noteIds[0] !== 'root') { | ||||
|         noteIds = ['root'].concat(noteIds); | ||||
|     } | ||||
|  | ||||
|     return noteIds; | ||||
| } | ||||
|  | ||||
| function isNotePathInHiddenSubtree(notePath) { | ||||
|     return notePath?.includes("root/_hidden"); | ||||
| } | ||||
| @@ -328,8 +300,6 @@ function isNotePathInHiddenSubtree(notePath) { | ||||
| export default { | ||||
|     resolveNotePath, | ||||
|     resolveNotePathToSegments, | ||||
|     getSomeNotePath, | ||||
|     getSomeNotePathSegments, | ||||
|     getParentProtectedStatus, | ||||
|     getNotePath, | ||||
|     getNoteIdFromNotePath, | ||||
| @@ -340,6 +310,5 @@ export default { | ||||
|     getNoteTitleWithPathAsSuffix, | ||||
|     getHashValueFromAddress, | ||||
|     isNotePathInAddress, | ||||
|     parseNotePath, | ||||
|     isNotePathInHiddenSubtree | ||||
| }; | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| import server from "../../services/server.js"; | ||||
| import froca from "../../services/froca.js"; | ||||
| import treeService from "../../services/tree.js"; | ||||
| import linkService from "../../services/link.js"; | ||||
| import attributeAutocompleteService from "../../services/attribute_autocomplete.js"; | ||||
| import noteAutocompleteService from "../../services/note_autocomplete.js"; | ||||
| @@ -9,6 +8,7 @@ import NoteContextAwareWidget from "../note_context_aware_widget.js"; | ||||
| import SpacedUpdate from "../../services/spaced_update.js"; | ||||
| import utils from "../../services/utils.js"; | ||||
| import shortcutService from "../../services/shortcuts.js"; | ||||
| import appContext from "../../components/app_context.js"; | ||||
|  | ||||
| const TPL = ` | ||||
| <div class="attr-detail"> | ||||
| @@ -598,9 +598,10 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget { | ||||
|  | ||||
|             const displayedResults = results.length <= DISPLAYED_NOTES ? results : results.slice(0, DISPLAYED_NOTES); | ||||
|             const displayedNotes = await froca.getNotes(displayedResults.map(res => res.noteId)); | ||||
|             const hoistedNoteId = appContext.tabManager.getActiveContext()?.hoistedNoteId; | ||||
|  | ||||
|             for (const note of displayedNotes) { | ||||
|                 const notePath = treeService.getSomeNotePath(note); | ||||
|                 const notePath = note.getBestNotePathString(hoistedNoteId); | ||||
|                 const $noteLink = await linkService.createNoteLink(notePath, {showNotePath: true}); | ||||
|  | ||||
|                 this.$relatedNotesList.append( | ||||
|   | ||||
| @@ -7,7 +7,6 @@ import libraryLoader from "../../services/library_loader.js"; | ||||
| import froca from "../../services/froca.js"; | ||||
| import attributeRenderer from "../../services/attribute_renderer.js"; | ||||
| import noteCreateService from "../../services/note_create.js"; | ||||
| import treeService from "../../services/tree.js"; | ||||
| import attributeService from "../../services/attributes.js"; | ||||
|  | ||||
| const HELP_TEXT = ` | ||||
| @@ -503,7 +502,7 @@ export default class AttributeEditorWidget extends NoteContextAwareWidget { | ||||
|             title: title | ||||
|         }); | ||||
|  | ||||
|         return treeService.getSomeNotePath(note); | ||||
|         return note.getBestNotePathString(); | ||||
|     } | ||||
|  | ||||
|     async updateAttributeList(attributes) { | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| import linkService from '../../services/link.js'; | ||||
| import utils from '../../services/utils.js'; | ||||
| import server from '../../services/server.js'; | ||||
| import treeService from "../../services/tree.js"; | ||||
| import froca from "../../services/froca.js"; | ||||
| import appContext from "../../components/app_context.js"; | ||||
| import hoistedNoteService from "../../services/hoisted_note.js"; | ||||
| @@ -108,7 +107,7 @@ export default class RecentChangesDialog extends BasicWidget { | ||||
|                     } | ||||
|                 } else { | ||||
|                     const note = await froca.getNote(change.noteId); | ||||
|                     const notePath = treeService.getSomeNotePath(note); | ||||
|                     const notePath = note.getBestNotePathString(); | ||||
|  | ||||
|                     if (notePath) { | ||||
|                         $noteLink = await linkService.createNoteLink(notePath, { | ||||
|   | ||||
| @@ -72,7 +72,7 @@ export default class NotePathsWidget extends NoteContextAwareWidget { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         const sortedNotePaths = this.note.getSortedNotePaths(this.hoistedNoteId) | ||||
|         const sortedNotePaths = this.note.getSortedNotePathRecords(this.hoistedNoteId) | ||||
|             .filter(notePath => !notePath.isHidden); | ||||
|  | ||||
|         if (sortedNotePaths.length > 0) { | ||||
|   | ||||
| @@ -25,7 +25,7 @@ export default class SharedSwitchWidget extends SwitchWidget { | ||||
|     } | ||||
|  | ||||
|     async switchOn() { | ||||
|         await branchService.cloneNoteToNote(this.noteId, '_share'); | ||||
|         await branchService.cloneNoteToParentNote(this.noteId, '_share'); | ||||
|  | ||||
|         syncService.syncNow(true); | ||||
|     } | ||||
|   | ||||
| @@ -4,7 +4,6 @@ import mimeTypesService from '../../services/mime_types.js'; | ||||
| import utils from "../../services/utils.js"; | ||||
| import keyboardActionService from "../../services/keyboard_actions.js"; | ||||
| import froca from "../../services/froca.js"; | ||||
| import treeService from "../../services/tree.js"; | ||||
| import noteCreateService from "../../services/note_create.js"; | ||||
| import AbstractTextTypeWidget from "./abstract_text_type_widget.js"; | ||||
| import link from "../../services/link.js"; | ||||
| @@ -378,7 +377,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         return treeService.getSomeNotePath(resp.note); | ||||
|         return resp.note.getBestNotePathString(); | ||||
|     } | ||||
|  | ||||
|     async refreshIncludedNoteEvent({noteId}) { | ||||
|   | ||||
| @@ -9,11 +9,11 @@ function cloneNoteToBranch(req) { | ||||
|     return cloningService.cloneNoteToBranch(noteId, parentBranchId, prefix); | ||||
| } | ||||
|  | ||||
| function cloneNoteToNote(req) { | ||||
| function cloneNoteToParentNote(req) { | ||||
|     const {noteId, parentNoteId} = req.params; | ||||
|     const {prefix} = req.body; | ||||
|  | ||||
|     return cloningService.cloneNoteToNote(noteId, parentNoteId, prefix); | ||||
|     return cloningService.cloneNoteToParentNote(noteId, parentNoteId, prefix); | ||||
| } | ||||
|  | ||||
| function cloneNoteAfter(req) { | ||||
| @@ -30,7 +30,7 @@ function toggleNoteInParent(req) { | ||||
|  | ||||
| module.exports = { | ||||
|     cloneNoteToBranch, | ||||
|     cloneNoteToNote, | ||||
|     cloneNoteToParentNote, | ||||
|     cloneNoteAfter, | ||||
|     toggleNoteInParent | ||||
| }; | ||||
|   | ||||
| @@ -143,7 +143,7 @@ function register(app) { | ||||
|  | ||||
|     apiRoute(PUT, '/api/notes/:noteId/clone-to-branch/:parentBranchId', cloningApiRoute.cloneNoteToBranch); | ||||
|     apiRoute(PUT, '/api/notes/:noteId/toggle-in-parent/:parentNoteId/:present', cloningApiRoute.toggleNoteInParent); | ||||
|     apiRoute(PUT, '/api/notes/:noteId/clone-to-note/:parentNoteId', cloningApiRoute.cloneNoteToNote); | ||||
|     apiRoute(PUT, '/api/notes/:noteId/clone-to-note/:parentNoteId', cloningApiRoute.cloneNoteToParentNote); | ||||
|     apiRoute(PUT, '/api/notes/:noteId/clone-after/:afterBranchId', cloningApiRoute.cloneNoteAfter); | ||||
|  | ||||
|     route(GET, '/api/notes/:branchId/export/:type/:format/:version/:taskId', [auth.checkApiAuthOrElectron], exportRoute.exportBranch); | ||||
|   | ||||
| @@ -83,7 +83,7 @@ const ACTION_HANDLERS = { | ||||
|         let res; | ||||
|  | ||||
|         if (note.getParentBranches().length > 1) { | ||||
|             res = cloningService.cloneNoteToNote(note.noteId, action.targetParentNoteId); | ||||
|             res = cloningService.cloneNoteToParentNote(note.noteId, action.targetParentNoteId); | ||||
|         } | ||||
|         else { | ||||
|             res = branchService.moveBranchToNote(note.getParentBranches()[0], action.targetParentNoteId); | ||||
|   | ||||
| @@ -8,7 +8,7 @@ const becca = require("../becca/becca"); | ||||
| const beccaService = require("../becca/becca_service"); | ||||
| const log = require("./log"); | ||||
|  | ||||
| function cloneNoteToNote(noteId, parentNoteId, prefix) { | ||||
| function cloneNoteToParentNote(noteId, parentNoteId, prefix) { | ||||
|     const parentNote = becca.getNote(parentNoteId); | ||||
|  | ||||
|     if (parentNote.type === 'search') { | ||||
| @@ -19,7 +19,7 @@ function cloneNoteToNote(noteId, parentNoteId, prefix) { | ||||
|     } | ||||
|  | ||||
|     if (isNoteDeleted(noteId) || isNoteDeleted(parentNoteId)) { | ||||
|         return { success: false, message: 'Note is deleted.' }; | ||||
|         return { success: false, message: 'Note cannot be cloned because either the cloned note or the intended parent is deleted.' }; | ||||
|     } | ||||
|  | ||||
|     const validationResult = treeService.validateParentChild(parentNoteId, noteId); | ||||
| @@ -35,7 +35,7 @@ function cloneNoteToNote(noteId, parentNoteId, prefix) { | ||||
|         isExpanded: 0 | ||||
|     }).save(); | ||||
|  | ||||
|     log.info(`Cloned note '${noteId}' to new parent note '${parentNoteId}' with prefix '${prefix}'`); | ||||
|     log.info(`Cloned note '${noteId}' to a new parent note '${parentNoteId}' with prefix '${prefix}'`); | ||||
|  | ||||
|     return { | ||||
|         success: true, | ||||
| @@ -51,7 +51,7 @@ function cloneNoteToBranch(noteId, parentBranchId, prefix) { | ||||
|         return { success: false, message: `Parent branch ${parentBranchId} does not exist.` }; | ||||
|     } | ||||
|  | ||||
|     const ret = cloneNoteToNote(noteId, parentBranch.noteId, prefix); | ||||
|     const ret = cloneNoteToParentNote(noteId, parentBranch.noteId, prefix); | ||||
|  | ||||
|     parentBranch.isExpanded = true; // the new target should be expanded, so it immediately shows up to the user | ||||
|     parentBranch.save(); | ||||
| @@ -182,7 +182,7 @@ function isNoteDeleted(noteId) { | ||||
|  | ||||
| module.exports = { | ||||
|     cloneNoteToBranch, | ||||
|     cloneNoteToNote, | ||||
|     cloneNoteToParentNote, | ||||
|     ensureNoteIsPresentInParent, | ||||
|     ensureNoteIsAbsentFromParent, | ||||
|     toggleNoteInParent, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user