From 9a215f97f5fe6af0e21073f224199d6fb7b60f9d Mon Sep 17 00:00:00 2001 From: Oliver Date: Mon, 29 Jan 2024 17:51:29 +1100 Subject: [PATCH] [PUI] Tables (#6357) * Cleanup SupplierPartTable * Show PurchaseOrder table on SupplierPart page * Perform edit actions as PATCH requests * Implement ManufacturerPartParameter table * Fix link * supplier part link fix * Revert code which introduced bug * Remove unused import --- .../ManufacturerPartParameterTable.tsx | 96 +++++++++++++++++++ .../tables/purchasing/SupplierPartTable.tsx | 8 +- src/frontend/src/enums/ApiEndpoints.tsx | 1 + src/frontend/src/forms/CompanyForms.tsx | 12 +++ src/frontend/src/functions/forms.tsx | 7 +- .../pages/company/ManufacturerPartDetail.tsx | 12 ++- .../src/pages/company/SupplierPartDetail.tsx | 14 ++- src/frontend/src/states/ApiState.tsx | 2 + 8 files changed, 143 insertions(+), 9 deletions(-) create mode 100644 src/frontend/src/components/tables/purchasing/ManufacturerPartParameterTable.tsx diff --git a/src/frontend/src/components/tables/purchasing/ManufacturerPartParameterTable.tsx b/src/frontend/src/components/tables/purchasing/ManufacturerPartParameterTable.tsx new file mode 100644 index 0000000000..a0c8008b88 --- /dev/null +++ b/src/frontend/src/components/tables/purchasing/ManufacturerPartParameterTable.tsx @@ -0,0 +1,96 @@ +import { t } from '@lingui/macro'; +import { useCallback, useMemo } from 'react'; + +import { ApiPaths } from '../../../enums/ApiEndpoints'; +import { UserRoles } from '../../../enums/Roles'; +import { useManufacturerPartParameterFields } from '../../../forms/CompanyForms'; +import { openDeleteApiForm, openEditApiForm } from '../../../functions/forms'; +import { useTable } from '../../../hooks/UseTable'; +import { apiUrl } from '../../../states/ApiState'; +import { useUserState } from '../../../states/UserState'; +import { TableColumn } from '../Column'; +import { InvenTreeTable } from '../InvenTreeTable'; +import { RowDeleteAction, RowEditAction } from '../RowActions'; + +export default function ManufacturerPartParameterTable({ + params +}: { + params: any; +}) { + const table = useTable('manufacturer-part-parameter'); + const user = useUserState(); + + const tableColumns: TableColumn[] = useMemo(() => { + return [ + { + accessor: 'name', + title: t`Name`, + sortable: true, + switchable: false + }, + { + accessor: 'value', + title: t`Value`, + sortable: true, + switchable: false + }, + { + accessor: 'units', + title: t`Units`, + sortable: false, + switchable: true + } + ]; + }, []); + + const fields = useManufacturerPartParameterFields(); + + const rowActions = useCallback( + (record: any) => { + return [ + RowEditAction({ + hidden: !user.hasChangeRole(UserRoles.purchase_order), + onClick: () => { + openEditApiForm({ + url: ApiPaths.manufacturer_part_parameter_list, + pk: record.pk, + title: t`Edit Parameter`, + fields: fields, + onFormSuccess: table.refreshTable, + successMessage: t`Parameter updated` + }); + } + }), + RowDeleteAction({ + hidden: !user.hasDeleteRole(UserRoles.purchase_order), + onClick: () => { + record.pk && + openDeleteApiForm({ + url: ApiPaths.manufacturer_part_parameter_list, + pk: record.pk, + title: t`Delete Parameter`, + onFormSuccess: table.refreshTable, + successMessage: t`Parameter deleted`, + preFormWarning: t`Are you sure you want to delete this parameter?` + }); + } + }) + ]; + }, + [user] + ); + + return ( + + ); +} diff --git a/src/frontend/src/components/tables/purchasing/SupplierPartTable.tsx b/src/frontend/src/components/tables/purchasing/SupplierPartTable.tsx index 2def89a928..b991e2c165 100644 --- a/src/frontend/src/components/tables/purchasing/SupplierPartTable.tsx +++ b/src/frontend/src/components/tables/purchasing/SupplierPartTable.tsx @@ -48,11 +48,13 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode { render: (record: any) => { let supplier = record?.supplier_detail ?? {}; - return ( + return supplier?.pk ? ( + ) : ( + '-' ); } }, @@ -70,11 +72,13 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode { render: (record: any) => { let manufacturer = record?.manufacturer_detail ?? {}; - return ( + return manufacturer?.pk ? ( + ) : ( + '-' ); } }, diff --git a/src/frontend/src/enums/ApiEndpoints.tsx b/src/frontend/src/enums/ApiEndpoints.tsx index f804ff289c..d2ee26a5df 100644 --- a/src/frontend/src/enums/ApiEndpoints.tsx +++ b/src/frontend/src/enums/ApiEndpoints.tsx @@ -68,6 +68,7 @@ export enum ApiPaths { supplier_part_list = 'api-supplier-part-list', manufacturer_part_list = 'api-manufacturer-part-list', manufacturer_part_attachment_list = 'api-manufacturer-part-attachment-list', + manufacturer_part_parameter_list = 'api-manufacturer-part-parameter-list', address_list = 'api-address-list', contact_list = 'api-contact-list', diff --git a/src/frontend/src/forms/CompanyForms.tsx b/src/frontend/src/forms/CompanyForms.tsx index 0477367a13..d0c41ed2a7 100644 --- a/src/frontend/src/forms/CompanyForms.tsx +++ b/src/frontend/src/forms/CompanyForms.tsx @@ -95,6 +95,18 @@ export function useManufacturerPartFields() { }, []); } +export function useManufacturerPartParameterFields() { + return useMemo(() => { + const fields: ApiFormFieldSet = { + name: {}, + value: {}, + units: {} + }; + + return fields; + }, []); +} + /** * Field set for editing a company instance */ diff --git a/src/frontend/src/functions/forms.tsx b/src/frontend/src/functions/forms.tsx index 39c38108ae..b2b49d4296 100644 --- a/src/frontend/src/functions/forms.tsx +++ b/src/frontend/src/functions/forms.tsx @@ -64,6 +64,11 @@ export function extractAvailableFields( method = method.toUpperCase(); + // PATCH method is supported, but metadata is provided via PUT + if (method === 'PATCH') { + method = 'PUT'; + } + if (!(method in actions)) { // Missing method - this means user does not have appropriate permission permissionDenied(); @@ -290,7 +295,7 @@ export function openEditApiForm(props: OpenApiFormProps) { let editProps: OpenApiFormProps = { ...props, fetchInitialData: props.fetchInitialData ?? true, - method: 'PUT' + method: 'PATCH' }; openModalApiForm(editProps); diff --git a/src/frontend/src/pages/company/ManufacturerPartDetail.tsx b/src/frontend/src/pages/company/ManufacturerPartDetail.tsx index 4be641aa3a..067bd6db73 100644 --- a/src/frontend/src/pages/company/ManufacturerPartDetail.tsx +++ b/src/frontend/src/pages/company/ManufacturerPartDetail.tsx @@ -12,6 +12,7 @@ import { useParams } from 'react-router-dom'; import { PageDetail } from '../../components/nav/PageDetail'; import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; import { AttachmentTable } from '../../components/tables/general/AttachmentTable'; +import ManufacturerPartParameterTable from '../../components/tables/purchasing/ManufacturerPartParameterTable'; import { SupplierPartTable } from '../../components/tables/purchasing/SupplierPartTable'; import { ApiPaths } from '../../enums/ApiEndpoints'; import { useInstance } from '../../hooks/UseInstance'; @@ -39,7 +40,14 @@ export default function ManufacturerPartDetail() { { name: 'parameters', label: t`Parameters`, - icon: + icon: , + content: manufacturerPart?.pk ? ( + + ) : ( + + ) }, { name: 'suppliers', @@ -78,7 +86,7 @@ export default function ManufacturerPartDetail() { }, { name: manufacturerPart?.manufacturer_detail?.name ?? t`Manufacturer`, - url: `/company/manufacturer/${manufacturerPart?.manufacturer_detail?.id}/` + url: `/purchasing/manufacturer/${manufacturerPart?.manufacturer_detail?.pk}/` } ]; }, [manufacturerPart]); diff --git a/src/frontend/src/pages/company/SupplierPartDetail.tsx b/src/frontend/src/pages/company/SupplierPartDetail.tsx index 161dcffec2..a903cb7ec0 100644 --- a/src/frontend/src/pages/company/SupplierPartDetail.tsx +++ b/src/frontend/src/pages/company/SupplierPartDetail.tsx @@ -1,5 +1,5 @@ import { t } from '@lingui/macro'; -import { LoadingOverlay, Stack } from '@mantine/core'; +import { LoadingOverlay, Skeleton, Stack } from '@mantine/core'; import { IconCurrencyDollar, IconInfoCircle, @@ -11,6 +11,7 @@ import { useParams } from 'react-router-dom'; import { PageDetail } from '../../components/nav/PageDetail'; import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; +import { PurchaseOrderTable } from '../../components/tables/purchasing/PurchaseOrderTable'; import { ApiPaths } from '../../enums/ApiEndpoints'; import { useInstance } from '../../hooks/UseInstance'; @@ -42,7 +43,12 @@ export default function SupplierPartDetail() { { name: 'purchaseorders', label: t`Purchase Orders`, - icon: + icon: , + content: supplierPart?.pk ? ( + + ) : ( + + ) }, { name: 'pricing', @@ -50,7 +56,7 @@ export default function SupplierPartDetail() { icon: } ]; - }, []); + }, [supplierPart]); const breadcrumbs = useMemo(() => { return [ @@ -60,7 +66,7 @@ export default function SupplierPartDetail() { }, { name: supplierPart?.supplier_detail?.name ?? t`Supplier`, - url: `/company/supplier/${supplierPart?.supplier_detail?.pk ?? ''}` + url: `/purchasing/supplier/${supplierPart?.supplier_detail?.pk ?? ''}` } ]; }, [supplierPart]); diff --git a/src/frontend/src/states/ApiState.tsx b/src/frontend/src/states/ApiState.tsx index 34f0bd4e35..4a660a8be1 100644 --- a/src/frontend/src/states/ApiState.tsx +++ b/src/frontend/src/states/ApiState.tsx @@ -185,6 +185,8 @@ export function apiEndpoint(path: ApiPaths): string { return 'company/part/manufacturer/'; case ApiPaths.manufacturer_part_attachment_list: return 'company/part/manufacturer/attachment/'; + case ApiPaths.manufacturer_part_parameter_list: + return 'company/part/manufacturer/parameter/'; case ApiPaths.stock_item_list: return 'stock/'; case ApiPaths.stock_tracking_list: