diff --git a/public/javascripts/context_menu.js b/public/javascripts/context_menu.js
index ca2af98d5..5659376a5 100644
--- a/public/javascripts/context_menu.js
+++ b/public/javascripts/context_menu.js
@@ -71,7 +71,8 @@ const contextMenu = (function() {
{title: "Paste into Ctrl+V", cmd: "pasteInto", uiIcon: "ui-icon-clipboard"},
{title: "Paste after", cmd: "pasteAfter", uiIcon: "ui-icon-clipboard"},
{title: "----"},
- {title: "Collapse sub-tree Alt+-", cmd: "collapse-sub-tree", uiIcon: "ui-icon-minus"}
+ {title: "Collapse sub-tree Alt+-", cmd: "collapse-sub-tree", uiIcon: "ui-icon-minus"},
+ {title: "Force note sync", cmd: "force-note-sync", uiIcon: "ui-icon-refresh"}
],
beforeOpen: (event, ui) => {
const node = $.ui.fancytree.getNode(ui.target);
@@ -125,6 +126,9 @@ const contextMenu = (function() {
else if (ui.cmd === "collapse-sub-tree") {
noteTree.collapseTree(node);
}
+ else if (ui.cmd === "force-note-sync") {
+ forceNoteSync(node.data.note_id);
+ }
else {
messaging.logError("Unknown command: " + ui.cmd);
}
diff --git a/public/javascripts/sync.js b/public/javascripts/sync.js
index 49f2b33f1..f3fa93005 100644
--- a/public/javascripts/sync.js
+++ b/public/javascripts/sync.js
@@ -13,4 +13,10 @@ async function syncNow() {
showError("Sync failed: " + result.message);
}
+}
+
+async function forceNoteSync(noteId) {
+ const result = await server.post('sync/force-note-sync/' + noteId);
+
+ showMessage("Note added to sync queue.");
}
\ No newline at end of file
diff --git a/routes/api/sync.js b/routes/api/sync.js
index 6646f54a7..bc0c1449d 100644
--- a/routes/api/sync.js
+++ b/routes/api/sync.js
@@ -46,6 +46,30 @@ router.post('/force-full-sync', auth.checkApiAuth, async (req, res, next) => {
res.send({});
});
+router.post('/force-note-sync/:noteId', auth.checkApiAuth, async (req, res, next) => {
+ const noteId = req.params.noteId;
+
+ await sql.doInTransaction(async () => {
+ await sync_table.addNoteSync(noteId);
+
+ for (const noteTreeId of await sql.getFirstColumn("SELECT note_tree_id FROM notes_tree WHERE is_deleted = 0 AND note_id = ?", [noteId])) {
+ await sync_table.addNoteTreeSync(noteTreeId);
+ await sync_table.addRecentNoteSync(noteTreeId);
+ }
+
+ for (const noteHistoryId of await sql.getFirstColumn("SELECT note_history_id FROM notes_history WHERE note_id = ?", [noteId])) {
+ await sync_table.addNoteTreeSync(noteHistoryId);
+ }
+ });
+
+ log.info("Forcing note sync for " + noteId);
+
+ // not awaiting for the job to finish (will probably take a long time)
+ sync.sync();
+
+ res.send({});
+});
+
router.get('/changed', auth.checkApiAuth, async (req, res, next) => {
const lastSyncId = parseInt(req.query.lastSyncId);
diff --git a/services/sync_table.js b/services/sync_table.js
index 960f4b7f9..b195d6c5f 100644
--- a/services/sync_table.js
+++ b/services/sync_table.js
@@ -24,8 +24,8 @@ async function addOptionsSync(optName, sourceId) {
await addEntitySync("options", optName, sourceId);
}
-async function addRecentNoteSync(notePath, sourceId) {
- await addEntitySync("recent_notes", notePath, sourceId);
+async function addRecentNoteSync(noteTreeId, sourceId) {
+ await addEntitySync("recent_notes", noteTreeId, sourceId);
}
async function addEntitySync(entityName, entityId, sourceId) {