duplicate (single) note

This commit is contained in:
zadam 2019-10-19 12:36:16 +02:00
parent 00bb1236ce
commit b16c2d19b6
16 changed files with 147 additions and 70 deletions

View 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);

View File

@ -0,0 +1,2 @@
UPDATE branches SET notePosition = notePosition * 10;
UPDATE attributes SET position = position * 10;

View File

@ -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);

View File

@ -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) {

View File

@ -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;
}); });
}; };

View File

@ -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
}; };

View File

@ -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);
} }

View File

@ -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

View File

@ -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
}; };

View File

@ -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);

View File

@ -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";

View File

@ -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();

View File

@ -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)) {

View File

@ -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
}; };

View File

@ -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);

View File

@ -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);