mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-28 11:36:44 +00:00
[UI] Report ouputs (#9003)
* Typo fixes * Display table of generated reports * Display generated label outputs * Translation * Allow sorting of API Endpoints * Add template detail to output serializers * Add extra table column
This commit is contained in:
parent
bef6270ff6
commit
eba004d835
@ -1,13 +1,17 @@
|
|||||||
"""InvenTree API version information."""
|
"""InvenTree API version information."""
|
||||||
|
|
||||||
# InvenTree API version
|
# 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."""
|
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
|
||||||
|
|
||||||
|
|
||||||
INVENTREE_API_TEXT = """
|
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
|
v307 - 2025-01-29 : https://github.com/inventree/InvenTree/pull/8969
|
||||||
- Extend Info Endpoint to include customizations
|
- Extend Info Endpoint to include customizations
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ import report.helpers
|
|||||||
import report.models
|
import report.models
|
||||||
import report.serializers
|
import report.serializers
|
||||||
from InvenTree.api import BulkDeleteMixin, MetadataView
|
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 InvenTree.mixins import ListAPI, ListCreateAPI, RetrieveUpdateDestroyAPI
|
||||||
from plugin.builtin.labels.inventree_label import InvenTreeLabelPlugin
|
from plugin.builtin.labels.inventree_label import InvenTreeLabelPlugin
|
||||||
|
|
||||||
@ -309,14 +309,26 @@ class ReportAssetDetail(TemplatePermissionMixin, RetrieveUpdateDestroyAPI):
|
|||||||
serializer_class = report.serializers.ReportAssetSerializer
|
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."""
|
"""List endpoint for LabelOutput objects."""
|
||||||
|
|
||||||
queryset = report.models.LabelOutput.objects.all()
|
queryset = report.models.LabelOutput.objects.all()
|
||||||
serializer_class = report.serializers.LabelOutputSerializer
|
serializer_class = report.serializers.LabelOutputSerializer
|
||||||
|
|
||||||
|
|
||||||
class ReportOutputList(TemplatePermissionMixin, BulkDeleteMixin, ListAPI):
|
class ReportOutputList(
|
||||||
|
TemplatePermissionMixin, TemplateOutputMixin, BulkDeleteMixin, ListAPI
|
||||||
|
):
|
||||||
"""List endpoint for ReportOutput objects."""
|
"""List endpoint for ReportOutput objects."""
|
||||||
|
|
||||||
queryset = report.models.ReportOutput.objects.all()
|
queryset = report.models.ReportOutput.objects.all()
|
||||||
|
@ -193,7 +193,11 @@ class LabelOutputSerializer(BaseOutputSerializer):
|
|||||||
"""Metaclass options."""
|
"""Metaclass options."""
|
||||||
|
|
||||||
model = report.models.LabelOutput
|
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):
|
class ReportOutputSerializer(BaseOutputSerializer):
|
||||||
@ -203,7 +207,11 @@ class ReportOutputSerializer(BaseOutputSerializer):
|
|||||||
"""Metaclass options."""
|
"""Metaclass options."""
|
||||||
|
|
||||||
model = report.models.ReportOutput
|
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):
|
class ReportSnippetSerializer(InvenTreeModelSerializer):
|
||||||
|
@ -89,7 +89,7 @@ export function CurrencyTable({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function CurrencyManagmentPanel() {
|
export default function CurrencyManagementPanel() {
|
||||||
const [info, setInfo] = useState<any>({});
|
const [info, setInfo] = useState<any>({});
|
||||||
|
|
||||||
return (
|
return (
|
@ -44,11 +44,13 @@ const TaskManagementPanel = Loadable(
|
|||||||
lazy(() => import('./TaskManagementPanel'))
|
lazy(() => import('./TaskManagementPanel'))
|
||||||
);
|
);
|
||||||
|
|
||||||
const CurrencyManagmentPanel = Loadable(
|
const CurrencyManagementPanel = Loadable(
|
||||||
lazy(() => import('./CurrencyManagmentPanel'))
|
lazy(() => import('./CurrencyManagementPanel'))
|
||||||
);
|
);
|
||||||
|
|
||||||
const UnitManagmentPanel = Loadable(lazy(() => import('./UnitManagmentPanel')));
|
const UnitManagementPanel = Loadable(
|
||||||
|
lazy(() => import('./UnitManagementPanel'))
|
||||||
|
);
|
||||||
|
|
||||||
const PluginManagementPanel = Loadable(
|
const PluginManagementPanel = Loadable(
|
||||||
lazy(() => import('./PluginManagementPanel'))
|
lazy(() => import('./PluginManagementPanel'))
|
||||||
@ -137,10 +139,10 @@ export default function AdminCenter() {
|
|||||||
name: 'currencies',
|
name: 'currencies',
|
||||||
label: t`Currencies`,
|
label: t`Currencies`,
|
||||||
icon: <IconCoins />,
|
icon: <IconCoins />,
|
||||||
content: <CurrencyManagmentPanel />
|
content: <CurrencyManagementPanel />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'projectcodes',
|
name: 'project-codes',
|
||||||
label: t`Project Codes`,
|
label: t`Project Codes`,
|
||||||
icon: <IconListDetails />,
|
icon: <IconListDetails />,
|
||||||
content: (
|
content: (
|
||||||
@ -151,16 +153,16 @@ export default function AdminCenter() {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'customstates',
|
name: 'custom-states',
|
||||||
label: t`Custom States`,
|
label: t`Custom States`,
|
||||||
icon: <IconListDetails />,
|
icon: <IconListDetails />,
|
||||||
content: <CustomStateTable />
|
content: <CustomStateTable />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'customunits',
|
name: 'custom-units',
|
||||||
label: t`Custom Units`,
|
label: t`Custom Units`,
|
||||||
icon: <IconScale />,
|
icon: <IconScale />,
|
||||||
content: <UnitManagmentPanel />
|
content: <UnitManagementPanel />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'part-parameters',
|
name: 'part-parameters',
|
||||||
|
@ -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 { ApiEndpoints } from '../../../../enums/ApiEndpoints';
|
||||||
import { ModelType } from '../../../../enums/ModelType';
|
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 (
|
return (
|
||||||
<TemplateTable
|
<TemplateTable
|
||||||
templateProps={{
|
templateProps={{
|
||||||
@ -17,3 +23,29 @@ export default function LabelTemplatePanel() {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default function LabelTemplatePanel() {
|
||||||
|
return (
|
||||||
|
<Accordion defaultValue={['templates']} multiple>
|
||||||
|
<Accordion.Item value='templates'>
|
||||||
|
<Accordion.Control>
|
||||||
|
<StylishText size='lg'>{t`Label Templates`}</StylishText>
|
||||||
|
</Accordion.Control>
|
||||||
|
<Accordion.Panel>
|
||||||
|
<LabelTemplateTable />
|
||||||
|
</Accordion.Panel>
|
||||||
|
</Accordion.Item>
|
||||||
|
<Accordion.Item value='outputs'>
|
||||||
|
<Accordion.Control>
|
||||||
|
<StylishText size='lg'>{t`Generated Labels`}</StylishText>
|
||||||
|
</Accordion.Control>
|
||||||
|
<Accordion.Panel>
|
||||||
|
<TemplateOutputTable
|
||||||
|
endpoint={ApiEndpoints.label_output}
|
||||||
|
withPlugins
|
||||||
|
/>
|
||||||
|
</Accordion.Panel>
|
||||||
|
</Accordion.Item>
|
||||||
|
</Accordion>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
|
|
||||||
|
import { Accordion } from '@mantine/core';
|
||||||
import { YesNoButton } from '../../../../components/buttons/YesNoButton';
|
import { YesNoButton } from '../../../../components/buttons/YesNoButton';
|
||||||
|
import { StylishText } from '../../../../components/items/StylishText';
|
||||||
import { ApiEndpoints } from '../../../../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../../../../enums/ApiEndpoints';
|
||||||
import { ModelType } from '../../../../enums/ModelType';
|
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 (
|
return (
|
||||||
<TemplateTable
|
<TemplateTable
|
||||||
templateProps={{
|
templateProps={{
|
||||||
@ -33,3 +38,26 @@ export default function ReportTemplateTable() {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default function ReportTemplatePanel() {
|
||||||
|
return (
|
||||||
|
<Accordion defaultValue={['templates']} multiple>
|
||||||
|
<Accordion.Item value='templates'>
|
||||||
|
<Accordion.Control>
|
||||||
|
<StylishText size='lg'>{t`Report Templates`}</StylishText>
|
||||||
|
</Accordion.Control>
|
||||||
|
<Accordion.Panel>
|
||||||
|
<ReportTemplateTable />
|
||||||
|
</Accordion.Panel>
|
||||||
|
</Accordion.Item>
|
||||||
|
<Accordion.Item value='outputs'>
|
||||||
|
<Accordion.Control>
|
||||||
|
<StylishText size='lg'>{t`Generated Reports`}</StylishText>
|
||||||
|
</Accordion.Control>
|
||||||
|
<Accordion.Panel>
|
||||||
|
<TemplateOutputTable endpoint={ApiEndpoints.report_output} />
|
||||||
|
</Accordion.Panel>
|
||||||
|
</Accordion.Item>
|
||||||
|
</Accordion>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -48,7 +48,7 @@ function AllUnitTable() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function UnitManagmentPanel() {
|
export default function UnitManagementPanel() {
|
||||||
return (
|
return (
|
||||||
<Stack gap='xs'>
|
<Stack gap='xs'>
|
||||||
<Accordion defaultValue='custom'>
|
<Accordion defaultValue='custom'>
|
@ -42,7 +42,7 @@ import { useTable } from '../../hooks/UseTable';
|
|||||||
import { apiUrl } from '../../states/ApiState';
|
import { apiUrl } from '../../states/ApiState';
|
||||||
import { useUserState } from '../../states/UserState';
|
import { useUserState } from '../../states/UserState';
|
||||||
import type { TableColumn } from '../Column';
|
import type { TableColumn } from '../Column';
|
||||||
import { BooleanColumn } from '../ColumnRenderers';
|
import { BooleanColumn, DateColumn } from '../ColumnRenderers';
|
||||||
import type { TableFilter } from '../Filter';
|
import type { TableFilter } from '../Filter';
|
||||||
import { InvenTreeTable } from '../InvenTreeTable';
|
import { InvenTreeTable } from '../InvenTreeTable';
|
||||||
import {
|
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 <AttachmentLink attachment={record.output} />;
|
||||||
|
} 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 (
|
||||||
|
<>
|
||||||
|
<InvenTreeTable
|
||||||
|
url={apiUrl(endpoint)}
|
||||||
|
tableState={table}
|
||||||
|
columns={tableColumns}
|
||||||
|
props={{
|
||||||
|
enableSearch: false,
|
||||||
|
enableColumnSwitching: false,
|
||||||
|
enableSelection: true,
|
||||||
|
enableBulkDelete: true
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user