mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-31 05:05:42 +00:00 
			
		
		
		
	[PUI] Small tweaks (#6868)
* Add "customer" detail to StockDetail page * Hide completed tests field if not needed * Fix "build" and "consumed_by" fields * Fix icon * Fix breadcrumb URLs - Remove hard-coded strings - Fix broken links * Add serial icon * More breadcrumb updates * useMemo to simplify filters drawer
This commit is contained in:
		| @@ -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; | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -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'; | ||||
|   | ||||
| @@ -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] | ||||
|   | ||||
| @@ -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] | ||||
|   | ||||
| @@ -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] | ||||
|   | ||||
| @@ -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] | ||||
|   | ||||
| @@ -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 ( | ||||
|     <Drawer | ||||
|       size="sm" | ||||
| @@ -190,13 +196,11 @@ export function FilterSelectDrawer({ | ||||
|       title={<StylishText size="lg">{t`Table Filters`}</StylishText>} | ||||
|     > | ||||
|       <Stack spacing="xs"> | ||||
|         {tableState.activeFilters && | ||||
|         {hasFilters && | ||||
|           tableState.activeFilters?.map((f) => ( | ||||
|             <FilterItem key={f.name} flt={f} tableState={tableState} /> | ||||
|           ))} | ||||
|         {tableState.activeFilters && tableState.activeFilters.length > 0 && ( | ||||
|           <Divider /> | ||||
|         )} | ||||
|         {hasFilters && <Divider />} | ||||
|         {addFilter && ( | ||||
|           <Stack spacing="xs"> | ||||
|             <FilterAddGroup | ||||
|   | ||||
		Reference in New Issue
	
	Block a user