bulk action dialog converted to widget

This commit is contained in:
zadam 2022-06-11 23:29:52 +02:00
parent 8e23c15763
commit 2115b76047
11 changed files with 224 additions and 66 deletions

97
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "trilium", "name": "trilium",
"version": "0.52.0-beta", "version": "0.52.2",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "trilium", "name": "trilium",
"version": "0.52.0-beta", "version": "0.52.2",
"hasInstallScript": true, "hasInstallScript": true,
"license": "AGPL-3.0-only", "license": "AGPL-3.0-only",
"dependencies": { "dependencies": {
@ -21,7 +21,7 @@
"commonmark": "0.30.0", "commonmark": "0.30.0",
"cookie-parser": "1.4.6", "cookie-parser": "1.4.6",
"csurf": "1.11.0", "csurf": "1.11.0",
"dayjs": "1.11.2", "dayjs": "1.11.3",
"ejs": "3.1.8", "ejs": "3.1.8",
"electron-debug": "3.2.0", "electron-debug": "3.2.0",
"electron-dl": "3.3.1", "electron-dl": "3.3.1",
@ -65,7 +65,7 @@
"tmp": "0.2.1", "tmp": "0.2.1",
"turndown": "7.1.1", "turndown": "7.1.1",
"unescape": "1.0.1", "unescape": "1.0.1",
"ws": "8.7.0", "ws": "8.8.0",
"yauzl": "2.10.0" "yauzl": "2.10.0"
}, },
"bin": { "bin": {
@ -78,9 +78,9 @@
"electron-packager": "15.5.1", "electron-packager": "15.5.1",
"electron-rebuild": "3.2.7", "electron-rebuild": "3.2.7",
"esm": "3.2.25", "esm": "3.2.25",
"jasmine": "4.1.0", "jasmine": "4.2.0",
"jsdoc": "3.6.10", "jsdoc": "3.6.10",
"lorem-ipsum": "2.0.4", "lorem-ipsum": "2.0.8",
"rcedit": "3.0.1", "rcedit": "3.0.1",
"webpack": "5.73.0", "webpack": "5.73.0",
"webpack-cli": "4.9.2" "webpack-cli": "4.9.2"
@ -3093,9 +3093,9 @@
} }
}, },
"node_modules/dayjs": { "node_modules/dayjs": {
"version": "1.11.2", "version": "1.11.3",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.2.tgz", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.3.tgz",
"integrity": "sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==" "integrity": "sha512-xxwlswWOlGhzgQ4TKzASQkUhqERI3egRNqgV4ScR8wlANA/A9tZ7miXa44vTTKEq5l7vWoL5G57bG3zA+Kow0A=="
}, },
"node_modules/debug": { "node_modules/debug": {
"version": "4.3.4", "version": "4.3.4",
@ -6337,22 +6337,22 @@
"integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g=="
}, },
"node_modules/jasmine": { "node_modules/jasmine": {
"version": "4.1.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/jasmine/-/jasmine-4.1.0.tgz", "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-4.2.0.tgz",
"integrity": "sha512-4VhjbUgwfNS9CBnUMoSWr9tdNgOoOhNIjAD8YRxTn+PmOf4qTSC0Uqhk66dWGnz2vJxtNIU0uBjiwnsp4Ud9VA==", "integrity": "sha512-6SQRXHs5O++mp52PkoJoi9zuLYqp1IaqepRNmAQn5rUBo9VUnckpkkXQQD5PAuCCVVB1ULDImvWYCPV/ZVnaGQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"glob": "^7.1.6", "glob": "^7.1.6",
"jasmine-core": "^4.1.0" "jasmine-core": "^4.2.0"
}, },
"bin": { "bin": {
"jasmine": "bin/jasmine.js" "jasmine": "bin/jasmine.js"
} }
}, },
"node_modules/jasmine-core": { "node_modules/jasmine-core": {
"version": "4.1.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.1.0.tgz", "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.2.0.tgz",
"integrity": "sha512-8E8BiffCL8sBwK1zU9cbavLe8xpJAgOduSJ6N8PJVv8VosQ/nxVTuXj2kUeHxTlZBVvh24G19ga7xdiaxlceKg==", "integrity": "sha512-OcFpBrIhnbmb9wfI8cqPSJ50pv3Wg4/NSgoZIqHzIwO/2a9qivJWzv8hUvaREIMYYJBas6AvfXATFdVuzzCqVw==",
"dev": true "dev": true
}, },
"node_modules/jest-worker": { "node_modules/jest-worker": {
@ -6855,12 +6855,12 @@
} }
}, },
"node_modules/lorem-ipsum": { "node_modules/lorem-ipsum": {
"version": "2.0.4", "version": "2.0.8",
"resolved": "https://registry.npmjs.org/lorem-ipsum/-/lorem-ipsum-2.0.4.tgz", "resolved": "https://registry.npmjs.org/lorem-ipsum/-/lorem-ipsum-2.0.8.tgz",
"integrity": "sha512-TD+ERYfxjYiUfOyaKU6OH4euumNVeKoo3BxIhokb7bGmoCULsME48onF9NVxYK3CU1z9L5ALnkDkW8lIkHvMNQ==", "integrity": "sha512-5RIwHuCb979RASgCJH0VKERn9cQo/+NcAi2BMe9ddj+gp7hujl6BI+qdOG4nVsLDpwWEJwTVYXNKP6BGgbcoGA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"commander": "^2.17.1" "commander": "^9.3.0"
}, },
"bin": { "bin": {
"lorem-ipsum": "dist/bin/lorem-ipsum.bin.js" "lorem-ipsum": "dist/bin/lorem-ipsum.bin.js"
@ -6871,10 +6871,13 @@
} }
}, },
"node_modules/lorem-ipsum/node_modules/commander": { "node_modules/lorem-ipsum/node_modules/commander": {
"version": "2.20.3", "version": "9.3.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-9.3.0.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "integrity": "sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw==",
"dev": true "dev": true,
"engines": {
"node": "^12.20.0 || >=14"
}
}, },
"node_modules/lowercase-keys": { "node_modules/lowercase-keys": {
"version": "1.0.1", "version": "1.0.1",
@ -10538,9 +10541,9 @@
} }
}, },
"node_modules/ws": { "node_modules/ws": {
"version": "8.7.0", "version": "8.8.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.7.0.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.0.tgz",
"integrity": "sha512-c2gsP0PRwcLFzUiA8Mkr37/MI7ilIlHQxaEAtd0uNMbVMoy8puJyafRlm0bV9MbGSabUPeLrRRaqIBcFcA2Pqg==", "integrity": "sha512-JDAgSYQ1ksuwqfChJusw1LSJ8BizJ2e/vVu5Lxjq3YvNJNlROv1ui4i+c/kUUrPheBvQl4c5UbERhTwKa6QBJQ==",
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=10.0.0"
}, },
@ -13191,9 +13194,9 @@
} }
}, },
"dayjs": { "dayjs": {
"version": "1.11.2", "version": "1.11.3",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.2.tgz", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.3.tgz",
"integrity": "sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==" "integrity": "sha512-xxwlswWOlGhzgQ4TKzASQkUhqERI3egRNqgV4ScR8wlANA/A9tZ7miXa44vTTKEq5l7vWoL5G57bG3zA+Kow0A=="
}, },
"debug": { "debug": {
"version": "4.3.4", "version": "4.3.4",
@ -15649,19 +15652,19 @@
} }
}, },
"jasmine": { "jasmine": {
"version": "4.1.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/jasmine/-/jasmine-4.1.0.tgz", "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-4.2.0.tgz",
"integrity": "sha512-4VhjbUgwfNS9CBnUMoSWr9tdNgOoOhNIjAD8YRxTn+PmOf4qTSC0Uqhk66dWGnz2vJxtNIU0uBjiwnsp4Ud9VA==", "integrity": "sha512-6SQRXHs5O++mp52PkoJoi9zuLYqp1IaqepRNmAQn5rUBo9VUnckpkkXQQD5PAuCCVVB1ULDImvWYCPV/ZVnaGQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"glob": "^7.1.6", "glob": "^7.1.6",
"jasmine-core": "^4.1.0" "jasmine-core": "^4.2.0"
} }
}, },
"jasmine-core": { "jasmine-core": {
"version": "4.1.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.1.0.tgz", "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.2.0.tgz",
"integrity": "sha512-8E8BiffCL8sBwK1zU9cbavLe8xpJAgOduSJ6N8PJVv8VosQ/nxVTuXj2kUeHxTlZBVvh24G19ga7xdiaxlceKg==", "integrity": "sha512-OcFpBrIhnbmb9wfI8cqPSJ50pv3Wg4/NSgoZIqHzIwO/2a9qivJWzv8hUvaREIMYYJBas6AvfXATFdVuzzCqVw==",
"dev": true "dev": true
}, },
"jest-worker": { "jest-worker": {
@ -16075,18 +16078,18 @@
} }
}, },
"lorem-ipsum": { "lorem-ipsum": {
"version": "2.0.4", "version": "2.0.8",
"resolved": "https://registry.npmjs.org/lorem-ipsum/-/lorem-ipsum-2.0.4.tgz", "resolved": "https://registry.npmjs.org/lorem-ipsum/-/lorem-ipsum-2.0.8.tgz",
"integrity": "sha512-TD+ERYfxjYiUfOyaKU6OH4euumNVeKoo3BxIhokb7bGmoCULsME48onF9NVxYK3CU1z9L5ALnkDkW8lIkHvMNQ==", "integrity": "sha512-5RIwHuCb979RASgCJH0VKERn9cQo/+NcAi2BMe9ddj+gp7hujl6BI+qdOG4nVsLDpwWEJwTVYXNKP6BGgbcoGA==",
"dev": true, "dev": true,
"requires": { "requires": {
"commander": "^2.17.1" "commander": "^9.3.0"
}, },
"dependencies": { "dependencies": {
"commander": { "commander": {
"version": "2.20.3", "version": "9.3.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-9.3.0.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "integrity": "sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw==",
"dev": true "dev": true
} }
} }
@ -18915,9 +18918,9 @@
} }
}, },
"ws": { "ws": {
"version": "8.7.0", "version": "8.8.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.7.0.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.0.tgz",
"integrity": "sha512-c2gsP0PRwcLFzUiA8Mkr37/MI7ilIlHQxaEAtd0uNMbVMoy8puJyafRlm0bV9MbGSabUPeLrRRaqIBcFcA2Pqg==", "integrity": "sha512-JDAgSYQ1ksuwqfChJusw1LSJ8BizJ2e/vVu5Lxjq3YvNJNlROv1ui4i+c/kUUrPheBvQl4c5UbERhTwKa6QBJQ==",
"requires": {} "requires": {}
}, },
"xdg-basedir": { "xdg-basedir": {

View File

@ -80,7 +80,7 @@
"tmp": "0.2.1", "tmp": "0.2.1",
"turndown": "7.1.1", "turndown": "7.1.1",
"unescape": "1.0.1", "unescape": "1.0.1",
"ws": "8.7.0", "ws": "8.8.0",
"yauzl": "2.10.0" "yauzl": "2.10.0"
}, },
"devDependencies": { "devDependencies": {
@ -90,9 +90,9 @@
"electron-packager": "15.5.1", "electron-packager": "15.5.1",
"electron-rebuild": "3.2.7", "electron-rebuild": "3.2.7",
"esm": "3.2.25", "esm": "3.2.25",
"jasmine": "4.1.0", "jasmine": "4.2.0",
"jsdoc": "3.6.10", "jsdoc": "3.6.10",
"lorem-ipsum": "2.0.4", "lorem-ipsum": "2.0.8",
"rcedit": "3.0.1", "rcedit": "3.0.1",
"webpack": "5.73.0", "webpack": "5.73.0",
"webpack-cli": "4.9.2" "webpack-cli": "4.9.2"

View File

@ -50,6 +50,7 @@ import BacklinksWidget from "../widgets/backlinks.js";
import SharedInfoWidget from "../widgets/shared_info.js"; import SharedInfoWidget from "../widgets/shared_info.js";
import FindWidget from "../widgets/find.js"; import FindWidget from "../widgets/find.js";
import TocWidget from "../widgets/toc.js"; import TocWidget from "../widgets/toc.js";
import BulkActionsDialog from "../widgets/dialogs/bulk_actions.js";
export default class DesktopLayout { export default class DesktopLayout {
constructor(customWidgets) { constructor(customWidgets) {
@ -174,6 +175,7 @@ export default class DesktopLayout {
.child(...this.customWidgets.get('right-pane')) .child(...this.customWidgets.get('right-pane'))
) )
) )
); )
.child(new BulkActionsDialog());
} }
} }

