mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
[PUI] Part parameter table (#6599)
* Refactor for PartTable * Skeleton for ParametricPartTable * Implement parametric part table * Table updates
This commit is contained in:
parent
a2a7b60d41
commit
820d7c6a15
@ -8,13 +8,14 @@ import {
|
|||||||
import { useMemo, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import { PlaceholderPanel } from '../../components/items/Placeholder';
|
|
||||||
import { PageDetail } from '../../components/nav/PageDetail';
|
import { PageDetail } from '../../components/nav/PageDetail';
|
||||||
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
||||||
import { PartCategoryTree } from '../../components/nav/PartCategoryTree';
|
import { PartCategoryTree } from '../../components/nav/PartCategoryTree';
|
||||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||||
import { useInstance } from '../../hooks/UseInstance';
|
import { useInstance } from '../../hooks/UseInstance';
|
||||||
|
import ParametricPartTable from '../../tables/part/ParametricPartTable';
|
||||||
import { PartCategoryTable } from '../../tables/part/PartCategoryTable';
|
import { PartCategoryTable } from '../../tables/part/PartCategoryTable';
|
||||||
|
import { PartParameterTable } from '../../tables/part/PartParameterTable';
|
||||||
import { PartListTable } from '../../tables/part/PartTable';
|
import { PartListTable } from '../../tables/part/PartTable';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -70,7 +71,7 @@ export default function CategoryDetail({}: {}) {
|
|||||||
name: 'parameters',
|
name: 'parameters',
|
||||||
label: t`Parameters`,
|
label: t`Parameters`,
|
||||||
icon: <IconListDetails />,
|
icon: <IconListDetails />,
|
||||||
content: <PlaceholderPanel />
|
content: <ParametricPartTable categoryId={id} />
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[category, id]
|
[category, id]
|
||||||
|
@ -29,7 +29,6 @@ import {
|
|||||||
UnlinkBarcodeAction,
|
UnlinkBarcodeAction,
|
||||||
ViewBarcodeAction
|
ViewBarcodeAction
|
||||||
} from '../../components/items/ActionDropdown';
|
} from '../../components/items/ActionDropdown';
|
||||||
import { PlaceholderPanel } from '../../components/items/Placeholder';
|
|
||||||
import { PageDetail } from '../../components/nav/PageDetail';
|
import { PageDetail } from '../../components/nav/PageDetail';
|
||||||
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
||||||
import { StockLocationTree } from '../../components/nav/StockLocationTree';
|
import { StockLocationTree } from '../../components/nav/StockLocationTree';
|
||||||
@ -69,20 +68,17 @@ export default function StockDetail() {
|
|||||||
{
|
{
|
||||||
name: 'details',
|
name: 'details',
|
||||||
label: t`Details`,
|
label: t`Details`,
|
||||||
icon: <IconInfoCircle />,
|
icon: <IconInfoCircle />
|
||||||
content: <PlaceholderPanel />
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'tracking',
|
name: 'tracking',
|
||||||
label: t`Stock Tracking`,
|
label: t`Stock Tracking`,
|
||||||
icon: <IconHistory />,
|
icon: <IconHistory />
|
||||||
content: <PlaceholderPanel />
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'allocations',
|
name: 'allocations',
|
||||||
label: t`Allocations`,
|
label: t`Allocations`,
|
||||||
icon: <IconBookmark />,
|
icon: <IconBookmark />,
|
||||||
content: <PlaceholderPanel />,
|
|
||||||
hidden:
|
hidden:
|
||||||
!stockitem?.part_detail?.salable && !stockitem?.part_detail?.component
|
!stockitem?.part_detail?.salable && !stockitem?.part_detail?.component
|
||||||
},
|
},
|
||||||
|
122
src/frontend/src/tables/part/ParametricPartTable.tsx
Normal file
122
src/frontend/src/tables/part/ParametricPartTable.tsx
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
import { t } from '@lingui/macro';
|
||||||
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { api } from '../../App';
|
||||||
|
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||||
|
import { ModelType } from '../../enums/ModelType';
|
||||||
|
import { getDetailUrl } from '../../functions/urls';
|
||||||
|
import { useTable } from '../../hooks/UseTable';
|
||||||
|
import { apiUrl } from '../../states/ApiState';
|
||||||
|
import { useUserState } from '../../states/UserState';
|
||||||
|
import { TableColumn } from '../Column';
|
||||||
|
import { DescriptionColumn, PartColumn } from '../ColumnRenderers';
|
||||||
|
import { InvenTreeTable } from '../InvenTreeTable';
|
||||||
|
import { TableHoverCard } from '../TableHoverCard';
|
||||||
|
|
||||||
|
export default function ParametricPartTable({
|
||||||
|
categoryId
|
||||||
|
}: {
|
||||||
|
categoryId?: any;
|
||||||
|
}) {
|
||||||
|
const table = useTable('parametric-parts');
|
||||||
|
const user = useUserState();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const categoryParmeters = useQuery({
|
||||||
|
queryKey: ['category-parameters', categoryId],
|
||||||
|
queryFn: async () => {
|
||||||
|
return api
|
||||||
|
.get(apiUrl(ApiEndpoints.part_parameter_template_list), {
|
||||||
|
params: {
|
||||||
|
category: categoryId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((response) => response.data)
|
||||||
|
.catch((_error) => []);
|
||||||
|
},
|
||||||
|
refetchOnMount: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const parameterColumns: TableColumn[] = useMemo(() => {
|
||||||
|
let data = categoryParmeters.data ?? [];
|
||||||
|
|
||||||
|
return data.map((template: any) => {
|
||||||
|
return {
|
||||||
|
accessor: `parameter_${template.pk}`,
|
||||||
|
title: template.name,
|
||||||
|
sortable: true,
|
||||||
|
render: (record: any) => {
|
||||||
|
// Find matching template parameter
|
||||||
|
let parameter = record.parameters?.find(
|
||||||
|
(p: any) => p.template == template.pk
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!parameter) {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
let extra: any[] = [];
|
||||||
|
|
||||||
|
if (
|
||||||
|
template.units &&
|
||||||
|
parameter.data_numeric &&
|
||||||
|
parameter.data_numeric != parameter.data
|
||||||
|
) {
|
||||||
|
extra.push(`${parameter.data_numeric} [${template.units}]`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableHoverCard
|
||||||
|
value={parameter.data}
|
||||||
|
extra={extra}
|
||||||
|
title={t`Internal Units`}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}, [categoryParmeters.data]);
|
||||||
|
|
||||||
|
const tableColumns: TableColumn[] = useMemo(() => {
|
||||||
|
const partColumns: TableColumn[] = [
|
||||||
|
{
|
||||||
|
accessor: 'name',
|
||||||
|
sortable: true,
|
||||||
|
switchable: false,
|
||||||
|
noWrap: true,
|
||||||
|
render: (record: any) => PartColumn(record)
|
||||||
|
},
|
||||||
|
DescriptionColumn({}),
|
||||||
|
{
|
||||||
|
accessor: 'IPN',
|
||||||
|
sortable: true
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return [...partColumns, ...parameterColumns];
|
||||||
|
}, [parameterColumns]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<InvenTreeTable
|
||||||
|
url={apiUrl(ApiEndpoints.part_list)}
|
||||||
|
tableState={table}
|
||||||
|
columns={tableColumns}
|
||||||
|
props={{
|
||||||
|
enableDownload: false,
|
||||||
|
params: {
|
||||||
|
category: categoryId,
|
||||||
|
cascade: true,
|
||||||
|
category_detail: true,
|
||||||
|
parameters: true
|
||||||
|
},
|
||||||
|
onRowClick: (record) => {
|
||||||
|
if (record.pk) {
|
||||||
|
navigate(getDetailUrl(ModelType.part, record.pk));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
@ -19,6 +19,7 @@ import { TableColumn } from '../Column';
|
|||||||
import { DescriptionColumn, PartColumn } from '../ColumnRenderers';
|
import { DescriptionColumn, PartColumn } from '../ColumnRenderers';
|
||||||
import { InvenTreeTable } from '../InvenTreeTable';
|
import { InvenTreeTable } from '../InvenTreeTable';
|
||||||
import { RowDeleteAction, RowEditAction } from '../RowActions';
|
import { RowDeleteAction, RowEditAction } from '../RowActions';
|
||||||
|
import { TableHoverCard } from '../TableHoverCard';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a table listing parameters for a given part
|
* Construct a table listing parameters for a given part
|
||||||
@ -65,13 +66,23 @@ export function PartParameterTable({ partId }: { partId: any }) {
|
|||||||
return <YesNoButton value={record.data} />;
|
return <YesNoButton value={record.data} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (record.data_numeric) {
|
let extra: any[] = [];
|
||||||
// TODO: Numeric data
|
|
||||||
|
if (
|
||||||
|
template.units &&
|
||||||
|
record.data_numeric &&
|
||||||
|
record.data_numeric != record.data
|
||||||
|
) {
|
||||||
|
extra.push(`${record.data_numeric} [${template.units}]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Units
|
return (
|
||||||
|
<TableHoverCard
|
||||||
return record.data;
|
value={record.data}
|
||||||
|
extra={extra}
|
||||||
|
title={t`Internal Units`}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -17,7 +17,7 @@ import { useTable } from '../../hooks/UseTable';
|
|||||||
import { apiUrl } from '../../states/ApiState';
|
import { apiUrl } from '../../states/ApiState';
|
||||||
import { useUserState } from '../../states/UserState';
|
import { useUserState } from '../../states/UserState';
|
||||||
import { TableColumn } from '../Column';
|
import { TableColumn } from '../Column';
|
||||||
import { DescriptionColumn, LinkColumn } from '../ColumnRenderers';
|
import { DescriptionColumn, LinkColumn, PartColumn } from '../ColumnRenderers';
|
||||||
import { TableFilter } from '../Filter';
|
import { TableFilter } from '../Filter';
|
||||||
import { InvenTreeTable, InvenTreeTableProps } from '../InvenTreeTable';
|
import { InvenTreeTable, InvenTreeTableProps } from '../InvenTreeTable';
|
||||||
import { TableHoverCard } from '../TableHoverCard';
|
import { TableHoverCard } from '../TableHoverCard';
|
||||||
@ -31,15 +31,7 @@ function partTableColumns(): TableColumn[] {
|
|||||||
accessor: 'name',
|
accessor: 'name',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
noWrap: true,
|
noWrap: true,
|
||||||
render: function (record: any) {
|
render: (record: any) => PartColumn(record)
|
||||||
return (
|
|
||||||
<Thumbnail
|
|
||||||
src={record.thumbnail || record.image}
|
|
||||||
alt={record.name}
|
|
||||||
text={record.full_name}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessor: 'IPN',
|
accessor: 'IPN',
|
||||||
|
Loading…
Reference in New Issue
Block a user