mirror of
https://github.com/inventree/InvenTree.git
synced 2025-12-16 17:28:11 +00:00
Refactor segmented panels
This commit is contained in:
@@ -8,7 +8,7 @@ export type PanelType = {
|
|||||||
label: string;
|
label: string;
|
||||||
controls?: ReactNode;
|
controls?: ReactNode;
|
||||||
icon?: ReactNode;
|
icon?: ReactNode;
|
||||||
content: ReactNode;
|
content?: ReactNode;
|
||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
showHeadline?: boolean;
|
showHeadline?: boolean;
|
||||||
|
|||||||
53
src/frontend/src/components/panels/SegmentedControlPanel.tsx
Normal file
53
src/frontend/src/components/panels/SegmentedControlPanel.tsx
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import SegmentedIconControl from '../buttons/SegmentedIconControl';
|
||||||
|
import type { PanelType } from './Panel';
|
||||||
|
|
||||||
|
export type SegmentedControlPanelSelection = {
|
||||||
|
value: string;
|
||||||
|
label: string;
|
||||||
|
icon: React.ReactNode;
|
||||||
|
content: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface SegmentedPanelType extends PanelType {
|
||||||
|
options: SegmentedControlPanelSelection[];
|
||||||
|
selection: string;
|
||||||
|
onChange: (value: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a panel which can be used to display multiple options,
|
||||||
|
* based on a built-in segmented control.
|
||||||
|
*/
|
||||||
|
export default function SegmentedControlPanel(
|
||||||
|
props: SegmentedPanelType
|
||||||
|
): PanelType {
|
||||||
|
// Extract the content based on the selection
|
||||||
|
let content = null;
|
||||||
|
|
||||||
|
for (const option of props.options) {
|
||||||
|
if (option.value === props.selection) {
|
||||||
|
content = option.content;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (content === null && props.options.length > 0) {
|
||||||
|
content = props.options[0].content;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...props,
|
||||||
|
content: content,
|
||||||
|
controls: (
|
||||||
|
<SegmentedIconControl
|
||||||
|
value={props.selection}
|
||||||
|
onChange={props.onChange}
|
||||||
|
data={props.options.map((option: any) => ({
|
||||||
|
value: option.value,
|
||||||
|
label: option.label,
|
||||||
|
icon: option.icon
|
||||||
|
}))}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -7,12 +7,12 @@ import { ModelType } from '@lib/enums/ModelType';
|
|||||||
import { UserRoles } from '@lib/enums/Roles';
|
import { UserRoles } from '@lib/enums/Roles';
|
||||||
import type { TableFilter } from '@lib/types/Filters';
|
import type { TableFilter } from '@lib/types/Filters';
|
||||||
import { useLocalStorage } from '@mantine/hooks';
|
import { useLocalStorage } from '@mantine/hooks';
|
||||||
import SegmentedIconControl from '../../components/buttons/SegmentedIconControl';
|
|
||||||
import OrderCalendar from '../../components/calendar/OrderCalendar';
|
import OrderCalendar from '../../components/calendar/OrderCalendar';
|
||||||
import PermissionDenied from '../../components/errors/PermissionDenied';
|
import PermissionDenied from '../../components/errors/PermissionDenied';
|
||||||
import { PageDetail } from '../../components/nav/PageDetail';
|
import { PageDetail } from '../../components/nav/PageDetail';
|
||||||
import type { PanelType } from '../../components/panels/Panel';
|
import type { PanelType } from '../../components/panels/Panel';
|
||||||
import { PanelGroup } from '../../components/panels/PanelGroup';
|
import { PanelGroup } from '../../components/panels/PanelGroup';
|
||||||
|
import SegmentedControlPanel from '../../components/panels/SegmentedControlPanel';
|
||||||
import { useGlobalSettingsState } from '../../states/SettingsStates';
|
import { useGlobalSettingsState } from '../../states/SettingsStates';
|
||||||
import { useUserState } from '../../states/UserState';
|
import { useUserState } from '../../states/UserState';
|
||||||
import { PartCategoryFilter } from '../../tables/Filter';
|
import { PartCategoryFilter } from '../../tables/Filter';
|
||||||
@@ -43,20 +43,6 @@ function BuildOrderCalendar() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function BuildOverview({
|
|
||||||
view
|
|
||||||
}: {
|
|
||||||
view: string;
|
|
||||||
}) {
|
|
||||||
switch (view) {
|
|
||||||
case 'calendar':
|
|
||||||
return <BuildOrderCalendar />;
|
|
||||||
case 'table':
|
|
||||||
default:
|
|
||||||
return <BuildOrderTable />;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build Order index page
|
* Build Order index page
|
||||||
*/
|
*/
|
||||||
@@ -64,34 +50,35 @@ export default function BuildIndex() {
|
|||||||
const user = useUserState();
|
const user = useUserState();
|
||||||
|
|
||||||
const [buildOrderView, setBuildOrderView] = useLocalStorage<string>({
|
const [buildOrderView, setBuildOrderView] = useLocalStorage<string>({
|
||||||
key: 'buildOrderView',
|
key: 'build-order-view',
|
||||||
defaultValue: 'table'
|
defaultValue: 'table'
|
||||||
});
|
});
|
||||||
|
|
||||||
const panels: PanelType[] = useMemo(() => {
|
const panels: PanelType[] = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
{
|
SegmentedControlPanel({
|
||||||
name: 'buildorders',
|
name: 'buildorder',
|
||||||
label: t`Build Orders`,
|
label: t`Build Orders`,
|
||||||
content: <BuildOverview view={buildOrderView} />,
|
|
||||||
icon: <IconTools />,
|
icon: <IconTools />,
|
||||||
controls: (
|
selection: buildOrderView,
|
||||||
<SegmentedIconControl
|
onChange: setBuildOrderView,
|
||||||
value={buildOrderView}
|
options: [
|
||||||
onChange={setBuildOrderView}
|
{
|
||||||
data={[
|
value: 'table',
|
||||||
{ value: 'table', label: t`Table View`, icon: <IconTable /> },
|
label: t`Table View`,
|
||||||
|
icon: <IconTable />,
|
||||||
|
content: <BuildOrderTable />
|
||||||
|
},
|
||||||
{
|
{
|
||||||
value: 'calendar',
|
value: 'calendar',
|
||||||
label: t`Calendar View`,
|
label: t`Calendar View`,
|
||||||
icon: <IconCalendar />
|
icon: <IconCalendar />,
|
||||||
}
|
content: <BuildOrderCalendar />
|
||||||
]}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
];
|
];
|
||||||
}, [buildOrderView, setBuildOrderView]);
|
}, [user, buildOrderView]);
|
||||||
|
|
||||||
if (!user.isLoggedIn() || !user.hasViewRole(UserRoles.build)) {
|
if (!user.isLoggedIn() || !user.hasViewRole(UserRoles.build)) {
|
||||||
return <PermissionDenied />;
|
return <PermissionDenied />;
|
||||||
|
|||||||
@@ -14,68 +14,55 @@ import { useMemo } from 'react';
|
|||||||
import { ModelType } from '@lib/enums/ModelType';
|
import { ModelType } from '@lib/enums/ModelType';
|
||||||
import { UserRoles } from '@lib/enums/Roles';
|
import { UserRoles } from '@lib/enums/Roles';
|
||||||
import { useLocalStorage } from '@mantine/hooks';
|
import { useLocalStorage } from '@mantine/hooks';
|
||||||
import SegmentedIconControl from '../../components/buttons/SegmentedIconControl';
|
|
||||||
import OrderCalendar from '../../components/calendar/OrderCalendar';
|
import OrderCalendar from '../../components/calendar/OrderCalendar';
|
||||||
import PermissionDenied from '../../components/errors/PermissionDenied';
|
import PermissionDenied from '../../components/errors/PermissionDenied';
|
||||||
import { PageDetail } from '../../components/nav/PageDetail';
|
import { PageDetail } from '../../components/nav/PageDetail';
|
||||||
import { PanelGroup } from '../../components/panels/PanelGroup';
|
import { PanelGroup } from '../../components/panels/PanelGroup';
|
||||||
|
import SegmentedControlPanel from '../../components/panels/SegmentedControlPanel';
|
||||||
import { useUserState } from '../../states/UserState';
|
import { useUserState } from '../../states/UserState';
|
||||||
import { CompanyTable } from '../../tables/company/CompanyTable';
|
import { CompanyTable } from '../../tables/company/CompanyTable';
|
||||||
import { ManufacturerPartTable } from '../../tables/purchasing/ManufacturerPartTable';
|
import { ManufacturerPartTable } from '../../tables/purchasing/ManufacturerPartTable';
|
||||||
import { PurchaseOrderTable } from '../../tables/purchasing/PurchaseOrderTable';
|
import { PurchaseOrderTable } from '../../tables/purchasing/PurchaseOrderTable';
|
||||||
import { SupplierPartTable } from '../../tables/purchasing/SupplierPartTable';
|
import { SupplierPartTable } from '../../tables/purchasing/SupplierPartTable';
|
||||||
|
|
||||||
function PurchaseOrderOverview({
|
|
||||||
view
|
|
||||||
}: {
|
|
||||||
view: string;
|
|
||||||
}) {
|
|
||||||
switch (view) {
|
|
||||||
case 'calendar':
|
|
||||||
return (
|
|
||||||
<OrderCalendar
|
|
||||||
model={ModelType.purchaseorder}
|
|
||||||
role={UserRoles.purchase_order}
|
|
||||||
params={{ outstanding: true }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case 'table':
|
|
||||||
default:
|
|
||||||
return <PurchaseOrderTable />;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function PurchasingIndex() {
|
export default function PurchasingIndex() {
|
||||||
const user = useUserState();
|
const user = useUserState();
|
||||||
|
|
||||||
const [purchaseOrderView, setpurchaseOrderView] = useLocalStorage<string>({
|
const [purchaseOrderView, setPurchaseOrderView] = useLocalStorage<string>({
|
||||||
key: 'purchaseOrderView',
|
key: 'purchase-order-view',
|
||||||
defaultValue: 'table'
|
defaultValue: 'table'
|
||||||
});
|
});
|
||||||
|
|
||||||
const panels = useMemo(() => {
|
const panels = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
{
|
SegmentedControlPanel({
|
||||||
name: 'purchaseorders',
|
name: 'purchaseorders',
|
||||||
label: t`Purchase Orders`,
|
label: t`Purchase Orders`,
|
||||||
icon: <IconShoppingCart />,
|
icon: <IconShoppingCart />,
|
||||||
hidden: !user.hasViewRole(UserRoles.purchase_order),
|
hidden: !user.hasViewRole(UserRoles.purchase_order),
|
||||||
content: <PurchaseOrderOverview view={purchaseOrderView} />,
|
selection: purchaseOrderView,
|
||||||
controls: (
|
onChange: setPurchaseOrderView,
|
||||||
<SegmentedIconControl
|
options: [
|
||||||
value={purchaseOrderView}
|
{
|
||||||
onChange={setpurchaseOrderView}
|
value: 'table',
|
||||||
data={[
|
label: t`Table View`,
|
||||||
{ value: 'table', label: t`Table View`, icon: <IconTable /> },
|
icon: <IconTable />,
|
||||||
|
content: <PurchaseOrderTable />
|
||||||
|
},
|
||||||
{
|
{
|
||||||
value: 'calendar',
|
value: 'calendar',
|
||||||
label: t`Calendar View`,
|
label: t`Calendar View`,
|
||||||
icon: <IconCalendar />
|
icon: <IconCalendar />,
|
||||||
}
|
content: (
|
||||||
]}
|
<OrderCalendar
|
||||||
|
model={ModelType.purchaseorder}
|
||||||
|
role={UserRoles.purchase_order}
|
||||||
|
params={{ outstanding: true }}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
}
|
||||||
|
]
|
||||||
|
}),
|
||||||
{
|
{
|
||||||
name: 'suppliers',
|
name: 'suppliers',
|
||||||
label: t`Suppliers`,
|
label: t`Suppliers`,
|
||||||
|
|||||||
@@ -13,57 +13,17 @@ import { useMemo } from 'react';
|
|||||||
import { ModelType } from '@lib/enums/ModelType';
|
import { ModelType } from '@lib/enums/ModelType';
|
||||||
import { UserRoles } from '@lib/enums/Roles';
|
import { UserRoles } from '@lib/enums/Roles';
|
||||||
import { useLocalStorage } from '@mantine/hooks';
|
import { useLocalStorage } from '@mantine/hooks';
|
||||||
import SegmentedIconControl from '../../components/buttons/SegmentedIconControl';
|
|
||||||
import OrderCalendar from '../../components/calendar/OrderCalendar';
|
import OrderCalendar from '../../components/calendar/OrderCalendar';
|
||||||
import PermissionDenied from '../../components/errors/PermissionDenied';
|
import PermissionDenied from '../../components/errors/PermissionDenied';
|
||||||
import { PageDetail } from '../../components/nav/PageDetail';
|
import { PageDetail } from '../../components/nav/PageDetail';
|
||||||
import { PanelGroup } from '../../components/panels/PanelGroup';
|
import { PanelGroup } from '../../components/panels/PanelGroup';
|
||||||
|
import SegmentedControlPanel from '../../components/panels/SegmentedControlPanel';
|
||||||
import { useUserState } from '../../states/UserState';
|
import { useUserState } from '../../states/UserState';
|
||||||
import { CompanyTable } from '../../tables/company/CompanyTable';
|
import { CompanyTable } from '../../tables/company/CompanyTable';
|
||||||
import { ReturnOrderTable } from '../../tables/sales/ReturnOrderTable';
|
import { ReturnOrderTable } from '../../tables/sales/ReturnOrderTable';
|
||||||
import SalesOrderShipmentTable from '../../tables/sales/SalesOrderShipmentTable';
|
import SalesOrderShipmentTable from '../../tables/sales/SalesOrderShipmentTable';
|
||||||
import { SalesOrderTable } from '../../tables/sales/SalesOrderTable';
|
import { SalesOrderTable } from '../../tables/sales/SalesOrderTable';
|
||||||
|
|
||||||
function SalesOrderOverview({
|
|
||||||
view
|
|
||||||
}: {
|
|
||||||
view: string;
|
|
||||||
}) {
|
|
||||||
switch (view) {
|
|
||||||
case 'calendar':
|
|
||||||
return (
|
|
||||||
<OrderCalendar
|
|
||||||
model={ModelType.salesorder}
|
|
||||||
role={UserRoles.sales_order}
|
|
||||||
params={{ outstanding: true }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case 'table':
|
|
||||||
default:
|
|
||||||
return <SalesOrderTable />;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function ReturnOrderOverview({
|
|
||||||
view
|
|
||||||
}: {
|
|
||||||
view: string;
|
|
||||||
}) {
|
|
||||||
switch (view) {
|
|
||||||
case 'calendar':
|
|
||||||
return (
|
|
||||||
<OrderCalendar
|
|
||||||
model={ModelType.returnorder}
|
|
||||||
role={UserRoles.return_order}
|
|
||||||
params={{ outstanding: true }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case 'table':
|
|
||||||
default:
|
|
||||||
return <ReturnOrderTable />;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function SalesIndex() {
|
export default function SalesIndex() {
|
||||||
const user = useUserState();
|
const user = useUserState();
|
||||||
|
|
||||||
@@ -79,27 +39,34 @@ export default function SalesIndex() {
|
|||||||
|
|
||||||
const panels = useMemo(() => {
|
const panels = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
{
|
SegmentedControlPanel({
|
||||||
name: 'salesorders',
|
name: 'salesorders',
|
||||||
label: t`Sales Orders`,
|
label: t`Sales Orders`,
|
||||||
icon: <IconTruckDelivery />,
|
icon: <IconTruckDelivery />,
|
||||||
content: <SalesOrderOverview view={salesOrderView} />,
|
hidden: !user.hasViewRole(UserRoles.sales_order),
|
||||||
controls: (
|
selection: salesOrderView,
|
||||||
<SegmentedIconControl
|
onChange: setSalesOrderView,
|
||||||
value={salesOrderView}
|
options: [
|
||||||
onChange={setSalesOrderView}
|
{
|
||||||
data={[
|
value: 'table',
|
||||||
{ value: 'table', label: t`Table View`, icon: <IconTable /> },
|
label: t`Table View`,
|
||||||
|
icon: <IconTable />,
|
||||||
|
content: <SalesOrderTable />
|
||||||
|
},
|
||||||
{
|
{
|
||||||
value: 'calendar',
|
value: 'calendar',
|
||||||
label: t`Calendar View`,
|
label: t`Calendar View`,
|
||||||
icon: <IconCalendar />
|
icon: <IconCalendar />,
|
||||||
}
|
content: (
|
||||||
]}
|
<OrderCalendar
|
||||||
|
model={ModelType.returnorder}
|
||||||
|
role={UserRoles.return_order}
|
||||||
|
params={{ outstanding: true }}
|
||||||
/>
|
/>
|
||||||
),
|
)
|
||||||
hidden: !user.hasViewRole(UserRoles.sales_order)
|
}
|
||||||
},
|
]
|
||||||
|
}),
|
||||||
{
|
{
|
||||||
name: 'shipments',
|
name: 'shipments',
|
||||||
label: t`Pending Shipments`,
|
label: t`Pending Shipments`,
|
||||||
@@ -112,27 +79,34 @@ export default function SalesIndex() {
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
SegmentedControlPanel({
|
||||||
name: 'returnorders',
|
name: 'returnorders',
|
||||||
label: t`Return Orders`,
|
label: t`Return Orders`,
|
||||||
icon: <IconTruckReturn />,
|
icon: <IconTruckReturn />,
|
||||||
content: <ReturnOrderOverview view={returnOrderView} />,
|
hidden: !user.hasViewRole(UserRoles.return_order),
|
||||||
controls: (
|
selection: returnOrderView,
|
||||||
<SegmentedIconControl
|
onChange: setReturnOrderView,
|
||||||
value={returnOrderView}
|
options: [
|
||||||
onChange={setReturnOrderView}
|
{
|
||||||
data={[
|
value: 'table',
|
||||||
{ value: 'table', label: t`Table View`, icon: <IconTable /> },
|
label: t`Table View`,
|
||||||
|
icon: <IconTable />,
|
||||||
|
content: <ReturnOrderTable />
|
||||||
|
},
|
||||||
{
|
{
|
||||||
value: 'calendar',
|
value: 'calendar',
|
||||||
label: t`Calendar View`,
|
label: t`Calendar View`,
|
||||||
icon: <IconCalendar />
|
icon: <IconCalendar />,
|
||||||
}
|
content: (
|
||||||
]}
|
<OrderCalendar
|
||||||
|
model={ModelType.returnorder}
|
||||||
|
role={UserRoles.return_order}
|
||||||
|
params={{ outstanding: true }}
|
||||||
/>
|
/>
|
||||||
),
|
)
|
||||||
hidden: !user.hasViewRole(UserRoles.return_order)
|
}
|
||||||
},
|
]
|
||||||
|
}),
|
||||||
{
|
{
|
||||||
name: 'customers',
|
name: 'customers',
|
||||||
label: t`Customers`,
|
label: t`Customers`,
|
||||||
|
|||||||
Reference in New Issue
Block a user