ui-soxo-bootstrap-core 2.6.1-dev.2 → 2.6.1-dev.20

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 (66) hide show
  1. package/core/components/extra-info/extra-info-details.js +2 -2
  2. package/core/components/index.js +2 -11
  3. package/core/components/landing-api/landing-api.js +91 -15
  4. package/core/components/landing-api/landing-api.scss +22 -0
  5. package/core/components/license-management/license-alert.js +97 -0
  6. package/core/lib/Store.js +3 -3
  7. package/core/lib/components/global-header/animations.js +78 -4
  8. package/core/lib/components/global-header/global-header.js +224 -255
  9. package/core/lib/components/global-header/global-header.scss +162 -24
  10. package/core/lib/components/sidemenu/animations.js +84 -2
  11. package/core/lib/components/sidemenu/sidemenu.js +191 -65
  12. package/core/lib/components/sidemenu/sidemenu.scss +221 -14
  13. package/core/lib/elements/basic/country-phone-input/country-phone-input.js +14 -8
  14. package/core/lib/elements/basic/dragabble-wrapper/draggable-wrapper.js +1 -1
  15. package/core/lib/elements/basic/menu-tree/menu-tree.js +26 -13
  16. package/core/lib/models/forms/components/form-creator/form-creator.scss +4 -3
  17. package/core/lib/models/menus/components/menu-list/menu-list.js +424 -467
  18. package/core/lib/models/process/components/process-dashboard/process-dashboard.js +469 -3
  19. package/core/lib/models/process/components/process-dashboard/process-dashboard.scss +4 -0
  20. package/core/lib/pages/change-password/change-password.js +17 -24
  21. package/core/lib/pages/change-password/change-password.scss +45 -48
  22. package/core/lib/pages/login/commnication-mode-selection.js +2 -2
  23. package/core/lib/pages/login/login.js +47 -62
  24. package/core/lib/pages/login/login.scss +9 -0
  25. package/core/lib/pages/login/reset-password.js +17 -17
  26. package/core/lib/pages/login/reset-password.scss +10 -1
  27. package/core/lib/pages/profile/themes.json +4 -4
  28. package/core/lib/utils/api/api.utils.js +30 -18
  29. package/core/lib/utils/common/common.utils.js +49 -35
  30. package/core/lib/utils/http/http.utils.js +2 -1
  31. package/core/lib/utils/index.js +4 -1
  32. package/core/models/base/base.js +7 -3
  33. package/core/models/core-scripts/core-scripts.js +134 -126
  34. package/core/models/doctor/components/doctor-add/doctor-add.js +9 -4
  35. package/core/models/menus/components/menu-add/menu-add.js +1 -1
  36. package/core/models/menus/components/menu-lists/menu-lists.js +53 -54
  37. package/core/models/menus/menus.js +27 -2
  38. package/core/models/roles/components/role-add/role-add.js +92 -59
  39. package/core/models/roles/components/role-list/role-list.js +1 -1
  40. package/core/models/staff/components/staff-add/staff-add.js +20 -32
  41. package/core/models/users/components/assign-role/assign-role.js +145 -50
  42. package/core/models/users/components/assign-role/assign-role.scss +209 -45
  43. package/core/models/users/components/assign-role/avatar-props.js +45 -0
  44. package/core/models/users/components/user-add/user-add.js +46 -55
  45. package/core/models/users/components/user-add/user-edit.js +25 -4
  46. package/core/models/users/users.js +9 -1
  47. package/core/modules/dashboard/components/dashboard-card/menu-dashboard-card.js +1 -1
  48. package/core/modules/reporting/components/reporting-dashboard/README.md +316 -0
  49. package/core/modules/reporting/components/reporting-dashboard/adavance-search/advance-search.js +147 -0
  50. package/core/modules/reporting/components/reporting-dashboard/adavance-search/advance-search.scss +76 -0
  51. package/core/modules/reporting/components/reporting-dashboard/display-columns/build-display-columns.js +90 -0
  52. package/core/modules/reporting/components/reporting-dashboard/display-columns/build-display-columns.test.js +74 -0
  53. package/core/modules/reporting/components/reporting-dashboard/display-columns/display-cell-renderer.js +252 -0
  54. package/core/modules/reporting/components/reporting-dashboard/display-columns/display-cell-renderer.test.js +126 -0
  55. package/core/modules/reporting/components/reporting-dashboard/reporting-dashboard.js +326 -436
  56. package/core/modules/reporting/components/reporting-dashboard/reporting-dashboard.scss +7 -0
  57. package/core/modules/steps/action-buttons.js +33 -15
  58. package/core/modules/steps/action-buttons.scss +55 -9
  59. package/core/modules/steps/chat-assistant.js +141 -0
  60. package/core/modules/steps/openai-realtime.js +275 -0
  61. package/core/modules/steps/readme.md +167 -0
  62. package/core/modules/steps/steps.js +1078 -57
  63. package/core/modules/steps/steps.scss +539 -90
  64. package/core/modules/steps/timeline.js +21 -19
  65. package/core/modules/steps/voice-navigation.js +709 -0
  66. package/package.json +2 -1
