2018-03-25 13:02:39 -04:00
|
|
|
import Branch from "../entities/branch.js";
|
|
|
|
import NoteShort from "../entities/note_short.js";
|
2019-08-26 20:21:43 +02:00
|
|
|
import ws from "./ws.js";
|
2018-04-16 20:40:18 -04:00
|
|
|
import server from "./server.js";
|
2018-03-25 12:29:00 -04:00
|
|
|
|
2019-04-14 18:32:56 +02:00
|
|
|
/**
|
|
|
|
* TreeCache keeps a read only cache of note tree structure in frontend's memory.
|
|
|
|
*/
|
2018-03-25 12:29:00 -04:00
|
|
|
class TreeCache {
|
2018-08-16 23:00:04 +02:00
|
|
|
constructor() {
|
|
|
|
this.init();
|
|
|
|
}
|
|
|
|
|
|
|
|
init() {
|
2018-03-25 12:29:00 -04:00
|
|
|
/** @type {Object.<string, NoteShort>} */
|
|
|
|
this.notes = {};
|
2018-04-16 20:40:18 -04:00
|
|
|
|
|
|
|
/** @type {Object.<string, Branch>} */
|
|
|
|
this.branches = {};
|
|
|
|
}
|
|
|
|
|
2019-10-25 21:47:14 +02:00
|
|
|
load(noteRows, branchRows) {
|
|
|
|
this.init();
|
|
|
|
|
|
|
|
this.addResp(noteRows, branchRows);
|
|
|
|
}
|
|
|
|
|
|
|
|
addResp(noteRows, branchRows) {
|
2019-10-26 09:51:08 +02:00
|
|
|
const branchesByNotes = {};
|
2018-03-25 12:29:00 -04:00
|
|
|
|
|
|
|
for (const branchRow of branchRows) {
|
|
|
|
const branch = new Branch(this, branchRow);
|
|
|
|
|
2019-10-26 09:51:08 +02:00
|
|
|
branchesByNotes[branch.noteId] = branchesByNotes[branch.noteId] || [];
|
|
|
|
branchesByNotes[branch.noteId].push(branch);
|
|
|
|
|
|
|
|
branchesByNotes[branch.parentNoteId] = branchesByNotes[branch.parentNoteId] || [];
|
|
|
|
branchesByNotes[branch.parentNoteId].push(branch);
|
2018-03-25 12:29:00 -04:00
|
|
|
}
|
|
|
|
|
2019-10-26 09:51:08 +02:00
|
|
|
for (const noteRow of noteRows) {
|
|
|
|
const {noteId} = noteRow;
|
|
|
|
|
|
|
|
const oldNote = this.notes[noteId];
|
|
|
|
|
|
|
|
if (oldNote) {
|
|
|
|
for (const childNoteId of oldNote.children) {
|
|
|
|
const childNote = this.notes[childNoteId];
|
|
|
|
|
|
|
|
if (childNote) {
|
|
|
|
childNote.parents = childNote.parents.filter(p => p !== noteId);
|
|
|
|
|
|
|
|
const branchId = childNote.parentToBranch[noteId];
|
|
|
|
|
|
|
|
if (branchId in this.branches) {
|
|
|
|
delete this.branches[branchId];
|
|
|
|
}
|
|
|
|
|
|
|
|
delete childNote.parentToBranch[noteId];
|
|
|
|
}
|
|
|
|
}
|
2019-04-13 22:10:16 +02:00
|
|
|
|
2019-10-26 09:51:08 +02:00
|
|
|
for (const parentNoteId of oldNote.parents) {
|
|
|
|
const parentNote = this.notes[parentNoteId];
|
2019-04-13 22:10:16 +02:00
|
|
|
|
2019-10-26 09:51:08 +02:00
|
|
|
if (parentNote) {
|
|
|
|
parentNote.children = parentNote.children.filter(p => p !== noteId);
|
2019-04-13 22:10:16 +02:00
|
|
|
|
2019-10-26 09:51:08 +02:00
|
|
|
const branchId = parentNote.childToBranch[noteId];
|
|
|
|
|
|
|
|
if (branchId in this.branches) {
|
|
|
|
delete this.branches[branchId];
|
|
|
|
}
|
|
|
|
|
|
|
|
delete parentNote.childToBranch[noteId];
|
|
|
|
}
|
|
|
|
}
|
2019-10-20 12:29:34 +02:00
|
|
|
}
|
2019-04-13 22:10:16 +02:00
|
|
|
|
2019-10-26 22:50:46 +02:00
|
|
|
for (const branch of branchesByNotes[noteId] || []) { // can be empty for deleted notes
|
2019-10-26 20:48:56 +02:00
|
|
|
this.addBranch(branch);
|
|
|
|
}
|
|
|
|
|
2019-10-26 22:50:46 +02:00
|
|
|
const note = new NoteShort(this, noteRow, branchesByNotes[noteId] || []);
|
2019-04-13 22:10:16 +02:00
|
|
|
|
2019-10-26 09:51:08 +02:00
|
|
|
this.notes[note.noteId] = note;
|
2019-04-13 22:10:16 +02:00
|
|
|
|
2019-10-26 09:51:08 +02:00
|
|
|
for (const childNoteId of note.children) {
|
|
|
|
const childNote = this.notes[childNoteId];
|
2019-04-13 22:10:16 +02:00
|
|
|
|
2019-10-26 09:51:08 +02:00
|
|
|
if (childNote) {
|
|
|
|
childNote.addParent(noteId, note.childToBranch[childNoteId]);
|
|
|
|
}
|
|
|
|
}
|
2019-04-13 22:56:45 +02:00
|
|
|
|
2019-10-26 09:51:08 +02:00
|
|
|
for (const parentNoteId of note.parents) {
|
|
|
|
const parentNote = this.notes[parentNoteId];
|
2019-04-13 22:56:45 +02:00
|
|
|
|
2019-10-26 09:51:08 +02:00
|
|
|
if (parentNote) {
|
|
|
|
parentNote.addChild(noteId, note.parentToBranch[parentNoteId]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async reloadNotes(noteIds) {
|
|
|
|
const resp = await server.post('tree/load', { noteIds });
|
|
|
|
|
|
|
|
this.addResp(resp.notes, resp.branches);
|
2019-04-13 22:56:45 +02:00
|
|
|
}
|
|
|
|
|
2019-04-13 22:10:16 +02:00
|
|
|
/** @return {Promise<NoteShort[]>} */
|
2018-08-16 23:00:04 +02:00
|
|
|
async getNotes(noteIds, silentNotFoundError = false) {
|
2018-04-16 23:13:33 -04:00
|
|
|
const missingNoteIds = noteIds.filter(noteId => this.notes[noteId] === undefined);
|
2018-04-16 20:40:18 -04:00
|
|
|
|
2018-04-16 23:13:33 -04:00
|
|
|
if (missingNoteIds.length > 0) {
|
|
|
|
const resp = await server.post('tree/load', { noteIds: missingNoteIds });
|
2018-04-16 20:40:18 -04:00
|
|
|
|
2019-10-25 21:47:14 +02:00
|
|
|
this.addResp(resp.notes, resp.branches);
|
2018-04-16 20:40:18 -04:00
|
|
|
}
|
|
|
|
|
2018-04-16 23:13:33 -04:00
|
|
|
return noteIds.map(noteId => {
|
2018-08-16 23:00:04 +02:00
|
|
|
if (!this.notes[noteId] && !silentNotFoundError) {
|
2019-08-26 20:21:43 +02:00
|
|
|
ws.logError(`Can't find note "${noteId}"`);
|
2018-08-06 11:30:37 +02:00
|
|
|
|
2018-08-12 12:59:38 +02:00
|
|
|
return null;
|
2018-04-16 23:13:33 -04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
return this.notes[noteId];
|
|
|
|
}
|
2018-08-12 12:59:38 +02:00
|
|
|
}).filter(note => note !== null);
|
2018-04-16 23:13:33 -04:00
|
|
|
}
|
|
|
|
|
2019-04-13 22:10:16 +02:00
|
|
|
/** @return {Promise<boolean>} */
|
|
|
|
async noteExists(noteId) {
|
|
|
|
const notes = await this.getNotes([noteId], true);
|
|
|
|
|
|
|
|
return notes.length === 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @return {Promise<NoteShort>} */
|
2019-09-08 11:25:57 +02:00
|
|
|
async getNote(noteId, silentNotFoundError = false) {
|
2018-05-26 16:16:34 -04:00
|
|
|
if (noteId === 'none') {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2019-09-08 11:25:57 +02:00
|
|
|
return (await this.getNotes([noteId], silentNotFoundError))[0];
|
2018-03-25 12:29:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
addBranch(branch) {
|
|
|
|
this.branches[branch.branchId] = branch;
|
|
|
|
}
|
|
|
|
|
2019-10-26 09:58:00 +02:00
|
|
|
getBranches(branchIds) {
|
|
|
|
return branchIds
|
|
|
|
.map(branchId => this.getBranch(branchId))
|
|
|
|
.filter(b => b !== null);
|
|
|
|
}
|
2018-04-16 20:40:18 -04:00
|
|
|
|
2019-10-26 09:58:00 +02:00
|
|
|
/** @return {Branch} */
|
2019-10-26 22:50:46 +02:00
|
|
|
getBranch(branchId, silentNotFoundError = false) {
|
2019-10-26 09:58:00 +02:00
|
|
|
if (!(branchId in this.branches)) {
|
2019-10-26 22:50:46 +02:00
|
|
|
if (!silentNotFoundError) {
|
|
|
|
console.error(`Not existing branch ${branchId}`);
|
|
|
|
}
|
2018-04-16 20:40:18 -04:00
|
|
|
}
|
2019-10-26 20:48:56 +02:00
|
|
|
else {
|
|
|
|
return this.branches[branchId];
|
|
|
|
}
|
2018-03-25 12:29:00 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const treeCache = new TreeCache();
|
|
|
|
|
|
|
|
export default treeCache;
|