[UI] Bulk Delete Enhancements (#12601)

* Add optional filtering for bulkDelete

* Enhanced pre-form content
This commit is contained in:
Oliver
2026-08-10 15:53:03 +10:00
committed by GitHub
parent 76bce6a7b1
commit e55a6e78d2
3 changed files with 44 additions and 2 deletions
+2
View File
@@ -168,6 +168,7 @@ export type RowViewProps = RowAction & RowModelProps & RowViewBehaviorProps;
* @param tableState : TableState - State manager for the table * @param tableState : TableState - State manager for the table
* @param defaultSortColumn : string - Default column to sort by * @param defaultSortColumn : string - Default column to sort by
* @param noRecordsText : string - Text to display when no records are found * @param noRecordsText : string - Text to display when no records are found
* @param bulkDeleteFilter : (record: any) => boolean - Callback function to determine if a record is eligible for bulk deletion
* @param enableBulkDelete : boolean - Enable bulk deletion of records * @param enableBulkDelete : boolean - Enable bulk deletion of records
* @param enableDownload : boolean - Enable download actions * @param enableDownload : boolean - Enable download actions
* @param enableFilters : boolean - Enable filter actions * @param enableFilters : boolean - Enable filter actions
@@ -198,6 +199,7 @@ export type InvenTreeTableProps<T = any> = {
params?: any; params?: any;
defaultSortColumn?: string; defaultSortColumn?: string;
noRecordsText?: string; noRecordsText?: string;
bulkDeleteFilter?: (record: T) => boolean;
enableBulkDelete?: boolean; enableBulkDelete?: boolean;
enableDownload?: boolean; enableDownload?: boolean;
enableFilters?: boolean; enableFilters?: boolean;
@@ -9,6 +9,7 @@ import {
Paper, Paper,
Space, Space,
Stack, Stack,
Text,
Tooltip Tooltip
} from '@mantine/core'; } from '@mantine/core';
import { import {
@@ -102,6 +103,38 @@ export default function InvenTreeTableHeader({
searchTerm: tableState.searchTerm searchTerm: tableState.searchTerm
}); });
const bulkDeleteIds: number[] = useMemo(() => {
if (!tableProps.enableBulkDelete) {
return [];
}
const selectedRecords = tableState.selectedRecords ?? [];
const filterFn = tableProps.bulkDeleteFilter ?? (() => true);
return selectedRecords
.filter((record) => filterFn(record))
.map(
(record) => resolveItem(record, tableState.idAccessor || 'pk') as number
);
}, [
tableProps.enableBulkDelete,
tableProps.bulkDeleteFilter,
tableState.idAccessor,
tableState.selectedRecords
]);
const deleteItemsText = useMemo(() => {
const N = bulkDeleteIds.length;
if (N === 0) {
return t`No items selected`;
} else if (N === 1) {
return t`1 selected item will be deleted`;
} else {
return t`${N} selected items will be deleted`;
}
}, [bulkDeleteIds]);
const deleteRecords = useDeleteApiFormModal({ const deleteRecords = useDeleteApiFormModal({
url: tableUrl ?? '', url: tableUrl ?? '',
title: t`Delete Selected Items`, title: t`Delete Selected Items`,
@@ -110,11 +143,14 @@ export default function InvenTreeTableHeader({
color='red' color='red'
title={t`Are you sure you want to delete the selected items?`} title={t`Are you sure you want to delete the selected items?`}
> >
{t`This action cannot be undone`} <Stack gap='xs'>
<Text size='sm'>{deleteItemsText}</Text>
<Text size='sm'>{t`This action cannot be undone`}</Text>
</Stack>
</Alert> </Alert>
), ),
initialData: { initialData: {
items: tableState.selectedIds items: bulkDeleteIds
}, },
fields: { fields: {
items: { items: {
+4
View File
@@ -742,6 +742,10 @@ export function BomTable({
enableSelection: isEditing && !isLocked, enableSelection: isEditing && !isLocked,
enableBulkDelete: enableBulkDelete:
isEditing && !isLocked && user.hasDeleteRole(UserRoles.bom), isEditing && !isLocked && user.hasDeleteRole(UserRoles.bom),
bulkDeleteFilter: (record: any) => {
// If the BOM item is defined for a different parent, then it cannot be deleted
return record.part === partId;
},
enableDownload: true, enableDownload: true,
rowExpansion: isEditing ? undefined : rowExpansion rowExpansion: isEditing ? undefined : rowExpansion
}} }}