@dashadmin/dash-components 1.3.25 → 1.3.28

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.
Files changed (112) hide show
  1. package/README.md +35 -0
  2. package/dist/components/AuditLog/AuditLog.js +345 -1
  3. package/dist/components/AuditLog/index.js +4 -1
  4. package/dist/components/AutoCompleteArrayInput/AutoCompleteCheckBoxInput.js +630 -3
  5. package/dist/components/AutoCompleteArrayInput/AutocompleteCheckBoxArrayInput.js +53 -1
  6. package/dist/components/AutoCompleteArrayInputAutoSearch/AutoCompleteCheckBoxInput.js +647 -3
  7. package/dist/components/AutoCompleteArrayInputAutoSearch/AutocompleteCheckBoxArrayInput.js +53 -1
  8. package/dist/components/Json/Json.js +235 -1
  9. package/dist/components/JsonColorSelector/JsonColorSelector.js +1172 -1
  10. package/dist/components/JsonColorSelector/JsonColorSelectorEnhanced.js +863 -2
  11. package/dist/components/JsonColorSelector/JsonCssVarValues.js +738 -1
  12. package/dist/components/JsonColorSelector/components/ColorEditDialog.js +426 -1
  13. package/dist/components/JsonColorSelector/components/ColorPaletteItem.js +75 -1
  14. package/dist/components/JsonColorSelector/components/ImageColorExtractor.js +283 -1
  15. package/dist/components/JsonColorSelector/helpers/functions.js +101 -1
  16. package/dist/components/JsonColorSelector/useAsyncColorThief.js +105 -1
  17. package/dist/components/ListActive/ListActive.js +126 -1
  18. package/dist/components/ListActive/ListBoolean.js +124 -1
  19. package/dist/components/NotificationPreferences/NotificationPreferences.js +317 -1
  20. package/dist/components/NotificationPreferences/index.js +7 -1
  21. package/dist/components/SearchableSelects/RASearchableSelect.js +236 -1
  22. package/dist/components/SearchableSelects/RASearchableSelectCheckboxes.js +479 -1
  23. package/dist/components/SearchableSelects/RASearchableSelectChips.js +465 -1
  24. package/dist/components/SearchableSelects/RASearchableSelectChipsRecordContext.js +295 -1
  25. package/dist/components/SearchableSelects/SearchableSelect.js +202 -1
  26. package/dist/components/SearchableSelects/SearchableSelectCheckboxes.js +290 -1
  27. package/dist/components/SortableDataGrid/SortableDataGrid.js +72 -1
  28. package/dist/components/SortableDataGrid/SortableDataGridBody.js +167 -1
  29. package/dist/components/SortableDataGrid/SortableDataGridHeader.js +109 -1
  30. package/dist/components/SortableDataGrid/SortableDataGridRow.js +283 -1
  31. package/dist/components/Upload/SingleImageUploader.js +40 -1
  32. package/dist/components/custom/PackageCopyMethod.js +78 -1
  33. package/dist/components/custom/PackageRadioButtonGroup.js +45 -1
  34. package/dist/components/dialog/Basic.js +8 -1
  35. package/dist/components/dialog/Correct.js +14 -1
  36. package/dist/components/dialog/Error.js +14 -1
  37. package/dist/components/dialog/Info.js +14 -1
  38. package/dist/components/dialog/InfoV2.js +21 -1
  39. package/dist/components/dialog/NotFound.js +14 -1
  40. package/dist/components/dialog/QuickSearch.js +117 -1
  41. package/dist/components/notifications/NotificationsCenter.js +597 -1
  42. package/dist/components/notifications/index.js +24 -1
  43. package/dist/components/tables/PaginationComponent.js +36 -1
  44. package/dist/components/theme/AppLoadingFallback.js +38 -2
  45. package/dist/components/theme/ErrorBoundary.js +52 -1
  46. package/dist/components/theme/InitialLoader.js +13 -1
  47. package/dist/components/theme/NotFound.js +136 -1
  48. package/dist/components/theme/NotResults.js +38 -1
  49. package/dist/hooks/useDraggable.js +6 -1
  50. package/dist/hooks/useNotifications.js +8 -1
  51. package/dist/hooks/useQuickSearch.js +26 -1
  52. package/dist/index.js +66 -5567
  53. package/dist/utils/setNativeValue.js +17 -1
  54. package/package.json +148 -132
  55. package/src/components/AuditLog/AuditLog.tsx +476 -0
  56. package/src/components/AuditLog/index.ts +2 -0
  57. package/src/components/AutoCompleteArrayInput/AutoCompleteCheckBoxInput.tsx +917 -0
  58. package/src/components/AutoCompleteArrayInput/AutocompleteCheckBoxArrayInput.tsx +39 -0
  59. package/src/components/AutoCompleteArrayInputAutoSearch/AutoCompleteCheckBoxInput.tsx +916 -0
  60. package/src/components/AutoCompleteArrayInputAutoSearch/AutocompleteCheckBoxArrayInput.tsx +44 -0
  61. package/src/components/Json/Json.tsx +312 -0
  62. package/src/components/JsonColorSelector/JsonColorSelector.tsx +1435 -0
  63. package/src/components/JsonColorSelector/JsonColorSelectorEnhanced.tsx +1029 -0
  64. package/src/components/JsonColorSelector/JsonCssVarValues.tsx +863 -0
  65. package/src/components/JsonColorSelector/components/ColorEditDialog.tsx +491 -0
  66. package/src/components/JsonColorSelector/components/ColorPaletteItem.tsx +80 -0
  67. package/src/components/JsonColorSelector/components/ImageColorExtractor.tsx +328 -0
  68. package/src/components/JsonColorSelector/helpers/functions.tsx +123 -0
  69. package/src/components/JsonColorSelector/interfaces/interfaces.tsx +22 -0
  70. package/src/components/JsonColorSelector/useAsyncColorThief.tsx +97 -0
  71. package/src/components/ListActive/ListActive.tsx +106 -0
  72. package/src/components/ListActive/ListBoolean.tsx +96 -0
  73. package/src/components/NotificationPreferences/NotificationPreferences.tsx +463 -0
  74. package/src/components/NotificationPreferences/index.tsx +2 -0
  75. package/src/components/SearchableSelects/RASearchableSelect.tsx +300 -0
  76. package/src/components/SearchableSelects/RASearchableSelectCheckboxes.tsx +604 -0
  77. package/src/components/SearchableSelects/RASearchableSelectChips.tsx +558 -0
  78. package/src/components/SearchableSelects/RASearchableSelectChipsRecordContext.tsx +362 -0
  79. package/src/components/SearchableSelects/SearchableSelect.tsx +321 -0
  80. package/src/components/SearchableSelects/SearchableSelectCheckboxes.tsx +355 -0
  81. package/src/components/SortableDataGrid/SortableDataGrid.tsx +56 -0
  82. package/src/components/SortableDataGrid/SortableDataGridBody.tsx +175 -0
  83. package/src/components/SortableDataGrid/SortableDataGridHeader.tsx +171 -0
  84. package/src/components/SortableDataGrid/SortableDataGridRow.tsx +247 -0
  85. package/src/components/Upload/SingleImageUploader.tsx +55 -0
  86. package/src/components/custom/PackageCopyMethod.tsx +109 -0
  87. package/src/components/custom/PackageRadioButtonGroup.tsx +47 -0
  88. package/src/components/dialog/Basic.tsx +11 -0
  89. package/src/components/dialog/Correct.tsx +16 -0
  90. package/src/components/dialog/Error.tsx +15 -0
  91. package/src/components/dialog/Info.tsx +15 -0
  92. package/src/components/dialog/InfoV2.tsx +35 -0
  93. package/src/components/dialog/NotFound.tsx +18 -0
  94. package/src/components/dialog/QuickSearch.tsx +115 -0
  95. package/src/components/notifications/NotificationsCenter.tsx +792 -0
  96. package/src/components/notifications/index.ts +42 -0
  97. package/src/components/tables/PaginationComponent.tsx +17 -0
  98. package/src/components/theme/AppLoadingFallback.tsx +42 -0
  99. package/src/components/theme/ErrorBoundary.tsx +57 -0
  100. package/src/components/theme/InitialLoader.tsx +16 -0
  101. package/src/components/theme/NotFound.tsx +124 -0
  102. package/src/components/theme/NotResults.tsx +54 -0
  103. package/src/hooks/useDraggable.ts +11 -0
  104. package/src/hooks/useNotifications.ts +14 -0
  105. package/src/hooks/useQuickSearch.tsx +29 -0
  106. package/src/index.tsx +77 -0
  107. package/src/utils/setNativeValue.tsx +23 -0
  108. package/dist/color-thief-CTwGFhOB.js +0 -272
  109. /package/{dist → src}/components/AutoCompleteArrayInputAutoSearch/AutocompleteCheckBoxArrayAutoSearch.tsx.wip +0 -0
  110. /package/{dist → src}/components/JsonColorSelector/JsonColorSelector.tsx.bkup +0 -0
  111. /package/{dist → src}/components/SortableDataGrid/README.md +0 -0
  112. /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;
@@ -0,0 +1,2 @@
1
+ export { default as AuditLog } from './AuditLog';
2
+ export type { AuditLogProps, ActivityLogRecord } from './AuditLog';