mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-30 20:55:42 +00:00 
			
		
		
		
	[UI] Duplicate part fixes (#10709)
* Refactor part duplication - Move duplication items into the form definition * Expand to part variants table
This commit is contained in:
		| @@ -1,5 +1,5 @@ | |||||||
| import { t } from '@lingui/core/macro'; | import { t } from '@lingui/core/macro'; | ||||||
| import { IconPackages } from '@tabler/icons-react'; | import { IconBuildingStore, IconCopy, IconPackages } from '@tabler/icons-react'; | ||||||
| import { useMemo, useState } from 'react'; | import { useMemo, useState } from 'react'; | ||||||
|  |  | ||||||
| import { ApiEndpoints } from '@lib/enums/ApiEndpoints'; | import { ApiEndpoints } from '@lib/enums/ApiEndpoints'; | ||||||
| @@ -12,8 +12,10 @@ import { useGlobalSettingsState } from '../states/SettingsStates'; | |||||||
|  * Construct a set of fields for creating / editing a Part instance |  * Construct a set of fields for creating / editing a Part instance | ||||||
|  */ |  */ | ||||||
| export function usePartFields({ | export function usePartFields({ | ||||||
|   create = false |   create = false, | ||||||
|  |   duplicatePartInstance | ||||||
| }: { | }: { | ||||||
|  |   duplicatePartInstance?: any; | ||||||
|   create?: boolean; |   create?: boolean; | ||||||
| }): ApiFormFieldSet { | }): ApiFormFieldSet { | ||||||
|   const settings = useGlobalSettingsState(); |   const settings = useGlobalSettingsState(); | ||||||
| @@ -89,6 +91,7 @@ export function usePartFields({ | |||||||
|       }; |       }; | ||||||
|  |  | ||||||
|       fields.initial_supplier = { |       fields.initial_supplier = { | ||||||
|  |         icon: <IconBuildingStore />, | ||||||
|         children: { |         children: { | ||||||
|           supplier: { |           supplier: { | ||||||
|             filters: { |             filters: { | ||||||
| @@ -106,6 +109,36 @@ export function usePartFields({ | |||||||
|       }; |       }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // Additional fields for part duplication | ||||||
|  |     if (create && duplicatePartInstance?.pk) { | ||||||
|  |       fields.duplicate = { | ||||||
|  |         icon: <IconCopy />, | ||||||
|  |         children: { | ||||||
|  |           part: { | ||||||
|  |             value: duplicatePartInstance?.pk, | ||||||
|  |             hidden: true | ||||||
|  |           }, | ||||||
|  |           copy_image: { | ||||||
|  |             value: true | ||||||
|  |           }, | ||||||
|  |           copy_bom: { | ||||||
|  |             value: settings.isSet('PART_COPY_BOM'), | ||||||
|  |             hidden: !duplicatePartInstance?.assembly | ||||||
|  |           }, | ||||||
|  |           copy_notes: { | ||||||
|  |             value: true | ||||||
|  |           }, | ||||||
|  |           copy_parameters: { | ||||||
|  |             value: settings.isSet('PART_COPY_PARAMETERS') | ||||||
|  |           }, | ||||||
|  |           copy_tests: { | ||||||
|  |             value: true, | ||||||
|  |             hidden: !duplicatePartInstance?.testable | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       }; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     if (settings.isSet('PART_REVISION_ASSEMBLY_ONLY')) { |     if (settings.isSet('PART_REVISION_ASSEMBLY_ONLY')) { | ||||||
|       fields.revision_of.filters['assembly'] = true; |       fields.revision_of.filters['assembly'] = true; | ||||||
|     } |     } | ||||||
| @@ -126,7 +159,7 @@ export function usePartFields({ | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     return fields; |     return fields; | ||||||
|   }, [create, settings]); |   }, [create, duplicatePartInstance, settings]); | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|   | |||||||
| @@ -47,7 +47,7 @@ import { UserRoles } from '@lib/enums/Roles'; | |||||||
| import { apiUrl } from '@lib/functions/Api'; | import { apiUrl } from '@lib/functions/Api'; | ||||||
| import { getDetailUrl } from '@lib/functions/Navigation'; | import { getDetailUrl } from '@lib/functions/Navigation'; | ||||||
| import { ActionButton } from '@lib/index'; | import { ActionButton } from '@lib/index'; | ||||||
| import type { ApiFormFieldSet, StockOperationProps } from '@lib/types/Forms'; | import type { StockOperationProps } from '@lib/types/Forms'; | ||||||
| import AdminButton from '../../components/buttons/AdminButton'; | import AdminButton from '../../components/buttons/AdminButton'; | ||||||
| import { PrintingActions } from '../../components/buttons/PrintingActions'; | import { PrintingActions } from '../../components/buttons/PrintingActions'; | ||||||
| import StarredToggleButton from '../../components/buttons/StarredToggleButton'; | import StarredToggleButton from '../../components/buttons/StarredToggleButton'; | ||||||
| @@ -1048,38 +1048,10 @@ export default function PartDetail() { | |||||||
|     onFormSuccess: refreshInstance |     onFormSuccess: refreshInstance | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   const createPartFields = usePartFields({ create: true }); |   const duplicatePartFields = usePartFields({ | ||||||
|  |     create: true, | ||||||
|   const duplicatePartFields: ApiFormFieldSet = useMemo(() => { |     duplicatePartInstance: part | ||||||
|     return { |   }); | ||||||
|       ...createPartFields, |  | ||||||
|       duplicate: { |  | ||||||
|         children: { |  | ||||||
|           part: { |  | ||||||
|             value: part.pk, |  | ||||||
|             hidden: true |  | ||||||
|           }, |  | ||||||
|           copy_image: { |  | ||||||
|             value: true |  | ||||||
|           }, |  | ||||||
|           copy_bom: { |  | ||||||
|             value: part.assembly && globalSettings.isSet('PART_COPY_BOM'), |  | ||||||
|             hidden: !part.assembly |  | ||||||
|           }, |  | ||||||
|           copy_notes: { |  | ||||||
|             value: true |  | ||||||
|           }, |  | ||||||
|           copy_parameters: { |  | ||||||
|             value: globalSettings.isSet('PART_COPY_PARAMETERS') |  | ||||||
|           }, |  | ||||||
|           copy_tests: { |  | ||||||
|             value: part.testable, |  | ||||||
|             hidden: !part.testable |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     }; |  | ||||||
|   }, [createPartFields, globalSettings, part]); |  | ||||||
|  |  | ||||||
|   const duplicatePart = useCreateApiFormModal({ |   const duplicatePart = useCreateApiFormModal({ | ||||||
|     url: ApiEndpoints.part_list, |     url: ApiEndpoints.part_list, | ||||||
|   | |||||||
| @@ -336,11 +336,13 @@ function partTableFilters(): TableFilter[] { | |||||||
|  */ |  */ | ||||||
| export function PartListTable({ | export function PartListTable({ | ||||||
|   enableImport = true, |   enableImport = true, | ||||||
|  |   basePartInstance, | ||||||
|   props, |   props, | ||||||
|   defaultPartData |   defaultPartData | ||||||
| }: Readonly<{ | }: Readonly<{ | ||||||
|   enableImport?: boolean; |   enableImport?: boolean; | ||||||
|   props?: InvenTreeTableProps; |   props?: InvenTreeTableProps; | ||||||
|  |   basePartInstance?: any; | ||||||
|   defaultPartData?: any; |   defaultPartData?: any; | ||||||
| }>) { | }>) { | ||||||
|   const tableColumns = useMemo(() => partTableColumns(), []); |   const tableColumns = useMemo(() => partTableColumns(), []); | ||||||
| @@ -384,10 +386,15 @@ export function PartListTable({ | |||||||
|     return defaultPartData ?? props?.params ?? {}; |     return defaultPartData ?? props?.params ?? {}; | ||||||
|   }, [defaultPartData, props?.params]); |   }, [defaultPartData, props?.params]); | ||||||
|  |  | ||||||
|  |   const newPartFields = usePartFields({ | ||||||
|  |     create: true, | ||||||
|  |     duplicatePartInstance: basePartInstance | ||||||
|  |   }); | ||||||
|  |  | ||||||
|   const newPart = useCreateApiFormModal({ |   const newPart = useCreateApiFormModal({ | ||||||
|     url: ApiEndpoints.part_list, |     url: ApiEndpoints.part_list, | ||||||
|     title: t`Add Part`, |     title: t`Add Part`, | ||||||
|     fields: usePartFields({ create: true }), |     fields: newPartFields, | ||||||
|     initialData: initialPartData, |     initialData: initialPartData, | ||||||
|     follow: true, |     follow: true, | ||||||
|     modelType: ModelType.part |     modelType: ModelType.part | ||||||
|   | |||||||
| @@ -43,6 +43,7 @@ export function PartVariantTable({ part }: Readonly<{ part: any }>) { | |||||||
|           ancestor: part.pk |           ancestor: part.pk | ||||||
|         } |         } | ||||||
|       }} |       }} | ||||||
|  |       basePartInstance={part} | ||||||
|       defaultPartData={{ |       defaultPartData={{ | ||||||
|         ...part, |         ...part, | ||||||
|         variant_of: part.pk, |         variant_of: part.pk, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user