2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-12 18:15:40 +00:00
* 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:
Oliver
2024-01-13 19:27:47 +11:00
committed by GitHub
parent 5180d86388
commit ef679b1663
9 changed files with 233 additions and 4 deletions

View File

@ -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}>

View 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();
}
}}
/>
</>
);
}

View File

@ -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'
}

View File

@ -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`,

View File

@ -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: