ui-soxo-bootstrap-core 2.6.1-dev.1 → 2.6.1-dev.11

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.
Files changed (51) hide show
  1. package/core/components/extra-info/extra-info-details.js +2 -2
  2. package/core/lib/Store.js +3 -3
  3. package/core/lib/components/global-header/global-header.js +2 -2
  4. package/core/lib/components/sidemenu/sidemenu.js +19 -13
  5. package/core/lib/elements/basic/country-phone-input/country-phone-input.js +14 -8
  6. package/core/lib/elements/basic/dragabble-wrapper/draggable-wrapper.js +1 -1
  7. package/core/lib/elements/basic/menu-tree/menu-tree.js +26 -13
  8. package/core/lib/models/forms/components/form-creator/form-creator.scss +5 -4
  9. package/core/lib/models/menus/components/menu-list/menu-list.js +424 -467
  10. package/core/lib/pages/change-password/change-password.js +17 -24
  11. package/core/lib/pages/change-password/change-password.scss +45 -48
  12. package/core/lib/pages/login/commnication-mode-selection.js +46 -0
  13. package/core/lib/pages/login/communication-mode-selection.scss +60 -0
  14. package/core/lib/pages/login/login.js +126 -22
  15. package/core/lib/pages/login/login.scss +229 -334
  16. package/core/lib/pages/login/reset-password.js +124 -0
  17. package/core/lib/pages/login/reset-password.scss +31 -0
  18. package/core/lib/pages/profile/themes.json +4 -4
  19. package/core/lib/utils/api/api.utils.js +30 -18
  20. package/core/lib/utils/common/common.utils.js +85 -0
  21. package/core/lib/utils/http/http.utils.js +1 -0
  22. package/core/lib/utils/index.js +4 -1
  23. package/core/models/base/base.js +7 -3
  24. package/core/models/core-scripts/core-scripts.js +9 -0
  25. package/core/models/doctor/components/doctor-add/doctor-add.js +9 -4
  26. package/core/models/menus/components/menu-add/menu-add.js +1 -1
  27. package/core/models/menus/components/menu-lists/menu-lists.js +5 -9
  28. package/core/models/menus/menus.js +21 -2
  29. package/core/models/roles/components/role-add/role-add.js +92 -59
  30. package/core/models/roles/components/role-list/role-list.js +1 -1
  31. package/core/models/staff/components/staff-add/staff-add.js +20 -32
  32. package/core/models/users/components/assign-role/assign-role.js +145 -50
  33. package/core/models/users/components/assign-role/assign-role.scss +209 -45
  34. package/core/models/users/components/assign-role/avatar-props.js +45 -0
  35. package/core/models/users/components/user-add/user-add.js +46 -55
  36. package/core/models/users/components/user-add/user-edit.js +25 -4
  37. package/core/models/users/users.js +16 -1
  38. package/core/modules/dashboard/components/dashboard-card/menu-dashboard-card.js +1 -1
  39. package/core/modules/reporting/components/reporting-dashboard/README.md +316 -0
  40. package/core/modules/reporting/components/reporting-dashboard/adavance-search/advance-search.js +266 -0
  41. package/core/modules/reporting/components/reporting-dashboard/display-columns/build-display-columns.js +75 -0
  42. package/core/modules/reporting/components/reporting-dashboard/display-columns/build-display-columns.test.js +74 -0
  43. package/core/modules/reporting/components/reporting-dashboard/display-columns/display-cell-renderer.js +252 -0
  44. package/core/modules/reporting/components/reporting-dashboard/display-columns/display-cell-renderer.test.js +126 -0
  45. package/core/modules/reporting/components/reporting-dashboard/reporting-dashboard.js +285 -399
  46. package/core/modules/steps/action-buttons.js +42 -44
  47. package/core/modules/steps/action-buttons.scss +35 -6
  48. package/core/modules/steps/steps.js +12 -10
  49. package/core/modules/steps/steps.scss +229 -31
  50. package/core/modules/steps/timeline.js +21 -19
  51. package/package.json +2 -1
