diff --git a/src/frontend/src/forms/PartForms.tsx b/src/frontend/src/forms/PartForms.tsx
index 7a0a724b0b..d5059f9826 100644
--- a/src/frontend/src/forms/PartForms.tsx
+++ b/src/frontend/src/forms/PartForms.tsx
@@ -1,5 +1,5 @@
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 { 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
*/
export function usePartFields({
- create = false
+ create = false,
+ duplicatePartInstance
}: {
+ duplicatePartInstance?: any;
create?: boolean;
}): ApiFormFieldSet {
const settings = useGlobalSettingsState();
@@ -89,6 +91,7 @@ export function usePartFields({
};
fields.initial_supplier = {
+ icon: ,
children: {
supplier: {
filters: {
@@ -106,6 +109,36 @@ export function usePartFields({
};
}
+ // Additional fields for part duplication
+ if (create && duplicatePartInstance?.pk) {
+ fields.duplicate = {
+ icon: ,
+ 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')) {
fields.revision_of.filters['assembly'] = true;
}
@@ -126,7 +159,7 @@ export function usePartFields({
}
return fields;
- }, [create, settings]);
+ }, [create, duplicatePartInstance, settings]);
}
/**
diff --git a/src/frontend/src/pages/part/PartDetail.tsx b/src/frontend/src/pages/part/PartDetail.tsx
index a35d50482e..aaa42fecef 100644
--- a/src/frontend/src/pages/part/PartDetail.tsx
+++ b/src/frontend/src/pages/part/PartDetail.tsx
@@ -47,7 +47,7 @@ import { UserRoles } from '@lib/enums/Roles';
import { apiUrl } from '@lib/functions/Api';
import { getDetailUrl } from '@lib/functions/Navigation';
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 { PrintingActions } from '../../components/buttons/PrintingActions';
import StarredToggleButton from '../../components/buttons/StarredToggleButton';
@@ -1048,38 +1048,10 @@ export default function PartDetail() {
onFormSuccess: refreshInstance
});
- const createPartFields = usePartFields({ create: true });
-
- const duplicatePartFields: ApiFormFieldSet = useMemo(() => {
- 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 duplicatePartFields = usePartFields({
+ create: true,
+ duplicatePartInstance: part
+ });
const duplicatePart = useCreateApiFormModal({
url: ApiEndpoints.part_list,
diff --git a/src/frontend/src/tables/part/PartTable.tsx b/src/frontend/src/tables/part/PartTable.tsx
index ce5b19359b..7093149492 100644
--- a/src/frontend/src/tables/part/PartTable.tsx
+++ b/src/frontend/src/tables/part/PartTable.tsx
@@ -336,11 +336,13 @@ function partTableFilters(): TableFilter[] {
*/
export function PartListTable({
enableImport = true,
+ basePartInstance,
props,
defaultPartData
}: Readonly<{
enableImport?: boolean;
props?: InvenTreeTableProps;
+ basePartInstance?: any;
defaultPartData?: any;
}>) {
const tableColumns = useMemo(() => partTableColumns(), []);
@@ -384,10 +386,15 @@ export function PartListTable({
return defaultPartData ?? props?.params ?? {};
}, [defaultPartData, props?.params]);
+ const newPartFields = usePartFields({
+ create: true,
+ duplicatePartInstance: basePartInstance
+ });
+
const newPart = useCreateApiFormModal({
url: ApiEndpoints.part_list,
title: t`Add Part`,
- fields: usePartFields({ create: true }),
+ fields: newPartFields,
initialData: initialPartData,
follow: true,
modelType: ModelType.part
diff --git a/src/frontend/src/tables/part/PartVariantTable.tsx b/src/frontend/src/tables/part/PartVariantTable.tsx
index 53fa6ef247..845e654b3b 100644
--- a/src/frontend/src/tables/part/PartVariantTable.tsx
+++ b/src/frontend/src/tables/part/PartVariantTable.tsx
@@ -43,6 +43,7 @@ export function PartVariantTable({ part }: Readonly<{ part: any }>) {
ancestor: part.pk
}
}}
+ basePartInstance={part}
defaultPartData={{
...part,
variant_of: part.pk,