mirror of
https://github.com/zadam/trilium.git
synced 2025-01-07 15:49:01 +08:00
Merge branch 'master' into canvas
This commit is contained in:
commit
b17f442d1f
10 changed files with 56 additions and 13 deletions
1
db/migrations/0114__fix_root_note_cycle.sql
Normal file
1
db/migrations/0114__fix_root_note_cycle.sql
Normal file
|
@ -0,0 +1 @@
|
|||
update branches set parentNoteId = 'none' where branchId = 'root'
|
|
@ -5,6 +5,13 @@ import infoService from "./info.js";
|
|||
import treeCache from "./tree_cache.js";
|
||||
|
||||
async function moveBeforeNode(nodesToMove, beforeNode) {
|
||||
nodesToMove = filterRootNote(nodesToMove);
|
||||
|
||||
if (beforeNode.data.noteId === 'root') {
|
||||
alert('Cannot move notes before root note.');
|
||||
return;
|
||||
}
|
||||
|
||||
for (const nodeToMove of nodesToMove) {
|
||||
const resp = await server.put('branches/' + nodeToMove.data.branchId + '/move-before/' + beforeNode.data.branchId);
|
||||
|
||||
|
@ -18,6 +25,13 @@ async function moveBeforeNode(nodesToMove, beforeNode) {
|
|||
}
|
||||
|
||||
async function moveAfterNode(nodesToMove, afterNode) {
|
||||
nodesToMove = filterRootNote(nodesToMove);
|
||||
|
||||
if (afterNode.data.noteId === 'root') {
|
||||
alert('Cannot move notes after root note.');
|
||||
return;
|
||||
}
|
||||
|
||||
nodesToMove.reverse(); // need to reverse to keep the note order
|
||||
|
||||
for (const nodeToMove of nodesToMove) {
|
||||
|
@ -33,6 +47,8 @@ async function moveAfterNode(nodesToMove, afterNode) {
|
|||
}
|
||||
|
||||
async function moveToNode(nodesToMove, toNode) {
|
||||
nodesToMove = filterRootNote(nodesToMove);
|
||||
|
||||
for (const nodeToMove of nodesToMove) {
|
||||
const resp = await server.put('branches/' + nodeToMove.data.branchId + '/move-to/' + toNode.data.noteId);
|
||||
|
||||
|
@ -58,8 +74,13 @@ async function moveToNode(nodesToMove, toNode) {
|
|||
}
|
||||
}
|
||||
|
||||
function filterRootNote(nodes) {
|
||||
// some operations are not possible on root notes
|
||||
return nodes.filter(node => node.data.noteId !== 'root');
|
||||
}
|
||||
|
||||
async function deleteNodes(nodes) {
|
||||
nodes = nodes.filter(node => node.data.noteId !== 'root');
|
||||
nodes = filterRootNote(nodes);
|
||||
|
||||
if (nodes.length === 0 || !confirm('Are you sure you want to delete select note(s) and all the sub-notes?')) {
|
||||
return;
|
||||
|
@ -94,7 +115,7 @@ async function deleteNodes(nodes) {
|
|||
}
|
||||
|
||||
async function moveNodeUpInHierarchy(node) {
|
||||
if (utils.isTopLevelNode(node)) {
|
||||
if (utils.isRootNode(node) || utils.isTopLevelNode(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,10 @@ const dragAndDropSetup = {
|
|||
preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
|
||||
|
||||
dragStart: (node, data) => {
|
||||
if (node.data.noteId === 'root') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This function MUST be defined to enable dragging for the tree.
|
||||
// Return false to cancel dragging of node.
|
||||
return true;
|
||||
|
|
|
@ -105,7 +105,7 @@ const keyBindings = {
|
|||
return false;
|
||||
},
|
||||
"backspace": node => {
|
||||
if (!utils.isTopLevelNode(node)) {
|
||||
if (!utils.isRootNode(node)) {
|
||||
node.getParent().setActive().then(treeService.clearSelectedNodes);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -4,7 +4,7 @@ import treeCache from "./tree_cache.js";
|
|||
const $tree = $("#tree");
|
||||
|
||||
function getParentProtectedStatus(node) {
|
||||
return utils.isTopLevelNode(node) ? 0 : node.getParent().data.isProtected;
|
||||
return utils.isRootNode(node) ? 0 : node.getParent().data.isProtected;
|
||||
}
|
||||
|
||||
function getNodeByKey(key) {
|
||||
|
@ -32,6 +32,8 @@ function getNotePath(node) {
|
|||
node = node.getParent();
|
||||
}
|
||||
|
||||
path.push('root');
|
||||
|
||||
return path.reverse().join("/");
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ function isTopLevelNode(node) {
|
|||
}
|
||||
|
||||
function isRootNode(node) {
|
||||
return node.key === "root_1";
|
||||
return node.data.noteId === "root";
|
||||
}
|
||||
|
||||
function escapeHtml(str) {
|
||||
|
|
|
@ -21,7 +21,7 @@ async function moveBranchToParent(req) {
|
|||
const validationResult = await tree.validateParentChild(parentNoteId, noteToMove.noteId, branchId);
|
||||
|
||||
if (!validationResult.success) {
|
||||
return [400, validationResult];
|
||||
return [200, validationResult];
|
||||
}
|
||||
|
||||
const maxNotePos = await sql.getValue('SELECT MAX(notePosition) FROM branches WHERE parentNoteId = ? AND isDeleted = 0', [parentNoteId]);
|
||||
|
@ -45,7 +45,7 @@ async function moveBranchBeforeNote(req) {
|
|||
const validationResult = await tree.validateParentChild(beforeNote.parentNoteId, noteToMove.noteId, branchId);
|
||||
|
||||
if (!validationResult.success) {
|
||||
return [400, validationResult];
|
||||
return [200, validationResult];
|
||||
}
|
||||
|
||||
// we don't change dateModified so other changes are prioritized in case of conflict
|
||||
|
@ -73,7 +73,7 @@ async function moveBranchAfterNote(req) {
|
|||
const validationResult = await tree.validateParentChild(afterNote.parentNoteId, noteToMove.noteId, branchId);
|
||||
|
||||
if (!validationResult.success) {
|
||||
return [400, validationResult];
|
||||
return [200, validationResult];
|
||||
}
|
||||
|
||||
// we don't change dateModified so other changes are prioritized in case of conflict
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
const build = require('./build');
|
||||
const packageJson = require('../../package');
|
||||
|
||||
const APP_DB_VERSION = 113;
|
||||
const APP_DB_VERSION = 114;
|
||||
const SYNC_VERSION = 1;
|
||||
|
||||
module.exports = {
|
||||
|
|
|
@ -28,10 +28,7 @@ async function checkTreeCycles(errorList) {
|
|||
const childNoteId = row.noteId;
|
||||
const parentNoteId = row.parentNoteId;
|
||||
|
||||
if (!childToParents[childNoteId]) {
|
||||
childToParents[childNoteId] = [];
|
||||
}
|
||||
|
||||
childToParents[childNoteId] = childToParents[childNoteId] || [];
|
||||
childToParents[childNoteId].push(parentNoteId);
|
||||
}
|
||||
|
||||
|
@ -40,6 +37,11 @@ async function checkTreeCycles(errorList) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!childToParents[noteId] || childToParents[noteId].length === 0) {
|
||||
errorList.push(`No parents found for noteId=${noteId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const parentNoteId of childToParents[noteId]) {
|
||||
if (path.includes(parentNoteId)) {
|
||||
errorList.push(`Tree cycle detected at parent-child relationship: ${parentNoteId} - ${noteId}, whole path: ${path}`);
|
||||
|
@ -58,6 +60,10 @@ async function checkTreeCycles(errorList) {
|
|||
for (const noteId of noteIds) {
|
||||
checkTreeCycle(noteId, [], errorList);
|
||||
}
|
||||
|
||||
if (childToParents['root'].length !== 1 || childToParents['root'][0] !== 'none') {
|
||||
errorList.push('Incorrect root parent: ' + JSON.stringify(childToParents['root']));
|
||||
}
|
||||
}
|
||||
|
||||
async function runSyncRowChecks(table, key, errorList) {
|
||||
|
|
|
@ -7,6 +7,15 @@ const syncTableService = require('./sync_table');
|
|||
const protectedSessionService = require('./protected_session');
|
||||
|
||||
async function validateParentChild(parentNoteId, childNoteId, branchId = null) {
|
||||
if (childNoteId === 'root') {
|
||||
return { success: false, message: 'Cannot move root note.'};
|
||||
}
|
||||
|
||||
if (parentNoteId === 'none') {
|
||||
// this shouldn't happen
|
||||
return { success: false, message: 'Cannot move anything into root parent.' };
|
||||
}
|
||||
|
||||
const existing = await getExistingBranch(parentNoteId, childNoteId);
|
||||
|
||||
if (existing && (branchId === null || existing.branchId !== branchId)) {
|
||||
|
|
Loading…
Reference in a new issue