[PUI] Small tweaks (#6868)

* Add "customer" detail to StockDetail page

* Hide completed tests field if not needed

* Fix "build" and "consumed_by" fields

* Fix icon

* Fix breadcrumb URLs

- Remove hard-coded strings
- Fix broken links

* Add serial icon

* More breadcrumb updates

* useMemo to simplify filters drawer
This commit is contained in:
Oliver 2024-03-27 17:21:15 +11:00 committed by GitHub
parent 4059d9ffeb
commit c2a9b0252a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 47 additions and 16 deletions

View File

@ -53,7 +53,7 @@ export type DetailsField =
| StringDetailField
| BooleanField
| LinkDetailField
| ProgressBarfield
| ProgressBarField
| StatusField
);
@ -85,7 +85,7 @@ type ExternalLinkField = {
external: true;
};
type ProgressBarfield = {
type ProgressBarField = {
type: 'progressbar';
progress: number;
total: number;
@ -96,8 +96,6 @@ type StatusField = {
model: ModelType;
};
type FieldValueType = string | number | undefined;
type FieldProps = {
field_data: any;
field_value: string | number;

View File

@ -104,6 +104,8 @@ const icons = {
variants: IconVersions,
allocations: IconBookmarks,
bom: IconListTree,
build: IconTools,
build_order: IconTools,
builds: IconTools,
used_in: IconStack2,
manufacturers: IconBuildingFactory2,
@ -170,6 +172,7 @@ const icons = {
quantity: IconNumbers,
progress: IconProgressCheck,
reference: IconHash,
serial: IconHash,
website: IconWorld,
email: IconMail,
phone: IconPhone,

View File

@ -25,6 +25,7 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { useManufacturerPartFields } from '../../forms/CompanyForms';
import { getDetailUrl } from '../../functions/urls';
import { useEditApiFormModal } from '../../hooks/UseForm';
import { useInstance } from '../../hooks/UseInstance';
import { apiUrl } from '../../states/ApiState';

View File

@ -23,6 +23,7 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { partCategoryFields } from '../../forms/PartForms';
import { getDetailUrl } from '../../functions/urls';
import { useEditApiFormModal } from '../../hooks/UseForm';
import { useInstance } from '../../hooks/UseInstance';
import { useUserState } from '../../states/UserState';
@ -212,7 +213,7 @@ export default function CategoryDetail({}: {}) {
{ name: t`Parts`, url: '/part' },
...(category.path ?? []).map((c: any) => ({
name: c.name,
url: `/part/category/${c.pk}`
url: getDetailUrl(ModelType.partcategory, c.pk)
}))
],
[category]

View File

@ -63,6 +63,7 @@ import {
useTransferStockItem
} from '../../forms/StockForms';
import { InvenTreeIcon } from '../../functions/icons';
import { getDetailUrl } from '../../functions/urls';
import { useEditApiFormModal } from '../../hooks/UseForm';
import { useInstance } from '../../hooks/UseInstance';
import { apiUrl } from '../../states/ApiState';
@ -624,7 +625,7 @@ export default function PartDetail() {
{ name: t`Parts`, url: '/part' },
...(part.category_path ?? []).map((c: any) => ({
name: c.name,
url: `/part/category/${c.pk}`
url: getDetailUrl(ModelType.partcategory, c.pk)
}))
],
[part]

View File

@ -34,6 +34,7 @@ import {
useTransferStockItem
} from '../../forms/StockForms';
import { InvenTreeIcon } from '../../functions/icons';
import { getDetailUrl } from '../../functions/urls';
import { useEditApiFormModal } from '../../hooks/UseForm';
import { useInstance } from '../../hooks/UseInstance';
import { useUserState } from '../../states/UserState';
@ -288,7 +289,7 @@ export default function Stock() {
{ name: t`Stock`, url: '/stock' },
...(location.path ?? []).map((l: any) => ({
name: l.name,
url: `/stock/location/${l.pk}`
url: getDetailUrl(ModelType.stocklocation, l.pk)
}))
],
[location]

View File

@ -51,6 +51,7 @@ import {
useTransferStockItem
} from '../../forms/StockForms';
import { InvenTreeIcon } from '../../functions/icons';
import { getDetailUrl } from '../../functions/urls';
import { useInstance } from '../../hooks/UseInstance';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
@ -82,6 +83,7 @@ export default function StockDetail() {
const detailsPanel = useMemo(() => {
let data = stockitem;
let part = stockitem?.part_detail ?? {};
data.available_stock = Math.max(0, data.quantity - data.allocated);
@ -99,14 +101,16 @@ export default function StockDetail() {
},
{
name: 'status',
type: 'text',
label: t`Stock Status`
type: 'status',
label: t`Stock Status`,
model: ModelType.stockitem
},
{
type: 'text',
name: 'tests',
label: `Completed Tests`,
icon: 'progress'
icon: 'progress',
hidden: !part?.trackable
},
{
type: 'text',
@ -174,6 +178,7 @@ export default function StockDetail() {
return text;
},
icon: 'stock',
model: ModelType.stockitem,
hidden: !stockitem.belongs_to
},
@ -182,7 +187,17 @@ export default function StockDetail() {
name: 'consumed_by',
label: t`Consumed By`,
model: ModelType.build,
hidden: !stockitem.consumed_by
hidden: !stockitem.consumed_by,
icon: 'build',
model_field: 'reference'
},
{
type: 'link',
name: 'build',
label: t`Build Order`,
model: ModelType.build,
hidden: !stockitem.build,
model_field: 'reference'
},
{
type: 'link',
@ -192,6 +207,13 @@ export default function StockDetail() {
hidden: !stockitem.sales_order,
icon: 'sales_orders',
model_field: 'reference'
},
{
type: 'link',
name: 'customer',
label: t`Customer`,
model: ModelType.company,
hidden: !stockitem.customer
}
];
@ -317,7 +339,7 @@ export default function StockDetail() {
{ name: t`Stock`, url: '/stock' },
...(stockitem.location_path ?? []).map((l: any) => ({
name: l.name,
url: apiUrl(ApiEndpoints.stock_location_list, l.pk)
url: getDetailUrl(ModelType.stocklocation, l.pk)
}))
],
[stockitem]

View File

@ -180,6 +180,12 @@ export function FilterSelectDrawer({
setAddFilter(false);
}, [tableState.activeFilters]);
const hasFilters: boolean = useMemo(() => {
let filters = tableState?.activeFilters ?? [];
return filters.length > 0;
}, [tableState.activeFilters]);
return (
<Drawer
size="sm"
@ -190,13 +196,11 @@ export function FilterSelectDrawer({
title={<StylishText size="lg">{t`Table Filters`}</StylishText>}
>
<Stack spacing="xs">
{tableState.activeFilters &&
{hasFilters &&
tableState.activeFilters?.map((f) => (
<FilterItem key={f.name} flt={f} tableState={tableState} />
))}
{tableState.activeFilters && tableState.activeFilters.length > 0 && (
<Divider />
)}
{hasFilters && <Divider />}
{addFilter && (
<Stack spacing="xs">
<FilterAddGroup