renaming note_tree to branch

This commit is contained in:
azivner 2018-03-24 21:39:15 -04:00
parent 511fb89af0
commit 4c472ce78b
45 changed files with 540 additions and 508 deletions

View File

@ -11,11 +11,11 @@
<collation id="5" parent="1" name="RTRIM"/>
<table id="6" parent="2" name="api_tokens"/>
<table id="7" parent="2" name="attributes"/>
<table id="8" parent="2" name="event_log"/>
<table id="9" parent="2" name="images"/>
<table id="10" parent="2" name="note_images"/>
<table id="11" parent="2" name="note_revisions"/>
<table id="12" parent="2" name="note_tree"/>
<table id="8" parent="2" name="branches"/>
<table id="9" parent="2" name="event_log"/>
<table id="10" parent="2" name="images"/>
<table id="11" parent="2" name="note_images"/>
<table id="12" parent="2" name="note_revisions"/>
<table id="13" parent="2" name="notes"/>
<table id="14" parent="2" name="options"/>
<table id="15" parent="2" name="recent_notes"/>
@ -122,199 +122,202 @@ value</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_attributes_1</UnderlyingIndexName>
</key>
<column id="38" parent="8" name="id">
<column id="38" parent="8" name="branchId">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="39" parent="8" name="noteId">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="40" parent="8" name="parentNoteId">
<Position>3</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="41" parent="8" name="notePosition">
<Position>4</Position>
<DataType>INTEGER|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="42" parent="8" name="prefix">
<Position>5</Position>
<DataType>TEXT|0s</DataType>
</column>
<column id="43" parent="8" name="isExpanded">
<Position>6</Position>
<DataType>BOOLEAN|0s</DataType>
</column>
<column id="44" parent="8" name="isDeleted">
<Position>7</Position>
<DataType>INTEGER|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="45" parent="8" name="dateModified">
<Position>8</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="46" parent="8" name="sqlite_autoindex_branches_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>branchId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<index id="47" parent="8" name="IDX_branches_noteId_parentNoteId">
<ColNames>noteId
parentNoteId</ColNames>
<ColumnCollations>
</ColumnCollations>
</index>
<index id="48" parent="8" name="IDX_branches_noteId">
<ColNames>noteId</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<key id="49" parent="8">
<ColNames>branchId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_branches_1</UnderlyingIndexName>
</key>
<column id="50" parent="9" name="id">
<Position>1</Position>
<DataType>INTEGER|0s</DataType>
<NotNull>1</NotNull>
<SequenceIdentity>1</SequenceIdentity>
</column>
<column id="39" parent="8" name="noteId">
<column id="51" parent="9" name="noteId">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
</column>
<column id="40" parent="8" name="comment">
<column id="52" parent="9" name="comment">
<Position>3</Position>
<DataType>TEXT|0s</DataType>
</column>
<column id="41" parent="8" name="dateAdded">
<column id="53" parent="9" name="dateAdded">
<Position>4</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<key id="42" parent="8">
<key id="54" parent="9">
<ColNames>id</ColNames>
<Primary>1</Primary>
</key>
<foreign-key id="43" parent="8">
<foreign-key id="55" parent="9">
<ColNames>noteId</ColNames>
<RefTableName>notes</RefTableName>
<RefColNames>noteId</RefColNames>
</foreign-key>
<column id="44" parent="9" name="imageId">
<column id="56" parent="10" name="imageId">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="45" parent="9" name="format">
<column id="57" parent="10" name="format">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="46" parent="9" name="checksum">
<column id="58" parent="10" name="checksum">
<Position>3</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="47" parent="9" name="name">
<column id="59" parent="10" name="name">
<Position>4</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="48" parent="9" name="data">
<column id="60" parent="10" name="data">
<Position>5</Position>
<DataType>BLOB|0s</DataType>
</column>
<column id="49" parent="9" name="isDeleted">
<column id="61" parent="10" name="isDeleted">
<Position>6</Position>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="50" parent="9" name="dateModified">
<column id="62" parent="10" name="dateModified">
<Position>7</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="51" parent="9" name="dateCreated">
<column id="63" parent="10" name="dateCreated">
<Position>8</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="52" parent="9" name="sqlite_autoindex_images_1">
<index id="64" parent="10" name="sqlite_autoindex_images_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>imageId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="53" parent="9">
<key id="65" parent="10">
<ColNames>imageId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_images_1</UnderlyingIndexName>
</key>
<column id="54" parent="10" name="noteImageId">
<column id="66" parent="11" name="noteImageId">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="55" parent="10" name="noteId">
<column id="67" parent="11" name="noteId">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="56" parent="10" name="imageId">
<column id="68" parent="11" name="imageId">
<Position>3</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="57" parent="10" name="isDeleted">
<column id="69" parent="11" name="isDeleted">
<Position>4</Position>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="58" parent="10" name="dateModified">
<column id="70" parent="11" name="dateModified">
<Position>5</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="59" parent="10" name="dateCreated">
<column id="71" parent="11" name="dateCreated">
<Position>6</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="60" parent="10" name="sqlite_autoindex_note_images_1">
<index id="72" parent="11" name="sqlite_autoindex_note_images_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>noteImageId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<index id="61" parent="10" name="IDX_note_images_noteId_imageId">
<index id="73" parent="11" name="IDX_note_images_noteId_imageId">
<ColNames>noteId
imageId</ColNames>
<ColumnCollations>
</ColumnCollations>
</index>
<index id="62" parent="10" name="IDX_note_images_noteId">
<index id="74" parent="11" name="IDX_note_images_noteId">
<ColNames>noteId</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="63" parent="10" name="IDX_note_images_imageId">
<index id="75" parent="11" name="IDX_note_images_imageId">
<ColNames>imageId</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<key id="64" parent="10">
<key id="76" parent="11">
<ColNames>noteImageId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_note_images_1</UnderlyingIndexName>
</key>
<column id="65" parent="11" name="noteRevisionId">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="66" parent="11" name="noteId">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="67" parent="11" name="title">
<Position>3</Position>
<DataType>TEXT|0s</DataType>
</column>
<column id="68" parent="11" name="content">
<Position>4</Position>
<DataType>TEXT|0s</DataType>
</column>
<column id="69" parent="11" name="isProtected">
<Position>5</Position>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="70" parent="11" name="dateModifiedFrom">
<Position>6</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="71" parent="11" name="dateModifiedTo">
<Position>7</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="72" parent="11" name="sqlite_autoindex_note_revisions_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>noteRevisionId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<index id="73" parent="11" name="IDX_note_revisions_noteId">
<ColNames>noteId</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="74" parent="11" name="IDX_note_revisions_dateModifiedFrom">
<ColNames>dateModifiedFrom</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="75" parent="11" name="IDX_note_revisions_dateModifiedTo">
<ColNames>dateModifiedTo</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<key id="76" parent="11">
<ColNames>noteRevisionId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_note_revisions_1</UnderlyingIndexName>
</key>
<column id="77" parent="12" name="noteTreeId">
<column id="77" parent="12" name="noteRevisionId">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
@ -324,55 +327,52 @@ imageId</ColNames>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="79" parent="12" name="parentNoteId">
<column id="79" parent="12" name="title">
<Position>3</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="80" parent="12" name="notePosition">
<column id="80" parent="12" name="content">
<Position>4</Position>
<DataType>INTEGER|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="81" parent="12" name="prefix">
<Position>5</Position>
<DataType>TEXT|0s</DataType>
</column>
<column id="82" parent="12" name="isExpanded">
<Position>6</Position>
<DataType>BOOLEAN|0s</DataType>
</column>
<column id="83" parent="12" name="isDeleted">
<Position>7</Position>
<DataType>INTEGER|0s</DataType>
<column id="81" parent="12" name="isProtected">
<Position>5</Position>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="84" parent="12" name="dateModified">
<Position>8</Position>
<column id="82" parent="12" name="dateModifiedFrom">
<Position>6</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="85" parent="12" name="sqlite_autoindex_note_tree_1">
<column id="83" parent="12" name="dateModifiedTo">
<Position>7</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="84" parent="12" name="sqlite_autoindex_note_revisions_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>noteTreeId</ColNames>
<ColNames>noteRevisionId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<index id="86" parent="12" name="IDX_note_tree_noteId_parentNoteId">
<ColNames>noteId
parentNoteId</ColNames>
<ColumnCollations>
</ColumnCollations>
</index>
<index id="87" parent="12" name="IDX_note_tree_noteId">
<index id="85" parent="12" name="IDX_note_revisions_noteId">
<ColNames>noteId</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="86" parent="12" name="IDX_note_revisions_dateModifiedFrom">
<ColNames>dateModifiedFrom</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="87" parent="12" name="IDX_note_revisions_dateModifiedTo">
<ColNames>dateModifiedTo</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<key id="88" parent="12">
<ColNames>noteTreeId</ColNames>
<ColNames>noteRevisionId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_note_tree_1</UnderlyingIndexName>
<UnderlyingIndexName>sqlite_autoindex_note_revisions_1</UnderlyingIndexName>
</key>
<column id="89" parent="13" name="noteId">
<Position>1</Position>
@ -466,7 +466,7 @@ parentNoteId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_options_1</UnderlyingIndexName>
</key>
<column id="107" parent="15" name="noteTreeId">
<column id="107" parent="15" name="branchId">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
@ -487,12 +487,12 @@ parentNoteId</ColNames>
</column>
<index id="111" parent="15" name="sqlite_autoindex_recent_notes_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>noteTreeId</ColNames>
<ColNames>branchId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="112" parent="15">
<ColNames>noteTreeId</ColNames>
<ColNames>branchId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_recent_notes_1</UnderlyingIndexName>
</key>

View File

@ -0,0 +1,38 @@
CREATE TABLE "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,
`dateModified` TEXT NOT NULL,
PRIMARY KEY(`branchId`)
);
INSERT INTO branches (branchId, noteId, parentNoteId, notePosition, prefix, isExpanded, isDeleted, dateModified)
SELECT noteTreeId, noteId, parentNoteId, notePosition, prefix, isExpanded, isDeleted, dateModified FROM note_tree;
DROP TABLE note_tree;
CREATE INDEX `IDX_branches_noteId` ON `branches` (
`noteId`
);
CREATE INDEX `IDX_branches_noteId_parentNoteId` ON `branches` (
`noteId`,
`parentNoteId`
);
CREATE TABLE `recent_notes_mig` (
`branchId` TEXT NOT NULL PRIMARY KEY,
`notePath` TEXT NOT NULL,
`dateAccessed` TEXT NOT NULL,
isDeleted INT
);
INSERT INTO recent_notes_mig (branchId, notePath, dateAccessed, isDeleted)
SELECT noteTreeId, notePath, dateAccessed, isDeleted FROM recent_notes;
DROP TABLE recent_notes;
ALTER TABLE recent_notes_mig RENAME TO recent_notes;

18
src/entities/branch.js Normal file
View File

@ -0,0 +1,18 @@
"use strict";
const Entity = require('./entity');
class Branch extends Entity {
static get tableName() { return "branches"; }
static get primaryKeyName() { return "branchId"; }
async getNote() {
return this.repository.getEntity("SELECT * FROM branches WHERE isDeleted = 0 AND noteId = ?", [this.noteId]);
}
async getParentNote() {
return this.repository.getEntity("SELECT * FROM branches WHERE isDeleted = 0 AND parentNoteId = ?", [this.parentNoteId]);
}
}
module.exports = Branch;

View File

