@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.1.1",
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.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.2",
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 || `/ajax/files/download/${id}`;
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) => response.blob()) // Convert response to Blob
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
- switch (s.type) {
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
- const resSave = await Download(s.url, s.method, payload);
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
- if (resSave.data) {
450
- saveAs(resSave.data);
451
- }
452
- break;
453
- case 'fetch':
454
- if (s.payload?.length > 0) {
455
- s.payload.forEach((p) => {
456
- if (data[p]) {
457
- payload[p] = data[p];
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
- const resFetch = await CustomFetch(s.url, s.method, payload);
485
+ case 'fetch':
486
+ toastId = toast.loading('Fetching data...');
463
487
 
464
- if (resFetch.data.error === '') {
465
- toast.success(
466
- s.message ? s.message : 'Form fetched successfully'
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
- break;
470
- default:
471
- console.info(s, 'default');
472
- break;
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
- const activeFormData =
717
- data[type].length > 0 && Array.isArray(data[type])
718
- ? data[type][0]
719
- : data[type];
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);