erasing note revisions

This commit is contained in:
zadam 2019-11-09 15:21:14 +01:00
parent 7cd75cebfc
commit 9b24ae0600
10 changed files with 213 additions and 92 deletions

View File

@ -309,359 +309,365 @@ parentNoteId</ColNames>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="74" parent="11" name="isProtected">
<column id="74" parent="11" name="isErased">
<Position>5</Position>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="75" parent="11" name="utcDateLastEdited">
<column id="75" parent="11" name="isProtected">
<Position>6</Position>
<DataType>TEXT|0s</DataType>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="76" parent="11" name="utcDateCreated">
<column id="76" parent="11" name="utcDateLastEdited">
<Position>7</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="77" parent="11" name="utcDateModified">
<column id="77" parent="11" name="utcDateCreated">
<Position>8</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="78" parent="11" name="dateLastEdited">
<column id="78" parent="11" name="utcDateModified">
<Position>9</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="79" parent="11" name="dateCreated">
<column id="79" parent="11" name="dateLastEdited">
<Position>10</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="80" parent="11" name="type">
<column id="80" parent="11" name="dateCreated">
<Position>11</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&apos;&apos;</DefaultExpression>
</column>
<column id="81" parent="11" name="mime">
<column id="81" parent="11" name="type">
<Position>12</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&apos;&apos;</DefaultExpression>
</column>
<column id="82" parent="11" name="hash">
<column id="82" parent="11" name="mime">
<Position>13</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&apos;&apos;</DefaultExpression>
</column>
<index id="83" parent="11" name="sqlite_autoindex_note_revisions_1">
<column id="83" parent="11" name="hash">
<Position>14</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&apos;&apos;</DefaultExpression>
</column>
<index id="84" parent="11" name="sqlite_autoindex_note_revisions_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>noteRevisionId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<index id="84" parent="11" name="IDX_note_revisions_noteId">
<index id="85" parent="11" name="IDX_note_revisions_noteId">
<ColNames>noteId</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="85" parent="11" name="IDX_note_revisions_utcDateLastEdited">
<index id="86" parent="11" name="IDX_note_revisions_utcDateLastEdited">
<ColNames>utcDateLastEdited</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="86" parent="11" name="IDX_note_revisions_utcDateCreated">
<index id="87" parent="11" name="IDX_note_revisions_utcDateCreated">
<ColNames>utcDateCreated</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="87" parent="11" name="IDX_note_revisions_dateLastEdited">
<index id="88" parent="11" name="IDX_note_revisions_dateLastEdited">
<ColNames>dateLastEdited</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="88" parent="11" name="IDX_note_revisions_dateCreated">
<index id="89" parent="11" name="IDX_note_revisions_dateCreated">
<ColNames>dateCreated</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<key id="89" parent="11">
<key id="90" parent="11">
<ColNames>noteRevisionId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_note_revisions_1</UnderlyingIndexName>
</key>
<column id="90" parent="12" name="noteId">
<column id="91" parent="12" name="noteId">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="91" parent="12" name="title">
<column id="92" parent="12" name="title">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&quot;note&quot;</DefaultExpression>
</column>
<column id="92" parent="12" name="contentLength">
<column id="93" parent="12" name="contentLength">
<Position>3</Position>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="93" parent="12" name="isProtected">
<column id="94" parent="12" name="isProtected">
<Position>4</Position>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="94" parent="12" name="type">
<column id="95" parent="12" name="type">
<Position>5</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&apos;text&apos;</DefaultExpression>
</column>
<column id="95" parent="12" name="mime">
<column id="96" parent="12" name="mime">
<Position>6</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&apos;text/html&apos;</DefaultExpression>
</column>
<column id="96" parent="12" name="hash">
<column id="97" parent="12" name="hash">
<Position>7</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&quot;&quot;</DefaultExpression>
</column>
<column id="97" parent="12" name="isDeleted">
<column id="98" parent="12" name="isDeleted">
<Position>8</Position>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="98" parent="12" name="isErased">
<column id="99" parent="12" name="isErased">
<Position>9</Position>
<DataType>INT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="99" parent="12" name="dateCreated">
<column id="100" parent="12" name="dateCreated">
<Position>10</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="100" parent="12" name="dateModified">
<column id="101" parent="12" name="dateModified">
<Position>11</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="101" parent="12" name="utcDateCreated">
<column id="102" parent="12" name="utcDateCreated">
<Position>12</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="102" parent="12" name="utcDateModified">
<column id="103" parent="12" name="utcDateModified">
<Position>13</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="103" parent="12" name="sqlite_autoindex_notes_1">
<index id="104" parent="12" name="sqlite_autoindex_notes_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>noteId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<index id="104" parent="12" name="IDX_notes_title">
<index id="105" parent="12" name="IDX_notes_title">
<ColNames>title</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="105" parent="12" name="IDX_notes_type">
<index id="106" parent="12" name="IDX_notes_type">
<ColNames>type</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="106" parent="12" name="IDX_notes_isDeleted">
<index id="107" parent="12" name="IDX_notes_isDeleted">
<ColNames>isDeleted</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="107" parent="12" name="IDX_notes_dateCreated">
<index id="108" parent="12" name="IDX_notes_dateCreated">
<ColNames>dateCreated</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="108" parent="12" name="IDX_notes_dateModified">
<index id="109" parent="12" name="IDX_notes_dateModified">
<ColNames>dateModified</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="109" parent="12" name="IDX_notes_utcDateCreated">
<index id="110" parent="12" name="IDX_notes_utcDateCreated">
<ColNames>utcDateCreated</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<index id="110" parent="12" name="IDX_notes_utcDateModified">
<index id="111" parent="12" name="IDX_notes_utcDateModified">
<ColNames>utcDateModified</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<key id="111" parent="12">
<key id="112" parent="12">
<ColNames>noteId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_notes_1</UnderlyingIndexName>
</key>
<column id="112" parent="13" name="name">
<column id="113" parent="13" name="name">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="113" parent="13" name="value">
<column id="114" parent="13" name="value">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
</column>
<column id="114" parent="13" name="isSynced">
<column id="115" parent="13" name="isSynced">
<Position>3</Position>
<DataType>INTEGER|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>0</DefaultExpression>
</column>
<column id="115" parent="13" name="hash">
<column id="116" parent="13" name="hash">
<Position>4</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&quot;&quot;</DefaultExpression>
</column>
<column id="116" parent="13" name="utcDateCreated">
<column id="117" parent="13" name="utcDateCreated">
<Position>5</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="117" parent="13" name="utcDateModified">
<column id="118" parent="13" name="utcDateModified">
<Position>6</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="118" parent="13" name="sqlite_autoindex_options_1">
<index id="119" parent="13" name="sqlite_autoindex_options_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>name</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="119" parent="13">
<key id="120" parent="13">
<ColNames>name</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_options_1</UnderlyingIndexName>
</key>
<column id="120" parent="14" name="noteId">
<column id="121" parent="14" name="noteId">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="121" parent="14" name="notePath">
<column id="122" parent="14" name="notePath">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="122" parent="14" name="hash">
<column id="123" parent="14" name="hash">
<Position>3</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
<DefaultExpression>&quot;&quot;</DefaultExpression>
</column>
<column id="123" parent="14" name="utcDateCreated">
<column id="124" parent="14" name="utcDateCreated">
<Position>4</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="124" parent="14" name="isDeleted">
<column id="125" parent="14" name="isDeleted">
<Position>5</Position>
<DataType>INT|0s</DataType>
</column>
<index id="125" parent="14" name="sqlite_autoindex_recent_notes_1">
<index id="126" parent="14" name="sqlite_autoindex_recent_notes_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>noteId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="126" parent="14">
<key id="127" parent="14">
<ColNames>noteId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_recent_notes_1</UnderlyingIndexName>
</key>
<column id="127" parent="15" name="sourceId">
<column id="128" parent="15" name="sourceId">
<Position>1</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="128" parent="15" name="utcDateCreated">
<column id="129" parent="15" name="utcDateCreated">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="129" parent="15" name="sqlite_autoindex_source_ids_1">
<index id="130" parent="15" name="sqlite_autoindex_source_ids_1">
<NameSurrogate>1</NameSurrogate>
<ColNames>sourceId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<key id="130" parent="15">
<key id="131" parent="15">
<ColNames>sourceId</ColNames>
<Primary>1</Primary>
<UnderlyingIndexName>sqlite_autoindex_source_ids_1</UnderlyingIndexName>
</key>
<column id="131" parent="16" name="type">
<column id="132" parent="16" name="type">
<Position>1</Position>
<DataType>text|0s</DataType>
</column>
<column id="132" parent="16" name="name">
<column id="133" parent="16" name="name">
<Position>2</Position>
<DataType>text|0s</DataType>
</column>
<column id="133" parent="16" name="tbl_name">
<column id="134" parent="16" name="tbl_name">
<Position>3</Position>
<DataType>text|0s</DataType>
</column>
<column id="134" parent="16" name="rootpage">
<column id="135" parent="16" name="rootpage">
<Position>4</Position>
<DataType>int|0s</DataType>
</column>
<column id="135" parent="16" name="sql">
<column id="136" parent="16" name="sql">
<Position>5</Position>
<DataType>text|0s</DataType>
</column>
<column id="136" parent="17" name="name">
<column id="137" parent="17" name="name">
<Position>1</Position>
</column>
<column id="137" parent="17" name="seq">
<column id="138" parent="17" name="seq">
<Position>2</Position>
</column>
<column id="138" parent="18" name="id">
<column id="139" parent="18" name="id">
<Position>1</Position>
<DataType>INTEGER|0s</DataType>
<NotNull>1</NotNull>
<SequenceIdentity>1</SequenceIdentity>
</column>
<column id="139" parent="18" name="entityName">
<column id="140" parent="18" name="entityName">
<Position>2</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="140" parent="18" name="entityId">
<column id="141" parent="18" name="entityId">
<Position>3</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="141" parent="18" name="sourceId">
<column id="142" parent="18" name="sourceId">
<Position>4</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<column id="142" parent="18" name="utcSyncDate">
<column id="143" parent="18" name="utcSyncDate">
<Position>5</Position>
<DataType>TEXT|0s</DataType>
<NotNull>1</NotNull>
</column>
<index id="143" parent="18" name="IDX_sync_entityName_entityId">
<index id="144" parent="18" name="IDX_sync_entityName_entityId">
<ColNames>entityName
entityId</ColNames>
<ColumnCollations></ColumnCollations>
<Unique>1</Unique>
</index>
<index id="144" parent="18" name="IDX_sync_utcSyncDate">
<index id="145" parent="18" name="IDX_sync_utcSyncDate">
<ColNames>utcSyncDate</ColNames>
<ColumnCollations></ColumnCollations>
</index>
<key id="145" parent="18">
<key id="146" parent="18">
<ColNames>id</ColNames>
<Primary>1</Primary>
</key>

