@medplum/react 2.0.0 → 2.0.2
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/dist/cjs/DiagnosticReportDisplay/DiagnosticReportDisplay.d.ts +2 -0
- package/dist/cjs/DiagnosticReportDisplay/DiagnosticReportDisplay.stories.d.ts +1 -0
- package/dist/cjs/MedplumProvider/MedplumProvider.d.ts +8 -0
- package/dist/cjs/NoteDisplay/NoteDisplay.d.ts +6 -0
- package/dist/cjs/{ResourceDiffTable/ResourceDiffTable.stories.d.ts → NoteDisplay/NoteDisplay.stories.d.ts} +3 -1
- package/dist/cjs/QuantityInput/QuantityInput.d.ts +1 -0
- package/dist/cjs/QuantityInput/QuantityInput.stories.d.ts +7 -0
- package/dist/cjs/ReferenceRangeEditor/ReferenceRangeEditor.d.ts +1 -2
- package/dist/cjs/ResourceTimeline/ResourceTimeline.d.ts +2 -2
- package/dist/cjs/index.cjs +1206 -1204
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.min.cjs +1 -1
- package/dist/esm/AddressDisplay/AddressDisplay.mjs +2 -2
- package/dist/esm/AddressDisplay/AddressDisplay.mjs.map +1 -1
- package/dist/esm/AddressInput/AddressInput.mjs +9 -9
- package/dist/esm/AddressInput/AddressInput.mjs.map +1 -1
- package/dist/esm/AnnotationInput/AnnotationInput.mjs +2 -2
- package/dist/esm/AnnotationInput/AnnotationInput.mjs.map +1 -1
- package/dist/esm/AsyncAutocomplete/AsyncAutocomplete.mjs +2 -2
- package/dist/esm/AsyncAutocomplete/AsyncAutocomplete.mjs.map +1 -1
- package/dist/esm/AttachmentArrayDisplay/AttachmentArrayDisplay.mjs +4 -4
- package/dist/esm/AttachmentArrayDisplay/AttachmentArrayDisplay.mjs.map +1 -1
- package/dist/esm/AttachmentArrayInput/AttachmentArrayInput.mjs +19 -19
- package/dist/esm/AttachmentArrayInput/AttachmentArrayInput.mjs.map +1 -1
- package/dist/esm/AttachmentButton/AttachmentButton.mjs +3 -3
- package/dist/esm/AttachmentButton/AttachmentButton.mjs.map +1 -1
- package/dist/esm/AttachmentDisplay/AttachmentDisplay.mjs +9 -9
- package/dist/esm/AttachmentDisplay/AttachmentDisplay.mjs.map +1 -1
- package/dist/esm/AttachmentInput/AttachmentInput.mjs +5 -5
- package/dist/esm/AttachmentInput/AttachmentInput.mjs.map +1 -1
- package/dist/esm/BackboneElementDisplay/BackboneElementDisplay.mjs +6 -6
- package/dist/esm/BackboneElementDisplay/BackboneElementDisplay.mjs.map +1 -1
- package/dist/esm/BackboneElementInput/BackboneElementInput.mjs +7 -7
- package/dist/esm/BackboneElementInput/BackboneElementInput.mjs.map +1 -1
- package/dist/esm/CalendarInput/CalendarInput.mjs +18 -18
- package/dist/esm/CalendarInput/CalendarInput.mjs.map +1 -1
- package/dist/esm/CheckboxFormSection/CheckboxFormSection.mjs +5 -5
- package/dist/esm/CheckboxFormSection/CheckboxFormSection.mjs.map +1 -1
- package/dist/esm/CodeInput/CodeInput.mjs +2 -2
- package/dist/esm/CodeInput/CodeInput.mjs.map +1 -1
- package/dist/esm/CodeableConceptDisplay/CodeableConceptDisplay.mjs +2 -2
- package/dist/esm/CodeableConceptDisplay/CodeableConceptDisplay.mjs.map +1 -1
- package/dist/esm/CodeableConceptInput/CodeableConceptInput.mjs +2 -2
- package/dist/esm/CodeableConceptInput/CodeableConceptInput.mjs.map +1 -1
- package/dist/esm/CodingDisplay/CodingDisplay.mjs +2 -2
- package/dist/esm/CodingDisplay/CodingDisplay.mjs.map +1 -1
- package/dist/esm/CodingInput/CodingInput.mjs +2 -2
- package/dist/esm/CodingInput/CodingInput.mjs.map +1 -1
- package/dist/esm/ContactDetailDisplay/ContactDetailDisplay.mjs +3 -3
- package/dist/esm/ContactDetailDisplay/ContactDetailDisplay.mjs.map +1 -1
- package/dist/esm/ContactDetailInput/ContactDetailInput.mjs +4 -4
- package/dist/esm/ContactDetailInput/ContactDetailInput.mjs.map +1 -1
- package/dist/esm/ContactPointDisplay/ContactPointDisplay.mjs +2 -2
- package/dist/esm/ContactPointDisplay/ContactPointDisplay.mjs.map +1 -1
- package/dist/esm/ContactPointInput/ContactPointInput.mjs +5 -5
- package/dist/esm/ContactPointInput/ContactPointInput.mjs.map +1 -1
- package/dist/esm/Container/Container.mjs +2 -2
- package/dist/esm/Container/Container.mjs.map +1 -1
- package/dist/esm/DateTimeInput/DateTimeInput.mjs +2 -2
- package/dist/esm/DateTimeInput/DateTimeInput.mjs.map +1 -1
- package/dist/esm/DefaultResourceTimeline/DefaultResourceTimeline.mjs +7 -19
- package/dist/esm/DefaultResourceTimeline/DefaultResourceTimeline.mjs.map +1 -1
- package/dist/esm/DescriptionList/DescriptionList.mjs +5 -5
- package/dist/esm/DescriptionList/DescriptionList.mjs.map +1 -1
- package/dist/esm/DiagnosticReportDisplay/DiagnosticReportDisplay.d.ts +2 -0
- package/dist/esm/DiagnosticReportDisplay/DiagnosticReportDisplay.mjs +56 -52
- package/dist/esm/DiagnosticReportDisplay/DiagnosticReportDisplay.mjs.map +1 -1
- package/dist/esm/DiagnosticReportDisplay/DiagnosticReportDisplay.stories.d.ts +1 -0
- package/dist/esm/Document/Document.mjs +3 -3
- package/dist/esm/Document/Document.mjs.map +1 -1
- package/dist/esm/EncounterTimeline/EncounterTimeline.mjs +8 -25
- package/dist/esm/EncounterTimeline/EncounterTimeline.mjs.map +1 -1
- package/dist/esm/ErrorBoundary/ErrorBoundary.mjs +4 -4
- package/dist/esm/ErrorBoundary/ErrorBoundary.mjs.map +1 -1
- package/dist/esm/ExtensionInput/ExtensionInput.mjs +2 -2
- package/dist/esm/ExtensionInput/ExtensionInput.mjs.map +1 -1
- package/dist/esm/FhirPathDisplay/FhirPathDisplay.mjs +2 -2
- package/dist/esm/FhirPathDisplay/FhirPathDisplay.mjs.map +1 -1
- package/dist/esm/FhirPathTable/FhirPathTable.mjs +19 -19
- package/dist/esm/FhirPathTable/FhirPathTable.mjs.map +1 -1
- package/dist/esm/Form/Form.mjs +2 -2
- package/dist/esm/Form/Form.mjs.map +1 -1
- package/dist/esm/FormSection/FormSection.mjs +2 -2
- package/dist/esm/FormSection/FormSection.mjs.map +1 -1
- package/dist/esm/GoogleButton/GoogleButton.mjs +8 -6
- package/dist/esm/GoogleButton/GoogleButton.mjs.map +1 -1
- package/dist/esm/HumanNameDisplay/HumanNameDisplay.mjs +2 -2
- package/dist/esm/HumanNameDisplay/HumanNameDisplay.mjs.map +1 -1
- package/dist/esm/HumanNameInput/HumanNameInput.mjs +7 -7
- package/dist/esm/HumanNameInput/HumanNameInput.mjs.map +1 -1
- package/dist/esm/IdentifierDisplay/IdentifierDisplay.mjs +2 -2
- package/dist/esm/IdentifierDisplay/IdentifierDisplay.mjs.map +1 -1
- package/dist/esm/IdentifierInput/IdentifierInput.mjs +4 -4
- package/dist/esm/IdentifierInput/IdentifierInput.mjs.map +1 -1
- package/dist/esm/Logo/Logo.mjs +8 -8
- package/dist/esm/Logo/Logo.mjs.map +1 -1
- package/dist/esm/MedplumLink/MedplumLink.mjs +4 -4
- package/dist/esm/MedplumLink/MedplumLink.mjs.map +1 -1
- package/dist/esm/MedplumProvider/MedplumProvider.d.ts +8 -0
- package/dist/esm/MedplumProvider/MedplumProvider.mjs +19 -3
- package/dist/esm/MedplumProvider/MedplumProvider.mjs.map +1 -1
- package/dist/esm/MoneyDisplay/MoneyDisplay.mjs +2 -2
- package/dist/esm/MoneyDisplay/MoneyDisplay.mjs.map +1 -1
- package/dist/esm/MoneyInput/MoneyInput.mjs +4 -4
- package/dist/esm/MoneyInput/MoneyInput.mjs.map +1 -1
- package/dist/esm/NoteDisplay/NoteDisplay.d.ts +6 -0
- package/dist/esm/NoteDisplay/NoteDisplay.mjs +18 -0
- package/dist/esm/NoteDisplay/NoteDisplay.mjs.map +1 -0
- package/dist/esm/{ResourceDiffTable/ResourceDiffTable.stories.d.ts → NoteDisplay/NoteDisplay.stories.d.ts} +3 -1
- package/dist/esm/OperationOutcomeAlert/OperationOutcomeAlert.mjs +3 -3
- package/dist/esm/OperationOutcomeAlert/OperationOutcomeAlert.mjs.map +1 -1
- package/dist/esm/Panel/Panel.mjs +2 -2
- package/dist/esm/Panel/Panel.mjs.map +1 -1
- package/dist/esm/PatientTimeline/PatientTimeline.mjs +13 -20
- package/dist/esm/PatientTimeline/PatientTimeline.mjs.map +1 -1
- package/dist/esm/PeriodInput/PeriodInput.mjs +4 -4
- package/dist/esm/PeriodInput/PeriodInput.mjs.map +1 -1
- package/dist/esm/PlanDefinitionBuilder/PlanDefinitionBuilder.mjs +34 -34
- package/dist/esm/PlanDefinitionBuilder/PlanDefinitionBuilder.mjs.map +1 -1
- package/dist/esm/QuantityDisplay/QuantityDisplay.mjs +2 -2
- package/dist/esm/QuantityDisplay/QuantityDisplay.mjs.map +1 -1
- package/dist/esm/QuantityInput/QuantityInput.d.ts +1 -0
- package/dist/esm/QuantityInput/QuantityInput.mjs +14 -8
- package/dist/esm/QuantityInput/QuantityInput.mjs.map +1 -1
- package/dist/esm/QuantityInput/QuantityInput.stories.d.ts +7 -0
- package/dist/esm/QuestionnaireBuilder/QuestionnaireBuilder.mjs +31 -31
- package/dist/esm/QuestionnaireBuilder/QuestionnaireBuilder.mjs.map +1 -1
- package/dist/esm/QuestionnaireForm/QuestionnaireForm.mjs +33 -33
- package/dist/esm/QuestionnaireForm/QuestionnaireForm.mjs.map +1 -1
- package/dist/esm/RangeDisplay/RangeDisplay.mjs +2 -2
- package/dist/esm/RangeDisplay/RangeDisplay.mjs.map +1 -1
- package/dist/esm/RangeInput/RangeInput.mjs +4 -4
- package/dist/esm/RangeInput/RangeInput.mjs.map +1 -1
- package/dist/esm/RatioDisplay/RatioDisplay.mjs +4 -4
- package/dist/esm/RatioDisplay/RatioDisplay.mjs.map +1 -1
- package/dist/esm/RatioInput/RatioInput.mjs +4 -4
- package/dist/esm/RatioInput/RatioInput.mjs.map +1 -1
- package/dist/esm/ReferenceDisplay/ReferenceDisplay.mjs +3 -3
- package/dist/esm/ReferenceDisplay/ReferenceDisplay.mjs.map +1 -1
- package/dist/esm/ReferenceInput/ReferenceInput.mjs +4 -4
- package/dist/esm/ReferenceInput/ReferenceInput.mjs.map +1 -1
- package/dist/esm/ReferenceRangeEditor/ReferenceRangeEditor.d.ts +1 -2
- package/dist/esm/ReferenceRangeEditor/ReferenceRangeEditor.mjs +31 -31
- package/dist/esm/ReferenceRangeEditor/ReferenceRangeEditor.mjs.map +1 -1
- package/dist/esm/RequestGroupDisplay/RequestGroupDisplay.mjs +15 -15
- package/dist/esm/RequestGroupDisplay/RequestGroupDisplay.mjs.map +1 -1
- package/dist/esm/ResourceArrayDisplay/ResourceArrayDisplay.mjs +3 -3
- package/dist/esm/ResourceArrayDisplay/ResourceArrayDisplay.mjs.map +1 -1
- package/dist/esm/ResourceArrayInput/ResourceArrayInput.mjs +18 -18
- package/dist/esm/ResourceArrayInput/ResourceArrayInput.mjs.map +1 -1
- package/dist/esm/ResourceAvatar/ResourceAvatar.mjs +4 -4
- package/dist/esm/ResourceAvatar/ResourceAvatar.mjs.map +1 -1
- package/dist/esm/ResourceBadge/ResourceBadge.mjs +4 -4
- package/dist/esm/ResourceBadge/ResourceBadge.mjs.map +1 -1
- package/dist/esm/ResourceBlame/ResourceBlame.mjs +13 -13
- package/dist/esm/ResourceBlame/ResourceBlame.mjs.map +1 -1
- package/dist/esm/ResourceDiff/ResourceDiff.mjs +7 -7
- package/dist/esm/ResourceDiff/ResourceDiff.mjs.map +1 -1
- package/dist/esm/ResourceDiffTable/ResourceDiffTable.mjs +18 -18
- package/dist/esm/ResourceDiffTable/ResourceDiffTable.mjs.map +1 -1
- package/dist/esm/ResourceForm/ResourceForm.mjs +12 -12
- package/dist/esm/ResourceForm/ResourceForm.mjs.map +1 -1
- package/dist/esm/ResourceHistoryTable/ResourceHistoryTable.mjs +17 -17
- package/dist/esm/ResourceHistoryTable/ResourceHistoryTable.mjs.map +1 -1
- package/dist/esm/ResourceInput/ResourceInput.mjs +8 -8
- package/dist/esm/ResourceInput/ResourceInput.mjs.map +1 -1
- package/dist/esm/ResourceName/ResourceName.mjs +2 -2
- package/dist/esm/ResourceName/ResourceName.mjs.map +1 -1
- package/dist/esm/ResourcePropertyDisplay/ResourcePropertyDisplay.mjs +27 -27
- package/dist/esm/ResourcePropertyDisplay/ResourcePropertyDisplay.mjs.map +1 -1
- package/dist/esm/ResourcePropertyInput/ResourcePropertyInput.mjs +35 -35
- package/dist/esm/ResourcePropertyInput/ResourcePropertyInput.mjs.map +1 -1
- package/dist/esm/ResourceTable/ResourceTable.mjs +2 -2
- package/dist/esm/ResourceTable/ResourceTable.mjs.map +1 -1
- package/dist/esm/ResourceTimeline/ResourceTimeline.d.ts +2 -2
- package/dist/esm/ResourceTimeline/ResourceTimeline.mjs +67 -73
- package/dist/esm/ResourceTimeline/ResourceTimeline.mjs.map +1 -1
- package/dist/esm/Scheduler/Scheduler.mjs +22 -22
- package/dist/esm/Scheduler/Scheduler.mjs.map +1 -1
- package/dist/esm/SearchControl/SearchControl.mjs +49 -49
- package/dist/esm/SearchControl/SearchControl.mjs.map +1 -1
- package/dist/esm/SearchControl/SearchUtils.mjs +4 -4
- package/dist/esm/SearchControl/SearchUtils.mjs.map +1 -1
- package/dist/esm/SearchFieldEditor/SearchFieldEditor.mjs +25 -25
- package/dist/esm/SearchFieldEditor/SearchFieldEditor.mjs.map +1 -1
- package/dist/esm/SearchFilterEditor/SearchFilterEditor.mjs +37 -37
- package/dist/esm/SearchFilterEditor/SearchFilterEditor.mjs.map +1 -1
- package/dist/esm/SearchFilterValueDialog/SearchFilterValueDialog.mjs +6 -6
- package/dist/esm/SearchFilterValueDialog/SearchFilterValueDialog.mjs.map +1 -1
- package/dist/esm/SearchFilterValueDisplay/SearchFilterValueDisplay.mjs +4 -4
- package/dist/esm/SearchFilterValueDisplay/SearchFilterValueDisplay.mjs.map +1 -1
- package/dist/esm/SearchFilterValueInput/SearchFilterValueInput.mjs +8 -8
- package/dist/esm/SearchFilterValueInput/SearchFilterValueInput.mjs.map +1 -1
- package/dist/esm/SearchPopupMenu/SearchPopupMenu.mjs +62 -62
- package/dist/esm/SearchPopupMenu/SearchPopupMenu.mjs.map +1 -1
- package/dist/esm/ServiceRequestTimeline/ServiceRequestTimeline.mjs +9 -31
- package/dist/esm/ServiceRequestTimeline/ServiceRequestTimeline.mjs.map +1 -1
- package/dist/esm/StatusBadge/StatusBadge.mjs +2 -2
- package/dist/esm/StatusBadge/StatusBadge.mjs.map +1 -1
- package/dist/esm/Timeline/Timeline.mjs +20 -20
- package/dist/esm/Timeline/Timeline.mjs.map +1 -1
- package/dist/esm/TimingInput/TimingInput.mjs +19 -19
- package/dist/esm/TimingInput/TimingInput.mjs.map +1 -1
- package/dist/esm/ValueSetAutocomplete/ValueSetAutocomplete.mjs +2 -2
- package/dist/esm/ValueSetAutocomplete/ValueSetAutocomplete.mjs.map +1 -1
- package/dist/esm/auth/AuthenticationForm.mjs +22 -22
- package/dist/esm/auth/AuthenticationForm.mjs.map +1 -1
- package/dist/esm/auth/ChooseProfileForm.mjs +11 -11
- package/dist/esm/auth/ChooseProfileForm.mjs.map +1 -1
- package/dist/esm/auth/ChooseScopeForm.mjs +9 -9
- package/dist/esm/auth/ChooseScopeForm.mjs.map +1 -1
- package/dist/esm/auth/MfaForm.mjs +12 -12
- package/dist/esm/auth/MfaForm.mjs.map +1 -1
- package/dist/esm/auth/NewProjectForm.mjs +12 -12
- package/dist/esm/auth/NewProjectForm.mjs.map +1 -1
- package/dist/esm/auth/NewUserForm.mjs +22 -22
- package/dist/esm/auth/NewUserForm.mjs.map +1 -1
- package/dist/esm/auth/RegisterForm.mjs +5 -5
- package/dist/esm/auth/RegisterForm.mjs.map +1 -1
- package/dist/esm/auth/SignInForm.mjs +8 -8
- package/dist/esm/auth/SignInForm.mjs.map +1 -1
- package/dist/esm/index.min.mjs +1 -1
- package/dist/esm/index.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons/icons-react/dist/index.esm.mjs +6 -0
- package/dist/esm/node_modules/@tabler/icons/icons-react/dist/index.esm.mjs.map +1 -0
- package/dist/esm/useResource/useResource.mjs +3 -0
- package/dist/esm/useResource/useResource.mjs.map +1 -1
- package/package.json +20 -25
- package/rollup.config.mjs +0 -110
package/dist/cjs/index.cjs
CHANGED
|
@@ -1,15 +1,34 @@
|
|
|
1
1
|
(function (global, factory) {
|
|
2
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@medplum/core'), require('react'), require('@mantine/core'), require('@
|
|
3
|
-
typeof define === 'function' && define.amd ? define(['exports', '@medplum/core', 'react', '@mantine/core', '@
|
|
4
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.medplum = global.medplum || {}, global.medplum.react = {}), global.medplum.core, global.React, global.mantine.core, global.
|
|
5
|
-
})(this, (function (exports, core,
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@medplum/core'), require('react'), require('@mantine/core'), require('@mantine/notifications')) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports', '@medplum/core', 'react', '@mantine/core', '@mantine/notifications'], factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.medplum = global.medplum || {}, global.medplum.react = {}), global.medplum.core, global.React, global.mantine.core, global.mantine.notifications));
|
|
5
|
+
})(this, (function (exports, core, e, core$1, notifications) { 'use strict';
|
|
6
|
+
|
|
7
|
+
function _interopNamespaceDefault(e) {
|
|
8
|
+
var n = Object.create(null);
|
|
9
|
+
if (e) {
|
|
10
|
+
Object.keys(e).forEach(function (k) {
|
|
11
|
+
if (k !== 'default') {
|
|
12
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
13
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
get: function () { return e[k]; }
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
n.default = e;
|
|
21
|
+
return Object.freeze(n);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
var e__namespace = /*#__PURE__*/_interopNamespaceDefault(e);
|
|
6
25
|
|
|
7
26
|
function AddressDisplay(props) {
|
|
8
27
|
const address = props.value;
|
|
9
28
|
if (!address) {
|
|
10
29
|
return null;
|
|
11
30
|
}
|
|
12
|
-
return
|
|
31
|
+
return e.createElement(e.Fragment, null, core.formatAddress(address));
|
|
13
32
|
}
|
|
14
33
|
|
|
15
34
|
function getLine(address, index) {
|
|
@@ -24,8 +43,8 @@
|
|
|
24
43
|
return { ...address, line };
|
|
25
44
|
}
|
|
26
45
|
function AddressInput(props) {
|
|
27
|
-
const [value, setValue] =
|
|
28
|
-
const valueRef =
|
|
46
|
+
const [value, setValue] = e.useState(props.defaultValue || {});
|
|
47
|
+
const valueRef = e.useRef();
|
|
29
48
|
valueRef.current = value;
|
|
30
49
|
function setValueWrapper(newValue) {
|
|
31
50
|
setValue(newValue);
|
|
@@ -54,17 +73,17 @@
|
|
|
54
73
|
function setPostalCode(postalCode) {
|
|
55
74
|
setValueWrapper({ ...valueRef.current, postalCode });
|
|
56
75
|
}
|
|
57
|
-
return (
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
76
|
+
return (e.createElement(core$1.Group, { spacing: "xs", grow: true, noWrap: true },
|
|
77
|
+
e.createElement(core$1.NativeSelect, { "data-testid": "address-use", defaultValue: value?.use, onChange: (e) => setUse(e.currentTarget.value), data: ['', 'home', 'work', 'temp', 'old', 'billing'] }),
|
|
78
|
+
e.createElement(core$1.NativeSelect, { "data-testid": "address-type", defaultValue: value?.type, onChange: (e) => setType(e.currentTarget.value), data: ['', 'postal', 'physical', 'both'] }),
|
|
79
|
+
e.createElement(core$1.TextInput, { placeholder: "Line 1", defaultValue: getLine(value, 0), onChange: (e) => setLine1(e.currentTarget.value) }),
|
|
80
|
+
e.createElement(core$1.TextInput, { placeholder: "Line 2", defaultValue: getLine(value, 1), onChange: (e) => setLine2(e.currentTarget.value) }),
|
|
81
|
+
e.createElement(core$1.TextInput, { placeholder: "City", defaultValue: value.city, onChange: (e) => setCity(e.currentTarget.value) }),
|
|
82
|
+
e.createElement(core$1.TextInput, { placeholder: "State", defaultValue: value.state, onChange: (e) => setState(e.currentTarget.value) }),
|
|
83
|
+
e.createElement(core$1.TextInput, { placeholder: "Postal Code", defaultValue: value.postalCode, onChange: (e) => setPostalCode(e.currentTarget.value) })));
|
|
65
84
|
}
|
|
66
85
|
|
|
67
|
-
const reactContext =
|
|
86
|
+
const reactContext = e.createContext(undefined);
|
|
68
87
|
/**
|
|
69
88
|
* The MedplumProvider component provides Medplum context state.
|
|
70
89
|
*
|
|
@@ -74,11 +93,12 @@
|
|
|
74
93
|
*/
|
|
75
94
|
function MedplumProvider(props) {
|
|
76
95
|
const medplum = props.medplum;
|
|
77
|
-
const
|
|
96
|
+
const navigate = props.navigate || defaultNavigate;
|
|
97
|
+
const [state, setState] = e.useState({
|
|
78
98
|
profile: medplum.getProfile(),
|
|
79
99
|
loading: false,
|
|
80
100
|
});
|
|
81
|
-
|
|
101
|
+
e.useEffect(() => {
|
|
82
102
|
function eventListener() {
|
|
83
103
|
setState({
|
|
84
104
|
...state,
|
|
@@ -91,14 +111,15 @@
|
|
|
91
111
|
const medplumContext = {
|
|
92
112
|
...state,
|
|
93
113
|
medplum,
|
|
114
|
+
navigate,
|
|
94
115
|
};
|
|
95
|
-
return
|
|
116
|
+
return e.createElement(reactContext.Provider, { value: medplumContext }, props.children);
|
|
96
117
|
}
|
|
97
118
|
/**
|
|
98
119
|
* Returns the MedplumContext instance.
|
|
99
120
|
*/
|
|
100
121
|
function useMedplumContext() {
|
|
101
|
-
return
|
|
122
|
+
return e.useContext(reactContext);
|
|
102
123
|
}
|
|
103
124
|
/**
|
|
104
125
|
* Returns the MedplumClient instance.
|
|
@@ -107,6 +128,13 @@
|
|
|
107
128
|
function useMedplum() {
|
|
108
129
|
return useMedplumContext().medplum;
|
|
109
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Returns the Medplum navigate function.
|
|
133
|
+
* @returns The Medplum navigate function.
|
|
134
|
+
*/
|
|
135
|
+
function useMedplumNavigate() {
|
|
136
|
+
return useMedplumContext().navigate;
|
|
137
|
+
}
|
|
110
138
|
/**
|
|
111
139
|
* Returns the current Medplum user profile (if signed in).
|
|
112
140
|
* This is a shortcut for useMedplumContext().profile.
|
|
@@ -115,11 +143,18 @@
|
|
|
115
143
|
function useMedplumProfile() {
|
|
116
144
|
return useMedplumContext().profile;
|
|
117
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* The default "navigate" function which simply uses window.location.href.
|
|
148
|
+
* @param path The path to navigate to.
|
|
149
|
+
*/
|
|
150
|
+
function defaultNavigate(path) {
|
|
151
|
+
window.location.assign(path);
|
|
152
|
+
}
|
|
118
153
|
|
|
119
154
|
function AnnotationInput(props) {
|
|
120
155
|
const author = useMedplumProfile();
|
|
121
|
-
const [value, setValue] =
|
|
122
|
-
const valueRef =
|
|
156
|
+
const [value, setValue] = e.useState(props.defaultValue || {});
|
|
157
|
+
const valueRef = e.useRef();
|
|
123
158
|
valueRef.current = value;
|
|
124
159
|
function setText(text) {
|
|
125
160
|
const newValue = text
|
|
@@ -134,7 +169,7 @@
|
|
|
134
169
|
props.onChange(newValue);
|
|
135
170
|
}
|
|
136
171
|
}
|
|
137
|
-
return (
|
|
172
|
+
return (e.createElement(core$1.TextInput, { name: props.name, placeholder: "Annotation text", defaultValue: value.text, onChange: (e) => setText(e.currentTarget.value) }));
|
|
138
173
|
}
|
|
139
174
|
|
|
140
175
|
/**
|
|
@@ -172,23 +207,23 @@
|
|
|
172
207
|
function AsyncAutocomplete(props) {
|
|
173
208
|
const { defaultValue, toKey, toOption, loadOptions, onChange, onCreate, ...rest } = props;
|
|
174
209
|
const defaultItems = toDefaultItems(defaultValue);
|
|
175
|
-
const inputRef =
|
|
176
|
-
const [lastValue, setLastValue] =
|
|
177
|
-
const [timer, setTimer] =
|
|
178
|
-
const [abortController, setAbortController] =
|
|
179
|
-
const [autoSubmit, setAutoSubmit] =
|
|
180
|
-
const [options, setOptions] =
|
|
181
|
-
const lastValueRef =
|
|
210
|
+
const inputRef = e.useRef(null);
|
|
211
|
+
const [lastValue, setLastValue] = e.useState(undefined);
|
|
212
|
+
const [timer, setTimer] = e.useState();
|
|
213
|
+
const [abortController, setAbortController] = e.useState();
|
|
214
|
+
const [autoSubmit, setAutoSubmit] = e.useState();
|
|
215
|
+
const [options, setOptions] = e.useState(defaultItems?.map(toOption));
|
|
216
|
+
const lastValueRef = e.useRef();
|
|
182
217
|
lastValueRef.current = lastValue;
|
|
183
|
-
const timerRef =
|
|
218
|
+
const timerRef = e.useRef();
|
|
184
219
|
timerRef.current = timer;
|
|
185
|
-
const abortControllerRef =
|
|
220
|
+
const abortControllerRef = e.useRef();
|
|
186
221
|
abortControllerRef.current = abortController;
|
|
187
|
-
const autoSubmitRef =
|
|
222
|
+
const autoSubmitRef = e.useRef();
|
|
188
223
|
autoSubmitRef.current = autoSubmit;
|
|
189
|
-
const optionsRef =
|
|
224
|
+
const optionsRef = e.useRef();
|
|
190
225
|
optionsRef.current = options;
|
|
191
|
-
const handleTimer =
|
|
226
|
+
const handleTimer = e.useCallback(() => {
|
|
192
227
|
setTimer(undefined);
|
|
193
228
|
const value = inputRef.current?.value?.trim() || '';
|
|
194
229
|
if (value === lastValueRef.current) {
|
|
@@ -213,7 +248,7 @@
|
|
|
213
248
|
})
|
|
214
249
|
.catch(console.log);
|
|
215
250
|
}, [loadOptions, onChange, toOption]);
|
|
216
|
-
const handleSearchChange =
|
|
251
|
+
const handleSearchChange = e.useCallback(() => {
|
|
217
252
|
if (abortControllerRef.current) {
|
|
218
253
|
abortControllerRef.current.abort();
|
|
219
254
|
setAbortController(undefined);
|
|
@@ -224,7 +259,7 @@
|
|
|
224
259
|
const newTimer = window.setTimeout(() => handleTimer(), 100);
|
|
225
260
|
setTimer(newTimer);
|
|
226
261
|
}, [handleTimer]);
|
|
227
|
-
const handleChange =
|
|
262
|
+
const handleChange = e.useCallback((values) => {
|
|
228
263
|
const result = [];
|
|
229
264
|
for (const value of values) {
|
|
230
265
|
let item = optionsRef.current?.find((option) => option.value === value)?.resource;
|
|
@@ -235,7 +270,7 @@
|
|
|
235
270
|
}
|
|
236
271
|
onChange(result);
|
|
237
272
|
}, [onChange, onCreate]);
|
|
238
|
-
const handleKeyDown =
|
|
273
|
+
const handleKeyDown = e.useCallback((e) => {
|
|
239
274
|
if (e.key === 'Enter') {
|
|
240
275
|
if (!timerRef.current && !abortControllerRef.current) {
|
|
241
276
|
killEvent(e);
|
|
@@ -251,20 +286,20 @@
|
|
|
251
286
|
}
|
|
252
287
|
}
|
|
253
288
|
}, [handleChange]);
|
|
254
|
-
const handleCreate =
|
|
289
|
+
const handleCreate = e.useCallback((input) => {
|
|
255
290
|
const option = toOption(onCreate(input));
|
|
256
291
|
setOptions([...optionsRef.current, option]);
|
|
257
292
|
return option;
|
|
258
293
|
}, [onCreate, setOptions, toOption]);
|
|
259
|
-
const handleFilter =
|
|
260
|
-
|
|
294
|
+
const handleFilter = e.useCallback((_value, selected) => !selected, []);
|
|
295
|
+
e.useEffect(() => {
|
|
261
296
|
return () => {
|
|
262
297
|
if (abortControllerRef.current) {
|
|
263
298
|
abortControllerRef.current.abort();
|
|
264
299
|
}
|
|
265
300
|
};
|
|
266
301
|
}, []);
|
|
267
|
-
return (
|
|
302
|
+
return (e.createElement(core$1.MultiSelect, { ...rest, ref: inputRef, defaultValue: defaultItems.map(toKey), searchable: true, onKeyDown: handleKeyDown, onSearchChange: handleSearchChange, data: options, onFocus: handleTimer, onChange: handleChange, onCreate: handleCreate, rightSectionWidth: 40, rightSection: abortController ? e.createElement(core$1.Loader, { size: 16 }) : null, filter: handleFilter }));
|
|
268
303
|
}
|
|
269
304
|
function toDefaultItems(defaultValue) {
|
|
270
305
|
if (!defaultValue) {
|
|
@@ -282,25 +317,27 @@
|
|
|
282
317
|
if (!url) {
|
|
283
318
|
return null;
|
|
284
319
|
}
|
|
285
|
-
return (
|
|
286
|
-
contentType?.startsWith('image/') && (
|
|
287
|
-
contentType?.startsWith('video/') && (
|
|
288
|
-
|
|
289
|
-
contentType === 'application/pdf' && !title?.endsWith('.pdf') && (
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
320
|
+
return (e.createElement("div", { "data-testid": "attachment-display" },
|
|
321
|
+
contentType?.startsWith('image/') && (e.createElement("img", { "data-testid": "attachment-image", style: { maxWidth: props.maxWidth }, src: url, alt: value?.title })),
|
|
322
|
+
contentType?.startsWith('video/') && (e.createElement("video", { "data-testid": "attachment-video", style: { maxWidth: props.maxWidth }, controls: true },
|
|
323
|
+
e.createElement("source", { type: contentType, src: url }))),
|
|
324
|
+
contentType === 'application/pdf' && !title?.endsWith('.pdf') && (e.createElement("div", { "data-testid": "attachment-pdf", style: { maxWidth: props.maxWidth, minHeight: 400 } },
|
|
325
|
+
e.createElement("iframe", { width: "100%", height: "400", src: url + '#navpanes=0', allowFullScreen: true, frameBorder: 0, seamless: true }))),
|
|
326
|
+
e.createElement("div", { "data-testid": "download-link", style: { padding: '2px 16px 16px 16px' } },
|
|
327
|
+
e.createElement(core$1.Anchor, { href: value?.url, "data-testid": "attachment-details", target: "_blank", rel: "noopener noreferrer" }, value?.title || 'Download'))));
|
|
293
328
|
}
|
|
294
329
|
|
|
295
330
|
function AttachmentArrayDisplay(props) {
|
|
296
|
-
return (
|
|
297
|
-
props.values.map((v, index) => (
|
|
298
|
-
|
|
331
|
+
return (e.createElement("div", null, props.values &&
|
|
332
|
+
props.values.map((v, index) => (e.createElement("div", { key: 'attatchment-' + index },
|
|
333
|
+
e.createElement(AttachmentDisplay, { value: v, maxWidth: props.maxWidth }))))));
|
|
299
334
|
}
|
|
300
335
|
|
|
336
|
+
function t(){return t=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var o=arguments[t];for(var r in o)Object.prototype.hasOwnProperty.call(o,r)&&(e[r]=o[r]);}return e},t.apply(this,arguments)}function o(e,t){if(null==e)return {};var o,r,n=function(e,t){if(null==e)return {};var o,r,n={},l=Object.keys(e);for(r=0;r<l.length;r++)o=l[r],t.indexOf(o)>=0||(n[o]=e[o]);return n}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r<l.length;r++)o=l[r],t.indexOf(o)>=0||Object.prototype.propertyIsEnumerable.call(e,o)&&(n[o]=e[o]);}return n}var te=["size","color","stroke"];function oe(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,te);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-adjustments-horizontal",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("circle",{cx:14,cy:6,r:2}),e__namespace.createElement("line",{x1:4,y1:6,x2:12,y2:6}),e__namespace.createElement("line",{x1:16,y1:6,x2:20,y2:6}),e__namespace.createElement("circle",{cx:8,cy:12,r:2}),e__namespace.createElement("line",{x1:4,y1:12,x2:6,y2:12}),e__namespace.createElement("line",{x1:10,y1:12,x2:20,y2:12}),e__namespace.createElement("circle",{cx:17,cy:18,r:2}),e__namespace.createElement("line",{x1:4,y1:18,x2:15,y2:18}),e__namespace.createElement("line",{x1:19,y1:18,x2:20,y2:18}))}var Ne=["size","color","stroke"];function We(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,Ne);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-alert-circle",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("circle",{cx:12,cy:12,r:9}),e__namespace.createElement("line",{x1:12,y1:8,x2:12,y2:12}),e__namespace.createElement("line",{x1:12,y1:16,x2:12.01,y2:16}))}var Gv=["size","color","stroke"];function Jv(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,Gv);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-bleach-off",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("path",{d:"M5 19h14m1.986 -1.977a2.001 2.001 0 0 0 -.146 -.773l-7.1 -12.25a2 2 0 0 0 -3.5 0l-.815 1.405m-1.488 2.568l-4.797 8.277a2 2 0 0 0 1.75 2.75"}),e__namespace.createElement("path",{d:"M3 3l18 18"}))}var Kv=["size","color","stroke"];function Qv(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,Kv);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-bleach",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("path",{d:"M5 19h14a2 2 0 0 0 1.84 -2.75l-7.1 -12.25a2 2 0 0 0 -3.5 0l-7.1 12.25a2 2 0 0 0 1.75 2.75"}))}var zw=["size","color","stroke"];function bw(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,zw);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-box-multiple",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("rect",{x:7,y:3,width:14,height:14,rx:2}),e__namespace.createElement("path",{d:"M17 17v2a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2v-10a2 2 0 0 1 2 -2h2"}))}var Gw=["size","color","stroke"];function Jw(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,Gw);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-brackets-contain",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("path",{d:"M7 4h-4v16h4"}),e__namespace.createElement("path",{d:"M17 4h4v16h-4"}),e__namespace.createElement("path",{d:"M8 16h.01"}),e__namespace.createElement("path",{d:"M12 16h.01"}),e__namespace.createElement("path",{d:"M16 16h.01"}))}var yC=["size","color","stroke"];function CC(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,yC);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-bucket-off",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("path",{d:"M5.029 5.036c-.655 .58 -1.029 1.25 -1.029 1.964c0 2.033 3.033 3.712 6.96 3.967m3.788 -.21c3.064 -.559 5.252 -2.029 5.252 -3.757c0 -2.21 -3.582 -4 -8 -4c-1.605 0 -3.1 .236 -4.352 .643"}),e__namespace.createElement("path",{d:"M4 7c0 .664 .088 1.324 .263 1.965l2.737 10.035c.5 1.5 2.239 2 5 2s4.5 -.5 5 -2c.1 -.3 .252 -.812 .457 -1.535m.862 -3.146c.262 -.975 .735 -2.76 1.418 -5.354a7.45 7.45 0 0 0 .263 -1.965"}),e__namespace.createElement("path",{d:"M3 3l18 18"}))}var jC=["size","color","stroke"];function BC(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,jC);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-bucket",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("ellipse",{cx:12,cy:7,rx:8,ry:4}),e__namespace.createElement("path",{d:"M4 7c0 .664 .088 1.324 .263 1.965l2.737 10.035c.5 1.5 2.239 2 5 2s4.5 -.5 5 -2c.333 -1 1.246 -4.345 2.737 -10.035a7.45 7.45 0 0 0 .263 -1.965"}))}var fB=["size","color","stroke"];function zB(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,fB);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-calendar",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("rect",{x:4,y:5,width:16,height:16,rx:2}),e__namespace.createElement("line",{x1:16,y1:3,x2:16,y2:7}),e__namespace.createElement("line",{x1:8,y1:3,x2:8,y2:7}),e__namespace.createElement("line",{x1:4,y1:11,x2:20,y2:11}),e__namespace.createElement("line",{x1:11,y1:15,x2:12,y2:15}),e__namespace.createElement("line",{x1:12,y1:15,x2:12,y2:18}))}var AW=["size","color","stroke"];function DW(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,AW);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-check",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("path",{d:"M5 12l5 5l10 -10"}))}var FW=["size","color","stroke"];function GW(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,FW);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-checkbox",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("polyline",{points:"9 11 12 14 20 6"}),e__namespace.createElement("path",{d:"M20 12v6a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2v-12a2 2 0 0 1 2 -2h9"}))}var SP=["size","color","stroke"];function IP(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,SP);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-circle-minus",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("circle",{cx:12,cy:12,r:9}),e__namespace.createElement("line",{x1:9,y1:12,x2:15,y2:12}))}var aS=["size","color","stroke"];function iS(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,aS);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-circle-plus",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("circle",{cx:12,cy:12,r:9}),e__namespace.createElement("line",{x1:9,y1:12,x2:15,y2:12}),e__namespace.createElement("line",{x1:12,y1:9,x2:12,y2:15}))}var VA=["size","color","stroke"];function XA(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,VA);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-cloud-upload",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("path",{d:"M7 18a4.6 4.4 0 0 1 0 -9a5 4.5 0 0 1 11 2h1a3.5 3.5 0 0 1 0 7h-1"}),e__namespace.createElement("polyline",{points:"9 15 12 12 15 15"}),e__namespace.createElement("line",{x1:12,y1:12,x2:12,y2:21}))}var cF=["size","color","stroke"];function sF(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,cF);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-columns",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("line",{x1:4,y1:6,x2:9.5,y2:6}),e__namespace.createElement("line",{x1:4,y1:10,x2:9.5,y2:10}),e__namespace.createElement("line",{x1:4,y1:14,x2:9.5,y2:14}),e__namespace.createElement("line",{x1:4,y1:18,x2:9.5,y2:18}),e__namespace.createElement("line",{x1:14.5,y1:6,x2:20,y2:6}),e__namespace.createElement("line",{x1:14.5,y1:10,x2:20,y2:10}),e__namespace.createElement("line",{x1:14.5,y1:14,x2:20,y2:14}),e__namespace.createElement("line",{x1:14.5,y1:18,x2:20,y2:18}))}var jK=["size","color","stroke"];function BK(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,jK);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-currency-dollar",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("path",{d:"M16.7 8a3 3 0 0 0 -2.7 -2h-4a3 3 0 0 0 0 6h4a3 3 0 0 1 0 6h-4a3 3 0 0 1 -2.7 -2"}),e__namespace.createElement("path",{d:"M12 3v3m0 12v3"}))}var jX=["size","color","stroke"];function BX(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,jX);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-dots",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("circle",{cx:5,cy:12,r:1}),e__namespace.createElement("circle",{cx:12,cy:12,r:1}),e__namespace.createElement("circle",{cx:19,cy:12,r:1}))}var yY=["size","color","stroke"];function CY(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,yY);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-edit",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("path",{d:"M7 7h-1a2 2 0 0 0 -2 2v9a2 2 0 0 0 2 2h9a2 2 0 0 0 2 -2v-1"}),e__namespace.createElement("path",{d:"M20.385 6.585a2.1 2.1 0 0 0 -2.97 -2.97l-8.415 8.385v3h3l8.385 -8.415z"}),e__namespace.createElement("path",{d:"M16 5l3 3"}))}var oZ=["size","color","stroke"];function rZ(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,oZ);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-equal-not",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("path",{d:"M5 10h14"}),e__namespace.createElement("path",{d:"M5 14h14"}),e__namespace.createElement("path",{d:"M5 19l14 -14"}))}var nZ=["size","color","stroke"];function lZ(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,nZ);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-equal",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("path",{d:"M5 10h14"}),e__namespace.createElement("path",{d:"M5 14h14"}))}var j$=["size","color","stroke"];function B$(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,j$);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-file-alert",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("path",{d:"M14 3v4a1 1 0 0 0 1 1h4"}),e__namespace.createElement("path",{d:"M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2z"}),e__namespace.createElement("line",{x1:12,y1:17,x2:12.01,y2:17}),e__namespace.createElement("line",{x1:12,y1:11,x2:12,y2:14}))}var V_=["size","color","stroke"];function X_(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,V_);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-file-plus",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("path",{d:"M14 3v4a1 1 0 0 0 1 1h4"}),e__namespace.createElement("path",{d:"M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2z"}),e__namespace.createElement("line",{x1:12,y1:11,x2:12,y2:17}),e__namespace.createElement("line",{x1:9,y1:14,x2:15,y2:14}))}var Q0=["size","color","stroke"];function R0(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,Q0);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-filter",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("path",{d:"M5.5 5h13a1 1 0 0 1 .5 1.5l-5 5.5l0 7l-4 -3l0 -4l-5 -5.5a1 1 0 0 1 .5 -1.5"}))}var Wae=["size","color","stroke"];function qae(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,Wae);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-list-details",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("path",{d:"M13 5h8"}),e__namespace.createElement("path",{d:"M13 9h5"}),e__namespace.createElement("path",{d:"M13 15h8"}),e__namespace.createElement("path",{d:"M13 19h5"}),e__namespace.createElement("rect",{x:3,y:4,width:6,height:6,rx:1}),e__namespace.createElement("rect",{x:3,y:14,width:6,height:6,rx:1}))}var yse=["size","color","stroke"];function Cse(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,yse);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-math-greater",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("path",{d:"M5 18l14 -6l-14 -6"}))}var Ose=["size","color","stroke"];function Pse(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,Ose);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-math-lower",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("path",{d:"M19 18l-14 -6l14 -6"}))}var bde=["size","color","stroke"];function Lde(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,bde);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-message",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("path",{d:"M4 21v-13a3 3 0 0 1 3 -3h10a3 3 0 0 1 3 3v6a3 3 0 0 1 -3 3h-9l-4 4"}),e__namespace.createElement("line",{x1:8,y1:9,x2:16,y2:9}),e__namespace.createElement("line",{x1:8,y1:13,x2:14,y2:13}))}var pge=["size","color","stroke"];function Ege(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,pge);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-pin",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("path",{d:"M15 4.5l-4 4l-4 1.5l-1.5 1.5l7 7l1.5 -1.5l1.5 -4l4 -4"}),e__namespace.createElement("line",{x1:9,y1:15,x2:4.5,y2:19.5}),e__namespace.createElement("line",{x1:14.5,y1:4,x2:20,y2:9.5}))}var Mge=["size","color","stroke"];function xge(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,Mge);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-pinned-off",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("line",{x1:3,y1:3,x2:21,y2:21}),e__namespace.createElement("path",{d:"M15 4.5l-3.249 3.249m-2.57 1.433l-2.181 .818l-1.5 1.5l7 7l1.5 -1.5l.82 -2.186m1.43 -2.563l3.25 -3.251"}),e__namespace.createElement("line",{x1:9,y1:15,x2:4.5,y2:19.5}),e__namespace.createElement("line",{x1:14.5,y1:4,x2:20,y2:9.5}))}var jje=["size","color","stroke"];function Bje(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,jje);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-settings",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("path",{d:"M10.325 4.317c.426 -1.756 2.924 -1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543 -.94 3.31 .826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756 .426 1.756 2.924 0 3.35a1.724 1.724 0 0 0 -1.066 2.573c.94 1.543 -.826 3.31 -2.37 2.37a1.724 1.724 0 0 0 -2.572 1.065c-.426 1.756 -2.924 1.756 -3.35 0a1.724 1.724 0 0 0 -2.573 -1.066c-1.543 .94 -3.31 -.826 -2.37 -2.37a1.724 1.724 0 0 0 -1.065 -2.572c-1.756 -.426 -1.756 -2.924 0 -3.35a1.724 1.724 0 0 0 1.066 -2.573c-.94 -1.543 .826 -3.31 2.37 -2.37c1 .608 2.296 .07 2.572 -1.065z"}),e__namespace.createElement("circle",{cx:12,cy:12,r:3}))}var aNe=["size","color","stroke"];function iNe(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,aNe);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-sort-ascending",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("line",{x1:4,y1:6,x2:11,y2:6}),e__namespace.createElement("line",{x1:4,y1:12,x2:11,y2:12}),e__namespace.createElement("line",{x1:4,y1:18,x2:13,y2:18}),e__namespace.createElement("polyline",{points:"15 9 18 6 21 9"}),e__namespace.createElement("line",{x1:18,y1:6,x2:18,y2:18}))}var kNe=["size","color","stroke"];function wNe(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,kNe);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-sort-descending",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("line",{x1:4,y1:6,x2:13,y2:6}),e__namespace.createElement("line",{x1:4,y1:12,x2:11,y2:12}),e__namespace.createElement("line",{x1:4,y1:18,x2:11,y2:18}),e__namespace.createElement("polyline",{points:"15 15 18 18 21 15"}),e__namespace.createElement("line",{x1:18,y1:6,x2:18,y2:18}))}var QSe=["size","color","stroke"];function RSe(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,QSe);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-square",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("rect",{x:4,y:4,width:16,height:16,rx:2}))}var $Ae=["size","color","stroke"];function _Ae(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,$Ae);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-table-export",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("path",{d:"M11.5 20h-5.5a2 2 0 0 1 -2 -2v-12a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v7.5m-16 -3.5h16m-10 -6v16m4 -1h7m-3 -3l3 3l-3 3"}))}var fKe=["size","color","stroke"];function zKe(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,fKe);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-trash",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("line",{x1:4,y1:7,x2:20,y2:7}),e__namespace.createElement("line",{x1:10,y1:11,x2:10,y2:17}),e__namespace.createElement("line",{x1:14,y1:11,x2:14,y2:17}),e__namespace.createElement("path",{d:"M5 7l1 12a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2l1 -12"}),e__namespace.createElement("path",{d:"M9 7v-3a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v3"}))}var WXe=["size","color","stroke"];function qXe(r){var n=r.size,l=void 0===n?24:n,a=r.color,i=void 0===a?"currentColor":a,c=r.stroke,s=void 0===c?2:c,h=o(r,WXe);return e__namespace.createElement("svg",t({xmlns:"http://www.w3.org/2000/svg",className:"icon icon-tabler icon-tabler-x",width:l,height:l,viewBox:"0 0 24 24",strokeWidth:s,stroke:i,fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},h),e__namespace.createElement("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),e__namespace.createElement("line",{x1:18,y1:6,x2:6,y2:18}),e__namespace.createElement("line",{x1:6,y1:6,x2:18,y2:18}))}
|
|
337
|
+
|
|
301
338
|
function AttachmentButton(props) {
|
|
302
339
|
const medplum = useMedplum();
|
|
303
|
-
const fileInputRef =
|
|
340
|
+
const fileInputRef = e.useRef(null);
|
|
304
341
|
function onClick(e) {
|
|
305
342
|
killEvent(e);
|
|
306
343
|
fileInputRef.current?.click();
|
|
@@ -343,14 +380,14 @@
|
|
|
343
380
|
alert(outcome?.issue?.[0]?.details?.text);
|
|
344
381
|
});
|
|
345
382
|
}
|
|
346
|
-
return (
|
|
347
|
-
|
|
383
|
+
return (e.createElement(e.Fragment, null,
|
|
384
|
+
e.createElement("input", { type: "file", "data-testid": "upload-file-input", style: { display: 'none' }, ref: fileInputRef, onChange: (e) => onFileChange(e) }),
|
|
348
385
|
props.children({ onClick })));
|
|
349
386
|
}
|
|
350
387
|
|
|
351
388
|
function AttachmentArrayInput(props) {
|
|
352
|
-
const [values, setValues] =
|
|
353
|
-
const valuesRef =
|
|
389
|
+
const [values, setValues] = e.useState(props.defaultValue ?? []);
|
|
390
|
+
const valuesRef = e.useRef();
|
|
354
391
|
valuesRef.current = values;
|
|
355
392
|
function setValuesWrapper(newValues) {
|
|
356
393
|
setValues(newValues);
|
|
@@ -358,33 +395,33 @@
|
|
|
358
395
|
props.onChange(newValues);
|
|
359
396
|
}
|
|
360
397
|
}
|
|
361
|
-
return (
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
values.map((v, index) => (
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
398
|
+
return (e.createElement("table", { style: { width: '100%' } },
|
|
399
|
+
e.createElement("colgroup", null,
|
|
400
|
+
e.createElement("col", { width: "97%" }),
|
|
401
|
+
e.createElement("col", { width: "3%" })),
|
|
402
|
+
e.createElement("tbody", null,
|
|
403
|
+
values.map((v, index) => (e.createElement("tr", { key: `${index}-${values.length}` },
|
|
404
|
+
e.createElement("td", null,
|
|
405
|
+
e.createElement(AttachmentDisplay, { value: v, maxWidth: 200 })),
|
|
406
|
+
e.createElement("td", null,
|
|
407
|
+
e.createElement(core$1.ActionIcon, { title: "Remove", size: "sm", onClick: (e) => {
|
|
371
408
|
killEvent(e);
|
|
372
409
|
const copy = values.slice();
|
|
373
410
|
copy.splice(index, 1);
|
|
374
411
|
setValuesWrapper(copy);
|
|
375
412
|
} },
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
413
|
+
e.createElement(IP, null)))))),
|
|
414
|
+
e.createElement("tr", null,
|
|
415
|
+
e.createElement("td", null),
|
|
416
|
+
e.createElement("td", null,
|
|
417
|
+
e.createElement(AttachmentButton, { onUpload: (attachment) => {
|
|
381
418
|
setValuesWrapper([...valuesRef.current, attachment]);
|
|
382
|
-
} }, (props) => (
|
|
383
|
-
|
|
419
|
+
} }, (props) => (e.createElement(core$1.ActionIcon, { ...props, title: "Add", size: "sm", color: "green" },
|
|
420
|
+
e.createElement(XA, { size: 16 })))))))));
|
|
384
421
|
}
|
|
385
422
|
|
|
386
423
|
function AttachmentInput(props) {
|
|
387
|
-
const [value, setValue] =
|
|
424
|
+
const [value, setValue] = e.useState(props.defaultValue);
|
|
388
425
|
function setValueWrapper(newValue) {
|
|
389
426
|
setValue(newValue);
|
|
390
427
|
if (props.onChange) {
|
|
@@ -392,17 +429,17 @@
|
|
|
392
429
|
}
|
|
393
430
|
}
|
|
394
431
|
if (value) {
|
|
395
|
-
return (
|
|
396
|
-
|
|
397
|
-
|
|
432
|
+
return (e.createElement(e.Fragment, null,
|
|
433
|
+
e.createElement(AttachmentDisplay, { value: value, maxWidth: 200 }),
|
|
434
|
+
e.createElement(core$1.Button, { onClick: (e) => {
|
|
398
435
|
killEvent(e);
|
|
399
436
|
setValueWrapper(undefined);
|
|
400
437
|
} }, "Remove")));
|
|
401
438
|
}
|
|
402
|
-
return (
|
|
439
|
+
return (e.createElement(AttachmentButton, { onUpload: setValueWrapper }, (props) => e.createElement(core$1.Button, { ...props }, "Upload...")));
|
|
403
440
|
}
|
|
404
441
|
|
|
405
|
-
const useStyles$
|
|
442
|
+
const useStyles$e = core$1.createStyles(() => ({
|
|
406
443
|
root: {
|
|
407
444
|
'@media (max-width: 800px)': {
|
|
408
445
|
paddingLeft: 4,
|
|
@@ -412,11 +449,11 @@
|
|
|
412
449
|
}));
|
|
413
450
|
function Container(props) {
|
|
414
451
|
const { children, ...others } = props;
|
|
415
|
-
const { classes } = useStyles$
|
|
416
|
-
return (
|
|
452
|
+
const { classes } = useStyles$e();
|
|
453
|
+
return (e.createElement(core$1.Container, { className: classes.root, ...others }, children));
|
|
417
454
|
}
|
|
418
455
|
|
|
419
|
-
const useStyles$
|
|
456
|
+
const useStyles$d = core$1.createStyles((theme, { width, fill }) => ({
|
|
420
457
|
paper: {
|
|
421
458
|
maxWidth: width,
|
|
422
459
|
margin: `${theme.spacing.xl}px auto`,
|
|
@@ -441,14 +478,14 @@
|
|
|
441
478
|
};
|
|
442
479
|
function Panel(props) {
|
|
443
480
|
const { className, children, width, fill, unstyled, ...others } = core$1.useComponentDefaultProps('Panel', defaultProps$1, props);
|
|
444
|
-
const { classes, cx } = useStyles$
|
|
445
|
-
return (
|
|
481
|
+
const { classes, cx } = useStyles$d({ width, fill }, { name: 'Panel', unstyled });
|
|
482
|
+
return (e.createElement(core$1.Paper, { className: cx(classes.paper, className), ...others }, children));
|
|
446
483
|
}
|
|
447
484
|
|
|
448
485
|
function Document(props) {
|
|
449
486
|
const { children, ...others } = props;
|
|
450
|
-
return (
|
|
451
|
-
|
|
487
|
+
return (e.createElement(Container, null,
|
|
488
|
+
e.createElement(Panel, { ...others }, children)));
|
|
452
489
|
}
|
|
453
490
|
|
|
454
491
|
/**
|
|
@@ -499,7 +536,7 @@
|
|
|
499
536
|
}
|
|
500
537
|
|
|
501
538
|
function Form(props) {
|
|
502
|
-
return (
|
|
539
|
+
return (e.createElement("form", { style: props.style, "data-testid": props.testid, onSubmit: (e) => {
|
|
503
540
|
e.preventDefault();
|
|
504
541
|
const formData = parseForm(e.target);
|
|
505
542
|
if (props.onSubmit) {
|
|
@@ -509,13 +546,13 @@
|
|
|
509
546
|
}
|
|
510
547
|
|
|
511
548
|
function Logo(props) {
|
|
512
|
-
return (
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
549
|
+
return (e.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 491 491", style: { width: props.size, height: props.size } },
|
|
550
|
+
e.createElement("title", null, "Medplum Logo"),
|
|
551
|
+
e.createElement("path", { fill: props.fill || '#ad7136', d: "M282 67c6-16 16-29 29-40L289 0c-22 17-37 41-43 68l17 23 19-24z" }),
|
|
552
|
+
e.createElement("path", { fill: props.fill || '#946af9', d: "M311 63c-17 0-33 4-48 11-16-7-32-11-49-11-87 0-158 96-158 214s71 214 158 214c17 0 33-4 49-11 15 7 31 11 48 11 87 0 158-96 158-214S398 63 311 63z" }),
|
|
553
|
+
e.createElement("path", { fill: props.fill || '#7857c5', d: "M231 489l-17 2c-87 0-158-96-158-214S127 63 214 63l17 1c-39 12-70 102-70 213s31 201 70 212z" }),
|
|
554
|
+
e.createElement("path", { fill: props.fill || '#40bc26', d: "M207 220a176 176 0 01-177 43A176 176 0 01251 43l1 5c17 59 2 125-45 172z" }),
|
|
555
|
+
e.createElement("path", { fill: props.fill || '#33961e', d: "M252 48A421 421 0 0057 270l-27-7A176 176 0 01251 43l1 5z" })));
|
|
519
556
|
}
|
|
520
557
|
|
|
521
558
|
function getErrorsForInput(outcome, expression) {
|
|
@@ -548,8 +585,8 @@
|
|
|
548
585
|
|
|
549
586
|
function NewProjectForm(props) {
|
|
550
587
|
const medplum = useMedplum();
|
|
551
|
-
const [outcome, setOutcome] =
|
|
552
|
-
return (
|
|
588
|
+
const [outcome, setOutcome] = e.useState();
|
|
589
|
+
return (e.createElement(Form, { style: { maxWidth: 400 }, onSubmit: async (formData) => {
|
|
553
590
|
try {
|
|
554
591
|
props.handleAuthResponse(await medplum.startNewProject({
|
|
555
592
|
login: props.login,
|
|
@@ -560,20 +597,20 @@
|
|
|
560
597
|
setOutcome(err);
|
|
561
598
|
}
|
|
562
599
|
} },
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
600
|
+
e.createElement(core$1.Center, { sx: { flexDirection: 'column' } },
|
|
601
|
+
e.createElement(Logo, { size: 32 }),
|
|
602
|
+
e.createElement(core$1.Title, null, "Create project")),
|
|
603
|
+
e.createElement(core$1.Stack, { spacing: "xl" },
|
|
604
|
+
e.createElement(core$1.TextInput, { name: "projectName", label: "Project Name", placeholder: "My Project", required: true, autoFocus: true, error: getErrorsForInput(outcome, 'firstName') }),
|
|
605
|
+
e.createElement(core$1.Text, { color: "dimmed", size: "xs" },
|
|
569
606
|
"By clicking submit you agree to the Medplum",
|
|
570
607
|
' ',
|
|
571
|
-
|
|
608
|
+
e.createElement(core$1.Anchor, { href: "https://www.medplum.com/privacy" }, "Privacy\u00A0Policy"),
|
|
572
609
|
' and ',
|
|
573
|
-
|
|
610
|
+
e.createElement(core$1.Anchor, { href: "https://www.medplum.com/terms" }, "Terms\u00A0of\u00A0Service"),
|
|
574
611
|
".")),
|
|
575
|
-
|
|
576
|
-
|
|
612
|
+
e.createElement(core$1.Group, { position: "right", mt: "xl", noWrap: true },
|
|
613
|
+
e.createElement(core$1.Button, { type: "submit" }, "Create project"))));
|
|
577
614
|
}
|
|
578
615
|
|
|
579
616
|
/**
|
|
@@ -592,11 +629,11 @@
|
|
|
592
629
|
function GoogleButton(props) {
|
|
593
630
|
const medplum = useMedplum();
|
|
594
631
|
const { googleClientId, handleGoogleCredential } = props;
|
|
595
|
-
const parentRef =
|
|
596
|
-
const [scriptLoaded, setScriptLoaded] =
|
|
597
|
-
const [initialized, setInitialized] =
|
|
598
|
-
const [buttonRendered, setButtonRendered] =
|
|
599
|
-
|
|
632
|
+
const parentRef = e.useRef(null);
|
|
633
|
+
const [scriptLoaded, setScriptLoaded] = e.useState(typeof google !== 'undefined');
|
|
634
|
+
const [initialized, setInitialized] = e.useState(false);
|
|
635
|
+
const [buttonRendered, setButtonRendered] = e.useState(false);
|
|
636
|
+
e.useEffect(() => {
|
|
600
637
|
if (typeof google === 'undefined') {
|
|
601
638
|
createScriptTag('https://accounts.google.com/gsi/client', () => setScriptLoaded(true));
|
|
602
639
|
return;
|
|
@@ -616,16 +653,18 @@
|
|
|
616
653
|
if (!googleClientId) {
|
|
617
654
|
return null;
|
|
618
655
|
}
|
|
619
|
-
return
|
|
656
|
+
return e.createElement("div", { ref: parentRef });
|
|
620
657
|
}
|
|
621
658
|
function getGoogleClientId(clientId) {
|
|
622
659
|
if (clientId) {
|
|
623
660
|
return clientId;
|
|
624
661
|
}
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
662
|
+
if (typeof window !== 'undefined') {
|
|
663
|
+
const origin = window.location.protocol + '//' + window.location.host;
|
|
664
|
+
const authorizedOrigins = "undefined"?.split(',') ?? [];
|
|
665
|
+
if (authorizedOrigins.includes(origin)) {
|
|
666
|
+
return "undefined";
|
|
667
|
+
}
|
|
629
668
|
}
|
|
630
669
|
return undefined;
|
|
631
670
|
}
|
|
@@ -634,7 +673,7 @@
|
|
|
634
673
|
if (!props.issues) {
|
|
635
674
|
return null;
|
|
636
675
|
}
|
|
637
|
-
return (
|
|
676
|
+
return (e.createElement(core$1.Alert, { icon: e.createElement(We, { size: 16 }), color: "red" }, props.issues.map((issue) => (e.createElement("div", { "data-testid": "text-field-error", key: issue.details?.text }, issue.details?.text)))));
|
|
638
677
|
}
|
|
639
678
|
|
|
640
679
|
/**
|
|
@@ -669,10 +708,10 @@
|
|
|
669
708
|
const googleClientId = getGoogleClientId(props.googleClientId);
|
|
670
709
|
const recaptchaSiteKey = props.recaptchaSiteKey;
|
|
671
710
|
const medplum = useMedplum();
|
|
672
|
-
const [outcome, setOutcome] =
|
|
711
|
+
const [outcome, setOutcome] = e.useState();
|
|
673
712
|
const issues = getIssuesForExpression(outcome, undefined);
|
|
674
|
-
|
|
675
|
-
return (
|
|
713
|
+
e.useEffect(() => initRecaptcha(recaptchaSiteKey), [recaptchaSiteKey]);
|
|
714
|
+
return (e.createElement(Form, { style: { maxWidth: 400 }, onSubmit: async (formData) => {
|
|
676
715
|
try {
|
|
677
716
|
const recaptchaToken = await getRecaptcha(recaptchaSiteKey);
|
|
678
717
|
props.handleAuthResponse(await medplum.startNewUser({
|
|
@@ -690,11 +729,11 @@
|
|
|
690
729
|
setOutcome(err);
|
|
691
730
|
}
|
|
692
731
|
} },
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
googleClientId && (
|
|
696
|
-
|
|
697
|
-
|
|
732
|
+
e.createElement(core$1.Center, { sx: { flexDirection: 'column' } }, props.children),
|
|
733
|
+
e.createElement(OperationOutcomeAlert, { issues: issues }),
|
|
734
|
+
googleClientId && (e.createElement(e.Fragment, null,
|
|
735
|
+
e.createElement(core$1.Group, { position: "center", p: "xl", style: { height: 70 } },
|
|
736
|
+
e.createElement(GoogleButton, { googleClientId: googleClientId, handleGoogleCredential: async (response) => {
|
|
698
737
|
try {
|
|
699
738
|
props.handleAuthResponse(await medplum.startGoogleLogin({
|
|
700
739
|
googleClientId: response.clientId,
|
|
@@ -706,37 +745,37 @@
|
|
|
706
745
|
setOutcome(err);
|
|
707
746
|
}
|
|
708
747
|
} })),
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
748
|
+
e.createElement(core$1.Divider, { label: "or", labelPosition: "center", my: "lg" }))),
|
|
749
|
+
e.createElement(core$1.Stack, { spacing: "xl" },
|
|
750
|
+
e.createElement(core$1.TextInput, { name: "firstName", type: "text", label: "First name", placeholder: "First name", required: true, autoFocus: true, error: getErrorsForInput(outcome, 'firstName') }),
|
|
751
|
+
e.createElement(core$1.TextInput, { name: "lastName", type: "text", label: "Last name", placeholder: "Last name", required: true, error: getErrorsForInput(outcome, 'lastName') }),
|
|
752
|
+
e.createElement(core$1.TextInput, { name: "email", type: "email", label: "Email", placeholder: "name@domain.com", required: true, error: getErrorsForInput(outcome, 'email') }),
|
|
753
|
+
e.createElement(core$1.PasswordInput, { name: "password", label: "Password", autoComplete: "off", required: true, error: getErrorsForInput(outcome, 'password') }),
|
|
754
|
+
e.createElement(core$1.Text, { color: "dimmed", size: "xs" },
|
|
716
755
|
"By clicking submit you agree to the Medplum",
|
|
717
756
|
' ',
|
|
718
|
-
|
|
757
|
+
e.createElement(core$1.Anchor, { href: "https://www.medplum.com/privacy" }, "Privacy\u00A0Policy"),
|
|
719
758
|
' and ',
|
|
720
|
-
|
|
759
|
+
e.createElement(core$1.Anchor, { href: "https://www.medplum.com/terms" }, "Terms\u00A0of\u00A0Service"),
|
|
721
760
|
"."),
|
|
722
|
-
|
|
761
|
+
e.createElement(core$1.Text, { color: "dimmed", size: "xs" },
|
|
723
762
|
"This site is protected by reCAPTCHA and the Google",
|
|
724
763
|
' ',
|
|
725
|
-
|
|
764
|
+
e.createElement(core$1.Anchor, { href: "https://policies.google.com/privacy" }, "Privacy\u00A0Policy"),
|
|
726
765
|
' and ',
|
|
727
|
-
|
|
766
|
+
e.createElement(core$1.Anchor, { href: "https://policies.google.com/terms" }, "Terms\u00A0of\u00A0Service"),
|
|
728
767
|
" apply.")),
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
768
|
+
e.createElement(core$1.Group, { position: "apart", mt: "xl", noWrap: true },
|
|
769
|
+
e.createElement(core$1.Checkbox, { name: "remember", label: "Remember me", size: "xs" }),
|
|
770
|
+
e.createElement(core$1.Button, { type: "submit" }, "Create account"))));
|
|
732
771
|
}
|
|
733
772
|
|
|
734
773
|
function RegisterForm(props) {
|
|
735
774
|
const { type, projectId, googleClientId, recaptchaSiteKey, onSuccess } = props;
|
|
736
775
|
const medplum = useMedplum();
|
|
737
|
-
const [login, setLogin] =
|
|
738
|
-
const [outcome, setOutcome] =
|
|
739
|
-
|
|
776
|
+
const [login, setLogin] = e.useState(undefined);
|
|
777
|
+
const [outcome, setOutcome] = e.useState();
|
|
778
|
+
e.useEffect(() => {
|
|
740
779
|
if (type === 'patient' && login) {
|
|
741
780
|
medplum
|
|
742
781
|
.startNewPatient({ login, projectId: projectId })
|
|
@@ -756,26 +795,26 @@
|
|
|
756
795
|
setLogin(response.login);
|
|
757
796
|
}
|
|
758
797
|
}
|
|
759
|
-
return (
|
|
760
|
-
outcome &&
|
|
761
|
-
!login && (
|
|
762
|
-
login && type === 'project' &&
|
|
798
|
+
return (e.createElement(Document, { width: 450 },
|
|
799
|
+
outcome && e.createElement("pre", null, JSON.stringify(outcome, null, 2)),
|
|
800
|
+
!login && (e.createElement(NewUserForm, { projectId: projectId, googleClientId: googleClientId, recaptchaSiteKey: recaptchaSiteKey, handleAuthResponse: handleAuthResponse }, props.children)),
|
|
801
|
+
login && type === 'project' && e.createElement(NewProjectForm, { login: login, handleAuthResponse: handleAuthResponse })));
|
|
763
802
|
}
|
|
764
803
|
|
|
765
804
|
function AuthenticationForm(props) {
|
|
766
|
-
const [email, setEmail] =
|
|
805
|
+
const [email, setEmail] = e.useState();
|
|
767
806
|
if (!email) {
|
|
768
|
-
return
|
|
807
|
+
return e.createElement(EmailForm, { setEmail: setEmail, ...props });
|
|
769
808
|
}
|
|
770
809
|
else {
|
|
771
|
-
return
|
|
810
|
+
return e.createElement(PasswordForm, { email: email, ...props });
|
|
772
811
|
}
|
|
773
812
|
}
|
|
774
813
|
function EmailForm(props) {
|
|
775
814
|
const { setEmail, onRegister, handleAuthResponse, children, ...baseLoginRequest } = props;
|
|
776
815
|
const medplum = useMedplum();
|
|
777
816
|
const googleClientId = getGoogleClientId(props.googleClientId);
|
|
778
|
-
const isExternalAuth =
|
|
817
|
+
const isExternalAuth = e.useCallback(async (authMethod) => {
|
|
779
818
|
if (!authMethod.authorizeUrl) {
|
|
780
819
|
return false;
|
|
781
820
|
}
|
|
@@ -788,13 +827,13 @@
|
|
|
788
827
|
window.location.assign(url.toString());
|
|
789
828
|
return true;
|
|
790
829
|
}, [medplum, baseLoginRequest]);
|
|
791
|
-
const handleSubmit =
|
|
830
|
+
const handleSubmit = e.useCallback(async (formData) => {
|
|
792
831
|
const authMethod = await medplum.post('auth/method', { email: formData.email });
|
|
793
832
|
if (!(await isExternalAuth(authMethod))) {
|
|
794
833
|
setEmail(formData.email);
|
|
795
834
|
}
|
|
796
835
|
}, [medplum, isExternalAuth, setEmail]);
|
|
797
|
-
const handleGoogleCredential =
|
|
836
|
+
const handleGoogleCredential = e.useCallback(async (response) => {
|
|
798
837
|
const authResponse = await medplum.startGoogleLogin({
|
|
799
838
|
...baseLoginRequest,
|
|
800
839
|
googleCredential: response.credential,
|
|
@@ -803,23 +842,23 @@
|
|
|
803
842
|
handleAuthResponse(authResponse);
|
|
804
843
|
}
|
|
805
844
|
}, [medplum, baseLoginRequest, isExternalAuth, handleAuthResponse]);
|
|
806
|
-
return (
|
|
807
|
-
|
|
808
|
-
googleClientId && (
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
onRegister && (
|
|
815
|
-
|
|
845
|
+
return (e.createElement(Form, { style: { maxWidth: 400 }, onSubmit: handleSubmit },
|
|
846
|
+
e.createElement(core$1.Center, { sx: { flexDirection: 'column' } }, children),
|
|
847
|
+
googleClientId && (e.createElement(e.Fragment, null,
|
|
848
|
+
e.createElement(core$1.Group, { position: "center", p: "xl", style: { height: 70 } },
|
|
849
|
+
e.createElement(GoogleButton, { googleClientId: googleClientId, handleGoogleCredential: handleGoogleCredential })),
|
|
850
|
+
e.createElement(core$1.Divider, { label: "or", labelPosition: "center", my: "lg" }))),
|
|
851
|
+
e.createElement(core$1.TextInput, { name: "email", type: "email", label: "Email", placeholder: "name@domain.com", required: true, autoFocus: true }),
|
|
852
|
+
e.createElement(core$1.Group, { position: "apart", mt: "xl", spacing: 0, noWrap: true },
|
|
853
|
+
onRegister && (e.createElement(core$1.Anchor, { component: "button", type: "button", color: "dimmed", onClick: onRegister, size: "xs" }, "Register")),
|
|
854
|
+
e.createElement(core$1.Button, { type: "submit" }, "Next"))));
|
|
816
855
|
}
|
|
817
856
|
function PasswordForm(props) {
|
|
818
857
|
const { onForgotPassword, handleAuthResponse, children, ...baseLoginRequest } = props;
|
|
819
858
|
const medplum = useMedplum();
|
|
820
|
-
const [outcome, setOutcome] =
|
|
859
|
+
const [outcome, setOutcome] = e.useState();
|
|
821
860
|
const issues = getIssuesForExpression(outcome, undefined);
|
|
822
|
-
const handleSubmit =
|
|
861
|
+
const handleSubmit = e.useCallback((formData) => {
|
|
823
862
|
medplum
|
|
824
863
|
.startLogin({
|
|
825
864
|
...baseLoginRequest,
|
|
@@ -829,24 +868,24 @@
|
|
|
829
868
|
.then(handleAuthResponse)
|
|
830
869
|
.catch(setOutcome);
|
|
831
870
|
}, [medplum, baseLoginRequest, handleAuthResponse]);
|
|
832
|
-
return (
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
onForgotPassword && (
|
|
839
|
-
|
|
840
|
-
|
|
871
|
+
return (e.createElement(Form, { style: { maxWidth: 400 }, onSubmit: handleSubmit },
|
|
872
|
+
e.createElement(core$1.Center, { sx: { flexDirection: 'column' } }, children),
|
|
873
|
+
e.createElement(OperationOutcomeAlert, { issues: issues }),
|
|
874
|
+
e.createElement(core$1.Stack, { spacing: "xl" },
|
|
875
|
+
e.createElement(core$1.PasswordInput, { name: "password", type: "password", label: "Password", autoComplete: "off", required: true, error: getErrorsForInput(outcome, 'password') })),
|
|
876
|
+
e.createElement(core$1.Group, { position: "apart", mt: "xl", spacing: 0, noWrap: true },
|
|
877
|
+
onForgotPassword && (e.createElement(core$1.Anchor, { component: "button", type: "button", color: "dimmed", onClick: onForgotPassword, size: "xs" }, "Forgot password")),
|
|
878
|
+
e.createElement(core$1.Checkbox, { id: "remember", name: "remember", label: "Remember me", size: "xs", sx: { lineHeight: 1 } }),
|
|
879
|
+
e.createElement(core$1.Button, { type: "submit" }, "Sign in"))));
|
|
841
880
|
}
|
|
842
881
|
|
|
843
882
|
function ChooseProfileForm(props) {
|
|
844
883
|
const medplum = useMedplum();
|
|
845
|
-
return (
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
props.memberships.map((membership) => (
|
|
884
|
+
return (e.createElement(core$1.Stack, null,
|
|
885
|
+
e.createElement(core$1.Center, { sx: { flexDirection: 'column' } },
|
|
886
|
+
e.createElement(Logo, { size: 32 }),
|
|
887
|
+
e.createElement(core$1.Title, null, "Choose profile")),
|
|
888
|
+
props.memberships.map((membership) => (e.createElement(core$1.UnstyledButton, { key: membership.id, onClick: () => {
|
|
850
889
|
medplum
|
|
851
890
|
.post('auth/profile', {
|
|
852
891
|
login: props.login,
|
|
@@ -855,16 +894,16 @@
|
|
|
855
894
|
.then(props.handleAuthResponse)
|
|
856
895
|
.catch(console.log);
|
|
857
896
|
} },
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
897
|
+
e.createElement(core$1.Group, null,
|
|
898
|
+
e.createElement(core$1.Avatar, { radius: "xl" }),
|
|
899
|
+
e.createElement("div", { style: { flex: 1 } },
|
|
900
|
+
e.createElement(core$1.Text, { size: "sm", weight: 500 }, membership.profile?.display),
|
|
901
|
+
e.createElement(core$1.Text, { color: "dimmed", size: "xs" }, membership.project?.display))))))));
|
|
863
902
|
}
|
|
864
903
|
|
|
865
904
|
function ChooseScopeForm(props) {
|
|
866
905
|
const medplum = useMedplum();
|
|
867
|
-
return (
|
|
906
|
+
return (e.createElement(Form, { style: { maxWidth: 400 }, onSubmit: (formData) => {
|
|
868
907
|
medplum
|
|
869
908
|
.post('auth/scope', {
|
|
870
909
|
login: props.login,
|
|
@@ -873,19 +912,19 @@
|
|
|
873
912
|
.then(props.handleAuthResponse)
|
|
874
913
|
.catch(console.log);
|
|
875
914
|
} },
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
915
|
+
e.createElement(core$1.Stack, null,
|
|
916
|
+
e.createElement(core$1.Center, { sx: { flexDirection: 'column' } },
|
|
917
|
+
e.createElement(Logo, { size: 32 }),
|
|
918
|
+
e.createElement(core$1.Title, null, "Choose scope")),
|
|
919
|
+
e.createElement(core$1.Stack, null, (props.scope || 'openid').split(' ').map((scopeName) => (e.createElement(core$1.Checkbox, { key: scopeName, id: scopeName, name: scopeName, label: scopeName, defaultChecked: true })))),
|
|
920
|
+
e.createElement(core$1.Group, { position: "right", mt: "xl" },
|
|
921
|
+
e.createElement(core$1.Button, { type: "submit" }, "Set scope")))));
|
|
883
922
|
}
|
|
884
923
|
|
|
885
924
|
function MfaForm(props) {
|
|
886
925
|
const medplum = useMedplum();
|
|
887
|
-
const [errorMessage, setErrorMessage] =
|
|
888
|
-
return (
|
|
926
|
+
const [errorMessage, setErrorMessage] = e.useState(undefined);
|
|
927
|
+
return (e.createElement(Form, { style: { maxWidth: 400 }, onSubmit: (formData) => {
|
|
889
928
|
setErrorMessage(undefined);
|
|
890
929
|
medplum
|
|
891
930
|
.post('auth/mfa/verify', {
|
|
@@ -895,15 +934,15 @@
|
|
|
895
934
|
.then(props.handleAuthResponse)
|
|
896
935
|
.catch((err) => setErrorMessage(core.normalizeErrorString(err)));
|
|
897
936
|
} },
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
errorMessage && (
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
937
|
+
e.createElement(core$1.Stack, null,
|
|
938
|
+
e.createElement(core$1.Center, { sx: { flexDirection: 'column' } },
|
|
939
|
+
e.createElement(Logo, { size: 32 }),
|
|
940
|
+
e.createElement(core$1.Title, null, "Enter MFA code")),
|
|
941
|
+
errorMessage && (e.createElement(core$1.Alert, { icon: e.createElement(We, { size: 16 }), title: "Error", color: "red" }, errorMessage)),
|
|
942
|
+
e.createElement(core$1.Stack, null,
|
|
943
|
+
e.createElement(core$1.TextInput, { name: "token", label: "MFA code", required: true })),
|
|
944
|
+
e.createElement(core$1.Group, { position: "right", mt: "xl" },
|
|
945
|
+
e.createElement(core$1.Button, { type: "submit" }, "Submit code")))));
|
|
907
946
|
}
|
|
908
947
|
|
|
909
948
|
/**
|
|
@@ -919,10 +958,10 @@
|
|
|
919
958
|
function SignInForm(props) {
|
|
920
959
|
const { chooseScopes, onSuccess, onForgotPassword, onRegister, onCode, ...baseLoginRequest } = props;
|
|
921
960
|
const medplum = useMedplum();
|
|
922
|
-
const [login, setLogin] =
|
|
923
|
-
const [mfaRequired, setAuthenticatorRequired] =
|
|
924
|
-
const [memberships, setMemberships] =
|
|
925
|
-
const handleCode =
|
|
961
|
+
const [login, setLogin] = e.useState(undefined);
|
|
962
|
+
const [mfaRequired, setAuthenticatorRequired] = e.useState(false);
|
|
963
|
+
const [memberships, setMemberships] = e.useState(undefined);
|
|
964
|
+
const handleCode = e.useCallback((code) => {
|
|
926
965
|
if (onCode) {
|
|
927
966
|
onCode(code);
|
|
928
967
|
}
|
|
@@ -937,7 +976,7 @@
|
|
|
937
976
|
.catch(console.log);
|
|
938
977
|
}
|
|
939
978
|
}, [medplum, onCode, onSuccess]);
|
|
940
|
-
const handleAuthResponse =
|
|
979
|
+
const handleAuthResponse = e.useCallback((response) => {
|
|
941
980
|
setAuthenticatorRequired(!!response.mfaRequired);
|
|
942
981
|
if (response.login) {
|
|
943
982
|
setLogin(response.login);
|
|
@@ -954,10 +993,10 @@
|
|
|
954
993
|
}
|
|
955
994
|
}
|
|
956
995
|
}, [chooseScopes, handleCode]);
|
|
957
|
-
const handleScopeResponse =
|
|
996
|
+
const handleScopeResponse = e.useCallback((response) => {
|
|
958
997
|
handleCode(response.code);
|
|
959
998
|
}, [handleCode]);
|
|
960
|
-
|
|
999
|
+
e.useEffect(() => {
|
|
961
1000
|
if (props.login) {
|
|
962
1001
|
medplum
|
|
963
1002
|
.get('auth/login/' + props.login)
|
|
@@ -965,24 +1004,24 @@
|
|
|
965
1004
|
.catch(console.error);
|
|
966
1005
|
}
|
|
967
1006
|
}, [medplum, props, handleAuthResponse]);
|
|
968
|
-
return (
|
|
1007
|
+
return (e.createElement(Document, { width: 450 }, (() => {
|
|
969
1008
|
if (!login) {
|
|
970
|
-
return (
|
|
1009
|
+
return (e.createElement(AuthenticationForm, { onForgotPassword: onForgotPassword, onRegister: onRegister, handleAuthResponse: handleAuthResponse, ...baseLoginRequest }, props.children));
|
|
971
1010
|
}
|
|
972
1011
|
else if (mfaRequired) {
|
|
973
|
-
return
|
|
1012
|
+
return e.createElement(MfaForm, { login: login, handleAuthResponse: handleAuthResponse });
|
|
974
1013
|
}
|
|
975
1014
|
else if (memberships) {
|
|
976
|
-
return
|
|
1015
|
+
return e.createElement(ChooseProfileForm, { login: login, memberships: memberships, handleAuthResponse: handleAuthResponse });
|
|
977
1016
|
}
|
|
978
1017
|
else if (props.projectId === 'new') {
|
|
979
|
-
return
|
|
1018
|
+
return e.createElement(NewProjectForm, { login: login, handleAuthResponse: handleAuthResponse });
|
|
980
1019
|
}
|
|
981
1020
|
else if (props.chooseScopes) {
|
|
982
|
-
return
|
|
1021
|
+
return e.createElement(ChooseScopeForm, { login: login, scope: props.scope, handleAuthResponse: handleScopeResponse });
|
|
983
1022
|
}
|
|
984
1023
|
else {
|
|
985
|
-
return
|
|
1024
|
+
return e.createElement("div", null, "Success");
|
|
986
1025
|
}
|
|
987
1026
|
})()));
|
|
988
1027
|
}
|
|
@@ -997,7 +1036,7 @@
|
|
|
997
1036
|
'modifierExtension',
|
|
998
1037
|
];
|
|
999
1038
|
|
|
1000
|
-
const useStyles$
|
|
1039
|
+
const useStyles$c = core$1.createStyles((theme) => ({
|
|
1001
1040
|
root: {
|
|
1002
1041
|
display: 'grid',
|
|
1003
1042
|
gridTemplateColumns: '30% 70%',
|
|
@@ -1018,21 +1057,21 @@
|
|
|
1018
1057
|
}));
|
|
1019
1058
|
function DescriptionList(props) {
|
|
1020
1059
|
const { children, compact } = props;
|
|
1021
|
-
const { classes, cx } = useStyles$
|
|
1022
|
-
return
|
|
1060
|
+
const { classes, cx } = useStyles$c();
|
|
1061
|
+
return e.createElement("dl", { className: cx(classes.root, { [classes.compact]: compact }) }, children);
|
|
1023
1062
|
}
|
|
1024
1063
|
function DescriptionListEntry(props) {
|
|
1025
|
-
return (
|
|
1026
|
-
|
|
1027
|
-
|
|
1064
|
+
return (e.createElement(e.Fragment, null,
|
|
1065
|
+
e.createElement("dt", null, props.term),
|
|
1066
|
+
e.createElement("dd", null, props.children)));
|
|
1028
1067
|
}
|
|
1029
1068
|
|
|
1030
1069
|
function CodeableConceptDisplay(props) {
|
|
1031
|
-
return
|
|
1070
|
+
return e.createElement(e.Fragment, null, core.formatCodeableConcept(props.value));
|
|
1032
1071
|
}
|
|
1033
1072
|
|
|
1034
1073
|
function CodingDisplay(props) {
|
|
1035
|
-
return
|
|
1074
|
+
return e.createElement(e.Fragment, null, core.formatCoding(props.value));
|
|
1036
1075
|
}
|
|
1037
1076
|
|
|
1038
1077
|
function ContactPointDisplay(props) {
|
|
@@ -1057,7 +1096,7 @@
|
|
|
1057
1096
|
}
|
|
1058
1097
|
builder.push(']');
|
|
1059
1098
|
}
|
|
1060
|
-
return
|
|
1099
|
+
return e.createElement(e.Fragment, null, builder.join('').trim());
|
|
1061
1100
|
}
|
|
1062
1101
|
|
|
1063
1102
|
function ContactDetailDisplay(props) {
|
|
@@ -1065,10 +1104,10 @@
|
|
|
1065
1104
|
if (!contactDetail) {
|
|
1066
1105
|
return null;
|
|
1067
1106
|
}
|
|
1068
|
-
return (
|
|
1107
|
+
return (e.createElement(e.Fragment, null,
|
|
1069
1108
|
contactDetail.name,
|
|
1070
1109
|
contactDetail.name && ': ',
|
|
1071
|
-
contactDetail.telecom?.map((telecom, index) => (
|
|
1110
|
+
contactDetail.telecom?.map((telecom, index) => (e.createElement(ContactPointDisplay, { key: 'telecom-' + index, value: telecom })))));
|
|
1072
1111
|
}
|
|
1073
1112
|
|
|
1074
1113
|
function HumanNameDisplay(props) {
|
|
@@ -1076,26 +1115,26 @@
|
|
|
1076
1115
|
if (!name) {
|
|
1077
1116
|
return null;
|
|
1078
1117
|
}
|
|
1079
|
-
return
|
|
1118
|
+
return e.createElement(e.Fragment, null, core.formatHumanName(name, props.options));
|
|
1080
1119
|
}
|
|
1081
1120
|
|
|
1082
1121
|
function IdentifierDisplay(props) {
|
|
1083
|
-
return (
|
|
1122
|
+
return (e.createElement("div", null,
|
|
1084
1123
|
props.value?.system,
|
|
1085
1124
|
": ",
|
|
1086
1125
|
props.value?.value));
|
|
1087
1126
|
}
|
|
1088
1127
|
|
|
1089
1128
|
function MoneyDisplay(props) {
|
|
1090
|
-
return
|
|
1129
|
+
return e.createElement(e.Fragment, null, core.formatMoney(props.value));
|
|
1091
1130
|
}
|
|
1092
1131
|
|
|
1093
1132
|
function QuantityDisplay(props) {
|
|
1094
|
-
return
|
|
1133
|
+
return e.createElement(e.Fragment, null, core.formatQuantity(props.value));
|
|
1095
1134
|
}
|
|
1096
1135
|
|
|
1097
1136
|
function RangeDisplay(props) {
|
|
1098
|
-
return
|
|
1137
|
+
return e.createElement(e.Fragment, null, core.formatRange(props.value));
|
|
1099
1138
|
}
|
|
1100
1139
|
|
|
1101
1140
|
function RatioDisplay(props) {
|
|
@@ -1103,20 +1142,20 @@
|
|
|
1103
1142
|
if (!value) {
|
|
1104
1143
|
return null;
|
|
1105
1144
|
}
|
|
1106
|
-
return (
|
|
1107
|
-
|
|
1145
|
+
return (e.createElement(e.Fragment, null,
|
|
1146
|
+
e.createElement(QuantityDisplay, { value: value.numerator }),
|
|
1108
1147
|
"\u00A0/\u00A0",
|
|
1109
|
-
|
|
1148
|
+
e.createElement(QuantityDisplay, { value: value.denominator })));
|
|
1110
1149
|
}
|
|
1111
1150
|
|
|
1112
1151
|
function MedplumLink(props) {
|
|
1113
|
-
const navigate =
|
|
1152
|
+
const navigate = useMedplumNavigate();
|
|
1114
1153
|
const { to, suffix, label, onClick, children, ...rest } = props;
|
|
1115
1154
|
let href = getHref(to);
|
|
1116
1155
|
if (suffix) {
|
|
1117
1156
|
href += '/' + suffix;
|
|
1118
1157
|
}
|
|
1119
|
-
return (
|
|
1158
|
+
return (e.createElement(core$1.Anchor, { href: href, "aria-label": label, onClick: (e) => {
|
|
1120
1159
|
killEvent(e);
|
|
1121
1160
|
if (onClick) {
|
|
1122
1161
|
onClick();
|
|
@@ -1161,10 +1200,10 @@
|
|
|
1161
1200
|
// The "link" prop defaults to "true"; undefined is treated as "true"
|
|
1162
1201
|
// To disable the link, it must be explicitly "false"
|
|
1163
1202
|
if (props.link !== false && props.value.reference) {
|
|
1164
|
-
return
|
|
1203
|
+
return e.createElement(MedplumLink, { to: props.value }, displayString);
|
|
1165
1204
|
}
|
|
1166
1205
|
else {
|
|
1167
|
-
return
|
|
1206
|
+
return e.createElement(e.Fragment, null, displayString);
|
|
1168
1207
|
}
|
|
1169
1208
|
}
|
|
1170
1209
|
|
|
@@ -1172,21 +1211,21 @@
|
|
|
1172
1211
|
const property = props.property;
|
|
1173
1212
|
const values = props.values ?? [];
|
|
1174
1213
|
const propertyType = property.type?.[0]?.code;
|
|
1175
|
-
return (
|
|
1176
|
-
|
|
1214
|
+
return (e.createElement(e.Fragment, null, values.map((v, index) => (e.createElement("div", { key: `${index}-${values.length}` },
|
|
1215
|
+
e.createElement(ResourcePropertyDisplay, { arrayElement: true, property: property, propertyType: propertyType, value: v, ignoreMissingValues: props.ignoreMissingValues, link: props.link }))))));
|
|
1177
1216
|
}
|
|
1178
1217
|
|
|
1179
1218
|
function ResourcePropertyDisplay(props) {
|
|
1180
1219
|
const { property, propertyType, value } = props;
|
|
1181
1220
|
if (property?.max === '*' && !props.arrayElement) {
|
|
1182
1221
|
if (propertyType === 'Attachment') {
|
|
1183
|
-
return
|
|
1222
|
+
return e.createElement(AttachmentArrayDisplay, { values: value, maxWidth: props.maxWidth });
|
|
1184
1223
|
}
|
|
1185
|
-
return (
|
|
1224
|
+
return (e.createElement(ResourceArrayDisplay, { property: property, values: value, ignoreMissingValues: props.ignoreMissingValues, link: props.link }));
|
|
1186
1225
|
}
|
|
1187
1226
|
switch (propertyType) {
|
|
1188
1227
|
case core.PropertyType.boolean:
|
|
1189
|
-
return
|
|
1228
|
+
return e.createElement(e.Fragment, null, value === undefined ? '' : Boolean(value).toString());
|
|
1190
1229
|
case core.PropertyType.SystemString:
|
|
1191
1230
|
case core.PropertyType.code:
|
|
1192
1231
|
case core.PropertyType.date:
|
|
@@ -1196,55 +1235,55 @@
|
|
|
1196
1235
|
case core.PropertyType.unsignedInt:
|
|
1197
1236
|
case core.PropertyType.uri:
|
|
1198
1237
|
case core.PropertyType.url:
|
|
1199
|
-
return
|
|
1238
|
+
return e.createElement(e.Fragment, null, value);
|
|
1200
1239
|
case core.PropertyType.canonical:
|
|
1201
|
-
return
|
|
1240
|
+
return e.createElement(ReferenceDisplay, { value: { reference: value }, link: props.link });
|
|
1202
1241
|
case core.PropertyType.dateTime:
|
|
1203
1242
|
case core.PropertyType.instant:
|
|
1204
|
-
return
|
|
1243
|
+
return e.createElement(e.Fragment, null, core.formatDateTime(value));
|
|
1205
1244
|
case core.PropertyType.markdown:
|
|
1206
|
-
return
|
|
1245
|
+
return e.createElement("pre", null, value);
|
|
1207
1246
|
case core.PropertyType.Address:
|
|
1208
|
-
return
|
|
1247
|
+
return e.createElement(AddressDisplay, { value: value });
|
|
1209
1248
|
case core.PropertyType.Annotation:
|
|
1210
|
-
return
|
|
1249
|
+
return e.createElement(e.Fragment, null, value?.text);
|
|
1211
1250
|
case core.PropertyType.Attachment:
|
|
1212
|
-
return
|
|
1251
|
+
return e.createElement(AttachmentDisplay, { value: value, maxWidth: props.maxWidth });
|
|
1213
1252
|
case core.PropertyType.CodeableConcept:
|
|
1214
|
-
return
|
|
1253
|
+
return e.createElement(CodeableConceptDisplay, { value: value });
|
|
1215
1254
|
case core.PropertyType.Coding:
|
|
1216
|
-
return
|
|
1255
|
+
return e.createElement(CodingDisplay, { value: value });
|
|
1217
1256
|
case core.PropertyType.ContactDetail:
|
|
1218
|
-
return
|
|
1257
|
+
return e.createElement(ContactDetailDisplay, { value: value });
|
|
1219
1258
|
case core.PropertyType.ContactPoint:
|
|
1220
|
-
return
|
|
1259
|
+
return e.createElement(ContactPointDisplay, { value: value });
|
|
1221
1260
|
case core.PropertyType.HumanName:
|
|
1222
|
-
return
|
|
1261
|
+
return e.createElement(HumanNameDisplay, { value: value });
|
|
1223
1262
|
case core.PropertyType.Identifier:
|
|
1224
|
-
return
|
|
1263
|
+
return e.createElement(IdentifierDisplay, { value: value });
|
|
1225
1264
|
case core.PropertyType.Money:
|
|
1226
|
-
return
|
|
1265
|
+
return e.createElement(MoneyDisplay, { value: value });
|
|
1227
1266
|
case core.PropertyType.Period:
|
|
1228
|
-
return
|
|
1267
|
+
return e.createElement(e.Fragment, null, core.formatPeriod(value));
|
|
1229
1268
|
case core.PropertyType.Quantity:
|
|
1230
1269
|
case core.PropertyType.Duration:
|
|
1231
|
-
return
|
|
1270
|
+
return e.createElement(QuantityDisplay, { value: value });
|
|
1232
1271
|
case core.PropertyType.Range:
|
|
1233
|
-
return
|
|
1272
|
+
return e.createElement(RangeDisplay, { value: value });
|
|
1234
1273
|
case core.PropertyType.Ratio:
|
|
1235
|
-
return
|
|
1274
|
+
return e.createElement(RatioDisplay, { value: value });
|
|
1236
1275
|
case core.PropertyType.Reference:
|
|
1237
|
-
return
|
|
1276
|
+
return e.createElement(ReferenceDisplay, { value: value, link: props.link });
|
|
1238
1277
|
case core.PropertyType.Timing:
|
|
1239
|
-
return
|
|
1278
|
+
return e.createElement(e.Fragment, null, core.formatTiming(value));
|
|
1240
1279
|
case core.PropertyType.Dosage:
|
|
1241
1280
|
case core.PropertyType.UsageContext:
|
|
1242
|
-
return (
|
|
1281
|
+
return (e.createElement(BackboneElementDisplay, { value: { type: propertyType, value }, compact: true, ignoreMissingValues: props.ignoreMissingValues }));
|
|
1243
1282
|
default:
|
|
1244
1283
|
if (!property?.path) {
|
|
1245
1284
|
throw Error(`Displaying property of type ${props.propertyType} requires element definition path`);
|
|
1246
1285
|
}
|
|
1247
|
-
return (
|
|
1286
|
+
return (e.createElement(BackboneElementDisplay, { value: { type: core.getElementDefinitionTypeName(property), value }, compact: true, ignoreMissingValues: props.ignoreMissingValues }));
|
|
1248
1287
|
}
|
|
1249
1288
|
}
|
|
1250
1289
|
/**
|
|
@@ -1277,7 +1316,7 @@
|
|
|
1277
1316
|
const typeName = typedValue.type;
|
|
1278
1317
|
const typeSchema = core.globalSchema.types[typeName];
|
|
1279
1318
|
if (!typeSchema) {
|
|
1280
|
-
return
|
|
1319
|
+
return e.createElement("div", null,
|
|
1281
1320
|
typeName,
|
|
1282
1321
|
"\u00A0not implemented");
|
|
1283
1322
|
}
|
|
@@ -1288,9 +1327,9 @@
|
|
|
1288
1327
|
// Special case for common BackboneElement pattern
|
|
1289
1328
|
// Where there is an object with a single property 'name'
|
|
1290
1329
|
// Just display the name value.
|
|
1291
|
-
return
|
|
1330
|
+
return e.createElement("div", null, value.name);
|
|
1292
1331
|
}
|
|
1293
|
-
return (
|
|
1332
|
+
return (e.createElement(DescriptionList, { compact: props.compact }, Object.entries(typeSchema.properties).map((entry) => {
|
|
1294
1333
|
const key = entry[0];
|
|
1295
1334
|
if (DEFAULT_IGNORED_PROPERTIES.indexOf(key) >= 0) {
|
|
1296
1335
|
return null;
|
|
@@ -1304,20 +1343,20 @@
|
|
|
1304
1343
|
(!propertyValue || (Array.isArray(propertyValue) && propertyValue.length === 0))) {
|
|
1305
1344
|
return null;
|
|
1306
1345
|
}
|
|
1307
|
-
return (
|
|
1308
|
-
|
|
1346
|
+
return (e.createElement(DescriptionListEntry, { key: key, term: core.getPropertyDisplayName(key) },
|
|
1347
|
+
e.createElement(ResourcePropertyDisplay, { property: property, propertyType: propertyType, value: propertyValue, ignoreMissingValues: props.ignoreMissingValues, link: props.link })));
|
|
1309
1348
|
})));
|
|
1310
1349
|
}
|
|
1311
1350
|
|
|
1312
1351
|
function CheckboxFormSection(props) {
|
|
1313
|
-
return (
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1352
|
+
return (e.createElement(core$1.Group, { noWrap: true },
|
|
1353
|
+
e.createElement("div", null, props.children),
|
|
1354
|
+
e.createElement("div", null,
|
|
1355
|
+
e.createElement(core$1.Input.Wrapper, { id: props.htmlFor, label: props.title, description: props.description }, (() => null)()))));
|
|
1317
1356
|
}
|
|
1318
1357
|
|
|
1319
1358
|
function FormSection(props) {
|
|
1320
|
-
return (
|
|
1359
|
+
return (e.createElement(core$1.Input.Wrapper, { id: props.htmlFor, label: props.title, description: props.description, error: getErrorsForInput(props.outcome, props.htmlFor) }, props.children));
|
|
1321
1360
|
}
|
|
1322
1361
|
|
|
1323
1362
|
const system = {
|
|
@@ -1337,8 +1376,11 @@
|
|
|
1337
1376
|
*/
|
|
1338
1377
|
function useResource(value) {
|
|
1339
1378
|
const medplum = useMedplum();
|
|
1340
|
-
const [resource, setResource] =
|
|
1341
|
-
|
|
1379
|
+
const [resource, setResource] = e.useState(getInitialResource(medplum, value));
|
|
1380
|
+
e.useEffect(() => {
|
|
1381
|
+
setResource(getInitialResource(medplum, value));
|
|
1382
|
+
}, [medplum, value]);
|
|
1383
|
+
e.useEffect(() => {
|
|
1342
1384
|
let subscribed = true;
|
|
1343
1385
|
if (!resource && value && 'reference' in value && value.reference) {
|
|
1344
1386
|
medplum
|
|
@@ -1383,32 +1425,32 @@
|
|
|
1383
1425
|
function ResourceForm(props) {
|
|
1384
1426
|
const medplum = useMedplum();
|
|
1385
1427
|
const defaultValue = useResource(props.defaultValue);
|
|
1386
|
-
const [schema, setSchema] =
|
|
1387
|
-
const [value, setValue] =
|
|
1388
|
-
|
|
1428
|
+
const [schema, setSchema] = e.useState();
|
|
1429
|
+
const [value, setValue] = e.useState();
|
|
1430
|
+
e.useEffect(() => {
|
|
1389
1431
|
if (defaultValue) {
|
|
1390
1432
|
setValue(JSON.parse(JSON.stringify(defaultValue)));
|
|
1391
1433
|
medplum.requestSchema(defaultValue.resourceType).then(setSchema).catch(console.log);
|
|
1392
1434
|
}
|
|
1393
1435
|
}, [medplum, defaultValue]);
|
|
1394
1436
|
if (!schema || !value) {
|
|
1395
|
-
return
|
|
1437
|
+
return e.createElement("div", null, "Loading...");
|
|
1396
1438
|
}
|
|
1397
|
-
return (
|
|
1439
|
+
return (e.createElement("form", { noValidate: true, autoComplete: "off", onSubmit: (e) => {
|
|
1398
1440
|
e.preventDefault();
|
|
1399
1441
|
if (props.onSubmit) {
|
|
1400
1442
|
props.onSubmit(value);
|
|
1401
1443
|
}
|
|
1402
1444
|
} },
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
props.onDelete && (
|
|
1445
|
+
e.createElement(core$1.Stack, { mb: "xl" },
|
|
1446
|
+
e.createElement(FormSection, { title: "Resource Type", htmlFor: "resourceType", outcome: props.outcome },
|
|
1447
|
+
e.createElement(core$1.TextInput, { name: "resourceType", defaultValue: value.resourceType, disabled: true })),
|
|
1448
|
+
e.createElement(FormSection, { title: "ID", htmlFor: "id", outcome: props.outcome },
|
|
1449
|
+
e.createElement(core$1.TextInput, { name: "id", defaultValue: value.id, disabled: true }))),
|
|
1450
|
+
e.createElement(BackboneElementInput, { typeName: value.resourceType, defaultValue: value, outcome: props.outcome, onChange: setValue }),
|
|
1451
|
+
e.createElement(core$1.Group, { position: "right", mt: "xl" },
|
|
1452
|
+
e.createElement(core$1.Button, { type: "submit" }, "OK"),
|
|
1453
|
+
props.onDelete && (e.createElement(core$1.Button, { variant: "outline", color: "red", type: "button", onClick: () => {
|
|
1412
1454
|
props.onDelete(value);
|
|
1413
1455
|
} }, "Delete")))));
|
|
1414
1456
|
}
|
|
@@ -1445,7 +1487,7 @@
|
|
|
1445
1487
|
function ValueSetAutocomplete(props) {
|
|
1446
1488
|
const medplum = useMedplum();
|
|
1447
1489
|
const { elementDefinition, ...rest } = props;
|
|
1448
|
-
const loadValues =
|
|
1490
|
+
const loadValues = e.useCallback(async (input, signal) => {
|
|
1449
1491
|
const system = elementDefinition.binding?.valueSet;
|
|
1450
1492
|
const valueSet = await medplum.searchValueSet(system, input, { signal });
|
|
1451
1493
|
const valueSetElements = valueSet.expansion?.contains;
|
|
@@ -1457,14 +1499,14 @@
|
|
|
1457
1499
|
}
|
|
1458
1500
|
return newData;
|
|
1459
1501
|
}, [medplum, elementDefinition]);
|
|
1460
|
-
return (
|
|
1502
|
+
return (e.createElement(AsyncAutocomplete, { ...rest, creatable: true, clearable: true, toKey: toKey, toOption: toOption, loadOptions: loadValues, getCreateLabel: (query) => `+ Create ${query}`, onCreate: createValue }));
|
|
1461
1503
|
}
|
|
1462
1504
|
function getDisplay(item) {
|
|
1463
1505
|
return item.display || item.code || '';
|
|
1464
1506
|
}
|
|
1465
1507
|
|
|
1466
1508
|
function CodeableConceptInput(props) {
|
|
1467
|
-
const [value, setValue] =
|
|
1509
|
+
const [value, setValue] = e.useState(props.defaultValue);
|
|
1468
1510
|
function handleChange(newValues) {
|
|
1469
1511
|
const newConcept = valueSetElementToCodeableConcept(newValues);
|
|
1470
1512
|
setValue(newConcept);
|
|
@@ -1472,7 +1514,7 @@
|
|
|
1472
1514
|
props.onChange(newConcept);
|
|
1473
1515
|
}
|
|
1474
1516
|
}
|
|
1475
|
-
return (
|
|
1517
|
+
return (e.createElement(ValueSetAutocomplete, { elementDefinition: props.property, name: props.name, placeholder: props.placeholder, defaultValue: value && codeableConceptToValueSetElement(value), onChange: handleChange }));
|
|
1476
1518
|
}
|
|
1477
1519
|
function codeableConceptToValueSetElement(concept) {
|
|
1478
1520
|
return concept.coding?.map((c) => ({
|
|
@@ -1495,7 +1537,7 @@
|
|
|
1495
1537
|
}
|
|
1496
1538
|
|
|
1497
1539
|
function CodeInput(props) {
|
|
1498
|
-
const [value, setValue] =
|
|
1540
|
+
const [value, setValue] = e.useState(props.defaultValue);
|
|
1499
1541
|
function handleChange(newValues) {
|
|
1500
1542
|
const newValue = newValues[0];
|
|
1501
1543
|
const newCode = valueSetElementToCode(newValue);
|
|
@@ -1504,7 +1546,7 @@
|
|
|
1504
1546
|
props.onChange(newCode);
|
|
1505
1547
|
}
|
|
1506
1548
|
}
|
|
1507
|
-
return (
|
|
1549
|
+
return (e.createElement(ValueSetAutocomplete, { elementDefinition: props.property, name: props.name, placeholder: props.placeholder, defaultValue: codeToValueSetElement(value), onChange: handleChange }));
|
|
1508
1550
|
}
|
|
1509
1551
|
function codeToValueSetElement(code) {
|
|
1510
1552
|
return code ? { code } : undefined;
|
|
@@ -1514,7 +1556,7 @@
|
|
|
1514
1556
|
}
|
|
1515
1557
|
|
|
1516
1558
|
function CodingInput(props) {
|
|
1517
|
-
const [value, setValue] =
|
|
1559
|
+
const [value, setValue] = e.useState(props.defaultValue);
|
|
1518
1560
|
function handleChange(newValues) {
|
|
1519
1561
|
const newValue = newValues[0];
|
|
1520
1562
|
const newConcept = newValue && valueSetElementToCoding(newValue);
|
|
@@ -1523,7 +1565,7 @@
|
|
|
1523
1565
|
props.onChange(newConcept);
|
|
1524
1566
|
}
|
|
1525
1567
|
}
|
|
1526
|
-
return (
|
|
1568
|
+
return (e.createElement(ValueSetAutocomplete, { elementDefinition: props.property, name: props.name, placeholder: props.placeholder, defaultValue: value && codingToValueSetElement(value), onChange: handleChange }));
|
|
1527
1569
|
}
|
|
1528
1570
|
function codingToValueSetElement(coding) {
|
|
1529
1571
|
return {
|
|
@@ -1541,8 +1583,8 @@
|
|
|
1541
1583
|
}
|
|
1542
1584
|
|
|
1543
1585
|
function ContactPointInput(props) {
|
|
1544
|
-
const [contactPoint, setContactPoint] =
|
|
1545
|
-
const ref =
|
|
1586
|
+
const [contactPoint, setContactPoint] = e.useState(props.defaultValue);
|
|
1587
|
+
const ref = e.useRef();
|
|
1546
1588
|
ref.current = contactPoint;
|
|
1547
1589
|
function setContactPointWrapper(newValue) {
|
|
1548
1590
|
if (newValue && Object.keys(newValue).length === 0) {
|
|
@@ -1574,15 +1616,15 @@
|
|
|
1574
1616
|
}
|
|
1575
1617
|
setContactPointWrapper(newValue);
|
|
1576
1618
|
}
|
|
1577
|
-
return (
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1619
|
+
return (e.createElement(core$1.Group, { spacing: "xs", grow: true, noWrap: true },
|
|
1620
|
+
e.createElement(core$1.NativeSelect, { "data-testid": "system", defaultValue: contactPoint?.system, onChange: (e) => setSystem(e.currentTarget.value), data: ['', 'email', 'phone', 'fax', 'pager', 'sms', 'other'] }),
|
|
1621
|
+
e.createElement(core$1.NativeSelect, { "data-testid": "use", defaultValue: contactPoint?.use, onChange: (e) => setUse(e.currentTarget.value), data: ['', 'home', 'work', 'temp', 'old', 'mobile'] }),
|
|
1622
|
+
e.createElement(core$1.TextInput, { placeholder: "Value", defaultValue: contactPoint?.value, onChange: (e) => setValue(e.currentTarget.value) })));
|
|
1581
1623
|
}
|
|
1582
1624
|
|
|
1583
1625
|
function ContactDetailInput(props) {
|
|
1584
|
-
const [contactPoint, setContactDetail] =
|
|
1585
|
-
const ref =
|
|
1626
|
+
const [contactPoint, setContactDetail] = e.useState(props.defaultValue);
|
|
1627
|
+
const ref = e.useRef();
|
|
1586
1628
|
ref.current = contactPoint;
|
|
1587
1629
|
function setContactDetailWrapper(newValue) {
|
|
1588
1630
|
setContactDetail(newValue);
|
|
@@ -1604,9 +1646,9 @@
|
|
|
1604
1646
|
}
|
|
1605
1647
|
setContactDetailWrapper(newValue);
|
|
1606
1648
|
}
|
|
1607
|
-
return (
|
|
1608
|
-
|
|
1609
|
-
|
|
1649
|
+
return (e.createElement(core$1.Group, { spacing: "xs", grow: true, noWrap: true },
|
|
1650
|
+
e.createElement(core$1.TextInput, { "data-testid": props.name + '-name', name: props.name + '-name', placeholder: "Name", style: { width: 180 }, defaultValue: contactPoint?.name, onChange: (e) => setName(e.currentTarget.value) }),
|
|
1651
|
+
e.createElement(ContactPointInput, { name: props.name + '-telecom', defaultValue: contactPoint?.telecom?.[0], onChange: setTelecom })));
|
|
1610
1652
|
}
|
|
1611
1653
|
|
|
1612
1654
|
/**
|
|
@@ -1618,7 +1660,7 @@
|
|
|
1618
1660
|
* @returns The JSX element to render.
|
|
1619
1661
|
*/
|
|
1620
1662
|
function DateTimeInput(props) {
|
|
1621
|
-
return (
|
|
1663
|
+
return (e.createElement(core$1.TextInput, { id: props.name, name: props.name, "data-testid": props.name, placeholder: props.placeholder, type: getInputType(), defaultValue: convertIsoToLocal(props.defaultValue), error: getErrorsForInput(props.outcome, props.name), onChange: (e) => {
|
|
1622
1664
|
if (props.onChange) {
|
|
1623
1665
|
const newValue = e.currentTarget.value;
|
|
1624
1666
|
props.onChange(convertLocalToIso(newValue));
|
|
@@ -1673,7 +1715,7 @@
|
|
|
1673
1715
|
}
|
|
1674
1716
|
|
|
1675
1717
|
function ExtensionInput(props) {
|
|
1676
|
-
return (
|
|
1718
|
+
return (e.createElement(core$1.JsonInput, { id: props.name, name: props.name, "data-testid": "extension-input", defaultValue: core.stringify(props.defaultValue), onChange: (newValue) => {
|
|
1677
1719
|
if (props.onChange) {
|
|
1678
1720
|
props.onChange(JSON.parse(newValue));
|
|
1679
1721
|
}
|
|
@@ -1681,8 +1723,8 @@
|
|
|
1681
1723
|
}
|
|
1682
1724
|
|
|
1683
1725
|
function HumanNameInput(props) {
|
|
1684
|
-
const [value, setValue] =
|
|
1685
|
-
const valueRef =
|
|
1726
|
+
const [value, setValue] = e.useState(props.defaultValue);
|
|
1727
|
+
const valueRef = e.useRef();
|
|
1686
1728
|
valueRef.current = value;
|
|
1687
1729
|
function setValueWrapper(newValue) {
|
|
1688
1730
|
setValue(newValue);
|
|
@@ -1717,25 +1759,25 @@
|
|
|
1717
1759
|
suffix: suffix ? suffix.split(' ') : undefined,
|
|
1718
1760
|
});
|
|
1719
1761
|
}
|
|
1720
|
-
return (
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1762
|
+
return (e.createElement(core$1.Group, { spacing: "xs", grow: true, noWrap: true },
|
|
1763
|
+
e.createElement(core$1.NativeSelect, { defaultValue: value?.use, "data-testid": "use", onChange: (e) => setUse(e.currentTarget.value), data: ['', 'temp', 'old', 'usual', 'official', 'nickname', 'anonymous', 'maiden'] }),
|
|
1764
|
+
e.createElement(core$1.TextInput, { placeholder: "Prefix", defaultValue: value?.prefix?.join(' '), onChange: (e) => setPrefix(e.currentTarget.value) }),
|
|
1765
|
+
e.createElement(core$1.TextInput, { placeholder: "Given", defaultValue: value?.given?.join(' '), onChange: (e) => setGiven(e.currentTarget.value) }),
|
|
1766
|
+
e.createElement(core$1.TextInput, { placeholder: "Family", defaultValue: value?.family, onChange: (e) => setFamily(e.currentTarget.value) }),
|
|
1767
|
+
e.createElement(core$1.TextInput, { placeholder: "Suffix", defaultValue: value?.suffix?.join(' '), onChange: (e) => setSuffix(e.currentTarget.value) })));
|
|
1726
1768
|
}
|
|
1727
1769
|
|
|
1728
1770
|
function IdentifierInput(props) {
|
|
1729
|
-
const [value, setValue] =
|
|
1771
|
+
const [value, setValue] = e.useState(props.defaultValue);
|
|
1730
1772
|
function setValueWrapper(newValue) {
|
|
1731
1773
|
setValue(newValue);
|
|
1732
1774
|
if (props.onChange) {
|
|
1733
1775
|
props.onChange(newValue);
|
|
1734
1776
|
}
|
|
1735
1777
|
}
|
|
1736
|
-
return (
|
|
1737
|
-
|
|
1738
|
-
|
|
1778
|
+
return (e.createElement(core$1.Group, { spacing: "xs", grow: true, noWrap: true },
|
|
1779
|
+
e.createElement(core$1.TextInput, { placeholder: "System", defaultValue: value?.system, onChange: (e) => setValueWrapper({ ...value, system: e.currentTarget.value }) }),
|
|
1780
|
+
e.createElement(core$1.TextInput, { placeholder: "Value", defaultValue: value?.value, onChange: (e) => setValueWrapper({ ...value, value: e.currentTarget.value }) })));
|
|
1739
1781
|
}
|
|
1740
1782
|
|
|
1741
1783
|
/*
|
|
@@ -1755,26 +1797,26 @@
|
|
|
1755
1797
|
const data = ['USD', 'EUR', 'CAD', 'GBP', 'AUD'];
|
|
1756
1798
|
function MoneyInput(props) {
|
|
1757
1799
|
const { onChange } = props;
|
|
1758
|
-
const [value, setValue] =
|
|
1759
|
-
const setValueWrapper =
|
|
1800
|
+
const [value, setValue] = e.useState(props.defaultValue);
|
|
1801
|
+
const setValueWrapper = e.useCallback((newValue) => {
|
|
1760
1802
|
setValue(newValue);
|
|
1761
1803
|
if (onChange) {
|
|
1762
1804
|
onChange(newValue);
|
|
1763
1805
|
}
|
|
1764
1806
|
}, [onChange]);
|
|
1765
|
-
const handleCurrencyChange =
|
|
1807
|
+
const handleCurrencyChange = e.useCallback((e) => {
|
|
1766
1808
|
setValueWrapper({
|
|
1767
1809
|
...value,
|
|
1768
1810
|
currency: e.currentTarget.value,
|
|
1769
1811
|
});
|
|
1770
1812
|
}, [value, setValueWrapper]);
|
|
1771
|
-
const handleValueChange =
|
|
1813
|
+
const handleValueChange = e.useCallback((e) => {
|
|
1772
1814
|
setValueWrapper({
|
|
1773
1815
|
...value,
|
|
1774
1816
|
value: e.currentTarget.valueAsNumber,
|
|
1775
1817
|
});
|
|
1776
1818
|
}, [value, setValueWrapper]);
|
|
1777
|
-
const select = (
|
|
1819
|
+
const select = (e.createElement(core$1.NativeSelect, { defaultValue: value?.currency, data: data, styles: {
|
|
1778
1820
|
input: {
|
|
1779
1821
|
fontWeight: 500,
|
|
1780
1822
|
borderTopLeftRadius: 0,
|
|
@@ -1782,40 +1824,46 @@
|
|
|
1782
1824
|
width: 92,
|
|
1783
1825
|
},
|
|
1784
1826
|
}, onChange: handleCurrencyChange }));
|
|
1785
|
-
return (
|
|
1827
|
+
return (e.createElement(core$1.TextInput, { type: "number", label: props.label, placeholder: props.placeholder || 'Value', defaultValue: value?.value?.toString() || 'USD', icon: e.createElement(BK, { size: 14 }), rightSection: select, rightSectionWidth: 92, onChange: handleValueChange }));
|
|
1786
1828
|
}
|
|
1787
1829
|
|
|
1788
1830
|
function PeriodInput(props) {
|
|
1789
|
-
const [value, setValue] =
|
|
1831
|
+
const [value, setValue] = e.useState(props.defaultValue);
|
|
1790
1832
|
function setValueWrapper(newValue) {
|
|
1791
1833
|
setValue(newValue);
|
|
1792
1834
|
if (props.onChange) {
|
|
1793
1835
|
props.onChange(newValue);
|
|
1794
1836
|
}
|
|
1795
1837
|
}
|
|
1796
|
-
return (
|
|
1797
|
-
|
|
1798
|
-
|
|
1838
|
+
return (e.createElement(core$1.Group, { spacing: "xs", grow: true, noWrap: true },
|
|
1839
|
+
e.createElement(DateTimeInput, { name: props.name + '.start', placeholder: "Start", defaultValue: value?.start, onChange: (newValue) => setValueWrapper({ ...value, start: newValue }) }),
|
|
1840
|
+
e.createElement(DateTimeInput, { name: props.name + '.end', placeholder: "End", defaultValue: value?.end, onChange: (newValue) => setValueWrapper({ ...value, end: newValue }) })));
|
|
1799
1841
|
}
|
|
1800
1842
|
|
|
1801
1843
|
function QuantityInput(props) {
|
|
1802
|
-
const [value, setValue] =
|
|
1844
|
+
const [value, setValue] = e.useState(props.defaultValue);
|
|
1803
1845
|
function setValueWrapper(newValue) {
|
|
1804
1846
|
setValue(newValue);
|
|
1805
1847
|
if (props.onChange) {
|
|
1806
1848
|
props.onChange(newValue);
|
|
1807
1849
|
}
|
|
1808
1850
|
}
|
|
1809
|
-
return (
|
|
1810
|
-
|
|
1851
|
+
return (e.createElement(core$1.Group, { spacing: "xs", grow: true, noWrap: true },
|
|
1852
|
+
e.createElement(core$1.NativeSelect, { style: { width: 80 }, "data-testid": props.name + '-comparator', defaultValue: value?.comparator, data: ['', '<', '<=', '>=', '>'], onChange: (e) => setValueWrapper({
|
|
1811
1853
|
...value,
|
|
1812
1854
|
comparator: e.currentTarget.value,
|
|
1813
1855
|
}) }),
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1856
|
+
e.createElement(core$1.TextInput, { id: props.name, name: props.name, "data-testid": props.name + '-value', type: "number", placeholder: "Value", defaultValue: value?.value, step: "any", onWheel: (e) => {
|
|
1857
|
+
if (props.disableWheel) {
|
|
1858
|
+
e.currentTarget.blur();
|
|
1859
|
+
}
|
|
1860
|
+
}, onChange: (e) => {
|
|
1861
|
+
setValueWrapper({
|
|
1862
|
+
...value,
|
|
1863
|
+
value: tryParseNumber(e.currentTarget.value),
|
|
1864
|
+
});
|
|
1865
|
+
} }),
|
|
1866
|
+
e.createElement(core$1.TextInput, { placeholder: "Unit", "data-testid": props.name + '-unit', defaultValue: value?.unit, onChange: (e) => setValueWrapper({
|
|
1819
1867
|
...value,
|
|
1820
1868
|
unit: e.currentTarget.value,
|
|
1821
1869
|
}) })));
|
|
@@ -1834,19 +1882,19 @@
|
|
|
1834
1882
|
* @returns Range input element.
|
|
1835
1883
|
*/
|
|
1836
1884
|
function RangeInput(props) {
|
|
1837
|
-
const [value, setValue] =
|
|
1885
|
+
const [value, setValue] = e.useState(props.defaultValue);
|
|
1838
1886
|
function setValueWrapper(newValue) {
|
|
1839
1887
|
setValue(newValue);
|
|
1840
1888
|
if (props.onChange) {
|
|
1841
1889
|
props.onChange(newValue);
|
|
1842
1890
|
}
|
|
1843
1891
|
}
|
|
1844
|
-
return (
|
|
1845
|
-
|
|
1892
|
+
return (e.createElement(core$1.Group, { spacing: "xs", grow: true, noWrap: true },
|
|
1893
|
+
e.createElement(QuantityInput, { name: props.name + '-low', defaultValue: value?.low, onChange: (v) => setValueWrapper({
|
|
1846
1894
|
...value,
|
|
1847
1895
|
low: v,
|
|
1848
1896
|
}) }),
|
|
1849
|
-
|
|
1897
|
+
e.createElement(QuantityInput, { name: props.name + '-high', defaultValue: value?.high, onChange: (v) => setValueWrapper({
|
|
1850
1898
|
...value,
|
|
1851
1899
|
high: v,
|
|
1852
1900
|
}) })));
|
|
@@ -1859,19 +1907,19 @@
|
|
|
1859
1907
|
* @returns Ratio input element.
|
|
1860
1908
|
*/
|
|
1861
1909
|
function RatioInput(props) {
|
|
1862
|
-
const [value, setValue] =
|
|
1910
|
+
const [value, setValue] = e.useState(props.defaultValue);
|
|
1863
1911
|
function setValueWrapper(newValue) {
|
|
1864
1912
|
setValue(newValue);
|
|
1865
1913
|
if (props.onChange) {
|
|
1866
1914
|
props.onChange(newValue);
|
|
1867
1915
|
}
|
|
1868
1916
|
}
|
|
1869
|
-
return (
|
|
1870
|
-
|
|
1917
|
+
return (e.createElement(core$1.Group, { spacing: "xs", grow: true, noWrap: true },
|
|
1918
|
+
e.createElement(QuantityInput, { name: props.name + '-numerator', defaultValue: value?.numerator, onChange: (v) => setValueWrapper({
|
|
1871
1919
|
...value,
|
|
1872
1920
|
numerator: v,
|
|
1873
1921
|
}) }),
|
|
1874
|
-
|
|
1922
|
+
e.createElement(QuantityInput, { name: props.name + '-denominator', defaultValue: value?.denominator, onChange: (v) => setValueWrapper({
|
|
1875
1923
|
...value,
|
|
1876
1924
|
denominator: v,
|
|
1877
1925
|
}) })));
|
|
@@ -1886,10 +1934,10 @@
|
|
|
1886
1934
|
delete avatarProps.value;
|
|
1887
1935
|
delete avatarProps.link;
|
|
1888
1936
|
if (props.link) {
|
|
1889
|
-
return (
|
|
1890
|
-
|
|
1937
|
+
return (e.createElement(MedplumLink, { to: resource },
|
|
1938
|
+
e.createElement(core$1.Avatar, { src: imageUrl, alt: text, radius: radius, ...avatarProps })));
|
|
1891
1939
|
}
|
|
1892
|
-
return
|
|
1940
|
+
return e.createElement(core$1.Avatar, { src: imageUrl, alt: text, radius: radius, ...avatarProps });
|
|
1893
1941
|
}
|
|
1894
1942
|
|
|
1895
1943
|
/**
|
|
@@ -1912,10 +1960,10 @@
|
|
|
1912
1960
|
function ResourceInput(props) {
|
|
1913
1961
|
const medplum = useMedplum();
|
|
1914
1962
|
const defaultValue = useResource(props.defaultValue);
|
|
1915
|
-
const [value, setValue] =
|
|
1916
|
-
const [loading, setLoading] =
|
|
1917
|
-
const [data, setData] =
|
|
1918
|
-
|
|
1963
|
+
const [value, setValue] = e.useState(defaultValue ? core.getDisplayString(defaultValue) : '');
|
|
1964
|
+
const [loading, setLoading] = e.useState(false);
|
|
1965
|
+
const [data, setData] = e.useState([]);
|
|
1966
|
+
e.useEffect(() => {
|
|
1919
1967
|
if (defaultValue) {
|
|
1920
1968
|
setValue(core.getDisplayString(defaultValue));
|
|
1921
1969
|
}
|
|
@@ -1942,25 +1990,25 @@
|
|
|
1942
1990
|
props.onChange(item.resource);
|
|
1943
1991
|
}
|
|
1944
1992
|
}
|
|
1945
|
-
return (
|
|
1993
|
+
return (e.createElement(core$1.Autocomplete, { itemComponent: ItemComponent, value: value, data: data, placeholder: props.placeholder, onFocus: () => loadValues(value), onChange: handleChange, onItemSubmit: handleSelect, rightSection: loading ? e.createElement(core$1.Loader, { size: 16 }) : null }));
|
|
1946
1994
|
}
|
|
1947
|
-
const ItemComponent =
|
|
1948
|
-
return (
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1995
|
+
const ItemComponent = e.forwardRef(({ value, resource, ...others }, ref) => {
|
|
1996
|
+
return (e.createElement("div", { ref: ref, ...others },
|
|
1997
|
+
e.createElement(core$1.Group, { noWrap: true },
|
|
1998
|
+
e.createElement(ResourceAvatar, { value: resource }),
|
|
1999
|
+
e.createElement("div", null,
|
|
2000
|
+
e.createElement(core$1.Text, null, value),
|
|
2001
|
+
e.createElement(core$1.Text, { size: "xs", color: "dimmed" }, resource.birthDate)))));
|
|
1954
2002
|
});
|
|
1955
2003
|
|
|
1956
2004
|
function ReferenceInput(props) {
|
|
1957
2005
|
const targetTypes = getTargetTypes$1(props.targetTypes);
|
|
1958
2006
|
const initialResourceType = getInitialResourceType(props.defaultValue, targetTypes);
|
|
1959
|
-
const [value, setValue] =
|
|
1960
|
-
const [resourceType, setResourceType] =
|
|
1961
|
-
const valueRef =
|
|
2007
|
+
const [value, setValue] = e.useState(props.defaultValue);
|
|
2008
|
+
const [resourceType, setResourceType] = e.useState(initialResourceType);
|
|
2009
|
+
const valueRef = e.useRef();
|
|
1962
2010
|
valueRef.current = value;
|
|
1963
|
-
const resourceTypeRef =
|
|
2011
|
+
const resourceTypeRef = e.useRef();
|
|
1964
2012
|
resourceTypeRef.current = resourceType;
|
|
1965
2013
|
function setValueHelper(newValue) {
|
|
1966
2014
|
setValue(newValue);
|
|
@@ -1968,9 +2016,9 @@
|
|
|
1968
2016
|
props.onChange(newValue);
|
|
1969
2017
|
}
|
|
1970
2018
|
}
|
|
1971
|
-
return (
|
|
1972
|
-
targetTypes ? (
|
|
1973
|
-
|
|
2019
|
+
return (e.createElement(core$1.Group, { spacing: "xs", grow: true, noWrap: true },
|
|
2020
|
+
targetTypes ? (e.createElement(core$1.NativeSelect, { "data-testid": "reference-input-resource-type-select", defaultValue: resourceType, onChange: (e) => setResourceType(e.currentTarget.value), data: targetTypes })) : (e.createElement(core$1.TextInput, { "data-testid": "reference-input-resource-type-input", defaultValue: resourceType, onChange: (e) => setResourceType(e.currentTarget.value) })),
|
|
2021
|
+
e.createElement(ResourceInput, { resourceType: resourceType, name: props.name + '-id', placeholder: props.placeholder, defaultValue: value, onChange: (item) => {
|
|
1974
2022
|
setValueHelper(item ? core.createReference(item) : undefined);
|
|
1975
2023
|
} })));
|
|
1976
2024
|
}
|
|
@@ -1992,8 +2040,8 @@
|
|
|
1992
2040
|
}
|
|
1993
2041
|
|
|
1994
2042
|
function ResourceArrayInput(props) {
|
|
1995
|
-
const [values, setValues] =
|
|
1996
|
-
const valuesRef =
|
|
2043
|
+
const [values, setValues] = e.useState(props.defaultValue && Array.isArray(props.defaultValue) ? props.defaultValue : []);
|
|
2044
|
+
const valuesRef = e.useRef();
|
|
1997
2045
|
valuesRef.current = values;
|
|
1998
2046
|
function setValuesWrapper(newValues) {
|
|
1999
2047
|
setValues(newValues);
|
|
@@ -2001,49 +2049,49 @@
|
|
|
2001
2049
|
props.onChange(newValues);
|
|
2002
2050
|
}
|
|
2003
2051
|
}
|
|
2004
|
-
return (
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
values.map((v, index) => (
|
|
2010
|
-
|
|
2011
|
-
|
|
2052
|
+
return (e.createElement("table", { style: { width: '100%', borderCollapse: 'collapse' } },
|
|
2053
|
+
e.createElement("colgroup", null,
|
|
2054
|
+
e.createElement("col", { width: "97%" }),
|
|
2055
|
+
e.createElement("col", { width: "3%" })),
|
|
2056
|
+
e.createElement("tbody", null,
|
|
2057
|
+
values.map((v, index) => (e.createElement("tr", { key: `${index}-${values.length}` },
|
|
2058
|
+
e.createElement("td", null,
|
|
2059
|
+
e.createElement(ResourcePropertyInput, { arrayElement: true, property: props.property, name: props.name + '.' + index, defaultValue: v, onChange: (newValue) => {
|
|
2012
2060
|
const copy = [...valuesRef.current];
|
|
2013
2061
|
copy[index] = newValue;
|
|
2014
2062
|
setValuesWrapper(copy);
|
|
2015
2063
|
} })),
|
|
2016
|
-
|
|
2017
|
-
|
|
2064
|
+
e.createElement("td", { style: { textAlign: 'right' } },
|
|
2065
|
+
e.createElement(core$1.ActionIcon, { title: "Remove", size: "sm", onClick: (e) => {
|
|
2018
2066
|
killEvent(e);
|
|
2019
2067
|
const copy = [...valuesRef.current];
|
|
2020
2068
|
copy.splice(index, 1);
|
|
2021
2069
|
setValuesWrapper(copy);
|
|
2022
2070
|
} },
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2071
|
+
e.createElement(IP, null)))))),
|
|
2072
|
+
e.createElement("tr", null,
|
|
2073
|
+
e.createElement("td", null),
|
|
2074
|
+
e.createElement("td", { style: { textAlign: 'right' } },
|
|
2075
|
+
e.createElement(core$1.ActionIcon, { title: "Add", size: "sm", color: "green", onClick: (e) => {
|
|
2028
2076
|
killEvent(e);
|
|
2029
2077
|
const copy = [...valuesRef.current];
|
|
2030
2078
|
copy.push(undefined);
|
|
2031
2079
|
setValuesWrapper(copy);
|
|
2032
2080
|
} },
|
|
2033
|
-
|
|
2081
|
+
e.createElement(iS, null)))))));
|
|
2034
2082
|
}
|
|
2035
2083
|
|
|
2036
2084
|
const daysOfWeek = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
|
|
2037
2085
|
function TimingInput(props) {
|
|
2038
|
-
const [value, setValue] =
|
|
2039
|
-
const [open, setOpen] =
|
|
2040
|
-
const valueRef =
|
|
2086
|
+
const [value, setValue] = e.useState(props.defaultValue || {});
|
|
2087
|
+
const [open, setOpen] = e.useState(false);
|
|
2088
|
+
const valueRef = e.useRef();
|
|
2041
2089
|
valueRef.current = value;
|
|
2042
|
-
return (
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2090
|
+
return (e.createElement(e.Fragment, null,
|
|
2091
|
+
e.createElement(core$1.Group, { spacing: "xs", grow: true, noWrap: true },
|
|
2092
|
+
e.createElement("span", null, core.formatTiming(valueRef.current) || 'No repeat'),
|
|
2093
|
+
e.createElement(core$1.Button, { onClick: () => setOpen(true) }, "Edit")),
|
|
2094
|
+
e.createElement(TimingEditorDialog, { visible: open, defaultValue: valueRef.current, onOk: (newValue) => {
|
|
2047
2095
|
if (props.onChange) {
|
|
2048
2096
|
props.onChange(newValue);
|
|
2049
2097
|
}
|
|
@@ -2052,8 +2100,8 @@
|
|
|
2052
2100
|
}, onCancel: () => setOpen(false) })));
|
|
2053
2101
|
}
|
|
2054
2102
|
function TimingEditorDialog(props) {
|
|
2055
|
-
const [value, setValue] =
|
|
2056
|
-
const valueRef =
|
|
2103
|
+
const [value, setValue] = e.useState(props.defaultValue || {});
|
|
2104
|
+
const valueRef = e.useRef();
|
|
2057
2105
|
valueRef.current = value;
|
|
2058
2106
|
function setStart(newStart) {
|
|
2059
2107
|
setValue({ ...valueRef.current, event: [newStart] });
|
|
@@ -2087,24 +2135,24 @@
|
|
|
2087
2135
|
setRepeat({ ...valueRef.current?.repeat, dayOfWeek: existing.filter((d) => d !== day) });
|
|
2088
2136
|
}
|
|
2089
2137
|
}
|
|
2090
|
-
return (
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2138
|
+
return (e.createElement(core$1.Modal, { title: "Timing", closeButtonLabel: "Close", opened: props.visible, onClose: () => props.onCancel() },
|
|
2139
|
+
e.createElement("div", { style: { padding: '5px 20px', textAlign: 'left' } },
|
|
2140
|
+
e.createElement(FormSection, { title: "Starts on", htmlFor: 'timing-dialog-start' },
|
|
2141
|
+
e.createElement(DateTimeInput, { name: 'timing-dialog-start', onChange: (newValue) => setStart(newValue) })),
|
|
2142
|
+
e.createElement(FormSection, { title: "Repeat every", htmlFor: 'timing-dialog-period' },
|
|
2143
|
+
e.createElement(core$1.Group, { spacing: "xs", grow: true, noWrap: true },
|
|
2144
|
+
e.createElement(core$1.TextInput, { type: "number", step: 1, id: "timing-dialog-period", name: "timing-dialog-period", defaultValue: value?.repeat?.period, onChange: (e) => setPeriod(parseInt(e.currentTarget.value)) }),
|
|
2145
|
+
e.createElement(core$1.NativeSelect, { id: "timing-dialog-periodUnit", name: "timing-dialog-periodUnit", defaultValue: value?.repeat?.periodUnit, onChange: (e) => setPeriodUnit(e.currentTarget.value), data: [
|
|
2098
2146
|
{ label: 'day', value: 'd' },
|
|
2099
2147
|
{ label: 'week', value: 'wk' },
|
|
2100
2148
|
{ label: 'month', value: 'mo' },
|
|
2101
2149
|
{ label: 'year', value: 'a' },
|
|
2102
2150
|
] }))),
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2151
|
+
e.createElement(FormSection, { title: "Repeat on" },
|
|
2152
|
+
e.createElement(core$1.Group, { spacing: "xs", grow: true, noWrap: true }, daysOfWeek.map((day) => (e.createElement(e.Fragment, { key: day },
|
|
2153
|
+
e.createElement("label", { htmlFor: 'timing-dialog-repeat-' + day }, day.charAt(0).toUpperCase()),
|
|
2154
|
+
e.createElement(core$1.Checkbox, { id: 'timing-dialog-repeat-' + day, name: 'timing-dialog-repeat-' + day, onChange: (e) => setDayOfWeek(day, e.currentTarget.checked) }))))))),
|
|
2155
|
+
e.createElement(core$1.Button, { onClick: () => props.onOk(value) }, "OK")));
|
|
2108
2156
|
}
|
|
2109
2157
|
|
|
2110
2158
|
function ResourcePropertyInput(props) {
|
|
@@ -2114,16 +2162,16 @@
|
|
|
2114
2162
|
const value = props.defaultValue;
|
|
2115
2163
|
if (property.max === '*' && !props.arrayElement) {
|
|
2116
2164
|
if (propertyType === 'Attachment') {
|
|
2117
|
-
return
|
|
2165
|
+
return e.createElement(AttachmentArrayInput, { name: name, defaultValue: value, onChange: props.onChange });
|
|
2118
2166
|
}
|
|
2119
|
-
return
|
|
2167
|
+
return e.createElement(ResourceArrayInput, { property: property, name: name, defaultValue: value, onChange: props.onChange });
|
|
2120
2168
|
}
|
|
2121
2169
|
const propertyTypes = property.type;
|
|
2122
2170
|
if (propertyTypes.length > 1) {
|
|
2123
|
-
return
|
|
2171
|
+
return e.createElement(ElementDefinitionInputSelector, { elementDefinitionTypes: propertyTypes, ...props });
|
|
2124
2172
|
}
|
|
2125
2173
|
else {
|
|
2126
|
-
return
|
|
2174
|
+
return e.createElement(ElementDefinitionTypeInput, { elementDefinitionType: propertyTypes[0], ...props });
|
|
2127
2175
|
}
|
|
2128
2176
|
}
|
|
2129
2177
|
function ElementDefinitionInputSelector(props) {
|
|
@@ -2135,15 +2183,15 @@
|
|
|
2135
2183
|
if (!initialPropertyType) {
|
|
2136
2184
|
initialPropertyType = propertyTypes[0];
|
|
2137
2185
|
}
|
|
2138
|
-
const [selectedType, setSelectedType] =
|
|
2139
|
-
return (
|
|
2140
|
-
|
|
2186
|
+
const [selectedType, setSelectedType] = e.useState(initialPropertyType);
|
|
2187
|
+
return (e.createElement(core$1.Group, { spacing: "xs", grow: true, noWrap: true },
|
|
2188
|
+
e.createElement(core$1.NativeSelect, { style: { width: '200px' }, defaultValue: selectedType?.code, onChange: (e) => {
|
|
2141
2189
|
setSelectedType(propertyTypes.find((type) => type.code === e.currentTarget.value));
|
|
2142
2190
|
}, data: propertyTypes.map((type) => ({
|
|
2143
2191
|
value: type.code,
|
|
2144
2192
|
label: type.code,
|
|
2145
2193
|
})) }),
|
|
2146
|
-
|
|
2194
|
+
e.createElement(ElementDefinitionTypeInput, { ...props, elementDefinitionType: selectedType, onChange: (newValue) => {
|
|
2147
2195
|
if (props.onChange) {
|
|
2148
2196
|
props.onChange(newValue, props.name.replace('[x]', core.capitalize(selectedType.code)));
|
|
2149
2197
|
}
|
|
@@ -2163,39 +2211,39 @@
|
|
|
2163
2211
|
case core.PropertyType.time:
|
|
2164
2212
|
case core.PropertyType.uri:
|
|
2165
2213
|
case core.PropertyType.url:
|
|
2166
|
-
return (
|
|
2214
|
+
return (e.createElement(core$1.TextInput, { id: name, name: name, "data-testid": name, defaultValue: value, onChange: (e) => {
|
|
2167
2215
|
if (props.onChange) {
|
|
2168
2216
|
props.onChange(e.currentTarget.value);
|
|
2169
2217
|
}
|
|
2170
2218
|
}, error: getErrorsForInput(props.outcome, name) }));
|
|
2171
2219
|
case core.PropertyType.date:
|
|
2172
|
-
return (
|
|
2220
|
+
return (e.createElement(core$1.TextInput, { type: "date", id: name, name: name, "data-testid": name, defaultValue: value, onChange: (e) => {
|
|
2173
2221
|
if (props.onChange) {
|
|
2174
2222
|
props.onChange(e.currentTarget.value);
|
|
2175
2223
|
}
|
|
2176
2224
|
}, error: getErrorsForInput(props.outcome, name) }));
|
|
2177
2225
|
case core.PropertyType.dateTime:
|
|
2178
2226
|
case core.PropertyType.instant:
|
|
2179
|
-
return
|
|
2227
|
+
return e.createElement(DateTimeInput, { name: name, defaultValue: value, onChange: props.onChange, outcome: props.outcome });
|
|
2180
2228
|
case core.PropertyType.decimal:
|
|
2181
2229
|
case core.PropertyType.integer:
|
|
2182
2230
|
case core.PropertyType.positiveInt:
|
|
2183
2231
|
case core.PropertyType.unsignedInt:
|
|
2184
|
-
return (
|
|
2232
|
+
return (e.createElement(core$1.TextInput, { type: "number", step: propertyType === core.PropertyType.decimal ? 'any' : '1', id: name, name: name, "data-testid": name, defaultValue: value, onChange: (e) => {
|
|
2185
2233
|
if (props.onChange) {
|
|
2186
2234
|
props.onChange(e.currentTarget.valueAsNumber);
|
|
2187
2235
|
}
|
|
2188
2236
|
} }));
|
|
2189
2237
|
case core.PropertyType.code:
|
|
2190
|
-
return
|
|
2238
|
+
return e.createElement(CodeInput, { property: property, name: name, defaultValue: value, onChange: props.onChange });
|
|
2191
2239
|
case core.PropertyType.boolean:
|
|
2192
|
-
return (
|
|
2240
|
+
return (e.createElement(core$1.Checkbox, { id: name, name: name, "data-testid": name, defaultChecked: !!value, onChange: (e) => {
|
|
2193
2241
|
if (props.onChange) {
|
|
2194
2242
|
props.onChange(e.currentTarget.checked);
|
|
2195
2243
|
}
|
|
2196
2244
|
} }));
|
|
2197
2245
|
case core.PropertyType.markdown:
|
|
2198
|
-
return (
|
|
2246
|
+
return (e.createElement(core$1.Textarea, { id: name, name: name, "data-testid": name, defaultValue: value, onChange: (e) => {
|
|
2199
2247
|
if (props.onChange) {
|
|
2200
2248
|
props.onChange(e.currentTarget.value);
|
|
2201
2249
|
}
|
|
@@ -2203,45 +2251,45 @@
|
|
|
2203
2251
|
// 2.24.0.2 Complex Types
|
|
2204
2252
|
// https://www.hl7.org/fhir/datatypes.html#complex
|
|
2205
2253
|
case core.PropertyType.Address:
|
|
2206
|
-
return
|
|
2254
|
+
return e.createElement(AddressInput, { name: name, defaultValue: value, onChange: props.onChange });
|
|
2207
2255
|
case core.PropertyType.Annotation:
|
|
2208
|
-
return
|
|
2256
|
+
return e.createElement(AnnotationInput, { name: name, defaultValue: value, onChange: props.onChange });
|
|
2209
2257
|
case core.PropertyType.Attachment:
|
|
2210
|
-
return
|
|
2258
|
+
return e.createElement(AttachmentInput, { name: name, defaultValue: value, onChange: props.onChange });
|
|
2211
2259
|
case core.PropertyType.CodeableConcept:
|
|
2212
|
-
return
|
|
2260
|
+
return e.createElement(CodeableConceptInput, { property: property, name: name, defaultValue: value, onChange: props.onChange });
|
|
2213
2261
|
case core.PropertyType.Coding:
|
|
2214
|
-
return
|
|
2262
|
+
return e.createElement(CodingInput, { property: property, name: name, defaultValue: value, onChange: props.onChange });
|
|
2215
2263
|
case core.PropertyType.ContactDetail:
|
|
2216
|
-
return
|
|
2264
|
+
return e.createElement(ContactDetailInput, { name: name, defaultValue: value, onChange: props.onChange });
|
|
2217
2265
|
case core.PropertyType.ContactPoint:
|
|
2218
|
-
return
|
|
2266
|
+
return e.createElement(ContactPointInput, { name: name, defaultValue: value, onChange: props.onChange });
|
|
2219
2267
|
case core.PropertyType.Extension:
|
|
2220
|
-
return
|
|
2268
|
+
return e.createElement(ExtensionInput, { name: name, defaultValue: value, onChange: props.onChange });
|
|
2221
2269
|
case core.PropertyType.HumanName:
|
|
2222
|
-
return
|
|
2270
|
+
return e.createElement(HumanNameInput, { name: name, defaultValue: value, onChange: props.onChange });
|
|
2223
2271
|
case core.PropertyType.Identifier:
|
|
2224
|
-
return
|
|
2272
|
+
return e.createElement(IdentifierInput, { name: name, defaultValue: value, onChange: props.onChange });
|
|
2225
2273
|
case core.PropertyType.Money:
|
|
2226
|
-
return
|
|
2274
|
+
return e.createElement(MoneyInput, { name: name, defaultValue: value, onChange: props.onChange });
|
|
2227
2275
|
case core.PropertyType.Period:
|
|
2228
|
-
return
|
|
2276
|
+
return e.createElement(PeriodInput, { name: name, defaultValue: value, onChange: props.onChange });
|
|
2229
2277
|
case core.PropertyType.Duration:
|
|
2230
2278
|
case core.PropertyType.Quantity:
|
|
2231
|
-
return
|
|
2279
|
+
return e.createElement(QuantityInput, { name: name, defaultValue: value, onChange: props.onChange });
|
|
2232
2280
|
case core.PropertyType.Range:
|
|
2233
|
-
return
|
|
2281
|
+
return e.createElement(RangeInput, { name: name, defaultValue: value, onChange: props.onChange });
|
|
2234
2282
|
case core.PropertyType.Ratio:
|
|
2235
|
-
return
|
|
2283
|
+
return e.createElement(RatioInput, { name: name, defaultValue: value, onChange: props.onChange });
|
|
2236
2284
|
case core.PropertyType.Reference:
|
|
2237
|
-
return (
|
|
2285
|
+
return (e.createElement(ReferenceInput, { name: name, defaultValue: value, targetTypes: getTargetTypes(property), onChange: props.onChange }));
|
|
2238
2286
|
case core.PropertyType.Timing:
|
|
2239
|
-
return
|
|
2287
|
+
return e.createElement(TimingInput, { name: name, defaultValue: value, onChange: props.onChange });
|
|
2240
2288
|
case core.PropertyType.Dosage:
|
|
2241
2289
|
case core.PropertyType.UsageContext:
|
|
2242
|
-
return (
|
|
2290
|
+
return (e.createElement(BackboneElementInput, { typeName: propertyType, defaultValue: value, onChange: props.onChange, outcome: props.outcome }));
|
|
2243
2291
|
default:
|
|
2244
|
-
return (
|
|
2292
|
+
return (e.createElement(BackboneElementInput, { typeName: core.getElementDefinitionTypeName(property), defaultValue: value, onChange: props.onChange, outcome: props.outcome }));
|
|
2245
2293
|
}
|
|
2246
2294
|
}
|
|
2247
2295
|
function getTargetTypes(property) {
|
|
@@ -2249,7 +2297,7 @@
|
|
|
2249
2297
|
}
|
|
2250
2298
|
|
|
2251
2299
|
function BackboneElementInput(props) {
|
|
2252
|
-
const [value, setValue] =
|
|
2300
|
+
const [value, setValue] = e.useState(props.defaultValue ?? {});
|
|
2253
2301
|
function setValueWrapper(newValue) {
|
|
2254
2302
|
setValue(newValue);
|
|
2255
2303
|
if (props.onChange) {
|
|
@@ -2259,12 +2307,12 @@
|
|
|
2259
2307
|
const typeName = props.typeName;
|
|
2260
2308
|
const typeSchema = core.globalSchema.types[typeName];
|
|
2261
2309
|
if (!typeSchema) {
|
|
2262
|
-
return
|
|
2310
|
+
return e.createElement("div", null,
|
|
2263
2311
|
typeName,
|
|
2264
2312
|
"\u00A0not implemented");
|
|
2265
2313
|
}
|
|
2266
2314
|
const typedValue = { type: typeName, value };
|
|
2267
|
-
return (
|
|
2315
|
+
return (e.createElement(core$1.Stack, null, Object.entries(typeSchema.properties).map((entry) => {
|
|
2268
2316
|
const key = entry[0];
|
|
2269
2317
|
if (key === 'id' || DEFAULT_IGNORED_PROPERTIES.indexOf(key) >= 0) {
|
|
2270
2318
|
return null;
|
|
@@ -2275,19 +2323,19 @@
|
|
|
2275
2323
|
}
|
|
2276
2324
|
const [propertyValue, propertyType] = getValueAndType(typedValue, key);
|
|
2277
2325
|
if (property.type.length === 1 && property.type[0].code === 'boolean') {
|
|
2278
|
-
return (
|
|
2279
|
-
|
|
2326
|
+
return (e.createElement(CheckboxFormSection, { key: key, title: core.getPropertyDisplayName(key), description: property.definition, htmlFor: key },
|
|
2327
|
+
e.createElement(ResourcePropertyInput, { property: property, name: key, defaultValue: propertyValue, defaultPropertyType: propertyType, outcome: props.outcome, onChange: (newValue, propName) => {
|
|
2280
2328
|
setValueWrapper(setPropertyValue(value, key, propName ?? key, entry[1], newValue));
|
|
2281
2329
|
} })));
|
|
2282
2330
|
}
|
|
2283
|
-
return (
|
|
2284
|
-
|
|
2331
|
+
return (e.createElement(FormSection, { key: key, title: core.getPropertyDisplayName(key), description: property.definition, htmlFor: key, outcome: props.outcome },
|
|
2332
|
+
e.createElement(ResourcePropertyInput, { property: property, name: key, defaultValue: propertyValue, defaultPropertyType: propertyType, outcome: props.outcome, onChange: (newValue, propName) => {
|
|
2285
2333
|
setValueWrapper(setPropertyValue(value, key, propName ?? key, entry[1], newValue));
|
|
2286
2334
|
} })));
|
|
2287
2335
|
})));
|
|
2288
2336
|
}
|
|
2289
2337
|
|
|
2290
|
-
const useStyles$
|
|
2338
|
+
const useStyles$b = core$1.createStyles((theme) => ({
|
|
2291
2339
|
table: {
|
|
2292
2340
|
width: 350,
|
|
2293
2341
|
'& th': {
|
|
@@ -2332,9 +2380,9 @@
|
|
|
2332
2380
|
return date.toLocaleString('default', { month: 'long' }) + ' ' + date.getFullYear();
|
|
2333
2381
|
}
|
|
2334
2382
|
function CalendarInput(props) {
|
|
2335
|
-
const { classes } = useStyles$
|
|
2383
|
+
const { classes } = useStyles$b();
|
|
2336
2384
|
const { onChangeMonth, onClick } = props;
|
|
2337
|
-
const [month, setMonth] =
|
|
2385
|
+
const [month, setMonth] = e.useState(getStartMonth);
|
|
2338
2386
|
function moveMonth(delta) {
|
|
2339
2387
|
setMonth((currMonth) => {
|
|
2340
2388
|
const newMonth = new Date(currMonth.getTime());
|
|
@@ -2343,24 +2391,24 @@
|
|
|
2343
2391
|
return newMonth;
|
|
2344
2392
|
});
|
|
2345
2393
|
}
|
|
2346
|
-
const grid =
|
|
2347
|
-
return (
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2394
|
+
const grid = e.useMemo(() => buildGrid(month, props.slots), [month, props.slots]);
|
|
2395
|
+
return (e.createElement("div", null,
|
|
2396
|
+
e.createElement(core$1.Group, { position: "apart", spacing: "xs", grow: true, noWrap: true },
|
|
2397
|
+
e.createElement("p", { style: { flex: 1 } }, getMonthString(month)),
|
|
2398
|
+
e.createElement(core$1.Group, { position: "right", spacing: "xs" },
|
|
2399
|
+
e.createElement(core$1.Button, { variant: "outline", "aria-label": "Previous month", onClick: () => moveMonth(-1) }, "<"),
|
|
2400
|
+
e.createElement(core$1.Button, { variant: "outline", "aria-label": "Next month", onClick: () => moveMonth(1) }, ">"))),
|
|
2401
|
+
e.createElement("table", { className: classes.table },
|
|
2402
|
+
e.createElement("thead", null,
|
|
2403
|
+
e.createElement("tr", null,
|
|
2404
|
+
e.createElement("th", null, "SUN"),
|
|
2405
|
+
e.createElement("th", null, "MON"),
|
|
2406
|
+
e.createElement("th", null, "TUE"),
|
|
2407
|
+
e.createElement("th", null, "WED"),
|
|
2408
|
+
e.createElement("th", null, "THU"),
|
|
2409
|
+
e.createElement("th", null, "FRI"),
|
|
2410
|
+
e.createElement("th", null, "SAT"))),
|
|
2411
|
+
e.createElement("tbody", null, grid.map((week, weekIndex) => (e.createElement("tr", { key: 'week-' + weekIndex }, week.map((day, dayIndex) => (e.createElement("td", { key: 'day-' + dayIndex }, day && (e.createElement(core$1.Button, { disabled: !day.available, onClick: () => onClick(day.date) }, day.date.getDate()))))))))))));
|
|
2364
2412
|
}
|
|
2365
2413
|
function getStartMonth() {
|
|
2366
2414
|
const result = new Date();
|
|
@@ -2415,6 +2463,19 @@
|
|
|
2415
2463
|
return false;
|
|
2416
2464
|
}
|
|
2417
2465
|
|
|
2466
|
+
const useStyles$a = core$1.createStyles((theme) => ({
|
|
2467
|
+
noteBody: { fontSize: theme.fontSizes.sm },
|
|
2468
|
+
noteCite: { fontSize: theme.fontSizes.xs, marginBlockStart: 3 },
|
|
2469
|
+
noteRoot: { padding: 5 },
|
|
2470
|
+
}));
|
|
2471
|
+
function NoteDisplay({ value }) {
|
|
2472
|
+
const { classes } = useStyles$a();
|
|
2473
|
+
if (!value) {
|
|
2474
|
+
return null;
|
|
2475
|
+
}
|
|
2476
|
+
return (e.createElement(core$1.Stack, { justify: "flex-start", spacing: "xs" }, value.map((note, index) => note.text && (e.createElement(core$1.Blockquote, { key: `note-${index}`, classNames: { cite: classes.noteCite, body: classes.noteBody, root: classes.noteRoot }, cite: note.authorReference?.display || note.authorString, icon: null }, note.text)))));
|
|
2477
|
+
}
|
|
2478
|
+
|
|
2418
2479
|
function ResourceName(props) {
|
|
2419
2480
|
const { value, link, ...rest } = props;
|
|
2420
2481
|
const resource = useResource(value);
|
|
@@ -2422,13 +2483,13 @@
|
|
|
2422
2483
|
return null;
|
|
2423
2484
|
}
|
|
2424
2485
|
const text = core.getDisplayString(resource);
|
|
2425
|
-
return link ? (
|
|
2486
|
+
return link ? (e.createElement(MedplumLink, { to: resource, ...rest }, text)) : (e.createElement(core$1.Text, { component: "span", ...rest }, text));
|
|
2426
2487
|
}
|
|
2427
2488
|
|
|
2428
2489
|
function ResourceBadge(props) {
|
|
2429
|
-
return (
|
|
2430
|
-
|
|
2431
|
-
|
|
2490
|
+
return (e.createElement(core$1.Group, { spacing: "xs" },
|
|
2491
|
+
e.createElement(ResourceAvatar, { size: 24, radius: 12, value: props.value, link: props.link }),
|
|
2492
|
+
e.createElement(ResourceName, { value: props.value, link: props.link })));
|
|
2432
2493
|
}
|
|
2433
2494
|
|
|
2434
2495
|
/*
|
|
@@ -2486,7 +2547,7 @@
|
|
|
2486
2547
|
stat: 'red',
|
|
2487
2548
|
};
|
|
2488
2549
|
function StatusBadge(props) {
|
|
2489
|
-
return
|
|
2550
|
+
return e.createElement(core$1.Badge, { color: statusToColor[props.status] }, props.status);
|
|
2490
2551
|
}
|
|
2491
2552
|
|
|
2492
2553
|
const useStyles$9 = core$1.createStyles((theme) => ({
|
|
@@ -2507,6 +2568,9 @@
|
|
|
2507
2568
|
border: `0.1px solid ${theme.colors.red[5]}`,
|
|
2508
2569
|
},
|
|
2509
2570
|
},
|
|
2571
|
+
noteBody: { fontSize: theme.fontSizes.sm },
|
|
2572
|
+
noteCite: { fontSize: theme.fontSizes.xs, marginBlockStart: 3 },
|
|
2573
|
+
noteRoot: { padding: 5 },
|
|
2510
2574
|
}));
|
|
2511
2575
|
function DiagnosticReportDisplay(props) {
|
|
2512
2576
|
const diagnosticReport = useResource(props.value);
|
|
@@ -2514,51 +2578,46 @@
|
|
|
2514
2578
|
if (!diagnosticReport) {
|
|
2515
2579
|
return null;
|
|
2516
2580
|
}
|
|
2517
|
-
|
|
2581
|
+
const specimenNotes = specimen?.note || [];
|
|
2518
2582
|
if (diagnosticReport.presentedForm && diagnosticReport.presentedForm.length > 0) {
|
|
2519
2583
|
const pf = diagnosticReport.presentedForm[0];
|
|
2520
2584
|
if (pf.contentType?.startsWith('text/plain') && pf.data) {
|
|
2521
|
-
|
|
2585
|
+
specimenNotes.push({ text: window.atob(pf.data) });
|
|
2522
2586
|
}
|
|
2523
2587
|
}
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
React.createElement(core$1.Group, { mt: "md", spacing: 30 },
|
|
2532
|
-
diagnosticReport.subject && (React.createElement("div", null,
|
|
2533
|
-
React.createElement(core$1.Text, { size: "xs", transform: "uppercase", color: "dimmed" }, "Subject"),
|
|
2534
|
-
React.createElement(core$1.Text, null,
|
|
2535
|
-
React.createElement(ResourceBadge, { value: diagnosticReport.subject, link: true })))),
|
|
2588
|
+
return (e.createElement(core$1.Stack, null,
|
|
2589
|
+
e.createElement(core$1.Title, null, "Diagnostic Report"),
|
|
2590
|
+
e.createElement(core$1.Group, { mt: "md", spacing: 30 },
|
|
2591
|
+
diagnosticReport.subject && (e.createElement("div", null,
|
|
2592
|
+
e.createElement(core$1.Text, { size: "xs", transform: "uppercase", color: "dimmed" }, "Subject"),
|
|
2593
|
+
e.createElement(core$1.Text, null,
|
|
2594
|
+
e.createElement(ResourceBadge, { value: diagnosticReport.subject, link: true })))),
|
|
2536
2595
|
diagnosticReport.resultsInterpreter &&
|
|
2537
|
-
diagnosticReport.resultsInterpreter.map((interpreter) => (
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
diagnosticReport.issued && (
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
diagnosticReport.status && (
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
diagnosticReport.result &&
|
|
2548
|
-
|
|
2596
|
+
diagnosticReport.resultsInterpreter.map((interpreter) => (e.createElement("div", { key: interpreter.reference },
|
|
2597
|
+
e.createElement(core$1.Text, { size: "xs", transform: "uppercase", color: "dimmed" }, "Interpreter"),
|
|
2598
|
+
e.createElement(core$1.Text, null,
|
|
2599
|
+
e.createElement(ResourceBadge, { value: interpreter, link: true }))))),
|
|
2600
|
+
diagnosticReport.issued && (e.createElement("div", null,
|
|
2601
|
+
e.createElement(core$1.Text, { size: "xs", transform: "uppercase", color: "dimmed" }, "Issued"),
|
|
2602
|
+
e.createElement(core$1.Text, null, core.formatDateTime(diagnosticReport.issued)))),
|
|
2603
|
+
diagnosticReport.status && (e.createElement("div", null,
|
|
2604
|
+
e.createElement(core$1.Text, { size: "xs", transform: "uppercase", color: "dimmed" }, "Status"),
|
|
2605
|
+
e.createElement(core$1.Text, null, core.capitalize(diagnosticReport.status))))),
|
|
2606
|
+
diagnosticReport.result && (e.createElement(ObservationTable, { hideObservationNotes: props.hideObservationNotes, value: diagnosticReport.result })),
|
|
2607
|
+
specimenNotes.length > 0 && e.createElement(NoteDisplay, { value: specimenNotes })));
|
|
2549
2608
|
}
|
|
2550
2609
|
function ObservationTable(props) {
|
|
2551
2610
|
const { classes } = useStyles$9();
|
|
2552
|
-
return (
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2611
|
+
return (e.createElement("table", { className: classes.table },
|
|
2612
|
+
e.createElement("thead", null,
|
|
2613
|
+
e.createElement("tr", null,
|
|
2614
|
+
e.createElement("th", null, "Test"),
|
|
2615
|
+
e.createElement("th", null, "Value"),
|
|
2616
|
+
e.createElement("th", null, "Reference Range"),
|
|
2617
|
+
e.createElement("th", null, "Interpretation"),
|
|
2618
|
+
e.createElement("th", null, "Category"),
|
|
2619
|
+
e.createElement("th", null, "Status"))),
|
|
2620
|
+
e.createElement("tbody", null, props.value?.map((observation, index) => (e.createElement(ObservationRow, { key: `obs-${index}-${observation.id}`, hideObservationNotes: props.hideObservationNotes, value: observation }))))));
|
|
2562
2621
|
}
|
|
2563
2622
|
function ObservationRow(props) {
|
|
2564
2623
|
const { classes, cx } = useStyles$9();
|
|
@@ -2566,23 +2625,28 @@
|
|
|
2566
2625
|
if (!observation) {
|
|
2567
2626
|
return null;
|
|
2568
2627
|
}
|
|
2628
|
+
const displayNotes = !props.hideObservationNotes && observation?.note;
|
|
2569
2629
|
const critical = isCritical(observation);
|
|
2570
|
-
return (
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2630
|
+
return (e.createElement(e.Fragment, null,
|
|
2631
|
+
e.createElement("tr", { className: cx({ [classes.criticalRow]: critical }) },
|
|
2632
|
+
e.createElement("td", { rowSpan: displayNotes ? 2 : 1 },
|
|
2633
|
+
e.createElement(MedplumLink, { to: observation },
|
|
2634
|
+
e.createElement(CodeableConceptDisplay, { value: observation.code }))),
|
|
2635
|
+
e.createElement("td", null,
|
|
2636
|
+
e.createElement(ObservationValueDisplay, { value: observation })),
|
|
2637
|
+
e.createElement("td", null,
|
|
2638
|
+
e.createElement(ReferenceRangeDisplay, { value: observation.referenceRange })),
|
|
2639
|
+
e.createElement("td", null, observation.interpretation && observation.interpretation.length > 0 && (e.createElement(CodeableConceptDisplay, { value: observation.interpretation[0] }))),
|
|
2640
|
+
e.createElement("td", null, observation.category && observation.category.length > 0 && (e.createElement("ul", null, observation.category.map((concept, index) => (e.createElement("li", { key: `category-${index}` },
|
|
2641
|
+
e.createElement(CodeableConceptDisplay, { value: concept }))))))),
|
|
2642
|
+
e.createElement("td", null, observation.status && e.createElement(StatusBadge, { status: observation.status }))),
|
|
2643
|
+
displayNotes && (e.createElement("tr", null,
|
|
2644
|
+
e.createElement("td", { colSpan: 5 },
|
|
2645
|
+
e.createElement(NoteDisplay, { value: observation.note }))))));
|
|
2582
2646
|
}
|
|
2583
2647
|
function ObservationValueDisplay(props) {
|
|
2584
2648
|
const obs = props.value;
|
|
2585
|
-
return
|
|
2649
|
+
return e.createElement(e.Fragment, null, core.formatObservationValue(obs));
|
|
2586
2650
|
}
|
|
2587
2651
|
function ReferenceRangeDisplay(props) {
|
|
2588
2652
|
const range = props.value && props.value.length > 0 && props.value[0];
|
|
@@ -2590,9 +2654,9 @@
|
|
|
2590
2654
|
return null;
|
|
2591
2655
|
}
|
|
2592
2656
|
if (range.text) {
|
|
2593
|
-
return
|
|
2657
|
+
return e.createElement(e.Fragment, null, range.text);
|
|
2594
2658
|
}
|
|
2595
|
-
return
|
|
2659
|
+
return e.createElement(RangeDisplay, { value: range });
|
|
2596
2660
|
}
|
|
2597
2661
|
/**
|
|
2598
2662
|
* Returns true if the observation is critical.
|
|
@@ -2628,8 +2692,8 @@
|
|
|
2628
2692
|
function ResourceDiffTable(props) {
|
|
2629
2693
|
const { classes } = useStyles$8();
|
|
2630
2694
|
const medplum = useMedplum();
|
|
2631
|
-
const [schema, setSchema] =
|
|
2632
|
-
|
|
2695
|
+
const [schema, setSchema] = e.useState();
|
|
2696
|
+
e.useEffect(() => {
|
|
2633
2697
|
medplum.requestSchema(props.original.resourceType).then(setSchema).catch(console.log);
|
|
2634
2698
|
}, [medplum, props.original.resourceType]);
|
|
2635
2699
|
if (!schema) {
|
|
@@ -2639,17 +2703,17 @@
|
|
|
2639
2703
|
if (!typeSchema) {
|
|
2640
2704
|
return null;
|
|
2641
2705
|
}
|
|
2642
|
-
return (
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2706
|
+
return (e.createElement("table", { className: classes.root },
|
|
2707
|
+
e.createElement("colgroup", null,
|
|
2708
|
+
e.createElement("col", { style: { width: '30%' } }),
|
|
2709
|
+
e.createElement("col", { style: { width: '35%' } }),
|
|
2710
|
+
e.createElement("col", { style: { width: '35%' } })),
|
|
2711
|
+
e.createElement("thead", null,
|
|
2712
|
+
e.createElement("tr", null,
|
|
2713
|
+
e.createElement("th", null, "Property"),
|
|
2714
|
+
e.createElement("th", null, "Before"),
|
|
2715
|
+
e.createElement("th", null, "After"))),
|
|
2716
|
+
e.createElement("tbody", null, Object.entries(typeSchema.properties).map((entry) => {
|
|
2653
2717
|
const key = entry[0];
|
|
2654
2718
|
if (key === 'id' || key === 'meta') {
|
|
2655
2719
|
return null;
|
|
@@ -2663,12 +2727,12 @@
|
|
|
2663
2727
|
if (core.stringify(originalPropertyValue) === core.stringify(revisedPropertyValue)) {
|
|
2664
2728
|
return null;
|
|
2665
2729
|
}
|
|
2666
|
-
return (
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2730
|
+
return (e.createElement("tr", { key: key },
|
|
2731
|
+
e.createElement("td", null, core.getPropertyDisplayName(key)),
|
|
2732
|
+
e.createElement("td", { className: classes.removed },
|
|
2733
|
+
e.createElement(ResourcePropertyDisplay, { property: property, propertyType: originalPropertyType, value: originalPropertyValue, ignoreMissingValues: true })),
|
|
2734
|
+
e.createElement("td", { className: classes.added },
|
|
2735
|
+
e.createElement(ResourcePropertyDisplay, { property: property, propertyType: revisedPropertyType, value: revisedPropertyValue, ignoreMissingValues: true }))));
|
|
2672
2736
|
}))));
|
|
2673
2737
|
}
|
|
2674
2738
|
function isEmpty(value) {
|
|
@@ -2680,8 +2744,8 @@
|
|
|
2680
2744
|
function ResourceTable(props) {
|
|
2681
2745
|
const medplum = useMedplum();
|
|
2682
2746
|
const value = useResource(props.value);
|
|
2683
|
-
const [schema, setSchema] =
|
|
2684
|
-
|
|
2747
|
+
const [schema, setSchema] = e.useState();
|
|
2748
|
+
e.useEffect(() => {
|
|
2685
2749
|
if (value) {
|
|
2686
2750
|
medplum.requestSchema(value.resourceType).then(setSchema).catch(console.log);
|
|
2687
2751
|
}
|
|
@@ -2689,14 +2753,14 @@
|
|
|
2689
2753
|
if (!schema || !value) {
|
|
2690
2754
|
return null;
|
|
2691
2755
|
}
|
|
2692
|
-
return (
|
|
2756
|
+
return (e.createElement(BackboneElementDisplay, { value: { type: value.resourceType, value }, ignoreMissingValues: props.ignoreMissingValues }));
|
|
2693
2757
|
}
|
|
2694
2758
|
|
|
2695
2759
|
/**
|
|
2696
2760
|
* ErrorBoundary is a React component that handles errors in its child components.
|
|
2697
2761
|
* See: https://reactjs.org/docs/error-boundaries.html
|
|
2698
2762
|
*/
|
|
2699
|
-
class ErrorBoundary extends
|
|
2763
|
+
class ErrorBoundary extends e.Component {
|
|
2700
2764
|
constructor(props) {
|
|
2701
2765
|
super(props);
|
|
2702
2766
|
this.state = {};
|
|
@@ -2709,36 +2773,36 @@
|
|
|
2709
2773
|
}
|
|
2710
2774
|
render() {
|
|
2711
2775
|
if (this.state.error) {
|
|
2712
|
-
return (
|
|
2776
|
+
return (e.createElement(core$1.Alert, { icon: e.createElement(We, { size: 16 }), title: "Something went wrong", color: "red" }, core.normalizeErrorString(this.state.error)));
|
|
2713
2777
|
}
|
|
2714
2778
|
return this.props.children;
|
|
2715
2779
|
}
|
|
2716
2780
|
}
|
|
2717
2781
|
|
|
2718
2782
|
function Timeline(props) {
|
|
2719
|
-
return
|
|
2783
|
+
return e.createElement(Container, null, props.children);
|
|
2720
2784
|
}
|
|
2721
2785
|
function TimelineItem(props) {
|
|
2722
2786
|
const { resource, profile, padding, popupMenuItems, ...others } = props;
|
|
2723
2787
|
const author = profile ?? resource.meta?.author;
|
|
2724
|
-
return (
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
popupMenuItems && (
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2788
|
+
return (e.createElement(Panel, { "data-testid": "timeline-item", fill: true, ...others },
|
|
2789
|
+
e.createElement(core$1.Group, { position: "apart", spacing: 8, mx: "xs", my: "sm" },
|
|
2790
|
+
e.createElement(ResourceAvatar, { value: author, link: true, size: "md" }),
|
|
2791
|
+
e.createElement("div", { style: { flex: 1 } },
|
|
2792
|
+
e.createElement(core$1.Text, { size: "sm" },
|
|
2793
|
+
e.createElement(ResourceName, { color: "dark", weight: 500, value: author, link: true })),
|
|
2794
|
+
e.createElement(core$1.Text, { size: "xs" },
|
|
2795
|
+
e.createElement(MedplumLink, { color: "dimmed", to: props.resource }, core.formatDateTime(props.resource.meta?.lastUpdated)),
|
|
2796
|
+
e.createElement(core$1.Text, { component: "span", color: "dimmed", mx: 8 }, "\u00B7"),
|
|
2797
|
+
e.createElement(MedplumLink, { color: "dimmed", to: props.resource }, props.resource.resourceType))),
|
|
2798
|
+
popupMenuItems && (e.createElement(core$1.Menu, { position: "bottom-end", shadow: "md", width: 200 },
|
|
2799
|
+
e.createElement(core$1.Menu.Target, null,
|
|
2800
|
+
e.createElement(core$1.ActionIcon, { radius: "xl", "aria-label": `Actions for ${core.getReferenceString(props.resource)}` },
|
|
2801
|
+
e.createElement(BX, null))),
|
|
2738
2802
|
popupMenuItems))),
|
|
2739
|
-
|
|
2740
|
-
padding &&
|
|
2741
|
-
!padding &&
|
|
2803
|
+
e.createElement(ErrorBoundary, null,
|
|
2804
|
+
padding && e.createElement("div", { style: { padding: '0 16px 16px 16px' } }, props.children),
|
|
2805
|
+
!padding && e.createElement(e.Fragment, null, props.children))));
|
|
2742
2806
|
}
|
|
2743
2807
|
|
|
2744
2808
|
/**
|
|
@@ -2792,54 +2856,49 @@
|
|
|
2792
2856
|
},
|
|
2793
2857
|
}));
|
|
2794
2858
|
function ResourceTimeline(props) {
|
|
2795
|
-
const navigate = reactRouterDom.useNavigate();
|
|
2796
2859
|
const medplum = useMedplum();
|
|
2860
|
+
const navigate = useMedplumNavigate();
|
|
2797
2861
|
const sender = medplum.getProfile();
|
|
2798
|
-
const inputRef =
|
|
2862
|
+
const inputRef = e.useRef(null);
|
|
2799
2863
|
const resource = useResource(props.value);
|
|
2800
|
-
const [history, setHistory] =
|
|
2801
|
-
const [items, setItems] =
|
|
2802
|
-
const
|
|
2803
|
-
const itemsRef =
|
|
2864
|
+
const [history, setHistory] = e.useState();
|
|
2865
|
+
const [items, setItems] = e.useState([]);
|
|
2866
|
+
const loadTimelineResources = props.loadTimelineResources;
|
|
2867
|
+
const itemsRef = e.useRef(items);
|
|
2804
2868
|
itemsRef.current = items;
|
|
2805
|
-
const loadTimeline =
|
|
2869
|
+
const loadTimeline = e.useCallback(() => {
|
|
2806
2870
|
if (!resource) {
|
|
2807
2871
|
setItems([]);
|
|
2808
2872
|
setHistory({});
|
|
2809
2873
|
return;
|
|
2810
2874
|
}
|
|
2811
|
-
medplum
|
|
2812
|
-
}, [medplum, resource,
|
|
2813
|
-
|
|
2875
|
+
loadTimelineResources(medplum, resource).then(handleBatchResponse).catch(console.log);
|
|
2876
|
+
}, [medplum, resource, loadTimelineResources]);
|
|
2877
|
+
e.useEffect(() => {
|
|
2814
2878
|
loadTimeline();
|
|
2815
2879
|
}, [loadTimeline]);
|
|
2816
2880
|
/**
|
|
2817
2881
|
* Handles a batch request response.
|
|
2818
2882
|
* @param batchResponse The batch response.
|
|
2819
2883
|
*/
|
|
2820
|
-
function handleBatchResponse(
|
|
2884
|
+
function handleBatchResponse(bundles) {
|
|
2821
2885
|
const newItems = [];
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
for (const entry of bundle.entry) {
|
|
2834
|
-
if (entry.resource) {
|
|
2835
|
-
newItems.push(entry.resource);
|
|
2836
|
-
}
|
|
2837
|
-
}
|
|
2886
|
+
for (const bundle of bundles) {
|
|
2887
|
+
if (!bundle) {
|
|
2888
|
+
// User may not have access to all resource types
|
|
2889
|
+
continue;
|
|
2890
|
+
}
|
|
2891
|
+
if (bundle.type === 'history') {
|
|
2892
|
+
setHistory(bundle);
|
|
2893
|
+
}
|
|
2894
|
+
if (bundle.entry) {
|
|
2895
|
+
for (const entry of bundle.entry) {
|
|
2896
|
+
newItems.push(entry.resource);
|
|
2838
2897
|
}
|
|
2839
2898
|
}
|
|
2840
|
-
sortByDateAndPriority(newItems);
|
|
2841
|
-
newItems.reverse();
|
|
2842
2899
|
}
|
|
2900
|
+
sortByDateAndPriority(newItems);
|
|
2901
|
+
newItems.reverse();
|
|
2843
2902
|
setItems(newItems);
|
|
2844
2903
|
}
|
|
2845
2904
|
/**
|
|
@@ -2885,7 +2944,7 @@
|
|
|
2885
2944
|
color: 'teal',
|
|
2886
2945
|
title: 'Upload complete',
|
|
2887
2946
|
message: '',
|
|
2888
|
-
icon:
|
|
2947
|
+
icon: e.createElement(DW, { size: 16 }),
|
|
2889
2948
|
autoClose: 2000,
|
|
2890
2949
|
}))
|
|
2891
2950
|
.catch((reason) => notifications.updateNotification({
|
|
@@ -2893,7 +2952,7 @@
|
|
|
2893
2952
|
color: 'red',
|
|
2894
2953
|
title: 'Upload error',
|
|
2895
2954
|
message: core.normalizeErrorString(reason),
|
|
2896
|
-
icon:
|
|
2955
|
+
icon: e.createElement(B$, { size: 16 }),
|
|
2897
2956
|
autoClose: 2000,
|
|
2898
2957
|
}));
|
|
2899
2958
|
}
|
|
@@ -2939,12 +2998,12 @@
|
|
|
2939
2998
|
});
|
|
2940
2999
|
}
|
|
2941
3000
|
if (!resource) {
|
|
2942
|
-
return (
|
|
2943
|
-
|
|
3001
|
+
return (e.createElement(core$1.Center, { style: { width: '100%', height: '100%' } },
|
|
3002
|
+
e.createElement(core$1.Loader, null)));
|
|
2944
3003
|
}
|
|
2945
|
-
return (
|
|
2946
|
-
props.createCommunication && (
|
|
2947
|
-
|
|
3004
|
+
return (e.createElement(Timeline, null,
|
|
3005
|
+
props.createCommunication && (e.createElement(Panel, null,
|
|
3006
|
+
e.createElement(Form, { testid: "timeline-form", onSubmit: (formData) => {
|
|
2948
3007
|
createComment(formData.text);
|
|
2949
3008
|
const input = inputRef.current;
|
|
2950
3009
|
if (input) {
|
|
@@ -2952,55 +3011,55 @@
|
|
|
2952
3011
|
input.focus();
|
|
2953
3012
|
}
|
|
2954
3013
|
} },
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
3014
|
+
e.createElement(core$1.Group, { spacing: "xs", noWrap: true, style: { width: '100%' } },
|
|
3015
|
+
e.createElement(ResourceAvatar, { value: sender }),
|
|
3016
|
+
e.createElement(core$1.TextInput, { name: "text", ref: inputRef, placeholder: "Add comment", style: { width: '100%', maxWidth: 300 } }),
|
|
3017
|
+
e.createElement(core$1.ActionIcon, { type: "submit", radius: "xl", color: "blue", variant: "filled" },
|
|
3018
|
+
e.createElement(Lde, { size: 16 })),
|
|
3019
|
+
e.createElement(AttachmentButton, { onUpload: createMedia, onUploadStart: onUploadStart, onUploadProgress: onUploadProgress }, (props) => (e.createElement(core$1.ActionIcon, { ...props, radius: "xl", color: "blue", variant: "filled" },
|
|
3020
|
+
e.createElement(XA, { size: 16 })))))))),
|
|
2962
3021
|
items.map((item) => {
|
|
3022
|
+
const key = `${item.resourceType}/${item.id}/${item.meta?.versionId}`;
|
|
2963
3023
|
if (item.resourceType === resource.resourceType && item.id === resource.id) {
|
|
2964
|
-
return (
|
|
3024
|
+
return (e.createElement(HistoryTimelineItem, { key: key, history: history, resource: item, onDetails: onVersionDetails }));
|
|
2965
3025
|
}
|
|
2966
|
-
const key = `${item.resourceType}/${item.id}`;
|
|
2967
3026
|
switch (item.resourceType) {
|
|
2968
3027
|
case 'AuditEvent':
|
|
2969
|
-
return
|
|
3028
|
+
return e.createElement(AuditEventTimelineItem, { key: key, resource: item, onDetails: onDetails });
|
|
2970
3029
|
case 'Communication':
|
|
2971
|
-
return (
|
|
3030
|
+
return (e.createElement(CommunicationTimelineItem, { key: key, resource: item, onPin: item.priority !== 'stat' ? onPin : undefined, onUnpin: item.priority === 'stat' ? onUnpin : undefined, onDetails: onDetails, onEdit: onEdit, onDelete: onDelete }));
|
|
2972
3031
|
case 'DiagnosticReport':
|
|
2973
|
-
return (
|
|
3032
|
+
return (e.createElement(DiagnosticReportTimelineItem, { key: key, resource: item, onDetails: onDetails, onEdit: onEdit, onDelete: onDelete }));
|
|
2974
3033
|
case 'Media':
|
|
2975
|
-
return (
|
|
3034
|
+
return (e.createElement(MediaTimelineItem, { key: key, resource: item, onDetails: onDetails, onEdit: onEdit, onDelete: onDelete }));
|
|
2976
3035
|
default:
|
|
2977
|
-
return (
|
|
2978
|
-
|
|
3036
|
+
return (e.createElement(TimelineItem, { key: key, resource: item, padding: true },
|
|
3037
|
+
e.createElement(ResourceTable, { value: item, ignoreMissingValues: true })));
|
|
2979
3038
|
}
|
|
2980
3039
|
})));
|
|
2981
3040
|
}
|
|
2982
3041
|
function TimelineItemPopupMenu(props) {
|
|
2983
|
-
return (
|
|
2984
|
-
|
|
2985
|
-
props.onPin && (
|
|
2986
|
-
props.onUnpin && (
|
|
2987
|
-
props.onDetails && (
|
|
2988
|
-
props.onEdit && (
|
|
2989
|
-
props.onDelete && (
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
3042
|
+
return (e.createElement(core$1.Menu.Dropdown, null,
|
|
3043
|
+
e.createElement(core$1.Menu.Label, null, "Resource"),
|
|
3044
|
+
props.onPin && (e.createElement(core$1.Menu.Item, { icon: e.createElement(Ege, { size: 14 }), onClick: () => props.onPin(props.resource), "aria-label": `Pin ${core.getReferenceString(props.resource)}` }, "Pin")),
|
|
3045
|
+
props.onUnpin && (e.createElement(core$1.Menu.Item, { icon: e.createElement(xge, { size: 14 }), onClick: () => props.onUnpin(props.resource), "aria-label": `Unpin ${core.getReferenceString(props.resource)}` }, "Unpin")),
|
|
3046
|
+
props.onDetails && (e.createElement(core$1.Menu.Item, { icon: e.createElement(qae, { size: 14 }), onClick: () => props.onDetails(props.resource), "aria-label": `Details ${core.getReferenceString(props.resource)}` }, "Details")),
|
|
3047
|
+
props.onEdit && (e.createElement(core$1.Menu.Item, { icon: e.createElement(CY, { size: 14 }), onClick: () => props.onEdit(props.resource), "aria-label": `Edit ${core.getReferenceString(props.resource)}` }, "Edit")),
|
|
3048
|
+
props.onDelete && (e.createElement(e.Fragment, null,
|
|
3049
|
+
e.createElement(core$1.Menu.Divider, null),
|
|
3050
|
+
e.createElement(core$1.Menu.Label, null, "Danger zone"),
|
|
3051
|
+
e.createElement(core$1.Menu.Item, { color: "red", icon: e.createElement(zKe, { size: 14 }), onClick: () => props.onDelete(props.resource), "aria-label": `Delete ${core.getReferenceString(props.resource)}` }, "Delete")))));
|
|
2993
3052
|
}
|
|
2994
3053
|
function HistoryTimelineItem(props) {
|
|
2995
3054
|
const previous = getPrevious(props.history, props.resource);
|
|
2996
3055
|
if (previous) {
|
|
2997
|
-
return (
|
|
2998
|
-
|
|
3056
|
+
return (e.createElement(TimelineItem, { resource: props.resource, padding: true, popupMenuItems: e.createElement(TimelineItemPopupMenu, { ...props }) },
|
|
3057
|
+
e.createElement(ResourceDiffTable, { original: previous, revised: props.resource })));
|
|
2999
3058
|
}
|
|
3000
3059
|
else {
|
|
3001
|
-
return (
|
|
3002
|
-
|
|
3003
|
-
|
|
3060
|
+
return (e.createElement(TimelineItem, { resource: props.resource, padding: true, popupMenuItems: e.createElement(TimelineItemPopupMenu, { ...props }) },
|
|
3061
|
+
e.createElement("h3", null, "Created"),
|
|
3062
|
+
e.createElement(ResourceTable, { value: props.resource, ignoreMissingValues: true })));
|
|
3004
3063
|
}
|
|
3005
3064
|
}
|
|
3006
3065
|
function getPrevious(history, version) {
|
|
@@ -3015,8 +3074,8 @@
|
|
|
3015
3074
|
const { classes } = useStyles$7();
|
|
3016
3075
|
const routine = !props.resource.priority || props.resource.priority === 'routine';
|
|
3017
3076
|
const className = routine ? undefined : classes.pinnedComment;
|
|
3018
|
-
return (
|
|
3019
|
-
|
|
3077
|
+
return (e.createElement(TimelineItem, { resource: props.resource, profile: props.resource.sender, padding: true, className: className, popupMenuItems: e.createElement(TimelineItemPopupMenu, { ...props }) },
|
|
3078
|
+
e.createElement("p", null, props.resource.payload?.[0]?.contentString)));
|
|
3020
3079
|
}
|
|
3021
3080
|
function MediaTimelineItem(props) {
|
|
3022
3081
|
const contentType = props.resource.content?.contentType;
|
|
@@ -3024,17 +3083,17 @@
|
|
|
3024
3083
|
!contentType.startsWith('image/') &&
|
|
3025
3084
|
!contentType.startsWith('video/') &&
|
|
3026
3085
|
contentType !== 'application/pdf';
|
|
3027
|
-
return (
|
|
3028
|
-
|
|
3086
|
+
return (e.createElement(TimelineItem, { resource: props.resource, padding: !!padding, popupMenuItems: e.createElement(TimelineItemPopupMenu, { ...props }) },
|
|
3087
|
+
e.createElement(AttachmentDisplay, { value: props.resource.content })));
|
|
3029
3088
|
}
|
|
3030
3089
|
function AuditEventTimelineItem(props) {
|
|
3031
|
-
return (
|
|
3032
|
-
|
|
3033
|
-
|
|
3090
|
+
return (e.createElement(TimelineItem, { resource: props.resource, padding: true, popupMenuItems: e.createElement(TimelineItemPopupMenu, { ...props }) },
|
|
3091
|
+
e.createElement(core$1.ScrollArea, null,
|
|
3092
|
+
e.createElement("pre", null, props.resource.outcomeDesc))));
|
|
3034
3093
|
}
|
|
3035
3094
|
function DiagnosticReportTimelineItem(props) {
|
|
3036
|
-
return (
|
|
3037
|
-
|
|
3095
|
+
return (e.createElement(TimelineItem, { resource: props.resource, padding: true, popupMenuItems: e.createElement(TimelineItemPopupMenu, { ...props }) },
|
|
3096
|
+
e.createElement(DiagnosticReportDisplay, { value: props.resource })));
|
|
3038
3097
|
}
|
|
3039
3098
|
function getProgressMessage(e) {
|
|
3040
3099
|
if (e.lengthComputable) {
|
|
@@ -3052,51 +3111,22 @@
|
|
|
3052
3111
|
}
|
|
3053
3112
|
|
|
3054
3113
|
function DefaultResourceTimeline(props) {
|
|
3055
|
-
return (
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
method: 'GET',
|
|
3062
|
-
url: `${core.getReferenceString(resource)}/_history`,
|
|
3063
|
-
},
|
|
3064
|
-
},
|
|
3065
|
-
{
|
|
3066
|
-
request: {
|
|
3067
|
-
method: 'GET',
|
|
3068
|
-
url: `AuditEvent?entity=${core.getReferenceString(resource)}&_sort=-_lastUpdated`,
|
|
3069
|
-
},
|
|
3070
|
-
},
|
|
3071
|
-
],
|
|
3072
|
-
}) }));
|
|
3114
|
+
return (e.createElement(ResourceTimeline, { value: props.resource, loadTimelineResources: async (medplum, resource) => {
|
|
3115
|
+
return Promise.all([
|
|
3116
|
+
medplum.readHistory(resource.resourceType, resource.id),
|
|
3117
|
+
medplum.search('AuditEvent', '_sort=-_lastUpdated&entity=' + core.getReferenceString(resource)),
|
|
3118
|
+
]);
|
|
3119
|
+
} }));
|
|
3073
3120
|
}
|
|
3074
3121
|
|
|
3075
3122
|
function EncounterTimeline(props) {
|
|
3076
|
-
return (
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
url: `${core.getReferenceString(resource)}/_history`,
|
|
3084
|
-
},
|
|
3085
|
-
},
|
|
3086
|
-
{
|
|
3087
|
-
request: {
|
|
3088
|
-
method: 'GET',
|
|
3089
|
-
url: `Communication?encounter=${core.getReferenceString(resource)}`,
|
|
3090
|
-
},
|
|
3091
|
-
},
|
|
3092
|
-
{
|
|
3093
|
-
request: {
|
|
3094
|
-
method: 'GET',
|
|
3095
|
-
url: `Media?encounter=${core.getReferenceString(resource)}`,
|
|
3096
|
-
},
|
|
3097
|
-
},
|
|
3098
|
-
],
|
|
3099
|
-
}), createCommunication: (resource, sender, text) => ({
|
|
3123
|
+
return (e.createElement(ResourceTimeline, { value: props.encounter, loadTimelineResources: async (medplum, resource) => {
|
|
3124
|
+
return Promise.all([
|
|
3125
|
+
medplum.readHistory('Encounter', resource.id),
|
|
3126
|
+
medplum.search('Communication', 'encounter=' + core.getReferenceString(resource)),
|
|
3127
|
+
medplum.search('Media', 'encounter=' + core.getReferenceString(resource)),
|
|
3128
|
+
]);
|
|
3129
|
+
}, createCommunication: (resource, sender, text) => ({
|
|
3100
3130
|
resourceType: 'Communication',
|
|
3101
3131
|
status: 'completed',
|
|
3102
3132
|
encounter: core.createReference(resource),
|
|
@@ -3129,7 +3159,7 @@
|
|
|
3129
3159
|
Received ${value.length} elements \
|
|
3130
3160
|
[${JSON.stringify(value, null, 2)}]`);
|
|
3131
3161
|
}
|
|
3132
|
-
return
|
|
3162
|
+
return e.createElement(ResourcePropertyDisplay, { value: value[0] || '', propertyType: props.propertyType });
|
|
3133
3163
|
}
|
|
3134
3164
|
|
|
3135
3165
|
const searchParamToOperators = {
|
|
@@ -3578,7 +3608,7 @@
|
|
|
3578
3608
|
if (!value) {
|
|
3579
3609
|
return null;
|
|
3580
3610
|
}
|
|
3581
|
-
return (
|
|
3611
|
+
return (e.createElement(ResourcePropertyDisplay, { property: elementDefinition, propertyType: propertyType, value: value, maxWidth: 200, ignoreMissingValues: true, link: false }));
|
|
3582
3612
|
}
|
|
3583
3613
|
/**
|
|
3584
3614
|
* Returns a fragment to be displayed in the search table for a search parameter.
|
|
@@ -3593,18 +3623,18 @@
|
|
|
3593
3623
|
return null;
|
|
3594
3624
|
}
|
|
3595
3625
|
if (elementDefinition) {
|
|
3596
|
-
return (
|
|
3626
|
+
return (e.createElement(ResourcePropertyDisplay, { propertyType: value[0].type, value: value[0].value, maxWidth: 200, ignoreMissingValues: true, link: false }));
|
|
3597
3627
|
}
|
|
3598
|
-
return (
|
|
3628
|
+
return (e.createElement(e.Fragment, null, value.map((v, index) => (e.createElement("span", { key: `${index}-${value.length}` }, typeof v === 'object' ? JSON.stringify(v) : v)))));
|
|
3599
3629
|
}
|
|
3600
3630
|
|
|
3601
3631
|
function SearchFieldEditor(props) {
|
|
3602
|
-
const [state, setState] =
|
|
3632
|
+
const [state, setState] = e.useState({
|
|
3603
3633
|
search: JSON.parse(core.stringify(props.search)),
|
|
3604
3634
|
});
|
|
3605
|
-
const availableRef =
|
|
3606
|
-
const selectedRef =
|
|
3607
|
-
|
|
3635
|
+
const availableRef = e.useRef(null);
|
|
3636
|
+
const selectedRef = e.useRef(null);
|
|
3637
|
+
e.useEffect(() => {
|
|
3608
3638
|
setState({ search: props.search });
|
|
3609
3639
|
}, [props.search]);
|
|
3610
3640
|
/**
|
|
@@ -3736,30 +3766,30 @@
|
|
|
3736
3766
|
const available = getFieldsList(typeDef)
|
|
3737
3767
|
.filter((field) => !selected?.includes(field))
|
|
3738
3768
|
.sort();
|
|
3739
|
-
return (
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3769
|
+
return (e.createElement(core$1.Modal, { title: "Fields", closeButtonLabel: "Close", opened: props.visible, onClose: props.onCancel },
|
|
3770
|
+
e.createElement("div", null,
|
|
3771
|
+
e.createElement("table", { style: { margin: 'auto' } },
|
|
3772
|
+
e.createElement("thead", null,
|
|
3773
|
+
e.createElement("tr", null,
|
|
3774
|
+
e.createElement("th", { colSpan: 2, align: "center" }, "Available"),
|
|
3775
|
+
e.createElement("th", { colSpan: 2, align: "center" }, "Selected"))),
|
|
3776
|
+
e.createElement("tbody", null,
|
|
3777
|
+
e.createElement("tr", null,
|
|
3778
|
+
e.createElement("td", { colSpan: 2, align: "center" },
|
|
3779
|
+
e.createElement("select", { ref: availableRef, size: 15, tabIndex: 1, style: { width: '200px' }, onKeyDown: (e) => handleAvailableKeyDown(e), onDoubleClick: () => handleAvailableDoubleClick(), "data-testid": "available" }, available.map((key) => (e.createElement("option", { key: key, value: key }, buildFieldNameString(key)))))),
|
|
3780
|
+
e.createElement("td", { colSpan: 2, align: "center" },
|
|
3781
|
+
e.createElement("select", { ref: selectedRef, size: 15, tabIndex: 4, style: { width: '200px' }, onKeyDown: (e) => handleSelectedKeyDown(e), onDoubleClick: () => handleSelectedDoubleClick(), "data-testid": "selected" }, selected.map((key) => (e.createElement("option", { key: key, value: key }, buildFieldNameString(key)))))))),
|
|
3782
|
+
e.createElement("tfoot", null,
|
|
3783
|
+
e.createElement("tr", null,
|
|
3784
|
+
e.createElement("td", { align: "center" },
|
|
3785
|
+
e.createElement(core$1.Button, { compact: true, variant: "outline", onClick: onAddField }, "Add")),
|
|
3786
|
+
e.createElement("td", { align: "center" },
|
|
3787
|
+
e.createElement(core$1.Button, { compact: true, variant: "outline", onClick: onRemoveField }, "Remove")),
|
|
3788
|
+
e.createElement("td", { align: "center" },
|
|
3789
|
+
e.createElement(core$1.Button, { compact: true, variant: "outline", onClick: onMoveUp }, "Up")),
|
|
3790
|
+
e.createElement("td", { align: "center" },
|
|
3791
|
+
e.createElement(core$1.Button, { compact: true, variant: "outline", onClick: onMoveDown }, "Down")))))),
|
|
3792
|
+
e.createElement(core$1.Button, { onClick: () => props.onOk(state.search) }, "OK")));
|
|
3763
3793
|
}
|
|
3764
3794
|
/**
|
|
3765
3795
|
* Returns a list of fields/columns available for a type.
|
|
@@ -3795,14 +3825,14 @@
|
|
|
3795
3825
|
const searchParam = core.globalSchema.types[resourceType]?.searchParams?.[filter.code];
|
|
3796
3826
|
if (searchParam) {
|
|
3797
3827
|
if (searchParam.type === 'reference') {
|
|
3798
|
-
return
|
|
3828
|
+
return e.createElement(ResourceName, { value: { reference: filter.value } });
|
|
3799
3829
|
}
|
|
3800
3830
|
const searchParamDetails = core.getSearchParameterDetails(resourceType, searchParam);
|
|
3801
3831
|
if (filter.code === '_lastUpdated' || searchParamDetails.type === core.SearchParameterType.DATETIME) {
|
|
3802
|
-
return
|
|
3832
|
+
return e.createElement(e.Fragment, null, core.formatDateTime(filter.value));
|
|
3803
3833
|
}
|
|
3804
3834
|
}
|
|
3805
|
-
return
|
|
3835
|
+
return e.createElement(e.Fragment, null, filter.value);
|
|
3806
3836
|
}
|
|
3807
3837
|
|
|
3808
3838
|
function SearchFilterValueInput(props) {
|
|
@@ -3810,7 +3840,7 @@
|
|
|
3810
3840
|
const name = 'filter-value';
|
|
3811
3841
|
switch (details.type) {
|
|
3812
3842
|
case core.SearchParameterType.REFERENCE:
|
|
3813
|
-
return (
|
|
3843
|
+
return (e.createElement(ReferenceInput, { name: name, defaultValue: { reference: props.defaultValue }, targetTypes: props.searchParam?.target, onChange: (newReference) => {
|
|
3814
3844
|
if (newReference) {
|
|
3815
3845
|
props.onChange(newReference.reference);
|
|
3816
3846
|
}
|
|
@@ -3819,15 +3849,15 @@
|
|
|
3819
3849
|
}
|
|
3820
3850
|
} }));
|
|
3821
3851
|
case core.SearchParameterType.BOOLEAN:
|
|
3822
|
-
return (
|
|
3852
|
+
return (e.createElement(core$1.Checkbox, { name: name, "data-testid": name, defaultChecked: props.defaultValue === 'true', onChange: (e) => props.onChange(e.currentTarget.checked.toString()) }));
|
|
3823
3853
|
case core.SearchParameterType.DATE:
|
|
3824
|
-
return (
|
|
3854
|
+
return (e.createElement(core$1.TextInput, { type: "date", name: name, "data-testid": name, defaultValue: props.defaultValue, onChange: (e) => props.onChange(e.currentTarget.value) }));
|
|
3825
3855
|
case core.SearchParameterType.DATETIME:
|
|
3826
|
-
return
|
|
3856
|
+
return e.createElement(DateTimeInput, { name: name, defaultValue: props.defaultValue, onChange: props.onChange });
|
|
3827
3857
|
case core.SearchParameterType.NUMBER:
|
|
3828
|
-
return (
|
|
3858
|
+
return (e.createElement(core$1.TextInput, { type: "number", name: name, "data-testid": name, defaultValue: props.defaultValue, onChange: (e) => props.onChange(e.currentTarget.value) }));
|
|
3829
3859
|
case core.SearchParameterType.QUANTITY:
|
|
3830
|
-
return (
|
|
3860
|
+
return (e.createElement(QuantityInput, { name: name, defaultValue: tryParseQuantity(props.defaultValue), onChange: (newQuantity) => {
|
|
3831
3861
|
if (newQuantity) {
|
|
3832
3862
|
props.onChange(`${newQuantity.value}`);
|
|
3833
3863
|
}
|
|
@@ -3836,7 +3866,7 @@
|
|
|
3836
3866
|
}
|
|
3837
3867
|
} }));
|
|
3838
3868
|
default:
|
|
3839
|
-
return (
|
|
3869
|
+
return (e.createElement(core$1.TextInput, { name: name, "data-testid": name, defaultValue: props.defaultValue, autoFocus: props.autoFocus, onChange: (e) => props.onChange(e.currentTarget.value), placeholder: "Search value" }));
|
|
3840
3870
|
}
|
|
3841
3871
|
}
|
|
3842
3872
|
function tryParseQuantity(value) {
|
|
@@ -3854,11 +3884,11 @@
|
|
|
3854
3884
|
}
|
|
3855
3885
|
|
|
3856
3886
|
function SearchFilterEditor(props) {
|
|
3857
|
-
const [search, setSearch] =
|
|
3858
|
-
const [editingIndex, setEditingIndex] =
|
|
3859
|
-
const searchRef =
|
|
3887
|
+
const [search, setSearch] = e.useState(JSON.parse(core.stringify(props.search)));
|
|
3888
|
+
const [editingIndex, setEditingIndex] = e.useState(-1);
|
|
3889
|
+
const searchRef = e.useRef(search);
|
|
3860
3890
|
searchRef.current = search;
|
|
3861
|
-
|
|
3891
|
+
e.useEffect(() => {
|
|
3862
3892
|
setSearch(JSON.parse(core.stringify(props.search)));
|
|
3863
3893
|
}, [props.search]);
|
|
3864
3894
|
function onAddFilter(filter) {
|
|
@@ -3870,24 +3900,24 @@
|
|
|
3870
3900
|
const resourceType = props.search.resourceType;
|
|
3871
3901
|
const searchParams = core.globalSchema.types[resourceType].searchParams;
|
|
3872
3902
|
const filters = search.filters || [];
|
|
3873
|
-
return (
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3903
|
+
return (e.createElement(core$1.Modal, { title: "Filters", closeButtonLabel: "Close", size: 900, opened: props.visible, onClose: props.onCancel },
|
|
3904
|
+
e.createElement("div", null,
|
|
3905
|
+
e.createElement("table", null,
|
|
3906
|
+
e.createElement("colgroup", null,
|
|
3907
|
+
e.createElement("col", { style: { width: 200 } }),
|
|
3908
|
+
e.createElement("col", { style: { width: 200 } }),
|
|
3909
|
+
e.createElement("col", { style: { width: 380 } }),
|
|
3910
|
+
e.createElement("col", { style: { width: 120 } })),
|
|
3911
|
+
e.createElement("thead", null,
|
|
3912
|
+
e.createElement("tr", null,
|
|
3913
|
+
e.createElement("th", null, "Field"),
|
|
3914
|
+
e.createElement("th", null, "Operation"),
|
|
3915
|
+
e.createElement("th", null, "Value"),
|
|
3916
|
+
e.createElement("th", null, "Actions"))),
|
|
3917
|
+
e.createElement("tbody", null,
|
|
3888
3918
|
filters.map((filter, index) => {
|
|
3889
3919
|
if (index === editingIndex) {
|
|
3890
|
-
return (
|
|
3920
|
+
return (e.createElement(FilterRowInput, { key: `filter-${index}-${filters.length}-input`, resourceType: resourceType, searchParams: searchParams, defaultValue: filter, okText: "Save", onOk: (newFilter) => {
|
|
3891
3921
|
const newFilters = [...filters];
|
|
3892
3922
|
newFilters[index] = newFilter;
|
|
3893
3923
|
setSearch(setFilters(searchRef.current, newFilters));
|
|
@@ -3895,27 +3925,27 @@
|
|
|
3895
3925
|
}, onCancel: () => setEditingIndex(-1) }));
|
|
3896
3926
|
}
|
|
3897
3927
|
else {
|
|
3898
|
-
return (
|
|
3928
|
+
return (e.createElement(FilterRowDisplay, { key: `filter-${index}-${filters.length}-display`, resourceType: resourceType, searchParams: searchParams, filter: filter, onEdit: () => setEditingIndex(index), onDelete: () => setSearch(deleteFilter(searchRef.current, index)) }));
|
|
3899
3929
|
}
|
|
3900
3930
|
}),
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3931
|
+
e.createElement(FilterRowInput, { resourceType: resourceType, searchParams: searchParams, okText: "Add", onOk: onAddFilter })))),
|
|
3932
|
+
e.createElement(core$1.Group, { position: "right", mt: "xl" },
|
|
3933
|
+
e.createElement(core$1.Button, { onClick: () => props.onOk(searchRef.current) }, "OK"))));
|
|
3904
3934
|
}
|
|
3905
3935
|
function FilterRowDisplay(props) {
|
|
3906
3936
|
const { filter } = props;
|
|
3907
|
-
return (
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3937
|
+
return (e.createElement("tr", null,
|
|
3938
|
+
e.createElement("td", null, buildFieldNameString(filter.code)),
|
|
3939
|
+
e.createElement("td", null, getOpString(filter.operator)),
|
|
3940
|
+
e.createElement("td", null,
|
|
3941
|
+
e.createElement(SearchFilterValueDisplay, { resourceType: props.resourceType, filter: filter })),
|
|
3942
|
+
e.createElement("td", null,
|
|
3943
|
+
e.createElement(core$1.Button, { compact: true, variant: "outline", onClick: props.onEdit }, "Edit"),
|
|
3944
|
+
e.createElement(core$1.Button, { compact: true, variant: "outline", onClick: props.onDelete }, "Delete"))));
|
|
3915
3945
|
}
|
|
3916
3946
|
function FilterRowInput(props) {
|
|
3917
|
-
const [value, setValue] =
|
|
3918
|
-
const valueRef =
|
|
3947
|
+
const [value, setValue] = e.useState(props.defaultValue ?? {});
|
|
3948
|
+
const valueRef = e.useRef(value);
|
|
3919
3949
|
valueRef.current = value;
|
|
3920
3950
|
function setFilterCode(newCode) {
|
|
3921
3951
|
setValue({ ...valueRef.current, code: newCode });
|
|
@@ -3928,32 +3958,32 @@
|
|
|
3928
3958
|
}
|
|
3929
3959
|
const searchParam = props.searchParams[value.code];
|
|
3930
3960
|
const operators = searchParam && getSearchOperators(searchParam);
|
|
3931
|
-
return (
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
value.code && value.operator && value.value && (
|
|
3961
|
+
return (e.createElement("tr", null,
|
|
3962
|
+
e.createElement("td", null,
|
|
3963
|
+
e.createElement(core$1.NativeSelect, { "data-testid": "filter-field", defaultValue: valueRef.current.code, onChange: (e) => setFilterCode(e.currentTarget.value), data: Object.keys(props.searchParams).map((param) => ({ value: param, label: buildFieldNameString(param) })) })),
|
|
3964
|
+
e.createElement("td", null, operators && (e.createElement(core$1.NativeSelect, { "data-testid": "filter-operation", defaultValue: value.operator, onChange: (e) => setFilterOperator(e.currentTarget.value), data: ['', ...operators.map((op) => ({ value: op, label: getOpString(op) }))] }))),
|
|
3965
|
+
e.createElement("td", null, searchParam && value.operator && (e.createElement(SearchFilterValueInput, { resourceType: props.resourceType, searchParam: searchParam, defaultValue: value.value, onChange: setFilterValue }))),
|
|
3966
|
+
e.createElement("td", null,
|
|
3967
|
+
value.code && value.operator && value.value && (e.createElement(core$1.Button, { compact: true, variant: "outline", onClick: () => {
|
|
3938
3968
|
props.onOk(valueRef.current);
|
|
3939
3969
|
setValue({});
|
|
3940
3970
|
} }, props.okText)),
|
|
3941
|
-
props.onCancel && (
|
|
3971
|
+
props.onCancel && (e.createElement(core$1.Button, { compact: true, variant: "outline", onClick: props.onCancel }, "Cancel")))));
|
|
3942
3972
|
}
|
|
3943
3973
|
|
|
3944
3974
|
function SearchFilterValueDialog(props) {
|
|
3945
|
-
const [value, setValue] =
|
|
3975
|
+
const [value, setValue] = e.useState(props.defaultValue ?? '');
|
|
3946
3976
|
if (!props.visible || !props.searchParam || !props.filter) {
|
|
3947
3977
|
return null;
|
|
3948
3978
|
}
|
|
3949
3979
|
function onOk() {
|
|
3950
3980
|
props.onOk({ ...props.filter, value });
|
|
3951
3981
|
}
|
|
3952
|
-
return (
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3982
|
+
return (e.createElement(core$1.Modal, { title: props.title, size: "xl", opened: props.visible, onClose: props.onCancel },
|
|
3983
|
+
e.createElement("div", { style: { width: 500 } },
|
|
3984
|
+
e.createElement(Form, { onSubmit: onOk },
|
|
3985
|
+
e.createElement(SearchFilterValueInput, { resourceType: props.resourceType, searchParam: props.searchParam, defaultValue: value, autoFocus: true, onChange: setValue }))),
|
|
3986
|
+
e.createElement(core$1.Button, { onClick: onOk }, "OK")));
|
|
3957
3987
|
}
|
|
3958
3988
|
|
|
3959
3989
|
function SearchPopupMenu(props) {
|
|
@@ -3974,26 +4004,26 @@
|
|
|
3974
4004
|
}
|
|
3975
4005
|
// If there is only one search parameter, then show it directly
|
|
3976
4006
|
if (props.searchParams.length === 1) {
|
|
3977
|
-
return (
|
|
4007
|
+
return (e.createElement(SearchParameterSubMenu, { search: props.search, searchParam: props.searchParams[0], onSort: onSort, onPrompt: onPrompt, onChange: onChange, onClear: onClear }));
|
|
3978
4008
|
}
|
|
3979
4009
|
// Otherwise, show a menu, with each search parameter as a sub menu
|
|
3980
|
-
return (
|
|
4010
|
+
return (e.createElement(core$1.Menu.Dropdown, null, props.searchParams.map((searchParam) => (e.createElement(core$1.Menu.Item, { key: searchParam.code }, buildFieldNameString(searchParam.code))))));
|
|
3981
4011
|
}
|
|
3982
4012
|
function SearchParameterSubMenu(props) {
|
|
3983
4013
|
switch (props.searchParam.type) {
|
|
3984
4014
|
case 'date':
|
|
3985
|
-
return
|
|
4015
|
+
return e.createElement(DateFilterSubMenu, { ...props });
|
|
3986
4016
|
case 'number':
|
|
3987
4017
|
case 'quantity':
|
|
3988
|
-
return
|
|
4018
|
+
return e.createElement(NumericFilterSubMenu, { ...props });
|
|
3989
4019
|
case 'reference':
|
|
3990
|
-
return
|
|
4020
|
+
return e.createElement(ReferenceFilterSubMenu, { ...props });
|
|
3991
4021
|
case 'string':
|
|
3992
4022
|
case 'token':
|
|
3993
4023
|
case 'uri':
|
|
3994
|
-
return
|
|
4024
|
+
return e.createElement(TextFilterSubMenu, { ...props });
|
|
3995
4025
|
default:
|
|
3996
|
-
return
|
|
4026
|
+
return e.createElement(e.Fragment, null,
|
|
3997
4027
|
"Unknown search param type: ",
|
|
3998
4028
|
props.searchParam.type);
|
|
3999
4029
|
}
|
|
@@ -4001,72 +4031,72 @@
|
|
|
4001
4031
|
function DateFilterSubMenu(props) {
|
|
4002
4032
|
const { searchParam } = props;
|
|
4003
4033
|
const code = searchParam.code;
|
|
4004
|
-
return (
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4034
|
+
return (e.createElement(core$1.Menu.Dropdown, null,
|
|
4035
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(iNe, { size: 14 }), onClick: () => props.onSort(searchParam, false) }, "Sort Oldest to Newest"),
|
|
4036
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(wNe, { size: 14 }), onClick: () => props.onSort(searchParam, true) }, "Sort Newest to Oldest"),
|
|
4037
|
+
e.createElement(core$1.Menu.Divider, null),
|
|
4038
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(lZ, { size: 14 }), onClick: () => props.onPrompt(searchParam, core.Operator.EQUALS) }, "Equals..."),
|
|
4039
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(rZ, { size: 14 }), onClick: () => props.onPrompt(searchParam, core.Operator.NOT_EQUALS) }, "Does not equal..."),
|
|
4040
|
+
e.createElement(core$1.Menu.Divider, null),
|
|
4041
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(Pse, { size: 14 }), onClick: () => props.onPrompt(searchParam, core.Operator.ENDS_BEFORE) }, "Before..."),
|
|
4042
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(Cse, { size: 14 }), onClick: () => props.onPrompt(searchParam, core.Operator.STARTS_AFTER) }, "After..."),
|
|
4043
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(Jw, { size: 14 }), onClick: () => props.onPrompt(searchParam, core.Operator.EQUALS) }, "Between..."),
|
|
4044
|
+
e.createElement(core$1.Menu.Divider, null),
|
|
4045
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(zB, { size: 14 }), onClick: () => props.onChange(addTomorrowFilter(props.search, code)) }, "Tomorrow"),
|
|
4046
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(zB, { size: 14 }), onClick: () => props.onChange(addTodayFilter(props.search, code)) }, "Today"),
|
|
4047
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(zB, { size: 14 }), onClick: () => props.onChange(addYesterdayFilter(props.search, code)) }, "Yesterday"),
|
|
4048
|
+
e.createElement(core$1.Menu.Divider, null),
|
|
4049
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(zB, { size: 14 }), onClick: () => props.onChange(addNextMonthFilter(props.search, code)) }, "Next Month"),
|
|
4050
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(zB, { size: 14 }), onClick: () => props.onChange(addThisMonthFilter(props.search, code)) }, "This Month"),
|
|
4051
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(zB, { size: 14 }), onClick: () => props.onChange(addLastMonthFilter(props.search, code)) }, "Last Month"),
|
|
4052
|
+
e.createElement(core$1.Menu.Divider, null),
|
|
4053
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(zB, { size: 14 }), onClick: () => props.onChange(addYearToDateFilter(props.search, code)) }, "Year to date"),
|
|
4054
|
+
e.createElement(CommonMenuItems, { ...props })));
|
|
4025
4055
|
}
|
|
4026
4056
|
function NumericFilterSubMenu(props) {
|
|
4027
4057
|
const { searchParam } = props;
|
|
4028
|
-
return (
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4058
|
+
return (e.createElement(core$1.Menu.Dropdown, null,
|
|
4059
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(iNe, { size: 14 }), onClick: () => props.onSort(searchParam, false) }, "Sort Smallest to Largest"),
|
|
4060
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(wNe, { size: 14 }), onClick: () => props.onSort(searchParam, true) }, "Sort Largest to Smallest"),
|
|
4061
|
+
e.createElement(core$1.Menu.Divider, null),
|
|
4062
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(lZ, { size: 14 }), onClick: () => props.onPrompt(searchParam, core.Operator.EQUALS) }, "Equals..."),
|
|
4063
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(rZ, { size: 14 }), onClick: () => props.onPrompt(searchParam, core.Operator.NOT_EQUALS) }, "Does not equal..."),
|
|
4064
|
+
e.createElement(core$1.Menu.Divider, null),
|
|
4065
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(Cse, { size: 14 }), onClick: () => props.onPrompt(searchParam, core.Operator.GREATER_THAN) }, "Greater than..."),
|
|
4066
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(Bje, { size: 14 }), onClick: () => props.onPrompt(searchParam, core.Operator.GREATER_THAN_OR_EQUALS) }, "Greater than or equal to..."),
|
|
4067
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(Pse, { size: 14 }), onClick: () => props.onPrompt(searchParam, core.Operator.LESS_THAN) }, "Less than..."),
|
|
4068
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(Bje, { size: 14 }), onClick: () => props.onPrompt(searchParam, core.Operator.LESS_THAN_OR_EQUALS) }, "Less than or equal to..."),
|
|
4069
|
+
e.createElement(CommonMenuItems, { ...props })));
|
|
4040
4070
|
}
|
|
4041
4071
|
function ReferenceFilterSubMenu(props) {
|
|
4042
4072
|
const { searchParam } = props;
|
|
4043
|
-
return (
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4073
|
+
return (e.createElement(core$1.Menu.Dropdown, null,
|
|
4074
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(lZ, { size: 14 }), onClick: () => props.onPrompt(searchParam, core.Operator.EQUALS) }, "Equals..."),
|
|
4075
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(rZ, { size: 14 }), onClick: () => props.onPrompt(searchParam, core.Operator.NOT) }, "Does not equal..."),
|
|
4076
|
+
e.createElement(CommonMenuItems, { ...props })));
|
|
4047
4077
|
}
|
|
4048
4078
|
function TextFilterSubMenu(props) {
|
|
4049
4079
|
const { searchParam } = props;
|
|
4050
|
-
return (
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4080
|
+
return (e.createElement(core$1.Menu.Dropdown, null,
|
|
4081
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(iNe, { size: 14 }), onClick: () => props.onSort(searchParam, false) }, "Sort A to Z"),
|
|
4082
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(wNe, { size: 14 }), onClick: () => props.onSort(searchParam, true) }, "Sort Z to A"),
|
|
4083
|
+
e.createElement(core$1.Menu.Divider, null),
|
|
4084
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(lZ, { size: 14 }), onClick: () => props.onPrompt(searchParam, core.Operator.EQUALS) }, "Equals..."),
|
|
4085
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(rZ, { size: 14 }), onClick: () => props.onPrompt(searchParam, core.Operator.NOT) }, "Does not equal..."),
|
|
4086
|
+
e.createElement(core$1.Menu.Divider, null),
|
|
4087
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(BC, { size: 14 }), onClick: () => props.onPrompt(searchParam, core.Operator.CONTAINS) }, "Contains..."),
|
|
4088
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(CC, { size: 14 }), onClick: () => props.onPrompt(searchParam, core.Operator.EQUALS) }, "Does not contain..."),
|
|
4089
|
+
e.createElement(CommonMenuItems, { ...props })));
|
|
4060
4090
|
}
|
|
4061
4091
|
function CommonMenuItems(props) {
|
|
4062
4092
|
const { searchParam } = props;
|
|
4063
4093
|
const code = searchParam.code;
|
|
4064
|
-
return (
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4094
|
+
return (e.createElement(e.Fragment, null,
|
|
4095
|
+
e.createElement(core$1.Menu.Divider, null),
|
|
4096
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(Qv, { size: 14 }), onClick: () => props.onChange(addMissingFilter(props.search, code)) }, "Missing"),
|
|
4097
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(Jv, { size: 14 }), onClick: () => props.onChange(addMissingFilter(props.search, code, false)) }, "Not missing"),
|
|
4098
|
+
e.createElement(core$1.Menu.Divider, null),
|
|
4099
|
+
e.createElement(core$1.Menu.Item, { icon: e.createElement(qXe, { size: 14 }), onClick: () => props.onClear(searchParam) }, "Clear filters")));
|
|
4070
4100
|
}
|
|
4071
4101
|
|
|
4072
4102
|
/**
|
|
@@ -4218,18 +4248,18 @@
|
|
|
4218
4248
|
function SearchControl(props) {
|
|
4219
4249
|
const { classes } = useStyles$6();
|
|
4220
4250
|
const medplum = useMedplum();
|
|
4221
|
-
const [schemaLoaded, setSchemaLoaded] =
|
|
4222
|
-
const [outcome, setOutcome] =
|
|
4251
|
+
const [schemaLoaded, setSchemaLoaded] = e.useState(false);
|
|
4252
|
+
const [outcome, setOutcome] = e.useState();
|
|
4223
4253
|
const { search, onLoad } = props;
|
|
4224
|
-
const [state, setState] =
|
|
4254
|
+
const [state, setState] = e.useState({
|
|
4225
4255
|
selected: {},
|
|
4226
4256
|
fieldEditorVisible: false,
|
|
4227
4257
|
filterEditorVisible: false,
|
|
4228
4258
|
filterDialogVisible: false,
|
|
4229
4259
|
});
|
|
4230
|
-
const stateRef =
|
|
4260
|
+
const stateRef = e.useRef(state);
|
|
4231
4261
|
stateRef.current = state;
|
|
4232
|
-
|
|
4262
|
+
e.useEffect(() => {
|
|
4233
4263
|
setOutcome(undefined);
|
|
4234
4264
|
medplum
|
|
4235
4265
|
.search(search.resourceType, core.formatSearchQuery({ ...search, total: 'accurate', fields: undefined }))
|
|
@@ -4316,7 +4346,7 @@
|
|
|
4316
4346
|
props.onAuxClick(new SearchClickEvent(resource, e));
|
|
4317
4347
|
}
|
|
4318
4348
|
}
|
|
4319
|
-
|
|
4349
|
+
e.useEffect(() => {
|
|
4320
4350
|
setSchemaLoaded(false);
|
|
4321
4351
|
medplum
|
|
4322
4352
|
.requestSchema(props.search.resourceType)
|
|
@@ -4325,8 +4355,8 @@
|
|
|
4325
4355
|
}, [medplum, props.search.resourceType]);
|
|
4326
4356
|
const typeSchema = schemaLoaded && core.globalSchema?.types?.[props.search.resourceType];
|
|
4327
4357
|
if (!typeSchema) {
|
|
4328
|
-
return (
|
|
4329
|
-
|
|
4358
|
+
return (e.createElement(core$1.Center, { style: { width: '100%', height: '100%' } },
|
|
4359
|
+
e.createElement(core$1.Loader, null)));
|
|
4330
4360
|
}
|
|
4331
4361
|
const checkboxColumn = props.checkboxesEnabled;
|
|
4332
4362
|
const fields = getFieldDefinitions(search);
|
|
@@ -4338,36 +4368,36 @@
|
|
|
4338
4368
|
const buttonColor = 'gray';
|
|
4339
4369
|
const iconSize = 16;
|
|
4340
4370
|
const isMobile = window.innerWidth < 768;
|
|
4341
|
-
return (
|
|
4342
|
-
!props.hideToolbar && (
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
props.onNew && (
|
|
4347
|
-
!isMobile && props.onExport && (
|
|
4348
|
-
!isMobile && props.onDelete && (
|
|
4349
|
-
!isMobile && props.onBulk && (
|
|
4350
|
-
lastResult && (
|
|
4371
|
+
return (e.createElement("div", { className: classes.root, "data-testid": "search-control" },
|
|
4372
|
+
!props.hideToolbar && (e.createElement(core$1.Group, { position: "apart", mb: "xl" },
|
|
4373
|
+
e.createElement(core$1.Group, { spacing: 2 },
|
|
4374
|
+
e.createElement(core$1.Button, { compact: true, variant: buttonVariant, color: buttonColor, leftIcon: e.createElement(R0, { size: iconSize }), onClick: () => setState({ ...stateRef.current, fieldEditorVisible: true }) }, "Fields"),
|
|
4375
|
+
e.createElement(core$1.Button, { compact: true, variant: buttonVariant, color: buttonColor, leftIcon: e.createElement(sF, { size: iconSize }), onClick: () => setState({ ...stateRef.current, filterEditorVisible: true }) }, "Filters"),
|
|
4376
|
+
props.onNew && (e.createElement(core$1.Button, { compact: true, variant: buttonVariant, color: buttonColor, leftIcon: e.createElement(X_, { size: iconSize }), onClick: props.onNew }, "New...")),
|
|
4377
|
+
!isMobile && props.onExport && (e.createElement(core$1.Button, { compact: true, variant: buttonVariant, color: buttonColor, leftIcon: e.createElement(_Ae, { size: iconSize }), onClick: props.onExport }, "Export...")),
|
|
4378
|
+
!isMobile && props.onDelete && (e.createElement(core$1.Button, { compact: true, variant: buttonVariant, color: buttonColor, leftIcon: e.createElement(zKe, { size: iconSize }), onClick: () => props.onDelete(Object.keys(state.selected)) }, "Delete...")),
|
|
4379
|
+
!isMobile && props.onBulk && (e.createElement(core$1.Button, { compact: true, variant: buttonVariant, color: buttonColor, leftIcon: e.createElement(bw, { size: iconSize }), onClick: () => props.onBulk(Object.keys(state.selected)) }, "Bulk..."))),
|
|
4380
|
+
lastResult && (e.createElement(core$1.Text, { size: "xs", color: "dimmed" },
|
|
4351
4381
|
getStart$1(search, lastResult.total),
|
|
4352
4382
|
"-",
|
|
4353
4383
|
getEnd$1(search, lastResult.total),
|
|
4354
4384
|
" of",
|
|
4355
4385
|
' ',
|
|
4356
4386
|
lastResult.total?.toLocaleString())))),
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
checkboxColumn && (
|
|
4361
|
-
|
|
4362
|
-
fields.map((field) => (
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4387
|
+
e.createElement(core$1.Table, { className: classes.table },
|
|
4388
|
+
e.createElement("thead", null,
|
|
4389
|
+
e.createElement("tr", null,
|
|
4390
|
+
checkboxColumn && (e.createElement("th", null,
|
|
4391
|
+
e.createElement("input", { type: "checkbox", value: "checked", "aria-label": "all-checkbox", "data-testid": "all-checkbox", checked: isAllSelected(), onChange: (e) => handleAllCheckboxClick(e) }))),
|
|
4392
|
+
fields.map((field) => (e.createElement("th", { key: field.name },
|
|
4393
|
+
e.createElement(core$1.Menu, { shadow: "md", width: 240, position: "bottom-end" },
|
|
4394
|
+
e.createElement(core$1.Menu.Target, null,
|
|
4395
|
+
e.createElement(core$1.UnstyledButton, { className: classes.control },
|
|
4396
|
+
e.createElement(core$1.Group, { position: "apart", noWrap: true },
|
|
4397
|
+
e.createElement(core$1.Text, { weight: 500, size: "sm" }, buildFieldNameString(field.name)),
|
|
4398
|
+
e.createElement(core$1.Center, { className: classes.icon },
|
|
4399
|
+
e.createElement(oe, { size: 14, stroke: 1.5 }))))),
|
|
4400
|
+
e.createElement(SearchPopupMenu, { search: props.search, searchParams: field.searchParams, onPrompt: (searchParam, filter) => {
|
|
4371
4401
|
setState({
|
|
4372
4402
|
...stateRef.current,
|
|
4373
4403
|
filterDialogVisible: true,
|
|
@@ -4377,18 +4407,18 @@
|
|
|
4377
4407
|
}, onChange: (result) => {
|
|
4378
4408
|
emitSearchChange(result);
|
|
4379
4409
|
} })))))),
|
|
4380
|
-
!props.hideFilters && (
|
|
4381
|
-
checkboxColumn &&
|
|
4382
|
-
fields.map((field) => (
|
|
4383
|
-
|
|
4384
|
-
checkboxColumn && (
|
|
4385
|
-
|
|
4386
|
-
fields.map((field) => (
|
|
4387
|
-
resources?.length === 0 && (
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
lastResult?.total !== undefined && lastResult.total > 0 && (
|
|
4391
|
-
|
|
4410
|
+
!props.hideFilters && (e.createElement("tr", null,
|
|
4411
|
+
checkboxColumn && e.createElement("th", null),
|
|
4412
|
+
fields.map((field) => (e.createElement("th", { key: field.name }, field.searchParams && (e.createElement(FilterDescription, { resourceType: resourceType, searchParams: field.searchParams, filters: props.search.filters })))))))),
|
|
4413
|
+
e.createElement("tbody", null, resources?.map((resource) => resource && (e.createElement("tr", { key: resource.id, className: classes.tr, "data-testid": "search-control-row", onClick: (e) => handleRowClick(e, resource), onAuxClick: (e) => handleRowClick(e, resource) },
|
|
4414
|
+
checkboxColumn && (e.createElement("td", null,
|
|
4415
|
+
e.createElement("input", { type: "checkbox", value: "checked", "data-testid": "row-checkbox", "aria-label": `Checkbox for ${resource.id}`, checked: !!state.selected[resource.id], onChange: (e) => handleSingleCheckboxClick(e, resource.id) }))),
|
|
4416
|
+
fields.map((field) => (e.createElement("td", { key: field.name }, renderValue(resource, field))))))))),
|
|
4417
|
+
resources?.length === 0 && (e.createElement(Container, null,
|
|
4418
|
+
e.createElement(core$1.Center, null,
|
|
4419
|
+
e.createElement(core$1.Text, { size: "xl", color: "dimmed" }, "No results")))),
|
|
4420
|
+
lastResult?.total !== undefined && lastResult.total > 0 && (e.createElement(core$1.Center, { m: "md", p: "md" },
|
|
4421
|
+
e.createElement(core$1.Pagination, { page: getPage(search), total: getTotalPages(search, lastResult.total), onChange: (newPage) => emitSearchChange(setPage(search, newPage)), getItemAriaLabel: (page) => {
|
|
4392
4422
|
switch (page) {
|
|
4393
4423
|
case 'prev':
|
|
4394
4424
|
return 'Previous page';
|
|
@@ -4398,9 +4428,9 @@
|
|
|
4398
4428
|
return undefined;
|
|
4399
4429
|
}
|
|
4400
4430
|
} }))),
|
|
4401
|
-
outcome && (
|
|
4402
|
-
|
|
4403
|
-
|
|
4431
|
+
outcome && (e.createElement("div", { "data-testid": "search-error" },
|
|
4432
|
+
e.createElement("pre", { style: { textAlign: 'left' } }, JSON.stringify(outcome, undefined, 2)))),
|
|
4433
|
+
e.createElement(SearchFieldEditor, { search: props.search, visible: stateRef.current.fieldEditorVisible, onOk: (result) => {
|
|
4404
4434
|
emitSearchChange(result);
|
|
4405
4435
|
setState({
|
|
4406
4436
|
...stateRef.current,
|
|
@@ -4412,7 +4442,7 @@
|
|
|
4412
4442
|
fieldEditorVisible: false,
|
|
4413
4443
|
});
|
|
4414
4444
|
} }),
|
|
4415
|
-
|
|
4445
|
+
e.createElement(SearchFilterEditor, { search: props.search, visible: stateRef.current.filterEditorVisible, onOk: (result) => {
|
|
4416
4446
|
emitSearchChange(result);
|
|
4417
4447
|
setState({
|
|
4418
4448
|
...stateRef.current,
|
|
@@ -4424,7 +4454,7 @@
|
|
|
4424
4454
|
filterEditorVisible: false,
|
|
4425
4455
|
});
|
|
4426
4456
|
} }),
|
|
4427
|
-
|
|
4457
|
+
e.createElement(SearchFilterValueDialog, { key: state.filterDialogSearchParam?.code, visible: stateRef.current.filterDialogVisible, title: 'Input', resourceType: resourceType, searchParam: state.filterDialogSearchParam, filter: state.filterDialogFilter, defaultValue: '', onOk: (filter) => {
|
|
4428
4458
|
emitSearchChange(addFilter(props.search, filter.code, filter.operator, filter.value));
|
|
4429
4459
|
setState({
|
|
4430
4460
|
...stateRef.current,
|
|
@@ -4437,16 +4467,16 @@
|
|
|
4437
4467
|
});
|
|
4438
4468
|
} })));
|
|
4439
4469
|
}
|
|
4440
|
-
const MemoizedSearchControl =
|
|
4470
|
+
const MemoizedSearchControl = e.memo(SearchControl);
|
|
4441
4471
|
function FilterDescription(props) {
|
|
4442
4472
|
const filters = (props.filters ?? []).filter((f) => props.searchParams.find((p) => p.code === f.code));
|
|
4443
4473
|
if (filters.length === 0) {
|
|
4444
|
-
return
|
|
4474
|
+
return e.createElement("span", null, "no filters");
|
|
4445
4475
|
}
|
|
4446
|
-
return (
|
|
4476
|
+
return (e.createElement(e.Fragment, null, filters.map((filter, index) => (e.createElement("div", { key: `filter-${index}-${filters.length}` },
|
|
4447
4477
|
getOpString(filter.operator),
|
|
4448
4478
|
"\u00A0",
|
|
4449
|
-
|
|
4479
|
+
e.createElement(SearchFilterValueDisplay, { resourceType: props.resourceType, filter: filter }))))));
|
|
4450
4480
|
}
|
|
4451
4481
|
function getPage(search) {
|
|
4452
4482
|
return Math.floor((search.offset || 0) / (search.count || core.DEFAULT_SEARCH_COUNT)) + 1;
|
|
@@ -4467,16 +4497,16 @@
|
|
|
4467
4497
|
*/
|
|
4468
4498
|
function FhirPathTable(props) {
|
|
4469
4499
|
const medplum = useMedplum();
|
|
4470
|
-
const [schema, setSchema] =
|
|
4471
|
-
const [outcome, setOutcome] =
|
|
4500
|
+
const [schema, setSchema] = e.useState();
|
|
4501
|
+
const [outcome, setOutcome] = e.useState();
|
|
4472
4502
|
const { query, fields } = props;
|
|
4473
|
-
const [response, setResponse] =
|
|
4474
|
-
const [selected, setSelected] =
|
|
4475
|
-
const responseRef =
|
|
4503
|
+
const [response, setResponse] = e.useState();
|
|
4504
|
+
const [selected, setSelected] = e.useState({});
|
|
4505
|
+
const responseRef = e.useRef();
|
|
4476
4506
|
responseRef.current = response;
|
|
4477
|
-
const selectedRef =
|
|
4507
|
+
const selectedRef = e.useRef({});
|
|
4478
4508
|
selectedRef.current = selected;
|
|
4479
|
-
|
|
4509
|
+
e.useEffect(() => {
|
|
4480
4510
|
setOutcome(undefined);
|
|
4481
4511
|
medplum.graphql(query).then(setResponse).catch(setOutcome);
|
|
4482
4512
|
}, [medplum, query]);
|
|
@@ -4533,7 +4563,7 @@
|
|
|
4533
4563
|
props.onAuxClick(new SearchClickEvent(resource, e));
|
|
4534
4564
|
}
|
|
4535
4565
|
}
|
|
4536
|
-
|
|
4566
|
+
e.useEffect(() => {
|
|
4537
4567
|
medplum
|
|
4538
4568
|
.requestSchema(props.resourceType)
|
|
4539
4569
|
.then((newSchema) => {
|
|
@@ -4545,50 +4575,43 @@
|
|
|
4545
4575
|
}, [medplum, props.resourceType]);
|
|
4546
4576
|
const typeSchema = schema?.types?.[props.resourceType];
|
|
4547
4577
|
if (!typeSchema) {
|
|
4548
|
-
return
|
|
4578
|
+
return e.createElement(core$1.Loader, null);
|
|
4549
4579
|
}
|
|
4550
4580
|
const checkboxColumn = props.checkboxesEnabled;
|
|
4551
|
-
return (
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
checkboxColumn && (
|
|
4556
|
-
|
|
4557
|
-
fields.map((field) => (
|
|
4558
|
-
|
|
4559
|
-
checkboxColumn && (
|
|
4560
|
-
|
|
4581
|
+
return (e.createElement("div", { onContextMenu: (e) => killEvent(e), "data-testid": "search-control" },
|
|
4582
|
+
e.createElement(core$1.Table, null,
|
|
4583
|
+
e.createElement("thead", null,
|
|
4584
|
+
e.createElement("tr", null,
|
|
4585
|
+
checkboxColumn && (e.createElement("th", null,
|
|
4586
|
+
e.createElement("input", { type: "checkbox", value: "checked", "aria-label": "all-checkbox", "data-testid": "all-checkbox", checked: isAllSelected(), onChange: (e) => handleAllCheckboxClick(e) }))),
|
|
4587
|
+
fields.map((field) => (e.createElement("th", { key: field.name }, field.name))))),
|
|
4588
|
+
e.createElement("tbody", null, response?.data?.ResourceList?.map((resource) => resource && (e.createElement("tr", { key: resource.id, "data-testid": "search-control-row", onClick: (e) => handleRowClick(e, resource), onAuxClick: (e) => handleRowClick(e, resource) },
|
|
4589
|
+
checkboxColumn && (e.createElement("td", null,
|
|
4590
|
+
e.createElement("input", { type: "checkbox", value: "checked", "data-testid": "row-checkbox", "aria-label": `Checkbox for ${resource.id}`, checked: !!selected[resource.id], onChange: (e) => handleSingleCheckboxClick(e, resource.id) }))),
|
|
4561
4591
|
fields.map((field) => {
|
|
4562
|
-
return (
|
|
4563
|
-
|
|
4592
|
+
return (e.createElement("td", { key: field.name },
|
|
4593
|
+
e.createElement(FhirPathDisplay, { propertyType: field.propertyType, path: field.fhirPath, resource: resource })));
|
|
4564
4594
|
})))))),
|
|
4565
|
-
response?.data?.ResourceList?.length === 0 &&
|
|
4566
|
-
outcome && (
|
|
4567
|
-
|
|
4568
|
-
props.onBulk && (
|
|
4595
|
+
response?.data?.ResourceList?.length === 0 && e.createElement("div", { "data-testid": "empty-search" }, "No results"),
|
|
4596
|
+
outcome && (e.createElement("div", { "data-testid": "search-error" },
|
|
4597
|
+
e.createElement("pre", { style: { textAlign: 'left' } }, JSON.stringify(outcome, undefined, 2)))),
|
|
4598
|
+
props.onBulk && (e.createElement(core$1.Button, { onClick: () => props.onBulk(Object.keys(selectedRef.current)) }, "Bulk..."))));
|
|
4569
4599
|
}
|
|
4570
|
-
const MemoizedFhirPathTable =
|
|
4600
|
+
const MemoizedFhirPathTable = e.memo(FhirPathTable);
|
|
4571
4601
|
|
|
4572
|
-
const searches = [
|
|
4573
|
-
'$/_history',
|
|
4574
|
-
'Communication?subject=$',
|
|
4575
|
-
'Device?patient=$',
|
|
4576
|
-
'DeviceRequest?patient=$',
|
|
4577
|
-
'DiagnosticReport?subject=$',
|
|
4578
|
-
'Media?subject=$',
|
|
4579
|
-
'ServiceRequest?subject=$',
|
|
4580
|
-
];
|
|
4581
4602
|
function PatientTimeline(props) {
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4603
|
+
const loadTimelineResources = e.useCallback((medplum, resource) => {
|
|
4604
|
+
return Promise.all([
|
|
4605
|
+
medplum.readHistory('Patient', resource.id),
|
|
4606
|
+
medplum.search('Communication', 'subject=' + core.getReferenceString(resource)),
|
|
4607
|
+
medplum.search('Device', 'patient=' + core.getReferenceString(resource)),
|
|
4608
|
+
medplum.search('DeviceRequest', 'patient=' + core.getReferenceString(resource)),
|
|
4609
|
+
medplum.search('DiagnosticReport', 'subject=' + core.getReferenceString(resource)),
|
|
4610
|
+
medplum.search('Media', 'subject=' + core.getReferenceString(resource)),
|
|
4611
|
+
medplum.search('ServiceRequest', 'subject=' + core.getReferenceString(resource)),
|
|
4612
|
+
]);
|
|
4613
|
+
}, []);
|
|
4614
|
+
return (e.createElement(ResourceTimeline, { value: props.patient, loadTimelineResources: loadTimelineResources, createCommunication: (resource, sender, text) => ({
|
|
4592
4615
|
resourceType: 'Communication',
|
|
4593
4616
|
status: 'completed',
|
|
4594
4617
|
subject: core.createReference(resource),
|
|
@@ -4634,22 +4657,22 @@
|
|
|
4634
4657
|
function PlanDefinitionBuilder(props) {
|
|
4635
4658
|
const medplum = useMedplum();
|
|
4636
4659
|
const defaultValue = useResource(props.value);
|
|
4637
|
-
const [schema, setSchema] =
|
|
4638
|
-
const [selectedKey, setSelectedKey] =
|
|
4639
|
-
const [hoverKey, setHoverKey] =
|
|
4640
|
-
const [value, setValue] =
|
|
4660
|
+
const [schema, setSchema] = e.useState(undefined);
|
|
4661
|
+
const [selectedKey, setSelectedKey] = e.useState();
|
|
4662
|
+
const [hoverKey, setHoverKey] = e.useState();
|
|
4663
|
+
const [value, setValue] = e.useState();
|
|
4641
4664
|
function handleDocumentMouseOver() {
|
|
4642
4665
|
setHoverKey(undefined);
|
|
4643
4666
|
}
|
|
4644
4667
|
function handleDocumentClick() {
|
|
4645
4668
|
setSelectedKey(undefined);
|
|
4646
4669
|
}
|
|
4647
|
-
const valueRef =
|
|
4670
|
+
const valueRef = e.useRef();
|
|
4648
4671
|
valueRef.current = value;
|
|
4649
|
-
|
|
4672
|
+
e.useEffect(() => {
|
|
4650
4673
|
medplum.requestSchema('PlanDefinition').then(setSchema).catch(console.log);
|
|
4651
4674
|
}, [medplum]);
|
|
4652
|
-
|
|
4675
|
+
e.useEffect(() => {
|
|
4653
4676
|
setValue(ensurePlanDefinitionKeys(defaultValue ?? { resourceType: 'PlanDefinition' }));
|
|
4654
4677
|
document.addEventListener('mouseover', handleDocumentMouseOver);
|
|
4655
4678
|
document.addEventListener('click', handleDocumentClick);
|
|
@@ -4667,15 +4690,15 @@
|
|
|
4667
4690
|
[property]: newValue,
|
|
4668
4691
|
});
|
|
4669
4692
|
}
|
|
4670
|
-
return (
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4693
|
+
return (e.createElement("div", null,
|
|
4694
|
+
e.createElement(Form, { testid: "questionnaire-form", onSubmit: () => props.onSubmit(value) },
|
|
4695
|
+
e.createElement(core$1.TextInput, { label: "Plan Title", defaultValue: value.title, onChange: (e) => changeProperty('title', e.currentTarget.value) }),
|
|
4696
|
+
e.createElement(ActionArrayBuilder, { actions: value.action || [], selectedKey: selectedKey, setSelectedKey: setSelectedKey, hoverKey: hoverKey, setHoverKey: setHoverKey, onChange: (x) => changeProperty('action', x) }),
|
|
4697
|
+
e.createElement(core$1.Button, { type: "submit" }, "Save"))));
|
|
4675
4698
|
}
|
|
4676
4699
|
function ActionArrayBuilder(props) {
|
|
4677
4700
|
const { classes } = useStyles$5();
|
|
4678
|
-
const actionsRef =
|
|
4701
|
+
const actionsRef = e.useRef();
|
|
4679
4702
|
actionsRef.current = props.actions;
|
|
4680
4703
|
function changeAction(changedAction) {
|
|
4681
4704
|
props.onChange(actionsRef.current.map((i) => (i.id === changedAction.id ? changedAction : i)));
|
|
@@ -4687,11 +4710,11 @@
|
|
|
4687
4710
|
function removeAction(removedAction) {
|
|
4688
4711
|
props.onChange(actionsRef.current.filter((i) => i !== removedAction));
|
|
4689
4712
|
}
|
|
4690
|
-
return (
|
|
4691
|
-
props.actions.map((action) => (
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4713
|
+
return (e.createElement("div", { className: classes.section },
|
|
4714
|
+
props.actions.map((action) => (e.createElement("div", { key: action.id },
|
|
4715
|
+
e.createElement(ActionBuilder, { action: action, selectedKey: props.selectedKey, setSelectedKey: props.setSelectedKey, hoverKey: props.hoverKey, setHoverKey: props.setHoverKey, onChange: changeAction, onRemove: () => removeAction(action) })))),
|
|
4716
|
+
e.createElement("div", { className: classes.bottomActions },
|
|
4717
|
+
e.createElement(core$1.Anchor, { href: "#", onClick: (e) => {
|
|
4695
4718
|
killEvent(e);
|
|
4696
4719
|
addAction({ id: generateId$1() });
|
|
4697
4720
|
} }, "Add action"))));
|
|
@@ -4714,10 +4737,10 @@
|
|
|
4714
4737
|
[classes.editing]: editing,
|
|
4715
4738
|
[classes.hovering]: hovering && !editing,
|
|
4716
4739
|
});
|
|
4717
|
-
return (
|
|
4718
|
-
editing ? (
|
|
4719
|
-
|
|
4720
|
-
|
|
4740
|
+
return (e.createElement("div", { "data-testid": action.id, className: className, onClick: onClick, onMouseOver: onHover },
|
|
4741
|
+
editing ? (e.createElement(ActionEditor, { action: action, actionType: actionType, onChange: props.onChange, selectedKey: props.selectedKey, setSelectedKey: props.setSelectedKey, hoverKey: props.hoverKey, setHoverKey: props.setHoverKey, onRemove: props.onRemove })) : (e.createElement(ActionDisplay, { action: action, actionType: actionType })),
|
|
4742
|
+
e.createElement("div", { className: classes.bottomActions },
|
|
4743
|
+
e.createElement(core$1.Anchor, { href: "#", onClick: (e) => {
|
|
4721
4744
|
e.preventDefault();
|
|
4722
4745
|
props.onRemove();
|
|
4723
4746
|
} }, "Remove"))));
|
|
@@ -4731,53 +4754,53 @@
|
|
|
4731
4754
|
function ActionDisplay(props) {
|
|
4732
4755
|
const { action, actionType } = props;
|
|
4733
4756
|
const [propertyValue, propertyType] = getActionTiming(action);
|
|
4734
|
-
return (
|
|
4735
|
-
|
|
4757
|
+
return (e.createElement("div", null,
|
|
4758
|
+
e.createElement("div", null,
|
|
4736
4759
|
action.title || 'Untitled',
|
|
4737
4760
|
" ",
|
|
4738
4761
|
actionType && `(${actionType})`),
|
|
4739
|
-
action.definitionCanonical && (
|
|
4740
|
-
|
|
4741
|
-
propertyValue && (
|
|
4742
|
-
|
|
4762
|
+
action.definitionCanonical && (e.createElement("div", null,
|
|
4763
|
+
e.createElement(ReferenceDisplay, { value: { reference: action.definitionCanonical } }))),
|
|
4764
|
+
propertyValue && (e.createElement("div", null,
|
|
4765
|
+
e.createElement(ResourcePropertyDisplay, { property: timingProperty, propertyType: propertyType, value: propertyValue })))));
|
|
4743
4766
|
}
|
|
4744
4767
|
function ActionEditor(props) {
|
|
4745
4768
|
const { action } = props;
|
|
4746
|
-
const [actionType, setActionType] =
|
|
4769
|
+
const [actionType, setActionType] = e.useState(props.actionType);
|
|
4747
4770
|
function changeProperty(property, value) {
|
|
4748
4771
|
props.onChange({
|
|
4749
4772
|
...action,
|
|
4750
4773
|
[property]: value,
|
|
4751
4774
|
});
|
|
4752
4775
|
}
|
|
4753
|
-
return (
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
action.action && action.action.length > 0 && (
|
|
4776
|
+
return (e.createElement(core$1.Stack, { spacing: "xl" },
|
|
4777
|
+
e.createElement(core$1.TextInput, { name: `actionTitle-${action.id}`, label: "Title", defaultValue: action.title, onChange: (e) => changeProperty('title', e.currentTarget.value) }),
|
|
4778
|
+
e.createElement(core$1.TextInput, { name: `actionDescription-${action.id}`, label: "Description", defaultValue: action.description, onChange: (e) => changeProperty('description', e.currentTarget.value) }),
|
|
4779
|
+
e.createElement(core$1.NativeSelect, { label: "Type of Action", description: "The type of the action to be performed.", name: `actionType-${action.id}`, defaultValue: actionType, onChange: (e) => setActionType(e.currentTarget.value), data: ['', 'appointment', 'lab', 'questionnaire', 'task'] }),
|
|
4780
|
+
action.action && action.action.length > 0 && (e.createElement(ActionArrayBuilder, { actions: action.action, selectedKey: props.selectedKey, setSelectedKey: props.setSelectedKey, hoverKey: props.hoverKey, setHoverKey: props.setHoverKey, onChange: (x) => changeProperty('action', x) })),
|
|
4758
4781
|
(() => {
|
|
4759
4782
|
switch (actionType) {
|
|
4760
4783
|
case 'appointment':
|
|
4761
|
-
return (
|
|
4784
|
+
return (e.createElement(ActionResourceTypeBuilder, { title: "Appointment", description: "The subject must schedule an appointment from the schedule.", resourceType: "Schedule", action: action, onChange: props.onChange }));
|
|
4762
4785
|
case 'lab':
|
|
4763
|
-
return (
|
|
4786
|
+
return (e.createElement(ActionResourceTypeBuilder, { title: "Lab", description: "The subject must complete the following lab panel.", resourceType: "ActivityDefinition", action: action, onChange: props.onChange }));
|
|
4764
4787
|
case 'questionnaire':
|
|
4765
|
-
return (
|
|
4788
|
+
return (e.createElement(ActionResourceTypeBuilder, { title: "Questionnaire", description: "The subject must complete the selected questionnaire.", resourceType: "Questionnaire", action: action, onChange: props.onChange }));
|
|
4766
4789
|
case 'task':
|
|
4767
|
-
return (
|
|
4790
|
+
return (e.createElement(ActionResourceTypeBuilder, { title: "Task", description: "The subject must complete the following task.", resourceType: "ActivityDefinition", action: action, onChange: props.onChange }));
|
|
4768
4791
|
default:
|
|
4769
4792
|
return null;
|
|
4770
4793
|
}
|
|
4771
4794
|
})(),
|
|
4772
|
-
|
|
4773
|
-
|
|
4795
|
+
e.createElement(FormSection, { title: "Timing", description: "When the action should take place." },
|
|
4796
|
+
e.createElement(ActionTimingInput, { name: 'timing-' + action.id, action: action, onChange: props.onChange }))));
|
|
4774
4797
|
}
|
|
4775
4798
|
function ActionResourceTypeBuilder(props) {
|
|
4776
4799
|
const { id, definitionCanonical } = props.action;
|
|
4777
4800
|
const reference = definitionCanonical?.startsWith(props.resourceType + '/')
|
|
4778
4801
|
? { reference: definitionCanonical }
|
|
4779
4802
|
: undefined;
|
|
4780
|
-
return (
|
|
4803
|
+
return (e.createElement(ResourceInput, { name: id, resourceType: props.resourceType, defaultValue: reference, loadOnFocus: true, onChange: (newValue) => {
|
|
4781
4804
|
if (newValue) {
|
|
4782
4805
|
props.onChange({ ...props.action, definitionCanonical: core.getReferenceString(newValue) });
|
|
4783
4806
|
}
|
|
@@ -4790,7 +4813,7 @@
|
|
|
4790
4813
|
const value = props.action;
|
|
4791
4814
|
const key = 'timing';
|
|
4792
4815
|
const [propertyValue, propertyType] = getActionTiming(value);
|
|
4793
|
-
return (
|
|
4816
|
+
return (e.createElement(ResourcePropertyInput, { property: timingProperty, name: "timing[x]", defaultValue: propertyValue, defaultPropertyType: propertyType, onChange: (newValue, propName) => {
|
|
4794
4817
|
props.onChange(setPropertyValue(value, key, propName ?? key, timingProperty, newValue));
|
|
4795
4818
|
} }));
|
|
4796
4819
|
}
|
|
@@ -4873,24 +4896,23 @@
|
|
|
4873
4896
|
function QuestionnaireForm(props) {
|
|
4874
4897
|
const medplum = useMedplum();
|
|
4875
4898
|
const source = medplum.getProfile();
|
|
4876
|
-
const [schema, setSchema] =
|
|
4899
|
+
const [schema, setSchema] = e.useState();
|
|
4877
4900
|
const questionnaire = useResource(props.questionnaire);
|
|
4878
|
-
const [response, setResponse] =
|
|
4879
|
-
const [answers, setAnswers] =
|
|
4880
|
-
|
|
4901
|
+
const [response, setResponse] = e.useState();
|
|
4902
|
+
const [answers, setAnswers] = e.useState({});
|
|
4903
|
+
e.useEffect(() => {
|
|
4881
4904
|
medplum
|
|
4882
4905
|
.requestSchema('Questionnaire')
|
|
4883
4906
|
.then(() => medplum.requestSchema('QuestionnaireResponse'))
|
|
4884
4907
|
.then(setSchema)
|
|
4885
4908
|
.catch(console.log);
|
|
4886
4909
|
}, [medplum]);
|
|
4887
|
-
|
|
4910
|
+
e.useEffect(() => {
|
|
4888
4911
|
setResponse(questionnaire ? buildInitialResponse(questionnaire) : undefined);
|
|
4889
4912
|
}, [questionnaire]);
|
|
4890
4913
|
function setItems(newResponseItems) {
|
|
4891
4914
|
const newResponse = {
|
|
4892
4915
|
resourceType: 'QuestionnaireResponse',
|
|
4893
|
-
status: 'completed',
|
|
4894
4916
|
item: newResponseItems,
|
|
4895
4917
|
};
|
|
4896
4918
|
setResponse(newResponse);
|
|
@@ -4899,7 +4921,7 @@
|
|
|
4899
4921
|
if (!schema || !questionnaire) {
|
|
4900
4922
|
return null;
|
|
4901
4923
|
}
|
|
4902
|
-
return (
|
|
4924
|
+
return (e.createElement(Form, { testid: "questionnaire-form", onSubmit: () => {
|
|
4903
4925
|
if (props.onSubmit && response) {
|
|
4904
4926
|
props.onSubmit({
|
|
4905
4927
|
...response,
|
|
@@ -4907,43 +4929,44 @@
|
|
|
4907
4929
|
subject: props.subject,
|
|
4908
4930
|
source: core.createReference(source),
|
|
4909
4931
|
authored: new Date().toISOString(),
|
|
4932
|
+
status: 'completed',
|
|
4910
4933
|
});
|
|
4911
4934
|
}
|
|
4912
4935
|
} },
|
|
4913
|
-
questionnaire.title &&
|
|
4914
|
-
questionnaire.item && (
|
|
4915
|
-
|
|
4916
|
-
|
|
4936
|
+
questionnaire.title && e.createElement(core$1.Title, null, questionnaire.title),
|
|
4937
|
+
questionnaire.item && (e.createElement(QuestionnaireFormItemArray, { items: questionnaire.item, answers: answers, onChange: setItems })),
|
|
4938
|
+
e.createElement(core$1.Group, { position: "right", mt: "xl" },
|
|
4939
|
+
e.createElement(core$1.Button, { type: "submit" }, props.submitButtonText || 'OK'))));
|
|
4917
4940
|
}
|
|
4918
4941
|
function QuestionnaireFormItemArray(props) {
|
|
4919
|
-
const [responseItems, setResponseItems] =
|
|
4942
|
+
const [responseItems, setResponseItems] = e.useState(buildInitialResponseItems(props.items));
|
|
4920
4943
|
function setResponseItem(index, newResponseItem) {
|
|
4921
4944
|
const newResponseItems = responseItems.slice();
|
|
4922
4945
|
newResponseItems[index] = newResponseItem;
|
|
4923
4946
|
setResponseItems(newResponseItems);
|
|
4924
4947
|
props.onChange(newResponseItems);
|
|
4925
4948
|
}
|
|
4926
|
-
return (
|
|
4949
|
+
return (e.createElement(core$1.Stack, null, props.items.map((item, index) => {
|
|
4927
4950
|
if (!isQuestionEnabled(item, props.answers)) {
|
|
4928
4951
|
return null;
|
|
4929
4952
|
}
|
|
4930
4953
|
if (item.type === exports.QuestionnaireItemType.display) {
|
|
4931
|
-
return
|
|
4954
|
+
return e.createElement("p", { key: item.linkId }, item.text);
|
|
4932
4955
|
}
|
|
4933
4956
|
if (item.type === exports.QuestionnaireItemType.group) {
|
|
4934
|
-
return (
|
|
4957
|
+
return (e.createElement(QuestionnaireFormItem, { key: item.linkId, item: item, answers: props.answers, onChange: (newResponseItem) => setResponseItem(index, newResponseItem) }));
|
|
4935
4958
|
}
|
|
4936
4959
|
if (item.type === exports.QuestionnaireItemType.boolean) {
|
|
4937
4960
|
const initial = item.initial && item.initial.length > 0 ? item.initial[0] : undefined;
|
|
4938
|
-
return (
|
|
4939
|
-
|
|
4961
|
+
return (e.createElement(CheckboxFormSection, { key: item.linkId, title: item.text, htmlFor: item.linkId },
|
|
4962
|
+
e.createElement(core$1.Checkbox, { id: item.linkId, name: item.linkId, defaultChecked: initial?.valueBoolean, onChange: (e) => setResponseItem(index, {
|
|
4940
4963
|
linkId: item.linkId,
|
|
4941
4964
|
text: item.text,
|
|
4942
4965
|
answer: [{ valueBoolean: e.currentTarget.checked }],
|
|
4943
4966
|
}) })));
|
|
4944
4967
|
}
|
|
4945
|
-
return (
|
|
4946
|
-
|
|
4968
|
+
return (e.createElement(FormSection, { key: item.linkId, htmlFor: item.linkId, title: item.text || '' },
|
|
4969
|
+
e.createElement(QuestionnaireFormItem, { item: item, answers: props.answers, onChange: (newResponseItem) => setResponseItem(index, newResponseItem) })));
|
|
4947
4970
|
})));
|
|
4948
4971
|
}
|
|
4949
4972
|
function QuestionnaireFormItem(props) {
|
|
@@ -4973,39 +4996,39 @@
|
|
|
4973
4996
|
}
|
|
4974
4997
|
switch (type) {
|
|
4975
4998
|
case exports.QuestionnaireItemType.group:
|
|
4976
|
-
return (
|
|
4977
|
-
|
|
4978
|
-
item.item && (
|
|
4999
|
+
return (e.createElement("div", null,
|
|
5000
|
+
e.createElement("h3", null, item.text),
|
|
5001
|
+
item.item && (e.createElement(QuestionnaireFormItemArray, { items: item.item, answers: props.answers, onChange: onChangeItem }))));
|
|
4979
5002
|
case exports.QuestionnaireItemType.boolean:
|
|
4980
|
-
return (
|
|
5003
|
+
return (e.createElement(core$1.Checkbox, { id: name, name: name, defaultChecked: initial?.valueBoolean, onChange: (e) => onChangeAnswer({ valueBoolean: e.currentTarget.checked }) }));
|
|
4981
5004
|
case exports.QuestionnaireItemType.decimal:
|
|
4982
|
-
return (
|
|
5005
|
+
return (e.createElement(core$1.TextInput, { type: "number", step: "any", id: name, name: name, defaultValue: initial?.valueDecimal, onChange: (e) => onChangeAnswer({ valueDecimal: e.currentTarget.valueAsNumber }) }));
|
|
4983
5006
|
case exports.QuestionnaireItemType.integer:
|
|
4984
|
-
return (
|
|
5007
|
+
return (e.createElement(core$1.TextInput, { type: "number", step: 1, id: name, name: name, defaultValue: initial?.valueInteger, onChange: (e) => onChangeAnswer({ valueInteger: e.currentTarget.valueAsNumber }) }));
|
|
4985
5008
|
case exports.QuestionnaireItemType.date:
|
|
4986
|
-
return (
|
|
5009
|
+
return (e.createElement(core$1.TextInput, { type: "date", id: name, name: name, defaultValue: initial?.valueDate, onChange: (e) => onChangeAnswer({ valueDate: e.currentTarget.value }) }));
|
|
4987
5010
|
case exports.QuestionnaireItemType.dateTime:
|
|
4988
|
-
return (
|
|
5011
|
+
return (e.createElement(DateTimeInput, { name: name, defaultValue: initial?.valueDateTime, onChange: (newValue) => onChangeAnswer({ valueDateTime: newValue }) }));
|
|
4989
5012
|
case exports.QuestionnaireItemType.time:
|
|
4990
|
-
return (
|
|
5013
|
+
return (e.createElement(core$1.TextInput, { type: "time", id: name, name: name, defaultValue: initial?.valueTime, onChange: (e) => onChangeAnswer({ valueTime: e.currentTarget.value }) }));
|
|
4991
5014
|
case exports.QuestionnaireItemType.string:
|
|
4992
5015
|
case exports.QuestionnaireItemType.url:
|
|
4993
|
-
return (
|
|
5016
|
+
return (e.createElement(core$1.TextInput, { id: name, name: name, defaultValue: initial?.valueString, onChange: (e) => onChangeAnswer({ valueString: e.currentTarget.value }) }));
|
|
4994
5017
|
case exports.QuestionnaireItemType.text:
|
|
4995
|
-
return (
|
|
5018
|
+
return (e.createElement(core$1.Textarea, { id: name, name: name, defaultValue: initial?.valueString, onChange: (e) => onChangeAnswer({ valueString: e.currentTarget.value }) }));
|
|
4996
5019
|
case exports.QuestionnaireItemType.attachment:
|
|
4997
|
-
return (
|
|
5020
|
+
return (e.createElement(AttachmentInput, { name: name, defaultValue: initial?.valueAttachment, onChange: (newValue) => onChangeAnswer({ valueAttachment: newValue }) }));
|
|
4998
5021
|
case exports.QuestionnaireItemType.reference:
|
|
4999
|
-
return (
|
|
5022
|
+
return (e.createElement(ReferenceInput, { name: name, defaultValue: initial?.valueReference, onChange: (newValue) => onChangeAnswer({ valueReference: newValue }) }));
|
|
5000
5023
|
case exports.QuestionnaireItemType.quantity:
|
|
5001
|
-
return (
|
|
5024
|
+
return (e.createElement(QuantityInput, { name: name, defaultValue: initial?.valueQuantity, onChange: (newValue) => onChangeAnswer({ valueQuantity: newValue }), disableWheel: true }));
|
|
5002
5025
|
case exports.QuestionnaireItemType.choice:
|
|
5003
5026
|
case exports.QuestionnaireItemType.openChoice:
|
|
5004
5027
|
if (isDropDownChoice(item)) {
|
|
5005
|
-
return (
|
|
5028
|
+
return (e.createElement(QuestionnaireChoiceDropDownInput, { name: name, item: item, initial: initial, onChangeAnswer: onChangeAnswer }));
|
|
5006
5029
|
}
|
|
5007
5030
|
else {
|
|
5008
|
-
return (
|
|
5031
|
+
return (e.createElement(QuestionnaireChoiceRadioInput, { name: name, item: item, initial: initial, onChangeAnswer: onChangeAnswer }));
|
|
5009
5032
|
}
|
|
5010
5033
|
}
|
|
5011
5034
|
return null;
|
|
@@ -5020,7 +5043,7 @@
|
|
|
5020
5043
|
data.push(typedValueToString(optionValue));
|
|
5021
5044
|
}
|
|
5022
5045
|
}
|
|
5023
|
-
return (
|
|
5046
|
+
return (e.createElement(core$1.NativeSelect, { id: name, name: name, onChange: (e) => {
|
|
5024
5047
|
const index = e.currentTarget.selectedIndex;
|
|
5025
5048
|
if (index === 0) {
|
|
5026
5049
|
props.onChangeAnswer({});
|
|
@@ -5061,14 +5084,14 @@
|
|
|
5061
5084
|
options.push([optionName, optionValue]);
|
|
5062
5085
|
}
|
|
5063
5086
|
}
|
|
5064
|
-
return (
|
|
5087
|
+
return (e.createElement(core$1.Radio.Group, { name: name, orientation: "vertical", defaultValue: defaultValue, onChange: (newValue) => {
|
|
5065
5088
|
const option = options.find((option) => option[0] === newValue);
|
|
5066
5089
|
if (option) {
|
|
5067
5090
|
const optionValue = option[1];
|
|
5068
5091
|
const propertyName = 'value' + core.capitalize(optionValue.type);
|
|
5069
5092
|
onChangeAnswer({ [propertyName]: optionValue.value });
|
|
5070
5093
|
}
|
|
5071
|
-
} }, options.map(([optionName, optionValue]) => (
|
|
5094
|
+
} }, options.map(([optionName, optionValue]) => (e.createElement(core$1.Radio, { key: optionName, id: optionName, value: optionName, label: e.createElement(ResourcePropertyDisplay, { property: valueElementDefinition, propertyType: optionValue.type, value: optionValue.value }) })))));
|
|
5072
5095
|
}
|
|
5073
5096
|
function buildInitialResponse(questionnaire) {
|
|
5074
5097
|
const response = {
|
|
@@ -5175,20 +5198,20 @@
|
|
|
5175
5198
|
function QuestionnaireBuilder(props) {
|
|
5176
5199
|
const medplum = useMedplum();
|
|
5177
5200
|
const defaultValue = useResource(props.questionnaire);
|
|
5178
|
-
const [schema, setSchema] =
|
|
5179
|
-
const [value, setValue] =
|
|
5180
|
-
const [selectedKey, setSelectedKey] =
|
|
5181
|
-
const [hoverKey, setHoverKey] =
|
|
5201
|
+
const [schema, setSchema] = e.useState();
|
|
5202
|
+
const [value, setValue] = e.useState();
|
|
5203
|
+
const [selectedKey, setSelectedKey] = e.useState();
|
|
5204
|
+
const [hoverKey, setHoverKey] = e.useState();
|
|
5182
5205
|
function handleDocumentMouseOver() {
|
|
5183
5206
|
setHoverKey(undefined);
|
|
5184
5207
|
}
|
|
5185
5208
|
function handleDocumentClick() {
|
|
5186
5209
|
setSelectedKey(undefined);
|
|
5187
5210
|
}
|
|
5188
|
-
|
|
5211
|
+
e.useEffect(() => {
|
|
5189
5212
|
medplum.requestSchema('Questionnaire').then(setSchema).catch(console.log);
|
|
5190
5213
|
}, [medplum]);
|
|
5191
|
-
|
|
5214
|
+
e.useEffect(() => {
|
|
5192
5215
|
setValue(ensureQuestionnaireKeys(defaultValue ?? { resourceType: 'Questionnaire' }));
|
|
5193
5216
|
document.addEventListener('mouseover', handleDocumentMouseOver);
|
|
5194
5217
|
document.addEventListener('click', handleDocumentClick);
|
|
@@ -5200,10 +5223,10 @@
|
|
|
5200
5223
|
if (!schema || !value) {
|
|
5201
5224
|
return null;
|
|
5202
5225
|
}
|
|
5203
|
-
return (
|
|
5204
|
-
|
|
5205
|
-
|
|
5206
|
-
|
|
5226
|
+
return (e.createElement("div", null,
|
|
5227
|
+
e.createElement(Form, { testid: "questionnaire-form", onSubmit: () => props.onSubmit(value) },
|
|
5228
|
+
e.createElement(ItemBuilder, { item: value, selectedKey: selectedKey, setSelectedKey: setSelectedKey, hoverKey: hoverKey, setHoverKey: setHoverKey, onChange: setValue }),
|
|
5229
|
+
e.createElement(core$1.Button, { type: "submit" }, "Save"))));
|
|
5207
5230
|
}
|
|
5208
5231
|
function ItemBuilder(props) {
|
|
5209
5232
|
const { classes, cx } = useStyles$4();
|
|
@@ -5214,7 +5237,7 @@
|
|
|
5214
5237
|
const linkId = item.linkId ?? '[untitled]';
|
|
5215
5238
|
const editing = props.selectedKey === props.item.id;
|
|
5216
5239
|
const hovering = props.hoverKey === props.item.id;
|
|
5217
|
-
const itemRef =
|
|
5240
|
+
const itemRef = e.useRef();
|
|
5218
5241
|
itemRef.current = props.item;
|
|
5219
5242
|
function onClick(e) {
|
|
5220
5243
|
killEvent(e);
|
|
@@ -5253,20 +5276,20 @@
|
|
|
5253
5276
|
[classes.editing]: editing,
|
|
5254
5277
|
[classes.hovering]: hovering && !editing,
|
|
5255
5278
|
});
|
|
5256
|
-
return (
|
|
5257
|
-
|
|
5258
|
-
isResource && (
|
|
5259
|
-
!isResource && (
|
|
5260
|
-
isChoiceQuestion(item) && (
|
|
5261
|
-
resource.title &&
|
|
5262
|
-
item.text &&
|
|
5263
|
-
!isContainer &&
|
|
5279
|
+
return (e.createElement("div", { "data-testid": item.linkId, className: className, onClick: onClick, onMouseOver: onHover },
|
|
5280
|
+
e.createElement("div", { className: classes.questionBody }, editing ? (e.createElement(e.Fragment, null,
|
|
5281
|
+
isResource && (e.createElement(core$1.TextInput, { size: "xl", defaultValue: resource.title, onChange: (e) => changeProperty('title', e.currentTarget.value) })),
|
|
5282
|
+
!isResource && (e.createElement(core$1.Textarea, { autosize: true, minRows: 2, defaultValue: item.text, onChange: (e) => changeProperty('text', e.currentTarget.value) })),
|
|
5283
|
+
isChoiceQuestion(item) && (e.createElement(AnswerBuilder, { options: item.answerOption, onChange: (newOptions) => changeProperty('answerOption', newOptions) })))) : (e.createElement(e.Fragment, null,
|
|
5284
|
+
resource.title && e.createElement(core$1.Title, null, resource.title),
|
|
5285
|
+
item.text && e.createElement("div", null, item.text),
|
|
5286
|
+
!isContainer && e.createElement(QuestionnaireFormItem, { item: item, answers: {}, onChange: () => undefined })))),
|
|
5264
5287
|
item.item &&
|
|
5265
|
-
item.item.map((i) => (
|
|
5266
|
-
|
|
5267
|
-
!isContainer && (
|
|
5268
|
-
|
|
5269
|
-
!isContainer && (
|
|
5288
|
+
item.item.map((i) => (e.createElement("div", { key: i.id },
|
|
5289
|
+
e.createElement(ItemBuilder, { item: i, selectedKey: props.selectedKey, setSelectedKey: props.setSelectedKey, hoverKey: props.hoverKey, setHoverKey: props.setHoverKey, onChange: changeItem, onRemove: () => removeItem(i) })))),
|
|
5290
|
+
!isContainer && (e.createElement("div", { className: classes.topActions }, editing ? (e.createElement(e.Fragment, null,
|
|
5291
|
+
e.createElement(core$1.TextInput, { size: "xs", className: classes.linkIdInput, defaultValue: item.linkId, onChange: (e) => changeProperty('linkId', e.currentTarget.value) }),
|
|
5292
|
+
!isContainer && (e.createElement(core$1.NativeSelect, { size: "xs", className: classes.typeSelect, defaultValue: item.type, onChange: (e) => changeProperty('type', e.currentTarget.value), data: [
|
|
5270
5293
|
{ value: 'display', label: 'Display' },
|
|
5271
5294
|
{ value: 'boolean', label: 'Boolean' },
|
|
5272
5295
|
{ value: 'decimal', label: 'Decimal' },
|
|
@@ -5282,10 +5305,10 @@
|
|
|
5282
5305
|
{ value: 'attachment', label: 'Attachment' },
|
|
5283
5306
|
{ value: 'reference', label: 'Reference' },
|
|
5284
5307
|
{ value: 'quantity', label: 'Quantity' },
|
|
5285
|
-
] })))) : (
|
|
5286
|
-
|
|
5287
|
-
isContainer && (
|
|
5288
|
-
|
|
5308
|
+
] })))) : (e.createElement("div", null, linkId)))),
|
|
5309
|
+
e.createElement("div", { className: classes.bottomActions },
|
|
5310
|
+
isContainer && (e.createElement(e.Fragment, null,
|
|
5311
|
+
e.createElement(core$1.Anchor, { href: "#", onClick: (e) => {
|
|
5289
5312
|
e.preventDefault();
|
|
5290
5313
|
addItem({
|
|
5291
5314
|
id: generateId(),
|
|
@@ -5294,7 +5317,7 @@
|
|
|
5294
5317
|
text: 'Question',
|
|
5295
5318
|
});
|
|
5296
5319
|
} }, "Add item"),
|
|
5297
|
-
|
|
5320
|
+
e.createElement(core$1.Anchor, { href: "#", onClick: (e) => {
|
|
5298
5321
|
e.preventDefault();
|
|
5299
5322
|
addItem({
|
|
5300
5323
|
id: generateId(),
|
|
@@ -5303,7 +5326,7 @@
|
|
|
5303
5326
|
text: 'Group',
|
|
5304
5327
|
});
|
|
5305
5328
|
} }, "Add group"))),
|
|
5306
|
-
editing && !isResource && (
|
|
5329
|
+
editing && !isResource && (e.createElement(core$1.Anchor, { href: "#", onClick: (e) => {
|
|
5307
5330
|
e.preventDefault();
|
|
5308
5331
|
if (props.onRemove) {
|
|
5309
5332
|
props.onRemove();
|
|
@@ -5313,30 +5336,30 @@
|
|
|
5313
5336
|
function AnswerBuilder(props) {
|
|
5314
5337
|
const property = core.globalSchema.types['QuestionnaireItemAnswerOption'].properties['value[x]'];
|
|
5315
5338
|
const options = props.options ?? [];
|
|
5316
|
-
return (
|
|
5339
|
+
return (e.createElement("div", null,
|
|
5317
5340
|
options.map((option) => {
|
|
5318
5341
|
const [propertyValue, propertyType] = getValueAndType({ type: 'QuestionnaireItemAnswerOption', value: option }, 'value');
|
|
5319
|
-
return (
|
|
5342
|
+
return (e.createElement("div", { key: option.id, style: {
|
|
5320
5343
|
display: 'flex',
|
|
5321
5344
|
flexDirection: 'row',
|
|
5322
5345
|
justifyContent: 'space-between',
|
|
5323
5346
|
alignItems: 'center',
|
|
5324
5347
|
width: '80%',
|
|
5325
5348
|
} },
|
|
5326
|
-
|
|
5327
|
-
|
|
5349
|
+
e.createElement("div", null,
|
|
5350
|
+
e.createElement(ResourcePropertyInput, { key: option.id, name: "value[x]", property: property, defaultPropertyType: propertyType, defaultValue: propertyValue, onChange: (newValue, propName) => {
|
|
5328
5351
|
const newOptions = [...options];
|
|
5329
5352
|
const index = newOptions.findIndex((o) => o.id === option.id);
|
|
5330
5353
|
newOptions[index] = { id: option.id, [propName]: newValue };
|
|
5331
5354
|
props.onChange(newOptions);
|
|
5332
5355
|
} })),
|
|
5333
|
-
|
|
5334
|
-
|
|
5356
|
+
e.createElement("div", null,
|
|
5357
|
+
e.createElement(core$1.Anchor, { href: "#", onClick: (e) => {
|
|
5335
5358
|
killEvent(e);
|
|
5336
5359
|
props.onChange(options.filter((o) => o.id !== option.id));
|
|
5337
5360
|
} }, "Remove"))));
|
|
5338
5361
|
}),
|
|
5339
|
-
|
|
5362
|
+
e.createElement(core$1.Anchor, { href: "#", onClick: (e) => {
|
|
5340
5363
|
killEvent(e);
|
|
5341
5364
|
props.onChange([
|
|
5342
5365
|
...options,
|
|
@@ -5423,23 +5446,23 @@
|
|
|
5423
5446
|
function ReferenceRangeEditor(props) {
|
|
5424
5447
|
props = Object.assign(defaultProps, props);
|
|
5425
5448
|
const defaultDefinition = props.definition;
|
|
5426
|
-
const [intervalGroups, setIntervalGroups] =
|
|
5427
|
-
const [groupId, setGroupId] =
|
|
5428
|
-
const [intervalId, setIntervalId] =
|
|
5429
|
-
|
|
5449
|
+
const [intervalGroups, setIntervalGroups] = e.useState([]);
|
|
5450
|
+
const [groupId, setGroupId] = e.useState(1);
|
|
5451
|
+
const [intervalId, setIntervalId] = e.useState(1);
|
|
5452
|
+
e.useEffect(() => {
|
|
5430
5453
|
const definition = ensureQualifiedIntervalKeys(defaultDefinition, setIntervalId);
|
|
5431
5454
|
setIntervalGroups(groupQualifiedIntervals(definition.qualifiedInterval || [], setGroupId));
|
|
5432
5455
|
}, [defaultDefinition]);
|
|
5433
|
-
return (
|
|
5434
|
-
|
|
5435
|
-
|
|
5456
|
+
return (e.createElement(Form, { testid: "reference-range-editor", onSubmit: submitDefinition },
|
|
5457
|
+
e.createElement(core$1.Stack, null, intervalGroups.map((intervalGroup) => (e.createElement(ReferenceRangeGroupEditor, { unit: getUnitString(defaultDefinition.quantitativeDetails?.unit), onChange: changeInterval, onAdd: addInterval, onRemove: removeInterval, onRemoveGroup: removeGroup, key: `group-${intervalGroup.id}`, intervalGroup: intervalGroup })))),
|
|
5458
|
+
e.createElement(core$1.ActionIcon, { title: "Add Group", size: "sm", onClick: (e) => {
|
|
5436
5459
|
killEvent(e);
|
|
5437
5460
|
addGroup({ id: `group-id-${groupId}`, filters: {}, intervals: [] });
|
|
5438
5461
|
setGroupId((id) => id + 1);
|
|
5439
5462
|
} },
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5463
|
+
e.createElement(iS, null)),
|
|
5464
|
+
e.createElement(core$1.Group, { position: "right" },
|
|
5465
|
+
e.createElement(core$1.Button, { type: "submit" }, "Save"))));
|
|
5443
5466
|
/**
|
|
5444
5467
|
* Submit qualified intervals
|
|
5445
5468
|
*/
|
|
@@ -5503,31 +5526,31 @@
|
|
|
5503
5526
|
function ReferenceRangeGroupEditor(props) {
|
|
5504
5527
|
const { intervalGroup, unit } = props;
|
|
5505
5528
|
const { classes } = useStyles$3();
|
|
5506
|
-
return (
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
|
|
5529
|
+
return (e.createElement(Container, { "data-testid": intervalGroup.id, className: classes.section },
|
|
5530
|
+
e.createElement(core$1.Stack, { spacing: 'lg' },
|
|
5531
|
+
e.createElement(core$1.Group, { position: "right" },
|
|
5532
|
+
e.createElement(core$1.ActionIcon, { title: "Remove Group", "data-testid": `remove-group-button-${intervalGroup.id}`, key: `remove-group-button-${intervalGroup.id}`, size: "sm", onClick: (e) => {
|
|
5510
5533
|
killEvent(e);
|
|
5511
5534
|
props.onRemoveGroup(intervalGroup);
|
|
5512
5535
|
} },
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
intervalGroup.intervals.map((interval) => (
|
|
5517
|
-
|
|
5518
|
-
|
|
5536
|
+
e.createElement(IP, null))),
|
|
5537
|
+
e.createElement(ReferenceRangeGroupFilters, { intervalGroup: intervalGroup, onChange: props.onChange }),
|
|
5538
|
+
e.createElement(core$1.Divider, null),
|
|
5539
|
+
intervalGroup.intervals.map((interval) => (e.createElement(core$1.Stack, { key: `interval-${interval.id}`, spacing: 'xs' },
|
|
5540
|
+
e.createElement(core$1.Group, null,
|
|
5541
|
+
e.createElement(core$1.TextInput, { key: `condition-${interval.id}`, "data-testid": `condition-${interval.id}`, defaultValue: interval.condition, label: 'Condition: ', size: 'sm', onChange: (e) => {
|
|
5519
5542
|
killEvent(e);
|
|
5520
5543
|
props.onChange(intervalGroup.id, { ...interval, condition: e.currentTarget.value.trim() });
|
|
5521
5544
|
} }),
|
|
5522
|
-
|
|
5545
|
+
e.createElement(core$1.ActionIcon, { title: "Remove Interval", size: "sm", key: `remove-interval-${interval.id}`, "data-testid": `remove-interval-${interval.id}`, onClick: (e) => {
|
|
5523
5546
|
killEvent(e);
|
|
5524
5547
|
props.onRemove(intervalGroup.id, interval);
|
|
5525
5548
|
} },
|
|
5526
|
-
|
|
5527
|
-
|
|
5549
|
+
e.createElement(IP, null))),
|
|
5550
|
+
e.createElement(RangeInput, { onChange: (range) => {
|
|
5528
5551
|
props.onChange(intervalGroup.id, { ...interval, range });
|
|
5529
5552
|
}, key: `range-${interval.id}`, name: `range-${interval.id}`, defaultValue: interval.range })))),
|
|
5530
|
-
|
|
5553
|
+
e.createElement(core$1.ActionIcon, { title: "Add Interval", size: "sm", onClick: (e) => {
|
|
5531
5554
|
killEvent(e);
|
|
5532
5555
|
props.onAdd(intervalGroup.id, {
|
|
5533
5556
|
range: {
|
|
@@ -5536,7 +5559,7 @@
|
|
|
5536
5559
|
},
|
|
5537
5560
|
});
|
|
5538
5561
|
} },
|
|
5539
|
-
|
|
5562
|
+
e.createElement(iS, null)))));
|
|
5540
5563
|
}
|
|
5541
5564
|
/**
|
|
5542
5565
|
* Render the "filters" section of the IntervalGroup. Also populates some initial
|
|
@@ -5556,9 +5579,9 @@
|
|
|
5556
5579
|
};
|
|
5557
5580
|
}
|
|
5558
5581
|
}
|
|
5559
|
-
return (
|
|
5560
|
-
|
|
5561
|
-
|
|
5582
|
+
return (e.createElement(core$1.Stack, { style: { maxWidth: '50%' } },
|
|
5583
|
+
e.createElement(core$1.Group, null,
|
|
5584
|
+
e.createElement(core$1.NativeSelect, { data: ['', 'male', 'female'], label: "Gender:", defaultValue: intervalGroup.filters.gender || '', onChange: (e) => {
|
|
5562
5585
|
for (const interval of intervalGroup.intervals) {
|
|
5563
5586
|
let newGender = e.currentTarget?.value;
|
|
5564
5587
|
if (newGender === '') {
|
|
@@ -5570,15 +5593,15 @@
|
|
|
5570
5593
|
});
|
|
5571
5594
|
}
|
|
5572
5595
|
} })),
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
|
|
5596
|
+
e.createElement(core$1.Group, { spacing: 'xs' },
|
|
5597
|
+
e.createElement(core$1.Text, { component: "label", htmlFor: `div-age-${intervalGroup.id}` }, "Age:"),
|
|
5598
|
+
e.createElement("div", { id: `div-age-${intervalGroup.id}` },
|
|
5599
|
+
e.createElement(RangeInput, { key: `age-${intervalGroup.id}`, name: `age-${intervalGroup.id}`, defaultValue: intervalGroup.filters['age'], onChange: (ageRange) => {
|
|
5577
5600
|
for (const interval of intervalGroup.intervals) {
|
|
5578
5601
|
onChange(intervalGroup.id, { ...interval, age: ageRange });
|
|
5579
5602
|
}
|
|
5580
5603
|
} }))),
|
|
5581
|
-
|
|
5604
|
+
e.createElement(core$1.NativeSelect, { data: ['', 'pre-puberty', 'follicular', 'midcycle', 'luteal', 'postmenopausal'], label: "Endocrine:", defaultValue: intervalGroup.filters.context?.text || '', onChange: (e) => {
|
|
5582
5605
|
for (const interval of intervalGroup.intervals) {
|
|
5583
5606
|
let newEndocrine = e.currentTarget?.value;
|
|
5584
5607
|
if (newEndocrine === '') {
|
|
@@ -5671,9 +5694,9 @@
|
|
|
5671
5694
|
function RequestGroupDisplay(props) {
|
|
5672
5695
|
const medplum = useMedplum();
|
|
5673
5696
|
const requestGroup = useResource(props.value);
|
|
5674
|
-
const [startedLoading, setStartedLoading] =
|
|
5675
|
-
const [responseBundle, setResponseBundle] =
|
|
5676
|
-
|
|
5697
|
+
const [startedLoading, setStartedLoading] = e.useState(false);
|
|
5698
|
+
const [responseBundle, setResponseBundle] = e.useState();
|
|
5699
|
+
e.useEffect(() => {
|
|
5677
5700
|
if (requestGroup && !startedLoading) {
|
|
5678
5701
|
medplum.executeBatch(buildBatchRequest(requestGroup)).then(setResponseBundle).catch(console.log);
|
|
5679
5702
|
setStartedLoading(true);
|
|
@@ -5682,26 +5705,26 @@
|
|
|
5682
5705
|
if (!requestGroup || !responseBundle) {
|
|
5683
5706
|
return null;
|
|
5684
5707
|
}
|
|
5685
|
-
return (
|
|
5708
|
+
return (e.createElement(core$1.Grid, null, requestGroup.action?.map((action, index) => {
|
|
5686
5709
|
const task = action.resource && findBundleEntry(action.resource);
|
|
5687
5710
|
const taskInput = task?.input?.[0]?.valueReference;
|
|
5688
5711
|
const taskOutput = task?.output?.[0]?.valueReference;
|
|
5689
|
-
return (
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
action.description &&
|
|
5694
|
-
|
|
5712
|
+
return (e.createElement(e.Fragment, { key: `action-${index}` },
|
|
5713
|
+
e.createElement(core$1.Grid.Col, { span: 1, p: "md" }, task?.status === 'completed' ? e.createElement(GW, null) : e.createElement(RSe, { color: "gray" })),
|
|
5714
|
+
e.createElement(core$1.Grid.Col, { span: 9, p: "xs" },
|
|
5715
|
+
e.createElement(core$1.Text, { weight: 500 }, action.title),
|
|
5716
|
+
action.description && e.createElement("div", null, action.description),
|
|
5717
|
+
e.createElement("div", null,
|
|
5695
5718
|
"Last edited by\u00A0",
|
|
5696
|
-
|
|
5719
|
+
e.createElement(ResourceName, { value: task?.meta?.author }),
|
|
5697
5720
|
"\u00A0on\u00A0",
|
|
5698
5721
|
core.formatDateTime(task?.meta?.lastUpdated)),
|
|
5699
|
-
|
|
5722
|
+
e.createElement("div", null,
|
|
5700
5723
|
"Status: ",
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
taskInput && !taskOutput &&
|
|
5704
|
-
taskInput && taskOutput && (
|
|
5724
|
+
e.createElement(StatusBadge, { status: task?.status || 'unknown' }))),
|
|
5725
|
+
e.createElement(core$1.Grid.Col, { span: 2, p: "md" },
|
|
5726
|
+
taskInput && !taskOutput && e.createElement(core$1.Button, { onClick: () => props.onStart(task, taskInput) }, "Start"),
|
|
5727
|
+
taskInput && taskOutput && (e.createElement(core$1.Button, { onClick: () => props.onEdit(task, taskInput, taskOutput) }, "Edit")))));
|
|
5705
5728
|
})));
|
|
5706
5729
|
function buildBatchRequest(request) {
|
|
5707
5730
|
const batchEntries = [];
|
|
@@ -5961,28 +5984,28 @@
|
|
|
5961
5984
|
function ResourceBlame(props) {
|
|
5962
5985
|
const { classes } = useStyles$2();
|
|
5963
5986
|
const medplum = useMedplum();
|
|
5964
|
-
const [value, setValue] =
|
|
5965
|
-
|
|
5987
|
+
const [value, setValue] = e.useState(props.history);
|
|
5988
|
+
e.useEffect(() => {
|
|
5966
5989
|
if (!props.history && props.resourceType && props.id) {
|
|
5967
5990
|
medplum.readHistory(props.resourceType, props.id).then(setValue).catch(console.log);
|
|
5968
5991
|
}
|
|
5969
5992
|
}, [medplum, props.history, props.resourceType, props.id]);
|
|
5970
5993
|
if (!value) {
|
|
5971
|
-
return
|
|
5994
|
+
return e.createElement("div", null, "Loading...");
|
|
5972
5995
|
}
|
|
5973
5996
|
const resource = value.entry?.[0]?.resource;
|
|
5974
5997
|
const table = blame(value);
|
|
5975
|
-
return (
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
row.span > 0 && (
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
|
|
5998
|
+
return (e.createElement("div", { className: classes.container },
|
|
5999
|
+
e.createElement("table", { className: classes.root },
|
|
6000
|
+
e.createElement("tbody", null, table.map((row, index) => (e.createElement("tr", { key: 'row-' + index, className: row.span > 0 ? classes.startRow : classes.normalRow },
|
|
6001
|
+
row.span > 0 && (e.createElement(e.Fragment, null,
|
|
6002
|
+
e.createElement("td", { className: classes.author, rowSpan: row.span },
|
|
6003
|
+
e.createElement(ResourceBadge, { value: row.meta.author, link: true })),
|
|
6004
|
+
e.createElement("td", { className: classes.dateTime, rowSpan: row.span },
|
|
6005
|
+
e.createElement(MedplumLink, { to: getVersionUrl$1(resource, row.meta.versionId) }, getTimeString(row.meta.lastUpdated))))),
|
|
6006
|
+
e.createElement("td", { className: classes.lineNumber }, index + 1),
|
|
6007
|
+
e.createElement("td", { className: classes.line },
|
|
6008
|
+
e.createElement("pre", { className: classes.pre }, row.value)))))))));
|
|
5986
6009
|
}
|
|
5987
6010
|
function getVersionUrl$1(resource, versionId) {
|
|
5988
6011
|
return `/${resource.resourceType}/${resource.id}/_history/${versionId}`;
|
|
@@ -6034,23 +6057,23 @@
|
|
|
6034
6057
|
const original = core.stringify(originalResource, true).match(/[^\r\n]+/g);
|
|
6035
6058
|
const revised = core.stringify(revisedResource, true).match(/[^\r\n]+/g);
|
|
6036
6059
|
const deltas = diff(original, revised);
|
|
6037
|
-
return (
|
|
6060
|
+
return (e.createElement("pre", { style: { color: 'gray' } }, deltas.map((delta, index) => (e.createElement(ChangeDiff, { key: 'delta' + index, delta: delta })))));
|
|
6038
6061
|
}
|
|
6039
6062
|
function ChangeDiff(props) {
|
|
6040
6063
|
const { classes } = useStyles$1();
|
|
6041
|
-
return (
|
|
6064
|
+
return (e.createElement(e.Fragment, null,
|
|
6042
6065
|
"...",
|
|
6043
|
-
|
|
6044
|
-
props.delta.original.lines.length > 0 && (
|
|
6045
|
-
props.delta.revised.lines.length > 0 && (
|
|
6066
|
+
e.createElement("br", null),
|
|
6067
|
+
props.delta.original.lines.length > 0 && (e.createElement("div", { className: classes.removed }, props.delta.original.lines.join('\n'))),
|
|
6068
|
+
props.delta.revised.lines.length > 0 && (e.createElement("div", { className: classes.added }, props.delta.revised.lines.join('\n'))),
|
|
6046
6069
|
"...",
|
|
6047
|
-
|
|
6070
|
+
e.createElement("br", null)));
|
|
6048
6071
|
}
|
|
6049
6072
|
|
|
6050
6073
|
function ResourceHistoryTable(props) {
|
|
6051
6074
|
const medplum = useMedplum();
|
|
6052
|
-
const [value, setValue] =
|
|
6053
|
-
|
|
6075
|
+
const [value, setValue] = e.useState(props.history);
|
|
6076
|
+
e.useEffect(() => {
|
|
6054
6077
|
if (!props.history && props.resourceType && props.id) {
|
|
6055
6078
|
medplum
|
|
6056
6079
|
.readHistory(props.resourceType, props.id)
|
|
@@ -6059,29 +6082,29 @@
|
|
|
6059
6082
|
}
|
|
6060
6083
|
}, [medplum, props.history, props.resourceType, props.id]);
|
|
6061
6084
|
if (!value) {
|
|
6062
|
-
return
|
|
6085
|
+
return e.createElement("div", null, "Loading...");
|
|
6063
6086
|
}
|
|
6064
|
-
return (
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
6070
|
-
|
|
6087
|
+
return (e.createElement(core$1.Table, { withBorder: true, withColumnBorders: true },
|
|
6088
|
+
e.createElement("thead", null,
|
|
6089
|
+
e.createElement("tr", null,
|
|
6090
|
+
e.createElement("th", null, "Author"),
|
|
6091
|
+
e.createElement("th", null, "Date"),
|
|
6092
|
+
e.createElement("th", null, "Version"))),
|
|
6093
|
+
e.createElement("tbody", null, value.entry?.map((entry, index) => (e.createElement(HistoryRow, { key: 'entry-' + index, entry: entry }))))));
|
|
6071
6094
|
}
|
|
6072
6095
|
function HistoryRow(props) {
|
|
6073
6096
|
const { response, resource } = props.entry;
|
|
6074
6097
|
if (resource) {
|
|
6075
|
-
return (
|
|
6076
|
-
|
|
6077
|
-
|
|
6078
|
-
|
|
6079
|
-
|
|
6080
|
-
|
|
6098
|
+
return (e.createElement("tr", null,
|
|
6099
|
+
e.createElement("td", null,
|
|
6100
|
+
e.createElement(ResourceBadge, { value: resource.meta?.author, link: true })),
|
|
6101
|
+
e.createElement("td", null, core.formatDateTime(resource.meta?.lastUpdated)),
|
|
6102
|
+
e.createElement("td", null,
|
|
6103
|
+
e.createElement(MedplumLink, { to: getVersionUrl(resource) }, resource.meta?.versionId))));
|
|
6081
6104
|
}
|
|
6082
6105
|
else {
|
|
6083
|
-
return (
|
|
6084
|
-
|
|
6106
|
+
return (e.createElement("tr", null,
|
|
6107
|
+
e.createElement("td", { colSpan: 3 }, core.normalizeErrorString(response?.outcome))));
|
|
6085
6108
|
}
|
|
6086
6109
|
}
|
|
6087
6110
|
function getVersionUrl(resource) {
|
|
@@ -6108,14 +6131,14 @@
|
|
|
6108
6131
|
const medplum = useMedplum();
|
|
6109
6132
|
const schedule = useResource(props.schedule);
|
|
6110
6133
|
const questionnaire = useResource(props.questionnaire);
|
|
6111
|
-
const [slots, setSlots] =
|
|
6112
|
-
const slotsRef =
|
|
6134
|
+
const [slots, setSlots] = e.useState();
|
|
6135
|
+
const slotsRef = e.useRef();
|
|
6113
6136
|
slotsRef.current = slots;
|
|
6114
|
-
const [month, setMonth] =
|
|
6115
|
-
const [date, setDate] =
|
|
6116
|
-
const [slot, setSlot] =
|
|
6117
|
-
const [response, setResponse] =
|
|
6118
|
-
|
|
6137
|
+
const [month, setMonth] = e.useState(getStartMonth());
|
|
6138
|
+
const [date, setDate] = e.useState();
|
|
6139
|
+
const [slot, setSlot] = e.useState();
|
|
6140
|
+
const [response, setResponse] = e.useState();
|
|
6141
|
+
e.useEffect(() => {
|
|
6119
6142
|
if (schedule) {
|
|
6120
6143
|
setSlots([]);
|
|
6121
6144
|
medplum
|
|
@@ -6136,30 +6159,30 @@
|
|
|
6136
6159
|
return null;
|
|
6137
6160
|
}
|
|
6138
6161
|
const actor = schedule.actor?.[0];
|
|
6139
|
-
return (
|
|
6140
|
-
|
|
6141
|
-
actor &&
|
|
6142
|
-
actor && (
|
|
6143
|
-
|
|
6144
|
-
|
|
6145
|
-
date &&
|
|
6146
|
-
slot &&
|
|
6147
|
-
|
|
6148
|
-
!date && (
|
|
6149
|
-
|
|
6150
|
-
|
|
6151
|
-
date && !slot && (
|
|
6152
|
-
|
|
6153
|
-
|
|
6162
|
+
return (e.createElement("div", { className: classes.container, "data-testid": "scheduler" },
|
|
6163
|
+
e.createElement("div", { className: classes.info },
|
|
6164
|
+
actor && e.createElement(ResourceAvatar, { value: actor, size: "xl" }),
|
|
6165
|
+
actor && (e.createElement(core$1.Text, { size: "xl", weight: 500 },
|
|
6166
|
+
e.createElement(ResourceName, { value: actor }))),
|
|
6167
|
+
e.createElement("p", null, "1 hour"),
|
|
6168
|
+
date && e.createElement("p", null, date.toLocaleDateString()),
|
|
6169
|
+
slot && e.createElement("p", null, formatTime(new Date(slot.start)))),
|
|
6170
|
+
e.createElement("div", { className: classes.selection },
|
|
6171
|
+
!date && (e.createElement("div", null,
|
|
6172
|
+
e.createElement("h3", null, "Select date"),
|
|
6173
|
+
e.createElement(CalendarInput, { slots: slots, onChangeMonth: setMonth, onClick: setDate }))),
|
|
6174
|
+
date && !slot && (e.createElement("div", null,
|
|
6175
|
+
e.createElement("h3", null, "Select time"),
|
|
6176
|
+
e.createElement(core$1.Stack, null, slots.map((s) => {
|
|
6154
6177
|
const slotStart = new Date(s.start);
|
|
6155
6178
|
return (slotStart.getTime() > date.getTime() &&
|
|
6156
|
-
slotStart.getTime() < date.getTime() + 24 * 3600 * 1000 && (
|
|
6157
|
-
|
|
6179
|
+
slotStart.getTime() < date.getTime() + 24 * 3600 * 1000 && (e.createElement("div", { key: s.id },
|
|
6180
|
+
e.createElement(core$1.Button, { variant: "outline", style: { width: 150 }, onClick: () => setSlot(s) }, formatTime(slotStart)))));
|
|
6158
6181
|
})))),
|
|
6159
|
-
date && slot && !response && (
|
|
6160
|
-
date && slot && response && (
|
|
6161
|
-
|
|
6162
|
-
|
|
6182
|
+
date && slot && !response && (e.createElement(QuestionnaireForm, { questionnaire: questionnaire, submitButtonText: 'Next', onSubmit: setResponse })),
|
|
6183
|
+
date && slot && response && (e.createElement("div", null,
|
|
6184
|
+
e.createElement("h3", null, "You're all set!"),
|
|
6185
|
+
e.createElement("p", null, "Check your email for a calendar invite."))))));
|
|
6163
6186
|
}
|
|
6164
6187
|
function getStart(month) {
|
|
6165
6188
|
return formatSlotInstant(month.getTime());
|
|
@@ -6175,36 +6198,14 @@
|
|
|
6175
6198
|
}
|
|
6176
6199
|
|
|
6177
6200
|
function ServiceRequestTimeline(props) {
|
|
6178
|
-
return (
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
},
|
|
6187
|
-
},
|
|
6188
|
-
{
|
|
6189
|
-
request: {
|
|
6190
|
-
method: 'GET',
|
|
6191
|
-
url: `Communication?based-on=${core.getReferenceString(resource)}&_sort=-_lastUpdated`,
|
|
6192
|
-
},
|
|
6193
|
-
},
|
|
6194
|
-
{
|
|
6195
|
-
request: {
|
|
6196
|
-
method: 'GET',
|
|
6197
|
-
url: `Media?_count=100&based-on=${core.getReferenceString(resource)}&_sort=-_lastUpdated`,
|
|
6198
|
-
},
|
|
6199
|
-
},
|
|
6200
|
-
{
|
|
6201
|
-
request: {
|
|
6202
|
-
method: 'GET',
|
|
6203
|
-
url: `DiagnosticReport?based-on=${core.getReferenceString(resource)}&_sort=-_lastUpdated`,
|
|
6204
|
-
},
|
|
6205
|
-
},
|
|
6206
|
-
],
|
|
6207
|
-
}), createCommunication: (resource, sender, text) => ({
|
|
6201
|
+
return (e.createElement(ResourceTimeline, { value: props.serviceRequest, loadTimelineResources: async (medplum, resource) => {
|
|
6202
|
+
return Promise.all([
|
|
6203
|
+
medplum.readHistory('ServiceRequest', resource.id),
|
|
6204
|
+
medplum.search('Communication', 'based-on=' + core.getReferenceString(resource)),
|
|
6205
|
+
medplum.search('Media', '_count=100&based-on=' + core.getReferenceString(resource)),
|
|
6206
|
+
medplum.search('DiagnosticReport', 'based-on=' + core.getReferenceString(resource)),
|
|
6207
|
+
]);
|
|
6208
|
+
}, createCommunication: (resource, sender, text) => ({
|
|
6208
6209
|
resourceType: 'Communication',
|
|
6209
6210
|
status: 'completed',
|
|
6210
6211
|
basedOn: [core.createReference(resource)],
|
|
@@ -6357,6 +6358,7 @@
|
|
|
6357
6358
|
exports.toggleSort = toggleSort;
|
|
6358
6359
|
exports.useMedplum = useMedplum;
|
|
6359
6360
|
exports.useMedplumContext = useMedplumContext;
|
|
6361
|
+
exports.useMedplumNavigate = useMedplumNavigate;
|
|
6360
6362
|
exports.useMedplumProfile = useMedplumProfile;
|
|
6361
6363
|
exports.useResource = useResource;
|
|
6362
6364
|
|