@medplum/react 0.9.34 → 0.9.36
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/README.md +1 -1
- package/dist/cjs/QuestionnaireUtils.d.ts +1 -10
- package/dist/cjs/SearchControlField.d.ts +2 -3
- package/dist/cjs/SearchFieldEditor.d.ts +1 -2
- package/dist/cjs/SearchFilterEditor.d.ts +1 -2
- package/dist/cjs/SearchFilterValueDialog.d.ts +1 -2
- package/dist/cjs/SearchFilterValueDisplay.d.ts +1 -1
- package/dist/cjs/SearchFilterValueInput.d.ts +0 -2
- package/dist/cjs/SearchPopupMenu.d.ts +1 -2
- package/dist/cjs/auth/AuthenticationForm.d.ts +1 -0
- package/dist/cjs/index.js +95 -124
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/index.min.js +1 -1
- package/dist/cjs/index.min.js.map +1 -1
- package/dist/cjs/styles.css +51 -51
- package/dist/esm/AddressInput.js.map +1 -1
- package/dist/esm/ContactPointInput.js +2 -1
- package/dist/esm/ContactPointInput.js.map +1 -1
- package/dist/esm/GoogleButton.js +1 -1
- package/dist/esm/GoogleButton.js.map +1 -1
- package/dist/esm/HumanNameInput.js.map +1 -1
- package/dist/esm/PlanDefinitionBuilder.js +2 -0
- package/dist/esm/PlanDefinitionBuilder.js.map +1 -1
- package/dist/esm/Popup.js +15 -1
- package/dist/esm/Popup.js.map +1 -1
- package/dist/esm/QuantityInput.js.map +1 -1
- package/dist/esm/QuestionnaireBuilder.js +9 -0
- package/dist/esm/QuestionnaireBuilder.js.map +1 -1
- package/dist/esm/QuestionnaireUtils.d.ts +1 -10
- package/dist/esm/QuestionnaireUtils.js +1 -78
- package/dist/esm/QuestionnaireUtils.js.map +1 -1
- package/dist/esm/RequestGroupDisplay.js +1 -0
- package/dist/esm/RequestGroupDisplay.js.map +1 -1
- package/dist/esm/ResourceTimeline.js.map +1 -1
- package/dist/esm/SearchControl.js +11 -14
- package/dist/esm/SearchControl.js.map +1 -1
- package/dist/esm/SearchControlField.d.ts +2 -3
- package/dist/esm/SearchControlField.js +6 -8
- package/dist/esm/SearchControlField.js.map +1 -1
- package/dist/esm/SearchFieldEditor.d.ts +1 -2
- package/dist/esm/SearchFieldEditor.js +2 -2
- package/dist/esm/SearchFieldEditor.js.map +1 -1
- package/dist/esm/SearchFilterEditor.d.ts +1 -2
- package/dist/esm/SearchFilterEditor.js +5 -6
- package/dist/esm/SearchFilterEditor.js.map +1 -1
- package/dist/esm/SearchFilterValueDialog.d.ts +1 -2
- package/dist/esm/SearchFilterValueDialog.js +1 -1
- package/dist/esm/SearchFilterValueDialog.js.map +1 -1
- package/dist/esm/SearchFilterValueDisplay.d.ts +1 -1
- package/dist/esm/SearchFilterValueDisplay.js +11 -11
- package/dist/esm/SearchFilterValueDisplay.js.map +1 -1
- package/dist/esm/SearchFilterValueInput.d.ts +0 -2
- package/dist/esm/SearchFilterValueInput.js +1 -1
- package/dist/esm/SearchFilterValueInput.js.map +1 -1
- package/dist/esm/SearchPopupMenu.d.ts +1 -2
- package/dist/esm/SearchPopupMenu.js.map +1 -1
- package/dist/esm/TimingInput.js.map +1 -1
- package/dist/esm/auth/AuthenticationForm.d.ts +1 -0
- package/dist/esm/auth/AuthenticationForm.js +14 -6
- package/dist/esm/auth/AuthenticationForm.js.map +1 -1
- package/dist/esm/auth/SignInForm.js +1 -1
- package/dist/esm/auth/SignInForm.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.min.js +1 -1
- package/dist/esm/index.min.js.map +1 -1
- package/dist/esm/styles.css +51 -51
- package/dist/esm/utils/blame.js +1 -0
- package/dist/esm/utils/blame.js.map +1 -1
- package/dist/esm/utils/outcomes.js +19 -1
- package/dist/esm/utils/outcomes.js.map +1 -1
- package/package.json +11 -11
- package/stats.html +0 -4034
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ The Medplum React Component Library provides many helpful components to quickly
|
|
|
4
4
|
|
|
5
5
|
The Medplum SDK can be used with any compliant FHIR server. However, some advanced features are only available when paired with a Medplum server.
|
|
6
6
|
|
|
7
|
-
Check out a live demo:
|
|
7
|
+
Check out a live demo: <https://storybook.medplum.com/>
|
|
8
8
|
|
|
9
9
|
## Key Features
|
|
10
10
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { QuestionnaireItem } from '@medplum/fhirtypes';
|
|
2
2
|
export declare enum QuestionnaireItemType {
|
|
3
3
|
group = "group",
|
|
4
4
|
display = "display",
|
|
@@ -18,13 +18,4 @@ export declare enum QuestionnaireItemType {
|
|
|
18
18
|
reference = "reference",
|
|
19
19
|
quantity = "quantity"
|
|
20
20
|
}
|
|
21
|
-
/**
|
|
22
|
-
* Adds initial values to a questionnaire resource from key value pairs.
|
|
23
|
-
* The values map uses "linkId" as key.
|
|
24
|
-
* The value depends on the questionnaire item type.
|
|
25
|
-
* @param questionnaire The original questionnaire.
|
|
26
|
-
* @param values Key value pairs for initial values.
|
|
27
|
-
* @returns Rewritten questionnaire with initial values.
|
|
28
|
-
*/
|
|
29
|
-
export declare function addQuestionnaireInitialValues(questionnaire: Questionnaire, values: Record<string, string>): Questionnaire;
|
|
30
21
|
export declare function isChoiceQuestion(item: QuestionnaireItem): boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SearchRequest } from '@medplum/core';
|
|
2
2
|
import { ElementDefinition, SearchParameter } from '@medplum/fhirtypes';
|
|
3
3
|
/**
|
|
4
4
|
* The SearchControlField type describes a field in the search control.
|
|
@@ -34,8 +34,7 @@ export interface SearchControlField {
|
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
36
|
* Returns the collection of field definitions for the search request.
|
|
37
|
-
* @param typeSchema The schema for the resource type
|
|
38
37
|
* @param search The search request definition.
|
|
39
38
|
* @returns An array of field definitions.
|
|
40
39
|
*/
|
|
41
|
-
export declare function getFieldDefinitions(
|
|
40
|
+
export declare function getFieldDefinitions(search: SearchRequest): SearchControlField[];
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import {
|
|
2
|
+
import { SearchRequest } from '@medplum/core';
|
|
3
3
|
interface SearchFieldEditorProps {
|
|
4
|
-
schema: IndexedStructureDefinition;
|
|
5
4
|
visible: boolean;
|
|
6
5
|
search: SearchRequest;
|
|
7
6
|
onOk: (search: SearchRequest) => void;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import {
|
|
2
|
+
import { SearchRequest } from '@medplum/core';
|
|
3
3
|
import './SearchFilterEditor.css';
|
|
4
4
|
export interface SearchFilterEditorProps {
|
|
5
|
-
schema: IndexedStructureDefinition;
|
|
6
5
|
visible: boolean;
|
|
7
6
|
search: SearchRequest;
|
|
8
7
|
onOk: (search: SearchRequest) => void;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import { Filter
|
|
2
|
+
import { Filter } from '@medplum/core';
|
|
3
3
|
import { SearchParameter } from '@medplum/fhirtypes';
|
|
4
4
|
export interface SearchFilterValueDialogProps {
|
|
5
5
|
title: string;
|
|
6
6
|
visible: boolean;
|
|
7
|
-
schema: IndexedStructureDefinition;
|
|
8
7
|
resourceType: string;
|
|
9
8
|
searchParam?: SearchParameter;
|
|
10
9
|
filter?: Filter;
|
|
@@ -4,4 +4,4 @@ export interface SearchFilterValueDisplayProps {
|
|
|
4
4
|
readonly resourceType: string;
|
|
5
5
|
readonly filter: Filter;
|
|
6
6
|
}
|
|
7
|
-
export declare function SearchFilterValueDisplay(props: SearchFilterValueDisplayProps): JSX.Element
|
|
7
|
+
export declare function SearchFilterValueDisplay(props: SearchFilterValueDisplayProps): JSX.Element;
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import { IndexedStructureDefinition } from '@medplum/core';
|
|
3
2
|
import { SearchParameter } from '@medplum/fhirtypes';
|
|
4
3
|
export interface SearchFilterValueInputProps {
|
|
5
|
-
schema: IndexedStructureDefinition;
|
|
6
4
|
resourceType: string;
|
|
7
5
|
searchParam: SearchParameter;
|
|
8
6
|
defaultValue?: string;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import { Filter,
|
|
2
|
+
import { Filter, SearchRequest } from '@medplum/core';
|
|
3
3
|
import { SearchParameter } from '@medplum/fhirtypes';
|
|
4
4
|
export interface SearchPopupMenuProps {
|
|
5
|
-
schema: IndexedStructureDefinition;
|
|
6
5
|
search: SearchRequest;
|
|
7
6
|
visible: boolean;
|
|
8
7
|
x: number;
|
|
@@ -6,6 +6,7 @@ export interface AuthenticationFormProps {
|
|
|
6
6
|
readonly scope?: string;
|
|
7
7
|
readonly nonce?: string;
|
|
8
8
|
readonly googleClientId?: string;
|
|
9
|
+
readonly generatePkce?: boolean;
|
|
9
10
|
readonly codeChallenge?: string;
|
|
10
11
|
readonly codeChallengeMethod?: string;
|
|
11
12
|
readonly onForgotPassword?: () => void;
|
package/dist/cjs/index.js
CHANGED
|
@@ -18,7 +18,25 @@
|
|
|
18
18
|
|
|
19
19
|
function getIssuesForExpression(outcome, expression) {
|
|
20
20
|
var _a;
|
|
21
|
-
return (_a = outcome === null || outcome === void 0 ? void 0 : outcome.issue) === null || _a === void 0 ? void 0 : _a.filter((issue) => { var _a; return ((_a = issue.expression) === null || _a === void 0 ? void 0 : _a[0]
|
|
21
|
+
return (_a = outcome === null || outcome === void 0 ? void 0 : outcome.issue) === null || _a === void 0 ? void 0 : _a.filter((issue) => { var _a; return isExpressionMatch((_a = issue.expression) === null || _a === void 0 ? void 0 : _a[0], expression); });
|
|
22
|
+
}
|
|
23
|
+
function isExpressionMatch(expr1, expr2) {
|
|
24
|
+
// Expression can be either "fieldName" or "resourceType.fieldName"
|
|
25
|
+
if (expr1 === expr2) {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
if (!expr1 || !expr2) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
const dot1 = expr1.indexOf('.');
|
|
32
|
+
if (dot1 >= 0 && expr1.substring(dot1 + 1) === expr2) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
const dot2 = expr2.indexOf('.');
|
|
36
|
+
if (dot2 >= 0 && expr2.substring(dot2 + 1) === expr1) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
22
40
|
}
|
|
23
41
|
|
|
24
42
|
function Input(props) {
|
|
@@ -518,7 +536,7 @@
|
|
|
518
536
|
return clientId;
|
|
519
537
|
}
|
|
520
538
|
const origin = window.location.protocol + '//' + window.location.host;
|
|
521
|
-
const authorizedOrigins = (_b = (_a = "http://localhost:3000,http://127.0.0.1:3000,http://localhost:6006,http://127.0.0.1:6006,https://app.medplum.com,https://docs.medplum.com") === null || _a === void 0 ? void 0 : _a.split(',')) !== null && _b !== void 0 ? _b : [];
|
|
539
|
+
const authorizedOrigins = (_b = (_a = "http://localhost:3000,http://127.0.0.1:3000,http://localhost:6006,http://127.0.0.1:6006,https://app.medplum.com,https://docs.medplum.com,https://storybook.medplum.com,https://graphiql.medplum.com,https://www.medplum.com") === null || _a === void 0 ? void 0 : _a.split(',')) !== null && _b !== void 0 ? _b : [];
|
|
522
540
|
if (authorizedOrigins.includes(origin)) {
|
|
523
541
|
return "921088377005-3j1sa10vr6hj86jgmdfh2l53v3mp7lfi.apps.googleusercontent.com";
|
|
524
542
|
}
|
|
@@ -706,9 +724,16 @@
|
|
|
706
724
|
const googleClientId = getGoogleClientId(props.googleClientId);
|
|
707
725
|
const [outcome, setOutcome] = React.useState();
|
|
708
726
|
const issues = getIssuesForExpression(outcome, undefined);
|
|
727
|
+
function startPkce() {
|
|
728
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
729
|
+
if (props.generatePkce) {
|
|
730
|
+
yield medplum.startPkce();
|
|
731
|
+
}
|
|
732
|
+
});
|
|
733
|
+
}
|
|
709
734
|
return (React__default["default"].createElement(Form, { style: { maxWidth: 400 }, onSubmit: (formData) => {
|
|
710
|
-
|
|
711
|
-
.startLogin({
|
|
735
|
+
startPkce()
|
|
736
|
+
.then(() => medplum.startLogin({
|
|
712
737
|
projectId: props.projectId,
|
|
713
738
|
clientId: props.clientId,
|
|
714
739
|
scope: props.scope,
|
|
@@ -718,7 +743,7 @@
|
|
|
718
743
|
email: formData.email,
|
|
719
744
|
password: formData.password,
|
|
720
745
|
remember: formData.remember === 'true',
|
|
721
|
-
})
|
|
746
|
+
}))
|
|
722
747
|
.then(props.handleAuthResponse)
|
|
723
748
|
.catch(setOutcome);
|
|
724
749
|
} },
|
|
@@ -730,8 +755,8 @@
|
|
|
730
755
|
googleClientId && (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
731
756
|
React__default["default"].createElement("div", { className: "medplum-signin-google-container" },
|
|
732
757
|
React__default["default"].createElement(GoogleButton, { googleClientId: googleClientId, handleGoogleCredential: (response) => {
|
|
733
|
-
|
|
734
|
-
.startGoogleLogin({
|
|
758
|
+
startPkce()
|
|
759
|
+
.then(() => medplum.startGoogleLogin({
|
|
735
760
|
projectId: props.projectId,
|
|
736
761
|
clientId: props.clientId,
|
|
737
762
|
scope: props.scope,
|
|
@@ -740,7 +765,7 @@
|
|
|
740
765
|
codeChallengeMethod: props.codeChallengeMethod,
|
|
741
766
|
googleClientId: response.clientId,
|
|
742
767
|
googleCredential: response.credential,
|
|
743
|
-
})
|
|
768
|
+
}))
|
|
744
769
|
.then(props.handleAuthResponse)
|
|
745
770
|
.catch(setOutcome);
|
|
746
771
|
} })),
|
|
@@ -891,7 +916,7 @@
|
|
|
891
916
|
}
|
|
892
917
|
return (React__default["default"].createElement(Document, { width: 450 }, (() => {
|
|
893
918
|
if (!login) {
|
|
894
|
-
return (React__default["default"].createElement(AuthenticationForm, { projectId: props.projectId, clientId: props.clientId, scope: props.scope, nonce: props.nonce, googleClientId: props.googleClientId, codeChallenge: props.codeChallenge, codeChallengeMethod: props.codeChallengeMethod, onForgotPassword: props.onForgotPassword, onRegister: props.onRegister, handleAuthResponse: handleAuthResponse }, props.children));
|
|
919
|
+
return (React__default["default"].createElement(AuthenticationForm, { projectId: props.projectId, clientId: props.clientId, scope: props.scope, nonce: props.nonce, googleClientId: props.googleClientId, generatePkce: !props.onCode, codeChallenge: props.codeChallenge, codeChallengeMethod: props.codeChallengeMethod, onForgotPassword: props.onForgotPassword, onRegister: props.onRegister, handleAuthResponse: handleAuthResponse }, props.children));
|
|
895
920
|
}
|
|
896
921
|
else if (memberships) {
|
|
897
922
|
return React__default["default"].createElement(ChooseProfileForm, { login: login, memberships: memberships, handleAuthResponse: handleAuthResponse });
|
|
@@ -1685,7 +1710,8 @@
|
|
|
1685
1710
|
React__default["default"].createElement("option", null, "pager"),
|
|
1686
1711
|
React__default["default"].createElement("option", null, "phone"),
|
|
1687
1712
|
React__default["default"].createElement("option", null, "other"),
|
|
1688
|
-
React__default["default"].createElement("option", null, "sms")
|
|
1713
|
+
React__default["default"].createElement("option", null, "sms"),
|
|
1714
|
+
React__default["default"].createElement("option", null, "url")),
|
|
1689
1715
|
React__default["default"].createElement(Select, { defaultValue: contactPoint === null || contactPoint === void 0 ? void 0 : contactPoint.use, onChange: setUse, testid: "use" },
|
|
1690
1716
|
React__default["default"].createElement("option", null),
|
|
1691
1717
|
React__default["default"].createElement("option", null, "home"),
|
|
@@ -2550,11 +2576,24 @@
|
|
|
2550
2576
|
((_b = propsRef.current) === null || _b === void 0 ? void 0 : _b.autoClose) &&
|
|
2551
2577
|
(ref === null || ref === void 0 ? void 0 : ref.current) &&
|
|
2552
2578
|
!ref.current.contains(e.target)) {
|
|
2579
|
+
killEvent(e);
|
|
2553
2580
|
props.onClose();
|
|
2554
2581
|
}
|
|
2555
2582
|
}
|
|
2583
|
+
function handleScroll(e) {
|
|
2584
|
+
var _a;
|
|
2585
|
+
if ((_a = propsRef.current) === null || _a === void 0 ? void 0 : _a.visible) {
|
|
2586
|
+
killEvent(e);
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2556
2589
|
document.addEventListener('click', handleClick, true);
|
|
2557
|
-
|
|
2590
|
+
window.addEventListener('wheel', handleScroll, { passive: false });
|
|
2591
|
+
window.addEventListener('touchmove', handleScroll, true);
|
|
2592
|
+
return () => {
|
|
2593
|
+
document.removeEventListener('click', handleClick, true);
|
|
2594
|
+
window.removeEventListener('wheel', handleScroll);
|
|
2595
|
+
window.removeEventListener('touchmove', handleScroll, true);
|
|
2596
|
+
};
|
|
2558
2597
|
}, [props]);
|
|
2559
2598
|
// Listen for changes in the location
|
|
2560
2599
|
// If the browser navigates to a new page, close the popup
|
|
@@ -2956,27 +2995,25 @@
|
|
|
2956
2995
|
|
|
2957
2996
|
/**
|
|
2958
2997
|
* Returns the collection of field definitions for the search request.
|
|
2959
|
-
* @param typeSchema The schema for the resource type
|
|
2960
2998
|
* @param search The search request definition.
|
|
2961
2999
|
* @returns An array of field definitions.
|
|
2962
3000
|
*/
|
|
2963
|
-
function getFieldDefinitions(
|
|
3001
|
+
function getFieldDefinitions(search) {
|
|
2964
3002
|
const resourceType = search.resourceType;
|
|
2965
3003
|
const fields = [];
|
|
2966
3004
|
for (const name of search.fields || ['id', '_lastUpdated']) {
|
|
2967
|
-
fields.push(getFieldDefinition(
|
|
3005
|
+
fields.push(getFieldDefinition(resourceType, name));
|
|
2968
3006
|
}
|
|
2969
3007
|
return fields;
|
|
2970
3008
|
}
|
|
2971
3009
|
/**
|
|
2972
3010
|
* Return the field definition for a given field name.
|
|
2973
3011
|
* Field names can be either property names or search parameter codes.
|
|
2974
|
-
* @param typeSchema The schema for the resource type
|
|
2975
3012
|
* @param resourceType The resource type.
|
|
2976
3013
|
* @param name The search field name (either property name or search parameter code).
|
|
2977
3014
|
* @returns The field definition.
|
|
2978
3015
|
*/
|
|
2979
|
-
function getFieldDefinition(
|
|
3016
|
+
function getFieldDefinition(resourceType, name) {
|
|
2980
3017
|
var _a;
|
|
2981
3018
|
if (name === '_lastUpdated') {
|
|
2982
3019
|
return {
|
|
@@ -3008,7 +3045,7 @@
|
|
|
3008
3045
|
],
|
|
3009
3046
|
};
|
|
3010
3047
|
}
|
|
3011
|
-
const typeSchema =
|
|
3048
|
+
const typeSchema = core.globalSchema.types[resourceType];
|
|
3012
3049
|
const exactElementDefinition = typeSchema.properties[name];
|
|
3013
3050
|
const exactSearchParam = (_a = typeSchema.searchParams) === null || _a === void 0 ? void 0 : _a[name.toLowerCase()];
|
|
3014
3051
|
// Best case: Exact match of element definition or search parameter.
|
|
@@ -3039,7 +3076,7 @@
|
|
|
3039
3076
|
// Patient.email is a search parameter for the Patient.telecom element.
|
|
3040
3077
|
// So we need to walk backwards to find the element definition.
|
|
3041
3078
|
if (exactSearchParam) {
|
|
3042
|
-
const details = core.getSearchParameterDetails(
|
|
3079
|
+
const details = core.getSearchParameterDetails(resourceType, exactSearchParam);
|
|
3043
3080
|
return { name, elementDefinition: details.elementDefinition, searchParams: [exactSearchParam] };
|
|
3044
3081
|
}
|
|
3045
3082
|
// Worst case: no element definition and no search parameter.
|
|
@@ -3655,7 +3692,7 @@
|
|
|
3655
3692
|
return null;
|
|
3656
3693
|
}
|
|
3657
3694
|
const resourceType = props.search.resourceType;
|
|
3658
|
-
const typeDef =
|
|
3695
|
+
const typeDef = core.globalSchema.types[resourceType];
|
|
3659
3696
|
const selected = (_a = state.search.fields) !== null && _a !== void 0 ? _a : [];
|
|
3660
3697
|
const available = getFieldsList(typeDef)
|
|
3661
3698
|
.filter((field) => !(selected === null || selected === void 0 ? void 0 : selected.includes(field)))
|
|
@@ -3715,22 +3752,23 @@
|
|
|
3715
3752
|
|
|
3716
3753
|
function SearchFilterValueDisplay(props) {
|
|
3717
3754
|
var _a, _b;
|
|
3718
|
-
const
|
|
3719
|
-
const
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3755
|
+
const { resourceType, filter } = props;
|
|
3756
|
+
const searchParam = (_b = (_a = core.globalSchema.types[resourceType]) === null || _a === void 0 ? void 0 : _a.searchParams) === null || _b === void 0 ? void 0 : _b[filter.code];
|
|
3757
|
+
if (searchParam) {
|
|
3758
|
+
if (searchParam.type === 'reference') {
|
|
3759
|
+
return React__default["default"].createElement(ResourceName, { value: { reference: filter.value } });
|
|
3760
|
+
}
|
|
3761
|
+
const searchParamDetails = core.getSearchParameterDetails(resourceType, searchParam);
|
|
3762
|
+
if (filter.code === '_lastUpdated' || searchParamDetails.type === core.SearchParameterType.DATETIME) {
|
|
3763
|
+
return React__default["default"].createElement(React__default["default"].Fragment, null, core.formatDateTime(filter.value));
|
|
3764
|
+
}
|
|
3727
3765
|
}
|
|
3728
3766
|
return React__default["default"].createElement(React__default["default"].Fragment, null, filter.value);
|
|
3729
3767
|
}
|
|
3730
3768
|
|
|
3731
3769
|
function SearchFilterValueInput(props) {
|
|
3732
3770
|
var _a;
|
|
3733
|
-
const details = core.getSearchParameterDetails(props.
|
|
3771
|
+
const details = core.getSearchParameterDetails(props.resourceType, props.searchParam);
|
|
3734
3772
|
const name = 'filter-value';
|
|
3735
3773
|
switch (details.type) {
|
|
3736
3774
|
case core.SearchParameterType.REFERENCE:
|
|
@@ -3791,9 +3829,8 @@
|
|
|
3791
3829
|
if (!props.visible) {
|
|
3792
3830
|
return null;
|
|
3793
3831
|
}
|
|
3794
|
-
const schema = props.schema;
|
|
3795
3832
|
const resourceType = props.search.resourceType;
|
|
3796
|
-
const searchParams =
|
|
3833
|
+
const searchParams = core.globalSchema.types[resourceType].searchParams;
|
|
3797
3834
|
const filters = search.filters || [];
|
|
3798
3835
|
return (React__default["default"].createElement(Dialog, { title: "Filters", visible: props.visible, onOk: () => props.onOk(searchRef.current), onCancel: props.onCancel },
|
|
3799
3836
|
React__default["default"].createElement("div", { className: "medplum-filter-editor" },
|
|
@@ -3812,7 +3849,7 @@
|
|
|
3812
3849
|
React__default["default"].createElement("tbody", null,
|
|
3813
3850
|
filters.map((filter, index) => {
|
|
3814
3851
|
if (index === editingIndex) {
|
|
3815
|
-
return (React__default["default"].createElement(FilterRowInput, { key: `filter-${index}-${filters.length}-input`,
|
|
3852
|
+
return (React__default["default"].createElement(FilterRowInput, { key: `filter-${index}-${filters.length}-input`, resourceType: resourceType, searchParams: searchParams, defaultValue: filter, okText: "Save", onOk: (newFilter) => {
|
|
3816
3853
|
const newFilters = [...filters];
|
|
3817
3854
|
newFilters[index] = newFilter;
|
|
3818
3855
|
setSearch(setFilters(searchRef.current, newFilters));
|
|
@@ -3823,7 +3860,7 @@
|
|
|
3823
3860
|
return (React__default["default"].createElement(FilterRowDisplay, { key: `filter-${index}-${filters.length}-display`, resourceType: resourceType, searchParams: searchParams, filter: filter, onEdit: () => setEditingIndex(index), onDelete: () => setSearch(deleteFilter(searchRef.current, index)) }));
|
|
3824
3861
|
}
|
|
3825
3862
|
}),
|
|
3826
|
-
React__default["default"].createElement(FilterRowInput, {
|
|
3863
|
+
React__default["default"].createElement(FilterRowInput, { resourceType: resourceType, searchParams: searchParams, okText: "Add", onOk: onAddFilter }))))));
|
|
3827
3864
|
}
|
|
3828
3865
|
function FilterRowDisplay(props) {
|
|
3829
3866
|
const { filter } = props;
|
|
@@ -3860,7 +3897,7 @@
|
|
|
3860
3897
|
React__default["default"].createElement("td", null, operators && (React__default["default"].createElement(Select, { testid: "filter-operation", defaultValue: value.operator, onChange: setFilterOperator },
|
|
3861
3898
|
React__default["default"].createElement("option", { value: "" }),
|
|
3862
3899
|
operators.map((operator) => (React__default["default"].createElement("option", { key: operator, value: operator }, getOpString(operator))))))),
|
|
3863
|
-
React__default["default"].createElement("td", null, searchParam && value.operator && (React__default["default"].createElement(SearchFilterValueInput, {
|
|
3900
|
+
React__default["default"].createElement("td", null, searchParam && value.operator && (React__default["default"].createElement(SearchFilterValueInput, { resourceType: props.resourceType, searchParam: searchParam, defaultValue: value.value, onChange: setFilterValue }))),
|
|
3864
3901
|
React__default["default"].createElement("td", null,
|
|
3865
3902
|
value.code && value.operator && value.value && (React__default["default"].createElement(Button, { size: "small", onClick: () => {
|
|
3866
3903
|
props.onOk(valueRef.current);
|
|
@@ -3881,7 +3918,7 @@
|
|
|
3881
3918
|
return (React__default["default"].createElement(Dialog, { title: props.title, visible: props.visible, onOk: onOk, onCancel: props.onCancel },
|
|
3882
3919
|
React__default["default"].createElement("div", { style: { width: 500 } },
|
|
3883
3920
|
React__default["default"].createElement(Form, { onSubmit: onOk },
|
|
3884
|
-
React__default["default"].createElement(SearchFilterValueInput, {
|
|
3921
|
+
React__default["default"].createElement(SearchFilterValueInput, { resourceType: props.resourceType, searchParam: props.searchParam, defaultValue: value, autoFocus: true, onChange: setValue })))));
|
|
3885
3922
|
}
|
|
3886
3923
|
|
|
3887
3924
|
function MenuSeparator() {
|
|
@@ -4077,7 +4114,7 @@
|
|
|
4077
4114
|
function SearchControl(props) {
|
|
4078
4115
|
var _a, _b, _c, _d;
|
|
4079
4116
|
const medplum = useMedplum();
|
|
4080
|
-
const [
|
|
4117
|
+
const [schemaLoaded, setSchemaLoaded] = React.useState(false);
|
|
4081
4118
|
const [outcome, setOutcome] = React.useState();
|
|
4082
4119
|
const { search, onLoad } = props;
|
|
4083
4120
|
const [state, setState] = React.useState({
|
|
@@ -4095,7 +4132,7 @@
|
|
|
4095
4132
|
React.useEffect(() => {
|
|
4096
4133
|
setOutcome(undefined);
|
|
4097
4134
|
medplum
|
|
4098
|
-
.search(search.resourceType, core.formatSearchQuery(Object.assign(Object.assign({}, search), { total: 'accurate' })))
|
|
4135
|
+
.search(search.resourceType, core.formatSearchQuery(Object.assign(Object.assign({}, search), { total: 'accurate', fields: undefined })))
|
|
4099
4136
|
.then((response) => {
|
|
4100
4137
|
setState(Object.assign(Object.assign({}, stateRef.current), { searchResponse: response }));
|
|
4101
4138
|
if (onLoad) {
|
|
@@ -4187,21 +4224,18 @@
|
|
|
4187
4224
|
}
|
|
4188
4225
|
}
|
|
4189
4226
|
React.useEffect(() => {
|
|
4227
|
+
setSchemaLoaded(false);
|
|
4190
4228
|
medplum
|
|
4191
4229
|
.requestSchema(props.search.resourceType)
|
|
4192
|
-
.then((
|
|
4193
|
-
// The schema could have the same object identity,
|
|
4194
|
-
// so need to use the spread operator to kick React re-render.
|
|
4195
|
-
setSchema(Object.assign({}, newSchema));
|
|
4196
|
-
})
|
|
4230
|
+
.then(() => setSchemaLoaded(true))
|
|
4197
4231
|
.catch(console.log);
|
|
4198
4232
|
}, [medplum, props.search.resourceType]);
|
|
4199
|
-
const typeSchema = (_a =
|
|
4233
|
+
const typeSchema = schemaLoaded && ((_a = core.globalSchema === null || core.globalSchema === void 0 ? void 0 : core.globalSchema.types) === null || _a === void 0 ? void 0 : _a[props.search.resourceType]);
|
|
4200
4234
|
if (!typeSchema) {
|
|
4201
4235
|
return React__default["default"].createElement(Loading, null);
|
|
4202
4236
|
}
|
|
4203
4237
|
const checkboxColumn = props.checkboxesEnabled;
|
|
4204
|
-
const fields = getFieldDefinitions(
|
|
4238
|
+
const fields = getFieldDefinitions(search);
|
|
4205
4239
|
const resourceType = search.resourceType;
|
|
4206
4240
|
const lastResult = state.searchResponse;
|
|
4207
4241
|
const entries = lastResult === null || lastResult === void 0 ? void 0 : lastResult.entry;
|
|
@@ -4251,7 +4285,7 @@
|
|
|
4251
4285
|
(resources === null || resources === void 0 ? void 0 : resources.length) === 0 && (React__default["default"].createElement("div", { "data-testid": "empty-search", className: "medplum-empty-search" }, "No results")),
|
|
4252
4286
|
outcome && (React__default["default"].createElement("div", { "data-testid": "search-error", className: "medplum-empty-search" },
|
|
4253
4287
|
React__default["default"].createElement("pre", { style: { textAlign: 'left' } }, JSON.stringify(outcome, undefined, 2)))),
|
|
4254
|
-
React__default["default"].createElement(SearchPopupMenu, {
|
|
4288
|
+
React__default["default"].createElement(SearchPopupMenu, { search: props.search, visible: state.popupVisible, x: state.popupX, y: state.popupY, searchParams: state.popupSearchParams, onPrompt: (searchParam, filter) => {
|
|
4255
4289
|
setState(Object.assign(Object.assign({}, stateRef.current), { popupVisible: false, filterDialogVisible: true, filterDialogSearchParam: searchParam, filterDialogFilter: filter }));
|
|
4256
4290
|
}, onChange: (result) => {
|
|
4257
4291
|
emitSearchChange(result);
|
|
@@ -4259,19 +4293,19 @@
|
|
|
4259
4293
|
}, onClose: () => {
|
|
4260
4294
|
setState(Object.assign(Object.assign({}, stateRef.current), { popupVisible: false, popupSearchParams: undefined }));
|
|
4261
4295
|
} }),
|
|
4262
|
-
React__default["default"].createElement(SearchFieldEditor, {
|
|
4296
|
+
React__default["default"].createElement(SearchFieldEditor, { search: props.search, visible: stateRef.current.fieldEditorVisible, onOk: (result) => {
|
|
4263
4297
|
emitSearchChange(result);
|
|
4264
4298
|
setState(Object.assign(Object.assign({}, stateRef.current), { fieldEditorVisible: false }));
|
|
4265
4299
|
}, onCancel: () => {
|
|
4266
4300
|
setState(Object.assign(Object.assign({}, stateRef.current), { fieldEditorVisible: false }));
|
|
4267
4301
|
} }),
|
|
4268
|
-
React__default["default"].createElement(SearchFilterEditor, {
|
|
4302
|
+
React__default["default"].createElement(SearchFilterEditor, { search: props.search, visible: stateRef.current.filterEditorVisible, onOk: (result) => {
|
|
4269
4303
|
emitSearchChange(result);
|
|
4270
4304
|
setState(Object.assign(Object.assign({}, stateRef.current), { filterEditorVisible: false }));
|
|
4271
4305
|
}, onCancel: () => {
|
|
4272
4306
|
setState(Object.assign(Object.assign({}, stateRef.current), { filterEditorVisible: false }));
|
|
4273
4307
|
} }),
|
|
4274
|
-
React__default["default"].createElement(SearchFilterValueDialog, { visible: stateRef.current.filterDialogVisible, title: 'Input',
|
|
4308
|
+
React__default["default"].createElement(SearchFilterValueDialog, { visible: stateRef.current.filterDialogVisible, title: 'Input', resourceType: resourceType, searchParam: state.filterDialogSearchParam, filter: state.filterDialogFilter, defaultValue: '', onOk: (filter) => {
|
|
4275
4309
|
emitSearchChange(addFilter(props.search, filter.code, filter.operator, filter.value));
|
|
4276
4310
|
setState(Object.assign(Object.assign({}, stateRef.current), { filterDialogVisible: false }));
|
|
4277
4311
|
}, onCancel: () => {
|
|
@@ -4820,6 +4854,8 @@
|
|
|
4820
4854
|
return (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
4821
4855
|
React__default["default"].createElement(FormSection, { title: "Title", htmlFor: `actionTitle-${action.id}` },
|
|
4822
4856
|
React__default["default"].createElement(Input, { name: `actionTitle-${action.id}`, defaultValue: action.title, onChange: (newValue) => changeProperty('title', newValue) })),
|
|
4857
|
+
React__default["default"].createElement(FormSection, { title: "Description", htmlFor: `actionDescription-${action.id}` },
|
|
4858
|
+
React__default["default"].createElement(Input, { name: `actionDescription-${action.id}`, defaultValue: action.description, onChange: (newValue) => changeProperty('description', newValue) })),
|
|
4823
4859
|
React__default["default"].createElement(FormSection, { title: "Type of Action", description: "The type of the action to be performed.", htmlFor: `actionType-${action.id}` },
|
|
4824
4860
|
React__default["default"].createElement(Select, { name: `actionType-${action.id}`, defaultValue: actionType, onChange: setActionType },
|
|
4825
4861
|
React__default["default"].createElement("option", null),
|
|
@@ -4934,81 +4970,6 @@
|
|
|
4934
4970
|
QuestionnaireItemType["reference"] = "reference";
|
|
4935
4971
|
QuestionnaireItemType["quantity"] = "quantity";
|
|
4936
4972
|
})(exports.QuestionnaireItemType || (exports.QuestionnaireItemType = {}));
|
|
4937
|
-
/**
|
|
4938
|
-
* Adds initial values to a questionnaire resource from key value pairs.
|
|
4939
|
-
* The values map uses "linkId" as key.
|
|
4940
|
-
* The value depends on the questionnaire item type.
|
|
4941
|
-
* @param questionnaire The original questionnaire.
|
|
4942
|
-
* @param values Key value pairs for initial values.
|
|
4943
|
-
* @returns Rewritten questionnaire with initial values.
|
|
4944
|
-
*/
|
|
4945
|
-
function addQuestionnaireInitialValues(questionnaire, values) {
|
|
4946
|
-
return Object.assign(Object.assign({}, questionnaire), { item: addInitialValuesToItemArray(questionnaire.item, values) });
|
|
4947
|
-
}
|
|
4948
|
-
function addInitialValuesToItemArray(items, values) {
|
|
4949
|
-
if (!items) {
|
|
4950
|
-
return undefined;
|
|
4951
|
-
}
|
|
4952
|
-
return items.map((item) => addInitialValueToItem(item, values));
|
|
4953
|
-
}
|
|
4954
|
-
function addInitialValueToItem(item, values) {
|
|
4955
|
-
const { linkId, type } = item;
|
|
4956
|
-
if (!linkId || !type) {
|
|
4957
|
-
return item;
|
|
4958
|
-
}
|
|
4959
|
-
if (type === 'group') {
|
|
4960
|
-
return Object.assign(Object.assign({}, item), { item: addInitialValuesToItemArray(item.item, values) });
|
|
4961
|
-
}
|
|
4962
|
-
const suppliedValue = values[linkId];
|
|
4963
|
-
if (!suppliedValue) {
|
|
4964
|
-
return item;
|
|
4965
|
-
}
|
|
4966
|
-
let initialValue = undefined;
|
|
4967
|
-
switch (type) {
|
|
4968
|
-
case core.PropertyType.boolean:
|
|
4969
|
-
initialValue = { valueBoolean: suppliedValue === 'true' };
|
|
4970
|
-
break;
|
|
4971
|
-
case core.PropertyType.code:
|
|
4972
|
-
case core.PropertyType.Coding:
|
|
4973
|
-
initialValue = { valueCoding: { code: suppliedValue } };
|
|
4974
|
-
break;
|
|
4975
|
-
case core.PropertyType.date:
|
|
4976
|
-
initialValue = { valueDate: suppliedValue };
|
|
4977
|
-
break;
|
|
4978
|
-
case core.PropertyType.dateTime:
|
|
4979
|
-
case core.PropertyType.instant:
|
|
4980
|
-
initialValue = { valueDateTime: suppliedValue };
|
|
4981
|
-
break;
|
|
4982
|
-
case core.PropertyType.decimal:
|
|
4983
|
-
initialValue = { valueDecimal: parseFloat(suppliedValue) };
|
|
4984
|
-
break;
|
|
4985
|
-
case core.PropertyType.integer:
|
|
4986
|
-
case core.PropertyType.positiveInt:
|
|
4987
|
-
case core.PropertyType.unsignedInt:
|
|
4988
|
-
initialValue = { valueInteger: parseInt(suppliedValue) };
|
|
4989
|
-
break;
|
|
4990
|
-
case core.PropertyType.SystemString:
|
|
4991
|
-
case core.PropertyType.string:
|
|
4992
|
-
case core.PropertyType.markdown:
|
|
4993
|
-
initialValue = { valueString: suppliedValue };
|
|
4994
|
-
break;
|
|
4995
|
-
case core.PropertyType.time:
|
|
4996
|
-
initialValue = { valueTime: suppliedValue };
|
|
4997
|
-
break;
|
|
4998
|
-
case core.PropertyType.uri:
|
|
4999
|
-
case core.PropertyType.url:
|
|
5000
|
-
initialValue = { valueUri: suppliedValue };
|
|
5001
|
-
break;
|
|
5002
|
-
case core.PropertyType.canonical:
|
|
5003
|
-
case core.PropertyType.Reference:
|
|
5004
|
-
initialValue = { valueReference: { reference: suppliedValue } };
|
|
5005
|
-
break;
|
|
5006
|
-
}
|
|
5007
|
-
if (!initialValue) {
|
|
5008
|
-
return item;
|
|
5009
|
-
}
|
|
5010
|
-
return Object.assign(Object.assign({}, item), { initial: [initialValue] });
|
|
5011
|
-
}
|
|
5012
4973
|
function isChoiceQuestion(item) {
|
|
5013
4974
|
return item.type === 'choice' || item.type === 'open-choice';
|
|
5014
4975
|
}
|
|
@@ -5442,6 +5403,15 @@
|
|
|
5442
5403
|
if (!items) {
|
|
5443
5404
|
return undefined;
|
|
5444
5405
|
}
|
|
5406
|
+
items.forEach((item) => {
|
|
5407
|
+
var _a, _b;
|
|
5408
|
+
if ((_a = item.id) === null || _a === void 0 ? void 0 : _a.match(/^id-\d+$/)) {
|
|
5409
|
+
nextId = Math.max(nextId, parseInt(item.id.substring(3)) + 1);
|
|
5410
|
+
}
|
|
5411
|
+
if ((_b = item.linkId) === null || _b === void 0 ? void 0 : _b.match(/^q\d+$/)) {
|
|
5412
|
+
nextLinkId = Math.max(nextLinkId, parseInt(item.linkId.substring(1)) + 1);
|
|
5413
|
+
}
|
|
5414
|
+
});
|
|
5445
5415
|
return items.map((item) => (Object.assign(Object.assign({}, item), { id: item.id || generateId(), item: ensureQuestionnaireItemKeys(item.item), answerOption: ensureQuestionnaireOptionKeys(item.answerOption) })));
|
|
5446
5416
|
}
|
|
5447
5417
|
function ensureQuestionnaireOptionKeys(options) {
|
|
@@ -5479,6 +5449,7 @@
|
|
|
5479
5449
|
React__default["default"].createElement("div", { className: "medplum-request-group-task-checkmark" }, (task === null || task === void 0 ? void 0 : task.status) === 'completed' ? '🗹' : '☐'),
|
|
5480
5450
|
React__default["default"].createElement("div", { className: "medplum-request-group-task-details" },
|
|
5481
5451
|
React__default["default"].createElement("div", { className: "medplum-request-group-task-title" }, action.title),
|
|
5452
|
+
action.description && React__default["default"].createElement("div", null, action.description),
|
|
5482
5453
|
React__default["default"].createElement("div", null,
|
|
5483
5454
|
"Last edited by\u00A0",
|
|
5484
5455
|
React__default["default"].createElement(ResourceName, { value: (_e = task === null || task === void 0 ? void 0 : task.meta) === null || _e === void 0 ? void 0 : _e.author }),
|
|
@@ -5636,6 +5607,7 @@
|
|
|
5636
5607
|
function blame(history) {
|
|
5637
5608
|
// Convert to array of array of lines
|
|
5638
5609
|
const versions = history.entry
|
|
5610
|
+
.filter((entry) => !!entry.resource)
|
|
5639
5611
|
.map((entry) => {
|
|
5640
5612
|
var _a;
|
|
5641
5613
|
return ({
|
|
@@ -6178,7 +6150,6 @@
|
|
|
6178
6150
|
exports.addLastMonthFilter = addLastMonthFilter;
|
|
6179
6151
|
exports.addMissingFilter = addMissingFilter;
|
|
6180
6152
|
exports.addNextMonthFilter = addNextMonthFilter;
|
|
6181
|
-
exports.addQuestionnaireInitialValues = addQuestionnaireInitialValues;
|
|
6182
6153
|
exports.addThisMonthFilter = addThisMonthFilter;
|
|
6183
6154
|
exports.addTodayFilter = addTodayFilter;
|
|
6184
6155
|
exports.addTomorrowFilter = addTomorrowFilter;
|