View File

@ -91,7 +91,7 @@ class TreeContextMenu {
enabled: notSearch && noSelectedNotes }, enabled: notSearch && noSelectedNotes },
{ title: "Import into note", command: "importIntoNote", uiIcon: "bx bx-empty", { title: "Import into note", command: "importIntoNote", uiIcon: "bx bx-empty",
enabled: notSearch && noSelectedNotes }, enabled: notSearch && noSelectedNotes },
{ title: "Bulk assign attributes", command: "bulkAssignAttributes", uiIcon: "bx bx-empty", { title: "Bulk actions", command: "bulkActions", uiIcon: "bx bx-empty",
enabled: true } enabled: true }
].filter(row => row !== null); ].filter(row => row !== null);
} }

View File

@ -1,6 +1,5 @@
import server from "../../services/server.js"; import server from "../../services/server.js";
import ws from "../../services/ws.js"; import ws from "../../services/ws.js";
import Component from "../component.js";
import utils from "../../services/utils.js"; import utils from "../../services/utils.js";
export default class AbstractBulkAction { export default class AbstractBulkAction {
@ -48,6 +47,6 @@ export default class AbstractBulkAction {
await ws.waitForMaxKnownEntityChangeId(); await ws.waitForMaxKnownEntityChangeId();
await this.triggerCommand('refreshSearchDefinition'); //await this.triggerCommand('refreshSearchDefinition');
} }
} }

