mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	hoisting notes WIP
This commit is contained in:
		
							
								
								
									
										2
									
								
								db/migrations/0121__add_hoisting_option.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								db/migrations/0121__add_hoisting_option.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | |||||||
|  | INSERT INTO options (name, value, dateCreated, dateModified, isSynced) | ||||||
|  | VALUES ('hoistedNoteId', 'root', '2018-12-11T18:31:00.874Z', '2018-12-11T18:31:00.874Z', 0); | ||||||
| @@ -4,6 +4,10 @@ function initContextMenu(event, contextMenuItems, selectContextMenuItem) { | |||||||
|     $contextMenuContainer.empty(); |     $contextMenuContainer.empty(); | ||||||
|  |  | ||||||
|     for (const item of contextMenuItems) { |     for (const item of contextMenuItems) { | ||||||
|  |         if (item.hidden) { | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         if (item.title === '----') { |         if (item.title === '----') { | ||||||
|             $contextMenuContainer.append($("<div>").addClass("dropdown-divider")); |             $contextMenuContainer.append($("<div>").addClass("dropdown-divider")); | ||||||
|         } else { |         } else { | ||||||
|   | |||||||
							
								
								
									
										25
									
								
								src/public/javascripts/services/hoisted_note.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/public/javascripts/services/hoisted_note.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | import optionsInit from './options_init.js'; | ||||||
|  | import server from "./server.js"; | ||||||
|  |  | ||||||
|  | let hoistedNoteId; | ||||||
|  |  | ||||||
|  | optionsInit.optionsReady.then(options => { | ||||||
|  |     hoistedNoteId = options['hoistedNoteId']; | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | async function getHoistedNoteId() { | ||||||
|  |     await optionsInit.optionsReady; | ||||||
|  |  | ||||||
|  |     return hoistedNoteId; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | async function setHoistedNoteId(noteId) { | ||||||
|  |     hoistedNoteId = noteId; | ||||||
|  |  | ||||||
|  |     await server.put('options/hoistedNoteId/' + noteId); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export default { | ||||||
|  |     getHoistedNoteId, | ||||||
|  |     setHoistedNoteId | ||||||
|  | } | ||||||
| @@ -4,13 +4,18 @@ import Branch from "../entities/branch.js"; | |||||||
| import server from "./server.js"; | import server from "./server.js"; | ||||||
| import treeCache from "./tree_cache.js"; | import treeCache from "./tree_cache.js"; | ||||||
| import messagingService from "./messaging.js"; | import messagingService from "./messaging.js"; | ||||||
|  | import hoistedNoteService from "./hoisted_note.js"; | ||||||
|  |  | ||||||
| async function prepareTree(noteRows, branchRows, relations) { | async function prepareTree(noteRows, branchRows, relations) { | ||||||
|     utils.assertArguments(noteRows, branchRows, relations); |     utils.assertArguments(noteRows, branchRows, relations); | ||||||
|  |  | ||||||
|     treeCache.load(noteRows, branchRows, relations); |     treeCache.load(noteRows, branchRows, relations); | ||||||
|  |  | ||||||
|     return [ await prepareNode(await treeCache.getBranch('root')) ]; |     const hoistedNoteId = await hoistedNoteService.getHoistedNoteId(); | ||||||
|  |     const hoistedNote = await treeCache.getNote(hoistedNoteId); | ||||||
|  |     const hoistedBranch = (await hoistedNote.getBranches())[0]; | ||||||
|  |  | ||||||
|  |     return [ await prepareNode(hoistedBranch) ]; | ||||||
| } | } | ||||||
|  |  | ||||||
| async function prepareBranch(note) { | async function prepareBranch(note) { | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ import exportDialog from '../dialogs/export.js'; | |||||||
| import infoService from "./info.js"; | import infoService from "./info.js"; | ||||||
| import treeCache from "./tree_cache.js"; | import treeCache from "./tree_cache.js"; | ||||||
| import syncService from "./sync.js"; | import syncService from "./sync.js"; | ||||||
| import contextMenuService from "./context_menu.js"; | import hoistedNoteService from './hoisted_note.js'; | ||||||
|  |  | ||||||
| const $tree = $("#tree"); | const $tree = $("#tree"); | ||||||
|  |  | ||||||
| @@ -83,6 +83,8 @@ const contextMenuItems = [ | |||||||
|     {title: "Insert child note <kbd>Ctrl+P</kbd>", cmd: "insertChildNote", uiIcon: "plus"}, |     {title: "Insert child note <kbd>Ctrl+P</kbd>", cmd: "insertChildNote", uiIcon: "plus"}, | ||||||
|     {title: "Delete", cmd: "delete", uiIcon: "trash"}, |     {title: "Delete", cmd: "delete", uiIcon: "trash"}, | ||||||
|     {title: "----"}, |     {title: "----"}, | ||||||
|  |     {title: "Hoist note", cmd: "hoist", uiIcon: "arrow-up"}, | ||||||
|  |     {title: "Unhoist note", cmd: "unhoist", uiIcon: "arrow-up"}, | ||||||
|     {title: "Edit branch prefix <kbd>F2</kbd>", cmd: "editBranchPrefix", uiIcon: "pencil"}, |     {title: "Edit branch prefix <kbd>F2</kbd>", cmd: "editBranchPrefix", uiIcon: "pencil"}, | ||||||
|     {title: "----"}, |     {title: "----"}, | ||||||
|     {title: "Protect subtree", cmd: "protectSubtree", uiIcon: "shield-check"}, |     {title: "Protect subtree", cmd: "protectSubtree", uiIcon: "shield-check"}, | ||||||
| @@ -101,6 +103,16 @@ const contextMenuItems = [ | |||||||
|     {title: "Sort alphabetically <kbd>Alt+S</kbd>", cmd: "sortAlphabetically", uiIcon: "arrows-v"} |     {title: "Sort alphabetically <kbd>Alt+S</kbd>", cmd: "sortAlphabetically", uiIcon: "arrows-v"} | ||||||
| ]; | ]; | ||||||
|  |  | ||||||
|  | function hideItem(cmd, hidden) { | ||||||
|  |     const item = contextMenuItems.find(item => item.cmd === cmd); | ||||||
|  |  | ||||||
|  |     if (!item) { | ||||||
|  |         throw new Error(`Command ${cmd} has not been found!`); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     item.hidden = hidden; | ||||||
|  | } | ||||||
|  |  | ||||||
| function enableItem(cmd, enabled) { | function enableItem(cmd, enabled) { | ||||||
|     const item = contextMenuItems.find(item => item.cmd === cmd); |     const item = contextMenuItems.find(item => item.cmd === cmd); | ||||||
|      |      | ||||||
| @@ -130,6 +142,11 @@ async function getContextMenuItems(event) { | |||||||
|     enableItem("export", note.type !== 'search'); |     enableItem("export", note.type !== 'search'); | ||||||
|     enableItem("editBranchPrefix", isNotRoot && parentNote.type !== 'search'); |     enableItem("editBranchPrefix", isNotRoot && parentNote.type !== 'search'); | ||||||
|  |  | ||||||
|  |     const hoistedNoteId = await hoistedNoteService.getHoistedNoteId(); | ||||||
|  |  | ||||||
|  |     hideItem("hoist", note.noteId === hoistedNoteId); | ||||||
|  |     hideItem("unhoist", note.noteId !== hoistedNoteId || !isNotRoot); | ||||||
|  |  | ||||||
|     // Activate node on right-click |     // Activate node on right-click | ||||||
|     node.setActive(); |     node.setActive(); | ||||||
|  |  | ||||||
| @@ -194,6 +211,12 @@ function selectContextMenuItem(event, cmd) { | |||||||
|     else if (cmd === "sortAlphabetically") { |     else if (cmd === "sortAlphabetically") { | ||||||
|         treeService.sortAlphabetically(node.data.noteId); |         treeService.sortAlphabetically(node.data.noteId); | ||||||
|     } |     } | ||||||
|  |     else if (cmd === "hoist") { | ||||||
|  |         hoistedNoteService.setHoistedNoteId(node.data.noteId); | ||||||
|  |     } | ||||||
|  |     else if (cmd === "unhoist") { | ||||||
|  |         hoistedNoteService.setHoistedNoteId('root'); | ||||||
|  |     } | ||||||
|     else { |     else { | ||||||
|         messagingService.logError("Unknown command: " + cmd); |         messagingService.logError("Unknown command: " + cmd); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ const log = require('../../services/log'); | |||||||
|  |  | ||||||
| // options allowed to be updated directly in options dialog | // options allowed to be updated directly in options dialog | ||||||
| const ALLOWED_OPTIONS = ['protectedSessionTimeout', 'noteRevisionSnapshotTimeInterval', | const ALLOWED_OPTIONS = ['protectedSessionTimeout', 'noteRevisionSnapshotTimeInterval', | ||||||
|     'zoomFactor', 'theme', 'syncServerHost', 'syncServerTimeout', 'syncProxy', 'leftPaneMinWidth', 'leftPaneWidthPercent']; |     'zoomFactor', 'theme', 'syncServerHost', 'syncServerTimeout', 'syncProxy', 'leftPaneMinWidth', 'leftPaneWidthPercent', 'hoistedNoteId']; | ||||||
|  |  | ||||||
| async function getOptions() { | async function getOptions() { | ||||||
|     return await optionService.getOptionsMap(ALLOWED_OPTIONS); |     return await optionService.getOptionsMap(ALLOWED_OPTIONS); | ||||||
|   | |||||||
| @@ -50,18 +50,20 @@ async function getRelations(noteIds) { | |||||||
| } | } | ||||||
|  |  | ||||||
| async function getTree() { | async function getTree() { | ||||||
|  |     const hoistedNoteId = await optionService.getOption('hoistedNoteId'); | ||||||
|  |  | ||||||
|     // we fetch all branches of notes, even if that particular branch isn't visible |     // we fetch all branches of notes, even if that particular branch isn't visible | ||||||
|     // this allows us to e.g. detect and properly display clones |     // this allows us to e.g. detect and properly display clones | ||||||
|     const branches = await sql.getRows(` |     const branches = await sql.getRows(` | ||||||
|         WITH RECURSIVE |         WITH RECURSIVE | ||||||
|             tree(branchId, noteId, isExpanded) AS ( |             tree(branchId, noteId, isExpanded) AS ( | ||||||
|             SELECT branchId, noteId, isExpanded FROM branches WHERE branchId = 'root'  |             SELECT branchId, noteId, isExpanded FROM branches WHERE noteId = ?  | ||||||
|             UNION ALL |             UNION ALL | ||||||
|             SELECT branches.branchId, branches.noteId, branches.isExpanded FROM branches |             SELECT branches.branchId, branches.noteId, branches.isExpanded FROM branches | ||||||
|               JOIN tree ON branches.parentNoteId = tree.noteId |               JOIN tree ON branches.parentNoteId = tree.noteId | ||||||
|               WHERE tree.isExpanded = 1 AND branches.isDeleted = 0 |               WHERE tree.isExpanded = 1 AND branches.isDeleted = 0 | ||||||
|           ) |           ) | ||||||
|         SELECT branches.* FROM tree JOIN branches USING(noteId) WHERE branches.isDeleted = 0 ORDER BY branches.notePosition`); |         SELECT branches.* FROM tree JOIN branches USING(noteId) WHERE branches.isDeleted = 0 ORDER BY branches.notePosition`, [hoistedNoteId]); | ||||||
|  |  | ||||||
|     const noteIds = Array.from(new Set(branches.map(b => b.noteId))); |     const noteIds = Array.from(new Set(branches.map(b => b.noteId))); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
| const build = require('./build'); | const build = require('./build'); | ||||||
| const packageJson = require('../../package'); | const packageJson = require('../../package'); | ||||||
|  |  | ||||||
| const APP_DB_VERSION = 120; | const APP_DB_VERSION = 121; | ||||||
| const SYNC_VERSION = 2; | const SYNC_VERSION = 2; | ||||||
|  |  | ||||||
| module.exports = { | module.exports = { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user