@visns-studio/visns-components 5.4.2 → 5.4.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/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"dependencies": {
|
|
3
3
|
"@emotion/is-prop-valid": "^1.3.1",
|
|
4
|
-
"@fontsource/barlow": "^5.
|
|
4
|
+
"@fontsource/barlow": "^5.2.5",
|
|
5
5
|
"@inovua/reactdatagrid-community": "^5.10.2",
|
|
6
6
|
"@inovua/reactdatagrid-enterprise": "^5.10.2",
|
|
7
7
|
"@nivo/bar": "^0.88.0",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"fabric": "^6.5.4",
|
|
20
20
|
"file-saver": "^2.0.5",
|
|
21
21
|
"framer-motion": "^11.18.2",
|
|
22
|
-
"html-react-parser": "^5.2.
|
|
22
|
+
"html-react-parser": "^5.2.3",
|
|
23
23
|
"lodash": "^4.17.21",
|
|
24
24
|
"lodash.debounce": "^4.0.8",
|
|
25
25
|
"moment": "^2.30.1",
|
|
@@ -78,7 +78,7 @@
|
|
|
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.4",
|
|
82
82
|
"description": "Various packages to assist in the development of our Custom Applications.",
|
|
83
83
|
"main": "src/index.js",
|
|
84
84
|
"files": [
|
|
@@ -1070,10 +1070,14 @@ function GenericDetail({
|
|
|
1070
1070
|
case 'dropzone':
|
|
1071
1071
|
const downloadFile = (file) => {
|
|
1072
1072
|
const { id, file_url, file_name } = file;
|
|
1073
|
+
const toastId = toast.loading(
|
|
1074
|
+
'Downloading file...'
|
|
1075
|
+
);
|
|
1073
1076
|
|
|
1074
1077
|
// If file_url exists, use it for the download, else use the id to download
|
|
1075
1078
|
const urlToDownload =
|
|
1076
|
-
file_url ||
|
|
1079
|
+
file_url ||
|
|
1080
|
+
`/ajax/files/downloadContent/${id}`;
|
|
1077
1081
|
|
|
1078
1082
|
// Use fetch to retrieve the file as a blob
|
|
1079
1083
|
fetch(urlToDownload, {
|
|
@@ -1083,19 +1087,129 @@ function GenericDetail({
|
|
|
1083
1087
|
'application/octet-stream', // Specify content type as binary
|
|
1084
1088
|
},
|
|
1085
1089
|
})
|
|
1086
|
-
.then((response) =>
|
|
1090
|
+
.then(async (response) => {
|
|
1091
|
+
if (!response.ok) {
|
|
1092
|
+
// Try to extract error message from response if possible
|
|
1093
|
+
// Clone the response to read it as JSON first
|
|
1094
|
+
const clonedResponse =
|
|
1095
|
+
response.clone();
|
|
1096
|
+
|
|
1097
|
+
try {
|
|
1098
|
+
// First try to parse as JSON
|
|
1099
|
+
const errorData =
|
|
1100
|
+
await clonedResponse.json();
|
|
1101
|
+
|
|
1102
|
+
if (
|
|
1103
|
+
errorData &&
|
|
1104
|
+
errorData.error
|
|
1105
|
+
) {
|
|
1106
|
+
throw new Error(
|
|
1107
|
+
errorData.error
|
|
1108
|
+
);
|
|
1109
|
+
} else if (
|
|
1110
|
+
errorData &&
|
|
1111
|
+
errorData.message
|
|
1112
|
+
) {
|
|
1113
|
+
throw new Error(
|
|
1114
|
+
errorData.message
|
|
1115
|
+
);
|
|
1116
|
+
} else if (
|
|
1117
|
+
errorData &&
|
|
1118
|
+
errorData.value
|
|
1119
|
+
) {
|
|
1120
|
+
throw new Error(
|
|
1121
|
+
errorData.value
|
|
1122
|
+
);
|
|
1123
|
+
} else {
|
|
1124
|
+
// JSON parsed but no known error fields
|
|
1125
|
+
throw new Error(
|
|
1126
|
+
`HTTP error! Status: ${response.status}`
|
|
1127
|
+
);
|
|
1128
|
+
}
|
|
1129
|
+
} catch (jsonError) {
|
|
1130
|
+
// If we can't parse as JSON, try to get text
|
|
1131
|
+
try {
|
|
1132
|
+
const textResponse =
|
|
1133
|
+
response.clone();
|
|
1134
|
+
const errorText =
|
|
1135
|
+
await textResponse.text();
|
|
1136
|
+
|
|
1137
|
+
// Check if the text looks like JSON but wasn't parsed correctly
|
|
1138
|
+
if (
|
|
1139
|
+
errorText.includes(
|
|
1140
|
+
'"error":'
|
|
1141
|
+
)
|
|
1142
|
+
) {
|
|
1143
|
+
// Try to extract the error message with regex
|
|
1144
|
+
const errorMatch =
|
|
1145
|
+
errorText.match(
|
|
1146
|
+
/"error":"([^"]+)"/i
|
|
1147
|
+
);
|
|
1148
|
+
if (
|
|
1149
|
+
errorMatch &&
|
|
1150
|
+
errorMatch[1]
|
|
1151
|
+
) {
|
|
1152
|
+
throw new Error(
|
|
1153
|
+
errorMatch[1]
|
|
1154
|
+
);
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
// If we got text but couldn't extract a specific error
|
|
1159
|
+
if (
|
|
1160
|
+
errorText &&
|
|
1161
|
+
errorText.length < 100
|
|
1162
|
+
) {
|
|
1163
|
+
throw new Error(
|
|
1164
|
+
errorText
|
|
1165
|
+
);
|
|
1166
|
+
}
|
|
1167
|
+
} catch (textError) {
|
|
1168
|
+
// If all else fails, fall back to status
|
|
1169
|
+
throw new Error(
|
|
1170
|
+
`HTTP error! Status: ${response.status}`
|
|
1171
|
+
);
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
return response.blob(); // Convert response to Blob
|
|
1176
|
+
})
|
|
1087
1177
|
.then((blob) => {
|
|
1178
|
+
// Validate that we have a valid blob with content
|
|
1179
|
+
if (!blob || blob.size === 0) {
|
|
1180
|
+
throw new Error(
|
|
1181
|
+
'Downloaded file is empty or invalid'
|
|
1182
|
+
);
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1088
1185
|
// Use FileSaver to download the file with the specified name
|
|
1089
1186
|
saveAs(blob, file_name);
|
|
1187
|
+
|
|
1188
|
+
toast.update(toastId, {
|
|
1189
|
+
render: 'Download successful!',
|
|
1190
|
+
type: 'success',
|
|
1191
|
+
isLoading: false,
|
|
1192
|
+
autoClose: 5000,
|
|
1193
|
+
closeButton: true,
|
|
1194
|
+
});
|
|
1090
1195
|
})
|
|
1091
1196
|
.catch((error) => {
|
|
1092
1197
|
console.error(
|
|
1093
1198
|
'Error downloading the file:',
|
|
1094
1199
|
error
|
|
1095
1200
|
);
|
|
1201
|
+
|
|
1202
|
+
toast.update(toastId, {
|
|
1203
|
+
render: `Error downloading file: ${
|
|
1204
|
+
error.message || 'Unknown error'
|
|
1205
|
+
}`,
|
|
1206
|
+
type: 'error',
|
|
1207
|
+
isLoading: false,
|
|
1208
|
+
autoClose: 5000,
|
|
1209
|
+
closeButton: true,
|
|
1210
|
+
});
|
|
1096
1211
|
});
|
|
1097
1212
|
};
|
|
1098
|
-
|
|
1099
1213
|
const deleteFile = (e, id, name) => {
|
|
1100
1214
|
if (e) {
|
|
1101
1215
|
e.stopPropagation();
|
|
@@ -434,42 +434,109 @@ const GenericDynamic = ({
|
|
|
434
434
|
|
|
435
435
|
const handleCustomButton = async (s) => {
|
|
436
436
|
let payload = {};
|
|
437
|
-
|
|
438
|
-
case 'save':
|
|
439
|
-
if (s.payload?.length > 0) {
|
|
440
|
-
s.payload.forEach((p) => {
|
|
441
|
-
if (data[p]) {
|
|
442
|
-
payload[p] = data[p];
|
|
443
|
-
}
|
|
444
|
-
});
|
|
445
|
-
}
|
|
437
|
+
let toastId;
|
|
446
438
|
|
|
447
|
-
|
|
439
|
+
try {
|
|
440
|
+
switch (s.type) {
|
|
441
|
+
case 'save':
|
|
442
|
+
toastId = toast.loading('Downloading file...');
|
|
443
|
+
|
|
444
|
+
if (s.payload?.length > 0) {
|
|
445
|
+
s.payload.forEach((p) => {
|
|
446
|
+
if (data[p]) {
|
|
447
|
+
payload[p] = data[p];
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
}
|
|
448
451
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
452
|
+
const resSave = await Download(s.url, s.method, payload);
|
|
453
|
+
|
|
454
|
+
if (resSave.data) {
|
|
455
|
+
// Check if response has a value property which indicates an error
|
|
456
|
+
if (resSave.data.value) {
|
|
457
|
+
toast.update(toastId, {
|
|
458
|
+
render: `Error: ${resSave.data.value}`,
|
|
459
|
+
type: 'error',
|
|
460
|
+
isLoading: false,
|
|
461
|
+
autoClose: 5000,
|
|
462
|
+
closeButton: true,
|
|
463
|
+
});
|
|
464
|
+
} else {
|
|
465
|
+
saveAs(resSave.data);
|
|
466
|
+
toast.update(toastId, {
|
|
467
|
+
render: 'Download successful!',
|
|
468
|
+
type: 'success',
|
|
469
|
+
isLoading: false,
|
|
470
|
+
autoClose: 5000,
|
|
471
|
+
closeButton: true,
|
|
472
|
+
});
|
|
458
473
|
}
|
|
459
|
-
}
|
|
460
|
-
|
|
474
|
+
} else {
|
|
475
|
+
toast.update(toastId, {
|
|
476
|
+
render: 'Error: No data received',
|
|
477
|
+
type: 'error',
|
|
478
|
+
isLoading: false,
|
|
479
|
+
autoClose: 5000,
|
|
480
|
+
closeButton: true,
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
break;
|
|
461
484
|
|
|
462
|
-
|
|
485
|
+
case 'fetch':
|
|
486
|
+
toastId = toast.loading('Fetching data...');
|
|
463
487
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
488
|
+
if (s.payload?.length > 0) {
|
|
489
|
+
s.payload.forEach((p) => {
|
|
490
|
+
if (data[p]) {
|
|
491
|
+
payload[p] = data[p];
|
|
492
|
+
}
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
const resFetch = await CustomFetch(
|
|
497
|
+
s.url,
|
|
498
|
+
s.method,
|
|
499
|
+
payload
|
|
467
500
|
);
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
501
|
+
|
|
502
|
+
if (resFetch.data.error === '') {
|
|
503
|
+
toast.update(toastId, {
|
|
504
|
+
render: s.message
|
|
505
|
+
? s.message
|
|
506
|
+
: 'Form fetched successfully',
|
|
507
|
+
type: 'success',
|
|
508
|
+
isLoading: false,
|
|
509
|
+
autoClose: 5000,
|
|
510
|
+
closeButton: true,
|
|
511
|
+
});
|
|
512
|
+
} else {
|
|
513
|
+
toast.update(toastId, {
|
|
514
|
+
render: `Error: ${resFetch.data.error}`,
|
|
515
|
+
type: 'error',
|
|
516
|
+
isLoading: false,
|
|
517
|
+
autoClose: 5000,
|
|
518
|
+
closeButton: true,
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
break;
|
|
522
|
+
|
|
523
|
+
default:
|
|
524
|
+
console.info(s, 'default');
|
|
525
|
+
break;
|
|
526
|
+
}
|
|
527
|
+
} catch (error) {
|
|
528
|
+
console.error('Error in handleCustomButton:', error);
|
|
529
|
+
if (toastId) {
|
|
530
|
+
toast.update(toastId, {
|
|
531
|
+
render: `Error: ${error.message || 'Unknown error'}`,
|
|
532
|
+
type: 'error',
|
|
533
|
+
isLoading: false,
|
|
534
|
+
autoClose: 5000,
|
|
535
|
+
closeButton: true,
|
|
536
|
+
});
|
|
537
|
+
} else {
|
|
538
|
+
toast.error(`Error: ${error.message || 'Unknown error'}`);
|
|
539
|
+
}
|
|
473
540
|
}
|
|
474
541
|
};
|
|
475
542
|
|
|
@@ -713,10 +780,33 @@ const GenericDynamic = ({
|
|
|
713
780
|
setActiveFormKey(0);
|
|
714
781
|
}
|
|
715
782
|
} else {
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
783
|
+
let activeFormData;
|
|
784
|
+
|
|
785
|
+
if (Array.isArray(data[type])) {
|
|
786
|
+
console.info('a');
|
|
787
|
+
// Check if this is an array of fields or an array of arrays of fields
|
|
788
|
+
if (data[type].length > 0) {
|
|
789
|
+
// Check if the first item has field properties or is itself an array of fields
|
|
790
|
+
const firstItem = data[type][0];
|
|
791
|
+
if (
|
|
792
|
+
Array.isArray(firstItem) ||
|
|
793
|
+
(typeof firstItem === 'object' &&
|
|
794
|
+
firstItem !== null &&
|
|
795
|
+
(firstItem.hasOwnProperty('id') ||
|
|
796
|
+
firstItem.hasOwnProperty('type')))
|
|
797
|
+
) {
|
|
798
|
+
activeFormData = data[type];
|
|
799
|
+
} else {
|
|
800
|
+
activeFormData = data[type][0];
|
|
801
|
+
}
|
|
802
|
+
} else {
|
|
803
|
+
// Empty array, use as is
|
|
804
|
+
activeFormData = data[type];
|
|
805
|
+
}
|
|
806
|
+
} else {
|
|
807
|
+
// Not an array, use as is
|
|
808
|
+
activeFormData = data[type];
|
|
809
|
+
}
|
|
720
810
|
|
|
721
811
|
setActiveForm(activeFormData);
|
|
722
812
|
setActiveFormKey(0);
|