@openmrs/esm-patient-programs-app 3.2.1-pre.211 → 3.2.1-pre.219
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/.turbo/turbo-build.log +34 -36
- package/dist/109.js +1 -0
- package/dist/13.js +1 -0
- package/dist/145.js +1 -1
- package/dist/154.js +2 -0
- package/dist/154.js.LICENSE.txt +53 -0
- package/dist/238.js +2 -0
- package/dist/{707.js.LICENSE.txt → 238.js.LICENSE.txt} +0 -0
- package/dist/340.js +1 -0
- package/dist/435.js +1 -1
- package/dist/461.js +1 -0
- package/dist/574.js +1 -1
- package/dist/709.js +1 -0
- package/dist/784.js +1 -1
- package/dist/784.js.LICENSE.txt +2 -7
- package/dist/858.js +1 -1
- package/dist/main.js +1 -0
- package/dist/openmrs-esm-patient-programs-app.js +1 -1
- package/dist/openmrs-esm-patient-programs-app.js.buildmanifest.json +128 -223
- package/dist/openmrs-esm-patient-programs-app.old +1 -1
- package/package.json +6 -10
- package/src/index.ts +1 -1
- package/src/programs/program-action-button/program-action-button.component.tsx +4 -4
- package/src/programs/programs-detailed-summary.component.tsx +42 -51
- package/src/programs/programs-detailed-summary.scss +1 -4
- package/src/programs/programs-detailed-summary.test.tsx +15 -5
- package/src/programs/programs-form.component.tsx +11 -10
- package/src/programs/programs-form.scss +1 -9
- package/src/programs/programs-form.test.tsx +104 -196
- package/src/programs/programs-overview.component.tsx +33 -39
- package/src/programs/programs-overview.scss +1 -3
- package/src/programs/programs-overview.test.tsx +6 -7
- package/translations/en.json +1 -1
- package/dist/186.js +0 -2
- package/dist/186.js.LICENSE.txt +0 -23
- package/dist/336.js +0 -2
- package/dist/336.js.LICENSE.txt +0 -20
- package/dist/337.js +0 -1
- package/dist/402.js +0 -1
- package/dist/478.js +0 -2
- package/dist/478.js.LICENSE.txt +0 -8
- package/dist/499.js +0 -1
- package/dist/60.js +0 -1
- package/dist/635.js +0 -2
- package/dist/635.js.LICENSE.txt +0 -16
- package/dist/692.js +0 -1
- package/dist/701.js +0 -1
- package/dist/707.js +0 -2
- package/dist/93.js +0 -1
- package/dist/963.js +0 -2
- package/dist/963.js.LICENSE.txt +0 -23
|
@@ -1,27 +1,20 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { throwError } from 'rxjs';
|
|
3
3
|
import { of } from 'rxjs/internal/observable/of';
|
|
4
|
-
import {
|
|
4
|
+
import { render, screen, waitFor, within } from '@testing-library/react';
|
|
5
5
|
import userEvent from '@testing-library/user-event';
|
|
6
|
-
import {
|
|
7
|
-
createErrorHandler,
|
|
8
|
-
formatDate,
|
|
9
|
-
openmrsFetch,
|
|
10
|
-
parseDate,
|
|
11
|
-
showNotification,
|
|
12
|
-
showToast,
|
|
13
|
-
useLayoutType,
|
|
14
|
-
} from '@openmrs/esm-framework';
|
|
6
|
+
import { createErrorHandler, openmrsFetch, showNotification, showToast } from '@openmrs/esm-framework';
|
|
15
7
|
import { mockPatient } from '../../../../__mocks__/patient.mock';
|
|
16
8
|
import {
|
|
17
9
|
mockCareProgramsResponse,
|
|
18
10
|
mockEnrolledProgramsResponse,
|
|
19
11
|
mockLocationsResponse,
|
|
20
|
-
mockProgramResponse,
|
|
21
12
|
} from '../../../../__mocks__/programs.mock';
|
|
22
13
|
import { createProgramEnrollment, updateProgramEnrollment } from './programs.resource';
|
|
23
14
|
import ProgramsForm from './programs-form.component';
|
|
24
15
|
|
|
16
|
+
jest.setTimeout(20000);
|
|
17
|
+
|
|
25
18
|
const testProps = {
|
|
26
19
|
closeWorkspace: jest.fn(),
|
|
27
20
|
patientUuid: mockPatient.id,
|
|
@@ -34,7 +27,6 @@ const mockUpdateProgramEnrollment = updateProgramEnrollment as jest.Mock;
|
|
|
34
27
|
const mockOpenmrsFetch = openmrsFetch as jest.Mock;
|
|
35
28
|
const mockShowNotification = showNotification as jest.Mock;
|
|
36
29
|
const mockShowToast = showToast as jest.Mock;
|
|
37
|
-
const mockUseLayoutType = useLayoutType as jest.Mock;
|
|
38
30
|
|
|
39
31
|
jest.mock('@openmrs/esm-framework', () => {
|
|
40
32
|
const originalModule = jest.requireActual('@openmrs/esm-framework');
|
|
@@ -58,219 +50,135 @@ jest.mock('./programs.resource', () => {
|
|
|
58
50
|
};
|
|
59
51
|
});
|
|
60
52
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
} else if (/program/.test(url)) {
|
|
65
|
-
return { data: { results: mockCareProgramsResponse } };
|
|
66
|
-
} else {
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
});
|
|
53
|
+
describe('ProgramsForm', () => {
|
|
54
|
+
it('renders a success toast notification upon successfully recording a program enrollment', async () => {
|
|
55
|
+
const user = userEvent.setup();
|
|
70
56
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
renderProgramsForm();
|
|
57
|
+
const inpatientWardUuid = 'b1a8b05e-3542-4037-bbd3-998ee9c40574';
|
|
58
|
+
const oncologyScreeningProgramUuid = '11b129ca-a5e7-4025-84bf-b92a173e20de';
|
|
74
59
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
expect(screen.getByRole('option', { name: /Oncology Screening and Diagnosis/i })).toBeInTheDocument();
|
|
81
|
-
expect(screen.getByRole('option', { name: /Choose a location/i })).toBeInTheDocument();
|
|
82
|
-
expect(screen.getByRole('option', { name: /Amani Hospital/i })).toBeInTheDocument();
|
|
83
|
-
expect(screen.getByRole('option', { name: /Inpatient Ward/i })).toBeInTheDocument();
|
|
84
|
-
expect(screen.getByRole('option', { name: /Isolation Ward/i })).toBeInTheDocument();
|
|
85
|
-
expect(screen.getByRole('option', { name: /Laboratory/i })).toBeInTheDocument();
|
|
60
|
+
mockOpenmrsFetch.mockReturnValueOnce({ data: { results: mockCareProgramsResponse } });
|
|
61
|
+
mockOpenmrsFetch.mockReturnValueOnce({ data: { results: mockEnrolledProgramsResponse } });
|
|
62
|
+
mockCreateProgramEnrollment.mockReturnValueOnce(of({ status: 201, statusText: 'Created' }));
|
|
63
|
+
|
|
64
|
+
renderProgramsForm();
|
|
86
65
|
|
|
87
|
-
const cancelButton = screen.getByRole('button', { name: /cancel/i });
|
|
88
66
|
const enrollButton = screen.getByRole('button', { name: /save and close/i });
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
});
|
|
67
|
+
const enrollmentDateInput = screen.getAllByRole('textbox', { name: '' })[0];
|
|
68
|
+
const selectLocationInput = screen.getAllByRole('combobox', { name: '' })[1];
|
|
69
|
+
const selectProgramInput = screen.getAllByRole('combobox', { name: '' })[0];
|
|
93
70
|
|
|
94
|
-
|
|
95
|
-
|
|
71
|
+
await waitFor(() => user.type(enrollmentDateInput, '2020-05-05'));
|
|
72
|
+
await waitFor(() => user.selectOptions(selectProgramInput, [oncologyScreeningProgramUuid]));
|
|
73
|
+
await waitFor(() => user.selectOptions(selectLocationInput, [inpatientWardUuid]));
|
|
96
74
|
|
|
97
|
-
|
|
98
|
-
expect(within(programSelect).getByRole('option', { name: /HIV Care and Treatment/ })).toBeInTheDocument();
|
|
99
|
-
expect(within(programSelect).getAllByRole('option').length).toBe(1);
|
|
75
|
+
expect(screen.getByRole('option', { name: /Inpatient Ward/i })).toBeInTheDocument();
|
|
100
76
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
expect(
|
|
77
|
+
await waitFor(() => user.click(enrollButton));
|
|
78
|
+
|
|
79
|
+
expect(mockCreateProgramEnrollment).toHaveBeenCalledTimes(1);
|
|
80
|
+
expect(mockCreateProgramEnrollment).toHaveBeenCalledWith(
|
|
81
|
+
expect.objectContaining({
|
|
82
|
+
dateCompleted: null,
|
|
83
|
+
location: inpatientWardUuid,
|
|
84
|
+
patient: mockPatient.id,
|
|
85
|
+
program: oncologyScreeningProgramUuid,
|
|
86
|
+
}),
|
|
87
|
+
new AbortController(),
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
expect(mockShowToast).toHaveBeenCalledTimes(1);
|
|
91
|
+
expect(mockShowToast).toHaveBeenCalledWith({
|
|
92
|
+
critical: true,
|
|
93
|
+
description: 'It is now visible in the Programs table',
|
|
94
|
+
kind: 'success',
|
|
95
|
+
title: 'Program enrollment saved',
|
|
96
|
+
});
|
|
97
|
+
});
|
|
105
98
|
|
|
106
|
-
|
|
99
|
+
it('updates a program enrollment', async () => {
|
|
100
|
+
const user = userEvent.setup();
|
|
107
101
|
|
|
108
|
-
|
|
109
|
-
const locationSelect = within(enrollmentLocation).getByRole('combobox');
|
|
110
|
-
const amani = screen.getByRole('option', { name: /Amani Hospital/i });
|
|
111
|
-
expect(amani).toBeInTheDocument();
|
|
112
|
-
expect(locationSelect).toHaveValue(mockLocationsResponse[0].uuid);
|
|
113
|
-
expect(screen.getByRole('option', { name: /Inpatient Ward/i })).toBeInTheDocument();
|
|
114
|
-
expect(screen.getByRole('option', { name: /Isolation Ward/i })).toBeInTheDocument();
|
|
115
|
-
expect(screen.getByRole('option', { name: /Laboratory/i })).toBeInTheDocument();
|
|
102
|
+
renderProgramsForm(mockEnrolledProgramsResponse[0].uuid);
|
|
116
103
|
|
|
117
|
-
const cancelButton = screen.getByRole('button', { name: /cancel/i });
|
|
118
104
|
const enrollButton = screen.getByRole('button', { name: /save and close/i });
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
expect(enrollButton).not.toBeDisabled();
|
|
122
|
-
});
|
|
105
|
+
const dateCompletedGroup = screen.getByRole('group', { name: /Date completed/i });
|
|
106
|
+
const dateCompletedInput = within(dateCompletedGroup).getByRole('textbox');
|
|
123
107
|
|
|
124
|
-
|
|
125
|
-
renderProgramsForm();
|
|
108
|
+
mockUpdateProgramEnrollment.mockReturnValueOnce(of({ status: 200, statusText: 'OK' }));
|
|
126
109
|
|
|
127
|
-
|
|
128
|
-
userEvent.click(cancelButton);
|
|
110
|
+
await waitFor(() => user.type(dateCompletedInput, '05/05/2020'));
|
|
129
111
|
|
|
130
|
-
expect(
|
|
131
|
-
});
|
|
112
|
+
expect(dateCompletedInput).toHaveValue('05/05/2020');
|
|
132
113
|
|
|
133
|
-
|
|
134
|
-
mockUseLayoutType.mockReturnValueOnce('tablet').mockReturnValueOnce('tablet');
|
|
114
|
+
await waitFor(() => user.tab());
|
|
135
115
|
|
|
136
|
-
|
|
116
|
+
expect(enrollButton).not.toBeDisabled();
|
|
137
117
|
|
|
138
|
-
|
|
139
|
-
|
|
118
|
+
await waitFor(() => user.click(enrollButton));
|
|
119
|
+
|
|
120
|
+
expect(mockUpdateProgramEnrollment).toHaveBeenCalledTimes(1);
|
|
121
|
+
expect(mockUpdateProgramEnrollment).toHaveBeenCalledWith(
|
|
122
|
+
mockEnrolledProgramsResponse[0].uuid,
|
|
123
|
+
expect.objectContaining({
|
|
124
|
+
dateEnrolled: '2020-01-16T00:00:00+00:00',
|
|
125
|
+
dateCompleted: '2020-05-05T00:00:00+00:00',
|
|
126
|
+
location: mockEnrolledProgramsResponse[0].location.uuid,
|
|
127
|
+
patient: mockPatient.id,
|
|
128
|
+
program: mockEnrolledProgramsResponse[0].program.uuid,
|
|
129
|
+
}),
|
|
130
|
+
new AbortController(),
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
expect(mockShowToast).toHaveBeenCalledWith(
|
|
134
|
+
expect.objectContaining({
|
|
135
|
+
critical: true,
|
|
136
|
+
description: 'Changes to the program are now visible in the Programs table',
|
|
137
|
+
kind: 'success',
|
|
138
|
+
title: 'Program enrollment updated',
|
|
139
|
+
}),
|
|
140
|
+
);
|
|
140
141
|
});
|
|
141
142
|
|
|
142
|
-
|
|
143
|
+
it('renders an error notification if there was a problem recording a program enrollment', async () => {
|
|
144
|
+
const user = userEvent.setup();
|
|
145
|
+
|
|
143
146
|
const inpatientWardUuid = 'b1a8b05e-3542-4037-bbd3-998ee9c40574';
|
|
144
147
|
const oncologyScreeningProgramUuid = '11b129ca-a5e7-4025-84bf-b92a173e20de';
|
|
145
148
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
+
const error = {
|
|
150
|
+
message: 'Internal Server Error',
|
|
151
|
+
response: {
|
|
152
|
+
status: 500,
|
|
153
|
+
statusText: 'Internal Server Error',
|
|
154
|
+
},
|
|
155
|
+
};
|
|
149
156
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
const cancelButton = screen.getByRole('button', { name: /cancel/i });
|
|
154
|
-
const enrollButton = screen.getByRole('button', { name: /save and close/i });
|
|
155
|
-
const enrollmentDateInput = screen.getAllByRole('textbox', { name: '' })[0];
|
|
156
|
-
const selectLocationInput = screen.getAllByRole('combobox', { name: '' })[1];
|
|
157
|
-
const selectProgramInput = screen.getAllByRole('combobox', { name: '' })[0];
|
|
158
|
-
|
|
159
|
-
mockCreateProgramEnrollment.mockReturnValueOnce(of({ status: 201, statusText: 'Created' }));
|
|
160
|
-
|
|
161
|
-
userEvent.selectOptions(selectProgramInput, [oncologyScreeningProgramUuid]);
|
|
162
|
-
userEvent.selectOptions(selectLocationInput, [inpatientWardUuid]);
|
|
163
|
-
userEvent.clear(enrollmentDateInput);
|
|
164
|
-
userEvent.type(enrollmentDateInput, '05/05/2020');
|
|
165
|
-
fireEvent.blur(enrollmentDateInput);
|
|
166
|
-
|
|
167
|
-
expect(screen.getByDisplayValue('Oncology Screening and Diagnosis')).toBeInTheDocument();
|
|
168
|
-
expect(screen.getByDisplayValue('Inpatient Ward')).toBeInTheDocument();
|
|
169
|
-
expect(enrollButton).not.toBeDisabled();
|
|
170
|
-
|
|
171
|
-
await waitFor(() => userEvent.click(enrollButton));
|
|
172
|
-
|
|
173
|
-
expect(mockCreateProgramEnrollment).toHaveBeenCalledTimes(1);
|
|
174
|
-
expect(mockCreateProgramEnrollment).toHaveBeenCalledWith(
|
|
175
|
-
expect.objectContaining({
|
|
176
|
-
dateEnrolled: '2020-05-05T00:00:00+00:00',
|
|
177
|
-
dateCompleted: null,
|
|
178
|
-
location: inpatientWardUuid,
|
|
179
|
-
patient: mockPatient.id,
|
|
180
|
-
program: oncologyScreeningProgramUuid,
|
|
181
|
-
}),
|
|
182
|
-
new AbortController(),
|
|
183
|
-
);
|
|
184
|
-
|
|
185
|
-
expect(mockShowToast).toHaveBeenCalledTimes(1);
|
|
186
|
-
expect(mockShowToast).toHaveBeenCalledWith(
|
|
187
|
-
expect.objectContaining({
|
|
188
|
-
critical: true,
|
|
189
|
-
description: 'It is now visible in the Programs table',
|
|
190
|
-
kind: 'success',
|
|
191
|
-
title: 'Program enrollment saved',
|
|
192
|
-
}),
|
|
193
|
-
);
|
|
194
|
-
});
|
|
157
|
+
mockOpenmrsFetch.mockReturnValueOnce({ data: { results: mockCareProgramsResponse } });
|
|
158
|
+
mockOpenmrsFetch.mockReturnValueOnce({ data: { results: mockEnrolledProgramsResponse } });
|
|
159
|
+
mockCreateProgramEnrollment.mockReturnValueOnce(throwError(error));
|
|
195
160
|
|
|
196
|
-
|
|
197
|
-
renderProgramsForm(mockEnrolledProgramsResponse[0].uuid);
|
|
198
|
-
|
|
199
|
-
const enrollButton = screen.getByRole('button', { name: /save and close/i });
|
|
200
|
-
const dateCompletedGroup = screen.getByRole('group', { name: /Date completed/i });
|
|
201
|
-
const dateCompletedInput = within(dateCompletedGroup).getByRole('textbox');
|
|
202
|
-
|
|
203
|
-
mockUpdateProgramEnrollment.mockReturnValueOnce(of({ status: 200, statusText: 'OK' }));
|
|
204
|
-
|
|
205
|
-
userEvent.type(dateCompletedInput, '05/05/2020');
|
|
206
|
-
expect(dateCompletedInput).toHaveValue('05/05/2020');
|
|
207
|
-
fireEvent.blur(dateCompletedInput);
|
|
208
|
-
|
|
209
|
-
expect(enrollButton).not.toBeDisabled();
|
|
210
|
-
|
|
211
|
-
await waitFor(() => userEvent.click(enrollButton));
|
|
212
|
-
|
|
213
|
-
expect(mockUpdateProgramEnrollment).toHaveBeenCalledTimes(1);
|
|
214
|
-
expect(mockUpdateProgramEnrollment).toHaveBeenCalledWith(
|
|
215
|
-
mockEnrolledProgramsResponse[0].uuid,
|
|
216
|
-
expect.objectContaining({
|
|
217
|
-
dateEnrolled: '2020-01-16T00:00:00+00:00',
|
|
218
|
-
dateCompleted: '2020-05-05T00:00:00+00:00',
|
|
219
|
-
location: mockEnrolledProgramsResponse[0].location.uuid,
|
|
220
|
-
patient: mockPatient.id,
|
|
221
|
-
program: mockEnrolledProgramsResponse[0].program.uuid,
|
|
222
|
-
}),
|
|
223
|
-
new AbortController(),
|
|
224
|
-
);
|
|
225
|
-
|
|
226
|
-
expect(mockShowToast).toHaveBeenCalledTimes(1);
|
|
227
|
-
expect(mockShowToast).toHaveBeenCalledWith(
|
|
228
|
-
expect.objectContaining({
|
|
229
|
-
critical: true,
|
|
230
|
-
description: 'Changes to the program are now visible in the Programs table',
|
|
231
|
-
kind: 'success',
|
|
232
|
-
title: 'Program enrollment updated',
|
|
233
|
-
}),
|
|
234
|
-
);
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
xit('renders an error notification if there was a problem recording a program enrollment', async () => {
|
|
238
|
-
renderProgramsForm();
|
|
239
|
-
|
|
240
|
-
const cancelButton = screen.getByRole('button', { name: /cancel/i });
|
|
241
|
-
const enrollButton = screen.getByRole('button', { name: /save and close/i });
|
|
242
|
-
const enrollmentDateInput = screen.getAllByRole('textbox', { name: '' })[0];
|
|
243
|
-
const selectLocationInput = screen.getAllByRole('combobox', { name: '' })[1];
|
|
244
|
-
const selectProgramInput = screen.getAllByRole('combobox', { name: '' })[0];
|
|
245
|
-
|
|
246
|
-
const error = {
|
|
247
|
-
message: 'Internal Server Error',
|
|
248
|
-
response: {
|
|
249
|
-
status: 500,
|
|
250
|
-
statusText: 'Internal Server Error',
|
|
251
|
-
},
|
|
252
|
-
};
|
|
161
|
+
renderProgramsForm();
|
|
253
162
|
|
|
254
|
-
|
|
163
|
+
const enrollButton = screen.getByRole('button', { name: /save and close/i });
|
|
164
|
+
const enrollmentDateInput = screen.getAllByRole('textbox', { name: '' })[0];
|
|
165
|
+
const selectLocationInput = screen.getAllByRole('combobox', { name: '' })[1];
|
|
166
|
+
const selectProgramInput = screen.getAllByRole('combobox', { name: '' })[0];
|
|
255
167
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
168
|
+
await waitFor(() => user.type(enrollmentDateInput, '2020-05-05'));
|
|
169
|
+
await waitFor(() => user.selectOptions(selectProgramInput, [oncologyScreeningProgramUuid]));
|
|
170
|
+
await waitFor(() => user.selectOptions(selectLocationInput, [inpatientWardUuid]));
|
|
259
171
|
|
|
260
|
-
|
|
261
|
-
expect(screen.getByDisplayValue('2020-05-05')).toBeInTheDocument();
|
|
262
|
-
expect(screen.getByDisplayValue('Inpatient Ward')).toBeInTheDocument();
|
|
263
|
-
expect(enrollButton).not.toBeDisabled();
|
|
172
|
+
expect(enrollButton).not.toBeDisabled();
|
|
264
173
|
|
|
265
|
-
|
|
174
|
+
await waitFor(() => user.click(enrollButton));
|
|
266
175
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
});
|
|
176
|
+
expect(mockCreateErrorHandler).toHaveBeenCalledTimes(1);
|
|
177
|
+
expect(mockShowNotification).toHaveBeenCalledWith({
|
|
178
|
+
critical: true,
|
|
179
|
+
description: 'Internal Server Error',
|
|
180
|
+
kind: 'error',
|
|
181
|
+
title: 'Error saving program enrollment',
|
|
274
182
|
});
|
|
275
183
|
});
|
|
276
184
|
});
|
|
@@ -1,34 +1,33 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import { formatDate, formatDatetime, useConfig, usePagination } from '@openmrs/esm-framework';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import capitalize from 'lodash-es/capitalize';
|
|
5
4
|
import {
|
|
5
|
+
Button,
|
|
6
6
|
DataTable,
|
|
7
7
|
DataTableSkeleton,
|
|
8
|
-
Button,
|
|
9
8
|
InlineLoading,
|
|
9
|
+
InlineNotification,
|
|
10
10
|
Table,
|
|
11
|
+
TableBody,
|
|
11
12
|
TableCell,
|
|
12
13
|
TableContainer,
|
|
13
|
-
TableBody,
|
|
14
14
|
TableHead,
|
|
15
15
|
TableHeader,
|
|
16
16
|
TableRow,
|
|
17
|
-
|
|
18
|
-
} from 'carbon
|
|
17
|
+
} from '@carbon/react';
|
|
18
|
+
import { Add } from '@carbon/react/icons';
|
|
19
19
|
import {
|
|
20
|
+
launchPatientWorkspace,
|
|
20
21
|
CardHeader,
|
|
21
22
|
EmptyState,
|
|
22
23
|
ErrorState,
|
|
23
24
|
PatientChartPagination,
|
|
24
|
-
launchPatientWorkspace,
|
|
25
25
|
} from '@openmrs/esm-patient-common-lib';
|
|
26
|
-
import {
|
|
26
|
+
import { ConfigObject, formatDate, formatDatetime, useConfig, usePagination } from '@openmrs/esm-framework';
|
|
27
27
|
import { usePrograms } from './programs.resource';
|
|
28
|
-
import { ConfigObject } from '../config-schema';
|
|
29
|
-
import { capitalize } from 'lodash';
|
|
30
28
|
import ProgramActionButton from './program-action-button/program-action-button.component';
|
|
31
29
|
import { ConfigurableProgram } from '../types';
|
|
30
|
+
import styles from './programs-overview.scss';
|
|
32
31
|
|
|
33
32
|
interface ProgramsOverviewProps {
|
|
34
33
|
basePath: string;
|
|
@@ -37,8 +36,8 @@ interface ProgramsOverviewProps {
|
|
|
37
36
|
|
|
38
37
|
const ProgramsOverview: React.FC<ProgramsOverviewProps> = ({ basePath, patientUuid }) => {
|
|
39
38
|
const programsCount = 5;
|
|
40
|
-
const config = useConfig() as ConfigObject;
|
|
41
39
|
const { t } = useTranslation();
|
|
40
|
+
const config = useConfig() as ConfigObject;
|
|
42
41
|
const displayText = t('programs', 'Program enrollments');
|
|
43
42
|
const headerTitle = t('carePrograms', 'Care Programs');
|
|
44
43
|
const urlLabel = t('seeAll', 'See all');
|
|
@@ -46,14 +45,14 @@ const ProgramsOverview: React.FC<ProgramsOverviewProps> = ({ basePath, patientUu
|
|
|
46
45
|
const isConfigurable = config.customUrl ? true : false;
|
|
47
46
|
|
|
48
47
|
const {
|
|
49
|
-
enrollments,
|
|
50
|
-
isLoading,
|
|
51
|
-
isError,
|
|
52
48
|
activeEnrollments,
|
|
53
|
-
isValidating,
|
|
54
49
|
availablePrograms,
|
|
55
|
-
eligiblePrograms,
|
|
56
50
|
configurablePrograms,
|
|
51
|
+
eligiblePrograms,
|
|
52
|
+
enrollments,
|
|
53
|
+
isError,
|
|
54
|
+
isLoading,
|
|
55
|
+
isValidating,
|
|
57
56
|
} = usePrograms(patientUuid);
|
|
58
57
|
|
|
59
58
|
const {
|
|
@@ -111,7 +110,7 @@ const ProgramsOverview: React.FC<ProgramsOverviewProps> = ({ basePath, patientUu
|
|
|
111
110
|
<span>{isValidating ? <InlineLoading /> : null}</span>
|
|
112
111
|
<Button
|
|
113
112
|
kind="ghost"
|
|
114
|
-
renderIcon={
|
|
113
|
+
renderIcon={(props) => <Add size={16} {...props} />}
|
|
115
114
|
iconDescription="Add programs"
|
|
116
115
|
onClick={launchProgramsForm}
|
|
117
116
|
disabled={availablePrograms?.length && eligiblePrograms?.length === 0}
|
|
@@ -119,24 +118,19 @@ const ProgramsOverview: React.FC<ProgramsOverviewProps> = ({ basePath, patientUu
|
|
|
119
118
|
{t('add', 'Add')}
|
|
120
119
|
</Button>
|
|
121
120
|
</CardHeader>
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
isSortable={true}
|
|
136
|
-
size="short"
|
|
137
|
-
>
|
|
138
|
-
{({ rows, headers, getHeaderProps, getTableProps }) => (
|
|
139
|
-
<Table {...getTableProps()} useZebraStyles>
|
|
121
|
+
{availablePrograms?.length && eligiblePrograms?.length === 0 && (
|
|
122
|
+
<InlineNotification
|
|
123
|
+
style={{ minWidth: '100%', margin: '0rem', padding: '0rem' }}
|
|
124
|
+
kind={'info'}
|
|
125
|
+
lowContrast
|
|
126
|
+
subtitle={t('noEligibleEnrollments', 'There are no more programs left to enroll this patient in')}
|
|
127
|
+
title={t('fullyEnrolled', 'Enrolled in all programs')}
|
|
128
|
+
/>
|
|
129
|
+
)}
|
|
130
|
+
<DataTable rows={tableRows} headers={tableHeaders} isSortable size="sm" useZebraStyles>
|
|
131
|
+
{({ rows, headers, getHeaderProps, getTableProps }) => (
|
|
132
|
+
<TableContainer>
|
|
133
|
+
<Table {...getTableProps()}>
|
|
140
134
|
<TableHead>
|
|
141
135
|
<TableRow>
|
|
142
136
|
{headers.map((header) => (
|
|
@@ -162,9 +156,9 @@ const ProgramsOverview: React.FC<ProgramsOverviewProps> = ({ basePath, patientUu
|
|
|
162
156
|
))}
|
|
163
157
|
</TableBody>
|
|
164
158
|
</Table>
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
</
|
|
159
|
+
</TableContainer>
|
|
160
|
+
)}
|
|
161
|
+
</DataTable>
|
|
168
162
|
<PatientChartPagination
|
|
169
163
|
currentItems={paginatedEnrollments.length}
|
|
170
164
|
onPageNumberChange={({ page }) => goTo(page)}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { screen } from '@testing-library/react';
|
|
2
|
+
import { screen, waitFor } from '@testing-library/react';
|
|
3
3
|
import userEvent from '@testing-library/user-event';
|
|
4
4
|
import { openmrsFetch, usePagination } from '@openmrs/esm-framework';
|
|
5
5
|
import { launchPatientWorkspace } from '@openmrs/esm-patient-common-lib';
|
|
@@ -67,14 +67,12 @@ describe('ProgramsOverview', () => {
|
|
|
67
67
|
await waitForLoadingToFinish();
|
|
68
68
|
|
|
69
69
|
expect(screen.getByText(/Care Programs/i)).toBeInTheDocument();
|
|
70
|
-
expect(
|
|
71
|
-
screen.getByText(
|
|
72
|
-
/Sorry, there was a problem displaying this information. You can try to reload this page, or contact the site administrator and quote the error code above./,
|
|
73
|
-
),
|
|
74
|
-
).toBeInTheDocument();
|
|
70
|
+
expect(screen.getByText(/Sorry, there was a problem displaying this information./)).toBeInTheDocument();
|
|
75
71
|
});
|
|
76
72
|
|
|
77
73
|
it("renders a tabular overview of the patient's active program enrollments when available", async () => {
|
|
74
|
+
const user = userEvent.setup();
|
|
75
|
+
|
|
78
76
|
mockOpenmrsFetch.mockReturnValueOnce({ data: { results: mockEnrolledProgramsResponse } });
|
|
79
77
|
mockUsePagination.mockImplementation(() => ({
|
|
80
78
|
currentPage: 1,
|
|
@@ -103,7 +101,8 @@ describe('ProgramsOverview', () => {
|
|
|
103
101
|
expect(screen.getByRole('row', { name: /HIV Care and Treatment/i })).toBeInTheDocument();
|
|
104
102
|
|
|
105
103
|
// Clicking "Add" launches the programs form in a workspace
|
|
106
|
-
|
|
104
|
+
await waitFor(() => user.click(addButton));
|
|
105
|
+
|
|
107
106
|
expect(launchPatientWorkspace).toHaveBeenCalledWith('programs-form-workspace');
|
|
108
107
|
});
|
|
109
108
|
});
|
package/translations/en.json
CHANGED
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
"fullyEnrolled": "Enrolled in all programs",
|
|
22
22
|
"location": "Location",
|
|
23
23
|
"noEligibleEnrollments": "There are no more programs left to enroll this patient in",
|
|
24
|
-
"program": "Program",
|
|
25
24
|
"programEnrollments": "Program enrollments",
|
|
26
25
|
"programEnrollmentSaveError": "Error saving program enrollment",
|
|
26
|
+
"programName": "Program name",
|
|
27
27
|
"programs": "programs",
|
|
28
28
|
"required": "Required",
|
|
29
29
|
"saveAndClose": "Save and close",
|