@visns-studio/visns-components 5.12.2 → 5.12.4
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/README.md +2 -2
- package/package.json +1 -1
- package/src/components/DataGrid.jsx +95 -51
- package/src/components/columns/ColumnRenderers.jsx +322 -20
- package/src/components/generic/GenericDetail.jsx +200 -3
- package/src/components/generic/GenericIndex.jsx +31 -18
- package/src/components/generic/StagePopupModal.jsx +451 -0
- package/src/components/styles/StagePopupModal.module.scss +234 -0
- package/src/components/utils/ConfirmDialog.js +1 -1
- package/src/index.js +2 -0
package/README.md
CHANGED
|
@@ -343,7 +343,7 @@ The DataGrid component utilizes a modular column renderer system with 28 special
|
|
|
343
343
|
- `relation` - Related data display
|
|
344
344
|
- `relationArray` - Array of related data
|
|
345
345
|
- `richtext` - HTML content rendering
|
|
346
|
-
- `stage` - Stage-based displays
|
|
346
|
+
- `stage` - Stage-based displays with optional toggle functionality
|
|
347
347
|
- `time` - Time formatting
|
|
348
348
|
- `timer` - Interactive timer controls
|
|
349
349
|
- `url` - Clickable links
|
|
@@ -351,7 +351,7 @@ The DataGrid component utilizes a modular column renderer system with 28 special
|
|
|
351
351
|
- `address` - Formatted address display
|
|
352
352
|
- `createdBy` - User creation tracking
|
|
353
353
|
- `daterange` - Date range formatting
|
|
354
|
-
- `stageCounter` -
|
|
354
|
+
- `stageCounter` - Interactive visual stage progression with toggle functionality
|
|
355
355
|
|
|
356
356
|
All column renderers are exported from `@visns-studio/visns-components` and can be used individually or as part of the DataGrid component.
|
|
357
357
|
|
package/package.json
CHANGED
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
"react-dom": "^17.0.0 || ^18.0.0"
|
|
88
88
|
},
|
|
89
89
|
"name": "@visns-studio/visns-components",
|
|
90
|
-
"version": "5.12.
|
|
90
|
+
"version": "5.12.4",
|
|
91
91
|
"description": "Various packages to assist in the development of our Custom Applications.",
|
|
92
92
|
"main": "src/index.js",
|
|
93
93
|
"files": [
|
|
@@ -40,9 +40,12 @@ import DateFilter from '@visns-studio/visns-datagrid-enterprise/DateFilter';
|
|
|
40
40
|
import ReactDataGrid from '@visns-studio/visns-datagrid-enterprise';
|
|
41
41
|
import { toast } from 'react-toastify';
|
|
42
42
|
import fetchUtil from '../utils/fetchUtil';
|
|
43
|
-
import { confirmDialog } from '
|
|
43
|
+
import { confirmDialog } from './utils/ConfirmDialog';
|
|
44
44
|
import { DEFAULT_INTELLIGENT_SORTING_CONFIG } from '../utils/relationshipSortingUtils';
|
|
45
|
-
import {
|
|
45
|
+
import {
|
|
46
|
+
extractColumnsMetadata,
|
|
47
|
+
isColumnSortable,
|
|
48
|
+
} from '../utils/columnsMetadataUtils';
|
|
46
49
|
import {
|
|
47
50
|
AlarmClock,
|
|
48
51
|
RotateCcw,
|
|
@@ -207,10 +210,10 @@ const loadData = async (
|
|
|
207
210
|
try {
|
|
208
211
|
const response = await fetchUtil.post(url, params);
|
|
209
212
|
const { data, total } = response.data;
|
|
210
|
-
|
|
213
|
+
|
|
211
214
|
// Extract columns metadata if available
|
|
212
215
|
const metadata = extractColumnsMetadata(response);
|
|
213
|
-
|
|
216
|
+
|
|
214
217
|
return { data, count: total, metadata };
|
|
215
218
|
} catch (error) {
|
|
216
219
|
console.error('Error fetching data:', error);
|
|
@@ -391,7 +394,7 @@ const DataGrid = forwardRef(
|
|
|
391
394
|
if (res.metadata) {
|
|
392
395
|
setColumnsMetadata(res.metadata);
|
|
393
396
|
}
|
|
394
|
-
|
|
397
|
+
|
|
395
398
|
// Sort data by grouping field if grouping is enabled
|
|
396
399
|
if (ajaxSetting?.groupBy?.length > 0) {
|
|
397
400
|
const groupField = ajaxSetting.groupBy[0]; // groupBy is array of strings
|
|
@@ -449,9 +452,9 @@ const DataGrid = forwardRef(
|
|
|
449
452
|
}, 10);
|
|
450
453
|
});
|
|
451
454
|
|
|
452
|
-
return sqlResult.then(res => ({
|
|
455
|
+
return sqlResult.then((res) => ({
|
|
453
456
|
data: res.data,
|
|
454
|
-
count: res.count
|
|
457
|
+
count: res.count,
|
|
455
458
|
}));
|
|
456
459
|
},
|
|
457
460
|
[ajaxSetting, dSearch, collapsedGroups]
|
|
@@ -872,15 +875,12 @@ const DataGrid = forwardRef(
|
|
|
872
875
|
case 'file':
|
|
873
876
|
case 'image':
|
|
874
877
|
case 'undo':
|
|
878
|
+
case 'restore':
|
|
875
879
|
// Execute the action directly since confirmation was already handled
|
|
876
|
-
CustomFetch(
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
(result) => {
|
|
881
|
-
toast.success(result.message);
|
|
882
|
-
}
|
|
883
|
-
);
|
|
880
|
+
CustomFetch(s.url, 'POST', { id: d[s.key] }, (result) => {
|
|
881
|
+
toast.success(result.message);
|
|
882
|
+
handleReload(); // Add reload to refresh data after action
|
|
883
|
+
});
|
|
884
884
|
break;
|
|
885
885
|
case 'clone':
|
|
886
886
|
if (s.url && s.url !== '') {
|
|
@@ -1346,17 +1346,19 @@ const DataGrid = forwardRef(
|
|
|
1346
1346
|
if (iconConfig.formModal) {
|
|
1347
1347
|
// Get all rows in the group for bulk editing
|
|
1348
1348
|
const groupRows = getGroupRows(groupValue);
|
|
1349
|
-
const groupRowIds = groupRows.map(
|
|
1350
|
-
|
|
1349
|
+
const groupRowIds = groupRows.map(
|
|
1350
|
+
(row) => row[form?.primaryKey || 'id']
|
|
1351
|
+
);
|
|
1352
|
+
|
|
1351
1353
|
// Set bulk edit data
|
|
1352
1354
|
setBulkEditMode(true);
|
|
1353
1355
|
setBulkEditGroupData({
|
|
1354
1356
|
groupValue: groupValue,
|
|
1355
1357
|
groupRows: groupRows,
|
|
1356
1358
|
groupRowIds: groupRowIds,
|
|
1357
|
-
iconConfig: iconConfig
|
|
1359
|
+
iconConfig: iconConfig,
|
|
1358
1360
|
});
|
|
1359
|
-
|
|
1361
|
+
|
|
1360
1362
|
// Open modal for bulk editing
|
|
1361
1363
|
modalOpen('update', null);
|
|
1362
1364
|
} else {
|
|
@@ -2374,8 +2376,11 @@ const DataGrid = forwardRef(
|
|
|
2374
2376
|
|
|
2375
2377
|
// Check if column is sortable based on metadata
|
|
2376
2378
|
const columnKey = column.id;
|
|
2377
|
-
const sortable = isColumnSortable(
|
|
2378
|
-
|
|
2379
|
+
const sortable = isColumnSortable(
|
|
2380
|
+
columnKey,
|
|
2381
|
+
columnsMetadata
|
|
2382
|
+
);
|
|
2383
|
+
|
|
2379
2384
|
const commonProps = {
|
|
2380
2385
|
header: column.label,
|
|
2381
2386
|
defaultFlex: 1,
|
|
@@ -2481,20 +2486,26 @@ const DataGrid = forwardRef(
|
|
|
2481
2486
|
? column.filter.placeholder
|
|
2482
2487
|
: 'All Options',
|
|
2483
2488
|
dataSource: selectedDataSource,
|
|
2484
|
-
searchable:
|
|
2489
|
+
searchable:
|
|
2490
|
+
column.filter.searchable !== false,
|
|
2485
2491
|
// Enable clear functionality even when searchable is false
|
|
2486
|
-
allowClearWhenNotSearchable:
|
|
2492
|
+
allowClearWhenNotSearchable:
|
|
2493
|
+
column.filter.searchable === false,
|
|
2487
2494
|
// Explicitly enable clear icon
|
|
2488
2495
|
clearIcon: true,
|
|
2489
2496
|
};
|
|
2490
|
-
|
|
2497
|
+
|
|
2491
2498
|
// Debug: Check if fix is applied
|
|
2492
2499
|
if (column.filter.searchable === false) {
|
|
2493
|
-
console.log(
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2500
|
+
console.log(
|
|
2501
|
+
'Filter Debug - searchable=false:',
|
|
2502
|
+
{
|
|
2503
|
+
columnName:
|
|
2504
|
+
column.name || 'unknown',
|
|
2505
|
+
props: filterEditorProps,
|
|
2506
|
+
visnsDataGridVersion: 'v1.0.18',
|
|
2507
|
+
}
|
|
2508
|
+
);
|
|
2498
2509
|
}
|
|
2499
2510
|
break;
|
|
2500
2511
|
default:
|
|
@@ -2638,7 +2649,9 @@ const DataGrid = forwardRef(
|
|
|
2638
2649
|
filterEditor,
|
|
2639
2650
|
filterEditorProps,
|
|
2640
2651
|
relationName,
|
|
2641
|
-
intelligentSortingConfig:
|
|
2652
|
+
intelligentSortingConfig:
|
|
2653
|
+
tableSetting?.intelligentSorting ||
|
|
2654
|
+
DEFAULT_INTELLIGENT_SORTING_CONFIG,
|
|
2642
2655
|
});
|
|
2643
2656
|
case 'relationArray':
|
|
2644
2657
|
return renderRelationArrayColumn({
|
|
@@ -2647,7 +2660,9 @@ const DataGrid = forwardRef(
|
|
|
2647
2660
|
filterEditor,
|
|
2648
2661
|
filterEditorProps,
|
|
2649
2662
|
relationName,
|
|
2650
|
-
intelligentSortingConfig:
|
|
2663
|
+
intelligentSortingConfig:
|
|
2664
|
+
tableSetting?.intelligentSorting ||
|
|
2665
|
+
DEFAULT_INTELLIGENT_SORTING_CONFIG,
|
|
2651
2666
|
});
|
|
2652
2667
|
case 'richtext':
|
|
2653
2668
|
return renderRichTextColumn({
|
|
@@ -2658,6 +2673,7 @@ const DataGrid = forwardRef(
|
|
|
2658
2673
|
return renderStageColumn({
|
|
2659
2674
|
column,
|
|
2660
2675
|
commonProps,
|
|
2676
|
+
onUpdate: handleReload,
|
|
2661
2677
|
});
|
|
2662
2678
|
case 'time':
|
|
2663
2679
|
return renderTimeColumn({
|
|
@@ -2678,6 +2694,7 @@ const DataGrid = forwardRef(
|
|
|
2678
2694
|
column,
|
|
2679
2695
|
commonProps,
|
|
2680
2696
|
navigate,
|
|
2697
|
+
onUpdate: handleReload,
|
|
2681
2698
|
});
|
|
2682
2699
|
case 'url':
|
|
2683
2700
|
return renderUrlColumn({ column, commonProps });
|
|
@@ -2695,22 +2712,37 @@ const DataGrid = forwardRef(
|
|
|
2695
2712
|
: column.id;
|
|
2696
2713
|
|
|
2697
2714
|
// Auto-detect columns that should have word wrap enabled
|
|
2698
|
-
const shouldAutoEnableWordWrap =
|
|
2715
|
+
const shouldAutoEnableWordWrap =
|
|
2699
2716
|
column.wordWrap !== false && // Allow explicit disable with wordWrap: false
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2717
|
+
// Text-heavy column patterns
|
|
2718
|
+
(/^(task|description|notes?|comments?|content|message|details?|summary|reason|remarks?)$/i.test(
|
|
2719
|
+
columnId
|
|
2720
|
+
) ||
|
|
2721
|
+
/.*_(task|description|notes?|comments?|content|message|details?|summary|reason|remarks?)$/i.test(
|
|
2722
|
+
columnId
|
|
2723
|
+
) ||
|
|
2724
|
+
/(task|description|notes?|comments?|content|message|details?|summary|reason|remarks?)_.*$/i.test(
|
|
2725
|
+
columnId
|
|
2726
|
+
) ||
|
|
2705
2727
|
// Check for long labels that might indicate text content
|
|
2706
|
-
(column.label &&
|
|
2707
|
-
|
|
2728
|
+
(column.label &&
|
|
2729
|
+
column.label.length > 15 &&
|
|
2730
|
+
/description|notes|comments|details|content/i.test(
|
|
2731
|
+
column.label
|
|
2732
|
+
)));
|
|
2708
2733
|
|
|
2709
|
-
const finalWordWrap =
|
|
2734
|
+
const finalWordWrap =
|
|
2735
|
+
column.wordWrap === true ||
|
|
2736
|
+
shouldAutoEnableWordWrap;
|
|
2710
2737
|
|
|
2711
2738
|
// Debug logging for word wrap detection
|
|
2712
|
-
if (
|
|
2713
|
-
|
|
2739
|
+
if (
|
|
2740
|
+
shouldAutoEnableWordWrap &&
|
|
2741
|
+
column.wordWrap !== true
|
|
2742
|
+
) {
|
|
2743
|
+
console.log(
|
|
2744
|
+
`DataGrid: Auto-enabled wordWrap for column "${columnId}" (${column.label})`
|
|
2745
|
+
);
|
|
2714
2746
|
}
|
|
2715
2747
|
|
|
2716
2748
|
return {
|
|
@@ -2718,7 +2750,9 @@ const DataGrid = forwardRef(
|
|
|
2718
2750
|
name: columnId,
|
|
2719
2751
|
filterEditor: filterEditor,
|
|
2720
2752
|
filterEditorProps: filterEditorProps,
|
|
2721
|
-
className: finalWordWrap
|
|
2753
|
+
className: finalWordWrap
|
|
2754
|
+
? 'cell-word-wrap'
|
|
2755
|
+
: '',
|
|
2722
2756
|
render: ({ data }) => {
|
|
2723
2757
|
if (
|
|
2724
2758
|
data &&
|
|
@@ -2748,8 +2782,11 @@ const DataGrid = forwardRef(
|
|
|
2748
2782
|
);
|
|
2749
2783
|
}
|
|
2750
2784
|
|
|
2751
|
-
// If removeFormat is true, strip HTML tags
|
|
2752
|
-
if (
|
|
2785
|
+
// If removeFormat or stripHtml is true, strip HTML tags
|
|
2786
|
+
if (
|
|
2787
|
+
column.removeFormat ||
|
|
2788
|
+
column.stripHtml
|
|
2789
|
+
) {
|
|
2753
2790
|
content = content.replace(
|
|
2754
2791
|
/<\/?[^>]+(>|$)/g,
|
|
2755
2792
|
''
|
|
@@ -3091,15 +3128,22 @@ const DataGrid = forwardRef(
|
|
|
3091
3128
|
{/* Top container with search, action buttons, and auto-refresh */}
|
|
3092
3129
|
{/* Only show top container if there are controls to display */}
|
|
3093
3130
|
{(() => {
|
|
3094
|
-
const hasSearchOrCreate =
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3131
|
+
const hasSearchOrCreate =
|
|
3132
|
+
!form.searchDisable || !form.createDisable;
|
|
3133
|
+
const hasAutoRefresh =
|
|
3134
|
+
!shouldRelocateAutoRefresh() &&
|
|
3135
|
+
ajaxSetting &&
|
|
3136
|
+
ajaxSetting.autoRefresh !== undefined;
|
|
3137
|
+
|
|
3138
|
+
// If DataGridSearch would return null (both search and create disabled),
|
|
3098
3139
|
// only show container if there are other controls besides auto-refresh
|
|
3099
|
-
if (
|
|
3140
|
+
if (
|
|
3141
|
+
form.searchDisable === true &&
|
|
3142
|
+
form.createDisable === true
|
|
3143
|
+
) {
|
|
3100
3144
|
return false; // Hide AutoRefreshControls when it would be the only control
|
|
3101
3145
|
}
|
|
3102
|
-
|
|
3146
|
+
|
|
3103
3147
|
return hasSearchOrCreate || hasAutoRefresh;
|
|
3104
3148
|
})() && (
|
|
3105
3149
|
<div className={styles.dataGridTopContainer}>
|