diff --git a/src/backend/InvenTree/plugin/api.py b/src/backend/InvenTree/plugin/api.py
index b898eb2c98..df737d4eab 100644
--- a/src/backend/InvenTree/plugin/api.py
+++ b/src/backend/InvenTree/plugin/api.py
@@ -427,29 +427,47 @@ class PluginPanelList(APIView):
# TODO: Allow plugins to fill this data out
...
- panels = [
- {
- 'plugin': 'myplugin',
- 'name': 'test-plugin',
- 'label': 'My Plugin',
- 'icon': 'part',
- 'content': '
hello world
',
- },
- {
- 'plugin': 'myplugin',
- 'name': 'test-plugin-2',
- 'label': 'My Plugin 2',
- 'icon': 'email',
- 'content': 'hello world 2
',
- },
- {
- 'plugin': 'myplugin',
- 'name': 'test-plugin-3',
- 'label': 'My Plugin 3',
- 'icon': 'website',
- 'content': 'hello world 3
',
- },
- ]
+ user = request.user
+ target_model = request.query_params.get('target_model', None)
+ target_id = request.query_params.get('target_id', None)
+
+ if target_model == 'part' and target_id:
+ panels = [
+ *panels,
+ {
+ 'plugin': 'myplugin',
+ 'name': 'test-plugin',
+ 'label': 'My Plugin',
+ 'icon': 'part',
+ 'content': 'hello world
',
+ },
+ {
+ 'plugin': 'myplugin',
+ 'name': 'test-plugin-2',
+ 'label': 'My Plugin 2',
+ 'icon': 'email',
+ 'content': 'hello world 2
',
+ },
+ {
+ 'plugin': 'myplugin',
+ 'name': 'test-plugin-3',
+ 'label': 'My Plugin 3',
+ 'icon': 'website',
+ 'content': 'hello world 3
',
+ },
+ ]
+
+ if target_model == 'partcategory':
+ panels = [
+ *panels,
+ {
+ 'plugin': 'cat',
+ 'name': 'demo-cat',
+ 'label': 'Custom Category',
+ 'icon': 'customer',
+ 'content': 'This should only appear for a category',
+ },
+ ]
return Response(PluginSerializers.PluginPanelSerializer(panels, many=True).data)
diff --git a/src/frontend/src/pages/part/CategoryDetail.tsx b/src/frontend/src/pages/part/CategoryDetail.tsx
index a94999e396..ab6c7eeaf1 100644
--- a/src/frontend/src/pages/part/CategoryDetail.tsx
+++ b/src/frontend/src/pages/part/CategoryDetail.tsx
@@ -20,7 +20,8 @@ import {
} from '../../components/items/ActionDropdown';
import NavigationTree from '../../components/nav/NavigationTree';
import { PageDetail } from '../../components/nav/PageDetail';
-import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
+import { PanelType } from '../../components/nav/Panel';
+import { PanelGroup } from '../../components/nav/PanelGroup';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
@@ -31,6 +32,7 @@ import {
useEditApiFormModal
} from '../../hooks/UseForm';
import { useInstance } from '../../hooks/UseInstance';
+import { usePluginPanels } from '../../hooks/UsePluginPanels';
import { useUserState } from '../../states/UserState';
import ParametricPartTable from '../../tables/part/ParametricPartTable';
import { PartCategoryTable } from '../../tables/part/PartCategoryTable';
@@ -260,6 +262,15 @@ export default function CategoryDetail({}: {}) {
[category, id]
);
+ const pluginPanels = usePluginPanels({
+ targetModel: ModelType.partcategory,
+ targetId: id
+ });
+
+ const panels: PanelType[] = useMemo(() => {
+ return [...categoryPanels, ...pluginPanels.panels];
+ }, [categoryPanels, pluginPanels]);
+
const breadcrumbs = useMemo(
() => [
{ name: t`Parts`, url: '/part' },
@@ -296,7 +307,7 @@ export default function CategoryDetail({}: {}) {
}}
actions={categoryActions}
/>
-
+
>
);