diff --git a/src/public/app/services/tree_context_menu.js b/src/public/app/services/tree_context_menu.js
index 086beb2cb..a027a79eb 100644
--- a/src/public/app/services/tree_context_menu.js
+++ b/src/public/app/services/tree_context_menu.js
@@ -130,7 +130,17 @@ class TreeContextMenu {
this.treeWidget.triggerCommand("openNewNoteSplit", {ntxId, notePath});
}
else {
- this.treeWidget.triggerCommand(command, {node: this.node, notePath: notePath});
+ const selectedOrActiveBranchIds = this.treeWidget.getSelectedOrActiveBranchIds(this.node);
+ const selectedOrActiveNoteIds = selectedOrActiveBranchIds
+ .map(branchId => froca.getBranch(branchId).noteId)
+ .filter(noteId => !!noteId);
+
+ this.treeWidget.triggerCommand(command, {
+ node: this.node,
+ notePath: notePath,
+ selectedOrActiveBranchIds,
+ selectedOrActiveNoteIds
+ });
}
}
}
diff --git a/src/public/app/widgets/bulk_actions/label/add_label.js b/src/public/app/widgets/bulk_actions/label/add_label.js
index 85a026d3e..8e120e0ce 100644
--- a/src/public/app/widgets/bulk_actions/label/add_label.js
+++ b/src/public/app/widgets/bulk_actions/label/add_label.js
@@ -55,7 +55,7 @@ export default class AddLabelBulkAction extends AbstractBulkAction {
labelName: $labelName.val(),
labelValue: $labelValue.val()
});
- }, 1000)
+ }, 1000);
$labelName.on('input', () => spacedUpdate.scheduleUpdate());
$labelValue.on('input', () => spacedUpdate.scheduleUpdate());
diff --git a/src/public/app/widgets/dialogs/bulk_actions.js b/src/public/app/widgets/dialogs/bulk_actions.js
index 54b9537f6..df179c1f7 100644
--- a/src/public/app/widgets/dialogs/bulk_actions.js
+++ b/src/public/app/widgets/dialogs/bulk_actions.js
@@ -2,6 +2,8 @@ import BasicWidget from "../basic_widget.js";
import froca from "../../services/froca.js";
import bulkActionService from "../../services/bulk_action.js";
import utils from "../../services/utils.js";
+import server from "../../services/server.js";
+import toastService from "../../services/toast.js";
const TPL = `
@@ -60,7 +62,7 @@ const TPL = `
@@ -79,6 +81,15 @@ export default class BulkActionsDialog extends BasicWidget {
await this.refresh();
});
+
+ this.$executeButton = this.$widget.find(".execute-bulk-actions");
+ this.$executeButton.on("click", async () => {
+ await server.post("bulk-action", { noteIds: this.selectedOrActiveNoteIds });
+
+ toastService.showMessage("Bulk actions have been executed successfully.", 3000);
+
+ utils.closeActiveDialog();
+ });
}
async refresh() {
@@ -119,12 +130,15 @@ export default class BulkActionsDialog extends BasicWidget {
}
entitiesReloadedEvent({loadResults}) {
- if (loadResults.getAttributes().find(attr => attr.type === 'label' && attr.name === 'action')) {
+ // only refreshing deleted attrs, otherwise components update themselves
+ if (loadResults.getAttributes().find(attr => attr.type === 'label' && attr.name === 'action' && attr.isDeleted)) {
this.refresh();
}
}
- async bulkActionsEvent({node}) {
+ async bulkActionsEvent({selectedOrActiveNoteIds}) {
+ this.selectedOrActiveNoteIds = selectedOrActiveNoteIds;
+
await this.refresh();
utils.openDialog(this.$widget);
diff --git a/src/public/app/widgets/ribbon_widgets/search_definition.js b/src/public/app/widgets/ribbon_widgets/search_definition.js
index eb05c5bb9..3c1451313 100644
--- a/src/public/app/widgets/ribbon_widgets/search_definition.js
+++ b/src/public/app/widgets/ribbon_widgets/search_definition.js
@@ -307,7 +307,8 @@ export default class SearchDefinitionWidget extends NoteContextAwareWidget {
}
entitiesReloadedEvent({loadResults}) {
- if (loadResults.getAttributes().find(attr => attr.type === 'label' && attr.name === 'action')) {
+ // only refreshing deleted attrs, otherwise components update themselves
+ if (loadResults.getAttributes().find(attr => attr.type === 'label' && attr.name === 'action' && attr.isDeleted)) {
this.refresh();
}
}
diff --git a/src/routes/api/bulk_action.js b/src/routes/api/bulk_action.js
new file mode 100644
index 000000000..20104a46b
--- /dev/null
+++ b/src/routes/api/bulk_action.js
@@ -0,0 +1,14 @@
+const becca = require("../../becca/becca");
+const bulkActionService = require("../../services/bulk_actions");
+
+function execute(req) {
+ const {noteIds} = req.body;
+
+ const bulkActionNote = becca.getNote('bulkaction');
+
+ bulkActionService.executeActions(bulkActionNote, noteIds);
+}
+
+module.exports = {
+ execute
+};
diff --git a/src/routes/routes.js b/src/routes/routes.js
index 29aaf93a1..543c3822c 100644
--- a/src/routes/routes.js
+++ b/src/routes/routes.js
@@ -31,6 +31,7 @@ const scriptRoute = require('./api/script');
const senderRoute = require('./api/sender');
const filesRoute = require('./api/files');
const searchRoute = require('./api/search');
+const bulkActionRoute = require('./api/bulk_action');
const specialNotesRoute = require('./api/special_notes');
const noteMapRoute = require('./api/note_map');
const clipperRoute = require('./api/clipper');
@@ -357,6 +358,8 @@ function register(app) {
apiRoute(GET, '/api/search/:searchString', searchRoute.search);
apiRoute(GET, '/api/search-templates', searchRoute.searchTemplates);
+ apiRoute(POST, '/api/bulk-action', bulkActionRoute.execute);
+
route(POST, '/api/login/sync', [], loginApiRoute.loginSync, apiResultHandler);
// this is for entering protected mode so user has to be already logged-in (that's the reason we don't require username)
apiRoute(POST, '/api/login/protected', loginApiRoute.loginToProtectedSession);