View File

@ -5,7 +5,7 @@ const TPL = `
<tr> <tr>
<td colspan="2"> <td colspan="2">
<div style="display: flex; align-items: center"> <div style="display: flex; align-items: center">
<div style="margin-right: 10px;">Rename label from:</div> <div style="margin-right: 10px; flex-shrink: 0;">Rename label from:</div>
<input type="text" <input type="text"
class="form-control old-label-name" class="form-control old-label-name"
@ -45,7 +45,7 @@ export default class RenameLabelBulkAction extends AbstractBulkAction {
oldLabelName: $oldLabelName.val(), oldLabelName: $oldLabelName.val(),
newLabelName: $newLabelName.val() newLabelName: $newLabelName.val()
}); });
}, 1000) }, 1000);
$oldLabelName.on('input', () => spacedUpdate.scheduleUpdate()); $oldLabelName.on('input', () => spacedUpdate.scheduleUpdate());
$newLabelName.on('input', () => spacedUpdate.scheduleUpdate()); $newLabelName.on('input', () => spacedUpdate.scheduleUpdate());

View File

@ -5,7 +5,7 @@ const TPL = `
<tr> <tr>
<td colspan="2"> <td colspan="2">
<div style="display: flex; align-items: center"> <div style="display: flex; align-items: center">
<div style="margin-right: 10px;">Rename relation from:</div> <div style="margin-right: 10px; flex-shrink: 0;">Rename relation from:</div>
<input type="text" <input type="text"
class="form-control old-relation-name" class="form-control old-relation-name"