@@ -21,7 +21,7 @@ import ExtraInfo from './extra-info';
21
21
 
22
22
  const { TabPane } = Tabs;
23
23
 
24
- export default function ExtraInfoDetail({ modeValue, icon, title, tabPosition = 'left', showDrawerData, dbPtr, callback, ...record }) {
24
+ export default function ExtraInfoDetail({ modeValue, icon, title, tabPosition = 'left', showDrawerData, dbPtr, callback, drawerWidth = '35%', ...record }) {
25
25
  // State to control drawer
26
26
  const [open, setOpen] = useState(false);
27
27
 
@@ -121,7 +121,7 @@ export default function ExtraInfoDetail({ modeValue, icon, title, tabPosition =
121
121
  {/* */}
122
122
 
123
123
  {/* */}
124
- <Drawer width={'35%'} title={title} onClose={onClose} open={open}>
124
+ <Drawer width={drawerWidth} title={title} onClose={onClose} open={open}>
125
125
  <div className="main-drawer-content">
126
126
  <div className="drawer-container">
127
127
  <div className="drawer-click">
@@ -1,7 +1,3 @@
1
-
2
-
3
-
4
-
5
1
  import LandingAPI from './landing-api/landing-api';
6
2
 
7
3
  import ExtraInfoDetail from './extra-info/extra-info-details';
@@ -11,11 +7,6 @@ import RootApplicationAPI from './root-application-api/root-application-api';
11
7
  import { HomePageAPI } from '../modules';
12
8
 
13
9
  import { ExternalWindow } from './external-window/external-window';
10
+ import LicenseAlert from './license-management/license-alert';
14
11
 
15
- export {
16
- LandingAPI,
17
- RootApplicationAPI,
18
- ExtraInfoDetail,
19
- HomePageAPI,
20
- ExternalWindow
21
- }
12
+ export { LandingAPI, RootApplicationAPI, ExtraInfoDetail, HomePageAPI, ExternalWindow, LicenseAlert };
@@ -1,4 +1,4 @@
1
- import React, { useState, useEffect, useContext } from 'react';
1
+ import React, { useState, useEffect, useContext, useRef } from 'react';
2
2
 
3
3
  import { Route, Switch } from 'react-router-dom';
4
4
 
@@ -17,6 +17,27 @@ import ReportingDashboard from '../../modules/reporting/components/reporting-das
17
17
  import PropTypes from 'prop-types';
18
18
 
19
19
  import { MenusAPI, CoreScripts } from '../../models';
20
+ import LicenseAlert from '../license-management/license-alert';
21
+
22
+ const motivatingMessages = [
23
+ 'Setting things up for a great start...',
24
+ 'Good things are loading. Stay with us.',
25
+ 'Almost there. Preparing your workspace.',
26
+ 'You are one moment away from your dashboard.',
27
+ 'Getting everything ready for you.',
28
+ 'Great care takes a second. Loading now.',
29
+ ];
30
+
31
+ function getRandomMessage(previousMessage = '') {
32
+ const options = motivatingMessages.filter((message) => message !== previousMessage);
33
+
34
+ if (!options.length) {
35
+ return motivatingMessages[0];
36
+ }
37
+
38
+ const randomIndex = Math.floor(Math.random() * options.length);
39
+ return options[randomIndex];
40
+ }
20
41
 
21
42
  /**
22
43
  * Landing API
@@ -24,7 +45,7 @@ import { MenusAPI, CoreScripts } from '../../models';
24
45
  * @param {*} param0
25
46
  * @returns
26
47
  */
27
- export default function LandingApi({ history, CustomComponents, CustomModels, appSettings, ...props }) {
48
+ export default function LandingApi({ history, CustomComponents, CustomModels, appSettings, transitionPending = false, onHomeReady, ...props }) {
28
49
  const [loader, setLoader] = useState(false);
29
50
 
30
51
  // const [modules, setModules] = useState([]);
@@ -34,12 +55,20 @@ export default function LandingApi({ history, CustomComponents, CustomModels, ap
34
55
  const { dispatch, user = {} } = useContext(GlobalContext);
35
56
 
36
57
  const [allModules, setAllModules] = useState();
58
+ const homeReadyNotifiedRef = useRef(false);
59
+ const messageIntervalRef = useRef(null);
37
60
 
38
61
  const [meta, setMeta] = useState({});
62
+ const [loadingMessage, setLoadingMessage] = useState('');
63
+ const [licenseData, setLicenseData] = useState(null);
64
+
65
+ const [licAlert, setLicAlert] = useState(false);
66
+ // License data state
39
67
 
40
68
  // const [reports, setReports] = useState([]);
41
69
 
42
70
  var config = {};
71
+ //fetch license summary
43
72
 
44
73
  // Variable decides the control of homepage
45
74
  // #TODO This is a temporary fix - Homemage
@@ -49,7 +78,20 @@ export default function LandingApi({ history, CustomComponents, CustomModels, ap
49
78
  if (process.env.REACT_APP_DISABLEHOMEPAGE) {
50
79
  disableHomepage = JSON.parse(process.env.REACT_APP_DISABLEHOMEPAGE);
51
80
  }
52
-
81
+ const fetchSummary = async () => {
82
+ try {
83
+ const res = await MenusAPI.getSummary();
84
+ if (res?.data) {
85
+ setLicenseData(res?.data);
86
+ setLicAlert(true);
87
+ } else {
88
+ setLicenseData(null);
89
+ setLicAlert(false);
90
+ }
91
+ } catch (err) {
92
+ console.error(err);
93
+ }
94
+ };
53
95
  // useEffect(() => {
54
96
 
55
97
  // // Initialize the menus for the logged in user
@@ -70,14 +112,56 @@ export default function LandingApi({ history, CustomComponents, CustomModels, ap
70
112
  initializeUserMenus();
71
113
  }, []);
72
114
 
115
+ useEffect(() => {
116
+ if (!transitionPending) {
117
+ homeReadyNotifiedRef.current = false;
118
+ return;
119
+ }
120
+
121
+ if (!loader && allModules && !homeReadyNotifiedRef.current) {
122
+ homeReadyNotifiedRef.current = true;
123
+ if (typeof onHomeReady === 'function') {
124
+ onHomeReady();
125
+ }
126
+ }
127
+ }, [transitionPending, loader, allModules, onHomeReady]);
128
+
129
+ useEffect(() => {
130
+ if (!loader) {
131
+ setLoadingMessage('');
132
+
133
+ if (messageIntervalRef.current) {
134
+ clearInterval(messageIntervalRef.current);
135
+ messageIntervalRef.current = null;
136
+ }
137
+
138
+ return;
139
+ }
140
+
141
+ setLoadingMessage((previousMessage) => getRandomMessage(previousMessage));
142
+
143
+ messageIntervalRef.current = setInterval(() => {
144
+ setLoadingMessage((previousMessage) => getRandomMessage(previousMessage));
145
+ }, 2200);
146
+
147
+ return () => {
148
+ if (messageIntervalRef.current) {
149
+ clearInterval(messageIntervalRef.current);
150
+ messageIntervalRef.current = null;
151
+ }
152
+ };
153
+ }, [loader]);
154
+
73
155
  /**
74
156
  * Initialize the user menus
75
157
  */
76
158
  async function initializeUserMenus() {
77
159
  // need to find what implement, with a login who has the respective value ("wug_custreportids")
160
+
78
161
  const report = await loadScripts(user);
79
162
 
80
163
  await loadMenus(report);
164
+ // fetch license summary
81
165
  }
82
166
 
83
167
  // const keyMap = {
@@ -96,26 +180,21 @@ export default function LandingApi({ history, CustomComponents, CustomModels, ap
96
180
  * @param reports
97
181
  */
98
182
  async function loadMenus(reports) {
99
-
100
183
  setLoader(true);
101
184
 
102
185
  // setReports(report)
103
-
186
+ fetchSummary();
104
187
  const result = await MenusAPI.getMenus(user);
105
188
 
106
189
  // console.log(result);
107
190
 
108
191
  if (result && Array.isArray(result.result) && result.result.length) {
109
-
110
192
  // setModules(result.result);
111
-
112
193
  // result.result.map((ele) => {
113
194
  // let languageString = JSON.parse(ele.attributes)
114
195
  // console.log('language_string', languageString);
115
196
  // if (languageString && languageString.languages) {
116
-
117
197
  // const language = i18n.language;
118
-
119
198
  // i18n.addResourceBundle(language, 'translation', languageString.languages[i18n.language]);
120
199
  // }
121
200
  // })
@@ -126,7 +205,6 @@ export default function LandingApi({ history, CustomComponents, CustomModels, ap
126
205
  dispatch({ type: 'settings', payload: result.result.settings });
127
206
  }
128
207
 
129
-
130
208
  // Reports length
131
209
  if (reports.length) {
132
210
  reportMenus = [
@@ -161,7 +239,6 @@ export default function LandingApi({ history, CustomComponents, CustomModels, ap
161
239
  //If there is no roles assigned to the user
162
240
  setAllModules([...coreModules]);
163
241
  }
164
-
165
242
  } else {
166
243
  // for nura
167
244
  if (result && result.result.menus && reportMenus) {
@@ -170,14 +247,10 @@ export default function LandingApi({ history, CustomComponents, CustomModels, ap
170
247
  //If there is no roles assigned to the user
171
248
  setAllModules([...coreModules]);
172
249
  }
173
-
174
-
175
250
  }
176
251
  setLoader(false);
177
-
178
252
  }
179
253
 
180
-
181
254
  /**
182
255
  * Load the scripts
183
256
  *
@@ -240,11 +313,14 @@ export default function LandingApi({ history, CustomComponents, CustomModels, ap
240
313
  modules={allModules}
241
314
  user={user}
242
315
  history={history}
316
+ licenseData={licenseData}
317
+ licAlert={licAlert}
243
318
  >
244
319
  {loader ? (
245
320
  <Card className="skeleton-card">
246
321
  <div className="skeleton-wrapper">
247
322
  <Skeleton paragraph={{ rows: 4 }} />
323
+ <p className="motivating-text">{loadingMessage}</p>
248
324
  </div>
249
325
  </Card>
250
326
  ) : (
@@ -11,9 +11,31 @@
11
11
  }
12
12
 
13
13
  .skeleton-wrapper {
14
+ .motivating-text {
15
+ margin-top: 14px;
16
+ margin-bottom: 4px;
17
+ font-size: 14px;
18
+ line-height: 20px;
19
+ text-align: center;
20
+ color: #5e6d86;
21
+ font-weight: 500;
22
+ animation: skeletonTextFade 0.4s ease-in-out;
23
+ }
14
24
  }
15
25
 
16
26
  .wrapper-loader {
17
27
  margin: 20px;
18
28
  }
19
29
  }
30
+
31
+ @keyframes skeletonTextFade {
32
+ from {
33
+ opacity: 0;
34
+ transform: translateY(2px);
35
+ }
36
+
37
+ to {
38
+ opacity: 1;
39
+ transform: translateY(0);
40
+ }
41
+ }
@@ -0,0 +1,97 @@
1
+ import { Alert } from 'antd';
2
+ import React, { useState, useEffect } from 'react';
3
+
4
+ export default function LicenseAlert({ data }) {
5
+ // setting visibility of alert based on license status
6
+ const [visible, setVisible] = useState(true);
7
+ // resolve alert configuration based on license data
8
+ const alertConfig = resolveLicenseAlert(data);
9
+ // auto-hide alert after 10 seconds or when data changes
10
+ useEffect(() => {
11
+ if (alertConfig) {
12
+ setVisible(true);
13
+
14
+ const timer = setTimeout(() => {
15
+ setVisible(false);
16
+ }, 10000); // 10 seconds
17
+
18
+ return () => {
19
+ clearTimeout(timer);
20
+ };
21
+ }
22
+ }, [data]);
23
+ // if no alert configuration or not visible, render nothing
24
+ if (!alertConfig || !visible) return null;
25
+
26
+ return (
27
+ // render the alert with appropriate type, message, and description
28
+ <Alert
29
+ type={alertConfig.type}
30
+ message={alertConfig.message}
31
+ description={alertConfig.description}
32
+ showIcon
33
+ closable
34
+ onClose={() => setVisible(false)}
35
+ />
36
+ );
37
+ }
38
+ // function to determine alert configuration based on license data
39
+ function resolveLicenseAlert(data) {
40
+ if (!data) return null;
41
+ // destructure relevant fields from license data
42
+ const { status, expiresInDays, isExpiringSoon, gracePeriod } = data;
43
+
44
+ // ===== NOT INSTALLED =====
45
+ if (status === 'NOT_INSTALLED') {
46
+ return {
47
+ type: 'error',
48
+ message: 'License not found',
49
+ description: 'Please install a valid license to continue.',
50
+ };
51
+ }
52
+
53
+ // ===== GRACE PERIOD =====
54
+ if (gracePeriod) {
55
+ return {
56
+ type: 'warning',
57
+ message: 'Grace period mode',
58
+ description: 'License expired. Running in read-only mode.',
59
+ };
60
+ }
61
+
62
+ // ===== EXPIRING SOON =====
63
+ if (status === 'ACTIVE' && isExpiringSoon) {
64
+ let descriptionText = '';
65
+ // customize message based on how soon the license is expiring
66
+ if (expiresInDays === 1) {
67
+ descriptionText = 'Your license will expire today. Please renew immediately.';
68
+ } else {
69
+ descriptionText = `Your license will expire in ${expiresInDays} days. Please plan for renewal.`;
70
+ }
71
+
72
+ return {
73
+ type: 'warning',
74
+ message: 'License expiring soon',
75
+ description: descriptionText,
76
+ };
77
+ }
78
+
79
+ // ===== NOT INSTALLED =====
80
+ if (status === 'NOT_INSTALLED') {
81
+ return {
82
+ type: 'error',
83
+ message: 'License not found',
84
+ description: 'Please install a valid license to continue.',
85
+ };
86
+ }
87
+ // =====EXPIRED=====
88
+ if (status === 'EXPIRED') {
89
+ return {
90
+ type: 'error',
91
+ message: 'License expired',
92
+ description: 'Your license has expired. Please renew or install a new license.',
93
+ };
94
+ }
95
+
96
+ return null;
97
+ }
package/core/lib/Store.js CHANGED
@@ -50,7 +50,7 @@ const initialTheme = () => {
50
50
  // manage theme with env
51
51
  const isEnvThemeTrue = process.env.REACT_APP_THEME;
52
52
 
53
- console.log('REACT_APP_THEME:', isEnvThemeTrue);
53
+ // console.log('REACT_APP_THEME:', isEnvThemeTrue);
54
54
  const matchedTheme = themes.find((t) => t.name === isEnvThemeTrue);
55
55
 
56
56
  if (matchedTheme) return matchedTheme;
@@ -64,7 +64,7 @@ const initialTheme = () => {
64
64
  // Fallback to default
65
65
  return themes[0];
66
66
  } catch (e) {
67
- console.error('Error loading theme:', e);
67
+ // console.error('Error loading theme:', e);
68
68
  return themes[0];
69
69
  }
70
70
  };
@@ -94,7 +94,7 @@ export const GlobalProvider = ({ children, CustomModels,CustomComponents, appSet
94
94
 
95
95
  const [state, dispatch] = useReducer(AppReducer, initialState);
96
96
 
97
- console.log(state);
97
+ // console.log(state);
98
98
 
99
99
  const { isMobile } = useDeviceDetect();
100
100
 
@@ -1,18 +1,92 @@
1
1
  export const boxVariants = {
2
- entering: { x: -50, opacity: 0},
2
+ entering: { x: -24, opacity: 0, scale: 0.985 },
3
3
  entered: {
4
4
  x: 0,
5
5
  opacity: 1,
6
+ scale: 1,
6
7
  transition: {
7
8
  x: {
8
- duration: 0.5,
9
+ duration: 0.45,
9
10
  ease: [.62,.28,.23,.99]
10
11
  },
11
12
  opacity: {
12
- duration: 0.5,
13
+ duration: 0.35,
13
14
  ease: [.62,.28,.23,.99]
15
+ },
16
+ scale: {
17
+ duration: 0.45,
18
+ ease: [.22,1,.36,1]
14
19
  }
15
20
  },
16
21
 
17
22
  }
18
- }
23
+ };
24
+
25
+ export const headerShellVariants = {
26
+ hidden: {
27
+ y: -14,
28
+ opacity: 0,
29
+ scale: 0.995,
30
+ filter: 'blur(6px)',
31
+ },
32
+ visible: {
33
+ y: 0,
34
+ opacity: 1,
35
+ scale: 1,
36
+ filter: 'blur(0px)',
37
+ transition: {
38
+ duration: 0.45,
39
+ ease: [.22,1,.36,1],
40
+ when: 'beforeChildren',
41
+ staggerChildren: 0.045,
42
+ },
43
+ },
44
+ };
45
+
46
+ export const headerClusterVariants = {
47
+ hidden: { opacity: 0, x: -12 },
48
+ visible: {
49
+ opacity: 1,
50
+ x: 0,
51
+ transition: {
52
+ duration: 0.32,
53
+ ease: [.22,1,.36,1],
54
+ },
55
+ },
56
+ };
57
+
58
+ export const headerActionsVariants = {
59
+ hidden: {},
60
+ visible: {
61
+ transition: {
62
+ staggerChildren: 0.05,
63
+ delayChildren: 0.08,
64
+ },
65
+ },
66
+ };
67
+
68
+ export const headerActionItemVariants = {
69
+ hidden: { opacity: 0, y: -8, scale: 0.98 },
70
+ visible: {
71
+ opacity: 1,
72
+ y: 0,
73
+ scale: 1,
74
+ transition: {
75
+ duration: 0.28,
76
+ ease: [.22,1,.36,1],
77
+ },
78
+ },
79
+ };
80
+
81
+ export const contentRevealVariants = {
82
+ hidden: { opacity: 0, y: 10 },
83
+ visible: {
84
+ opacity: 1,
85
+ y: 0,
86
+ transition: {
87
+ duration: 0.35,
88
+ ease: [.22,1,.36,1],
89
+ delay: 0.08,
90
+ },
91
+ },
92
+ };