diff --git a/src/public/javascripts/services/branches.js b/src/public/javascripts/services/branches.js index dda7097cd..adad473bd 100644 --- a/src/public/javascripts/services/branches.js +++ b/src/public/javascripts/services/branches.js @@ -58,6 +58,11 @@ async function moveToNode(nodesToMove, toNode) { nodesToMove = await filterRootNote(nodesToMove); for (const nodeToMove of nodesToMove) { + if (nodeToMove.data.noteId === await hoistedNoteService.getHoistedNoteId() + || nodeToMove.getParent().data.noteType === 'search') { + continue; + } + const resp = await server.put('branches/' + nodeToMove.data.branchId + '/move-to/' + toNode.data.noteId); if (!resp.success) { @@ -152,7 +157,9 @@ async function deleteNodes(nodes) { } async function moveNodeUpInHierarchy(node) { - if (await hoistedNoteService.isRootNode(node) || await hoistedNoteService.isTopLevelNode(node)) { + if (await hoistedNoteService.isRootNode(node) + || await hoistedNoteService.isTopLevelNode(node) + || node.getParent().data.noteType === 'search') { return; } diff --git a/src/public/javascripts/services/clipboard.js b/src/public/javascripts/services/clipboard.js index a13c335ed..ec198bf1c 100644 --- a/src/public/javascripts/services/clipboard.js +++ b/src/public/javascripts/services/clipboard.js @@ -2,6 +2,7 @@ import treeUtils from "./tree_utils.js"; import treeChangesService from "./branches.js"; import cloningService from "./cloning.js"; import toastService from "./toast.js"; +import hoistedNoteService from "./hoisted_note.js"; let clipboardIds = []; let clipboardMode = null; @@ -66,10 +67,16 @@ function copy(nodes) { } function cut(nodes) { - clipboardIds = nodes.map(node => node.key); - clipboardMode = 'cut'; + clipboardIds = nodes + .filter(node => node.data.noteId !== hoistedNoteService.getHoistedNoteNoPromise()) + .filter(node => node.getParent().data.noteType !== 'search') + .map(node => node.data.noteId); - toastService.showMessage("Note(s) have been cut into clipboard."); + if (clipboardIds.length > 0) { + clipboardMode = 'cut'; + + toastService.showMessage("Note(s) have been cut into clipboard."); + } } function isEmpty() { diff --git a/src/public/javascripts/services/drag_and_drop.js b/src/public/javascripts/services/drag_and_drop.js index 2fa1f9087..0b2025e8f 100644 --- a/src/public/javascripts/services/drag_and_drop.js +++ b/src/public/javascripts/services/drag_and_drop.js @@ -1,11 +1,13 @@ import treeService from './tree.js'; import treeChangesService from './branches.js'; +import hoistedNoteService from './hoisted_note.js'; const dragAndDropSetup = { autoExpandMS: 600, dragStart: (node, data) => { // don't allow dragging root node - if (node.data.noteId === 'root') { + if (node.data.noteId === hoistedNoteService.getHoistedNoteNoPromise() + || node.getParent().data.noteType === 'search') { return false; } @@ -25,6 +27,17 @@ const dragAndDropSetup = { dragEnter: (node, data) => true, // allow drop on any node dragOver: (node, data) => true, dragDrop: async (node, data) => { + if ((data.hitMode === 'over' && node.data.noteType === 'search') || + (['after', 'before'].includes(data.hitMode) + && (node.data.noteId === hoistedNoteService.getHoistedNoteNoPromise() || node.getParent().data.noteType === 'search'))) { + + const infoDialog = await import('../dialogs/info.js'); + + await infoDialog.info("Dropping notes into this location is not allowed."); + + return; + } + const dataTransfer = data.dataTransfer; if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) { diff --git a/src/public/javascripts/services/hoisted_note.js b/src/public/javascripts/services/hoisted_note.js index e7741baf4..ca5b218b1 100644 --- a/src/public/javascripts/services/hoisted_note.js +++ b/src/public/javascripts/services/hoisted_note.js @@ -3,12 +3,16 @@ import server from "./server.js"; import tree from "./tree.js"; import noteDetailService from "./note_detail.js"; -let hoistedNoteId; +let hoistedNoteId = 'root'; optionsService.waitForOptions().then(options => { hoistedNoteId = options.get('hoistedNoteId'); }); +function getHoistedNoteNoPromise() { + return hoistedNoteId; +} + async function getHoistedNoteId() { await optionsService.waitForOptions(); @@ -49,6 +53,7 @@ async function isRootNode(node) { export default { getHoistedNoteId, + getHoistedNoteNoPromise, setHoistedNoteId, unhoist, isTopLevelNode, diff --git a/src/public/javascripts/services/tree.js b/src/public/javascripts/services/tree.js index 370fbb89a..6754136de 100644 --- a/src/public/javascripts/services/tree.js +++ b/src/public/javascripts/services/tree.js @@ -676,6 +676,7 @@ async function createNote(node, parentNoteId, target, extraOptions = {}) { refKey: branchEntity.noteId, branchId: branchEntity.branchId, isProtected: extraOptions.isProtected, + type: noteEntity.type, extraClasses: await treeBuilder.getExtraClasses(noteEntity), icon: await treeBuilder.getIcon(noteEntity), folder: extraOptions.type === 'search', diff --git a/src/public/javascripts/services/tree_builder.js b/src/public/javascripts/services/tree_builder.js index 8ff5e2ae0..9cfe9b44c 100644 --- a/src/public/javascripts/services/tree_builder.js +++ b/src/public/javascripts/services/tree_builder.js @@ -70,6 +70,7 @@ async function prepareNode(branch) { parentNoteId: branch.parentNoteId, branchId: branch.branchId, isProtected: note.isProtected, + noteType: note.type, title: utils.escapeHtml(title), extraClasses: await getExtraClasses(note), icon: await getIcon(note), diff --git a/src/public/javascripts/services/tree_context_menu.js b/src/public/javascripts/services/tree_context_menu.js index fcace29df..dda3f31d4 100644 --- a/src/public/javascripts/services/tree_context_menu.js +++ b/src/public/javascripts/services/tree_context_menu.js @@ -65,7 +65,7 @@ class TreeContextMenu { { title: "Copy / clone Ctrl+C", cmd: "copy", uiIcon: "files", enabled: isNotRoot }, { title: "Cut Ctrl+X", cmd: "cut", uiIcon: "scissors", - enabled: isNotRoot }, + enabled: isNotRoot && !isHoisted && parentNotSearch }, { title: "Paste into Ctrl+V", cmd: "pasteInto", uiIcon: "clipboard", enabled: !clipboard.isEmpty() && notSearch && noSelectedNotes }, { title: "Paste after", cmd: "pasteAfter", uiIcon: "clipboard",