calculate affected counts and take into account includeDescendants when executing

This commit is contained in:
zadam 2022-06-12 10:35:30 +02:00
parent 63f0e441b9
commit 1bfc5fb77f
3 changed files with 59 additions and 7 deletions

View File

@ -47,8 +47,8 @@ const TPL = `
<h4>Affected notes: <span class="affected-note-count">0</span></h4> <h4>Affected notes: <span class="affected-note-count">0</span></h4>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" value="" class="include-descendants"> <label class="form-check-label">
<label class="form-check-label" for="include-descendants"> <input class="include-descendants form-check-input" type="checkbox" value="">
Include descendant notes Include descendant notes
</label> </label>
</div> </div>
@ -71,6 +71,12 @@ const TPL = `
export default class BulkActionsDialog extends BasicWidget { export default class BulkActionsDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.$includeDescendants = this.$widget.find(".include-descendants");
this.$includeDescendants.on("change", () => this.refresh());
this.$affectedNoteCount = this.$widget.find(".affected-note-count");
this.$availableActionList = this.$widget.find(".bulk-available-action-list"); this.$availableActionList = this.$widget.find(".bulk-available-action-list");
this.$existingActionList = this.$widget.find(".bulk-existing-action-list"); this.$existingActionList = this.$widget.find(".bulk-existing-action-list");
@ -84,7 +90,10 @@ export default class BulkActionsDialog extends BasicWidget {
this.$executeButton = this.$widget.find(".execute-bulk-actions"); this.$executeButton = this.$widget.find(".execute-bulk-actions");
this.$executeButton.on("click", async () => { this.$executeButton.on("click", async () => {
await server.post("bulk-action", { noteIds: this.selectedOrActiveNoteIds }); await server.post("bulk-action/execute", {
noteIds: this.selectedOrActiveNoteIds,
includeDescendants: this.$includeDescendants.is(":checked")
});
toastService.showMessage("Bulk actions have been executed successfully.", 3000); toastService.showMessage("Bulk actions have been executed successfully.", 3000);
@ -95,6 +104,13 @@ export default class BulkActionsDialog extends BasicWidget {
async refresh() { async refresh() {
this.renderAvailableActions(); this.renderAvailableActions();
const {affectedNoteCount} = await server.post('bulk-action/affected-notes', {
noteIds: this.selectedOrActiveNoteIds,
includeDescendants: this.$includeDescendants.is(":checked")
});
this.$affectedNoteCount.text(affectedNoteCount);
const bulkActionNote = await froca.getNote('bulkaction'); const bulkActionNote = await froca.getNote('bulkaction');
const actions = bulkActionService.parseActions(bulkActionNote); const actions = bulkActionService.parseActions(bulkActionNote);
@ -138,6 +154,7 @@ export default class BulkActionsDialog extends BasicWidget {
async bulkActionsEvent({selectedOrActiveNoteIds}) { async bulkActionsEvent({selectedOrActiveNoteIds}) {
this.selectedOrActiveNoteIds = selectedOrActiveNoteIds; this.selectedOrActiveNoteIds = selectedOrActiveNoteIds;
this.$includeDescendants.prop("checked", false);
await this.refresh(); await this.refresh();

View File

@ -2,13 +2,47 @@ const becca = require("../../becca/becca");
const bulkActionService = require("../../services/bulk_actions"); const bulkActionService = require("../../services/bulk_actions");
function execute(req) { function execute(req) {
const {noteIds} = req.body; const {noteIds, includeDescendants} = req.body;
const affectedNoteIds = getAffectedNoteIds(noteIds, includeDescendants);
const bulkActionNote = becca.getNote('bulkaction'); const bulkActionNote = becca.getNote('bulkaction');
bulkActionService.executeActions(bulkActionNote, noteIds); bulkActionService.executeActions(bulkActionNote, affectedNoteIds);
}
function getAffectedNoteCount(req) {
const {noteIds, includeDescendants} = req.body;
const affectedNoteIds = getAffectedNoteIds(noteIds, includeDescendants);
return {
affectedNoteCount: affectedNoteIds.size
};
}
function getAffectedNoteIds(noteIds, includeDescendants) {
const affectedNoteIds = new Set();
for (const noteId of noteIds) {
const note = becca.getNote(noteId);
if (!note) {
continue;
}
affectedNoteIds.add(noteId);
if (includeDescendants) {
for (const descendantNoteId of note.getDescendantNoteIds()) {
affectedNoteIds.add(descendantNoteId);
}
}
}
return affectedNoteIds;
} }
module.exports = { module.exports = {
execute execute,
getAffectedNoteCount
}; };

View File

@ -358,7 +358,8 @@ function register(app) {
apiRoute(GET, '/api/search/:searchString', searchRoute.search); apiRoute(GET, '/api/search/:searchString', searchRoute.search);
apiRoute(GET, '/api/search-templates', searchRoute.searchTemplates); apiRoute(GET, '/api/search-templates', searchRoute.searchTemplates);
apiRoute(POST, '/api/bulk-action', bulkActionRoute.execute); apiRoute(POST, '/api/bulk-action/execute', bulkActionRoute.execute);
apiRoute(POST, '/api/bulk-action/affected-notes', bulkActionRoute.getAffectedNoteCount);
route(POST, '/api/login/sync', [], loginApiRoute.loginSync, apiResultHandler); 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) // this is for entering protected mode so user has to be already logged-in (that's the reason we don't require username)