Skip to content

All: Support for note history (WIP) #1415

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
May 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
fb73ef7
Started revisions support
laurent22 Apr 4, 2019
8712dfa
More rev changes
laurent22 Apr 4, 2019
baff7ae
More rev changes
laurent22 Apr 4, 2019
337bdb2
More revs changes
laurent22 Apr 6, 2019
b6e2f3f
Fixed deletion algorithm
laurent22 Apr 6, 2019
228e596
More tests and moved updated time to separate field
laurent22 Apr 7, 2019
4a7664d
Display info when restoring note
laurent22 Apr 8, 2019
7c744a4
Better handling of existing notes
laurent22 Apr 9, 2019
b461fe9
wip
laurent22 Apr 12, 2019
0f88a92
Further improvements and fixed tests
laurent22 Apr 12, 2019
ba7c309
Better handling of changes created via sync
laurent22 Apr 12, 2019
0ac5cca
Enable chokidar again
laurent22 Apr 12, 2019
b3633ba
Testing special case
laurent22 Apr 13, 2019
f1e2f82
Further improved logic to handle notes that existed before the revisi…
laurent22 Apr 28, 2019
3202d98
Merge branch 'master' into revisions
laurent22 Apr 28, 2019
0a58332
Added tests
laurent22 Apr 28, 2019
113c68b
Merge branch 'master' into revisions
laurent22 Apr 28, 2019
20be38a
Better handling of encrypted revisions
laurent22 Apr 28, 2019
2ae6943
Improved handling of deleted note revisions by moving logic to collec…
laurent22 Apr 28, 2019
2c41cf3
Improved handling of old notes by moving logic to collectRevision()
laurent22 Apr 29, 2019
0da91ba
Handle case when deleting revisions while one is still encrypted
laurent22 Apr 29, 2019
bbc2143
UI tweaks
laurent22 Apr 29, 2019
316d6b5
Added revision service to mobile app
laurent22 May 1, 2019
be150f0
Fixed config screens on mobile and desktop
laurent22 May 3, 2019
cf95d36
Merge branch 'master' into revisions
laurent22 May 3, 2019
5542101
Enabled revisions on CLI app
laurent22 May 6, 2019
a01a1cd
Merge branch 'master' into revisions
laurent22 May 6, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CliClient/app/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const fs = require('fs-extra');
const { cliUtils } = require('./cli-utils.js');
const Cache = require('lib/Cache');
const WelcomeUtils = require('lib/WelcomeUtils');
const RevisionService = require('lib/services/RevisionService');

