@visns-studio/visns-components 5.4.4 → 5.4.6
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 +14 -14
- package/src/components/crm/DataGrid.jsx +2 -0
- package/src/components/crm/README_DATAGRID.md +70 -0
- package/src/components/crm/generic/GenericDashboard.jsx +223 -27
- package/src/components/crm/generic/GenericIndex.jsx +2 -0
- package/src/components/crm/styles/DataGrid.module.scss +2 -2
- package/src/components/styles/global.css +2 -2
- package/src/examples/CustomHoverDataGrid.jsx +92 -0
package/package.json
CHANGED
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
"akar-icons": "^1.9.31",
|
|
15
15
|
"array-move": "^4.0.0",
|
|
16
16
|
"awesome-debounce-promise": "^2.1.0",
|
|
17
|
-
"axios": "^1.8.
|
|
17
|
+
"axios": "^1.8.4",
|
|
18
18
|
"dayjs": "^1.11.13",
|
|
19
|
-
"fabric": "^6.
|
|
19
|
+
"fabric": "^6.6.2",
|
|
20
20
|
"file-saver": "^2.0.5",
|
|
21
21
|
"framer-motion": "^11.18.2",
|
|
22
22
|
"html-react-parser": "^5.2.3",
|
|
@@ -27,20 +27,20 @@
|
|
|
27
27
|
"numeral": "^2.0.6",
|
|
28
28
|
"pluralize": "^8.0.0",
|
|
29
29
|
"quill-image-uploader": "^1.3.0",
|
|
30
|
-
"react-big-calendar": "^1.
|
|
30
|
+
"react-big-calendar": "^1.18.0",
|
|
31
31
|
"react-color": "^2.19.3",
|
|
32
32
|
"react-confirm-alert": "^3.0.6",
|
|
33
33
|
"react-copy-to-clipboard": "^5.1.0",
|
|
34
34
|
"react-datepicker": "^7.6.0",
|
|
35
|
-
"react-dropzone": "^14.3.
|
|
35
|
+
"react-dropzone": "^14.3.8",
|
|
36
36
|
"react-grid-gallery": "^1.0.1",
|
|
37
37
|
"react-number-format": "^5.4.3",
|
|
38
38
|
"react-password-strength-bar": "^0.4.1",
|
|
39
39
|
"react-promise-tracker": "^2.1.1",
|
|
40
40
|
"react-quill": "^2.0.0",
|
|
41
41
|
"react-reveal": "^1.2.2",
|
|
42
|
-
"react-router-dom": "^6.
|
|
43
|
-
"react-select": "^5.
|
|
42
|
+
"react-router-dom": "^6.30.0",
|
|
43
|
+
"react-select": "^5.10.1",
|
|
44
44
|
"react-signature-pad-wrapper": "^4.1.0",
|
|
45
45
|
"react-slugify": "^4.0.1",
|
|
46
46
|
"react-sortable-hoc": "^2.0.0",
|
|
@@ -55,30 +55,30 @@
|
|
|
55
55
|
"truncate": "^3.0.0",
|
|
56
56
|
"uuid": "^10.0.0",
|
|
57
57
|
"validator": "^13.15.0",
|
|
58
|
-
"vite": "^5.4.
|
|
58
|
+
"vite": "^5.4.16",
|
|
59
59
|
"yarn": "^1.22.22"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
|
-
"@babel/core": "^7.26.
|
|
63
|
-
"@babel/plugin-transform-runtime": "^7.
|
|
64
|
-
"@babel/preset-env": "^7.26.
|
|
62
|
+
"@babel/core": "^7.26.10",
|
|
63
|
+
"@babel/plugin-transform-runtime": "^7.26.10",
|
|
64
|
+
"@babel/preset-env": "^7.26.9",
|
|
65
65
|
"@babel/preset-react": "^7.26.3",
|
|
66
66
|
"babel-loader": "^9.2.1",
|
|
67
67
|
"copy-webpack-plugin": "^12.0.2",
|
|
68
68
|
"css-loader": "^7.1.2",
|
|
69
|
-
"css-minimizer-webpack-plugin": "^7.0.
|
|
69
|
+
"css-minimizer-webpack-plugin": "^7.0.2",
|
|
70
70
|
"mini-css-extract-plugin": "^2.9.2",
|
|
71
71
|
"react": "^18.3.1",
|
|
72
72
|
"react-dom": "^18.3.1",
|
|
73
|
-
"sass": "^1.
|
|
74
|
-
"sass-loader": "^16.0.
|
|
73
|
+
"sass": "^1.86.2",
|
|
74
|
+
"sass-loader": "^16.0.5"
|
|
75
75
|
},
|
|
76
76
|
"peerDependencies": {
|
|
77
77
|
"react": "^17.0.0 || ^18.0.0",
|
|
78
78
|
"react-dom": "^17.0.0 || ^18.0.0"
|
|
79
79
|
},
|
|
80
80
|
"name": "@visns-studio/visns-components",
|
|
81
|
-
"version": "5.4.
|
|
81
|
+
"version": "5.4.6",
|
|
82
82
|
"description": "Various packages to assist in the development of our Custom Applications.",
|
|
83
83
|
"main": "src/index.js",
|
|
84
84
|
"files": [
|
|
@@ -133,6 +133,7 @@ const DataGrid = forwardRef(
|
|
|
133
133
|
columns,
|
|
134
134
|
form,
|
|
135
135
|
gridHeight,
|
|
136
|
+
hoverColor,
|
|
136
137
|
mapbox,
|
|
137
138
|
pageData,
|
|
138
139
|
pageSetting,
|
|
@@ -2856,6 +2857,7 @@ const DataGrid = forwardRef(
|
|
|
2856
2857
|
: 450
|
|
2857
2858
|
: 400,
|
|
2858
2859
|
boxShadow: 'none',
|
|
2860
|
+
...(hoverColor ? { '--hover-color': hoverColor } : {}),
|
|
2859
2861
|
});
|
|
2860
2862
|
const headerProps = {
|
|
2861
2863
|
style: style ? style : {},
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# DataGrid Component
|
|
2
|
+
|
|
3
|
+
## Customizing Hover Color
|
|
4
|
+
|
|
5
|
+
The DataGrid component now supports customizable hover colors. This allows you to set different hover colors for different instances of the DataGrid.
|
|
6
|
+
|
|
7
|
+
### Method 1: Using the hoverColor Prop (Recommended)
|
|
8
|
+
|
|
9
|
+
The simplest way to set a custom hover color is to use the `hoverColor` prop directly:
|
|
10
|
+
|
|
11
|
+
```jsx
|
|
12
|
+
import DataGrid from './components/crm/DataGrid';
|
|
13
|
+
|
|
14
|
+
// In your component
|
|
15
|
+
<DataGrid
|
|
16
|
+
hoverColor="rgb(255, 240, 230)" // Custom hover color
|
|
17
|
+
// other props...
|
|
18
|
+
/>;
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Method 2: Using CSS Variables in Component Props
|
|
22
|
+
|
|
23
|
+
You can pass a custom style object to the DataGrid component with the `--hover-color` CSS variable:
|
|
24
|
+
|
|
25
|
+
```jsx
|
|
26
|
+
import DataGrid from './components/crm/DataGrid';
|
|
27
|
+
|
|
28
|
+
// Define custom styles with hover color
|
|
29
|
+
const customStyle = {
|
|
30
|
+
'--hover-color': 'rgb(255, 240, 230)', // Custom hover color
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// In your component
|
|
34
|
+
<DataGrid
|
|
35
|
+
style={customStyle}
|
|
36
|
+
// other props...
|
|
37
|
+
/>;
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Method 3: Using CSS/SCSS
|
|
41
|
+
|
|
42
|
+
You can define the `--hover-color` CSS variable in your CSS or SCSS files:
|
|
43
|
+
|
|
44
|
+
```css
|
|
45
|
+
/* Global default hover color */
|
|
46
|
+
:root {
|
|
47
|
+
--hover-color: rgb(230, 240, 250);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* For specific containers */
|
|
51
|
+
.special-grid-container {
|
|
52
|
+
--hover-color: rgb(255, 240, 230);
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Then apply the class to your container:
|
|
57
|
+
|
|
58
|
+
```jsx
|
|
59
|
+
<div className="special-grid-container">
|
|
60
|
+
<DataGrid {...props} />
|
|
61
|
+
</div>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Default Value
|
|
65
|
+
|
|
66
|
+
If no hover color is specified (via prop or CSS variable), the DataGrid will use a default light blue color (`rgb(230, 240, 250)`).
|
|
67
|
+
|
|
68
|
+
### Example
|
|
69
|
+
|
|
70
|
+
See the `src/examples/CustomHoverDataGrid.jsx` file for a complete example of how to implement custom hover colors using all three methods.
|
|
@@ -23,8 +23,9 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
|
|
|
23
23
|
const swapy = useRef(null);
|
|
24
24
|
const container = useRef(null);
|
|
25
25
|
const navigate = useNavigate();
|
|
26
|
+
const initialLoadRef = useRef(true); // Ref to track initial load
|
|
26
27
|
const [dashboardSetting, setDashboardSetting] = useState(
|
|
27
|
-
userProfile.dashboard_setting || setting
|
|
28
|
+
dynamicDashboard ? userProfile.dashboard_setting || setting : setting
|
|
28
29
|
);
|
|
29
30
|
const [data, setData] = useState({});
|
|
30
31
|
const [dropdowns, setDropdowns] = useState({});
|
|
@@ -84,6 +85,7 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
|
|
|
84
85
|
try {
|
|
85
86
|
const promises = dashboardSetting.widgets.map(async (widget) => {
|
|
86
87
|
const widgetFilters = appliedFilters[widget.id] || {};
|
|
88
|
+
|
|
87
89
|
if (widget.filters) {
|
|
88
90
|
for (const filter of widget.filters) {
|
|
89
91
|
if (filter.url) {
|
|
@@ -110,12 +112,12 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
|
|
|
110
112
|
}
|
|
111
113
|
}
|
|
112
114
|
}
|
|
113
|
-
|
|
114
115
|
if (widget.api?.url && widget.api?.method) {
|
|
115
116
|
const requestParams = {
|
|
116
|
-
...widgetFilters,
|
|
117
117
|
...(widget.api.params || {}),
|
|
118
|
+
...widgetFilters,
|
|
118
119
|
};
|
|
120
|
+
|
|
119
121
|
return CustomFetch(
|
|
120
122
|
widget.api.url,
|
|
121
123
|
widget.api.method,
|
|
@@ -124,11 +126,21 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
|
|
|
124
126
|
}
|
|
125
127
|
return null;
|
|
126
128
|
});
|
|
129
|
+
|
|
127
130
|
const results = await Promise.all(promises);
|
|
131
|
+
|
|
128
132
|
const fetchedData = dashboardSetting.widgets.reduce(
|
|
129
133
|
(acc, widget, index) => {
|
|
130
134
|
if (results[index]) {
|
|
131
|
-
|
|
135
|
+
// Check if the response indicates an error
|
|
136
|
+
if (results[index]?.data?.value) {
|
|
137
|
+
console.error(
|
|
138
|
+
`API error for widget ${widget.id}:`,
|
|
139
|
+
results[index].data.value
|
|
140
|
+
);
|
|
141
|
+
} else {
|
|
142
|
+
acc[widget.id] = results[index]?.data;
|
|
143
|
+
}
|
|
132
144
|
}
|
|
133
145
|
return acc;
|
|
134
146
|
},
|
|
@@ -140,19 +152,41 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
|
|
|
140
152
|
}
|
|
141
153
|
};
|
|
142
154
|
|
|
155
|
+
// Single useEffect for initial data fetch
|
|
143
156
|
useEffect(() => {
|
|
144
|
-
//
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
157
|
+
// This will run once after filters are initialized
|
|
158
|
+
if (Object.keys(filters).length > 0 && initialLoadRef.current) {
|
|
159
|
+
// Fetch data once with initial filters
|
|
160
|
+
fetchData(filters);
|
|
161
|
+
// Mark initial load as complete
|
|
162
|
+
initialLoadRef.current = false;
|
|
163
|
+
}
|
|
164
|
+
}, [filters]);
|
|
165
|
+
|
|
166
|
+
// Handle filter changes after initial load
|
|
167
|
+
const isInitialFilterChangeRef = useRef(true);
|
|
148
168
|
|
|
149
|
-
|
|
150
|
-
|
|
169
|
+
useEffect(() => {
|
|
170
|
+
// Skip the first filter change (which happens during initialization)
|
|
171
|
+
if (isInitialFilterChangeRef.current) {
|
|
172
|
+
isInitialFilterChangeRef.current = false;
|
|
151
173
|
return;
|
|
152
174
|
}
|
|
153
175
|
|
|
154
|
-
|
|
155
|
-
|
|
176
|
+
// Only fetch data if filters have been initialized
|
|
177
|
+
if (!initialLoadRef.current && Object.keys(filters).length > 0) {
|
|
178
|
+
fetchData(filters);
|
|
179
|
+
}
|
|
180
|
+
}, [filters]);
|
|
181
|
+
|
|
182
|
+
// Handle dashboardSetting changes
|
|
183
|
+
useEffect(() => {
|
|
184
|
+
// Skip the initial render
|
|
185
|
+
if (!initialLoadRef.current) {
|
|
186
|
+
// Only fetch data if it's not the initial load
|
|
187
|
+
fetchData(filters);
|
|
188
|
+
}
|
|
189
|
+
}, [dashboardSetting]);
|
|
156
190
|
|
|
157
191
|
const openModal = (widgetId) => {
|
|
158
192
|
setModalContent(widgetId);
|
|
@@ -453,10 +487,12 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
|
|
|
453
487
|
<button
|
|
454
488
|
className={`${styles.btn} ${styles['btn-secondary']}`}
|
|
455
489
|
onClick={() => {
|
|
490
|
+
// Clear filters
|
|
456
491
|
setFilters((prevFilters) => ({
|
|
457
492
|
...prevFilters,
|
|
458
493
|
[widget.id]: {},
|
|
459
494
|
}));
|
|
495
|
+
|
|
460
496
|
fetchData();
|
|
461
497
|
}}
|
|
462
498
|
>
|
|
@@ -470,11 +506,22 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
|
|
|
470
506
|
|
|
471
507
|
const renderWidget = (widget) => {
|
|
472
508
|
const widgetData = data[widget.id] || [];
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
509
|
+
|
|
510
|
+
// More detailed check for valid data
|
|
511
|
+
const hasData =
|
|
512
|
+
// Array with items
|
|
513
|
+
(Array.isArray(widgetData) && widgetData.length > 0) ||
|
|
514
|
+
// Object with data array
|
|
515
|
+
(widgetData?.data &&
|
|
516
|
+
Array.isArray(widgetData.data) &&
|
|
517
|
+
widgetData.data.length > 0) ||
|
|
518
|
+
// Simple value for counter widgets
|
|
519
|
+
(widget.type === 'counter' &&
|
|
520
|
+
widgetData !== null &&
|
|
521
|
+
widgetData !== undefined);
|
|
522
|
+
|
|
523
|
+
if (hasData || widget.type === 'bar') {
|
|
524
|
+
// Always try to render bar charts for debugging
|
|
478
525
|
switch (widget.type) {
|
|
479
526
|
case 'counter':
|
|
480
527
|
return (
|
|
@@ -524,8 +571,33 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
|
|
|
524
571
|
let colors = {};
|
|
525
572
|
let keys = [];
|
|
526
573
|
|
|
527
|
-
// Handle
|
|
574
|
+
// Handle specific structure with bar.data property
|
|
528
575
|
if (
|
|
576
|
+
widgetData.bar &&
|
|
577
|
+
widgetData.bar.data &&
|
|
578
|
+
Array.isArray(widgetData.bar.data)
|
|
579
|
+
) {
|
|
580
|
+
barData = widgetData.bar.data;
|
|
581
|
+
|
|
582
|
+
// Use the keys from the data
|
|
583
|
+
if (widgetData.keys && Array.isArray(widgetData.keys)) {
|
|
584
|
+
keys = widgetData.keys;
|
|
585
|
+
} else if (barData[0]) {
|
|
586
|
+
// Extract keys from the first item, excluding indexBy field (usually 'supervisor')
|
|
587
|
+
const indexField =
|
|
588
|
+
widget.props.indexBy || 'supervisor';
|
|
589
|
+
keys = Object.keys(barData[0] || {}).filter(
|
|
590
|
+
(key) => key !== indexField
|
|
591
|
+
);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// Set the indexBy field based on the data structure
|
|
595
|
+
if (barData[0] && barData[0].supervisor) {
|
|
596
|
+
widget.props.indexBy = 'supervisor';
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
// Handle new data structure (from your first example)
|
|
600
|
+
else if (
|
|
529
601
|
widgetData.data &&
|
|
530
602
|
Array.isArray(widgetData.data) &&
|
|
531
603
|
widgetData.colors
|
|
@@ -533,9 +605,13 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
|
|
|
533
605
|
barData = widgetData.data;
|
|
534
606
|
colors = widgetData.colors;
|
|
535
607
|
// Extract keys from the first data item, excluding 'month' or any other index field
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
608
|
+
if (barData[0]) {
|
|
609
|
+
keys = Object.keys(barData[0] || {}).filter(
|
|
610
|
+
(key) => key !== 'month'
|
|
611
|
+
);
|
|
612
|
+
} else {
|
|
613
|
+
console.log(`No data items found in barData`);
|
|
614
|
+
}
|
|
539
615
|
}
|
|
540
616
|
// Handle newer data structure (from your second example)
|
|
541
617
|
else if (
|
|
@@ -545,6 +621,7 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
|
|
|
545
621
|
) {
|
|
546
622
|
barData = widgetData.data;
|
|
547
623
|
keys = widgetData.keys;
|
|
624
|
+
|
|
548
625
|
// Extract colors from the first data item
|
|
549
626
|
if (barData[0]) {
|
|
550
627
|
keys.forEach((key) => {
|
|
@@ -555,25 +632,103 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
|
|
|
555
632
|
});
|
|
556
633
|
}
|
|
557
634
|
}
|
|
635
|
+
// Handle array of arrays structure
|
|
636
|
+
else if (
|
|
637
|
+
Array.isArray(widgetData) &&
|
|
638
|
+
widgetData.length > 0 &&
|
|
639
|
+
Array.isArray(widgetData[0])
|
|
640
|
+
) {
|
|
641
|
+
barData = widgetData[0];
|
|
642
|
+
// Try to extract keys from the first item
|
|
643
|
+
if (barData[0]) {
|
|
644
|
+
keys = Object.keys(barData[0] || {}).filter(
|
|
645
|
+
(key) => key !== 'month'
|
|
646
|
+
);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
558
649
|
// Handle legacy data structure
|
|
559
650
|
else {
|
|
560
651
|
barData =
|
|
561
652
|
widgetData.bar?.data ||
|
|
562
653
|
widgetData.data ||
|
|
563
654
|
widgetData;
|
|
655
|
+
|
|
656
|
+
// Check if barData is an array of arrays and use the first one
|
|
657
|
+
if (
|
|
658
|
+
Array.isArray(barData) &&
|
|
659
|
+
barData.length > 0 &&
|
|
660
|
+
Array.isArray(barData[0])
|
|
661
|
+
) {
|
|
662
|
+
barData = barData[0];
|
|
663
|
+
}
|
|
664
|
+
|
|
564
665
|
if (widgetData.keys) {
|
|
565
|
-
keys = widgetData.keys
|
|
666
|
+
keys = Array.isArray(widgetData.keys)
|
|
667
|
+
? widgetData.keys
|
|
668
|
+
: [];
|
|
669
|
+
} else if (barData && barData[0]) {
|
|
670
|
+
// Try to extract keys from the first item
|
|
671
|
+
keys = Object.keys(barData[0] || {}).filter(
|
|
672
|
+
(key) => key !== 'month'
|
|
673
|
+
);
|
|
566
674
|
}
|
|
567
675
|
}
|
|
568
676
|
|
|
569
|
-
//
|
|
570
|
-
if
|
|
677
|
+
// Always use static colors from props if available
|
|
678
|
+
// First check if we have stored original colors
|
|
679
|
+
if (
|
|
680
|
+
widget.props._originalColors &&
|
|
681
|
+
Array.isArray(widget.props._originalColors)
|
|
682
|
+
) {
|
|
683
|
+
// Use the stored original colors
|
|
684
|
+
const originalColors = widget.props._originalColors;
|
|
685
|
+
|
|
686
|
+
// Create a direct mapping of keys to colors
|
|
687
|
+
const colorMap = {};
|
|
688
|
+
if (Array.isArray(keys)) {
|
|
689
|
+
keys.forEach((key, index) => {
|
|
690
|
+
colorMap[key] =
|
|
691
|
+
originalColors[
|
|
692
|
+
index % originalColors.length
|
|
693
|
+
];
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
// Otherwise use the colors from the props
|
|
698
|
+
else if (
|
|
699
|
+
widget.props.colors &&
|
|
700
|
+
Array.isArray(widget.props.colors) &&
|
|
701
|
+
widget.props.colors.length > 0
|
|
702
|
+
) {
|
|
703
|
+
// Store the original colors array
|
|
704
|
+
const originalColors = [...widget.props.colors];
|
|
705
|
+
|
|
706
|
+
// Create a direct mapping of keys to colors
|
|
707
|
+
const colorMap = {};
|
|
708
|
+
if (Array.isArray(keys)) {
|
|
709
|
+
keys.forEach((key, index) => {
|
|
710
|
+
colorMap[key] =
|
|
711
|
+
originalColors[
|
|
712
|
+
index % originalColors.length
|
|
713
|
+
];
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
// Store the original colors array in a separate property
|
|
718
|
+
// This ensures it's preserved for future renders
|
|
719
|
+
widget.props._originalColors = originalColors;
|
|
720
|
+
}
|
|
721
|
+
// Fallback to API colors if no static colors in props
|
|
722
|
+
else if (Object.keys(colors).length > 0) {
|
|
571
723
|
widget.props.colors = ({ id }) => colors[id];
|
|
572
724
|
}
|
|
573
725
|
|
|
574
726
|
// Set keys in props if they exist
|
|
575
|
-
if (keys.length > 0) {
|
|
727
|
+
if (Array.isArray(keys) && keys.length > 0) {
|
|
576
728
|
widget.props.keys = keys;
|
|
729
|
+
} else {
|
|
730
|
+
// Set default keys if none are found
|
|
731
|
+
widget.props.keys = ['value'];
|
|
577
732
|
}
|
|
578
733
|
|
|
579
734
|
// Handle legend setup
|
|
@@ -604,19 +759,60 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
|
|
|
604
759
|
widget.props.tooltip = CustomTooltip;
|
|
605
760
|
}
|
|
606
761
|
|
|
607
|
-
|
|
762
|
+
// Ensure barData is an array and has items
|
|
763
|
+
if (Array.isArray(barData) && barData.length > 0) {
|
|
764
|
+
// Make sure we have an indexBy field in each data item
|
|
765
|
+
const indexField = widget.props.indexBy || 'month';
|
|
766
|
+
const hasIndexField = barData.every(
|
|
767
|
+
(item) =>
|
|
768
|
+
item &&
|
|
769
|
+
typeof item === 'object' &&
|
|
770
|
+
indexField in item
|
|
771
|
+
);
|
|
772
|
+
|
|
773
|
+
if (!hasIndexField) {
|
|
774
|
+
console.warn(
|
|
775
|
+
`Bar data items missing required index field '${indexField}'`
|
|
776
|
+
);
|
|
777
|
+
// Add a default index if missing
|
|
778
|
+
barData = barData.map((item, i) => ({
|
|
779
|
+
...item,
|
|
780
|
+
[indexField]:
|
|
781
|
+
item[indexField] || `Item ${i + 1}`,
|
|
782
|
+
}));
|
|
783
|
+
}
|
|
784
|
+
|
|
608
785
|
return (
|
|
609
786
|
<div style={{ height: widget.height || '600px' }}>
|
|
610
787
|
<ResponsiveBar
|
|
611
788
|
key={`${widget.id}-${widget.size}`}
|
|
612
789
|
data={barData}
|
|
790
|
+
indexBy={indexField}
|
|
791
|
+
{...widget.props}
|
|
792
|
+
/>
|
|
793
|
+
</div>
|
|
794
|
+
);
|
|
795
|
+
} else {
|
|
796
|
+
// Create dummy data if no data is available
|
|
797
|
+
const dummyData = [
|
|
798
|
+
{
|
|
799
|
+
month: 'No Data',
|
|
800
|
+
value: 0,
|
|
801
|
+
},
|
|
802
|
+
];
|
|
803
|
+
|
|
804
|
+
return (
|
|
805
|
+
<div style={{ height: widget.height || '600px' }}>
|
|
806
|
+
<ResponsiveBar
|
|
807
|
+
key={`${widget.id}-${widget.size}`}
|
|
808
|
+
data={dummyData}
|
|
613
809
|
indexBy="month"
|
|
810
|
+
keys={['value']}
|
|
614
811
|
{...widget.props}
|
|
615
812
|
/>
|
|
616
813
|
</div>
|
|
617
814
|
);
|
|
618
815
|
}
|
|
619
|
-
break;
|
|
620
816
|
}
|
|
621
817
|
case 'line':
|
|
622
818
|
if (widgetData.length > 0) {
|
|
@@ -40,6 +40,7 @@ function useConfig(setting, tabs, filters, setRowsSelected, tableSetting) {
|
|
|
40
40
|
columns: setting.columns,
|
|
41
41
|
setRowsSelected,
|
|
42
42
|
settings: setting.settings,
|
|
43
|
+
style: setting.style || {},
|
|
43
44
|
tableSetting,
|
|
44
45
|
type: setting.type ? setting.type : 'table',
|
|
45
46
|
});
|
|
@@ -340,6 +341,7 @@ function GenericIndex({
|
|
|
340
341
|
<Table
|
|
341
342
|
{...config}
|
|
342
343
|
ref={gridRef}
|
|
344
|
+
hoverColor={config.style.hoverColor}
|
|
343
345
|
gridHeight={windowHeight * 0.65}
|
|
344
346
|
setConfig={setConfig}
|
|
345
347
|
setTableData={setTableData}
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
.vs-datagrid--row:hover {
|
|
25
25
|
.InovuaReactDataGrid__row-cell-wrap {
|
|
26
|
-
background: rgb(
|
|
26
|
+
background: var(--hover-color, rgb(230, 240, 250)) !important;
|
|
27
27
|
cursor: pointer;
|
|
28
28
|
}
|
|
29
29
|
}
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
|
|
39
39
|
.InovuaReactDataGrid__row-hover-target:hover {
|
|
40
40
|
color: var(--primary-color) !important;
|
|
41
|
-
background: rgb(
|
|
41
|
+
background: var(--hover-color, rgb(230, 240, 250)) !important;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
.InovuaReactDataGrid__row:hover {
|
|
@@ -161,7 +161,7 @@ input[type]:not([type='search']):not([type='url']):not([type='hidden']):not(
|
|
|
161
161
|
|
|
162
162
|
.vs-datagrid--row:hover {
|
|
163
163
|
.InovuaReactDataGrid__row-cell-wrap {
|
|
164
|
-
background: rgb(
|
|
164
|
+
background: var(--hover-color, rgb(230, 240, 250)) !important;
|
|
165
165
|
cursor: pointer;
|
|
166
166
|
}
|
|
167
167
|
}
|
|
@@ -176,7 +176,7 @@ input[type]:not([type='search']):not([type='url']):not([type='hidden']):not(
|
|
|
176
176
|
|
|
177
177
|
.InovuaReactDataGrid__row-hover-target:hover {
|
|
178
178
|
color: var(--paragraph-color) !important;
|
|
179
|
-
background: rgb(
|
|
179
|
+
background: var(--hover-color, rgb(230, 240, 250)) !important;
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
.InovuaReactDataGrid__row:hover {
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import DataGrid from '../components/crm/DataGrid';
|
|
3
|
+
|
|
4
|
+
// Example of using custom hover color with DataGrid
|
|
5
|
+
const CustomHoverDataGrid = () => {
|
|
6
|
+
// Example DataGrid props with direct hoverColor prop
|
|
7
|
+
const exampleProps = {
|
|
8
|
+
// Your DataGrid props here
|
|
9
|
+
hoverColor: 'rgb(255, 240, 230)', // Peachy hover color
|
|
10
|
+
// Other props...
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// Define custom styles with hover color (alternative method)
|
|
14
|
+
const customStyle = {
|
|
15
|
+
// You can define any CSS variables here
|
|
16
|
+
'--hover-color': 'rgb(230, 255, 230)', // Light green hover color
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<div>
|
|
21
|
+
<h2>DataGrid with Custom Hover Color</h2>
|
|
22
|
+
<p>
|
|
23
|
+
This example shows how to customize the hover color of the
|
|
24
|
+
DataGrid.
|
|
25
|
+
</p>
|
|
26
|
+
|
|
27
|
+
<h3>Method 1: Using the hoverColor prop (Recommended)</h3>
|
|
28
|
+
<div>
|
|
29
|
+
<DataGrid {...exampleProps} />
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<h3>Method 2: Using CSS Variables in style prop</h3>
|
|
33
|
+
<div>
|
|
34
|
+
<DataGrid style={customStyle} />
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<h3>Method 3: Using CSS/SCSS classes</h3>
|
|
38
|
+
<div className="custom-hover-grid">
|
|
39
|
+
<DataGrid />
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<h3>How to Use Custom Hover Colors</h3>
|
|
43
|
+
<p>You can set a custom hover color in three ways:</p>
|
|
44
|
+
<ol>
|
|
45
|
+
<li>
|
|
46
|
+
<strong>Using the hoverColor prop (Recommended):</strong>
|
|
47
|
+
<pre>
|
|
48
|
+
{`
|
|
49
|
+
// Direct prop approach
|
|
50
|
+
<DataGrid
|
|
51
|
+
hoverColor="rgb(255, 240, 230)"
|
|
52
|
+
{...otherProps}
|
|
53
|
+
/>
|
|
54
|
+
`}
|
|
55
|
+
</pre>
|
|
56
|
+
</li>
|
|
57
|
+
<li>
|
|
58
|
+
<strong>Using CSS Variables in style prop:</strong>
|
|
59
|
+
<pre>
|
|
60
|
+
{`
|
|
61
|
+
// Define in your component
|
|
62
|
+
const customStyle = {
|
|
63
|
+
'--hover-color': 'rgb(230, 255, 230)'
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// Apply to DataGrid
|
|
67
|
+
<DataGrid style={customStyle} {...otherProps} />
|
|
68
|
+
`}
|
|
69
|
+
</pre>
|
|
70
|
+
</li>
|
|
71
|
+
<li>
|
|
72
|
+
<strong>Using CSS/SCSS:</strong>
|
|
73
|
+
<pre>
|
|
74
|
+
{`
|
|
75
|
+
/* In your CSS/SCSS file */
|
|
76
|
+
:root {
|
|
77
|
+
--hover-color: rgb(230, 240, 250);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* For specific containers */
|
|
81
|
+
.custom-hover-grid {
|
|
82
|
+
--hover-color: rgb(200, 220, 255);
|
|
83
|
+
}
|
|
84
|
+
`}
|
|
85
|
+
</pre>
|
|
86
|
+
</li>
|
|
87
|
+
</ol>
|
|
88
|
+
</div>
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export default CustomHoverDataGrid;
|