mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
add move to dialog
This commit is contained in:
parent
5b4a2bd71c
commit
4cda661c1b
@ -83,42 +83,25 @@ CREATE TABLE IF NOT EXISTS "branches" (
|
||||
CREATE INDEX `IDX_branches_noteId` ON `branches` (`noteId`);
|
||||
CREATE INDEX `IDX_branches_noteId_parentNoteId` ON `branches` (`noteId`,`parentNoteId`);
|
||||
CREATE INDEX IDX_branches_parentNoteId ON branches (parentNoteId);
|
||||
CREATE TABLE IF NOT EXISTS "note_revisions" (`noteRevisionId` TEXT NOT NULL PRIMARY KEY,
|
||||
`noteId` TEXT NOT NULL,
|
||||
`title` TEXT,
|
||||
`contentLength` INT NOT NULL,
|
||||
`isProtected` INT NOT NULL DEFAULT 0,
|
||||
`utcDateLastEdited` TEXT NOT NULL,
|
||||
`utcDateCreated` TEXT NOT NULL,
|
||||
`utcDateModified` TEXT NOT NULL,
|
||||
`dateLastEdited` TEXT NOT NULL,
|
||||
`dateCreated` TEXT NOT NULL,
|
||||
type TEXT DEFAULT '' NOT NULL,
|
||||
mime TEXT DEFAULT '' NOT NULL,
|
||||
hash TEXT DEFAULT '' NOT NULL);
|
||||
CREATE TABLE IF NOT EXISTS "note_revision_contents" (`noteRevisionId` TEXT NOT NULL PRIMARY KEY,
|
||||
`content` TEXT,
|
||||
hash TEXT DEFAULT '' NOT NULL,
|
||||
`utcDateModified` TEXT NOT NULL);
|
||||
CREATE INDEX `IDX_note_revisions_noteId` ON `note_revisions` (`noteId`);
|
||||
CREATE INDEX `IDX_note_revisions_utcDateCreated` ON `note_revisions` (`utcDateCreated`);
|
||||
CREATE INDEX `IDX_note_revisions_utcDateLastEdited` ON `note_revisions` (`utcDateLastEdited`);
|
||||
CREATE INDEX `IDX_note_revisions_dateCreated` ON `note_revisions` (`dateCreated`);
|
||||
CREATE INDEX `IDX_note_revisions_dateLastEdited` ON `note_revisions` (`dateLastEdited`);
|
||||
CREATE TABLE IF NOT EXISTS "notes" (
|
||||
`noteId` TEXT NOT NULL,
|
||||
`title` TEXT NOT NULL DEFAULT "note",
|
||||
`isProtected` INT NOT NULL DEFAULT 0,
|
||||
`type` TEXT NOT NULL DEFAULT 'text',
|
||||
`mime` TEXT NOT NULL DEFAULT 'text/html',
|
||||
`hash` TEXT DEFAULT "" NOT NULL,
|
||||
`isDeleted` INT NOT NULL DEFAULT 0,
|
||||
`isErased` INT NOT NULL DEFAULT 0,
|
||||
`dateCreated` TEXT NOT NULL,
|
||||
`dateModified` TEXT NOT NULL,
|
||||
`utcDateCreated` TEXT NOT NULL,
|
||||
`utcDateModified` TEXT NOT NULL,
|
||||
PRIMARY KEY(`noteId`));
|
||||
`noteId` TEXT NOT NULL,
|
||||
`title` TEXT NOT NULL DEFAULT "note",
|
||||
`contentLength` INT NOT NULL,
|
||||
`isProtected` INT NOT NULL DEFAULT 0,
|
||||
`type` TEXT NOT NULL DEFAULT 'text',
|
||||
`mime` TEXT NOT NULL DEFAULT 'text/html',
|
||||
`hash` TEXT DEFAULT "" NOT NULL,
|
||||
`isDeleted` INT NOT NULL DEFAULT 0,
|
||||
`isErased` INT NOT NULL DEFAULT 0,
|
||||
`dateCreated` TEXT NOT NULL,
|
||||
`dateModified` TEXT NOT NULL,
|
||||
`utcDateCreated` TEXT NOT NULL,
|
||||
`utcDateModified` TEXT NOT NULL,
|
||||
PRIMARY KEY(`noteId`));
|
||||
CREATE INDEX `IDX_notes_isDeleted` ON `notes` (`isDeleted`);
|
||||
CREATE INDEX `IDX_notes_title` ON `notes` (`title`);
|
||||
CREATE INDEX `IDX_notes_type` ON `notes` (`type`);
|
||||
@ -126,3 +109,22 @@ CREATE INDEX `IDX_notes_dateCreated` ON `notes` (`dateCreated`);
|
||||
CREATE INDEX `IDX_notes_dateModified` ON `notes` (`dateModified`);
|
||||
CREATE INDEX `IDX_notes_utcDateModified` ON `notes` (`utcDateModified`);
|
||||
CREATE INDEX `IDX_notes_utcDateCreated` ON `notes` (`utcDateCreated`);
|
||||
CREATE TABLE IF NOT EXISTS "note_revisions" (`noteRevisionId` TEXT NOT NULL PRIMARY KEY,
|
||||
`noteId` TEXT NOT NULL,
|
||||
`title` TEXT,
|
||||
`contentLength` INT NOT NULL,
|
||||
`isErased` INT NOT NULL DEFAULT 0,
|
||||
`isProtected` INT NOT NULL DEFAULT 0,
|
||||
`utcDateLastEdited` TEXT NOT NULL,
|
||||
`utcDateCreated` TEXT NOT NULL,
|
||||
`utcDateModified` TEXT NOT NULL,
|
||||
`dateLastEdited` TEXT NOT NULL,
|
||||
`dateCreated` TEXT NOT NULL,
|
||||
type TEXT DEFAULT '' NOT NULL,
|
||||
mime TEXT DEFAULT '' NOT NULL,
|
||||
hash TEXT DEFAULT '' NOT NULL);
|
||||
CREATE INDEX `IDX_note_revisions_noteId` ON `note_revisions` (`noteId`);
|
||||
CREATE INDEX `IDX_note_revisions_utcDateCreated` ON `note_revisions` (`utcDateCreated`);
|
||||
CREATE INDEX `IDX_note_revisions_utcDateLastEdited` ON `note_revisions` (`utcDateLastEdited`);
|
||||
CREATE INDEX `IDX_note_revisions_dateCreated` ON `note_revisions` (`dateCreated`);
|
||||
CREATE INDEX `IDX_note_revisions_dateLastEdited` ON `note_revisions` (`dateLastEdited`);
|
||||
|
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "trilium",
|
||||
"version": "0.36.4",
|
||||
"version": "0.36.5",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
62
src/public/javascripts/dialogs/move_to.js
Normal file
62
src/public/javascripts/dialogs/move_to.js
Normal file
@ -0,0 +1,62 @@
|
||||
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 toastService from "../services/toast.js";
|
||||
import treeCache from "../services/tree_cache.js";
|
||||
import treeChangesService from "../services/branches.js";
|
||||
import treeService from "../services/tree.js";
|
||||
|
||||
const $dialog = $("#move-to-dialog");
|
||||
const $form = $("#move-to-form");
|
||||
const $noteAutoComplete = $("#move-to-note-autocomplete");
|
||||
const $movePrefix = $("#move-prefix");
|
||||
const $noteList = $("#move-to-note-list");
|
||||
|
||||
let movedNodes;
|
||||
|
||||
export async function showDialog(nodes) {
|
||||
movedNodes = nodes;
|
||||
|
||||
utils.closeActiveDialog();
|
||||
|
||||
glob.activeDialog = $dialog;
|
||||
|
||||
$dialog.modal();
|
||||
|
||||
$noteAutoComplete.val('').trigger('focus');
|
||||
|
||||
$noteList.empty();
|
||||
|
||||
for (const node of movedNodes) {
|
||||
const note = await treeCache.getNote(node.data.noteId);
|
||||
|
||||
$noteList.append($("<li>").text(note.title));
|
||||
}
|
||||
|
||||
noteAutocompleteService.initNoteAutocomplete($noteAutoComplete);
|
||||
noteAutocompleteService.showRecentNotes($noteAutoComplete);
|
||||
}
|
||||
|
||||
async function moveNotesTo(notePath) {
|
||||
const targetNode = await treeService.getNodeFromPath(notePath);
|
||||
|
||||
await treeChangesService.moveToNode(movedNodes, targetNode);
|
||||
|
||||
toastService.showMessage(`Selected notes have been moved into ${targetNode.title}`);
|
||||
}
|
||||
|
||||
$form.on('submit', () => {
|
||||
const notePath = $noteAutoComplete.getSelectedPath();
|
||||
|
||||
if (notePath) {
|
||||
$dialog.modal('hide');
|
||||
|
||||
moveNotesTo(notePath);
|
||||
}
|
||||
else {
|
||||
console.error("No path to move to.");
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
@ -18,6 +18,7 @@ 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";
|
||||
const MOVE_TO = "../dialogs/move_to.js";
|
||||
|
||||
function registerEntrypoints() {
|
||||
// hot keys are active also inside inputs and content editables
|
||||
@ -189,14 +190,22 @@ function registerEntrypoints() {
|
||||
|
||||
utils.bindGlobalShortcut('ctrl+shift+c', () => import(CLONE_TO).then(d => {
|
||||
const activeNode = treeService.getActiveNode();
|
||||
console.log("activeNode", activeNode);
|
||||
|
||||
const selectedOrActiveNodes = treeService.getSelectedOrActiveNodes(activeNode);
|
||||
console.log("selectedOrActiveNodes", selectedOrActiveNodes);
|
||||
|
||||
const noteIds = selectedOrActiveNodes.map(node => node.data.noteId);
|
||||
|
||||
d.showDialog(noteIds);
|
||||
}));
|
||||
|
||||
utils.bindGlobalShortcut('ctrl+shift+x', () => import(MOVE_TO).then(d => {
|
||||
const activeNode = treeService.getActiveNode();
|
||||
|
||||
const selectedOrActiveNodes = treeService.getSelectedOrActiveNodes(activeNode);
|
||||
|
||||
d.showDialog(selectedOrActiveNodes);
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
export default {
|
||||
|
@ -17,11 +17,12 @@ class TreeContextMenu {
|
||||
|
||||
getNoteTypeItems(baseCmd) {
|
||||
return [
|
||||
{ title: "Text", cmd: baseCmd + "_text", uiIcon: "file" },
|
||||
{ title: "Code", cmd: baseCmd + "_code", uiIcon: "terminal" },
|
||||
{ title: "Saved search", cmd: baseCmd + "_search", uiIcon: "search-folder" },
|
||||
{ title: "Relation Map", cmd: baseCmd + "_relation-map", uiIcon: "map" },
|
||||
{ title: "Render HTML note", cmd: baseCmd + "_render", uiIcon: "play" }
|
||||
{ title: "Text", cmd: baseCmd + "_text", uiIcon: "note" },
|
||||
{ title: "Code", cmd: baseCmd + "_code", uiIcon: "code" },
|
||||
{ title: "Saved search", cmd: baseCmd + "_search", uiIcon: "file-find" },
|
||||
{ title: "Relation Map", cmd: baseCmd + "_relation-map", uiIcon: "map-alt" },
|
||||
{ title: "Render HTML note", cmd: baseCmd + "_render", uiIcon: "extension" },
|
||||
{ title: "Book", cmd: baseCmd + "_book", uiIcon: "book" }
|
||||
];
|
||||
}
|
||||
|
||||
@ -63,11 +64,13 @@ class TreeContextMenu {
|
||||
{ title: "Unprotect subtree", cmd: "unprotectSubtree", uiIcon: "shield", enabled: noSelectedNotes },
|
||||
{ title: "----" },
|
||||
{ title: "Copy / clone <kbd>Ctrl+C</kbd>", cmd: "copy", uiIcon: "copy",
|
||||
enabled: isNotRoot },
|
||||
enabled: isNotRoot && !isHoisted },
|
||||
{ title: "Clone to ... <kbd>Ctrl+Shift+C</kbd>", cmd: "cloneTo", uiIcon: "empty",
|
||||
enabled: isNotRoot },
|
||||
enabled: isNotRoot && !isHoisted },
|
||||
{ title: "Cut <kbd>Ctrl+X</kbd>", cmd: "cut", uiIcon: "cut",
|
||||
enabled: isNotRoot && !isHoisted && parentNotSearch },
|
||||
{ title: "Move to ... <kbd>Ctrl+Shift+X</kbd>", cmd: "moveTo", uiIcon: "empty",
|
||||
enabled: isNotRoot && !isHoisted && parentNotSearch },
|
||||
{ title: "Paste into <kbd>Ctrl+V</kbd>", cmd: "pasteInto", uiIcon: "paste",
|
||||
enabled: !clipboard.isEmpty() && notSearch && noSelectedNotes },
|
||||
{ title: "Paste after", cmd: "pasteAfter", uiIcon: "paste",
|
||||
@ -127,11 +130,16 @@ class TreeContextMenu {
|
||||
const nodes = treeService.getSelectedOrActiveNodes(this.node);
|
||||
const noteIds = nodes.map(node => node.data.noteId);
|
||||
|
||||
import("../dialogs/clone_to.js").then(d => d.showDialog(noteIds))
|
||||
import("../dialogs/clone_to.js").then(d => d.showDialog(noteIds));
|
||||
}
|
||||
else if (cmd === "cut") {
|
||||
clipboard.cut(treeService.getSelectedOrActiveNodes(this.node));
|
||||
}
|
||||
else if (cmd === "moveTo") {
|
||||
const nodes = treeService.getSelectedOrActiveNodes(this.node);
|
||||
|
||||
import("../dialogs/move_to.js").then(d => d.showDialog(nodes));
|
||||
}
|
||||
else if (cmd === "pasteAfter") {
|
||||
clipboard.pasteAfter(this.node);
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ async function findBrokenReferenceIssues() {
|
||||
}
|
||||
});
|
||||
|
||||
await findAndFixIssues(`
|
||||
await findIssues(`
|
||||
SELECT noteRevisionId, note_revisions.noteId
|
||||
FROM note_revisions LEFT JOIN notes USING(noteId)
|
||||
WHERE notes.noteId IS NULL`,
|
||||
|
@ -176,6 +176,7 @@
|
||||
<% include dialogs/note_info.ejs %>
|
||||
<% include dialogs/link_map.ejs %>
|
||||
<% include dialogs/clone_to.ejs %>
|
||||
<% include dialogs/move_to.ejs %>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
31
src/views/dialogs/move_to.ejs
Normal file
31
src/views/dialogs/move_to.ejs
Normal file
@ -0,0 +1,31 @@
|
||||
<div id="move-to-dialog" class="modal mx-auto" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-lg" style="max-width: 1000px" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title mr-auto">Move notes to ...</h5>
|
||||
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close" style="margin-left: 0 !important;">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form id="move-to-form">
|
||||
<div class="modal-body">
|
||||
<h5>Notes to move</h5>
|
||||
|
||||
<ul id="move-to-note-list" style="max-height: 200px; overflow: auto;"></ul>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="move-to-note-autocomplete">Target parent note</label>
|
||||
|
||||
<div class="input-group">
|
||||
<input id="move-to-note-autocomplete" class="form-control" placeholder="search for note by its name">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary">Move to selected note <kbd>enter</kbd></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
Loading…
x
Reference in New Issue
Block a user