@ampath/esm-laboratory-app 1.3.0-next.2
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/.editorconfig +12 -0
- package/.eslintignore +2 -0
- package/.eslintrc +68 -0
- package/.husky/pre-commit +7 -0
- package/.husky/pre-push +6 -0
- package/.prettierignore +12 -0
- package/.prettierrc +8 -0
- package/.tx/config +11 -0
- package/.yarn/plugins/@yarnpkg/plugin-outdated.cjs +35 -0
- package/README.md +54 -0
- package/__mocks__/react-i18next.js +50 -0
- package/assets/screenshots/labs_enter_results.png +0 -0
- package/assets/screenshots/labs_general_dashboard.png +0 -0
- package/dist/1119.js +1 -0
- package/dist/1197.js +1 -0
- package/dist/1222.js +1 -0
- package/dist/1222.js.map +1 -0
- package/dist/1243.js +1 -0
- package/dist/1243.js.map +1 -0
- package/dist/2146.js +1 -0
- package/dist/2690.js +1 -0
- package/dist/3099.js +1 -0
- package/dist/3106.js +1 -0
- package/dist/3106.js.map +1 -0
- package/dist/312.js +1 -0
- package/dist/312.js.map +1 -0
- package/dist/3352.js +1 -0
- package/dist/3352.js.map +1 -0
- package/dist/3535.js +1 -0
- package/dist/3535.js.map +1 -0
- package/dist/3584.js +1 -0
- package/dist/4044.js +1 -0
- package/dist/4044.js.map +1 -0
- package/dist/4055.js +1 -0
- package/dist/4132.js +1 -0
- package/dist/4300.js +1 -0
- package/dist/4335.js +1 -0
- package/dist/439.js +1 -0
- package/dist/4535.js +1 -0
- package/dist/4535.js.map +1 -0
- package/dist/4618.js +1 -0
- package/dist/4652.js +1 -0
- package/dist/4748.js +2 -0
- package/dist/4748.js.LICENSE.txt +9 -0
- package/dist/4748.js.map +1 -0
- package/dist/4920.js +1 -0
- package/dist/4920.js.map +1 -0
- package/dist/4944.js +1 -0
- package/dist/5048.js +2 -0
- package/dist/5048.js.LICENSE.txt +29 -0
- package/dist/5048.js.map +1 -0
- package/dist/5088.js +1 -0
- package/dist/5088.js.map +1 -0
- package/dist/5173.js +1 -0
- package/dist/5241.js +1 -0
- package/dist/53.js +1 -0
- package/dist/53.js.map +1 -0
- package/dist/5339.js +1 -0
- package/dist/5339.js.map +1 -0
- package/dist/5348.js +1 -0
- package/dist/5348.js.map +1 -0
- package/dist/5380.js +1 -0
- package/dist/5380.js.map +1 -0
- package/dist/5442.js +1 -0
- package/dist/5661.js +1 -0
- package/dist/5780.js +2 -0
- package/dist/5780.js.LICENSE.txt +9 -0
- package/dist/5780.js.map +1 -0
- package/dist/6022.js +1 -0
- package/dist/6468.js +1 -0
- package/dist/6589.js +1 -0
- package/dist/6679.js +1 -0
- package/dist/6753.js +1 -0
- package/dist/6753.js.map +1 -0
- package/dist/6777.js +2 -0
- package/dist/6777.js.LICENSE.txt +19 -0
- package/dist/6777.js.map +1 -0
- package/dist/679.js +2 -0
- package/dist/679.js.LICENSE.txt +9 -0
- package/dist/679.js.map +1 -0
- package/dist/6840.js +1 -0
- package/dist/6859.js +1 -0
- package/dist/7097.js +1 -0
- package/dist/7129.js +1 -0
- package/dist/7129.js.map +1 -0
- package/dist/7159.js +1 -0
- package/dist/723.js +1 -0
- package/dist/7617.js +1 -0
- package/dist/791.js +1 -0
- package/dist/791.js.map +1 -0
- package/dist/795.js +1 -0
- package/dist/8163.js +1 -0
- package/dist/8349.js +1 -0
- package/dist/8371.js +1 -0
- package/dist/841.js +1 -0
- package/dist/841.js.map +1 -0
- package/dist/8618.js +1 -0
- package/dist/8627.js +2 -0
- package/dist/8627.js.LICENSE.txt +25 -0
- package/dist/8627.js.map +1 -0
- package/dist/8898.js +2 -0
- package/dist/8898.js.LICENSE.txt +32 -0
- package/dist/8898.js.map +1 -0
- package/dist/890.js +1 -0
- package/dist/9214.js +1 -0
- package/dist/9321.js +1 -0
- package/dist/9321.js.map +1 -0
- package/dist/9452.js +1 -0
- package/dist/9452.js.map +1 -0
- package/dist/9538.js +1 -0
- package/dist/9569.js +1 -0
- package/dist/9695.js +1 -0
- package/dist/9695.js.map +1 -0
- package/dist/986.js +1 -0
- package/dist/9879.js +1 -0
- package/dist/9895.js +1 -0
- package/dist/9900.js +1 -0
- package/dist/9910.js +1 -0
- package/dist/9910.js.map +1 -0
- package/dist/9913.js +1 -0
- package/dist/main.js +2 -0
- package/dist/main.js.LICENSE.txt +45 -0
- package/dist/main.js.map +1 -0
- package/dist/openmrs-esm-laboratory-app.js +1 -0
- package/dist/openmrs-esm-laboratory-app.js.buildmanifest.json +1744 -0
- package/dist/openmrs-esm-laboratory-app.js.map +1 -0
- package/dist/routes.json +1 -0
- package/e2e/README.md +117 -0
- package/e2e/commands/encounter-operations.ts +63 -0
- package/e2e/commands/index.ts +5 -0
- package/e2e/commands/patient-operations.ts +109 -0
- package/e2e/commands/provider-operations.ts +9 -0
- package/e2e/commands/test-order-operations.ts +46 -0
- package/e2e/commands/types/index.ts +157 -0
- package/e2e/commands/visit-operations.ts +38 -0
- package/e2e/core/global-setup.ts +32 -0
- package/e2e/core/index.ts +1 -0
- package/e2e/core/test.ts +31 -0
- package/e2e/fixtures/api.ts +27 -0
- package/e2e/fixtures/fhirApi.ts +28 -0
- package/e2e/fixtures/index.ts +2 -0
- package/e2e/pages/index.ts +1 -0
- package/e2e/pages/laboratory-page.ts +28 -0
- package/e2e/specs/add-lab-results.spec.ts +111 -0
- package/e2e/specs/reject-lab-request.spec.ts +88 -0
- package/e2e/specs/test-orders.spec.ts +69 -0
- package/e2e/support/github/Dockerfile +34 -0
- package/e2e/support/github/docker-compose.yml +24 -0
- package/e2e/support/github/run-e2e-docker-env.sh +58 -0
- package/example.env +7 -0
- package/jest.config.js +35 -0
- package/package.json +105 -0
- package/playwright.config.ts +42 -0
- package/src/components/create-dashboard-link.component.tsx +37 -0
- package/src/components/loader/loader.component.tsx +11 -0
- package/src/components/loader/loader.scss +9 -0
- package/src/components/orders-table/list-order-details.component.tsx +143 -0
- package/src/components/orders-table/list-order-details.scss +136 -0
- package/src/components/orders-table/order-detail.scss +18 -0
- package/src/components/orders-table/orders-data-table.component.tsx +349 -0
- package/src/components/orders-table/orders-data-table.scss +129 -0
- package/src/components/orders-table/orders-data-table.test.tsx +214 -0
- package/src/components/orders-table/orders-date-range-picker.component.tsx +32 -0
- package/src/components/orders-table/orders-date-range-picker.scss +7 -0
- package/src/components/summary-tile/lab-summary-tile.component.tsx +31 -0
- package/src/components/summary-tile/lab-summary-tile.scss +64 -0
- package/src/config-schema.ts +39 -0
- package/src/constants.ts +2 -0
- package/src/declarations.d.ts +2 -0
- package/src/index.ts +123 -0
- package/src/lab-tabs/actions/actions.scss +26 -0
- package/src/lab-tabs/actions/add-lab-request-results-action.component.tsx +46 -0
- package/src/lab-tabs/actions/amend-lab-results-action.component.tsx +40 -0
- package/src/lab-tabs/actions/approve-lab-results-action.component.tsx +36 -0
- package/src/lab-tabs/actions/pickup-lab-request-action.component.tsx +36 -0
- package/src/lab-tabs/actions/reject-lab-request-action.component.tsx +36 -0
- package/src/lab-tabs/data-table-extensions/completed-lab-requests-table.extension.tsx +8 -0
- package/src/lab-tabs/data-table-extensions/declined-lab-requests-table-extension.tsx +8 -0
- package/src/lab-tabs/data-table-extensions/in-progress-lab-requests-table.extension.tsx +8 -0
- package/src/lab-tabs/data-table-extensions/pending-review-lab-request-table.extension.tsx +8 -0
- package/src/lab-tabs/data-table-extensions/tests-ordered-table.extension.tsx +8 -0
- package/src/lab-tabs/laboratory-tabs.component.tsx +81 -0
- package/src/lab-tabs/laboratory-tabs.scss +38 -0
- package/src/lab-tabs/modals/approval-lab-results-modal.component.tsx +70 -0
- package/src/lab-tabs/modals/pickup-lab-request-modal.component.tsx +67 -0
- package/src/lab-tabs/modals/pickup-lab-request-modal.test.tsx +127 -0
- package/src/lab-tabs/modals/reject-lab-request-modal.component.tsx +86 -0
- package/src/lab-tabs/modals/reject-lab-request-modal.scss +13 -0
- package/src/lab-tabs/modals/reject-lab-request-modal.test.tsx +152 -0
- package/src/lab-tiles/all-lab-requests-tile.component.tsx +19 -0
- package/src/lab-tiles/completed-lab-requests-tile.component.tsx +19 -0
- package/src/lab-tiles/in-progress-lab-requests-tile.component.tsx +19 -0
- package/src/lab-tiles/laboratory-summary-tiles.component.tsx +52 -0
- package/src/lab-tiles/laboratory-summary-tiles.scss +16 -0
- package/src/lab-tiles/pending-review-lab-results-tile.component.tsx +22 -0
- package/src/laboratory-dashboard.component.tsx +30 -0
- package/src/laboratory-dashboard.scss +5 -0
- package/src/laboratory.resource.ts +108 -0
- package/src/root.component.tsx +15 -0
- package/src/routes.json +204 -0
- package/src/types.ts +39 -0
- package/tools/i18next-parser.config.js +93 -0
- package/tools/index.ts +1 -0
- package/tools/setup-tests.ts +8 -0
- package/tools/test-utils.ts +44 -0
- package/tools/update-openmrs-deps.mjs +42 -0
- package/translations/am.json +79 -0
- package/translations/ar.json +79 -0
- package/translations/ar_SY.json +79 -0
- package/translations/bn.json +79 -0
- package/translations/cs.json +79 -0
- package/translations/de.json +79 -0
- package/translations/en.json +79 -0
- package/translations/en_US.json +79 -0
- package/translations/es.json +79 -0
- package/translations/es_MX.json +79 -0
- package/translations/fr.json +79 -0
- package/translations/he.json +79 -0
- package/translations/hi.json +79 -0
- package/translations/hi_IN.json +79 -0
- package/translations/id.json +79 -0
- package/translations/it.json +79 -0
- package/translations/ka.json +79 -0
- package/translations/km.json +79 -0
- package/translations/ku.json +79 -0
- package/translations/ky.json +79 -0
- package/translations/lg.json +79 -0
- package/translations/ne.json +79 -0
- package/translations/pl.json +79 -0
- package/translations/pt.json +79 -0
- package/translations/pt_BR.json +79 -0
- package/translations/qu.json +79 -0
- package/translations/ro_RO.json +79 -0
- package/translations/ru_RU.json +79 -0
- package/translations/si.json +79 -0
- package/translations/sq.json +79 -0
- package/translations/sw.json +79 -0
- package/translations/sw_KE.json +79 -0
- package/translations/tr.json +79 -0
- package/translations/tr_TR.json +79 -0
- package/translations/uk.json +79 -0
- package/translations/uz.json +79 -0
- package/translations/uz@Latn.json +79 -0
- package/translations/uz_UZ.json +79 -0
- package/translations/vi.json +79 -0
- package/translations/zh.json +79 -0
- package/translations/zh_CN.json +79 -0
- package/translations/zh_TW.json +79 -0
- package/tsconfig.json +28 -0
- package/turbo.json +15 -0
- package/webpack.config.js +25 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { useLabOrders } from '../laboratory.resource';
|
|
4
|
+
import LabSummaryTile from '../components/summary-tile/lab-summary-tile.component';
|
|
5
|
+
|
|
6
|
+
const PendingReviewLabRequestsTile = () => {
|
|
7
|
+
const { t } = useTranslation();
|
|
8
|
+
const { labOrders } = useLabOrders({
|
|
9
|
+
status: 'DRAFT',
|
|
10
|
+
excludeCanceled: false,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<LabSummaryTile
|
|
15
|
+
label={t('pendingReview', 'Pending Review')}
|
|
16
|
+
value={labOrders?.length}
|
|
17
|
+
headerLabel={t('awaitingApproval', 'Awaiting Approval')}
|
|
18
|
+
/>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default PendingReviewLabRequestsTile;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import dayjs from 'dayjs';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { LaboratoryPictogram, PageHeader, useDefineAppContext } from '@openmrs/esm-framework';
|
|
5
|
+
import { type DateFilterContext } from './types';
|
|
6
|
+
import LaboratoryOrdersTabs from './lab-tabs/laboratory-tabs.component';
|
|
7
|
+
import LaboratorySummaryTiles from './lab-tiles/laboratory-summary-tiles.component';
|
|
8
|
+
import styles from './laboratory-dashboard.scss';
|
|
9
|
+
|
|
10
|
+
const LaboratoryDashboard: React.FC = () => {
|
|
11
|
+
const { t } = useTranslation();
|
|
12
|
+
const [dateRange, setDateRange] = useState<[Date, Date]>([dayjs().startOf('day').toDate(), new Date()]);
|
|
13
|
+
useDefineAppContext<DateFilterContext>('laboratory-date-filter', { dateRange, setDateRange });
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<div>
|
|
17
|
+
<PageHeader
|
|
18
|
+
illustration={<LaboratoryPictogram />}
|
|
19
|
+
title={t('laboratory', 'Laboratory')}
|
|
20
|
+
className={styles.pageHeader}
|
|
21
|
+
/>
|
|
22
|
+
<div>
|
|
23
|
+
<LaboratorySummaryTiles />
|
|
24
|
+
<LaboratoryOrdersTabs />
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default LaboratoryDashboard;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
import dayjs from 'dayjs';
|
|
3
|
+
import useSWR, { mutate } from 'swr';
|
|
4
|
+
import { openmrsFetch, type Order, restBaseUrl, useAppContext, useConfig } from '@openmrs/esm-framework';
|
|
5
|
+
import type { DateFilterContext, FulfillerStatus } from './types';
|
|
6
|
+
import { type Config } from './config-schema';
|
|
7
|
+
|
|
8
|
+
const useLabOrdersDefaultParams: UseLabOrdersParams = {
|
|
9
|
+
status: null,
|
|
10
|
+
newOrdersOnly: false,
|
|
11
|
+
excludeCanceled: true,
|
|
12
|
+
includePatientId: false,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
interface UseLabOrdersParams {
|
|
16
|
+
status: FulfillerStatus;
|
|
17
|
+
newOrdersOnly: boolean;
|
|
18
|
+
excludeCanceled: boolean;
|
|
19
|
+
includePatientId: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Custom hook for retrieving laboratory orders.
|
|
24
|
+
*
|
|
25
|
+
* @param status - The fulfiller status to filter by (e.g. 'IN_PROGRESS', 'COMPLETED')
|
|
26
|
+
* @param newOrdersOnly - Whether to return only new orders that haven't been picked (action=NEW, fulfillerStatus=null). Filtered client-side as the REST API doesn't support this query natively.
|
|
27
|
+
* @param excludeCanceled - Whether to exclude canceled, discontinued and expired orders
|
|
28
|
+
* @param includePatientId - Whether to include patient identifiers in the response
|
|
29
|
+
*/
|
|
30
|
+
export function useLabOrders(params: Partial<UseLabOrdersParams> = useLabOrdersDefaultParams) {
|
|
31
|
+
const definedParams = Object.fromEntries(Object.entries(params).filter(([, v]) => v !== undefined));
|
|
32
|
+
const { status, newOrdersOnly, excludeCanceled, includePatientId } = {
|
|
33
|
+
...useLabOrdersDefaultParams,
|
|
34
|
+
...definedParams,
|
|
35
|
+
};
|
|
36
|
+
const { dateRange } = useAppContext<DateFilterContext>('laboratory-date-filter') ?? {
|
|
37
|
+
dateRange: [dayjs().startOf('day').toDate(), new Date()],
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const { laboratoryOrderTypeUuid } = useConfig();
|
|
41
|
+
const customRepresentation = `custom:(uuid,orderNumber,patient:(uuid,display,person:(uuid,display,age,birthdate,gender)${
|
|
42
|
+
includePatientId ? ',identifiers' : ''
|
|
43
|
+
}),concept:(uuid,display),action,careSetting:(uuid,display,description,careSettingType,display),previousOrder,dateActivated,scheduledDate,dateStopped,autoExpireDate,encounter:(uuid,display),orderer:(uuid,display),orderReason,orderReasonNonCoded,orderType:(uuid,display,name,description,conceptClasses,parent),urgency,instructions,commentToFulfiller,display,fulfillerStatus,fulfillerComment,accessionNumber,specimenSource,laterality,clinicalHistory,frequency,numberOfRepeats)`;
|
|
44
|
+
let url = `${restBaseUrl}/order?orderTypes=${laboratoryOrderTypeUuid}&v=${customRepresentation}`;
|
|
45
|
+
url = status ? url + `&fulfillerStatus=${status}` : url;
|
|
46
|
+
url = excludeCanceled ? `${url}&excludeCanceledAndExpired=true&excludeDiscontinueOrders=true` : url;
|
|
47
|
+
url = dateRange
|
|
48
|
+
? `${url}&activatedOnOrAfterDate=${dateRange.at(0).toISOString()}&activatedOnOrBeforeDate=${dateRange
|
|
49
|
+
.at(1)
|
|
50
|
+
.toISOString()}`
|
|
51
|
+
: url;
|
|
52
|
+
|
|
53
|
+
const { data, error, mutate, isLoading, isValidating } = useSWR<{
|
|
54
|
+
data: { results: Array<Order> };
|
|
55
|
+
}>(`${url}`, openmrsFetch);
|
|
56
|
+
|
|
57
|
+
const filteredOrders = data?.data?.results?.filter(
|
|
58
|
+
(order) => !newOrdersOnly || (order?.action === 'NEW' && order?.fulfillerStatus === null),
|
|
59
|
+
);
|
|
60
|
+
return {
|
|
61
|
+
labOrders: filteredOrders ?? [],
|
|
62
|
+
isLoading,
|
|
63
|
+
isError: error,
|
|
64
|
+
mutate,
|
|
65
|
+
isValidating,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function setFulfillerStatus(orderId: string, status: FulfillerStatus, abortController: AbortController) {
|
|
70
|
+
return openmrsFetch(`${restBaseUrl}/order/${orderId}/fulfillerdetails/`, {
|
|
71
|
+
method: 'POST',
|
|
72
|
+
headers: {
|
|
73
|
+
'Content-Type': 'application/json',
|
|
74
|
+
},
|
|
75
|
+
signal: abortController.signal,
|
|
76
|
+
body: { fulfillerStatus: status },
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function rejectLabOrder(orderId: string, comment: string, abortController: AbortController) {
|
|
81
|
+
return openmrsFetch(`${restBaseUrl}/order/${orderId}/fulfillerdetails/`, {
|
|
82
|
+
method: 'POST',
|
|
83
|
+
headers: {
|
|
84
|
+
'Content-Type': 'application/json',
|
|
85
|
+
},
|
|
86
|
+
signal: abortController.signal,
|
|
87
|
+
body: {
|
|
88
|
+
fulfillerStatus: 'DECLINED',
|
|
89
|
+
fulfillerComment: comment,
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Custom hook that returns a function to invalidate and refetch all lab orders.
|
|
96
|
+
* Use this after mutations to ensure the UI reflects the latest data.
|
|
97
|
+
*/
|
|
98
|
+
export function useInvalidateLabOrders() {
|
|
99
|
+
const { laboratoryOrderTypeUuid } = useConfig<Config>();
|
|
100
|
+
|
|
101
|
+
return useCallback(() => {
|
|
102
|
+
mutate(
|
|
103
|
+
(key) => typeof key === 'string' && key.startsWith(`${restBaseUrl}/order?orderTypes=${laboratoryOrderTypeUuid}`),
|
|
104
|
+
undefined,
|
|
105
|
+
{ revalidate: true },
|
|
106
|
+
);
|
|
107
|
+
}, [laboratoryOrderTypeUuid]);
|
|
108
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { BrowserRouter, Route, Routes } from 'react-router-dom';
|
|
3
|
+
import LaboratoryDashboard from './laboratory-dashboard.component';
|
|
4
|
+
|
|
5
|
+
const Root: React.FC = () => {
|
|
6
|
+
return (
|
|
7
|
+
<BrowserRouter basename={`${window.spaBase}/home/laboratory`}>
|
|
8
|
+
<Routes>
|
|
9
|
+
<Route path="/" element={<LaboratoryDashboard />} />
|
|
10
|
+
</Routes>
|
|
11
|
+
</BrowserRouter>
|
|
12
|
+
);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default Root;
|
package/src/routes.json
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.openmrs.org/routes.schema.json",
|
|
3
|
+
"backendDependencies": {
|
|
4
|
+
"webservices.rest": ">=2.2.0"
|
|
5
|
+
},
|
|
6
|
+
"pages": [
|
|
7
|
+
{
|
|
8
|
+
"component": "root",
|
|
9
|
+
"route": "laboratory"
|
|
10
|
+
}
|
|
11
|
+
],
|
|
12
|
+
"extensions": [
|
|
13
|
+
{
|
|
14
|
+
"name": "laboratory-dashboard",
|
|
15
|
+
"slot": "laboratory-dashboard-slot",
|
|
16
|
+
"component": "root"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"name": "laboratory-dashboard-link",
|
|
20
|
+
"slot": "homepage-dashboard-slot",
|
|
21
|
+
"component": "laboratoryDashboardLink",
|
|
22
|
+
"meta": {
|
|
23
|
+
"name": "laboratory",
|
|
24
|
+
"slot": "laboratory-dashboard-slot",
|
|
25
|
+
"title": "Laboratory"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"name": "pickup-lab-request-modal",
|
|
30
|
+
"component": "pickupLabRequestModal"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "approval-lab-results-modal",
|
|
34
|
+
"component": "approvalLabResultsModal"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name": "reject-lab-request-modal",
|
|
38
|
+
"component": "rejectLabRequestModal"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"name": "all-lab-requests-table",
|
|
42
|
+
"slot": "lab-panels-slot",
|
|
43
|
+
"order": 0,
|
|
44
|
+
"component": "allLabRequestsTable",
|
|
45
|
+
"meta": {
|
|
46
|
+
"name": "testsOrderedPanel",
|
|
47
|
+
"title": "Tests ordered"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"name": "inprogress-lab-requests-table",
|
|
52
|
+
"slot": "lab-panels-slot",
|
|
53
|
+
"component": "inprogressLabRequestsTable",
|
|
54
|
+
"order": 1,
|
|
55
|
+
"meta": {
|
|
56
|
+
"name": "inprogressPanel",
|
|
57
|
+
"title": "In progress"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"name": "completed-lab-requests-table",
|
|
62
|
+
"slot": "lab-panels-slot",
|
|
63
|
+
"component": "completedLabRequestsTable",
|
|
64
|
+
"order": 3,
|
|
65
|
+
"meta": {
|
|
66
|
+
"name": "completedPanel",
|
|
67
|
+
"title": "Completed"
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"name": "tests-ordered-tile-component",
|
|
72
|
+
"slot": "lab-tiles-slot",
|
|
73
|
+
"component": "testOrderedTile",
|
|
74
|
+
"meta": {
|
|
75
|
+
"name": "testsOrderedTileSlot",
|
|
76
|
+
"title": "Ordered tests"
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"name": "pending-review-lab-requests-table",
|
|
81
|
+
"slot": "lab-panels-slot",
|
|
82
|
+
"component": "pendingReviewLabRequestsTable",
|
|
83
|
+
"order": 2,
|
|
84
|
+
"meta": {
|
|
85
|
+
"name": "pendingReviewPanel",
|
|
86
|
+
"title": "Pending review tests"
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"name": "worklist-tile-component",
|
|
91
|
+
"slot": "lab-tiles-slot",
|
|
92
|
+
"component": "worklistTile",
|
|
93
|
+
"meta": {
|
|
94
|
+
"name": "worklistTileSlot",
|
|
95
|
+
"title": "Worklist"
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"name": "pending-review-list-tile-component",
|
|
100
|
+
"slot": "lab-tiles-slot",
|
|
101
|
+
"component": "pendingReviewListTile",
|
|
102
|
+
"meta": {
|
|
103
|
+
"name": "pendingReviewTileSlot",
|
|
104
|
+
"title": "Pending review tests"
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"name": "completed-tile-component",
|
|
109
|
+
"slot": "lab-tiles-slot",
|
|
110
|
+
"component": "completedTile",
|
|
111
|
+
"meta": {
|
|
112
|
+
"name": "completedTileSlot",
|
|
113
|
+
"title": "Completed"
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"name": "declined-tile-component",
|
|
118
|
+
"slot": "lab-panels-slot",
|
|
119
|
+
"component": "declinedLabRequestsTable",
|
|
120
|
+
"order": 4,
|
|
121
|
+
"meta": {
|
|
122
|
+
"name": "declinedPanel",
|
|
123
|
+
"title": "Declined tests"
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"name": "pick-lab-request-action",
|
|
128
|
+
"component": "pickupLabRequestAction",
|
|
129
|
+
"slot": "tests-ordered-actions-slot"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"name": "approve-lab-results-tests-ordered-action",
|
|
133
|
+
"component": "approveLabResultsAction",
|
|
134
|
+
"slot": "approved-ordered-actions-slot"
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"name": "amend-lab-results-tests-ordered-action",
|
|
138
|
+
"component": "amendLabResultsAction",
|
|
139
|
+
"slot": "amended-ordered-actions-slot"
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"name": "reject-lab-request-tests-ordered-action",
|
|
143
|
+
"component": "rejectLabRequestAction",
|
|
144
|
+
"slot": "rejected-ordered-actions-slot"
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"name": "reject-lab-request-worklist-action",
|
|
148
|
+
"component": "rejectLabRequestAction",
|
|
149
|
+
"slot": "inprogress-tests-actions-slot"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"name": "add-lab-request-results-action",
|
|
153
|
+
"component": "addLabRequestResultsAction",
|
|
154
|
+
"slot": "inprogress-tests-actions-slot"
|
|
155
|
+
}
|
|
156
|
+
],
|
|
157
|
+
"workspaces2": [
|
|
158
|
+
{
|
|
159
|
+
"name": "lab-app-test-results-form-workspace",
|
|
160
|
+
"component": "@openmrs/esm-patient-orders-app#exportedTestResultsFormWorkspace",
|
|
161
|
+
"window": "labs-app-test-results-window"
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"name": "add-test-order-patient-search-workspace",
|
|
165
|
+
"component": "@openmrs/esm-patient-search-app#patientSearchWorkspace2",
|
|
166
|
+
"window": "add-test-order-window"
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
"name": "add-test-order-start-visit-workspace",
|
|
170
|
+
"component": "@openmrs/esm-patient-chart-app#exportedVisitForm",
|
|
171
|
+
"window": "add-test-order-window"
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"name": "add-test-order-basket-workspace",
|
|
175
|
+
"component": "@openmrs/esm-patient-orders-app#exportedOrderBasketWorkspace",
|
|
176
|
+
"window": "add-test-order-window"
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"name": "add-test-order-basket-add-lab-order-workspace",
|
|
180
|
+
"component": "@openmrs/esm-patient-tests-app#exportedAddLabOrderWorkspace",
|
|
181
|
+
"window": "add-test-order-window"
|
|
182
|
+
}
|
|
183
|
+
],
|
|
184
|
+
"workspaceWindows2": [
|
|
185
|
+
{
|
|
186
|
+
"name": "labs-app-test-results-window",
|
|
187
|
+
"group": "labs-app-group"
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"name": "add-test-order-window",
|
|
191
|
+
"group": "add-test-order-group"
|
|
192
|
+
}
|
|
193
|
+
],
|
|
194
|
+
"workspaceGroups2": [
|
|
195
|
+
{
|
|
196
|
+
"name": "labs-app-group",
|
|
197
|
+
"scopePattern": "/home/laboratory"
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"name": "add-test-order-group",
|
|
201
|
+
"scopePattern": "/home/laboratory"
|
|
202
|
+
}
|
|
203
|
+
]
|
|
204
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type Order as FrameworkOrder, type OrderUrgency } from '@openmrs/esm-framework';
|
|
2
|
+
|
|
3
|
+
type FrameworkFulfillerStatus = FrameworkOrder['fulfillerStatus'];
|
|
4
|
+
export type FulfillerStatus = FrameworkFulfillerStatus | 'DRAFT' | null;
|
|
5
|
+
|
|
6
|
+
export type Order = Omit<FrameworkOrder, 'fulfillerStatus' | 'fulfillerComment'> & {
|
|
7
|
+
fulfillerStatus?: FulfillerStatus;
|
|
8
|
+
fulfillerComment?: string | null;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export interface FlattenedOrder {
|
|
12
|
+
id: string;
|
|
13
|
+
patientUuid: string;
|
|
14
|
+
orderNumber: string;
|
|
15
|
+
display: string;
|
|
16
|
+
dateActivated: string;
|
|
17
|
+
fulfillerStatus: FulfillerStatus;
|
|
18
|
+
urgency: OrderUrgency;
|
|
19
|
+
orderer?: string;
|
|
20
|
+
instructions?: string;
|
|
21
|
+
fulfillerComment?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface GroupedOrders {
|
|
25
|
+
patientUuid: string;
|
|
26
|
+
patientId?: string;
|
|
27
|
+
patientName?: string;
|
|
28
|
+
patientAge?: number;
|
|
29
|
+
patientDob?: string;
|
|
30
|
+
patientSex?: string;
|
|
31
|
+
totalOrders: number;
|
|
32
|
+
orders: Array<FlattenedOrder>;
|
|
33
|
+
originalOrders: Array<Order>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type DateFilterContext = {
|
|
37
|
+
dateRange: [Date, Date] | null;
|
|
38
|
+
setDateRange: React.Dispatch<React.SetStateAction<[Date, Date] | null>>;
|
|
39
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
contextSeparator: false,
|
|
3
|
+
// Key separator used in your translation keys
|
|
4
|
+
|
|
5
|
+
createOldCatalogs: false,
|
|
6
|
+
// Save the \_old files
|
|
7
|
+
|
|
8
|
+
defaultNamespace: "translations",
|
|
9
|
+
// Default namespace used in your i18next config
|
|
10
|
+
|
|
11
|
+
defaultValue: (_, __, key) => key,
|
|
12
|
+
// Default value to give to empty keys
|
|
13
|
+
// You may also specify a function accepting the locale, namespace, and key as arguments
|
|
14
|
+
|
|
15
|
+
indentation: 2,
|
|
16
|
+
// Indentation of the catalog files
|
|
17
|
+
|
|
18
|
+
keepRemoved: false,
|
|
19
|
+
// Keep keys from the catalog that are no longer in code
|
|
20
|
+
|
|
21
|
+
keySeparator: ".",
|
|
22
|
+
// Key separator used in your translation keys
|
|
23
|
+
// If you want to use plain english keys, separators such as `.` and `:` will conflict. You might want to set `keySeparator: false` and `namespaceSeparator: false`. That way, `t('Status: Loading...')` will not think that there are a namespace and three separator dots for instance.
|
|
24
|
+
|
|
25
|
+
// see below for more details
|
|
26
|
+
lexers: {
|
|
27
|
+
hbs: ["HandlebarsLexer"],
|
|
28
|
+
handlebars: ["HandlebarsLexer"],
|
|
29
|
+
|
|
30
|
+
htm: ["HTMLLexer"],
|
|
31
|
+
html: ["HTMLLexer"],
|
|
32
|
+
|
|
33
|
+
mjs: ["JavascriptLexer"],
|
|
34
|
+
js: ["JavascriptLexer"], // if you're writing jsx inside .js files, change this to JsxLexer
|
|
35
|
+
ts: ["JavascriptLexer"],
|
|
36
|
+
jsx: ["JsxLexer"],
|
|
37
|
+
tsx: ["JsxLexer"],
|
|
38
|
+
|
|
39
|
+
default: ["JavascriptLexer"],
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
lineEnding: "lf",
|
|
43
|
+
// Control the line ending. See options at https://github.com/ryanve/eol
|
|
44
|
+
|
|
45
|
+
locales: ["en"],
|
|
46
|
+
// An array of the locales in your applications
|
|
47
|
+
|
|
48
|
+
namespaceSeparator: ":",
|
|
49
|
+
// Namespace separator used in your translation keys
|
|
50
|
+
// If you want to use plain english keys, separators such as `.` and `:` will conflict. You might want to set `keySeparator: false` and `namespaceSeparator: false`. That way, `t('Status: Loading...')` will not think that there are a namespace and three separator dots for instance.
|
|
51
|
+
|
|
52
|
+
output: "$NAMESPACE/$LOCALE.json",
|
|
53
|
+
// Supports $LOCALE and $NAMESPACE injection
|
|
54
|
+
// Supports JSON (.json) and YAML (.yml) file formats
|
|
55
|
+
// Where to write the locale files relative to process.cwd()
|
|
56
|
+
|
|
57
|
+
pluralSeparator: "_",
|
|
58
|
+
// Plural separator used in your translation keys
|
|
59
|
+
// If you want to use plain english keys, separators such as `_` might conflict. You might want to set `pluralSeparator` to a different string that does not occur in your keys.
|
|
60
|
+
|
|
61
|
+
input: undefined,
|
|
62
|
+
// An array of globs that describe where to look for source files
|
|
63
|
+
// relative to the location of the configuration file
|
|
64
|
+
|
|
65
|
+
sort: true,
|
|
66
|
+
// Whether or not to sort the catalog
|
|
67
|
+
|
|
68
|
+
skipDefaultValues: false,
|
|
69
|
+
// Whether to ignore default values
|
|
70
|
+
// You may also specify a function accepting the locale and namespace as arguments
|
|
71
|
+
|
|
72
|
+
useKeysAsDefaultValue: false,
|
|
73
|
+
// Whether to use the keys as the default value; ex. "Hello": "Hello", "World": "World"
|
|
74
|
+
// This option takes precedence over the `defaultValue` and `skipDefaultValues` options
|
|
75
|
+
// You may also specify a function accepting the locale and namespace as arguments
|
|
76
|
+
|
|
77
|
+
verbose: false,
|
|
78
|
+
// Display info about the parsing including some stats
|
|
79
|
+
|
|
80
|
+
failOnWarnings: false,
|
|
81
|
+
// Exit with an exit code of 1 on warnings
|
|
82
|
+
|
|
83
|
+
customValueTemplate: null,
|
|
84
|
+
// If you wish to customize the value output the value as an object, you can set your own format.
|
|
85
|
+
// ${defaultValue} is the default value you set in your translation function.
|
|
86
|
+
// Any other custom property will be automatically extracted.
|
|
87
|
+
//
|
|
88
|
+
// Example:
|
|
89
|
+
// {
|
|
90
|
+
// message: "${defaultValue}",
|
|
91
|
+
// description: "${maxLength}", // t('my-key', {maxLength: 150})
|
|
92
|
+
// }
|
|
93
|
+
};
|
package/tools/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { mockPatient } from './test-utils';
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const mockPatient = {
|
|
2
|
+
resourceType: 'Patient',
|
|
3
|
+
id: '8673ee4f-e2ab-4077-ba55-4980f408773e',
|
|
4
|
+
extension: [
|
|
5
|
+
{
|
|
6
|
+
url: 'http://fhir-es.transcendinsights.com/stu3/StructureDefinition/resource-date-created',
|
|
7
|
+
valueDateTime: '2017-01-18T09:42:40+00:00',
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
url: 'https://purl.org/elab/fhir/StructureDefinition/Creator-crew-version1',
|
|
11
|
+
valueString: 'daemon',
|
|
12
|
+
},
|
|
13
|
+
],
|
|
14
|
+
identifier: [
|
|
15
|
+
{
|
|
16
|
+
id: '1f0ad7a1-430f-4397-b571-59ea654a52db',
|
|
17
|
+
use: 'secondary',
|
|
18
|
+
system: 'Old Identification Number',
|
|
19
|
+
value: '100732HE',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
id: '1f0ad7a1-430f-4397-b571-59ea654a52db',
|
|
23
|
+
use: 'usual',
|
|
24
|
+
system: 'OpenMRS ID',
|
|
25
|
+
value: '100GEJ',
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
active: true,
|
|
29
|
+
name: [
|
|
30
|
+
{
|
|
31
|
+
id: 'efdb246f-4142-4c12-a27a-9be60b9592e9',
|
|
32
|
+
use: 'usual',
|
|
33
|
+
family: 'Wilson',
|
|
34
|
+
given: ['John'],
|
|
35
|
+
text: 'Wilson, John',
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
gender: 'male',
|
|
39
|
+
birthDate: '1972-04-04',
|
|
40
|
+
deceasedBoolean: false,
|
|
41
|
+
address: [],
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export { mockPatient };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
|
|
3
|
+
try {
|
|
4
|
+
execSync(`yarn up --fixed '@openmrs/*@next' 'openmrs@next'`, {
|
|
5
|
+
stdio: ['ignore', 'inherit', 'inherit'],
|
|
6
|
+
windowsHide: true,
|
|
7
|
+
});
|
|
8
|
+
} catch (error) {
|
|
9
|
+
console.error(`Error while updating dependencies: ${error.message ?? error}`);
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
execSync(`yarn dedupe`, {
|
|
15
|
+
stdio: ['ignore', 'inherit', 'inherit'],
|
|
16
|
+
windowsHide: true,
|
|
17
|
+
});
|
|
18
|
+
} catch (error) {
|
|
19
|
+
console.error(`Error while deduplicating dependencies: ${error.message ?? error}`);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
execSync(`git diff-index --quiet HEAD --`, {
|
|
25
|
+
stdio: 'ignore',
|
|
26
|
+
windowsHide: true,
|
|
27
|
+
});
|
|
28
|
+
process.exit(0);
|
|
29
|
+
} catch (error) {
|
|
30
|
+
// git diff-index --quite HEAD --
|
|
31
|
+
// exits with status 1 if there are changes; we only need to run yarn verify if there are changes
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
execSync(`yarn verify`, {
|
|
36
|
+
stdio: ['ignore', 'inherit', 'inherit'],
|
|
37
|
+
windowsHide: true,
|
|
38
|
+
});
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.error(`Error while running yarn verify: ${error.message ?? error}. Updates require manual intervention.`);
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|