class Application extends BaseApplication {

Expand Down Expand Up @@ -422,6 +423,8 @@ class Application extends BaseApplication {
const tags = await Tag.allWithNotes();

ResourceService.runInBackground();

RevisionService.instance().runInBackground();

this.dispatch({
type: 'TAG_UPDATE_ALL',
Expand Down
2 changes: 2 additions & 0 deletions CliClient/app/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const Tag = require('lib/models/Tag.js');
const NoteTag = require('lib/models/NoteTag.js');
const MasterKey = require('lib/models/MasterKey');
const Setting = require('lib/models/Setting.js');
const Revision = require('lib/models/Revision.js');
const { Logger } = require('lib/logger.js');
const { FsDriverNode } = require('lib/fs-driver-node.js');
const { shimInit } = require('lib/shim-init-node.js');
Expand All @@ -43,6 +44,7 @@ BaseItem.loadClass('Resource', Resource);
BaseItem.loadClass('Tag', Tag);
BaseItem.loadClass('NoteTag', NoteTag);
BaseItem.loadClass('MasterKey', MasterKey);
BaseItem.loadClass('Revision', Revision);

Setting.setConstant('appId', 'net.cozic.joplin-cli');
Setting.setConstant('appType', 'cli');
Expand Down
7 changes: 6 additions & 1 deletion CliClient/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions CliClient/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"base-64": "^0.1.0",
"compare-version": "^0.1.2",
"diacritics": "^1.3.0",
"diff-match-patch": "^1.0.4",
"es6-promise-pool": "^2.5.0",
"follow-redirects": "^1.2.4",
"form-data": "^2.1.4",
Expand Down
2 changes: 2 additions & 0 deletions CliClient/run_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@ npm test tests-build/models_Folder.js
npm test tests-build/models_ItemChange.js
npm test tests-build/models_Note.js
npm test tests-build/models_Resource.js
npm test tests-build/models_Revision.js
npm test tests-build/models_Setting.js
npm test tests-build/models_Tag.js
npm test tests-build/pathUtils.js
npm test tests-build/services_InteropService.js
npm test tests-build/services_ResourceService.js
npm test tests-build/services_rest_Api.js
npm test tests-build/services_SearchEngine.js
npm test tests-build/services_Revision.js
npm test tests-build/StringUtils.js
npm test tests-build/synchronizer.js
npm test tests-build/urlUtils.js
3 changes: 1 addition & 2 deletions CliClient/tests/encryption.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ describe('Encryption', function() {

beforeEach(async (done) => {
await setupDatabaseAndSynchronizer(1);
//await setupDatabaseAndSynchronizer(2);
//await switchClient(1);
await switchClient(1);
service = new EncryptionService();
BaseItem.encryptionService_ = service;
Setting.setValue('encryption.enabled', true);
Expand Down
10 changes: 4 additions & 6 deletions CliClient/tests/models_ItemChange.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require('app-module-path').addPath(__dirname);

const { time } = require('lib/time-utils.js');
const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
const { asyncTest, fileContentEqual, revisionService, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
const SearchEngine = require('lib/services/SearchEngine');
const ResourceService = require('lib/services/ResourceService');
const ItemChangeUtils = require('lib/services/ItemChangeUtils');
Expand Down Expand Up @@ -34,19 +34,17 @@ describe('models_ItemChange', function() {
const resourceService = new ResourceService();

await searchEngine.syncTables();

// If we run this now, it should not delete any change because
// the resource service has not yet processed the change
await ItemChangeUtils.deleteProcessedChanges();

expect(await ItemChange.lastChangeId()).toBe(1);

await resourceService.indexNoteResources();

// Now that the resource service has processed the change,
// the change can be deleted.
await ItemChangeUtils.deleteProcessedChanges();
expect(await ItemChange.lastChangeId()).toBe(1);

await revisionService().collectRevisions();
await ItemChangeUtils.deleteProcessedChanges();
expect(await ItemChange.lastChangeId()).toBe(0);
}));

Expand Down
71 changes: 71 additions & 0 deletions CliClient/tests/models_Revision.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
require('app-module-path').addPath(__dirname);

const { time } = require('lib/time-utils.js');
const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
const Folder = require('lib/models/Folder.js');
const Note = require('lib/models/Note.js');
const NoteTag = require('lib/models/NoteTag.js');
const Tag = require('lib/models/Tag.js');
const Revision = require('lib/models/Revision.js');
const BaseModel = require('lib/BaseModel.js');
const { shim } = require('lib/shim');

process.on('unhandledRejection', (reason, p) => {
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
});

describe('models_Revision', function() {

beforeEach(async (done) => {
await setupDatabaseAndSynchronizer(1);
await switchClient(1);
done();
});

it('should create patches of text and apply it', asyncTest(async () => {
const note1 = await Note.save({ body: 'my note\nsecond line' });

const patch = Revision.createTextPatch(note1.body, 'my new note\nsecond line');
const merged = Revision.applyTextPatch(note1.body, patch);

expect(merged).toBe('my new note\nsecond line');
}));

it('should create patches of objects and apply it', asyncTest(async () => {
const oldObject = {
one: '123',
two: '456',
three: '789',
};

const newObject = {
one: '123',
three: '999',
}

const patch = Revision.createObjectPatch(oldObject, newObject);
const merged = Revision.applyObjectPatch(oldObject, patch);

expect(JSON.stringify(merged)).toBe(JSON.stringify(newObject));
}));

it('should move target revision to the top', asyncTest(async () => {
const revs = [
{ id: '123' },
{ id: '456' },
{ id: '789' },
];

let newRevs;
newRevs = Revision.moveRevisionToTop({ id: '456' }, revs);
expect(newRevs[0].id).toBe('123');
expect(newRevs[1].id).toBe('789');
expect(newRevs[2].id).toBe('456');

newRevs = Revision.moveRevisionToTop({ id: '789' }, revs);
expect(newRevs[0].id).toBe('123');
expect(newRevs[1].id).toBe('456');
expect(newRevs[2].id).toBe('789');
}));

});
Loading