@kenyaemr/esm-ward-app 7.0.3-pre.88 → 7.0.3-pre.94
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 +24 -16
- package/dist/130.js +1 -1
- package/dist/130.js.map +1 -1
- package/dist/169.js +1 -0
- package/dist/169.js.map +1 -0
- package/dist/269.js +1 -0
- package/dist/269.js.map +1 -0
- package/dist/346.js +1 -0
- package/dist/346.js.map +1 -0
- package/dist/348.js +1 -0
- package/dist/348.js.map +1 -0
- package/dist/466.js +1 -0
- package/dist/466.js.map +1 -0
- package/dist/501.js +1 -0
- package/dist/501.js.map +1 -0
- package/dist/574.js +1 -1
- package/dist/577.js +1 -0
- package/dist/577.js.map +1 -0
- package/dist/659.js +1 -0
- package/dist/659.js.map +1 -0
- package/dist/749.js +1 -0
- package/dist/749.js.map +1 -0
- package/dist/76.js +1 -0
- package/dist/76.js.map +1 -0
- package/dist/767.js +1 -0
- package/dist/767.js.map +1 -0
- package/dist/793.js +2 -0
- package/dist/793.js.map +1 -0
- package/dist/803.js +1 -0
- package/dist/803.js.map +1 -0
- package/dist/940.js +1 -0
- package/dist/940.js.map +1 -0
- package/dist/960.js +1 -0
- package/dist/960.js.map +1 -0
- package/dist/kenyaemr-esm-ward-app.js +1 -1
- package/dist/kenyaemr-esm-ward-app.js.buildmanifest.json +330 -42
- package/dist/kenyaemr-esm-ward-app.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +2 -2
- package/src/action-menu-buttons/transfer-workspace-siderail.component.tsx +27 -0
- package/src/beds/empty-bed.component.tsx +1 -1
- package/src/beds/empty-bed.scss +6 -6
- package/src/beds/occupied-bed.component.tsx +5 -5
- package/src/beds/occupied-bed.scss +2 -3
- package/src/beds/occupied-bed.test.tsx +37 -21
- package/src/beds/unassigned-patient.component.tsx +20 -0
- package/src/beds/unassigned-patient.scss +6 -0
- package/src/config-schema-admission-request-note.ts +9 -0
- package/src/config-schema-extension-colored-obs-tags.ts +91 -0
- package/src/config-schema.ts +165 -231
- package/src/createDashboardLink.component.tsx +42 -0
- package/src/hooks/useAdmissionLocation.ts +12 -7
- package/src/hooks/useCurrentWardCardConfig.ts +32 -0
- package/src/hooks/useEmrConfiguration.ts +112 -0
- package/src/hooks/useInpatientAdmission.ts +28 -0
- package/src/hooks/useInpatientRequest.ts +39 -9
- package/src/hooks/useLocation.test.ts +38 -0
- package/src/hooks/useLocation.ts +9 -0
- package/src/hooks/useLocations.ts +54 -0
- package/src/hooks/useMostRecentObs.ts +27 -0
- package/src/hooks/useRestPatient.ts +18 -0
- package/src/hooks/useWardLocation.test.ts +108 -0
- package/src/hooks/useWardLocation.ts +26 -0
- package/src/index.ts +71 -4
- package/src/location-selector/location-selector.component.tsx +118 -0
- package/src/location-selector/location-selector.scss +48 -0
- package/src/root.component.tsx +2 -1
- package/src/routes.json +79 -12
- package/src/types/index.ts +87 -46
- package/src/ward-patient-card/card-rows/admission-request-note.extension.tsx +27 -0
- package/src/ward-patient-card/card-rows/colored-obs-tags-card-row.extension.tsx +13 -0
- package/src/ward-patient-card/row-elements/ward-patient-age.tsx +7 -13
- package/src/ward-patient-card/row-elements/ward-patient-bed-number.tsx +2 -2
- package/src/ward-patient-card/row-elements/ward-patient-coded-obs-tags.tsx +51 -50
- package/src/ward-patient-card/row-elements/ward-patient-gender.component.tsx +27 -0
- package/src/ward-patient-card/row-elements/ward-patient-header-address.tsx +16 -15
- package/src/ward-patient-card/row-elements/ward-patient-identifier.tsx +53 -0
- package/src/ward-patient-card/row-elements/ward-patient-name.tsx +7 -7
- package/src/ward-patient-card/row-elements/ward-patient-obs.resource.ts +4 -4
- package/src/ward-patient-card/row-elements/ward-patient-obs.tsx +45 -44
- package/src/ward-patient-card/row-elements/ward-patient-time-on-ward.tsx +22 -0
- package/src/ward-patient-card/row-elements/ward-patient-time-since-admission.tsx +22 -0
- package/src/ward-patient-card/ward-patient-card-element.component.tsx +65 -0
- package/src/ward-patient-card/ward-patient-card.component.tsx +64 -0
- package/src/ward-patient-card/ward-patient-card.scss +61 -12
- package/src/ward-patient-workspace/ward-patient-action-button.extension.tsx +18 -0
- package/src/ward-patient-workspace/ward-patient.style.scss +11 -0
- package/src/ward-patient-workspace/ward-patient.workspace.tsx +51 -0
- package/src/ward-view/ward-bed.component.tsx +0 -1
- package/src/ward-view/ward-view.component.tsx +114 -76
- package/src/ward-view/ward-view.resource.ts +2 -2
- package/src/ward-view/ward-view.scss +4 -4
- package/src/ward-view/ward-view.test.tsx +76 -49
- package/src/ward-view-header/admission-requests-bar.component.tsx +29 -28
- package/src/ward-view-header/admission-requests-bar.test.tsx +11 -15
- package/src/ward-view-header/admission-requests.scss +20 -25
- package/src/ward-view-header/ward-view-header.component.tsx +7 -7
- package/src/ward-view-header/ward-view-header.scss +2 -2
- package/src/ward-workspace/admission-request-card/admission-request-card-actions.component.tsx +29 -0
- package/src/ward-workspace/admission-request-card/admission-request-card-header.component.tsx +51 -0
- package/src/ward-workspace/admission-request-card/admission-request-card.component.tsx +16 -0
- package/src/ward-workspace/admission-request-card/admission-request-card.scss +49 -0
- package/src/ward-workspace/admission-request-workspace/admission-requests-workspace.scss +12 -0
- package/src/ward-workspace/admission-request-workspace/admission-requests-workspace.test.tsx +48 -0
- package/src/ward-workspace/admission-request-workspace/admission-requests.workspace.tsx +61 -0
- package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.scss +35 -0
- package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.test.tsx +341 -0
- package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.workspace.tsx +267 -0
- package/src/ward-workspace/admit-patient-form-workspace/types.ts +7 -0
- package/src/ward-workspace/patient-banner/patient-banner.component.tsx +29 -0
- package/src/ward-workspace/patient-banner/style.scss +23 -0
- package/src/ward-workspace/patient-transfer-bed-swap/patient-bed-swap-form.component.tsx +210 -0
- package/src/ward-workspace/patient-transfer-bed-swap/patient-transfer-request-form.component.tsx +238 -0
- package/src/ward-workspace/patient-transfer-bed-swap/patient-transfer-swap.scss +73 -0
- package/src/ward-workspace/patient-transfer-bed-swap/patient-transfer-swap.workspace.tsx +44 -0
- package/src/ward-workspace/ward-patient-notes/form/notes-form.component.tsx +180 -0
- package/src/ward-workspace/ward-patient-notes/form/notes-form.scss +30 -0
- package/src/ward-workspace/ward-patient-notes/form/notes-form.test.tsx +116 -0
- package/src/ward-workspace/ward-patient-notes/history/note.component.tsx +53 -0
- package/src/ward-workspace/ward-patient-notes/history/notes-container.component.tsx +55 -0
- package/src/ward-workspace/ward-patient-notes/history/notes-container.test.tsx +84 -0
- package/src/ward-workspace/ward-patient-notes/history/styles.scss +61 -0
- package/src/ward-workspace/ward-patient-notes/notes-action-button.extension.tsx +18 -0
- package/src/ward-workspace/ward-patient-notes/notes.resource.ts +71 -0
- package/src/ward-workspace/ward-patient-notes/notes.workspace.tsx +25 -0
- package/src/ward-workspace/ward-patient-notes/types.ts +44 -0
- package/src/ward.resource.ts +25 -0
- package/translations/en.json +63 -2
- package/dist/443.js +0 -1
- package/dist/443.js.map +0 -1
- package/dist/589.js +0 -1
- package/dist/589.js.map +0 -1
- package/dist/695.js +0 -2
- package/dist/695.js.map +0 -1
- package/src/hooks/useAdmittedPatients.ts +0 -13
- package/src/ward-patient-card/row-elements/row-elements.scss +0 -16
- package/src/ward-patient-card/ward-patient-card-row.resources.tsx +0 -92
- package/src/ward-patient-card/ward-patient-card.tsx +0 -20
- package/src/ward-workspace/admission-request-card.component.tsx +0 -23
- package/src/ward-workspace/admission-request-card.scss +0 -34
- package/src/ward-workspace/admission-request-workspace.test.tsx +0 -38
- package/src/ward-workspace/admission-requests-workspace.component.tsx +0 -21
- package/src/ward-workspace/admission-requests-workspace.scss +0 -13
- /package/dist/{695.js.LICENSE.txt → 793.js.LICENSE.txt} +0 -0
package/src/config-schema.ts
CHANGED
|
@@ -1,136 +1,143 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { patientCardElementTypes, type PatientCardElementType } from './types';
|
|
1
|
+
import { type ConfigSchema, Type, validators } from '@openmrs/esm-framework';
|
|
3
2
|
|
|
4
|
-
const defaultWardPatientCard: WardPatientCardDefinition = {
|
|
5
|
-
id: 'default
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
rowType: 'header',
|
|
9
|
-
elements: ['bed-number', 'patient-name', 'patient-age', 'patient-address'],
|
|
10
|
-
},
|
|
11
|
-
],
|
|
3
|
+
export const defaultWardPatientCard: WardPatientCardDefinition = {
|
|
4
|
+
id: 'default',
|
|
5
|
+
headerRowElements: ['patient-age', 'patient-address', 'patient-identifier'],
|
|
6
|
+
footerRowElements: [],
|
|
12
7
|
appliedTo: null,
|
|
13
8
|
};
|
|
14
9
|
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
export const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
'
|
|
27
|
-
'
|
|
28
|
-
'
|
|
29
|
-
'
|
|
30
|
-
|
|
10
|
+
export const builtInPatientCardElements = ['patient-age', 'time-on-ward', 'time-since-admission'];
|
|
11
|
+
|
|
12
|
+
export const addressFields = [
|
|
13
|
+
'cityVillage',
|
|
14
|
+
'stateProvince',
|
|
15
|
+
'country',
|
|
16
|
+
'postalCode',
|
|
17
|
+
'countyDistrict',
|
|
18
|
+
'latitude',
|
|
19
|
+
'longitude',
|
|
20
|
+
'address1',
|
|
21
|
+
'address2',
|
|
22
|
+
'address3',
|
|
23
|
+
'address4',
|
|
24
|
+
'address5',
|
|
25
|
+
'address6',
|
|
26
|
+
'address7',
|
|
27
|
+
'address8',
|
|
28
|
+
'address9',
|
|
29
|
+
'address10',
|
|
30
|
+
'address11',
|
|
31
|
+
'address12',
|
|
32
|
+
'address13',
|
|
33
|
+
'address14',
|
|
34
|
+
'address15',
|
|
35
|
+
] as const;
|
|
36
|
+
|
|
37
|
+
type AddressField = keyof typeof addressFields;
|
|
31
38
|
|
|
32
39
|
export const configSchema: ConfigSchema = {
|
|
33
40
|
wardPatientCards: {
|
|
34
41
|
_description: 'Configure the display of ward patient cards',
|
|
35
|
-
|
|
42
|
+
obsElementDefinitions: {
|
|
36
43
|
_type: Type.Array,
|
|
44
|
+
_description: 'Defines obs display elements that can be included in the card header or footer.',
|
|
37
45
|
_default: [],
|
|
38
46
|
_elements: {
|
|
39
47
|
id: {
|
|
40
48
|
_type: Type.String,
|
|
41
|
-
_description: 'The unique identifier for this
|
|
49
|
+
_description: 'The unique identifier for this patient card element',
|
|
50
|
+
},
|
|
51
|
+
conceptUuid: {
|
|
52
|
+
_type: Type.UUID,
|
|
53
|
+
_description: 'Identifies the concept to use to identify the desired observations.',
|
|
42
54
|
},
|
|
43
|
-
|
|
55
|
+
label: {
|
|
44
56
|
_type: Type.String,
|
|
45
|
-
_description:
|
|
46
|
-
|
|
57
|
+
_description:
|
|
58
|
+
"Optional. The custom label or i18n key to the translated label to display. If not provided, defaults to the concept's name. (Note that this can be set to an empty string to not show a label)",
|
|
59
|
+
_default: null,
|
|
47
60
|
},
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
61
|
+
labelI18nModule: {
|
|
62
|
+
_type: Type.String,
|
|
63
|
+
_description:
|
|
64
|
+
'Optional. The custom module to use for translation of the label. If not provided, the label will not be translated.',
|
|
65
|
+
_default: null,
|
|
66
|
+
},
|
|
67
|
+
orderBy: {
|
|
68
|
+
_type: Type.String,
|
|
69
|
+
_description:
|
|
70
|
+
"One of 'ascending' or 'descending', specifying whether to display the obs by obsDatetime ascendingly or descendingly.",
|
|
71
|
+
_default: 'descending',
|
|
72
|
+
_validators: [validators.oneOf(['ascending', 'descending'])],
|
|
73
|
+
},
|
|
74
|
+
limit: {
|
|
75
|
+
_type: Type.Number,
|
|
76
|
+
_description:
|
|
77
|
+
'If set to a number greater than one, this will show multiple obs for this concept, which will appear as a list. Set to 0 for unlimited.',
|
|
78
|
+
_default: 1,
|
|
79
|
+
},
|
|
80
|
+
onlyWithinCurrentVisit: {
|
|
81
|
+
_type: Type.Boolean,
|
|
82
|
+
_description:
|
|
83
|
+
'Optional. If true, limits display to only observations within current visit. Defaults to false',
|
|
84
|
+
_default: false,
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
identifierElementDefinitions: {
|
|
89
|
+
_type: Type.Array,
|
|
90
|
+
_description: `Defines patient identifier elements that can be included in the card header or footer. The default element 'patient-identifier' displays the preferred identifier.`,
|
|
91
|
+
_default: [
|
|
92
|
+
{
|
|
93
|
+
id: 'patient-identifier',
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
_elements: {
|
|
97
|
+
id: {
|
|
98
|
+
_type: Type.String,
|
|
99
|
+
_description: 'The unique identifier for this patient card element',
|
|
100
|
+
},
|
|
101
|
+
identifierTypeUuid: {
|
|
102
|
+
_type: Type.UUID,
|
|
103
|
+
_description:
|
|
104
|
+
'The UUID of the identifier type to display. If not provided, defaults to the preferred identifier.',
|
|
105
|
+
_default: null,
|
|
106
|
+
},
|
|
107
|
+
label: {
|
|
108
|
+
_type: Type.String,
|
|
109
|
+
_description:
|
|
110
|
+
'the custom label or i18n key to the translated label to display for patient identifier. If not provided, defaults to the patient-identifier name.',
|
|
111
|
+
_default: null,
|
|
112
|
+
},
|
|
113
|
+
labelI18nModule: {
|
|
114
|
+
_type: Type.String,
|
|
115
|
+
_description: 'Optional. The custom module to use for translation of the label',
|
|
116
|
+
_default: null,
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
addressElementDefinitions: {
|
|
121
|
+
_type: Type.Array,
|
|
122
|
+
_description: 'Defines patient address elements that can be included in the card header or footer.',
|
|
123
|
+
_default: [
|
|
124
|
+
{
|
|
125
|
+
id: 'patient-address',
|
|
126
|
+
fields: ['cityVillage', 'country'],
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
_elements: {
|
|
130
|
+
fields: {
|
|
131
|
+
id: {
|
|
132
|
+
_type: Type.String,
|
|
133
|
+
_description: 'The unique identifier for this patient card element',
|
|
56
134
|
},
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
_description: 'Required. Identifies the concept to use to identify the desired observations.',
|
|
62
|
-
_default: null,
|
|
63
|
-
},
|
|
64
|
-
label: {
|
|
65
|
-
_type: Type.String,
|
|
66
|
-
_description:
|
|
67
|
-
"Optional. The custom label or i18n key to the translated label to display. If not provided, defaults to the concept's name. (Note that this can be set to an empty string to not show a label)",
|
|
68
|
-
_default: null,
|
|
69
|
-
},
|
|
70
|
-
labelI18nModule: {
|
|
71
|
-
_type: Type.String,
|
|
72
|
-
_description: 'Optional. The custom module to use for translation of the label',
|
|
73
|
-
_default: null,
|
|
74
|
-
},
|
|
75
|
-
orderBy: {
|
|
135
|
+
fields: {
|
|
136
|
+
_type: Type.Array,
|
|
137
|
+
_description: 'The fields of the address to display',
|
|
138
|
+
_elements: {
|
|
76
139
|
_type: Type.String,
|
|
77
|
-
|
|
78
|
-
"Optional. One of 'ascending' or 'descending', specifying whether to display the obs by obsDatetime ascendingly or descendingly. Defaults to ascending.",
|
|
79
|
-
_default: 'descending',
|
|
80
|
-
_validators: [validators.oneOf(['ascending', 'descending'])],
|
|
81
|
-
},
|
|
82
|
-
limit: {
|
|
83
|
-
_type: Type.Number,
|
|
84
|
-
_description: 'Optional. Limits the max number of obs to display. Unlimited by default.',
|
|
85
|
-
_default: null,
|
|
86
|
-
},
|
|
87
|
-
onlyWithinCurrentVisit: {
|
|
88
|
-
_type: Type.Boolean,
|
|
89
|
-
_description:
|
|
90
|
-
'Optional. If true, limits display to only observations within current visit. Defaults to false',
|
|
91
|
-
_default: false,
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
codedObsTags: {
|
|
95
|
-
_description: 'Config for the patientCardElementType "patient-coded-obs-tags"',
|
|
96
|
-
conceptUuid: {
|
|
97
|
-
_type: Type.UUID,
|
|
98
|
-
_description: 'Required. Identifies the concept to use to identify the desired observations.',
|
|
99
|
-
_default: null,
|
|
100
|
-
},
|
|
101
|
-
summaryLabel: {
|
|
102
|
-
_type: Type.String,
|
|
103
|
-
_description: `Optional. The custom label or i18n key to the translated label to display for the summary tag. The summary tag shows the count of the number of answers that are present but not configured to show as their own tags. If not provided, defaults to the name of the concept.`,
|
|
104
|
-
_default: null,
|
|
105
|
-
},
|
|
106
|
-
summaryLabelI18nModule: {
|
|
107
|
-
_type: Type.String,
|
|
108
|
-
_description: 'Optional. The custom module to use for translation of the summary label',
|
|
109
|
-
_default: null,
|
|
110
|
-
},
|
|
111
|
-
summaryLabelColor: {
|
|
112
|
-
_type: Type.String,
|
|
113
|
-
_description:
|
|
114
|
-
'The color of the summary tag. See https://react.carbondesignsystem.com/?path=/docs/components-tag--overview for a list of supported colors',
|
|
115
|
-
_default: null,
|
|
116
|
-
},
|
|
117
|
-
tags: {
|
|
118
|
-
_description: `An array specifying concept sets and color. Observations with coded values that are members of the specified concept sets will be displayed as their own tags with the specified color. Any observation with coded values not belonging to any concept sets specified will be summarized as a count in the summary tag. If a concept set is listed multiple times, the first matching applied-to rule takes precedence.`,
|
|
119
|
-
_type: Type.Array,
|
|
120
|
-
_elements: {
|
|
121
|
-
color: {
|
|
122
|
-
_type: Type.String,
|
|
123
|
-
_description:
|
|
124
|
-
'Color of the tag. See https://react.carbondesignsystem.com/?path=/docs/components-tag--overview for a list of supported colors.',
|
|
125
|
-
},
|
|
126
|
-
appliedToConceptSets: {
|
|
127
|
-
_type: Type.Array,
|
|
128
|
-
_description: `The concept sets which the color applies to. Observations with coded values that are members of the specified concept sets will be displayed as their own tag with the specified color. If an observation's coded value belongs to multiple concept sets, the first matching applied-to rule takes precedence.`,
|
|
129
|
-
_elements: {
|
|
130
|
-
_type: Type.UUID,
|
|
131
|
-
},
|
|
132
|
-
},
|
|
133
|
-
},
|
|
140
|
+
_validators: [validators.oneOf(addressFields)],
|
|
134
141
|
},
|
|
135
142
|
},
|
|
136
143
|
},
|
|
@@ -144,31 +151,36 @@ export const configSchema: ConfigSchema = {
|
|
|
144
151
|
_elements: {
|
|
145
152
|
id: {
|
|
146
153
|
_type: Type.String,
|
|
147
|
-
_description:
|
|
154
|
+
_description:
|
|
155
|
+
'The unique identifier for this card definition. This is used to set the name of the extension slot the card has, where the rows go. The slot name is "ward-patient-card-<id>", unless the id is "default", in which case the slot name is "ward-patient-card".',
|
|
156
|
+
_default: 'default',
|
|
148
157
|
},
|
|
149
|
-
|
|
158
|
+
headerRowElements: {
|
|
150
159
|
_type: Type.Array,
|
|
160
|
+
_description: `IDs of patient card elements to appear in the header row. These can be built-in, or custom ones can be defined in patientCardElementDefinitions. Built-in elements are: '${builtInPatientCardElements.join(
|
|
161
|
+
"', '",
|
|
162
|
+
)}'.`,
|
|
151
163
|
_elements: {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
},
|
|
163
|
-
},
|
|
164
|
+
_type: Type.String,
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
footerRowElements: {
|
|
168
|
+
_type: Type.Array,
|
|
169
|
+
_description: `IDs of patient card elements to appear in the footer row. These can be built-in, or custom ones can be defined in patientCardElementDefinitions. Built-in elements are: '${builtInPatientCardElements.join(
|
|
170
|
+
"', '",
|
|
171
|
+
)}'.`,
|
|
172
|
+
_elements: {
|
|
173
|
+
_type: Type.String,
|
|
164
174
|
},
|
|
165
175
|
},
|
|
166
176
|
appliedTo: {
|
|
167
177
|
_type: Type.Array,
|
|
178
|
+
_description:
|
|
179
|
+
'Conditions under which this card definition should be used. If not provided, the configuration is applied to all wards.',
|
|
168
180
|
_elements: {
|
|
169
181
|
location: {
|
|
170
182
|
_type: Type.UUID,
|
|
171
|
-
_description: 'The UUID of the location. If not provided, applies to all
|
|
183
|
+
_description: 'The UUID of the location. If not provided, applies to all wards.',
|
|
172
184
|
_default: null,
|
|
173
185
|
},
|
|
174
186
|
},
|
|
@@ -183,120 +195,42 @@ export interface WardConfigObject {
|
|
|
183
195
|
}
|
|
184
196
|
|
|
185
197
|
export interface WardPatientCardsConfig {
|
|
186
|
-
|
|
198
|
+
obsElementDefinitions: Array<ObsElementDefinition>;
|
|
199
|
+
identifierElementDefinitions: Array<IdentifierElementDefinition>;
|
|
200
|
+
addressElementDefinitions: Array<AddressElementDefinition>;
|
|
187
201
|
cardDefinitions: Array<WardPatientCardDefinition>;
|
|
188
202
|
}
|
|
189
203
|
|
|
190
|
-
export interface
|
|
204
|
+
export interface ObsElementDefinition {
|
|
191
205
|
id: string;
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* an array of (either built-in or custom) patient card element ids
|
|
200
|
-
*/
|
|
201
|
-
elements: Array<string>;
|
|
202
|
-
}>;
|
|
203
|
-
appliedTo?: Array<{
|
|
204
|
-
/**
|
|
205
|
-
* locationUuid. If given, only applies to patients at the specified ward locations. (If not provided, applies to all locations)
|
|
206
|
-
*/
|
|
207
|
-
location: string;
|
|
208
|
-
}>;
|
|
206
|
+
conceptUuid: string;
|
|
207
|
+
onlyWithinCurrentVisit: boolean;
|
|
208
|
+
orderBy: 'ascending' | 'descending';
|
|
209
|
+
limit: number;
|
|
210
|
+
label?: string;
|
|
211
|
+
labelI18nModule?: string;
|
|
209
212
|
}
|
|
210
213
|
|
|
211
|
-
export
|
|
214
|
+
export interface IdentifierElementDefinition {
|
|
212
215
|
id: string;
|
|
213
|
-
|
|
214
|
-
config?: PatientCardElementConfig;
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
export interface PatientAddressElementConfig {
|
|
218
|
-
addressFields: Array<keyof PersonAddress>;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
export interface PatientObsElementConfig {
|
|
222
|
-
/**
|
|
223
|
-
* Required. Identifies the concept to use to identify the desired observations.
|
|
224
|
-
*/
|
|
225
|
-
conceptUuid: string;
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Optional. The custom label or i18n key to the translated label to display. If not provided, defaults to the concept's name.
|
|
229
|
-
* (Note that this can be set to an empty string to not show a label)
|
|
230
|
-
*/
|
|
216
|
+
identifierTypeUuid: string;
|
|
231
217
|
label?: string;
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* Optional. The custom module to use for translation of the label
|
|
235
|
-
*/
|
|
236
218
|
labelI18nModule?: string;
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Optional. One of 'ascending' or 'descending', specifying whether to display the obs by obsDatetime ascendingly or descendingly. Defaults to descending.
|
|
240
|
-
*/
|
|
241
|
-
orderBy?: 'ascending' | 'descending';
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* Optional. Limits the max number of obs to display. Unlimited by default.
|
|
245
|
-
*/
|
|
246
|
-
limit?: number;
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Optional. If true, limits display to only observations within current visit
|
|
250
|
-
*/
|
|
251
|
-
onlyWithinCurrentVisit?: boolean;
|
|
252
219
|
}
|
|
253
220
|
|
|
254
|
-
export interface
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
conceptUuid: string;
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* Optional. The custom label or i18n key to the translated label to display for the summary tag. The summary tag
|
|
262
|
-
* shows the count of the number of answers that are present but not configured to show as their own tags. If not
|
|
263
|
-
* provided, defaults to the name of the concept.
|
|
264
|
-
*/
|
|
265
|
-
summaryLabel?: string;
|
|
266
|
-
/**
|
|
267
|
-
* Optional. The custom module to use for translation of the summary label
|
|
268
|
-
*/
|
|
269
|
-
summaryLabelI18nModule?: string;
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* The color of the summary tag.
|
|
273
|
-
* See https://react.carbondesignsystem.com/?path=/docs/components-tag--overview for a list of supported colors
|
|
274
|
-
*/
|
|
275
|
-
summaryLabelColor?: string;
|
|
276
|
-
|
|
277
|
-
/**
|
|
278
|
-
* An array specifying concept sets and color. Observations with coded values that are members of the specified concept sets
|
|
279
|
-
* will be displayed as their own tags with the specified color. Any observation with coded values not belonging to
|
|
280
|
-
* any concept sets specified will be summarized as a count in the summary tag. If a concept set is listed multiple times,
|
|
281
|
-
* the first matching applied-to rule takes precedence.
|
|
282
|
-
*/
|
|
283
|
-
tags: Array<{
|
|
284
|
-
/**
|
|
285
|
-
* Color of the tag. See https://react.carbondesignsystem.com/?path=/docs/components-tag--overview for a list of supported colors.
|
|
286
|
-
*/
|
|
287
|
-
color: string;
|
|
221
|
+
export interface AddressElementDefinition {
|
|
222
|
+
id: string;
|
|
223
|
+
fields: Array<AddressField>;
|
|
224
|
+
}
|
|
288
225
|
|
|
226
|
+
export interface WardPatientCardDefinition {
|
|
227
|
+
id: string;
|
|
228
|
+
headerRowElements: Array<string>;
|
|
229
|
+
footerRowElements: Array<string>;
|
|
230
|
+
appliedTo?: Array<{
|
|
289
231
|
/**
|
|
290
|
-
*
|
|
291
|
-
* will be displayed as their own tag with the specified color.
|
|
292
|
-
* If an observation's coded value belongs to multiple concept sets, the first matching applied-to rule takes precedence.
|
|
232
|
+
* locationUuid. If given, only applies to patients at the specified ward locations. (If not provided, applies to all locations)
|
|
293
233
|
*/
|
|
294
|
-
|
|
234
|
+
location: string;
|
|
295
235
|
}>;
|
|
296
236
|
}
|
|
297
|
-
|
|
298
|
-
export type PatientCardElementConfig = {
|
|
299
|
-
address: PatientAddressElementConfig;
|
|
300
|
-
obs: PatientObsElementConfig;
|
|
301
|
-
codedObsTags: PatientCodedObsTagsElementConfig;
|
|
302
|
-
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import { ConfigurableLink } from '@openmrs/esm-framework';
|
|
4
|
+
import { BrowserRouter, useLocation } from 'react-router-dom';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
|
|
7
|
+
export interface DashboardLinkConfig {
|
|
8
|
+
name: string;
|
|
9
|
+
title: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// TODO: extract this out into the esm-framework and all 4 copies of this file in this repo?
|
|
13
|
+
|
|
14
|
+
function DashboardExtension({ dashboardLinkConfig }: { dashboardLinkConfig: DashboardLinkConfig }) {
|
|
15
|
+
//
|
|
16
|
+
const { t } = useTranslation();
|
|
17
|
+
const { name, title } = dashboardLinkConfig;
|
|
18
|
+
const location = useLocation();
|
|
19
|
+
const spaBasePath = `${window.spaBase}/home`;
|
|
20
|
+
|
|
21
|
+
const navLink = useMemo(() => {
|
|
22
|
+
const pathArray = location.pathname.split('/home');
|
|
23
|
+
const lastElement = pathArray[pathArray.length - 1];
|
|
24
|
+
return decodeURIComponent(lastElement);
|
|
25
|
+
}, [location.pathname]);
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<ConfigurableLink
|
|
29
|
+
className={classNames('cds--side-nav__link', {
|
|
30
|
+
'active-left-nav-link': navLink.match(name),
|
|
31
|
+
})}
|
|
32
|
+
to={`${spaBasePath}/${name}`}>
|
|
33
|
+
{t(title)}
|
|
34
|
+
</ConfigurableLink>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const createDashboardLink = (dashboardLinkConfig: DashboardLinkConfig) => () => (
|
|
39
|
+
<BrowserRouter>
|
|
40
|
+
<DashboardExtension dashboardLinkConfig={dashboardLinkConfig} />
|
|
41
|
+
</BrowserRouter>
|
|
42
|
+
);
|
|
@@ -1,13 +1,18 @@
|
|
|
1
|
-
import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import { type FetchResponse, openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
|
|
2
|
+
import { type AdmissionLocationFetchResponse } from '../types/index';
|
|
3
|
+
import useSWRImmutable from 'swr/immutable';
|
|
4
|
+
import useWardLocation from './useWardLocation';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const { data, ...rest } = useSWR<{ data: AdmissionLocation }, Error>(apiUrl, openmrsFetch);
|
|
6
|
+
const requestRep =
|
|
7
|
+
'custom:(ward,totalBeds,occupiedBeds,bedLayouts:(rowNumber,columnNumber,bedNumber,bedId,bedUuid,status,location,patients:(person:full,identifiers,uuid)))';
|
|
8
8
|
|
|
9
|
+
// note "admissionLocation" sn't the clearest name, but it matches the endpoint; endpoint fetches bed information (including info about patients in those beds) for a location (as provided by the bed management module)
|
|
10
|
+
export function useAdmissionLocation(rep: string = requestRep) {
|
|
11
|
+
const { location } = useWardLocation();
|
|
12
|
+
const apiUrl = location?.uuid ? `${restBaseUrl}/admissionLocation/${location?.uuid}?v=${rep}` : null;
|
|
13
|
+
const { data, ...rest } = useSWRImmutable<FetchResponse<AdmissionLocationFetchResponse>, Error>(apiUrl, openmrsFetch);
|
|
9
14
|
return {
|
|
10
|
-
admissionLocation: data?.data
|
|
15
|
+
admissionLocation: data?.data,
|
|
11
16
|
...rest,
|
|
12
17
|
};
|
|
13
18
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { useConfig } from '@openmrs/esm-framework';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { type WardConfigObject, defaultWardPatientCard } from '../config-schema';
|
|
4
|
+
import useWardLocation from './useWardLocation';
|
|
5
|
+
|
|
6
|
+
export function useCurrentWardCardConfig() {
|
|
7
|
+
const { wardPatientCards } = useConfig<WardConfigObject>();
|
|
8
|
+
const {
|
|
9
|
+
location: { uuid: locationUuid },
|
|
10
|
+
} = useWardLocation();
|
|
11
|
+
|
|
12
|
+
const currentWardCardConfig = useMemo(() => {
|
|
13
|
+
const cardDefinition = wardPatientCards.cardDefinitions.find((cardDef) => {
|
|
14
|
+
return (
|
|
15
|
+
cardDef.appliedTo == null ||
|
|
16
|
+
cardDef.appliedTo?.length == 0 ||
|
|
17
|
+
cardDef.appliedTo.some((criteria) => criteria.location == locationUuid)
|
|
18
|
+
);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
return cardDefinition;
|
|
22
|
+
}, [wardPatientCards, locationUuid]);
|
|
23
|
+
|
|
24
|
+
if (!currentWardCardConfig) {
|
|
25
|
+
console.warn(
|
|
26
|
+
'No ward card configuration has `appliedTo` criteria that matches the current location. Using the default configuration.',
|
|
27
|
+
);
|
|
28
|
+
return defaultWardPatientCard;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return currentWardCardConfig;
|
|
32
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { type FetchResponse, openmrsFetch, type OpenmrsResource, restBaseUrl } from '@openmrs/esm-framework';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import useSWRImmutable from 'swr/immutable';
|
|
4
|
+
import type { DispositionType } from '../types';
|
|
5
|
+
|
|
6
|
+
interface LocationTag extends OpenmrsResource {
|
|
7
|
+
name: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface EmrApiConfigurationResponse {
|
|
11
|
+
admissionEncounterType: OpenmrsResource;
|
|
12
|
+
clinicianEncounterRole: OpenmrsResource;
|
|
13
|
+
consultFreeTextCommentsConcept: OpenmrsResource;
|
|
14
|
+
visitNoteEncounterType: OpenmrsResource;
|
|
15
|
+
transferWithinHospitalEncounterType: OpenmrsResource;
|
|
16
|
+
supportsTransferLocationTag: LocationTag;
|
|
17
|
+
supportsAdmissionLocationTag: LocationTag;
|
|
18
|
+
supportsLoginLocationTag: LocationTag;
|
|
19
|
+
supportsVisitsLocationTag: LocationTag;
|
|
20
|
+
dispositionDescriptor: {
|
|
21
|
+
admissionLocationConcept: OpenmrsResource;
|
|
22
|
+
dateOfDeathConcept: OpenmrsResource;
|
|
23
|
+
dispositionConcept: OpenmrsResource;
|
|
24
|
+
internalTransferLocationConcept: OpenmrsResource;
|
|
25
|
+
dispositionSetConcept: OpenmrsResource;
|
|
26
|
+
};
|
|
27
|
+
dispositions: Array<{
|
|
28
|
+
encounterTypes: null;
|
|
29
|
+
keepsVisitOpen: null;
|
|
30
|
+
additionalObs: null;
|
|
31
|
+
careSettingTypes: ['OUTPATIENT'];
|
|
32
|
+
name: string;
|
|
33
|
+
conceptCode: string;
|
|
34
|
+
type: DispositionType;
|
|
35
|
+
actions: [];
|
|
36
|
+
excludedEncounterTypes: Array<string>;
|
|
37
|
+
uuid: string;
|
|
38
|
+
}>;
|
|
39
|
+
// There are many more keys to this object, but we only need these for now
|
|
40
|
+
// Add more keys as needed
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const customRepProps = [
|
|
44
|
+
['metadataSourceName', 'ref'],
|
|
45
|
+
['orderingProviderEncounterRole', 'ref'],
|
|
46
|
+
['supportsTransferLocationTag', '(uuid,display,name,links)'],
|
|
47
|
+
['unknownLocation', 'ref'],
|
|
48
|
+
['denyAdmissionConcept', 'ref'],
|
|
49
|
+
['admissionForm', 'ref'],
|
|
50
|
+
['exitFromInpatientEncounterType', 'ref'],
|
|
51
|
+
['extraPatientIdentifierTypes', 'ref'],
|
|
52
|
+
['consultFreeTextCommentsConcept', 'ref'],
|
|
53
|
+
['sameAsConceptMapType', 'ref'],
|
|
54
|
+
['testPatientPersonAttributeType', 'ref'],
|
|
55
|
+
['admissionDecisionConcept', 'ref'],
|
|
56
|
+
['supportsAdmissionLocationTag', '(uuid,display,name,links)'],
|
|
57
|
+
['checkInEncounterType', 'ref'],
|
|
58
|
+
['transferWithinHospitalEncounterType', 'ref'],
|
|
59
|
+
['suppressedDiagnosisConcepts', 'ref'],
|
|
60
|
+
['primaryIdentifierType', 'ref'],
|
|
61
|
+
['nonDiagnosisConceptSets', 'ref'],
|
|
62
|
+
['fullPrivilegeLevel', 'ref'],
|
|
63
|
+
['unknownProvider', 'ref'],
|
|
64
|
+
['diagnosisSets', 'ref'],
|
|
65
|
+
['personImageDirectory', 'ref'],
|
|
66
|
+
['visitNoteEncounterType', 'ref'],
|
|
67
|
+
['consultEncounterType', 'ref'],
|
|
68
|
+
['diagnosisMetadata', 'ref'],
|
|
69
|
+
['narrowerThanConceptMapType', 'ref'],
|
|
70
|
+
['clinicianEncounterRole', 'ref'],
|
|
71
|
+
['conceptSourcesForDiagnosisSearch', 'ref'],
|
|
72
|
+
['patientDiedConcept', 'ref'],
|
|
73
|
+
['emrApiConceptSource', 'ref'],
|
|
74
|
+
['lastViewedPatientSizeLimit', 'ref'],
|
|
75
|
+
['identifierTypesToSearch', 'ref'],
|
|
76
|
+
['telephoneAttributeType', 'ref'],
|
|
77
|
+
['checkInClerkEncounterRole', 'ref'],
|
|
78
|
+
['dischargeForm', 'ref'],
|
|
79
|
+
['unknownCauseOfDeathConcept', 'ref'],
|
|
80
|
+
['visitAssignmentHandlerAdjustEncounterTimeOfDayIfNecessary', 'ref'],
|
|
81
|
+
['atFacilityVisitType', 'ref'],
|
|
82
|
+
['visitExpireHours', 'ref'],
|
|
83
|
+
['admissionEncounterType', 'ref'],
|
|
84
|
+
['motherChildRelationshipType', 'ref'],
|
|
85
|
+
['dispositions', 'ref'],
|
|
86
|
+
['dispositionDescriptor', 'ref'],
|
|
87
|
+
['highPrivilegeLevel', 'ref'],
|
|
88
|
+
['supportsLoginLocationTag', '(uuid,display,name,links)'],
|
|
89
|
+
['unknownPatientPersonAttributeType', 'ref'],
|
|
90
|
+
['supportsVisitsLocationTag', '(uuid,display,name,links)'],
|
|
91
|
+
['transferForm', 'ref'],
|
|
92
|
+
];
|
|
93
|
+
|
|
94
|
+
const customRep = `custom:${customRepProps.map((prop) => prop.join(':')).join(',')}`;
|
|
95
|
+
|
|
96
|
+
export default function useEmrConfiguration() {
|
|
97
|
+
const swrData = useSWRImmutable<FetchResponse<EmrApiConfigurationResponse>>(
|
|
98
|
+
`${restBaseUrl}/emrapi/configuration?v=${customRep}`,
|
|
99
|
+
openmrsFetch,
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
const results = useMemo(
|
|
103
|
+
() => ({
|
|
104
|
+
emrConfiguration: swrData.data?.data,
|
|
105
|
+
isLoadingEmrConfiguration: swrData.isLoading,
|
|
106
|
+
mutateEmrConfiguration: swrData.mutate,
|
|
107
|
+
errorFetchingEmrConfiguration: swrData.error,
|
|
108
|
+
}),
|
|
109
|
+
[swrData],
|
|
110
|
+
);
|
|
111
|
+
return results;
|
|
112
|
+
}
|