robobyte-front-builder 1.0.17 → 1.0.19
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/package.json +1 -1
- package/src/lib/providers/RoboByteFrontBuilderProvider.jsx +6 -2
- package/src/pages/reportModule/reportBuilder/index.js +719 -561
- package/src/pages/reportModule/reportBuilder/reportViewer/index.js +135 -80
- package/src/pages/reportModule/reportBuilder/reports/index.js +51 -11
- package/src/pages/reportModule/reportBuilder/reportsPermissions/index.js +127 -0
- package/src/services/helper/multiSelectEditorByBuilder.js +245 -0
- package/src/services/helper/reportSessionHelper.js +83 -0
- package/src/views/genericTable/ColumnConfiguratorDialog.js +762 -0
- package/src/views/genericTable/FormattingSettingsDialog.js +546 -0
- package/src/views/genericTable/ReportSettingsDialog.js +151 -0
- package/src/views/genericTable/SGrid.js +872 -159
- package/src/views/genericTable/TAGGrid.js +83 -69
- package/src/views/genericTable/convertStringFunctions.js +200 -0
- package/src/views/genericTable/updateRefHelpers.js +421 -0
- package/src/views/rolePermissions/UpdateReportPermissionDialog.js +315 -0
|
@@ -0,0 +1,762 @@
|
|
|
1
|
+
import React, {useState, useRef} from 'react'
|
|
2
|
+
import {
|
|
3
|
+
Dialog,
|
|
4
|
+
DialogTitle,
|
|
5
|
+
DialogContent,
|
|
6
|
+
DialogActions,
|
|
7
|
+
Button,
|
|
8
|
+
Box,
|
|
9
|
+
Typography,
|
|
10
|
+
TextField,
|
|
11
|
+
IconButton,
|
|
12
|
+
List,
|
|
13
|
+
ListItem,
|
|
14
|
+
Paper,
|
|
15
|
+
Divider,
|
|
16
|
+
Accordion,
|
|
17
|
+
AccordionSummary,
|
|
18
|
+
AccordionDetails,
|
|
19
|
+
Alert,
|
|
20
|
+
Autocomplete,
|
|
21
|
+
Checkbox,
|
|
22
|
+
FormControlLabel
|
|
23
|
+
} from '@mui/material'
|
|
24
|
+
import {Add, Delete, ContentCopy, ExpandMore, Edit} from '@mui/icons-material'
|
|
25
|
+
import dynamic from 'next/dynamic'
|
|
26
|
+
|
|
27
|
+
const MonacoEditor = dynamic(() => import('@monaco-editor/react'), {ssr: false})
|
|
28
|
+
|
|
29
|
+
// Common AG Grid cell renderers
|
|
30
|
+
const CELL_RENDERERS = [
|
|
31
|
+
'agCheckboxCellRenderer',
|
|
32
|
+
'agGroupCellRenderer',
|
|
33
|
+
'agAnimateShowChangeCellRenderer',
|
|
34
|
+
'agAnimateSlideCellRenderer',
|
|
35
|
+
'agLoadingCellRenderer',
|
|
36
|
+
'agSkeletonCellRenderer',
|
|
37
|
+
'agSparklineCellRenderer'
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
// Common AG Grid cell editors
|
|
41
|
+
const CELL_EDITORS = [
|
|
42
|
+
'agTextCellEditor',
|
|
43
|
+
'agSelectCellEditor',
|
|
44
|
+
'agRichSelectCellEditor',
|
|
45
|
+
'agLargeTextCellEditor',
|
|
46
|
+
'agNumberCellEditor',
|
|
47
|
+
'agDateCellEditor',
|
|
48
|
+
'agDateStringCellEditor',
|
|
49
|
+
'agCheckboxCellEditor',
|
|
50
|
+
'MultiSelectEditorWrapper'
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
const ColumnConfiguratorDialog = ({open, onClose, onResult}) => {
|
|
54
|
+
const [extraCols, setExtraCols] = useState([])
|
|
55
|
+
const [columnsConfig, setColumnsConfig] = useState([])
|
|
56
|
+
const [editingExtraColIndex, setEditingExtraColIndex] = useState(null)
|
|
57
|
+
const [editingColumnConfigIndex, setEditingColumnConfigIndex] = useState(null)
|
|
58
|
+
const [newExtraCol, setNewExtraCol] = useState({
|
|
59
|
+
headerName: '',
|
|
60
|
+
field: '',
|
|
61
|
+
editable: true,
|
|
62
|
+
cellRenderer: '',
|
|
63
|
+
cellEditor: '',
|
|
64
|
+
cellEditorParams: '',
|
|
65
|
+
valueSetter: '',
|
|
66
|
+
valueGetter: '',
|
|
67
|
+
additionalParams: ''
|
|
68
|
+
})
|
|
69
|
+
const [newColumnConfig, setNewColumnConfig] = useState({
|
|
70
|
+
field: '',
|
|
71
|
+
editable: false,
|
|
72
|
+
cellRenderer: '',
|
|
73
|
+
cellEditor: '',
|
|
74
|
+
cellEditorParams: '',
|
|
75
|
+
valueSetter: '',
|
|
76
|
+
valueGetter: '',
|
|
77
|
+
additionalParams: ''
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
const handleAddExtraCol = () => {
|
|
81
|
+
if (!newExtraCol.headerName || !newExtraCol.field) {
|
|
82
|
+
return
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (editingExtraColIndex !== null) {
|
|
86
|
+
// Update existing
|
|
87
|
+
const updated = [...extraCols]
|
|
88
|
+
updated[editingExtraColIndex] = {...newExtraCol}
|
|
89
|
+
setExtraCols(updated)
|
|
90
|
+
setEditingExtraColIndex(null)
|
|
91
|
+
} else {
|
|
92
|
+
// Add new
|
|
93
|
+
setExtraCols([...extraCols, {...newExtraCol}])
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
setNewExtraCol({
|
|
97
|
+
headerName: '',
|
|
98
|
+
field: '',
|
|
99
|
+
editable: true,
|
|
100
|
+
cellRenderer: '',
|
|
101
|
+
cellEditor: '',
|
|
102
|
+
cellEditorParams: '',
|
|
103
|
+
valueSetter: '',
|
|
104
|
+
valueGetter: '',
|
|
105
|
+
additionalParams: ''
|
|
106
|
+
})
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const handleEditExtraCol = (index) => {
|
|
110
|
+
setNewExtraCol({...extraCols[index]})
|
|
111
|
+
setEditingExtraColIndex(index)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const handleCancelEditExtraCol = () => {
|
|
115
|
+
setNewExtraCol({
|
|
116
|
+
headerName: '',
|
|
117
|
+
field: '',
|
|
118
|
+
editable: true,
|
|
119
|
+
cellRenderer: '',
|
|
120
|
+
cellEditor: '',
|
|
121
|
+
cellEditorParams: '',
|
|
122
|
+
valueSetter: '',
|
|
123
|
+
valueGetter: '',
|
|
124
|
+
additionalParams: ''
|
|
125
|
+
})
|
|
126
|
+
setEditingExtraColIndex(null)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const handleRemoveExtraCol = (index) => {
|
|
130
|
+
setExtraCols(extraCols.filter((_, i) => i !== index))
|
|
131
|
+
if (editingExtraColIndex === index) {
|
|
132
|
+
handleCancelEditExtraCol()
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const handleAddColumnConfig = () => {
|
|
137
|
+
if (!newColumnConfig.field) {
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (editingColumnConfigIndex !== null) {
|
|
142
|
+
// Update existing
|
|
143
|
+
const updated = [...columnsConfig]
|
|
144
|
+
updated[editingColumnConfigIndex] = {...newColumnConfig}
|
|
145
|
+
setColumnsConfig(updated)
|
|
146
|
+
setEditingColumnConfigIndex(null)
|
|
147
|
+
} else {
|
|
148
|
+
// Add new
|
|
149
|
+
setColumnsConfig([...columnsConfig, {...newColumnConfig}])
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
setNewColumnConfig({
|
|
153
|
+
field: '',
|
|
154
|
+
editable: false,
|
|
155
|
+
cellRenderer: '',
|
|
156
|
+
cellEditor: '',
|
|
157
|
+
cellEditorParams: '',
|
|
158
|
+
valueSetter: '',
|
|
159
|
+
valueGetter: '',
|
|
160
|
+
additionalParams: ''
|
|
161
|
+
})
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const handleEditColumnConfig = (index) => {
|
|
165
|
+
setNewColumnConfig({...columnsConfig[index]})
|
|
166
|
+
setEditingColumnConfigIndex(index)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const handleCancelEditColumnConfig = () => {
|
|
170
|
+
setNewColumnConfig({
|
|
171
|
+
field: '',
|
|
172
|
+
editable: false,
|
|
173
|
+
cellRenderer: '',
|
|
174
|
+
cellEditor: '',
|
|
175
|
+
cellEditorParams: '',
|
|
176
|
+
valueSetter: '',
|
|
177
|
+
valueGetter: '',
|
|
178
|
+
additionalParams: ''
|
|
179
|
+
})
|
|
180
|
+
setEditingColumnConfigIndex(null)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const handleRemoveColumnConfig = (index) => {
|
|
184
|
+
setColumnsConfig(columnsConfig.filter((_, i) => i !== index))
|
|
185
|
+
if (editingColumnConfigIndex === index) {
|
|
186
|
+
handleCancelEditColumnConfig()
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const buildResult = () => {
|
|
191
|
+
const processedExtraCols = extraCols.map(col => {
|
|
192
|
+
console.log('Processing extraCol:', col.field, 'additionalParams:', col.additionalParams)
|
|
193
|
+
|
|
194
|
+
const colDef = {
|
|
195
|
+
headerName: col.headerName,
|
|
196
|
+
field: col.field,
|
|
197
|
+
editable: col.editable
|
|
198
|
+
}
|
|
199
|
+
if (col.cellRenderer) colDef.cellRenderer = col.cellRenderer
|
|
200
|
+
if (col.cellEditor) colDef.cellEditor = col.cellEditor
|
|
201
|
+
if (col.cellEditorParams) colDef.cellEditorParams = col.cellEditorParams
|
|
202
|
+
if (col.valueSetter) colDef.valueSetter = col.valueSetter
|
|
203
|
+
if (col.valueGetter) colDef.valueGetter = col.valueGetter
|
|
204
|
+
|
|
205
|
+
// Parse and merge additional params
|
|
206
|
+
if (col.additionalParams && col.additionalParams.trim()) {
|
|
207
|
+
console.log('Attempting to parse:', `{${col.additionalParams}}`)
|
|
208
|
+
try {
|
|
209
|
+
const additionalObj = JSON.parse(`{${col.additionalParams}}`)
|
|
210
|
+
console.log('Parsed successfully:', additionalObj)
|
|
211
|
+
Object.assign(colDef, additionalObj)
|
|
212
|
+
} catch (e) {
|
|
213
|
+
console.error('Failed to parse additionalParams for extraCol:', col.additionalParams, e)
|
|
214
|
+
}
|
|
215
|
+
} else {
|
|
216
|
+
console.log('additionalParams is empty or whitespace')
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return colDef
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
const processedColumnsConfig = columnsConfig.map(config => {
|
|
223
|
+
const configObj = {
|
|
224
|
+
editable: config.editable,
|
|
225
|
+
...(config.valueSetter && {valueSetter: config.valueSetter}),
|
|
226
|
+
...(config.valueGetter && {valueGetter: config.valueGetter})
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (config.cellRenderer) configObj.cellRenderer = config.cellRenderer
|
|
230
|
+
if (config.cellEditor) configObj.cellEditor = config.cellEditor
|
|
231
|
+
if (config.cellEditorParams) configObj.cellEditorParams = config.cellEditorParams
|
|
232
|
+
|
|
233
|
+
// Parse and merge additional params
|
|
234
|
+
if (config.additionalParams && config.additionalParams.trim()) {
|
|
235
|
+
try {
|
|
236
|
+
const additionalObj = JSON.parse(`{${config.additionalParams}}`)
|
|
237
|
+
Object.assign(configObj, additionalObj)
|
|
238
|
+
} catch (e) {
|
|
239
|
+
console.warn('Failed to parse additionalParams for columnConfig:', config.additionalParams, e)
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
field: config.field,
|
|
245
|
+
config: configObj
|
|
246
|
+
}
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
return {
|
|
250
|
+
extraCols: processedExtraCols,
|
|
251
|
+
columnsConfig: processedColumnsConfig
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const handleGenerate = () => {
|
|
256
|
+
const result = buildResult()
|
|
257
|
+
onResult(result)
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const handleCopyJSON = () => {
|
|
261
|
+
const result = buildResult()
|
|
262
|
+
navigator.clipboard.writeText(JSON.stringify(result, null, 2))
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return (
|
|
266
|
+
<Dialog open={open} onClose={onClose} maxWidth="lg" fullWidth>
|
|
267
|
+
<DialogTitle>
|
|
268
|
+
<Box display="flex" justifyContent="space-between" alignItems="center">
|
|
269
|
+
<Typography variant="h6">Column Configurator</Typography>
|
|
270
|
+
<IconButton onClick={handleCopyJSON} size="small" title="Copy JSON to clipboard">
|
|
271
|
+
<ContentCopy/>
|
|
272
|
+
</IconButton>
|
|
273
|
+
</Box>
|
|
274
|
+
</DialogTitle>
|
|
275
|
+
<DialogContent>
|
|
276
|
+
<Box sx={{display: 'flex', flexDirection: 'column', gap: 3}}>
|
|
277
|
+
{/* Extra Columns Section */}
|
|
278
|
+
<Accordion defaultExpanded>
|
|
279
|
+
<AccordionSummary expandIcon={<ExpandMore/>}>
|
|
280
|
+
<Typography variant="h6">Extra Columns ({extraCols.length})</Typography>
|
|
281
|
+
</AccordionSummary>
|
|
282
|
+
<AccordionDetails>
|
|
283
|
+
<Box sx={{display: 'flex', flexDirection: 'column', gap: 2}}>
|
|
284
|
+
<Alert severity="info" sx={{mb: 2}}>
|
|
285
|
+
Extra columns are additional columns that don't exist in the report data. They can be used for
|
|
286
|
+
custom fields with editable values.
|
|
287
|
+
</Alert>
|
|
288
|
+
|
|
289
|
+
<Paper sx={{p: 2, bgcolor: 'background.default'}}>
|
|
290
|
+
<Box sx={{display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2}}>
|
|
291
|
+
<Typography variant="subtitle2">
|
|
292
|
+
{editingExtraColIndex !== null ? 'Edit Extra Column' : 'Add New Extra Column'}
|
|
293
|
+
</Typography>
|
|
294
|
+
{editingExtraColIndex !== null && (
|
|
295
|
+
<Button size="small" onClick={handleCancelEditExtraCol}>
|
|
296
|
+
Cancel Edit
|
|
297
|
+
</Button>
|
|
298
|
+
)}
|
|
299
|
+
</Box>
|
|
300
|
+
<Box sx={{display: 'flex', gap: 2, flexWrap: 'wrap', alignItems: 'flex-start'}}>
|
|
301
|
+
<TextField
|
|
302
|
+
size="small"
|
|
303
|
+
label="Header Name"
|
|
304
|
+
value={newExtraCol.headerName}
|
|
305
|
+
onChange={(e) => setNewExtraCol({...newExtraCol, headerName: e.target.value})}
|
|
306
|
+
sx={{flex: 1, minWidth: 150}}
|
|
307
|
+
/>
|
|
308
|
+
<TextField
|
|
309
|
+
size="small"
|
|
310
|
+
label="Field"
|
|
311
|
+
value={newExtraCol.field}
|
|
312
|
+
onChange={(e) => setNewExtraCol({...newExtraCol, field: e.target.value})}
|
|
313
|
+
sx={{flex: 1, minWidth: 150}}
|
|
314
|
+
/>
|
|
315
|
+
<FormControlLabel
|
|
316
|
+
control={
|
|
317
|
+
<Checkbox
|
|
318
|
+
checked={newExtraCol.editable}
|
|
319
|
+
onChange={(e) => setNewExtraCol({...newExtraCol, editable: e.target.checked})}
|
|
320
|
+
/>
|
|
321
|
+
}
|
|
322
|
+
label="Editable"
|
|
323
|
+
sx={{minWidth: 100}}
|
|
324
|
+
/>
|
|
325
|
+
<Autocomplete
|
|
326
|
+
size="small"
|
|
327
|
+
freeSolo
|
|
328
|
+
options={CELL_RENDERERS}
|
|
329
|
+
value={newExtraCol.cellRenderer}
|
|
330
|
+
onChange={(e, newValue) => setNewExtraCol({...newExtraCol, cellRenderer: newValue || ''})}
|
|
331
|
+
onInputChange={(e, newValue) => setNewExtraCol({...newExtraCol, cellRenderer: newValue || ''})}
|
|
332
|
+
renderInput={(params) => (
|
|
333
|
+
<TextField
|
|
334
|
+
{...params}
|
|
335
|
+
label="Cell Renderer"
|
|
336
|
+
placeholder="agCheckboxCellRenderer"
|
|
337
|
+
/>
|
|
338
|
+
)}
|
|
339
|
+
sx={{flex: 1, minWidth: 200}}
|
|
340
|
+
/>
|
|
341
|
+
<Autocomplete
|
|
342
|
+
size="small"
|
|
343
|
+
freeSolo
|
|
344
|
+
options={CELL_EDITORS}
|
|
345
|
+
value={newExtraCol.cellEditor}
|
|
346
|
+
onChange={(e, newValue) => setNewExtraCol({...newExtraCol, cellEditor: newValue || ''})}
|
|
347
|
+
onInputChange={(e, newValue) => setNewExtraCol({...newExtraCol, cellEditor: newValue || ''})}
|
|
348
|
+
renderInput={(params) => (
|
|
349
|
+
<TextField
|
|
350
|
+
{...params}
|
|
351
|
+
label="Cell Editor"
|
|
352
|
+
placeholder="agCheckboxCellEditor"
|
|
353
|
+
/>
|
|
354
|
+
)}
|
|
355
|
+
sx={{flex: 1, minWidth: 200}}
|
|
356
|
+
/>
|
|
357
|
+
</Box>
|
|
358
|
+
{newExtraCol.cellEditor === 'MultiSelectEditorWrapper' && (
|
|
359
|
+
<Box sx={{mt: 2}}>
|
|
360
|
+
<Alert severity="warning" sx={{mb: 2}}>
|
|
361
|
+
<Typography variant="caption">
|
|
362
|
+
MultiSelectEditorWrapper requires cellEditorParams with: fieldName, filterFields, uniqueId,
|
|
363
|
+
value, isSingle, asyncFetchOptions
|
|
364
|
+
</Typography>
|
|
365
|
+
</Alert>
|
|
366
|
+
<Typography variant="caption" sx={{mb: 1, display: 'block'}}>
|
|
367
|
+
Cell Editor Params (Function or Object)
|
|
368
|
+
</Typography>
|
|
369
|
+
<Box sx={{border: '1px solid #ddd', borderRadius: 1}}>
|
|
370
|
+
<MonacoEditor
|
|
371
|
+
height="200px"
|
|
372
|
+
language="javascript"
|
|
373
|
+
theme="vs-dark"
|
|
374
|
+
value={newExtraCol.cellEditorParams}
|
|
375
|
+
onChange={(value) => setNewExtraCol({...newExtraCol, cellEditorParams: value || ''})}
|
|
376
|
+
options={{
|
|
377
|
+
minimap: {enabled: false},
|
|
378
|
+
fontSize: 12,
|
|
379
|
+
lineNumbers: 'on',
|
|
380
|
+
scrollBeyondLastLine: false,
|
|
381
|
+
automaticLayout: true
|
|
382
|
+
}}
|
|
383
|
+
/>
|
|
384
|
+
</Box>
|
|
385
|
+
</Box>
|
|
386
|
+
)}
|
|
387
|
+
<Box sx={{mt: 2}}>
|
|
388
|
+
<Typography variant="caption" sx={{mb: 1, display: 'block'}}>
|
|
389
|
+
Value Setter (optional)
|
|
390
|
+
</Typography>
|
|
391
|
+
<Box sx={{border: '1px solid #ddd', borderRadius: 1}}>
|
|
392
|
+
<MonacoEditor
|
|
393
|
+
height="120px"
|
|
394
|
+
language="javascript"
|
|
395
|
+
theme="vs-dark"
|
|
396
|
+
value={newExtraCol.valueSetter}
|
|
397
|
+
onChange={(value) => setNewExtraCol({...newExtraCol, valueSetter: value || ''})}
|
|
398
|
+
options={{
|
|
399
|
+
minimap: {enabled: false},
|
|
400
|
+
fontSize: 12,
|
|
401
|
+
lineNumbers: 'on',
|
|
402
|
+
scrollBeyondLastLine: false,
|
|
403
|
+
automaticLayout: true
|
|
404
|
+
}}
|
|
405
|
+
/>
|
|
406
|
+
</Box>
|
|
407
|
+
</Box>
|
|
408
|
+
<Box sx={{mt: 2}}>
|
|
409
|
+
<Typography variant="caption" sx={{mb: 1, display: 'block'}}>
|
|
410
|
+
Value Getter (optional)
|
|
411
|
+
</Typography>
|
|
412
|
+
<Box sx={{border: '1px solid #ddd', borderRadius: 1}}>
|
|
413
|
+
<MonacoEditor
|
|
414
|
+
height="120px"
|
|
415
|
+
language="javascript"
|
|
416
|
+
theme="vs-dark"
|
|
417
|
+
value={newExtraCol.valueGetter}
|
|
418
|
+
onChange={(value) => setNewExtraCol({...newExtraCol, valueGetter: value || ''})}
|
|
419
|
+
options={{
|
|
420
|
+
minimap: {enabled: false},
|
|
421
|
+
fontSize: 12,
|
|
422
|
+
lineNumbers: 'on',
|
|
423
|
+
scrollBeyondLastLine: false,
|
|
424
|
+
automaticLayout: true
|
|
425
|
+
}}
|
|
426
|
+
/>
|
|
427
|
+
</Box>
|
|
428
|
+
</Box>
|
|
429
|
+
<Box sx={{mt: 2}}>
|
|
430
|
+
<Typography variant="caption" sx={{mb: 1, display: 'block'}}>
|
|
431
|
+
Additional Column Parameters (valueFormatter, width, etc.)
|
|
432
|
+
</Typography>
|
|
433
|
+
<Alert severity="info" sx={{mb: 1, fontSize: '0.75rem'}}>
|
|
434
|
+
Add any AG Grid column properties as key-value pairs (without outer braces).
|
|
435
|
+
Example: valueFormatter: (p) => p.value?.name, width: 200
|
|
436
|
+
</Alert>
|
|
437
|
+
<Box sx={{border: '1px solid #ddd', borderRadius: 1}}>
|
|
438
|
+
<MonacoEditor
|
|
439
|
+
height="150px"
|
|
440
|
+
language="javascript"
|
|
441
|
+
theme="vs-dark"
|
|
442
|
+
value={newExtraCol.additionalParams}
|
|
443
|
+
onChange={(value) => setNewExtraCol({...newExtraCol, additionalParams: value || ''})}
|
|
444
|
+
options={{
|
|
445
|
+
minimap: {enabled: false},
|
|
446
|
+
fontSize: 12,
|
|
447
|
+
lineNumbers: 'on',
|
|
448
|
+
scrollBeyondLastLine: false,
|
|
449
|
+
automaticLayout: true
|
|
450
|
+
}}
|
|
451
|
+
/>
|
|
452
|
+
</Box>
|
|
453
|
+
</Box>
|
|
454
|
+
<Box sx={{display: 'flex', justifyContent: 'flex-end', mt: 2}}>
|
|
455
|
+
<Button
|
|
456
|
+
variant="contained"
|
|
457
|
+
startIcon={editingExtraColIndex !== null ? <Edit/> : <Add/>}
|
|
458
|
+
onClick={handleAddExtraCol}
|
|
459
|
+
disabled={!newExtraCol.headerName || !newExtraCol.field}
|
|
460
|
+
>
|
|
461
|
+
{editingExtraColIndex !== null ? 'Update' : 'Add'}
|
|
462
|
+
</Button>
|
|
463
|
+
</Box>
|
|
464
|
+
</Paper>
|
|
465
|
+
|
|
466
|
+
<List sx={{bgcolor: 'background.paper', borderRadius: 1}}>
|
|
467
|
+
{extraCols.map((col, index) => (
|
|
468
|
+
<ListItem
|
|
469
|
+
key={index}
|
|
470
|
+
secondaryAction={
|
|
471
|
+
<Box>
|
|
472
|
+
<IconButton onClick={() => handleEditExtraCol(index)}>
|
|
473
|
+
<Edit/>
|
|
474
|
+
</IconButton>
|
|
475
|
+
<IconButton edge="end" onClick={() => handleRemoveExtraCol(index)}>
|
|
476
|
+
<Delete/>
|
|
477
|
+
</IconButton>
|
|
478
|
+
</Box>
|
|
479
|
+
}
|
|
480
|
+
>
|
|
481
|
+
<Box sx={{width: '100%'}}>
|
|
482
|
+
<Typography variant="body1" fontWeight="bold">
|
|
483
|
+
{col.headerName} ({col.field})
|
|
484
|
+
</Typography>
|
|
485
|
+
<Typography variant="caption" color="text.secondary" component="div">
|
|
486
|
+
Editable: {col.editable ? 'Yes' : 'No'} | Renderer: {col.cellRenderer || 'default'} | Editor: {col.cellEditor || 'default'}
|
|
487
|
+
{col.cellEditorParams && <> | Has cellEditorParams</>}
|
|
488
|
+
{col.valueSetter && <> | Has valueSetter</>}
|
|
489
|
+
{col.valueGetter && <> | Has valueGetter</>}
|
|
490
|
+
{col.additionalParams && <> | Has additionalParams</>}
|
|
491
|
+
</Typography>
|
|
492
|
+
</Box>
|
|
493
|
+
</ListItem>
|
|
494
|
+
))}
|
|
495
|
+
{extraCols.length === 0 && (
|
|
496
|
+
<ListItem>
|
|
497
|
+
<Typography variant="body2" color="text.secondary">
|
|
498
|
+
No extra columns defined yet
|
|
499
|
+
</Typography>
|
|
500
|
+
</ListItem>
|
|
501
|
+
)}
|
|
502
|
+
</List>
|
|
503
|
+
</Box>
|
|
504
|
+
</AccordionDetails>
|
|
505
|
+
</Accordion>
|
|
506
|
+
|
|
507
|
+
{/* Column Config Section */}
|
|
508
|
+
<Accordion defaultExpanded>
|
|
509
|
+
<AccordionSummary expandIcon={<ExpandMore/>}>
|
|
510
|
+
<Typography variant="h6">Column Configurations ({columnsConfig.length})</Typography>
|
|
511
|
+
</AccordionSummary>
|
|
512
|
+
<AccordionDetails>
|
|
513
|
+
<Box sx={{display: 'flex', flexDirection: 'column', gap: 2}}>
|
|
514
|
+
<Alert severity="info" sx={{mb: 2}}>
|
|
515
|
+
Column configurations modify existing columns in the report. Use valueSetter and valueGetter to
|
|
516
|
+
manage custom values.
|
|
517
|
+
</Alert>
|
|
518
|
+
|
|
519
|
+
<Paper sx={{p: 2, bgcolor: 'background.default'}}>
|
|
520
|
+
<Box sx={{display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2}}>
|
|
521
|
+
<Typography variant="subtitle2">
|
|
522
|
+
{editingColumnConfigIndex !== null ? 'Edit Column Config' : 'Add New Column Config'}
|
|
523
|
+
</Typography>
|
|
524
|
+
{editingColumnConfigIndex !== null && (
|
|
525
|
+
<Button size="small" onClick={handleCancelEditColumnConfig}>
|
|
526
|
+
Cancel Edit
|
|
527
|
+
</Button>
|
|
528
|
+
)}
|
|
529
|
+
</Box>
|
|
530
|
+
<Box sx={{display: 'flex', flexDirection: 'column', gap: 2}}>
|
|
531
|
+
<TextField
|
|
532
|
+
size="small"
|
|
533
|
+
label="Field Name"
|
|
534
|
+
value={newColumnConfig.field}
|
|
535
|
+
onChange={(e) => setNewColumnConfig({...newColumnConfig, field: e.target.value})}
|
|
536
|
+
fullWidth
|
|
537
|
+
/>
|
|
538
|
+
<FormControlLabel
|
|
539
|
+
control={
|
|
540
|
+
<Checkbox
|
|
541
|
+
checked={newColumnConfig.editable}
|
|
542
|
+
onChange={(e) => setNewColumnConfig({...newColumnConfig, editable: e.target.checked})}
|
|
543
|
+
/>
|
|
544
|
+
}
|
|
545
|
+
label="Editable"
|
|
546
|
+
/>
|
|
547
|
+
<Box sx={{display: 'flex', gap: 2}}>
|
|
548
|
+
<Autocomplete
|
|
549
|
+
size="small"
|
|
550
|
+
freeSolo
|
|
551
|
+
options={CELL_RENDERERS}
|
|
552
|
+
value={newColumnConfig.cellRenderer}
|
|
553
|
+
onChange={(e, newValue) => setNewColumnConfig({...newColumnConfig, cellRenderer: newValue || ''})}
|
|
554
|
+
onInputChange={(e, newValue) => setNewColumnConfig({...newColumnConfig, cellRenderer: newValue || ''})}
|
|
555
|
+
renderInput={(params) => (
|
|
556
|
+
<TextField
|
|
557
|
+
{...params}
|
|
558
|
+
label="Cell Renderer"
|
|
559
|
+
placeholder="agCheckboxCellRenderer"
|
|
560
|
+
/>
|
|
561
|
+
)}
|
|
562
|
+
sx={{flex: 1}}
|
|
563
|
+
/>
|
|
564
|
+
<Autocomplete
|
|
565
|
+
size="small"
|
|
566
|
+
freeSolo
|
|
567
|
+
options={CELL_EDITORS}
|
|
568
|
+
value={newColumnConfig.cellEditor}
|
|
569
|
+
onChange={(e, newValue) => setNewColumnConfig({...newColumnConfig, cellEditor: newValue || ''})}
|
|
570
|
+
onInputChange={(e, newValue) => setNewColumnConfig({...newColumnConfig, cellEditor: newValue || ''})}
|
|
571
|
+
renderInput={(params) => (
|
|
572
|
+
<TextField
|
|
573
|
+
{...params}
|
|
574
|
+
label="Cell Editor"
|
|
575
|
+
placeholder="agCheckboxCellEditor"
|
|
576
|
+
/>
|
|
577
|
+
)}
|
|
578
|
+
sx={{flex: 1}}
|
|
579
|
+
/>
|
|
580
|
+
</Box>
|
|
581
|
+
{newColumnConfig.cellEditor === 'MultiSelectEditorWrapper' && (
|
|
582
|
+
<Box>
|
|
583
|
+
<Alert severity="warning" sx={{mb: 1}}>
|
|
584
|
+
<Typography variant="caption">
|
|
585
|
+
MultiSelectEditorWrapper requires cellEditorParams with: fieldName, filterFields, uniqueId,
|
|
586
|
+
value, isSingle, asyncFetchOptions
|
|
587
|
+
</Typography>
|
|
588
|
+
</Alert>
|
|
589
|
+
<Typography variant="caption" sx={{mb: 1, display: 'block'}}>
|
|
590
|
+
Cell Editor Params (Function or Object)
|
|
591
|
+
</Typography>
|
|
592
|
+
<Box sx={{border: '1px solid #ddd', borderRadius: 1}}>
|
|
593
|
+
<MonacoEditor
|
|
594
|
+
height="150px"
|
|
595
|
+
language="javascript"
|
|
596
|
+
theme="vs-dark"
|
|
597
|
+
value={newColumnConfig.cellEditorParams}
|
|
598
|
+
onChange={(value) => setNewColumnConfig({...newColumnConfig, cellEditorParams: value || ''})}
|
|
599
|
+
options={{
|
|
600
|
+
minimap: {enabled: false},
|
|
601
|
+
fontSize: 12,
|
|
602
|
+
lineNumbers: 'on',
|
|
603
|
+
scrollBeyondLastLine: false,
|
|
604
|
+
automaticLayout: true
|
|
605
|
+
}}
|
|
606
|
+
/>
|
|
607
|
+
</Box>
|
|
608
|
+
</Box>
|
|
609
|
+
)}
|
|
610
|
+
<Box>
|
|
611
|
+
<Typography variant="caption" sx={{mb: 1, display: 'block'}}>
|
|
612
|
+
Value Setter (optional)
|
|
613
|
+
</Typography>
|
|
614
|
+
<Box sx={{border: '1px solid #ddd', borderRadius: 1}}>
|
|
615
|
+
<MonacoEditor
|
|
616
|
+
height="120px"
|
|
617
|
+
language="javascript"
|
|
618
|
+
theme="vs-dark"
|
|
619
|
+
value={newColumnConfig.valueSetter}
|
|
620
|
+
onChange={(value) => setNewColumnConfig({...newColumnConfig, valueSetter: value || ''})}
|
|
621
|
+
options={{
|
|
622
|
+
minimap: {enabled: false},
|
|
623
|
+
fontSize: 12,
|
|
624
|
+
lineNumbers: 'on',
|
|
625
|
+
scrollBeyondLastLine: false,
|
|
626
|
+
automaticLayout: true
|
|
627
|
+
}}
|
|
628
|
+
/>
|
|
629
|
+
</Box>
|
|
630
|
+
</Box>
|
|
631
|
+
<Box>
|
|
632
|
+
<Typography variant="caption" sx={{mb: 1, display: 'block'}}>
|
|
633
|
+
Value Getter (optional)
|
|
634
|
+
</Typography>
|
|
635
|
+
<Box sx={{border: '1px solid #ddd', borderRadius: 1}}>
|
|
636
|
+
<MonacoEditor
|
|
637
|
+
height="120px"
|
|
638
|
+
language="javascript"
|
|
639
|
+
theme="vs-dark"
|
|
640
|
+
value={newColumnConfig.valueGetter}
|
|
641
|
+
onChange={(value) => setNewColumnConfig({...newColumnConfig, valueGetter: value || ''})}
|
|
642
|
+
options={{
|
|
643
|
+
minimap: {enabled: false},
|
|
644
|
+
fontSize: 12,
|
|
645
|
+
lineNumbers: 'on',
|
|
646
|
+
scrollBeyondLastLine: false,
|
|
647
|
+
automaticLayout: true
|
|
648
|
+
}}
|
|
649
|
+
/>
|
|
650
|
+
</Box>
|
|
651
|
+
</Box>
|
|
652
|
+
<Box>
|
|
653
|
+
<Typography variant="caption" sx={{mb: 1, display: 'block'}}>
|
|
654
|
+
Additional Column Parameters
|
|
655
|
+
</Typography>
|
|
656
|
+
<Alert severity="info" sx={{mb: 1, fontSize: '0.75rem'}}>
|
|
657
|
+
Add any AG Grid column config properties as key-value pairs (without outer braces).
|
|
658
|
+
Example: valueFormatter: (p) => p.value?.name, width: 200
|
|
659
|
+
</Alert>
|
|
660
|
+
<Box sx={{border: '1px solid #ddd', borderRadius: 1}}>
|
|
661
|
+
<MonacoEditor
|
|
662
|
+
height="120px"
|
|
663
|
+
language="javascript"
|
|
664
|
+
theme="vs-dark"
|
|
665
|
+
value={newColumnConfig.additionalParams}
|
|
666
|
+
onChange={(value) => setNewColumnConfig({...newColumnConfig, additionalParams: value || ''})}
|
|
667
|
+
options={{
|
|
668
|
+
minimap: {enabled: false},
|
|
669
|
+
fontSize: 12,
|
|
670
|
+
lineNumbers: 'on',
|
|
671
|
+
scrollBeyondLastLine: false,
|
|
672
|
+
automaticLayout: true
|
|
673
|
+
}}
|
|
674
|
+
/>
|
|
675
|
+
</Box>
|
|
676
|
+
</Box>
|
|
677
|
+
<Button
|
|
678
|
+
variant="contained"
|
|
679
|
+
startIcon={editingColumnConfigIndex !== null ? <Edit/> : <Add/>}
|
|
680
|
+
onClick={handleAddColumnConfig}
|
|
681
|
+
disabled={!newColumnConfig.field}
|
|
682
|
+
sx={{alignSelf: 'flex-start'}}
|
|
683
|
+
>
|
|
684
|
+
{editingColumnConfigIndex !== null ? 'Update' : 'Add'}
|
|
685
|
+
</Button>
|
|
686
|
+
</Box>
|
|
687
|
+
</Paper>
|
|
688
|
+
|
|
689
|
+
<List sx={{bgcolor: 'background.paper', borderRadius: 1}}>
|
|
690
|
+
{columnsConfig.map((config, index) => (
|
|
691
|
+
<ListItem
|
|
692
|
+
key={index}
|
|
693
|
+
secondaryAction={
|
|
694
|
+
<Box>
|
|
695
|
+
<IconButton onClick={() => handleEditColumnConfig(index)}>
|
|
696
|
+
<Edit/>
|
|
697
|
+
</IconButton>
|
|
698
|
+
<IconButton edge="end" onClick={() => handleRemoveColumnConfig(index)}>
|
|
699
|
+
<Delete/>
|
|
700
|
+
</IconButton>
|
|
701
|
+
</Box>
|
|
702
|
+
}
|
|
703
|
+
>
|
|
704
|
+
<Box sx={{width: '100%'}}>
|
|
705
|
+
<Typography variant="body1" fontWeight="bold">
|
|
706
|
+
{config.field}
|
|
707
|
+
</Typography>
|
|
708
|
+
<Typography variant="caption" color="text.secondary" component="div">
|
|
709
|
+
Editable: {config.editable ? 'Yes' : 'No'}
|
|
710
|
+
{config.cellRenderer && <> | Renderer: {config.cellRenderer}</>}
|
|
711
|
+
{config.cellEditor && <> | Editor: {config.cellEditor}</>}
|
|
712
|
+
{config.cellEditorParams && <> | Has cellEditorParams</>}
|
|
713
|
+
{config.valueSetter && <> | Has valueSetter</>}
|
|
714
|
+
{config.valueGetter && <> | Has valueGetter</>}
|
|
715
|
+
{config.additionalParams && <> | Has additionalParams</>}
|
|
716
|
+
</Typography>
|
|
717
|
+
</Box>
|
|
718
|
+
</ListItem>
|
|
719
|
+
))}
|
|
720
|
+
{columnsConfig.length === 0 && (
|
|
721
|
+
<ListItem>
|
|
722
|
+
<Typography variant="body2" color="text.secondary">
|
|
723
|
+
No column configurations defined yet
|
|
724
|
+
</Typography>
|
|
725
|
+
</ListItem>
|
|
726
|
+
)}
|
|
727
|
+
</List>
|
|
728
|
+
</Box>
|
|
729
|
+
</AccordionDetails>
|
|
730
|
+
</Accordion>
|
|
731
|
+
|
|
732
|
+
{/* JSON Preview */}
|
|
733
|
+
<Paper sx={{p: 2, bgcolor: 'background.default'}}>
|
|
734
|
+
<Typography variant="subtitle2" sx={{mb: 2}}>JSON Preview</Typography>
|
|
735
|
+
<Box
|
|
736
|
+
component="pre"
|
|
737
|
+
sx={{
|
|
738
|
+
p: 2,
|
|
739
|
+
bgcolor: 'grey.900',
|
|
740
|
+
color: 'grey.100',
|
|
741
|
+
borderRadius: 1,
|
|
742
|
+
overflow: 'auto',
|
|
743
|
+
maxHeight: 300,
|
|
744
|
+
fontSize: '0.875rem'
|
|
745
|
+
}}
|
|
746
|
+
>
|
|
747
|
+
{JSON.stringify(buildResult(), null, 2)}
|
|
748
|
+
</Box>
|
|
749
|
+
</Paper>
|
|
750
|
+
</Box>
|
|
751
|
+
</DialogContent>
|
|
752
|
+
<DialogActions>
|
|
753
|
+
<Button onClick={onClose}>Close</Button>
|
|
754
|
+
<Button variant="contained" onClick={handleGenerate}>
|
|
755
|
+
Generate Result
|
|
756
|
+
</Button>
|
|
757
|
+
</DialogActions>
|
|
758
|
+
</Dialog>
|
|
759
|
+
)
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
export default ColumnConfiguratorDialog
|