fhir-react 0.3.5 → 0.3.8
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/.circleci/config.yml +1 -1
- package/.eslintrc +10 -1
- package/.stylelintrc +6 -2
- package/README.md +19 -1
- package/build/index.js +15 -11
- package/build/style.css +9 -8
- package/package.json +55 -54
- package/src/assets/containers/AdverseEvent/adverse-event.svg +6 -0
- package/src/assets/containers/Coverage/coverage.svg +4 -0
- package/src/assets/containers/{ResourceCategory/resource-placeholder.svg → Generic/generic.svg} +0 -0
- package/src/assets/containers/MedicationDispense/medication-dispense.svg +5 -0
- package/src/assets/containers/MedicationOrder/medication-order.svg +5 -0
- package/src/assets/containers/MedicationRequest/medication-request.svg +5 -0
- package/src/assets/containers/Organization/organization.svg +5 -0
- package/src/assets/containers/PractitionerRole/practitioner-role.svg +5 -0
- package/src/assets/containers/ReferralRequest/referral-request.svg +8 -0
- package/src/assets/containers/RelatedPerson/related-person.svg +6 -0
- package/src/assets/containers/ResourceCategory/resource-category.svg +3 -0
- package/src/components/containers/Accordion/Accordion.js +21 -13
- package/src/components/datatypes/Attachment/Attachment.css +5 -0
- package/src/components/datatypes/Attachment/Attachment.js +7 -2
- package/src/components/datatypes/CodeableConcept/CodeableConcept.js +6 -3
- package/src/components/datatypes/Coding/Coding.js +7 -3
- package/src/components/datatypes/Identifier/Identifier.js +7 -3
- package/src/components/datatypes/Reference/Reference.js +7 -1
- package/src/components/datatypes/Telecom/Telecom.js +2 -3
- package/src/components/resources/AdverseEvent/AdverseEvent.js +81 -42
- package/src/components/resources/AdverseEvent/AdverseEvent.stories.js +12 -2
- package/src/components/resources/AdverseEvent/AdverseEvent.test.js +109 -2
- package/src/components/resources/AllergyIntolerance/AllergyIntolerance.js +9 -5
- package/src/components/resources/AllergyIntolerance/AllergyIntolerance.stories.js +5 -4
- package/src/components/resources/AllergyIntolerance/AllergyIntolerance.test.js +107 -1
- package/src/components/resources/Appointment/Appointment.js +2 -1
- package/src/components/resources/Appointment/Appointment.test.js +36 -1
- package/src/components/resources/Binary/Binary.js +1 -2
- package/src/components/resources/Binary/Binary.stories.js +10 -4
- package/src/components/resources/Binary/Binary.test.js +67 -0
- package/src/components/resources/Bundle/Bundle.css +7 -0
- package/src/components/resources/Bundle/Bundle.js +15 -11
- package/src/components/resources/Bundle/Bundle.stories.js +12 -78
- package/src/components/resources/Bundle/Bundle.test.js +0 -3
- package/src/components/resources/CarePlan/CarePlan.js +2 -1
- package/src/components/resources/CarePlan/CarePlan.stories.js +31 -5
- package/src/components/resources/CarePlan/CarePlan.test.js +114 -6
- package/src/components/resources/CareTeam/CareTeam.js +72 -50
- package/src/components/resources/CareTeam/CareTeam.stories.js +20 -3
- package/src/components/resources/CareTeam/CareTeam.test.js +109 -1
- package/src/components/resources/CareTeam/CareTeamParticipants.js +1 -1
- package/src/components/resources/Claim/CareTeam.js +55 -0
- package/src/components/resources/Claim/Claim.css +2 -11
- package/src/components/resources/Claim/Claim.js +158 -309
- package/src/components/resources/Claim/Claim.stories.js +37 -5
- package/src/components/resources/Claim/Claim.test.js +104 -1
- package/src/components/resources/Claim/Diagnosis.js +61 -0
- package/src/components/resources/Claim/Insurance.js +58 -0
- package/src/components/resources/Claim/Item.js +79 -0
- package/src/components/resources/Claim/Items.js +29 -0
- package/src/components/resources/ClaimResponse/AddedItem.js +61 -11
- package/src/components/resources/ClaimResponse/AddedItems.js +5 -9
- package/src/components/resources/ClaimResponse/ClaimResponse.js +137 -83
- package/src/components/resources/ClaimResponse/ClaimResponse.stories.js +15 -2
- package/src/components/resources/ClaimResponse/ClaimResponse.test.js +112 -1
- package/src/components/resources/ClaimResponse/Item.js +44 -9
- package/src/components/resources/ClaimResponse/Items.js +5 -4
- package/src/components/resources/Condition/Condition.js +3 -3
- package/src/components/resources/Condition/Condition.test.js +37 -4
- package/src/components/resources/Coverage/Coverage.js +97 -69
- package/src/components/resources/Coverage/Coverage.stories.js +31 -5
- package/src/components/resources/Coverage/Coverage.test.js +111 -4
- package/src/components/resources/Device/Device.js +2 -1
- package/src/components/resources/Device/Device.stories.js +33 -5
- package/src/components/resources/Device/Device.test.js +108 -1
- package/src/components/resources/DiagnosticReport/DiagnosticReport.js +7 -2
- package/src/components/resources/DiagnosticReport/DiagnosticReport.stories.js +5 -4
- package/src/components/resources/DiagnosticReport/DiagnosticReport.test.js +107 -1
- package/src/components/resources/DocumentReference/DocumentReference.js +7 -2
- package/src/components/resources/DocumentReference/DocumentReference.stories.js +3 -2
- package/src/components/resources/DocumentReference/DocumentReference.test.js +113 -1
- package/src/components/resources/Encounter/Encounter.js +2 -1
- package/src/components/resources/Encounter/Encounter.test.js +36 -1
- package/src/components/resources/ExplanationOfBenefit/ExplanationOfBenefit.js +2 -0
- package/src/components/resources/ExplanationOfBenefit/ExplanationOfBenefit.test.js +38 -1
- package/src/components/resources/FamilyMemberHistory/FamilyMemberHistory.js +7 -2
- package/src/components/resources/FamilyMemberHistory/FamilyMemberHistory.stories.js +3 -2
- package/src/components/resources/FamilyMemberHistory/FamilyMemberHistory.test.js +108 -1
- package/src/components/resources/Generic/Generic.js +20 -7
- package/src/components/resources/Generic/Generic.stories.js +2 -1
- package/src/components/resources/Generic/Generic.test.js +26 -7
- package/src/components/resources/Goal/Goal.js +3 -5
- package/src/components/resources/Goal/Goal.stories.js +5 -4
- package/src/components/resources/Goal/Goal.test.js +101 -1
- package/src/components/resources/Immunization/Immunization.js +2 -2
- package/src/components/resources/Immunization/Immunization.test.js +36 -1
- package/src/components/resources/List/DrugTierDefinitionExtension.js +79 -35
- package/src/components/resources/List/Entries.js +3 -3
- package/src/components/resources/List/List.js +135 -88
- package/src/components/resources/List/List.stories.js +38 -5
- package/src/components/resources/List/List.test.js +105 -1
- package/src/components/resources/Location/Location.js +65 -47
- package/src/components/resources/Location/Location.stories.js +11 -4
- package/src/components/resources/Location/Location.test.js +106 -4
- package/src/components/resources/Medication/Medication.js +91 -51
- package/src/components/resources/Medication/Medication.stories.js +37 -7
- package/src/components/resources/Medication/Medication.test.js +113 -4
- package/src/components/resources/MedicationAdministration/MedicationAdministration.js +86 -62
- package/src/components/resources/MedicationAdministration/MedicationAdministration.stories.js +7 -0
- package/src/components/resources/MedicationAdministration/MedicationAdministration.test.js +117 -1
- package/src/components/resources/MedicationDispense/DosageInstruction.js +25 -0
- package/src/components/resources/MedicationDispense/MedicationDispense.js +68 -68
- package/src/components/resources/MedicationDispense/MedicationDispense.stories.js +7 -0
- package/src/components/resources/MedicationDispense/MedicationDispense.test.js +108 -1
- package/src/components/resources/MedicationKnowledge/MedicationKnowledge.js +115 -66
- package/src/components/resources/MedicationKnowledge/MedicationKnowledge.stories.js +6 -0
- package/src/components/resources/MedicationKnowledge/MedicationKnowledge.test.js +110 -1
- package/src/components/resources/MedicationOrder/MedicationOrder.js +3 -4
- package/src/components/resources/MedicationOrder/MedicationOrder.stories.js +1 -2
- package/src/components/resources/MedicationOrder/MedicationOrder.test.js +102 -4
- package/src/components/resources/MedicationRequest/MedicationRequest.js +3 -4
- package/src/components/resources/MedicationRequest/MedicationRequest.stories.js +11 -6
- package/src/components/resources/MedicationRequest/MedicationRequest.test.js +100 -4
- package/src/components/resources/MedicationStatement/MedicationDosage.js +2 -2
- package/src/components/resources/MedicationStatement/MedicationStatement.js +8 -2
- package/src/components/resources/MedicationStatement/MedicationStatement.stories.js +5 -4
- package/src/components/resources/MedicationStatement/MedicationStatement.test.js +108 -1
- package/src/components/resources/Observation/Observation.js +2 -1
- package/src/components/resources/Observation/Observation.test.js +30 -1
- package/src/components/resources/Organization/Organization.js +56 -37
- package/src/components/resources/Organization/Organization.stories.js +15 -2
- package/src/components/resources/Organization/Organization.test.js +109 -1
- package/src/components/resources/Patient/Patient.js +2 -0
- package/src/components/resources/Patient/Patient.test.js +31 -2
- package/src/components/resources/Practitioner/Practitioner.js +2 -1
- package/src/components/resources/Practitioner/Practitioner.test.js +36 -1
- package/src/components/resources/PractitionerRole/PractitionerRole.js +50 -29
- package/src/components/resources/PractitionerRole/PractitionerRole.stories.js +7 -0
- package/src/components/resources/PractitionerRole/PractitionerRole.test.js +108 -1
- package/src/components/resources/Procedure/Procedure.js +2 -2
- package/src/components/resources/Procedure/Procedure.test.js +30 -1
- package/src/components/resources/Questionnaire/Group.js +53 -0
- package/src/components/resources/Questionnaire/Items.js +45 -0
- package/src/components/resources/Questionnaire/Questionnaire.css +24 -5
- package/src/components/resources/Questionnaire/Questionnaire.js +31 -170
- package/src/components/resources/Questionnaire/Questionnaire.stories.js +8 -0
- package/src/components/resources/Questionnaire/Questionnaire.test.js +194 -15
- package/src/components/resources/Questionnaire/Questions.js +40 -0
- package/src/components/resources/Questionnaire/getQuestionText.js +20 -0
- package/src/components/resources/QuestionnaireResponse/Answers.js +59 -0
- package/src/components/resources/QuestionnaireResponse/Group.js +70 -0
- package/src/components/resources/QuestionnaireResponse/Items.js +45 -0
- package/src/components/resources/QuestionnaireResponse/QuestionnaireResponse.css +33 -8
- package/src/components/resources/QuestionnaireResponse/QuestionnaireResponse.js +52 -236
- package/src/components/resources/QuestionnaireResponse/QuestionnaireResponse.stories.js +8 -0
- package/src/components/resources/QuestionnaireResponse/QuestionnaireResponse.test.js +38 -3
- package/src/components/resources/QuestionnaireResponse/Questions.js +43 -0
- package/src/components/resources/QuestionnaireResponse/getQuestionText.js +22 -0
- package/src/components/resources/ReferralRequest/ReferralRequest.js +65 -40
- package/src/components/resources/ReferralRequest/ReferralRequest.test.js +111 -11
- package/src/components/resources/RelatedPerson/RelatedPerson.js +151 -0
- package/src/components/resources/RelatedPerson/RelatedPerson.stories.js +46 -0
- package/src/components/resources/RelatedPerson/RelatedPerson.test.js +156 -0
- package/src/components/resources/RelatedPerson/index.js +3 -0
- package/src/components/resources/ResearchStudy/ResearchStudy.js +160 -130
- package/src/components/resources/ResearchStudy/ResearchStudy.stories.js +2 -0
- package/src/components/resources/ResearchStudy/ResearchStudy.test.js +108 -1
- package/src/components/resources/ResourceCategory/ResourceCategory.js +7 -12
- package/src/components/resources/ResourceCategory/ResourceCategory.stories.js +13 -2
- package/src/components/resources/ResourceCategory/ResourceCategory.test.js +77 -18
- package/src/components/ui/index.js +32 -12
- package/src/fixtures/dstu2/resources/relatedPerson/example1.json +79 -0
- package/src/fixtures/example-icons.jsx +81 -11
- package/src/fixtures/r4/resources/relatedPerson/example1.json +64 -0
- package/src/fixtures/stu3/resources/relatedPerson/example1.json +43 -0
- package/src/style.scss +3 -1
|
@@ -2,164 +2,15 @@ import React from 'react';
|
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import _get from 'lodash/get';
|
|
4
4
|
|
|
5
|
-
import { Root, Header,
|
|
5
|
+
import { Root, Header, Badge, Body, Value } from '../../ui';
|
|
6
6
|
import Date from '../../datatypes/Date';
|
|
7
7
|
import Coding from '../../datatypes/Coding';
|
|
8
8
|
|
|
9
9
|
import './Questionnaire.css';
|
|
10
|
-
import Reference from '../../datatypes/Reference/Reference';
|
|
11
10
|
import fhirVersions from '../fhirResourceVersions';
|
|
12
11
|
import UnhandledResourceDataStructure from '../UnhandledResourceDataStructure';
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
let text = _get(item, 'text');
|
|
16
|
-
if (!text) {
|
|
17
|
-
// DSTU2
|
|
18
|
-
const groupConcept = _get(item, 'concept.0');
|
|
19
|
-
if (groupConcept) {
|
|
20
|
-
text = <Coding fhirData={groupConcept} />;
|
|
21
|
-
}
|
|
22
|
-
// STU3 & R4
|
|
23
|
-
const groupCode = _get(item, 'code.0');
|
|
24
|
-
if (!text && groupCode) {
|
|
25
|
-
text = <Coding fhirData={groupCode} />;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return text;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const Questions = props => {
|
|
32
|
-
const { questions, prepareItems } = props;
|
|
33
|
-
if (!Array.isArray(questions) || questions.length === 0) {
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return (
|
|
38
|
-
<ul className="fhir-resource__Questionnaire-questions-list">
|
|
39
|
-
{questions.map((item, i) => {
|
|
40
|
-
const hasLinkId = item.linkId;
|
|
41
|
-
let type = _get(item, 'type');
|
|
42
|
-
if (type === 'group') {
|
|
43
|
-
type = '';
|
|
44
|
-
}
|
|
45
|
-
const options = _get(item, 'options');
|
|
46
|
-
|
|
47
|
-
const text = getQuestionText(item);
|
|
48
|
-
const hasDetails = type || options;
|
|
49
|
-
return (
|
|
50
|
-
<li key={`item-${i}`} data-testid={`linkId-${item.linkId}`}>
|
|
51
|
-
{hasLinkId && <Badge>{item.linkId}</Badge>}
|
|
52
|
-
{text}
|
|
53
|
-
{hasDetails && (
|
|
54
|
-
<div className="fhir-resource__Questionnaire-questions-list-item-details">
|
|
55
|
-
{type && (
|
|
56
|
-
<div className="fhir-resource__Questionnaire-questions-list-item-details-el">
|
|
57
|
-
Type: {type}
|
|
58
|
-
</div>
|
|
59
|
-
)}
|
|
60
|
-
{options && (
|
|
61
|
-
<div className="fhir-resource__Questionnaire-questions-list-item-details-el">
|
|
62
|
-
Options: <Reference fhirData={options} />
|
|
63
|
-
</div>
|
|
64
|
-
)}
|
|
65
|
-
</div>
|
|
66
|
-
)}
|
|
67
|
-
{item.item && (
|
|
68
|
-
<Group data={item.item} prepareItems={prepareItems} />
|
|
69
|
-
)}
|
|
70
|
-
</li>
|
|
71
|
-
);
|
|
72
|
-
})}
|
|
73
|
-
</ul>
|
|
74
|
-
);
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
Questions.propTypes = {
|
|
78
|
-
questions: PropTypes.array,
|
|
79
|
-
prepareItems: PropTypes.func.isRequired,
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
const Group = props => {
|
|
83
|
-
const { data, prepareItems } = props;
|
|
84
|
-
if (!Array.isArray(data) || data.length === 0) {
|
|
85
|
-
return null;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return data.map(prepareItems).map((item, i) => {
|
|
89
|
-
const linkId = _get(item, 'linkId', '');
|
|
90
|
-
|
|
91
|
-
const text = getQuestionText(item);
|
|
92
|
-
let nestedItems = _get(item, 'item', []);
|
|
93
|
-
nestedItems = nestedItems.map(prepareItems);
|
|
94
|
-
const isGroup = _get(item, 'isGroup');
|
|
95
|
-
return (
|
|
96
|
-
<ul key={`item-${i}`} className="fhir-resource__Questionnaire-list">
|
|
97
|
-
<li
|
|
98
|
-
className="fhir-resource__Questionnaire-list-title"
|
|
99
|
-
data-testid={`linkId-${item.linkId}`}
|
|
100
|
-
>
|
|
101
|
-
<Badge>{linkId}</Badge>
|
|
102
|
-
<span>{text}</span>
|
|
103
|
-
</li>
|
|
104
|
-
{!isGroup && (
|
|
105
|
-
<li>
|
|
106
|
-
{<Questions questions={nestedItems} prepareItems={prepareItems} />}
|
|
107
|
-
</li>
|
|
108
|
-
)}
|
|
109
|
-
{isGroup && (
|
|
110
|
-
<li>
|
|
111
|
-
<Group data={nestedItems} prepareItems={prepareItems} />
|
|
112
|
-
</li>
|
|
113
|
-
)}
|
|
114
|
-
</ul>
|
|
115
|
-
);
|
|
116
|
-
});
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
Group.propTypes = {
|
|
120
|
-
data: PropTypes.array,
|
|
121
|
-
prepareItems: PropTypes.func.isRequired,
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
const Items = props => {
|
|
125
|
-
const { fhirVersion, data } = props;
|
|
126
|
-
|
|
127
|
-
if (fhirVersion === fhirVersions.DSTU2) {
|
|
128
|
-
const prepareItems = item => ({
|
|
129
|
-
...item,
|
|
130
|
-
item: _get(item, 'question') || _get(item, 'group') || [],
|
|
131
|
-
isGroup: !!_get(item, 'group'),
|
|
132
|
-
});
|
|
133
|
-
return <Group data={data} prepareItems={prepareItems} />;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (fhirVersion === fhirVersions.STU3) {
|
|
137
|
-
const prepareItems = item => ({
|
|
138
|
-
...item,
|
|
139
|
-
isGroup: _get(item, 'type') === 'group',
|
|
140
|
-
});
|
|
141
|
-
return <Group data={data} prepareItems={prepareItems} />;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
if (fhirVersion === fhirVersions.R4) {
|
|
145
|
-
const prepareItems = item => ({
|
|
146
|
-
...item,
|
|
147
|
-
isGroup: _get(item, 'type') === 'group',
|
|
148
|
-
});
|
|
149
|
-
return <Group data={data} prepareItems={prepareItems} />;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
return null;
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
Items.propTypes = {
|
|
156
|
-
data: PropTypes.array,
|
|
157
|
-
fhirVersion: PropTypes.oneOf([
|
|
158
|
-
fhirVersions.DSTU2,
|
|
159
|
-
fhirVersions.STU3,
|
|
160
|
-
fhirVersions.R4,
|
|
161
|
-
]).isRequired,
|
|
162
|
-
};
|
|
12
|
+
import Items from './Items';
|
|
13
|
+
import Accordion from '../../containers/Accordion';
|
|
163
14
|
|
|
164
15
|
const commonDTO = fhirResource => {
|
|
165
16
|
const status = _get(fhirResource, 'status');
|
|
@@ -224,8 +75,7 @@ const resourceDTO = (fhirVersion, fhirResource) => {
|
|
|
224
75
|
}
|
|
225
76
|
};
|
|
226
77
|
|
|
227
|
-
const Questionnaire =
|
|
228
|
-
const { fhirResource, fhirVersion } = props;
|
|
78
|
+
const Questionnaire = ({ fhirResource, fhirVersion, fhirIcons, onClick }) => {
|
|
229
79
|
let fhirResourceData = {};
|
|
230
80
|
|
|
231
81
|
try {
|
|
@@ -238,22 +88,33 @@ const Questionnaire = props => {
|
|
|
238
88
|
|
|
239
89
|
return (
|
|
240
90
|
<Root name="Questionnaire">
|
|
241
|
-
<
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
<
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
91
|
+
<Accordion
|
|
92
|
+
headerContent={
|
|
93
|
+
<Header
|
|
94
|
+
resourceName="Questionnaire"
|
|
95
|
+
title={title}
|
|
96
|
+
badges={status && <Badge data-testid="status">{status}</Badge>}
|
|
97
|
+
additionalContent={
|
|
98
|
+
dateTime && (
|
|
99
|
+
<Value label="On" data-testid="dateTime">
|
|
100
|
+
<Date fhirData={dateTime} isBlack />
|
|
101
|
+
</Value>
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
icon={fhirIcons}
|
|
105
|
+
/>
|
|
106
|
+
}
|
|
107
|
+
bodyContent={
|
|
108
|
+
<Body>
|
|
109
|
+
{rootItems && (
|
|
110
|
+
<div className="overflow-auto">
|
|
111
|
+
<Items fhirVersion={fhirVersion} data={rootItems} />
|
|
112
|
+
</div>
|
|
113
|
+
)}
|
|
114
|
+
</Body>
|
|
115
|
+
}
|
|
116
|
+
onClick={onClick}
|
|
117
|
+
/>
|
|
257
118
|
</Root>
|
|
258
119
|
);
|
|
259
120
|
};
|
|
@@ -15,6 +15,9 @@ import r4Example1 from '../../../fixtures/r4/resources/questionnaire/example1.js
|
|
|
15
15
|
import r4Example2 from '../../../fixtures/r4/resources/questionnaire/example2.json';
|
|
16
16
|
import r4Example3 from '../../../fixtures/r4/resources/questionnaire/example3.json';
|
|
17
17
|
|
|
18
|
+
import fhirIcons from '../../../fixtures/example-icons';
|
|
19
|
+
import QuestionnaireIcon from '../../../assets/containers/Questionnaire/questionnaire.svg';
|
|
20
|
+
|
|
18
21
|
export default { title: 'Questionnaire' };
|
|
19
22
|
|
|
20
23
|
export const DefaultVisualizationDSTU2 = () => {
|
|
@@ -23,6 +26,7 @@ export const DefaultVisualizationDSTU2 = () => {
|
|
|
23
26
|
<Questionnaire
|
|
24
27
|
fhirResource={fhirResource}
|
|
25
28
|
fhirVersion={fhirVersions.DSTU2}
|
|
29
|
+
fhirIcons={require('../../../assets/containers/Questionnaire/questionnaire.svg')}
|
|
26
30
|
/>
|
|
27
31
|
);
|
|
28
32
|
};
|
|
@@ -33,6 +37,7 @@ export const Example2OfDSTU2 = () => {
|
|
|
33
37
|
<Questionnaire
|
|
34
38
|
fhirResource={fhirResource}
|
|
35
39
|
fhirVersion={fhirVersions.DSTU2}
|
|
40
|
+
fhirIcons={QuestionnaireIcon}
|
|
36
41
|
/>
|
|
37
42
|
);
|
|
38
43
|
};
|
|
@@ -43,6 +48,7 @@ export const Example3OfDSTU2 = () => {
|
|
|
43
48
|
<Questionnaire
|
|
44
49
|
fhirResource={fhirResource}
|
|
45
50
|
fhirVersion={fhirVersions.DSTU2}
|
|
51
|
+
fhirIcons={fhirIcons}
|
|
46
52
|
/>
|
|
47
53
|
);
|
|
48
54
|
};
|
|
@@ -53,6 +59,7 @@ export const Example1OfSTU3 = () => {
|
|
|
53
59
|
<Questionnaire
|
|
54
60
|
fhirResource={fhirResource}
|
|
55
61
|
fhirVersion={fhirVersions.STU3}
|
|
62
|
+
fhirIcons={false}
|
|
56
63
|
/>
|
|
57
64
|
);
|
|
58
65
|
};
|
|
@@ -63,6 +70,7 @@ export const Example2OfSTU3 = () => {
|
|
|
63
70
|
<Questionnaire
|
|
64
71
|
fhirResource={fhirResource}
|
|
65
72
|
fhirVersion={fhirVersions.STU3}
|
|
73
|
+
fhirIcons={'random text'}
|
|
66
74
|
/>
|
|
67
75
|
);
|
|
68
76
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { render } from '@testing-library/react';
|
|
2
|
+
import { fireEvent, render } from '@testing-library/react';
|
|
3
3
|
|
|
4
4
|
import Questionnaire from './Questionnaire';
|
|
5
5
|
import fhirVersions from '../fhirResourceVersions';
|
|
@@ -13,7 +13,151 @@ import stu3Example2 from '../../../fixtures/stu3/resources/questionnaire/example
|
|
|
13
13
|
import r4Example1 from '../../../fixtures/r4/resources/questionnaire/example1.json';
|
|
14
14
|
import r4Example2 from '../../../fixtures/r4/resources/questionnaire/example2.json';
|
|
15
15
|
|
|
16
|
+
import fhirIcons from '../../../fixtures/example-icons';
|
|
17
|
+
|
|
16
18
|
describe('Questionnaire should render component correctly', () => {
|
|
19
|
+
it('component without a fhirIcons props should render a default icon', () => {
|
|
20
|
+
const defaultProps = {
|
|
21
|
+
fhirVersion: fhirVersions.DSTU2,
|
|
22
|
+
fhirResource: dstu2Example1,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const { getByAltText } = render(<Questionnaire {...defaultProps} />);
|
|
26
|
+
const headerIcon = getByAltText('questionnaire');
|
|
27
|
+
|
|
28
|
+
expect(headerIcon.getAttribute('src')).toContain('IMAGE_MOCK');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('component with a false as a fhirIcons props should render a placeholder', () => {
|
|
32
|
+
const defaultProps = {
|
|
33
|
+
fhirVersion: fhirVersions.DSTU2,
|
|
34
|
+
fhirResource: dstu2Example1,
|
|
35
|
+
fhirIcons: false,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const { getByTestId } = render(<Questionnaire {...defaultProps} />);
|
|
39
|
+
const headerIcon = getByTestId('placeholder');
|
|
40
|
+
|
|
41
|
+
expect(headerIcon).toBeTruthy();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('component with the img as a fhirIcons props should render an img', () => {
|
|
45
|
+
const defaultProps = {
|
|
46
|
+
fhirVersion: fhirVersions.DSTU2,
|
|
47
|
+
fhirResource: dstu2Example1,
|
|
48
|
+
fhirIcons: (
|
|
49
|
+
<img
|
|
50
|
+
src={require('../assets/containers/Questionnaire/questionnaire.svg')}
|
|
51
|
+
alt="clipboard and pen"
|
|
52
|
+
/>
|
|
53
|
+
),
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const { getByAltText } = render(<Questionnaire {...defaultProps} />);
|
|
57
|
+
const headerIcon = getByAltText('clipboard and pen');
|
|
58
|
+
|
|
59
|
+
expect(headerIcon.getAttribute('src')).toContain('IMAGE_MOCK');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('component with the resources object as a fhirIcons props should render an img', () => {
|
|
63
|
+
const defaultProps = {
|
|
64
|
+
fhirVersion: fhirVersions.DSTU2,
|
|
65
|
+
fhirResource: dstu2Example1,
|
|
66
|
+
fhirIcons: fhirIcons,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const { getByAltText } = render(<Questionnaire {...defaultProps} />);
|
|
70
|
+
const headerIcon = getByAltText('clipboard and pen');
|
|
71
|
+
|
|
72
|
+
expect(headerIcon.getAttribute('src')).toContain('IMAGE_MOCK');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('component with the url as a fhirIcons props should render an img', () => {
|
|
76
|
+
const avatarSrc =
|
|
77
|
+
'https://www.gravatar.com/avatar/?s=50&r=any&default=identicon&forcedefault=1';
|
|
78
|
+
const defaultProps = {
|
|
79
|
+
fhirVersion: fhirVersions.DSTU2,
|
|
80
|
+
fhirResource: dstu2Example1,
|
|
81
|
+
fhirIcons: avatarSrc,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const { getByAltText } = render(<Questionnaire {...defaultProps} />);
|
|
85
|
+
const headerIcon = getByAltText('header icon');
|
|
86
|
+
|
|
87
|
+
expect(headerIcon.getAttribute('src')).toContain(avatarSrc);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('component without a fhirIcons props should render a default icon', () => {
|
|
91
|
+
const defaultProps = {
|
|
92
|
+
fhirVersion: fhirVersions.DSTU2,
|
|
93
|
+
fhirResource: dstu2Example1,
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const { getByAltText } = render(<Questionnaire {...defaultProps} />);
|
|
97
|
+
const headerIcon = getByAltText('questionnaire');
|
|
98
|
+
|
|
99
|
+
expect(headerIcon.getAttribute('src')).toContain('IMAGE_MOCK');
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('component with a false as a fhirIcons props should render a placeholder', () => {
|
|
103
|
+
const defaultProps = {
|
|
104
|
+
fhirVersion: fhirVersions.DSTU2,
|
|
105
|
+
fhirResource: dstu2Example1,
|
|
106
|
+
fhirIcons: false,
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const { getByTestId } = render(<Questionnaire {...defaultProps} />);
|
|
110
|
+
const headerIcon = getByTestId('placeholder');
|
|
111
|
+
|
|
112
|
+
expect(headerIcon).toBeTruthy();
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('component with the img as a fhirIcons props should render an img', () => {
|
|
116
|
+
const defaultProps = {
|
|
117
|
+
fhirVersion: fhirVersions.DSTU2,
|
|
118
|
+
fhirResource: dstu2Example1,
|
|
119
|
+
fhirIcons: (
|
|
120
|
+
<img
|
|
121
|
+
src={require('../assets/containers/Questionnaire/questionnaire.svg')}
|
|
122
|
+
alt="clipboard and pen"
|
|
123
|
+
/>
|
|
124
|
+
),
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const { getByAltText } = render(<Questionnaire {...defaultProps} />);
|
|
128
|
+
const headerIcon = getByAltText('clipboard and pen');
|
|
129
|
+
|
|
130
|
+
expect(headerIcon.getAttribute('src')).toContain('IMAGE_MOCK');
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('component with the resources object as a fhirIcons props should render an img', () => {
|
|
134
|
+
const defaultProps = {
|
|
135
|
+
fhirVersion: fhirVersions.DSTU2,
|
|
136
|
+
fhirResource: dstu2Example1,
|
|
137
|
+
fhirIcons: fhirIcons,
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const { getByAltText } = render(<Questionnaire {...defaultProps} />);
|
|
141
|
+
const headerIcon = getByAltText('clipboard and pen');
|
|
142
|
+
|
|
143
|
+
expect(headerIcon.getAttribute('src')).toContain('IMAGE_MOCK');
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('component with the url as a fhirIcons props should render an img', () => {
|
|
147
|
+
const avatarSrc =
|
|
148
|
+
'https://www.gravatar.com/avatar/?s=50&r=any&default=identicon&forcedefault=1';
|
|
149
|
+
const defaultProps = {
|
|
150
|
+
fhirVersion: fhirVersions.DSTU2,
|
|
151
|
+
fhirResource: dstu2Example1,
|
|
152
|
+
fhirIcons: avatarSrc,
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const { getByAltText } = render(<Questionnaire {...defaultProps} />);
|
|
156
|
+
const headerIcon = getByAltText('header icon');
|
|
157
|
+
|
|
158
|
+
expect(headerIcon.getAttribute('src')).toContain(avatarSrc);
|
|
159
|
+
});
|
|
160
|
+
|
|
17
161
|
it('should render component correctly with DSTU2 source data', () => {
|
|
18
162
|
const defaultProps = {
|
|
19
163
|
fhirResource: dstu2Example1,
|
|
@@ -34,16 +178,16 @@ describe('Questionnaire should render component correctly', () => {
|
|
|
34
178
|
|
|
35
179
|
// contain id and test of questions of subgroup
|
|
36
180
|
expect(String(getByTestId('linkId-2.1').textContent).trim()).toEqual(
|
|
37
|
-
'
|
|
181
|
+
'What is your gender?',
|
|
38
182
|
);
|
|
39
183
|
expect(String(getByTestId('linkId-2.2').textContent).trim()).toEqual(
|
|
40
|
-
'
|
|
184
|
+
'What is your date of birth?',
|
|
41
185
|
);
|
|
42
186
|
expect(String(getByTestId('linkId-2.3').textContent).trim()).toEqual(
|
|
43
|
-
'
|
|
187
|
+
'What is your country of birth?',
|
|
44
188
|
);
|
|
45
189
|
expect(String(getByTestId('linkId-2.4').textContent).trim()).toEqual(
|
|
46
|
-
'
|
|
190
|
+
'What is your marital status?',
|
|
47
191
|
);
|
|
48
192
|
});
|
|
49
193
|
|
|
@@ -90,21 +234,21 @@ describe('Questionnaire should render component correctly', () => {
|
|
|
90
234
|
|
|
91
235
|
// contain subgroup description
|
|
92
236
|
expect(String(getByTestId('linkId-2').textContent).trim()).toContain(
|
|
93
|
-
'
|
|
237
|
+
'General questions',
|
|
94
238
|
);
|
|
95
239
|
|
|
96
240
|
// contain id and test of questions of subgroup
|
|
97
241
|
expect(String(getByTestId('linkId-2.1').textContent).trim()).toContain(
|
|
98
|
-
'
|
|
242
|
+
'What is your gender?',
|
|
99
243
|
);
|
|
100
244
|
expect(String(getByTestId('linkId-2.2').textContent).trim()).toEqual(
|
|
101
|
-
'
|
|
245
|
+
'What is your date of birth?',
|
|
102
246
|
);
|
|
103
247
|
expect(String(getByTestId('linkId-2.3').textContent).trim()).toEqual(
|
|
104
|
-
'
|
|
248
|
+
'What is your country of birth?',
|
|
105
249
|
);
|
|
106
250
|
expect(String(getByTestId('linkId-2.4').textContent).trim()).toEqual(
|
|
107
|
-
'
|
|
251
|
+
'What is your marital status?',
|
|
108
252
|
);
|
|
109
253
|
});
|
|
110
254
|
|
|
@@ -151,21 +295,21 @@ describe('Questionnaire should render component correctly', () => {
|
|
|
151
295
|
|
|
152
296
|
// contain subgroup description
|
|
153
297
|
expect(String(getByTestId('linkId-2').textContent).trim()).toContain(
|
|
154
|
-
'
|
|
298
|
+
'General questions',
|
|
155
299
|
);
|
|
156
300
|
|
|
157
301
|
// contain id and test of questions of subgroup
|
|
158
302
|
expect(String(getByTestId('linkId-2.1').textContent).trim()).toContain(
|
|
159
|
-
'
|
|
303
|
+
'What is your gender?',
|
|
160
304
|
);
|
|
161
305
|
expect(String(getByTestId('linkId-2.2').textContent).trim()).toEqual(
|
|
162
|
-
'
|
|
306
|
+
'What is your date of birth?',
|
|
163
307
|
);
|
|
164
308
|
expect(String(getByTestId('linkId-2.3').textContent).trim()).toEqual(
|
|
165
|
-
'
|
|
309
|
+
'What is your country of birth?',
|
|
166
310
|
);
|
|
167
311
|
expect(String(getByTestId('linkId-2.4').textContent).trim()).toEqual(
|
|
168
|
-
'
|
|
312
|
+
'What is your marital status?',
|
|
169
313
|
);
|
|
170
314
|
});
|
|
171
315
|
|
|
@@ -196,4 +340,39 @@ describe('Questionnaire should render component correctly', () => {
|
|
|
196
340
|
String(getByTestId('linkId-1.1.1.1.1').textContent).trim(),
|
|
197
341
|
).toContain('Angina Pectoris');
|
|
198
342
|
});
|
|
343
|
+
|
|
344
|
+
it('should fire custom onClick function', () => {
|
|
345
|
+
const defaultProps = {
|
|
346
|
+
fhirResource: r4Example1,
|
|
347
|
+
fhirVersion: fhirVersions.R4,
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
const onClick = jest.fn();
|
|
351
|
+
const { getByRole } = render(
|
|
352
|
+
<Questionnaire {...defaultProps} onClick={onClick} />,
|
|
353
|
+
);
|
|
354
|
+
const accordion = getByRole('button');
|
|
355
|
+
fireEvent.click(accordion);
|
|
356
|
+
|
|
357
|
+
const attribute = accordion.getAttribute('data-bs-toggle');
|
|
358
|
+
expect(attribute).not.toEqual('collapse');
|
|
359
|
+
expect(onClick).toHaveBeenCalled();
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
it('should not fire custom onClick function', () => {
|
|
363
|
+
const defaultProps = {
|
|
364
|
+
fhirResource: r4Example1,
|
|
365
|
+
fhirVersion: fhirVersions.R4,
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
const onClick = 'test';
|
|
369
|
+
const { getByRole } = render(
|
|
370
|
+
<Questionnaire {...defaultProps} onClick={onClick} />,
|
|
371
|
+
);
|
|
372
|
+
const accordion = getByRole('button');
|
|
373
|
+
fireEvent.click(accordion);
|
|
374
|
+
|
|
375
|
+
const attribute = accordion.getAttribute('data-bs-toggle');
|
|
376
|
+
expect(attribute).toEqual('collapse');
|
|
377
|
+
});
|
|
199
378
|
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import PropTypes from 'prop-types';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import Group from './Group';
|
|
4
|
+
import { getQuestionText } from './getQuestionText';
|
|
5
|
+
|
|
6
|
+
const Questions = ({ questions, prepareItems }) => {
|
|
7
|
+
if (!Array.isArray(questions) || questions.length === 0) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<ul className="fhir-resource__Questionnaire-questions-list">
|
|
13
|
+
{questions.map((item, i) => {
|
|
14
|
+
const text = getQuestionText(item);
|
|
15
|
+
return (
|
|
16
|
+
text && (
|
|
17
|
+
<li
|
|
18
|
+
key={`questionnaire-questions-item-${i}`}
|
|
19
|
+
data-testid={`linkId-${item.linkId}`}
|
|
20
|
+
>
|
|
21
|
+
<div className="fhir-resource__Questionnaire-questions-list-element">
|
|
22
|
+
{text}
|
|
23
|
+
</div>
|
|
24
|
+
{item.item && item.item.length > 0 && (
|
|
25
|
+
<Group data={item.item} prepareItems={prepareItems} isChild />
|
|
26
|
+
)}
|
|
27
|
+
</li>
|
|
28
|
+
)
|
|
29
|
+
);
|
|
30
|
+
})}
|
|
31
|
+
</ul>
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
Questions.propTypes = {
|
|
36
|
+
questions: PropTypes.array,
|
|
37
|
+
prepareItems: PropTypes.func.isRequired,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export default Questions;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import _get from 'lodash/get';
|
|
2
|
+
import Coding from '../../datatypes/Coding';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
export const getQuestionText = item => {
|
|
6
|
+
let text = _get(item, 'text');
|
|
7
|
+
if (!text) {
|
|
8
|
+
// DSTU2
|
|
9
|
+
const groupConcept = _get(item, 'concept.0');
|
|
10
|
+
if (groupConcept) {
|
|
11
|
+
text = <Coding fhirData={groupConcept} />;
|
|
12
|
+
}
|
|
13
|
+
// STU3 & R4
|
|
14
|
+
const groupCode = _get(item, 'code.0');
|
|
15
|
+
if (!text && groupCode) {
|
|
16
|
+
text = <Coding fhirData={groupCode} />;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return text;
|
|
20
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import Date from '../../datatypes/Date';
|
|
2
|
+
import Coding from '../../datatypes/Coding';
|
|
3
|
+
import Attachment from '../../datatypes/Attachment';
|
|
4
|
+
import Quantity from '../../datatypes/Quantity';
|
|
5
|
+
import _get from 'lodash/get';
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import Group from './Group';
|
|
8
|
+
|
|
9
|
+
const answerTypes = {
|
|
10
|
+
valueString: value => value,
|
|
11
|
+
valueDecimal: value => value,
|
|
12
|
+
valueInteger: value => value,
|
|
13
|
+
valueDate: value => <Date fhirData={value} isBlack />,
|
|
14
|
+
valueDateTime: value => <Date fhirData={value} isBlack />,
|
|
15
|
+
valueCoding: value => <Coding fhirData={value} />,
|
|
16
|
+
valueAttachment: value => <Attachment fhirData={value} />,
|
|
17
|
+
valueQuantity: value => <Quantity fhirData={value} />,
|
|
18
|
+
valueBoolean: value => (value ? 'Yes' : 'No'),
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const Answers = props => {
|
|
22
|
+
const { data, prepareItems } = props;
|
|
23
|
+
if (!Array.isArray(data)) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
return (
|
|
27
|
+
<div className="fhir-resource__QuestionnaireResponse-questions-list-item-details">
|
|
28
|
+
{data.map(answer => {
|
|
29
|
+
return Object.keys(answer).map((answerKey, i) => {
|
|
30
|
+
const toRender = [];
|
|
31
|
+
if (typeof answerTypes[answerKey] === 'function') {
|
|
32
|
+
toRender.push(
|
|
33
|
+
<div
|
|
34
|
+
key={`questionnaire-response-answer-item-${i}`}
|
|
35
|
+
className="fhir-resource__QuestionnaireResponse-questions-list-item-details-el"
|
|
36
|
+
data-testid={`${props['data-testid']}-${i}`}
|
|
37
|
+
>
|
|
38
|
+
{answerTypes[answerKey](answer[answerKey])}{' '}
|
|
39
|
+
</div>,
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
if (_get(answer, 'item')) {
|
|
43
|
+
toRender.push(
|
|
44
|
+
<Group
|
|
45
|
+
key={`questionnaire-response-answer-group-item-${i}`}
|
|
46
|
+
data={answer.item}
|
|
47
|
+
prepareItems={prepareItems}
|
|
48
|
+
isChild
|
|
49
|
+
/>,
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
return toRender;
|
|
53
|
+
});
|
|
54
|
+
})}
|
|
55
|
+
</div>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export default Answers;
|