ui-soxo-bootstrap-core 2.4.24 → 2.4.25-dev.6
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/.github/workflows/npm-publish.yml +37 -15
- package/README.md +260 -0
- package/core/components/extra-info/extra-info-details.js +109 -126
- package/core/components/landing-api/landing-api.js +22 -30
- package/core/lib/Store.js +20 -18
- package/core/lib/components/index.js +4 -1
- package/core/lib/components/sidemenu/sidemenu.js +153 -256
- package/core/lib/components/sidemenu/sidemenu.scss +39 -26
- package/core/lib/hooks/index.js +2 -12
- package/core/lib/hooks/use-otp-timer.js +99 -0
- package/core/lib/pages/login/login.js +255 -139
- package/core/lib/pages/login/login.scss +140 -32
- package/core/models/dashboard/dashboard.js +14 -0
- package/core/models/doctor/components/doctor-add/doctor-add.js +403 -0
- package/core/models/doctor/components/doctor-add/doctor-add.scss +32 -0
- package/core/models/menus/components/menu-add/menu-add.js +230 -268
- package/core/models/menus/components/menu-lists/menu-lists.js +126 -89
- package/core/models/menus/components/menu-lists/menu-lists.scss +9 -0
- package/core/models/menus/menus.js +247 -267
- package/core/models/roles/components/role-add/role-add.js +269 -227
- package/core/models/roles/components/role-list/role-list.js +8 -6
- package/core/models/roles/roles.js +182 -174
- package/core/models/users/components/user-add/user-add.js +619 -365
- package/core/models/users/components/user-add/user-edit.js +90 -0
- package/core/models/users/users.js +261 -165
- package/core/modules/index.js +5 -8
- package/core/modules/reporting/components/index.js +5 -0
- package/core/modules/reporting/components/reporting-dashboard/reporting-dashboard.js +65 -2
- package/core/modules/steps/action-buttons.js +79 -0
- package/core/modules/steps/steps.js +553 -0
- package/core/modules/steps/steps.scss +158 -0
- package/core/modules/steps/timeline.js +49 -0
- package/package.json +2 -2
|
@@ -2,8 +2,7 @@ import React, { useState, useEffect, useContext } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { useLocation } from 'react-router-dom';
|
|
4
4
|
|
|
5
|
-
import { Skeleton, Typography, message, Switch, Form, Input, Select, Checkbox } from 'antd';
|
|
6
|
-
|
|
5
|
+
import { Skeleton, Typography, message, Switch, Form, Input, Select, Checkbox, Row, Col } from 'antd';
|
|
7
6
|
|
|
8
7
|
import AsyncSelect from 'react-select/async';
|
|
9
8
|
|
|
@@ -12,350 +11,593 @@ import { Table, Card, Button, JSONInput, GlobalContext } from './../../../../lib
|
|
|
12
11
|
import { ModelsAPI, PagesAPI } from '../../..';
|
|
13
12
|
|
|
14
13
|
import { UsersAPI } from '../../..';
|
|
14
|
+
import DoctorAdd from '../../../doctor/components/doctor-add/doctor-add';
|
|
15
15
|
|
|
16
16
|
const { Title } = Typography;
|
|
17
17
|
|
|
18
18
|
const { Option } = Select;
|
|
19
19
|
|
|
20
|
-
const UserAdd = ({ model, callback, edit, history, formContent, match, additional_queries, props }) => {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
} else {
|
|
67
|
-
|
|
68
|
-
formContent.attributes = {};
|
|
69
|
-
|
|
70
|
-
}
|
|
20
|
+
const UserAdd = ({ model, callback, edit, history, formContent, match, additional_queries, props, mode = 'Add', attributes }) => {
|
|
21
|
+
/**Getting user data */
|
|
22
|
+
const { user = {} } = useContext(GlobalContext);
|
|
23
|
+
// let mode = 'Add';
|
|
24
|
+
|
|
25
|
+
const [disabled, setDisabled] = useState(true);
|
|
26
|
+
|
|
27
|
+
const [selectedOption, setSelectedOption] = useState(null);
|
|
28
|
+
// for selected branches
|
|
29
|
+
const [selectedBranches, setSelectedBranches] = useState([]);
|
|
30
|
+
|
|
31
|
+
// for default branch
|
|
32
|
+
const [defaultBranch, setDefaultBranch] = useState(null);
|
|
33
|
+
//Need to check this condition
|
|
34
|
+
const [authentication, setAuthentication] = useState(false);
|
|
35
|
+
|
|
36
|
+
/**To store user values */
|
|
37
|
+
const [users, setUsers] = useState([]);
|
|
38
|
+
const [doctorID, setDoctorID] = useState(false);
|
|
39
|
+
const [selectedDoctor, setSelectedDoctor] = useState(null);
|
|
40
|
+
/**Converting to JSON */
|
|
41
|
+
let firmDetails = JSON.parse(user.firm.f_otherdetails1);
|
|
42
|
+
|
|
43
|
+
/**Variable for cheaking mandatory condition of mobile*/
|
|
44
|
+
let mobileRequired;
|
|
45
|
+
|
|
46
|
+
/**If mode is mobile and fa is 'MND' or 'USR' then mobile is mandatory */
|
|
47
|
+
if (((firmDetails && firmDetails.FA === 'MND') || (firmDetails && firmDetails.FA === 'USR')) && firmDetails.mode === 'mobile') {
|
|
48
|
+
mobileRequired = true;
|
|
49
|
+
} else {
|
|
50
|
+
mobileRequired = false;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (formContent?.id) {
|
|
54
|
+
mode = 'Edit';
|
|
55
|
+
} else if (formContent?.copy) {
|
|
56
|
+
mode = 'Copy';
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (formContent?.attributes) {
|
|
60
|
+
if (typeof formContent.attributes === 'string') {
|
|
61
|
+
if (formContent.attributes !== '') {
|
|
62
|
+
formContent.attributes = JSON.parse(formContent.attributes);
|
|
63
|
+
} else {
|
|
64
|
+
if (formContent) {
|
|
65
|
+
formContent.attributes = {};
|
|
71
66
|
}
|
|
72
|
-
|
|
73
|
-
formContent.attributes = {}
|
|
67
|
+
}
|
|
74
68
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const [form] = Form.useForm();
|
|
79
|
-
|
|
80
|
-
const [body, setBody] = useState(formContent);
|
|
81
|
-
|
|
82
|
-
const [isPasswordVisible, setIsPasswordVisible] = useState(false);
|
|
83
|
-
|
|
84
|
-
const formData = {
|
|
85
|
-
...body,
|
|
86
|
-
/**If panel is open then takes password in body */
|
|
87
|
-
password: !isPasswordVisible ? "" : body.password
|
|
69
|
+
} else {
|
|
70
|
+
if (formContent) {
|
|
71
|
+
formContent.attributes = {};
|
|
88
72
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const [loading, setLoading] = useState(true);
|
|
76
|
+
// user type state
|
|
77
|
+
const [userType, setUserType] = useState('general');
|
|
78
|
+
// state for branches list
|
|
79
|
+
const [branches, setBranches] = useState([]);
|
|
80
|
+
// designation list state
|
|
81
|
+
const [designations, setDesignations] = useState([]);
|
|
82
|
+
// department list state
|
|
83
|
+
const [departments, setDepartments] = useState([]);
|
|
84
|
+
// doctor list state
|
|
85
|
+
const [doctorList, setDoctorList] = useState([]);
|
|
86
|
+
|
|
87
|
+
const [form] = Form.useForm();
|
|
88
|
+
|
|
89
|
+
const [body, setBody] = useState(formContent);
|
|
90
|
+
|
|
91
|
+
const [isPasswordVisible, setIsPasswordVisible] = useState(false);
|
|
92
|
+
const [visible, setVisible] = useState(false);
|
|
93
|
+
|
|
94
|
+
const formData = {
|
|
95
|
+
...body,
|
|
96
|
+
/**If panel is open then takes password in body */
|
|
97
|
+
password: !isPasswordVisible ? '' : body.password,
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
let passwordRegex;
|
|
101
|
+
let passwordRegexMessage;
|
|
102
|
+
|
|
103
|
+
if (props && props?.passwordRegex && props?.passwordRegexMessage) {
|
|
104
|
+
passwordRegex = props.passwordRegex;
|
|
105
|
+
passwordRegexMessage = props.passwordRegexMessage;
|
|
106
|
+
} else if (process.env.REACT_APP_PASSWORD_REGEX && process.env.REACT_APP_PASSWORD_REGEX_MESSAGE) {
|
|
107
|
+
passwordRegex = process.env.REACT_APP_PASSWORD_REGEX;
|
|
108
|
+
passwordRegexMessage = process.env.REACT_APP_PASSWORD_REGEX_MESSAGE;
|
|
109
|
+
} else {
|
|
110
|
+
passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*(),.?":{}|<>])[A-Za-z\d!@#$%^&*(),.?":{}|<>]{8,}$/;
|
|
111
|
+
passwordRegexMessage =
|
|
112
|
+
'Password must be at least 8 characters long and contain atleast one uppercase letter, one lowercase letter, one digit and one special character';
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
useEffect(() => {
|
|
116
|
+
if (!loading && formContent) {
|
|
117
|
+
form.resetFields(); // clear previous values
|
|
118
|
+
form.setFieldsValue(formContent);
|
|
103
119
|
}
|
|
120
|
+
}, [loading, formContent]);
|
|
121
|
+
|
|
122
|
+
useEffect(() => {
|
|
123
|
+
if (formContent?.auth_user) {
|
|
124
|
+
setSelectedOption({
|
|
125
|
+
value: formContent.auth_user,
|
|
126
|
+
label: formContent.auth_user, // Add a helper function to capitalize
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}, [formContent?.auth_user]);
|
|
104
130
|
|
|
131
|
+
useEffect(() => {
|
|
132
|
+
loadUsers();
|
|
133
|
+
setLoading(false);
|
|
105
134
|
|
|
135
|
+
if (firmDetails) {
|
|
136
|
+
/**if firmmas.otherdetails - 2FA == MND, then, 2FA option will be enabled by default and read-only */
|
|
137
|
+
if (firmDetails.FA == 'MND') {
|
|
138
|
+
setAuthentication(true);
|
|
106
139
|
|
|
140
|
+
setDisabled(true);
|
|
107
141
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
value: formContent.auth_user,
|
|
112
|
-
label: formContent.auth_user, // Add a helper function to capitalize
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
}, [formContent.auth_user]);
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
useEffect(() => {
|
|
119
|
-
|
|
120
|
-
loadUsers()
|
|
121
|
-
setLoading(false);
|
|
122
|
-
|
|
123
|
-
if (firmDetails) {
|
|
124
|
-
|
|
125
|
-
/**if firmmas.otherdetails - 2FA == MND, then, 2FA option will be enabled by default and read-only */
|
|
126
|
-
if (firmDetails.FA == 'MND') {
|
|
127
|
-
|
|
128
|
-
setAuthentication(true)
|
|
129
|
-
|
|
130
|
-
setDisabled(true)
|
|
131
|
-
|
|
132
|
-
/**if firmmas.otherdetails - 2FA == OPT, then, 2FA option will be enabled by default and editable */
|
|
133
|
-
} else if (firmDetails.FA == 'USR') {
|
|
134
|
-
|
|
135
|
-
setAuthentication(true)
|
|
136
|
-
|
|
137
|
-
setDisabled(true)
|
|
138
|
-
|
|
139
|
-
/**if firmmas.otherdetails - 2FA == NAP, then, 2FA option will be disabled by default and read-only*/
|
|
140
|
-
} else if (firmDetails.FA == 'NAP') {
|
|
141
|
-
|
|
142
|
-
setAuthentication(false)
|
|
143
|
-
|
|
144
|
-
setDisabled(true)
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}, []);
|
|
142
|
+
/**if firmmas.otherdetails - 2FA == OPT, then, 2FA option will be enabled by default and editable */
|
|
143
|
+
} else if (firmDetails.FA == 'USR') {
|
|
144
|
+
setAuthentication(true);
|
|
151
145
|
|
|
152
|
-
|
|
153
|
-
* Submit values
|
|
154
|
-
*/
|
|
155
|
-
const onSubmit = (values) => {
|
|
146
|
+
setDisabled(true);
|
|
156
147
|
|
|
157
|
-
/**
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
148
|
+
/**if firmmas.otherdetails - 2FA == NAP, then, 2FA option will be disabled by default and read-only*/
|
|
149
|
+
} else if (firmDetails.FA == 'NAP') {
|
|
150
|
+
setAuthentication(false);
|
|
161
151
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
152
|
+
setDisabled(true);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}, []);
|
|
156
|
+
/**
|
|
157
|
+
*Define the options dynamically
|
|
158
|
+
*/
|
|
159
|
+
const getUserTypeOptions = () => [
|
|
160
|
+
{ label: 'General', value: 'GEN' },
|
|
161
|
+
{ label: 'Doctor', value: 'RAD' },
|
|
162
|
+
{ label: 'Radiographer', value: 'TECH' },
|
|
163
|
+
];
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Get Branch List
|
|
167
|
+
*/
|
|
168
|
+
const getBranches = () => {
|
|
169
|
+
setLoading(true);
|
|
170
|
+
UsersAPI.getBranches().then(async (result) => {
|
|
171
|
+
const details = await result.result.map((ele) => {
|
|
172
|
+
return {
|
|
173
|
+
...ele,
|
|
174
|
+
...(ele.br_otherdet1 ? JSON.parse(ele.br_otherdet1) : {}),
|
|
175
|
+
};
|
|
176
|
+
});
|
|
177
|
+
setBranches(details);
|
|
178
|
+
setLoading(false);
|
|
179
|
+
});
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
/** Get Designation List */
|
|
183
|
+
const getDesignations = () => {
|
|
184
|
+
setLoading(true);
|
|
185
|
+
UsersAPI.getDesignations()
|
|
186
|
+
.then((result) => {
|
|
187
|
+
if (result?.success && Array.isArray(result.result)) {
|
|
188
|
+
const details = result.result.map((ele) => ({
|
|
189
|
+
label: ele.dg_desc?.trim() || '',
|
|
190
|
+
value: ele.dg_code,
|
|
191
|
+
}));
|
|
192
|
+
setDesignations(details);
|
|
193
|
+
} else {
|
|
194
|
+
setDesignations([]);
|
|
166
195
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
196
|
+
})
|
|
197
|
+
.catch((error) => {
|
|
198
|
+
console.error('Error fetching designations:', error);
|
|
199
|
+
setDesignations([]);
|
|
200
|
+
})
|
|
201
|
+
.finally(() => setLoading(false));
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
/** Get Department List */
|
|
205
|
+
const getDepartments = () => {
|
|
206
|
+
setLoading(true);
|
|
207
|
+
UsersAPI.getDepartments()
|
|
208
|
+
.then((result) => {
|
|
209
|
+
if (result?.success && Array.isArray(result.result)) {
|
|
210
|
+
const details = result.result.map((ele) => ({
|
|
211
|
+
label: ele.dp_desc?.trim() || '',
|
|
212
|
+
value: ele.dp_id,
|
|
213
|
+
}));
|
|
214
|
+
setDepartments(details);
|
|
215
|
+
} else {
|
|
216
|
+
setDepartments([]);
|
|
179
217
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
218
|
+
})
|
|
219
|
+
.catch((error) => {
|
|
220
|
+
console.error('Error fetching departments:', error);
|
|
221
|
+
setDepartments([]);
|
|
222
|
+
})
|
|
223
|
+
.finally(() => setLoading(false));
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
/** Get Doctor List */
|
|
227
|
+
const getDoctors = () => {
|
|
228
|
+
UsersAPI.getDoctors()
|
|
229
|
+
.then((res) => {
|
|
230
|
+
if (res?.success && Array.isArray(res.result)) {
|
|
231
|
+
const list = res.result.map((doc) => ({
|
|
232
|
+
label: `${doc.do_name} (${doc.do_code})`,
|
|
233
|
+
value: doc.do_code,
|
|
234
|
+
}));
|
|
235
|
+
setDoctorList(list);
|
|
189
236
|
}
|
|
237
|
+
})
|
|
238
|
+
.catch((err) => console.error('Doctor API Error:', err));
|
|
239
|
+
};
|
|
190
240
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
UsersAPI.updateUser({ id, formBody: values }).then((result) => {
|
|
241
|
+
// Function to handle user type change
|
|
242
|
+
const handleUserTypeChange = (value) => {
|
|
243
|
+
setUserType(value);
|
|
195
244
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
245
|
+
if (value === 'RAD') {
|
|
246
|
+
getDoctors(); // load doctor list
|
|
247
|
+
} else {
|
|
248
|
+
form.setFieldsValue({ default_code: undefined });
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
useEffect(() => {
|
|
253
|
+
getBranches();
|
|
254
|
+
getDesignations();
|
|
255
|
+
getDepartments();
|
|
256
|
+
getDoctors(); // load doctor list
|
|
257
|
+
}, []);
|
|
258
|
+
|
|
259
|
+
useEffect(() => {
|
|
260
|
+
if (formContent && formContent.user_type) {
|
|
261
|
+
form.setFieldsValue({ user_type: formContent.user_type });
|
|
262
|
+
setUserType(formContent.user_type);
|
|
263
|
+
|
|
264
|
+
if (formContent.user_type === 'RAD' && formContent.doctor_code) {
|
|
265
|
+
form.setFieldsValue({ default_code: formContent.doctor_code });
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
if (formContent?.id && formContent?.organization_details) {
|
|
269
|
+
try {
|
|
270
|
+
const org = JSON.parse(formContent.organization_details);
|
|
271
|
+
const branchIds = org.branch_ids?.map((b) => b.id) || [];
|
|
272
|
+
const defaultBranchObj = org.branch_ids?.find((b) => b.DefaultBranch === 'true');
|
|
273
|
+
const defaultBr = defaultBranchObj?.id || null;
|
|
274
|
+
|
|
275
|
+
setSelectedBranches(branchIds);
|
|
276
|
+
setDefaultBranch(defaultBr);
|
|
277
|
+
|
|
278
|
+
form.setFieldsValue({
|
|
279
|
+
selectedBranches: branchIds,
|
|
280
|
+
defaultBranch: defaultBr,
|
|
281
|
+
});
|
|
282
|
+
} catch (err) {
|
|
283
|
+
console.error('Invalid organization_details JSON', err);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}, [formContent]);
|
|
287
|
+
// Generate branch options for Select component
|
|
288
|
+
const branchOptions = branches.map((branch) => ({
|
|
289
|
+
label: branch.br_desc,
|
|
290
|
+
value: branch.br_code,
|
|
291
|
+
}));
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Submit values
|
|
240
295
|
*/
|
|
241
|
-
|
|
296
|
+
const onSubmit = (values) => {
|
|
297
|
+
console.log('values____________', values);
|
|
298
|
+
/**If PanelOpen is open and edit mode then password will be existing password else new password*/
|
|
299
|
+
if (!isPasswordVisible && mode === 'Edit') {
|
|
300
|
+
values.password = body.password;
|
|
301
|
+
}
|
|
302
|
+
values.user_type = values.user_type;
|
|
242
303
|
|
|
243
|
-
|
|
304
|
+
if (values.user_type === 'RAD') {
|
|
305
|
+
values.doctor_code = values.default_code;
|
|
306
|
+
} else {
|
|
307
|
+
values.doctor_code = null;
|
|
308
|
+
}
|
|
309
|
+
values = {
|
|
310
|
+
...values,
|
|
311
|
+
auth_type: 'LDAP',
|
|
312
|
+
FA: authentication,
|
|
244
313
|
};
|
|
245
314
|
|
|
315
|
+
setLoading(true);
|
|
316
|
+
|
|
317
|
+
let id = formContent?.id;
|
|
318
|
+
if (props?.ldap && selectedOption && selectedOption.value) {
|
|
319
|
+
values = {
|
|
320
|
+
...values,
|
|
321
|
+
addAllBranches: props.ldap.addAllBranches,
|
|
322
|
+
auth_user: selectedOption.value,
|
|
323
|
+
auth_type: 'LDAP',
|
|
324
|
+
FA: authentication,
|
|
325
|
+
};
|
|
326
|
+
}
|
|
246
327
|
|
|
247
|
-
|
|
328
|
+
if (values.attributes && typeof values === 'object') {
|
|
329
|
+
values = {
|
|
330
|
+
...values,
|
|
331
|
+
auth_type: 'LDAP',
|
|
248
332
|
|
|
249
|
-
|
|
333
|
+
attributes: JSON.stringify(values.attributes),
|
|
334
|
+
};
|
|
250
335
|
}
|
|
251
336
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
*/
|
|
255
|
-
function loadUsers() {
|
|
337
|
+
if (id) {
|
|
338
|
+
// Update of model
|
|
256
339
|
|
|
257
|
-
|
|
340
|
+
UsersAPI.updateUser({ id, formBody: values }).then((result) => {
|
|
341
|
+
if (result.success) message.success(result.message);
|
|
342
|
+
else message.error(result.message);
|
|
258
343
|
|
|
259
|
-
|
|
344
|
+
setLoading(false);
|
|
260
345
|
|
|
261
|
-
|
|
346
|
+
callback();
|
|
347
|
+
});
|
|
348
|
+
} else {
|
|
349
|
+
// Append the additional queries to the object
|
|
350
|
+
// additional_queries.forEach(({ field, value }) => {
|
|
351
|
+
// values[field] = value;
|
|
352
|
+
// });
|
|
353
|
+
if (Array.isArray(additional_queries)) {
|
|
354
|
+
additional_queries.forEach(({ field, value }) => {
|
|
355
|
+
values[field] = value;
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// add new model
|
|
360
|
+
UsersAPI.create(values).then((result) => {
|
|
361
|
+
// callback();
|
|
362
|
+
if (result.success) message.success(result.message);
|
|
363
|
+
else message.error(result.message);
|
|
262
364
|
|
|
263
|
-
|
|
365
|
+
setLoading(false);
|
|
264
366
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
}));
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Function on handle change
|
|
273
|
-
* @param {*} selected
|
|
274
|
-
*/
|
|
275
|
-
const handleChange = (selected) => {
|
|
276
|
-
setSelectedOption(selected);
|
|
277
|
-
};
|
|
278
|
-
/**
|
|
279
|
-
*
|
|
280
|
-
* @param {*} inputValue
|
|
281
|
-
* @param {*} callback
|
|
282
|
-
*/
|
|
283
|
-
|
|
284
|
-
const loadOptions = (inputValue, callback) => {
|
|
285
|
-
// Filter options based on input
|
|
286
|
-
const filteredOptions = options.filter(option =>
|
|
287
|
-
option.label.toLowerCase().includes(inputValue.toLowerCase())
|
|
288
|
-
);
|
|
289
|
-
callback(filteredOptions);
|
|
290
|
-
};
|
|
367
|
+
callback();
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
};
|
|
291
371
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
372
|
+
/**
|
|
373
|
+
* Function on handle change
|
|
374
|
+
* @param {*} selected
|
|
375
|
+
*/
|
|
376
|
+
const handleCheackChange = (e) => {
|
|
377
|
+
setIsPasswordVisible(e.target.checked);
|
|
378
|
+
};
|
|
295
379
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
<Form initialValues={formData} form={form} layout="vertical" onFinish={onSubmit}>
|
|
380
|
+
function changeView(result) {
|
|
381
|
+
setAuthentication(result);
|
|
382
|
+
}
|
|
300
383
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
384
|
+
/**
|
|
385
|
+
* Function to add load userrs
|
|
386
|
+
*/
|
|
387
|
+
function loadUsers() {
|
|
388
|
+
// UsersAPI.getLdapUsers().then((result) => {
|
|
389
|
+
// setUsers(result.result);
|
|
390
|
+
// });
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// Transform array into react-select options
|
|
394
|
+
let options = users.map((item) => ({
|
|
395
|
+
value: item.name,
|
|
396
|
+
label: item.name, // Capitalize the first letter
|
|
397
|
+
}));
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Function on handle change
|
|
401
|
+
* @param {*} selected
|
|
402
|
+
*/
|
|
403
|
+
const handleChange = (selected) => {
|
|
404
|
+
setSelectedOption(selected);
|
|
405
|
+
};
|
|
406
|
+
/**
|
|
407
|
+
*
|
|
408
|
+
* @param {*} inputValue
|
|
409
|
+
* @param {*} callback
|
|
410
|
+
*/
|
|
306
411
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
412
|
+
const loadOptions = (inputValue, callback) => {
|
|
413
|
+
// Filter options based on input
|
|
414
|
+
const filteredOptions = options.filter((option) => option.label.toLowerCase().includes(inputValue.toLowerCase()));
|
|
415
|
+
callback(filteredOptions);
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
return (
|
|
419
|
+
<section className="collection-add">
|
|
420
|
+
<Title level={4}>{mode} User</Title>
|
|
421
|
+
|
|
422
|
+
{loading ? (
|
|
423
|
+
<Skeleton />
|
|
424
|
+
) : (
|
|
425
|
+
<Form initialValues={formData} form={form} layout="vertical" onFinish={onSubmit}>
|
|
426
|
+
{/* user type */}
|
|
427
|
+
<Row gutter={16}>
|
|
428
|
+
<Col span={6}>
|
|
429
|
+
<Form.Item
|
|
430
|
+
name="user_type"
|
|
431
|
+
label="User Type"
|
|
432
|
+
allowClear
|
|
433
|
+
showSearch
|
|
434
|
+
initialValue="GEN"
|
|
435
|
+
rules={[{ required: true, message: 'Please select a user type' }]}
|
|
436
|
+
>
|
|
437
|
+
<Select options={getUserTypeOptions()} onChange={handleUserTypeChange} />
|
|
438
|
+
</Form.Item>
|
|
439
|
+
</Col>
|
|
440
|
+
<Col span={12}>
|
|
441
|
+
{/* username */}
|
|
442
|
+
<Form.Item name={'name'} label="Name" rules={[{ required: true, message: 'Please enter your user name' }]}>
|
|
443
|
+
<Input placeholder="Enter Name" autoFocus />
|
|
444
|
+
</Form.Item>
|
|
445
|
+
</Col>
|
|
446
|
+
<Col span={6}>
|
|
447
|
+
{' '}
|
|
448
|
+
{/* Show extra dropdown only if user type is Doctor */}
|
|
449
|
+
{userType === 'RAD' && (
|
|
450
|
+
<Form.Item name="default_code" label="Default Code" rules={[{ required: true, message: 'Please select a default code' }]}>
|
|
451
|
+
<Select
|
|
452
|
+
placeholder="Select Code"
|
|
453
|
+
options={doctorList}
|
|
454
|
+
showSearch
|
|
455
|
+
optionFilterProp="label"
|
|
456
|
+
dropdownRender={(menu) => (
|
|
457
|
+
<>
|
|
458
|
+
{menu}
|
|
459
|
+
<div
|
|
460
|
+
style={{
|
|
461
|
+
padding: '8px',
|
|
462
|
+
cursor: 'pointer',
|
|
463
|
+
borderTop: '1px solid #f0f0f0',
|
|
464
|
+
color: '#1890ff',
|
|
465
|
+
}}
|
|
466
|
+
onClick={() => setVisible(true)}
|
|
349
467
|
>
|
|
350
|
-
|
|
351
|
-
</
|
|
468
|
+
+ Add New Doctor
|
|
469
|
+
</div>
|
|
470
|
+
</>
|
|
352
471
|
)}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
{
|
|
358
|
-
{
|
|
472
|
+
/>
|
|
473
|
+
{/* Render DoctorAdd OUTSIDE the Select */}
|
|
474
|
+
<DoctorAdd
|
|
475
|
+
visible={visible}
|
|
476
|
+
onCancel={() => setVisible(false)}
|
|
477
|
+
attributes={attributes}
|
|
478
|
+
doctorData={selectedDoctor}
|
|
479
|
+
doctorId={doctorID}
|
|
480
|
+
onSuccess={getDoctors}
|
|
481
|
+
/>
|
|
482
|
+
</Form.Item>
|
|
483
|
+
)}
|
|
484
|
+
</Col>
|
|
485
|
+
</Row>
|
|
486
|
+
<Row gutter={16}>
|
|
487
|
+
<Col span={8}>
|
|
488
|
+
{/* email */}
|
|
489
|
+
<Form.Item name={'email'} label="User Name / Email" rules={[{ required: true, message: 'Please enter your email' }]}>
|
|
490
|
+
<Input placeholder="Enter Email Address" />
|
|
491
|
+
</Form.Item>
|
|
492
|
+
</Col>
|
|
493
|
+
<Col span={8}>
|
|
494
|
+
{/* Mobile */}
|
|
495
|
+
<Form.Item name="mobile" label="Mobile" rules={[{ required: true, message: 'Please enter your mobile number' }]}>
|
|
496
|
+
<Input placeholder="Enter Mobile" />
|
|
497
|
+
</Form.Item>
|
|
498
|
+
</Col>
|
|
499
|
+
<Col span={8}>
|
|
500
|
+
{/* Designation */}
|
|
501
|
+
<Form.Item name="designation" label="Designation">
|
|
502
|
+
<Select placeholder="Select Designation" options={designations} allowClear showSearch optionFilterProp="label" />
|
|
503
|
+
</Form.Item>
|
|
504
|
+
</Col>
|
|
505
|
+
</Row>
|
|
506
|
+
<Row gutter={16}>
|
|
507
|
+
{' '}
|
|
508
|
+
<Col span={8}>
|
|
509
|
+
{/* Department */}
|
|
510
|
+
<Form.Item name="department" label="Department">
|
|
511
|
+
<Select placeholder="Select Department" options={departments} allowClear showSearch optionFilterProp="label" />
|
|
512
|
+
</Form.Item>
|
|
513
|
+
</Col>
|
|
514
|
+
<Col span={8}>
|
|
515
|
+
{/* Branch */}
|
|
516
|
+
<Form.Item label="Branches" name="selectedBranches" rules={[{ required: true, message: 'Please select at least one branch' }]}>
|
|
517
|
+
<Select
|
|
518
|
+
mode="multiple"
|
|
519
|
+
placeholder="Select Branches"
|
|
520
|
+
value={selectedBranches}
|
|
521
|
+
onChange={(value) => {
|
|
522
|
+
setSelectedBranches(value);
|
|
523
|
+
|
|
524
|
+
// ⬅NEW: remove defaultBranch if it’s not in selectedBranches
|
|
525
|
+
if (!value.includes(defaultBranch)) {
|
|
526
|
+
setDefaultBranch(undefined);
|
|
527
|
+
form.setFieldsValue({ defaultBranch: undefined });
|
|
528
|
+
}
|
|
529
|
+
}}
|
|
530
|
+
options={branchOptions}
|
|
531
|
+
allowClear
|
|
532
|
+
showSearch
|
|
533
|
+
optionFilterProp="label"
|
|
534
|
+
maxTagCount={5} // Show only 5 tags
|
|
535
|
+
maxTagPlaceholder={(omittedValues) => `+${omittedValues.length}`} // Show "+n"
|
|
536
|
+
/>
|
|
537
|
+
</Form.Item>
|
|
538
|
+
</Col>
|
|
539
|
+
<Col span={8}>
|
|
540
|
+
{/* Default Branch */}
|
|
541
|
+
<Form.Item label="Default Branch" name="defaultBranch" rules={[{ required: true, message: 'Please select default branch' }]}>
|
|
542
|
+
<Select placeholder="Select Default Branch" onChange={setDefaultBranch}>
|
|
543
|
+
{branchOptions
|
|
544
|
+
.filter((opt) => selectedBranches.includes(opt.value))
|
|
545
|
+
.map((opt) => (
|
|
546
|
+
<Option key={opt.value} value={opt.value}>
|
|
547
|
+
{opt.label}
|
|
548
|
+
</Option>
|
|
549
|
+
))}
|
|
550
|
+
</Select>
|
|
551
|
+
</Form.Item>
|
|
552
|
+
</Col>
|
|
553
|
+
</Row>
|
|
554
|
+
<Row gutter={16}>
|
|
555
|
+
<Col span={8}>
|
|
556
|
+
{formContent?.id ? (
|
|
557
|
+
<>
|
|
558
|
+
<Form.Item>
|
|
559
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
560
|
+
<Checkbox onChange={handleCheackChange} />
|
|
561
|
+
<span>Select the option if you want to change the password</span>
|
|
562
|
+
</div>
|
|
563
|
+
</Form.Item>
|
|
564
|
+
|
|
565
|
+
{isPasswordVisible && (
|
|
566
|
+
<Form.Item
|
|
567
|
+
name="password"
|
|
568
|
+
label="Password"
|
|
569
|
+
rules={[
|
|
570
|
+
{ required: true, message: 'Please enter your password' },
|
|
571
|
+
{ pattern: passwordRegex, message: passwordRegexMessage },
|
|
572
|
+
]}
|
|
573
|
+
>
|
|
574
|
+
<Input.Password placeholder="Enter password" autoComplete="new-password" />
|
|
575
|
+
</Form.Item>
|
|
576
|
+
)}
|
|
577
|
+
</>
|
|
578
|
+
) : (
|
|
579
|
+
<Form.Item
|
|
580
|
+
name="password"
|
|
581
|
+
label="Password"
|
|
582
|
+
rules={[
|
|
583
|
+
{
|
|
584
|
+
required: true,
|
|
585
|
+
message: 'Please enter your password',
|
|
586
|
+
},
|
|
587
|
+
{
|
|
588
|
+
pattern: new RegExp(passwordRegex),
|
|
589
|
+
message: passwordRegexMessage,
|
|
590
|
+
},
|
|
591
|
+
]}
|
|
592
|
+
>
|
|
593
|
+
<Input.Password visibilityToggle={false} placeholder="Enter password" autoComplete="new-password" />
|
|
594
|
+
</Form.Item>
|
|
595
|
+
)}
|
|
596
|
+
</Col>
|
|
597
|
+
{/* </Form.Item> */}
|
|
598
|
+
|
|
599
|
+
{/* Path */}
|
|
600
|
+
{/* <Form.Item name="password" label="Password"
|
|
359
601
|
rules={[
|
|
360
602
|
{
|
|
361
603
|
required: true,
|
|
@@ -368,25 +610,25 @@ const UserAdd = ({ model, callback, edit, history, formContent, match, additiona
|
|
|
368
610
|
]}>
|
|
369
611
|
<Input.Password visibilityToggle={false} placeholder="Enter password" autoComplete='new-password' />
|
|
370
612
|
</Form.Item> */}
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
{/* Path */}
|
|
375
|
-
<Form.Item name="user_group" label="User Group" required>
|
|
376
|
-
<Input placeholder="Enter User Group" />
|
|
377
|
-
</Form.Item>
|
|
613
|
+
{/* Path Ends */}
|
|
378
614
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
615
|
+
{/* Path */}
|
|
616
|
+
<Col span={8}>
|
|
617
|
+
<Form.Item name="user_group" label="User Group" rules={[{ required: true, message: 'Please enter your user group' }]}>
|
|
618
|
+
<Input placeholder="Enter User Group" />
|
|
619
|
+
</Form.Item>
|
|
620
|
+
</Col>
|
|
382
621
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
<Input placeholder="Enter auth_type" value={"LDAP"} disabled />
|
|
622
|
+
{/* <Form.Item name="mobile" label="Mobile" required={mobileRequired}>
|
|
623
|
+
<Input placeholder="Enter Mobile" />
|
|
624
|
+
</Form.Item> */}
|
|
387
625
|
|
|
626
|
+
{props?.ldap && (
|
|
627
|
+
<>
|
|
628
|
+
<Form.Item name="auth_type" label="auth_type">
|
|
629
|
+
<Input placeholder="Enter auth_type" value={'LDAP'} disabled />
|
|
388
630
|
|
|
389
|
-
|
|
631
|
+
{/* <Select
|
|
390
632
|
|
|
391
633
|
placeholder="Auth Type"
|
|
392
634
|
defaultValue={'LDAP'}
|
|
@@ -399,7 +641,7 @@ const UserAdd = ({ model, callback, edit, history, formContent, match, additiona
|
|
|
399
641
|
</Option>
|
|
400
642
|
</Select> */}
|
|
401
643
|
|
|
402
|
-
|
|
644
|
+
{/* <div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
|
403
645
|
|
|
404
646
|
<div style={{ width: '40%' }}>
|
|
405
647
|
|
|
@@ -408,51 +650,63 @@ const UserAdd = ({ model, callback, edit, history, formContent, match, additiona
|
|
|
408
650
|
|
|
409
651
|
|
|
410
652
|
</div> */}
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
653
|
+
</Form.Item>
|
|
654
|
+
|
|
655
|
+
{/* Path */}
|
|
656
|
+
<Form.Item name="auth_user" label="User Name" required>
|
|
657
|
+
<Input placeholder="Enter User Name" />
|
|
658
|
+
</Form.Item>
|
|
659
|
+
</>
|
|
660
|
+
)}
|
|
661
|
+
</Row>
|
|
662
|
+
<Row gutter={16}>
|
|
663
|
+
<Col span={8}>
|
|
664
|
+
<Form.Item>
|
|
665
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
666
|
+
<Switch
|
|
667
|
+
disabled={disabled}
|
|
668
|
+
// defaultChecked={view}
|
|
669
|
+
onChange={changeView}
|
|
670
|
+
checked={authentication}
|
|
671
|
+
// disabled={disabled}
|
|
672
|
+
defaultChecked
|
|
673
|
+
// checkedChildren={<OrderedListOutlined />}
|
|
674
|
+
// unCheckedChildren={<PicCenterOutlined />}
|
|
675
|
+
/>
|
|
676
|
+
<span>Enable Two Factor Authentication</span>
|
|
677
|
+
</div>
|
|
678
|
+
</Form.Item>
|
|
679
|
+
</Col>
|
|
680
|
+
<Col span={8}>
|
|
681
|
+
{/* <label>User Status</label> */}
|
|
682
|
+
<Form.Item
|
|
683
|
+
name="active"
|
|
684
|
+
valuePropName="checked"
|
|
685
|
+
getValueFromEvent={(e) => (e.target.checked ? true : false)}
|
|
686
|
+
getValueProps={(value) => ({ checked: value === true })}
|
|
687
|
+
style={{ marginBottom: 0 }}
|
|
688
|
+
>
|
|
689
|
+
<Checkbox>Active</Checkbox>
|
|
690
|
+
</Form.Item>
|
|
691
|
+
</Col>
|
|
692
|
+
</Row>
|
|
693
|
+
{/* Path Ends */}
|
|
694
|
+
|
|
695
|
+
{/* Path */}
|
|
696
|
+
{/* <Form.Item name="active" label="Active" required>
|
|
442
697
|
<Switch />
|
|
443
698
|
</Form.Item> */}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
);
|
|
699
|
+
{/* Path Ends */}
|
|
700
|
+
|
|
701
|
+
<Form.Item>
|
|
702
|
+
<Button loading={loading} htmlType={'submit'} type="primary">
|
|
703
|
+
Submit
|
|
704
|
+
</Button>
|
|
705
|
+
</Form.Item>
|
|
706
|
+
</Form>
|
|
707
|
+
)}
|
|
708
|
+
</section>
|
|
709
|
+
);
|
|
456
710
|
};
|
|
457
711
|
|
|
458
712
|
export default UserAdd;
|