mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-28 11:36:44 +00:00
[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:
parent
4059d9ffeb
commit
c2a9b0252a
@ -53,7 +53,7 @@ export type DetailsField =
|
|||||||
| StringDetailField
|
| StringDetailField
|
||||||
| BooleanField
|
| BooleanField
|
||||||
| LinkDetailField
|
| LinkDetailField
|
||||||
| ProgressBarfield
|
| ProgressBarField
|
||||||
| StatusField
|
| StatusField
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ type ExternalLinkField = {
|
|||||||
external: true;
|
external: true;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ProgressBarfield = {
|
type ProgressBarField = {
|
||||||
type: 'progressbar';
|
type: 'progressbar';
|
||||||
progress: number;
|
progress: number;
|
||||||
total: number;
|
total: number;
|
||||||
@ -96,8 +96,6 @@ type StatusField = {
|
|||||||
model: ModelType;
|
model: ModelType;
|
||||||
};
|
};
|
||||||
|
|
||||||
type FieldValueType = string | number | undefined;
|
|
||||||
|
|
||||||
type FieldProps = {
|
type FieldProps = {
|
||||||
field_data: any;
|
field_data: any;
|
||||||
field_value: string | number;
|
field_value: string | number;
|
||||||
|
@ -104,6 +104,8 @@ const icons = {
|
|||||||
variants: IconVersions,
|
variants: IconVersions,
|
||||||
allocations: IconBookmarks,
|
allocations: IconBookmarks,
|
||||||
bom: IconListTree,
|
bom: IconListTree,
|
||||||
|
build: IconTools,
|
||||||
|
build_order: IconTools,
|
||||||
builds: IconTools,
|
builds: IconTools,
|
||||||
used_in: IconStack2,
|
used_in: IconStack2,
|
||||||
manufacturers: IconBuildingFactory2,
|
manufacturers: IconBuildingFactory2,
|
||||||
@ -170,6 +172,7 @@ const icons = {
|
|||||||
quantity: IconNumbers,
|
quantity: IconNumbers,
|
||||||
progress: IconProgressCheck,
|
progress: IconProgressCheck,
|
||||||
reference: IconHash,
|
reference: IconHash,
|
||||||
|
serial: IconHash,
|
||||||
website: IconWorld,
|
website: IconWorld,
|
||||||
email: IconMail,
|
email: IconMail,
|
||||||
phone: IconPhone,
|
phone: IconPhone,
|
||||||
|
@ -25,6 +25,7 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
|||||||
import { ModelType } from '../../enums/ModelType';
|
import { ModelType } from '../../enums/ModelType';
|
||||||
import { UserRoles } from '../../enums/Roles';
|
import { UserRoles } from '../../enums/Roles';
|
||||||
import { useManufacturerPartFields } from '../../forms/CompanyForms';
|
import { useManufacturerPartFields } from '../../forms/CompanyForms';
|
||||||
|
import { getDetailUrl } from '../../functions/urls';
|
||||||
import { useEditApiFormModal } from '../../hooks/UseForm';
|
import { useEditApiFormModal } from '../../hooks/UseForm';
|
||||||
import { useInstance } from '../../hooks/UseInstance';
|
import { useInstance } from '../../hooks/UseInstance';
|
||||||
import { apiUrl } from '../../states/ApiState';
|
import { apiUrl } from '../../states/ApiState';
|
||||||
|
@ -23,6 +23,7 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
|||||||
import { ModelType } from '../../enums/ModelType';
|
import { ModelType } from '../../enums/ModelType';
|
||||||
import { UserRoles } from '../../enums/Roles';
|
import { UserRoles } from '../../enums/Roles';
|
||||||
import { partCategoryFields } from '../../forms/PartForms';
|
import { partCategoryFields } from '../../forms/PartForms';
|
||||||
|
import { getDetailUrl } from '../../functions/urls';
|
||||||
import { useEditApiFormModal } from '../../hooks/UseForm';
|
import { useEditApiFormModal } from '../../hooks/UseForm';
|
||||||
import { useInstance } from '../../hooks/UseInstance';
|
import { useInstance } from '../../hooks/UseInstance';
|
||||||
import { useUserState } from '../../states/UserState';
|
import { useUserState } from '../../states/UserState';
|
||||||
@ -212,7 +213,7 @@ export default function CategoryDetail({}: {}) {
|
|||||||
{ name: t`Parts`, url: '/part' },
|
{ name: t`Parts`, url: '/part' },
|
||||||
...(category.path ?? []).map((c: any) => ({
|
...(category.path ?? []).map((c: any) => ({
|
||||||
name: c.name,
|
name: c.name,
|
||||||
url: `/part/category/${c.pk}`
|
url: getDetailUrl(ModelType.partcategory, c.pk)
|
||||||
}))
|
}))
|
||||||
],
|
],
|
||||||
[category]
|
[category]
|
||||||
|
@ -63,6 +63,7 @@ import {
|
|||||||
useTransferStockItem
|
useTransferStockItem
|
||||||
} from '../../forms/StockForms';
|
} from '../../forms/StockForms';
|
||||||
import { InvenTreeIcon } from '../../functions/icons';
|
import { InvenTreeIcon } from '../../functions/icons';
|
||||||
|
import { getDetailUrl } from '../../functions/urls';
|
||||||
import { useEditApiFormModal } from '../../hooks/UseForm';
|
import { useEditApiFormModal } from '../../hooks/UseForm';
|
||||||
import { useInstance } from '../../hooks/UseInstance';
|
import { useInstance } from '../../hooks/UseInstance';
|
||||||
import { apiUrl } from '../../states/ApiState';
|
import { apiUrl } from '../../states/ApiState';
|
||||||
@ -624,7 +625,7 @@ export default function PartDetail() {
|
|||||||
{ name: t`Parts`, url: '/part' },
|
{ name: t`Parts`, url: '/part' },
|
||||||
...(part.category_path ?? []).map((c: any) => ({
|
...(part.category_path ?? []).map((c: any) => ({
|
||||||
name: c.name,
|
name: c.name,
|
||||||
url: `/part/category/${c.pk}`
|
url: getDetailUrl(ModelType.partcategory, c.pk)
|
||||||
}))
|
}))
|
||||||
],
|
],
|
||||||
[part]
|
[part]
|
||||||
|
@ -34,6 +34,7 @@ import {
|
|||||||
useTransferStockItem
|
useTransferStockItem
|
||||||
} from '../../forms/StockForms';
|
} from '../../forms/StockForms';
|
||||||
import { InvenTreeIcon } from '../../functions/icons';
|
import { InvenTreeIcon } from '../../functions/icons';
|
||||||
|
import { getDetailUrl } from '../../functions/urls';
|
||||||
import { useEditApiFormModal } from '../../hooks/UseForm';
|
import { useEditApiFormModal } from '../../hooks/UseForm';
|
||||||
import { useInstance } from '../../hooks/UseInstance';
|
import { useInstance } from '../../hooks/UseInstance';
|
||||||
import { useUserState } from '../../states/UserState';
|
import { useUserState } from '../../states/UserState';
|
||||||
@ -288,7 +289,7 @@ export default function Stock() {
|
|||||||
{ name: t`Stock`, url: '/stock' },
|
{ name: t`Stock`, url: '/stock' },
|
||||||
...(location.path ?? []).map((l: any) => ({
|
...(location.path ?? []).map((l: any) => ({
|
||||||
name: l.name,
|
name: l.name,
|
||||||
url: `/stock/location/${l.pk}`
|
url: getDetailUrl(ModelType.stocklocation, l.pk)
|
||||||
}))
|
}))
|
||||||
],
|
],
|
||||||
[location]
|
[location]
|
||||||
|
@ -51,6 +51,7 @@ import {
|
|||||||
useTransferStockItem
|
useTransferStockItem
|
||||||
} from '../../forms/StockForms';
|
} from '../../forms/StockForms';
|
||||||
import { InvenTreeIcon } from '../../functions/icons';
|
import { InvenTreeIcon } from '../../functions/icons';
|
||||||
|
import { getDetailUrl } from '../../functions/urls';
|
||||||
import { useInstance } from '../../hooks/UseInstance';
|
import { useInstance } from '../../hooks/UseInstance';
|
||||||
import { apiUrl } from '../../states/ApiState';
|
import { apiUrl } from '../../states/ApiState';
|
||||||
import { useUserState } from '../../states/UserState';
|
import { useUserState } from '../../states/UserState';
|
||||||
@ -82,6 +83,7 @@ export default function StockDetail() {
|
|||||||
|
|
||||||
const detailsPanel = useMemo(() => {
|
const detailsPanel = useMemo(() => {
|
||||||
let data = stockitem;
|
let data = stockitem;
|
||||||
|
let part = stockitem?.part_detail ?? {};
|
||||||
|
|
||||||
data.available_stock = Math.max(0, data.quantity - data.allocated);
|
data.available_stock = Math.max(0, data.quantity - data.allocated);
|
||||||
|
|
||||||
@ -99,14 +101,16 @@ export default function StockDetail() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'status',
|
name: 'status',
|
||||||
type: 'text',
|
type: 'status',
|
||||||
label: t`Stock Status`
|
label: t`Stock Status`,
|
||||||
|
model: ModelType.stockitem
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'text',
|
type: 'text',
|
||||||
name: 'tests',
|
name: 'tests',
|
||||||
label: `Completed Tests`,
|
label: `Completed Tests`,
|
||||||
icon: 'progress'
|
icon: 'progress',
|
||||||
|
hidden: !part?.trackable
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'text',
|
type: 'text',
|
||||||
@ -174,6 +178,7 @@ export default function StockDetail() {
|
|||||||
|
|
||||||
return text;
|
return text;
|
||||||
},
|
},
|
||||||
|
icon: 'stock',
|
||||||
model: ModelType.stockitem,
|
model: ModelType.stockitem,
|
||||||
hidden: !stockitem.belongs_to
|
hidden: !stockitem.belongs_to
|
||||||
},
|
},
|
||||||
@ -182,7 +187,17 @@ export default function StockDetail() {
|
|||||||
name: 'consumed_by',
|
name: 'consumed_by',
|
||||||
label: t`Consumed By`,
|
label: t`Consumed By`,
|
||||||
model: ModelType.build,
|
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',
|
type: 'link',
|
||||||
@ -192,6 +207,13 @@ export default function StockDetail() {
|
|||||||
hidden: !stockitem.sales_order,
|
hidden: !stockitem.sales_order,
|
||||||
icon: 'sales_orders',
|
icon: 'sales_orders',
|
||||||
model_field: 'reference'
|
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' },
|
{ name: t`Stock`, url: '/stock' },
|
||||||
...(stockitem.location_path ?? []).map((l: any) => ({
|
...(stockitem.location_path ?? []).map((l: any) => ({
|
||||||
name: l.name,
|
name: l.name,
|
||||||
url: apiUrl(ApiEndpoints.stock_location_list, l.pk)
|
url: getDetailUrl(ModelType.stocklocation, l.pk)
|
||||||
}))
|
}))
|
||||||
],
|
],
|
||||||
[stockitem]
|
[stockitem]
|
||||||
|
@ -180,6 +180,12 @@ export function FilterSelectDrawer({
|
|||||||
setAddFilter(false);
|
setAddFilter(false);
|
||||||
}, [tableState.activeFilters]);
|
}, [tableState.activeFilters]);
|
||||||
|
|
||||||
|
const hasFilters: boolean = useMemo(() => {
|
||||||
|
let filters = tableState?.activeFilters ?? [];
|
||||||
|
|
||||||
|
return filters.length > 0;
|
||||||
|
}, [tableState.activeFilters]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Drawer
|
<Drawer
|
||||||
size="sm"
|
size="sm"
|
||||||
@ -190,13 +196,11 @@ export function FilterSelectDrawer({
|
|||||||
title={<StylishText size="lg">{t`Table Filters`}</StylishText>}
|
title={<StylishText size="lg">{t`Table Filters`}</StylishText>}
|
||||||
>
|
>
|
||||||
<Stack spacing="xs">
|
<Stack spacing="xs">
|
||||||
{tableState.activeFilters &&
|
{hasFilters &&
|
||||||
tableState.activeFilters?.map((f) => (
|
tableState.activeFilters?.map((f) => (
|
||||||
<FilterItem key={f.name} flt={f} tableState={tableState} />
|
<FilterItem key={f.name} flt={f} tableState={tableState} />
|
||||||
))}
|
))}
|
||||||
{tableState.activeFilters && tableState.activeFilters.length > 0 && (
|
{hasFilters && <Divider />}
|
||||||
<Divider />
|
|
||||||
)}
|
|
||||||
{addFilter && (
|
{addFilter && (
|
||||||
<Stack spacing="xs">
|
<Stack spacing="xs">
|
||||||
<FilterAddGroup
|
<FilterAddGroup
|
||||||
|
Loading…
x
Reference in New Issue
Block a user