@openmrs/esm-patient-common-lib 11.3.1-patch.9310 → 11.3.1-patch.9508
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/package.json +1 -1
- package/src/empty-state/empty-state.test.tsx +4 -4
- package/src/form-entry/form-entry.ts +2 -22
- package/src/form-entry-interop.ts +152 -0
- package/src/index.ts +1 -0
- package/src/launchStartVisitPrompt.tsx +1 -2
- package/src/orders/index.ts +2 -4
- package/src/orders/postOrders.ts +1 -1
- package/src/orders/types/order.ts +9 -109
- package/src/orders/useOrders.ts +5 -5
- package/src/store/patient-chart-store.ts +3 -3
- package/src/workspaces.ts +24 -48
- package/src/orders/showOrderSuccessToast.ts +0 -28
- package/src/orders/useMutatePatientOrders.ts +0 -24
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import userEvent from '@testing-library/user-event';
|
|
3
3
|
import { render, screen } from '@testing-library/react';
|
|
4
|
-
import {
|
|
4
|
+
import { launchWorkspace } from '@openmrs/esm-framework';
|
|
5
5
|
import { EmptyState } from '.';
|
|
6
6
|
|
|
7
|
-
const mockLaunchWorkspace = jest.mocked(
|
|
7
|
+
const mockLaunchWorkspace = jest.mocked(launchWorkspace);
|
|
8
8
|
|
|
9
9
|
describe('EmptyState', () => {
|
|
10
10
|
it('renders an empty state widget card', () => {
|
|
@@ -12,7 +12,7 @@ describe('EmptyState', () => {
|
|
|
12
12
|
<EmptyState
|
|
13
13
|
headerTitle="appointments"
|
|
14
14
|
displayText="appointments"
|
|
15
|
-
launchForm={() =>
|
|
15
|
+
launchForm={() => launchWorkspace('sample-form-workspace')}
|
|
16
16
|
/>,
|
|
17
17
|
);
|
|
18
18
|
|
|
@@ -28,7 +28,7 @@ describe('EmptyState', () => {
|
|
|
28
28
|
<EmptyState
|
|
29
29
|
headerTitle="appointments"
|
|
30
30
|
displayText="appointments"
|
|
31
|
-
launchForm={() =>
|
|
31
|
+
launchForm={() => launchWorkspace('sample-form-workspace')}
|
|
32
32
|
/>,
|
|
33
33
|
);
|
|
34
34
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type HtmlFormEntryForm } from '../types';
|
|
2
2
|
|
|
3
3
|
export interface FormEntryProps {
|
|
4
4
|
encounterUuid?: string;
|
|
@@ -7,26 +7,6 @@ export interface FormEntryProps {
|
|
|
7
7
|
visitTypeUuid?: string;
|
|
8
8
|
visitStartDatetime?: string;
|
|
9
9
|
visitStopDatetime?: string;
|
|
10
|
+
htmlForm?: HtmlFormEntryForm;
|
|
10
11
|
additionalProps?: Record<string, any>;
|
|
11
12
|
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Workspace control props are made optional to support usage in non-workspace contexts,
|
|
15
|
-
* such as the Fast Data Entry app or other standalone form zones.
|
|
16
|
-
*/
|
|
17
|
-
export interface FormRendererProps {
|
|
18
|
-
additionalProps?: Record<string, any>;
|
|
19
|
-
encounterUuid?: string;
|
|
20
|
-
formUuid: string;
|
|
21
|
-
patientUuid: string;
|
|
22
|
-
patient: fhir.Patient;
|
|
23
|
-
visit?: Visit;
|
|
24
|
-
visitUuid?: string;
|
|
25
|
-
hideControls?: boolean;
|
|
26
|
-
hidePatientBanner?: boolean;
|
|
27
|
-
handlePostResponse?: (encounter: Encounter) => void;
|
|
28
|
-
preFilledQuestions?: Record<string, string>;
|
|
29
|
-
launchChildWorkspace?: Workspace2DefinitionProps['launchChildWorkspace'];
|
|
30
|
-
closeWorkspace?: Workspace2DefinitionProps['closeWorkspace'];
|
|
31
|
-
setHasUnsavedChanges?(hasUnsavedChanges: boolean);
|
|
32
|
-
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { launchWorkspace } from '@openmrs/esm-framework';
|
|
2
|
+
import { type Form, type HtmlFormEntryForm } from './types';
|
|
3
|
+
import { launchStartVisitPrompt } from './launchStartVisitPrompt';
|
|
4
|
+
|
|
5
|
+
export const clinicalFormsWorkspace = 'clinical-forms-workspace';
|
|
6
|
+
export const formEntryWorkspace = 'patient-form-entry-workspace';
|
|
7
|
+
export const htmlFormEntryWorkspace = 'patient-html-form-entry-workspace';
|
|
8
|
+
|
|
9
|
+
const formEngineResourceName = 'formEngine';
|
|
10
|
+
const htmlformentryFormEngine = 'htmlformentry';
|
|
11
|
+
const uiStyleResourceName = 'uiStyle';
|
|
12
|
+
const uiStyleSimple = 'simple';
|
|
13
|
+
|
|
14
|
+
export function launchFormEntryOrHtmlForms(
|
|
15
|
+
htmlFormEntryForms: Array<HtmlFormEntryForm>,
|
|
16
|
+
patientUuid: string,
|
|
17
|
+
form: Form,
|
|
18
|
+
visitUuid?: string,
|
|
19
|
+
encounterUuid?: string,
|
|
20
|
+
visitTypeUuid?: string,
|
|
21
|
+
visitStartDatetime?: string,
|
|
22
|
+
visitStopDatetime?: string,
|
|
23
|
+
mutateForms?: () => void,
|
|
24
|
+
clinicalFormsWorkspaceName = clinicalFormsWorkspace,
|
|
25
|
+
formEntryWorkspaceName = formEntryWorkspace,
|
|
26
|
+
htmlFormEntryWorkspaceName = htmlFormEntryWorkspace,
|
|
27
|
+
) {
|
|
28
|
+
if (visitUuid) {
|
|
29
|
+
const { uuid: formUuid, display, name } = form ?? {};
|
|
30
|
+
const formName = display ?? name ?? '--';
|
|
31
|
+
|
|
32
|
+
const htmlForm = toHtmlForm(form, htmlFormEntryForms);
|
|
33
|
+
if (htmlForm) {
|
|
34
|
+
launchHtmlFormEntry(patientUuid, formName, encounterUuid, visitUuid, htmlForm, htmlFormEntryWorkspaceName);
|
|
35
|
+
} else {
|
|
36
|
+
launchFormEntry(
|
|
37
|
+
formUuid,
|
|
38
|
+
patientUuid,
|
|
39
|
+
encounterUuid,
|
|
40
|
+
formName,
|
|
41
|
+
visitUuid,
|
|
42
|
+
visitTypeUuid,
|
|
43
|
+
visitStartDatetime,
|
|
44
|
+
visitStopDatetime,
|
|
45
|
+
htmlForm,
|
|
46
|
+
mutateForms,
|
|
47
|
+
clinicalFormsWorkspaceName,
|
|
48
|
+
formEntryWorkspaceName,
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
} else {
|
|
52
|
+
launchStartVisitPrompt();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function launchFormEntry(
|
|
57
|
+
formUuid: string,
|
|
58
|
+
patientUuid: string,
|
|
59
|
+
encounterUuid?: string,
|
|
60
|
+
formName?: string,
|
|
61
|
+
visitUuid?: string,
|
|
62
|
+
visitTypeUuid?: string,
|
|
63
|
+
visitStartDatetime?: string,
|
|
64
|
+
visitStopDatetime?: string,
|
|
65
|
+
htmlForm?: HtmlFormEntryForm,
|
|
66
|
+
mutateForm?: () => void,
|
|
67
|
+
clinicalFormsWorkspaceName = clinicalFormsWorkspace,
|
|
68
|
+
formEntryWorkspaceName = formEntryWorkspace,
|
|
69
|
+
) {
|
|
70
|
+
launchWorkspace(formEntryWorkspaceName, {
|
|
71
|
+
workspaceTitle: formName,
|
|
72
|
+
clinicalFormsWorkspaceName,
|
|
73
|
+
formEntryWorkspaceName,
|
|
74
|
+
patientUuid,
|
|
75
|
+
mutateForm,
|
|
76
|
+
formInfo: {
|
|
77
|
+
encounterUuid,
|
|
78
|
+
formUuid,
|
|
79
|
+
patientUuid,
|
|
80
|
+
visitTypeUuid: visitTypeUuid,
|
|
81
|
+
visitUuid: visitUuid,
|
|
82
|
+
visitStartDatetime,
|
|
83
|
+
visitStopDatetime,
|
|
84
|
+
htmlForm,
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function launchHtmlFormEntry(
|
|
90
|
+
patientUuid: string,
|
|
91
|
+
formName: string,
|
|
92
|
+
encounterUuid: string,
|
|
93
|
+
visitUuid: string,
|
|
94
|
+
htmlForm: HtmlFormEntryForm,
|
|
95
|
+
workspaceName = htmlFormEntryWorkspace,
|
|
96
|
+
) {
|
|
97
|
+
launchWorkspace(workspaceName, {
|
|
98
|
+
workspaceTitle: formName,
|
|
99
|
+
patientUuid,
|
|
100
|
+
formInfo: {
|
|
101
|
+
encounterUuid,
|
|
102
|
+
visitUuid,
|
|
103
|
+
htmlForm,
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* For a given form , check if it is an HTML form. If it is, return the HtmlFormEntryForm object,
|
|
110
|
+
* otherwise return null
|
|
111
|
+
* @param form
|
|
112
|
+
* @param htmlFormEntryForms A list of HTML forms configured in @esm-patient-forms-app's config
|
|
113
|
+
*
|
|
114
|
+
* @returns
|
|
115
|
+
*/
|
|
116
|
+
function toHtmlForm(form: Form, htmlFormEntryForms: Array<HtmlFormEntryForm>): HtmlFormEntryForm {
|
|
117
|
+
const isHtmlForm =
|
|
118
|
+
htmlFormEntryForms?.some((hfeForm) => hfeForm.formUuid === form.uuid) ||
|
|
119
|
+
form.resources?.some((resource) => {
|
|
120
|
+
return resource.name === formEngineResourceName && resource.valueReference === htmlformentryFormEngine;
|
|
121
|
+
});
|
|
122
|
+
if (isHtmlForm) {
|
|
123
|
+
const hfeForm = htmlFormEntryForms?.find((f) => f.formUuid === form.uuid);
|
|
124
|
+
const simple = form.resources?.some((r) => r.name === uiStyleResourceName && r.valueReference === uiStyleSimple);
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
formUuid: form.uuid,
|
|
128
|
+
formName: hfeForm?.formName ?? form.display ?? form.name,
|
|
129
|
+
formUiResource: hfeForm?.formUiResource,
|
|
130
|
+
formUiPage: hfeForm?.formUiPage ?? (simple ? 'enterHtmlFormWithSimpleUi' : 'enterHtmlFormWithStandardUi'),
|
|
131
|
+
formEditUiPage: hfeForm?.formEditUiPage ?? (simple ? 'editHtmlFormWithSimpleUi' : 'editHtmlFormWithStandardUi'),
|
|
132
|
+
};
|
|
133
|
+
} else {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Given a list of forms and a list of HtmlFormEntryForm objects from configuration, return a List of HtmlFormEntryForm
|
|
140
|
+
* returned forms either
|
|
141
|
+
* a) have a form resource with a name of `formEngine` and a value of `htmlformentry, or
|
|
142
|
+
* b) have an entry in the HtmlFormEntryForm array for a given form uuid
|
|
143
|
+
* The HtmlFormEntryForm configuration provides a means to override the name and rendering mode of a given form
|
|
144
|
+
* @param allForms
|
|
145
|
+
* @param htmlFormEntryForms
|
|
146
|
+
*/
|
|
147
|
+
export function mapFormsToHtmlFormEntryForms(
|
|
148
|
+
allForms: Array<Form>,
|
|
149
|
+
htmlFormEntryForms: Array<HtmlFormEntryForm>,
|
|
150
|
+
): Array<HtmlFormEntryForm> {
|
|
151
|
+
return allForms?.map((form) => toHtmlForm(form, htmlFormEntryForms))?.filter((form) => form !== null);
|
|
152
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from './compare';
|
|
|
3
3
|
export * from './dashboards/createDashboardLink';
|
|
4
4
|
export * from './empty-state';
|
|
5
5
|
export * from './error-state';
|
|
6
|
+
export * from './form-entry-interop';
|
|
6
7
|
export * from './form-entry/form-entry';
|
|
7
8
|
export * from './launchStartVisitPrompt';
|
|
8
9
|
export * from './offline/visit';
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { showModal } from '@openmrs/esm-framework';
|
|
2
2
|
|
|
3
|
-
export
|
|
3
|
+
export function launchStartVisitPrompt() {
|
|
4
4
|
const dispose = showModal('start-visit-dialog', {
|
|
5
5
|
closeModal: () => dispose(),
|
|
6
|
-
onVisitStarted,
|
|
7
6
|
});
|
|
8
7
|
}
|
package/src/orders/index.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
+
export * from './useOrderBasket';
|
|
1
2
|
export * from './postOrders';
|
|
2
|
-
export * from './
|
|
3
|
+
export * from './useOrders';
|
|
3
4
|
export * from './types';
|
|
4
|
-
export * from './useMutatePatientOrders';
|
|
5
|
-
export * from './useOrderBasket';
|
|
6
5
|
export * from './useOrderableConceptSets';
|
|
7
|
-
export * from './useOrders';
|
|
8
6
|
export * from './useOrderType';
|
|
9
7
|
export * from './useOrderTypes';
|
package/src/orders/postOrders.ts
CHANGED
|
@@ -120,7 +120,7 @@ export async function postOrders(patientUuid: string, encounterUuid: string, abo
|
|
|
120
120
|
return erroredItems;
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
|
|
123
|
+
function postOrder(body: OrderPost, abortController?: AbortController) {
|
|
124
124
|
return openmrsFetch(`${restBaseUrl}/order`, {
|
|
125
125
|
method: 'POST',
|
|
126
126
|
signal: abortController?.signal,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { OpenmrsResource } from '@openmrs/esm-framework';
|
|
2
2
|
|
|
3
3
|
export interface Concept extends OpenmrsResource {
|
|
4
4
|
name?: {
|
|
@@ -71,8 +71,6 @@ export interface OrderBasketItem {
|
|
|
71
71
|
orderType?: string;
|
|
72
72
|
orderNumber?: string;
|
|
73
73
|
scheduledDate?: Date;
|
|
74
|
-
encounterUuid?: string;
|
|
75
|
-
visit: Visit;
|
|
76
74
|
}
|
|
77
75
|
|
|
78
76
|
export type OrderUrgency = 'ROUTINE' | 'STAT' | 'ON_SCHEDULED_DATE';
|
|
@@ -144,7 +142,7 @@ export interface Order {
|
|
|
144
142
|
drug: Drug;
|
|
145
143
|
duration: number;
|
|
146
144
|
durationUnits: OpenmrsResource;
|
|
147
|
-
encounter:
|
|
145
|
+
encounter: OpenmrsResource;
|
|
148
146
|
frequency: OpenmrsResource;
|
|
149
147
|
instructions?: string | null;
|
|
150
148
|
numRefills: number;
|
|
@@ -209,114 +207,16 @@ export interface OrderType {
|
|
|
209
207
|
description: string;
|
|
210
208
|
}
|
|
211
209
|
|
|
212
|
-
export type FulfillerStatus =
|
|
210
|
+
export type FulfillerStatus =
|
|
211
|
+
| 'RECEIVED'
|
|
212
|
+
| 'IN_PROGRESS'
|
|
213
|
+
| 'EXCEPTION'
|
|
214
|
+
| 'ON_HOLD'
|
|
215
|
+
| 'DECLINED'
|
|
216
|
+
| 'COMPLETED';
|
|
213
217
|
|
|
214
218
|
export type PostDataPrepFunction = (
|
|
215
219
|
order: OrderBasketItem,
|
|
216
220
|
patientUuid: string,
|
|
217
221
|
encounterUuid: string | null,
|
|
218
222
|
) => OrderPost;
|
|
219
|
-
|
|
220
|
-
export interface OrderBasketExtensionProps {
|
|
221
|
-
patient: fhir.Patient;
|
|
222
|
-
launchDrugOrderForm(order?: DrugOrderBasketItem): void;
|
|
223
|
-
launchLabOrderForm(orderTypeUuid: string, order?: TestOrderBasketItem): void;
|
|
224
|
-
launchGeneralOrderForm(orderTypeUuid: string, order?: OrderBasketItem): void;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
export interface DrugOrderBasketItem extends OrderBasketItem {
|
|
228
|
-
drug: Drug;
|
|
229
|
-
unit: DosingUnit;
|
|
230
|
-
commonMedicationName: string;
|
|
231
|
-
dosage: number;
|
|
232
|
-
frequency: MedicationFrequency;
|
|
233
|
-
route: MedicationRoute;
|
|
234
|
-
quantityUnits: QuantityUnit;
|
|
235
|
-
patientInstructions: string;
|
|
236
|
-
asNeeded: boolean;
|
|
237
|
-
asNeededCondition: string;
|
|
238
|
-
startDate: Date | string;
|
|
239
|
-
durationUnit: DurationUnit;
|
|
240
|
-
duration: number | null;
|
|
241
|
-
pillsDispensed: number | null;
|
|
242
|
-
numRefills: number | null;
|
|
243
|
-
indication: string;
|
|
244
|
-
isFreeTextDosage: boolean;
|
|
245
|
-
freeTextDosage: string;
|
|
246
|
-
previousOrder?: string;
|
|
247
|
-
template?: OrderTemplate;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
export interface DrugOrderTemplate {
|
|
251
|
-
uuid: string;
|
|
252
|
-
name: string;
|
|
253
|
-
drug: Drug;
|
|
254
|
-
template: OrderTemplate;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
export interface OrderTemplate {
|
|
258
|
-
type: string;
|
|
259
|
-
dosingType: string;
|
|
260
|
-
dosingInstructions: DosingInstructions;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
export interface DosingInstructions {
|
|
264
|
-
dose: Array<MedicationDosage>;
|
|
265
|
-
units: Array<DosingUnit>;
|
|
266
|
-
route: Array<MedicationRoute>;
|
|
267
|
-
frequency: Array<MedicationFrequency>;
|
|
268
|
-
instructions?: Array<MedicationInstructions>;
|
|
269
|
-
durationUnits?: Array<DurationUnit>;
|
|
270
|
-
quantityUnits?: Array<QuantityUnit>;
|
|
271
|
-
asNeeded?: boolean;
|
|
272
|
-
asNeededCondition?: string;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
export interface MedicationDosage extends Omit<CommonMedicationProps, 'value'> {
|
|
276
|
-
value: number;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
export type MedicationFrequency = CommonMedicationValueCoded;
|
|
280
|
-
|
|
281
|
-
export type MedicationRoute = CommonMedicationValueCoded;
|
|
282
|
-
|
|
283
|
-
export type MedicationInstructions = CommonMedicationProps;
|
|
284
|
-
|
|
285
|
-
export type DosingUnit = CommonMedicationValueCoded;
|
|
286
|
-
|
|
287
|
-
export type QuantityUnit = CommonMedicationValueCoded;
|
|
288
|
-
|
|
289
|
-
export type DurationUnit = CommonMedicationValueCoded;
|
|
290
|
-
|
|
291
|
-
interface CommonMedicationProps {
|
|
292
|
-
value: string;
|
|
293
|
-
default?: boolean;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
export interface CommonMedicationValueCoded extends CommonMedicationProps {
|
|
297
|
-
valueCoded: string;
|
|
298
|
-
names?: string[];
|
|
299
|
-
}
|
|
300
|
-
export interface TestOrderBasketItem extends OrderBasketItem {
|
|
301
|
-
testType: {
|
|
302
|
-
label: string;
|
|
303
|
-
conceptUuid: string;
|
|
304
|
-
};
|
|
305
|
-
orderReason?: string;
|
|
306
|
-
specimenSource?: string;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
export interface OrderBasketWindowProps {
|
|
310
|
-
encounterUuid: string;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
export interface ExportedOrderBasketWindowProps {
|
|
314
|
-
encounterUuid: string;
|
|
315
|
-
drugOrderWorkspaceName: string;
|
|
316
|
-
labOrderWorkspaceName: string;
|
|
317
|
-
generalOrderWorkspaceName: string;
|
|
318
|
-
patient: fhir.Patient;
|
|
319
|
-
patientUuid: string;
|
|
320
|
-
visitContext: Visit;
|
|
321
|
-
mutateVisitContext: () => void;
|
|
322
|
-
}
|
package/src/orders/useOrders.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useCallback, useMemo } from 'react';
|
|
2
2
|
import useSWR, { useSWRConfig } from 'swr';
|
|
3
3
|
import { type FetchResponse, openmrsFetch, restBaseUrl, translateFrom } from '@openmrs/esm-framework';
|
|
4
|
-
import type {
|
|
4
|
+
import type { PatientOrderFetchResponse, PriorityOption } from './types';
|
|
5
5
|
|
|
6
6
|
export type Status = 'ACTIVE' | 'any';
|
|
7
7
|
export const careSettingUuid = '6f0c9a92-6f24-11e3-af88-005056821db0';
|
|
@@ -10,7 +10,7 @@ const patientChartAppModuleName = '@openmrs/esm-patient-chart-app';
|
|
|
10
10
|
export const drugCustomRepresentation =
|
|
11
11
|
'custom:(uuid,dosingType,orderNumber,accessionNumber,' +
|
|
12
12
|
'patient:ref,action,careSetting:ref,previousOrder:ref,dateActivated,scheduledDate,dateStopped,autoExpireDate,' +
|
|
13
|
-
'orderType:ref,encounter:
|
|
13
|
+
'orderType:ref,encounter:ref,orderer:(uuid,display,person:(display)),orderReason,orderReasonNonCoded,orderType,urgency,instructions,' +
|
|
14
14
|
'commentToFulfiller,drug:(uuid,display,strength,dosageForm:(display,uuid),concept),dose,doseUnits:ref,' +
|
|
15
15
|
'frequency:ref,asNeeded,asNeededCondition,quantity,quantityUnits:ref,numRefills,dosingInstructions,' +
|
|
16
16
|
'duration,durationUnits:ref,route:ref,brandName,dispenseAsWritten)';
|
|
@@ -25,8 +25,8 @@ export function usePatientOrders(
|
|
|
25
25
|
const { mutate } = useSWRConfig();
|
|
26
26
|
const baseOrdersUrl =
|
|
27
27
|
startDate && endDate
|
|
28
|
-
? `${restBaseUrl}/order?patient=${patientUuid}&careSetting=${careSettingUuid}&v=default&activatedOnOrAfterDate=${startDate}&activatedOnOrBeforeDate=${endDate}`
|
|
29
|
-
: `${restBaseUrl}/order?patient=${patientUuid}&careSetting=${careSettingUuid}&v=default&status=${status}`;
|
|
28
|
+
? `${restBaseUrl}/order?patient=${patientUuid}&careSetting=${careSettingUuid}&v=default&activatedOnOrAfterDate=${startDate}&activatedOnOrBeforeDate=${endDate}&excludeDiscontinueOrders=true`
|
|
29
|
+
: `${restBaseUrl}/order?patient=${patientUuid}&careSetting=${careSettingUuid}&v=default&status=${status}&excludeDiscontinueOrders=true`;
|
|
30
30
|
const ordersUrl = orderType ? `${baseOrdersUrl}&orderTypes=${orderType}` : baseOrdersUrl;
|
|
31
31
|
|
|
32
32
|
const { data, error, isLoading, isValidating } = useSWR<FetchResponse<PatientOrderFetchResponse>, Error>(
|
|
@@ -60,7 +60,7 @@ export function usePatientOrders(
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
export function getDrugOrderByUuid(orderUuid: string) {
|
|
63
|
-
return openmrsFetch
|
|
63
|
+
return openmrsFetch(`${restBaseUrl}/order/${orderUuid}?v=${drugCustomRepresentation}`);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
// See the Urgency enum in https://github.com/openmrs/openmrs-core/blob/492dcd35b85d48730bd19da48f6db146cc882c22/api/src/main/java/org/openmrs/Order.java
|
|
@@ -16,7 +16,7 @@ const patientChartStore = createGlobalStore<PatientChartStore>(patientChartStore
|
|
|
16
16
|
mutateVisitContext: null,
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
-
const
|
|
19
|
+
const patientChartStoreActions = {
|
|
20
20
|
setPatient(_, patient: fhir.Patient) {
|
|
21
21
|
return { patient, patientUuid: patient?.id ?? null };
|
|
22
22
|
},
|
|
@@ -33,11 +33,11 @@ const patientCharStoreActions = {
|
|
|
33
33
|
* the clinical forms workspace in the ward app)
|
|
34
34
|
* should have the patient / visitContext explicitly passed in as props.
|
|
35
35
|
*
|
|
36
|
-
* As a safety feature, this hook requires the
|
|
36
|
+
* As a safety feature, this hook requires the patientUuid as the input, and only
|
|
37
37
|
* returns the actual store values if input patientUuid matches that in the store.
|
|
38
38
|
*/
|
|
39
39
|
export function usePatientChartStore(patientUuid: string) {
|
|
40
|
-
const store = useStoreWithActions(patientChartStore,
|
|
40
|
+
const store = useStoreWithActions(patientChartStore, patientChartStoreActions);
|
|
41
41
|
if (store.patientUuid === patientUuid) {
|
|
42
42
|
return store;
|
|
43
43
|
} else {
|
package/src/workspaces.ts
CHANGED
|
@@ -1,29 +1,23 @@
|
|
|
1
1
|
import { useCallback } from 'react';
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
type DefaultWorkspaceProps,
|
|
4
|
+
launchWorkspace,
|
|
5
|
+
navigateAndLaunchWorkspace,
|
|
5
6
|
showModal,
|
|
6
7
|
useFeatureFlag,
|
|
7
8
|
type Visit,
|
|
8
|
-
type Workspace2DefinitionProps,
|
|
9
9
|
} from '@openmrs/esm-framework';
|
|
10
|
+
import { launchStartVisitPrompt } from './launchStartVisitPrompt';
|
|
10
11
|
import { usePatientChartStore } from './store/patient-chart-store';
|
|
11
12
|
import { useSystemVisitSetting } from './useSystemVisitSetting';
|
|
12
13
|
|
|
13
|
-
export interface
|
|
14
|
+
export interface DefaultPatientWorkspaceProps extends DefaultWorkspaceProps {
|
|
14
15
|
patient: fhir.Patient;
|
|
15
16
|
patientUuid: string;
|
|
16
17
|
visitContext: Visit;
|
|
17
18
|
mutateVisitContext: () => void;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
export interface PatientChartWorkspaceActionButtonProps {
|
|
21
|
-
groupProps: PatientWorkspaceGroupProps;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface PatientWorkspace2DefinitionProps<WorkspaceProps extends Object, WindowProps extends Object>
|
|
25
|
-
extends Workspace2DefinitionProps<WorkspaceProps, WindowProps, PatientWorkspaceGroupProps> {}
|
|
26
|
-
|
|
27
21
|
export function launchPatientChartWithWorkspaceOpen({
|
|
28
22
|
patientUuid,
|
|
29
23
|
workspaceName,
|
|
@@ -35,55 +29,37 @@ export function launchPatientChartWithWorkspaceOpen({
|
|
|
35
29
|
dashboardName?: string;
|
|
36
30
|
additionalProps?: object;
|
|
37
31
|
}) {
|
|
38
|
-
|
|
39
|
-
|
|
32
|
+
navigateAndLaunchWorkspace({
|
|
33
|
+
targetUrl: '${openmrsSpaBase}/patient/' + `${patientUuid}/chart` + (dashboardName ? `/${dashboardName}` : ''),
|
|
34
|
+
workspaceName: workspaceName,
|
|
35
|
+
contextKey: `patient/${patientUuid}`,
|
|
36
|
+
additionalProps,
|
|
37
|
+
});
|
|
40
38
|
}
|
|
41
39
|
|
|
42
40
|
export function useLaunchWorkspaceRequiringVisit<T extends object>(patientUuid: string, workspaceName: string) {
|
|
43
|
-
const startVisitIfNeeded = useStartVisitIfNeeded(patientUuid);
|
|
44
|
-
const launchPatientWorkspaceCb = useCallback(
|
|
45
|
-
(workspaceProps?: T, windowProps?: any, groupProps?: any) => {
|
|
46
|
-
startVisitIfNeeded().then((didStartVisit) => {
|
|
47
|
-
if (didStartVisit) {
|
|
48
|
-
launchWorkspace2(workspaceName, workspaceProps, windowProps);
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
},
|
|
52
|
-
[startVisitIfNeeded, workspaceName],
|
|
53
|
-
);
|
|
54
|
-
return launchPatientWorkspaceCb;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export function useStartVisitIfNeeded(patientUuid: string) {
|
|
58
41
|
const { visitContext } = usePatientChartStore(patientUuid);
|
|
59
42
|
const { systemVisitEnabled } = useSystemVisitSetting();
|
|
60
43
|
const isRdeEnabled = useFeatureFlag('rde');
|
|
61
44
|
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
45
|
+
const launchPatientWorkspaceCb = useCallback(
|
|
46
|
+
(additionalProps?: T) => {
|
|
47
|
+
if (!systemVisitEnabled || visitContext) {
|
|
48
|
+
launchWorkspace(workspaceName, additionalProps);
|
|
49
|
+
} else {
|
|
67
50
|
if (isRdeEnabled) {
|
|
68
51
|
const dispose = showModal('visit-context-switcher', {
|
|
69
52
|
patientUuid,
|
|
70
|
-
closeModal: () =>
|
|
71
|
-
|
|
72
|
-
resolve(false);
|
|
73
|
-
},
|
|
74
|
-
onAfterVisitSelected: () => {
|
|
75
|
-
resolve(true);
|
|
76
|
-
},
|
|
53
|
+
closeModal: () => dispose(),
|
|
54
|
+
onAfterVisitSelected: () => launchWorkspace(workspaceName, additionalProps),
|
|
77
55
|
size: 'sm',
|
|
78
56
|
});
|
|
79
57
|
} else {
|
|
80
|
-
|
|
81
|
-
closeModal: () => dispose(),
|
|
82
|
-
onVisitStarted: () => resolve(true),
|
|
83
|
-
});
|
|
58
|
+
launchStartVisitPrompt();
|
|
84
59
|
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
[visitContext, systemVisitEnabled, workspaceName, isRdeEnabled, patientUuid],
|
|
63
|
+
);
|
|
64
|
+
return launchPatientWorkspaceCb;
|
|
89
65
|
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { showSnackbar } from '@openmrs/esm-framework';
|
|
2
|
-
import { type TFunction } from 'i18next';
|
|
3
|
-
import { type OrderBasketItem } from './types';
|
|
4
|
-
|
|
5
|
-
export function showOrderSuccessToast(t: TFunction, patientOrderItems: OrderBasketItem[]) {
|
|
6
|
-
const orderedString = patientOrderItems
|
|
7
|
-
.filter((item) => ['NEW', 'RENEW'].includes(item.action))
|
|
8
|
-
.map((item) => item.display)
|
|
9
|
-
.join(', ');
|
|
10
|
-
const updatedString = patientOrderItems
|
|
11
|
-
.filter((item) => item.action === 'REVISE')
|
|
12
|
-
.map((item) => item.display)
|
|
13
|
-
.join(', ');
|
|
14
|
-
const discontinuedString = patientOrderItems
|
|
15
|
-
.filter((item) => item.action === 'DISCONTINUE')
|
|
16
|
-
.map((item) => item.display)
|
|
17
|
-
.join(', ');
|
|
18
|
-
|
|
19
|
-
showSnackbar({
|
|
20
|
-
isLowContrast: true,
|
|
21
|
-
kind: 'success',
|
|
22
|
-
title: t('orderCompleted', 'Placed orders'),
|
|
23
|
-
subtitle:
|
|
24
|
-
(orderedString && `${t('ordered', 'Placed order for')} ${orderedString}. `) +
|
|
25
|
-
(updatedString && `${t('updated', 'Updated')} ${updatedString}. `) +
|
|
26
|
-
(discontinuedString && `${t('discontinued', 'Discontinued')} ${discontinuedString}.`),
|
|
27
|
-
});
|
|
28
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { restBaseUrl } from '@openmrs/esm-framework';
|
|
2
|
-
import { useCallback } from 'react';
|
|
3
|
-
import { useSWRConfig } from 'swr';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Returns a function which refreshes the patient orders cache. Uses SWR's mutate function.
|
|
7
|
-
* Refreshes patient orders for all kinds of orders.
|
|
8
|
-
*
|
|
9
|
-
* @param patientUuid The UUID of the patient to get an order mutate function for.
|
|
10
|
-
*/
|
|
11
|
-
export function useMutatePatientOrders(patientUuid: string) {
|
|
12
|
-
const { mutate } = useSWRConfig();
|
|
13
|
-
const mutateOrders = useCallback(
|
|
14
|
-
() =>
|
|
15
|
-
mutate((key) => {
|
|
16
|
-
return typeof key === 'string' && key.startsWith(`${restBaseUrl}/order?patient=${patientUuid}`);
|
|
17
|
-
}),
|
|
18
|
-
[patientUuid, mutate],
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
return {
|
|
22
|
-
mutate: mutateOrders,
|
|
23
|
-
};
|
|
24
|
-
}
|