View File

@ -0,0 +1,132 @@
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";
const TPL = `
<div class="bulk-assign-attributes-dialog modal mx-auto" tabindex="-1" role="dialog">
<style>
.bulk-assign-attributes-dialog .modal-body h4:not(:first-child) {
margin-top: 20px;
}
.bulk-available-action-list button {
padding: 2px 7px;
margin-right: 10px;
margin-bottom: 5px;
}
.bulk-existing-action-list {
width: 100%;
}
.bulk-existing-action-list td {
padding: 7px;
}
.bulk-existing-action-list .button-column {
/* minimal width so that table remains static sized and most space remains for middle column with settings */
width: 50px;
white-space: nowrap;
text-align: right;
}
</style>
<div class="modal-dialog modal-xl" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title mr-auto">Bulk assign attributes</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" style="margin-left: 0 !important;">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<h4>Affected notes: <span class="affected-note-count">0</span></h4>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" class="include-descendants">
<label class="form-check-label" for="include-descendants">
Include descendant notes
</label>
</div>
<h4>Available actions</h4>
<table class="bulk-available-action-list"></table>
<h4>Chosen actions</h4>
<table class="bulk-existing-action-list"></table>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Execute bulk actions</button>
</div>
</div>
</div>
</div>`;
export default class BulkActionsDialog extends BasicWidget {
doRender() {
this.$widget = $(TPL);
this.$availableActionList = this.$widget.find(".bulk-available-action-list");
this.$existingActionList = this.$widget.find(".bulk-existing-action-list");
this.$widget.on('click', '[data-action-add]', async event => {
const actionName = $(event.target).attr('data-action-add');
await bulkActionService.addAction('bulkaction', actionName);
await this.refresh();
});
}
async refresh() {
this.renderAvailableActions();
const bulkActionNote = await froca.getNote('bulkaction');
const actions = bulkActionService.parseActions(bulkActionNote);
this.$existingActionList.empty();
if (actions.length > 0) {
this.$existingActionList.append(...actions.map(action => action.render()));
} else {
this.$existingActionList.append($("<p>None yet ... add an action by clicking one of the available ones above.</p>"))
}
}
renderAvailableActions() {
this.$availableActionList.empty();
for (const actionGroup of bulkActionService.ACTION_GROUPS) {
const $actionGroupList = $("<td>");
const $actionGroup = $("<tr>")
.append($("<td>").text(actionGroup.title + ": "))
.append($actionGroupList);
for (const action of actionGroup.actions) {
$actionGroupList.append(
$('<button class="btn btn-sm">')
.attr('data-action-add', action.actionName)
.text(action.actionTitle)
);
}
this.$availableActionList.append($actionGroup);
}
}
entitiesReloadedEvent({loadResults}) {
if (loadResults.getAttributes().find(attr => attr.type === 'label' && attr.name === 'action')) {
this.refresh();
}
}
async bulkActionsEvent({node}) {
await this.refresh();
utils.openDialog(this.$widget);
}
}

