mirror of
https://github.com/inventree/InvenTree.git
synced 2026-05-09 03:03:41 +00:00
d1354fc147
* Move useFilterSet state to the @lib
* Refactor useTable hook into @lib
* Refactor string helper functions
* Refactor constructFormUrl func
* Refactor Boundary component
* Refactor StoredTableState
* More refactoring
* Refactor CopyButton and CopyableCell
* Pass table render func to plugins
* Provide internal wrapper function, while allowing the "api" and "navigate" functions to be provided by the caller
* Adds <InvenTreeTable /> component which is exposed to plugins
* Update frontend versioning
* Update docs
* Handle condition where UI does not provide table rendering function
* Move queryFilters out of custom state
* Fix exported type
* Extract searchParams
- Cannot be used outside of router component
- Only provide when the table is generated internally
* Bump UI version
* Fix for right-click context menu
- Function needs to be defined with the context menu provider
(cherry picked from commit 23f43ffd33)
Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
239 lines
5.9 KiB
TypeScript
239 lines
5.9 KiB
TypeScript
import { t } from '@lingui/core/macro';
|
|
import { type ReactNode, useCallback, useMemo, useState } from 'react';
|
|
|
|
import { AddItemButton } from '@lib/components/AddItemButton';
|
|
import {
|
|
type RowAction,
|
|
RowDeleteAction,
|
|
RowDuplicateAction,
|
|
RowEditAction
|
|
} from '@lib/components/RowActions';
|
|
import { ApiEndpoints } from '@lib/enums/ApiEndpoints';
|
|
import { ModelType } from '@lib/enums/ModelType';
|
|
import { UserRoles } from '@lib/enums/Roles';
|
|
import { apiUrl } from '@lib/functions/Api';
|
|
import useTable from '@lib/hooks/UseTable';
|
|
import type { TableFilter } from '@lib/types/Filters';
|
|
import type { TableColumn } from '@lib/types/Tables';
|
|
import { useManufacturerPartFields } from '../../forms/CompanyForms';
|
|
import {
|
|
useCreateApiFormModal,
|
|
useDeleteApiFormModal,
|
|
useEditApiFormModal
|
|
} from '../../hooks/UseForm';
|
|
import { useUserState } from '../../states/UserState';
|
|
import {
|
|
CompanyColumn,
|
|
DescriptionColumn,
|
|
IPNColumn,
|
|
LinkColumn,
|
|
PartColumn
|
|
} from '../ColumnRenderers';
|
|
import { InvenTreeTable } from '../InvenTreeTable';
|
|
|
|
/*
|
|
* Construct a table listing manufacturer parts
|
|
*/
|
|
export function ManufacturerPartTable({
|
|
manufacturerId,
|
|
partId
|
|
}: Readonly<{
|
|
manufacturerId?: number;
|
|
partId?: number;
|
|
}>): ReactNode {
|
|
const tableId: string = useMemo(() => {
|
|
let tId = 'manufacturer-part';
|
|
|
|
if (manufacturerId) {
|
|
tId += '-manufacturer';
|
|
}
|
|
|
|
if (partId) {
|
|
tId += '-part';
|
|
}
|
|
|
|
return tId;
|
|
}, [manufacturerId, partId]);
|
|
|
|
const initialFilters = useMemo(() => {
|
|
const filters: TableFilter[] = [];
|
|
|
|
if (!manufacturerId) {
|
|
filters.push({
|
|
name: 'manufacturer_active',
|
|
value: 'true'
|
|
});
|
|
}
|
|
|
|
if (!partId) {
|
|
filters.push({
|
|
name: 'part_active',
|
|
value: 'true'
|
|
});
|
|
}
|
|
|
|
return filters;
|
|
}, [manufacturerId, partId]);
|
|
|
|
const table = useTable(tableId, {
|
|
initialFilters: initialFilters
|
|
});
|
|
|
|
const user = useUserState();
|
|
|
|
// Construct table columns for this table
|
|
const tableColumns: TableColumn[] = useMemo(() => {
|
|
return [
|
|
PartColumn({
|
|
switchable: !!partId
|
|
}),
|
|
IPNColumn({}),
|
|
{
|
|
accessor: 'manufacturer',
|
|
sortable: true,
|
|
render: (record: any) => (
|
|
<CompanyColumn company={record?.manufacturer_detail} />
|
|
)
|
|
},
|
|
{
|
|
accessor: 'MPN',
|
|
title: t`MPN`,
|
|
sortable: true,
|
|
copyable: true
|
|
},
|
|
DescriptionColumn({}),
|
|
LinkColumn({})
|
|
];
|
|
}, [partId]);
|
|
|
|
const manufacturerPartFields = useManufacturerPartFields();
|
|
|
|
const [selectedPart, setSelectedPart] = useState<any>(undefined);
|
|
|
|
const createManufacturerPart = useCreateApiFormModal({
|
|
url: ApiEndpoints.manufacturer_part_list,
|
|
title: t`Add Manufacturer Part`,
|
|
fields: manufacturerPartFields,
|
|
table: table,
|
|
initialData: {
|
|
manufacturer: manufacturerId,
|
|
part: partId
|
|
},
|
|
keepOpenOption: true
|
|
});
|
|
|
|
const editManufacturerPart = useEditApiFormModal({
|
|
url: ApiEndpoints.manufacturer_part_list,
|
|
pk: selectedPart?.pk,
|
|
title: t`Edit Manufacturer Part`,
|
|
fields: useMemo(() => manufacturerPartFields, [manufacturerPartFields]),
|
|
table: table
|
|
});
|
|
|
|
const duplicateManufacturerPart = useCreateApiFormModal({
|
|
url: ApiEndpoints.manufacturer_part_list,
|
|
title: t`Add Manufacturer Part`,
|
|
fields: useMemo(() => manufacturerPartFields, [manufacturerPartFields]),
|
|
table: table,
|
|
initialData: {
|
|
...selectedPart
|
|
}
|
|
});
|
|
|
|
const deleteManufacturerPart = useDeleteApiFormModal({
|
|
url: ApiEndpoints.manufacturer_part_list,
|
|
pk: selectedPart?.pk,
|
|
title: t`Delete Manufacturer Part`,
|
|
table: table
|
|
});
|
|
|
|
const tableFilters: TableFilter[] = useMemo(() => {
|
|
return [
|
|
{
|
|
name: 'part_active',
|
|
label: t`Active Part`,
|
|
description: t`Show manufacturer parts for active internal parts.`,
|
|
type: 'boolean'
|
|
},
|
|
{
|
|
name: 'manufacturer_active',
|
|
label: t`Active Manufacturer`,
|
|
active: !manufacturerId,
|
|
description: t`Show manufacturer parts for active manufacturers.`,
|
|
type: 'boolean'
|
|
}
|
|
];
|
|
}, [manufacturerId]);
|
|
|
|
const tableActions = useMemo(() => {
|
|
const can_add =
|
|
user.hasAddRole(UserRoles.purchase_order) &&
|
|
user.hasAddRole(UserRoles.part);
|
|
|
|
return [
|
|
<AddItemButton
|
|
key='add-manufacturer-part'
|
|
tooltip={t`Add Manufacturer Part`}
|
|
onClick={() => createManufacturerPart.open()}
|
|
hidden={!can_add}
|
|
/>
|
|
];
|
|
}, [user]);
|
|
|
|
const rowActions = useCallback(
|
|
(record: any): RowAction[] => {
|
|
return [
|
|
RowEditAction({
|
|
hidden: !user.hasChangeRole(UserRoles.purchase_order),
|
|
onClick: () => {
|
|
setSelectedPart(record);
|
|
editManufacturerPart.open();
|
|
}
|
|
}),
|
|
RowDuplicateAction({
|
|
hidden: !user.hasAddRole(UserRoles.purchase_order),
|
|
onClick: () => {
|
|
setSelectedPart(record);
|
|
duplicateManufacturerPart.open();
|
|
}
|
|
}),
|
|
RowDeleteAction({
|
|
hidden: !user.hasDeleteRole(UserRoles.purchase_order),
|
|
onClick: () => {
|
|
setSelectedPart(record);
|
|
deleteManufacturerPart.open();
|
|
}
|
|
})
|
|
];
|
|
},
|
|
[user]
|
|
);
|
|
|
|
return (
|
|
<>
|
|
{createManufacturerPart.modal}
|
|
{duplicateManufacturerPart.modal}
|
|
{editManufacturerPart.modal}
|
|
{deleteManufacturerPart.modal}
|
|
<InvenTreeTable
|
|
url={apiUrl(ApiEndpoints.manufacturer_part_list)}
|
|
tableState={table}
|
|
columns={tableColumns}
|
|
props={{
|
|
params: {
|
|
part: partId,
|
|
manufacturer: manufacturerId,
|
|
part_detail: true,
|
|
manufacturer_detail: true
|
|
},
|
|
enableDownload: true,
|
|
rowActions: rowActions,
|
|
tableActions: tableActions,
|
|
tableFilters: tableFilters,
|
|
modelType: ModelType.manufacturerpart
|
|
}}
|
|
/>
|
|
</>
|
|
);
|
|
}
|