mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
[PUI] Tweaks (#7007)
* Allow pk field spec for row click * Fix row click-through for UsedInTable * Cleanup "details" view for part page * Add 'stock' column to parametric part table * Add details badges to some pages * Add extra badges to PartDetailPage
This commit is contained in:
parent
cbbdb70762
commit
f4d748ebed
26
src/frontend/src/components/details/DetailsBadge.tsx
Normal file
26
src/frontend/src/components/details/DetailsBadge.tsx
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { Badge } from '@mantine/core';
|
||||||
|
|
||||||
|
export type DetailsBadgeProps = {
|
||||||
|
color: string;
|
||||||
|
label: string;
|
||||||
|
size?: string;
|
||||||
|
visible?: boolean;
|
||||||
|
key?: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function DetailsBadge(props: DetailsBadgeProps) {
|
||||||
|
if (props.visible == false) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Badge
|
||||||
|
key={props.key}
|
||||||
|
color={props.color}
|
||||||
|
variant="filled"
|
||||||
|
size={props.size ?? 'lg'}
|
||||||
|
>
|
||||||
|
{props.label}
|
||||||
|
</Badge>
|
||||||
|
);
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
import { Group, Paper, Space, Stack, Text } from '@mantine/core';
|
import { Group, Paper, Space, Stack, Text } from '@mantine/core';
|
||||||
import { Fragment, ReactNode } from 'react';
|
import { Fragment, ReactNode } from 'react';
|
||||||
|
|
||||||
|
import DetailsBadge, { DetailsBadgeProps } from '../details/DetailsBadge';
|
||||||
import { ApiImage } from '../images/ApiImage';
|
import { ApiImage } from '../images/ApiImage';
|
||||||
import { StylishText } from '../items/StylishText';
|
import { StylishText } from '../items/StylishText';
|
||||||
import { Breadcrumb, BreadcrumbList } from './BreadcrumbList';
|
import { Breadcrumb, BreadcrumbList } from './BreadcrumbList';
|
||||||
@ -15,6 +16,7 @@ export function PageDetail({
|
|||||||
title,
|
title,
|
||||||
subtitle,
|
subtitle,
|
||||||
detail,
|
detail,
|
||||||
|
badges,
|
||||||
imageUrl,
|
imageUrl,
|
||||||
breadcrumbs,
|
breadcrumbs,
|
||||||
breadcrumbAction,
|
breadcrumbAction,
|
||||||
@ -24,6 +26,7 @@ export function PageDetail({
|
|||||||
subtitle?: string;
|
subtitle?: string;
|
||||||
imageUrl?: string;
|
imageUrl?: string;
|
||||||
detail?: ReactNode;
|
detail?: ReactNode;
|
||||||
|
badges?: ReactNode[];
|
||||||
breadcrumbs?: Breadcrumb[];
|
breadcrumbs?: Breadcrumb[];
|
||||||
breadcrumbAction?: () => void;
|
breadcrumbAction?: () => void;
|
||||||
actions?: ReactNode[];
|
actions?: ReactNode[];
|
||||||
@ -56,6 +59,9 @@ export function PageDetail({
|
|||||||
</Group>
|
</Group>
|
||||||
<Space />
|
<Space />
|
||||||
{detail}
|
{detail}
|
||||||
|
<Group position="right" spacing="xs" noWrap>
|
||||||
|
{badges}
|
||||||
|
</Group>
|
||||||
<Space />
|
<Space />
|
||||||
{actions && (
|
{actions && (
|
||||||
<Group spacing={5} position="right">
|
<Group spacing={5} position="right">
|
||||||
|
@ -334,16 +334,17 @@ export default function BuildDetail() {
|
|||||||
];
|
];
|
||||||
}, [id, build, user]);
|
}, [id, build, user]);
|
||||||
|
|
||||||
const buildDetail = useMemo(() => {
|
const buildBadges = useMemo(() => {
|
||||||
return build?.status ? (
|
return instanceQuery.isFetching
|
||||||
StatusRenderer({
|
? []
|
||||||
status: build.status,
|
: [
|
||||||
type: ModelType.build
|
<StatusRenderer
|
||||||
})
|
status={build.status}
|
||||||
) : (
|
type={ModelType.build}
|
||||||
<Skeleton />
|
options={{ size: 'lg' }}
|
||||||
);
|
/>
|
||||||
}, [build, id]);
|
];
|
||||||
|
}, [build, instanceQuery]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -353,7 +354,7 @@ export default function BuildDetail() {
|
|||||||
<PageDetail
|
<PageDetail
|
||||||
title={build.reference}
|
title={build.reference}
|
||||||
subtitle={build.title}
|
subtitle={build.title}
|
||||||
detail={buildDetail}
|
badges={buildBadges}
|
||||||
imageUrl={build.part_detail?.image ?? build.part_detail?.thumbnail}
|
imageUrl={build.part_detail?.image ?? build.part_detail?.thumbnail}
|
||||||
breadcrumbs={[
|
breadcrumbs={[
|
||||||
{ name: t`Build Orders`, url: '/build' },
|
{ name: t`Build Orders`, url: '/build' },
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import {
|
import {
|
||||||
|
Badge,
|
||||||
Grid,
|
Grid,
|
||||||
Group,
|
Group,
|
||||||
LoadingOverlay,
|
LoadingOverlay,
|
||||||
@ -30,11 +31,14 @@ import {
|
|||||||
IconVersions
|
IconVersions
|
||||||
} from '@tabler/icons-react';
|
} from '@tabler/icons-react';
|
||||||
import { useSuspenseQuery } from '@tanstack/react-query';
|
import { useSuspenseQuery } from '@tanstack/react-query';
|
||||||
import { useMemo, useState } from 'react';
|
import { ReactNode, useMemo, useState } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import { api } from '../../App';
|
import { api } from '../../App';
|
||||||
import { DetailsField, DetailsTable } from '../../components/details/Details';
|
import { DetailsField, DetailsTable } from '../../components/details/Details';
|
||||||
|
import DetailsBadge, {
|
||||||
|
DetailsBadgeProps
|
||||||
|
} from '../../components/details/DetailsBadge';
|
||||||
import { DetailsImage } from '../../components/details/DetailsImage';
|
import { DetailsImage } from '../../components/details/DetailsImage';
|
||||||
import { ItemDetailsGrid } from '../../components/details/ItemDetails';
|
import { ItemDetailsGrid } from '../../components/details/ItemDetails';
|
||||||
import { PartIcons } from '../../components/details/PartIcons';
|
import { PartIcons } from '../../components/details/PartIcons';
|
||||||
@ -631,15 +635,34 @@ export default function PartDetail() {
|
|||||||
[part]
|
[part]
|
||||||
);
|
);
|
||||||
|
|
||||||
const partDetail = useMemo(() => {
|
const badges: ReactNode[] = useMemo(() => {
|
||||||
return (
|
if (instanceQuery.isLoading || instanceQuery.isFetching) {
|
||||||
<Group spacing="xs" noWrap={true}>
|
return [];
|
||||||
<Stack spacing="xs">
|
}
|
||||||
<Text>Stock: {part.in_stock}</Text>
|
|
||||||
</Stack>
|
return [
|
||||||
</Group>
|
<DetailsBadge
|
||||||
);
|
label={t`In Stock` + `: ${part.in_stock}`}
|
||||||
}, [part, id]);
|
color={part.in_stock >= part.minimum_stock ? 'green' : 'orange'}
|
||||||
|
visible={part.in_stock > 0}
|
||||||
|
/>,
|
||||||
|
<DetailsBadge
|
||||||
|
label={t`No Stock`}
|
||||||
|
color="red"
|
||||||
|
visible={part.in_stock == 0}
|
||||||
|
/>,
|
||||||
|
<DetailsBadge
|
||||||
|
label={t`On Order` + `: ${part.ordering}`}
|
||||||
|
color="blue"
|
||||||
|
visible={part.on_order > 0}
|
||||||
|
/>,
|
||||||
|
<DetailsBadge
|
||||||
|
label={t`In Production` + `: ${part.building}`}
|
||||||
|
color="blue"
|
||||||
|
visible={part.building > 0}
|
||||||
|
/>
|
||||||
|
];
|
||||||
|
}, [part, instanceQuery]);
|
||||||
|
|
||||||
const partFields = usePartFields({ create: false });
|
const partFields = usePartFields({ create: false });
|
||||||
|
|
||||||
@ -740,7 +763,7 @@ export default function PartDetail() {
|
|||||||
title={t`Part` + ': ' + part.full_name}
|
title={t`Part` + ': ' + part.full_name}
|
||||||
subtitle={part.description}
|
subtitle={part.description}
|
||||||
imageUrl={part.image}
|
imageUrl={part.image}
|
||||||
detail={partDetail}
|
badges={badges}
|
||||||
breadcrumbs={breadcrumbs}
|
breadcrumbs={breadcrumbs}
|
||||||
breadcrumbAction={() => {
|
breadcrumbAction={() => {
|
||||||
setTreeOpen(true);
|
setTreeOpen(true);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { Grid, LoadingOverlay, Skeleton, Stack } from '@mantine/core';
|
import { Grid, Group, LoadingOverlay, Skeleton, Stack } from '@mantine/core';
|
||||||
import {
|
import {
|
||||||
IconDots,
|
IconDots,
|
||||||
IconInfoCircle,
|
IconInfoCircle,
|
||||||
@ -8,7 +8,7 @@ import {
|
|||||||
IconPackages,
|
IconPackages,
|
||||||
IconPaperclip
|
IconPaperclip
|
||||||
} from '@tabler/icons-react';
|
} from '@tabler/icons-react';
|
||||||
import { useMemo } from 'react';
|
import { ReactNode, useMemo } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import { DetailsField, DetailsTable } from '../../components/details/Details';
|
import { DetailsField, DetailsTable } from '../../components/details/Details';
|
||||||
@ -25,6 +25,7 @@ import {
|
|||||||
} from '../../components/items/ActionDropdown';
|
} from '../../components/items/ActionDropdown';
|
||||||
import { PageDetail } from '../../components/nav/PageDetail';
|
import { PageDetail } from '../../components/nav/PageDetail';
|
||||||
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
||||||
|
import { StatusRenderer } from '../../components/render/StatusRenderer';
|
||||||
import { NotesEditor } from '../../components/widgets/MarkdownEditor';
|
import { NotesEditor } from '../../components/widgets/MarkdownEditor';
|
||||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||||
import { ModelType } from '../../enums/ModelType';
|
import { ModelType } from '../../enums/ModelType';
|
||||||
@ -297,6 +298,18 @@ export default function PurchaseOrderDetail() {
|
|||||||
];
|
];
|
||||||
}, [id, order, user]);
|
}, [id, order, user]);
|
||||||
|
|
||||||
|
const orderBadges: ReactNode[] = useMemo(() => {
|
||||||
|
return instanceQuery.isLoading
|
||||||
|
? []
|
||||||
|
: [
|
||||||
|
<StatusRenderer
|
||||||
|
status={order.status}
|
||||||
|
type={ModelType.purchaseorder}
|
||||||
|
options={{ size: 'lg' }}
|
||||||
|
/>
|
||||||
|
];
|
||||||
|
}, [order, instanceQuery]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{editPurchaseOrder.modal}
|
{editPurchaseOrder.modal}
|
||||||
@ -308,6 +321,7 @@ export default function PurchaseOrderDetail() {
|
|||||||
imageUrl={order.supplier_detail?.image}
|
imageUrl={order.supplier_detail?.image}
|
||||||
breadcrumbs={[{ name: t`Purchasing`, url: '/purchasing/' }]}
|
breadcrumbs={[{ name: t`Purchasing`, url: '/purchasing/' }]}
|
||||||
actions={poActions}
|
actions={poActions}
|
||||||
|
badges={orderBadges}
|
||||||
/>
|
/>
|
||||||
<PanelGroup pageKey="purchaseorder" panels={orderPanels} />
|
<PanelGroup pageKey="purchaseorder" panels={orderPanels} />
|
||||||
</Stack>
|
</Stack>
|
||||||
|
@ -6,7 +6,7 @@ import {
|
|||||||
IconNotes,
|
IconNotes,
|
||||||
IconPaperclip
|
IconPaperclip
|
||||||
} from '@tabler/icons-react';
|
} from '@tabler/icons-react';
|
||||||
import { useMemo } from 'react';
|
import { ReactNode, useMemo } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import { DetailsField, DetailsTable } from '../../components/details/Details';
|
import { DetailsField, DetailsTable } from '../../components/details/Details';
|
||||||
@ -14,6 +14,7 @@ import { DetailsImage } from '../../components/details/DetailsImage';
|
|||||||
import { ItemDetailsGrid } from '../../components/details/ItemDetails';
|
import { ItemDetailsGrid } from '../../components/details/ItemDetails';
|
||||||
import { PageDetail } from '../../components/nav/PageDetail';
|
import { PageDetail } from '../../components/nav/PageDetail';
|
||||||
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
||||||
|
import { StatusRenderer } from '../../components/render/StatusRenderer';
|
||||||
import { NotesEditor } from '../../components/widgets/MarkdownEditor';
|
import { NotesEditor } from '../../components/widgets/MarkdownEditor';
|
||||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||||
import { ModelType } from '../../enums/ModelType';
|
import { ModelType } from '../../enums/ModelType';
|
||||||
@ -220,6 +221,18 @@ export default function ReturnOrderDetail() {
|
|||||||
];
|
];
|
||||||
}, [order, id]);
|
}, [order, id]);
|
||||||
|
|
||||||
|
const orderBadges: ReactNode[] = useMemo(() => {
|
||||||
|
return instanceQuery.isLoading
|
||||||
|
? []
|
||||||
|
: [
|
||||||
|
<StatusRenderer
|
||||||
|
status={order.status}
|
||||||
|
type={ModelType.returnorder}
|
||||||
|
options={{ size: 'lg' }}
|
||||||
|
/>
|
||||||
|
];
|
||||||
|
}, [order, instanceQuery]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack spacing="xs">
|
<Stack spacing="xs">
|
||||||
@ -228,6 +241,7 @@ export default function ReturnOrderDetail() {
|
|||||||
title={t`Return Order` + `: ${order.reference}`}
|
title={t`Return Order` + `: ${order.reference}`}
|
||||||
subtitle={order.description}
|
subtitle={order.description}
|
||||||
imageUrl={order.customer_detail?.image}
|
imageUrl={order.customer_detail?.image}
|
||||||
|
badges={orderBadges}
|
||||||
breadcrumbs={[{ name: t`Sales`, url: '/sales/' }]}
|
breadcrumbs={[{ name: t`Sales`, url: '/sales/' }]}
|
||||||
/>
|
/>
|
||||||
<PanelGroup pageKey="returnorder" panels={orderPanels} />
|
<PanelGroup pageKey="returnorder" panels={orderPanels} />
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
IconTruckDelivery,
|
IconTruckDelivery,
|
||||||
IconTruckLoading
|
IconTruckLoading
|
||||||
} from '@tabler/icons-react';
|
} from '@tabler/icons-react';
|
||||||
import { useMemo } from 'react';
|
import { ReactNode, useMemo } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import { DetailsField, DetailsTable } from '../../components/details/Details';
|
import { DetailsField, DetailsTable } from '../../components/details/Details';
|
||||||
@ -17,6 +17,7 @@ import { DetailsImage } from '../../components/details/DetailsImage';
|
|||||||
import { ItemDetailsGrid } from '../../components/details/ItemDetails';
|
import { ItemDetailsGrid } from '../../components/details/ItemDetails';
|
||||||
import { PageDetail } from '../../components/nav/PageDetail';
|
import { PageDetail } from '../../components/nav/PageDetail';
|
||||||
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
||||||
|
import { StatusRenderer } from '../../components/render/StatusRenderer';
|
||||||
import { NotesEditor } from '../../components/widgets/MarkdownEditor';
|
import { NotesEditor } from '../../components/widgets/MarkdownEditor';
|
||||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||||
import { ModelType } from '../../enums/ModelType';
|
import { ModelType } from '../../enums/ModelType';
|
||||||
@ -244,6 +245,18 @@ export default function SalesOrderDetail() {
|
|||||||
];
|
];
|
||||||
}, [order, id]);
|
}, [order, id]);
|
||||||
|
|
||||||
|
const orderBadges: ReactNode[] = useMemo(() => {
|
||||||
|
return instanceQuery.isLoading
|
||||||
|
? []
|
||||||
|
: [
|
||||||
|
<StatusRenderer
|
||||||
|
status={order.status}
|
||||||
|
type={ModelType.salesorder}
|
||||||
|
options={{ size: 'lg' }}
|
||||||
|
/>
|
||||||
|
];
|
||||||
|
}, [order, instanceQuery]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack spacing="xs">
|
<Stack spacing="xs">
|
||||||
@ -252,6 +265,7 @@ export default function SalesOrderDetail() {
|
|||||||
title={t`Sales Order` + `: ${order.reference}`}
|
title={t`Sales Order` + `: ${order.reference}`}
|
||||||
subtitle={order.description}
|
subtitle={order.description}
|
||||||
imageUrl={order.customer_detail?.image}
|
imageUrl={order.customer_detail?.image}
|
||||||
|
badges={orderBadges}
|
||||||
breadcrumbs={[{ name: t`Sales`, url: '/sales/' }]}
|
breadcrumbs={[{ name: t`Sales`, url: '/sales/' }]}
|
||||||
/>
|
/>
|
||||||
<PanelGroup pageKey="salesorder" panels={orderPanels} />
|
<PanelGroup pageKey="salesorder" panels={orderPanels} />
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import {
|
import {
|
||||||
Alert,
|
Alert,
|
||||||
|
Badge,
|
||||||
Grid,
|
Grid,
|
||||||
|
Group,
|
||||||
LoadingOverlay,
|
LoadingOverlay,
|
||||||
Skeleton,
|
Skeleton,
|
||||||
Stack,
|
Stack,
|
||||||
@ -20,10 +22,11 @@ import {
|
|||||||
IconPaperclip,
|
IconPaperclip,
|
||||||
IconSitemap
|
IconSitemap
|
||||||
} from '@tabler/icons-react';
|
} from '@tabler/icons-react';
|
||||||
import { useMemo, useState } from 'react';
|
import { ReactNode, useMemo, useState } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import { DetailsField, DetailsTable } from '../../components/details/Details';
|
import { DetailsField, DetailsTable } from '../../components/details/Details';
|
||||||
|
import DetailsBadge from '../../components/details/DetailsBadge';
|
||||||
import { DetailsImage } from '../../components/details/DetailsImage';
|
import { DetailsImage } from '../../components/details/DetailsImage';
|
||||||
import { ItemDetailsGrid } from '../../components/details/ItemDetails';
|
import { ItemDetailsGrid } from '../../components/details/ItemDetails';
|
||||||
import {
|
import {
|
||||||
@ -38,6 +41,7 @@ import {
|
|||||||
import { PageDetail } from '../../components/nav/PageDetail';
|
import { PageDetail } from '../../components/nav/PageDetail';
|
||||||
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
||||||
import { StockLocationTree } from '../../components/nav/StockLocationTree';
|
import { StockLocationTree } from '../../components/nav/StockLocationTree';
|
||||||
|
import { StatusRenderer } from '../../components/render/StatusRenderer';
|
||||||
import { NotesEditor } from '../../components/widgets/MarkdownEditor';
|
import { NotesEditor } from '../../components/widgets/MarkdownEditor';
|
||||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||||
import { ModelType } from '../../enums/ModelType';
|
import { ModelType } from '../../enums/ModelType';
|
||||||
@ -437,6 +441,33 @@ export default function StockDetail() {
|
|||||||
[id, stockitem, user]
|
[id, stockitem, user]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const stockBadges: ReactNode[] = useMemo(() => {
|
||||||
|
return instanceQuery.isLoading
|
||||||
|
? []
|
||||||
|
: [
|
||||||
|
<DetailsBadge
|
||||||
|
color="blue"
|
||||||
|
label={t`Serial Number` + `: ${stockitem.serial}`}
|
||||||
|
visible={!!stockitem.serial}
|
||||||
|
/>,
|
||||||
|
<DetailsBadge
|
||||||
|
color="blue"
|
||||||
|
label={t`Quantity` + `: ${stockitem.quantity}`}
|
||||||
|
visible={!stockitem.serial}
|
||||||
|
/>,
|
||||||
|
<DetailsBadge
|
||||||
|
color="blue"
|
||||||
|
label={t`Batch Code` + `: ${stockitem.batch}`}
|
||||||
|
visible={!!stockitem.batch}
|
||||||
|
/>,
|
||||||
|
<StatusRenderer
|
||||||
|
status={stockitem.status}
|
||||||
|
type={ModelType.stockitem}
|
||||||
|
options={{ size: 'lg' }}
|
||||||
|
/>
|
||||||
|
];
|
||||||
|
}, [stockitem, instanceQuery]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack>
|
<Stack>
|
||||||
<LoadingOverlay visible={instanceQuery.isFetching} />
|
<LoadingOverlay visible={instanceQuery.isFetching} />
|
||||||
@ -449,11 +480,7 @@ export default function StockDetail() {
|
|||||||
title={t`Stock Item`}
|
title={t`Stock Item`}
|
||||||
subtitle={stockitem.part_detail?.full_name}
|
subtitle={stockitem.part_detail?.full_name}
|
||||||
imageUrl={stockitem.part_detail?.thumbnail}
|
imageUrl={stockitem.part_detail?.thumbnail}
|
||||||
detail={
|
badges={stockBadges}
|
||||||
<Alert color="teal" title="Stock Item">
|
|
||||||
<Text>Quantity: {stockitem.quantity ?? 'idk'}</Text>
|
|
||||||
</Alert>
|
|
||||||
}
|
|
||||||
breadcrumbs={breadcrumbs}
|
breadcrumbs={breadcrumbs}
|
||||||
breadcrumbAction={() => {
|
breadcrumbAction={() => {
|
||||||
setTreeOpen(true);
|
setTreeOpen(true);
|
||||||
|
@ -91,6 +91,7 @@ export type InvenTreeTableProps<T = any> = {
|
|||||||
onRowClick?: (record: T, index: number, event: any) => void;
|
onRowClick?: (record: T, index: number, event: any) => void;
|
||||||
onCellClick?: DataTableCellClickHandler<T>;
|
onCellClick?: DataTableCellClickHandler<T>;
|
||||||
modelType?: ModelType;
|
modelType?: ModelType;
|
||||||
|
modelField?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -515,9 +516,12 @@ export function InvenTreeTable<T = any>({
|
|||||||
if (props.onRowClick) {
|
if (props.onRowClick) {
|
||||||
// If a custom row click handler is provided, use that
|
// If a custom row click handler is provided, use that
|
||||||
props.onRowClick(record, index, event);
|
props.onRowClick(record, index, event);
|
||||||
} else if (tableProps.modelType && record?.pk) {
|
} else if (tableProps.modelType) {
|
||||||
|
const pk = record?.[tableProps.modelField ?? 'pk'];
|
||||||
|
|
||||||
|
if (pk) {
|
||||||
// If a model type is provided, navigate to the detail view for that model
|
// If a model type is provided, navigate to the detail view for that model
|
||||||
let url = getDetailUrl(tableProps.modelType, record.pk);
|
let url = getDetailUrl(tableProps.modelType, pk);
|
||||||
|
|
||||||
// Should it be opened in a new tab?
|
// Should it be opened in a new tab?
|
||||||
if (event?.ctrlKey || event?.shiftKey) {
|
if (event?.ctrlKey || event?.shiftKey) {
|
||||||
@ -529,6 +533,7 @@ export function InvenTreeTable<T = any>({
|
|||||||
navigate(url);
|
navigate(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
[props.onRowClick]
|
[props.onRowClick]
|
||||||
);
|
);
|
||||||
|
@ -83,7 +83,8 @@ export function UsedInTable({
|
|||||||
sub_part_detail: true
|
sub_part_detail: true
|
||||||
},
|
},
|
||||||
tableFilters: tableFilters,
|
tableFilters: tableFilters,
|
||||||
modelType: ModelType.part
|
modelType: ModelType.part,
|
||||||
|
modelField: 'part'
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -234,6 +234,10 @@ export default function ParametricPartTable({
|
|||||||
{
|
{
|
||||||
accessor: 'IPN',
|
accessor: 'IPN',
|
||||||
sortable: true
|
sortable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessor: 'total_in_stock',
|
||||||
|
sortable: true
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user