@@ -0,0 +1,124 @@
1
+ /**
2
+ * ResetPassword Component
3
+ *
4
+ * Handles staff password reset flow:
5
+ * - Accepts username
6
+ * - Selects communication mode (email/SMS)
7
+ * - Calls API to send reset link
8
+ * - Displays success/error messages
9
+ * - Allows navigation back to login
10
+ *
11
+ * Props:
12
+ * @param {Function} onBack - Triggered when "Back to Login" is clicked
13
+ * @param {string} title - Page title
14
+ * @param {string} subtitle - Page subtitle
15
+ * @param {string} buttonText - Submit button text
16
+ * @param {string} defaultUsername - Pre-filled username
17
+ * @param {boolean} disabledUserName - Disable username field
18
+ */
19
+
20
+ import React, { useState, useEffect, useRef } from 'react';
21
+ import { Divider, Form, Input, message } from 'antd';
22
+ import { Button } from '../../elements';
23
+ import CommunicationModeSelection from './commnication-mode-selection';
24
+ import { motion } from 'framer-motion';
25
+ import './reset-password.scss';
26
+ import { UsersAPI } from '../../../models';
27
+
28
+ function ResetPassword({ onBack, title, subtitle, buttonText, defaultUsername, disabledUserName }) {
29
+ // Selected communication mode (default: email) */
30
+ const [communicationMode, setCommunicationMode] = useState('email');
31
+
32
+ const [modeError, setModeError] = useState(false);
33
+
34
+ // Loading state for submit button */
35
+ const [loading, setLoading] = useState(false);
36
+
37
+ const [form] = Form.useForm();
38
+
39
+ // Ref to username input auto focus
40
+ const inputRef = useRef(null);
41
+
42
+ // Pre-fills username if provided and disabled.
43
+ useEffect(() => {
44
+ if (disabledUserName && defaultUsername) {
45
+ form.setFieldsValue({ username: defaultUsername });
46
+ }
47
+ }, [disabledUserName, defaultUsername]);
48
+
49
+ useEffect(() => {
50
+ inputRef.current?.focus();
51
+ }, []);
52
+
53
+ /**
54
+ * Sends forgot password request to backend.
55
+ * Payload: { mode, username, user_type: 'staff' }
56
+ */
57
+ const handleSendForgetPassword = async (values) => {
58
+ const payload = {
59
+ mode: communicationMode,
60
+ username: values.username,
61
+ user_type: 'staff',
62
+ };
63
+ setLoading(true);
64
+
65
+ try {
66
+ const res = await UsersAPI.createForgotePassword(payload);
67
+
68
+ if (!res?.success) {
69
+ throw new Error(res?.message || 'Reset password failed');
70
+ }
71
+
72
+ message.success(res?.message || 'Reset password link sent');
73
+ } catch (err) {
74
+ message.warning(err?.message || 'Reset password failed');
75
+ } finally {
76
+ setLoading(false);
77
+ }
78
+ };
79
+
80
+ /**
81
+ * Clears auth storage and navigates back.
82
+ */
83
+ const handleBackToLogin = () => {
84
+ localStorage.removeItem('access_token');
85
+ localStorage.removeItem('refresh_token');
86
+ sessionStorage.clear();
87
+ onBack();
88
+ };
89
+
90
+ return (
91
+ <motion.div
92
+ className="forgot-password-container"
93
+ initial={{ opacity: 0, y: 30 }}
94
+ animate={{ opacity: 1, y: 0 }}
95
+ exit={{ opacity: 0, y: -20 }}
96
+ transition={{
97
+ duration: 0.30,
98
+ ease: 'easeOut',
99
+ }}
100
+ >
101
+ <h3 className="password-title">{title}</h3>
102
+ {/* <p className="password-subtitle">{subtitle}</p>
103
+ <Divider /> */}
104
+ <Form layout="vertical" form={form} onFinish={handleSendForgetPassword}>
105
+ <Form.Item label="Username" name="username" rules={[{ required: true, message: 'Please input your username' }]}>
106
+ <Input placeholder="Enter your username" disabled={disabledUserName} ref={inputRef}/>
107
+ </Form.Item>
108
+
109
+ <CommunicationModeSelection communicationMode={communicationMode} setCommunicationMode={setCommunicationMode} modeError={modeError} />
110
+
111
+ <Button type="primary" htmlType="submit" loading={loading}>
112
+ {buttonText}
113
+ </Button>
114
+ <div className="back-to-login">
115
+ <a onClick={handleBackToLogin}>
116
+ Back to Login
117
+ </a>
118
+ </div>
119
+ </Form>
120
+ </motion.div>
121
+ );
122
+ }
123
+
124
+ export default ResetPassword;
@@ -0,0 +1,31 @@
1
+ .forgot-password-container {
2
+
3
+ padding: 4px;
4
+ .password-title{
5
+ color: #1f1f1f;
6
+ margin: 0 0 8px;
7
+ }
8
+
9
+ .password-subtitle {
10
+ font-size: 14px;
11
+ font-weight: 400;
12
+ color: #6b7280;
13
+ line-height: 1.5;
14
+ margin: 0 0 20px;
15
+ }
16
+
17
+ .ant-divider {
18
+ margin: 0;
19
+ border-top: 1px solid #e5e7eb;
20
+ }
21
+
22
+ .back-to-login {
23
+ margin-top: 10px;
24
+ text-align: center;
25
+
26
+ a {
27
+ cursor: pointer;
28
+ color: #204b7e;
29
+ }
30
+ }
31
+ }
@@ -88,10 +88,10 @@
88
88
  "loginPageBackground": "linear-gradient(#D5F1FB, #24AEB8)",
