From c6c162cddac92c11645981966bfa50fb2a600e18 Mon Sep 17 00:00:00 2001 From: zadam Date: Wed, 19 Apr 2023 22:47:33 +0200 Subject: [PATCH] restore revision with attachments --- src/becca/entities/bnote.js | 4 +--- src/becca/entities/bnote_revision.js | 12 ++++++++++ .../widgets/type_widgets/attachment_detail.js | 9 ++++--- src/routes/api/note_revisions.js | 24 +++++++++++++++---- 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/becca/entities/bnote.js b/src/becca/entities/bnote.js index 1a97b9cf8..f58c377a7 100644 --- a/src/becca/entities/bnote.js +++ b/src/becca/entities/bnote.js @@ -1569,11 +1569,9 @@ class BNote extends AbstractBeccaEntity { noteRevision.save(); // to generate noteRevisionId which is then used to save attachments for (const noteAttachment of this.getAttachments()) { - const attachmentContent = noteAttachment.getContent(); - const revisionAttachment = noteAttachment.copy(); revisionAttachment.parentId = noteRevision.noteRevisionId; - revisionAttachment.setContent(attachmentContent, { + revisionAttachment.setContent(noteAttachment.getContent(), { forceSave: true, forceCold: true }); diff --git a/src/becca/entities/bnote_revision.js b/src/becca/entities/bnote_revision.js index 368a65ade..1e127c4a5 100644 --- a/src/becca/entities/bnote_revision.js +++ b/src/becca/entities/bnote_revision.js @@ -5,6 +5,8 @@ const utils = require('../../services/utils'); const dateUtils = require('../../services/date_utils'); const becca = require('../becca'); const AbstractBeccaEntity = require("./abstract_becca_entity"); +const sql = require("../../services/sql"); +const BAttachment = require("./battachment"); /** * NoteRevision represents snapshot of note's title and content at some point in the past. @@ -92,6 +94,16 @@ class BNoteRevision extends AbstractBeccaEntity { this._setContent(content, opts); } + /** @returns {BAttachment[]} */ + getAttachments() { + return sql.getRows(` + SELECT attachments.* + FROM attachments + WHERE parentId = ? + AND isDeleted = 0`, [this.noteRevisionId]) + .map(row => new BAttachment(row)); + } + beforeSaving() { super.beforeSaving(); diff --git a/src/public/app/widgets/type_widgets/attachment_detail.js b/src/public/app/widgets/type_widgets/attachment_detail.js index f1abecc17..449ad9323 100644 --- a/src/public/app/widgets/type_widgets/attachment_detail.js +++ b/src/public/app/widgets/type_widgets/attachment_detail.js @@ -28,9 +28,8 @@ export default class AttachmentDetailTypeWidget extends TypeWidget { async doRefresh(note) { this.$wrapper.empty(); this.children = []; - this.renderedAttachmentIds = new Set(); - const attachment = await server.get(`attachments/${this.noteContext.viewScope.attachmentId}/?includeContent=true`); + const attachment = await server.get(`attachments/${this.attachmentId}/?includeContent=true`); if (!attachment) { this.$wrapper.html("This attachment has been deleted."); @@ -46,10 +45,14 @@ export default class AttachmentDetailTypeWidget extends TypeWidget { } async entitiesReloadedEvent({loadResults}) { - const attachmentChange = loadResults.getAttachments().find(att => att.attachmentId === this.attachment.attachmentId); + const attachmentChange = loadResults.getAttachments().find(att => att.attachmentId === this.attachmentId); if (attachmentChange?.isDeleted) { this.refresh(); // all other updates are handled within AttachmentDetailWidget } } + + get attachmentId() { + return this.noteContext.viewScope.attachmentId; + } } diff --git a/src/routes/api/note_revisions.js b/src/routes/api/note_revisions.js index 2ac97e64a..f1a919aaa 100644 --- a/src/routes/api/note_revisions.js +++ b/src/routes/api/note_revisions.js @@ -95,11 +95,27 @@ function restoreNoteRevision(req) { if (noteRevision) { const note = noteRevision.getNote(); - note.saveNoteRevision(); + sql.transactional(() => { + note.saveNoteRevision(); - note.title = noteRevision.title; - note.setContent(noteRevision.getContent()); - note.save(); + for (const oldNoteAttachment of note.getAttachments()) { + oldNoteAttachment.markAsDeleted(); + } + + let revisionContent = noteRevision.getContent(); + + for (const revisionAttachment of noteRevision.getAttachments()) { + const noteAttachment = revisionAttachment.copy(); + noteAttachment.parentId = note.noteId; + noteAttachment.setContent(revisionAttachment.getContent(), { forceSave: true }); + + // content is rewritten to point to the restored revision attachments + revisionContent = revisionContent.replaceAll(`attachments/${revisionAttachment.attachmentId}`, `attachments/${noteAttachment.attachmentId}`); + } + + note.title = noteRevision.title; + note.setContent(revisionContent, { forceSave: true }); + }); } }