ui-soxo-bootstrap-core 2.6.48 → 2.6.50-dev.0

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.
@@ -7,8 +7,8 @@ import RootApplicationAPI from './root-application-api/root-application-api';
7
7
  import { HomePageAPI } from '../modules';
8
8
 
9
9
  import { ExternalWindow } from './external-window/external-window';
10
- // import LicenseAlert from './license-management/license-alert';
10
+ import LicenseAlert from './license-management/license-alert';
11
11
 
12
12
  export { LandingAPI, RootApplicationAPI, ExtraInfoDetail, HomePageAPI, ExternalWindow,
13
- // LicenseAlert
13
+ LicenseAlert
14
14
  };
@@ -58,28 +58,36 @@ export default function LandingApi({ history, CustomComponents, CustomModels, ap
58
58
 
59
59
  const [meta, setMeta] = useState({});
60
60
  const [loadingMessage, setLoadingMessage] = useState('');
61
- // const [licenseData, setLicenseData] = useState(null);
62
- // const [licAlert, setLicAlert] = useState(false);
61
+ const [licenseData, setLicenseData] = useState(null);
62
+ const [licAlert, setLicAlert] = useState(false);
63
63
 
64
64
  // const [reports, setReports] = useState([]);
65
65
 
66
66
  var config = {};
67
67
 
68
- // //fetch license summary
69
- // const fetchSummary = async () => {
70
- // try {
71
- // const res = await MenusAPI.getSummary();
72
- // if (res?.data) {
73
- // setLicenseData(res?.data);
74
- // setLicAlert(true);
75
- // } else {
76
- // setLicenseData(null);
77
- // setLicAlert(false);
78
- // }
79
- // } catch (err) {
80
- // console.error(err);
81
- // }
82
- // };
68
+ // Variable decides whether license-summary fetching/alerting runs at all
69
+ let disableLicense = false;
70
+
71
+ if (process.env.REACT_APP_DISABLE_LICENSE) {
72
+ disableLicense = JSON.parse(process.env.REACT_APP_DISABLE_LICENSE);
73
+ }
74
+
75
+ //fetch license summary
76
+ const fetchSummary = async () => {
77
+ if (disableLicense) return;
78
+ try {
79
+ const res = await MenusAPI.getSummary();
80
+ if (res?.data) {
81
+ setLicenseData(res?.data);
82
+ setLicAlert(true);
83
+ } else {
84
+ setLicenseData(null);
85
+ setLicAlert(false);
86
+ }
87
+ } catch (err) {
88
+ console.error(err);
89
+ }
90
+ };
83
91
 
84
92
  // Variable decides the control of homepage
85
93
  // #TODO This is a temporary fix - Homemage
@@ -285,7 +293,7 @@ export default function LandingApi({ history, CustomComponents, CustomModels, ap
285
293
 
286
294
  await loadMenus(report);
287
295
  // fetch license summary
288
- // fetchSummary();
296
+ fetchSummary();
289
297
  }
290
298
 
291
299
  // const keyMap = {
@@ -307,7 +315,7 @@ export default function LandingApi({ history, CustomComponents, CustomModels, ap
307
315
  setLoader(true);
308
316
 
309
317
  // setReports(report)
310
- // fetchSummary();
318
+ fetchSummary();
311
319
  const result = await MenusAPI.getMenus(user);
312
320
 
313
321
  // console.log(result);
@@ -437,8 +445,8 @@ export default function LandingApi({ history, CustomComponents, CustomModels, ap
437
445
  modules={allModules}
438
446
  user={user}
439
447
  history={history}
440
- // licenseData={licenseData}
441
- // licAlert={licAlert}
448
+ licenseData={licenseData}
449
+ licAlert={licAlert}
442
450
  >
443
451
  {loader ? (
444
452
  <Card className="skeleton-card">
@@ -1,97 +1,97 @@
1
- // import { Alert } from 'antd';
2
- // import React, { useState, useEffect } from 'react';
1
+ import { Alert } from 'antd';
2
+ import React, { useState, useEffect } from 'react';
3
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);
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
13
 
14
- // const timer = setTimeout(() => {
15
- // setVisible(false);
16
- // }, 10000); // 10 seconds
14
+ const timer = setTimeout(() => {
15
+ setVisible(false);
16
+ }, 10000); // 10 seconds
17
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;
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
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;
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
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
- // }
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
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
- // }
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
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 === 0) {
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
- // }
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 === 0) {
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
71
 
72
- // return {
73
- // type: 'warning',
74
- // message: 'License expiring soon',
75
- // description: descriptionText,
76
- // };
77
- // }
72
+ return {
73
+ type: 'warning',
74
+ message: 'License expiring soon',
75
+ description: descriptionText,
76
+ };
77
+ }
78
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
- // }
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
95
 
96
- // return null;
97
- // }
96
+ return null;
97
+ }
@@ -20,12 +20,12 @@ import LanguageSwitcher from '../language-switcher/language-switcher';
20
20
  import { useTranslation } from 'react-i18next';
21
21
  import SettingsUtil from '../../../utils/settings.utils';
22
22
  import SpotlightSearch from '../spotlight-search/spotlight-search.component';
23
- // import LicenseAlert from '../../../components/license-management/license-alert';
23
+ import LicenseAlert from '../../../components/license-management/license-alert';
24
24
 
25
25
  const { Title } = Typography;
26
26
  function GlobalHeaderContent({ loading, appSettings, children, isConnected, history, modules = [], sidemenu = [], reload, meta = {},
27
- // licAlert,
28
- // licenseData,
27
+ licAlert,
28
+ licenseData,
29
29
  ...props }) {
30
30
  let location = useLocation();
31
31
  // let location = {};
@@ -244,19 +244,19 @@ function GlobalHeaderContent({ loading, appSettings, children, isConnected, hist
244
244
 
245
245
 
246
246
 
247
- {/* {licAlert && licenseData && ( */}
248
- {/* // <div
249
- // style={{
250
- // top: 0,
251
- // marginTop: '3rem',
252
- // right: '2%',
253
- // position: 'absolute',
254
- // zIndex: 1008,
255
- // }}
256
- // >
257
- // <LicenseAlert data={licenseData} />
258
- // </div>
259
- )} */}
247
+ {licAlert && licenseData && (
248
+ <div
249
+ style={{
250
+ top: 0,
251
+ marginTop: '3rem',
252
+ right: '2%',
253
+ position: 'absolute',
254
+ zIndex: 1008,
255
+ }}
256
+ >
257
+ <LicenseAlert data={licenseData} />
258
+ </div>
259
+ )}
260
260
  </>
261
261
  );
262
262
  }
@@ -14,6 +14,10 @@ import FirebaseUtils from '../firebase.utils';
14
14
  import { Location } from '../location/location.utils';
15
15
  import { getRefreshToken, queueRequest, refreshAccessToken } from './auth.helper';
16
16
 
17
+ const isLicenseDisabled = process.env.REACT_APP_DISABLE_LICENSE
18
+ ? JSON.parse(process.env.REACT_APP_DISABLE_LICENSE)
19
+ : false;
20
+
17
21
  let headers = {
18
22
  // 'Accept': 'application/json',
19
23
  'Content-Type': 'application/json',
@@ -128,7 +132,7 @@ export async function ApiCall({ url, formBody, method, settings, ...props }) {
128
132
  const res = await fetch(baseUrl + url, payload);
129
133
  const refreshToken = getRefreshToken();
130
134
 
131
- if (res.status === 403) {
135
+ if (res.status === 403 && !isLicenseDisabled) {
132
136
  message.warn('Your license has expired. Please contact support.');
133
137
  }
134
138
 
@@ -90,41 +90,6 @@ export function getRedirectLink(entry = {}, record = {}, CustomComponents = {})
90
90
  return redirectLink;
91
91
  }
92
92
 
93
- /**
94
- * Resolves the PDF/file location for file-based action entries.
95
- *
96
- * Supports either:
97
- * - `entry.file_location` as a direct URL/path
98
- * - `entry.file_location` as a record field name
99
- *
100
- * @param {DisplayColumnEntry} entry
101
- * @param {DisplayRecord} record
102
- * @returns {string}
103
- */
104
- export function getFileLocation(entry = {}, record = {}) {
105
- if (entry.file_location && typeof entry.file_location === 'string' && record[entry.file_location]) {
106
- return record[entry.file_location];
107
- }
108
-
109
- return record.file_location || entry.file_location || '';
110
- }
111
-
112
- /**
113
- * Resolves a value from the row when a config field points to a record key,
114
- * otherwise returns the provided literal value.
115
- *
116
- * @param {*} value
117
- * @param {DisplayRecord} record
118
- * @returns {*}
119
- */
120
- function resolveRecordValue(value, record = {}) {
121
- if (typeof value === 'string' && Object.prototype.hasOwnProperty.call(record, value)) {
122
- return record[value];
123
- }
124
-
125
- return value;
126
- }
127
-
128
93
  /**
129
94
  * Resolves action label text with backward-compatible precedence.
130
95
  *
@@ -219,26 +184,17 @@ function renderCustomComponent({ entry, record, CustomComponents, refresh }) {
219
184
  */
220
185
  function FileActionLink({ entry, record, CustomComponents }) {
221
186
  const [isPdfVisible, setIsPdfVisible] = useState(false);
222
- const fileUrl = getFileLocation(entry, record);
223
187
  const actionLabel = getActionLabel(entry, record);
224
188
  const FileLoaderComponent = CustomComponents?.FileLoader;
225
189
 
226
- if (!fileUrl) {
227
- return null;
228
- }
190
+
229
191
 
230
192
  const fileLoaderProps = {
231
- url: fileUrl,
232
- type: resolveRecordValue(entry.file_type, record) || 'pdf',
233
- defaultScale: resolveRecordValue(entry.default_scale, record),
234
- viewerType: resolveRecordValue(entry.viewer_type, record),
193
+ url: record?.file_location + record?.file_name,
235
194
  config: {
236
- requireLinuxPath: resolveRecordValue(entry.require_linux_path, record),
237
- replaceBranch: resolveRecordValue(entry.replace_branch, record),
238
195
  ...(entry.file_loader_config || {}),
239
196
  },
240
- entry,
241
- record,
197
+ type:record?.Native_filetype,
242
198
  };
243
199
 
244
200
  return (
@@ -3,7 +3,6 @@ import {
3
3
  isLegacyActionEntry,
4
4
  isActionTypeEntry,
5
5
  getRedirectLink,
6
- getFileLocation,
7
6
  getActionLabel,
8
7
  renderDisplayCell,
9
8
  } from './display-cell-renderer';
@@ -29,13 +28,6 @@ describe('display-cell-renderer', () => {
29
28
  expect(link).toBe('/bill/10/visit/OP100');
30
29
  });
31
30
 
32
- test('resolves file location from direct config value or record field', () => {
33
- expect(getFileLocation({ file_location: 'https://example.com/report.pdf' }, {})).toBe('https://example.com/report.pdf');
34
- expect(getFileLocation({ file_location: 'document_url' }, { document_url: 'https://example.com/record.pdf' })).toBe(
35
- 'https://example.com/record.pdf',
36
- );
37
- });
38
-
39
31
  test('keeps legacy action label behavior unchanged', () => {
40
32
  const entry = {
41
33
  field: 'action',
@@ -111,24 +103,15 @@ describe('display-cell-renderer', () => {
111
103
  type: 'action',
112
104
  field: 'action_text',
113
105
  redirect_link_type: 'file',
114
- file_location: 'document_path',
115
- file_type: 'document_type',
116
- default_scale: 'zoom_level',
117
- viewer_type: 'inline_viewer',
118
- require_linux_path: 'needs_linux_path',
119
- replace_branch: 'should_replace_branch',
120
106
  file_loader_config: {
121
107
  sample: true,
122
108
  },
123
109
  },
124
110
  record: {
125
111
  action_text: 'Preview',
126
- document_path: '\\\\server\\reports\\doc.pdf',
127
- document_type: 'pdf',
128
- zoom_level: 1.25,
129
- inline_viewer: true,
130
- needs_linux_path: true,
131
- should_replace_branch: false,
112
+ file_location: '\\\\server\\reports\\',
113
+ file_name: 'doc.pdf',
114
+ Native_filetype: 'pdf',
132
115
  },
133
116
  refresh: jest.fn(),
134
117
  CustomComponents: { FileUpload },
@@ -140,14 +123,11 @@ describe('display-cell-renderer', () => {
140
123
  expect(modalContent.type).toBe(FileUpload);
141
124
  expect(modalContent.props.url).toBe('\\\\server\\reports\\doc.pdf');
142
125
  expect(modalContent.props.type).toBe('pdf');
143
- expect(modalContent.props.defaultScale).toBe(1.25);
144
- expect(modalContent.props.viewerType).toBe(true);
145
126
  expect(modalContent.props.config).toEqual({
146
127
  requireLinuxPath: true,
147
128
  replaceBranch: false,
148
129
  sample: true,
149
130
  });
150
- expect(modalContent.props.record.document_path).toBe('\\\\server\\reports\\doc.pdf');
151
131
  });
152
132
 
153
133
  test('renders styled tag/span/icon/text for non-action path', () => {
@@ -474,7 +474,7 @@ export default function ReportingTable({
474
474
  dataSource={filtered}
475
475
  columns={cols}
476
476
  sticky
477
- pagination={false}
477
+ pagination={true}
478
478
  summary={(pageData) => {
479
479
  const summaryCols = columns.filter((col) => col.enable_summary);
480
480
  if (!summaryCols.length) return null;
@@ -505,14 +505,14 @@ export default function ReportingTable({
505
505
  />
506
506
  )}
507
507
  <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: 8 }}>
508
- <Pagination
508
+ {/* <Pagination
509
509
  showSizeChanger
510
510
  current={pagination?.current}
511
511
  pageSize={pagination?.pageSize}
512
512
  total={pagination?.total}
513
513
  pageSizeOptions={[20, 30, 50, 100]}
514
- onChange={(page, pageSize) => handlePaginationInternal({ current: page, pageSize })}
515
- />
514
+ onChange={(page, pageSize) => handlePaginationInternal({ current: page, pageSize })} */}
515
+ {/* /> */}
516
516
  </div>
517
517
  <p className="size-hint">{patients ? patients.length : 0} records.</p>
518
518
  </Card>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ui-soxo-bootstrap-core",
3
- "version": "2.6.48",
3
+ "version": "2.6.50-dev.0",
4
4
  "description": "All the Core Components for you to start",
5
5
  "keywords": [
6
6
  "all in one"