@dashadmin/dash-components 1.3.25 → 1.3.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/AuditLog/AuditLog.js +345 -1
- package/dist/components/AuditLog/index.js +4 -1
- package/dist/components/AutoCompleteArrayInput/AutoCompleteCheckBoxInput.js +630 -3
- package/dist/components/AutoCompleteArrayInput/AutocompleteCheckBoxArrayInput.js +53 -1
- package/dist/components/AutoCompleteArrayInputAutoSearch/AutoCompleteCheckBoxInput.js +647 -3
- package/dist/components/AutoCompleteArrayInputAutoSearch/AutocompleteCheckBoxArrayInput.js +53 -1
- package/dist/components/Json/Json.js +235 -1
- package/dist/components/JsonColorSelector/JsonColorSelector.js +1172 -1
- package/dist/components/JsonColorSelector/JsonColorSelectorEnhanced.js +863 -2
- package/dist/components/JsonColorSelector/JsonCssVarValues.js +738 -1
- package/dist/components/JsonColorSelector/components/ColorEditDialog.js +426 -1
- package/dist/components/JsonColorSelector/components/ColorPaletteItem.js +75 -1
- package/dist/components/JsonColorSelector/components/ImageColorExtractor.js +283 -1
- package/dist/components/JsonColorSelector/helpers/functions.js +101 -1
- package/dist/components/JsonColorSelector/useAsyncColorThief.js +105 -1
- package/dist/components/ListActive/ListActive.js +126 -1
- package/dist/components/ListActive/ListBoolean.js +124 -1
- package/dist/components/NotificationPreferences/NotificationPreferences.js +317 -1
- package/dist/components/NotificationPreferences/index.js +7 -1
- package/dist/components/SearchableSelects/RASearchableSelect.js +236 -1
- package/dist/components/SearchableSelects/RASearchableSelectCheckboxes.js +479 -1
- package/dist/components/SearchableSelects/RASearchableSelectChips.js +465 -1
- package/dist/components/SearchableSelects/RASearchableSelectChipsRecordContext.js +295 -1
- package/dist/components/SearchableSelects/SearchableSelect.js +202 -1
- package/dist/components/SearchableSelects/SearchableSelectCheckboxes.js +290 -1
- package/dist/components/SortableDataGrid/SortableDataGrid.js +72 -1
- package/dist/components/SortableDataGrid/SortableDataGridBody.js +167 -1
- package/dist/components/SortableDataGrid/SortableDataGridHeader.js +109 -1
- package/dist/components/SortableDataGrid/SortableDataGridRow.js +283 -1
- package/dist/components/Upload/SingleImageUploader.js +40 -1
- package/dist/components/custom/PackageCopyMethod.js +78 -1
- package/dist/components/custom/PackageRadioButtonGroup.js +45 -1
- package/dist/components/dialog/Basic.js +8 -1
- package/dist/components/dialog/Correct.js +14 -1
- package/dist/components/dialog/Error.js +14 -1
- package/dist/components/dialog/Info.js +14 -1
- package/dist/components/dialog/InfoV2.js +21 -1
- package/dist/components/dialog/NotFound.js +14 -1
- package/dist/components/dialog/QuickSearch.js +117 -1
- package/dist/components/notifications/NotificationsCenter.js +597 -1
- package/dist/components/notifications/index.js +24 -1
- package/dist/components/tables/PaginationComponent.js +36 -1
- package/dist/components/theme/AppLoadingFallback.js +38 -2
- package/dist/components/theme/ErrorBoundary.js +52 -1
- package/dist/components/theme/InitialLoader.js +13 -1
- package/dist/components/theme/NotFound.js +136 -1
- package/dist/components/theme/NotResults.js +38 -1
- package/dist/hooks/useDraggable.js +6 -1
- package/dist/hooks/useNotifications.js +8 -1
- package/dist/hooks/useQuickSearch.js +26 -1
- package/dist/index.js +66 -5567
- package/dist/utils/setNativeValue.js +17 -1
- package/package.json +149 -132
- package/src/components/AuditLog/AuditLog.tsx +476 -0
- package/src/components/AuditLog/index.ts +2 -0
- package/src/components/AutoCompleteArrayInput/AutoCompleteCheckBoxInput.tsx +917 -0
- package/src/components/AutoCompleteArrayInput/AutocompleteCheckBoxArrayInput.tsx +39 -0
- package/src/components/AutoCompleteArrayInputAutoSearch/AutoCompleteCheckBoxInput.tsx +916 -0
- package/src/components/AutoCompleteArrayInputAutoSearch/AutocompleteCheckBoxArrayInput.tsx +44 -0
- package/src/components/Json/Json.tsx +312 -0
- package/src/components/JsonColorSelector/JsonColorSelector.tsx +1435 -0
- package/src/components/JsonColorSelector/JsonColorSelectorEnhanced.tsx +1029 -0
- package/src/components/JsonColorSelector/JsonCssVarValues.tsx +863 -0
- package/src/components/JsonColorSelector/components/ColorEditDialog.tsx +491 -0
- package/src/components/JsonColorSelector/components/ColorPaletteItem.tsx +80 -0
- package/src/components/JsonColorSelector/components/ImageColorExtractor.tsx +328 -0
- package/src/components/JsonColorSelector/helpers/functions.tsx +123 -0
- package/src/components/JsonColorSelector/interfaces/interfaces.tsx +22 -0
- package/src/components/JsonColorSelector/useAsyncColorThief.tsx +97 -0
- package/src/components/ListActive/ListActive.tsx +106 -0
- package/src/components/ListActive/ListBoolean.tsx +96 -0
- package/src/components/NotificationPreferences/NotificationPreferences.tsx +463 -0
- package/src/components/NotificationPreferences/index.tsx +2 -0
- package/src/components/SearchableSelects/RASearchableSelect.tsx +300 -0
- package/src/components/SearchableSelects/RASearchableSelectCheckboxes.tsx +604 -0
- package/src/components/SearchableSelects/RASearchableSelectChips.tsx +558 -0
- package/src/components/SearchableSelects/RASearchableSelectChipsRecordContext.tsx +362 -0
- package/src/components/SearchableSelects/SearchableSelect.tsx +321 -0
- package/src/components/SearchableSelects/SearchableSelectCheckboxes.tsx +355 -0
- package/src/components/SortableDataGrid/SortableDataGrid.tsx +56 -0
- package/src/components/SortableDataGrid/SortableDataGridBody.tsx +175 -0
- package/src/components/SortableDataGrid/SortableDataGridHeader.tsx +171 -0
- package/src/components/SortableDataGrid/SortableDataGridRow.tsx +247 -0
- package/src/components/Upload/SingleImageUploader.tsx +55 -0
- package/src/components/custom/PackageCopyMethod.tsx +109 -0
- package/src/components/custom/PackageRadioButtonGroup.tsx +47 -0
- package/src/components/dialog/Basic.tsx +11 -0
- package/src/components/dialog/Correct.tsx +16 -0
- package/src/components/dialog/Error.tsx +15 -0
- package/src/components/dialog/Info.tsx +15 -0
- package/src/components/dialog/InfoV2.tsx +35 -0
- package/src/components/dialog/NotFound.tsx +18 -0
- package/src/components/dialog/QuickSearch.tsx +115 -0
- package/src/components/notifications/NotificationsCenter.tsx +792 -0
- package/src/components/notifications/index.ts +42 -0
- package/src/components/tables/PaginationComponent.tsx +17 -0
- package/src/components/theme/AppLoadingFallback.tsx +42 -0
- package/src/components/theme/ErrorBoundary.tsx +57 -0
- package/src/components/theme/InitialLoader.tsx +16 -0
- package/src/components/theme/NotFound.tsx +124 -0
- package/src/components/theme/NotResults.tsx +54 -0
- package/src/hooks/useDraggable.ts +11 -0
- package/src/hooks/useNotifications.ts +14 -0
- package/src/hooks/useQuickSearch.tsx +29 -0
- package/src/index.tsx +77 -0
- package/src/utils/setNativeValue.tsx +23 -0
- package/dist/color-thief-CTwGFhOB.js +0 -272
- /package/{dist → src}/components/AutoCompleteArrayInputAutoSearch/AutocompleteCheckBoxArrayAutoSearch.tsx.wip +0 -0
- /package/{dist → src}/components/JsonColorSelector/JsonColorSelector.tsx.bkup +0 -0
- /package/{dist → src}/components/SortableDataGrid/README.md +0 -0
- /package/{dist → src}/styles/index.less +0 -0
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
import React, { useState, useMemo, useCallback } from "react";
|
|
2
|
+
import { useRecordContext, useGetList, Loading } from "react-admin";
|
|
3
|
+
import {
|
|
4
|
+
Box,
|
|
5
|
+
Typography,
|
|
6
|
+
Paper,
|
|
7
|
+
Button,
|
|
8
|
+
Dialog,
|
|
9
|
+
DialogTitle,
|
|
10
|
+
DialogContent,
|
|
11
|
+
DialogActions,
|
|
12
|
+
IconButton,
|
|
13
|
+
Chip,
|
|
14
|
+
Tooltip,
|
|
15
|
+
} from "@mui/material";
|
|
16
|
+
import {
|
|
17
|
+
DataGrid as MUIGrid,
|
|
18
|
+
GridColDef,
|
|
19
|
+
GridRowParams,
|
|
20
|
+
GridPaginationModel,
|
|
21
|
+
GridToolbarContainer,
|
|
22
|
+
GridToolbarExport,
|
|
23
|
+
} from "@mui/x-data-grid";
|
|
24
|
+
import VisibilityIcon from "@mui/icons-material/Visibility";
|
|
25
|
+
import CloseIcon from "@mui/icons-material/Close";
|
|
26
|
+
import HistoryIcon from "@mui/icons-material/History";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* AuditLog Component (Generic)
|
|
30
|
+
*
|
|
31
|
+
* A reusable component that displays audit logs (activity logs) for any model.
|
|
32
|
+
* Uses Spatie Activity Log data from the backend.
|
|
33
|
+
*
|
|
34
|
+
* Features:
|
|
35
|
+
* - Paginated DataGrid with sorting
|
|
36
|
+
* - Export functionality (CSV, Print)
|
|
37
|
+
* - JSON detail dialog for viewing full log properties
|
|
38
|
+
* - Works with any model that has audit logging enabled
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* // In your schema file:
|
|
42
|
+
* import { AuditLog } from 'dash-components';
|
|
43
|
+
*
|
|
44
|
+
* const myModelSchema = [
|
|
45
|
+
* // ... other fields
|
|
46
|
+
* {
|
|
47
|
+
* tab: 'Audit',
|
|
48
|
+
* attribute: 'audit_logs',
|
|
49
|
+
* label: 'Audit Logs',
|
|
50
|
+
* type: Array,
|
|
51
|
+
* inList: false,
|
|
52
|
+
* inEdit: true,
|
|
53
|
+
* inShow: true,
|
|
54
|
+
* inCreate: false,
|
|
55
|
+
* readOnly: true,
|
|
56
|
+
* custom: true,
|
|
57
|
+
* component: AuditLog,
|
|
58
|
+
* },
|
|
59
|
+
* ];
|
|
60
|
+
*/
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Props interface for the AuditLog component
|
|
64
|
+
* Compatible with dash-auto-admin custom field components
|
|
65
|
+
*/
|
|
66
|
+
export interface AuditLogProps {
|
|
67
|
+
/** The resource configuration from dash-auto-admin */
|
|
68
|
+
resourceConfig?: {
|
|
69
|
+
model?: string;
|
|
70
|
+
[key: string]: any;
|
|
71
|
+
};
|
|
72
|
+
/** The current mode: 'create', 'edit', 'view', 'list' */
|
|
73
|
+
method?: 'create' | 'edit' | 'view' | 'list' | 'show';
|
|
74
|
+
/** Optional custom resource path override */
|
|
75
|
+
resource?: string;
|
|
76
|
+
/** Any additional props */
|
|
77
|
+
[key: string]: any;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Activity log record interface from Spatie Activity Log
|
|
82
|
+
*/
|
|
83
|
+
export interface ActivityLogRecord {
|
|
84
|
+
id: number;
|
|
85
|
+
log_name: string;
|
|
86
|
+
description: string;
|
|
87
|
+
subject_type: string | null;
|
|
88
|
+
subject_id: number | null;
|
|
89
|
+
causer_type: string | null;
|
|
90
|
+
causer_id: number | null;
|
|
91
|
+
causer_name?: string;
|
|
92
|
+
properties: Record<string, any>;
|
|
93
|
+
event: string | null;
|
|
94
|
+
batch_uuid: string | null;
|
|
95
|
+
created_at: string;
|
|
96
|
+
updated_at: string;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
interface DialogState {
|
|
100
|
+
open: boolean;
|
|
101
|
+
log: ActivityLogRecord | null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Custom toolbar with export functionality
|
|
106
|
+
*/
|
|
107
|
+
const AuditToolbar: React.FC = () => {
|
|
108
|
+
return (
|
|
109
|
+
<GridToolbarContainer>
|
|
110
|
+
<GridToolbarExport
|
|
111
|
+
csvOptions={{
|
|
112
|
+
fileName: 'audit-logs-export',
|
|
113
|
+
delimiter: ',',
|
|
114
|
+
utf8WithBom: true,
|
|
115
|
+
}}
|
|
116
|
+
printOptions={{
|
|
117
|
+
hideFooter: true,
|
|
118
|
+
hideToolbar: true,
|
|
119
|
+
}}
|
|
120
|
+
/>
|
|
121
|
+
</GridToolbarContainer>
|
|
122
|
+
);
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* JSON Viewer Dialog for audit log details
|
|
127
|
+
*/
|
|
128
|
+
interface JsonDialogProps {
|
|
129
|
+
open: boolean;
|
|
130
|
+
log: ActivityLogRecord | null;
|
|
131
|
+
onClose: () => void;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const AuditJsonDialog: React.FC<JsonDialogProps> = ({ open, log, onClose }) => {
|
|
135
|
+
if (!log) return null;
|
|
136
|
+
|
|
137
|
+
const formatJson = (obj: any): string => {
|
|
138
|
+
try {
|
|
139
|
+
return JSON.stringify(obj, null, 2);
|
|
140
|
+
} catch {
|
|
141
|
+
return String(obj);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
return (
|
|
146
|
+
<Dialog
|
|
147
|
+
open={open}
|
|
148
|
+
onClose={onClose}
|
|
149
|
+
maxWidth="md"
|
|
150
|
+
fullWidth
|
|
151
|
+
aria-labelledby="audit-log-dialog-title"
|
|
152
|
+
>
|
|
153
|
+
<DialogTitle id="audit-log-dialog-title">
|
|
154
|
+
<Box display="flex" justifyContent="space-between" alignItems="center">
|
|
155
|
+
<Typography variant="h6">
|
|
156
|
+
Audit Log Details - {log.event || log.description}
|
|
157
|
+
</Typography>
|
|
158
|
+
<IconButton
|
|
159
|
+
edge="end"
|
|
160
|
+
color="inherit"
|
|
161
|
+
onClick={onClose}
|
|
162
|
+
aria-label="close"
|
|
163
|
+
>
|
|
164
|
+
<CloseIcon />
|
|
165
|
+
</IconButton>
|
|
166
|
+
</Box>
|
|
167
|
+
</DialogTitle>
|
|
168
|
+
<DialogContent dividers>
|
|
169
|
+
<Box mb={2}>
|
|
170
|
+
<Typography variant="subtitle2" color="textSecondary">
|
|
171
|
+
Event Information
|
|
172
|
+
</Typography>
|
|
173
|
+
<Paper variant="outlined" sx={{ p: 2, mt: 1 }}>
|
|
174
|
+
<Typography variant="body2">
|
|
175
|
+
<strong>ID:</strong> {log.id}
|
|
176
|
+
</Typography>
|
|
177
|
+
<Typography variant="body2">
|
|
178
|
+
<strong>Event:</strong> {log.event || 'N/A'}
|
|
179
|
+
</Typography>
|
|
180
|
+
<Typography variant="body2">
|
|
181
|
+
<strong>Description:</strong> {log.description}
|
|
182
|
+
</Typography>
|
|
183
|
+
<Typography variant="body2">
|
|
184
|
+
<strong>Log Name:</strong> {log.log_name}
|
|
185
|
+
</Typography>
|
|
186
|
+
<Typography variant="body2">
|
|
187
|
+
<strong>Created At:</strong> {new Date(log.created_at).toLocaleString()}
|
|
188
|
+
</Typography>
|
|
189
|
+
{log.causer_name && (
|
|
190
|
+
<Typography variant="body2">
|
|
191
|
+
<strong>Changed By:</strong> {log.causer_name}
|
|
192
|
+
</Typography>
|
|
193
|
+
)}
|
|
194
|
+
</Paper>
|
|
195
|
+
</Box>
|
|
196
|
+
|
|
197
|
+
<Box>
|
|
198
|
+
<Typography variant="subtitle2" color="textSecondary">
|
|
199
|
+
Properties (JSON)
|
|
200
|
+
</Typography>
|
|
201
|
+
<Paper
|
|
202
|
+
variant="outlined"
|
|
203
|
+
sx={{
|
|
204
|
+
p: 2,
|
|
205
|
+
mt: 1,
|
|
206
|
+
bgcolor: 'grey.900',
|
|
207
|
+
color: 'grey.100',
|
|
208
|
+
maxHeight: 400,
|
|
209
|
+
overflow: 'auto',
|
|
210
|
+
}}
|
|
211
|
+
>
|
|
212
|
+
<pre style={{ margin: 0, whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>
|
|
213
|
+
{formatJson(log.properties)}
|
|
214
|
+
</pre>
|
|
215
|
+
</Paper>
|
|
216
|
+
</Box>
|
|
217
|
+
</DialogContent>
|
|
218
|
+
<DialogActions>
|
|
219
|
+
<Button onClick={onClose} color="primary">
|
|
220
|
+
Close
|
|
221
|
+
</Button>
|
|
222
|
+
</DialogActions>
|
|
223
|
+
</Dialog>
|
|
224
|
+
);
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Get event color chip based on event type
|
|
229
|
+
*/
|
|
230
|
+
const getEventChip = (event: string | null, logName?: string): React.ReactNode => {
|
|
231
|
+
const eventLower = (event || '').toLowerCase();
|
|
232
|
+
let color: 'success' | 'warning' | 'error' | 'info' | 'default' = 'default';
|
|
233
|
+
|
|
234
|
+
switch (eventLower) {
|
|
235
|
+
case 'created':
|
|
236
|
+
color = 'success';
|
|
237
|
+
break;
|
|
238
|
+
case 'updated':
|
|
239
|
+
color = 'warning';
|
|
240
|
+
break;
|
|
241
|
+
case 'deleted':
|
|
242
|
+
color = 'error';
|
|
243
|
+
break;
|
|
244
|
+
case 'restored':
|
|
245
|
+
color = 'info';
|
|
246
|
+
break;
|
|
247
|
+
default:
|
|
248
|
+
color = 'default';
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return (
|
|
252
|
+
<Chip
|
|
253
|
+
label={event || 'N/A'}
|
|
254
|
+
color={color}
|
|
255
|
+
size="small"
|
|
256
|
+
variant="outlined"
|
|
257
|
+
/>
|
|
258
|
+
);
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* View mode - Display audit logs as a DataGrid
|
|
263
|
+
*/
|
|
264
|
+
const AuditLogView: React.FC<AuditLogProps> = ({ resourceConfig, resource: resourceOverride }) => {
|
|
265
|
+
const record = useRecordContext();
|
|
266
|
+
const [paginationModel, setPaginationModel] = useState<GridPaginationModel>({
|
|
267
|
+
page: 0,
|
|
268
|
+
pageSize: 10,
|
|
269
|
+
});
|
|
270
|
+
const [dialogState, setDialogState] = useState<DialogState>({
|
|
271
|
+
open: false,
|
|
272
|
+
log: null,
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
// Build the audit endpoint URL - uses resource override, resourceConfig model, or default
|
|
276
|
+
const baseResource = resourceOverride || resourceConfig?.model || '';
|
|
277
|
+
const auditResource = `${baseResource}/audit`;
|
|
278
|
+
|
|
279
|
+
const { data, total, isLoading, error } = useGetList<ActivityLogRecord>(
|
|
280
|
+
auditResource,
|
|
281
|
+
{
|
|
282
|
+
pagination: {
|
|
283
|
+
page: paginationModel.page + 1,
|
|
284
|
+
perPage: paginationModel.pageSize,
|
|
285
|
+
},
|
|
286
|
+
sort: { field: 'created_at', order: 'DESC' },
|
|
287
|
+
filter: { subject_id: record?.id },
|
|
288
|
+
},
|
|
289
|
+
{ enabled: !!record?.id, refetchOnWindowFocus: false }
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
const handleViewLog = useCallback((log: ActivityLogRecord) => {
|
|
293
|
+
setDialogState({ open: true, log });
|
|
294
|
+
}, []);
|
|
295
|
+
|
|
296
|
+
const handleCloseDialog = useCallback(() => {
|
|
297
|
+
setDialogState({ open: false, log: null });
|
|
298
|
+
}, []);
|
|
299
|
+
|
|
300
|
+
const columns: GridColDef[] = useMemo(
|
|
301
|
+
() => [
|
|
302
|
+
{
|
|
303
|
+
field: 'id',
|
|
304
|
+
headerName: 'ID',
|
|
305
|
+
type: 'number',
|
|
306
|
+
width: 80,
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
field: 'event',
|
|
310
|
+
headerName: 'Event',
|
|
311
|
+
width: 120,
|
|
312
|
+
renderCell: (params) => getEventChip(params.value),
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
field: 'description',
|
|
316
|
+
headerName: 'Description',
|
|
317
|
+
flex: 1,
|
|
318
|
+
minWidth: 200,
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
field: 'causer_name',
|
|
322
|
+
headerName: 'Changed By',
|
|
323
|
+
width: 150,
|
|
324
|
+
valueGetter: (value, row) => row.causer_name || 'System',
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
field: 'created_at',
|
|
328
|
+
headerName: 'Date',
|
|
329
|
+
width: 180,
|
|
330
|
+
valueFormatter: (value) =>
|
|
331
|
+
value ? new Date(value).toLocaleString() : '',
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
field: 'actions',
|
|
335
|
+
headerName: 'Actions',
|
|
336
|
+
type: 'actions',
|
|
337
|
+
width: 100,
|
|
338
|
+
getActions: (params: GridRowParams<ActivityLogRecord>) => [
|
|
339
|
+
<Tooltip title="View Details" key="view">
|
|
340
|
+
<IconButton
|
|
341
|
+
size="small"
|
|
342
|
+
onClick={() => handleViewLog(params.row)}
|
|
343
|
+
color="primary"
|
|
344
|
+
>
|
|
345
|
+
<VisibilityIcon fontSize="small" />
|
|
346
|
+
</IconButton>
|
|
347
|
+
</Tooltip>,
|
|
348
|
+
],
|
|
349
|
+
},
|
|
350
|
+
],
|
|
351
|
+
[handleViewLog]
|
|
352
|
+
);
|
|
353
|
+
|
|
354
|
+
if (!record?.id) {
|
|
355
|
+
return (
|
|
356
|
+
<Paper variant="outlined" sx={{ p: 3, textAlign: 'center' }}>
|
|
357
|
+
<HistoryIcon sx={{ fontSize: 48, color: 'text.secondary', mb: 1 }} />
|
|
358
|
+
<Typography variant="body1" color="text.secondary">
|
|
359
|
+
Save the record first to view audit logs
|
|
360
|
+
</Typography>
|
|
361
|
+
</Paper>
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (isLoading) {
|
|
366
|
+
return <Loading />;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
if (error) {
|
|
370
|
+
return (
|
|
371
|
+
<Paper variant="outlined" sx={{ p: 2 }}>
|
|
372
|
+
<Typography color="error">
|
|
373
|
+
Error loading audit logs: {(error as any)?.message || 'Unknown error'}
|
|
374
|
+
</Typography>
|
|
375
|
+
</Paper>
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
if (!data || data.length === 0) {
|
|
380
|
+
return (
|
|
381
|
+
<Paper variant="outlined" sx={{ p: 3, textAlign: 'center' }}>
|
|
382
|
+
<HistoryIcon sx={{ fontSize: 48, color: 'text.secondary', mb: 1 }} />
|
|
383
|
+
<Typography variant="body1" color="text.secondary">
|
|
384
|
+
No audit logs available for this record
|
|
385
|
+
</Typography>
|
|
386
|
+
</Paper>
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
return (
|
|
391
|
+
<>
|
|
392
|
+
<Box sx={{ width: '100%' }}>
|
|
393
|
+
<Paper variant="outlined">
|
|
394
|
+
<MUIGrid
|
|
395
|
+
rows={data}
|
|
396
|
+
columns={columns}
|
|
397
|
+
rowCount={total || 0}
|
|
398
|
+
loading={isLoading}
|
|
399
|
+
pageSizeOptions={[5, 10, 25, 50]}
|
|
400
|
+
paginationModel={paginationModel}
|
|
401
|
+
paginationMode="server"
|
|
402
|
+
onPaginationModelChange={setPaginationModel}
|
|
403
|
+
disableRowSelectionOnClick
|
|
404
|
+
autoHeight
|
|
405
|
+
slots={{
|
|
406
|
+
toolbar: AuditToolbar,
|
|
407
|
+
}}
|
|
408
|
+
sx={{
|
|
409
|
+
'& .MuiDataGrid-cell:focus': {
|
|
410
|
+
outline: 'none',
|
|
411
|
+
},
|
|
412
|
+
}}
|
|
413
|
+
/>
|
|
414
|
+
</Paper>
|
|
415
|
+
</Box>
|
|
416
|
+
|
|
417
|
+
<AuditJsonDialog
|
|
418
|
+
open={dialogState.open}
|
|
419
|
+
log={dialogState.log}
|
|
420
|
+
onClose={handleCloseDialog}
|
|
421
|
+
/>
|
|
422
|
+
</>
|
|
423
|
+
);
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Edit mode - Same as view mode for audit logs (read-only)
|
|
428
|
+
*/
|
|
429
|
+
const AuditLogEdit: React.FC<AuditLogProps> = (props) => {
|
|
430
|
+
return <AuditLogView {...props} />;
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* List mode - Display placeholder (audit logs viewed in detail)
|
|
435
|
+
*/
|
|
436
|
+
const AuditLogList: React.FC<AuditLogProps> = () => {
|
|
437
|
+
return (
|
|
438
|
+
<Typography variant="body2" color="text.secondary">
|
|
439
|
+
—
|
|
440
|
+
</Typography>
|
|
441
|
+
);
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Main Component - Routes to appropriate view based on method
|
|
446
|
+
*
|
|
447
|
+
* @param props - Component props including resourceConfig and method
|
|
448
|
+
* @returns The appropriate audit log view component
|
|
449
|
+
*/
|
|
450
|
+
const AuditLog: React.FC<AuditLogProps> = (props) => {
|
|
451
|
+
const { method } = props;
|
|
452
|
+
|
|
453
|
+
switch (method) {
|
|
454
|
+
case 'view':
|
|
455
|
+
case 'show':
|
|
456
|
+
return <AuditLogView {...props} />;
|
|
457
|
+
case 'edit':
|
|
458
|
+
return <AuditLogEdit {...props} />;
|
|
459
|
+
case 'list':
|
|
460
|
+
return <AuditLogList {...props} />;
|
|
461
|
+
case 'create':
|
|
462
|
+
// No audit logs for new records
|
|
463
|
+
return (
|
|
464
|
+
<Paper variant="outlined" sx={{ p: 3, textAlign: 'center' }}>
|
|
465
|
+
<HistoryIcon sx={{ fontSize: 48, color: 'text.secondary', mb: 1 }} />
|
|
466
|
+
<Typography variant="body1" color="text.secondary">
|
|
467
|
+
Audit logs will be available after the record is created
|
|
468
|
+
</Typography>
|
|
469
|
+
</Paper>
|
|
470
|
+
);
|
|
471
|
+
default:
|
|
472
|
+
return <AuditLogView {...props} />;
|
|
473
|
+
}
|
|
474
|
+
};
|
|
475
|
+
|
|
476
|
+
export default AuditLog;
|