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