89
89
  "bodyBackground": "#F0F6FF",
90
90
  "progressBar": "#24AEB8",
91
- "primaryButtonBg": "#446AA9",
91
+ "primaryButtonBg": "#204b7e",
92
92
  "primaryButtonHoverBg": "#2E4873",
93
93
  "primaryButtonText": "#FFFFFF",
94
- "primaryButtonActiveBg": "#446AA9",
94
+ "primaryButtonActiveBg": "#204b7e",
95
95
  "primaryButtonDisabledBg": "#C4C6CC",
96
96
  "primaryButtonDisabledText": "#6B7280",
97
97
 
@@ -104,14 +104,14 @@
104
104
 
105
105
  "dashedButtonBg": "#FFFFFF",
106
106
  "dashedButtonHoverBg": "#D1E3FF",
107
- "dashedButtonText": "#446AA9",
107
+ "dashedButtonText": "#204b7e",
108
108
  "dashedButtonActiveBg": "#B8C7FF",
109
109
  "dashedButtonDisabledBg": "#F0F6FF",
110
110
  "dashedButtonDisabledText": "#A9BCC6",
111
111
 
112
112
  "linkButtonBg": "transparent",
113
113
  "linkButtonHoverBg": "#F5F5F5",
114
- "linkButtonText": "#446AA9",
114
+ "linkButtonText": "#204b7e",
115
115
  "linkButtonActiveBg": "#D1E3FF",
116
116
  "linkButtonDisabledText": "#A9BCC6",
117
117
 
@@ -24,15 +24,15 @@ export default class ApiUtils {
24
24
  };
25
25
 
