diff --git a/db/migrations/0144__edited_notes_widget.sql b/db/migrations/0144__edited_notes_widget.sql
new file mode 100644
index 000000000..b635c142f
--- /dev/null
+++ b/db/migrations/0144__edited_notes_widget.sql
@@ -0,0 +1,2 @@
+INSERT INTO options (name, value, utcDateCreated, utcDateModified, isSynced)
+VALUES ('editedNotesWidget', '{"enabled":true,"expanded":true,"position":5}', '2018-07-29T18:31:00.874Z', '2018-07-29T18:31:00.874Z', 0);
\ No newline at end of file
diff --git a/src/public/javascripts/dialogs/options/sidebar.js b/src/public/javascripts/dialogs/options/sidebar.js
index 5fc29a712..43cc8a4c5 100644
--- a/src/public/javascripts/dialogs/options/sidebar.js
+++ b/src/public/javascripts/dialogs/options/sidebar.js
@@ -52,7 +52,8 @@ export default class SidebarOptions {
{name: 'noteInfo', title: 'Note info'},
{name: 'noteRevisions', title: 'Note revisions'},
{name: 'whatLinksHere', title: 'What links here'},
- {name: 'similarNotes', title: 'Similar notes'}
+ {name: 'similarNotes', title: 'Similar notes'},
+ {name: 'editedNotes', title: 'Edited notes (only on day note)'}
].map(widget => {
widget.option = this.parseJsonSafely(options[widget.name + 'Widget']) || {
enabled: true,
diff --git a/src/public/javascripts/services/sidebar.js b/src/public/javascripts/services/sidebar.js
index e8fc7f19c..3985a2cb0 100644
--- a/src/public/javascripts/services/sidebar.js
+++ b/src/public/javascripts/services/sidebar.js
@@ -66,7 +66,8 @@ class Sidebar {
import("../widgets/note_revisions.js"),
import("../widgets/attributes.js"),
import("../widgets/what_links_here.js"),
- import("../widgets/similar_notes.js")
+ import("../widgets/similar_notes.js"),
+ import("../widgets/edited_notes.js"),
])).map(m => m.default);
const options = await optionsService.waitForOptions();
diff --git a/src/public/javascripts/widgets/edited_notes.js b/src/public/javascripts/widgets/edited_notes.js
new file mode 100644
index 000000000..a700e7bb1
--- /dev/null
+++ b/src/public/javascripts/widgets/edited_notes.js
@@ -0,0 +1,51 @@
+import StandardWidget from "./standard_widget.js";
+import linkService from "../services/link.js";
+import server from "../services/server.js";
+import treeCache from "../services/tree_cache.js";
+
+class EditedNotesWidget extends StandardWidget {
+ getWidgetTitle() { return "Edited notes on this day"; }
+
+ getMaxHeight() { return "200px"; }
+
+ async isEnabled() {
+ return await this.ctx.note.hasLabel("dateNote");
+ }
+
+ async doRenderBody() {
+ // remember which title was when we found the similar notes
+ this.title = this.ctx.note.title;
+
+ let editedNotes = await server.get('edited-notes/' + await this.ctx.note.getLabelValue("dateNote"));
+
+ editedNotes = editedNotes.filter(note => note.noteId !== this.ctx.note.noteId);
+
+ if (editedNotes.length === 0) {
+ this.$body.text("No edited notes on this day yet ...");
+ return;
+ }
+
+ const noteIds = editedNotes.flatMap(note => note.notePath);
+
+ await treeCache.getNotes(noteIds); // preload all at once
+
+ const $list = $('
');
+
+ for (const editedNote of editedNotes) {
+ const note = await treeCache.getNote(editedNote.noteId);
+
+ if (!note) {
+ continue;
+ }
+
+ const $item = $("- ")
+ .append(editedNote.notePath ? await linkService.createNoteLinkWithPath(editedNote.notePath.join("/")) : editedNote.title);
+
+ $list.append($item);
+ }
+
+ this.$body.empty().append($list);
+ }
+}
+
+export default EditedNotesWidget;
\ No newline at end of file
diff --git a/src/public/javascripts/widgets/standard_widget.js b/src/public/javascripts/widgets/standard_widget.js
index a5596e2c4..5c9c866e6 100644
--- a/src/public/javascripts/widgets/standard_widget.js
+++ b/src/public/javascripts/widgets/standard_widget.js
@@ -26,7 +26,10 @@ class StandardWidget {
this.ctx = ctx;
// construct in camelCase
this.widgetName = this.constructor.name.substr(0, 1).toLowerCase() + this.constructor.name.substr(1);
- this.widgetOptions = options.getJson(this.widgetName) || {};
+ this.widgetOptions = options.getJson(this.widgetName) || {
+ expanded: true
+ };
+
this.state = sidebarState.widgets.find(s => s.name === this.widgetName) || {
expanded: this.widgetOptions.expanded
};
diff --git a/src/routes/api/note_revisions.js b/src/routes/api/note_revisions.js
index 66b90267a..84148248f 100644
--- a/src/routes/api/note_revisions.js
+++ b/src/routes/api/note_revisions.js
@@ -1,12 +1,34 @@
"use strict";
const repository = require('../../services/repository');
+const noteCacheService = require('../../services/note_cache');
async function getNoteRevisions(req) {
const noteId = req.params.noteId;
return await repository.getEntities("SELECT * FROM note_revisions WHERE noteId = ? order by utcDateModifiedTo desc", [noteId]);
}
+async function getEditedNotesOnDate(req) {
+ const date = req.params.date;
+
+ const notes = await repository.getEntities(`
+ select distinct notes.*
+ from notes
+ left join note_revisions using (noteId)
+ where substr(notes.dateCreated, 0, 11) = ?
+ or substr(notes.dateModified, 0, 11) = ?
+ or substr(note_revisions.dateModifiedFrom, 0, 11) = ?`, [date, date, date]);
+
+ for (const note of notes) {
+ const notePath = noteCacheService.getNotePath(note.noteId);
+
+ note.notePath = notePath ? notePath.notePath : null;
+ }
+
+ return notes;
+}
+
module.exports = {
- getNoteRevisions
+ getNoteRevisions,
+ getEditedNotesOnDate
};
\ No newline at end of file
diff --git a/src/routes/api/options.js b/src/routes/api/options.js
index 32fdf81e4..80e70d8c6 100644
--- a/src/routes/api/options.js
+++ b/src/routes/api/options.js
@@ -30,6 +30,7 @@ const ALLOWED_OPTIONS = [
'noteRevisionsWidget',
'whatLinksHereWidget',
'similarNotesWidget',
+ 'editedNotesWidget',
'codeNotesMimeTypes'
];
diff --git a/src/routes/routes.js b/src/routes/routes.js
index bd5fc8c05..45c99054b 100644
--- a/src/routes/routes.js
+++ b/src/routes/routes.js
@@ -135,6 +135,8 @@ function register(app) {
apiRoute(POST, '/api/notes/relation-map', notesApiRoute.getRelationMap);
apiRoute(PUT, '/api/notes/:noteId/change-title', notesApiRoute.changeTitle);
+ apiRoute(GET, '/api/edited-notes/:date', noteRevisionsApiRoute.getEditedNotesOnDate);
+
apiRoute(PUT, '/api/notes/:noteId/clone-to/:parentNoteId', cloningApiRoute.cloneNoteToParent);
apiRoute(PUT, '/api/notes/:noteId/clone-after/:afterBranchId', cloningApiRoute.cloneNoteAfter);
diff --git a/src/services/app_info.js b/src/services/app_info.js
index 671c7a1b0..049ea324b 100644
--- a/src/services/app_info.js
+++ b/src/services/app_info.js
@@ -4,7 +4,7 @@ const build = require('./build');
const packageJson = require('../../package');
const {TRILIUM_DATA_DIR} = require('./data_dir');
-const APP_DB_VERSION = 143;
+const APP_DB_VERSION = 144;
const SYNC_VERSION = 10;
const CLIPPER_PROTOCOL_VERSION = "1.0";
diff --git a/src/services/note_cache.js b/src/services/note_cache.js
index 5368fb09e..d91e36484 100644
--- a/src/services/note_cache.js
+++ b/src/services/note_cache.js
@@ -340,6 +340,7 @@ function getNotePath(noteId) {
noteId: noteId,
branchId: childParentToBranchId[`${noteId}-${parentNoteId}`],
title: noteTitle,
+ notePath: retPath,
path: retPath.join('/')
};
}