mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 10:26:08 +01:00 
			
		
		
		
	refactoring of note update
This commit is contained in:
		| @@ -1,10 +1,15 @@ | |||||||
| "use strict"; | "use strict"; | ||||||
|  |  | ||||||
| const Entity = require('./entity'); | const Entity = require('./entity'); | ||||||
|  | const utils = require('../services/utils'); | ||||||
|  |  | ||||||
| class Branch extends Entity { | class Branch extends Entity { | ||||||
|     static get tableName() { return "branches"; } |     static get tableName() { return "branches"; } | ||||||
|     static get primaryKeyName() { return "branchId"; } |     static get primaryKeyName() { return "branchId"; } | ||||||
|  |  | ||||||
|  |     beforeSaving() { | ||||||
|  |         this.dateModified = utils.nowDate() | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| module.exports = Branch; | module.exports = Branch; | ||||||
| @@ -1,5 +1,6 @@ | |||||||
| const Note = require('../entities/note'); | const Note = require('../entities/note'); | ||||||
| const NoteRevision = require('../entities/note_revision'); | const NoteRevision = require('../entities/note_revision'); | ||||||
|  | const NoteImage = require('../entities/note_image'); | ||||||
| const Branch = require('../entities/branch'); | const Branch = require('../entities/branch'); | ||||||
| const Label = require('../entities/label'); | const Label = require('../entities/label'); | ||||||
| const repository = require('../services/repository'); | const repository = require('../services/repository'); | ||||||
| @@ -13,6 +14,9 @@ function createEntityFromRow(row) { | |||||||
|     else if (row.noteRevisionId) { |     else if (row.noteRevisionId) { | ||||||
|         entity = new NoteRevision(row); |         entity = new NoteRevision(row); | ||||||
|     } |     } | ||||||
|  |     else if (row.noteImageId) { | ||||||
|  |         entity = new NoteImage(row); | ||||||
|  |     } | ||||||
|     else if (row.branchId) { |     else if (row.branchId) { | ||||||
|         entity = new Branch(row); |         entity = new Branch(row); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ | |||||||
|  |  | ||||||
| const Entity = require('./entity'); | const Entity = require('./entity'); | ||||||
| const repository = require('../services/repository'); | const repository = require('../services/repository'); | ||||||
|  | const utils = require('../services/utils'); | ||||||
|  |  | ||||||
| class Label extends Entity { | class Label extends Entity { | ||||||
|     static get tableName() { return "labels"; } |     static get tableName() { return "labels"; } | ||||||
| @@ -10,6 +11,14 @@ class Label extends Entity { | |||||||
|     async getNote() { |     async getNote() { | ||||||
|         return await repository.getEntity("SELECT * FROM notes WHERE noteId = ?", [this.noteId]); |         return await repository.getEntity("SELECT * FROM notes WHERE noteId = ?", [this.noteId]); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     beforeSaving() { | ||||||
|  |         if (!this.dateCreated) { | ||||||
|  |             this.dateCreated = utils.nowDate(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         this.dateModified = utils.nowDate(); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| module.exports = Label; | module.exports = Label; | ||||||
| @@ -3,6 +3,7 @@ | |||||||
| const Entity = require('./entity'); | const Entity = require('./entity'); | ||||||
| const protected_session = require('../services/protected_session'); | const protected_session = require('../services/protected_session'); | ||||||
| const repository = require('../services/repository'); | const repository = require('../services/repository'); | ||||||
|  | const utils = require('../services/utils'); | ||||||
|  |  | ||||||
| class Note extends Entity { | class Note extends Entity { | ||||||
|     static get tableName() { return "notes"; } |     static get tableName() { return "notes"; } | ||||||
| @@ -79,6 +80,10 @@ class Note extends Entity { | |||||||
|         return await repository.getEntities("SELECT * FROM note_revisions WHERE noteId = ?", [this.noteId]); |         return await repository.getEntities("SELECT * FROM note_revisions WHERE noteId = ?", [this.noteId]); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     async getNoteImages() { | ||||||
|  |         return await repository.getEntities("SELECT * FROM note_images WHERE noteId = ? AND isDeleted = 0", [this.noteId]); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     async getTrees() { |     async getTrees() { | ||||||
|         return await repository.getEntities("SELECT * FROM branches WHERE isDeleted = 0 AND noteId = ?", [this.noteId]); |         return await repository.getEntities("SELECT * FROM branches WHERE isDeleted = 0 AND noteId = ?", [this.noteId]); | ||||||
|     } |     } | ||||||
| @@ -127,11 +132,19 @@ class Note extends Entity { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     beforeSaving() { |     beforeSaving() { | ||||||
|         this.content = JSON.stringify(this.jsonContent, null, '\t'); |         if (this.isJson()) { | ||||||
|  |             this.content = JSON.stringify(this.jsonContent, null, '\t'); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         if (this.isProtected) { |         if (this.isProtected) { | ||||||
|             protected_session.encryptNote(this); |             protected_session.encryptNote(this); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         if (!this.dateCreated) { | ||||||
|  |             this.dateCreated = utils.nowDate(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         this.dateModified = utils.nowDate(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								src/entities/note_image.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/entities/note_image.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | "use strict"; | ||||||
|  |  | ||||||
|  | const Entity = require('./entity'); | ||||||
|  | const repository = require('../services/repository'); | ||||||
|  |  | ||||||
|  | class NoteImage extends Entity { | ||||||
|  |     static get tableName() { return "note_images"; } | ||||||
|  |     static get primaryKeyName() { return "noteImageId"; } | ||||||
|  |  | ||||||
|  |     async getNote() { | ||||||
|  |         return await repository.getEntity("SELECT * FROM notes WHERE noteId = ?", [this.noteId]); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module.exports = NoteImage; | ||||||
| @@ -177,7 +177,7 @@ function register(app) { | |||||||
|     apiRoute(POST, '/api/cleanup/vacuum-database', cleanupRoute.vacuumDatabase); |     apiRoute(POST, '/api/cleanup/vacuum-database', cleanupRoute.vacuumDatabase); | ||||||
|  |  | ||||||
|     route(GET, '/api/images/:imageId/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImage); |     route(GET, '/api/images/:imageId/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImage); | ||||||
|     route(POST, '/api/images', [auth.checkApiAuthOrElectron], imageRoute.uploadImage, apiResultHandler); |     route(POST, '/api/images', [auth.checkApiAuthOrElectron, uploadMiddleware], imageRoute.uploadImage, apiResultHandler); | ||||||
|  |  | ||||||
|     apiRoute(POST, '/api/script/exec', scriptRoute.exec); |     apiRoute(POST, '/api/script/exec', scriptRoute.exec); | ||||||
|     apiRoute(POST, '/api/script/run/:noteId', scriptRoute.run); |     apiRoute(POST, '/api/script/run/:noteId', scriptRoute.run); | ||||||
|   | |||||||
| @@ -5,6 +5,8 @@ const sync_table = require('./sync_table'); | |||||||
| const labels = require('./labels'); | const labels = require('./labels'); | ||||||
| const protected_session = require('./protected_session'); | const protected_session = require('./protected_session'); | ||||||
| const repository = require('./repository'); | const repository = require('./repository'); | ||||||
|  | const NoteImage = require('../entities/note_image'); | ||||||
|  | const NoteRevision = require('../entities/note_revision'); | ||||||
|  |  | ||||||
| async function createNewNote(parentNoteId, noteOpts) { | async function createNewNote(parentNoteId, noteOpts) { | ||||||
|     const noteId = utils.newNoteId(); |     const noteId = utils.newNoteId(); | ||||||
| @@ -127,110 +129,46 @@ async function protectNoteRecursively(note, protect) { | |||||||
| } | } | ||||||
|  |  | ||||||
| async function protectNote(note, protect) { | async function protectNote(note, protect) { | ||||||
|     let changed = false; |     if (protect !== note.isProtected) { | ||||||
|  |         note.isProtected = protect; | ||||||
|  |  | ||||||
|     if (protect && !note.isProtected) { |  | ||||||
|         note.isProtected = true; |  | ||||||
|  |  | ||||||
|         changed = true; |  | ||||||
|     } |  | ||||||
|     else if (!protect && note.isProtected) { |  | ||||||
|         note.isProtected = false; |  | ||||||
|  |  | ||||||
|         changed = true; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (changed) { |  | ||||||
|         await repository.updateEntity(note); |         await repository.updateEntity(note); | ||||||
|  |  | ||||||
|         await sync_table.addNoteSync(note.noteId); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     await protectNoteRevisions(note, protect); |     await protectNoteRevisions(note); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function protectNoteRevisions(note, protect) { | async function protectNoteRevisions(note) { | ||||||
|     for (const revision of await note.getRevisions()) { |     for (const revision of await note.getRevisions()) { | ||||||
|         let changed = false; |         if (note.isProtected !== revision.isProtected) { | ||||||
|  |             revision.isProtected = note.isProtected; | ||||||
|  |  | ||||||
|         if (protect && !revision.isProtected) { |  | ||||||
|             revision.isProtected = true; |  | ||||||
|  |  | ||||||
|             changed = true; |  | ||||||
|         } |  | ||||||
|         else if(!protect && revision.isProtected) { |  | ||||||
|             revision.isProtected = false; |  | ||||||
|  |  | ||||||
|             changed = true; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (changed) { |  | ||||||
|             await repository.updateEntity(revision); |             await repository.updateEntity(revision); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         await sync_table.addNoteRevisionSync(revision.noteRevisionId); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| async function saveNoteRevision(noteId, nowStr) { | async function saveNoteImages(note) { | ||||||
|     const oldNote = await sql.getRow("SELECT * FROM notes WHERE noteId = ?", [noteId]); |     if (note.type !== 'text') { | ||||||
|  |  | ||||||
|     if (oldNote.type === 'file') { |  | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (oldNote.isProtected) { |     const existingNoteImages = await note.getNoteImages(); | ||||||
|         protected_session.decryptNote(oldNote); |  | ||||||
|  |  | ||||||
|         oldNote.isProtected = false; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     const newNoteRevisionId = utils.newNoteRevisionId(); |  | ||||||
|  |  | ||||||
|     await sql.insert('note_revisions', { |  | ||||||
|         noteRevisionId: newNoteRevisionId, |  | ||||||
|         noteId: noteId, |  | ||||||
|         // title and text should be decrypted now |  | ||||||
|         title: oldNote.title, |  | ||||||
|         content: oldNote.content, |  | ||||||
|         isProtected: 0, // will be fixed in the protectNoteRevisions() call |  | ||||||
|         dateModifiedFrom: oldNote.dateModified, |  | ||||||
|         dateModifiedTo: nowStr |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     await sync_table.addNoteRevisionSync(newNoteRevisionId); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| async function saveNoteImages(noteId, noteText) { |  | ||||||
|     const existingNoteImages = await sql.getRows("SELECT * FROM note_images WHERE noteId = ?", [noteId]); |  | ||||||
|     const foundImageIds = []; |     const foundImageIds = []; | ||||||
|     const now = utils.nowDate(); |  | ||||||
|     const re = /src="\/api\/images\/([a-zA-Z0-9]+)\//g; |     const re = /src="\/api\/images\/([a-zA-Z0-9]+)\//g; | ||||||
|     let match; |     let match; | ||||||
|  |  | ||||||
|     while (match = re.exec(noteText)) { |     while (match = re.exec(note.content)) { | ||||||
|         const imageId = match[1]; |         const imageId = match[1]; | ||||||
|         const existingNoteImage = existingNoteImages.find(ni => ni.imageId === imageId); |         const existingNoteImage = existingNoteImages.find(ni => ni.imageId === imageId); | ||||||
|  |  | ||||||
|         if (!existingNoteImage) { |         if (!existingNoteImage) { | ||||||
|             const noteImageId = utils.newNoteImageId(); |             await repository.updateEntity(new NoteImage({ | ||||||
|  |                 noteImageId: utils.newNoteImageId(), | ||||||
|             await sql.insert("note_images", { |                 noteId: note.noteId, | ||||||
|                 noteImageId: noteImageId, |  | ||||||
|                 noteId: noteId, |  | ||||||
|                 imageId: imageId, |                 imageId: imageId, | ||||||
|                 isDeleted: 0, |                 isDeleted: 0 | ||||||
|                 dateModified: now, |             })); | ||||||
|                 dateCreated: now |  | ||||||
|             }); |  | ||||||
|  |  | ||||||
|             await sync_table.addNoteImageSync(noteImageId); |  | ||||||
|         } |  | ||||||
|         else if (existingNoteImage.isDeleted) { |  | ||||||
|             await sql.execute("UPDATE note_images SET isDeleted = 0, dateModified = ? WHERE noteImageId = ?", |  | ||||||
|                 [now, existingNoteImage.noteImageId]); |  | ||||||
|  |  | ||||||
|             await sync_table.addNoteImageSync(existingNoteImage.noteImageId); |  | ||||||
|         } |         } | ||||||
|         // else we don't need to do anything |         // else we don't need to do anything | ||||||
|  |  | ||||||
| @@ -241,67 +179,62 @@ async function saveNoteImages(noteId, noteText) { | |||||||
|     const unusedNoteImages = existingNoteImages.filter(ni => !foundImageIds.includes(ni.imageId)); |     const unusedNoteImages = existingNoteImages.filter(ni => !foundImageIds.includes(ni.imageId)); | ||||||
|  |  | ||||||
|     for (const unusedNoteImage of unusedNoteImages) { |     for (const unusedNoteImage of unusedNoteImages) { | ||||||
|         await sql.execute("UPDATE note_images SET isDeleted = 1, dateModified = ? WHERE noteImageId = ?", |         unusedNoteImage.isDeleted = 1; | ||||||
|             [now, unusedNoteImage.noteImageId]); |  | ||||||
|  |  | ||||||
|         await sync_table.addNoteImageSync(unusedNoteImage.noteImageId); |         await repository.updateEntity(unusedNoteImage); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| async function loadFile(noteId, newNote) { | async function saveNoteRevision(note) { | ||||||
|     const oldNote = await sql.getRow("SELECT * FROM notes WHERE noteId = ?", [noteId]); |     const labelsMap = await note.getLabelMap(); | ||||||
|  |  | ||||||
|     if (oldNote.isProtected) { |  | ||||||
|         await protected_session.decryptNote(oldNote); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     newNote.content = oldNote.content; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| async function updateNote(noteId, newNote) { |  | ||||||
|     if (newNote.type === 'file') { |  | ||||||
|         await loadFile(noteId, newNote); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (newNote.isProtected) { |  | ||||||
|         await protected_session.encryptNote(newNote); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     const labelsMap = await labels.getNoteLabelMap(noteId); |  | ||||||
|  |  | ||||||
|     const now = new Date(); |     const now = new Date(); | ||||||
|     const nowStr = utils.nowDate(); |  | ||||||
|  |  | ||||||
|     const noteRevisionSnapshotTimeInterval = parseInt(await options.getOption('note_revision_snapshot_time_interval')); |     const noteRevisionSnapshotTimeInterval = parseInt(await options.getOption('note_revision_snapshot_time_interval')); | ||||||
|  |  | ||||||
|     const revisionCutoff = utils.dateStr(new Date(now.getTime() - noteRevisionSnapshotTimeInterval * 1000)); |     const revisionCutoff = utils.dateStr(new Date(now.getTime() - noteRevisionSnapshotTimeInterval * 1000)); | ||||||
|  |  | ||||||
|     const existingnoteRevisionId = await sql.getValue( |     const existingnoteRevisionId = await sql.getValue( | ||||||
|         "SELECT noteRevisionId FROM note_revisions WHERE noteId = ? AND dateModifiedTo >= ?", [noteId, revisionCutoff]); |         "SELECT noteRevisionId FROM note_revisions WHERE noteId = ? AND dateModifiedTo >= ?", [note.noteId, revisionCutoff]); | ||||||
|  |  | ||||||
|     await sql.doInTransaction(async () => { |     const msSinceDateCreated = now.getTime() - utils.parseDateTime(note.dateCreated).getTime(); | ||||||
|         const msSinceDateCreated = now.getTime() - utils.parseDateTime(newNote.dateCreated).getTime(); |  | ||||||
|  |  | ||||||
|         if (labelsMap.disable_versioning !== 'true' |     if (note.type !== 'file' | ||||||
|             && !existingnoteRevisionId |         && labelsMap.disable_versioning !== 'true' | ||||||
|             && msSinceDateCreated >= noteRevisionSnapshotTimeInterval * 1000) { |         && !existingnoteRevisionId | ||||||
|  |         && msSinceDateCreated >= noteRevisionSnapshotTimeInterval * 1000) { | ||||||
|  |  | ||||||
|             await saveNoteRevision(noteId, nowStr); |         await repository.updateEntity(new NoteRevision({ | ||||||
|         } |             noteRevisionId: utils.newNoteRevisionId(), | ||||||
|  |             noteId: note.noteId, | ||||||
|  |             // title and text should be decrypted now | ||||||
|  |             title: note.title, | ||||||
|  |             content: note.content, | ||||||
|  |             isProtected: 0, // will be fixed in the protectNoteRevisions() call | ||||||
|  |             dateModifiedFrom: note.dateModified, | ||||||
|  |             dateModifiedTo: utils.nowDate() | ||||||
|  |         })); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|         await saveNoteImages(noteId, newNote.content); | async function updateNote(noteId, noteUpdates) { | ||||||
|  |     const note = await repository.getNote(noteId); | ||||||
|  |  | ||||||
|         await protectNoteRevisions(await repository.getNote(noteId), newNote.isProtected); |     if (note.type === 'file') { | ||||||
|  |         // for update file, newNote doesn't contain file payloads | ||||||
|  |         noteUpdates.content = note.content; | ||||||
|  |     } | ||||||
|  |  | ||||||
|         await sql.execute("UPDATE notes SET title = ?, content = ?, isProtected = ?, dateModified = ? WHERE noteId = ?", [ |     await saveNoteRevision(note); | ||||||
|             newNote.title, |  | ||||||
|             newNote.content, |  | ||||||
|             newNote.isProtected, |  | ||||||
|             nowStr, |  | ||||||
|             noteId]); |  | ||||||
|  |  | ||||||
|         await sync_table.addNoteSync(noteId); |     note.title = noteUpdates.title; | ||||||
|     }); |     note.content = noteUpdates.content; | ||||||
|  |     note.isProtected = noteUpdates.isProtected; | ||||||
|  |  | ||||||
|  |     await repository.updateEntity(note); | ||||||
|  |  | ||||||
|  |     await saveNoteImages(note); | ||||||
|  |  | ||||||
|  |     await protectNoteRevisions(note); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function deleteNote(branchId) { | async function deleteNote(branchId) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user