mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	added possibility to search by attached script returning note ids + some refactorings
This commit is contained in:
		| @@ -41,7 +41,7 @@ import macInit from './services/mac_init.js'; | |||||||
| import cssLoader from './services/css_loader.js'; | import cssLoader from './services/css_loader.js'; | ||||||
|  |  | ||||||
| // required for CKEditor image upload plugin | // required for CKEditor image upload plugin | ||||||
| window.glob.getCurrentNode = treeService.getCurrentNode; | window.glob.getActiveNode = treeService.getActiveNode; | ||||||
| window.glob.getHeaders = server.getHeaders; | window.glob.getHeaders = server.getHeaders; | ||||||
| window.glob.showAddLinkDialog = addLinkDialog.showDialog; | window.glob.showAddLinkDialog = addLinkDialog.showDialog; | ||||||
| // this is required by CKEditor when uploading images | // this is required by CKEditor when uploading images | ||||||
| @@ -120,7 +120,7 @@ if (utils.isElectron()) { | |||||||
|         await treeService.activateNote(parentNoteId); |         await treeService.activateNote(parentNoteId); | ||||||
|  |  | ||||||
|         setTimeout(async () => { |         setTimeout(async () => { | ||||||
|             const parentNode = treeService.getCurrentNode(); |             const parentNode = treeService.getActiveNode(); | ||||||
|  |  | ||||||
|             const {note} = await treeService.createNote(parentNode, parentNode.data.noteId, 'into', "text", parentNode.data.isProtected); |             const {note} = await treeService.createNote(parentNode, parentNode.data.noteId, 'into', "text", parentNode.data.isProtected); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ async function showDialog() { | |||||||
|  |  | ||||||
|     $dialog.modal(); |     $dialog.modal(); | ||||||
|  |  | ||||||
|     const currentNode = treeService.getCurrentNode(); |     const currentNode = treeService.getActiveNode(); | ||||||
|  |  | ||||||
|     branchId = currentNode.data.branchId; |     branchId = currentNode.data.branchId; | ||||||
|     const branch = await treeCache.getBranch(branchId); |     const branch = await treeCache.getBranch(branchId); | ||||||
|   | |||||||
| @@ -45,7 +45,7 @@ async function showDialog(defaultType) { | |||||||
|  |  | ||||||
|     $dialog.modal(); |     $dialog.modal(); | ||||||
|  |  | ||||||
|     const currentNode = treeService.getCurrentNode(); |     const currentNode = treeService.getActiveNode(); | ||||||
|     const noteTitle = await treeUtils.getNoteTitle(currentNode.data.noteId); |     const noteTitle = await treeUtils.getNoteTitle(currentNode.data.noteId); | ||||||
|  |  | ||||||
|     $noteTitle.html(noteTitle); |     $noteTitle.html(noteTitle); | ||||||
| @@ -69,7 +69,7 @@ $form.submit(() => { | |||||||
|  |  | ||||||
|     const exportVersion = exportFormat === 'opml' ? $dialog.find("input[name='opml-version']:checked").val() : "1.0"; |     const exportVersion = exportFormat === 'opml' ? $dialog.find("input[name='opml-version']:checked").val() : "1.0"; | ||||||
|  |  | ||||||
|     const currentNode = treeService.getCurrentNode(); |     const currentNode = treeService.getActiveNode(); | ||||||
|  |  | ||||||
|     exportBranch(currentNode.data.branchId, exportType, exportFormat, exportVersion); |     exportBranch(currentNode.data.branchId, exportType, exportFormat, exportVersion); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -35,14 +35,14 @@ async function showDialog() { | |||||||
|  |  | ||||||
|     glob.activeDialog = $dialog; |     glob.activeDialog = $dialog; | ||||||
|  |  | ||||||
|     const currentNode = treeService.getCurrentNode(); |     const currentNode = treeService.getActiveNode(); | ||||||
|     $noteTitle.text(await treeUtils.getNoteTitle(currentNode.data.noteId)); |     $noteTitle.text(await treeUtils.getNoteTitle(currentNode.data.noteId)); | ||||||
|  |  | ||||||
|     $dialog.modal(); |     $dialog.modal(); | ||||||
| } | } | ||||||
|  |  | ||||||
| $form.submit(() => { | $form.submit(() => { | ||||||
|     const currentNode = treeService.getCurrentNode(); |     const currentNode = treeService.getActiveNode(); | ||||||
|  |  | ||||||
|     // disabling so that import is not triggered again. |     // disabling so that import is not triggered again. | ||||||
|     $importButton.attr("disabled", "disabled"); |     $importButton.attr("disabled", "disabled"); | ||||||
|   | |||||||
| @@ -71,7 +71,7 @@ async function showTree() { | |||||||
| } | } | ||||||
|  |  | ||||||
| $("#note-menu-button").click(async e => { | $("#note-menu-button").click(async e => { | ||||||
|     const node = treeService.getCurrentNode(); |     const node = treeService.getActiveNode(); | ||||||
|     const branch = await treeCache.getBranch(node.data.branchId); |     const branch = await treeCache.getBranch(node.data.branchId); | ||||||
|     const note = await treeCache.getNote(node.data.noteId); |     const note = await treeCache.getNote(node.data.noteId); | ||||||
|     const parentNote = await treeCache.getNote(branch.parentNoteId); |     const parentNote = await treeCache.getNote(branch.parentNoteId); | ||||||
|   | |||||||
| @@ -138,7 +138,7 @@ function registerEntrypoints() { | |||||||
|  |  | ||||||
|     // FIXME: do we really need these at this point? |     // FIXME: do we really need these at this point? | ||||||
|     utils.bindShortcut("ctrl+shift+up", () => { |     utils.bindShortcut("ctrl+shift+up", () => { | ||||||
|         const node = treeService.getCurrentNode(); |         const node = treeService.getActiveNode(); | ||||||
|         node.navigate($.ui.keyCode.UP, true); |         node.navigate($.ui.keyCode.UP, true); | ||||||
|  |  | ||||||
|         $("#note-detail-text").focus(); |         $("#note-detail-text").focus(); | ||||||
| @@ -147,7 +147,7 @@ function registerEntrypoints() { | |||||||
|  |  | ||||||
|     // FIXME: do we really need these at this point? |     // FIXME: do we really need these at this point? | ||||||
|     utils.bindShortcut("ctrl+shift+down", () => { |     utils.bindShortcut("ctrl+shift+down", () => { | ||||||
|         const node = treeService.getCurrentNode(); |         const node = treeService.getActiveNode(); | ||||||
|         node.navigate($.ui.keyCode.DOWN, true); |         node.navigate($.ui.keyCode.DOWN, true); | ||||||
|  |  | ||||||
|         $("#note-detail-text").focus(); |         $("#note-detail-text").focus(); | ||||||
|   | |||||||
| @@ -187,7 +187,7 @@ async function loadNoteDetail(noteId) { | |||||||
|     // this is useful when user quickly switches notes (by e.g. holding down arrow) so that we don't |     // this is useful when user quickly switches notes (by e.g. holding down arrow) so that we don't | ||||||
|     // try to render all those loaded notes one after each other. This only guarantees that correct note |     // try to render all those loaded notes one after each other. This only guarantees that correct note | ||||||
|     // will be displayed independent of timing |     // will be displayed independent of timing | ||||||
|     const currentTreeNode = treeService.getCurrentNode(); |     const currentTreeNode = treeService.getActiveNode(); | ||||||
|     if (currentTreeNode && currentTreeNode.data.noteId !== loadedNote.noteId) { |     if (currentTreeNode && currentTreeNode.data.noteId !== loadedNote.noteId) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @@ -196,7 +196,7 @@ async function loadNoteDetail(noteId) { | |||||||
|     activeNote = loadedNote; |     activeNote = loadedNote; | ||||||
|  |  | ||||||
|     if (utils.isDesktop()) { |     if (utils.isDesktop()) { | ||||||
|         // needs to happen after loading the note itself because it references current noteId |         // needs to happen after loading the note itself because it references active noteId | ||||||
|         attributeService.refreshAttributes(); |         attributeService.refreshAttributes(); | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|   | |||||||
| @@ -43,7 +43,7 @@ function ensureProtectedSession(requireProtectedSession, modal) { | |||||||
|         $noteTitle.prop("readonly", true); |         $noteTitle.prop("readonly", true); | ||||||
|  |  | ||||||
|         if (modal) { |         if (modal) { | ||||||
|             if (treeService.getCurrentNode().data.isProtected) { |             if (treeService.getActiveNode().data.isProtected) { | ||||||
|                 $noteDetailWrapper.hide(); |                 $noteDetailWrapper.hide(); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ import confirmDialog from "../dialogs/confirm.js"; | |||||||
| const $tree = $("#tree"); | const $tree = $("#tree"); | ||||||
| const $createTopLevelNoteButton = $("#create-top-level-note-button"); | const $createTopLevelNoteButton = $("#create-top-level-note-button"); | ||||||
| const $collapseTreeButton = $("#collapse-tree-button"); | const $collapseTreeButton = $("#collapse-tree-button"); | ||||||
| const $scrollToCurrentNoteButton = $("#scroll-to-current-note-button"); | const $scrollToActiveNoteButton = $("#scroll-to-active-note-button"); | ||||||
| const $notePathList = $("#note-path-list"); | const $notePathList = $("#note-path-list"); | ||||||
| const $notePathCount = $("#note-path-count"); | const $notePathCount = $("#note-path-count"); | ||||||
|  |  | ||||||
| @@ -35,12 +35,12 @@ function getFocusedNode() { | |||||||
| } | } | ||||||
|  |  | ||||||
| // note that if you want to access data like noteId or isProtected, you need to go into "data" property | // note that if you want to access data like noteId or isProtected, you need to go into "data" property | ||||||
| function getCurrentNode() { | function getActiveNode() { | ||||||
|     return $tree.fancytree("getActiveNode"); |     return $tree.fancytree("getActiveNode"); | ||||||
| } | } | ||||||
|  |  | ||||||
| function getActiveNotePath() { | function getActiveNotePath() { | ||||||
|     const node = getCurrentNode(); |     const node = getActiveNode(); | ||||||
|  |  | ||||||
|     return treeUtils.getNotePath(node); |     return treeUtils.getNotePath(node); | ||||||
| } | } | ||||||
| @@ -356,7 +356,7 @@ function clearSelectedNodes() { | |||||||
|         selectedNode.setSelected(false); |         selectedNode.setSelected(false); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const currentNode = getCurrentNode(); |     const currentNode = getActiveNode(); | ||||||
|  |  | ||||||
|     if (currentNode) { |     if (currentNode) { | ||||||
|         currentNode.setSelected(true); |         currentNode.setSelected(true); | ||||||
| @@ -520,8 +520,8 @@ async function collapseTree(node = null) { | |||||||
|     node.visit(node => node.setExpanded(false)); |     node.visit(node => node.setExpanded(false)); | ||||||
| } | } | ||||||
|  |  | ||||||
| function scrollToCurrentNote() { | function scrollToActiveNote() { | ||||||
|     const node = getCurrentNode(); |     const node = getActiveNode(); | ||||||
|  |  | ||||||
|     if (node) { |     if (node) { | ||||||
|         node.makeVisible({scrollIntoView: true}); |         node.makeVisible({scrollIntoView: true}); | ||||||
| @@ -697,7 +697,7 @@ messagingService.subscribeToSyncMessages(syncData => { | |||||||
| }); | }); | ||||||
|  |  | ||||||
| utils.bindShortcut('ctrl+o', async () => { | utils.bindShortcut('ctrl+o', async () => { | ||||||
|     const node = getCurrentNode(); |     const node = getActiveNode(); | ||||||
|     const parentNoteId = node.data.parentNoteId; |     const parentNoteId = node.data.parentNoteId; | ||||||
|     const isProtected = treeUtils.getParentProtectedStatus(node); |     const isProtected = treeUtils.getParentProtectedStatus(node); | ||||||
|  |  | ||||||
| @@ -709,7 +709,7 @@ utils.bindShortcut('ctrl+o', async () => { | |||||||
| }); | }); | ||||||
|  |  | ||||||
| function createNoteInto() { | function createNoteInto() { | ||||||
|     const node = getCurrentNode(); |     const node = getActiveNode(); | ||||||
|  |  | ||||||
|     createNote(node, node.data.noteId, 'into', null, node.data.isProtected, true); |     createNote(node, node.data.noteId, 'into', null, node.data.isProtected, true); | ||||||
| } | } | ||||||
| @@ -742,7 +742,7 @@ window.glob.createNoteInto = createNoteInto; | |||||||
|  |  | ||||||
| utils.bindShortcut('ctrl+p', createNoteInto); | utils.bindShortcut('ctrl+p', createNoteInto); | ||||||
|  |  | ||||||
| utils.bindShortcut('ctrl+.', scrollToCurrentNote); | utils.bindShortcut('ctrl+.', scrollToActiveNote); | ||||||
|  |  | ||||||
| $(window).bind('hashchange', function() { | $(window).bind('hashchange', function() { | ||||||
|     if (isNotePathInAddress()) { |     if (isNotePathInAddress()) { | ||||||
| @@ -760,18 +760,18 @@ utils.bindShortcut('alt+c', () => collapseTree()); // don't use shortened form s | |||||||
| $collapseTreeButton.click(() => collapseTree()); | $collapseTreeButton.click(() => collapseTree()); | ||||||
|  |  | ||||||
| $createTopLevelNoteButton.click(createNewTopLevelNote); | $createTopLevelNoteButton.click(createNewTopLevelNote); | ||||||
| $scrollToCurrentNoteButton.click(scrollToCurrentNote); | $scrollToActiveNoteButton.click(scrollToActiveNote); | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|     reload, |     reload, | ||||||
|     collapseTree, |     collapseTree, | ||||||
|     scrollToCurrentNote, |     scrollToActiveNote, | ||||||
|     setBranchBackgroundBasedOnProtectedStatus, |     setBranchBackgroundBasedOnProtectedStatus, | ||||||
|     setProtected, |     setProtected, | ||||||
|     expandToNote, |     expandToNote, | ||||||
|     activateNote, |     activateNote, | ||||||
|     getFocusedNode, |     getFocusedNode, | ||||||
|     getCurrentNode, |     getActiveNode, | ||||||
|     getActiveNotePath, |     getActiveNotePath, | ||||||
|     setCurrentNotePathToHash, |     setCurrentNotePathToHash, | ||||||
|     setNoteTitle, |     setNoteTitle, | ||||||
|   | |||||||
| @@ -115,22 +115,7 @@ async function prepareRealBranch(parentNote) { | |||||||
| } | } | ||||||
|  |  | ||||||
| async function prepareSearchBranch(note) { | async function prepareSearchBranch(note) { | ||||||
|     const fullNote = await noteDetailService.loadNote(note.noteId); |     const results = await server.get('search-note/' + note.noteId); | ||||||
|  |  | ||||||
|     console.log("ZZZ", fullNote.noteContent.content); |  | ||||||
|  |  | ||||||
|     if (!fullNote.noteContent.content || !fullNote.noteContent.content.trim()) { |  | ||||||
|         return []; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     const json = JSON.parse(fullNote.noteContent.content); |  | ||||||
|  |  | ||||||
|     if (!json.searchString || !json.searchString.trim()) { |  | ||||||
|         return []; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     const results = (await server.get('search/' + encodeURIComponent(json.searchString))) |  | ||||||
|         .filter(res => res.noteId !== note.noteId); // this is necessary because title of the search note is often the same as the search text which would match and create circle |  | ||||||
|  |  | ||||||
|     // force to load all the notes at once instead of one by one |     // force to load all the notes at once instead of one by one | ||||||
|     await treeCache.getNotes(results.map(res => res.noteId)); |     await treeCache.getNotes(results.map(res => res.noteId)); | ||||||
| @@ -149,7 +134,7 @@ async function prepareSearchBranch(note) { | |||||||
|         treeCache.addBranch(branch); |         treeCache.addBranch(branch); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return await prepareRealBranch(fullNote); |     return await prepareRealBranch(note); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function getExtraClasses(note) { | async function getExtraClasses(note) { | ||||||
|   | |||||||
| @@ -158,7 +158,7 @@ async function getContextMenuItems(event) { | |||||||
|  |  | ||||||
| function selectContextMenuItem(event, cmd) { | function selectContextMenuItem(event, cmd) { | ||||||
|     // context menu is always triggered on current node |     // context menu is always triggered on current node | ||||||
|     const node = treeService.getCurrentNode(); |     const node = treeService.getActiveNode(); | ||||||
|  |  | ||||||
|     if (cmd.startsWith("insertNoteAfter")) { |     if (cmd.startsWith("insertNoteAfter")) { | ||||||
|         const parentNoteId = node.data.parentNoteId; |         const parentNoteId = node.data.parentNoteId; | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								src/public/libraries/ckeditor/ckeditor.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								src/public/libraries/ckeditor/ckeditor.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -28,7 +28,7 @@ | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     async function validatorJavaScript(text, options) { |     async function validatorJavaScript(text, options) { | ||||||
|         if (glob.getCurrentNote().mime === 'application/json') { |         if (glob.getActiveNote().mime === 'application/json') { | ||||||
|             // eslint doesn't seem to validate pure JSON well |             // eslint doesn't seem to validate pure JSON well | ||||||
|             return []; |             return []; | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -1,7 +1,10 @@ | |||||||
| "use strict"; | "use strict"; | ||||||
|  |  | ||||||
| const noteService = require('../../services/notes'); | const noteService = require('../../services/notes'); | ||||||
|  | const repository = require('../../services/repository'); | ||||||
| const noteCacheService = require('../../services/note_cache'); | const noteCacheService = require('../../services/note_cache'); | ||||||
|  | const log = require('../../services/log'); | ||||||
|  | const scriptService = require('../../services/script'); | ||||||
| const searchService = require('../../services/search'); | const searchService = require('../../services/search'); | ||||||
|  |  | ||||||
| async function searchNotes(req) { | async function searchNotes(req) { | ||||||
| @@ -24,7 +27,79 @@ async function saveSearchToNote(req) { | |||||||
|     return { noteId: note.noteId }; |     return { noteId: note.noteId }; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | async function searchFromNote(req) { | ||||||
|  |     const note = await repository.getNote(req.params.noteId); | ||||||
|  |  | ||||||
|  |     if (!note) { | ||||||
|  |         return [404, `Note ${req.params.noteId} has not been found.`]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (note.type !== 'search') { | ||||||
|  |         return [400, '`Note ${req.params.noteId} is not search note.`'] | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const json = await note.getJsonContent(); | ||||||
|  |  | ||||||
|  |     if (!json || !json.searchString) { | ||||||
|  |         return []; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     let noteIds; | ||||||
|  |  | ||||||
|  |     if (json.searchString.startsWith('=')) { | ||||||
|  |         const relationName = json.searchString.substr(1).trim(); | ||||||
|  |  | ||||||
|  |         noteIds = await searchFromRelation(note, relationName); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         noteIds = searchService.searchForNoteIds(json.searchString); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // we won't return search note's own noteId | ||||||
|  |     noteIds = noteIds.filter(noteId => noteId !== note.noteId); | ||||||
|  |  | ||||||
|  |     return noteIds.map(noteCacheService.getNotePath).filter(res => !!res); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | async function searchFromRelation(note, relationName) { | ||||||
|  |     const scriptNote = await note.getRelationTarget(relationName); | ||||||
|  |  | ||||||
|  |     if (!scriptNote) { | ||||||
|  |         log.info(`Search note's relation ${relationName} has not been found.`); | ||||||
|  |  | ||||||
|  |         return []; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!scriptNote.isJavaScript() || scriptNote.getScriptEnv() !== 'backend') { | ||||||
|  |         log.info(`Note ${scriptNote.noteId} is not executable.`); | ||||||
|  |  | ||||||
|  |         return []; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!note.isContentAvailable) { | ||||||
|  |         log.info(`Note ${scriptNote.noteId} is not available outside of protected session.`); | ||||||
|  |  | ||||||
|  |         return []; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const result = await scriptService.executeNote(scriptNote, { originEntity: note }); | ||||||
|  |  | ||||||
|  |     if (!Array.isArray(result)) { | ||||||
|  |         log.info(`Result from ${scriptNote.noteId} is not an array.`); | ||||||
|  |  | ||||||
|  |         return []; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (result.length === 0) { | ||||||
|  |         return []; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // we expect either array of noteIds (strings) or notes, in that case we extract noteIds ourselves | ||||||
|  |     return typeof result[0] === 'string' ? result : result.map(item => item.noteId); | ||||||
|  | } | ||||||
|  |  | ||||||
| module.exports = { | module.exports = { | ||||||
|     searchNotes, |     searchNotes, | ||||||
|     saveSearchToNote |     saveSearchToNote, | ||||||
|  |     searchFromNote | ||||||
| }; | }; | ||||||
| @@ -202,6 +202,7 @@ function register(app) { | |||||||
|  |  | ||||||
|     apiRoute(GET, '/api/search/:searchString', searchRoute.searchNotes); |     apiRoute(GET, '/api/search/:searchString', searchRoute.searchNotes); | ||||||
|     apiRoute(POST, '/api/search/:searchString', searchRoute.saveSearchToNote); |     apiRoute(POST, '/api/search/:searchString', searchRoute.saveSearchToNote); | ||||||
|  |     apiRoute(GET, '/api/search-note/:noteId', searchRoute.searchFromNote); | ||||||
|  |  | ||||||
|     route(POST, '/api/login/sync', [], loginApiRoute.loginSync, apiResultHandler); |     route(POST, '/api/login/sync', [], loginApiRoute.loginSync, apiResultHandler); | ||||||
|     // this is for entering protected mode so user has to be already logged-in (that's the reason we don't require username) |     // this is for entering protected mode so user has to be already logged-in (that's the reason we don't require username) | ||||||
|   | |||||||
| @@ -7,12 +7,14 @@ const log = require('./log'); | |||||||
|  |  | ||||||
| async function executeNote(note, apiParams) { | async function executeNote(note, apiParams) { | ||||||
|     if (!note.isJavaScript() || note.getScriptEnv() !== 'backend' || !note.isContentAvailable) { |     if (!note.isJavaScript() || note.getScriptEnv() !== 'backend' || !note.isContentAvailable) { | ||||||
|  |         log.info(`Cannot execute note ${note.noteId}`); | ||||||
|  |  | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const bundle = await getScriptBundle(note); |     const bundle = await getScriptBundle(note); | ||||||
|  |  | ||||||
|     await executeBundle(bundle, apiParams); |     return await executeBundle(bundle, apiParams); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function executeNoteNoException(note, apiParams) { | async function executeNoteNoException(note, apiParams) { | ||||||
|   | |||||||
| @@ -94,7 +94,7 @@ | |||||||
|  |  | ||||||
|             <a id="collapse-tree-button" title="Collapse note tree. Shortcut ALT+C" class="icon-action jam jam-layers"></a> |             <a id="collapse-tree-button" title="Collapse note tree. Shortcut ALT+C" class="icon-action jam jam-layers"></a> | ||||||
|  |  | ||||||
|             <a id="scroll-to-current-note-button" title="Scroll to current note. Shortcut CTRL+." class="icon-action jam jam-download"></a> |             <a id="scroll-to-active-note-button" title="Scroll to active note. Shortcut CTRL+." class="icon-action jam jam-download"></a> | ||||||
|  |  | ||||||
|             <a id="toggle-search-button" title="Search in notes. Shortcut CTRL+S" class="icon-action jam jam-search"></a> |             <a id="toggle-search-button" title="Search in notes. Shortcut CTRL+S" class="icon-action jam jam-search"></a> | ||||||
|         </div> |         </div> | ||||||
|   | |||||||
| @@ -13,17 +13,17 @@ | |||||||
|             <form id="add-link-form"> |             <form id="add-link-form"> | ||||||
|                 <div class="modal-body"> |                 <div class="modal-body"> | ||||||
|                     <div id="add-link-type-div" class="radio"> |                     <div id="add-link-type-div" class="radio"> | ||||||
|                         <label title="Add HTML link to the selected note at cursor in current note"> |                         <label title="Add HTML link to the selected note at cursor in active note"> | ||||||
|                             <input type="radio" name="add-link-type" value="html"/> |                             <input type="radio" name="add-link-type" value="html"/> | ||||||
|                             add normal HTML link</label> |                             add normal HTML link</label> | ||||||
|  |  | ||||||
|                         <label title="Add selected note as a child of current note"> |                         <label title="Add selected note as a child of active note"> | ||||||
|                             <input type="radio" name="add-link-type" value="selected-to-current"/> |                             <input type="radio" name="add-link-type" value="selected-to-current"/> | ||||||
|                             add selected note to current note</label> |                             add selected note to active note</label> | ||||||
|  |  | ||||||
|                         <label title="Add current note as a child of the selected note"> |                         <label title="Add active note as a child of the selected note"> | ||||||
|                             <input type="radio" name="add-link-type" value="current-to-selected"/> |                             <input type="radio" name="add-link-type" value="current-to-selected"/> | ||||||
|                             add current note to selected note</label> |                             add active note to selected note</label> | ||||||
|                     </div> |                     </div> | ||||||
|  |  | ||||||
|                     <div class="form-group"> |                     <div class="form-group"> | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ | |||||||
|                                     <li><kbd>LEFT/RIGHT</kbd> - collapse/expand node</li> |                                     <li><kbd>LEFT/RIGHT</kbd> - collapse/expand node</li> | ||||||
|                                     <li><kbd>ALT+LEFT/RIGHT</kbd> - go back / forwards in the history</li> |                                     <li><kbd>ALT+LEFT/RIGHT</kbd> - go back / forwards in the history</li> | ||||||
|                                     <li><kbd>CTRL+J</kbd> - show <a class="external" href="https://github.com/zadam/trilium/wiki/Note-navigation#jump-to-note">"Jump to" dialog</a></li> |                                     <li><kbd>CTRL+J</kbd> - show <a class="external" href="https://github.com/zadam/trilium/wiki/Note-navigation#jump-to-note">"Jump to" dialog</a></li> | ||||||
|                                     <li><kbd>CTRL+.</kbd> - scroll to current note</li> |                                     <li><kbd>CTRL+.</kbd> - scroll to active note</li> | ||||||
|                                     <li><kbd>BACKSPACE</kbd> - jumps to parent note</li> |                                     <li><kbd>BACKSPACE</kbd> - jumps to parent note</li> | ||||||
|                                     <li><kbd>ALT+C</kbd> - collapse whole note tree</li> |                                     <li><kbd>ALT+C</kbd> - collapse whole note tree</li> | ||||||
|                                     <li><kbd>ALT+-</kbd> (alt with minus sign) - collapse sub-tree</li> |                                     <li><kbd>ALT+-</kbd> (alt with minus sign) - collapse sub-tree</li> | ||||||
| @@ -35,9 +35,9 @@ | |||||||
|  |  | ||||||
|                             <p class="card-text"> |                             <p class="card-text"> | ||||||
|                                 <ul> |                                 <ul> | ||||||
|                                     <li><kbd>CTRL+O</kbd> - creates new note after the current note</li> |                                     <li><kbd>CTRL+O</kbd> - creates new note after the active note</li> | ||||||
|                                     <li><kbd>CTRL+P</kbd> - creates new sub-note into current note</li> |                                     <li><kbd>CTRL+P</kbd> - creates new sub-note into active note</li> | ||||||
|                                     <li><kbd>F2</kbd> - edit <a class="external" href="https://github.com/zadam/trilium/wiki/Tree concepts#prefix">prefix</a> of current note clone</li> |                                     <li><kbd>F2</kbd> - edit <a class="external" href="https://github.com/zadam/trilium/wiki/Tree concepts#prefix">prefix</a> of active note clone</li> | ||||||
|                                 </ul> |                                 </ul> | ||||||
|                             </p> |                             </p> | ||||||
|                         </div> |                         </div> | ||||||
| @@ -54,9 +54,9 @@ | |||||||
|                                     <li><kbd>SHIFT+UP/DOWN</kbd> - multi-select note above/below</li> |                                     <li><kbd>SHIFT+UP/DOWN</kbd> - multi-select note above/below</li> | ||||||
|                                     <li><kbd>CTRL+A</kbd> - select all notes in the current level</li> |                                     <li><kbd>CTRL+A</kbd> - select all notes in the current level</li> | ||||||
|                                     <li><kbd>CTRL+click</kbd> - select note</li> |                                     <li><kbd>CTRL+click</kbd> - select note</li> | ||||||
|                                 <li><kbd>CTRL+C</kbd> - copies current note (or current selection) into clipboard (used for <a class="external" href="https://github.com/zadam/trilium/wiki/Cloning notes">cloning</a>)</li> |                                 <li><kbd>CTRL+C</kbd> - copies active note (or current selection) into clipboard (used for <a class="external" href="https://github.com/zadam/trilium/wiki/Cloning notes">cloning</a>)</li> | ||||||
|                                     <li><kbd>CTRL+X</kbd> - cuts current (or current selection) note into clipboard (used for moving notes)</li> |                                     <li><kbd>CTRL+X</kbd> - cuts current (or current selection) note into clipboard (used for moving notes)</li> | ||||||
|                                     <li><kbd>CTRL+V</kbd> - pastes note(s) as sub-note into current note (which is either move or clone depending on whether it was copied or cut into clipboard)</li> |                                     <li><kbd>CTRL+V</kbd> - pastes note(s) as sub-note into active note (which is either move or clone depending on whether it was copied or cut into clipboard)</li> | ||||||
|                                     <li><kbd>DEL</kbd> - delete note / sub-tree</li> |                                     <li><kbd>DEL</kbd> - delete note / sub-tree</li> | ||||||
|                                 </ul> |                                 </ul> | ||||||
|                             </p> |                             </p> | ||||||
| @@ -73,7 +73,7 @@ | |||||||
|                                     <li><kbd>CTRL+K</kbd> - create / edit external link</li> |                                     <li><kbd>CTRL+K</kbd> - create / edit external link</li> | ||||||
|                                     <li><kbd>CTRL+L</kbd> - create internal link</li> |                                     <li><kbd>CTRL+L</kbd> - create internal link</li> | ||||||
|                                     <li><kbd>ALT+T</kbd> - inserts current date and time at caret position</li> |                                     <li><kbd>ALT+T</kbd> - inserts current date and time at caret position</li> | ||||||
|                                     <li><kbd>CTRL+.</kbd> - jump away to the tree pane and scroll to current note</li> |                                     <li><kbd>CTRL+.</kbd> - jump away to the tree pane and scroll to active note</li> | ||||||
|                                 </ul> |                                 </ul> | ||||||
|                             </p> |                             </p> | ||||||
|                         </div> |                         </div> | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ | |||||||
|  |  | ||||||
|             <a id="collapse-tree-button" title="Collapse note tree. Shortcut ALT+C" class="icon-action jam jam-layers"></a> |             <a id="collapse-tree-button" title="Collapse note tree. Shortcut ALT+C" class="icon-action jam jam-layers"></a> | ||||||
|  |  | ||||||
|             <a id="scroll-to-current-note-button" title="Scroll to current note. Shortcut CTRL+." class="icon-action jam jam-download"></a> |             <a id="scroll-to-active-note-button" title="Scroll to active note. Shortcut CTRL+." class="icon-action jam jam-download"></a> | ||||||
|  |  | ||||||
|             <div class="dropdown"> |             <div class="dropdown"> | ||||||
|                 <a id="global-actions-button" title="Global actions" class="icon-action jam jam-cogs dropdown-toggle" data-toggle="dropdown"></a> |                 <a id="global-actions-button" title="Global actions" class="icon-action jam jam-cogs dropdown-toggle" data-toggle="dropdown"></a> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user