@kenyaemr/esm-active-visits-app 7.0.2-pre.65
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 +32 -0
- package/dist/130.js +2 -0
- package/dist/130.js.LICENSE.txt +3 -0
- package/dist/130.js.map +1 -0
- package/dist/255.js +2 -0
- package/dist/255.js.LICENSE.txt +9 -0
- package/dist/255.js.map +1 -0
- package/dist/271.js +1 -0
- package/dist/316.js +2 -0
- package/dist/316.js.LICENSE.txt +19 -0
- package/dist/316.js.map +1 -0
- package/dist/319.js +1 -0
- package/dist/382.js +1 -0
- package/dist/382.js.map +1 -0
- package/dist/443.js +1 -0
- package/dist/443.js.map +1 -0
- package/dist/460.js +1 -0
- package/dist/574.js +1 -0
- package/dist/635.js +1 -0
- package/dist/635.js.map +1 -0
- package/dist/644.js +1 -0
- package/dist/729.js +1 -0
- package/dist/729.js.map +1 -0
- package/dist/757.js +1 -0
- package/dist/784.js +2 -0
- package/dist/784.js.LICENSE.txt +9 -0
- package/dist/784.js.map +1 -0
- package/dist/788.js +1 -0
- package/dist/807.js +1 -0
- package/dist/833.js +1 -0
- package/dist/835.js +1 -0
- package/dist/835.js.map +1 -0
- package/dist/875.js +2 -0
- package/dist/875.js.LICENSE.txt +15 -0
- package/dist/875.js.map +1 -0
- package/dist/879.js +1 -0
- package/dist/879.js.map +1 -0
- package/dist/kenyaemr-esm-active-visits-app.js +1 -0
- package/dist/kenyaemr-esm-active-visits-app.js.buildmanifest.json +580 -0
- package/dist/kenyaemr-esm-active-visits-app.js.map +1 -0
- package/dist/main.js +2 -0
- package/dist/main.js.LICENSE.txt +25 -0
- package/dist/main.js.map +1 -0
- package/dist/routes.json +1 -0
- package/jest.config.js +3 -0
- package/package.json +55 -0
- package/src/active-visits-widget/active-visits.component.tsx +311 -0
- package/src/active-visits-widget/active-visits.resource.tsx +148 -0
- package/src/active-visits-widget/active-visits.scss +191 -0
- package/src/active-visits-widget/active-visits.test.tsx +119 -0
- package/src/active-visits-widget/empty-data-illustration.component.tsx +39 -0
- package/src/config-schema.ts +57 -0
- package/src/declarations.d.ts +4 -0
- package/src/index.ts +21 -0
- package/src/root.scss +30 -0
- package/src/routes.json +20 -0
- package/src/types/index.ts +28 -0
- package/src/visits-summary/visit-detail-overview.scss +328 -0
- package/src/visits-summary/visit-detail.component.tsx +77 -0
- package/src/visits-summary/visit-detail.test.tsx +122 -0
- package/src/visits-summary/visit.resource.ts +190 -0
- package/src/visits-summary/visits-components/encounter-list.component.tsx +127 -0
- package/src/visits-summary/visits-components/encounter-observations.component.tsx +43 -0
- package/src/visits-summary/visits-components/encounter-observations.test.tsx +36 -0
- package/src/visits-summary/visits-components/medications-summary.component.tsx +105 -0
- package/src/visits-summary/visits-components/notes-summary.component.tsx +51 -0
- package/src/visits-summary/visits-components/tests-summary.component.tsx +21 -0
- package/src/visits-summary/visits-components/visit-summary.component.tsx +118 -0
- package/translations/am.json +35 -0
- package/translations/ar.json +35 -0
- package/translations/en.json +35 -0
- package/translations/es.json +35 -0
- package/translations/fr.json +35 -0
- package/translations/he.json +35 -0
- package/translations/km.json +35 -0
- package/translations/zh.json +35 -0
- package/translations/zh_CN.json +35 -0
- package/tsconfig.json +5 -0
- package/webpack.config.js +1 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
@use '@carbon/styles/scss/spacing';
|
|
2
|
+
@use '@carbon/styles/scss/type';
|
|
3
|
+
@import '../root.scss';
|
|
4
|
+
|
|
5
|
+
.container {
|
|
6
|
+
margin: 0rem 1rem;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.activeVisitsContainer {
|
|
10
|
+
background-color: $ui-02;
|
|
11
|
+
border: 1px solid $ui-03;
|
|
12
|
+
width: 100%;
|
|
13
|
+
margin: 0 auto;
|
|
14
|
+
max-width: 95vw;
|
|
15
|
+
padding-bottom: 0;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.activeVisitsDetailHeaderContainer {
|
|
19
|
+
display: flex;
|
|
20
|
+
justify-content: space-between;
|
|
21
|
+
align-items: center;
|
|
22
|
+
padding: spacing.$spacing-04 0 spacing.$spacing-04 spacing.$spacing-05;
|
|
23
|
+
background-color: $ui-02;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.activeVisitsTable {
|
|
27
|
+
tbody tr[data-parent-row] {
|
|
28
|
+
// Don't show a bottom border on the last row so we don't end up with a double border from the activeVisitContainer
|
|
29
|
+
&:nth-last-of-type(2) > td {
|
|
30
|
+
border-bottom: none;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.backgroundDataFetchingIndicator {
|
|
36
|
+
align-items: center;
|
|
37
|
+
display: flex;
|
|
38
|
+
flex: 1 1 0%;
|
|
39
|
+
justify-content: center;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.tableContainer section {
|
|
43
|
+
position: relative;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.tableContainer a {
|
|
47
|
+
text-decoration: none;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.pagination {
|
|
51
|
+
overflow: hidden;
|
|
52
|
+
|
|
53
|
+
&:global(.cds--pagination) {
|
|
54
|
+
border-top: 1px solid $ui-03;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.hiddenRow {
|
|
59
|
+
display: none;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.emptyRow {
|
|
63
|
+
padding: 0 1rem;
|
|
64
|
+
display: flex;
|
|
65
|
+
align-items: center;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.visitSummaryContainer {
|
|
69
|
+
width: 100%;
|
|
70
|
+
max-width: 768px;
|
|
71
|
+
margin: 1rem auto;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.expandedActiveVisitRow {
|
|
75
|
+
td {
|
|
76
|
+
padding: 0 2rem;
|
|
77
|
+
|
|
78
|
+
> div {
|
|
79
|
+
max-height: max-content !important;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
th[colspan] td[colspan] > div:first-child {
|
|
84
|
+
padding: 0 1rem;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
&:last-of-type th[colspan]:last-child {
|
|
88
|
+
border-bottom: none;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.action {
|
|
93
|
+
margin-bottom: spacing.$spacing-03;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.content {
|
|
97
|
+
@include type.type-style('heading-compact-01');
|
|
98
|
+
color: $text-02;
|
|
99
|
+
margin-top: spacing.$spacing-05;
|
|
100
|
+
margin-bottom: spacing.$spacing-03;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.desktopHeading,
|
|
104
|
+
.tabletHeading {
|
|
105
|
+
text-align: left;
|
|
106
|
+
text-transform: capitalize;
|
|
107
|
+
|
|
108
|
+
h4 {
|
|
109
|
+
@include type.type-style('heading-compact-02');
|
|
110
|
+
color: $text-02;
|
|
111
|
+
|
|
112
|
+
&:after {
|
|
113
|
+
content: '';
|
|
114
|
+
display: block;
|
|
115
|
+
width: 2rem;
|
|
116
|
+
padding-top: 3px;
|
|
117
|
+
border-bottom: 0.375rem solid;
|
|
118
|
+
@include brand-03(border-bottom-color);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.tile {
|
|
124
|
+
text-align: center;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.filterEmptyState {
|
|
128
|
+
display: flex;
|
|
129
|
+
justify-content: center;
|
|
130
|
+
align-items: center;
|
|
131
|
+
padding: spacing.$spacing-05;
|
|
132
|
+
margin: spacing.$spacing-11;
|
|
133
|
+
text-align: center;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.filterEmptyStateTile {
|
|
137
|
+
margin: auto;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.filterEmptyStateContent {
|
|
141
|
+
@include type.type-style('heading-compact-02');
|
|
142
|
+
color: $text-02;
|
|
143
|
+
margin-bottom: 0.5rem;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.filterEmptyStateHelper {
|
|
147
|
+
@include type.type-style('body-compact-01');
|
|
148
|
+
color: $text-02;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Overriding styles for RTL support
|
|
152
|
+
html[dir='rtl'] {
|
|
153
|
+
.activeVisitsContainer {
|
|
154
|
+
.activeVisitsDetailHeaderContainer {
|
|
155
|
+
padding: spacing.$spacing-04 spacing.$spacing-05 spacing.$spacing-04 0;
|
|
156
|
+
}
|
|
157
|
+
.desktopHeading,
|
|
158
|
+
.tabletHeading {
|
|
159
|
+
h4 {
|
|
160
|
+
text-align: right;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
div[role='search'] {
|
|
164
|
+
& :first-child {
|
|
165
|
+
svg {
|
|
166
|
+
left: unset;
|
|
167
|
+
right: spacing.$spacing-03;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
& :last-child {
|
|
171
|
+
right: unset;
|
|
172
|
+
left: 0;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
.tableContainer {
|
|
176
|
+
th > div {
|
|
177
|
+
text-align: right;
|
|
178
|
+
}
|
|
179
|
+
td {
|
|
180
|
+
text-align: right;
|
|
181
|
+
.serviceColor {
|
|
182
|
+
margin-right: 0;
|
|
183
|
+
margin-left: spacing.$spacing-03;
|
|
184
|
+
}
|
|
185
|
+
button {
|
|
186
|
+
text-align: right;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import userEvent from '@testing-library/user-event';
|
|
3
|
+
import { render, screen } from '@testing-library/react';
|
|
4
|
+
import { useConfig } from '@openmrs/esm-framework';
|
|
5
|
+
import { useActiveVisits } from './active-visits.resource';
|
|
6
|
+
import ActiveVisitsTable from './active-visits.component';
|
|
7
|
+
|
|
8
|
+
const mockUseActiveVisits = useActiveVisits as jest.Mock;
|
|
9
|
+
|
|
10
|
+
jest.mock('./active-visits.resource', () => ({
|
|
11
|
+
...jest.requireActual('./active-visits.resource'),
|
|
12
|
+
useActiveVisits: jest.fn(),
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
const mockUseConfig = useConfig as jest.Mock;
|
|
16
|
+
|
|
17
|
+
describe('ActiveVisitsTable', () => {
|
|
18
|
+
beforeEach(() => mockUseActiveVisits.mockReset());
|
|
19
|
+
|
|
20
|
+
it('renders data table with active visits', () => {
|
|
21
|
+
mockUseActiveVisits.mockImplementation(() => ({
|
|
22
|
+
activeVisits: [{ id: '1', name: 'John Doe', visitType: 'Checkup', patientUuid: 'uuid1' }],
|
|
23
|
+
isLoading: false,
|
|
24
|
+
isValidating: false,
|
|
25
|
+
error: null,
|
|
26
|
+
}));
|
|
27
|
+
render(<ActiveVisitsTable />);
|
|
28
|
+
|
|
29
|
+
expect(screen.getByText('Visit Time')).toBeInTheDocument();
|
|
30
|
+
expect(screen.getByText('ID Number')).toBeInTheDocument();
|
|
31
|
+
const expectedColumnHeaders = [/Visit Time/, /ID Number/, /Name/, /Gender/, /Age/, /Visit Type/];
|
|
32
|
+
expectedColumnHeaders.forEach((header) => {
|
|
33
|
+
expect(screen.getByRole('columnheader', { name: new RegExp(header, 'i') })).toBeInTheDocument();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const patientNameLink = screen.getByText('John Doe');
|
|
37
|
+
expect(patientNameLink).toBeInTheDocument();
|
|
38
|
+
expect(patientNameLink.tagName).toBe('A');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('filters active visits based on search input', async () => {
|
|
42
|
+
const user = userEvent.setup();
|
|
43
|
+
|
|
44
|
+
mockUseActiveVisits.mockImplementation(() => ({
|
|
45
|
+
activeVisits: [
|
|
46
|
+
{ id: '1', name: 'John Doe', visitType: 'Checkup', patientUuid: 'uuid1' },
|
|
47
|
+
{ id: '2', name: 'Some One', visitType: 'Checkup', patientUuid: 'uuid2' },
|
|
48
|
+
],
|
|
49
|
+
isLoading: false,
|
|
50
|
+
isValidating: false,
|
|
51
|
+
error: null,
|
|
52
|
+
}));
|
|
53
|
+
|
|
54
|
+
render(<ActiveVisitsTable />);
|
|
55
|
+
|
|
56
|
+
const searchInput = screen.getByPlaceholderText('Filter table');
|
|
57
|
+
await user.type(searchInput, 'John');
|
|
58
|
+
|
|
59
|
+
expect(screen.getByText('John Doe')).toBeInTheDocument();
|
|
60
|
+
expect(screen.queryByText('Some One')).toBeNull();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('displays empty state when there are no active visits', () => {
|
|
64
|
+
mockUseActiveVisits.mockImplementation(() => ({
|
|
65
|
+
activeVisits: [],
|
|
66
|
+
isLoading: false,
|
|
67
|
+
isValidating: false,
|
|
68
|
+
error: null,
|
|
69
|
+
}));
|
|
70
|
+
|
|
71
|
+
render(<ActiveVisitsTable />);
|
|
72
|
+
|
|
73
|
+
expect(screen.getByText('There are no active visits to display for this location.')).toBeInTheDocument();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should not display the table when the data is loading', () => {
|
|
77
|
+
mockUseActiveVisits.mockImplementation(() => ({
|
|
78
|
+
activeVisits: undefined,
|
|
79
|
+
isLoading: true,
|
|
80
|
+
isValidating: false,
|
|
81
|
+
error: null,
|
|
82
|
+
}));
|
|
83
|
+
|
|
84
|
+
render(<ActiveVisitsTable />);
|
|
85
|
+
|
|
86
|
+
const expectedColumnHeaders = [/Visit Time/, /ID Number/, /Name/, /Gender/, /Age/, /Visit Type/];
|
|
87
|
+
expectedColumnHeaders.forEach((header) => {
|
|
88
|
+
expect(screen.queryByRole('columnheader', { name: new RegExp(header, 'i') })).not.toBeInTheDocument();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should display the error state when there is error', () => {
|
|
93
|
+
mockUseActiveVisits.mockImplementation(() => ({
|
|
94
|
+
activeVisits: undefined,
|
|
95
|
+
isLoading: false,
|
|
96
|
+
isValidating: false,
|
|
97
|
+
error: 'Error in fetching data',
|
|
98
|
+
}));
|
|
99
|
+
|
|
100
|
+
render(<ActiveVisitsTable />);
|
|
101
|
+
|
|
102
|
+
expect(screen.getByText(/Error State/i)).toBeInTheDocument();
|
|
103
|
+
expect(screen.queryByRole('table')).not.toBeInTheDocument();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should display the pagination when pagination is true', () => {
|
|
107
|
+
mockUseActiveVisits.mockImplementation(() => ({
|
|
108
|
+
activeVisits: [
|
|
109
|
+
{ id: '1', name: 'John Doe', visitType: 'Checkup' },
|
|
110
|
+
{ id: '2', name: 'Some One', visitType: 'Checkup' },
|
|
111
|
+
],
|
|
112
|
+
isLoading: false,
|
|
113
|
+
isValidating: false,
|
|
114
|
+
error: null,
|
|
115
|
+
}));
|
|
116
|
+
|
|
117
|
+
render(<ActiveVisitsTable />);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
export const EmptyDataIllustration = ({ width = '64', height = '64' }) => {
|
|
4
|
+
return (
|
|
5
|
+
<svg width={width} height={height} viewBox="0 0 64 64">
|
|
6
|
+
<title>Empty data illustration</title>
|
|
7
|
+
<g fill="none" fillRule="evenodd">
|
|
8
|
+
<path
|
|
9
|
+
d="M38.133 13.186H21.947c-.768.001-1.39.623-1.39 1.391V50.55l-.186.057-3.97 1.216a.743.743 0 01-.927-.493L3.664 12.751a.742.742 0 01.492-.926l6.118-1.874 17.738-5.43 6.119-1.873a.741.741 0 01.926.492L38.076 13l.057.186z"
|
|
10
|
+
fill="#F4F4F4"
|
|
11
|
+
/>
|
|
12
|
+
<path
|
|
13
|
+
d="M41.664 13L38.026 1.117A1.576 1.576 0 0036.056.07l-8.601 2.633-17.737 5.43-8.603 2.634a1.578 1.578 0 00-1.046 1.97l12.436 40.616a1.58 1.58 0 001.969 1.046l5.897-1.805.185-.057v-.194l-.185.057-5.952 1.822a1.393 1.393 0 01-1.737-.923L.247 12.682a1.39 1.39 0 01.923-1.738L9.772 8.31 27.51 2.881 36.112.247a1.393 1.393 0 011.737.923L41.47 13l.057.186h.193l-.057-.185z"
|
|
14
|
+
fill="#8D8D8D"
|
|
15
|
+
/>
|
|
16
|
+
<path
|
|
17
|
+
d="M11.378 11.855a.836.836 0 01-.798-.59L9.385 7.361a.835.835 0 01.554-1.042l16.318-4.996a.836.836 0 011.042.554l1.195 3.902a.836.836 0 01-.554 1.043l-16.318 4.995a.831.831 0 01-.244.037z"
|
|
18
|
+
fill="#C6C6C6"
|
|
19
|
+
/>
|
|
20
|
+
<circle fill="#C6C6C6" cx={17.636} cy={2.314} r={1.855} />
|
|
21
|
+
<circle fill="#FFF" fillRule="nonzero" cx={17.636} cy={2.314} r={1.175} />
|
|
22
|
+
<path
|
|
23
|
+
d="M55.893 53.995H24.544a.79.79 0 01-.788-.789V15.644a.79.79 0 01.788-.788h31.349a.79.79 0 01.788.788v37.562a.79.79 0 01-.788.789z"
|
|
24
|
+
fill="#F4F4F4"
|
|
25
|
+
/>
|
|
26
|
+
<path
|
|
27
|
+
d="M41.47 13H21.948a1.579 1.579 0 00-1.576 1.577V52.4l.185-.057V14.577c.001-.768.623-1.39 1.391-1.39h19.581L41.471 13zm17.02 0H21.947a1.579 1.579 0 00-1.576 1.577v42.478c0 .87.706 1.576 1.576 1.577H58.49a1.579 1.579 0 001.576-1.577V14.577a1.579 1.579 0 00-1.576-1.576zm1.39 44.055c0 .768-.622 1.39-1.39 1.392H21.947c-.768-.001-1.39-.624-1.39-1.392V14.577c0-.768.622-1.39 1.39-1.39H58.49c.768 0 1.39.622 1.39 1.39v42.478z"
|
|
28
|
+
fill="#8D8D8D"
|
|
29
|
+
/>
|
|
30
|
+
<path
|
|
31
|
+
d="M48.751 17.082H31.686a.836.836 0 01-.835-.835v-4.081c0-.46.374-.834.835-.835H48.75c.461 0 .834.374.835.835v4.08c0 .462-.374.835-.835.836z"
|
|
32
|
+
fill="#C6C6C6"
|
|
33
|
+
/>
|
|
34
|
+
<circle fill="#C6C6C6" cx={40.218} cy={9.755} r={1.855} />
|
|
35
|
+
<circle fill="#FFF" fillRule="nonzero" cx={40.218} cy={9.755} r={1.13} />
|
|
36
|
+
</g>
|
|
37
|
+
</svg>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Type } from '@openmrs/esm-framework';
|
|
2
|
+
|
|
3
|
+
export interface SectionDefinition {
|
|
4
|
+
activeVisits: {
|
|
5
|
+
pageSize: Number;
|
|
6
|
+
pageSizes: Array<Number>;
|
|
7
|
+
identifiers: Array<IdentifiersDefinition>;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface IdentifiersDefinition {
|
|
12
|
+
id: Number;
|
|
13
|
+
header: {
|
|
14
|
+
key: string;
|
|
15
|
+
default: string;
|
|
16
|
+
};
|
|
17
|
+
identifierName: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const configSchema = {
|
|
21
|
+
activeVisits: {
|
|
22
|
+
pageSize: {
|
|
23
|
+
_type: Type.Number,
|
|
24
|
+
_description: 'Count of active visits to be shown in a single page.',
|
|
25
|
+
_default: 10,
|
|
26
|
+
},
|
|
27
|
+
pageSizes: {
|
|
28
|
+
_type: Type.Array,
|
|
29
|
+
_description: 'Customizable page sizes that user can choose',
|
|
30
|
+
_default: [10, 20, 50],
|
|
31
|
+
},
|
|
32
|
+
identifiers: {
|
|
33
|
+
_type: Type.Array,
|
|
34
|
+
_description: 'Customizable list of identifiers to display on active visits table',
|
|
35
|
+
_elements: {
|
|
36
|
+
header: {
|
|
37
|
+
key: {
|
|
38
|
+
_type: Type.String,
|
|
39
|
+
_default: null,
|
|
40
|
+
_description: 'Key to be used for translation purposes.',
|
|
41
|
+
},
|
|
42
|
+
default: {
|
|
43
|
+
_type: Type.String,
|
|
44
|
+
_default: null,
|
|
45
|
+
_description: 'Default text to be displayed if no translation is found.',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
identifierName: {
|
|
49
|
+
_type: Type.String,
|
|
50
|
+
_default: null,
|
|
51
|
+
_description: 'Name of the desired identifier to filter data returned from the visit resource.',
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
_default: null,
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { defineConfigSchema, getSyncLifecycle } from '@openmrs/esm-framework';
|
|
2
|
+
import { configSchema } from './config-schema';
|
|
3
|
+
import activeVisitsComponent from './active-visits-widget/active-visits.component';
|
|
4
|
+
import visitDetailComponent from './visits-summary/visit-detail.component';
|
|
5
|
+
|
|
6
|
+
const moduleName = '@kenyaemr/esm-active-visits-app';
|
|
7
|
+
|
|
8
|
+
const options = {
|
|
9
|
+
featureName: 'active-visits',
|
|
10
|
+
moduleName,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const importTranslation = require.context('../translations', false, /.json$/, 'lazy');
|
|
14
|
+
|
|
15
|
+
export function startupApp() {
|
|
16
|
+
defineConfigSchema(moduleName, configSchema);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const activeVisits = getSyncLifecycle(activeVisitsComponent, options);
|
|
20
|
+
|
|
21
|
+
export const visitDetail = getSyncLifecycle(visitDetailComponent, options);
|
package/src/root.scss
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
@use '@carbon/styles/scss/type';
|
|
2
|
+
@import '~@openmrs/esm-styleguide/src/vars';
|
|
3
|
+
|
|
4
|
+
.productiveHeading01 {
|
|
5
|
+
@include type.type-style('heading-compact-01');
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.productiveHeading02 {
|
|
9
|
+
@include type.type-style('heading-compact-02');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.bodyLong01 {
|
|
13
|
+
@include type.type-style('body-01');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.caption01 {
|
|
17
|
+
@include type.type-style('legal-01');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.bodyShort02 {
|
|
21
|
+
@include type.type-style('body-compact-02');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.text02 {
|
|
25
|
+
color: $text-02;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.text01 {
|
|
29
|
+
color: $ui-05;
|
|
30
|
+
}
|
package/src/routes.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.openmrs.org/routes.schema.json",
|
|
3
|
+
"backendDependencies": {
|
|
4
|
+
"webservices.rest": "^2.2.0"
|
|
5
|
+
},
|
|
6
|
+
"extensions": [
|
|
7
|
+
{
|
|
8
|
+
"name": "active-visits-widget",
|
|
9
|
+
"slot": "homepage-widgets-slot",
|
|
10
|
+
"component": "activeVisits",
|
|
11
|
+
"order": 0
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "visit-summary-widget",
|
|
15
|
+
"slot": "visit-summary-slot",
|
|
16
|
+
"component": "visitDetail"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"pages": []
|
|
20
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface SearchedPatient {
|
|
2
|
+
patientId: number;
|
|
3
|
+
uuid: string;
|
|
4
|
+
identifiers: Array<Identifier>;
|
|
5
|
+
person: {
|
|
6
|
+
age: number;
|
|
7
|
+
birthdate: string;
|
|
8
|
+
display: string;
|
|
9
|
+
gender: string;
|
|
10
|
+
};
|
|
11
|
+
display: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface Identifier {
|
|
15
|
+
display: string;
|
|
16
|
+
uuid: string;
|
|
17
|
+
identifier: string;
|
|
18
|
+
identifierType: {
|
|
19
|
+
uuid: string;
|
|
20
|
+
display: string;
|
|
21
|
+
};
|
|
22
|
+
location: {
|
|
23
|
+
uuid: string;
|
|
24
|
+
display: string;
|
|
25
|
+
};
|
|
26
|
+
preferred: boolean;
|
|
27
|
+
voided: boolean;
|
|
28
|
+
}
|