diff --git a/src/frontend/src/pages/part/CategoryDetail.tsx b/src/frontend/src/pages/part/CategoryDetail.tsx
index 32664a5ff9..938fe0356e 100644
--- a/src/frontend/src/pages/part/CategoryDetail.tsx
+++ b/src/frontend/src/pages/part/CategoryDetail.tsx
@@ -8,13 +8,14 @@ import {
import { useMemo, useState } from 'react';
import { useParams } from 'react-router-dom';
-import { PlaceholderPanel } from '../../components/items/Placeholder';
import { PageDetail } from '../../components/nav/PageDetail';
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
import { PartCategoryTree } from '../../components/nav/PartCategoryTree';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { useInstance } from '../../hooks/UseInstance';
+import ParametricPartTable from '../../tables/part/ParametricPartTable';
import { PartCategoryTable } from '../../tables/part/PartCategoryTable';
+import { PartParameterTable } from '../../tables/part/PartParameterTable';
import { PartListTable } from '../../tables/part/PartTable';
/**
@@ -70,7 +71,7 @@ export default function CategoryDetail({}: {}) {
name: 'parameters',
label: t`Parameters`,
icon: ,
- content:
+ content:
}
],
[category, id]
diff --git a/src/frontend/src/pages/stock/StockDetail.tsx b/src/frontend/src/pages/stock/StockDetail.tsx
index 468aad4ea0..4901bf20ed 100644
--- a/src/frontend/src/pages/stock/StockDetail.tsx
+++ b/src/frontend/src/pages/stock/StockDetail.tsx
@@ -29,7 +29,6 @@ import {
UnlinkBarcodeAction,
ViewBarcodeAction
} from '../../components/items/ActionDropdown';
-import { PlaceholderPanel } from '../../components/items/Placeholder';
import { PageDetail } from '../../components/nav/PageDetail';
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
import { StockLocationTree } from '../../components/nav/StockLocationTree';
@@ -69,20 +68,17 @@ export default function StockDetail() {
{
name: 'details',
label: t`Details`,
- icon: ,
- content:
+ icon:
},
{
name: 'tracking',
label: t`Stock Tracking`,
- icon: ,
- content:
+ icon:
},
{
name: 'allocations',
label: t`Allocations`,
icon: ,
- content: ,
hidden:
!stockitem?.part_detail?.salable && !stockitem?.part_detail?.component
},
diff --git a/src/frontend/src/tables/part/ParametricPartTable.tsx b/src/frontend/src/tables/part/ParametricPartTable.tsx
new file mode 100644
index 0000000000..c655f351b2
--- /dev/null
+++ b/src/frontend/src/tables/part/ParametricPartTable.tsx
@@ -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 (
+
+ );
+ }
+ };
+ });
+ }, [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 (
+ {
+ if (record.pk) {
+ navigate(getDetailUrl(ModelType.part, record.pk));
+ }
+ }
+ }}
+ />
+ );
+}
diff --git a/src/frontend/src/tables/part/PartParameterTable.tsx b/src/frontend/src/tables/part/PartParameterTable.tsx
index d9f6ce4f4e..a598cf885a 100644
--- a/src/frontend/src/tables/part/PartParameterTable.tsx
+++ b/src/frontend/src/tables/part/PartParameterTable.tsx
@@ -19,6 +19,7 @@ import { TableColumn } from '../Column';
import { DescriptionColumn, PartColumn } from '../ColumnRenderers';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../RowActions';
+import { TableHoverCard } from '../TableHoverCard';
/**
* Construct a table listing parameters for a given part
@@ -65,13 +66,23 @@ export function PartParameterTable({ partId }: { partId: any }) {
return ;
}
- if (record.data_numeric) {
- // TODO: Numeric data
+ let extra: any[] = [];
+
+ if (
+ template.units &&
+ record.data_numeric &&
+ record.data_numeric != record.data
+ ) {
+ extra.push(`${record.data_numeric} [${template.units}]`);
}
- // TODO: Units
-
- return record.data;
+ return (
+
+ );
}
},
{
diff --git a/src/frontend/src/tables/part/PartTable.tsx b/src/frontend/src/tables/part/PartTable.tsx
index 7616e7c977..49dc743f66 100644
--- a/src/frontend/src/tables/part/PartTable.tsx
+++ b/src/frontend/src/tables/part/PartTable.tsx
@@ -17,7 +17,7 @@ import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
-import { DescriptionColumn, LinkColumn } from '../ColumnRenderers';
+import { DescriptionColumn, LinkColumn, PartColumn } from '../ColumnRenderers';
import { TableFilter } from '../Filter';
import { InvenTreeTable, InvenTreeTableProps } from '../InvenTreeTable';
import { TableHoverCard } from '../TableHoverCard';
@@ -31,15 +31,7 @@ function partTableColumns(): TableColumn[] {
accessor: 'name',
sortable: true,
noWrap: true,
- render: function (record: any) {
- return (
-
- );
- }
+ render: (record: any) => PartColumn(record)
},
{
accessor: 'IPN',