mirror of
https://github.com/inventree/InvenTree.git
synced 2026-04-25 04:23:33 +00:00
refactor(frontend): make plugin support for panels more generic (#11787)
* feat(frontend): add more generic plugin support on PanelGroup * refactor exsisting use cases * add plugin panel support to StockLocation closes https://github.com/inventree/InvenTree/issues/11782 * stop re-using model field * re-order types * add panel support for core * change keys see https://github.com/inventree/InvenTree/pull/11787#discussion_r3127410867
This commit is contained in:
@@ -38,3 +38,16 @@ export enum ModelType {
|
||||
selectionentry = 'selectionentry',
|
||||
error = 'error'
|
||||
}
|
||||
|
||||
export enum PluginPanelKey {
|
||||
// settings / admin
|
||||
admincenter = 'admincenter',
|
||||
systemsettings = 'systemsettings',
|
||||
usersettings = 'usersettings',
|
||||
// generic
|
||||
core = 'core',
|
||||
// landing pages
|
||||
purchasing = 'purchasing',
|
||||
sales = 'sales',
|
||||
manufacturing = 'manufacturing'
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ import {
|
||||
} from 'react-router-dom';
|
||||
|
||||
import { Boundary } from '@lib/components/Boundary';
|
||||
import type { ModelType } from '@lib/enums/ModelType';
|
||||
import type { ModelType, PluginPanelKey } from '@lib/enums/ModelType';
|
||||
import { identifierString } from '@lib/functions/Conversion';
|
||||
import { cancelEvent } from '@lib/functions/Events';
|
||||
import { eventModified, getBaseUrl } from '@lib/functions/Navigation';
|
||||
@@ -61,6 +61,8 @@ import * as classes from './PanelGroup.css';
|
||||
* @param selectedPanel - The currently selected panel
|
||||
* @param onPanelChange - Callback when the active panel changes
|
||||
* @param collapsible - If true, the panel group can be collapsed (defaults to true)
|
||||
* @param pluginPanelWithoutId - If true, the panel group will load plugin panels even with no id provided
|
||||
* @param pluginPanelKey - The plugin panel key to use when loading plugin panels for this group from the backend
|
||||
*/
|
||||
export type PanelProps = {
|
||||
pageKey: string;
|
||||
@@ -68,11 +70,13 @@ export type PanelProps = {
|
||||
groups?: PanelGroupType[];
|
||||
instance?: any;
|
||||
reloadInstance?: () => void;
|
||||
model?: ModelType | string;
|
||||
model?: ModelType;
|
||||
id?: number | null;
|
||||
selectedPanel?: string;
|
||||
onPanelChange?: (panel: string) => void;
|
||||
collapsible?: boolean;
|
||||
pluginPanelWithoutId?: boolean;
|
||||
pluginPanelKey?: PluginPanelKey;
|
||||
};
|
||||
|
||||
function BasePanelGroup({
|
||||
@@ -85,7 +89,9 @@ function BasePanelGroup({
|
||||
instance,
|
||||
model,
|
||||
id,
|
||||
collapsible = true
|
||||
collapsible = true,
|
||||
pluginPanelWithoutId = false,
|
||||
pluginPanelKey
|
||||
}: Readonly<PanelProps>): ReactNode {
|
||||
const localState = useLocalState();
|
||||
const location = useLocation();
|
||||
@@ -96,9 +102,17 @@ function BasePanelGroup({
|
||||
const [expanded, setExpanded] = useState<boolean>(true);
|
||||
|
||||
// Hook to load plugins for this panel
|
||||
const _pluginId = useMemo(() => {
|
||||
if (id === undefined && pluginPanelWithoutId) return null;
|
||||
return id;
|
||||
}, [id, pluginPanelWithoutId]);
|
||||
const _pluginKey = useMemo(() => {
|
||||
if (model === undefined && pluginPanelWithoutId) return pluginPanelKey;
|
||||
return model;
|
||||
}, [model, pluginPanelWithoutId, pluginPanelKey]);
|
||||
const pluginPanelSet = usePluginPanels({
|
||||
id: id,
|
||||
model: model,
|
||||
id: _pluginId,
|
||||
model: _pluginKey,
|
||||
instance: instance,
|
||||
reloadFunc: reloadInstance
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@ import { type UseQueryResult, useQuery } from '@tanstack/react-query';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { ApiEndpoints } from '@lib/enums/ApiEndpoints';
|
||||
import type { ModelType } from '@lib/enums/ModelType';
|
||||
import type { ModelType, PluginPanelKey } from '@lib/enums/ModelType';
|
||||
import { apiUrl } from '@lib/functions/Api';
|
||||
import type { InvenTreePluginContext } from '@lib/types/Plugins';
|
||||
import { api } from '../App';
|
||||
@@ -39,7 +39,7 @@ export function usePluginPanels({
|
||||
}: {
|
||||
instance?: any;
|
||||
reloadFunc?: () => void;
|
||||
model?: ModelType | string;
|
||||
model?: ModelType | PluginPanelKey;
|
||||
id?: string | number | null;
|
||||
}): PluginPanelSet {
|
||||
const globalSettings = useGlobalSettingsState();
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
} from '@tabler/icons-react';
|
||||
import { lazy, useMemo } from 'react';
|
||||
|
||||
import { PluginPanelKey } from '@lib/enums/ModelType';
|
||||
import { UserRoles } from '@lib/enums/Roles';
|
||||
import PermissionDenied from '../../../../components/errors/PermissionDenied';
|
||||
import PageTitle from '../../../../components/nav/PageTitle';
|
||||
@@ -303,8 +304,8 @@ export default function AdminCenter() {
|
||||
panels={adminCenterPanels}
|
||||
groups={grouping}
|
||||
collapsible={true}
|
||||
model='admincenter'
|
||||
id={null}
|
||||
pluginPanelWithoutId
|
||||
pluginPanelKey={PluginPanelKey.admincenter}
|
||||
/>
|
||||
</Stack>
|
||||
) : (
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
} from '@tabler/icons-react';
|
||||
import { lazy, useMemo } from 'react';
|
||||
|
||||
import { PluginPanelKey } from '@lib/enums/ModelType';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import PermissionDenied from '../../../components/errors/PermissionDenied';
|
||||
import PageTitle from '../../../components/nav/PageTitle';
|
||||
@@ -376,8 +377,8 @@ export default function SystemSettings() {
|
||||
<PanelGroup
|
||||
pageKey='system-settings'
|
||||
panels={systemSettingsPanels}
|
||||
model='systemsettings'
|
||||
id={null}
|
||||
pluginPanelWithoutId
|
||||
pluginPanelKey={PluginPanelKey.systemsettings}
|
||||
/>
|
||||
</Stack>
|
||||
) : (
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
} from '@tabler/icons-react';
|
||||
import { lazy, useMemo } from 'react';
|
||||
|
||||
import { PluginPanelKey } from '@lib/enums/ModelType';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import PageTitle from '../../../components/nav/PageTitle';
|
||||
import { SettingsHeader } from '../../../components/nav/SettingsHeader';
|
||||
@@ -154,8 +155,8 @@ export default function UserSettings() {
|
||||
<PanelGroup
|
||||
pageKey='user-settings'
|
||||
panels={userSettingsPanels}
|
||||
model='usersettings'
|
||||
id={null}
|
||||
pluginPanelWithoutId
|
||||
pluginPanelKey={PluginPanelKey.usersettings}
|
||||
/>
|
||||
</Stack>
|
||||
</>
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
} from '@tabler/icons-react';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { ModelType } from '@lib/enums/ModelType';
|
||||
import { ModelType, PluginPanelKey } from '@lib/enums/ModelType';
|
||||
import { UserRoles } from '@lib/enums/Roles';
|
||||
import type { TableFilter } from '@lib/types/Filters';
|
||||
import { useLocalStorage } from '@mantine/hooks';
|
||||
@@ -102,8 +102,8 @@ export default function BuildIndex() {
|
||||
<PanelGroup
|
||||
pageKey='build-index'
|
||||
panels={panels}
|
||||
model='manufacturing'
|
||||
id={null}
|
||||
pluginPanelWithoutId
|
||||
pluginPanelKey={PluginPanelKey.manufacturing}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Stack } from '@mantine/core';
|
||||
import { IconUser, IconUsersGroup } from '@tabler/icons-react';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { PluginPanelKey } from '@lib/enums/ModelType';
|
||||
import PermissionDenied from '../../components/errors/PermissionDenied';
|
||||
import { PageDetail } from '../../components/nav/PageDetail';
|
||||
import { PanelGroup } from '../../components/panels/PanelGroup';
|
||||
@@ -44,7 +45,12 @@ export default function CoreIndex() {
|
||||
return (
|
||||
<Stack>
|
||||
<PageDetail title={t`System Overview`} />
|
||||
<PanelGroup pageKey='core-index' panels={panels} id={null} />
|
||||
<PanelGroup
|
||||
pageKey='core-index'
|
||||
panels={panels}
|
||||
pluginPanelWithoutId
|
||||
pluginPanelKey={PluginPanelKey.core}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
} from '@tabler/icons-react';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { ModelType } from '@lib/enums/ModelType';
|
||||
import { ModelType, PluginPanelKey } from '@lib/enums/ModelType';
|
||||
import { UserRoles } from '@lib/enums/Roles';
|
||||
import { useLocalStorage } from '@mantine/hooks';
|
||||
import OrderCalendar from '../../components/calendar/OrderCalendar';
|
||||
@@ -215,8 +215,8 @@ export default function PurchasingIndex() {
|
||||
<PanelGroup
|
||||
pageKey='purchasing-index'
|
||||
panels={panels}
|
||||
model={'purchasing'}
|
||||
id={null}
|
||||
pluginPanelWithoutId
|
||||
pluginPanelKey={PluginPanelKey.purchasing}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
} from '@tabler/icons-react';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { ModelType } from '@lib/enums/ModelType';
|
||||
import { ModelType, PluginPanelKey } from '@lib/enums/ModelType';
|
||||
import { UserRoles } from '@lib/enums/Roles';
|
||||
import { useLocalStorage } from '@mantine/hooks';
|
||||
import OrderCalendar from '../../components/calendar/OrderCalendar';
|
||||
@@ -170,8 +170,8 @@ export default function SalesIndex() {
|
||||
<PanelGroup
|
||||
pageKey='sales-index'
|
||||
panels={panels}
|
||||
model={'sales'}
|
||||
id={null}
|
||||
pluginPanelWithoutId
|
||||
pluginPanelKey={PluginPanelKey.sales}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
@@ -481,6 +481,7 @@ export default function Stock() {
|
||||
reloadInstance={refreshInstance}
|
||||
id={location?.pk}
|
||||
instance={location}
|
||||
pluginPanelWithoutId
|
||||
/>
|
||||
</Stack>
|
||||
{stockAdjustActions.modals.map((modal) => modal.modal)}
|
||||
|
||||
Reference in New Issue
Block a user