26
26
  static get = async ({ url, config = { queries: [], order: {} }, headers: customHeaders = {}, ...props }) => {
27
- const { headers: defaultHeaders } = settings;
27
+ const dbPtr = localStorage.getItem('db_ptr');
28
28
 
29
29
  try {
30
30
  return await GetData({
31
31
  url: createUrlParams(url, config),
32
32
  settings,
33
33
  headers: {
34
- ...defaultHeaders,
35
- // override here
34
+ ...(settings.headers || {}),
35
+ ...(dbPtr ? { db_ptr: dbPtr } : {}),
36
36
  ...customHeaders,
37
37
  },
38
38
  ...props,
@@ -43,15 +43,15 @@ export default class ApiUtils {
43
43
  };
44
44
 
45
45
  static getRecordDetail = async ({ url, config = { queries: [] }, headers: customHeaders = {}, ...props }) => {
46
- const { headers: defaultHeaders } = settings;
46
+ const dbPtr = localStorage.getItem('db_ptr');
47
47
 
48
48
  try {
49
49
  return await GetData({
50
50
  url: createUrlParams(url, config),
51
51
  settings,
52
52
  headers: {
53
- ...defaultHeaders,
54
- // override here
53
+ ...(settings.headers || {}),
54
+ ...(dbPtr ? { db_ptr: dbPtr } : {}),
55
55
  ...customHeaders,
56
56
  },
57
57
  ...props,
@@ -62,52 +62,64 @@ export default class ApiUtils {
62
62
  };
63
63
 
64
64
  static post = ({ url, formBody, headers: customHeaders = {}, ...props }) => {
65
- const { headers: defaultHeaders } = settings;
65
+ const dbPtr = localStorage.getItem('db_ptr');
66
66
 
67
67
  return PostData({
68
68
  url,
69
69
  formBody,
70
70
  settings,
71
71
  headers: {
72
- ...defaultHeaders,
73
- // override here
72
+ ...(settings.headers || {}),
73
+ ...(dbPtr ? { db_ptr: dbPtr } : {}),
74
74
  ...customHeaders,
75
75
  },
76
76
  ...props,
77
77
  });
78
78
  };
79
79
 
80
- static put = ({ url, formBody, ...props }) => {
81
- const { headers } = settings;
80
+ static put = ({ url, formBody, headers: customHeaders = {}, ...props }) => {
81
+ const dbPtr = localStorage.getItem('db_ptr');
82
82
 
83
83
  return PutData({
84
84
  url,
85
85
  settings,
86
86
  formBody,
87
- headers,
87
+ headers: {
88
+ ...(settings.headers || {}),
89
+ ...(dbPtr ? { db_ptr: dbPtr } : {}),
90
+ ...customHeaders,
91
+ },
88
92
  ...props,
89
93
  });
90
94
  };
91
95
 
92
- static patch = ({ url, formBody, ...props }) => {
93
- const { headers } = settings;
96
+ static patch = ({ url, formBody, headers: customHeaders = {}, ...props }) => {
97
+ const dbPtr = localStorage.getItem('db_ptr');
94
98
 
95
99
  return PatchData({
96
100
  url,
97
101
  settings,
98
102
  formBody,
99
- headers,
103
+ headers: {
104
+ ...(settings.headers || {}),
105
+ ...(dbPtr ? { db_ptr: dbPtr } : {}),
106
+ ...customHeaders,
107
+ },
100
108
  ...props,
101
109
  });
102
110
  };
103
111
 
104
- static delete = ({ url, formBody, ...props }) => {
105
- const { headers } = settings;
112
+ static delete = ({ url, formBody, headers: customHeaders = {}, ...props }) => {
113
+ const dbPtr = localStorage.getItem('db_ptr');
106
114
 
107
115
  return DeleteData({
108
116
  url,
109
117
  settings,
110
- headers,
118
+ headers: {
119
+ ...(settings.headers || {}),
120
+ ...(dbPtr ? { db_ptr: dbPtr } : {}),
121
+ ...customHeaders,
122
+ },
111
123
  ...props,
112
124
  });
113
125
  };
@@ -4,6 +4,7 @@ Implements utility functions to be used across project
4
4
 
5
5
  /*eslint no-useless-escape:"off",eqeqeq: "off"*/
6
6
  import moment from 'moment';
7
+ import { parsePhoneNumberFromString, isValidPhoneNumber } from 'libphonenumber-js';
7
8
 
8
9
  export function IsObjectHaveKeys(obj) {
9
10
  return obj && typeof obj == 'object' && Object.keys(obj).length;
@@ -122,6 +123,42 @@ export const checkLicenseStatus = (expiryDate) => {
122
123
  return { valid: true, daysLeft, message: null, level: null };
123
124
  };
124
125
 
126
+ /**
127
+ * Checks password expiry status.
128
+ *
129
+ * @param {string|Date} expiryDate
130
+ * @param {number} warningDays
131
+ * @param {string} expiredMessage
132
+ * @param {(daysLeft: number) => string} warningMessage
133
+ *
134
+ * @returns {{ valid: boolean, daysLeft: number, message: string|null, level: "error"|"warning"|null }}
135
+ */
136
+
137
+ export const checkExpiryStatus = ({ expiryDate, warningDays, expiredMessage, warningMessage }) => {
138
+ const expiry = new Date(expiryDate);
139
+
140
+ if (isNaN(expiry)) {
141
+ return { valid: false, daysLeft: 0, message: 'Invalid date', level: 'error' };
142
+ }
143
+
144
+ expiry.setHours(0, 0, 0, 0);
145
+ const today = new Date();
146
+ today.setHours(0, 0, 0, 0);
147
+
148
+ const msDiff = expiry.getTime() - today.getTime();
149
+ const daysLeft = Math.ceil(msDiff / (1000 * 60 * 60 * 24));
150
+
151
+ if (daysLeft < 0) {
152
+ return { valid: false, daysLeft, message: expiredMessage, level: 'error' };
153
+ }
154
+
155
+ if (daysLeft <= warningDays) {
156
+ return { valid: true, daysLeft, message: warningMessage(daysLeft), level: 'warning' };
157
+ }
158
+
159
+ return { valid: true, daysLeft, message: null, level: null };
160
+ };
161
+
125
162
  /**
126
163
  * Masks a mobile number by hiding all but the last `visibleDigits`.
127
164
  * Adds spacing only to the masked portion (groups of 3),
@@ -185,3 +222,51 @@ export function safeJSON(value) {
185
222
  return null;
186
223
  }
187
224
  }
225
+
226
+ /**
227
+ * Convert +countrycode phone into form compatible structure
228
+ * @param {string} phone
229
+ * @returns {object|null}
230
+ */
231
+ export const formatPhoneForForm = (phone) => {
232
+ if (!phone) return null;
233
+
234
+ const parsed = parsePhoneNumberFromString(phone);
235
+
236
+ if (!parsed) return null;
237
+
238
+ return {
239
+ value: parsed.nationalNumber,
240
+ code: {
241
+ dialCode: parsed.countryCallingCode,
242
+ countryCode: parsed.country?.toLowerCase(),
243
+ },
244
+ valid: true,
245
+ };
246
+ };
247
+
248
+ /**
249
+ * Validates a phone number from CountryPhoneInput.
250
+ * Builds full number using country dial code and checks validity.
251
+ *
252
+ * @param {Object} _ - Ant Design rule parameter (unused)
253
+ * @param {Object} val - Phone value object from form
254
+ * @returns {Promise<void>}
255
+ */
256
+ export const phoneValidator = (_, val) => {
257
+ if (!val || !val.value || !val?.code?.dialCode) {
258
+ return Promise.resolve();
259
+ }
260
+
261
+ const fullPhone = `+${val.code.dialCode}${val.value}`;
262
+
263
+ return isValidPhoneNumber(fullPhone) ? Promise.resolve() : Promise.reject('Invalid mobile number');
264
+ };
265
+
266
+ // Returns phone number with country code (e.g., +919876543210)
267
+ export const formatPhoneWithCountryCode = (phone) => {
268
+ if (phone && typeof phone === 'object' && phone.code) {
269
+ return `+${phone.code.dialCode}${phone.value}`;
270
+ }
271
+ return phone;
272
+ };
@@ -153,5 +153,6 @@ export async function ApiCall({ url, formBody, method, settings, ...props }) {
153
153
  return result;
154
154
  } catch (err) {
155
155
  console.error('Login error -->', err?.message);
156
+ throw err;
156
157
  }
157
158
  }
@@ -14,7 +14,7 @@ import { GetData, PostData, PutData, DeleteData } from './http/http.utils';
14
14
 
15
15
  import { getExportData } from './generic/generic.utils';
16
16
 
17
- import { ConvertBytesToArray, safeJSON } from './common/common.utils';
17
+ import { ConvertBytesToArray, safeJSON, formatPhoneForForm, phoneValidator, formatPhoneWithCountryCode } from './common/common.utils';
18
18
 
19
19
  import SettingsUtil from './setting.utils';
20
20
 
@@ -37,4 +37,7 @@ export {
37
37
  SettingsUtil,
38
38
  FormUtils,
39
39
  safeJSON,
40
+ formatPhoneForForm,
41
+ phoneValidator,
42
+ formatPhoneWithCountryCode,
40
43
  };
@@ -88,9 +88,13 @@ class BaseAPI {
88
88
  * Get the data from the table
89
89
  */
90
90
  get(config = {}) {
91
- // Get the records from firebase
92
-
93
- return ApiUtils.get({ url: config.url || this.endpoint, config });
91
+ const { url, headers, ...rest } = config;
92
+ return ApiUtils.get({
93
+ url: url || this.endpoint,
94
+ headers,
95
+ config: rest,
96
+ ...rest,
97
+ });
94
98
  }
95
99
 
96
100
  getRelations(id) {
@@ -97,6 +97,15 @@ class CoreScript extends Base {
97
97
  });
98
98
  };
99
99
 
100
+ getQuery = (formBody) => {
101
+
102
+ return ApiUtils.post({
103
+ url: `core-scripts/execute-script-api`,
104
+ formBody,
105
+ });
106
+ };
107
+
108
+
100
109
 
101
110
  /**
102
111
  *
@@ -6,7 +6,8 @@ import { useTranslation, Button } from './../../../../lib/';
6
6
  import { UsersAPI } from '../../..';
7
7
  import SignatureCanvasComponent from '../../../../lib/components/consent/signature-pad';
8
8
 
9
- const DoctorAdd = ({ visible, onCancel, attributes, doctorId, doctorData, onSuccess }) => {
9
+ const DoctorAdd = ({ visible, onCancel, doctorId, doctorData, onSuccess }) => {
10
+ // console.log('attributes', attributes);
10
11
  const [form] = Form.useForm();
11
12
  const { t } = useTranslation();
12
13
 
@@ -21,8 +22,8 @@ const DoctorAdd = ({ visible, onCancel, attributes, doctorId, doctorData, onSucc
21
22
  const [doctorID, setDoctorID] = useState(false);
22
23
  const [selectedDoctor, setSelectedDoctor] = useState(null);
23
24
 
24
- const propValues = attributes || {};
25
- const doctorType = propValues?.type;
25
+ // const propValues = attributes || {};
26
+ // const doctorType = propValues?.type;
26
27
 
27
28
  const editMode = Boolean(doctorId);
28
29
 
@@ -37,6 +38,10 @@ const DoctorAdd = ({ visible, onCancel, attributes, doctorId, doctorData, onSucc
37
38
  message: '',
38
39
  });
39
40
 
41
+ const getDoctorTypeOptions = () => [
42
+ { label: 'In House', value: 'DRINH' },
43
+ { label: 'Out Side', value: 'DROTR' },
44
+ ];
40
45
  /** Autofocus on modal open */
41
46
  useEffect(() => {
42
47
  if (visible) {
@@ -266,7 +271,7 @@ const DoctorAdd = ({ visible, onCancel, attributes, doctorId, doctorData, onSucc
266
271
  <Row gutter={16}>
267
272
  <Col span={8}>
268
273
  <Form.Item label="Type" name="type">
269
- <Select placeholder="Select Type" options={doctorType || []} showSearch />
274
+ <Select placeholder="Select Type" options={getDoctorTypeOptions() || []} showSearch />
270
275
  </Form.Item>
271
276
  </Col>
272
277
 
@@ -164,7 +164,7 @@ const MenuAdd = ({ model, callback, edit, history, formContent, match, additiona
164
164
  <div className="left-container">
165
165
  {/* Caption */}
166
166
  <Form.Item name={'caption'} label="Caption" rules={[{ required: true, message: 'Caption is required' }]}>
167
- <Input placeholder="Enter caption" />
167
+ <Input placeholder="Enter caption" autoFocus />
168
168
  </Form.Item>
169
169
  {/* Caption Ends */}
170
170
 
@@ -1,5 +1,5 @@
1
1
  import React, { useState, useCallback, useEffect } from 'react';
2
- import { Space, Popconfirm, Input, Drawer, Skeleton, Collapse, message } from 'antd';
2
+ import { Space, Popconfirm, Input, Drawer, Skeleton, Collapse, message, Tag } from 'antd';
3
3
  import { ReloadOutlined, DeleteOutlined, EditOutlined, PlusCircleFilled, CopyOutlined } from '@ant-design/icons';
4
4
  import { Button, Card, Switch, DraggableWrapper } from '../../../../lib';
5
5
  // for draggable menu list import { DndProvider } from "react-dnd";
@@ -55,7 +55,6 @@ const MenuLists = ({ model, match, relativeAdd = false, additional_queries = [],
55
55
  .catch(() => setLoading(false));
56
56
  };
57
57
 
58
- console.log('record', records);
59
58
  /**
60
59
  *
61
60
  */
@@ -206,7 +205,7 @@ const MenuLists = ({ model, match, relativeAdd = false, additional_queries = [],
206
205
 
207
206
  const filtered = records.filter((r) => r.name?.toUpperCase().includes(query.toUpperCase()));
208
207
 
209
- const visibleItems = dragMode ? records : filtered;
208
+ const visibleItems = filtered;
210
209
 
211
210
  const onSearch = (event) => {
212
211
  setQuery(event.target.value);
@@ -440,7 +439,7 @@ const MenuLists = ({ model, match, relativeAdd = false, additional_queries = [],
440
439
  function panelActions(item, model, setSelectedRecord, setDrawerTitle, setDrawerVisible, deleteRecord) {
441
440
  return (
442
441
  <Space onClick={(e) => e.stopPropagation()}>
443
- {/* NEW BUTTON Add Submenu */}
442
+ <Tag color={item.is_visible === true ? 'green' : 'blue'}>{item.is_visible === true ? 'VISIBLE' : 'HIDDEN'}</Tag>{' '}
444
443
  <Button
445
444
  size="small"
446
445
  type="dashed"
@@ -459,7 +458,6 @@ function panelActions(item, model, setSelectedRecord, setDrawerTitle, setDrawerV
459
458
  <PlusCircleFilled />
460
459
  Add Sub Menu
461
460
  </Button>
462
-
463
461
  {model.ModalAddComponent && (
464
462
  <Button
465
463
  size="small"
@@ -473,8 +471,7 @@ function panelActions(item, model, setSelectedRecord, setDrawerTitle, setDrawerV
473
471
  <EditOutlined />
474
472
  </Button>
475
473
  )}
476
-
477
- {/* <Button
474
+ <Button
478
475
  size="small"
479
476
  type="default"
480
477
  onClick={() => {
@@ -484,8 +481,7 @@ function panelActions(item, model, setSelectedRecord, setDrawerTitle, setDrawerV
484
481
  }}
485
482
  >
486
483
  <CopyOutlined />
487
- </Button> */}
488
-
484
+ </Button>
489
485
  <Popconfirm title="Are you sure?" onConfirm={() => deleteRecord(item)}>
490
486
  <Button danger size="small" type="default">
491
487
  <DeleteOutlined />
@@ -177,28 +177,47 @@ class MenusAPI extends Base {
177
177
  * @param {*} menu
178
178
  * @returns
179
179
  */
180
- getMenus = (config) => {
180
+ getMenus = (config, dbPtr = null) => {
181
181
  // Use 'core-menus' endpoint if REACT_APP_USE_CORE_MENUS is true (used for Matria)
182
182
  const url =
183
183
  process.env.REACT_APP_USE_CORE_MENUS === 'true'
184
184
  ? 'core-menus/get-menus' // Matria
185
185
  : 'menus/get-menus'; // NURA
186
186
 
187
+ if (!dbPtr) dbPtr = localStorage.db_ptr;
188
+
187
189
  return this.get({
188
190
  url,
189
191
  config,
192
+ headers: {
193
+ db_ptr: dbPtr,
194
+ },
195
+ }).then((result) => result);
196
+ };
197
+
198
+ getMenubyUser = (user_id) => {
199
+ const url = `menus/get-menus?userId=${user_id}`;
200
+ return this.get({
201
+ url,
190
202
  }).then((result) => result);
191
203
  };
192
204
 
193
205
  // get core-menu list with submenu
194
206
  getCoreMenuLists = () => {
195
207
  const url = 'core-menus/core-menus?step=1&header_id=null';
196
-
197
208
  return this.get({
198
209
  url,
199
210
  }).then((result) => result);
200
211
  };
201
212
 
213
+ getCoreMenuByRoleId = async (role_id) => {
214
+ const url = `menus/get-menus-by-role/${role_id}`;
215
+ const result = await this.get({
216
+ url,
217
+ });
218
+ return result;
219
+ };
220
+
202
221
  getCoreMenus = () => {
203
222
  return [
204
223
  // {