mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
[PUI] Adds NewPart form (#6598)
This commit is contained in:
parent
38d013ffe2
commit
a2a7b60d41
@ -1,99 +1,94 @@
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { IconPackages } from '@tabler/icons-react';
|
import { IconPackages } from '@tabler/icons-react';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
import { ApiFormFieldSet } from '../components/forms/fields/ApiFormField';
|
import { ApiFormFieldSet } from '../components/forms/fields/ApiFormField';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a set of fields for creating / editing a Part instance
|
* Construct a set of fields for creating / editing a Part instance
|
||||||
*/
|
*/
|
||||||
export function partFields({
|
export function usePartFields({
|
||||||
editing = false,
|
create = false
|
||||||
category_id
|
|
||||||
}: {
|
}: {
|
||||||
editing?: boolean;
|
create?: boolean;
|
||||||
category_id?: number;
|
|
||||||
}): ApiFormFieldSet {
|
}): ApiFormFieldSet {
|
||||||
let fields: ApiFormFieldSet = {
|
return useMemo(() => {
|
||||||
category: {
|
const fields: ApiFormFieldSet = {
|
||||||
filters: {
|
category: {
|
||||||
structural: false
|
filters: {
|
||||||
}
|
structural: false
|
||||||
},
|
}
|
||||||
name: {},
|
},
|
||||||
IPN: {},
|
name: {},
|
||||||
revision: {},
|
IPN: {},
|
||||||
description: {},
|
revision: {},
|
||||||
variant_of: {},
|
description: {},
|
||||||
keywords: {},
|
variant_of: {},
|
||||||
units: {},
|
keywords: {},
|
||||||
link: {},
|
units: {},
|
||||||
default_location: {
|
link: {},
|
||||||
filters: {
|
default_location: {
|
||||||
structural: false
|
filters: {
|
||||||
}
|
structural: false
|
||||||
},
|
}
|
||||||
default_expiry: {},
|
},
|
||||||
minimum_stock: {},
|
default_expiry: {},
|
||||||
responsible: {
|
minimum_stock: {},
|
||||||
filters: {
|
responsible: {
|
||||||
is_active: true
|
filters: {
|
||||||
}
|
is_active: true
|
||||||
},
|
}
|
||||||
component: {},
|
},
|
||||||
assembly: {},
|
component: {},
|
||||||
is_template: {},
|
assembly: {},
|
||||||
trackable: {},
|
is_template: {},
|
||||||
purchaseable: {},
|
trackable: {},
|
||||||
salable: {},
|
purchaseable: {},
|
||||||
virtual: {},
|
salable: {},
|
||||||
active: {}
|
virtual: {},
|
||||||
};
|
active: {}
|
||||||
|
|
||||||
if (category_id != null) {
|
|
||||||
// TODO: Set the value of the category field
|
|
||||||
}
|
|
||||||
|
|
||||||
// Additional fields for creation
|
|
||||||
if (!editing) {
|
|
||||||
// TODO: Hide 'active' field
|
|
||||||
|
|
||||||
fields.copy_category_parameters = {};
|
|
||||||
|
|
||||||
fields.initial_stock = {
|
|
||||||
icon: <IconPackages />,
|
|
||||||
children: {
|
|
||||||
quantity: {},
|
|
||||||
location: {}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fields.initial_supplier = {
|
// Additional fields for creation
|
||||||
children: {
|
if (create) {
|
||||||
supplier: {
|
fields.copy_category_parameters = {};
|
||||||
filters: {
|
|
||||||
is_supplier: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
sku: {},
|
|
||||||
manufacturer: {
|
|
||||||
filters: {
|
|
||||||
is_manufacturer: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mpn: {}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: pop 'expiry' field if expiry not enabled
|
fields.initial_stock = {
|
||||||
delete fields['default_expiry'];
|
icon: <IconPackages />,
|
||||||
|
children: {
|
||||||
|
quantity: {},
|
||||||
|
location: {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: pop 'revision' field if PART_ENABLE_REVISION is False
|
fields.initial_supplier = {
|
||||||
delete fields['revision'];
|
children: {
|
||||||
|
supplier: {
|
||||||
|
filters: {
|
||||||
|
is_supplier: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sku: {},
|
||||||
|
manufacturer: {
|
||||||
|
filters: {
|
||||||
|
is_manufacturer: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mpn: {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: handle part duplications
|
// TODO: pop 'expiry' field if expiry not enabled
|
||||||
|
delete fields['default_expiry'];
|
||||||
|
|
||||||
return fields;
|
// TODO: pop 'revision' field if PART_ENABLE_REVISION is False
|
||||||
|
delete fields['revision'];
|
||||||
|
|
||||||
|
// TODO: handle part duplications
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}, [create]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -10,7 +10,7 @@ import { StylishText } from '../../components/items/StylishText';
|
|||||||
import { StatusRenderer } from '../../components/render/StatusRenderer';
|
import { StatusRenderer } from '../../components/render/StatusRenderer';
|
||||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||||
import { ModelType } from '../../enums/ModelType';
|
import { ModelType } from '../../enums/ModelType';
|
||||||
import { partCategoryFields, partFields } from '../../forms/PartForms';
|
import { partCategoryFields, usePartFields } from '../../forms/PartForms';
|
||||||
import { useCreateStockItem } from '../../forms/StockForms';
|
import { useCreateStockItem } from '../../forms/StockForms';
|
||||||
import {
|
import {
|
||||||
useCreateApiFormModal,
|
useCreateApiFormModal,
|
||||||
@ -28,10 +28,13 @@ function ApiFormsPlayground() {
|
|||||||
fields: fields
|
fields: fields
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const createPartFields = usePartFields({ create: true });
|
||||||
|
const editPartFields = usePartFields({ create: false });
|
||||||
|
|
||||||
const newPart = useCreateApiFormModal({
|
const newPart = useCreateApiFormModal({
|
||||||
url: ApiEndpoints.part_list,
|
url: ApiEndpoints.part_list,
|
||||||
title: 'Create Part',
|
title: 'Create Part',
|
||||||
fields: partFields({}),
|
fields: createPartFields,
|
||||||
initialData: {
|
initialData: {
|
||||||
description: 'A part created via the API'
|
description: 'A part created via the API'
|
||||||
}
|
}
|
||||||
@ -41,7 +44,7 @@ function ApiFormsPlayground() {
|
|||||||
url: ApiEndpoints.part_list,
|
url: ApiEndpoints.part_list,
|
||||||
pk: 1,
|
pk: 1,
|
||||||
title: 'Edit Part',
|
title: 'Edit Part',
|
||||||
fields: partFields({ editing: true })
|
fields: editPartFields
|
||||||
});
|
});
|
||||||
|
|
||||||
const newAttachment = useCreateApiFormModal({
|
const newAttachment = useCreateApiFormModal({
|
||||||
@ -62,7 +65,7 @@ function ApiFormsPlayground() {
|
|||||||
const [name, setName] = useState('Hello');
|
const [name, setName] = useState('Hello');
|
||||||
|
|
||||||
const partFieldsState: any = useMemo<any>(() => {
|
const partFieldsState: any = useMemo<any>(() => {
|
||||||
const fields = partFields({});
|
const fields = editPartFields;
|
||||||
fields.name = {
|
fields.name = {
|
||||||
...fields.name,
|
...fields.name,
|
||||||
value: name,
|
value: name,
|
||||||
|
@ -46,7 +46,7 @@ import { formatPriceRange } from '../../defaults/formatters';
|
|||||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||||
import { ModelType } from '../../enums/ModelType';
|
import { ModelType } from '../../enums/ModelType';
|
||||||
import { UserRoles } from '../../enums/Roles';
|
import { UserRoles } from '../../enums/Roles';
|
||||||
import { partFields } from '../../forms/PartForms';
|
import { usePartFields } from '../../forms/PartForms';
|
||||||
import { useEditApiFormModal } from '../../hooks/UseForm';
|
import { useEditApiFormModal } from '../../hooks/UseForm';
|
||||||
import { useInstance } from '../../hooks/UseInstance';
|
import { useInstance } from '../../hooks/UseInstance';
|
||||||
import { apiUrl } from '../../states/ApiState';
|
import { apiUrl } from '../../states/ApiState';
|
||||||
@ -630,11 +630,13 @@ export default function PartDetail() {
|
|||||||
);
|
);
|
||||||
}, [part, id]);
|
}, [part, id]);
|
||||||
|
|
||||||
|
const partFields = usePartFields({ create: false });
|
||||||
|
|
||||||
const editPart = useEditApiFormModal({
|
const editPart = useEditApiFormModal({
|
||||||
url: ApiEndpoints.part_list,
|
url: ApiEndpoints.part_list,
|
||||||
pk: part.pk,
|
pk: part.pk,
|
||||||
title: t`Edit Part`,
|
title: t`Edit Part`,
|
||||||
fields: partFields({ editing: true }),
|
fields: partFields,
|
||||||
onFormSuccess: refreshInstance
|
onFormSuccess: refreshInstance
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3,14 +3,19 @@ import { Group, Text } from '@mantine/core';
|
|||||||
import { ReactNode, useMemo } from 'react';
|
import { ReactNode, useMemo } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { AddItemButton } from '../../components/buttons/AddItemButton';
|
||||||
import { Thumbnail } from '../../components/images/Thumbnail';
|
import { Thumbnail } from '../../components/images/Thumbnail';
|
||||||
import { formatPriceRange } from '../../defaults/formatters';
|
import { formatPriceRange } from '../../defaults/formatters';
|
||||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||||
import { ModelType } from '../../enums/ModelType';
|
import { ModelType } from '../../enums/ModelType';
|
||||||
|
import { UserRoles } from '../../enums/Roles';
|
||||||
|
import { usePartFields } from '../../forms/PartForms';
|
||||||
import { shortenString } from '../../functions/tables';
|
import { shortenString } from '../../functions/tables';
|
||||||
import { getDetailUrl } from '../../functions/urls';
|
import { getDetailUrl } from '../../functions/urls';
|
||||||
|
import { useCreateApiFormModal } from '../../hooks/UseForm';
|
||||||
import { useTable } from '../../hooks/UseTable';
|
import { useTable } from '../../hooks/UseTable';
|
||||||
import { apiUrl } from '../../states/ApiState';
|
import { apiUrl } from '../../states/ApiState';
|
||||||
|
import { useUserState } from '../../states/UserState';
|
||||||
import { TableColumn } from '../Column';
|
import { TableColumn } from '../Column';
|
||||||
import { DescriptionColumn, LinkColumn } from '../ColumnRenderers';
|
import { DescriptionColumn, LinkColumn } from '../ColumnRenderers';
|
||||||
import { TableFilter } from '../Filter';
|
import { TableFilter } from '../Filter';
|
||||||
@ -261,25 +266,53 @@ export function PartListTable({ props }: { props: InvenTreeTableProps }) {
|
|||||||
const tableFilters = useMemo(() => partTableFilters(), []);
|
const tableFilters = useMemo(() => partTableFilters(), []);
|
||||||
|
|
||||||
const table = useTable('part-list');
|
const table = useTable('part-list');
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const user = useUserState();
|
||||||
|
|
||||||
|
const newPart = useCreateApiFormModal({
|
||||||
|
url: ApiEndpoints.part_list,
|
||||||
|
title: t`Add Part`,
|
||||||
|
fields: usePartFields({ create: true }),
|
||||||
|
initialData: {
|
||||||
|
...(props.params ?? {})
|
||||||
|
},
|
||||||
|
onFormSuccess: (data: any) => {
|
||||||
|
if (data.pk) {
|
||||||
|
navigate(getDetailUrl(ModelType.part, data.pk));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const tableActions = useMemo(() => {
|
||||||
|
return [
|
||||||
|
<AddItemButton
|
||||||
|
hidden={!user.hasAddRole(UserRoles.part)}
|
||||||
|
tooltip={t`Add Part`}
|
||||||
|
onClick={() => newPart.open()}
|
||||||
|
/>
|
||||||
|
];
|
||||||
|
}, [user]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InvenTreeTable
|
<>
|
||||||
url={apiUrl(ApiEndpoints.part_list)}
|
{newPart.modal}
|
||||||
tableState={table}
|
<InvenTreeTable
|
||||||
columns={tableColumns}
|
url={apiUrl(ApiEndpoints.part_list)}
|
||||||
props={{
|
tableState={table}
|
||||||
...props,
|
columns={tableColumns}
|
||||||
enableDownload: true,
|
props={{
|
||||||
tableFilters: tableFilters,
|
...props,
|
||||||
params: {
|
enableDownload: true,
|
||||||
...props.params,
|
tableFilters: tableFilters,
|
||||||
category_detail: true
|
tableActions: tableActions,
|
||||||
},
|
params: {
|
||||||
onRowClick: (record) =>
|
...props.params,
|
||||||
navigate(getDetailUrl(ModelType.part, record.pk))
|
category_detail: true
|
||||||
}}
|
},
|
||||||
/>
|
onRowClick: (record) =>
|
||||||
|
navigate(getDetailUrl(ModelType.part, record.pk))
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user