From ab0486aaf1b1586c5b563c9c186f4a69115f5a0e Mon Sep 17 00:00:00 2001 From: azivner Date: Sat, 26 May 2018 16:16:34 -0400 Subject: [PATCH] expose root node, fixes #101 --- .../a2c75661-f9e2-478f-a69f-6a9409e69997.xml | 292 +++++++++++------- src/public/images/icons/tree-root.png | Bin 0 -> 240 bytes .../javascripts/services/context_menu.js | 10 +- src/public/javascripts/services/tree.js | 14 +- .../javascripts/services/tree_builder.js | 60 ++-- src/public/javascripts/services/tree_cache.js | 8 + src/public/stylesheets/style.css | 9 + 7 files changed, 247 insertions(+), 146 deletions(-) create mode 100644 src/public/images/icons/tree-root.png diff --git a/.idea/dataSources/a2c75661-f9e2-478f-a69f-6a9409e69997.xml b/.idea/dataSources/a2c75661-f9e2-478f-a69f-6a9409e69997.xml index 7d07bfbef..f4bf3db24 100644 --- a/.idea/dataSources/a2c75661-f9e2-478f-a69f-6a9409e69997.xml +++ b/.idea/dataSources/a2c75661-f9e2-478f-a69f-6a9409e69997.xml @@ -1,6 +1,6 @@ - + 3.16.1 @@ -50,546 +50,616 @@ 1 0 - + + 5 + TEXT|0s + 1 + "" + + 1 apiTokenId 1 - + apiTokenId 1 sqlite_autoindex_api_tokens_1 - + 1 TEXT|0s 1 - + 2 TEXT|0s 1 - + 3 TEXT|0s 1 - + 4 INTEGER|0s 1 - + 5 TEXT|0s - + 6 BOOLEAN|0s - + 7 INTEGER|0s 1 0 - + 8 TEXT|0s 1 - + + 9 + TEXT|0s + 1 + "" + + + 10 + TEXT|0s + 1 + '1970-01-01T00:00:00.000Z' + + 1 branchId 1 - + noteId parentNoteId - + noteId - + + parentNoteId + + + branchId 1 sqlite_autoindex_branches_1 - + 1 INTEGER|0s 1 1 - + 2 TEXT|0s - + 3 TEXT|0s - + 4 TEXT|0s 1 - + id 1 - + 1 TEXT|0s 1 - + 2 TEXT|0s 1 - + 3 TEXT|0s 1 - + 4 TEXT|0s 1 - + 5 BLOB|0s - + 6 INT|0s 1 0 - + 7 TEXT|0s 1 - + 8 TEXT|0s 1 - + + 9 + TEXT|0s + 1 + "" + + 1 imageId 1 - + imageId 1 sqlite_autoindex_images_1 - + 1 TEXT|0s 1 - + 2 TEXT|0s 1 - + 3 TEXT|0s 1 - + 4 TEXT|0s 1 '' - + 5 INT|0s 1 0 - + 6 TEXT|0s 1 - + 7 TEXT|0s 1 - + 8 INT|0s 1 - + + 9 + TEXT|0s + 1 + "" + + 1 labelId 1 - + noteId - + name value - + labelId 1 sqlite_autoindex_labels_1 - + 1 TEXT|0s 1 - + 2 TEXT|0s 1 - + 3 TEXT|0s 1 - + 4 INT|0s 1 0 - + 5 TEXT|0s 1 - + 6 TEXT|0s 1 - + + 7 + TEXT|0s + 1 + "" + + 1 noteImageId 1 - + noteId imageId - + noteId - + imageId - + noteImageId 1 sqlite_autoindex_note_images_1 - + 1 TEXT|0s 1 - + 2 TEXT|0s 1 - + 3 TEXT|0s - + 4 TEXT|0s - + 5 INT|0s 1 0 - + 6 TEXT|0s 1 - + 7 TEXT|0s 1 - + 8 TEXT|0s 1 '' - + 9 TEXT|0s 1 '' - + + 10 + TEXT|0s + 1 + "" + + 1 noteRevisionId 1 - + noteId - + dateModifiedFrom - + dateModifiedTo - + noteRevisionId 1 sqlite_autoindex_note_revisions_1 - + 1 TEXT|0s 1 - + 2 TEXT|0s 1 "unnamed" - + 3 TEXT|0s 1 "" - + 4 INT|0s 1 0 - + 5 INT|0s 1 0 - + 6 TEXT|0s 1 - + 7 TEXT|0s 1 - + 8 TEXT|0s 1 'text' - + 9 TEXT|0s 1 'text/html' - + + 10 + TEXT|0s + 1 + "" + + 1 noteId 1 - - isDeleted + + type - + noteId 1 sqlite_autoindex_notes_1 - + 1 TEXT|0s 1 - + 2 TEXT|0s - + 3 INT|0s - + 4 INTEGER|0s 1 0 - + + 5 + TEXT|0s + 1 + "" + + + 6 + TEXT|0s + 1 + '1970-01-01T00:00:00.000Z' + + 1 name 1 - + name 1 sqlite_autoindex_options_1 - + 1 TEXT|0s 1 - + 2 TEXT|0s 1 - + 3 TEXT|0s 1 - + 4 INT|0s - + + 5 + TEXT|0s + 1 + "" + + 1 branchId 1 - + branchId 1 sqlite_autoindex_recent_notes_1 - + 1 TEXT|0s 1 - + 2 TEXT|0s 1 - + 1 sourceId 1 - + sourceId 1 sqlite_autoindex_source_ids_1 - + 1 text|0s - + 2 text|0s - + 3 text|0s - + 4 integer|0s - + 5 text|0s - + 1 - + 2 - + 1 INTEGER|0s 1 1 - + 2 TEXT|0s 1 - + 3 TEXT|0s 1 - + 4 TEXT|0s 1 - + 5 TEXT|0s 1 - + entityName entityId 1 - + syncDate - + id 1 diff --git a/src/public/images/icons/tree-root.png b/src/public/images/icons/tree-root.png new file mode 100644 index 0000000000000000000000000000000000000000..8901eb9102c3a205808c0b433e5b8c8f12179427 GIT binary patch literal 240 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6;RN#5=* z4F5rJ!QSPQfg+p*9+AaB6Rv|Wqm#z$3ZNi+iKnkC`y*B<5mvP;oOM8vzjEqz!>@# 0 && (!parentNote || parentNote.type !== 'search')); - $tree.contextmenu("enableEntry", "pasteInto", clipboardIds.length > 0 && note.type !== 'search'); - $tree.contextmenu("enableEntry", "insertNoteHere", !parentNote || parentNote.type !== 'search'); + $tree.contextmenu("enableEntry", "insertNoteHere", isNotRoot && parentNote.type !== 'search'); $tree.contextmenu("enableEntry", "insertChildNote", note.type !== 'search'); + $tree.contextmenu("enableEntry", "delete", isNotRoot); + $tree.contextmenu("enableEntry", "copy", isNotRoot); + $tree.contextmenu("enableEntry", "cut", isNotRoot); + $tree.contextmenu("enableEntry", "pasteAfter", clipboardIds.length > 0 && isNotRoot && parentNote.type !== 'search'); + $tree.contextmenu("enableEntry", "pasteInto", clipboardIds.length > 0 && note.type !== 'search'); $tree.contextmenu("enableEntry", "importBranch", note.type !== 'search'); $tree.contextmenu("enableEntry", "exportBranch", note.type !== 'search'); diff --git a/src/public/javascripts/services/tree.js b/src/public/javascripts/services/tree.js index f48b70532..14969eec5 100644 --- a/src/public/javascripts/services/tree.js +++ b/src/public/javascripts/services/tree.js @@ -81,7 +81,7 @@ async function expandToNote(notePath, expandOpts) { const noteId = treeUtils.getNoteIdFromNotePath(notePath); - let parentNoteId = 'root'; + let parentNoteId = 'none'; for (const childNoteId of runPath) { const node = getNodesByNoteId(childNoteId).find(node => node.data.parentNoteId === parentNoteId); @@ -115,7 +115,10 @@ async function getRunPath(notePath) { utils.assertArguments(notePath); const path = notePath.split("/").reverse(); - path.push('root'); + + if (!path.includes("root")) { + path.push('root'); + } const effectivePath = []; let childNoteId = null; @@ -162,7 +165,7 @@ async function getRunPath(notePath) { } } - if (parentNoteId === 'root') { + if (parentNoteId === 'none') { break; } else { @@ -180,10 +183,6 @@ async function showParentList(noteId, node) { const note = await treeCache.getNote(noteId); const parents = await note.getParentNotes(); - if (!parents.length) { - infoService.throwError("Can't find parents for noteId=" + noteId); - } - if (parents.length <= 1) { $parentList.hide(); } @@ -294,6 +293,7 @@ function initFancyTree(tree) { extensions: ["hotkeys", "filter", "dnd", "clones"], source: tree, scrollParent: $tree, + minExpandLevel: 2, // root can't be collapsed click: (event, data) => { const targetType = data.targetType; const node = data.node; diff --git a/src/public/javascripts/services/tree_builder.js b/src/public/javascripts/services/tree_builder.js index 0c8bb5cdb..68dede509 100644 --- a/src/public/javascripts/services/tree_builder.js +++ b/src/public/javascripts/services/tree_builder.js @@ -10,7 +10,7 @@ async function prepareTree(noteRows, branchRows, relations) { treeCache.load(noteRows, branchRows, relations); - return await prepareRealBranch(await treeCache.getNote('root')); + return [ await prepareNode(await treeCache.getBranch('root')) ]; } async function prepareBranch(note) { @@ -22,6 +22,35 @@ async function prepareBranch(note) { } } +async function prepareNode(branch) { + const note = await branch.getNote(); + const title = (branch.prefix ? (branch.prefix + " - ") : "") + note.title; + + const node = { + noteId: note.noteId, + parentNoteId: branch.parentNoteId, + branchId: branch.branchId, + isProtected: note.isProtected, + title: utils.escapeHtml(title), + extraClasses: await getExtraClasses(note), + refKey: note.noteId, + expanded: note.type !== 'search' && branch.isExpanded + }; + + if (note.hasChildren() || note.type === 'search') { + node.folder = true; + + if (node.expanded && note.type !== 'search') { + node.children = await prepareRealBranch(note); + } + else { + node.lazy = true; + } + } + + return node; +} + async function prepareRealBranch(parentNote) { utils.assertArguments(parentNote); @@ -35,30 +64,7 @@ async function prepareRealBranch(parentNote) { const noteList = []; for (const branch of childBranches) { - const note = await branch.getNote(); - const title = (branch.prefix ? (branch.prefix + " - ") : "") + note.title; - - const node = { - noteId: note.noteId, - parentNoteId: branch.parentNoteId, - branchId: branch.branchId, - isProtected: note.isProtected, - title: utils.escapeHtml(title), - extraClasses: await getExtraClasses(note), - refKey: note.noteId, - expanded: note.type !== 'search' && branch.isExpanded - }; - - if (note.hasChildren() || note.type === 'search') { - node.folder = true; - - if (node.expanded && note.type !== 'search') { - node.children = await prepareRealBranch(note); - } - else { - node.lazy = true; - } - } + const node = await prepareNode(branch); noteList.push(node); } @@ -90,6 +96,10 @@ async function getExtraClasses(note) { const extraClasses = []; + if (note.noteId === 'root') { + extraClasses.push("tree-root"); + } + if (note.isProtected) { extraClasses.push("protected"); } diff --git a/src/public/javascripts/services/tree_cache.js b/src/public/javascripts/services/tree_cache.js index 4bd29030b..1b23a5055 100644 --- a/src/public/javascripts/services/tree_cache.js +++ b/src/public/javascripts/services/tree_cache.js @@ -58,6 +58,10 @@ class TreeCache { /** @return NoteShort */ async getNote(noteId) { + if (noteId === 'none') { + return null; + } + return (await this.getNotes([noteId]))[0]; } @@ -68,6 +72,10 @@ class TreeCache { } addBranchRelationship(branchId, childNoteId, parentNoteId) { + if (parentNoteId === 'none') { // applies only to root element + return; + } + this.childParentToBranch[childNoteId + '-' + parentNoteId] = branchId; this.parents[childNoteId] = this.parents[childNoteId] || []; diff --git a/src/public/stylesheets/style.css b/src/public/stylesheets/style.css index 1535e1383..e85b15f8a 100644 --- a/src/public/stylesheets/style.css +++ b/src/public/stylesheets/style.css @@ -105,6 +105,15 @@ span.fancytree-node.fancytree-active-clone:not(.fancytree-active) .fancytree-tit font-weight: bold; } +span.fancytree-node.tree-root > span.fancytree-icon { + background: url("../images/icons/tree-root.png") 0 0; +} + +/* first nesting level has lower left padding to avoid extra left padding. Other levels are not affected */ +.ui-fancytree > li > ul { + padding-left: 5px; +} + /* By default not focused active tree item is not easily visible, this makes it more visible */ span.fancytree-active:not(.fancytree-focused) .fancytree-title { background-color: #ddd !important;