diff --git a/docs/docs/manufacturing/bom.md b/docs/docs/manufacturing/bom.md index 4114b5b9ea..bca4bddbab 100644 --- a/docs/docs/manufacturing/bom.md +++ b/docs/docs/manufacturing/bom.md @@ -92,9 +92,16 @@ Note that inherited BOM Line Items only flow "downwards" in the variant inherita !!! info "Editing Inherited Items" When editing an inherited BOM Line Item for a template part, the changes are automatically reflected in the BOM of any variant parts. -## BOM Creation +## BOM Editing -BOMs can be created manually, by adjusting individual line items, or by uploading (importing) an existing BOM file. +Bills of Material (BOMs) can be created manually, by adjusting individual line items, or by uploading (importing) an existing BOM file. + +### Editing Mode + +By default, the BOM is displayed in "view" mode. To edit the BOM, click on the {{ icon("edit", color="blue", title="Edit") }} icon at the top of the BOM panel. This will enable editing mode, which allows you to add, adjust or delete BOM line items. + +!!! warning "Permissions" + Only users with the appropriate permissions can edit BOMs. If you do not have permission to edit the BOM, the "Edit" icon will not be visible. ### Importing a BOM diff --git a/src/frontend/src/tables/bom/BomTable.tsx b/src/frontend/src/tables/bom/BomTable.tsx index 7581cf2068..4833218473 100644 --- a/src/frontend/src/tables/bom/BomTable.tsx +++ b/src/frontend/src/tables/bom/BomTable.tsx @@ -1,3 +1,19 @@ +import { t } from '@lingui/core/macro'; +import { Alert, Group, Stack, Text } from '@mantine/core'; +import { showNotification } from '@mantine/notifications'; +import { + IconArrowRight, + IconCircleCheck, + IconEdit, + IconFileUpload, + IconLock, + IconPlus, + IconSwitch3 +} from '@tabler/icons-react'; +import { type ReactNode, useCallback, useMemo, useState } from 'react'; +import { useNavigate } from 'react-router-dom'; + +import { ActionButton } from '@lib/components/ActionButton'; import { type RowAction, RowDeleteAction, @@ -12,20 +28,6 @@ import { navigateToLink } from '@lib/functions/Navigation'; import useTable from '@lib/hooks/UseTable'; import type { TableFilter } from '@lib/types/Filters'; import type { TableColumn } from '@lib/types/Tables'; -import { t } from '@lingui/core/macro'; -import { Alert, Group, Stack, Text } from '@mantine/core'; -import { showNotification } from '@mantine/notifications'; -import { - IconArrowRight, - IconCircleCheck, - IconFileUpload, - IconLock, - IconPlus, - IconSwitch3 -} from '@tabler/icons-react'; -import { type ReactNode, useCallback, useMemo, useState } from 'react'; -import { useNavigate } from 'react-router-dom'; -import { Thumbnail } from '../../components/images/Thumbnail'; import { ActionDropdown } from '../../components/items/ActionDropdown'; import { RenderPart } from '../../components/render/Part'; import { useApi } from '../../contexts/ApiContext'; @@ -45,7 +47,8 @@ import { DescriptionColumn, IPNColumn, NoteColumn, - ReferenceColumn + ReferenceColumn, + RenderPartColumn } from '../ColumnRenderers'; import { PartCategoryFilter } from '../Filter'; import { InvenTreeTable } from '../InvenTreeTable'; @@ -80,27 +83,35 @@ export function BomTable({ const user = useUserState(); const table = useTable('bom'); const navigate = useNavigate(); + const openImporter = useImporterState((state) => state.openImporter); + const [isEditing, setIsEditing] = useState(false); + const tableColumns: TableColumn[] = useMemo(() => { return [ { accessor: 'sub_part', switchable: false, sortable: true, + minWidth: 250, render: (record: any) => { const part = record.sub_part_detail; + const extra = []; - if (record.part != partId) { + if (partId && record.part != partId) { extra.push( - {t`This BOM item is defined for a different parent`} + {t`This BOM item is defined for a different parent`} ); } if (!record.validated) { extra.push( - + {t`This BOM item has not been validated`} ); @@ -109,13 +120,7 @@ export function BomTable({ return ( part && ( - } + value={} iconColor={record.validated ? undefined : 'red'} extra={extra} title={t`Part Information`} @@ -376,7 +381,8 @@ export function BomTable({ return '-'; } - const can_build = Math.trunc(record.can_build); + const can_build = Math.max(0, Math.trunc(record.can_build)); + const value = ( { return [ @@ -614,7 +620,7 @@ export function BomTable({ }) ]; }, - [partId, partLocked, user] + [isEditing, partId, partLocked, user] ); const tableActions = useMemo(() => { @@ -624,7 +630,7 @@ export function BomTable({ tooltip={t`Add BOM Items`} position='bottom-start' icon={} - hidden={partLocked || !user.hasAddRole(UserRoles.part)} + hidden={!isEditing || partLocked || !user.hasAddRole(UserRoles.part)} actions={[ { name: t`Add BOM Item`, @@ -639,9 +645,29 @@ export function BomTable({ onClick: () => importBomItem.open() } ]} + />, +