@visns-studio/visns-components 4.10.6 → 4.10.8
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/components/crm/DataGrid.jsx +255 -16
package/package.json
CHANGED
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"react-dom": "^17.0.0 || ^18.0.0"
|
|
76
76
|
},
|
|
77
77
|
"name": "@visns-studio/visns-components",
|
|
78
|
-
"version": "4.10.
|
|
78
|
+
"version": "4.10.8",
|
|
79
79
|
"description": "Various packages to assist in the development of our Custom Applications.",
|
|
80
80
|
"main": "src/index.js",
|
|
81
81
|
"files": [
|
|
@@ -60,6 +60,7 @@ import CustomFetch from './Fetch';
|
|
|
60
60
|
import Download from './Download';
|
|
61
61
|
import Form from './Form';
|
|
62
62
|
import _ from 'lodash';
|
|
63
|
+
import { distance2D } from 'framer-motion';
|
|
63
64
|
|
|
64
65
|
const loadData = async (
|
|
65
66
|
{ skip, limit, sortInfo, filterValue },
|
|
@@ -149,6 +150,19 @@ const DataGrid = forwardRef(
|
|
|
149
150
|
}
|
|
150
151
|
}, [audioSource]);
|
|
151
152
|
|
|
153
|
+
/** JSON Modal States */
|
|
154
|
+
const [modalJsonShow, setModalJsonShow] = useState(false);
|
|
155
|
+
const [jsonData, setJsonData] = useState({});
|
|
156
|
+
|
|
157
|
+
/** JSON Modal Functions */
|
|
158
|
+
const modalJsonOpen = () => {
|
|
159
|
+
setModalJsonShow(true);
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const modalJsonClose = () => {
|
|
163
|
+
setModalJsonShow(false);
|
|
164
|
+
};
|
|
165
|
+
|
|
152
166
|
/** Gallery Modal States */
|
|
153
167
|
const [modalGalleryShow, setModalGalleryShow] = useState(false);
|
|
154
168
|
const [galleryData, setGalleryData] = useState([]);
|
|
@@ -228,23 +242,65 @@ const DataGrid = forwardRef(
|
|
|
228
242
|
const toastId = toast.loading('Starting download please wait...');
|
|
229
243
|
|
|
230
244
|
try {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
245
|
+
if (d.id && d.id > 0) {
|
|
246
|
+
const res = await Download(
|
|
247
|
+
`/ajax/files/download/${d.id}/null`,
|
|
248
|
+
'GET',
|
|
249
|
+
{}
|
|
250
|
+
);
|
|
236
251
|
|
|
237
|
-
|
|
238
|
-
|
|
252
|
+
if (res.data.error) {
|
|
253
|
+
toast.error(res.data.error);
|
|
254
|
+
} else {
|
|
255
|
+
// Assuming the response contains a Blob or similar data
|
|
256
|
+
if (res.data && res.data instanceof Blob) {
|
|
257
|
+
const fileName = `${d.file_name}`;
|
|
258
|
+
saveAs(res.data, fileName);
|
|
259
|
+
} else {
|
|
260
|
+
// Handle the case where the response is not a Blob
|
|
261
|
+
toast.error('Invalid file format received.');
|
|
262
|
+
}
|
|
263
|
+
}
|
|
239
264
|
} else {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
265
|
+
toast.error(
|
|
266
|
+
'An issue with downloading the file has occurred.'
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
} catch (error) {
|
|
270
|
+
console.info(error);
|
|
271
|
+
} finally {
|
|
272
|
+
// Dismiss the loading toast in the finally block to ensure it's always dismissed
|
|
273
|
+
toast.dismiss(toastId);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
const handleDownloadPath = async (file) => {
|
|
278
|
+
const toastId = toast.loading('Starting download please wait...');
|
|
279
|
+
|
|
280
|
+
try {
|
|
281
|
+
if (file.file_path && file.file_name && file.file_extension) {
|
|
282
|
+
const res = await Download(
|
|
283
|
+
`/ajax/files/downloadByPath`,
|
|
284
|
+
'POST',
|
|
285
|
+
{ ...file }
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
if (res.data.error) {
|
|
289
|
+
toast.error(res.data.error);
|
|
244
290
|
} else {
|
|
245
|
-
//
|
|
246
|
-
|
|
291
|
+
// Assuming the response contains a Blob or similar data
|
|
292
|
+
if (res.data && res.data instanceof Blob) {
|
|
293
|
+
const fileName = `${file.file_name}`;
|
|
294
|
+
saveAs(res.data, fileName);
|
|
295
|
+
} else {
|
|
296
|
+
// Handle the case where the response is not a Blob
|
|
297
|
+
toast.error('Invalid file format received.');
|
|
298
|
+
}
|
|
247
299
|
}
|
|
300
|
+
} else {
|
|
301
|
+
toast.error(
|
|
302
|
+
'An issue with downloading the file has occurred.'
|
|
303
|
+
);
|
|
248
304
|
}
|
|
249
305
|
} catch (error) {
|
|
250
306
|
console.info(error);
|
|
@@ -570,6 +626,15 @@ const DataGrid = forwardRef(
|
|
|
570
626
|
);
|
|
571
627
|
}
|
|
572
628
|
break;
|
|
629
|
+
case 'view':
|
|
630
|
+
modalJsonOpen();
|
|
631
|
+
console.info(d[s.key], s.headers);
|
|
632
|
+
setJsonData((prevState) => ({
|
|
633
|
+
...prevState,
|
|
634
|
+
data: d[s.key],
|
|
635
|
+
headers: s.headers,
|
|
636
|
+
}));
|
|
637
|
+
break;
|
|
573
638
|
case 'update':
|
|
574
639
|
modalOpen('update', d.id);
|
|
575
640
|
break;
|
|
@@ -1127,6 +1192,8 @@ const DataGrid = forwardRef(
|
|
|
1127
1192
|
return getIconComponent(Clock);
|
|
1128
1193
|
case 'update':
|
|
1129
1194
|
return getIconComponent(Edit);
|
|
1195
|
+
case 'view':
|
|
1196
|
+
return getIconComponent(Search);
|
|
1130
1197
|
default:
|
|
1131
1198
|
return null;
|
|
1132
1199
|
}
|
|
@@ -1709,9 +1776,19 @@ const DataGrid = forwardRef(
|
|
|
1709
1776
|
onClick={(e) => {
|
|
1710
1777
|
e.stopPropagation();
|
|
1711
1778
|
e.preventDefault();
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1779
|
+
|
|
1780
|
+
if (
|
|
1781
|
+
file.id &&
|
|
1782
|
+
file.id > 0
|
|
1783
|
+
) {
|
|
1784
|
+
handleDownload(
|
|
1785
|
+
file
|
|
1786
|
+
);
|
|
1787
|
+
} else {
|
|
1788
|
+
handleDownloadPath(
|
|
1789
|
+
file
|
|
1790
|
+
);
|
|
1791
|
+
}
|
|
1715
1792
|
}}
|
|
1716
1793
|
style={{
|
|
1717
1794
|
marginRight:
|
|
@@ -2526,6 +2603,69 @@ const DataGrid = forwardRef(
|
|
|
2526
2603
|
}
|
|
2527
2604
|
};
|
|
2528
2605
|
|
|
2606
|
+
const snakeCaseToTitle = (text) => {
|
|
2607
|
+
return text
|
|
2608
|
+
.replace(/_/g, ' ')
|
|
2609
|
+
.replace(/\b\w/g, (char) => char.toUpperCase()); // Capitalize first letter of each word
|
|
2610
|
+
};
|
|
2611
|
+
|
|
2612
|
+
// Recursive function to handle nested objects
|
|
2613
|
+
const renderField = (key, value) => {
|
|
2614
|
+
// If the value is an object, recursively render its fields
|
|
2615
|
+
if (typeof value === 'object' && value !== null) {
|
|
2616
|
+
return (
|
|
2617
|
+
<div key={key} style={{ marginBottom: '1rem' }}>
|
|
2618
|
+
<h4
|
|
2619
|
+
style={{
|
|
2620
|
+
fontSize: '1.2rem',
|
|
2621
|
+
marginBottom: '0.5rem',
|
|
2622
|
+
color: '#333',
|
|
2623
|
+
borderBottom: '1px solid #ccc',
|
|
2624
|
+
}}
|
|
2625
|
+
>
|
|
2626
|
+
{snakeCaseToTitle(key)}
|
|
2627
|
+
</h4>
|
|
2628
|
+
<div style={{ paddingLeft: '1.5rem' }}>
|
|
2629
|
+
{Object.keys(value).map((childKey) =>
|
|
2630
|
+
renderField(childKey, value[childKey])
|
|
2631
|
+
)}
|
|
2632
|
+
</div>
|
|
2633
|
+
</div>
|
|
2634
|
+
);
|
|
2635
|
+
}
|
|
2636
|
+
// Otherwise, render the key and value as a label and paragraph
|
|
2637
|
+
return (
|
|
2638
|
+
<div key={key} style={{ marginBottom: '1rem' }}>
|
|
2639
|
+
<span
|
|
2640
|
+
style={{
|
|
2641
|
+
fontWeight: 'bold',
|
|
2642
|
+
marginBottom: '0.2rem',
|
|
2643
|
+
display: 'block',
|
|
2644
|
+
color: '#444',
|
|
2645
|
+
}}
|
|
2646
|
+
>
|
|
2647
|
+
{snakeCaseToTitle(key)}
|
|
2648
|
+
</span>
|
|
2649
|
+
<p
|
|
2650
|
+
style={{
|
|
2651
|
+
margin: 0,
|
|
2652
|
+
color: '#666',
|
|
2653
|
+
backgroundColor: '#f9f9f9',
|
|
2654
|
+
padding: '0.5rem',
|
|
2655
|
+
borderRadius: '5px',
|
|
2656
|
+
}}
|
|
2657
|
+
>
|
|
2658
|
+
{value !== null ? value : 'N/A'}
|
|
2659
|
+
</p>
|
|
2660
|
+
</div>
|
|
2661
|
+
);
|
|
2662
|
+
};
|
|
2663
|
+
|
|
2664
|
+
const getHeaderLabel = (headers, parentKey) => {
|
|
2665
|
+
const headerObj = headers.find((header) => header.id === parentKey);
|
|
2666
|
+
return headerObj ? headerObj.label : snakeCaseToTitle(parentKey);
|
|
2667
|
+
};
|
|
2668
|
+
|
|
2529
2669
|
useEffect(() => {
|
|
2530
2670
|
columns.forEach((column) => {
|
|
2531
2671
|
if (column.filter && column.filter.url) {
|
|
@@ -2578,10 +2718,15 @@ const DataGrid = forwardRef(
|
|
|
2578
2718
|
: 400,
|
|
2579
2719
|
boxShadow: 'none',
|
|
2580
2720
|
});
|
|
2721
|
+
|
|
2581
2722
|
const headerProps = {
|
|
2582
2723
|
style: style ? style : {},
|
|
2583
2724
|
};
|
|
2584
2725
|
|
|
2726
|
+
useEffect(() => {
|
|
2727
|
+
console.info(jsonData);
|
|
2728
|
+
}, [jsonData]);
|
|
2729
|
+
|
|
2585
2730
|
useEffect(() => {
|
|
2586
2731
|
const getMinimumHeight = () => {
|
|
2587
2732
|
if (gridHeight > 0) return gridHeight;
|
|
@@ -2722,6 +2867,100 @@ const DataGrid = forwardRef(
|
|
|
2722
2867
|
</div>
|
|
2723
2868
|
</div>
|
|
2724
2869
|
</Popup>
|
|
2870
|
+
<Popup
|
|
2871
|
+
open={modalJsonShow}
|
|
2872
|
+
onClose={modalJsonClose}
|
|
2873
|
+
closeOnDocumentClick={false}
|
|
2874
|
+
>
|
|
2875
|
+
<div
|
|
2876
|
+
className={`${styles.modalwrap} ${styles['top--modal']}`}
|
|
2877
|
+
>
|
|
2878
|
+
<div className={styles.modal}>
|
|
2879
|
+
<div className={styles.modal__header}>
|
|
2880
|
+
<h1>View Data</h1>
|
|
2881
|
+
<button
|
|
2882
|
+
className={styles.modal__close}
|
|
2883
|
+
onClick={modalJsonClose}
|
|
2884
|
+
>
|
|
2885
|
+
<CircleX strokeWidth={1} size={24} />
|
|
2886
|
+
</button>
|
|
2887
|
+
</div>
|
|
2888
|
+
<div className={styles.modal__content}>
|
|
2889
|
+
<div className={styles.formcontainer}>
|
|
2890
|
+
<div
|
|
2891
|
+
style={{
|
|
2892
|
+
lineHeight: '1.5',
|
|
2893
|
+
}}
|
|
2894
|
+
>
|
|
2895
|
+
{jsonData.headers &&
|
|
2896
|
+
jsonData.headers.map((header) => {
|
|
2897
|
+
const parentKey = header.id;
|
|
2898
|
+
|
|
2899
|
+
// Skip rendering if the parentKey is "id" or doesn't exist in jsonData
|
|
2900
|
+
if (
|
|
2901
|
+
parentKey === 'id' ||
|
|
2902
|
+
!(
|
|
2903
|
+
parentKey in
|
|
2904
|
+
jsonData.data
|
|
2905
|
+
)
|
|
2906
|
+
)
|
|
2907
|
+
return null;
|
|
2908
|
+
|
|
2909
|
+
return (
|
|
2910
|
+
<div
|
|
2911
|
+
key={parentKey}
|
|
2912
|
+
style={{
|
|
2913
|
+
marginBottom:
|
|
2914
|
+
'2rem',
|
|
2915
|
+
}}
|
|
2916
|
+
>
|
|
2917
|
+
{/* Section Header */}
|
|
2918
|
+
<h3
|
|
2919
|
+
style={{
|
|
2920
|
+
fontSize:
|
|
2921
|
+
'1.4rem',
|
|
2922
|
+
marginBottom:
|
|
2923
|
+
'1rem',
|
|
2924
|
+
color: '#222',
|
|
2925
|
+
borderBottom:
|
|
2926
|
+
'2px solid #ddd',
|
|
2927
|
+
}}
|
|
2928
|
+
>
|
|
2929
|
+
{getHeaderLabel(
|
|
2930
|
+
jsonData.headers,
|
|
2931
|
+
parentKey
|
|
2932
|
+
)}
|
|
2933
|
+
</h3>
|
|
2934
|
+
<div
|
|
2935
|
+
style={{
|
|
2936
|
+
paddingLeft:
|
|
2937
|
+
'1rem',
|
|
2938
|
+
}}
|
|
2939
|
+
>
|
|
2940
|
+
{/* Render fields for each section */}
|
|
2941
|
+
{Object.keys(
|
|
2942
|
+
jsonData.data[
|
|
2943
|
+
parentKey
|
|
2944
|
+
]
|
|
2945
|
+
).map((childKey) =>
|
|
2946
|
+
renderField(
|
|
2947
|
+
childKey,
|
|
2948
|
+
jsonData
|
|
2949
|
+
.data[
|
|
2950
|
+
parentKey
|
|
2951
|
+
][childKey]
|
|
2952
|
+
)
|
|
2953
|
+
)}
|
|
2954
|
+
</div>
|
|
2955
|
+
</div>
|
|
2956
|
+
);
|
|
2957
|
+
})}
|
|
2958
|
+
</div>
|
|
2959
|
+
</div>
|
|
2960
|
+
</div>
|
|
2961
|
+
</div>
|
|
2962
|
+
</div>
|
|
2963
|
+
</Popup>
|
|
2725
2964
|
</>
|
|
2726
2965
|
);
|
|
2727
2966
|
}
|