mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
duplicate (single) note
This commit is contained in:
parent
00bb1236ce
commit
b16c2d19b6
22
db/migrations/0148__make_isExpanded_not_null.sql
Normal file
22
db/migrations/0148__make_isExpanded_not_null.sql
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS "mig_branches" (
|
||||||
|
`branchId` TEXT NOT NULL,
|
||||||
|
`noteId` TEXT NOT NULL,
|
||||||
|
`parentNoteId` TEXT NOT NULL,
|
||||||
|
`notePosition` INTEGER NOT NULL,
|
||||||
|
`prefix` TEXT,
|
||||||
|
`isExpanded` INTEGER NOT NULL DEFAULT 0,
|
||||||
|
`isDeleted` INTEGER NOT NULL DEFAULT 0,
|
||||||
|
`utcDateModified` TEXT NOT NULL,
|
||||||
|
utcDateCreated TEXT NOT NULL,
|
||||||
|
hash TEXT DEFAULT "" NOT NULL,
|
||||||
|
PRIMARY KEY(`branchId`));
|
||||||
|
|
||||||
|
INSERT INTO mig_branches (branchId, noteId, parentNoteId, notePosition, prefix, isExpanded, isDeleted, utcDateModified, utcDateCreated, hash)
|
||||||
|
SELECT branchId, noteId, parentNoteId, notePosition, prefix, COALESCE(isExpanded, 0), isDeleted, utcDateModified, utcDateCreated, hash FROM branches;
|
||||||
|
|
||||||
|
DROP TABLE branches;
|
||||||
|
ALTER TABLE mig_branches RENAME TO 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);
|
2
db/migrations/0149__space_out_positions.sql
Normal file
2
db/migrations/0149__space_out_positions.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
UPDATE branches SET notePosition = notePosition * 10;
|
||||||
|
UPDATE attributes SET position = position * 10;
|
@ -29,25 +29,6 @@ CREATE TABLE IF NOT EXISTS "api_tokens"
|
|||||||
utcDateCreated TEXT NOT NULL,
|
utcDateCreated TEXT NOT NULL,
|
||||||
isDeleted INT NOT NULL DEFAULT 0,
|
isDeleted INT NOT NULL DEFAULT 0,
|
||||||
hash TEXT DEFAULT "" NOT NULL);
|
hash TEXT DEFAULT "" NOT NULL);
|
||||||
CREATE TABLE IF NOT EXISTS "branches" (
|
|
||||||
`branchId` TEXT NOT NULL,
|
|
||||||
`noteId` TEXT NOT NULL,
|
|
||||||
`parentNoteId` TEXT NOT NULL,
|
|
||||||
`notePosition` INTEGER NOT NULL,
|
|
||||||
`prefix` TEXT,
|
|
||||||
`isExpanded` BOOLEAN,
|
|
||||||
`isDeleted` INTEGER NOT NULL DEFAULT 0,
|
|
||||||
`utcDateModified` TEXT NOT NULL,
|
|
||||||
utcDateCreated TEXT NOT NULL,
|
|
||||||
hash TEXT DEFAULT "" NOT NULL,
|
|
||||||
PRIMARY KEY(`branchId`)
|
|
||||||
);
|
|
||||||
CREATE TABLE IF NOT EXISTS "event_log" (
|
|
||||||
`eventId` TEXT NOT NULL PRIMARY KEY,
|
|
||||||
`noteId` TEXT,
|
|
||||||
`comment` TEXT,
|
|
||||||
`utcDateCreated` TEXT NOT NULL
|
|
||||||
);
|
|
||||||
CREATE TABLE IF NOT EXISTS "options"
|
CREATE TABLE IF NOT EXISTS "options"
|
||||||
(
|
(
|
||||||
name TEXT not null PRIMARY KEY,
|
name TEXT not null PRIMARY KEY,
|
||||||
@ -84,21 +65,6 @@ CREATE TABLE IF NOT EXISTS "notes" (
|
|||||||
`utcDateModified` TEXT NOT NULL,
|
`utcDateModified` TEXT NOT NULL,
|
||||||
PRIMARY KEY(`noteId`)
|
PRIMARY KEY(`noteId`)
|
||||||
);
|
);
|
||||||
CREATE TABLE IF NOT EXISTS "note_contents" (
|
|
||||||
`noteId` TEXT NOT NULL,
|
|
||||||
`content` TEXT NULL DEFAULT NULL,
|
|
||||||
`hash` TEXT DEFAULT "" NOT NULL,
|
|
||||||
`utcDateModified` TEXT NOT NULL,
|
|
||||||
PRIMARY KEY(`noteId`)
|
|
||||||
);
|
|
||||||
CREATE TABLE recent_notes
|
|
||||||
(
|
|
||||||
noteId TEXT not null primary key,
|
|
||||||
notePath TEXT not null,
|
|
||||||
hash TEXT default "" not null,
|
|
||||||
utcDateCreated TEXT not null,
|
|
||||||
isDeleted INT
|
|
||||||
);
|
|
||||||
CREATE UNIQUE INDEX `IDX_sync_entityName_entityId` ON `sync` (
|
CREATE UNIQUE INDEX `IDX_sync_entityName_entityId` ON `sync` (
|
||||||
`entityName`,
|
`entityName`,
|
||||||
`entityId`
|
`entityId`
|
||||||
@ -115,14 +81,6 @@ CREATE INDEX `IDX_note_revisions_dateModifiedFrom` ON `note_revisions` (
|
|||||||
CREATE INDEX `IDX_note_revisions_dateModifiedTo` ON `note_revisions` (
|
CREATE INDEX `IDX_note_revisions_dateModifiedTo` ON `note_revisions` (
|
||||||
`utcDateModifiedTo`
|
`utcDateModifiedTo`
|
||||||
);
|
);
|
||||||
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 INDEX IDX_attributes_name_value
|
CREATE INDEX IDX_attributes_name_value
|
||||||
on attributes (name, value);
|
on attributes (name, value);
|
||||||
CREATE INDEX IDX_attributes_name_index
|
CREATE INDEX IDX_attributes_name_index
|
||||||
@ -131,3 +89,33 @@ CREATE INDEX IDX_attributes_noteId_index
|
|||||||
on attributes (noteId);
|
on attributes (noteId);
|
||||||
CREATE INDEX IDX_attributes_value_index
|
CREATE INDEX IDX_attributes_value_index
|
||||||
on attributes (value);
|
on attributes (value);
|
||||||
|
CREATE TABLE IF NOT EXISTS "note_contents" (
|
||||||
|
`noteId` TEXT NOT NULL,
|
||||||
|
`content` TEXT NULL DEFAULT NULL,
|
||||||
|
`hash` TEXT DEFAULT "" NOT NULL,
|
||||||
|
`utcDateModified` TEXT NOT NULL,
|
||||||
|
PRIMARY KEY(`noteId`)
|
||||||
|
);
|
||||||
|
CREATE TABLE recent_notes
|
||||||
|
(
|
||||||
|
noteId TEXT not null primary key,
|
||||||
|
notePath TEXT not null,
|
||||||
|
hash TEXT default "" not null,
|
||||||
|
utcDateCreated TEXT not null,
|
||||||
|
isDeleted INT
|
||||||
|
);
|
||||||
|
CREATE TABLE IF NOT EXISTS "branches" (
|
||||||
|
`branchId` TEXT NOT NULL,
|
||||||
|
`noteId` TEXT NOT NULL,
|
||||||
|
`parentNoteId` TEXT NOT NULL,
|
||||||
|
`notePosition` INTEGER NOT NULL,
|
||||||
|
`prefix` TEXT,
|
||||||
|
`isExpanded` INTEGER NOT NULL DEFAULT 0,
|
||||||
|
`isDeleted` INTEGER NOT NULL DEFAULT 0,
|
||||||
|
`utcDateModified` TEXT NOT NULL,
|
||||||
|
utcDateCreated TEXT NOT NULL,
|
||||||
|
hash TEXT DEFAULT "" NOT NULL,
|
||||||
|
PRIMARY KEY(`branchId`));
|
||||||
|
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);
|
||||||
|
@ -42,7 +42,7 @@ class Branch extends Entity {
|
|||||||
async beforeSaving() {
|
async beforeSaving() {
|
||||||
if (this.notePosition === undefined) {
|
if (this.notePosition === undefined) {
|
||||||
const maxNotePos = await sql.getValue('SELECT MAX(notePosition) FROM branches WHERE parentNoteId = ? AND isDeleted = 0', [this.parentNoteId]);
|
const maxNotePos = await sql.getValue('SELECT MAX(notePosition) FROM branches WHERE parentNoteId = ? AND isDeleted = 0', [this.parentNoteId]);
|
||||||
this.notePosition = maxNotePos === null ? 0 : maxNotePos + 1;
|
this.notePosition = maxNotePos === null ? 0 : maxNotePos + 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.isDeleted) {
|
if (!this.isDeleted) {
|
||||||
|
@ -47,14 +47,15 @@ function AttributesModel() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.updateAttributePositions = function() {
|
this.updateAttributePositions = function() {
|
||||||
let position = 0;
|
let position = 10;
|
||||||
|
|
||||||
// we need to update positions by searching in the DOM, because order of the
|
// we need to update positions by searching in the DOM, because order of the
|
||||||
// attributes in the viewmodel (self.ownedAttributes()) stays the same
|
// attributes in the viewmodel (self.ownedAttributes()) stays the same
|
||||||
$ownedAttributesBody.find('input[name="position"]').each(function() {
|
$ownedAttributesBody.find('input[name="position"]').each(function() {
|
||||||
const attribute = self.getTargetAttribute(this);
|
const attribute = self.getTargetAttribute(this);
|
||||||
|
|
||||||
attribute().position = position++;
|
attribute().position = position;
|
||||||
|
position += 10;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -845,6 +845,18 @@ $tree.on('mousedown', '.fancytree-title', e => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function duplicateNote(noteId, parentNoteId) {
|
||||||
|
const {note} = await server.post(`notes/${noteId}/duplicate/${parentNoteId}`);
|
||||||
|
|
||||||
|
await reload();
|
||||||
|
|
||||||
|
await activateNote(note.noteId);
|
||||||
|
|
||||||
|
const origNote = await treeCache.getNote(noteId);
|
||||||
|
infoService.showMessage(`Note "${origNote.title}" has been duplicated`);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
utils.bindGlobalShortcut('alt+c', () => collapseTree()); // don't use shortened form since collapseTree() accepts argument
|
utils.bindGlobalShortcut('alt+c', () => collapseTree()); // don't use shortened form since collapseTree() accepts argument
|
||||||
$collapseTreeButton.click(() => collapseTree());
|
$collapseTreeButton.click(() => collapseTree());
|
||||||
|
|
||||||
@ -882,5 +894,6 @@ export default {
|
|||||||
resolveNotePath,
|
resolveNotePath,
|
||||||
getSomeNotePath,
|
getSomeNotePath,
|
||||||
focusTree,
|
focusTree,
|
||||||
scrollToActiveNote
|
scrollToActiveNote,
|
||||||
|
duplicateNote
|
||||||
};
|
};
|
@ -8,6 +8,7 @@ import syncService from "./sync.js";
|
|||||||
import hoistedNoteService from './hoisted_note.js';
|
import hoistedNoteService from './hoisted_note.js';
|
||||||
import noteDetailService from './note_detail.js';
|
import noteDetailService from './note_detail.js';
|
||||||
import clipboard from './clipboard.js';
|
import clipboard from './clipboard.js';
|
||||||
|
import protectedSessionHolder from "./protected_session_holder.js";
|
||||||
|
|
||||||
class TreeContextMenu {
|
class TreeContextMenu {
|
||||||
constructor(node) {
|
constructor(node) {
|
||||||
@ -68,6 +69,8 @@ class TreeContextMenu {
|
|||||||
enabled: !clipboard.isEmpty() && note.type !== 'search' && noSelectedNotes },
|
enabled: !clipboard.isEmpty() && note.type !== 'search' && noSelectedNotes },
|
||||||
{ title: "Paste after", cmd: "pasteAfter", uiIcon: "clipboard",
|
{ title: "Paste after", cmd: "pasteAfter", uiIcon: "clipboard",
|
||||||
enabled: !clipboard.isEmpty() && isNotRoot && parentNote.type !== 'search' && noSelectedNotes },
|
enabled: !clipboard.isEmpty() && isNotRoot && parentNote.type !== 'search' && noSelectedNotes },
|
||||||
|
{ title: "Duplicate note here", cmd: "duplicateNote", uiIcon: "empty",
|
||||||
|
enabled: noSelectedNotes && (!note.isProtected || protectedSessionHolder.isProtectedSessionAvailable()) },
|
||||||
{ title: "----" },
|
{ title: "----" },
|
||||||
{ title: "Export", cmd: "export", uiIcon: "empty",
|
{ title: "Export", cmd: "export", uiIcon: "empty",
|
||||||
enabled: note.type !== 'search' && noSelectedNotes },
|
enabled: note.type !== 'search' && noSelectedNotes },
|
||||||
@ -152,6 +155,11 @@ class TreeContextMenu {
|
|||||||
else if (cmd === "unhoist") {
|
else if (cmd === "unhoist") {
|
||||||
hoistedNoteService.unhoist();
|
hoistedNoteService.unhoist();
|
||||||
}
|
}
|
||||||
|
else if (cmd === "duplicateNote") {
|
||||||
|
const branch = await treeCache.getBranch(this.node.data.branchId);
|
||||||
|
|
||||||
|
treeService.duplicateNote(this.node.data.noteId, branch.parentNoteId);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
ws.logError("Unknown command: " + cmd);
|
ws.logError("Unknown command: " + cmd);
|
||||||
}
|
}
|
||||||
|
@ -14,8 +14,7 @@ const TaskContext = require('../../services/task_context');
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
async function moveBranchToParent(req) {
|
async function moveBranchToParent(req) {
|
||||||
const branchId = req.params.branchId;
|
const {branchId, parentNoteId} = req.params;
|
||||||
const parentNoteId = req.params.parentNoteId;
|
|
||||||
|
|
||||||
const noteToMove = await tree.getBranch(branchId);
|
const noteToMove = await tree.getBranch(branchId);
|
||||||
|
|
||||||
@ -26,7 +25,7 @@ async function moveBranchToParent(req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const maxNotePos = await sql.getValue('SELECT MAX(notePosition) FROM branches WHERE parentNoteId = ? AND isDeleted = 0', [parentNoteId]);
|
const maxNotePos = await sql.getValue('SELECT MAX(notePosition) FROM branches WHERE parentNoteId = ? AND isDeleted = 0', [parentNoteId]);
|
||||||
const newNotePos = maxNotePos === null ? 0 : maxNotePos + 1;
|
const newNotePos = maxNotePos === null ? 0 : maxNotePos + 10;
|
||||||
|
|
||||||
const branch = await repository.getBranch(branchId);
|
const branch = await repository.getBranch(branchId);
|
||||||
branch.parentNoteId = parentNoteId;
|
branch.parentNoteId = parentNoteId;
|
||||||
@ -37,8 +36,7 @@ async function moveBranchToParent(req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function moveBranchBeforeNote(req) {
|
async function moveBranchBeforeNote(req) {
|
||||||
const branchId = req.params.branchId;
|
const {branchId, beforeBranchId} = req.params;
|
||||||
const beforeBranchId = req.params.beforeBranchId;
|
|
||||||
|
|
||||||
const noteToMove = await tree.getBranch(branchId);
|
const noteToMove = await tree.getBranch(branchId);
|
||||||
const beforeNote = await tree.getBranch(beforeBranchId);
|
const beforeNote = await tree.getBranch(beforeBranchId);
|
||||||
@ -51,7 +49,7 @@ async function moveBranchBeforeNote(req) {
|
|||||||
|
|
||||||
// we don't change utcDateModified so other changes are prioritized in case of conflict
|
// we don't change utcDateModified so other changes are prioritized in case of conflict
|
||||||
// also we would have to sync all those modified branches otherwise hash checks would fail
|
// also we would have to sync all those modified branches otherwise hash checks would fail
|
||||||
await sql.execute("UPDATE branches SET notePosition = notePosition + 1 WHERE parentNoteId = ? AND notePosition >= ? AND isDeleted = 0",
|
await sql.execute("UPDATE branches SET notePosition = notePosition + 10 WHERE parentNoteId = ? AND notePosition >= ? AND isDeleted = 0",
|
||||||
[beforeNote.parentNoteId, beforeNote.notePosition]);
|
[beforeNote.parentNoteId, beforeNote.notePosition]);
|
||||||
|
|
||||||
await sync_table.addNoteReorderingSync(beforeNote.parentNoteId);
|
await sync_table.addNoteReorderingSync(beforeNote.parentNoteId);
|
||||||
@ -65,8 +63,7 @@ async function moveBranchBeforeNote(req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function moveBranchAfterNote(req) {
|
async function moveBranchAfterNote(req) {
|
||||||
const branchId = req.params.branchId;
|
const {branchId, afterBranchId} = req.params;
|
||||||
const afterBranchId = req.params.afterBranchId;
|
|
||||||
|
|
||||||
const noteToMove = await tree.getBranch(branchId);
|
const noteToMove = await tree.getBranch(branchId);
|
||||||
const afterNote = await tree.getBranch(afterBranchId);
|
const afterNote = await tree.getBranch(afterBranchId);
|
||||||
@ -79,22 +76,21 @@ async function moveBranchAfterNote(req) {
|
|||||||
|
|
||||||
// we don't change utcDateModified so other changes are prioritized in case of conflict
|
// we don't change utcDateModified so other changes are prioritized in case of conflict
|
||||||
// also we would have to sync all those modified branches otherwise hash checks would fail
|
// also we would have to sync all those modified branches otherwise hash checks would fail
|
||||||
await sql.execute("UPDATE branches SET notePosition = notePosition + 1 WHERE parentNoteId = ? AND notePosition > ? AND isDeleted = 0",
|
await sql.execute("UPDATE branches SET notePosition = notePosition + 10 WHERE parentNoteId = ? AND notePosition > ? AND isDeleted = 0",
|
||||||
[afterNote.parentNoteId, afterNote.notePosition]);
|
[afterNote.parentNoteId, afterNote.notePosition]);
|
||||||
|
|
||||||
await sync_table.addNoteReorderingSync(afterNote.parentNoteId);
|
await sync_table.addNoteReorderingSync(afterNote.parentNoteId);
|
||||||
|
|
||||||
const branch = await repository.getBranch(branchId);
|
const branch = await repository.getBranch(branchId);
|
||||||
branch.parentNoteId = afterNote.parentNoteId;
|
branch.parentNoteId = afterNote.parentNoteId;
|
||||||
branch.notePosition = afterNote.notePosition + 1;
|
branch.notePosition = afterNote.notePosition + 10;
|
||||||
await branch.save();
|
await branch.save();
|
||||||
|
|
||||||
return { success: true };
|
return { success: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setExpanded(req) {
|
async function setExpanded(req) {
|
||||||
const branchId = req.params.branchId;
|
const {branchId, expanded} = req.params;
|
||||||
const expanded = req.params.expanded;
|
|
||||||
|
|
||||||
await sql.execute("UPDATE branches SET isExpanded = ? WHERE branchId = ?", [expanded, branchId]);
|
await sql.execute("UPDATE branches SET isExpanded = ? WHERE branchId = ?", [expanded, branchId]);
|
||||||
// we don't sync expanded label
|
// we don't sync expanded label
|
||||||
|
@ -180,6 +180,12 @@ async function changeTitle(req) {
|
|||||||
await note.save();
|
await note.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function duplicateNote(req) {
|
||||||
|
const {noteId, parentNoteId} = req.params;
|
||||||
|
|
||||||
|
return await noteService.duplicateNote(noteId, parentNoteId);
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getNote,
|
getNote,
|
||||||
updateNote,
|
updateNote,
|
||||||
@ -190,5 +196,6 @@ module.exports = {
|
|||||||
setNoteTypeMime,
|
setNoteTypeMime,
|
||||||
getChildren,
|
getChildren,
|
||||||
getRelationMap,
|
getRelationMap,
|
||||||
changeTitle
|
changeTitle,
|
||||||
|
duplicateNote
|
||||||
};
|
};
|
@ -135,6 +135,7 @@ function register(app) {
|
|||||||
apiRoute(GET, '/api/notes/:noteId/revision-list', noteRevisionsApiRoute.getNoteRevisionList);
|
apiRoute(GET, '/api/notes/:noteId/revision-list', noteRevisionsApiRoute.getNoteRevisionList);
|
||||||
apiRoute(POST, '/api/notes/relation-map', notesApiRoute.getRelationMap);
|
apiRoute(POST, '/api/notes/relation-map', notesApiRoute.getRelationMap);
|
||||||
apiRoute(PUT, '/api/notes/:noteId/change-title', notesApiRoute.changeTitle);
|
apiRoute(PUT, '/api/notes/:noteId/change-title', notesApiRoute.changeTitle);
|
||||||
|
apiRoute(POST, '/api/notes/:noteId/duplicate/:parentNoteId', notesApiRoute.duplicateNote);
|
||||||
|
|
||||||
apiRoute(GET, '/api/edited-notes/:date', noteRevisionsApiRoute.getEditedNotesOnDate);
|
apiRoute(GET, '/api/edited-notes/:date', noteRevisionsApiRoute.getEditedNotesOnDate);
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ const build = require('./build');
|
|||||||
const packageJson = require('../../package');
|
const packageJson = require('../../package');
|
||||||
const {TRILIUM_DATA_DIR} = require('./data_dir');
|
const {TRILIUM_DATA_DIR} = require('./data_dir');
|
||||||
|
|
||||||
const APP_DB_VERSION = 147;
|
const APP_DB_VERSION = 149;
|
||||||
const SYNC_VERSION = 10;
|
const SYNC_VERSION = 10;
|
||||||
const CLIPPER_PROTOCOL_VERSION = "1.0";
|
const CLIPPER_PROTOCOL_VERSION = "1.0";
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ async function cloneNoteAfter(noteId, afterBranchId) {
|
|||||||
|
|
||||||
// we don't change utcDateModified so other changes are prioritized in case of conflict
|
// we don't change utcDateModified so other changes are prioritized in case of conflict
|
||||||
// also we would have to sync all those modified branches otherwise hash checks would fail
|
// also we would have to sync all those modified branches otherwise hash checks would fail
|
||||||
await sql.execute("UPDATE branches SET notePosition = notePosition + 1 WHERE parentNoteId = ? AND notePosition > ? AND isDeleted = 0",
|
await sql.execute("UPDATE branches SET notePosition = notePosition + 10 WHERE parentNoteId = ? AND notePosition > ? AND isDeleted = 0",
|
||||||
[afterNote.parentNoteId, afterNote.notePosition]);
|
[afterNote.parentNoteId, afterNote.notePosition]);
|
||||||
|
|
||||||
await syncTable.addNoteReorderingSync(afterNote.parentNoteId);
|
await syncTable.addNoteReorderingSync(afterNote.parentNoteId);
|
||||||
@ -89,7 +89,7 @@ async function cloneNoteAfter(noteId, afterBranchId) {
|
|||||||
const branch = await new Branch({
|
const branch = await new Branch({
|
||||||
noteId: noteId,
|
noteId: noteId,
|
||||||
parentNoteId: afterNote.parentNoteId,
|
parentNoteId: afterNote.parentNoteId,
|
||||||
notePosition: afterNote.notePosition + 1,
|
notePosition: afterNote.notePosition + 10,
|
||||||
isExpanded: 0
|
isExpanded: 0
|
||||||
}).save();
|
}).save();
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@ async function findExistencyIssues() {
|
|||||||
const branches = await repository.getEntities(`SELECT * FROM branches WHERE noteId = ? and parentNoteId = ? and isDeleted = 1`, [noteId, parentNoteId]);
|
const branches = await repository.getEntities(`SELECT * FROM branches WHERE noteId = ? and parentNoteId = ? and isDeleted = 1`, [noteId, parentNoteId]);
|
||||||
|
|
||||||
// it's not necessarily "original" branch, it's just the only one which will survive
|
// it's not necessarily "original" branch, it's just the only one which will survive
|
||||||
const origBranch = branches.get(0);
|
const origBranch = branches[0];
|
||||||
|
|
||||||
// delete all but the first branch
|
// delete all but the first branch
|
||||||
for (const branch of branches.slice(1)) {
|
for (const branch of branches.slice(1)) {
|
||||||
|
@ -21,15 +21,15 @@ async function getNewNotePosition(parentNoteId, noteData) {
|
|||||||
if (noteData.target === 'into') {
|
if (noteData.target === 'into') {
|
||||||
const maxNotePos = await sql.getValue('SELECT MAX(notePosition) FROM branches WHERE parentNoteId = ? AND isDeleted = 0', [parentNoteId]);
|
const maxNotePos = await sql.getValue('SELECT MAX(notePosition) FROM branches WHERE parentNoteId = ? AND isDeleted = 0', [parentNoteId]);
|
||||||
|
|
||||||
newNotePos = maxNotePos === null ? 0 : maxNotePos + 1;
|
newNotePos = maxNotePos === null ? 0 : maxNotePos + 10;
|
||||||
}
|
}
|
||||||
else if (noteData.target === 'after') {
|
else if (noteData.target === 'after') {
|
||||||
const afterNote = await sql.getRow('SELECT notePosition FROM branches WHERE branchId = ?', [noteData.target_branchId]);
|
const afterNote = await sql.getRow('SELECT notePosition FROM branches WHERE branchId = ?', [noteData.target_branchId]);
|
||||||
|
|
||||||
newNotePos = afterNote.notePosition + 1;
|
newNotePos = afterNote.notePosition + 10;
|
||||||
|
|
||||||
// not updating utcDateModified to avoig having to sync whole rows
|
// not updating utcDateModified to avoig having to sync whole rows
|
||||||
await sql.execute('UPDATE branches SET notePosition = notePosition + 1 WHERE parentNoteId = ? AND notePosition > ? AND isDeleted = 0',
|
await sql.execute('UPDATE branches SET notePosition = notePosition + 10 WHERE parentNoteId = ? AND notePosition > ? AND isDeleted = 0',
|
||||||
[parentNoteId, afterNote.notePosition]);
|
[parentNoteId, afterNote.notePosition]);
|
||||||
|
|
||||||
await syncTableService.addNoteReorderingSync(parentNoteId);
|
await syncTableService.addNoteReorderingSync(parentNoteId);
|
||||||
@ -465,6 +465,44 @@ async function cleanupDeletedNotes() {
|
|||||||
await sql.execute("UPDATE note_revisions SET content = NULL WHERE note_revisions.content IS NOT NULL AND noteId IN (SELECT noteId FROM notes WHERE isDeleted = 1 AND notes.utcDateModified <= ?)", [dateUtils.utcDateStr(cutoffDate)]);
|
await sql.execute("UPDATE note_revisions SET content = NULL WHERE note_revisions.content IS NOT NULL AND noteId IN (SELECT noteId FROM notes WHERE isDeleted = 1 AND notes.utcDateModified <= ?)", [dateUtils.utcDateStr(cutoffDate)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function duplicateNote(noteId, parentNoteId) {
|
||||||
|
const origNote = await repository.getNote(noteId);
|
||||||
|
|
||||||
|
if (origNote.isProtected && !protectedSessionService.isProtectedSessionAvailable()) {
|
||||||
|
throw new Error(`Cannot duplicate note=${origNote.noteId} because it is protected and protected session is not available`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// might be null if orig note is not in the target parentNoteId
|
||||||
|
const origBranch = (await origNote.getBranches()).find(branch => branch.parentNoteId === parentNoteId);
|
||||||
|
|
||||||
|
const newNote = new Note(origNote);
|
||||||
|
newNote.noteId = undefined; // force creation of new note
|
||||||
|
newNote.title += " (dup)";
|
||||||
|
|
||||||
|
await newNote.save();
|
||||||
|
await newNote.setContent(await origNote.getContent());
|
||||||
|
|
||||||
|
const newBranch = await new Branch({
|
||||||
|
noteId: newNote.noteId,
|
||||||
|
parentNoteId: parentNoteId,
|
||||||
|
// here increasing just by 1 to make sure it's directly after original
|
||||||
|
notePosition: origBranch ? origBranch.notePosition + 1 : null
|
||||||
|
}).save();
|
||||||
|
|
||||||
|
for (const attribute of await origNote.getAttributes()) {
|
||||||
|
const attr = new Attribute(attribute);
|
||||||
|
attr.attributeId = undefined; // force creation of new attribute
|
||||||
|
attr.noteId = newNote.noteId;
|
||||||
|
|
||||||
|
await attr.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
note: newNote,
|
||||||
|
branch: newBranch
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
sqlInit.dbReady.then(() => {
|
sqlInit.dbReady.then(() => {
|
||||||
// first cleanup kickoff 5 minutes after startup
|
// first cleanup kickoff 5 minutes after startup
|
||||||
setTimeout(cls.wrap(cleanupDeletedNotes), 5 * 60 * 1000);
|
setTimeout(cls.wrap(cleanupDeletedNotes), 5 * 60 * 1000);
|
||||||
@ -478,5 +516,6 @@ module.exports = {
|
|||||||
updateNote,
|
updateNote,
|
||||||
deleteBranch,
|
deleteBranch,
|
||||||
protectNoteRecursively,
|
protectNoteRecursively,
|
||||||
scanForLinks
|
scanForLinks,
|
||||||
|
duplicateNote
|
||||||
};
|
};
|
@ -109,7 +109,7 @@ async function createInitialDatabase(username, password, theme) {
|
|||||||
noteId: 'root',
|
noteId: 'root',
|
||||||
parentNoteId: 'none',
|
parentNoteId: 'none',
|
||||||
isExpanded: true,
|
isExpanded: true,
|
||||||
notePosition: 0
|
notePosition: 10
|
||||||
}).save();
|
}).save();
|
||||||
|
|
||||||
const dummyTaskContext = new TaskContext("1", 'import', false);
|
const dummyTaskContext = new TaskContext("1", 'import', false);
|
||||||
|
@ -110,13 +110,13 @@ async function sortNotesAlphabetically(parentNoteId, directoriesFirst = false) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let position = 1;
|
let position = 10;
|
||||||
|
|
||||||
for (const note of notes) {
|
for (const note of notes) {
|
||||||
await sql.execute("UPDATE branches SET notePosition = ? WHERE branchId = ?",
|
await sql.execute("UPDATE branches SET notePosition = ? WHERE branchId = ?",
|
||||||
[position, note.branchId]);
|
[position, note.branchId]);
|
||||||
|
|
||||||
position++;
|
position += 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
await syncTableService.addNoteReorderingSync(parentNoteId);
|
await syncTableService.addNoteReorderingSync(parentNoteId);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user