diff --git a/src/frontend/src/components/details/Details.tsx b/src/frontend/src/components/details/Details.tsx index c4867c9aa3..d82615212d 100644 --- a/src/frontend/src/components/details/Details.tsx +++ b/src/frontend/src/components/details/Details.tsx @@ -53,7 +53,7 @@ export type DetailsField = | StringDetailField | BooleanField | LinkDetailField - | ProgressBarfield + | ProgressBarField | StatusField ); @@ -85,7 +85,7 @@ type ExternalLinkField = { external: true; }; -type ProgressBarfield = { +type ProgressBarField = { type: 'progressbar'; progress: number; total: number; @@ -96,8 +96,6 @@ type StatusField = { model: ModelType; }; -type FieldValueType = string | number | undefined; - type FieldProps = { field_data: any; field_value: string | number; diff --git a/src/frontend/src/functions/icons.tsx b/src/frontend/src/functions/icons.tsx index 652f452086..6d8b0bed1d 100644 --- a/src/frontend/src/functions/icons.tsx +++ b/src/frontend/src/functions/icons.tsx @@ -104,6 +104,8 @@ const icons = { variants: IconVersions, allocations: IconBookmarks, bom: IconListTree, + build: IconTools, + build_order: IconTools, builds: IconTools, used_in: IconStack2, manufacturers: IconBuildingFactory2, @@ -170,6 +172,7 @@ const icons = { quantity: IconNumbers, progress: IconProgressCheck, reference: IconHash, + serial: IconHash, website: IconWorld, email: IconMail, phone: IconPhone, diff --git a/src/frontend/src/pages/company/ManufacturerPartDetail.tsx b/src/frontend/src/pages/company/ManufacturerPartDetail.tsx index 8fad09054f..35f8a7cbdb 100644 --- a/src/frontend/src/pages/company/ManufacturerPartDetail.tsx +++ b/src/frontend/src/pages/company/ManufacturerPartDetail.tsx @@ -25,6 +25,7 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ModelType } from '../../enums/ModelType'; import { UserRoles } from '../../enums/Roles'; import { useManufacturerPartFields } from '../../forms/CompanyForms'; +import { getDetailUrl } from '../../functions/urls'; import { useEditApiFormModal } from '../../hooks/UseForm'; import { useInstance } from '../../hooks/UseInstance'; import { apiUrl } from '../../states/ApiState'; diff --git a/src/frontend/src/pages/part/CategoryDetail.tsx b/src/frontend/src/pages/part/CategoryDetail.tsx index 22d27c5bbf..bf4db14067 100644 --- a/src/frontend/src/pages/part/CategoryDetail.tsx +++ b/src/frontend/src/pages/part/CategoryDetail.tsx @@ -23,6 +23,7 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ModelType } from '../../enums/ModelType'; import { UserRoles } from '../../enums/Roles'; import { partCategoryFields } from '../../forms/PartForms'; +import { getDetailUrl } from '../../functions/urls'; import { useEditApiFormModal } from '../../hooks/UseForm'; import { useInstance } from '../../hooks/UseInstance'; import { useUserState } from '../../states/UserState'; @@ -212,7 +213,7 @@ export default function CategoryDetail({}: {}) { { name: t`Parts`, url: '/part' }, ...(category.path ?? []).map((c: any) => ({ name: c.name, - url: `/part/category/${c.pk}` + url: getDetailUrl(ModelType.partcategory, c.pk) })) ], [category] diff --git a/src/frontend/src/pages/part/PartDetail.tsx b/src/frontend/src/pages/part/PartDetail.tsx index a00f1eaa12..836ac46e26 100644 --- a/src/frontend/src/pages/part/PartDetail.tsx +++ b/src/frontend/src/pages/part/PartDetail.tsx @@ -63,6 +63,7 @@ import { useTransferStockItem } from '../../forms/StockForms'; import { InvenTreeIcon } from '../../functions/icons'; +import { getDetailUrl } from '../../functions/urls'; import { useEditApiFormModal } from '../../hooks/UseForm'; import { useInstance } from '../../hooks/UseInstance'; import { apiUrl } from '../../states/ApiState'; @@ -624,7 +625,7 @@ export default function PartDetail() { { name: t`Parts`, url: '/part' }, ...(part.category_path ?? []).map((c: any) => ({ name: c.name, - url: `/part/category/${c.pk}` + url: getDetailUrl(ModelType.partcategory, c.pk) })) ], [part] diff --git a/src/frontend/src/pages/stock/LocationDetail.tsx b/src/frontend/src/pages/stock/LocationDetail.tsx index db58ec1a6b..7f99949c30 100644 --- a/src/frontend/src/pages/stock/LocationDetail.tsx +++ b/src/frontend/src/pages/stock/LocationDetail.tsx @@ -34,6 +34,7 @@ import { useTransferStockItem } from '../../forms/StockForms'; import { InvenTreeIcon } from '../../functions/icons'; +import { getDetailUrl } from '../../functions/urls'; import { useEditApiFormModal } from '../../hooks/UseForm'; import { useInstance } from '../../hooks/UseInstance'; import { useUserState } from '../../states/UserState'; @@ -288,7 +289,7 @@ export default function Stock() { { name: t`Stock`, url: '/stock' }, ...(location.path ?? []).map((l: any) => ({ name: l.name, - url: `/stock/location/${l.pk}` + url: getDetailUrl(ModelType.stocklocation, l.pk) })) ], [location] diff --git a/src/frontend/src/pages/stock/StockDetail.tsx b/src/frontend/src/pages/stock/StockDetail.tsx index 3380131f3d..3806d5c17b 100644 --- a/src/frontend/src/pages/stock/StockDetail.tsx +++ b/src/frontend/src/pages/stock/StockDetail.tsx @@ -51,6 +51,7 @@ import { useTransferStockItem } from '../../forms/StockForms'; import { InvenTreeIcon } from '../../functions/icons'; +import { getDetailUrl } from '../../functions/urls'; import { useInstance } from '../../hooks/UseInstance'; import { apiUrl } from '../../states/ApiState'; import { useUserState } from '../../states/UserState'; @@ -82,6 +83,7 @@ export default function StockDetail() { const detailsPanel = useMemo(() => { let data = stockitem; + let part = stockitem?.part_detail ?? {}; data.available_stock = Math.max(0, data.quantity - data.allocated); @@ -99,14 +101,16 @@ export default function StockDetail() { }, { name: 'status', - type: 'text', - label: t`Stock Status` + type: 'status', + label: t`Stock Status`, + model: ModelType.stockitem }, { type: 'text', name: 'tests', label: `Completed Tests`, - icon: 'progress' + icon: 'progress', + hidden: !part?.trackable }, { type: 'text', @@ -174,6 +178,7 @@ export default function StockDetail() { return text; }, + icon: 'stock', model: ModelType.stockitem, hidden: !stockitem.belongs_to }, @@ -182,7 +187,17 @@ export default function StockDetail() { name: 'consumed_by', label: t`Consumed By`, model: ModelType.build, - hidden: !stockitem.consumed_by + hidden: !stockitem.consumed_by, + icon: 'build', + model_field: 'reference' + }, + { + type: 'link', + name: 'build', + label: t`Build Order`, + model: ModelType.build, + hidden: !stockitem.build, + model_field: 'reference' }, { type: 'link', @@ -192,6 +207,13 @@ export default function StockDetail() { hidden: !stockitem.sales_order, icon: 'sales_orders', model_field: 'reference' + }, + { + type: 'link', + name: 'customer', + label: t`Customer`, + model: ModelType.company, + hidden: !stockitem.customer } ]; @@ -317,7 +339,7 @@ export default function StockDetail() { { name: t`Stock`, url: '/stock' }, ...(stockitem.location_path ?? []).map((l: any) => ({ name: l.name, - url: apiUrl(ApiEndpoints.stock_location_list, l.pk) + url: getDetailUrl(ModelType.stocklocation, l.pk) })) ], [stockitem] diff --git a/src/frontend/src/tables/FilterSelectDrawer.tsx b/src/frontend/src/tables/FilterSelectDrawer.tsx index 96d7c2d627..6a558e83fd 100644 --- a/src/frontend/src/tables/FilterSelectDrawer.tsx +++ b/src/frontend/src/tables/FilterSelectDrawer.tsx @@ -180,6 +180,12 @@ export function FilterSelectDrawer({ setAddFilter(false); }, [tableState.activeFilters]); + const hasFilters: boolean = useMemo(() => { + let filters = tableState?.activeFilters ?? []; + + return filters.length > 0; + }, [tableState.activeFilters]); + return ( {t`Table Filters`}} > - {tableState.activeFilters && + {hasFilters && tableState.activeFilters?.map((f) => ( ))} - {tableState.activeFilters && tableState.activeFilters.length > 0 && ( - - )} + {hasFilters && } {addFilter && (