From d2f72529b36d03342d9007f6fa54a623d3c9888a Mon Sep 17 00:00:00 2001 From: azivner Date: Fri, 28 Dec 2018 22:05:04 +0100 Subject: [PATCH] context menu with delete --- src/public/javascripts/entities/attribute.js | 4 +- .../javascripts/services/context_menu.js | 10 ++-- .../services/context_menu_items_container.js | 28 ++++++++++ src/public/javascripts/services/mobile.js | 35 ++++++++++++ .../services/note_detail_relation_map.js | 11 ++-- src/public/javascripts/services/tree.js | 4 +- .../javascripts/services/tree_context_menu.js | 55 +++++++------------ src/public/stylesheets/mobile.css | 4 ++ src/views/index.ejs | 2 +- src/views/mobile.ejs | 4 +- 10 files changed, 106 insertions(+), 51 deletions(-) create mode 100644 src/public/javascripts/services/context_menu_items_container.js diff --git a/src/public/javascripts/entities/attribute.js b/src/public/javascripts/entities/attribute.js index 9cc7c361e..1b388c4b5 100644 --- a/src/public/javascripts/entities/attribute.js +++ b/src/public/javascripts/entities/attribute.js @@ -31,4 +31,6 @@ class Attribute { get toString() { return `Attribute(attributeId=${this.attributeId}, type=${this.type}, name=${this.name})`; } -} \ No newline at end of file +} + +export default Attribute; \ No newline at end of file diff --git a/src/public/javascripts/services/context_menu.js b/src/public/javascripts/services/context_menu.js index 99416cf02..72585ea17 100644 --- a/src/public/javascripts/services/context_menu.js +++ b/src/public/javascripts/services/context_menu.js @@ -1,12 +1,12 @@ const $contextMenuContainer = $("#context-menu-container"); -function initContextMenu(event, contextMenuItems, selectContextMenuItem) { +function initContextMenu(event, itemContainer, selectContextMenuItem) { + event.stopPropagation(); + $contextMenuContainer.empty(); - for (const item of contextMenuItems) { - if (item.hidden) { - continue; - } + for (const item of itemContainer.getItems()) { + console.log("Adding " + item.title); if (item.title === '----') { $contextMenuContainer.append($("
").addClass("dropdown-divider")); diff --git a/src/public/javascripts/services/context_menu_items_container.js b/src/public/javascripts/services/context_menu_items_container.js new file mode 100644 index 000000000..0064af2c9 --- /dev/null +++ b/src/public/javascripts/services/context_menu_items_container.js @@ -0,0 +1,28 @@ +class ContextMenuItemsContainer { + constructor(items) { + // clone the item array and the items themselves + this.items = items.map(item => Object.assign({}, item)); + } + + hideItem(cmd, hidden = true) { + if (hidden) { + this.items = this.items.filter(item => item.cmd !== cmd); + } + } + + enableItem(cmd, enabled) { + const item = this.items.find(item => item.cmd === cmd); + + if (!item) { + throw new Error(`Command ${cmd} has not been found!`); + } + + item.enabled = enabled; + } + + getItems() { + return this.items; + } +} + +export default ContextMenuItemsContainer; diff --git a/src/public/javascripts/services/mobile.js b/src/public/javascripts/services/mobile.js index 9c54c4b5b..af4c804e6 100644 --- a/src/public/javascripts/services/mobile.js +++ b/src/public/javascripts/services/mobile.js @@ -3,6 +3,12 @@ import noteDetailService from "./note_detail.js"; import dragAndDropSetup from "./drag_and_drop.js"; import treeCache from "./tree_cache.js"; import treeBuilder from "./tree_builder.js"; +import contextMenuWidget from "./context_menu.js"; +import confirmDialog from "../dialogs/confirm.js"; +import server from "./server.js"; +import promptDialog from "../dialogs/prompt.js"; +import ContextMenuItemsContainer from "./context_menu_items_container.js"; +import treeChangesService from "./branches.js"; const $leftPane = $("#left-pane"); const $tree = $("#tree"); @@ -69,7 +75,36 @@ async function showTree() { } } }); +} +$("#note-menu-button").click(async e => { + const node = treeService.getCurrentNode(); + const branch = await treeCache.getBranch(node.data.branchId); + const note = await treeCache.getNote(node.data.noteId); + const parentNote = await treeCache.getNote(branch.parentNoteId); + const isNotRoot = note.noteId !== 'root'; + + const itemsContainer = new ContextMenuItemsContainer([ + {title: "Delete note", cmd: "delete", uiIcon: "trash"} + ]); + + itemsContainer.enableItem("delete", isNotRoot && parentNote.type !== 'search'); + + contextMenuWidget.initContextMenu(e, itemsContainer, noteContextMenuHandler); +}); + +async function noteContextMenuHandler(event, cmd) { + const node = treeService.getCurrentNode(); + + if (cmd === "delete") { + treeChangesService.deleteNodes([node]); + + // move to the tree + togglePanes(); + } + else { + throw new Error("Unrecognized command " + cmd); + } } showTree(); \ No newline at end of file diff --git a/src/public/javascripts/services/note_detail_relation_map.js b/src/public/javascripts/services/note_detail_relation_map.js index 0c54b7694..bd27d8692 100644 --- a/src/public/javascripts/services/note_detail_relation_map.js +++ b/src/public/javascripts/services/note_detail_relation_map.js @@ -9,6 +9,7 @@ import attributeAutocompleteService from "./attribute_autocomplete.js"; import promptDialog from "../dialogs/prompt.js"; import infoDialog from "../dialogs/info.js"; import confirmDialog from "../dialogs/confirm.js"; +import ContextMenuItemsContainer from "./context_menu_items_container.js"; const $component = $("#note-detail-relation-map"); const $relationMapContainer = $("#relation-map-container"); @@ -304,9 +305,9 @@ function connectionContextMenuHandler(connection, event) { event.preventDefault(); event.stopPropagation(); - const contextMenuItems = [ {title: "Remove relation", cmd: "remove", uiIcon: "trash"} ]; + const contextMenuItemsContainer = new ContextMenuItemsContainer([ {title: "Remove relation", cmd: "remove", uiIcon: "trash"} ]); - contextMenuWidget.initContextMenu(event, contextMenuItems, async (event, cmd) => { + contextMenuWidget.initContextMenu(event, contextMenuItemsContainer, async (event, cmd) => { if (cmd === 'remove') { if (!await confirmDialog.confirm("Are you sure you want to remove the relation?")) { return; @@ -380,12 +381,12 @@ async function connectionCreatedHandler(info, originalEvent) { } $relationMapContainer.on("contextmenu", ".note-box", e => { - const contextMenuItems = [ + const contextMenuItemsContainer = new ContextMenuItemsContainer([ {title: "Remove note", cmd: "remove", uiIcon: "trash"}, {title: "Edit title", cmd: "edit-title", uiIcon: "pencil"}, - ]; + ]); - contextMenuWidget.initContextMenu(e, contextMenuItems, noteContextMenuHandler); + contextMenuWidget.initContextMenu(e, contextMenuItemsContainer, noteContextMenuHandler); return false; }); diff --git a/src/public/javascripts/services/tree.js b/src/public/javascripts/services/tree.js index a68a3d2b6..3a50bcf2d 100644 --- a/src/public/javascripts/services/tree.js +++ b/src/public/javascripts/services/tree.js @@ -418,8 +418,8 @@ function initFancyTree(tree) { }); $tree.on('contextmenu', '.fancytree-node', function(e) { - treeContextMenuService.getContextMenuItems(e).then(contextMenuItems => { - contextMenuWidget.initContextMenu(e, contextMenuItems, treeContextMenuService.selectContextMenuItem); + treeContextMenuService.getContextMenuItems(e).then(contextMenuItemContainer => { + contextMenuWidget.initContextMenu(e, contextMenuItemContainer, treeContextMenuService.selectContextMenuItem); }); return false; // blocks default browser right click menu diff --git a/src/public/javascripts/services/tree_context_menu.js b/src/public/javascripts/services/tree_context_menu.js index 03d5a0425..57cffdb8b 100644 --- a/src/public/javascripts/services/tree_context_menu.js +++ b/src/public/javascripts/services/tree_context_menu.js @@ -11,6 +11,7 @@ import infoService from "./info.js"; import treeCache from "./tree_cache.js"; import syncService from "./sync.js"; import hoistedNoteService from './hoisted_note.js'; +import ContextMenuItemsContainer from './context_menu_items_container.js'; const $tree = $("#tree"); @@ -81,10 +82,10 @@ function cut(nodes) { const contextMenuItems = [ {title: "Insert note here Ctrl+O", cmd: "insertNoteHere", uiIcon: "plus"}, {title: "Insert child note Ctrl+P", cmd: "insertChildNote", uiIcon: "plus"}, - {title: "Delete", cmd: "delete", uiIcon: "trash"}, + {title: "Delete Delete", cmd: "delete", uiIcon: "trash"}, {title: "----"}, - {title: "Hoist note CTRL-H", cmd: "hoist", uiIcon: "arrow-up"}, - {title: "Unhoist note CTRL-H", cmd: "unhoist", uiIcon: "arrow-up"}, + {title: "Hoist note Ctrl-H", cmd: "hoist", uiIcon: "arrow-up"}, + {title: "Unhoist note Ctrl-H", cmd: "unhoist", uiIcon: "arrow-up"}, {title: "Edit branch prefix F2", cmd: "editBranchPrefix", uiIcon: "pencil"}, {title: "----"}, {title: "Protect subtree", cmd: "protectSubtree", uiIcon: "shield-check"}, @@ -103,26 +104,6 @@ const contextMenuItems = [ {title: "Sort alphabetically Alt+S", 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) { - const item = contextMenuItems.find(item => item.cmd === cmd); - - if (!item) { - throw new Error(`Command ${cmd} has not been found!`); - } - - item.enabled = enabled; -} - async function getContextMenuItems(event) { const node = $.ui.fancytree.getNode(event); const branch = await treeCache.getBranch(node.data.branchId); @@ -130,22 +111,24 @@ async function getContextMenuItems(event) { const parentNote = await treeCache.getNote(branch.parentNoteId); const isNotRoot = note.noteId !== 'root'; + const itemsContainer = new ContextMenuItemsContainer(contextMenuItems); + // Modify menu entries depending on node status - enableItem("insertNoteHere", isNotRoot && parentNote.type !== 'search'); - enableItem("insertChildNote", note.type !== 'search'); - enableItem("delete", isNotRoot && parentNote.type !== 'search'); - enableItem("copy", isNotRoot); - enableItem("cut", isNotRoot); - enableItem("pasteAfter", clipboardIds.length > 0 && isNotRoot && parentNote.type !== 'search'); - enableItem("pasteInto", clipboardIds.length > 0 && note.type !== 'search'); - enableItem("importIntoNote", note.type !== 'search'); - enableItem("export", note.type !== 'search'); - enableItem("editBranchPrefix", isNotRoot && parentNote.type !== 'search'); + itemsContainer.enableItem("insertNoteHere", isNotRoot && parentNote.type !== 'search'); + itemsContainer.enableItem("insertChildNote", note.type !== 'search'); + itemsContainer.enableItem("delete", isNotRoot && parentNote.type !== 'search'); + itemsContainer.enableItem("copy", isNotRoot); + itemsContainer.enableItem("cut", isNotRoot); + itemsContainer.enableItem("pasteAfter", clipboardIds.length > 0 && isNotRoot && parentNote.type !== 'search'); + itemsContainer.enableItem("pasteInto", clipboardIds.length > 0 && note.type !== 'search'); + itemsContainer.enableItem("importIntoNote", note.type !== 'search'); + itemsContainer.enableItem("export", note.type !== 'search'); + itemsContainer.enableItem("editBranchPrefix", isNotRoot && parentNote.type !== 'search'); const hoistedNoteId = await hoistedNoteService.getHoistedNoteId(); - hideItem("hoist", note.noteId === hoistedNoteId); - hideItem("unhoist", note.noteId !== hoistedNoteId || !isNotRoot); + itemsContainer.hideItem("hoist", note.noteId === hoistedNoteId); + itemsContainer.hideItem("unhoist", note.noteId !== hoistedNoteId || !isNotRoot); // Activate node on right-click node.setActive(); @@ -156,7 +139,7 @@ async function getContextMenuItems(event) { node.setSelected(true); treeService.clearSelectedNodes(); - return contextMenuItems; + return itemsContainer; } function selectContextMenuItem(event, cmd) { diff --git a/src/public/stylesheets/mobile.css b/src/public/stylesheets/mobile.css index 74b6d7353..04ffe2902 100644 --- a/src/public/stylesheets/mobile.css +++ b/src/public/stylesheets/mobile.css @@ -80,4 +80,8 @@ html, body { kbd { display: none; +} + +.dropdown-menu { + font-size: larger; } \ No newline at end of file diff --git a/src/views/index.ejs b/src/views/index.ejs index b53567439..c6fe35670 100644 --- a/src/views/index.ejs +++ b/src/views/index.ejs @@ -65,7 +65,7 @@
- + diff --git a/src/views/mobile.ejs b/src/views/mobile.ejs index 0088b6a14..1800d1388 100644 --- a/src/views/mobile.ejs +++ b/src/views/mobile.ejs @@ -11,7 +11,7 @@
- +
@@ -52,6 +52,8 @@
<% include dialogs/protected_session_password.ejs %> + +