mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Add some dummy data for the plugin panels
This commit is contained in:
parent
15ebbb6f04
commit
299839312f
@ -424,8 +424,33 @@ class PluginPanelList(APIView):
|
|||||||
|
|
||||||
# Extract all plugins from the registry which provide custom panels
|
# Extract all plugins from the registry which provide custom panels
|
||||||
for _plugin in registry.with_mixin('panel', active=True):
|
for _plugin in registry.with_mixin('panel', active=True):
|
||||||
|
# TODO: Allow plugins to fill this data out
|
||||||
...
|
...
|
||||||
|
|
||||||
|
panels = [
|
||||||
|
{
|
||||||
|
'plugin': 'myplugin',
|
||||||
|
'name': 'test-plugin',
|
||||||
|
'label': 'My Plugin',
|
||||||
|
'icon': 'part',
|
||||||
|
'content': '<div>hello world</div>',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'plugin': 'myplugin',
|
||||||
|
'name': 'test-plugin-2',
|
||||||
|
'label': 'My Plugin 2',
|
||||||
|
'icon': 'email',
|
||||||
|
'content': '<div>hello world 2</div>',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'plugin': 'myplugin',
|
||||||
|
'name': 'test-plugin-3',
|
||||||
|
'label': 'My Plugin 3',
|
||||||
|
'icon': 'website',
|
||||||
|
'content': '<div>hello world 3</div>',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
return Response(PluginSerializers.PluginPanelSerializer(panels, many=True).data)
|
return Response(PluginSerializers.PluginPanelSerializer(panels, many=True).data)
|
||||||
|
|
||||||
|
|
||||||
@ -437,7 +462,7 @@ plugin_api_urls = [
|
|||||||
'plugins/',
|
'plugins/',
|
||||||
include([
|
include([
|
||||||
path(
|
path(
|
||||||
'panel/',
|
'panels/',
|
||||||
include([
|
include([
|
||||||
path('', PluginPanelList.as_view(), name='api-plugin-panel-list')
|
path('', PluginPanelList.as_view(), name='api-plugin-panel-list')
|
||||||
]),
|
]),
|
||||||
|
@ -311,9 +311,10 @@ class PluginPanelSerializer(serializers.Serializer):
|
|||||||
class Meta:
|
class Meta:
|
||||||
"""Meta for serializer."""
|
"""Meta for serializer."""
|
||||||
|
|
||||||
fields = ['plugin', 'title', 'description', 'icon']
|
fields = ['plugin', 'name', 'label', 'icon']
|
||||||
|
|
||||||
plugin = serializers.CharField(label=_('Plugin Key'))
|
plugin = serializers.CharField(label=_('Plugin Key'))
|
||||||
title = serializers.CharField(label=_('Panel Title'))
|
name = serializers.CharField(label=_('Panel Name'))
|
||||||
description = serializers.CharField(label=_('Panel Description'))
|
label = serializers.CharField(label=_('Panel Label'))
|
||||||
icon = serializers.CharField(label=_('Panel Icon'))
|
icon = serializers.CharField(label=_('Panel Icon'))
|
||||||
|
content = serializers.CharField(label=_('Panel Content'))
|
||||||
|
@ -144,6 +144,7 @@ export enum ApiEndpoints {
|
|||||||
plugin_reload = 'plugins/reload/',
|
plugin_reload = 'plugins/reload/',
|
||||||
plugin_activate = 'plugins/:key/activate/',
|
plugin_activate = 'plugins/:key/activate/',
|
||||||
plugin_uninstall = 'plugins/:key/uninstall/',
|
plugin_uninstall = 'plugins/:key/uninstall/',
|
||||||
|
plugin_panel_list = 'plugins/panels/',
|
||||||
|
|
||||||
// Machine API endpoints
|
// Machine API endpoints
|
||||||
machine_types_list = 'machine/types/',
|
machine_types_list = 'machine/types/',
|
||||||
|
@ -50,6 +50,7 @@ import {
|
|||||||
IconPaperclip,
|
IconPaperclip,
|
||||||
IconPhone,
|
IconPhone,
|
||||||
IconPhoto,
|
IconPhoto,
|
||||||
|
IconPlug,
|
||||||
IconPoint,
|
IconPoint,
|
||||||
IconPrinter,
|
IconPrinter,
|
||||||
IconProgressCheck,
|
IconProgressCheck,
|
||||||
@ -199,7 +200,8 @@ const icons = {
|
|||||||
destination: IconFlag,
|
destination: IconFlag,
|
||||||
repeat_destination: IconFlagShare,
|
repeat_destination: IconFlagShare,
|
||||||
unlink: IconUnlink,
|
unlink: IconUnlink,
|
||||||
success: IconCircleCheck
|
success: IconCircleCheck,
|
||||||
|
plugin: IconPlug
|
||||||
};
|
};
|
||||||
|
|
||||||
export type InvenTreeIconType = keyof typeof icons;
|
export type InvenTreeIconType = keyof typeof icons;
|
||||||
|
@ -1,58 +1,70 @@
|
|||||||
|
import { t } from '@lingui/macro';
|
||||||
|
import { Alert, Text } from '@mantine/core';
|
||||||
import { useTimeout } from '@mantine/hooks';
|
import { useTimeout } from '@mantine/hooks';
|
||||||
import { Icon24Hours } from '@tabler/icons-react';
|
import { Icon24Hours } from '@tabler/icons-react';
|
||||||
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { ReactNode, useEffect, useMemo, useState } from 'react';
|
import { ReactNode, useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
|
import { api } from '../App';
|
||||||
import { PanelType } from '../components/nav/Panel';
|
import { PanelType } from '../components/nav/Panel';
|
||||||
|
import { ApiEndpoints } from '../enums/ApiEndpoints';
|
||||||
|
import { identifierString } from '../functions/conversion';
|
||||||
|
import { InvenTreeIcon } from '../functions/icons';
|
||||||
|
import { apiUrl } from '../states/ApiState';
|
||||||
|
|
||||||
export interface PluginPanelState extends PanelType {
|
export type PluginPanelState = {
|
||||||
pluginKey: string;
|
panels: PanelType[];
|
||||||
targetType: string;
|
};
|
||||||
targetId?: string | number | null;
|
|
||||||
|
// Placeholder content for a panel with no content
|
||||||
|
function PanelNoContent() {
|
||||||
|
return (
|
||||||
|
<Alert color="red" title={t`No Content`}>
|
||||||
|
<Text>{t`No content provided for this plugin`}</Text>
|
||||||
|
</Alert>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function usePluginPanel({
|
export function usePluginPanels({
|
||||||
pluginKey,
|
|
||||||
panelName,
|
|
||||||
targetModel,
|
targetModel,
|
||||||
targetId
|
targetId
|
||||||
}: {
|
}: {
|
||||||
pluginKey: string;
|
|
||||||
panelName: string;
|
|
||||||
targetModel: string;
|
targetModel: string;
|
||||||
targetId?: string | number | null;
|
targetId?: string | number | null;
|
||||||
}): PluginPanelState {
|
}): PluginPanelState {
|
||||||
// TODO: Query to fetch the "content" for the plugin
|
const { isFetching, data } = useQuery({
|
||||||
|
queryKey: [targetModel, targetId],
|
||||||
|
queryFn: () => {
|
||||||
|
return api
|
||||||
|
.get(apiUrl(ApiEndpoints.plugin_panel_list), {
|
||||||
|
params: {
|
||||||
|
target_model: targetModel,
|
||||||
|
target_id: targetId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((response: any) => response.data)
|
||||||
|
.catch((error: any) => {
|
||||||
|
console.error('Failed to fetch plugin panels:', error);
|
||||||
|
return [];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const [loaded, setLoaded] = useState<boolean>(false);
|
const panels: PanelType[] = useMemo(() => {
|
||||||
|
return (
|
||||||
const { start } = useTimeout(() => setLoaded(true), 5000);
|
data?.map((panel: any) => {
|
||||||
|
const pluginKey = panel.plugin || 'plugin';
|
||||||
useEffect(() => {
|
return {
|
||||||
start();
|
name: identifierString(`${pluginKey}-${panel.name}`),
|
||||||
console.log('starting timer!');
|
label: panel.label || t`Plugin Panel`,
|
||||||
}, []);
|
icon: <InvenTreeIcon icon={panel.icon ?? 'plugin'} />,
|
||||||
|
content: panel.content || <PanelNoContent />
|
||||||
const content = useMemo(() => {
|
};
|
||||||
return loaded ? (
|
}) ?? []
|
||||||
'plugin content loaded!'
|
|
||||||
) : (
|
|
||||||
<div>
|
|
||||||
<p>Plugin content goes here...</p>
|
|
||||||
<p>Plugin Key: {pluginKey}</p>
|
|
||||||
<p>Panel Name: {panelName}</p>
|
|
||||||
<p>Target Model: {targetModel}</p>
|
|
||||||
<p>Target ID: {targetId}</p>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}, [loaded, pluginKey, panelName, targetModel, targetId]);
|
}, [data]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
content: content,
|
panels: panels
|
||||||
name: panelName,
|
|
||||||
pluginKey: pluginKey,
|
|
||||||
targetType: targetModel,
|
|
||||||
targetId: targetId,
|
|
||||||
label: 'A plugin panel',
|
|
||||||
icon: <Icon24Hours />
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,8 @@ import {
|
|||||||
import { PlaceholderPanel } from '../../components/items/Placeholder';
|
import { PlaceholderPanel } from '../../components/items/Placeholder';
|
||||||
import NavigationTree from '../../components/nav/NavigationTree';
|
import NavigationTree from '../../components/nav/NavigationTree';
|
||||||
import { PageDetail } from '../../components/nav/PageDetail';
|
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 { formatPriceRange } from '../../defaults/formatters';
|
import { formatPriceRange } from '../../defaults/formatters';
|
||||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||||
import { ModelType } from '../../enums/ModelType';
|
import { ModelType } from '../../enums/ModelType';
|
||||||
@ -75,6 +76,7 @@ import {
|
|||||||
useEditApiFormModal
|
useEditApiFormModal
|
||||||
} from '../../hooks/UseForm';
|
} from '../../hooks/UseForm';
|
||||||
import { useInstance } from '../../hooks/UseInstance';
|
import { useInstance } from '../../hooks/UseInstance';
|
||||||
|
import { usePluginPanels } from '../../hooks/UsePluginPanels';
|
||||||
import { apiUrl } from '../../states/ApiState';
|
import { apiUrl } from '../../states/ApiState';
|
||||||
import { useUserState } from '../../states/UserState';
|
import { useUserState } from '../../states/UserState';
|
||||||
import { BomTable } from '../../tables/bom/BomTable';
|
import { BomTable } from '../../tables/bom/BomTable';
|
||||||
@ -640,6 +642,15 @@ export default function PartDetail() {
|
|||||||
];
|
];
|
||||||
}, [id, part, user]);
|
}, [id, part, user]);
|
||||||
|
|
||||||
|
const pluginPanels = usePluginPanels({
|
||||||
|
targetModel: ModelType.part,
|
||||||
|
targetId: id
|
||||||
|
});
|
||||||
|
|
||||||
|
const panels: PanelType[] = useMemo(() => {
|
||||||
|
return [...partPanels, ...pluginPanels.panels];
|
||||||
|
}, [partPanels, pluginPanels]);
|
||||||
|
|
||||||
const breadcrumbs = useMemo(
|
const breadcrumbs = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{ name: t`Parts`, url: '/part' },
|
{ name: t`Parts`, url: '/part' },
|
||||||
@ -844,7 +855,7 @@ export default function PartDetail() {
|
|||||||
}}
|
}}
|
||||||
actions={partActions}
|
actions={partActions}
|
||||||
/>
|
/>
|
||||||
<PanelGroup pageKey="part" panels={partPanels} />
|
<PanelGroup pageKey="part" panels={panels} />
|
||||||
{transferStockItems.modal}
|
{transferStockItems.modal}
|
||||||
{countStockItems.modal}
|
{countStockItems.modal}
|
||||||
</Stack>
|
</Stack>
|
||||||
|
Loading…
Reference in New Issue
Block a user