@ -79,50 +79,50 @@ class Note extends Entity {
}
async getTrees() {
return this.repository.getEntities("SELECT * FROM note_tree WHERE isDeleted = 0 AND noteId = ?", [this.noteId]);
return this.repository.getEntities("SELECT * FROM branches WHERE isDeleted = 0 AND noteId = ?", [this.noteId]);
}
async getChild(name) {
return this.repository.getEntity(`
SELECT notes.*
FROM note_tree
FROM branches
JOIN notes USING(noteId)
WHERE notes.isDeleted = 0
AND note_tree.isDeleted = 0
AND note_tree.parentNoteId = ?
AND branches.isDeleted = 0
AND branches.parentNoteId = ?
AND notes.title = ?`, [this.noteId, name]);
}
async getChildren() {
return this.repository.getEntities(`
SELECT notes.*
FROM note_tree
FROM branches
JOIN notes USING(noteId)
WHERE notes.isDeleted = 0
AND note_tree.isDeleted = 0
AND note_tree.parentNoteId = ?
ORDER BY note_tree.notePosition`, [this.noteId]);
AND branches.isDeleted = 0
AND branches.parentNoteId = ?
ORDER BY branches.notePosition`, [this.noteId]);
}
async getParents() {
return this.repository.getEntities(`
SELECT parent_notes.*
FROM
note_tree AS child_tree
branches AS child_tree
JOIN notes AS parent_notes ON parent_notes.noteId = child_tree.parentNoteId
WHERE child_tree.noteId = ?
AND child_tree.isDeleted = 0
AND parent_notes.isDeleted = 0`, [this.noteId]);
}
async getNoteTree() {
async getBranch() {
return this.repository.getEntities(`
SELECT note_tree.*
FROM note_tree
SELECT branches.*
FROM branches
JOIN notes USING(noteId)
WHERE notes.isDeleted = 0
AND note_tree.isDeleted = 0
AND note_tree.noteId = ?`, [this.noteId]);
AND branches.isDeleted = 0
AND branches.noteId = ?`, [this.noteId]);
}
beforeSaving() {

View File

@ -1,18 +0,0 @@
"use strict";
const Entity = require('./entity');
class NoteTree extends Entity {
static get tableName() { return "note_tree"; }
static get primaryKeyName() { return "noteTreeId"; }
async getNote() {
return this.repository.getEntity("SELECT * FROM note_tree WHERE isDeleted = 0 AND noteId = ?", [this.noteId]);
}
async getParentNote() {
return this.repository.getEntity("SELECT * FROM note_tree WHERE isDeleted = 0 AND parentNoteId = ?", [this.parentNoteId]);
}
}
module.exports = NoteTree;

View File

@ -24,7 +24,7 @@ function ScriptApi(startNote, currentNote) {
const $pluginButtons = $("#plugin-buttons");
async function activateNote(notePath) {
await noteTree.activateNode(notePath);
await treeService.activateNode(notePath);
}
function addButtonToToolbar(buttonId, button) {
@ -70,7 +70,7 @@ function ScriptApi(startNote, currentNote) {
currentNote: currentNote,
addButtonToToolbar,
activateNote,
getInstanceName: noteTree.getInstanceName,
getInstanceName: treeService.getInstanceName,
runOnServer
}
}

View File

@ -11,19 +11,19 @@ const cloning = (function() {
return;
}
await noteTree.reload();
await treeService.reload();
}
// beware that first arg is noteId and second is noteTreeId!
async function cloneNoteAfter(noteId, afterNoteTreeId) {
const resp = await server.put('notes/' + noteId + '/clone-after/' + afterNoteTreeId);
// beware that first arg is noteId and second is branchId!
async function cloneNoteAfter(noteId, afterBranchId) {
const resp = await server.put('notes/' + noteId + '/clone-after/' + afterBranchId);
if (!resp.success) {
alert(resp.message);
return;
}
await noteTree.reload();
await treeService.reload();
}
return {

View File

@ -17,7 +17,7 @@ const contextMenu = (function() {
}
else if (clipboardMode === 'copy') {
for (const noteId of clipboardIds) {
await cloning.cloneNoteAfter(noteId, node.data.noteTreeId);
await cloning.cloneNoteAfter(noteId, node.data.branchId);
}
// copy will keep clipboardIds and clipboardMode so it's possible to paste into multiple places
@ -95,9 +95,9 @@ const contextMenu = (function() {
],
beforeOpen: (event, ui) => {
const node = $.ui.fancytree.getNode(ui.target);
const nt = noteTree.getNoteTree(node.data.noteTreeId);
const note = noteTree.getNote(node.data.noteId);
const parentNote = noteTree.getNote(nt.parentNoteId);
const branch = treeService.getBranch(node.data.branchId);
const note = treeService.getNote(node.data.noteId);
const parentNote = treeService.getNote(branch.parentNoteId);
// Modify menu entries depending on node status
$tree.contextmenu("enableEntry", "pasteAfter", clipboardIds.length > 0 && (!parentNote || parentNote.type !== 'search'));
@ -121,10 +121,10 @@ const contextMenu = (function() {
const parentNoteId = node.data.parentNoteId;
const isProtected = treeUtils.getParentProtectedStatus(node);
noteTree.createNote(node, parentNoteId, 'after', isProtected);
treeService.createNote(node, parentNoteId, 'after', isProtected);
}
else if (ui.cmd === "insertChildNote") {
noteTree.createNote(node, node.data.noteId, 'into');
treeService.createNote(node, node.data.noteId, 'into');
}
else if (ui.cmd === "editTreePrefix") {
editTreePrefix.showDialog(node);
@ -136,10 +136,10 @@ const contextMenu = (function() {
protected_session.protectSubTree(node.data.noteId, false);
}
else if (ui.cmd === "copy") {
copy(noteTree.getSelectedNodes());
copy(treeService.getSelectedNodes());
}
else if (ui.cmd === "cut") {
cut(noteTree.getSelectedNodes());
cut(treeService.getSelectedNodes());
}
else if (ui.cmd === "pasteAfter") {
pasteAfter(node);
@ -148,7 +148,7 @@ const contextMenu = (function() {
pasteInto(node);
}
else if (ui.cmd === "delete") {
treeChanges.deleteNodes(noteTree.getSelectedNodes(true));
treeChanges.deleteNodes(treeService.getSelectedNodes(true));
}
else if (ui.cmd === "exportSubTree") {
exportSubTree(node.data.noteId);
@ -157,13 +157,13 @@ const contextMenu = (function() {
importSubTree(node.data.noteId);
}
else if (ui.cmd === "collapseSubTree") {
noteTree.collapseTree(node);
treeService.collapseTree(node);
}
else if (ui.cmd === "forceNoteSync") {
forceNoteSync(node.data.noteId);
}
else if (ui.cmd === "sortAlphabetically") {
noteTree.sortAlphabetically(node.data.noteId);
treeService.sortAlphabetically(node.data.noteId);
}
else {
messaging.logError("Unknown command: " + ui.cmd);

View File

@ -43,13 +43,13 @@ const addLink = (function() {
$linkTitle.val('');
function setDefaultLinkTitle(noteId) {
const noteTitle = noteTree.getNoteTitle(noteId);
const noteTitle = treeService.getNoteTitle(noteId);
$linkTitle.val(noteTitle);
}
$autoComplete.autocomplete({
source: noteTree.getAutocompleteItems(),
source: treeService.getAutocompleteItems(),
minLength: 0,
change: () => {
const val = $autoComplete.val();

View File

@ -6,7 +6,7 @@ const editTreePrefix = (function() {
const $treePrefixInput = $("#tree-prefix-input");
const $noteTitle = $('#tree-prefix-note-title');
let noteTreeId;
let branchId;
async function showDialog() {
glob.activeDialog = $dialog;
@ -16,14 +16,14 @@ const editTreePrefix = (function() {
width: 500
});
const currentNode = noteTree.getCurrentNode();
const currentNode = treeService.getCurrentNode();
noteTreeId = currentNode.data.noteTreeId;
const nt = noteTree.getNoteTree(noteTreeId);
branchId = currentNode.data.branchId;
const nt = treeService.getBranch(branchId);
$treePrefixInput.val(nt.prefix).focus();
const noteTitle = noteTree.getNoteTitle(currentNode.data.noteId);
const noteTitle = treeService.getNoteTitle(currentNode.data.noteId);
$noteTitle.html(noteTitle);
}
@ -31,9 +31,9 @@ const editTreePrefix = (function() {
$form.submit(() => {
const prefix = $treePrefixInput.val();
server.put('tree/' + noteTreeId + '/set-prefix', {
server.put('tree/' + branchId + '/set-prefix', {
prefix: prefix
}).then(() => noteTree.setPrefix(noteTreeId, prefix));
}).then(() => treeService.setPrefix(branchId, prefix));
$dialog.dialog("close");

View File

@ -17,7 +17,7 @@ const jumpToNote = (function() {
});
await $autoComplete.autocomplete({
source: await stopWatch("building autocomplete", noteTree.getAutocompleteItems),
source: await stopWatch("building autocomplete", treeService.getAutocompleteItems),
minLength: 0
});
}
@ -31,7 +31,7 @@ const jumpToNote = (function() {
const notePath = getSelectedNotePath();
if (notePath) {
noteTree.activateNode(notePath);
treeService.activateNode(notePath);
$dialog.dialog('close');
}

View File

@ -14,11 +14,11 @@ const recentNotes = (function() {
list = result.map(r => r.notePath);
}
function addRecentNote(noteTreeId, notePath) {
function addRecentNote(branchId, notePath) {
setTimeout(async () => {
// we include the note into recent list only if the user stayed on the note at least 5 seconds
if (notePath && notePath === noteTree.getCurrentNotePath()) {
const result = await server.put('recent-notes/' + noteTreeId + '/' + encodeURIComponent(notePath));
if (notePath && notePath === treeService.getCurrentNotePath()) {
const result = await server.put('recent-notes/' + branchId + '/' + encodeURIComponent(notePath));
list = result.map(r => r.notePath);
}
@ -38,14 +38,14 @@ const recentNotes = (function() {
$searchInput.val('');
// remove the current note
const recNotes = list.filter(note => note !== noteTree.getCurrentNotePath());
const recNotes = list.filter(note => note !== treeService.getCurrentNotePath());
$searchInput.autocomplete({
source: recNotes.map(notePath => {
let noteTitle;
try {
noteTitle = noteTree.getNotePathTitle(notePath);
noteTitle = treeService.getNotePathTitle(notePath);
}
catch (e) {
noteTitle = "[error - can't find note title]";
@ -61,7 +61,7 @@ const recentNotes = (function() {
minLength: 0,
autoFocus: true,
select: function (event, ui) {
noteTree.activateNode(ui.item.value);
treeService.activateNode(ui.item.value);
$searchInput.autocomplete('destroy');
$dialog.dialog('close');

View File

@ -49,7 +49,7 @@ const dragAndDropSetup = {
const nodeToMove = data.otherNode;
nodeToMove.setSelected(true);
const selectedNodes = noteTree.getSelectedNodes();
const selectedNodes = treeService.getSelectedNodes();
if (data.hitMode === "before") {
treeChanges.moveBeforeNode(selectedNodes, node);

View File

@ -28,5 +28,5 @@ $("#import-upload").change(async function() {
processData: false, // NEEDED, DON'T OMIT THIS
});
await noteTree.reload();
await treeService.reload();
});

View File

@ -55,7 +55,7 @@ $(document).bind('keydown', 'ctrl+f', () => {
});
$(document).bind('keydown', "ctrl+shift+up", () => {
const node = noteTree.getCurrentNode();
const node = treeService.getCurrentNode();
node.navigate($.ui.keyCode.UP, true);
$("#note-detail").focus();
@ -64,7 +64,7 @@ $(document).bind('keydown', "ctrl+shift+up", () => {
});
$(document).bind('keydown', "ctrl+shift+down", () => {
const node = noteTree.getCurrentNode();
const node = treeService.getCurrentNode();
node.navigate($.ui.keyCode.DOWN, true);
$("#note-detail").focus();
@ -211,16 +211,16 @@ $(document).ready(() => {
if (isElectron()) {
require('electron').ipcRenderer.on('create-day-sub-note', async function(event, parentNoteId) {
// this might occur when day note had to be created
if (!noteTree.noteExists(parentNoteId)) {
await noteTree.reload();
if (!treeService.noteExists(parentNoteId)) {
await treeService.reload();
}
await noteTree.activateNode(parentNoteId);
await treeService.activateNode(parentNoteId);
setTimeout(() => {
const node = noteTree.getCurrentNode();
const node = treeService.getCurrentNode();
noteTree.createNote(node, node.data.noteId, 'into', node.data.isProtected);
treeService.createNote(node, node.data.noteId, 'into', node.data.isProtected);
}, 500);
});
}
@ -244,7 +244,7 @@ $("#attachment-upload").change(async function() {
processData: false, // NEEDED, DON'T OMIT THIS
});
await noteTree.reload();
await treeService.reload();
await noteTree.activateNode(resp.noteId);
await treeService.activateNode(resp.noteId);
});

View File

@ -26,7 +26,7 @@ const link = (function() {
if (!noteTitle) {
const noteId = treeUtils.getNoteIdFromNotePath(notePath);
noteTitle = noteTree.getNoteTitle(noteId);
noteTitle = treeService.getNoteTitle(noteId);
}
const noteLink = $("<a>", {
@ -60,7 +60,7 @@ const link = (function() {
notePath = getNotePathFromLink(address);
}
noteTree.activateNode(notePath);
treeService.activateNode(notePath);
// this is quite ugly hack, but it seems like we can't close the tooltip otherwise
$("[role='tooltip']").remove();

View File

@ -29,12 +29,12 @@ const messaging = (function() {
const syncData = message.data.filter(sync => sync.sourceId !== glob.sourceId);
if (syncData.some(sync => sync.entityName === 'note_tree')
if (syncData.some(sync => sync.entityName === 'branches')
|| syncData.some(sync => sync.entityName === 'notes')) {
console.log(now(), "Reloading tree because of background changes");
noteTree.reload();
treeService.reload();
}
if (syncData.some(sync => sync.entityName === 'notes' && sync.entityId === noteEditor.getCurrentNoteId())) {

View File

@ -110,7 +110,7 @@ const noteEditor = (function() {
note.detail.title = title;
noteTree.setNoteTitle(note.detail.noteId, title);
treeService.setNoteTitle(note.detail.noteId, title);
}
async function saveNoteToServer(note) {
@ -264,7 +264,7 @@ const noteEditor = (function() {
noteChangeDisabled = false;
setNoteBackgroundIfProtected(currentNote);
noteTree.setNoteTreeBackgroundBasedOnProtectedStatus(noteId);
treeService.setBranchBackgroundBasedOnProtectedStatus(noteId);
// after loading new note make sure editor is scrolled to the top
$noteDetailWrapper.scrollTop(0);
@ -366,7 +366,7 @@ const noteEditor = (function() {
const title = $noteTitle.val();
noteTree.setNoteTitle(getCurrentNoteId(), title);
treeService.setNoteTitle(getCurrentNoteId(), title);
});
// so that tab jumps from note title (which has tabindex 1)

View File

@ -1,10 +1,10 @@
"use strict";
class TreeCache {
constructor(noteRows, noteTreeRows) {
constructor(noteRows, branchRows) {
this.parents = [];
this.children = [];
this.childParentToNoteTree = {};
this.childParentToBranch = {};
this.notes = {};
for (const noteRow of noteRows) {
@ -13,12 +13,12 @@ class TreeCache {
this.notes[note.noteId] = note;
}
this.noteTree = {};
for (const noteTreeRow of noteTreeRows) {
const nt = new NoteTree(this, noteTreeRow);
this.branches = {};
for (const branchRow of branchRows) {
const branch = new Branch(this, branchRow);
this.noteTree[nt.noteTreeId] = nt;
this.addNoteTree(nt);
this.branches[branch.branchId] = branch;
this.addBranch(branch);
}
}
@ -26,22 +26,24 @@ class TreeCache {
return this.notes[noteId];
}
addNoteTree(nt) {
this.parents[nt.noteId] = this.parents[nt.noteId] || [];
this.parents[nt.noteId].push(this.notes[nt.parentNoteId]);
addBranch(branch) {
this.parents[branch.noteId] = this.parents[branch.noteId] || [];
this.parents[branch.noteId].push(this.notes[branch.parentNoteId]);
this.children[nt.parentNoteId] = this.children[nt.parentNoteId] || [];
this.children[nt.parentNoteId].push(this.notes[nt.noteId]);
this.children[branch.parentNoteId] = this.children[branch.parentNoteId] || [];
this.children[branch.parentNoteId].push(this.notes[branch.noteId]);
this.childParentToNoteTree[nt.noteId + '-' + nt.parentNoteId] = nt;
this.childParentToBranch[branch.noteId + '-' + branch.parentNoteId] = branch;
}
add(note, nt) {
add(note, branch) {
this.notes[note.noteId] = note;
this.addBranch(branch);
}
async getNoteTree(childNoteId, parentNoteId) {
return this.childParentToNoteTree[childNoteId + '-' + parentNoteId];
async getBranch(childNoteId, parentNoteId) {
return this.childParentToBranch[childNoteId + '-' + parentNoteId];
}
}
@ -56,24 +58,24 @@ class NoteShort {
this.hideInAutocomplete = row.hideInAutocomplete;
}
async getNoteTrees() {
const noteTrees = [];
async getBranches() {
const branches = [];
for (const parent of this.treeCache.parents[this.noteId]) {
noteTrees.push(await this.treeCache.getNoteTree(this.noteId, p.noteId));
branches.push(await this.treeCache.getBranch(this.noteId, p.noteId));
}
return noteTrees;
return branches;
}
async getChildNoteTrees() {
const noteTrees = [];
async getChildBranches() {
const branches = [];
for (const child of this.treeCache.children[this.noteId]) {
noteTrees.push(await this.treeCache.getNoteTree(child.noteId, this.noteId));
branches.push(await this.treeCache.getBranch(child.noteId, this.noteId));
}
return noteTrees;
return branches;
}
async getParentNotes() {
@ -89,10 +91,10 @@ class NoteShort {
}
}
class NoteTree {
class Branch {
constructor(treeCache, row) {
this.treeCache = treeCache;
this.noteTreeId = row.noteTreeId;
this.branchId = row.branchId;
this.noteId = row.noteId;
this.note = null;
this.parentNoteId = row.parentNoteId;
@ -106,11 +108,11 @@ class NoteTree {
}
get toString() {
return `NoteTree(noteTreeId=${this.noteTreeId})`;
return `Branch(branchId=${this.branchId})`;
}
}
const noteTree = (function() {
const treeService = (function() {
let treeCache;
const $tree = $("#tree");
@ -126,8 +128,8 @@ const noteTree = (function() {
/** @type {Object.<string, NoteShort>} */
let noteMap = {};
/** @type {Object.<string, NoteTree>} */
let noteTreeMap = {};
/** @type {Object.<string, Branch>} */
let branchMap = {};
function getNote(noteId) {
const note = noteMap[noteId];
@ -139,7 +141,7 @@ const noteTree = (function() {
return note;
}
function getNoteTreeId(parentNoteId, childNoteId) {
function getBranchId(parentNoteId, childNoteId) {
assertArguments(parentNoteId, childNoteId);
@ -148,7 +150,7 @@ const noteTree = (function() {
// this can return undefined and client code should deal with it somehow
return parentChildToNoteTreeId[key];
return parentChildToBranchId[key];
}
function getNoteTitle(noteId, parentNoteId = null) {
@ -157,13 +159,13 @@ const noteTree = (function() {
let title = treeCache.getNote(noteId).title;
if (parentNoteId !== null) {
const noteTreeId = getNoteTreeId(parentNoteId, noteId);
const branchId = getBranchId(parentNoteId, noteId);
if (noteTreeId) {
const noteTree = noteTreeMap[noteTreeId];
if (branchId) {
const branch = branchMap[branchId];
if (noteTree.prefix) {
title = noteTree.prefix + ' - ' + title;
if (branch.prefix) {
title = branch.prefix + ' - ' + title;
}
}
}
@ -182,12 +184,12 @@ const noteTree = (function() {
return treeUtils.getNotePath(node);
}
function getNodesByNoteTreeId(noteTreeId) {
assertArguments(noteTreeId);
function getNodesByBranchId(branchId) {
assertArguments(branchId);
const noteTree = noteTreeMap[noteTreeId];
const branch = branchMap[branchId];
return getNodesByNoteId(noteTree.noteId).filter(node => node.data.noteTreeId === noteTreeId);
return getNodesByNoteId(branch.noteId).filter(node => node.data.branchId === branchId);
}
function getNodesByNoteId(noteId) {
@ -197,19 +199,19 @@ const noteTree = (function() {
return list ? list : []; // if no nodes with this refKey are found, fancy tree returns null
}
function setPrefix(noteTreeId, prefix) {
assertArguments(noteTreeId);
function setPrefix(branchId, prefix) {
assertArguments(branchId);
noteTreeMap[noteTreeId].prefix = prefix;
branchMap[branchId].prefix = prefix;
getNodesByNoteTreeId(noteTreeId).map(node => setNodeTitleWithPrefix(node));
getNodesByBranchId(branchId).map(node => setNodeTitleWithPrefix(node));
}
function setNodeTitleWithPrefix(node) {
const noteTitle = getNoteTitle(node.data.noteId);
const noteTree = noteTreeMap[node.data.noteTreeId];
const branch = branchMap[node.data.branchId];
const prefix = noteTree.prefix;
const prefix = branch.prefix;
const title = (prefix ? (prefix + " - ") : "") + noteTitle;
@ -222,32 +224,24 @@ const noteTree = (function() {
const parentNote = noteMap[parentNoteId];
const childNote = noteMap[childNoteId];
parentNote.children = parentNote.children.filter(note => note.noteId !== childNoteId);
childNote.parents = childNote.parents.filter(note => note.noteId !== parentNoteId);
childNote.noteTree = childNote.noteTree.filter(nt => nt.parentNoteId !== parentNoteId);
// FIXME
}
function setParentChildRelation(noteTreeId, parentNoteId, childNoteId) {
assertArguments(noteTreeId, parentNoteId, childNoteId);
function setParentChildRelation(branchId, parentNoteId, childNoteId) {
assertArguments(branchId, parentNoteId, childNoteId);
const parentNote = noteMap[parentNoteId];
const childNote = noteMap[childNoteId];
// FIXME: assert
childNote.parents.push(parentNote);
parentNote.children.push(childNote);
const noteTree = noteTreeMap[noteTreeId];
childNote.noteTree.push(noteTree);
}
async function prepareNoteTree(noteRows, noteTreeRows) {
async function prepareBranch(noteRows, branchRows) {
assertArguments(noteRows);
treeCache = new TreeCache(noteRows, noteTreeRows);
treeCache = new TreeCache(noteRows, branchRows);
return await prepareNoteTreeInner(treeCache.getNote('root'));
return await prepareBranchInner(treeCache.getNote('root'));
}
async function getExtraClasses(note) {
@ -268,31 +262,31 @@ const noteTree = (function() {
return extraClasses.join(" ");
}
async function prepareNoteTreeInner(parentNote) {
async function prepareBranchInner(parentNote) {
assertArguments(parentNote);
const childrenNoteTrees = await parentNote.getChildNoteTrees();
const childBranches = await parentNote.getChildBranches();
if (!childrenNoteTrees) {
if (!childBranches) {
messaging.logError(`No children for ${parentNote}. This shouldn't happen.`);
return;
}
const noteList = [];
for (const noteTree of childrenNoteTrees) {
const note = await noteTree.getNote();
const title = (noteTree.prefix ? (noteTree.prefix + " - ") : "") + note.title;
for (const branch of childBranches) {
const note = await branch.getNote();
const title = (branch.prefix ? (branch.prefix + " - ") : "") + note.title;
const node = {
noteId: note.noteId,
parentNoteId: noteTree.parentNoteId,
noteTreeId: noteTree.noteTreeId,
parentNoteId: branch.parentNoteId,
branchId: branch.branchId,
isProtected: note.isProtected,
title: escapeHtml(title),
extraClasses: getExtraClasses(note),
refKey: note.noteId,
expanded: note.type !== 'search' && noteTree.isExpanded
expanded: note.type !== 'search' && branch.isExpanded
};
const hasChildren = (await note.getChildNotes()).length > 0;
@ -301,7 +295,7 @@ const noteTree = (function() {
node.folder = true;
if (node.expanded && note.type !== 'search') {
node.children = await prepareNoteTreeInner(note);
node.children = await prepareBranchInner(note);
}
else {
node.lazy = true;
@ -485,23 +479,23 @@ const noteTree = (function() {
return path.reverse().join('/');
}
async function setExpandedToServer(noteTreeId, isExpanded) {
assertArguments(noteTreeId);
async function setExpandedToServer(branchId, isExpanded) {
assertArguments(branchId);
const expandedNum = isExpanded ? 1 : 0;
await server.put('tree/' + noteTreeId + '/expanded/' + expandedNum);
await server.put('tree/' + branchId + '/expanded/' + expandedNum);
}
function setCurrentNotePathToHash(node) {
assertArguments(node);
const currentNotePath = treeUtils.getNotePath(node);
const currentNoteTreeId = node.data.noteTreeId;
const currentBranchId = node.data.branchId;
document.location.hash = currentNotePath;
recentNotes.addRecentNote(currentNoteTreeId, currentNotePath);
recentNotes.addRecentNote(currentBranchId, currentNotePath);
}
function getSelectedNodes(stopOnParents = false) {
@ -520,8 +514,8 @@ const noteTree = (function() {
}
}
function initFancyTree(noteTree) {
assertArguments(noteTree);
function initFancyTree(branch) {
assertArguments(branch);
const keybindings = {
"del": node => {
@ -656,7 +650,7 @@ const noteTree = (function() {
autoScroll: true,
keyboard: false, // we takover keyboard handling in the hotkeys plugin
extensions: ["hotkeys", "filter", "dnd", "clones"],
source: noteTree,
source: branch,
scrollParent: $("#tree"),
click: (event, data) => {
const targetType = data.targetType;
@ -686,10 +680,10 @@ const noteTree = (function() {
showParentList(node.noteId, data.node);
},
expand: (event, data) => {
setExpandedToServer(data.node.data.noteTreeId, true);
setExpandedToServer(data.node.data.branchId, true);
},
collapse: (event, data) => {
setExpandedToServer(data.node.data.noteTreeId, false);
setExpandedToServer(data.node.data.branchId, false);
},
init: (event, data) => {
const noteId = treeUtils.getNoteIdFromNotePath(startNotePath);
@ -731,7 +725,7 @@ const noteTree = (function() {
data.result = loadSearchNote(noteId);
}
else {
data.result = await prepareNoteTreeInner(note);
data.result = await prepareBranchInner(note);
}
},
clones: {
@ -750,20 +744,20 @@ const noteTree = (function() {
const noteIds = await server.get('search/' + encodeURIComponent(json.searchString));
for (const noteId of noteIds) {
const noteTreeId = "virt" + randomString(10);
const branchId = "virt" + randomString(10);
noteTreeMap[noteTreeId] = {
noteTreeId: noteTreeId,
branchMap[branchId] = {
branchId: branchId,
noteId: noteId,
parentNoteId: searchNoteId,
prefix: '',
virtual: true
};
setParentChildRelation(noteTreeId, searchNoteId, noteId);
setParentChildRelation(branchId, searchNoteId, noteId);
}
return await prepareNoteTreeInner(searchNoteId);
return await prepareBranchInner(searchNoteId);
}
function getTree() {
@ -790,10 +784,10 @@ const noteTree = (function() {
startNotePath = getNotePathFromAddress();
}
return await prepareNoteTree(resp.notes, resp.noteTree);
return await prepareBranch(resp.notes, resp.branches);
}
$(() => loadTree().then(noteTree => initFancyTree(noteTree)));
$(() => loadTree().then(branch => initFancyTree(branch)));
function collapseTree(node = null) {
if (!node) {
@ -817,14 +811,14 @@ const noteTree = (function() {
}
}
function setNoteTreeBackgroundBasedOnProtectedStatus(noteId) {
function setBranchBackgroundBasedOnProtectedStatus(noteId) {
getNodesByNoteId(noteId).map(node => node.toggleClass("protected", !!node.data.isProtected));
}
function setProtected(noteId, isProtected) {
getNodesByNoteId(noteId).map(node => node.data.isProtected = isProtected);
setNoteTreeBackgroundBasedOnProtectedStatus(noteId);
setBranchBackgroundBasedOnProtectedStatus(noteId);
}
function getAutocompleteItems(parentNoteId, notePath, titlePath) {
@ -900,13 +894,13 @@ const noteTree = (function() {
const result = await server.post('notes/' + parentNoteId + '/children', {
title: newNoteName,
target: target,
target_noteTreeId: node.data.noteTreeId,
target_branchId: node.data.branchId,
isProtected: isProtected
});
setParentChildRelation(result.noteTreeId, parentNoteId, result.noteId);
setParentChildRelation(result.branchId, parentNoteId, result.noteId);
noteTreeMap[result.noteTreeId] = result;
branchMap[result.branchId] = result;
noteMap[result.noteId] = {
noteId: result.noteId,
@ -923,7 +917,7 @@ const noteTree = (function() {
noteId: result.noteId,
parentNoteId: parentNoteId,
refKey: result.noteId,
noteTreeId: result.noteTreeId,
branchId: result.branchId,
isProtected: isProtected,
extraClasses: getExtraClasses(result.note)
};
@ -967,8 +961,8 @@ const noteTree = (function() {
return instanceName;
}
function getNoteTree(noteTreeId) {
return noteTreeMap[noteTreeId];
function getBranch(branchId) {
return branchMap[branchId];
}
$(document).bind('keydown', 'ctrl+o', e => {
@ -1031,7 +1025,7 @@ const noteTree = (function() {
reload,
collapseTree,
scrollToCurrentNote,
setNoteTreeBackgroundBasedOnProtectedStatus,
setBranchBackgroundBasedOnProtectedStatus,
setProtected,
getCurrentNode,
expandToNote,
@ -1051,7 +1045,7 @@ const noteTree = (function() {
sortAlphabetically,
noteExists,
getInstanceName,
getNoteTree,
getBranch,
getNote
};
})();

View File

@ -91,7 +91,7 @@ const noteType = (function() {
await noteEditor.reload();
// for the note icon to be updated in the tree
await noteTree.reload();
await treeService.reload();
self.updateExecuteScriptButtonVisibility();
}

View File

@ -27,7 +27,7 @@ const protected_session = (function() {
if (requireProtectedSession && !isProtectedSessionAvailable()) {
protectedSessionDeferred = dfd;
if (noteTree.getCurrentNode().data.isProtected) {
if (treeService.getCurrentNode().data.isProtected) {
$noteDetailWrapper.hide();
}
@ -37,7 +37,7 @@ const protected_session = (function() {
open: () => {
if (!modal) {
// dialog steals focus for itself, which is not what we want for non-modal (viewing)
noteTree.getCurrentNode().setFocus();
treeService.getCurrentNode().setFocus();
}
}
});
@ -65,7 +65,7 @@ const protected_session = (function() {
$dialog.dialog("close");
noteEditor.reload();
noteTree.reload();
treeService.reload();
if (protectedSessionDeferred !== null) {
ensureDialogIsClosed($dialog, $password);
@ -121,7 +121,7 @@ const protected_session = (function() {
await noteEditor.saveNoteToServer(note);
noteTree.setProtected(note.detail.noteId, note.detail.isProtected);
treeService.setProtected(note.detail.noteId, note.detail.isProtected);
noteEditor.setNoteBackgroundIfProtected(note);
}
@ -137,7 +137,7 @@ const protected_session = (function() {
await noteEditor.saveNoteToServer(note);
noteTree.setProtected(note.detail.noteId, note.detail.isProtected);
treeService.setProtected(note.detail.noteId, note.detail.isProtected);
noteEditor.setNoteBackgroundIfProtected(note);
}
@ -155,7 +155,7 @@ const protected_session = (function() {
showMessage("Request to un/protect sub tree has finished successfully");
noteTree.reload();
treeService.reload();
noteEditor.reload();
}

View File

@ -35,7 +35,7 @@ async function doSearch() {
const noteIds = await server.get('search/' + encodeURIComponent(searchText));
for (const noteId of noteIds) {
await noteTree.expandToNote(noteId, {noAnimation: true, noEvents: true});
await treeService.expandToNote(noteId, {noAnimation: true, noEvents: true});
}
// Pass a string to perform case insensitive matching
@ -45,9 +45,9 @@ async function doSearch() {
async function saveSearch() {
const {noteId} = await server.post('search/' + encodeURIComponent($searchInput.val()));
await noteTree.reload();
await treeService.reload();
await noteTree.activateNode(noteId);
await treeService.activateNode(noteId);
}
$searchInput.keyup(e => {

View File

@ -3,7 +3,7 @@
const treeChanges = (function() {
async function moveBeforeNode(nodesToMove, beforeNode) {
for (const nodeToMove of nodesToMove) {
const resp = await server.put('tree/' + nodeToMove.data.noteTreeId + '/move-before/' + beforeNode.data.noteTreeId);
const resp = await server.put('tree/' + nodeToMove.data.branchId + '/move-before/' + beforeNode.data.branchId);
if (!resp.success) {
alert(resp.message);
@ -18,7 +18,7 @@ const treeChanges = (function() {
nodesToMove.reverse(); // need to reverse to keep the note order
for (const nodeToMove of nodesToMove) {
const resp = await server.put('tree/' + nodeToMove.data.noteTreeId + '/move-after/' + afterNode.data.noteTreeId);
const resp = await server.put('tree/' + nodeToMove.data.branchId + '/move-after/' + afterNode.data.branchId);
if (!resp.success) {
alert(resp.message);
@ -31,7 +31,7 @@ const treeChanges = (function() {
async function moveToNode(nodesToMove, toNode) {
for (const nodeToMove of nodesToMove) {
const resp = await server.put('tree/' + nodeToMove.data.noteTreeId + '/move-to/' + toNode.data.noteId);
const resp = await server.put('tree/' + nodeToMove.data.branchId + '/move-to/' + toNode.data.noteId);
if (!resp.success) {
alert(resp.message);
@ -61,7 +61,7 @@ const treeChanges = (function() {
}
for (const node of nodes) {
await server.remove('tree/' + node.data.noteTreeId);
await server.remove('tree/' + node.data.branchId);
}
// following code assumes that nodes contain only top-most selected nodes - getSelectedNodes has been
@ -80,10 +80,10 @@ const treeChanges = (function() {
// activate next element after this one is deleted so we don't lose focus
next.setActive();
noteTree.setCurrentNotePathToHash(next);
treeService.setCurrentNotePathToHash(next);
}
noteTree.reload();
treeService.reload();
showMessage("Note(s) has been deleted.");
}
@ -93,7 +93,7 @@ const treeChanges = (function() {
return;
}
const resp = await server.put('tree/' + node.data.noteTreeId + '/move-after/' + node.getParent().data.noteTreeId);
const resp = await server.put('tree/' + node.data.branchId + '/move-after/' + node.getParent().data.branchId);
if (!resp.success) {
alert(resp.message);
@ -111,15 +111,15 @@ const treeChanges = (function() {
function changeNode(node, func) {
assertArguments(node.data.parentNoteId, node.data.noteId);
noteTree.removeParentChildRelation(node.data.parentNoteId, node.data.noteId);
treeService.removeParentChildRelation(node.data.parentNoteId, node.data.noteId);
func(node);
node.data.parentNoteId = isTopLevelNode(node) ? 'root' : node.getParent().data.noteId;
noteTree.setParentChildRelation(node.data.noteTreeId, node.data.parentNoteId, node.data.noteId);
treeService.setParentChildRelation(node.data.branchId, node.data.parentNoteId, node.data.noteId);
noteTree.setCurrentNotePathToHash(node);
treeService.setCurrentNotePathToHash(node);
}
return {

File diff suppressed because one or more lines are too long

View File

@ -24,7 +24,7 @@ router.post('/cleanup-soft-deleted-items', auth.checkApiAuth, wrap(async (req, r
await sql.execute(`DELETE FROM attributes WHERE noteId IN (${noteIdsSql})`);
await sql.execute("DELETE FROM note_tree WHERE isDeleted = 1");
await sql.execute("DELETE FROM branches WHERE isDeleted = 1");
await sql.execute("DELETE FROM note_images WHERE isDeleted = 1");
@ -35,9 +35,9 @@ router.post('/cleanup-soft-deleted-items', auth.checkApiAuth, wrap(async (req, r
await sql.execute("DELETE FROM recent_notes");
await sync_table.cleanupSyncRowsForMissingEntities("notes", "noteId");
await sync_table.cleanupSyncRowsForMissingEntities("note_tree", "noteTreeId");
await sync_table.cleanupSyncRowsForMissingEntities("branches", "branchId");
await sync_table.cleanupSyncRowsForMissingEntities("note_revisions", "noteRevisionId");
await sync_table.cleanupSyncRowsForMissingEntities("recent_notes", "noteTreeId");
await sync_table.cleanupSyncRowsForMissingEntities("recent_notes", "branchId");
log.info("Following notes has been completely cleaned from database: " + noteIdsSql);
});

View File

@ -19,12 +19,12 @@ router.put('/:childNoteId/clone-to/:parentNoteId', auth.checkApiAuth, wrap(async
return;
}
const maxNotePos = await sql.getValue('SELECT MAX(notePosition) FROM note_tree 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;
await sql.doInTransaction(async () => {
const noteTree = {
noteTreeId: utils.newNoteTreeId(),
const branch = {
branchId: utils.newBranchId(),
noteId: childNoteId,
parentNoteId: parentNoteId,
prefix: prefix,
@ -34,22 +34,22 @@ router.put('/:childNoteId/clone-to/:parentNoteId', auth.checkApiAuth, wrap(async
isDeleted: 0
};
await sql.replace("note_tree", noteTree);
await sql.replace("branches", branch);
await sync_table.addNoteTreeSync(noteTree.noteTreeId, sourceId);
await sync_table.addBranchSync(branch.branchId, sourceId);
await sql.execute("UPDATE note_tree SET isExpanded = 1 WHERE noteId = ?", [parentNoteId]);
await sql.execute("UPDATE branches SET isExpanded = 1 WHERE noteId = ?", [parentNoteId]);
});
res.send({ success: true });
}));
router.put('/:noteId/clone-after/:afterNoteTreeId', auth.checkApiAuth, wrap(async (req, res, next) => {
router.put('/:noteId/clone-after/:afterBranchId', auth.checkApiAuth, wrap(async (req, res, next) => {
const noteId = req.params.noteId;
const afterNoteTreeId = req.params.afterNoteTreeId;
const afterBranchId = req.params.afterBranchId;
const sourceId = req.headers.source_id;
const afterNote = await tree.getNoteTree(afterNoteTreeId);
const afterNote = await tree.getBranch(afterBranchId);
if (!await tree.validateParentChild(res, afterNote.parentNoteId, noteId)) {
return;
@ -58,13 +58,13 @@ router.put('/:noteId/clone-after/:afterNoteTreeId', auth.checkApiAuth, wrap(asyn
await sql.doInTransaction(async () => {
// we don't change dateModified so other changes are prioritized in case of conflict
// also we would have to sync all those modified note trees otherwise hash checks would fail
await sql.execute("UPDATE note_tree SET notePosition = notePosition + 1 WHERE parentNoteId = ? AND notePosition > ? AND isDeleted = 0",
await sql.execute("UPDATE branches SET notePosition = notePosition + 1 WHERE parentNoteId = ? AND notePosition > ? AND isDeleted = 0",
[afterNote.parentNoteId, afterNote.notePosition]);
await sync_table.addNoteReorderingSync(afterNote.parentNoteId, sourceId);
const noteTree = {
noteTreeId: utils.newNoteTreeId(),
const branch = {
branchId: utils.newBranchId(),
noteId: noteId,
parentNoteId: afterNote.parentNoteId,
notePosition: afterNote.notePosition + 1,
@ -73,9 +73,9 @@ router.put('/:noteId/clone-after/:afterNoteTreeId', auth.checkApiAuth, wrap(asyn
isDeleted: 0
};
await sql.replace("note_tree", noteTree);
await sql.replace("branches", branch);
await sync_table.addNoteTreeSync(noteTree.noteTreeId, sourceId);
await sync_table.addBranchSync(branch.branchId, sourceId);
});
res.send({ success: true });

View File

@ -14,11 +14,11 @@ router.get('/:noteId/', auth.checkApiAuthOrElectron, wrap(async (req, res, next)
const noteId = req.params.noteId;
const repo = new Repository(req);
const noteTreeId = await sql.getValue('SELECT noteTreeId FROM note_tree WHERE noteId = ?', [noteId]);
const branchId = await sql.getValue('SELECT branchId FROM branches WHERE noteId = ?', [noteId]);
const pack = tar.pack();
const name = await exportNote(noteTreeId, '', pack, repo);
const name = await exportNote(branchId, '', pack, repo);
pack.finalize();
@ -28,9 +28,9 @@ router.get('/:noteId/', auth.checkApiAuthOrElectron, wrap(async (req, res, next)
pack.pipe(res);
}));
async function exportNote(noteTreeId, directory, pack, repo) {
const noteTree = await sql.getRow("SELECT * FROM note_tree WHERE noteTreeId = ?", [noteTreeId]);
const note = await repo.getEntity("SELECT notes.* FROM notes WHERE noteId = ?", [noteTree.noteId]);
async function exportNote(branchId, directory, pack, repo) {
const branch = await sql.getRow("SELECT * FROM branches WHERE branchId = ?", [branchId]);
const note = await repo.getEntity("SELECT notes.* FROM notes WHERE noteId = ?", [branch.noteId]);
if (note.isProtected) {
return;
@ -51,11 +51,11 @@ async function exportNote(noteTreeId, directory, pack, repo) {
pack.entry({ name: childFileName + ".dat", size: content.length }, content);
const children = await sql.getRows("SELECT * FROM note_tree WHERE parentNoteId = ? AND isDeleted = 0", [note.noteId]);
const children = await sql.getRows("SELECT * FROM branches WHERE parentNoteId = ? AND isDeleted = 0", [note.noteId]);
if (children.length > 0) {
for (const child of children) {
await exportNote(child.noteTreeId, childFileName + "/", pack, repo);
await exportNote(child.branchId, childFileName + "/", pack, repo);
}
}

View File

@ -48,11 +48,11 @@ router.post('/:parentNoteId/children', auth.checkApiAuth, wrap(async (req, res,
const newNote = req.body;
await sql.doInTransaction(async () => {
const { noteId, noteTreeId, note } = await notes.createNewNote(parentNoteId, newNote, req, sourceId);
const { noteId, branchId, note } = await notes.createNewNote(parentNoteId, newNote, req, sourceId);
res.send({
'noteId': noteId,
'noteTreeId': noteTreeId,
'branchId': branchId,
'note': note
});
});

View File

@ -13,20 +13,20 @@ router.get('', auth.checkApiAuth, wrap(async (req, res, next) => {
res.send(await getRecentNotes());
}));
router.put('/:noteTreeId/:notePath', auth.checkApiAuth, wrap(async (req, res, next) => {
const noteTreeId = req.params.noteTreeId;
router.put('/:branchId/:notePath', auth.checkApiAuth, wrap(async (req, res, next) => {
const branchId = req.params.branchId;
const notePath = req.params.notePath;
const sourceId = req.headers.source_id;
await sql.doInTransaction(async () => {
await sql.replace('recent_notes', {
noteTreeId: noteTreeId,
branchId: branchId,
notePath: notePath,
dateAccessed: utils.nowDate(),
isDeleted: 0
});
await sync_table.addRecentNoteSync(noteTreeId, sourceId);
await sync_table.addRecentNoteSync(branchId, sourceId);
await options.setOption('start_note_path', notePath, sourceId);
});
@ -40,10 +40,10 @@ async function getRecentNotes() {
recent_notes.*
FROM
recent_notes
JOIN note_tree USING(noteTreeId)
JOIN branches USING(branchId)
WHERE
recent_notes.isDeleted = 0
AND note_tree.isDeleted = 0
AND branches.isDeleted = 0
ORDER BY
dateAccessed DESC
LIMIT 200`);

View File

@ -53,9 +53,9 @@ router.post('/force-note-sync/:noteId', auth.checkApiAuth, wrap(async (req, res,
await sql.doInTransaction(async () => {
await sync_table.addNoteSync(noteId);
for (const noteTreeId of await sql.getColumn("SELECT noteTreeId FROM note_tree WHERE isDeleted = 0 AND noteId = ?", [noteId])) {
await sync_table.addNoteTreeSync(noteTreeId);
await sync_table.addRecentNoteSync(noteTreeId);
for (const branchId of await sql.getColumn("SELECT branchId FROM branches WHERE isDeleted = 0 AND noteId = ?", [noteId])) {
await sync_table.addBranchSync(branchId);
await sync_table.addRecentNoteSync(branchId);
}
for (const noteRevisionId of await sql.getColumn("SELECT noteRevisionId FROM note_revisions WHERE noteId = ?", [noteId])) {
@ -88,10 +88,10 @@ router.get('/notes/:noteId', auth.checkApiAuth, wrap(async (req, res, next) => {
});
}));
router.get('/note_tree/:noteTreeId', auth.checkApiAuth, wrap(async (req, res, next) => {
const noteTreeId = req.params.noteTreeId;
router.get('/branches/:branchId', auth.checkApiAuth, wrap(async (req, res, next) => {
const branchId = req.params.branchId;
res.send(await sql.getRow("SELECT * FROM note_tree WHERE noteTreeId = ?", [noteTreeId]));
res.send(await sql.getRow("SELECT * FROM branches WHERE branchId = ?", [branchId]));
}));
router.get('/note_revisions/:noteRevisionId', auth.checkApiAuth, wrap(async (req, res, next) => {
@ -117,14 +117,14 @@ router.get('/note_reordering/:parentNoteId', auth.checkApiAuth, wrap(async (req,
res.send({
parentNoteId: parentNoteId,
ordering: await sql.getMap("SELECT noteTreeId, notePosition FROM note_tree WHERE parentNoteId = ? AND isDeleted = 0", [parentNoteId])
ordering: await sql.getMap("SELECT branchId, notePosition FROM branches WHERE parentNoteId = ? AND isDeleted = 0", [parentNoteId])
});
}));
router.get('/recent_notes/:noteTreeId', auth.checkApiAuth, wrap(async (req, res, next) => {
const noteTreeId = req.params.noteTreeId;
router.get('/recent_notes/:branchId', auth.checkApiAuth, wrap(async (req, res, next) => {
const branchId = req.params.branchId;
res.send(await sql.getRow("SELECT * FROM recent_notes WHERE noteTreeId = ?", [noteTreeId]));
res.send(await sql.getRow("SELECT * FROM recent_notes WHERE branchId = ?", [branchId]));
}));
router.get('/images/:imageId', auth.checkApiAuth, wrap(async (req, res, next) => {
@ -162,8 +162,8 @@ router.put('/notes', auth.checkApiAuth, wrap(async (req, res, next) => {
res.send({});
}));
router.put('/note_tree', auth.checkApiAuth, wrap(async (req, res, next) => {
await syncUpdate.updateNoteTree(req.body.entity, req.body.sourceId);
router.put('/branches', auth.checkApiAuth, wrap(async (req, res, next) => {
await syncUpdate.updateBranch(req.body.entity, req.body.sourceId);
res.send({});
}));

View File

@ -12,16 +12,16 @@ const sync_table = require('../../services/sync_table');
const wrap = require('express-promise-wrap').wrap;
router.get('/', auth.checkApiAuth, wrap(async (req, res, next) => {
const noteTree = await sql.getRows(`
const branches = await sql.getRows(`
SELECT
noteTreeId,
branchId,
noteId,
parentNoteId,
notePosition,
prefix,
isExpanded
FROM
note_tree
branches
WHERE
isDeleted = 0
ORDER BY
@ -60,21 +60,21 @@ router.get('/', auth.checkApiAuth, wrap(async (req, res, next) => {
res.send({
instanceName: config.General ? config.General.instanceName : null,
noteTree: noteTree,
branches: branches,
notes: notes,
start_note_path: await options.getOption('start_note_path')
});
}));
router.put('/:noteTreeId/set-prefix', auth.checkApiAuth, wrap(async (req, res, next) => {
const noteTreeId = req.params.noteTreeId;
router.put('/:branchId/set-prefix', auth.checkApiAuth, wrap(async (req, res, next) => {
const branchId = req.params.branchId;
const sourceId = req.headers.source_id;
const prefix = utils.isEmptyOrWhitespace(req.body.prefix) ? null : req.body.prefix;
await sql.doInTransaction(async () => {
await sql.execute("UPDATE note_tree SET prefix = ?, dateModified = ? WHERE noteTreeId = ?", [prefix, utils.nowDate(), noteTreeId]);
await sql.execute("UPDATE branches SET prefix = ?, dateModified = ? WHERE branchId = ?", [prefix, utils.nowDate(), branchId]);
await sync_table.addNoteTreeSync(noteTreeId, sourceId);
await sync_table.addBranchSync(branchId, sourceId);
});
res.send({});

View File

@ -15,96 +15,96 @@ const wrap = require('express-promise-wrap').wrap;
* for not deleted note trees. There may be multiple deleted note-parent note relationships.
*/
router.put('/:noteTreeId/move-to/:parentNoteId', auth.checkApiAuth, wrap(async (req, res, next) => {
const noteTreeId = req.params.noteTreeId;
router.put('/:branchId/move-to/:parentNoteId', auth.checkApiAuth, wrap(async (req, res, next) => {
const branchId = req.params.branchId;
const parentNoteId = req.params.parentNoteId;
const sourceId = req.headers.source_id;
const noteToMove = await tree.getNoteTree(noteTreeId);
const noteToMove = await tree.getBranch(branchId);
if (!await tree.validateParentChild(res, parentNoteId, noteToMove.noteId, noteTreeId)) {
if (!await tree.validateParentChild(res, parentNoteId, noteToMove.noteId, branchId)) {
return;
}
const maxNotePos = await sql.getValue('SELECT MAX(notePosition) FROM note_tree 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 now = utils.nowDate();
await sql.doInTransaction(async () => {
await sql.execute("UPDATE note_tree SET parentNoteId = ?, notePosition = ?, dateModified = ? WHERE noteTreeId = ?",
[parentNoteId, newNotePos, now, noteTreeId]);
await sql.execute("UPDATE branches SET parentNoteId = ?, notePosition = ?, dateModified = ? WHERE branchId = ?",
[parentNoteId, newNotePos, now, branchId]);
await sync_table.addNoteTreeSync(noteTreeId, sourceId);
await sync_table.addBranchSync(branchId, sourceId);
});
res.send({ success: true });
}));
router.put('/:noteTreeId/move-before/:beforeNoteTreeId', auth.checkApiAuth, wrap(async (req, res, next) => {
const noteTreeId = req.params.noteTreeId;
const beforeNoteTreeId = req.params.beforeNoteTreeId;
router.put('/:branchId/move-before/:beforeBranchId', auth.checkApiAuth, wrap(async (req, res, next) => {
const branchId = req.params.branchId;
const beforeBranchId = req.params.beforeBranchId;
const sourceId = req.headers.source_id;
const noteToMove = await tree.getNoteTree(noteTreeId);
const beforeNote = await tree.getNoteTree(beforeNoteTreeId);
const noteToMove = await tree.getBranch(branchId);
const beforeNote = await tree.getBranch(beforeBranchId);
if (!await tree.validateParentChild(res, beforeNote.parentNoteId, noteToMove.noteId, noteTreeId)) {
if (!await tree.validateParentChild(res, beforeNote.parentNoteId, noteToMove.noteId, branchId)) {
return;
}
await sql.doInTransaction(async () => {
// we don't change dateModified so other changes are prioritized in case of conflict
// also we would have to sync all those modified note trees otherwise hash checks would fail
await sql.execute("UPDATE note_tree SET notePosition = notePosition + 1 WHERE parentNoteId = ? AND notePosition >= ? AND isDeleted = 0",
await sql.execute("UPDATE branches SET notePosition = notePosition + 1 WHERE parentNoteId = ? AND notePosition >= ? AND isDeleted = 0",
[beforeNote.parentNoteId, beforeNote.notePosition]);
await sync_table.addNoteReorderingSync(beforeNote.parentNoteId, sourceId);
await sql.execute("UPDATE note_tree SET parentNoteId = ?, notePosition = ?, dateModified = ? WHERE noteTreeId = ?",
[beforeNote.parentNoteId, beforeNote.notePosition, utils.nowDate(), noteTreeId]);
await sql.execute("UPDATE branches SET parentNoteId = ?, notePosition = ?, dateModified = ? WHERE branchId = ?",
[beforeNote.parentNoteId, beforeNote.notePosition, utils.nowDate(), branchId]);
await sync_table.addNoteTreeSync(noteTreeId, sourceId);
await sync_table.addBranchSync(branchId, sourceId);
});
res.send({ success: true });
}));
router.put('/:noteTreeId/move-after/:afterNoteTreeId', auth.checkApiAuth, wrap(async (req, res, next) => {
const noteTreeId = req.params.noteTreeId;
const afterNoteTreeId = req.params.afterNoteTreeId;
router.put('/:branchId/move-after/:afterBranchId', auth.checkApiAuth, wrap(async (req, res, next) => {
const branchId = req.params.branchId;
const afterBranchId = req.params.afterBranchId;
const sourceId = req.headers.source_id;
const noteToMove = await tree.getNoteTree(noteTreeId);
const afterNote = await tree.getNoteTree(afterNoteTreeId);
const noteToMove = await tree.getBranch(branchId);
const afterNote = await tree.getBranch(afterBranchId);
if (!await tree.validateParentChild(res, afterNote.parentNoteId, noteToMove.noteId, noteTreeId)) {
if (!await tree.validateParentChild(res, afterNote.parentNoteId, noteToMove.noteId, branchId)) {
return;
}
await sql.doInTransaction(async () => {
// we don't change dateModified so other changes are prioritized in case of conflict
// also we would have to sync all those modified note trees otherwise hash checks would fail
await sql.execute("UPDATE note_tree SET notePosition = notePosition + 1 WHERE parentNoteId = ? AND notePosition > ? AND isDeleted = 0",
await sql.execute("UPDATE branches SET notePosition = notePosition + 1 WHERE parentNoteId = ? AND notePosition > ? AND isDeleted = 0",
[afterNote.parentNoteId, afterNote.notePosition]);
await sync_table.addNoteReorderingSync(afterNote.parentNoteId, sourceId);
await sql.execute("UPDATE note_tree SET parentNoteId = ?, notePosition = ?, dateModified = ? WHERE noteTreeId = ?",
[afterNote.parentNoteId, afterNote.notePosition + 1, utils.nowDate(), noteTreeId]);
await sql.execute("UPDATE branches SET parentNoteId = ?, notePosition = ?, dateModified = ? WHERE branchId = ?",
[afterNote.parentNoteId, afterNote.notePosition + 1, utils.nowDate(), branchId]);
await sync_table.addNoteTreeSync(noteTreeId, sourceId);
await sync_table.addBranchSync(branchId, sourceId);
});
res.send({ success: true });
}));
router.put('/:noteTreeId/expanded/:expanded', auth.checkApiAuth, wrap(async (req, res, next) => {
const noteTreeId = req.params.noteTreeId;
router.put('/:branchId/expanded/:expanded', auth.checkApiAuth, wrap(async (req, res, next) => {
const branchId = req.params.branchId;
const expanded = req.params.expanded;
await sql.doInTransaction(async () => {
await sql.execute("UPDATE note_tree SET isExpanded = ? WHERE noteTreeId = ?", [expanded, noteTreeId]);
await sql.execute("UPDATE branches SET isExpanded = ? WHERE branchId = ?", [expanded, branchId]);
// we don't sync expanded attribute
});
@ -112,9 +112,9 @@ router.put('/:noteTreeId/expanded/:expanded', auth.checkApiAuth, wrap(async (req
res.send({});
}));
router.delete('/:noteTreeId', auth.checkApiAuth, wrap(async (req, res, next) => {
router.delete('/:branchId', auth.checkApiAuth, wrap(async (req, res, next) => {
await sql.doInTransaction(async () => {
await notes.deleteNote(req.params.noteTreeId, req.headers.source_id);
await notes.deleteNote(req.params.branchId, req.headers.source_id);
});
res.send({});

View File

@ -18,7 +18,7 @@ async function anonymize() {
await db.run("UPDATE notes SET title = 'title', content = 'text'");
await db.run("UPDATE note_revisions SET title = 'title', content = 'text'");
await db.run("UPDATE note_tree SET prefix = 'prefix' WHERE prefix IS NOT NULL");
await db.run("UPDATE branches SET prefix = 'prefix' WHERE prefix IS NOT NULL");
await db.run(`UPDATE options SET value = 'anonymized' WHERE name IN
('document_secret', 'encrypted_data_key', 'password_verification_hash',
'password_verification_salt', 'password_derived_key_salt')`);

View File

@ -3,7 +3,7 @@
const build = require('./build');
const packageJson = require('../../package');
const APP_DB_VERSION = 78;
const APP_DB_VERSION = 79;
module.exports = {
app_version: packageJson.version,

View File

@ -23,7 +23,7 @@ async function runCheck(query, errorText, errorList) {
async function checkTreeCycles(errorList) {
const childToParents = {};
const rows = await sql.getRows("SELECT noteId, parentNoteId FROM note_tree WHERE isDeleted = 0");
const rows = await sql.getRows("SELECT noteId, parentNoteId FROM branches WHERE isDeleted = 0");
for (const row of rows) {
const childNoteId = row.noteId;
@ -92,17 +92,17 @@ async function runAllChecks() {
noteId
FROM
notes
LEFT JOIN note_tree USING(noteId)
LEFT JOIN branches USING(noteId)
WHERE
noteId != 'root'
AND note_tree.noteTreeId IS NULL`,
"Missing note_tree records for following note IDs", errorList);
AND branches.branchId IS NULL`,
"Missing branches records for following note IDs", errorList);
await runCheck(`
SELECT
noteTreeId || ' > ' || note_tree.noteId
branchId || ' > ' || branches.noteId
FROM
note_tree
branches
LEFT JOIN notes USING(noteId)
WHERE
notes.noteId IS NULL`,
@ -110,24 +110,24 @@ async function runAllChecks() {
await runCheck(`
SELECT
noteTreeId
branchId
FROM
note_tree
branches
JOIN notes USING(noteId)
WHERE
notes.isDeleted = 1
AND note_tree.isDeleted = 0`,
AND branches.isDeleted = 0`,
"Note tree is not deleted even though main note is deleted for following note tree IDs", errorList);
await runCheck(`
SELECT
child.noteTreeId
child.branchId
FROM
note_tree AS child
branches AS child
WHERE
child.isDeleted = 0
AND child.parentNoteId != 'root'
AND (SELECT COUNT(*) FROM note_tree AS parent WHERE parent.noteId = child.parentNoteId
AND (SELECT COUNT(*) FROM branches AS parent WHERE parent.noteId = child.parentNoteId
AND parent.isDeleted = 0) = 0`,
"All parent note trees are deleted but child note tree is not for these child note tree IDs", errorList);
@ -137,18 +137,18 @@ async function runAllChecks() {
DISTINCT noteId
FROM
notes
JOIN note_tree USING(noteId)
JOIN branches USING(noteId)
WHERE
(SELECT COUNT(*) FROM note_tree WHERE notes.noteId = note_tree.noteId AND note_tree.isDeleted = 0) = 0
(SELECT COUNT(*) FROM branches WHERE notes.noteId = branches.noteId AND branches.isDeleted = 0) = 0
AND notes.isDeleted = 0
`, 'No undeleted note trees for note IDs', errorList);
await runCheck(`
SELECT
child.parentNoteId || ' > ' || child.noteId
FROM note_tree
FROM branches
AS child
LEFT JOIN note_tree AS parent ON parent.noteId = child.parentNoteId
LEFT JOIN branches AS parent ON parent.noteId = child.parentNoteId
WHERE
parent.noteId IS NULL
AND child.parentNoteId != 'root'`,
@ -165,14 +165,14 @@ async function runAllChecks() {
await runCheck(`
SELECT
note_tree.parentNoteId || ' > ' || note_tree.noteId
branches.parentNoteId || ' > ' || branches.noteId
FROM
note_tree
branches
WHERE
note_tree.isDeleted = 0
branches.isDeleted = 0
GROUP BY
note_tree.parentNoteId,
note_tree.noteId
branches.parentNoteId,
branches.noteId
HAVING
COUNT(*) > 1`,
"Duplicate undeleted parent note <-> note relationship - parent note ID > note ID", errorList);
@ -221,16 +221,16 @@ async function runAllChecks() {
SELECT
parentNoteId
FROM
note_tree
JOIN notes ON notes.noteId = note_tree.parentNoteId
branches
JOIN notes ON notes.noteId = branches.parentNoteId
WHERE
type == 'search'`,
"Search note has children", errorList);
await runSyncRowChecks("notes", "noteId", errorList);
await runSyncRowChecks("note_revisions", "noteRevisionId", errorList);
await runSyncRowChecks("note_tree", "noteTreeId", errorList);
await runSyncRowChecks("recent_notes", "noteTreeId", errorList);
await runSyncRowChecks("branches", "branchId", errorList);
await runSyncRowChecks("recent_notes", "branchId", errorList);
await runSyncRowChecks("images", "imageId", errorList);
await runSyncRowChecks("note_images", "noteImageId", errorList);
await runSyncRowChecks("attributes", "attributeId", errorList);

View File

@ -29,17 +29,17 @@ async function getHashes() {
FROM notes
ORDER BY noteId`)),
note_tree: getHash(await sql.getRows(`
branches: getHash(await sql.getRows(`
SELECT
noteTreeId,
branchId,
noteId,
parentNoteId,
notePosition,
dateModified,
isDeleted,
prefix
FROM note_tree
ORDER BY noteTreeId`)),
FROM branches
ORDER BY branchId`)),
note_revisions: getHash(await sql.getRows(`
SELECT
@ -54,7 +54,7 @@ async function getHashes() {
recent_notes: getHash(await sql.getRows(`
SELECT
noteTreeId,
branchId,
notePath,
dateAccessed,
isDeleted

View File

@ -23,10 +23,10 @@ async function createNote(parentNoteId, noteTitle, noteText) {
}
async function getNoteStartingWith(parentNoteId, startsWith) {
return await sql.getValue(`SELECT noteId FROM notes JOIN note_tree USING(noteId)
return await sql.getValue(`SELECT noteId FROM notes JOIN branches USING(noteId)
WHERE parentNoteId = ? AND title LIKE '${startsWith}%'
AND notes.isDeleted = 0 AND isProtected = 0
AND note_tree.isDeleted = 0`, [parentNoteId]);
AND branches.isDeleted = 0`, [parentNoteId]);
}
async function getRootCalendarNoteId() {

View File

@ -7,22 +7,22 @@ const protected_session = require('./protected_session');
async function createNewNote(parentNoteId, noteOpts, dataKey, sourceId) {
const noteId = utils.newNoteId();
const noteTreeId = utils.newNoteTreeId();
const branchId = utils.newBranchId();
let newNotePos = 0;
if (noteOpts.target === 'into') {
const maxNotePos = await sql.getValue('SELECT MAX(notePosition) FROM note_tree 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;
}
else if (noteOpts.target === 'after') {
const afterNote = await sql.getRow('SELECT notePosition FROM note_tree WHERE noteTreeId = ?', [noteOpts.target_noteTreeId]);
const afterNote = await sql.getRow('SELECT notePosition FROM branches WHERE branchId = ?', [noteOpts.target_branchId]);
newNotePos = afterNote.notePosition + 1;
// not updating dateModified to avoig having to sync whole rows
await sql.execute('UPDATE note_tree SET notePosition = notePosition + 1 WHERE parentNoteId = ? AND notePosition > ? AND isDeleted = 0',
await sql.execute('UPDATE branches SET notePosition = notePosition + 1 WHERE parentNoteId = ? AND notePosition > ? AND isDeleted = 0',
[parentNoteId, afterNote.notePosition]);
await sync_table.addNoteReorderingSync(parentNoteId, sourceId);
@ -64,8 +64,8 @@ async function createNewNote(parentNoteId, noteOpts, dataKey, sourceId) {
await sync_table.addNoteSync(noteId, sourceId);
await sql.insert("note_tree", {
noteTreeId: noteTreeId,
await sql.insert("branches", {
branchId: branchId,
noteId: noteId,
parentNoteId: parentNoteId,
notePosition: newNotePos,
@ -74,11 +74,11 @@ async function createNewNote(parentNoteId, noteOpts, dataKey, sourceId) {
isDeleted: 0
});
await sync_table.addNoteTreeSync(noteTreeId, sourceId);
await sync_table.addBranchSync(branchId, sourceId);
return {
noteId,
noteTreeId,
branchId,
note
};
}
@ -122,7 +122,7 @@ async function protectNoteRecursively(noteId, dataKey, protect, sourceId) {
await protectNote(note, dataKey, protect, sourceId);
const children = await sql.getColumn("SELECT noteId FROM note_tree WHERE parentNoteId = ? AND isDeleted = 0", [noteId]);
const children = await sql.getColumn("SELECT noteId FROM branches WHERE parentNoteId = ? AND isDeleted = 0", [noteId]);
for (const childNoteId of children) {
await protectNoteRecursively(childNoteId, dataKey, protect, sourceId);
@ -311,30 +311,30 @@ async function updateNote(noteId, newNote, dataKey, sourceId) {
});
}
async function deleteNote(noteTreeId, sourceId) {
const noteTree = await sql.getRowOrNull("SELECT * FROM note_tree WHERE noteTreeId = ?", [noteTreeId]);
async function deleteNote(branchId, sourceId) {
const branch = await sql.getRowOrNull("SELECT * FROM branches WHERE branchId = ?", [branchId]);
if (!noteTree || noteTree.isDeleted === 1) {
if (!branch || branch.isDeleted === 1) {
return;
}
const now = utils.nowDate();
await sql.execute("UPDATE note_tree SET isDeleted = 1, dateModified = ? WHERE noteTreeId = ?", [now, noteTreeId]);
await sync_table.addNoteTreeSync(noteTreeId, sourceId);
await sql.execute("UPDATE branches SET isDeleted = 1, dateModified = ? WHERE branchId = ?", [now, branchId]);
await sync_table.addBranchSync(branchId, sourceId);
const noteId = await sql.getValue("SELECT noteId FROM note_tree WHERE noteTreeId = ?", [noteTreeId]);
const noteId = await sql.getValue("SELECT noteId FROM branches WHERE branchId = ?", [branchId]);
const notDeletedNoteTreesCount = await sql.getValue("SELECT COUNT(*) FROM note_tree WHERE noteId = ? AND isDeleted = 0", [noteId]);
const notDeletedBranchsCount = await sql.getValue("SELECT COUNT(*) FROM branches WHERE noteId = ? AND isDeleted = 0", [noteId]);
if (!notDeletedNoteTreesCount) {
if (!notDeletedBranchsCount) {
await sql.execute("UPDATE notes SET isDeleted = 1, dateModified = ? WHERE noteId = ?", [now, noteId]);
await sync_table.addNoteSync(noteId, sourceId);
const children = await sql.getRows("SELECT noteTreeId FROM note_tree WHERE parentNoteId = ? AND isDeleted = 0", [noteId]);
const children = await sql.getRows("SELECT branchId FROM branches WHERE parentNoteId = ? AND isDeleted = 0", [noteId]);
for (const child of children) {
await deleteNote(child.noteTreeId, sourceId);
await deleteNote(child.branchId, sourceId);
}
}
}

View File

@ -2,7 +2,7 @@ const sql = require('./sql');
const protected_session = require('./protected_session');
const Note = require('../entities/note');
const NoteRevision = require('../entities/note_revision');
const NoteTree = require('../entities/note_tree');
const Branch = require('../entities/branch');
const Attribute = require('../entities/attribute');
const sync_table = require('../services/sync_table');
@ -46,8 +46,8 @@ class Repository {
else if (row.noteRevisionId) {
entity = new NoteRevision(this, row);
}
else if (row.noteTreeId) {
entity = new NoteTree(this, row);
else if (row.branchId) {
entity = new Branch(this, row);
}
else if (row.noteId) {
entity = new Note(this, row);

View File

@ -30,7 +30,7 @@ const dbReady = new Promise((resolve, reject) => {
const schema = fs.readFileSync(resource_dir.DB_INIT_DIR + '/schema.sql', 'UTF-8');
const notesSql = fs.readFileSync(resource_dir.DB_INIT_DIR + '/main_notes.sql', 'UTF-8');
const notesTreeSql = fs.readFileSync(resource_dir.DB_INIT_DIR + '/main_note_tree.sql', 'UTF-8');
const notesTreeSql = fs.readFileSync(resource_dir.DB_INIT_DIR + '/main_branches.sql', 'UTF-8');
const imagesSql = fs.readFileSync(resource_dir.DB_INIT_DIR + '/main_images.sql', 'UTF-8');
const notesImageSql = fs.readFileSync(resource_dir.DB_INIT_DIR + '/main_note_images.sql', 'UTF-8');
@ -41,7 +41,7 @@ const dbReady = new Promise((resolve, reject) => {
await executeScript(imagesSql);
await executeScript(notesImageSql);
const startNoteId = await getValue("SELECT noteId FROM note_tree WHERE parentNoteId = 'root' AND isDeleted = 0 ORDER BY notePosition");
const startNoteId = await getValue("SELECT noteId FROM branches WHERE parentNoteId = 'root' AND isDeleted = 0 ORDER BY notePosition");
await require('./options').initOptions(startNoteId);
await require('./sync_table').fillAllSyncRows();

View File

@ -125,8 +125,8 @@ async function pullSync(syncContext) {
else if (sync.entityName === 'notes') {
await syncUpdate.updateNote(resp.entity, syncContext.sourceId);
}
else if (sync.entityName === 'note_tree') {
await syncUpdate.updateNoteTree(resp, syncContext.sourceId);
else if (sync.entityName === 'branches') {
await syncUpdate.updateBranch(resp, syncContext.sourceId);
}
else if (sync.entityName === 'note_revisions') {
await syncUpdate.updateNoteHistory(resp, syncContext.sourceId);
@ -207,8 +207,8 @@ async function pushEntity(sync, syncContext) {
serializeNoteContentBuffer(entity);
}
else if (sync.entityName === 'note_tree') {
entity = await sql.getRow('SELECT * FROM note_tree WHERE noteTreeId = ?', [sync.entityId]);
else if (sync.entityName === 'branches') {
entity = await sql.getRow('SELECT * FROM branches WHERE branchId = ?', [sync.entityId]);
}
else if (sync.entityName === 'note_revisions') {
entity = await sql.getRow('SELECT * FROM note_revisions WHERE noteRevisionId = ?', [sync.entityId]);
@ -216,14 +216,14 @@ async function pushEntity(sync, syncContext) {
else if (sync.entityName === 'note_reordering') {
entity = {
parentNoteId: sync.entityId,
ordering: await sql.getMap('SELECT noteTreeId, notePosition FROM note_tree WHERE parentNoteId = ? AND isDeleted = 0', [sync.entityId])
ordering: await sql.getMap('SELECT branchId, notePosition FROM branches WHERE parentNoteId = ? AND isDeleted = 0', [sync.entityId])
};
}
else if (sync.entityName === 'options') {
entity = await sql.getRow('SELECT * FROM options WHERE name = ?', [sync.entityId]);
}
else if (sync.entityName === 'recent_notes') {
entity = await sql.getRow('SELECT * FROM recent_notes WHERE noteTreeId = ?', [sync.entityId]);
entity = await sql.getRow('SELECT * FROM recent_notes WHERE branchId = ?', [sync.entityId]);
}
else if (sync.entityName === 'images') {
entity = await sql.getRow('SELECT * FROM images WHERE imageId = ?', [sync.entityId]);

View File

@ -8,8 +8,8 @@ async function addNoteSync(noteId, sourceId) {
await addEntitySync("notes", noteId, sourceId)
}
async function addNoteTreeSync(noteTreeId, sourceId) {
await addEntitySync("note_tree", noteTreeId, sourceId)
async function addBranchSync(branchId, sourceId) {
await addEntitySync("branches", branchId, sourceId)
}
async function addNoteReorderingSync(parentNoteId, sourceId) {
@ -24,8 +24,8 @@ async function addOptionsSync(name, sourceId) {
await addEntitySync("options", name, sourceId);
}
async function addRecentNoteSync(noteTreeId, sourceId) {
await addEntitySync("recent_notes", noteTreeId, sourceId);
async function addRecentNoteSync(branchId, sourceId) {
await addEntitySync("recent_notes", branchId, sourceId);
}
async function addImageSync(imageId, sourceId) {
@ -91,9 +91,9 @@ async function fillSyncRows(entityName, entityKey) {
async function fillAllSyncRows() {
await fillSyncRows("notes", "noteId");
await fillSyncRows("note_tree", "noteTreeId");
await fillSyncRows("branches", "branchId");
await fillSyncRows("note_revisions", "noteRevisionId");
await fillSyncRows("recent_notes", "noteTreeId");
await fillSyncRows("recent_notes", "branchId");
await fillSyncRows("images", "imageId");
await fillSyncRows("note_images", "noteImageId");
await fillSyncRows("attributes", "attributeId");
@ -102,7 +102,7 @@ async function fillAllSyncRows() {
module.exports = {
addNoteSync,
addNoteTreeSync,
addBranchSync,
addNoteReorderingSync,
addNoteHistorySync,
addOptionsSync,

View File

@ -26,18 +26,18 @@ async function updateNote(entity, sourceId) {
}
}
async function updateNoteTree(entity, sourceId) {
const orig = await sql.getRowOrNull("SELECT * FROM note_tree WHERE noteTreeId = ?", [entity.noteTreeId]);
async function updateBranch(entity, sourceId) {
const orig = await sql.getRowOrNull("SELECT * FROM branches WHERE branchId = ?", [entity.branchId]);
await sql.doInTransaction(async () => {
if (orig === null || orig.dateModified < entity.dateModified) {
delete entity.isExpanded;
await sql.replace('note_tree', entity);
await sql.replace('branches', entity);
await sync_table.addNoteTreeSync(entity.noteTreeId, sourceId);
await sync_table.addBranchSync(entity.branchId, sourceId);
log.info("Update/sync note tree " + entity.noteTreeId);
log.info("Update/sync note tree " + entity.branchId);
}
});
}
@ -61,7 +61,7 @@ async function updateNoteHistory(entity, sourceId) {
async function updateNoteReordering(entity, sourceId) {
await sql.doInTransaction(async () => {
Object.keys(entity.ordering).forEach(async key => {
await sql.execute("UPDATE note_tree SET notePosition = ? WHERE noteTreeId = ?", [entity.ordering[key], key]);
await sql.execute("UPDATE branches SET notePosition = ? WHERE branchId = ?", [entity.ordering[key], key]);
});
await sync_table.addNoteReorderingSync(entity.parentNoteId, sourceId);
@ -87,13 +87,13 @@ async function updateOptions(entity, sourceId) {
}
async function updateRecentNotes(entity, sourceId) {
const orig = await sql.getRowOrNull("SELECT * FROM recent_notes WHERE noteTreeId = ?", [entity.noteTreeId]);
const orig = await sql.getRowOrNull("SELECT * FROM recent_notes WHERE branchId = ?", [entity.branchId]);
if (orig === null || orig.dateAccessed < entity.dateAccessed) {
await sql.doInTransaction(async () => {
await sql.replace('recent_notes', entity);
await sync_table.addRecentNoteSync(entity.noteTreeId, sourceId);
await sync_table.addRecentNoteSync(entity.branchId, sourceId);
});
}
}
@ -160,7 +160,7 @@ async function updateApiToken(entity, sourceId) {
module.exports = {
updateNote,
updateNoteTree,
updateBranch,
updateNoteHistory,
updateNoteReordering,
updateOptions,

View File

@ -4,10 +4,10 @@ const sql = require('./sql');
const sync_table = require('./sync_table');
const protected_session = require('./protected_session');
async function validateParentChild(res, parentNoteId, childNoteId, noteTreeId = null) {
const existing = await getExistingNoteTree(parentNoteId, childNoteId);
async function validateParentChild(res, parentNoteId, childNoteId, branchId = null) {
const existing = await getExistingBranch(parentNoteId, childNoteId);
if (existing && (noteTreeId === null || existing.noteTreeId !== noteTreeId)) {
if (existing && (branchId === null || existing.branchId !== branchId)) {
res.send({
success: false,
message: 'This note already exists in the target.'
@ -28,8 +28,8 @@ async function validateParentChild(res, parentNoteId, childNoteId, noteTreeId =
return true;
}
async function getExistingNoteTree(parentNoteId, childNoteId) {
return await sql.getRow('SELECT * FROM note_tree WHERE noteId = ? AND parentNoteId = ? AND isDeleted = 0', [childNoteId, parentNoteId]);
async function getExistingBranch(parentNoteId, childNoteId) {
return await sql.getRow('SELECT * FROM branches WHERE noteId = ? AND parentNoteId = ? AND isDeleted = 0', [childNoteId, parentNoteId]);
}
/**
@ -52,7 +52,7 @@ async function checkTreeCycle(parentNoteId, childNoteId) {
return false;
}
const parentNoteIds = await sql.getColumn("SELECT DISTINCT parentNoteId FROM note_tree WHERE noteId = ? AND isDeleted = 0", [parentNoteId]);
const parentNoteIds = await sql.getColumn("SELECT DISTINCT parentNoteId FROM branches WHERE noteId = ? AND isDeleted = 0", [parentNoteId]);
for (const pid of parentNoteIds) {
if (!await checkTreeCycleInner(pid)) {
@ -66,14 +66,14 @@ async function checkTreeCycle(parentNoteId, childNoteId) {
return await checkTreeCycleInner(parentNoteId);
}
async function getNoteTree(noteTreeId) {
return sql.getRow("SELECT * FROM note_tree WHERE noteTreeId = ?", [noteTreeId]);
async function getBranch(branchId) {
return sql.getRow("SELECT * FROM branches WHERE branchId = ?", [branchId]);
}
async function loadSubTreeNoteIds(parentNoteId, subTreeNoteIds) {
subTreeNoteIds.push(parentNoteId);
const children = await sql.getColumn("SELECT noteId FROM note_tree WHERE parentNoteId = ? AND isDeleted = 0", [parentNoteId]);
const children = await sql.getColumn("SELECT noteId FROM branches WHERE parentNoteId = ? AND isDeleted = 0", [parentNoteId]);
for (const childNoteId of children) {
await loadSubTreeNoteIds(childNoteId, subTreeNoteIds);
@ -82,9 +82,9 @@ async function loadSubTreeNoteIds(parentNoteId, subTreeNoteIds) {
async function sortNotesAlphabetically(parentNoteId, req, sourceId) {
await sql.doInTransaction(async () => {
const notes = await sql.getRows(`SELECT noteTreeId, noteId, title, isProtected
FROM notes JOIN note_tree USING(noteId)
WHERE note_tree.isDeleted = 0 AND parentNoteId = ?`, [parentNoteId]);
const notes = await sql.getRows(`SELECT branchId, noteId, title, isProtected
FROM notes JOIN branches USING(noteId)
WHERE branches.isDeleted = 0 AND parentNoteId = ?`, [parentNoteId]);
protected_session.decryptNotes(req, notes);
@ -93,8 +93,8 @@ async function sortNotesAlphabetically(parentNoteId, req, sourceId) {
let position = 1;
for (const note of notes) {
await sql.execute("UPDATE note_tree SET notePosition = ? WHERE noteTreeId = ?",
[position, note.noteTreeId]);
await sql.execute("UPDATE branches SET notePosition = ? WHERE branchId = ?",
[position, note.branchId]);
position++;
}
@ -105,6 +105,6 @@ async function sortNotesAlphabetically(parentNoteId, req, sourceId) {
module.exports = {
validateParentChild,
getNoteTree,
getBranch,
sortNotesAlphabetically
};

View File

@ -8,7 +8,7 @@ function newNoteId() {
return randomString(12);
}
function newNoteTreeId() {
function newBranchId() {
return randomString(12);
}
@ -155,7 +155,7 @@ module.exports = {
parseDate,
parseDateTime,
newNoteId,
newNoteTreeId,
newBranchId,
newNoteRevisionId,
newImageId,
newNoteImageId,