mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-12 18:15:40 +00:00
Error API (#6222)
* Adds API endpoint for fetching error information * Bump API version * Implement table for displaying server errors * Add support for "bulk delete" in new table component * Update API version with PR * Fix unused variables * Enable table sorting * Display error details
This commit is contained in:
@ -1,7 +1,16 @@
|
||||
import { t } from '@lingui/macro';
|
||||
import { ActionIcon, Indicator, Space, Stack, Tooltip } from '@mantine/core';
|
||||
import {
|
||||
ActionIcon,
|
||||
Alert,
|
||||
Indicator,
|
||||
Space,
|
||||
Stack,
|
||||
Tooltip
|
||||
} from '@mantine/core';
|
||||
import { Group } from '@mantine/core';
|
||||
import { IconFilter, IconRefresh } from '@tabler/icons-react';
|
||||
import { modals } from '@mantine/modals';
|
||||
import { showNotification } from '@mantine/notifications';
|
||||
import { IconFilter, IconRefresh, IconTrash } from '@tabler/icons-react';
|
||||
import { IconBarcode, IconPrinter } from '@tabler/icons-react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { DataTable, DataTableSortStatus } from 'mantine-datatable';
|
||||
@ -9,6 +18,7 @@ import { Fragment, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { api } from '../../App';
|
||||
import { TableState } from '../../hooks/UseTable';
|
||||
import { ActionButton } from '../buttons/ActionButton';
|
||||
import { ButtonMenu } from '../buttons/ButtonMenu';
|
||||
import { TableColumn } from './Column';
|
||||
import { TableColumnSelect } from './ColumnSelect';
|
||||
@ -27,6 +37,7 @@ const defaultPageSize: number = 25;
|
||||
* @param tableState : TableState - State manager for the table
|
||||
* @param defaultSortColumn : string - Default column to sort by
|
||||
* @param noRecordsText : string - Text to display when no records are found
|
||||
* @param enableBulkDelete : boolean - Enable bulk deletion of records
|
||||
* @param enableDownload : boolean - Enable download actions
|
||||
* @param enableFilters : boolean - Enable filter actions
|
||||
* @param enableSelection : boolean - Enable row selection
|
||||
@ -46,6 +57,7 @@ export type InvenTreeTableProps<T = any> = {
|
||||
params?: any;
|
||||
defaultSortColumn?: string;
|
||||
noRecordsText?: string;
|
||||
enableBulkDelete?: boolean;
|
||||
enableDownload?: boolean;
|
||||
enableFilters?: boolean;
|
||||
enableSelection?: boolean;
|
||||
@ -350,6 +362,58 @@ export function InvenTreeTable<T = any>({
|
||||
|
||||
const [recordCount, setRecordCount] = useState<number>(0);
|
||||
|
||||
// Callback function to delete the selected records in the table
|
||||
const deleteSelectedRecords = useCallback(() => {
|
||||
if (tableState.selectedRecords.length == 0) {
|
||||
// Ignore if no records are selected
|
||||
return;
|
||||
}
|
||||
|
||||
modals.openConfirmModal({
|
||||
title: t`Delete selected records`,
|
||||
children: (
|
||||
<Alert
|
||||
color="red"
|
||||
title={t`Are you sure you want to delete the selected records?`}
|
||||
>
|
||||
{t`This action cannot be undone!`}
|
||||
</Alert>
|
||||
),
|
||||
labels: {
|
||||
confirm: t`Delete`,
|
||||
cancel: t`Cancel`
|
||||
},
|
||||
confirmProps: {
|
||||
color: 'red'
|
||||
},
|
||||
onConfirm: () => {
|
||||
// Delete the selected records
|
||||
let selection = tableState.selectedRecords.map((record) => record.pk);
|
||||
|
||||
api
|
||||
.delete(url, {
|
||||
data: {
|
||||
items: selection
|
||||
}
|
||||
})
|
||||
.then((_response) => {
|
||||
// Refresh the table
|
||||
refetch();
|
||||
|
||||
// Show notification
|
||||
showNotification({
|
||||
title: t`Deleted records`,
|
||||
message: t`Records were deleted successfully`,
|
||||
color: 'green'
|
||||
});
|
||||
})
|
||||
.catch((_error) => {
|
||||
console.warn(`Bulk delete operation failed at ${url}`);
|
||||
});
|
||||
}
|
||||
});
|
||||
}, [tableState.selectedRecords]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{tableProps.enableFilters &&
|
||||
@ -385,6 +449,15 @@ export function InvenTreeTable<T = any>({
|
||||
actions={tableProps.printingActions ?? []}
|
||||
/>
|
||||
)}
|
||||
{(tableProps.enableBulkDelete ?? false) && (
|
||||
<ActionButton
|
||||
disabled={tableState.selectedRecords.length == 0}
|
||||
icon={<IconTrash />}
|
||||
color="red"
|
||||
tooltip={t`Delete selected records`}
|
||||
onClick={deleteSelectedRecords}
|
||||
/>
|
||||
)}
|
||||
</Group>
|
||||
<Space />
|
||||
<Group position="right" spacing={5}>
|
||||
|
91
src/frontend/src/components/tables/settings/ErrorTable.tsx
Normal file
91
src/frontend/src/components/tables/settings/ErrorTable.tsx
Normal file
@ -0,0 +1,91 @@
|
||||
import { t } from '@lingui/macro';
|
||||
import { Drawer, Text } from '@mantine/core';
|
||||
import { useDisclosure } from '@mantine/hooks';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
|
||||
import { ApiPaths } from '../../../enums/ApiEndpoints';
|
||||
import { openDeleteApiForm } from '../../../functions/forms';
|
||||
import { useTable } from '../../../hooks/UseTable';
|
||||
import { apiUrl } from '../../../states/ApiState';
|
||||
import { StylishText } from '../../items/StylishText';
|
||||
import { TableColumn } from '../Column';
|
||||
import { InvenTreeTable } from '../InvenTreeTable';
|
||||
import { RowAction, RowDeleteAction } from '../RowActions';
|
||||
|
||||
/*
|
||||
* Table for display server error information
|
||||
*/
|
||||
export default function ErrorReportTable() {
|
||||
const table = useTable('error-report');
|
||||
|
||||
const [error, setError] = useState<string>('');
|
||||
|
||||
const [opened, { open, close }] = useDisclosure(false);
|
||||
|
||||
const columns: TableColumn[] = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
accessor: 'when',
|
||||
title: t`When`,
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
accessor: 'path',
|
||||
title: t`Path`,
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
accessor: 'info',
|
||||
title: t`Error Information`
|
||||
}
|
||||
];
|
||||
}, []);
|
||||
|
||||
const rowActions = useCallback((record: any): RowAction[] => {
|
||||
return [
|
||||
RowDeleteAction({
|
||||
onClick: () => {
|
||||
openDeleteApiForm({
|
||||
url: ApiPaths.error_report_list,
|
||||
pk: record.pk,
|
||||
title: t`Delete error report`,
|
||||
onFormSuccess: table.refreshTable,
|
||||
successMessage: t`Error report deleted`,
|
||||
preFormWarning: t`Are you sure you want to delete this error report?`
|
||||
});
|
||||
}
|
||||
})
|
||||
];
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Drawer
|
||||
opened={opened}
|
||||
size="xl"
|
||||
position="right"
|
||||
title={<StylishText>{t`Error Details`}</StylishText>}
|
||||
onClose={close}
|
||||
>
|
||||
{error.split('\n').map((line: string) => {
|
||||
return <Text size="sm">{line}</Text>;
|
||||
})}
|
||||
</Drawer>
|
||||
<InvenTreeTable
|
||||
url={apiUrl(ApiPaths.error_report_list)}
|
||||
tableState={table}
|
||||
columns={columns}
|
||||
props={{
|
||||
enableBulkDelete: true,
|
||||
enableSelection: true,
|
||||
rowActions: rowActions,
|
||||
onRowClick: (row) => {
|
||||
console.log(row);
|
||||
setError(row.data);
|
||||
open();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
@ -89,6 +89,7 @@ export enum ApiPaths {
|
||||
plugin_reload = 'api-plugin-reload',
|
||||
plugin_registry_status = 'api-plugin-registry-status',
|
||||
|
||||
error_report_list = 'api-error-report-list',
|
||||
project_code_list = 'api-project-code-list',
|
||||
custom_unit_list = 'api-custom-unit-list'
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Trans, t } from '@lingui/macro';
|
||||
import { Divider, Paper, SimpleGrid, Stack, Text, Title } from '@mantine/core';
|
||||
import {
|
||||
IconExclamationCircle,
|
||||
IconList,
|
||||
IconListDetails,
|
||||
IconPlugConnected,
|
||||
@ -23,6 +24,10 @@ const PluginManagementPanel = Loadable(
|
||||
lazy(() => import('./PluginManagementPanel'))
|
||||
);
|
||||
|
||||
const ErrorReportTable = Loadable(
|
||||
lazy(() => import('../../../../components/tables/settings/ErrorTable'))
|
||||
);
|
||||
|
||||
const ProjectCodeTable = Loadable(
|
||||
lazy(() => import('../../../../components/tables/settings/ProjectCodeTable'))
|
||||
);
|
||||
@ -47,6 +52,12 @@ export default function AdminCenter() {
|
||||
icon: <IconUsersGroup />,
|
||||
content: <UserManagementPanel />
|
||||
},
|
||||
{
|
||||
name: 'errors',
|
||||
label: t`Error Reports`,
|
||||
icon: <IconExclamationCircle />,
|
||||
content: <ErrorReportTable />
|
||||
},
|
||||
{
|
||||
name: 'projectcodes',
|
||||
label: t`Project Codes`,
|
||||
|
@ -189,6 +189,8 @@ export function apiEndpoint(path: ApiPaths): string {
|
||||
return 'plugins/install/';
|
||||
case ApiPaths.plugin_reload:
|
||||
return 'plugins/reload/';
|
||||
case ApiPaths.error_report_list:
|
||||
return 'error-report/';
|
||||
case ApiPaths.project_code_list:
|
||||
return 'project-code/';
|
||||
case ApiPaths.custom_unit_list:
|
||||
|
Reference in New Issue
Block a user