diff --git a/.idea/dataSources/a2c75661-f9e2-478f-a69f-6a9409e69997.xml b/.idea/dataSources/a2c75661-f9e2-478f-a69f-6a9409e69997.xml
index e0790da91..22d1652a1 100644
--- a/.idea/dataSources/a2c75661-f9e2-478f-a69f-6a9409e69997.xml
+++ b/.idea/dataSources/a2c75661-f9e2-478f-a69f-6a9409e69997.xml
@@ -57,7 +57,6 @@
1
apiTokenId
-
1
@@ -126,25 +125,20 @@
1
attributeId
-
1
noteId
-
name
value
-
name
-
value
-
attributeId
@@ -204,21 +198,17 @@ value
1
branchId
-
1
noteId
parentNoteId
-
noteId
-
parentNoteId
-
branchId
@@ -246,7 +236,6 @@ parentNoteId
1
eventId
-
1
@@ -278,7 +267,6 @@ parentNoteId
1
noteId
-
1
@@ -351,20 +339,16 @@ parentNoteId
1
noteRevisionId
-
1
noteId
-
utcDateModifiedFrom
-
utcDateModifiedTo
-
noteRevisionId
@@ -435,7 +419,6 @@ parentNoteId
1
noteId
-
1
@@ -477,7 +460,6 @@ parentNoteId
1
name
-
1
@@ -513,7 +495,6 @@ parentNoteId
1
noteId
-
1
@@ -534,7 +515,6 @@ parentNoteId
1
sourceId
-
1
@@ -597,12 +577,10 @@ parentNoteId
entityName
entityId
-
1
utcSyncDate
-
id
diff --git a/src/public/javascripts/dialogs/export.js b/src/public/javascripts/dialogs/export.js
index 65929e3fe..99c40cf08 100644
--- a/src/public/javascripts/dialogs/export.js
+++ b/src/public/javascripts/dialogs/export.js
@@ -15,14 +15,14 @@ const $exportProgressCount = $("#export-progress-count");
const $exportButton = $("#export-button");
const $opmlVersions = $("#opml-versions");
-let exportId = '';
+let taskId = '';
let branchId = null;
export async function showDialog(node, defaultType) {
utils.closeActiveDialog();
- // each opening of the dialog resets the exportId so we don't associate it with previous exports anymore
- exportId = '';
+ // each opening of the dialog resets the taskId so we don't associate it with previous exports anymore
+ taskId = '';
$exportButton.removeAttr("disabled");
$exportProgressWrapper.hide();
$exportProgressCount.text('0');
@@ -77,9 +77,9 @@ $form.submit(() => {
});
function exportBranch(branchId, type, format, version) {
- exportId = utils.randomString(10);
+ taskId = utils.randomString(10);
- const url = utils.getHost() + `/api/notes/${branchId}/export/${type}/${format}/${version}/${exportId}`;
+ const url = utils.getHost() + `/api/notes/${branchId}/export/${type}/${format}/${version}/${taskId}`;
utils.download(url);
}
@@ -113,23 +113,23 @@ $('input[name=export-subtree-format]').change(function () {
});
ws.subscribeToMessages(async message => {
- if (message.type === 'export-error') {
+ if (message.type === 'task-error' && message.taskType === 'export') {
infoService.showError(message.message);
$dialog.modal('hide');
return;
}
- if (!message.exportId || message.exportId !== exportId) {
+ if (!message.taskId || message.taskId !== taskId) {
// incoming messages must correspond to this export instance
return;
}
- if (message.type === 'export-progress-count') {
+ if (message.type === 'task-progress-count' && message.taskType === 'export') {
$exportProgressWrapper.slideDown();
$exportProgressCount.text(message.progressCount);
}
- else if (message.type === 'export-finished') {
+ else if (message.type === 'task-succeeded' && message.taskType === 'export') {
$dialog.modal('hide');
infoService.showMessage("Export finished successfully.");
diff --git a/src/routes/api/export.js b/src/routes/api/export.js
index 4117800c1..b38be0041 100644
--- a/src/routes/api/export.js
+++ b/src/routes/api/export.js
@@ -4,64 +4,24 @@ const tarExportService = require('../../services/export/tar');
const singleExportService = require('../../services/export/single');
const opmlExportService = require('../../services/export/opml');
const repository = require("../../services/repository");
-const ws = require("../../services/ws.js");
+const TaskContext = require("../../services/task_context");
const log = require("../../services/log");
-class ExportContext {
- constructor(exportId) {
- // exportId is to distinguish between different export events - it is possible (though not recommended)
- // to have multiple exports going at the same time
- this.exportId = exportId;
- // count is mean to represent count of exported notes where practical, otherwise it's just some measure of progress
- this.progressCount = 0;
- this.lastSentCountTs = Date.now();
- }
-
- async increaseProgressCount() {
- this.progressCount++;
-
- if (Date.now() - this.lastSentCountTs >= 500) {
- this.lastSentCountTs = Date.now();
-
- await ws.sendMessageToAllClients({
- exportId: this.exportId,
- type: 'export-progress-count',
- progressCount: this.progressCount
- });
- }
- }
-
- async exportFinished() {
- await ws.sendMessageToAllClients({
- exportId: this.exportId,
- type: 'export-finished'
- });
- }
-
- // must remaing non-static
- async reportError(message) {
- await ws.sendMessageToAllClients({
- type: 'export-error',
- message: message
- });
- }
-}
-
async function exportBranch(req, res) {
- const {branchId, type, format, version, exportId} = req.params;
+ const {branchId, type, format, version, taskId} = req.params;
const branch = await repository.getBranch(branchId);
- const exportContext = new ExportContext(exportId);
+ const taskContext = new TaskContext(taskId, 'export');
try {
if (type === 'subtree' && (format === 'html' || format === 'markdown')) {
- await tarExportService.exportToTar(exportContext, branch, format, res);
+ await tarExportService.exportToTar(taskContext, branch, format, res);
}
else if (type === 'single') {
- await singleExportService.exportSingleNote(exportContext, branch, format, res);
+ await singleExportService.exportSingleNote(taskContext, branch, format, res);
}
else if (format === 'opml') {
- await opmlExportService.exportToOpml(exportContext, branch, version, res);
+ await opmlExportService.exportToOpml(taskContext, branch, version, res);
}
else {
return [404, "Unrecognized export format " + format];
@@ -69,7 +29,7 @@ async function exportBranch(req, res) {
}
catch (e) {
const message = "Export failed with following error: '" + e.message + "'. More details might be in the logs.";
- exportContext.reportError(message);
+ taskContext.reportError(message);
log.error(message + e.stack);
diff --git a/src/routes/api/notes.js b/src/routes/api/notes.js
index d5ff4b298..4695cb1e6 100644
--- a/src/routes/api/notes.js
+++ b/src/routes/api/notes.js
@@ -3,6 +3,8 @@
const noteService = require('../../services/notes');
const treeService = require('../../services/tree');
const repository = require('../../services/repository');
+const utils = require('../../services/utils');
+const TaskContext = require('../../services/task_context');
async function getNote(req) {
const noteId = req.params.noteId;
@@ -76,8 +78,10 @@ async function deleteNote(req) {
const note = await repository.getNote(noteId);
+ const taskContext = new TaskContext(utils.randomString(10), 'delete-note');
+
for (const branch of await note.getBranches()) {
- await noteService.deleteBranch(branch);
+ await noteService.deleteBranch(branch, taskContext);
}
}
diff --git a/src/routes/routes.js b/src/routes/routes.js
index b9df8fe5c..3f48807f4 100644
--- a/src/routes/routes.js
+++ b/src/routes/routes.js
@@ -141,7 +141,7 @@ function register(app) {
apiRoute(PUT, '/api/notes/:noteId/clone-to/:parentNoteId', cloningApiRoute.cloneNoteToParent);
apiRoute(PUT, '/api/notes/:noteId/clone-after/:afterBranchId', cloningApiRoute.cloneNoteAfter);
- route(GET, '/api/notes/:branchId/export/:type/:format/:version/:exportId', [auth.checkApiAuthOrElectron], exportRoute.exportBranch);
+ route(GET, '/api/notes/:branchId/export/:type/:format/:version/:taskId', [auth.checkApiAuthOrElectron], exportRoute.exportBranch);
route(POST, '/api/notes/:parentNoteId/import', [auth.checkApiAuthOrElectron, uploadMiddleware, csrfMiddleware], importRoute.importToBranch, apiResultHandler);
route(POST, '/api/notes/:parentNoteId/upload', [auth.checkApiAuthOrElectron, uploadMiddleware, csrfMiddleware],
diff --git a/src/services/export/opml.js b/src/services/export/opml.js
index 684da5ed6..16399da5b 100644
--- a/src/services/export/opml.js
+++ b/src/services/export/opml.js
@@ -3,7 +3,7 @@
const repository = require("../repository");
const utils = require('../utils');
-async function exportToOpml(exportContext, branch, version, res) {
+async function exportToOpml(taskContext, branch, version, res) {
if (!['1.0', '2.0'].includes(version)) {
throw new Error("Unrecognized OPML version " + version);
}
@@ -38,7 +38,7 @@ async function exportToOpml(exportContext, branch, version, res) {
throw new Error("Unrecognized OPML version " + opmlVersion);
}
- exportContext.increaseProgressCount();
+ taskContext.increaseProgressCount();
for (const child of await note.getChildBranches()) {
await exportNoteInner(child.branchId);
@@ -66,7 +66,7 @@ async function exportToOpml(exportContext, branch, version, res) {
`);
res.end();
- exportContext.exportFinished();
+ taskContext.taskSucceeded();
}
function prepareText(text) {
diff --git a/src/services/export/single.js b/src/services/export/single.js
index ebec3d48b..85ad1c0c7 100644
--- a/src/services/export/single.js
+++ b/src/services/export/single.js
@@ -5,7 +5,7 @@ const html = require('html');
const utils = require('../utils');
const mdService = require('./md');
-async function exportSingleNote(exportContext, branch, format, res) {
+async function exportSingleNote(taskContext, branch, format, res) {
const note = await branch.getNote();
if (note.type === 'image' || note.type === 'file') {
@@ -54,8 +54,8 @@ async function exportSingleNote(exportContext, branch, format, res) {
res.send(payload);
- exportContext.increaseProgressCount();
- exportContext.exportFinished();
+ taskContext.increaseProgressCount();
+ taskContext.taskSucceeded();
}
module.exports = {
diff --git a/src/services/export/tar.js b/src/services/export/tar.js
index 803d7e147..36481bf63 100644
--- a/src/services/export/tar.js
+++ b/src/services/export/tar.js
@@ -12,11 +12,11 @@ const protectedSessionService = require('../protected_session');
const sanitize = require("sanitize-filename");
/**
- * @param {ExportContext} exportContext
+ * @param {TaskContext} taskContext
* @param {Branch} branch
* @param {string} format - 'html' or 'markdown'
*/
-async function exportToTar(exportContext, branch, format, res) {
+async function exportToTar(taskContext, branch, format, res) {
const pack = tar.pack();
const noteIdToMeta = {};
@@ -124,7 +124,7 @@ async function exportToTar(exportContext, branch, format, res) {
})
};
- exportContext.increaseProgressCount();
+ taskContext.increaseProgressCount();
if (note.type === 'text') {
meta.format = format;
@@ -268,7 +268,7 @@ ${content}
pack.entry({name: filePathPrefix + noteMeta.dataFileName, size: content.length}, content);
}
- exportContext.increaseProgressCount();
+ taskContext.increaseProgressCount();
if (noteMeta.children && noteMeta.children.length > 0) {
const directoryPath = filePathPrefix + noteMeta.dirFileName;
@@ -315,7 +315,7 @@ ${content}
pack.pipe(res);
- exportContext.exportFinished();
+ taskContext.taskSucceeded();
}
module.exports = {
diff --git a/src/services/notes.js b/src/services/notes.js
index 853827f42..7123f639e 100644
--- a/src/services/notes.js
+++ b/src/services/notes.js
@@ -390,7 +390,9 @@ async function updateNote(noteId, noteUpdates) {
}
/** @return {boolean} - true if note has been deleted, false otherwise */
-async function deleteBranch(branch) {
+async function deleteBranch(branch, taskContext) {
+ taskContext.increaseProgressCount();
+
if (!branch || branch.isDeleted) {
return false;
}
@@ -413,7 +415,7 @@ async function deleteBranch(branch) {
await note.save();
for (const childBranch of await note.getChildBranches()) {
- await deleteBranch(childBranch);
+ await deleteBranch(childBranch, taskContext);
}
for (const attribute of await note.getOwnedAttributes()) {