mirror of
https://github.com/inventree/InvenTree.git
synced 2026-05-17 23:08:28 +00:00
[bug] Bulk edit fix (#11945)
* Prevent editing of items which do not point directly to the part * Allow table to define which records can be selected
This commit is contained in:
@@ -173,6 +173,7 @@ export type RowViewProps = RowAction & RowModelProps;
|
|||||||
* @param barcodeActions : any[] - List of barcode actions
|
* @param barcodeActions : any[] - List of barcode actions
|
||||||
* @param tableFilters : TableFilter[] - List of custom filters
|
* @param tableFilters : TableFilter[] - List of custom filters
|
||||||
* @param tableActions : any[] - List of custom action groups
|
* @param tableActions : any[] - List of custom action groups
|
||||||
|
* @param isRecordSelectable : (record: any, index: number) => boolean - Callback function to determine if a row is selectable
|
||||||
* @param detailAction: boolean - Enable detail action for each row (default = true)
|
* @param detailAction: boolean - Enable detail action for each row (default = true)
|
||||||
* @param dataFormatter : (data: any) => any - Callback function to reformat data returned by server (if not in default format)
|
* @param dataFormatter : (data: any) => any - Callback function to reformat data returned by server (if not in default format)
|
||||||
* @param rowActions : (record: any) => RowAction[] - Callback function to generate row actions
|
* @param rowActions : (record: any) => RowAction[] - Callback function to generate row actions
|
||||||
@@ -203,6 +204,7 @@ export type InvenTreeTableProps<T = any> = {
|
|||||||
barcodeActions?: React.ReactNode[];
|
barcodeActions?: React.ReactNode[];
|
||||||
tableFilters?: TableFilter[];
|
tableFilters?: TableFilter[];
|
||||||
tableActions?: React.ReactNode[];
|
tableActions?: React.ReactNode[];
|
||||||
|
isRecordSelectable?: (record: T, index: number) => boolean;
|
||||||
rowExpansion?: DataTableRowExpansionProps<T>;
|
rowExpansion?: DataTableRowExpansionProps<T>;
|
||||||
dataFormatter?: (data: any) => any;
|
dataFormatter?: (data: any) => any;
|
||||||
rowActions?: (record: T) => RowAction[];
|
rowActions?: (record: T) => RowAction[];
|
||||||
|
|||||||
@@ -860,6 +860,7 @@ export function InvenTreeTableInternal<T extends Record<string, any>>({
|
|||||||
onSelectedRecordsChange={
|
onSelectedRecordsChange={
|
||||||
enableSelection ? onSelectedRecordsChange : undefined
|
enableSelection ? onSelectedRecordsChange : undefined
|
||||||
}
|
}
|
||||||
|
isRecordSelectable={tableProps.isRecordSelectable}
|
||||||
rowExpansion={rowExpansion}
|
rowExpansion={rowExpansion}
|
||||||
fetching={isFetching}
|
fetching={isFetching}
|
||||||
noRecordsText={missingRecordsText}
|
noRecordsText={missingRecordsText}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import useTable from '@lib/hooks/UseTable';
|
|||||||
import { ActionButton, RowEditAction, UserRoles } from '@lib/index';
|
import { ActionButton, RowEditAction, UserRoles } from '@lib/index';
|
||||||
import type { TableFilter } from '@lib/types/Filters';
|
import type { TableFilter } from '@lib/types/Filters';
|
||||||
import type { RowAction, TableColumn } from '@lib/types/Tables';
|
import type { RowAction, TableColumn } from '@lib/types/Tables';
|
||||||
import { IconReplace } from '@tabler/icons-react';
|
import { IconExclamationCircle, IconReplace } from '@tabler/icons-react';
|
||||||
import { formatDecimal } from '../../defaults/formatters';
|
import { formatDecimal } from '../../defaults/formatters';
|
||||||
import { bomItemFields } from '../../forms/BomForms';
|
import { bomItemFields } from '../../forms/BomForms';
|
||||||
import {
|
import {
|
||||||
@@ -132,7 +132,10 @@ export function UsedInTable({
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
RowEditAction({
|
RowEditAction({
|
||||||
hidden: locked || !user.hasChangeRole(UserRoles.bom),
|
hidden:
|
||||||
|
locked ||
|
||||||
|
record.sub_part != partId ||
|
||||||
|
!user.hasChangeRole(UserRoles.bom),
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
setSelectedBomItem(record);
|
setSelectedBomItem(record);
|
||||||
editBomItem.open();
|
editBomItem.open();
|
||||||
@@ -140,14 +143,19 @@ export function UsedInTable({
|
|||||||
})
|
})
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
[user]
|
[user, partId]
|
||||||
);
|
);
|
||||||
|
|
||||||
const bulkReplaceParts = useMemo(() => {}, [table.selectedRecords]);
|
const bulkReplaceRecords: any[] = useMemo(() => {
|
||||||
|
// Only allow replacements of BomItem entries which point to this part
|
||||||
|
return table.selectedRecords.filter(
|
||||||
|
(record: any) => record.sub_part === partId
|
||||||
|
);
|
||||||
|
}, [table.selectedRecords, partId]);
|
||||||
|
|
||||||
const bulkReplace = useBulkEditApiFormModal({
|
const bulkReplace = useBulkEditApiFormModal({
|
||||||
url: ApiEndpoints.bom_list,
|
url: ApiEndpoints.bom_list,
|
||||||
items: table.selectedIds,
|
items: bulkReplaceRecords.map((record: any) => record.pk),
|
||||||
title: t`Replace Component`,
|
title: t`Replace Component`,
|
||||||
submitText: t`Replace`,
|
submitText: t`Replace`,
|
||||||
preFormContent: (
|
preFormContent: (
|
||||||
@@ -160,8 +168,18 @@ export function UsedInTable({
|
|||||||
>
|
>
|
||||||
<Text>{t`This action cannot be easily undone, so please ensure you have selected the correct assemblies.`}</Text>
|
<Text>{t`This action cannot be easily undone, so please ensure you have selected the correct assemblies.`}</Text>
|
||||||
</Alert>
|
</Alert>
|
||||||
<Text>{t`The selected assemblies will be updated with the new component.`}</Text>
|
{bulkReplaceRecords.length ? (
|
||||||
{table.selectedRecords.map((record: any) => {
|
<Text>{t`The selected assemblies will be updated with the new component.`}</Text>
|
||||||
|
) : (
|
||||||
|
<Alert
|
||||||
|
color='red'
|
||||||
|
icon={<IconExclamationCircle />}
|
||||||
|
title={t`No valid items selected`}
|
||||||
|
>
|
||||||
|
<Text>{t`Please select one or more valid assemblies to replace the component.`}</Text>
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
{bulkReplaceRecords?.map((record: any) => {
|
||||||
return <RenderPartColumn part={record.part_detail} key={record.pk} />;
|
return <RenderPartColumn part={record.part_detail} key={record.pk} />;
|
||||||
})}
|
})}
|
||||||
<Divider />
|
<Divider />
|
||||||
@@ -212,7 +230,8 @@ export function UsedInTable({
|
|||||||
modelType: ModelType.part,
|
modelType: ModelType.part,
|
||||||
modelField: 'part',
|
modelField: 'part',
|
||||||
tableActions: tableActions,
|
tableActions: tableActions,
|
||||||
tableFilters: tableFilters
|
tableFilters: tableFilters,
|
||||||
|
isRecordSelectable: (record: any) => record.sub_part === partId
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|||||||
Reference in New Issue
Block a user