[PUI] Tweaks (#7843)

* Part test template table updates

* Allow export from part test template table

* Allow actions for build lines

* Updates to BuildLine table
This commit is contained in:
Oliver 2024-08-09 18:24:19 +10:00 committed by GitHub
parent 21f623eea8
commit d68d52ba88
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 97 additions and 45 deletions

View File

@ -675,7 +675,7 @@ export default function PartDetail() {
icon: <IconTestPipe />,
hidden: !part.trackable,
content: part?.pk ? (
<PartTestTemplateTable partId={part?.pk} />
<PartTestTemplateTable partId={part?.pk} partLocked={part.locked} />
) : (
<Skeleton />
)

View File

@ -24,9 +24,11 @@ import { TableHoverCard } from '../TableHoverCard';
export default function BuildLineTable({
buildId,
outputId,
params = {}
}: {
buildId: number;
outputId?: number;
params?: any;
}) {
const table = useTable('buildline');
@ -237,35 +239,42 @@ export default function BuildLineTable({
const rowActions = useCallback(
(record: any) => {
let part = record.part_detail;
let part = record.part_detail ?? {};
// Consumable items have no appropriate actions
if (record?.bom_item_detail?.consumable) {
return [];
}
// Tracked items must be allocated to a particular output
if (record?.part_detail?.trackable) {
return [];
}
const hasOutput = !!outputId;
// Can allocate
let canAllocate =
user.hasChangeRole(UserRoles.build) &&
record.allocated < record.quantity &&
record.trackable == hasOutput;
let canOrder =
user.hasAddRole(UserRoles.purchase_order) && part.purchaseable;
let canBuild = user.hasAddRole(UserRoles.build) && part.assembly;
return [
{
icon: <IconArrowRight />,
title: t`Allocate Stock`,
hidden: record.allocated >= record.quantity,
hidden: !canAllocate,
color: 'green'
},
{
icon: <IconShoppingCart />,
title: t`Order Stock`,
hidden: !part?.purchaseable,
hidden: !canOrder,
color: 'blue'
},
{
icon: <IconTool />,
title: t`Build Stock`,
hidden: !part?.assembly || !user.hasAddRole(UserRoles.build),
hidden: !canBuild,
color: 'blue',
onClick: () => {
setInitialData({
@ -278,7 +287,7 @@ export default function BuildLineTable({
}
];
},
[user]
[user, outputId]
);
return (

View File

@ -1,6 +1,7 @@
import { Trans, t } from '@lingui/macro';
import { Alert, Badge, Text } from '@mantine/core';
import { useCallback, useMemo, useState } from 'react';
import { Alert, Badge, Stack, Text } from '@mantine/core';
import { IconArrowRight, IconLock } from '@tabler/icons-react';
import { ReactNode, useCallback, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { AddItemButton } from '../../components/buttons/AddItemButton';
@ -22,8 +23,15 @@ import { BooleanColumn, DescriptionColumn } from '../ColumnRenderers';
import { TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../RowActions';
import { TableHoverCard } from '../TableHoverCard';
export default function PartTestTemplateTable({ partId }: { partId: number }) {
export default function PartTestTemplateTable({
partId,
partLocked
}: {
partId: number;
partLocked?: boolean;
}) {
const table = useTable('part-test-template');
const user = useUserState();
const navigate = useNavigate();
@ -35,13 +43,27 @@ export default function PartTestTemplateTable({ partId }: { partId: number }) {
switchable: false,
sortable: true,
render: (record: any) => {
let extra: ReactNode[] = [];
if (record.part != partId) {
extra.push(
<Text size="sm">{t`Test is defined for a parent template part`}</Text>
);
}
return (
<TableHoverCard
value={
<Text
fw={record.required && 700}
c={record.enabled ? undefined : 'red'}
>
{record.test_name}
</Text>
}
title={t`Template Details`}
extra={extra}
/>
);
}
},
@ -175,20 +197,28 @@ export default function PartTestTemplateTable({ partId }: { partId: number }) {
const can_delete = user.hasDeleteRole(UserRoles.part);
if (record.part != partId) {
// No actions, as this test is defined for a parent part
return [];
// This test is defined for a parent part
return [
{
icon: <IconArrowRight />,
title: t`View Parent Part`,
onClick: () => {
navigate(getDetailUrl(ModelType.part, record.part));
}
}
];
}
return [
RowEditAction({
hidden: !can_edit,
hidden: partLocked || !can_edit,
onClick: () => {
setSelectedTest(record.pk);
editTestTemplate.open();
}
}),
RowDeleteAction({
hidden: !can_delete,
hidden: partLocked || !can_delete,
onClick: () => {
setSelectedTest(record.pk);
deleteTestTemplate.open();
@ -196,7 +226,7 @@ export default function PartTestTemplateTable({ partId }: { partId: number }) {
})
];
},
[user, partId]
[user, partId, partLocked]
);
const tableActions = useMemo(() => {
@ -206,16 +236,27 @@ export default function PartTestTemplateTable({ partId }: { partId: number }) {
<AddItemButton
tooltip={t`Add Test Template`}
onClick={() => newTestTemplate.open()}
hidden={!can_add}
hidden={partLocked || !can_add}
/>
];
}, [user]);
}, [user, partLocked]);
return (
<>
{newTestTemplate.modal}
{editTestTemplate.modal}
{deleteTestTemplate.modal}
<Stack gap="xs">
{partLocked && (
<Alert
title={t`Part is Locked`}
color="orange"
icon={<IconLock />}
p="xs"
>
<Text>{t`Part templates cannot be edited, as the part is locked`}</Text>
</Alert>
)}
<InvenTreeTable
url={apiUrl(ApiEndpoints.part_test_template_list)}
tableState={table}
@ -227,6 +268,7 @@ export default function PartTestTemplateTable({ partId }: { partId: number }) {
},
tableFilters: tableFilters,
tableActions: tableActions,
enableDownload: true,
rowActions: rowActions,
onRowClick: (row) => {
if (row.part && row.part != partId) {
@ -236,6 +278,7 @@ export default function PartTestTemplateTable({ partId }: { partId: number }) {
}
}}
/>
</Stack>
</>
);
}