diff --git a/src/public/javascripts/dialogs/clone_to.js b/src/public/javascripts/dialogs/clone_to.js
index 9ca17bc2f..147e5c8bd 100644
--- a/src/public/javascripts/dialogs/clone_to.js
+++ b/src/public/javascripts/dialogs/clone_to.js
@@ -2,7 +2,6 @@ import noteAutocompleteService from "../services/note_autocomplete.js";
import utils from "../services/utils.js";
import cloningService from "../services/cloning.js";
import treeUtils from "../services/tree_utils.js";
-import noteDetailService from "../services/note_detail.js";
import toastService from "../services/toast.js";
import treeCache from "../services/tree_cache.js";
@@ -10,14 +9,17 @@ const $dialog = $("#clone-to-dialog");
const $form = $("#clone-to-form");
const $noteAutoComplete = $("#clone-to-note-autocomplete");
const $clonePrefix = $("#clone-prefix");
+const $noteList = $("#clone-to-note-list");
-let clonedNoteId;
+let clonedNoteIds;
-export async function showDialog(noteId) {
- clonedNoteId = noteId || noteDetailService.getActiveTabNoteId();
+export async function showDialog(noteIds) {
+ clonedNoteIds = [];
- if (!clonedNoteId) {
- return;
+ for (const noteId of noteIds) {
+ if (!clonedNoteIds.includes(noteId)) {
+ clonedNoteIds.push(noteId);
+ }
}
utils.closeActiveDialog();
@@ -28,24 +30,38 @@ export async function showDialog(noteId) {
$noteAutoComplete.val('').trigger('focus');
+ $noteList.empty();
+
+ for (const noteId of clonedNoteIds) {
+ const note = await treeCache.getNote(noteId);
+
+ $noteList.append($("
").text(note.title));
+ }
+
noteAutocompleteService.initNoteAutocomplete($noteAutoComplete);
noteAutocompleteService.showRecentNotes($noteAutoComplete);
}
+async function cloneNotesTo(notePath) {
+ const targetNoteId = treeUtils.getNoteIdFromNotePath(notePath);
+
+ for (const cloneNoteId of clonedNoteIds) {
+ await cloningService.cloneNoteTo(cloneNoteId, targetNoteId, $clonePrefix.val());
+
+ const clonedNote = await treeCache.getNote(cloneNoteId);
+ const targetNote = await treeCache.getNote(targetNoteId);
+
+ toastService.showMessage(`Note "${clonedNote.title}" has been cloned into ${targetNote.title}`);
+ }
+}
+
$form.on('submit', () => {
const notePath = $noteAutoComplete.getSelectedPath();
if (notePath) {
$dialog.modal('hide');
- const targetNoteId = treeUtils.getNoteIdFromNotePath(notePath);
-
- cloningService.cloneNoteTo(clonedNoteId, targetNoteId, $clonePrefix.val()).then(async () => {
- const clonedNote = await treeCache.getNote(clonedNoteId);
- const targetNote = await treeCache.getNote(targetNoteId);
-
- toastService.showMessage(`Note "${clonedNote.title}" has been cloned into ${targetNote.title}`);
- });
+ cloneNotesTo(notePath);
}
else {
console.error("No path to clone to.");
diff --git a/src/public/javascripts/services/entrypoints.js b/src/public/javascripts/services/entrypoints.js
index 904a32524..ee4d7199c 100644
--- a/src/public/javascripts/services/entrypoints.js
+++ b/src/public/javascripts/services/entrypoints.js
@@ -16,7 +16,6 @@ const HELP = "../dialogs/help.js";
const NOTE_INFO = "../dialogs/note_info.js";
const ABOUT = "../dialogs/about.js";
const LINK_MAP = "../dialogs/link_map.js";
-const CLONE_TO = "../dialogs/clone_to.js";
function registerEntrypoints() {
// hot keys are active also inside inputs and content editables
@@ -185,8 +184,6 @@ function registerEntrypoints() {
return false;
});
-
- utils.bindGlobalShortcut('ctrl+e', () => import(CLONE_TO).then(d => d.showDialog()));
}
export default {
diff --git a/src/public/javascripts/services/tree.js b/src/public/javascripts/services/tree.js
index 442a288ad..dbbaa84be 100644
--- a/src/public/javascripts/services/tree.js
+++ b/src/public/javascripts/services/tree.js
@@ -342,6 +342,7 @@ function getSelectedOrActiveNodes(node) {
if (notes.length === 0) {
notes.push(node);
}
+
return notes;
}
diff --git a/src/public/javascripts/services/tree_context_menu.js b/src/public/javascripts/services/tree_context_menu.js
index 4569a3305..f2258d1af 100644
--- a/src/public/javascripts/services/tree_context_menu.js
+++ b/src/public/javascripts/services/tree_context_menu.js
@@ -64,6 +64,8 @@ class TreeContextMenu {
{ title: "----" },
{ title: "Copy / clone Ctrl+C", cmd: "copy", uiIcon: "copy",
enabled: isNotRoot },
+ { title: "Clone to ...", cmd: "cloneTo", uiIcon: "empty",
+ enabled: isNotRoot },
{ title: "Cut Ctrl+X", cmd: "cut", uiIcon: "cut",
enabled: isNotRoot && !isHoisted && parentNotSearch },
{ title: "Paste into Ctrl+V", cmd: "pasteInto", uiIcon: "paste",
@@ -121,6 +123,12 @@ class TreeContextMenu {
else if (cmd === "copy") {
clipboard.copy(treeService.getSelectedOrActiveNodes(this.node));
}
+ else if (cmd === "cloneTo") {
+ const nodes = treeService.getSelectedOrActiveNodes(this.node);
+ const noteIds = nodes.map(node => node.data.noteId);
+
+ import("../dialogs/clone_to.js").then(d => d.showDialog(noteIds))
+ }
else if (cmd === "cut") {
clipboard.cut(treeService.getSelectedOrActiveNodes(this.node));
}
diff --git a/src/views/dialogs/clone_to.ejs b/src/views/dialogs/clone_to.ejs
index e56df6c0a..93ac01af6 100644
--- a/src/views/dialogs/clone_to.ejs
+++ b/src/views/dialogs/clone_to.ejs
@@ -2,7 +2,7 @@