Bulk actions overview
Structure-defined bulk operations and execution
Bulk actions are defined in table structure and rendered in TableBulkActions as a dropdown above the table.
Structure → Redux
dispatch(_getStructureBulkActions(table?.bulkActions));Stored in bulkActions.bulkActions. Selected action in selectedBulkAction when confirmation or custom modal is needed.
What happens when you click a bulk action
File: ./ApiTables/core/TableBulkActions.tsx — function fireBulkAction(action)
Diagram
At a glance
Path A — Modal first
Withdrawalaction_key is store_with_drawal_bulk or create_withdrawal_bulk.
Runs _getSelectedBulkAction(action) → popup opens → POST happens on modal submit.
Path B — Direct API
Most bulk actionsExport, delete, and other bulk ops.
Runs bulkActionsPostHandler immediately with filters + selected_ids.
Step by step
User picks an item from the Bulk actions dropdown
Each item is an action from the API (action_key, method, action.api, label, …).
Code checks action.action_key
Withdrawal keys → Path A. Everything else → Path B.
Path A — open a modal first (withdrawal flows)
What the user sees: A popup opens. They fill fields and submit inside the modal.
What code does:
dispatch(_getSelectedBulkAction(action));Redux stores the action in bulkActions.selectedBulkAction.
./ApiTables/table-modals/ApiTablesModals.tsx watches that state and shows the matching popup:
action_key | Modal |
|---|---|
create_withdrawal_bulk | AddToCreditBulkModal |
store_with_drawal_bulk | Confirmation / custom flow (see modals doc) |
No table POST happens until the user completes the modal.
AddToCreditBulkModal may read auth from the global store (store.getState().auth) for bank accounts.
Path B — call the API immediately (most bulk actions)
What the user sees: Loader (app-wide), then download or table refresh.
What code does:
bulkActionsPostHandler(
action.method,
action.action.api.replace('/api', ''),
{
filters: appliedFilters, // active filters from Redux tableCore
selected_ids: selectedIds, // checkbox-selected row ids from Redux tableColumns
},
{ msg: '...', icon: 'excel' },
action
);Request body sent to the server:
| Field | Source | Meaning |
|---|---|---|
filters | state.tableCore.appliedFilters | Same filters as the current table view |
selected_ids | state.tableColumns.selectedIds | IDs of rows the user checked |
The HTTP method and URL come from the action definition (method, action.api).
Quick comparison
| Path A (modal) | Path B (direct POST) | |
|---|---|---|
| When | action_key is store_with_drawal_bulk or create_withdrawal_bulk | All other bulk actions |
| First step | Save action in Redux, open popup | bulkActionsPostHandler |
| Payload | Built inside the modal on submit | { filters, selected_ids } right away |
| Typical examples | Create withdrawal bulk | Export Excel, bulk delete, bulk update |
The actual branch in code
function fireBulkAction(action) {
const needsModal =
action.action_key === 'store_with_drawal_bulk' ||
action.action_key === 'create_withdrawal_bulk';
if (needsModal) {
dispatch(_getSelectedBulkAction(action));
} else {
bulkActionsPostHandler(action.method, url, {
filters: appliedFilters,
selected_ids: selectedIds,
}, loaderInfo, action);
}
}Post-response handling
useEffect on bulkActionPostResponse:
- Excel blob →
downloadBlob - URL in response →
downloadURL onSuccess/ stream handlers → reload or refetch per action config
handleBulkActionReponse in useUtilsProvider:
reload/deleteRow→triggerTableReload()- Packing
/packing/materials+ reload → updates global cart count
Global loader
bulkActionsPostHandler dispatches _setMainLoader on the app store while request runs.
Disabled states
Dropdown disabled when:
tableDataemptytableFetchingLoadingtrue