| 
									
										
										
										
											2018-03-25 13:02:39 -04:00
										 |  |  | import Branch from "../entities/branch.js"; | 
					
						
							|  |  |  | import NoteShort from "../entities/note_short.js"; | 
					
						
							| 
									
										
										
										
											2020-01-25 11:52:45 +01:00
										 |  |  | import Attribute from "../entities/attribute.js"; | 
					
						
							| 
									
										
										
										
											2020-01-25 13:46:55 +01:00
										 |  |  | import server from "./server.js"; | 
					
						
							| 
									
										
										
										
											2020-01-27 22:58:03 +01:00
										 |  |  | import {LoadResults} from "./load_results.js"; | 
					
						
							| 
									
										
										
										
											2020-02-01 18:29:18 +01:00
										 |  |  | import NoteComplement from "../entities/note_complement.js"; | 
					
						
							| 
									
										
										
										
											2020-02-01 22:29:32 +01:00
										 |  |  | import appContext from "./app_context.js"; | 
					
						
							| 
									
										
										
										
											2020-02-05 22:08:45 +01:00
										 |  |  | import options from "./options.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. | 
					
						
							| 
									
										
										
										
											2019-10-27 19:17:32 +01:00
										 |  |  |  * - notes are loaded lazily when unknown noteId is requested | 
					
						
							|  |  |  |  * - when note is loaded, all its parent and child branches are loaded as well. For a branch to be used, it's not must be loaded before | 
					
						
							|  |  |  |  * - deleted notes are present in the cache as well, but they don't have any branches. As a result check for deleted branch is done by presence check - if the branch is not there even though the corresponding note has been loaded, we can infer it is deleted. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Note and branch deletions are corner cases and usually not needed. | 
					
						
							| 
									
										
										
										
											2019-04-14 18:32:56 +02:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-03-25 12:29:00 -04:00
										 |  |  | class TreeCache { | 
					
						
							| 
									
										
										
										
											2018-08-16 23:00:04 +02:00
										 |  |  |     constructor() { | 
					
						
							| 
									
										
										
										
											2020-02-01 22:29:32 +01:00
										 |  |  |         this.initializedPromise = this.loadInitialTree(); | 
					
						
							| 
									
										
										
										
											2018-08-16 23:00:04 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-01 22:29:32 +01:00
										 |  |  |     async loadInitialTree() { | 
					
						
							|  |  |  |         const {notes, branches, attributes} = await server.get('tree'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // clear the cache only directly before adding new content which is important for e.g. switching to protected session
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 = {}; | 
					
						
							| 
									
										
										
										
											2020-01-25 11:52:45 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         /** @type {Object.<string, Attribute>} */ | 
					
						
							|  |  |  |         this.attributes = {}; | 
					
						
							| 
									
										
										
										
											2020-02-01 18:29:18 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         /** @type {Object.<string, Promise<NoteComplement>>} */ | 
					
						
							|  |  |  |         this.noteComplementPromises = {}; | 
					
						
							| 
									
										
										
										
											2019-10-25 21:47:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-01 22:29:32 +01:00
										 |  |  |         this.addResp(notes, branches, attributes); | 
					
						
							| 
									
										
										
										
											2019-10-25 21:47:14 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-25 11:52:45 +01:00
										 |  |  |     addResp(noteRows, branchRows, attributeRows) { | 
					
						
							| 
									
										
										
										
											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); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-27 19:17:32 +01:00
										 |  |  |                         delete this.branches[childNote.parentToBranch[noteId]]; | 
					
						
							| 
									
										
										
										
											2019-10-26 09:51:08 +02:00
										 |  |  |                         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-27 19:17:32 +01:00
										 |  |  |                         delete this.branches[parentNote.childToBranch[noteId]]; | 
					
						
							| 
									
										
										
										
											2019-10-26 09:51:08 +02:00
										 |  |  |                         delete parentNote.childToBranch[noteId]; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2019-10-20 12:29:34 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-04-13 22:10:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-31 20:52:31 +01:00
										 |  |  |             const note = new NoteShort(this, noteRow); | 
					
						
							| 
									
										
										
										
											2019-04-13 22:10:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-26 09:51:08 +02:00
										 |  |  |             this.notes[note.noteId] = note; | 
					
						
							| 
									
										
										
										
											2020-01-31 20:52:31 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-04-13 22:10:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-31 20:52:31 +01:00
										 |  |  |         for (const branchRow of branchRows) { | 
					
						
							|  |  |  |             const branch = new Branch(this, branchRow); | 
					
						
							| 
									
										
										
										
											2019-04-13 22:10:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-31 20:52:31 +01:00
										 |  |  |             this.branches[branch.branchId] = branch; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const childNote = this.notes[branch.noteId]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (childNote) { | 
					
						
							|  |  |  |                 childNote.addParent(branch.parentNoteId, branch.branchId); | 
					
						
							| 
									
										
										
										
											2019-10-26 09:51:08 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-04-13 22:56:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-31 20:52:31 +01:00
										 |  |  |             const parentNote = this.notes[branch.parentNoteId]; | 
					
						
							| 
									
										
										
										
											2019-04-13 22:56:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-31 20:52:31 +01:00
										 |  |  |             if (parentNote) { | 
					
						
							|  |  |  |                 parentNote.addChild(branch.noteId, branch.branchId); | 
					
						
							| 
									
										
										
										
											2019-10-26 09:51:08 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-01-25 11:52:45 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         for (const attributeRow of attributeRows) { | 
					
						
							|  |  |  |             const {attributeId} = attributeRow; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             this.attributes[attributeId] = new Attribute(this, attributeRow); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const note = this.notes[attributeRow.noteId]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (!note.attributes.includes(attributeId)) { | 
					
						
							|  |  |  |                 note.attributes.push(attributeId); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (attributeRow.type === 'relation') { | 
					
						
							|  |  |  |                 const targetNote = this.notes[attributeRow.value]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (targetNote) { | 
					
						
							|  |  |  |                     if (!note.targetRelations.includes(attributeId)) { | 
					
						
							|  |  |  |                         note.targetRelations.push(attributeId); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-10-26 09:51:08 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-26 11:41:40 +01:00
										 |  |  |     async reloadNotes(noteIds) { | 
					
						
							|  |  |  |         if (noteIds.length === 0) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-29 20:14:02 +01:00
										 |  |  |         noteIds = Array.from(new Set(noteIds)); // make noteIds unique
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-26 09:51:08 +02:00
										 |  |  |         const resp = await server.post('tree/load', { noteIds }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-25 13:46:55 +01:00
										 |  |  |         this.addResp(resp.notes, resp.branches, resp.attributes); | 
					
						
							| 
									
										
										
										
											2019-11-04 20:20:21 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         for (const note of resp.notes) { | 
					
						
							|  |  |  |             if (note.type === 'search') { | 
					
						
							|  |  |  |                 const searchResults = await server.get('search-note/' + note.noteId); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-16 19:07:32 +01:00
										 |  |  |                 if (!searchResults) { | 
					
						
							|  |  |  |                     throw new Error(`Search note ${note.noteId} failed.`); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 20:20:21 +01:00
										 |  |  |                 // force to load all the notes at once instead of one by one
 | 
					
						
							| 
									
										
										
										
											2020-01-26 11:41:40 +01:00
										 |  |  |                 await this.getNotes(searchResults.map(res => res.noteId)); | 
					
						
							| 
									
										
										
										
											2019-11-04 20:20:21 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 const branches = resp.branches.filter(b => b.noteId === note.noteId || b.parentNoteId === note.noteId); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 searchResults.forEach((result, index) => branches.push({ | 
					
						
							|  |  |  |                     // branchId should be repeatable since sometimes we reload some notes without rerendering the tree
 | 
					
						
							|  |  |  |                     branchId: "virt" + result.noteId + '-' + note.noteId, | 
					
						
							|  |  |  |                     noteId: result.noteId, | 
					
						
							|  |  |  |                     parentNoteId: note.noteId, | 
					
						
							| 
									
										
										
										
											2020-01-26 11:41:40 +01:00
										 |  |  |                     prefix: this.getBranch(result.branchId).prefix, | 
					
						
							| 
									
										
										
										
											2019-11-04 20:20:21 +01:00
										 |  |  |                     notePosition: (index + 1) * 10 | 
					
						
							|  |  |  |                 })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // update this note with standard (parent) branches + virtual (children) branches
 | 
					
						
							| 
									
										
										
										
											2020-01-26 11:41:40 +01:00
										 |  |  |                 this.addResp([note], branches, []); | 
					
						
							| 
									
										
										
										
											2019-11-04 20:20:21 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											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) { | 
					
						
							| 
									
										
										
										
											2019-12-16 22:00:44 +01:00
										 |  |  |         const missingNoteIds = noteIds.filter(noteId => !this.notes[noteId]); | 
					
						
							| 
									
										
										
										
											2018-04-16 20:40:18 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-26 11:41:40 +01:00
										 |  |  |         await this.reloadNotes(missingNoteIds); | 
					
						
							| 
									
										
										
										
											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) { | 
					
						
							| 
									
										
										
										
											2020-01-25 13:46:55 +01:00
										 |  |  |                 console.log(`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]; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-11-17 10:24:06 +01:00
										 |  |  |         }).filter(note => !!note); | 
					
						
							| 
									
										
										
										
											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') { | 
					
						
							| 
									
										
										
										
											2019-12-10 21:31:24 +01:00
										 |  |  |             console.log(`No 'none' note.`); | 
					
						
							|  |  |  |             return null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (!noteId) { | 
					
						
							|  |  |  |             console.log(`Falsy noteId ${noteId}, returning null.`); | 
					
						
							| 
									
										
										
										
											2018-05-26 16:16:34 -04:00
										 |  |  |             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
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-15 21:36:01 +01:00
										 |  |  |     getNoteFromCache(noteId) { | 
					
						
							|  |  |  |         return this.notes[noteId]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-01-21 21:43:23 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     async getBranchId(parentNoteId, childNoteId) { | 
					
						
							|  |  |  |         const child = await this.getNote(childNoteId); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return child.parentToBranch[parentNoteId]; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-01-26 10:42:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-01 18:29:18 +01:00
										 |  |  |     async getNoteComplement(noteId) { | 
					
						
							|  |  |  |         if (!this.noteComplementPromises[noteId]) { | 
					
						
							|  |  |  |             this.noteComplementPromises[noteId] = server.get('notes/' + noteId).then(row => new NoteComplement(row)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return await this.noteComplementPromises[noteId]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-29 21:38:58 +01:00
										 |  |  |     // FIXME does not actually belong here
 | 
					
						
							| 
									
										
										
										
											2020-01-26 11:41:40 +01:00
										 |  |  |     async processSyncRows(syncRows) { | 
					
						
							| 
									
										
										
										
											2020-01-29 21:38:58 +01:00
										 |  |  |         const loadResults = new LoadResults(this); | 
					
						
							| 
									
										
										
										
											2020-01-26 10:42:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-29 22:32:22 +01:00
										 |  |  |         syncRows.filter(sync => sync.entityName === 'notes').forEach(sync => { | 
					
						
							| 
									
										
										
										
											2020-01-30 22:38:31 +01:00
										 |  |  |             const note = this.notes[sync.entityId]; | 
					
						
							| 
									
										
										
										
											2020-01-29 22:32:22 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-30 22:38:31 +01:00
										 |  |  |             if (note) { | 
					
						
							|  |  |  |                 note.update(sync.entity); | 
					
						
							|  |  |  |                 loadResults.addNote(sync.entityId, sync.sourceId); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-01-29 22:32:22 +01:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-26 11:41:40 +01:00
										 |  |  |         syncRows.filter(sync => sync.entityName === 'branches').forEach(sync => { | 
					
						
							| 
									
										
										
										
											2020-01-31 20:52:31 +01:00
										 |  |  |             let branch = this.branches[sync.entityId]; | 
					
						
							|  |  |  |             const childNote = this.notes[sync.entity.noteId]; | 
					
						
							|  |  |  |             const parentNote = this.notes[sync.entity.parentNoteId]; | 
					
						
							| 
									
										
										
										
											2020-01-29 20:14:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-30 22:38:31 +01:00
										 |  |  |             if (branch) { | 
					
						
							| 
									
										
										
										
											2020-01-31 20:52:31 +01:00
										 |  |  |                 if (sync.entity.isDeleted) { | 
					
						
							|  |  |  |                     if (childNote) { | 
					
						
							|  |  |  |                         childNote.parents = childNote.parents.filter(parentNoteId => parentNoteId !== sync.entity.parentNoteId); | 
					
						
							|  |  |  |                         delete childNote.parentToBranch[sync.entity.parentNoteId]; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (parentNote) { | 
					
						
							|  |  |  |                         parentNote.children = parentNote.children.filter(childNoteId => childNoteId !== sync.entity.noteId); | 
					
						
							|  |  |  |                         delete parentNote.childToBranch[sync.entity.noteId]; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 else { | 
					
						
							|  |  |  |                     branch.update(sync.entity); | 
					
						
							|  |  |  |                     loadResults.addBranch(sync.entityId, sync.sourceId); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (childNote) { | 
					
						
							|  |  |  |                         childNote.addParent(branch.parentNoteId, branch.branchId); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (parentNote) { | 
					
						
							|  |  |  |                         parentNote.addChild(branch.noteId, branch.branchId); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else if (!sync.entity.isDeleted) { | 
					
						
							|  |  |  |                 if (childNote || parentNote) { | 
					
						
							|  |  |  |                     branch = new Branch(this, sync.entity); | 
					
						
							|  |  |  |                     this.branches[branch.branchId] = branch; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     loadResults.addBranch(sync.entityId, sync.sourceId); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (childNote) { | 
					
						
							|  |  |  |                         childNote.addParent(branch.parentNoteId, branch.branchId); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (parentNote) { | 
					
						
							|  |  |  |                         parentNote.addChild(branch.noteId, branch.branchId); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2020-01-30 22:38:31 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-01-29 20:14:02 +01:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2020-01-26 10:42:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-29 20:14:02 +01:00
										 |  |  |         syncRows.filter(sync => sync.entityName === 'note_reordering').forEach(sync => { | 
					
						
							| 
									
										
										
										
											2020-01-30 22:38:31 +01:00
										 |  |  |             for (const branchId in sync.positions) { | 
					
						
							|  |  |  |                 const branch = this.branches[branchId]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (branch) { | 
					
						
							|  |  |  |                     branch.notePosition = sync.positions[branchId]; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-01-26 10:42:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-29 20:14:02 +01:00
										 |  |  |             loadResults.addNoteReordering(sync.entityId, sync.sourceId); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2020-01-26 10:42:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-26 11:41:40 +01:00
										 |  |  |         // missing reloading the relation target note
 | 
					
						
							| 
									
										
										
										
											2020-01-29 20:14:02 +01:00
										 |  |  |         syncRows.filter(sync => sync.entityName === 'attributes').forEach(sync => { | 
					
						
							| 
									
										
										
										
											2020-01-31 20:52:31 +01:00
										 |  |  |             let attribute = this.attributes[sync.entityId]; | 
					
						
							|  |  |  |             const sourceNote = this.notes[sync.entity.noteId]; | 
					
						
							|  |  |  |             const targetNote = sync.entity.type === 'relation' && this.notes[sync.entity.value]; | 
					
						
							| 
									
										
										
										
											2020-01-29 20:14:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-30 22:38:31 +01:00
										 |  |  |             if (attribute) { | 
					
						
							|  |  |  |                 attribute.update(sync.entity); | 
					
						
							|  |  |  |                 loadResults.addAttribute(sync.entityId, sync.sourceId); | 
					
						
							| 
									
										
										
										
											2020-01-31 20:52:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 if (sync.entity.isDeleted) { | 
					
						
							|  |  |  |                     if (sourceNote) { | 
					
						
							|  |  |  |                         sourceNote.attributes = sourceNote.attributes.filter(attributeId => attributeId !== attribute.attributeId); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (targetNote) { | 
					
						
							|  |  |  |                         targetNote.targetRelations = targetNote.targetRelations.filter(attributeId => attributeId !== attribute.value); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else if (!sync.entity.isDeleted) { | 
					
						
							|  |  |  |                 if (sourceNote || targetNote) { | 
					
						
							|  |  |  |                     attribute = new Attribute(this, sync.entity); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     this.attributes[attribute.attributeId] = attribute; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     loadResults.addAttribute(sync.entityId, sync.sourceId); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (sourceNote && !sourceNote.attributes.includes(attribute.attributeId)) { | 
					
						
							|  |  |  |                         sourceNote.attributes.push(attribute.attributeId); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (targetNote && !targetNote.attributes.includes(attribute.attributeId)) { | 
					
						
							|  |  |  |                         targetNote.attributes.push(attribute.attributeId); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2020-01-30 22:38:31 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-01-29 20:14:02 +01:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2020-01-26 10:42:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-31 22:32:24 +01:00
										 |  |  |         syncRows.filter(sync => sync.entityName === 'note_contents').forEach(sync => { | 
					
						
							| 
									
										
										
										
											2020-02-01 18:29:18 +01:00
										 |  |  |             delete this.noteComplementPromises[sync.entityId]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-31 22:32:24 +01:00
										 |  |  |             loadResults.addNoteContent(sync.entityId, sync.sourceId); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-29 21:38:58 +01:00
										 |  |  |         syncRows.filter(sync => sync.entityName === 'note_revisions').forEach(sync => { | 
					
						
							|  |  |  |             loadResults.addNoteRevision(sync.entityId, sync.noteId, sync.sourceId); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-05 22:08:45 +01:00
										 |  |  |         syncRows.filter(sync => sync.entityName === 'options').forEach(sync => { | 
					
						
							|  |  |  |             options.set(sync.entity.name, sync.entity.value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             loadResults.addOption(sync.entity.name); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-29 20:14:02 +01:00
										 |  |  |         appContext.trigger('entitiesReloaded', {loadResults}); | 
					
						
							| 
									
										
										
										
											2020-01-26 10:42:24 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-25 12:29:00 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const treeCache = new TreeCache(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default treeCache; |