View File

@ -0,0 +1,26 @@
CREATE TABLE IF NOT EXISTS "note_revisions_mig" (`noteRevisionId` TEXT NOT NULL PRIMARY KEY,
`noteId` TEXT NOT NULL,
`title` TEXT,
`contentLength` INT NOT NULL,
`isErased` INT NOT NULL DEFAULT 0,
`isProtected` INT NOT NULL DEFAULT 0,
`utcDateLastEdited` TEXT NOT NULL,
`utcDateCreated` TEXT NOT NULL,
`utcDateModified` TEXT NOT NULL,
`dateLastEdited` TEXT NOT NULL,
`dateCreated` TEXT NOT NULL,
type TEXT DEFAULT '' NOT NULL,
mime TEXT DEFAULT '' NOT NULL,
hash TEXT DEFAULT '' NOT NULL);
INSERT INTO note_revisions_mig (noteRevisionId, noteId, title, contentLength, isErased, isProtected, utcDateLastEdited, utcDateCreated, utcDateModified, dateLastEdited, dateCreated, type, mime, hash)
SELECT noteRevisionId, noteId, title, contentLength, 0, isProtected, utcDateLastEdited, utcDateCreated, utcDateModified, dateLastEdited, dateCreated, type, mime, hash FROM note_revisions;
DROP TABLE note_revisions;
ALTER TABLE note_revisions_mig RENAME TO note_revisions;
CREATE INDEX `IDX_note_revisions_noteId` ON `note_revisions` (`noteId`);
CREATE INDEX `IDX_note_revisions_utcDateCreated` ON `note_revisions` (`utcDateCreated`);
CREATE INDEX `IDX_note_revisions_utcDateLastEdited` ON `note_revisions` (`utcDateLastEdited`);
CREATE INDEX `IDX_note_revisions_dateCreated` ON `note_revisions` (`dateCreated`);
CREATE INDEX `IDX_note_revisions_dateLastEdited` ON `note_revisions` (`dateLastEdited`);

