robobyte-front-builder 1.0.16 → 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 +26 -9
- package/src/pages/_app.js +0 -8
- 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,421 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper functions for managing updateRef in AG Grid
|
|
3
|
+
*
|
|
4
|
+
* updateRef structure: Array of row updates with original and updated data
|
|
5
|
+
* [
|
|
6
|
+
* {
|
|
7
|
+
* rowId: "123",
|
|
8
|
+
* originalData: {
|
|
9
|
+
* Id: 123,
|
|
10
|
+
* IsPublic: false, // original value
|
|
11
|
+
* Name: "Original Name",
|
|
12
|
+
* Product: { Name: "Original Product Name" }
|
|
13
|
+
* },
|
|
14
|
+
* data: {
|
|
15
|
+
* Id: 123,
|
|
16
|
+
* IsPublic: true, // updated field
|
|
17
|
+
* Name: "Original Name",
|
|
18
|
+
* Product: { Name: "Updated Name" } // updated nested field
|
|
19
|
+
* }
|
|
20
|
+
* },
|
|
21
|
+
* {
|
|
22
|
+
* rowId: "456",
|
|
23
|
+
* originalData: {
|
|
24
|
+
* Id: 456,
|
|
25
|
+
* Status: "Inactive",
|
|
26
|
+
* Name: "Original"
|
|
27
|
+
* },
|
|
28
|
+
* data: {
|
|
29
|
+
* Id: 456,
|
|
30
|
+
* Status: "Active", // updated field
|
|
31
|
+
* Name: "Original"
|
|
32
|
+
* }
|
|
33
|
+
* }
|
|
34
|
+
* ]
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Get nested value from object using dot notation path
|
|
39
|
+
* @param {object} obj - The object to traverse
|
|
40
|
+
* @param {string} path - Dot-separated path (e.g., "Product.Name")
|
|
41
|
+
* @returns {any} The value at the path, or undefined if not found
|
|
42
|
+
*/
|
|
43
|
+
export const getNestedValue = (obj, path) => {
|
|
44
|
+
if (!obj || !path) return undefined
|
|
45
|
+
|
|
46
|
+
const keys = path.split('.')
|
|
47
|
+
let current = obj
|
|
48
|
+
|
|
49
|
+
for (const key of keys) {
|
|
50
|
+
if (current == null) return undefined
|
|
51
|
+
current = current[key]
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return current
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Set nested value in object using dot notation path
|
|
59
|
+
* @param {object} obj - The object to modify
|
|
60
|
+
* @param {string} path - Dot-separated path (e.g., "Product.Name")
|
|
61
|
+
* @param {any} value - The value to set
|
|
62
|
+
*/
|
|
63
|
+
export const setNestedValue = (obj, path, value) => {
|
|
64
|
+
if (!obj || !path) return
|
|
65
|
+
|
|
66
|
+
const keys = path.split('.')
|
|
67
|
+
const lastKey = keys.pop()
|
|
68
|
+
let current = obj
|
|
69
|
+
|
|
70
|
+
// Navigate to the parent object
|
|
71
|
+
for (const key of keys) {
|
|
72
|
+
if (!(key in current)) {
|
|
73
|
+
current[key] = {}
|
|
74
|
+
}
|
|
75
|
+
current = current[key]
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Set the value
|
|
79
|
+
current[lastKey] = value
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Normalize rowId to string for comparison (handles both number and string)
|
|
84
|
+
* @param {string|number} rowId - The row ID to normalize
|
|
85
|
+
* @returns {string} Normalized row ID as string
|
|
86
|
+
*/
|
|
87
|
+
const normalizeRowId = (rowId) => {
|
|
88
|
+
return rowId != null ? String(rowId) : null
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Compare two rowIds (handles both number and string)
|
|
93
|
+
* @param {string|number} rowId1 - First row ID
|
|
94
|
+
* @param {string|number} rowId2 - Second row ID
|
|
95
|
+
* @returns {boolean} True if they match
|
|
96
|
+
*/
|
|
97
|
+
const compareRowIds = (rowId1, rowId2) => {
|
|
98
|
+
return normalizeRowId(rowId1) === normalizeRowId(rowId2)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Get the unique row ID from row data based on rowUniqueId configuration
|
|
103
|
+
* @param {object} rowData - The AG Grid row data
|
|
104
|
+
* @param {array} rowUniqueId - Array of field paths that uniquely identify a row (from settings)
|
|
105
|
+
* @returns {string} Composite key string
|
|
106
|
+
*/
|
|
107
|
+
export const getRowId = (rowData, rowUniqueId) => {
|
|
108
|
+
if (!rowData || !rowUniqueId || rowUniqueId.length === 0) {
|
|
109
|
+
return null
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// If single field, return its value directly as string
|
|
113
|
+
if (rowUniqueId.length === 1) {
|
|
114
|
+
const value = getNestedValue(rowData, rowUniqueId[0])
|
|
115
|
+
return value != null ? String(value) : null
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// If multiple fields, create composite key
|
|
119
|
+
const keyParts = rowUniqueId.map(fieldPath => {
|
|
120
|
+
const value = getNestedValue(rowData, fieldPath)
|
|
121
|
+
return value != null ? String(value) : ''
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
return keyParts.join('|')
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Update a field value in updateRef
|
|
129
|
+
* @param {React.MutableRefObject} updateRef - The ref object storing updates (array)
|
|
130
|
+
* @param {object} rowData - The AG Grid row data
|
|
131
|
+
* @param {array} rowUniqueId - Array of field paths for row identification
|
|
132
|
+
* @param {string} fieldPath - The field to update (supports dot notation)
|
|
133
|
+
* @param {any} newValue - The new value
|
|
134
|
+
*/
|
|
135
|
+
export const setUpdateRefValue = (updateRef, rowData, rowUniqueId, fieldPath, newValue) => {
|
|
136
|
+
if (!updateRef || !updateRef.current) {
|
|
137
|
+
// console.warn('updateRef is not initialized')
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const rowId = getRowId(rowData, rowUniqueId)
|
|
142
|
+
if (!rowId) {
|
|
143
|
+
// console.warn('Could not determine row ID from rowData', rowData, rowUniqueId)
|
|
144
|
+
return
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Ensure updateRef.current is an array
|
|
148
|
+
if (!Array.isArray(updateRef.current)) {
|
|
149
|
+
updateRef.current = []
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Find existing row update (use comparison to handle both string and number)
|
|
153
|
+
let rowUpdate = updateRef.current.find(item => compareRowIds(item.rowId, rowId))
|
|
154
|
+
|
|
155
|
+
if (!rowUpdate) {
|
|
156
|
+
// First edit: Create new row update entry with both originalData and data (deep clones)
|
|
157
|
+
rowUpdate = {
|
|
158
|
+
rowId: normalizeRowId(rowId),
|
|
159
|
+
originalData: JSON.parse(JSON.stringify(rowData)),
|
|
160
|
+
data: JSON.parse(JSON.stringify(rowData))
|
|
161
|
+
}
|
|
162
|
+
updateRef.current.push(rowUpdate)
|
|
163
|
+
} else {
|
|
164
|
+
// Row exists - merge with new rowData (...old, ...new)
|
|
165
|
+
// New fields are added, existing fields are updated, fields only in old are preserved
|
|
166
|
+
const clonedRowData = JSON.parse(JSON.stringify(rowData))
|
|
167
|
+
rowUpdate.data = {
|
|
168
|
+
...rowUpdate.data,
|
|
169
|
+
...clonedRowData
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Set the field value in the data object (supports nested paths)
|
|
174
|
+
setNestedValue(rowUpdate.data, fieldPath, newValue)
|
|
175
|
+
|
|
176
|
+
// console.log('updateRef updated:', rowId, fieldPath, newValue)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Update multiple fields in a row at once
|
|
181
|
+
* @param {React.MutableRefObject} updateRef - The ref object storing updates (array)
|
|
182
|
+
* @param {object} rowData - The AG Grid row data
|
|
183
|
+
* @param {array} rowUniqueId - Array of field paths for row identification
|
|
184
|
+
* @param {object} updates - Object with fieldPath: newValue pairs
|
|
185
|
+
*/
|
|
186
|
+
export const setUpdateRefRow = (updateRef, rowData, rowUniqueId, updates) => {
|
|
187
|
+
if (!updateRef || !updateRef.current) {
|
|
188
|
+
// console.warn('updateRef is not initialized')
|
|
189
|
+
return
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const rowId = getRowId(rowData, rowUniqueId)
|
|
193
|
+
if (!rowId) {
|
|
194
|
+
// console.warn('Could not determine row ID from rowData', rowData, rowUniqueId)
|
|
195
|
+
return
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Ensure updateRef.current is an array
|
|
199
|
+
if (!Array.isArray(updateRef.current)) {
|
|
200
|
+
updateRef.current = []
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Find existing row update (use comparison to handle both string and number)
|
|
204
|
+
let rowUpdate = updateRef.current.find(item => compareRowIds(item.rowId, rowId))
|
|
205
|
+
|
|
206
|
+
if (!rowUpdate) {
|
|
207
|
+
// First edit: Create new row update entry with both originalData and data (deep clones)
|
|
208
|
+
rowUpdate = {
|
|
209
|
+
rowId: normalizeRowId(rowId),
|
|
210
|
+
originalData: JSON.parse(JSON.stringify(rowData)),
|
|
211
|
+
data: JSON.parse(JSON.stringify(rowData))
|
|
212
|
+
}
|
|
213
|
+
updateRef.current.push(rowUpdate)
|
|
214
|
+
} else {
|
|
215
|
+
// Row exists - merge with new rowData (...old, ...new)
|
|
216
|
+
// New fields are added, existing fields are updated, fields only in old are preserved
|
|
217
|
+
const clonedRowData = JSON.parse(JSON.stringify(rowData))
|
|
218
|
+
rowUpdate.data = {
|
|
219
|
+
...rowUpdate.data,
|
|
220
|
+
...clonedRowData
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Apply all updates to the data object (supports nested paths)
|
|
225
|
+
Object.entries(updates).forEach(([fieldPath, value]) => {
|
|
226
|
+
setNestedValue(rowUpdate.data, fieldPath, value)
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
// console.log('updateRef row updated:', rowId, updates)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Get a field value from updateRef or fallback to original row data
|
|
234
|
+
* @param {React.MutableRefObject} updateRef - The ref object storing updates (array)
|
|
235
|
+
* @param {object} rowData - The AG Grid row data
|
|
236
|
+
* @param {array} rowUniqueId - Array of field paths for row identification
|
|
237
|
+
* @param {string} updateRefPath - The field path to get from updateRef.data (supports dot notation)
|
|
238
|
+
* @param {string} rowDataPath - The field path to get from original rowData if not in updateRef (optional, defaults to updateRefPath)
|
|
239
|
+
* @returns {any} The updated value if exists, otherwise the original value from rowData
|
|
240
|
+
*/
|
|
241
|
+
export const getUpdateRefValue = (updateRef, rowData, rowUniqueId, updateRefPath, rowDataPath) => {
|
|
242
|
+
// Default rowDataPath to updateRefPath if not provided
|
|
243
|
+
const fallbackPath = rowDataPath !== undefined ? rowDataPath : updateRefPath
|
|
244
|
+
|
|
245
|
+
if (!updateRef || !updateRef.current || !Array.isArray(updateRef.current)) {
|
|
246
|
+
return getNestedValue(rowData, fallbackPath)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const rowId = getRowId(rowData, rowUniqueId)
|
|
250
|
+
|
|
251
|
+
if (!rowId) {
|
|
252
|
+
return getNestedValue(rowData, fallbackPath)
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Find row update (use comparison to handle both string and number)
|
|
256
|
+
const rowUpdate = updateRef.current.find(item => compareRowIds(item.rowId, rowId))
|
|
257
|
+
|
|
258
|
+
if (!rowUpdate || !rowUpdate.data) {
|
|
259
|
+
return getNestedValue(rowData, fallbackPath)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Get value from the updated data object using updateRefPath
|
|
263
|
+
return getNestedValue(rowUpdate.data, updateRefPath)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Check if a row has been updated in updateRef
|
|
268
|
+
* @param {React.MutableRefObject} updateRef - The ref object storing updates (array)
|
|
269
|
+
* @param {object} rowData - The AG Grid row data
|
|
270
|
+
* @param {array} rowUniqueId - Array of field paths for row identification
|
|
271
|
+
* @returns {boolean} True if the row has been updated
|
|
272
|
+
*/
|
|
273
|
+
export const hasUpdateRefValue = (updateRef, rowData, rowUniqueId) => {
|
|
274
|
+
if (!updateRef || !updateRef.current || !Array.isArray(updateRef.current)) {
|
|
275
|
+
return false
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const rowId = getRowId(rowData, rowUniqueId)
|
|
279
|
+
if (!rowId) {
|
|
280
|
+
return false
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const rowUpdate = updateRef.current.find(item => compareRowIds(item.rowId, rowId))
|
|
284
|
+
return !!rowUpdate
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Remove a specific row from updateRef by rowData and rowUniqueId
|
|
289
|
+
* @param {React.MutableRefObject} updateRef - The ref object storing updates (array)
|
|
290
|
+
* @param {object} rowData - The AG Grid row data
|
|
291
|
+
* @param {array} rowUniqueId - Array of field paths for row identification
|
|
292
|
+
*/
|
|
293
|
+
export const removeUpdateRefByRowId = (updateRef, rowData, rowUniqueId) => {
|
|
294
|
+
if (!updateRef || !updateRef.current || !Array.isArray(updateRef.current)) {
|
|
295
|
+
return
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const rowId = getRowId(rowData, rowUniqueId)
|
|
299
|
+
if (!rowId) {
|
|
300
|
+
console.warn('Could not determine row ID from rowData', rowData, rowUniqueId)
|
|
301
|
+
return
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const index = updateRef.current.findIndex(item => compareRowIds(item.rowId, rowId))
|
|
305
|
+
if (index !== -1) {
|
|
306
|
+
updateRef.current.splice(index, 1)
|
|
307
|
+
console.log('updateRef row removed:', rowId)
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Clear all updates for a specific row
|
|
313
|
+
* @param {React.MutableRefObject} updateRef - The ref object storing updates (array)
|
|
314
|
+
* @param {object} rowData - The AG Grid row data
|
|
315
|
+
* @param {array} rowUniqueId - Array of field paths for row identification
|
|
316
|
+
*/
|
|
317
|
+
export const clearUpdateRefRow = (updateRef, rowData, rowUniqueId) => {
|
|
318
|
+
if (!updateRef || !updateRef.current || !Array.isArray(updateRef.current)) {
|
|
319
|
+
return
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const rowId = getRowId(rowData, rowUniqueId)
|
|
323
|
+
if (!rowId) {
|
|
324
|
+
return
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
removeUpdateRefByRowId(updateRef, rowId)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Normalize updateRef by merging duplicate entries (handles mixed number/string rowIds)
|
|
332
|
+
* @param {React.MutableRefObject} updateRef - The ref object storing updates (array)
|
|
333
|
+
*/
|
|
334
|
+
export const normalizeUpdateRef = (updateRef) => {
|
|
335
|
+
if (!updateRef || !updateRef.current || !Array.isArray(updateRef.current)) {
|
|
336
|
+
return
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const normalized = []
|
|
340
|
+
const seen = new Set()
|
|
341
|
+
|
|
342
|
+
updateRef.current.forEach(item => {
|
|
343
|
+
const normalizedId = normalizeRowId(item.rowId)
|
|
344
|
+
|
|
345
|
+
if (seen.has(normalizedId)) {
|
|
346
|
+
// Find existing entry and merge data
|
|
347
|
+
const existing = normalized.find(n => compareRowIds(n.rowId, normalizedId))
|
|
348
|
+
if (existing) {
|
|
349
|
+
// Merge data from duplicate entry (later values override)
|
|
350
|
+
Object.assign(existing.data, item.data)
|
|
351
|
+
// Keep originalData if not present
|
|
352
|
+
if (!existing.originalData && item.originalData) {
|
|
353
|
+
existing.originalData = item.originalData
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
} else {
|
|
357
|
+
// Add new normalized entry
|
|
358
|
+
normalized.push({
|
|
359
|
+
...item,
|
|
360
|
+
rowId: normalizedId
|
|
361
|
+
})
|
|
362
|
+
seen.add(normalizedId)
|
|
363
|
+
}
|
|
364
|
+
})
|
|
365
|
+
|
|
366
|
+
updateRef.current = normalized
|
|
367
|
+
console.log('updateRef normalized, merged duplicates')
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Clone updateRef to originalRefData (backup before changes)
|
|
372
|
+
* @param {React.MutableRefObject} updateRef - The ref object storing updates (array)
|
|
373
|
+
* @param {React.MutableRefObject} originalRefData - The ref to store the clone
|
|
374
|
+
*/
|
|
375
|
+
export const cloneUpdateRefToOriginal = (updateRef, originalRefData) => {
|
|
376
|
+
if (!updateRef || !updateRef.current || !originalRefData) {
|
|
377
|
+
return
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
originalRefData.current = JSON.parse(JSON.stringify(updateRef.current))
|
|
381
|
+
console.log('updateRef cloned to originalRefData:', originalRefData.current.length, 'rows')
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Restore updateRef from originalRefData (reset to backup)
|
|
386
|
+
* @param {React.MutableRefObject} updateRef - The ref object storing updates (array)
|
|
387
|
+
* @param {React.MutableRefObject} originalRefData - The ref with the backup data
|
|
388
|
+
*/
|
|
389
|
+
export const restoreUpdateRefFromOriginal = (updateRef, originalRefData) => {
|
|
390
|
+
if (!updateRef || !originalRefData || !originalRefData.current) {
|
|
391
|
+
return
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
updateRef.current = JSON.parse(JSON.stringify(originalRefData.current))
|
|
395
|
+
console.log('updateRef restored from originalRefData:', updateRef.current.length, 'rows')
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Clear all updates
|
|
400
|
+
* @param {React.MutableRefObject} updateRef - The ref object storing updates (array)
|
|
401
|
+
*/
|
|
402
|
+
export const clearAllUpdateRef = (updateRef) => {
|
|
403
|
+
if (!updateRef || !updateRef.current) {
|
|
404
|
+
return
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
updateRef.current = []
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Get all updated rows
|
|
412
|
+
* @param {React.MutableRefObject} updateRef - The ref object storing updates (array)
|
|
413
|
+
* @returns {array} The current updateRef.current array
|
|
414
|
+
*/
|
|
415
|
+
export const getAllUpdates = (updateRef) => {
|
|
416
|
+
if (!updateRef || !updateRef.current) {
|
|
417
|
+
return []
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return updateRef.current
|
|
421
|
+
}
|