View File

@ -1451,11 +1451,6 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
importDialog.showDialog(node.data.noteId); importDialog.showDialog(node.data.noteId);
} }
async bulkAssignAttributesCommand({node}) {
const bulkAssignAttributesDialog = await import('../dialogs/bulk_assign_attributes.js');
bulkAssignAttributesDialog.showDialog(this.getSelectedOrActiveNodes(node));
}
forceNoteSyncCommand({node}) { forceNoteSyncCommand({node}) {
syncService.forceNoteSync(node.data.noteId); syncService.forceNoteSync(node.data.noteId);
} }

View File

@ -305,4 +305,10 @@ export default class SearchDefinitionWidget extends NoteContextAwareWidget {
toastService.showMessage('Actions have been executed.', 3000); toastService.showMessage('Actions have been executed.', 3000);
} }
entitiesReloadedEvent({loadResults}) {
if (loadResults.getAttributes().find(attr => attr.type === 'label' && attr.name === 'action')) {
this.refresh();
}
}
} }

View File

@ -1,13 +1,32 @@
<style> <style>
#bulk-assign-attributes-dialog .modal-body h4:not(:first-child) {
margin-top: 20px;
}
#bulk-available-action-list button { #bulk-available-action-list button {
padding: 2px 7px; padding: 2px 7px;
margin-right: 10px; margin-right: 10px;
margin-bottom: 5px; margin-bottom: 5px;
} }
#bulk-existing-action-list {
width: 100%;
}
#bulk-existing-action-list td {
padding: 7px;
}
#bulk-existing-action-list .button-column {
/* minimal width so that table remains static sized and most space remains for middle column with settings */
width: 50px;
white-space: nowrap;
text-align: right;
}
</style> </style>
<div id="bulk-assign-attributes-dialog" class="modal mx-auto" tabindex="-1" role="dialog"> <div id="bulk-assign-attributes-dialog" class="modal mx-auto" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg" style="max-width: 1000px" role="document"> <div class="modal-dialog modal-xl" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title mr-auto">Bulk assign attributes</h5> <h5 class="modal-title mr-auto">Bulk assign attributes</h5>
@ -17,7 +36,7 @@
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
Affected notes: <span id="affected-note-count">0</span> <h4>Affected notes: <span id="affected-note-count">0</span></h4>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="include-descendants"> <input class="form-check-input" type="checkbox" value="" id="include-descendants">
@ -26,11 +45,13 @@
</label> </label>
</div> </div>
Available actions: <h4>Available actions</h4>
<table id="bulk-available-action-list"></table> <table id="bulk-available-action-list"></table>
<div id="bulk-existing-action-list"></div> <h4>Chosen actions</h4>
<table id="bulk-existing-action-list"></table>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="submit" class="btn btn-primary">Execute bulk actions</button> <button type="submit" class="btn btn-primary">Execute bulk actions</button>