View File

@ -16,8 +16,9 @@ const syncTableService = require('../services/sync_table');
* @property {string} type
* @property {string} mime
* @property {string} title
* @property {int} contentLength - length of content
* @property {string} isProtected
* @property {int} contentLength
* @property {boolean} isErased
* @property {boolean} isProtected
* @property {string} dateLastEdited
* @property {string} dateCreated
* @property {string} utcDateLastEdited
@ -29,7 +30,7 @@ const syncTableService = require('../services/sync_table');
class NoteRevision extends Entity {
static get entityName() { return "note_revisions"; }
static get primaryKeyName() { return "noteRevisionId"; }
static get hashedProperties() { return ["noteRevisionId", "noteId", "title", "contentLength", "isProtected", "dateLastEdited", "dateCreated", "utcDateLastEdited", "utcDateCreated", "utcDateModified"]; }
static get hashedProperties() { return ["noteRevisionId", "noteId", "title", "contentLength", "isErased", "isProtected", "dateLastEdited", "dateCreated", "utcDateLastEdited", "utcDateCreated", "utcDateModified"]; }
constructor(row) {
super(row);
@ -103,7 +104,7 @@ class NoteRevision extends Entity {
async setContent(content) {
// force updating note itself so that utcDateModified is represented correctly even for the content
this.forcedChange = true;
this.contentLength = content.length;
this.contentLength = content === null ? 0 : content.length;
await this.save();
this.content = content;

View File

@ -1,12 +1,14 @@
import noteDetailService from '../services/note_detail.js';
import utils from '../services/utils.js';
import server from '../services/server.js';
import toastService from "../services/toast.js";
const $dialog = $("#note-revisions-dialog");
const $list = $("#note-revision-list");
const $content = $("#note-revision-content");
const $title = $("#note-revision-title");
const $titleButtons = $("#note-revision-title-buttons");
const $eraseAllRevisionsButton = $("#note-revisions-erase-all-revisions-button");
let revisionItems = [];
let note;
@ -22,6 +24,10 @@ export async function showNoteRevisionsDialog(noteId, noteRevisionId) {
$dialog.modal();
await loadNoteRevisions(noteId, noteRevisionId);
}
async function loadNoteRevisions(noteId, noteRevisionId) {
$list.empty();
$content.empty();
@ -31,7 +37,7 @@ export async function showNoteRevisionsDialog(noteId, noteRevisionId) {
for (const item of revisionItems) {
$list.append($('<option>', {
value: item.noteRevisionId,
text: item.dateLastEdited
text: item.dateLastEdited.substr(0, 16) + (item.isErased ? ' (erased)' : '')
}));
}
@ -41,8 +47,7 @@ export async function showNoteRevisionsDialog(noteId, noteRevisionId) {
}
$list.val(noteRevisionId).trigger('change');
}
else {
} else {
$title.text("No revisions for this note yet...");
}
}
@ -52,15 +57,42 @@ $list.on('change', async () => {
const revisionItem = revisionItems.find(r => r.noteRevisionId === optVal);
$titleButtons.empty();
$content.empty();
if (revisionItem.isErased) {
$title.text('This revision has been erased');
return;
}
$title.html(revisionItem.title);
const $eraseRevisionButton = $('<button class="btn btn-sm" type="button">Erase this revision</button>');
$eraseRevisionButton.on('click', async () => {
const confirmDialog = await import('../dialogs/confirm.js');
const text = 'Do you want to erase this revision? This action will erase revision title and content, but still preserve revision metadata.';
if (await confirmDialog.confirm(text)) {
await server.remove(`notes/${revisionItem.noteId}/revisions/${revisionItem.noteRevisionId}`);
loadNoteRevisions(revisionItem.noteId);
toastService.showMessage('Note revision has been erased.');
}
});
$titleButtons
.append($eraseRevisionButton)
.append(' &nbsp; ');
const $downloadButton = $('<button class="btn btn-sm btn-primary" type="button">Download</button>');
$downloadButton.on('click', () => {
utils.download(utils.getHost() + `/api/notes/${revisionItem.noteId}/revisions/${revisionItem.noteRevisionId}/download`);
});
$titleButtons.html($downloadButton);
$titleButtons.append($downloadButton);
const fullNoteRevision = await server.get(`notes/${revisionItem.noteId}/revisions/${revisionItem.noteRevisionId}`);
@ -104,3 +136,16 @@ $list.on('change', async () => {
$content.text("Preview isn't available for this note type.");
}
});
$eraseAllRevisionsButton.on('click', async () => {
const confirmDialog = await import('../dialogs/confirm.js');
const text = 'Do you want to erase all revision of this note? This action will erase revision title and content, but still preserve revision metadata.';
if (await confirmDialog.confirm(text)) {
await server.remove(`notes/${note.noteId}/revisions`);
$dialog.modal('hide');
toastService.showMessage('Note revisions has been erased.');
}
});

View File

@ -7,13 +7,10 @@ const utils = require('../../services/utils');
const path = require('path');
async function getNoteRevisions(req) {
const {noteId} = req.params;
return await repository.getEntities(`
SELECT note_revisions.*
FROM note_revisions
WHERE noteId = ?
ORDER BY utcDateCreated DESC`, [noteId]);
SELECT * FROM note_revisions
WHERE noteId = ? AND isErased = 0
ORDER BY utcDateCreated DESC`, [req.params.noteId]);
}
async function getNoteRevision(req) {
@ -86,6 +83,31 @@ async function downloadNoteRevision(req, res) {
res.send(await noteRevision.getContent());
}
async function eraseOneNoteRevision(noteRevision) {
noteRevision.isErased = true;
noteRevision.title = null;
await noteRevision.setContent(null);
await noteRevision.save();
}
async function eraseAllNoteRevisions(req) {
const noteRevisionsToErase = await repository.getEntities(
'SELECT * FROM note_revisions WHERE isErased = 0 AND noteId = ?',
[req.params.noteId]);
for (const noteRevision of noteRevisionsToErase) {
await eraseOneNoteRevision(noteRevision);
}
}
async function eraseNoteRevision(req) {
const noteRevision = await repository.getNoteRevision(req.params.noteRevisionId);
if (noteRevision && !noteRevision.isErased) {
await eraseOneNoteRevision(noteRevision);
}
}
async function getEditedNotesOnDate(req) {
const date = req.params.date;
@ -110,5 +132,7 @@ module.exports = {
getNoteRevisions,
getNoteRevision,
downloadNoteRevision,
getEditedNotesOnDate
getEditedNotesOnDate,
eraseAllNoteRevisions,
eraseNoteRevision
};

View File

@ -132,7 +132,9 @@ function register(app) {
apiRoute(PUT, '/api/notes/:noteId/protect/:isProtected', notesApiRoute.protectSubtree);
apiRoute(PUT, /\/api\/notes\/(.*)\/type\/(.*)\/mime\/(.*)/, notesApiRoute.setNoteTypeMime);
apiRoute(GET, '/api/notes/:noteId/revisions', noteRevisionsApiRoute.getNoteRevisions);
apiRoute(DELETE, '/api/notes/:noteId/revisions', noteRevisionsApiRoute.eraseAllNoteRevisions);
apiRoute(GET, '/api/notes/:noteId/revisions/:noteRevisionId', noteRevisionsApiRoute.getNoteRevision);
apiRoute(DELETE, '/api/notes/:noteId/revisions/:noteRevisionId', noteRevisionsApiRoute.eraseNoteRevision);
route(GET, '/api/notes/:noteId/revisions/:noteRevisionId/download', [auth.checkApiAuthOrElectron], noteRevisionsApiRoute.downloadNoteRevision);
apiRoute(POST, '/api/notes/relation-map', notesApiRoute.getRelationMap);
apiRoute(PUT, '/api/notes/:noteId/change-title', notesApiRoute.changeTitle);

View File

@ -4,7 +4,7 @@ const build = require('./build');
const packageJson = require('../../package');
const {TRILIUM_DATA_DIR} = require('./data_dir');
const APP_DB_VERSION = 152;
const APP_DB_VERSION = 153;
const SYNC_VERSION = 11;
const CLIPPER_PROTOCOL_VERSION = "1.0";

View File

@ -470,11 +470,20 @@ async function eraseDeletedNotes() {
utcDateModified = '${utcNowDateTime}'
WHERE noteId IN (???)`, noteIdsToErase);
// deleting first contents since the WHERE relies on isErased = 0
await sql.executeMany(`
UPDATE note_revisions
UPDATE note_revision_contents
SET content = NULL,
utcDateModified = '${utcNowDateTime}'
WHERE noteId IN (???)`, noteIdsToErase);
WHERE noteRevisionId IN
(SELECT noteRevisionId FROM note_revisions WHERE isErased = 0 AND noteId IN ((???)))`, noteIdsToErase);
await sql.executeMany(`
UPDATE note_revisions
SET isErased = 1,
title = NULL,
utcDateModified = '${utcNowDateTime}'
WHERE isErased = 0 AND noteId IN (???)`, noteIdsToErase);
}
async function duplicateNote(noteId, parentNoteId) {

View File

@ -18,6 +18,9 @@ async function updateEntity(sync, entity, sourceId) {
else if (entityName === 'note_revisions') {
await updateNoteRevision(entity, sourceId);
}
else if (entityName === 'note_revision_contents') {
await updateNoteRevisionContent(entity, sourceId);
}
else if (entityName === 'note_reordering') {
await updateNoteReordering(sync.entityId, entity, sourceId);
}

View File

@ -4,6 +4,11 @@
<div class="modal-header">
<h5 class="modal-title mr-auto">Note revisions</h5>
<button class="btn btn-xs"
id="note-revisions-erase-all-revisions-button"
title="Erase all revisions of this note"
style="padding: 0 10px 0 10px;" type="button">Erase all revisions</button>
<button class="help-button" type="button" data-help-page="Note-revisions" title="Help on Note revisions">?</button>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" style="margin-left: 0 !important;">