ui-soxo-bootstrap-core 2.4.26 → 2.5.1
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/external-window/DEVELOPER_GUIDE.md +705 -0
- package/core/components/external-window/external-window.js +236 -0
- package/core/components/external-window/external-window.test.js +80 -0
- package/core/components/index.js +4 -1
- package/core/components/landing-api/landing-api.js +18 -18
- package/core/lib/Store.js +20 -18
- package/core/lib/components/index.js +4 -1
- package/core/lib/elements/basic/rangepicker/rangepicker.js +118 -29
- package/core/lib/elements/basic/switch/switch.js +34 -24
- package/core/models/dashboard/dashboard.js +14 -0
- package/core/modules/index.js +2 -4
- package/core/modules/reporting/components/reporting-dashboard/reporting-dashboard.js +53 -13
- package/core/modules/steps/action-buttons.js +76 -0
- package/core/modules/steps/action-buttons.scss +16 -0
- package/core/modules/steps/steps.js +346 -0
- package/core/modules/steps/steps.scss +159 -0
- package/core/modules/steps/timeline.js +54 -0
- package/jest.config.js +8 -0
- package/jest.setup.js +1 -0
- package/package.json +9 -4
|
@@ -1,36 +1,46 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Component for antd switch
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
import React, { useState, useContext, useEffect } from 'react';
|
|
6
|
-
import { GlobalContext } from '../../../Store';
|
|
7
|
-
|
|
4
|
+
import React, { useContext } from 'react';
|
|
8
5
|
import { Switch as AntdSwitch } from 'antd';
|
|
9
|
-
|
|
6
|
+
import { GlobalContext } from '../../../Store';
|
|
10
7
|
import PropTypes from 'prop-types';
|
|
11
8
|
|
|
12
|
-
export default function Switch({
|
|
9
|
+
export default function Switch({
|
|
10
|
+
checked,
|
|
11
|
+
defaultChecked,
|
|
12
|
+
onChange,
|
|
13
|
+
disabled,
|
|
14
|
+
id,
|
|
15
|
+
size,
|
|
16
|
+
checkedChildren,
|
|
17
|
+
unCheckedChildren,
|
|
18
|
+
className,
|
|
19
|
+
style,
|
|
20
|
+
}) {
|
|
13
21
|
const { state } = useContext(GlobalContext);
|
|
14
22
|
|
|
15
|
-
useEffect(() => {
|
|
16
|
-
// Reacting to theme changes
|
|
17
|
-
}, [state.theme.colors]);
|
|
18
|
-
|
|
19
23
|
return (
|
|
20
|
-
<
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
24
|
+
<AntdSwitch
|
|
25
|
+
id={id}
|
|
26
|
+
checked={checked}
|
|
27
|
+
defaultChecked={defaultChecked}
|
|
28
|
+
onChange={onChange}
|
|
29
|
+
disabled={disabled}
|
|
30
|
+
size={size}
|
|
31
|
+
checkedChildren={checkedChildren}
|
|
32
|
+
unCheckedChildren={unCheckedChildren}
|
|
33
|
+
className={className}
|
|
34
|
+
style={{
|
|
35
|
+
backgroundColor: checked
|
|
36
|
+
? state.theme.colors.primaryButtonBg
|
|
37
|
+
: state.theme.colors.primaryButtonDisabledBg,
|
|
38
|
+
borderColor: checked
|
|
39
|
+
? state.theme.colors.primaryButtonBg
|
|
40
|
+
: state.theme.colors.primaryButtonDisabledBg,
|
|
41
|
+
...style,
|
|
42
|
+
}}
|
|
43
|
+
/>
|
|
34
44
|
);
|
|
35
45
|
}
|
|
36
46
|
|
|
@@ -81,6 +81,20 @@ class Dashboard extends Base {
|
|
|
81
81
|
];
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
loadProcess(id) {
|
|
85
|
+
return ApiUtils.get({
|
|
86
|
+
url: `process/${id}`,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
processLog(formBody) {
|
|
91
|
+
return ApiUtils.post({
|
|
92
|
+
url: `process/process-log`,
|
|
93
|
+
formBody,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
84
98
|
/**
|
|
85
99
|
* Function to load dashboards based on user information
|
|
86
100
|
* @param {*} user
|
package/core/modules/index.js
CHANGED
|
@@ -16,14 +16,14 @@ import PopQueryDashboard from './dashboard/components/pop-query-dashboard/pop-qu
|
|
|
16
16
|
|
|
17
17
|
import HomePageAPI from './../pages/homepage-api/homepage-api';
|
|
18
18
|
|
|
19
|
-
import { Profile, ChangePassword } from './../lib';
|
|
20
|
-
|
|
21
19
|
import ReportingDashboard from '../modules/reporting/components/reporting-dashboard/reporting-dashboard';
|
|
22
20
|
|
|
23
21
|
import ChangeInfo from './Informations/change-info/change-info';
|
|
24
22
|
// All Dashboard Components Ends
|
|
23
|
+
import ProcessStepsPage from './steps/steps';
|
|
25
24
|
|
|
26
25
|
export {
|
|
26
|
+
ProcessStepsPage,
|
|
27
27
|
GenericList,
|
|
28
28
|
GenericAdd,
|
|
29
29
|
GenericEdit,
|
|
@@ -32,9 +32,7 @@ export {
|
|
|
32
32
|
DashboardCard,
|
|
33
33
|
PopQueryDashboard,
|
|
34
34
|
HomePageAPI,
|
|
35
|
-
Profile,
|
|
36
35
|
ReportingDashboard,
|
|
37
|
-
ChangePassword,
|
|
38
36
|
ChangeInfo,
|
|
39
37
|
};
|
|
40
38
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useState, useEffect, useContext, useRef } from 'react';
|
|
2
2
|
|
|
3
|
-
import { Table, Skeleton, Input, Tag, Modal, message, Pagination } from 'antd';
|
|
3
|
+
import { Table, Skeleton, Input, Tag, Modal, message, Pagination, Tooltip } from 'antd';
|
|
4
4
|
|
|
5
5
|
import { QrcodeOutlined } from '@ant-design/icons';
|
|
6
6
|
|
|
@@ -106,8 +106,17 @@ export default function ReportingDashboard({
|
|
|
106
106
|
setPatients([]);
|
|
107
107
|
const fetchId = idOverride || id;
|
|
108
108
|
await CoreScripts.getRecord({ id: fetchId, dbPtr }).then(async ({ result }) => {
|
|
109
|
+
// Check if display columns are provided from backend
|
|
110
|
+
if (result.display_columns) {
|
|
111
|
+
// Parse and set columns from stored JSON
|
|
112
|
+
|
|
113
|
+
setColumns(JSON.parse(result.display_columns));
|
|
114
|
+
} else {
|
|
115
|
+
// Reset columns if no display columns exist
|
|
116
|
+
|
|
117
|
+
setColumns([]);
|
|
118
|
+
}
|
|
109
119
|
await prepareInputParameters(result);
|
|
110
|
-
setColumns(JSON.parse(result.display_columns));
|
|
111
120
|
|
|
112
121
|
if (result.summary_columns) {
|
|
113
122
|
setSummaryColumns(JSON.parse(result.summary_columns));
|
|
@@ -160,11 +169,12 @@ export default function ReportingDashboard({
|
|
|
160
169
|
if (urlParams.script_id) scriptId.current = urlParams.script_id;
|
|
161
170
|
|
|
162
171
|
let otherDetails = record.other_details1 ? JSON.parse(record.other_details1) : null;
|
|
163
|
-
|
|
172
|
+
|
|
173
|
+
parameters = record.input_parameters ? JSON.parse(record.input_parameters) : null;
|
|
164
174
|
|
|
165
175
|
let formContent = {};
|
|
166
176
|
|
|
167
|
-
parameters = await parameters
|
|
177
|
+
parameters = await parameters?.map((record) => {
|
|
168
178
|
// Only if the url params does have a matching value ,
|
|
169
179
|
// we should not consider the default value
|
|
170
180
|
|
|
@@ -289,6 +299,17 @@ export default function ReportingDashboard({
|
|
|
289
299
|
}
|
|
290
300
|
// Update patients
|
|
291
301
|
setPatients(resultDetails || []);
|
|
302
|
+
// Check if columns are not yet defined
|
|
303
|
+
if (columns.length === 0 && resultDetails.length > 0) {
|
|
304
|
+
// Create columns dynamically from resultDetails keys
|
|
305
|
+
setColumns((prev) => {
|
|
306
|
+
if (prev.length > 0) return prev;
|
|
307
|
+
return Object.keys(resultDetails[0]).map((key) => ({
|
|
308
|
+
title: key,
|
|
309
|
+
field: key,
|
|
310
|
+
}));
|
|
311
|
+
});
|
|
312
|
+
}
|
|
292
313
|
|
|
293
314
|
if (result.length) {
|
|
294
315
|
// Set Pgination data into URL
|
|
@@ -565,7 +586,6 @@ function GuestList({
|
|
|
565
586
|
attributes,
|
|
566
587
|
fetchReportData,
|
|
567
588
|
}) {
|
|
568
|
-
console.log(attributes, '_____________________________________');
|
|
569
589
|
/**
|
|
570
590
|
* @param {*} propValues
|
|
571
591
|
*/
|
|
@@ -683,7 +703,7 @@ function GuestList({
|
|
|
683
703
|
redirectLink = redirectLink.replace(new RegExp('@' + replacement.field + ';', 'g'), record[replacement.field]);
|
|
684
704
|
});
|
|
685
705
|
|
|
686
|
-
return <Link to={`${redirectLink}`}>View</Link>;
|
|
706
|
+
return <Link to={`${redirectLink}`}>{entry.display_name_link ? entry.display_name_link : 'View'}</Link>;
|
|
687
707
|
} else if (entry.field === 'custom') {
|
|
688
708
|
// Make all the components in modules available for use in custom column of core script
|
|
689
709
|
// var genericComponents = require('./../../../../../../../nura-api-new/nura-desk/src/modules');
|
|
@@ -737,7 +757,7 @@ function GuestList({
|
|
|
737
757
|
|
|
738
758
|
// If the column type is 'span', render the field inside a <span> with inline color style
|
|
739
759
|
} else if (entry.columnType === 'span') {
|
|
740
|
-
return <span style={{ color: record.color_code }}>{record[entry.field]}</span>;
|
|
760
|
+
return <span style={{ color: record.color_code, overflowWrap: 'break-word', WebkitLineClamp: 3 }}>{record[entry.field]}</span>;
|
|
741
761
|
}
|
|
742
762
|
} else {
|
|
743
763
|
/**
|
|
@@ -769,14 +789,25 @@ function GuestList({
|
|
|
769
789
|
}
|
|
770
790
|
} else {
|
|
771
791
|
//If the value is neither 'Y' nor 'N', return the actual field value
|
|
772
|
-
return <span style={{ color: textColor }}>{record[entry.field]}</span>;
|
|
792
|
+
return <span style={{ color: textColor, whiteSpace: 'pre-wrap', overflowWrap: 'break-word' }}>{record[entry.field]}</span>;
|
|
773
793
|
}
|
|
774
794
|
}
|
|
775
795
|
}
|
|
776
796
|
},
|
|
777
797
|
field: entry.field,
|
|
778
|
-
title: entry.title,
|
|
798
|
+
// title: entry.title,
|
|
799
|
+
// title: (
|
|
800
|
+
// <Tooltip title={entry.title}>
|
|
801
|
+
// {entry.title}
|
|
802
|
+
// </Tooltip>
|
|
803
|
+
// ),
|
|
804
|
+
title: (
|
|
805
|
+
<Tooltip title={entry.tooltip || entry.title}>
|
|
806
|
+
<span>{entry.title}</span>
|
|
807
|
+
</Tooltip>
|
|
808
|
+
),
|
|
779
809
|
key: entry.field,
|
|
810
|
+
width: entry.width ? parseInt(entry.width) : 160,
|
|
780
811
|
fixed: entry.isFixedColumn ? entry.isFixedColumn : null, // Conditionally setting the 'fixed' key to 'left' if 'isColumnStatic' is true; otherwise, setting it to null.
|
|
781
812
|
// Check if filtering is enabled and patients is an array
|
|
782
813
|
filters:
|
|
@@ -800,7 +831,6 @@ function GuestList({
|
|
|
800
831
|
// Return the value from record.props if it exists
|
|
801
832
|
return description && record[description] ? record[description] : null;
|
|
802
833
|
}
|
|
803
|
-
|
|
804
834
|
return record[entry.field];
|
|
805
835
|
},
|
|
806
836
|
// Add align property based on column type
|
|
@@ -884,13 +914,21 @@ function GuestList({
|
|
|
884
914
|
// setData(data);
|
|
885
915
|
|
|
886
916
|
// Define export data
|
|
887
|
-
|
|
917
|
+
// Sanitize cols for export to ensure titles are strings
|
|
918
|
+
const exportCols = cols.map((col) => {
|
|
919
|
+
if (col.title && typeof col.title === 'object' && col.title.props) {
|
|
920
|
+
return { ...col, title: col.title.props.title };
|
|
921
|
+
}
|
|
922
|
+
return col;
|
|
923
|
+
});
|
|
924
|
+
|
|
925
|
+
let exportDatas = getExportData(patients, exportCols);
|
|
888
926
|
|
|
889
927
|
if (exportDatas.exportDataColumns.length && exportDatas.exportDataHeaders.length) {
|
|
890
928
|
setExportData({ exportDatas });
|
|
891
929
|
}
|
|
892
930
|
}
|
|
893
|
-
}, [patients]);
|
|
931
|
+
}, [patients, columns]);
|
|
894
932
|
|
|
895
933
|
let filtered;
|
|
896
934
|
|
|
@@ -1042,7 +1080,7 @@ function GuestList({
|
|
|
1042
1080
|
) : (
|
|
1043
1081
|
<TableComponent
|
|
1044
1082
|
size="small"
|
|
1045
|
-
scroll={{ x:
|
|
1083
|
+
scroll={{ x: 'max-content' }}
|
|
1046
1084
|
rowKey={(record) => record.OpNo}
|
|
1047
1085
|
dataSource={filtered ? filtered : patients} // In case if there is no filtered values we can use patient data
|
|
1048
1086
|
columns={cols}
|
|
@@ -1162,3 +1200,5 @@ function GuestList({
|
|
|
1162
1200
|
// </Card>
|
|
1163
1201
|
// );
|
|
1164
1202
|
// }
|
|
1203
|
+
// );
|
|
1204
|
+
// }
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ActionButtons
|
|
3
|
+
* Handles navigation and action controls for a multi-step process,
|
|
4
|
+
* including dynamic content rendering and process completion actions.
|
|
5
|
+
*/
|
|
6
|
+
import React, { useState } from 'react';
|
|
7
|
+
import { Skeleton } from 'antd';
|
|
8
|
+
import { Button } from '../../lib';
|
|
9
|
+
import './action-buttons.scss';
|
|
10
|
+
|
|
11
|
+
export default function ActionButtons({
|
|
12
|
+
loading,
|
|
13
|
+
steps,
|
|
14
|
+
activeStep,
|
|
15
|
+
isStepCompleted,
|
|
16
|
+
renderDynamicComponent,
|
|
17
|
+
handlePrevious,
|
|
18
|
+
handleNext,
|
|
19
|
+
handleSkip,
|
|
20
|
+
handleFinish,
|
|
21
|
+
handleStartNextProcess,
|
|
22
|
+
nextProcessId,
|
|
23
|
+
timelineCollapsed,
|
|
24
|
+
}) {
|
|
25
|
+
const [showNextProcess, setShowNextProcess] = useState(false);
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<>
|
|
29
|
+
<div style={{ minHeight: 300 }}>{loading ? <Skeleton active /> : renderDynamicComponent()}</div>
|
|
30
|
+
<>
|
|
31
|
+
<div className="action-buttons-container">
|
|
32
|
+
{/* Back button */}
|
|
33
|
+
<Button disabled={activeStep === 0} onClick={handlePrevious}>
|
|
34
|
+
Back
|
|
35
|
+
</Button>
|
|
36
|
+
|
|
37
|
+
{/* Skip button */}
|
|
38
|
+
{steps.length > 0 && steps[activeStep]?.allow_skip === 'Y' && (
|
|
39
|
+
<Button type="default" onClick={handleSkip} disabled={activeStep === steps.length - 1}>
|
|
40
|
+
Skip
|
|
41
|
+
</Button>
|
|
42
|
+
)}
|
|
43
|
+
|
|
44
|
+
{/* Next / Finish / Start Next */}
|
|
45
|
+
{steps[activeStep]?.order_seqtype === 'E' ? (
|
|
46
|
+
<>
|
|
47
|
+
{!showNextProcess && (
|
|
48
|
+
<Button
|
|
49
|
+
type="primary"
|
|
50
|
+
onClick={async () => {
|
|
51
|
+
const success = await handleFinish();
|
|
52
|
+
if (success && nextProcessId?.next_process_id) {
|
|
53
|
+
setShowNextProcess(true);
|
|
54
|
+
}
|
|
55
|
+
}}
|
|
56
|
+
>
|
|
57
|
+
Finish
|
|
58
|
+
</Button>
|
|
59
|
+
)}
|
|
60
|
+
|
|
61
|
+
{showNextProcess && nextProcessId?.next_process_id && (
|
|
62
|
+
<Button type="primary" onClick={handleStartNextProcess}>
|
|
63
|
+
Start {nextProcessId.next_process_name}
|
|
64
|
+
</Button>
|
|
65
|
+
)}
|
|
66
|
+
</>
|
|
67
|
+
) : (
|
|
68
|
+
<Button type="primary" disabled={activeStep === steps.length - 1 || !isStepCompleted} onClick={handleNext}>
|
|
69
|
+
Next →
|
|
70
|
+
</Button>
|
|
71
|
+
)}
|
|
72
|
+
</div>
|
|
73
|
+
</>
|
|
74
|
+
</>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
.action-buttons-container {
|
|
2
|
+
margin-top: 38px;
|
|
3
|
+
display: flex;
|
|
4
|
+
justify-content: flex-start;
|
|
5
|
+
gap: 10px;
|
|
6
|
+
position: sticky;
|
|
7
|
+
bottom: 0;
|
|
8
|
+
z-index: 1000;
|
|
9
|
+
background: #fff;
|
|
10
|
+
padding: 10px 0;
|
|
11
|
+
border-top: 1px solid #f0f0f0;
|
|
12
|
+
|
|
13
|
+
.ant-btn {
|
|
14
|
+
border-radius: 4px;
|
|
15
|
+
}
|
|
16
|
+
}
|