mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
[PUI] Details Pages (#6718)
* Add "details" view to SupplierPart page * Fix PartActions * Add placeholder for actions * Add "title" option to DetailsTable * Add edit form to supplier part page * Fix link to manufacturer part * Add "details" view to ManufacturerPartDetail page * Add edit for ManufacturerPart * Create new manufacturer part from company table * Tweak ActionIcon
This commit is contained in:
parent
57a1a81e9b
commit
160d014e44
@ -39,7 +39,7 @@ export function ActionButton(props: ActionButtonProps) {
|
||||
color={props.color}
|
||||
size={props.size}
|
||||
onClick={props.onClick ?? notYetImplemented}
|
||||
variant={props.variant}
|
||||
variant={props.variant ?? 'light'}
|
||||
>
|
||||
<Group spacing="xs" noWrap={true}>
|
||||
{props.icon}
|
||||
|
@ -7,6 +7,7 @@ import {
|
||||
Group,
|
||||
Paper,
|
||||
Skeleton,
|
||||
Stack,
|
||||
Table,
|
||||
Text,
|
||||
Tooltip
|
||||
@ -22,6 +23,7 @@ import { getDetailUrl } from '../../functions/urls';
|
||||
import { apiUrl } from '../../states/ApiState';
|
||||
import { useGlobalSettingsState } from '../../states/SettingsState';
|
||||
import { ProgressBar } from '../items/ProgressBar';
|
||||
import { StylishText } from '../items/StylishText';
|
||||
import { YesNoButton } from '../items/YesNoButton';
|
||||
import { getModelInfo } from '../render/ModelType';
|
||||
import { StatusRenderer } from '../render/StatusRenderer';
|
||||
@ -385,22 +387,27 @@ export function DetailsTableField({
|
||||
|
||||
export function DetailsTable({
|
||||
item,
|
||||
fields
|
||||
fields,
|
||||
title
|
||||
}: {
|
||||
item: any;
|
||||
fields: DetailsField[];
|
||||
title?: string;
|
||||
}) {
|
||||
return (
|
||||
<Paper p="xs" withBorder radius="xs">
|
||||
<Table striped>
|
||||
<tbody>
|
||||
{fields
|
||||
.filter((field: DetailsField) => !field.hidden)
|
||||
.map((field: DetailsField, index: number) => (
|
||||
<DetailsTableField field={field} item={item} key={index} />
|
||||
))}
|
||||
</tbody>
|
||||
</Table>
|
||||
<Stack spacing="xs">
|
||||
{title && <StylishText size="lg">{title}</StylishText>}
|
||||
<Table striped>
|
||||
<tbody>
|
||||
{fields
|
||||
.filter((field: DetailsField) => !field.hidden)
|
||||
.map((field: DetailsField, index: number) => (
|
||||
<DetailsTableField field={field} item={item} key={index} />
|
||||
))}
|
||||
</tbody>
|
||||
</Table>
|
||||
</Stack>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
@ -117,12 +117,15 @@ const icons = {
|
||||
test_templates: IconTestPipe,
|
||||
related_parts: IconLayersLinked,
|
||||
attachments: IconPaperclip,
|
||||
note: IconNotes,
|
||||
notes: IconNotes,
|
||||
photo: IconPhoto,
|
||||
upload: IconFileUpload,
|
||||
reject: IconX,
|
||||
select_image: IconGridDots,
|
||||
delete: IconTrash,
|
||||
packaging: IconPackage,
|
||||
packages: IconPackages,
|
||||
|
||||
// Part Icons
|
||||
active: IconCheck,
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { t } from '@lingui/macro';
|
||||
import { LoadingOverlay, Skeleton, Stack } from '@mantine/core';
|
||||
import { Grid, LoadingOverlay, Skeleton, Stack } from '@mantine/core';
|
||||
import {
|
||||
IconBuildingWarehouse,
|
||||
IconDots,
|
||||
IconInfoCircle,
|
||||
IconList,
|
||||
IconPaperclip
|
||||
@ -9,18 +10,38 @@ import {
|
||||
import { useMemo } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import { DetailsField, DetailsTable } from '../../components/details/Details';
|
||||
import { DetailsImage } from '../../components/details/DetailsImage';
|
||||
import { ItemDetailsGrid } from '../../components/details/ItemDetails';
|
||||
import {
|
||||
ActionDropdown,
|
||||
DeleteItemAction,
|
||||
DuplicateItemAction,
|
||||
EditItemAction
|
||||
} from '../../components/items/ActionDropdown';
|
||||
import { PageDetail } from '../../components/nav/PageDetail';
|
||||
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||
import { ModelType } from '../../enums/ModelType';
|
||||
import { UserRoles } from '../../enums/Roles';
|
||||
import { useManufacturerPartFields } from '../../forms/CompanyForms';
|
||||
import { useEditApiFormModal } from '../../hooks/UseForm';
|
||||
import { useInstance } from '../../hooks/UseInstance';
|
||||
import { apiUrl } from '../../states/ApiState';
|
||||
import { useUserState } from '../../states/UserState';
|
||||
import { AttachmentTable } from '../../tables/general/AttachmentTable';
|
||||
import ManufacturerPartParameterTable from '../../tables/purchasing/ManufacturerPartParameterTable';
|
||||
import { SupplierPartTable } from '../../tables/purchasing/SupplierPartTable';
|
||||
|
||||
export default function ManufacturerPartDetail() {
|
||||
const { id } = useParams();
|
||||
const user = useUserState();
|
||||
|
||||
const { instance: manufacturerPart, instanceQuery } = useInstance({
|
||||
const {
|
||||
instance: manufacturerPart,
|
||||
instanceQuery,
|
||||
refreshInstance
|
||||
} = useInstance({
|
||||
endpoint: ApiEndpoints.manufacturer_part_list,
|
||||
pk: id,
|
||||
hasPrimaryKey: true,
|
||||
@ -30,12 +51,91 @@ export default function ManufacturerPartDetail() {
|
||||
}
|
||||
});
|
||||
|
||||
const detailsPanel = useMemo(() => {
|
||||
if (instanceQuery.isFetching) {
|
||||
return <Skeleton />;
|
||||
}
|
||||
|
||||
let data = manufacturerPart ?? {};
|
||||
|
||||
let tl: DetailsField[] = [
|
||||
{
|
||||
type: 'link',
|
||||
name: 'part',
|
||||
label: t`Internal Part`,
|
||||
model: ModelType.part,
|
||||
hidden: !manufacturerPart.part
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'description',
|
||||
label: t`Description`,
|
||||
copy: true,
|
||||
hidden: !manufacturerPart.description
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
external: true,
|
||||
name: 'link',
|
||||
label: t`External Link`,
|
||||
copy: true,
|
||||
hidden: !manufacturerPart.link
|
||||
}
|
||||
];
|
||||
|
||||
let tr: DetailsField[] = [
|
||||
{
|
||||
type: 'link',
|
||||
name: 'manufacturer',
|
||||
label: t`Manufacturer`,
|
||||
icon: 'manufacturers',
|
||||
model: ModelType.company,
|
||||
hidden: !manufacturerPart.manufacturer
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'MPN',
|
||||
label: t`Manufacturer Part Number`,
|
||||
copy: true,
|
||||
hidden: !manufacturerPart.MPN,
|
||||
icon: 'reference'
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<ItemDetailsGrid>
|
||||
<Grid>
|
||||
<Grid.Col span={4}>
|
||||
<DetailsImage
|
||||
appRole={UserRoles.part}
|
||||
src={manufacturerPart?.part_detail?.image}
|
||||
apiPath={apiUrl(
|
||||
ApiEndpoints.part_list,
|
||||
manufacturerPart?.part_detail?.pk
|
||||
)}
|
||||
pk={manufacturerPart?.part_detail?.pk}
|
||||
/>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={8}>
|
||||
<DetailsTable
|
||||
title={t`Manufacturer Part`}
|
||||
fields={tl}
|
||||
item={data}
|
||||
/>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
<DetailsTable title={t`Manufacturer Details`} fields={tr} item={data} />
|
||||
</ItemDetailsGrid>
|
||||
);
|
||||
}, [manufacturerPart, instanceQuery]);
|
||||
|
||||
const panels: PanelType[] = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
name: 'details',
|
||||
label: t`Details`,
|
||||
icon: <IconInfoCircle />
|
||||
label: t`Manufacturer Part Details`,
|
||||
icon: <IconInfoCircle />,
|
||||
content: detailsPanel
|
||||
},
|
||||
{
|
||||
name: 'parameters',
|
||||
@ -78,6 +178,38 @@ export default function ManufacturerPartDetail() {
|
||||
];
|
||||
}, [manufacturerPart]);
|
||||
|
||||
const editManufacturerPartFields = useManufacturerPartFields();
|
||||
|
||||
const editManufacturerPart = useEditApiFormModal({
|
||||
url: ApiEndpoints.manufacturer_part_list,
|
||||
pk: manufacturerPart?.pk,
|
||||
title: t`Edit Manufacturer Part`,
|
||||
fields: editManufacturerPartFields,
|
||||
onFormSuccess: refreshInstance
|
||||
});
|
||||
|
||||
const manufacturerPartActions = useMemo(() => {
|
||||
return [
|
||||
<ActionDropdown
|
||||
key="part"
|
||||
tooltip={t`Manufacturer Part Actions`}
|
||||
icon={<IconDots />}
|
||||
actions={[
|
||||
DuplicateItemAction({
|
||||
hidden: !user.hasAddRole(UserRoles.purchase_order)
|
||||
}),
|
||||
EditItemAction({
|
||||
hidden: !user.hasChangeRole(UserRoles.purchase_order),
|
||||
onClick: () => editManufacturerPart.open()
|
||||
}),
|
||||
DeleteItemAction({
|
||||
hidden: !user.hasDeleteRole(UserRoles.purchase_order)
|
||||
})
|
||||
]}
|
||||
/>
|
||||
];
|
||||
}, [user]);
|
||||
|
||||
const breadcrumbs = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
@ -92,15 +224,19 @@ export default function ManufacturerPartDetail() {
|
||||
}, [manufacturerPart]);
|
||||
|
||||
return (
|
||||
<Stack spacing="xs">
|
||||
<LoadingOverlay visible={instanceQuery.isFetching} />
|
||||
<PageDetail
|
||||
title={t`ManufacturerPart`}
|
||||
subtitle={`${manufacturerPart.MPN} - ${manufacturerPart.part_detail?.name}`}
|
||||
breadcrumbs={breadcrumbs}
|
||||
imageUrl={manufacturerPart?.part_detail?.thumbnail}
|
||||
/>
|
||||
<PanelGroup pageKey="manufacturerpart" panels={panels} />
|
||||
</Stack>
|
||||
<>
|
||||
{editManufacturerPart.modal}
|
||||
<Stack spacing="xs">
|
||||
<LoadingOverlay visible={instanceQuery.isFetching} />
|
||||
<PageDetail
|
||||
title={t`ManufacturerPart`}
|
||||
subtitle={`${manufacturerPart.MPN} - ${manufacturerPart.part_detail?.name}`}
|
||||
breadcrumbs={breadcrumbs}
|
||||
actions={manufacturerPartActions}
|
||||
imageUrl={manufacturerPart?.part_detail?.thumbnail}
|
||||
/>
|
||||
<PanelGroup pageKey="manufacturerpart" panels={panels} />
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { t } from '@lingui/macro';
|
||||
import { LoadingOverlay, Skeleton, Stack } from '@mantine/core';
|
||||
import { Grid, LoadingOverlay, Skeleton, Stack } from '@mantine/core';
|
||||
import {
|
||||
IconCurrencyDollar,
|
||||
IconDots,
|
||||
IconInfoCircle,
|
||||
IconPackages,
|
||||
IconShoppingCart
|
||||
@ -9,16 +10,37 @@ import {
|
||||
import { useMemo } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import { DetailsField, DetailsTable } from '../../components/details/Details';
|
||||
import { DetailsImage } from '../../components/details/DetailsImage';
|
||||
import { ItemDetailsGrid } from '../../components/details/ItemDetails';
|
||||
import {
|
||||
ActionDropdown,
|
||||
DeleteItemAction,
|
||||
DuplicateItemAction,
|
||||
EditItemAction
|
||||
} from '../../components/items/ActionDropdown';
|
||||
import { PageDetail } from '../../components/nav/PageDetail';
|
||||
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||
import { ModelType } from '../../enums/ModelType';
|
||||
import { UserRoles } from '../../enums/Roles';
|
||||
import { useSupplierPartFields } from '../../forms/CompanyForms';
|
||||
import { useEditApiFormModal } from '../../hooks/UseForm';
|
||||
import { useInstance } from '../../hooks/UseInstance';
|
||||
import { apiUrl } from '../../states/ApiState';
|
||||
import { useUserState } from '../../states/UserState';
|
||||
import { PurchaseOrderTable } from '../../tables/purchasing/PurchaseOrderTable';
|
||||
|
||||
export default function SupplierPartDetail() {
|
||||
const { id } = useParams();
|
||||
|
||||
const { instance: supplierPart, instanceQuery } = useInstance({
|
||||
const user = useUserState();
|
||||
|
||||
const {
|
||||
instance: supplierPart,
|
||||
instanceQuery,
|
||||
refreshInstance
|
||||
} = useInstance({
|
||||
endpoint: ApiEndpoints.supplier_part_list,
|
||||
pk: id,
|
||||
hasPrimaryKey: true,
|
||||
@ -28,12 +50,153 @@ export default function SupplierPartDetail() {
|
||||
}
|
||||
});
|
||||
|
||||
const detailsPanel = useMemo(() => {
|
||||
if (instanceQuery.isFetching) {
|
||||
return <Skeleton />;
|
||||
}
|
||||
|
||||
let data = supplierPart ?? {};
|
||||
|
||||
// Access nested data
|
||||
data.manufacturer = data.manufacturer_detail?.pk;
|
||||
data.MPN = data.manufacturer_part_detail?.MPN;
|
||||
data.manufacturer_part = data.manufacturer_part_detail?.pk;
|
||||
|
||||
let tl: DetailsField[] = [
|
||||
{
|
||||
type: 'link',
|
||||
name: 'part',
|
||||
label: t`Internal Part`,
|
||||
model: ModelType.part,
|
||||
hidden: !supplierPart.part
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'description',
|
||||
label: t`Description`,
|
||||
copy: true
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
external: true,
|
||||
name: 'link',
|
||||
label: t`External Link`,
|
||||
copy: true,
|
||||
hidden: !supplierPart.link
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'note',
|
||||
label: t`Note`,
|
||||
copy: true,
|
||||
hidden: !supplierPart.note
|
||||
}
|
||||
];
|
||||
|
||||
let tr: DetailsField[] = [
|
||||
{
|
||||
type: 'link',
|
||||
name: 'supplier',
|
||||
label: t`Supplier`,
|
||||
model: ModelType.company,
|
||||
icon: 'suppliers',
|
||||
hidden: !supplierPart.supplier
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'SKU',
|
||||
label: t`SKU`,
|
||||
copy: true,
|
||||
icon: 'reference'
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
name: 'manufacturer',
|
||||
label: t`Manufacturer`,
|
||||
model: ModelType.company,
|
||||
icon: 'manufacturers',
|
||||
hidden: !data.manufacturer
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
name: 'manufacturer_part',
|
||||
model_field: 'MPN',
|
||||
label: t`Manufacturer Part Number`,
|
||||
model: ModelType.manufacturerpart,
|
||||
copy: true,
|
||||
icon: 'reference',
|
||||
hidden: !data.manufacturer_part
|
||||
}
|
||||
];
|
||||
|
||||
let bl: DetailsField[] = [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'packaging',
|
||||
label: t`Packaging`,
|
||||
copy: true,
|
||||
hidden: !data.packaging
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'pack_quantity',
|
||||
label: t`Pack Quantity`,
|
||||
copy: true,
|
||||
hidden: !data.pack_quantity,
|
||||
icon: 'packages'
|
||||
}
|
||||
];
|
||||
|
||||
let br: DetailsField[] = [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'available',
|
||||
label: t`Supplier Availability`,
|
||||
copy: true,
|
||||
icon: 'packages'
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'availability_updated',
|
||||
label: t`Availability Updated`,
|
||||
copy: true,
|
||||
hidden: !data.availability_updated,
|
||||
icon: 'calendar'
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<ItemDetailsGrid>
|
||||
<Grid>
|
||||
<Grid.Col span={4}>
|
||||
<DetailsImage
|
||||
appRole={UserRoles.part}
|
||||
src={supplierPart?.part_detail?.image}
|
||||
apiPath={apiUrl(
|
||||
ApiEndpoints.part_list,
|
||||
supplierPart?.part_detail?.pk
|
||||
)}
|
||||
pk={supplierPart?.part_detail?.pk}
|
||||
/>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={8}>
|
||||
<DetailsTable title={t`Supplier Part`} fields={tl} item={data} />
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
<DetailsTable title={t`Supplier`} fields={tr} item={data} />
|
||||
<DetailsTable title={t`Packaging`} fields={bl} item={data} />
|
||||
<DetailsTable title={t`Availability`} fields={br} item={data} />
|
||||
</ItemDetailsGrid>
|
||||
);
|
||||
}, [supplierPart, instanceQuery.isFetching]);
|
||||
|
||||
const panels: PanelType[] = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
name: 'details',
|
||||
label: t`Details`,
|
||||
icon: <IconInfoCircle />
|
||||
label: t`Supplier Part Details`,
|
||||
icon: <IconInfoCircle />,
|
||||
content: detailsPanel
|
||||
},
|
||||
{
|
||||
name: 'stock',
|
||||
@ -58,6 +221,41 @@ export default function SupplierPartDetail() {
|
||||
];
|
||||
}, [supplierPart]);
|
||||
|
||||
const supplierPartActions = useMemo(() => {
|
||||
return [
|
||||
<ActionDropdown
|
||||
key="part"
|
||||
tooltip={t`Supplier Part Actions`}
|
||||
icon={<IconDots />}
|
||||
actions={[
|
||||
DuplicateItemAction({
|
||||
hidden: !user.hasAddRole(UserRoles.purchase_order)
|
||||
}),
|
||||
EditItemAction({
|
||||
hidden: !user.hasChangeRole(UserRoles.purchase_order),
|
||||
onClick: () => editSuppliertPart.open()
|
||||
}),
|
||||
DeleteItemAction({
|
||||
hidden: !user.hasDeleteRole(UserRoles.purchase_order)
|
||||
})
|
||||
]}
|
||||
/>
|
||||
];
|
||||
}, [user]);
|
||||
|
||||
const editSupplierPartFields = useSupplierPartFields({
|
||||
hidePart: true,
|
||||
partPk: supplierPart?.pk
|
||||
});
|
||||
|
||||
const editSuppliertPart = useEditApiFormModal({
|
||||
url: ApiEndpoints.supplier_part_list,
|
||||
pk: supplierPart?.pk,
|
||||
title: t`Edit Supplier Part`,
|
||||
fields: editSupplierPartFields,
|
||||
onFormSuccess: refreshInstance
|
||||
});
|
||||
|
||||
const breadcrumbs = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
@ -72,15 +270,19 @@ export default function SupplierPartDetail() {
|
||||
}, [supplierPart]);
|
||||
|
||||
return (
|
||||
<Stack spacing="xs">
|
||||
<LoadingOverlay visible={instanceQuery.isFetching} />
|
||||
<PageDetail
|
||||
title={t`Supplier Part`}
|
||||
subtitle={`${supplierPart.SKU} - ${supplierPart?.part_detail?.name}`}
|
||||
breadcrumbs={breadcrumbs}
|
||||
imageUrl={supplierPart?.part_detail?.thumbnail}
|
||||
/>
|
||||
<PanelGroup pageKey="supplierpart" panels={panels} />
|
||||
</Stack>
|
||||
<>
|
||||
{editSuppliertPart.modal}
|
||||
<Stack spacing="xs">
|
||||
<LoadingOverlay visible={instanceQuery.isFetching} />
|
||||
<PageDetail
|
||||
title={t`Supplier Part`}
|
||||
subtitle={`${supplierPart.SKU} - ${supplierPart?.part_detail?.name}`}
|
||||
breadcrumbs={breadcrumbs}
|
||||
actions={supplierPartActions}
|
||||
imageUrl={supplierPart?.part_detail?.thumbnail}
|
||||
/>
|
||||
<PanelGroup pageKey="supplierpart" panels={panels} />
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -655,7 +655,6 @@ export default function PartDetail() {
|
||||
const transferStockItems = useTransferStockItem(stockActionProps);
|
||||
|
||||
const partActions = useMemo(() => {
|
||||
// TODO: Disable actions based on user permissions
|
||||
return [
|
||||
<BarcodeActionDropdown
|
||||
actions={[
|
||||
@ -679,6 +678,7 @@ export default function PartDetail() {
|
||||
),
|
||||
name: t`Count Stock`,
|
||||
tooltip: t`Count part stock`,
|
||||
hidden: !user.hasChangeRole(UserRoles.stock),
|
||||
onClick: () => {
|
||||
part.pk && countStockItems.open();
|
||||
}
|
||||
@ -689,6 +689,7 @@ export default function PartDetail() {
|
||||
),
|
||||
name: t`Transfer Stock`,
|
||||
tooltip: t`Transfer part stock`,
|
||||
hidden: !user.hasChangeRole(UserRoles.stock),
|
||||
onClick: () => {
|
||||
part.pk && transferStockItems.open();
|
||||
}
|
||||
@ -700,13 +701,15 @@ export default function PartDetail() {
|
||||
tooltip={t`Part Actions`}
|
||||
icon={<IconDots />}
|
||||
actions={[
|
||||
DuplicateItemAction({}),
|
||||
DuplicateItemAction({
|
||||
hidden: !user.hasAddRole(UserRoles.part)
|
||||
}),
|
||||
EditItemAction({
|
||||
hidden: !user.hasChangeRole(UserRoles.part),
|
||||
onClick: () => editPart.open()
|
||||
}),
|
||||
DeleteItemAction({
|
||||
hidden: part?.active
|
||||
hidden: part?.active || !user.hasDeleteRole(UserRoles.part)
|
||||
})
|
||||
]}
|
||||
/>
|
||||
|
@ -11,6 +11,7 @@ import { useManufacturerPartFields } from '../../forms/CompanyForms';
|
||||
import { openDeleteApiForm, openEditApiForm } from '../../functions/forms';
|
||||
import { notYetImplemented } from '../../functions/notifications';
|
||||
import { getDetailUrl } from '../../functions/urls';
|
||||
import { useCreateApiFormModal } from '../../hooks/UseForm';
|
||||
import { useTable } from '../../hooks/UseTable';
|
||||
import { apiUrl } from '../../states/ApiState';
|
||||
import { useUserState } from '../../states/UserState';
|
||||
@ -61,9 +62,15 @@ export function ManufacturerPartTable({ params }: { params: any }): ReactNode {
|
||||
];
|
||||
}, [params]);
|
||||
|
||||
const addManufacturerPart = useCallback(() => {
|
||||
notYetImplemented();
|
||||
}, []);
|
||||
const createManufacturerPart = useCreateApiFormModal({
|
||||
url: ApiEndpoints.manufacturer_part_list,
|
||||
title: t`Create Manufacturer Part`,
|
||||
fields: useManufacturerPartFields(),
|
||||
onFormSuccess: table.refreshTable,
|
||||
initialData: {
|
||||
manufacturer: params?.manufacturer
|
||||
}
|
||||
});
|
||||
|
||||
const tableActions = useMemo(() => {
|
||||
let can_add =
|
||||
@ -73,7 +80,7 @@ export function ManufacturerPartTable({ params }: { params: any }): ReactNode {
|
||||
return [
|
||||
<AddItemButton
|
||||
tooltip={t`Add Manufacturer Part`}
|
||||
onClick={addManufacturerPart}
|
||||
onClick={() => createManufacturerPart.open()}
|
||||
hidden={!can_add}
|
||||
/>
|
||||
];
|
||||
@ -118,24 +125,27 @@ export function ManufacturerPartTable({ params }: { params: any }): ReactNode {
|
||||
);
|
||||
|
||||
return (
|
||||
<InvenTreeTable
|
||||
url={apiUrl(ApiEndpoints.manufacturer_part_list)}
|
||||
tableState={table}
|
||||
columns={tableColumns}
|
||||
props={{
|
||||
params: {
|
||||
...params,
|
||||
part_detail: true,
|
||||
manufacturer_detail: true
|
||||
},
|
||||
rowActions: rowActions,
|
||||
tableActions: tableActions,
|
||||
onRowClick: (record: any) => {
|
||||
if (record?.pk) {
|
||||
navigate(getDetailUrl(ModelType.manufacturerpart, record.pk));
|
||||
<>
|
||||
{createManufacturerPart.modal}
|
||||
<InvenTreeTable
|
||||
url={apiUrl(ApiEndpoints.manufacturer_part_list)}
|
||||
tableState={table}
|
||||
columns={tableColumns}
|
||||
props={{
|
||||
params: {
|
||||
...params,
|
||||
part_detail: true,
|
||||
manufacturer_detail: true
|
||||
},
|
||||
rowActions: rowActions,
|
||||
tableActions: tableActions,
|
||||
onRowClick: (record: any) => {
|
||||
if (record?.pk) {
|
||||
navigate(getDetailUrl(ModelType.manufacturerpart, record.pk));
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user