diff --git a/src/backend/InvenTree/InvenTree/api_version.py b/src/backend/InvenTree/InvenTree/api_version.py index 9ca039c83f..e001a318fc 100644 --- a/src/backend/InvenTree/InvenTree/api_version.py +++ b/src/backend/InvenTree/InvenTree/api_version.py @@ -1,13 +1,17 @@ """InvenTree API version information.""" # InvenTree API version -INVENTREE_API_VERSION = 307 +INVENTREE_API_VERSION = 308 """Increment this API version number whenever there is a significant change to the API that any clients need to know about.""" INVENTREE_API_TEXT = """ +v308 - 2025-02-01 : https://github.com/inventree/InvenTree/pull/9003 + - Adds extra detail to the ReportOutput and LabelOutput API endpoints + - Allows ordering of output list endpoints + v307 - 2025-01-29 : https://github.com/inventree/InvenTree/pull/8969 - Extend Info Endpoint to include customizations diff --git a/src/backend/InvenTree/report/api.py b/src/backend/InvenTree/report/api.py index a5adbbc49d..d95601ffc5 100644 --- a/src/backend/InvenTree/report/api.py +++ b/src/backend/InvenTree/report/api.py @@ -19,7 +19,7 @@ import report.helpers import report.models import report.serializers from InvenTree.api import BulkDeleteMixin, MetadataView -from InvenTree.filters import InvenTreeSearchFilter +from InvenTree.filters import InvenTreeOrderingFilter, InvenTreeSearchFilter from InvenTree.mixins import ListAPI, ListCreateAPI, RetrieveUpdateDestroyAPI from plugin.builtin.labels.inventree_label import InvenTreeLabelPlugin @@ -309,14 +309,26 @@ class ReportAssetDetail(TemplatePermissionMixin, RetrieveUpdateDestroyAPI): serializer_class = report.serializers.ReportAssetSerializer -class LabelOutputList(TemplatePermissionMixin, BulkDeleteMixin, ListAPI): +class TemplateOutputMixin: + """Mixin class for template output API endpoints.""" + + filter_backends = [InvenTreeOrderingFilter] + ordering_fields = ['created', 'model_type', 'user'] + ordering_field_aliases = {'model_type': 'template__model_type'} + + +class LabelOutputList( + TemplatePermissionMixin, TemplateOutputMixin, BulkDeleteMixin, ListAPI +): """List endpoint for LabelOutput objects.""" queryset = report.models.LabelOutput.objects.all() serializer_class = report.serializers.LabelOutputSerializer -class ReportOutputList(TemplatePermissionMixin, BulkDeleteMixin, ListAPI): +class ReportOutputList( + TemplatePermissionMixin, TemplateOutputMixin, BulkDeleteMixin, ListAPI +): """List endpoint for ReportOutput objects.""" queryset = report.models.ReportOutput.objects.all() diff --git a/src/backend/InvenTree/report/serializers.py b/src/backend/InvenTree/report/serializers.py index 1bf2986db6..3816a8f4d4 100644 --- a/src/backend/InvenTree/report/serializers.py +++ b/src/backend/InvenTree/report/serializers.py @@ -193,7 +193,11 @@ class LabelOutputSerializer(BaseOutputSerializer): """Metaclass options.""" model = report.models.LabelOutput - fields = [*BaseOutputSerializer.base_fields(), 'plugin'] + fields = [*BaseOutputSerializer.base_fields(), 'plugin', 'template_detail'] + + template_detail = LabelTemplateSerializer( + source='template', many=False, read_only=True + ) class ReportOutputSerializer(BaseOutputSerializer): @@ -203,7 +207,11 @@ class ReportOutputSerializer(BaseOutputSerializer): """Metaclass options.""" model = report.models.ReportOutput - fields = BaseOutputSerializer.base_fields() + fields = [*BaseOutputSerializer.base_fields(), 'template_detail'] + + template_detail = ReportTemplateSerializer( + source='template', many=False, read_only=True + ) class ReportSnippetSerializer(InvenTreeModelSerializer): diff --git a/src/frontend/src/pages/Index/Settings/AdminCenter/CurrencyManagmentPanel.tsx b/src/frontend/src/pages/Index/Settings/AdminCenter/CurrencyManagementPanel.tsx similarity index 98% rename from src/frontend/src/pages/Index/Settings/AdminCenter/CurrencyManagmentPanel.tsx rename to src/frontend/src/pages/Index/Settings/AdminCenter/CurrencyManagementPanel.tsx index 505db6f5e1..6c08c88cb8 100644 --- a/src/frontend/src/pages/Index/Settings/AdminCenter/CurrencyManagmentPanel.tsx +++ b/src/frontend/src/pages/Index/Settings/AdminCenter/CurrencyManagementPanel.tsx @@ -89,7 +89,7 @@ export function CurrencyTable({ ); } -export default function CurrencyManagmentPanel() { +export default function CurrencyManagementPanel() { const [info, setInfo] = useState({}); return ( diff --git a/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx b/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx index 639737c181..ecf7841c90 100644 --- a/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx +++ b/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx @@ -44,11 +44,13 @@ const TaskManagementPanel = Loadable( lazy(() => import('./TaskManagementPanel')) ); -const CurrencyManagmentPanel = Loadable( - lazy(() => import('./CurrencyManagmentPanel')) +const CurrencyManagementPanel = Loadable( + lazy(() => import('./CurrencyManagementPanel')) ); -const UnitManagmentPanel = Loadable(lazy(() => import('./UnitManagmentPanel'))); +const UnitManagementPanel = Loadable( + lazy(() => import('./UnitManagementPanel')) +); const PluginManagementPanel = Loadable( lazy(() => import('./PluginManagementPanel')) @@ -137,10 +139,10 @@ export default function AdminCenter() { name: 'currencies', label: t`Currencies`, icon: , - content: + content: }, { - name: 'projectcodes', + name: 'project-codes', label: t`Project Codes`, icon: , content: ( @@ -151,16 +153,16 @@ export default function AdminCenter() { ) }, { - name: 'customstates', + name: 'custom-states', label: t`Custom States`, icon: , content: }, { - name: 'customunits', + name: 'custom-units', label: t`Custom Units`, icon: , - content: + content: }, { name: 'part-parameters', diff --git a/src/frontend/src/pages/Index/Settings/AdminCenter/LabelTemplatePanel.tsx b/src/frontend/src/pages/Index/Settings/AdminCenter/LabelTemplatePanel.tsx index cda9c40efa..5bfc1c2339 100644 --- a/src/frontend/src/pages/Index/Settings/AdminCenter/LabelTemplatePanel.tsx +++ b/src/frontend/src/pages/Index/Settings/AdminCenter/LabelTemplatePanel.tsx @@ -1,8 +1,14 @@ +import { t } from '@lingui/macro'; +import { Accordion } from '@mantine/core'; +import { StylishText } from '../../../../components/items/StylishText'; import { ApiEndpoints } from '../../../../enums/ApiEndpoints'; import { ModelType } from '../../../../enums/ModelType'; -import { TemplateTable } from '../../../../tables/settings/TemplateTable'; +import { + TemplateOutputTable, + TemplateTable +} from '../../../../tables/settings/TemplateTable'; -export default function LabelTemplatePanel() { +function LabelTemplateTable() { return ( ); } + +export default function LabelTemplatePanel() { + return ( + + + + {t`Label Templates`} + + + + + + + + {t`Generated Labels`} + + + + + + + ); +} diff --git a/src/frontend/src/pages/Index/Settings/AdminCenter/ReportTemplatePanel.tsx b/src/frontend/src/pages/Index/Settings/AdminCenter/ReportTemplatePanel.tsx index ee8190af7e..7cd05e1c2f 100644 --- a/src/frontend/src/pages/Index/Settings/AdminCenter/ReportTemplatePanel.tsx +++ b/src/frontend/src/pages/Index/Settings/AdminCenter/ReportTemplatePanel.tsx @@ -1,11 +1,16 @@ import { t } from '@lingui/macro'; +import { Accordion } from '@mantine/core'; import { YesNoButton } from '../../../../components/buttons/YesNoButton'; +import { StylishText } from '../../../../components/items/StylishText'; import { ApiEndpoints } from '../../../../enums/ApiEndpoints'; import { ModelType } from '../../../../enums/ModelType'; -import { TemplateTable } from '../../../../tables/settings/TemplateTable'; +import { + TemplateOutputTable, + TemplateTable +} from '../../../../tables/settings/TemplateTable'; -export default function ReportTemplateTable() { +function ReportTemplateTable() { return ( ); } + +export default function ReportTemplatePanel() { + return ( + + + + {t`Report Templates`} + + + + + + + + {t`Generated Reports`} + + + + + + + ); +} diff --git a/src/frontend/src/pages/Index/Settings/AdminCenter/UnitManagmentPanel.tsx b/src/frontend/src/pages/Index/Settings/AdminCenter/UnitManagementPanel.tsx similarity index 97% rename from src/frontend/src/pages/Index/Settings/AdminCenter/UnitManagmentPanel.tsx rename to src/frontend/src/pages/Index/Settings/AdminCenter/UnitManagementPanel.tsx index b38ab3d01d..91419b516d 100644 --- a/src/frontend/src/pages/Index/Settings/AdminCenter/UnitManagmentPanel.tsx +++ b/src/frontend/src/pages/Index/Settings/AdminCenter/UnitManagementPanel.tsx @@ -48,7 +48,7 @@ function AllUnitTable() { ); } -export default function UnitManagmentPanel() { +export default function UnitManagementPanel() { return ( diff --git a/src/frontend/src/tables/settings/TemplateTable.tsx b/src/frontend/src/tables/settings/TemplateTable.tsx index 162a091646..52c71fdded 100644 --- a/src/frontend/src/tables/settings/TemplateTable.tsx +++ b/src/frontend/src/tables/settings/TemplateTable.tsx @@ -42,7 +42,7 @@ import { useTable } from '../../hooks/UseTable'; import { apiUrl } from '../../states/ApiState'; import { useUserState } from '../../states/UserState'; import type { TableColumn } from '../Column'; -import { BooleanColumn } from '../ColumnRenderers'; +import { BooleanColumn, DateColumn } from '../ColumnRenderers'; import type { TableFilter } from '../Filter'; import { InvenTreeTable } from '../InvenTreeTable'; import { @@ -401,3 +401,78 @@ export function TemplateTable({ ); } + +export function TemplateOutputTable({ + endpoint, + withPlugins = false +}: { + endpoint: ApiEndpoints; + withPlugins?: boolean; +}) { + const table = useTable(`${endpoint}-output`); + + const tableColumns: TableColumn[] = useMemo(() => { + return [ + { + accessor: 'output', + sortable: false, + switchable: false, + title: t`Report Output`, + noWrap: true, + noContext: true, + render: (record: any) => { + if (record.output) { + return ; + } else { + return '-'; + } + } + }, + { + accessor: 'template_detail.name', + sortable: false, + switchable: false, + title: t`Template` + }, + { + accessor: 'model_type', + sortable: true, + switchable: false, + title: t`Model Type` + }, + DateColumn({ + accessor: 'created', + title: t`Creation Date`, + switchable: false, + sortable: true + }), + { + accessor: 'plugin', + title: t`Plugin`, + hidden: !withPlugins + }, + { + accessor: 'user_detail.username', + sortable: true, + ordering: 'user', + title: t`Created By` + } + ]; + }, [withPlugins]); + + return ( + <> + + + ); +}