mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
refactoring of note update
This commit is contained in:
parent
e8a5d0ae16
commit
5f7e74e15c
@ -1,10 +1,15 @@
|
||||
"use strict";
|
||||
|
||||
const Entity = require('./entity');
|
||||
const utils = require('../services/utils');
|
||||
|
||||
class Branch extends Entity {
|
||||
static get tableName() { return "branches"; }
|
||||
static get primaryKeyName() { return "branchId"; }
|
||||
|
||||
beforeSaving() {
|
||||
this.dateModified = utils.nowDate()
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Branch;
|
@ -1,5 +1,6 @@
|
||||
const Note = require('../entities/note');
|
||||
const NoteRevision = require('../entities/note_revision');
|
||||
const NoteImage = require('../entities/note_image');
|
||||
const Branch = require('../entities/branch');
|
||||
const Label = require('../entities/label');
|
||||
const repository = require('../services/repository');
|
||||
@ -13,6 +14,9 @@ function createEntityFromRow(row) {
|
||||
else if (row.noteRevisionId) {
|
||||
entity = new NoteRevision(row);
|
||||
}
|
||||
else if (row.noteImageId) {
|
||||
entity = new NoteImage(row);
|
||||
}
|
||||
else if (row.branchId) {
|
||||
entity = new Branch(row);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
const Entity = require('./entity');
|
||||
const repository = require('../services/repository');
|
||||
const utils = require('../services/utils');
|
||||
|
||||
class Label extends Entity {
|
||||
static get tableName() { return "labels"; }
|
||||
@ -10,6 +11,14 @@ class Label extends Entity {
|
||||
async getNote() {
|
||||
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;
|
@ -3,6 +3,7 @@
|
||||
const Entity = require('./entity');
|
||||
const protected_session = require('../services/protected_session');
|
||||
const repository = require('../services/repository');
|
||||
const utils = require('../services/utils');
|
||||
|
||||
class Note extends Entity {
|
||||
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]);
|
||||
}
|
||||
|
||||
async getNoteImages() {
|
||||
return await repository.getEntities("SELECT * FROM note_images WHERE noteId = ? AND isDeleted = 0", [this.noteId]);
|
||||
}
|
||||
|
||||
async getTrees() {
|
||||
return await repository.getEntities("SELECT * FROM branches WHERE isDeleted = 0 AND noteId = ?", [this.noteId]);
|
||||
}
|
||||
@ -127,11 +132,19 @@ class Note extends Entity {
|
||||
}
|
||||
|
||||
beforeSaving() {
|
||||
this.content = JSON.stringify(this.jsonContent, null, '\t');
|
||||
if (this.isJson()) {
|
||||
this.content = JSON.stringify(this.jsonContent, null, '\t');
|
||||
}
|
||||
|
||||
if (this.isProtected) {
|
||||
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);
|
||||
|
||||
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/run/:noteId', scriptRoute.run);
|
||||
|
@ -5,6 +5,8 @@ const sync_table = require('./sync_table');
|
||||
const labels = require('./labels');
|
||||
const protected_session = require('./protected_session');
|
||||
const repository = require('./repository');
|
||||
const NoteImage = require('../entities/note_image');
|
||||
const NoteRevision = require('../entities/note_revision');
|
||||
|
||||
async function createNewNote(parentNoteId, noteOpts) {
|
||||
const noteId = utils.newNoteId();
|
||||
@ -127,110 +129,46 @@ async function protectNoteRecursively(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 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()) {
|
||||
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 sync_table.addNoteRevisionSync(revision.noteRevisionId);
|
||||
}
|
||||
}
|
||||
|
||||
async function saveNoteRevision(noteId, nowStr) {
|
||||
const oldNote = await sql.getRow("SELECT * FROM notes WHERE noteId = ?", [noteId]);
|
||||
|
||||
if (oldNote.type === 'file') {
|
||||
async function saveNoteImages(note) {
|
||||
if (note.type !== 'text') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldNote.isProtected) {
|
||||
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 existingNoteImages = await note.getNoteImages();
|
||||
const foundImageIds = [];
|
||||
const now = utils.nowDate();
|
||||
const re = /src="\/api\/images\/([a-zA-Z0-9]+)\//g;
|
||||
let match;
|
||||
|
||||
while (match = re.exec(noteText)) {
|
||||
while (match = re.exec(note.content)) {
|
||||
const imageId = match[1];
|
||||
const existingNoteImage = existingNoteImages.find(ni => ni.imageId === imageId);
|
||||
|
||||
if (!existingNoteImage) {
|
||||
const noteImageId = utils.newNoteImageId();
|
||||
|
||||
await sql.insert("note_images", {
|
||||
noteImageId: noteImageId,
|
||||
noteId: noteId,
|
||||
await repository.updateEntity(new NoteImage({
|
||||
noteImageId: utils.newNoteImageId(),
|
||||
noteId: note.noteId,
|
||||
imageId: imageId,
|
||||
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);
|
||||
isDeleted: 0
|
||||
}));
|
||||
}
|
||||
// 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));
|
||||
|
||||
for (const unusedNoteImage of unusedNoteImages) {
|
||||
await sql.execute("UPDATE note_images SET isDeleted = 1, dateModified = ? WHERE noteImageId = ?",
|
||||
[now, unusedNoteImage.noteImageId]);
|
||||
unusedNoteImage.isDeleted = 1;
|
||||
|
||||
await sync_table.addNoteImageSync(unusedNoteImage.noteImageId);
|
||||
await repository.updateEntity(unusedNoteImage);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadFile(noteId, newNote) {
|
||||
const oldNote = await sql.getRow("SELECT * FROM notes WHERE noteId = ?", [noteId]);
|
||||
|
||||
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);
|
||||
async function saveNoteRevision(note) {
|
||||
const labelsMap = await note.getLabelMap();
|
||||
|
||||
const now = new Date();
|
||||
const nowStr = utils.nowDate();
|
||||
|
||||
const noteRevisionSnapshotTimeInterval = parseInt(await options.getOption('note_revision_snapshot_time_interval'));
|
||||
|
||||
const revisionCutoff = utils.dateStr(new Date(now.getTime() - noteRevisionSnapshotTimeInterval * 1000));
|
||||
|
||||
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(newNote.dateCreated).getTime();
|
||||
const msSinceDateCreated = now.getTime() - utils.parseDateTime(note.dateCreated).getTime();
|
||||
|
||||
if (labelsMap.disable_versioning !== 'true'
|
||||
&& !existingnoteRevisionId
|
||||
&& msSinceDateCreated >= noteRevisionSnapshotTimeInterval * 1000) {
|
||||
if (note.type !== 'file'
|
||||
&& labelsMap.disable_versioning !== 'true'
|
||||
&& !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 = ?", [
|
||||
newNote.title,
|
||||
newNote.content,
|
||||
newNote.isProtected,
|
||||
nowStr,
|
||||
noteId]);
|
||||
await saveNoteRevision(note);
|
||||
|
||||
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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user