ui-soxo-bootstrap-core 2.6.1-dev.11 → 2.6.1-dev.13
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/core/components/landing-api/landing-api.js +66 -2
- package/core/components/landing-api/landing-api.scss +22 -0
- package/core/lib/models/forms/components/form-creator/form-creator.scss +1 -1
- package/core/models/core-scripts/core-scripts.js +134 -135
- package/core/models/menus/components/menu-lists/menu-lists.js +49 -46
- package/core/modules/reporting/components/reporting-dashboard/adavance-search/advance-search.js +49 -168
- package/core/modules/reporting/components/reporting-dashboard/adavance-search/advance-search.scss +76 -0
- package/core/modules/reporting/components/reporting-dashboard/reporting-dashboard.js +187 -185
- package/core/modules/reporting/components/reporting-dashboard/reporting-dashboard.scss +7 -0
- package/core/modules/steps/action-buttons.js +6 -0
- package/core/modules/steps/action-buttons.scss +9 -3
- package/core/modules/steps/steps.js +46 -5
- package/core/modules/steps/steps.scss +82 -13
- package/package.json +1 -1
|
@@ -344,144 +344,6 @@ export default function ReportingDashboard({
|
|
|
344
344
|
}
|
|
345
345
|
};
|
|
346
346
|
|
|
347
|
-
/**
|
|
348
|
-
*
|
|
349
|
-
* @param {*} searchValues
|
|
350
|
-
* @param {*} searchParameters
|
|
351
|
-
* @returns
|
|
352
|
-
*/
|
|
353
|
-
const buildSearchCondition = (searchValues, searchParameters) => {
|
|
354
|
-
let searchCondition = '';
|
|
355
|
-
|
|
356
|
-
Object.keys(searchValues).forEach((key) => {
|
|
357
|
-
const arr = searchValues[key];
|
|
358
|
-
if (!Array.isArray(arr) || arr.length === 0) return;
|
|
359
|
-
|
|
360
|
-
const param = searchParameters.find((p) => p.field === key);
|
|
361
|
-
if (!param) return;
|
|
362
|
-
|
|
363
|
-
const operator = (param.search_operator || '').trim().toUpperCase();
|
|
364
|
-
const column = param.db_column || key;
|
|
365
|
-
|
|
366
|
-
if (operator === 'LIKE') {
|
|
367
|
-
const likeConditions = arr.map((v) => `${column} LIKE '${v}'`).join(' OR ');
|
|
368
|
-
searchCondition += ` AND (${likeConditions})`;
|
|
369
|
-
} else if (operator === 'IN') {
|
|
370
|
-
const valueList = arr.map((v) => `'${v}'`).join(',');
|
|
371
|
-
searchCondition += ` AND ${column} IN (${valueList})`;
|
|
372
|
-
} else if (operator === '=') {
|
|
373
|
-
const eqConditions = arr.map((v) => `${column} = '${v}'`).join(' OR ');
|
|
374
|
-
searchCondition += ` AND (${eqConditions})`;
|
|
375
|
-
} else if (operator === '!=') {
|
|
376
|
-
const neqConditions = arr.map((v) => `${column} != '${v}'`).join(' AND ');
|
|
377
|
-
searchCondition += ` AND (${neqConditions})`;
|
|
378
|
-
} else {
|
|
379
|
-
// fallback for other operators like > < >= <=
|
|
380
|
-
const conditions = arr.map((v) => `${column} ${operator} '${v}'`).join(' OR ');
|
|
381
|
-
searchCondition += ` AND (${conditions})`;
|
|
382
|
-
}
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
return searchCondition;
|
|
386
|
-
};
|
|
387
|
-
// const handleSubmit = (values) => {
|
|
388
|
-
// const hasSearchValues = Object.values(searchValues).some((v) => Array.isArray(v) && v.length > 0);
|
|
389
|
-
|
|
390
|
-
// // Check if regular form values have changed since the last submission.
|
|
391
|
-
// const regularValuesChanged = (() => {
|
|
392
|
-
// const newKeys = Object.keys(values);
|
|
393
|
-
// const oldKeys = Object.keys(formContents);
|
|
394
|
-
|
|
395
|
-
// if (newKeys.length !== oldKeys.length) return true;
|
|
396
|
-
|
|
397
|
-
// for (const key of newKeys) {
|
|
398
|
-
// const newValue = values[key];
|
|
399
|
-
// const oldValue = formContents[key];
|
|
400
|
-
|
|
401
|
-
// if (moment.isMoment(newValue) && moment.isMoment(oldValue)) {
|
|
402
|
-
// if (!newValue.isSame(oldValue)) {
|
|
403
|
-
// return true;
|
|
404
|
-
// }
|
|
405
|
-
// } else if (newValue !== oldValue) {
|
|
406
|
-
// // This is a shallow comparison, but should work for primitives and new array/object references.
|
|
407
|
-
// return true;
|
|
408
|
-
// }
|
|
409
|
-
// }
|
|
410
|
-
// return false;
|
|
411
|
-
// })();
|
|
412
|
-
|
|
413
|
-
// if (hasSearchValues && regularValuesChanged) {
|
|
414
|
-
// Modal.confirm({
|
|
415
|
-
// title: 'Combine Filters',
|
|
416
|
-
// content: 'You have applied both standard and advanced filters. Do you want to combine them?',
|
|
417
|
-
// okText: 'Yes, Apply Both',
|
|
418
|
-
// cancelText: 'No, Use Advanced Only',
|
|
419
|
-
// onOk: () => {
|
|
420
|
-
// // User chose to combine filters.
|
|
421
|
-
// const searchCondition = buildSearchCondition(searchValues, searchParameters);
|
|
422
|
-
// const finalValues = {
|
|
423
|
-
// ...values,
|
|
424
|
-
// search_condition: searchCondition,
|
|
425
|
-
// };
|
|
426
|
-
// onFinish(finalValues, 1);
|
|
427
|
-
// },
|
|
428
|
-
// onCancel: () => {
|
|
429
|
-
// // User chose to use only advanced search.
|
|
430
|
-
// const searchCondition = buildSearchCondition(searchValues, searchParameters);
|
|
431
|
-
// const resetValues = {};
|
|
432
|
-
// Object.keys(values).forEach((key) => {
|
|
433
|
-
// resetValues[key] = null;
|
|
434
|
-
// });
|
|
435
|
-
// const finalValues = {
|
|
436
|
-
// ...resetValues,
|
|
437
|
-
// search_condition: searchCondition,
|
|
438
|
-
// };
|
|
439
|
-
// onFinish(finalValues, 1);
|
|
440
|
-
// },
|
|
441
|
-
// });
|
|
442
|
-
// return; // Stop further execution, wait for modal response.
|
|
443
|
-
// }
|
|
444
|
-
|
|
445
|
-
// // --- Default behavior if the condition for the modal is not met ---
|
|
446
|
-
|
|
447
|
-
// let finalValues = values;
|
|
448
|
-
// if (hasSearchValues) {
|
|
449
|
-
// // If only advanced search has values (or regular filters haven't changed), reset regular filters.
|
|
450
|
-
// const searchCondition = buildSearchCondition(searchValues, searchParameters);
|
|
451
|
-
// const resetValues = {};
|
|
452
|
-
// Object.keys(values).forEach((key) => {
|
|
453
|
-
// resetValues[key] = null;
|
|
454
|
-
// });
|
|
455
|
-
// finalValues = {
|
|
456
|
-
// ...resetValues,
|
|
457
|
-
// search_condition: searchCondition,
|
|
458
|
-
// };
|
|
459
|
-
// }
|
|
460
|
-
|
|
461
|
-
// const { pageSize } = pagination;
|
|
462
|
-
// const resetPage = 1;
|
|
463
|
-
|
|
464
|
-
// scriptId.current = null;
|
|
465
|
-
|
|
466
|
-
// // Update URL only when NOT using advanced search
|
|
467
|
-
// if (!hasSearchValues) {
|
|
468
|
-
// const currentUrlParams = Location.search();
|
|
469
|
-
// const { script_id, selected_card, ...cleanParams } = currentUrlParams;
|
|
470
|
-
|
|
471
|
-
// const newParams = new URLSearchParams({
|
|
472
|
-
// ...cleanParams,
|
|
473
|
-
// current: resetPage,
|
|
474
|
-
// pageSize,
|
|
475
|
-
// });
|
|
476
|
-
|
|
477
|
-
// const newUrl = `${window.location.pathname}?${newParams.toString()}`;
|
|
478
|
-
// window.history.replaceState({}, '', newUrl);
|
|
479
|
-
// }
|
|
480
|
-
|
|
481
|
-
// // Call report API
|
|
482
|
-
// onFinish(finalValues, resetPage);
|
|
483
|
-
// };
|
|
484
|
-
|
|
485
347
|
const handleSubmit = (values) => {
|
|
486
348
|
const hasSearchValues = Object.values(searchValues).some((v) => Array.isArray(v) && v.length > 0);
|
|
487
349
|
|
|
@@ -511,11 +373,9 @@ export default function ReportingDashboard({
|
|
|
511
373
|
|
|
512
374
|
onOk() {
|
|
513
375
|
// YES → send form values + search condition
|
|
514
|
-
const searchCondition = buildSearchCondition(searchValues, searchParameters);
|
|
515
|
-
|
|
516
376
|
const finalValues = {
|
|
517
377
|
...values,
|
|
518
|
-
|
|
378
|
+
search_values: searchValues,
|
|
519
379
|
};
|
|
520
380
|
|
|
521
381
|
runSubmit(finalValues);
|
|
@@ -523,8 +383,6 @@ export default function ReportingDashboard({
|
|
|
523
383
|
|
|
524
384
|
onCancel() {
|
|
525
385
|
// NO → reset form values
|
|
526
|
-
const searchCondition = buildSearchCondition(searchValues, searchParameters);
|
|
527
|
-
|
|
528
386
|
const resetValues = {};
|
|
529
387
|
Object.keys(values).forEach((key) => {
|
|
530
388
|
resetValues[key] = null;
|
|
@@ -532,7 +390,7 @@ export default function ReportingDashboard({
|
|
|
532
390
|
|
|
533
391
|
const finalValues = {
|
|
534
392
|
...resetValues,
|
|
535
|
-
|
|
393
|
+
search_values: searchValues,
|
|
536
394
|
};
|
|
537
395
|
|
|
538
396
|
runSubmit(finalValues);
|
|
@@ -540,8 +398,6 @@ export default function ReportingDashboard({
|
|
|
540
398
|
});
|
|
541
399
|
} else {
|
|
542
400
|
// no form change
|
|
543
|
-
const searchCondition = buildSearchCondition(searchValues, searchParameters);
|
|
544
|
-
|
|
545
401
|
const resetValues = {};
|
|
546
402
|
Object.keys(values).forEach((key) => {
|
|
547
403
|
resetValues[key] = null;
|
|
@@ -549,7 +405,7 @@ export default function ReportingDashboard({
|
|
|
549
405
|
|
|
550
406
|
const finalValues = {
|
|
551
407
|
...resetValues,
|
|
552
|
-
|
|
408
|
+
search_values: searchValues,
|
|
553
409
|
};
|
|
554
410
|
|
|
555
411
|
runSubmit(finalValues);
|
|
@@ -562,7 +418,7 @@ export default function ReportingDashboard({
|
|
|
562
418
|
|
|
563
419
|
scriptId.current = null;
|
|
564
420
|
|
|
565
|
-
const hasSearchValues = finalValues.
|
|
421
|
+
const hasSearchValues = finalValues.search_values && Object.values(finalValues.search_values).some((v) => Array.isArray(v) && v.length > 0);
|
|
566
422
|
|
|
567
423
|
if (!hasSearchValues) {
|
|
568
424
|
const currentUrlParams = Location.search();
|
|
@@ -746,6 +602,7 @@ export default function ReportingDashboard({
|
|
|
746
602
|
key={param.field}
|
|
747
603
|
parameter={param}
|
|
748
604
|
field={param}
|
|
605
|
+
reportId={reportId}
|
|
749
606
|
value={searchValues[param.field] || []}
|
|
750
607
|
onChange={(value) => {
|
|
751
608
|
setSearchValues((prev) => ({
|
|
@@ -753,6 +610,32 @@ export default function ReportingDashboard({
|
|
|
753
610
|
[param.field]: value,
|
|
754
611
|
}));
|
|
755
612
|
}}
|
|
613
|
+
onReset={() => {
|
|
614
|
+
setSearchValues((prev) => {
|
|
615
|
+
const updated = {
|
|
616
|
+
...prev,
|
|
617
|
+
[param.field]: [],
|
|
618
|
+
};
|
|
619
|
+
|
|
620
|
+
// const finalValues = {
|
|
621
|
+
// ...formContents,
|
|
622
|
+
// search_values: updated,
|
|
623
|
+
// };
|
|
624
|
+
// console.log(finalValues);
|
|
625
|
+
// runSubmit(finalValues); // 🔥 refresh report correctly
|
|
626
|
+
getPatientDetails();
|
|
627
|
+
|
|
628
|
+
return updated;
|
|
629
|
+
});
|
|
630
|
+
}}
|
|
631
|
+
// onReset={() => {
|
|
632
|
+
// setSearchValues((prev) => ({
|
|
633
|
+
// ...prev,
|
|
634
|
+
// [param.field]: [],
|
|
635
|
+
// }));
|
|
636
|
+
|
|
637
|
+
// handleSubmit(formContents); // 🔥 refresh report
|
|
638
|
+
// }}
|
|
756
639
|
/>
|
|
757
640
|
))
|
|
758
641
|
: null}
|
|
@@ -978,6 +861,40 @@ function GuestList({
|
|
|
978
861
|
const handleCloseEdit = () => {
|
|
979
862
|
setShowEdit(false);
|
|
980
863
|
};
|
|
864
|
+
/**
|
|
865
|
+
*
|
|
866
|
+
*/
|
|
867
|
+
function calculateSummaryValues(summaryCols, pageData) {
|
|
868
|
+
const summaryValues = {};
|
|
869
|
+
|
|
870
|
+
summaryCols.forEach((col) => {
|
|
871
|
+
const field = col.field;
|
|
872
|
+
|
|
873
|
+
if (col.function === 'sum') {
|
|
874
|
+
summaryValues[field] = pageData.reduce((total, row) => total + Number(row[field] || 0), 0);
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
if (col.function === 'count') {
|
|
878
|
+
summaryValues[field] = pageData.length;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
if (col.function === 'avg') {
|
|
882
|
+
const total = pageData.reduce((sum, row) => sum + Number(row[field] || 0), 0);
|
|
883
|
+
summaryValues[field] = pageData.length ? total / pageData.length : 0;
|
|
884
|
+
}
|
|
885
|
+
if (col.function === 'min') {
|
|
886
|
+
const values = pageData.map((row) => Number(row[field] || 0));
|
|
887
|
+
summaryValues[field] = values.length ? Math.min(...values) : 0;
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
if (col.function === 'max') {
|
|
891
|
+
const values = pageData.map((row) => Number(row[field] || 0));
|
|
892
|
+
summaryValues[field] = values.length ? Math.max(...values) : 0;
|
|
893
|
+
}
|
|
894
|
+
});
|
|
895
|
+
|
|
896
|
+
return summaryValues;
|
|
897
|
+
}
|
|
981
898
|
return (
|
|
982
899
|
<>
|
|
983
900
|
<div className="table-header">
|
|
@@ -1053,46 +970,131 @@ function GuestList({
|
|
|
1053
970
|
sticky
|
|
1054
971
|
pagination={false}
|
|
1055
972
|
// title={config.caption}
|
|
973
|
+
// summary={(pageData) => {
|
|
974
|
+
// // Variable to save the summary data
|
|
975
|
+
// let summary = {};
|
|
976
|
+
|
|
977
|
+
// let summaryColumns = [
|
|
978
|
+
// { field: 'opb_amt', title: 'Amount' },
|
|
979
|
+
// { field: 'opb_netamt', title: 'Net Amount' },
|
|
980
|
+
// ];
|
|
981
|
+
|
|
982
|
+
// let tableColumns = cols;
|
|
983
|
+
|
|
984
|
+
// // Creating a copy of columns to append the summary configuration that is needed to set
|
|
985
|
+
// tableColumns.forEach((record, index) => {
|
|
986
|
+
// summaryColumns.forEach((inner) => {
|
|
987
|
+
// if (record.field === inner.field) {
|
|
988
|
+
// tableColumns[index].summary = inner;
|
|
989
|
+
// }
|
|
990
|
+
// });
|
|
991
|
+
// });
|
|
992
|
+
|
|
993
|
+
// // Initialize
|
|
994
|
+
// summaryColumns.map((item) => {
|
|
995
|
+
// return (summary[item.field] = 0);
|
|
996
|
+
// });
|
|
997
|
+
|
|
998
|
+
// // Find the total
|
|
999
|
+
// summaryColumns.map((item) => {
|
|
1000
|
+
// pageData.forEach((entry) => {
|
|
1001
|
+
// return (summary[item.field] = summary[item.field] + entry[item.field]);
|
|
1002
|
+
// });
|
|
1003
|
+
// });
|
|
1004
|
+
|
|
1005
|
+
// return (
|
|
1006
|
+
// <>
|
|
1007
|
+
// <Table.Summary.Row>
|
|
1008
|
+
// {tableColumns.map((column, key) => {
|
|
1009
|
+
// return <Table.Summary.Cell key={key}>{column.summary ? <>{summary[column.summary.field]}</> : null}</Table.Summary.Cell>;
|
|
1010
|
+
// })}
|
|
1011
|
+
// </Table.Summary.Row>
|
|
1012
|
+
// </>
|
|
1013
|
+
// );
|
|
1014
|
+
// }}
|
|
1015
|
+
// summary={(pageData) => {
|
|
1016
|
+
// const summaryCols = columns.filter((col) => col.enable_summary);
|
|
1017
|
+
// if (!summaryCols.length) return null;
|
|
1018
|
+
|
|
1019
|
+
// const summaryValues = {};
|
|
1020
|
+
|
|
1021
|
+
// summaryCols.forEach((col) => {
|
|
1022
|
+
// const field = col.field;
|
|
1023
|
+
|
|
1024
|
+
// if (col.function === 'sum') {
|
|
1025
|
+
// summaryValues[field] = pageData.reduce((total, row) => total + Number(row[field] || 0), 0);
|
|
1026
|
+
// }
|
|
1027
|
+
|
|
1028
|
+
// if (col.function === 'count') {
|
|
1029
|
+
// summaryValues[field] = pageData.length;
|
|
1030
|
+
// }
|
|
1031
|
+
|
|
1032
|
+
// if (col.function === 'avg') {
|
|
1033
|
+
// const total = pageData.reduce((sum, row) => sum + Number(row[field] || 0), 0);
|
|
1034
|
+
// summaryValues[field] = pageData.length ? total / pageData.length : 0;
|
|
1035
|
+
// }
|
|
1036
|
+
// });
|
|
1037
|
+
|
|
1038
|
+
// return (
|
|
1039
|
+
// <Table.Summary.Row className="report-summary-row">
|
|
1040
|
+
// {cols.map((col, index) => {
|
|
1041
|
+
// // show summary value
|
|
1042
|
+
// if (summaryValues[col.field] !== undefined) {
|
|
1043
|
+
// return (
|
|
1044
|
+
// <Table.Summary.Cell key={index}>
|
|
1045
|
+
// <strong>{summaryValues[col.field]}</strong>
|
|
1046
|
+
// </Table.Summary.Cell>
|
|
1047
|
+
// );
|
|
1048
|
+
// }
|
|
1049
|
+
|
|
1050
|
+
// // caption before summary column
|
|
1051
|
+
// const nextCol = cols[index + 1];
|
|
1052
|
+
// if (nextCol && summaryValues[nextCol.field] !== undefined) {
|
|
1053
|
+
// const configCol = columns.find((c) => c.field === nextCol.field);
|
|
1054
|
+
// return (
|
|
1055
|
+
// <Table.Summary.Cell key={index}>
|
|
1056
|
+
// <strong>{configCol?.summary_caption || 'Total'}</strong>
|
|
1057
|
+
// </Table.Summary.Cell>
|
|
1058
|
+
// );
|
|
1059
|
+
// }
|
|
1060
|
+
|
|
1061
|
+
// return <Table.Summary.Cell key={index} />;
|
|
1062
|
+
// })}
|
|
1063
|
+
// </Table.Summary.Row>
|
|
1064
|
+
// );
|
|
1065
|
+
// }}
|
|
1066
|
+
|
|
1056
1067
|
summary={(pageData) => {
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
{ field: 'opb_amt', title: 'Amount' },
|
|
1062
|
-
{ field: 'opb_netamt', title: 'Net Amount' },
|
|
1063
|
-
];
|
|
1064
|
-
|
|
1065
|
-
let tableColumns = cols;
|
|
1066
|
-
|
|
1067
|
-
// Creating a copy of columns to append the summary configuration that is needed to set
|
|
1068
|
-
tableColumns.forEach((record, index) => {
|
|
1069
|
-
summaryColumns.forEach((inner) => {
|
|
1070
|
-
if (record.field === inner.field) {
|
|
1071
|
-
tableColumns[index].summary = inner;
|
|
1072
|
-
}
|
|
1073
|
-
});
|
|
1074
|
-
});
|
|
1075
|
-
|
|
1076
|
-
// Initialize
|
|
1077
|
-
summaryColumns.map((item) => {
|
|
1078
|
-
return (summary[item.field] = 0);
|
|
1079
|
-
});
|
|
1080
|
-
|
|
1081
|
-
// Find the total
|
|
1082
|
-
summaryColumns.map((item) => {
|
|
1083
|
-
pageData.forEach((entry) => {
|
|
1084
|
-
return (summary[item.field] = summary[item.field] + entry[item.field]);
|
|
1085
|
-
});
|
|
1086
|
-
});
|
|
1068
|
+
const summaryCols = columns.filter((col) => col.enable_summary);
|
|
1069
|
+
if (!summaryCols.length) return null;
|
|
1070
|
+
|
|
1071
|
+
const summaryValues = calculateSummaryValues(summaryCols, pageData);
|
|
1087
1072
|
|
|
1088
1073
|
return (
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
return
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1074
|
+
<Table.Summary.Row>
|
|
1075
|
+
{cols.map((col, index) => {
|
|
1076
|
+
if (summaryValues[col.field] !== undefined) {
|
|
1077
|
+
return (
|
|
1078
|
+
<Table.Summary.Cell key={index}>
|
|
1079
|
+
<strong>{summaryValues[col.field]}</strong>
|
|
1080
|
+
</Table.Summary.Cell>
|
|
1081
|
+
);
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
const nextCol = cols[index + 1];
|
|
1085
|
+
if (nextCol && summaryValues[nextCol.field] !== undefined) {
|
|
1086
|
+
const configCol = columns.find((c) => c.field === nextCol.field);
|
|
1087
|
+
|
|
1088
|
+
return (
|
|
1089
|
+
<Table.Summary.Cell key={index}>
|
|
1090
|
+
<strong>{configCol?.summary_caption || 'Total'}</strong>
|
|
1091
|
+
</Table.Summary.Cell>
|
|
1092
|
+
);
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
return <Table.Summary.Cell key={index} />;
|
|
1096
|
+
})}
|
|
1097
|
+
</Table.Summary.Row>
|
|
1096
1098
|
);
|
|
1097
1099
|
}}
|
|
1098
1100
|
/>
|
|
@@ -13,6 +13,8 @@ export default function ActionButtons({
|
|
|
13
13
|
steps,
|
|
14
14
|
activeStep,
|
|
15
15
|
isStepCompleted,
|
|
16
|
+
isFullscreen,
|
|
17
|
+
onToggleFullscreen,
|
|
16
18
|
renderDynamicComponent,
|
|
17
19
|
handlePrevious,
|
|
18
20
|
handleNext,
|
|
@@ -37,6 +39,10 @@ export default function ActionButtons({
|
|
|
37
39
|
Back
|
|
38
40
|
</Button>
|
|
39
41
|
|
|
42
|
+
<Button type="default" onClick={onToggleFullscreen}>
|
|
43
|
+
{isFullscreen ? 'Exit Full Screen' : 'Switch to Full Screen'}
|
|
44
|
+
</Button>
|
|
45
|
+
|
|
40
46
|
{/* Skip button */}
|
|
41
47
|
{steps.length > 0 && steps[activeStep]?.allow_skip === 'Y' && (
|
|
42
48
|
<Button type="default" onClick={handleSkip} disabled={activeStep === steps.length - 1}>
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
overflow-y: auto;
|
|
12
12
|
overflow-x: hidden;
|
|
13
13
|
overscroll-behavior: contain;
|
|
14
|
+
|
|
14
15
|
padding-bottom: 8px;
|
|
15
16
|
}
|
|
16
17
|
|
|
@@ -27,7 +28,6 @@
|
|
|
27
28
|
border-top: 1px solid #f0f0f0;
|
|
28
29
|
box-shadow: 0 -2px 10px rgba(15, 23, 42, 0.04);
|
|
29
30
|
|
|
30
|
-
|
|
31
31
|
width: 61%;
|
|
32
32
|
padding: 10px;
|
|
33
33
|
position: fixed;
|
|
@@ -37,9 +37,15 @@
|
|
|
37
37
|
display: flex;
|
|
38
38
|
border-radius: 4px;
|
|
39
39
|
box-shadow: -1px -4px 10px 2px #f7f7f76e;
|
|
40
|
-
|
|
40
|
+
flex-wrap: wrap;
|
|
41
41
|
|
|
42
42
|
.ant-btn {
|
|
43
43
|
border-radius: 4px;
|
|
44
44
|
}
|
|
45
|
-
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.process-steps-page.is-fullscreen .action-buttons-container {
|
|
48
|
+
width: calc(100% - 24px);
|
|
49
|
+
left: 12px;
|
|
50
|
+
right: 12px;
|
|
51
|
+
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* - Handles process submission and optional chaining to the next process.
|
|
9
9
|
* - Provides a collapsible timeline view and action controls.
|
|
10
10
|
*/
|
|
11
|
-
import React, { useEffect, useState } from 'react';
|
|
11
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
12
12
|
import { Row, Col, Empty } from 'antd';
|
|
13
13
|
import { Card } from './../../lib';
|
|
14
14
|
import * as genericComponents from './../../lib';
|
|
@@ -36,8 +36,11 @@ export default function ProcessStepsPage({ match, CustomComponents = {}, ...prop
|
|
|
36
36
|
const [timelineCollapsed, setTimelineCollapsed] = useState(false);
|
|
37
37
|
const [showExternalWindow, setShowExternalWindow] = useState(false);
|
|
38
38
|
const [externalWin, setExternalWin] = useState(null);
|
|
39
|
+
const [isFullscreen, setIsFullscreen] = useState(false);
|
|
40
|
+
const processStepsRef = useRef(null);
|
|
39
41
|
|
|
40
42
|
const urlParams = Location.search();
|
|
43
|
+
const isConsultationMode = String(urlParams?.consultation).toLowerCase() === 'true';
|
|
41
44
|
let processId = urlParams.processId;
|
|
42
45
|
const [currentProcessId, setCurrentProcessId] = useState(processId);
|
|
43
46
|
// Load process details based on the current process ID
|
|
@@ -271,13 +274,49 @@ export default function ProcessStepsPage({ match, CustomComponents = {}, ...prop
|
|
|
271
274
|
};
|
|
272
275
|
}, [activeStep, steps, externalWin]);
|
|
273
276
|
|
|
277
|
+
useEffect(() => {
|
|
278
|
+
const syncFullscreenState = () => {
|
|
279
|
+
setIsFullscreen(document.fullscreenElement === processStepsRef.current);
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
document.addEventListener('fullscreenchange', syncFullscreenState);
|
|
283
|
+
syncFullscreenState();
|
|
284
|
+
|
|
285
|
+
return () => {
|
|
286
|
+
document.removeEventListener('fullscreenchange', syncFullscreenState);
|
|
287
|
+
};
|
|
288
|
+
}, []);
|
|
289
|
+
|
|
290
|
+
const handleToggleFullscreen = async () => {
|
|
291
|
+
const element = processStepsRef.current;
|
|
292
|
+
if (!element) return;
|
|
293
|
+
|
|
294
|
+
try {
|
|
295
|
+
if (document.fullscreenElement === element) {
|
|
296
|
+
if (document.exitFullscreen) {
|
|
297
|
+
await document.exitFullscreen();
|
|
298
|
+
}
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (element.requestFullscreen) {
|
|
303
|
+
await element.requestFullscreen();
|
|
304
|
+
}
|
|
305
|
+
} catch (error) {
|
|
306
|
+
console.error('Unable to toggle full screen for steps page:', error);
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
|
|
274
310
|
/**
|
|
275
311
|
* Renders the main process UI including timeline, step details,
|
|
276
312
|
* and action buttons. This content is reused in both normal view
|
|
277
313
|
* and external window view.
|
|
278
314
|
*/
|
|
279
|
-
const renderContent = () => (
|
|
280
|
-
<div
|
|
315
|
+
const renderContent = (attachRef = true) => (
|
|
316
|
+
<div
|
|
317
|
+
ref={attachRef ? processStepsRef : null}
|
|
318
|
+
className={`process-steps-page ${isConsultationMode ? 'consultation-mode' : ''} ${isFullscreen ? 'is-fullscreen' : ''}`}
|
|
319
|
+
>
|
|
281
320
|
<Card className="process-steps-card">
|
|
282
321
|
<Row gutter={20} className="process-steps-row" align="stretch">
|
|
283
322
|
<Col xs={24} sm={24} lg={timelineCollapsed ? 2 : 6} className="process-steps-timeline-col">
|
|
@@ -302,6 +341,8 @@ export default function ProcessStepsPage({ match, CustomComponents = {}, ...prop
|
|
|
302
341
|
steps={steps}
|
|
303
342
|
activeStep={activeStep}
|
|
304
343
|
isStepCompleted={isStepCompleted}
|
|
344
|
+
isFullscreen={isFullscreen}
|
|
345
|
+
onToggleFullscreen={handleToggleFullscreen}
|
|
305
346
|
renderDynamicComponent={DynamicComponent}
|
|
306
347
|
handlePrevious={handlePrevious}
|
|
307
348
|
handleNext={handleNext}
|
|
@@ -335,9 +376,9 @@ export default function ProcessStepsPage({ match, CustomComponents = {}, ...prop
|
|
|
335
376
|
width={props.ExternalWindowWidth || 1000}
|
|
336
377
|
height={props.ExternalWindowHeight || 1000}
|
|
337
378
|
>
|
|
338
|
-
{renderContent()}
|
|
379
|
+
{renderContent(false)}
|
|
339
380
|
</ExternalWindow>
|
|
340
|
-
{renderContent()}
|
|
381
|
+
{renderContent(true)}
|
|
341
382
|
</>
|
|
342
383
|
);
|
|
343
384
|
}
|