@digihmis/esm-administration-app 1.0.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.
- package/README.md +4 -0
- package/dist/101.js +1 -0
- package/dist/101.js.map +1 -0
- package/dist/117.js +1 -0
- package/dist/117.js.map +1 -0
- package/dist/132.js +1 -0
- package/dist/132.js.map +1 -0
- package/dist/15.js +1 -0
- package/dist/15.js.map +1 -0
- package/dist/152.js +1 -0
- package/dist/152.js.map +1 -0
- package/dist/153.js +1 -0
- package/dist/153.js.map +1 -0
- package/dist/190.js +1 -0
- package/dist/190.js.map +1 -0
- package/dist/209.js +1 -0
- package/dist/209.js.map +1 -0
- package/dist/266.js +1 -0
- package/dist/266.js.map +1 -0
- package/dist/317.js +1 -0
- package/dist/317.js.map +1 -0
- package/dist/349.js +1 -0
- package/dist/349.js.map +1 -0
- package/dist/371.js +1 -0
- package/dist/371.js.map +1 -0
- package/dist/378.js +1 -0
- package/dist/378.js.map +1 -0
- package/dist/394.js +1 -0
- package/dist/394.js.map +1 -0
- package/dist/442.js +1 -0
- package/dist/442.js.map +1 -0
- package/dist/45.js +1 -0
- package/dist/45.js.map +1 -0
- package/dist/454.js +1 -0
- package/dist/454.js.map +1 -0
- package/dist/466.js +1 -0
- package/dist/466.js.map +1 -0
- package/dist/482.js +1 -0
- package/dist/482.js.map +1 -0
- package/dist/501.js +1 -0
- package/dist/501.js.map +1 -0
- package/dist/508.js +1 -0
- package/dist/508.js.map +1 -0
- package/dist/578.js +1 -0
- package/dist/578.js.map +1 -0
- package/dist/598.js +1 -0
- package/dist/598.js.map +1 -0
- package/dist/606.js +1 -0
- package/dist/606.js.map +1 -0
- package/dist/61.js +1 -0
- package/dist/61.js.map +1 -0
- package/dist/640.js +1 -0
- package/dist/640.js.map +1 -0
- package/dist/685.js +1 -0
- package/dist/685.js.map +1 -0
- package/dist/689.js +1 -0
- package/dist/689.js.map +1 -0
- package/dist/709.js +1 -0
- package/dist/709.js.map +1 -0
- package/dist/712.js +1 -0
- package/dist/712.js.map +1 -0
- package/dist/720.js +1 -0
- package/dist/720.js.map +1 -0
- package/dist/737.js +12 -0
- package/dist/737.js.map +1 -0
- package/dist/742.js +1 -0
- package/dist/742.js.map +1 -0
- package/dist/747.js +1 -0
- package/dist/747.js.map +1 -0
- package/dist/771.js +1 -0
- package/dist/771.js.map +1 -0
- package/dist/806.js +1 -0
- package/dist/806.js.map +1 -0
- package/dist/912.js +1 -0
- package/dist/912.js.map +1 -0
- package/dist/913.js +1 -0
- package/dist/913.js.map +1 -0
- package/dist/916.js +15 -0
- package/dist/916.js.map +1 -0
- package/dist/940.js +1 -0
- package/dist/940.js.map +1 -0
- package/dist/digihmis-esm-administration-app.js +6 -0
- package/dist/digihmis-esm-administration-app.js.buildmanifest.json +1100 -0
- package/dist/digihmis-esm-administration-app.js.map +1 -0
- package/dist/main.js +17 -0
- package/dist/main.js.map +1 -0
- package/dist/routes.json +1 -0
- package/increment-version.js +17 -0
- package/jest.config.js +26 -0
- package/package.json +51 -0
- package/release-version.js +16 -0
- package/rspack.config.js +1 -0
- package/src/bed-management/bed-management.component.tsx +19 -0
- package/src/bed-management/bed-management.scss +0 -0
- package/src/billing-management/billing-charge-items/billing-charge-items-modal/billing-charge-items.modal.tsx +79 -0
- package/src/billing-management/billing-charge-items/billing-charge-items-modal/billing-charge-items.resource.ts +11 -0
- package/src/billing-management/billing-charge-items/billing-charge-items-workspace/billing-charge-item.workspace.tsx +212 -0
- package/src/billing-management/billing-charge-items/billing-charge-items-workspace/billing-charge-items.resource.ts +51 -0
- package/src/billing-management/billing-charge-items/billing-charge-items-workspace/billing-charge-service.workspace.tsx +296 -0
- package/src/billing-management/billing-charge-items/billing-charge-items-workspace/components/concept-search.component.tsx +67 -0
- package/src/billing-management/billing-charge-items/billing-charge-items-workspace/components/price.component.tsx +81 -0
- package/src/billing-management/billing-charge-items/billing-charge-items-workspace/components/stock-search.component.tsx +107 -0
- package/src/billing-management/billing-charge-items/billing-charge-items-workspace/global/billing-charge-commodity.scss +61 -0
- package/src/billing-management/billing-charge-items/billing-charge-items-workspace/global/billing-charge-items.scss +59 -0
- package/src/billing-management/billing-charge-items/billing-charge-items-workspace/schemas/form-schemas.ts +33 -0
- package/src/billing-management/billing-charge-items/billing-charge-items.component.tsx +222 -0
- package/src/billing-management/billing-charge-items/billing-charge-items.resource.ts +20 -0
- package/src/billing-management/billing-charge-items/billing-charge-items.scss +84 -0
- package/src/billing-management/billing-charge-items/type/index.ts +88 -0
- package/src/billing-management/billing-charge-items/utils/index.ts +96 -0
- package/src/billing-management/billing-management.component.tsx +21 -0
- package/src/billing-management/billing-management.scss +0 -0
- package/src/billing-management/billing-payment-modes/billing-payment-modes-modal/billing-delete-payment-modes.modal.scss +28 -0
- package/src/billing-management/billing-payment-modes/billing-payment-modes-modal/billing-delete-payment-modes.modal.tsx +67 -0
- package/src/billing-management/billing-payment-modes/billing-payment-modes-modal/delete-payment-mode.test.tsx +56 -0
- package/src/billing-management/billing-payment-modes/billing-payment-modes-workspace/billing-payment-modes-form-schema.ts +52 -0
- package/src/billing-management/billing-payment-modes/billing-payment-modes-workspace/billing-payment-modes.resource.ts +35 -0
- package/src/billing-management/billing-payment-modes/billing-payment-modes-workspace/billing-payment-modes.workspace.scss +33 -0
- package/src/billing-management/billing-payment-modes/billing-payment-modes-workspace/billing-payment-modes.workspace.test.tsx +239 -0
- package/src/billing-management/billing-payment-modes/billing-payment-modes-workspace/billing-payment-modes.workspace.tsx +218 -0
- package/src/billing-management/billing-payment-modes/billing-payment-modes-workspace/payment-attributes/payment-mode-attributes.component.tsx +156 -0
- package/src/billing-management/billing-payment-modes/billing-payment-modes-workspace/payment-attributes/payment-mode-attributes.scss +10 -0
- package/src/billing-management/billing-payment-modes/billing-payment-modes.component.tsx +243 -0
- package/src/billing-management/billing-payment-modes/billing-payment-modes.resource.ts +23 -0
- package/src/billing-management/billing-payment-modes/billing-payment-modes.scss +140 -0
- package/src/billing-management/billing-payment-modes/type/index.ts +42 -0
- package/src/billing-management/billing-payment-points/billing-payment-point-modal/billing-delete-payment-modes.modal.scss +28 -0
- package/src/billing-management/billing-payment-points/billing-payment-point-modal/billing-delete-payment-point.modal.tsx +72 -0
- package/src/billing-management/billing-payment-points/billing-payment-point-modal/delete-payment-point.test.tsx +56 -0
- package/src/billing-management/billing-payment-points/billing-payment-point.component.tsx +202 -0
- package/src/billing-management/billing-payment-points/billing-payment-point.resource.ts +16 -0
- package/src/billing-management/billing-payment-points/billing-payment-point.scss +0 -0
- package/src/billing-management/billing-payment-points/billing-payment-points-workspace/billing-payment-point.resource.ts +39 -0
- package/src/billing-management/billing-payment-points/billing-payment-points-workspace/billing-payment-point.workspace.scss +33 -0
- package/src/billing-management/billing-payment-points/billing-payment-points-workspace/billing-payment-points.workspace.tsx +194 -0
- package/src/billing-management/billing-payment-points/type/index.ts +35 -0
- package/src/billing-management/billing-tabs/billing-tabs.component.scss +15 -0
- package/src/billing-management/billing-tabs/billing-tabs.component.tsx +36 -0
- package/src/components/custom-icon-wrapper/custom-icon-wrapper.component.tsx +17 -0
- package/src/components/custom-page-header/custom-page-header.component.tsx +38 -0
- package/src/components/custom-page-header/custom-page-header.scss +76 -0
- package/src/config-schema.ts +142 -0
- package/src/constant/index.ts +1 -0
- package/src/dashboard.meta.ts +47 -0
- package/src/declarations.d.ts +6 -0
- package/src/form-builder/form-builder.component.tsx +19 -0
- package/src/form-builder/form-builder.scss +0 -0
- package/src/hooks/useConcept.ts +13 -0
- package/src/hooks/useQueues.ts +22 -0
- package/src/hooks/useSystemSetting.ts +18 -0
- package/src/index.ts +133 -0
- package/src/left-panel/left-panel.component.tsx +49 -0
- package/src/left-panel/left-panel.scss +13 -0
- package/src/location-management/components/auto-suggest/autosuggest.component.tsx +149 -0
- package/src/location-management/components/auto-suggest/autosuggest.scss +61 -0
- package/src/location-management/components/auto-suggest/location-autosuggest.component.tsx +97 -0
- package/src/location-management/components/auto-suggest/location-autosuggest.scss +48 -0
- package/src/location-management/components/custom-results-tile/results-tile.component.tsx +43 -0
- package/src/location-management/components/custom-results-tile/results-tile.scss +86 -0
- package/src/location-management/forms/add-location/add-location.workspace.scss +71 -0
- package/src/location-management/forms/add-location/add-location.workspace.tsx +199 -0
- package/src/location-management/forms/search-location/search-location.workspace.scss +71 -0
- package/src/location-management/forms/search-location/search-location.workspace.tsx +214 -0
- package/src/location-management/helpers/index.ts +33 -0
- package/src/location-management/hooks/UseFacilityLocations.ts +12 -0
- package/src/location-management/hooks/useLocation.ts +18 -0
- package/src/location-management/hooks/useLocationTags.ts +15 -0
- package/src/location-management/location-management-dashboard.component.tsx +21 -0
- package/src/location-management/location-management-dashboard.scss +3 -0
- package/src/location-management/tables/locations-table.component.tsx +242 -0
- package/src/location-management/tables/locations-table.resource.ts +26 -0
- package/src/location-management/tables/locations-table.scss +114 -0
- package/src/location-management/types/index.ts +120 -0
- package/src/queue-management/queue-management-dashboard.component.tsx +23 -0
- package/src/queue-management/queue-management-dashboard.scss +8 -0
- package/src/queue-management/queue-management-table/queue-management-table.component.tsx +296 -0
- package/src/queue-management/queue-management-table/queue-management-table.scss +78 -0
- package/src/queue-management/queue-management-table/queue-management.resource.ts +39 -0
- package/src/queue-management/queue-management-workspace/queue-room/queue-room-form.scss +56 -0
- package/src/queue-management/queue-management-workspace/queue-room/queue-room-form.test.tsx +82 -0
- package/src/queue-management/queue-management-workspace/queue-room/queue-room-form.workspace.tsx +169 -0
- package/src/queue-management/queue-management-workspace/queue-room/queue-room.resource.ts +20 -0
- package/src/queue-management/queue-management-workspace/queue-service/queue-service-form.scss +61 -0
- package/src/queue-management/queue-management-workspace/queue-service/queue-service-form.test.tsx +127 -0
- package/src/queue-management/queue-management-workspace/queue-service/queue-service-form.workspace.tsx +178 -0
- package/src/queue-management/queue-management-workspace/queue-service/queue-service.resource.ts +55 -0
- package/src/queue-management/queue-types/index.ts +33 -0
- package/src/routes.json +157 -0
- package/src/setup-tests.ts +1 -0
- package/src/system-info/system-info.component.tsx +338 -0
- package/src/system-info/system-info.resource.ts +40 -0
- package/src/system-info/system-info.scss +622 -0
- package/src/type/index.ts +6 -0
- package/translations/am.json +111 -0
- package/translations/ar.json +115 -0
- package/translations/en.json +111 -0
- package/translations/es.json +112 -0
- package/translations/fr.json +112 -0
- package/translations/he.json +112 -0
- package/translations/km.json +110 -0
- package/translations/pt.json +112 -0
- package/translations/sw.json +111 -0
- package/translations/vi.json +110 -0
- package/translations/zh.json +110 -0
- package/tsconfig.json +5 -0
- package/version.js +27 -0
package/src/routes.json
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.openmrs.org/routes.schema.json",
|
|
3
|
+
"backendDependencies": {
|
|
4
|
+
"fhir2": ">=1.2",
|
|
5
|
+
"webservices.rest": "^2.24.0"
|
|
6
|
+
},
|
|
7
|
+
"extensions": [
|
|
8
|
+
{
|
|
9
|
+
"name": "system-info-management-dashboard-link",
|
|
10
|
+
"slot": "administration-dashboard-slot",
|
|
11
|
+
"component": "systemInfoLeftPanelLink",
|
|
12
|
+
"meta": {
|
|
13
|
+
"name": "system-info-management",
|
|
14
|
+
"slot": "system-info-management-homepage-dashboard-slot",
|
|
15
|
+
"title": "System Info"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"name": "queue-management-dashboard-link",
|
|
20
|
+
"slot": "administration-dashboard-slot",
|
|
21
|
+
"component": "queueLeftPanelLink",
|
|
22
|
+
"meta": {
|
|
23
|
+
"name": "queue-management",
|
|
24
|
+
"slot": "queue-management-homepage-dashboard-slot",
|
|
25
|
+
"title": "Queue Management"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"name": "location-management-dashboard-link",
|
|
30
|
+
"slot": "administration-dashboard-slot",
|
|
31
|
+
"component": "locationLeftPanelLink",
|
|
32
|
+
"meta": {
|
|
33
|
+
"name": "location-management",
|
|
34
|
+
"slot": "location-management-homepage-dashboard-slot",
|
|
35
|
+
"title": "Location Management"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"name": "bed-management-dashboard-link",
|
|
40
|
+
"slot": "administration-dashboard-slot",
|
|
41
|
+
"component": "bedLeftPanelLink",
|
|
42
|
+
"meta": {
|
|
43
|
+
"name": "bed-management",
|
|
44
|
+
"slot": "bed-management-homepage-dashboard-slot",
|
|
45
|
+
"title": "Bed Management"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"name": "form-builder-dashboard-link",
|
|
50
|
+
"slot": "administration-dashboard-slot",
|
|
51
|
+
"component": "formBuilderLeftPanelLink",
|
|
52
|
+
"meta": {
|
|
53
|
+
"name": "form-builder",
|
|
54
|
+
"slot": "form-builder-homepage-dashboard-slot",
|
|
55
|
+
"title": "Form Builder"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "billing-management-dashboard-link",
|
|
60
|
+
"slot": "administration-dashboard-slot",
|
|
61
|
+
"component": "billingLeftPanelLink",
|
|
62
|
+
"meta": {
|
|
63
|
+
"name": "billing-management",
|
|
64
|
+
"slot": "billing-management-homepage-dashboard-slot",
|
|
65
|
+
"title": "Billing Management"
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"name": "queue-management-dashboard-content",
|
|
70
|
+
"slot": "queue-management-homepage-dashboard-slot",
|
|
71
|
+
"component": "queueManagementDashboard"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"name": "location-management-dashboard-content",
|
|
75
|
+
"slot": "location-management-homepage-dashboard-slot",
|
|
76
|
+
"component": "locationManagementDashboard"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"name": "bed-management-dashboard-content",
|
|
80
|
+
"slot": "bed-management-homepage-dashboard-slot",
|
|
81
|
+
"component": "bedManagementDashboard"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"name": "form-builder-dashboard-content",
|
|
85
|
+
"slot": "form-builder-homepage-dashboard-slot",
|
|
86
|
+
"component": "formBuilderDashboard"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"name": "billing-management-dashboard-content",
|
|
90
|
+
"slot": "billing-management-homepage-dashboard-slot",
|
|
91
|
+
"component": "billingManagementDashboard"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"name": "system-info-management-dashboard-content",
|
|
95
|
+
"slot": "system-info-management-homepage-dashboard-slot",
|
|
96
|
+
"component": "systemInfoDashboard"
|
|
97
|
+
}
|
|
98
|
+
],
|
|
99
|
+
"workspaces": [
|
|
100
|
+
{
|
|
101
|
+
"name": "service-queues-service-form",
|
|
102
|
+
"title": "addNewQueueService",
|
|
103
|
+
"component": "addNewQueueServiceWorkspace",
|
|
104
|
+
"type": "service-queues"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"name": "service-queues-room-workspace",
|
|
108
|
+
"title": "addNewQueueServiceRoom",
|
|
109
|
+
"component": "addNewQueueServiceRoomWorkspace",
|
|
110
|
+
"type": "service-queues"
|
|
111
|
+
},{
|
|
112
|
+
"name": "add-location-workspace",
|
|
113
|
+
"title": "addNewLocationWorkspace",
|
|
114
|
+
"component": "addNewLocationWorkspace",
|
|
115
|
+
"type": "location-management"
|
|
116
|
+
},{
|
|
117
|
+
"name": "search-location-workspace",
|
|
118
|
+
"title": "searchLocationWorkspace",
|
|
119
|
+
"component": "searchLocationWorkspace",
|
|
120
|
+
"type": "location-management"
|
|
121
|
+
},{
|
|
122
|
+
"name": "payment-mode-workspace",
|
|
123
|
+
"title": "paymentModeWorkspace",
|
|
124
|
+
"component": "paymentModeWorkspace",
|
|
125
|
+
"type": "billing-management"
|
|
126
|
+
},{
|
|
127
|
+
"name": "payment-point-workspace",
|
|
128
|
+
"title": "paymentPointWorkspace",
|
|
129
|
+
"component": "paymentPointWorkspace",
|
|
130
|
+
"type": "billing-management"
|
|
131
|
+
},{
|
|
132
|
+
"name": "billing-charge-service-workspace",
|
|
133
|
+
"title": "addServiceItem",
|
|
134
|
+
"component": "billableServiceForm",
|
|
135
|
+
"type": "billing-management"
|
|
136
|
+
},{
|
|
137
|
+
"name": "billing-charge-item-workspace",
|
|
138
|
+
"title": "addCommodityItem",
|
|
139
|
+
"component": "commodityForm",
|
|
140
|
+
"type": "billing-management"
|
|
141
|
+
}
|
|
142
|
+
],
|
|
143
|
+
"modals": [
|
|
144
|
+
{
|
|
145
|
+
"name": "delete-payment-mode-modal",
|
|
146
|
+
"component": "deletePaymentModeModal"
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"name": "delete-payment-point-modal",
|
|
150
|
+
"component": "deletePaymentPointModal"
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"name": "delete-billable-service-modal",
|
|
154
|
+
"component": "deleteBillableService"
|
|
155
|
+
}
|
|
156
|
+
]
|
|
157
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import '@testing-library/jest-dom/extend-expect';
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import React, { useState, useEffect, useCallback } from 'react';
|
|
2
|
+
import { formatDatetime } from '@openmrs/esm-framework';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import styles from './system-info.scss';
|
|
5
|
+
import { useFrontendModules, useModules } from './system-info.resource';
|
|
6
|
+
import {
|
|
7
|
+
ChevronDown,
|
|
8
|
+
ChevronUp,
|
|
9
|
+
Package,
|
|
10
|
+
Search,
|
|
11
|
+
CheckmarkFilled,
|
|
12
|
+
WarningAlt,
|
|
13
|
+
ArrowUp,
|
|
14
|
+
Renew,
|
|
15
|
+
} from '@carbon/react/icons';
|
|
16
|
+
import { IconButton, InlineLoading, SkeletonText } from '@carbon/react';
|
|
17
|
+
const packageInfo = require('../../release-version.js');
|
|
18
|
+
|
|
19
|
+
const compareVersions = (v1: string, v2: string): number => {
|
|
20
|
+
const parts1 = v1.replace(/^v/, '').split('.').map(Number);
|
|
21
|
+
const parts2 = v2.replace(/^v/, '').split('.').map(Number);
|
|
22
|
+
|
|
23
|
+
for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
|
|
24
|
+
const part1 = parts1[i] || 0;
|
|
25
|
+
const part2 = parts2[i] || 0;
|
|
26
|
+
|
|
27
|
+
if (part1 > part2) {
|
|
28
|
+
return 1;
|
|
29
|
+
}
|
|
30
|
+
if (part1 < part2) {
|
|
31
|
+
return -1;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return 0;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const SystemInfoDashboard: React.FC = () => {
|
|
38
|
+
const { t } = useTranslation();
|
|
39
|
+
const { modules, isLoading } = useModules();
|
|
40
|
+
const kenyaEMR = modules.find(({ uuid }) => uuid === 'kenyaemr');
|
|
41
|
+
const { VERSION } = packageInfo;
|
|
42
|
+
const installedModules = useFrontendModules();
|
|
43
|
+
|
|
44
|
+
const [showModules, setShowModules] = useState(true);
|
|
45
|
+
const [searchTerm, setSearchTerm] = useState('');
|
|
46
|
+
const [moduleVersions, setModuleVersions] = useState<Record<string, any>>({});
|
|
47
|
+
const [isCheckingVersions, setIsCheckingVersions] = useState(false);
|
|
48
|
+
const [hasCheckedOnMount, setHasCheckedOnMount] = useState(false);
|
|
49
|
+
|
|
50
|
+
const checkModuleVersions = useCallback(async () => {
|
|
51
|
+
if (installedModules.length === 0) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
setIsCheckingVersions(true);
|
|
56
|
+
const versions: Record<string, any> = {};
|
|
57
|
+
|
|
58
|
+
for (const module of installedModules) {
|
|
59
|
+
try {
|
|
60
|
+
const packageName = module.fullName || module.name;
|
|
61
|
+
|
|
62
|
+
const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`, {
|
|
63
|
+
signal: AbortSignal.timeout(5000),
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
if (response.ok) {
|
|
67
|
+
const data = await response.json();
|
|
68
|
+
versions[module.name] = {
|
|
69
|
+
latest: data.version,
|
|
70
|
+
packageName: packageName,
|
|
71
|
+
error: null,
|
|
72
|
+
};
|
|
73
|
+
} else {
|
|
74
|
+
versions[module.name] = {
|
|
75
|
+
latest: null,
|
|
76
|
+
error: 'Not found in registry',
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
} catch (err) {
|
|
80
|
+
versions[module.name] = {
|
|
81
|
+
latest: null,
|
|
82
|
+
error: 'Unable to check',
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
setModuleVersions(versions);
|
|
89
|
+
setIsCheckingVersions(false);
|
|
90
|
+
}, [installedModules]);
|
|
91
|
+
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
if (installedModules.length > 0 && !hasCheckedOnMount) {
|
|
94
|
+
setHasCheckedOnMount(true);
|
|
95
|
+
checkModuleVersions();
|
|
96
|
+
}
|
|
97
|
+
}, [installedModules.length, hasCheckedOnMount, checkModuleVersions]);
|
|
98
|
+
|
|
99
|
+
const filteredModules = installedModules.filter((module) =>
|
|
100
|
+
module.name.toLowerCase().includes(searchTerm.toLowerCase()),
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
const getModuleStatus = (moduleName: string, currentVersion: string) => {
|
|
104
|
+
const versionInfo = moduleVersions[moduleName];
|
|
105
|
+
|
|
106
|
+
if (!versionInfo || !versionInfo.latest) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const comparison = compareVersions(currentVersion, versionInfo.latest);
|
|
111
|
+
|
|
112
|
+
return { comparison, latestVersion: versionInfo.latest };
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const updateStats = installedModules.reduce(
|
|
116
|
+
(acc, module) => {
|
|
117
|
+
const status = getModuleStatus(module.name, module.version);
|
|
118
|
+
if (status) {
|
|
119
|
+
if (status.comparison < 0) {
|
|
120
|
+
acc.outdated++;
|
|
121
|
+
} else if (status.comparison === 0) {
|
|
122
|
+
acc.upToDate++;
|
|
123
|
+
} else {
|
|
124
|
+
acc.ahead++;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return acc;
|
|
128
|
+
},
|
|
129
|
+
{ outdated: 0, upToDate: 0, ahead: 0 },
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
const handleToggleModules = () => {
|
|
133
|
+
setShowModules(!showModules);
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const handleKeyDownToggle = (e: React.KeyboardEvent) => {
|
|
137
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
138
|
+
e.preventDefault();
|
|
139
|
+
handleToggleModules();
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
return (
|
|
144
|
+
<div className={styles.main}>
|
|
145
|
+
<div className={styles.aboutPage}>
|
|
146
|
+
<div className={styles.container}>
|
|
147
|
+
<div className={styles.title}>
|
|
148
|
+
<h3>{t('SystemInformation', 'System Information')}</h3>
|
|
149
|
+
</div>
|
|
150
|
+
<div className={styles.aboutBody}>
|
|
151
|
+
<p>DigiHMIS Version</p>
|
|
152
|
+
<p>{`v${kenyaEMR?.version}`}</p>
|
|
153
|
+
<p>SPA Version</p>
|
|
154
|
+
<p>{`v${VERSION.version}`}</p>
|
|
155
|
+
<p>{t('BuildDateTime', 'Build date time')}</p>
|
|
156
|
+
<p>{formatDatetime(new Date(VERSION.buildDate), { mode: 'standard' })}</p>
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
</div>
|
|
160
|
+
|
|
161
|
+
<div className={styles.aboutPage}>
|
|
162
|
+
<div className={styles.container}>
|
|
163
|
+
<div
|
|
164
|
+
className={styles.cardHeader}
|
|
165
|
+
onClick={handleToggleModules}
|
|
166
|
+
onKeyDown={handleKeyDownToggle}
|
|
167
|
+
role="button"
|
|
168
|
+
tabIndex={0}
|
|
169
|
+
aria-expanded={showModules}
|
|
170
|
+
aria-controls="module-list-content">
|
|
171
|
+
<div className={styles.cardHeaderContent}>
|
|
172
|
+
<Package size={20} />
|
|
173
|
+
<h3>Installed Frontend Modules</h3>
|
|
174
|
+
<span className={styles.badge}>{installedModules.length}</span>
|
|
175
|
+
{isCheckingVersions && <span className={styles.checkingStatus}>Checking for updates...</span>}
|
|
176
|
+
{!isCheckingVersions && updateStats.outdated > 0 && (
|
|
177
|
+
<span className={styles.updatesAvailable}>
|
|
178
|
+
{updateStats.outdated} update{updateStats.outdated !== 1 ? 's' : ''} available
|
|
179
|
+
</span>
|
|
180
|
+
)}
|
|
181
|
+
</div>
|
|
182
|
+
<div className={styles.cardHeaderActions}>
|
|
183
|
+
<IconButton
|
|
184
|
+
size="sm"
|
|
185
|
+
kind="ghost"
|
|
186
|
+
align="bottom"
|
|
187
|
+
label={t('checkForUpdates', 'Check for updates')}
|
|
188
|
+
disabled={isCheckingVersions}
|
|
189
|
+
onClick={(e) => {
|
|
190
|
+
e.stopPropagation();
|
|
191
|
+
checkModuleVersions();
|
|
192
|
+
}}>
|
|
193
|
+
{isCheckingVersions ? <InlineLoading /> : <Renew />}
|
|
194
|
+
</IconButton>
|
|
195
|
+
{showModules ? <ChevronUp size={20} /> : <ChevronDown size={20} />}
|
|
196
|
+
</div>
|
|
197
|
+
</div>
|
|
198
|
+
|
|
199
|
+
{showModules && (
|
|
200
|
+
<div className={styles.cardBody} id="module-list-content">
|
|
201
|
+
<div className={styles.searchContainer}>
|
|
202
|
+
<Search size={16} className={styles.searchIcon} />
|
|
203
|
+
<input
|
|
204
|
+
type="text"
|
|
205
|
+
placeholder={t('searchModules', 'Search modules...')}
|
|
206
|
+
value={searchTerm}
|
|
207
|
+
onChange={(e) => setSearchTerm(e.target.value)}
|
|
208
|
+
className={styles.searchInput}
|
|
209
|
+
/>
|
|
210
|
+
{searchTerm && (
|
|
211
|
+
<button
|
|
212
|
+
onClick={() => setSearchTerm('')}
|
|
213
|
+
className={styles.clearButton}
|
|
214
|
+
aria-label={t('clearSearch', 'Clear search')}>
|
|
215
|
+
×
|
|
216
|
+
</button>
|
|
217
|
+
)}
|
|
218
|
+
</div>
|
|
219
|
+
|
|
220
|
+
<div className={styles.moduleList}>
|
|
221
|
+
{isCheckingVersions && Object.keys(moduleVersions).length === 0 ? (
|
|
222
|
+
Array.from({ length: Math.min(5, installedModules.length) }).map((_, index) => (
|
|
223
|
+
<div key={index} className={styles.moduleItem}>
|
|
224
|
+
<div className={styles.moduleInfo}>
|
|
225
|
+
<Package size={16} className={styles.moduleIcon} />
|
|
226
|
+
<SkeletonText width="60%" />
|
|
227
|
+
</div>
|
|
228
|
+
<div className={styles.statusIndicator}>
|
|
229
|
+
<SkeletonText width="50px" />
|
|
230
|
+
</div>
|
|
231
|
+
</div>
|
|
232
|
+
))
|
|
233
|
+
) : filteredModules.length > 0 ? (
|
|
234
|
+
filteredModules.map((module, index) => {
|
|
235
|
+
const status = getModuleStatus(module.name, module.version);
|
|
236
|
+
const isLoadingThisModule = isCheckingVersions && !moduleVersions[module.name];
|
|
237
|
+
|
|
238
|
+
return (
|
|
239
|
+
<div key={index} className={styles.moduleItem}>
|
|
240
|
+
<div className={styles.moduleInfo}>
|
|
241
|
+
<Package size={16} className={styles.moduleIcon} />
|
|
242
|
+
<span className={styles.moduleName}>{module.name}</span>
|
|
243
|
+
</div>
|
|
244
|
+
<div className={styles.statusIndicator}>
|
|
245
|
+
<span className={styles.moduleVersion}>v{module.version}</span>
|
|
246
|
+
{isLoadingThisModule ? (
|
|
247
|
+
<InlineLoading description="" />
|
|
248
|
+
) : (
|
|
249
|
+
status && (
|
|
250
|
+
<>
|
|
251
|
+
{status.comparison === 0 && (
|
|
252
|
+
<CheckmarkFilled
|
|
253
|
+
size={16}
|
|
254
|
+
className={styles.statusIconUpToDate}
|
|
255
|
+
title={t('upToDate', 'Up to date')}
|
|
256
|
+
/>
|
|
257
|
+
)}
|
|
258
|
+
{status.comparison < 0 && (
|
|
259
|
+
<div className={styles.statusIndicator}>
|
|
260
|
+
<ArrowUp
|
|
261
|
+
size={16}
|
|
262
|
+
className={styles.statusIconUpdate}
|
|
263
|
+
title={t('updateAvailable', 'Update available: v{{version}}', {
|
|
264
|
+
version: status.latestVersion,
|
|
265
|
+
})}
|
|
266
|
+
/>
|
|
267
|
+
<span className={styles.latestVersion}>v{status.latestVersion}</span>
|
|
268
|
+
</div>
|
|
269
|
+
)}
|
|
270
|
+
{status.comparison > 0 && (
|
|
271
|
+
<WarningAlt
|
|
272
|
+
size={16}
|
|
273
|
+
className={styles.statusIconAhead}
|
|
274
|
+
title={t('aheadOfPublishedVersion', 'Ahead of published version')}
|
|
275
|
+
/>
|
|
276
|
+
)}
|
|
277
|
+
</>
|
|
278
|
+
)
|
|
279
|
+
)}
|
|
280
|
+
</div>
|
|
281
|
+
</div>
|
|
282
|
+
);
|
|
283
|
+
})
|
|
284
|
+
) : (
|
|
285
|
+
<div className={styles.emptyState}>
|
|
286
|
+
<Package size={32} />
|
|
287
|
+
<p>{t('noModulesFound', "No modules found matching '{{searchTerm}}'", { searchTerm })}</p>
|
|
288
|
+
</div>
|
|
289
|
+
)}
|
|
290
|
+
</div>
|
|
291
|
+
|
|
292
|
+
{searchTerm && filteredModules.length > 0 && (
|
|
293
|
+
<div className={styles.moduleSummary}>
|
|
294
|
+
{t('showingModules', 'Showing {{count}} of {{total}} modules', {
|
|
295
|
+
count: filteredModules.length,
|
|
296
|
+
total: installedModules.length,
|
|
297
|
+
})}
|
|
298
|
+
</div>
|
|
299
|
+
)}
|
|
300
|
+
|
|
301
|
+
{!searchTerm && !isCheckingVersions && Object.keys(moduleVersions).length > 0 && (
|
|
302
|
+
<div className={styles.moduleSummary}>
|
|
303
|
+
{updateStats.upToDate > 0 && `${updateStats.upToDate} up to date`}
|
|
304
|
+
{updateStats.upToDate > 0 && updateStats.outdated > 0 && ' • '}
|
|
305
|
+
{updateStats.outdated > 0 &&
|
|
306
|
+
`${updateStats.outdated} update${updateStats.outdated !== 1 ? 's' : ''} available`}
|
|
307
|
+
{(updateStats.upToDate > 0 || updateStats.outdated > 0) && updateStats.ahead > 0 && ' • '}
|
|
308
|
+
{updateStats.ahead > 0 && `${updateStats.ahead} ahead`}
|
|
309
|
+
</div>
|
|
310
|
+
)}
|
|
311
|
+
</div>
|
|
312
|
+
)}
|
|
313
|
+
</div>
|
|
314
|
+
</div>
|
|
315
|
+
|
|
316
|
+
<div className={styles.aboutPage}>
|
|
317
|
+
<div className={styles.container}>
|
|
318
|
+
<div className={styles.aboutBodyContact}>
|
|
319
|
+
<p>{t('AboutDigiHMIS', 'Made with ❤️ by the DigiHMIS Team')}</p>
|
|
320
|
+
<br />
|
|
321
|
+
<p>
|
|
322
|
+
{t('officialWebsite', 'Official Website:')} <a href="https://www.digihmis.org">www.digihmis.org</a>
|
|
323
|
+
</p>
|
|
324
|
+
<br />
|
|
325
|
+
<p>
|
|
326
|
+
{t('supportContact', 'For support, please contact us at')}{' '}
|
|
327
|
+
<a href="mailto:support@digihmis.org">support@digihmis.org</a>
|
|
328
|
+
</p>
|
|
329
|
+
<br />
|
|
330
|
+
<p>{t('telephoneSupport', 'Telephone Support:')} +254 707 000 000</p>
|
|
331
|
+
</div>
|
|
332
|
+
</div>
|
|
333
|
+
</div>
|
|
334
|
+
</div>
|
|
335
|
+
);
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
export default SystemInfoDashboard;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { OpenmrsResource, openmrsFetch } from '@openmrs/esm-framework';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import useSWRImmutable from 'swr/immutable';
|
|
4
|
+
import { FrontendModule } from '../type';
|
|
5
|
+
|
|
6
|
+
interface Modules extends OpenmrsResource {
|
|
7
|
+
version: string;
|
|
8
|
+
name: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function useModules() {
|
|
12
|
+
const { data, isLoading } = useSWRImmutable<{ data: { results: Array<Modules> } }>(
|
|
13
|
+
'ws/rest/v1/module?v=custom:(uuid,name,version)',
|
|
14
|
+
openmrsFetch,
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
return { modules: data?.data?.results ?? [], isLoading };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function useFrontendModules() {
|
|
21
|
+
return useMemo<Array<FrontendModule>>(() => {
|
|
22
|
+
return (window.installedModules ?? [])
|
|
23
|
+
.filter((module) => Boolean(module) && Boolean(module[1]))
|
|
24
|
+
.map((module) => {
|
|
25
|
+
const fullName = module[0];
|
|
26
|
+
const version = module[1].version;
|
|
27
|
+
|
|
28
|
+
const firstSlash = fullName.indexOf('/');
|
|
29
|
+
const orgName = firstSlash > 0 ? fullName.substring(0, firstSlash) : null;
|
|
30
|
+
const moduleName = firstSlash > 0 ? fullName.substring(firstSlash + 1) : fullName;
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
version,
|
|
34
|
+
name: moduleName,
|
|
35
|
+
fullName,
|
|
36
|
+
org: orgName,
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
}, []);
|
|
40
|
+
}
|