Skip to content

Commit

Permalink
Desktop: Allow restoring a delete note from note history using comman…
Browse files Browse the repository at this point in the history
…d palette
  • Loading branch information
laurent22 committed Jun 10, 2021
1 parent 00dc1d8 commit 5fd6571
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 4 deletions.
3 changes: 3 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ packages/app-desktop/commands/openProfileDirectory.js.map
packages/app-desktop/commands/replaceMisspelling.d.ts
packages/app-desktop/commands/replaceMisspelling.js
packages/app-desktop/commands/replaceMisspelling.js.map
packages/app-desktop/commands/restoreNoteRevision.d.ts
packages/app-desktop/commands/restoreNoteRevision.js
packages/app-desktop/commands/restoreNoteRevision.js.map
packages/app-desktop/commands/startExternalEditing.d.ts
packages/app-desktop/commands/startExternalEditing.js
packages/app-desktop/commands/startExternalEditing.js.map
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ packages/app-desktop/commands/openProfileDirectory.js.map
packages/app-desktop/commands/replaceMisspelling.d.ts
packages/app-desktop/commands/replaceMisspelling.js
packages/app-desktop/commands/replaceMisspelling.js.map
packages/app-desktop/commands/restoreNoteRevision.d.ts
packages/app-desktop/commands/restoreNoteRevision.js
packages/app-desktop/commands/restoreNoteRevision.js.map
packages/app-desktop/commands/startExternalEditing.d.ts
packages/app-desktop/commands/startExternalEditing.js
packages/app-desktop/commands/startExternalEditing.js.map
Expand Down
1 change: 1 addition & 0 deletions packages/app-desktop/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ const globalCommands = [
require('./commands/stopExternalEditing'),
require('./commands/toggleExternalEditing'),
require('./commands/toggleSafeMode'),
require('./commands/restoreNoteRevision'),
require('@joplin/lib/commands/historyBackward'),
require('@joplin/lib/commands/historyForward'),
require('@joplin/lib/commands/synchronize'),
Expand Down
20 changes: 20 additions & 0 deletions packages/app-desktop/commands/restoreNoteRevision.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
import RevisionService from '@joplin/lib/services/RevisionService';

export const declaration: CommandDeclaration = {
name: 'restoreNoteRevision',
label: 'Restore a note from history',
};

export const runtime = (): CommandRuntime => {
return {
execute: async (_context: CommandContext, noteId: string, reverseRevIndex: number = 0) => {
try {
const note = await RevisionService.instance().restoreNoteById(noteId, reverseRevIndex);
alert(RevisionService.instance().restoreSuccessMessage(note));
} catch (error) {
alert(error.message);
}
},
};
};
4 changes: 2 additions & 2 deletions packages/app-desktop/gui/NoteRevisionViewer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const shared = require('@joplin/lib/components/shared/note-screen-shared.js');
const { MarkupToHtml } = require('@joplin/renderer');
const time = require('@joplin/lib/time').default;
const ReactTooltip = require('react-tooltip');
const { urlDecode, substrWithEllipsis } = require('@joplin/lib/string-utils');
const { urlDecode } = require('@joplin/lib/string-utils');
const bridge = require('electron').remote.require('./bridge').default;
const markupLanguageUtils = require('../utils/markupLanguageUtils').default;

Expand Down Expand Up @@ -75,7 +75,7 @@ class NoteRevisionViewerComponent extends React.PureComponent {
this.setState({ restoring: true });
await RevisionService.instance().importRevisionNote(this.state.note);
this.setState({ restoring: false });
alert(_('The note "%s" has been successfully restored to the notebook "%s".', substrWithEllipsis(this.state.note.title, 0, 32), RevisionService.instance().restoreFolderTitle()));
alert(RevisionService.instance().restoreSuccessMessage(this.state.note));
}

backButton_click() {
Expand Down
21 changes: 19 additions & 2 deletions packages/lib/services/RevisionService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import shim from '../shim';
import BaseService from './BaseService';
import { _ } from '../locale';
import { ItemChangeEntity, NoteEntity, RevisionEntity } from './database/types';
const { substrWithEllipsis } = require('../string-utils');
const { sprintf } = require('sprintf-js');
const { wrapError } = require('../errorUtils');

Expand Down Expand Up @@ -230,7 +231,23 @@ export default class RevisionService extends BaseService {
return folder;
}

async importRevisionNote(note: NoteEntity) {
// reverseRevIndex = 0 means restoring the latest version. reverseRevIndex =
// 1 means the version before that, etc.
public async restoreNoteById(noteId: string, reverseRevIndex: number): Promise<NoteEntity> {
const revisions = await Revision.allByType(BaseModel.TYPE_NOTE, noteId);
if (!revisions.length) throw new Error(`No revision for note "${noteId}"`);

const revIndex = revisions.length - 1 - reverseRevIndex;

const note = await this.revisionNote(revisions, revIndex);
return this.importRevisionNote(note);
}

public restoreSuccessMessage(note: NoteEntity): string {
return _('The note "%s" has been successfully restored to the notebook "%s".', substrWithEllipsis(note.title, 0, 32), this.restoreFolderTitle());
}

async importRevisionNote(note: NoteEntity): Promise<NoteEntity> {
const toImport = Object.assign({}, note);
delete toImport.id;
delete toImport.updated_time;
Expand All @@ -242,7 +259,7 @@ export default class RevisionService extends BaseService {

toImport.parent_id = folder.id;

await Note.save(toImport);
return Note.save(toImport);
}

async maintenance() {
Expand Down

0 comments on commit 5fd6571

Please sign in to comment.