Skip to content

Commit

Permalink
[PUI] Tweaks (#7843)
Browse files Browse the repository at this point in the history
* Part test template table updates

* Allow export from part test template table

* Allow actions for build lines

* Updates to BuildLine table
  • Loading branch information
SchrodingersGat authored Aug 9, 2024
1 parent 21f623e commit d68d52b
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 45 deletions.
2 changes: 1 addition & 1 deletion src/frontend/src/pages/part/PartDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 />
)
Expand Down
27 changes: 18 additions & 9 deletions src/frontend/src/tables/build/BuildLineTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -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({
Expand All @@ -278,7 +287,7 @@ export default function BuildLineTable({
}
];
},
[user]
[user, outputId]
);

return (
Expand Down
113 changes: 78 additions & 35 deletions src/frontend/src/tables/part/PartTestTemplateTable.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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();
Expand All @@ -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 (
<Text
fw={record.required && 700}
c={record.enabled ? undefined : 'red'}
>
{record.test_name}
</Text>
<TableHoverCard
value={
<Text
fw={record.required && 700}
c={record.enabled ? undefined : 'red'}
>
{record.test_name}
</Text>
}
title={t`Template Details`}
extra={extra}
/>
);
}
},
Expand Down Expand Up @@ -175,28 +197,36 @@ 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();
}
})
];
},
[user, partId]
[user, partId, partLocked]
);

const tableActions = useMemo(() => {
Expand All @@ -206,36 +236,49 @@ 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}
<InvenTreeTable
url={apiUrl(ApiEndpoints.part_test_template_list)}
tableState={table}
columns={tableColumns}
props={{
params: {
part: partId,
part_detail: true
},
tableFilters: tableFilters,
tableActions: tableActions,
rowActions: rowActions,
onRowClick: (row) => {
if (row.part && row.part != partId) {
// This test is defined for a different part
navigate(getDetailUrl(ModelType.part, row.part));
<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}
columns={tableColumns}
props={{
params: {
part: partId,
part_detail: true
},
tableFilters: tableFilters,
tableActions: tableActions,
enableDownload: true,
rowActions: rowActions,
onRowClick: (row) => {
if (row.part && row.part != partId) {
// This test is defined for a different part
navigate(getDetailUrl(ModelType.part, row.part));
}
}
}
}}
/>
}}
/>
</Stack>
</>
);
}

0 comments on commit d68d52b

Please sign in to comment.