@medplum/react 0.9.32 → 0.9.35
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/QuestionnaireForm.d.ts +4 -1
- package/dist/cjs/Scheduler.d.ts +2 -1
- 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/SearchFilterValueInput.d.ts +0 -2
- package/dist/cjs/SearchPopupMenu.d.ts +1 -2
- package/dist/cjs/auth/AuthenticationForm.d.ts +2 -0
- package/dist/cjs/auth/SignInForm.d.ts +2 -0
- package/dist/cjs/index.js +125 -71
- 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/stories/QuestionnaireForm.stories.d.ts +1 -0
- package/dist/cjs/styles.css +51 -51
- package/dist/esm/GoogleButton.js +2 -2
- package/dist/esm/GoogleButton.js.map +1 -1
- package/dist/esm/Popup.js +5 -1
- package/dist/esm/Popup.js.map +1 -1
- package/dist/esm/QuestionnaireBuilder.js +1 -1
- package/dist/esm/QuestionnaireBuilder.js.map +1 -1
- package/dist/esm/QuestionnaireForm.d.ts +4 -1
- package/dist/esm/QuestionnaireForm.js +49 -10
- package/dist/esm/QuestionnaireForm.js.map +1 -1
- package/dist/esm/Scheduler.d.ts +2 -1
- package/dist/esm/Scheduler.js +18 -24
- package/dist/esm/Scheduler.js.map +1 -1
- package/dist/esm/SearchControl.js +10 -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/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/ServiceRequestTimeline.js +3 -3
- package/dist/esm/ServiceRequestTimeline.js.map +1 -1
- package/dist/esm/auth/AuthenticationForm.d.ts +2 -0
- package/dist/esm/auth/AuthenticationForm.js +4 -0
- package/dist/esm/auth/AuthenticationForm.js.map +1 -1
- package/dist/esm/auth/SignInForm.d.ts +2 -0
- 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/stories/QuestionnaireForm.stories.d.ts +1 -0
- 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 +13 -13
- package/stats.html +4034 -0
|
@@ -1,28 +1,26 @@
|
|
|
1
|
-
import { getSearchParameterDetails } from '@medplum/core';
|
|
1
|
+
import { globalSchema, getSearchParameterDetails } from '@medplum/core';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Returns the collection of field definitions for the search request.
|
|
5
|
-
* @param typeSchema The schema for the resource type
|
|
6
5
|
* @param search The search request definition.
|
|
7
6
|
* @returns An array of field definitions.
|
|
8
7
|
*/
|
|
9
|
-
function getFieldDefinitions(
|
|
8
|
+
function getFieldDefinitions(search) {
|
|
10
9
|
const resourceType = search.resourceType;
|
|
11
10
|
const fields = [];
|
|
12
11
|
for (const name of search.fields || ['id', '_lastUpdated']) {
|
|
13
|
-
fields.push(getFieldDefinition(
|
|
12
|
+
fields.push(getFieldDefinition(resourceType, name));
|
|
14
13
|
}
|
|
15
14
|
return fields;
|
|
16
15
|
}
|
|
17
16
|
/**
|
|
18
17
|
* Return the field definition for a given field name.
|
|
19
18
|
* Field names can be either property names or search parameter codes.
|
|
20
|
-
* @param typeSchema The schema for the resource type
|
|
21
19
|
* @param resourceType The resource type.
|
|
22
20
|
* @param name The search field name (either property name or search parameter code).
|
|
23
21
|
* @returns The field definition.
|
|
24
22
|
*/
|
|
25
|
-
function getFieldDefinition(
|
|
23
|
+
function getFieldDefinition(resourceType, name) {
|
|
26
24
|
var _a;
|
|
27
25
|
if (name === '_lastUpdated') {
|
|
28
26
|
return {
|
|
@@ -54,7 +52,7 @@ function getFieldDefinition(schema, resourceType, name) {
|
|
|
54
52
|
],
|
|
55
53
|
};
|
|
56
54
|
}
|
|
57
|
-
const typeSchema =
|
|
55
|
+
const typeSchema = globalSchema.types[resourceType];
|
|
58
56
|
const exactElementDefinition = typeSchema.properties[name];
|
|
59
57
|
const exactSearchParam = (_a = typeSchema.searchParams) === null || _a === void 0 ? void 0 : _a[name.toLowerCase()];
|
|
60
58
|
// Best case: Exact match of element definition or search parameter.
|
|
@@ -85,7 +83,7 @@ function getFieldDefinition(schema, resourceType, name) {
|
|
|
85
83
|
// Patient.email is a search parameter for the Patient.telecom element.
|
|
86
84
|
// So we need to walk backwards to find the element definition.
|
|
87
85
|
if (exactSearchParam) {
|
|
88
|
-
const details = getSearchParameterDetails(
|
|
86
|
+
const details = getSearchParameterDetails(resourceType, exactSearchParam);
|
|
89
87
|
return { name, elementDefinition: details.elementDefinition, searchParams: [exactSearchParam] };
|
|
90
88
|
}
|
|
91
89
|
// Worst case: no element definition and no search parameter.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchControlField.js","sources":["../../src/SearchControlField.ts"],"sourcesContent":["import { getSearchParameterDetails,
|
|
1
|
+
{"version":3,"file":"SearchControlField.js","sources":["../../src/SearchControlField.ts"],"sourcesContent":["import { getSearchParameterDetails, globalSchema, SearchRequest } from '@medplum/core';\nimport { ElementDefinition, SearchParameter } from '@medplum/fhirtypes';\n\n/**\n * The SearchControlField type describes a field in the search control.\n *\n * In a SearchRequest, a field is a simple string. Strings can be one of the following:\n * 1) Simple property names, which refer to ElementDefinition objects\n * 2) Search parameter names, which refer to SearchParameter resources\n *\n * Consider a few examples of how this becomes complicated.\n *\n * \"name\" (easy)\n * - element definition path=\"Patient.name\"\n * - search parameter code=\"name\"\n *\n * \"birthDate\" (medium)\n * - refers to the element definition path=\"Patient.birthDate\"\n * - refers to the search parameter code=\"birthdate\" (note the capitalization)\n *\n * \"email\" (hard)\n * - refers to the search parameter code=\"email\"\n * - refers to the element definition path=\"Patient.telecom\"\n *\n * In the last case, we start with the search parameter, and walk backwards to the\n * element definition in order to get type details for rendering.\n *\n * Overall, we want columns, fields, properties, and search parameters to feel seamless,\n * so we try our darndest to make this work.\n */\nexport interface SearchControlField {\n readonly name: string;\n readonly elementDefinition?: ElementDefinition;\n readonly searchParams?: SearchParameter[];\n}\n\n/**\n * Returns the collection of field definitions for the search request.\n * @param search The search request definition.\n * @returns An array of field definitions.\n */\nexport function getFieldDefinitions(search: SearchRequest): SearchControlField[] {\n const resourceType = search.resourceType;\n const fields = [] as SearchControlField[];\n\n for (const name of search.fields || ['id', '_lastUpdated']) {\n fields.push(getFieldDefinition(resourceType, name));\n }\n return fields;\n}\n\n/**\n * Return the field definition for a given field name.\n * Field names can be either property names or search parameter codes.\n * @param resourceType The resource type.\n * @param name The search field name (either property name or search parameter code).\n * @returns The field definition.\n */\nfunction getFieldDefinition(resourceType: string, name: string): SearchControlField {\n if (name === '_lastUpdated') {\n return {\n name: '_lastUpdated',\n searchParams: [\n {\n resourceType: 'SearchParameter',\n base: ['Resource'],\n code: '_lastUpdated',\n name: '_lastUpdated',\n type: 'date',\n expression: 'Resource.meta.lastUpdated',\n },\n ],\n };\n }\n\n if (name === 'meta.versionId') {\n return {\n name: 'meta.versionId',\n searchParams: [\n {\n resourceType: 'SearchParameter',\n base: ['Resource'],\n code: '_versionId',\n name: '_versionId',\n type: 'token',\n expression: 'Resource.meta.versionId',\n },\n ],\n };\n }\n\n const typeSchema = globalSchema.types[resourceType];\n const exactElementDefinition: ElementDefinition | undefined = typeSchema.properties[name];\n const exactSearchParam: SearchParameter | undefined = typeSchema.searchParams?.[name.toLowerCase()];\n\n // Best case: Exact match of element definition or search parameter.\n // Examples: ServiceRequest.subject, Patient.name, Patient.birthDate\n // In this case, we only show the one search parameter.\n if (exactElementDefinition && exactSearchParam) {\n return { name, elementDefinition: exactElementDefinition, searchParams: [exactSearchParam] };\n }\n\n // Next best case: Exact match of element definition\n // Examples: Observation.value\n // In this case, there could be zero or more search parameters that are a function of the element definition.\n // So search for those search parameters.\n if (exactElementDefinition) {\n let searchParams: SearchParameter[] | undefined = undefined;\n if (typeSchema.searchParams) {\n const path = `${resourceType}.${name.replaceAll('[x]', '')}`;\n searchParams = Object.values(typeSchema.searchParams).filter((p) => p.expression?.includes(path));\n if (searchParams.length === 0) {\n searchParams = undefined;\n }\n }\n return { name, elementDefinition: exactElementDefinition, searchParams };\n }\n\n // Search parameter case: Exact match of search parameter\n // Examples: Observation.value-quantity, Patient.email\n // Here we have a search parameter, but no element definition.\n // Observation.value-quantity is a search parameter for the Observation.value element.\n // Patient.email is a search parameter for the Patient.telecom element.\n // So we need to walk backwards to find the element definition.\n if (exactSearchParam) {\n const details = getSearchParameterDetails(resourceType, exactSearchParam);\n return { name, elementDefinition: details.elementDefinition, searchParams: [exactSearchParam] };\n }\n\n // Worst case: no element definition and no search parameter.\n // This is probably a malformed URL that includes an unknown field.\n // We will render the column header, but all cells will be empty.\n return { name };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -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,4 +1,4 @@
|
|
|
1
|
-
import { stringify } from '@medplum/core';
|
|
1
|
+
import { stringify, globalSchema } from '@medplum/core';
|
|
2
2
|
import React, { useState, useRef, useEffect } from 'react';
|
|
3
3
|
import { Button } from './Button.js';
|
|
4
4
|
import { Dialog } from './Dialog.js';
|
|
@@ -130,7 +130,7 @@ function SearchFieldEditor(props) {
|
|
|
130
130
|
return null;
|
|
131
131
|
}
|
|
132
132
|
const resourceType = props.search.resourceType;
|
|
133
|
-
const typeDef =
|
|
133
|
+
const typeDef = globalSchema.types[resourceType];
|
|
134
134
|
const selected = (_a = state.search.fields) !== null && _a !== void 0 ? _a : [];
|
|
135
135
|
const available = getFieldsList(typeDef)
|
|
136
136
|
.filter((field) => !(selected === null || selected === void 0 ? void 0 : selected.includes(field)))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchFieldEditor.js","sources":["../../src/SearchFieldEditor.tsx"],"sourcesContent":["import { IndexedStructureDefinition, SearchRequest, stringify, TypeSchema } from '@medplum/core';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { Button } from './Button';\nimport { Dialog } from './Dialog';\nimport { buildFieldNameString } from './SearchUtils';\n\ninterface SearchFieldEditorProps {\n schema: IndexedStructureDefinition;\n visible: boolean;\n search: SearchRequest;\n onOk: (search: SearchRequest) => void;\n onCancel: () => void;\n}\n\nexport function SearchFieldEditor(props: SearchFieldEditorProps): JSX.Element | null {\n const [state, setState] = useState({\n search: JSON.parse(stringify(props.search)) as SearchRequest,\n });\n\n const availableRef = useRef<HTMLSelectElement>(null);\n const selectedRef = useRef<HTMLSelectElement>(null);\n\n useEffect(() => {\n setState({ search: props.search });\n }, [props.search]);\n\n /**\n * Handles a key down event on the \"available\" field.\n * If the user presses enter, it is a shortcut for the \"Add\" button.\n *\n * @param {KeyboardEvent} e The keyboard event.\n */\n function handleAvailableKeyDown(e: React.KeyboardEvent): void {\n if (e.key === 'Enter') {\n onAddField();\n }\n }\n\n /**\n * Handles a double click on the \"available\" field.\n * If the user double clicks an entry, it is a shortcut for the \"Add\" button.\n */\n function handleAvailableDoubleClick(): void {\n onAddField();\n }\n\n /**\n * Handles a key down event on the \"available\" field.\n * If the user presses enter, it is a shortcut for the \"Add\" button.\n *\n * @param {KeyboardEvent} e The keyboard event.\n */\n function handleSelectedKeyDown(e: React.KeyboardEvent): void {\n if (e.key === 'Enter') {\n onRemoveField();\n }\n }\n\n /**\n * Handles a double click on the \"available\" field.\n * If the user double clicks an entry, it is a shortcut for the \"Add\" button.\n */\n function handleSelectedDoubleClick(): void {\n onRemoveField();\n }\n\n /**\n * Handles a click on the \"Add\" button.\n * Moves the \"available\" selection into the \"selected\" list.\n */\n function onAddField(): void {\n const currentField = state.search.fields ?? [];\n const key = availableRef.current?.value;\n if (key) {\n const newFields = [...currentField, key];\n setState({\n search: {\n ...state.search,\n fields: newFields,\n },\n });\n }\n }\n\n /**\n * Handles a click on the \"Remove\" button.\n * Moves the \"selected\" selection into the \"available\" list.\n */\n function onRemoveField(): void {\n const currentField = state.search.fields ?? [];\n const key = selectedRef.current?.value;\n if (key) {\n const newFields = [...currentField];\n newFields.splice(newFields.indexOf(key), 1);\n setState({\n search: {\n ...state.search,\n fields: newFields,\n },\n });\n }\n }\n\n /**\n * Handles a click on the \"Up\" button.\n * Moves the selection up one position in the list.\n */\n function onMoveUp(): void {\n const currentField = state.search.fields ?? [];\n const field = selectedRef.current?.value;\n if (field) {\n const newFields = [...currentField];\n const index = newFields.indexOf(field);\n swapFields(newFields, index, index - 1);\n\n setState({\n search: {\n ...state.search,\n fields: newFields,\n },\n });\n }\n }\n\n /**\n * Handles a click on the \"Down\" button.\n * Moves the selection down one position in the list.\n */\n function onMoveDown(): void {\n const currentField = state.search.fields ?? [];\n const field = selectedRef.current?.value;\n if (field) {\n const newFields = [...currentField];\n const index = newFields.indexOf(field);\n swapFields(newFields, index, index + 1);\n\n setState({\n search: {\n ...state.search,\n fields: newFields,\n },\n });\n }\n }\n\n /**\n * Swaps two fields in the search.\n *\n * @param {number} i The index of the first field.\n * @param {number} j The index of the second field.\n */\n function swapFields(fields: string[], i: number, j: number): void {\n const temp = fields[i];\n fields[i] = fields[j];\n fields[j] = temp;\n }\n\n if (!props.visible) {\n return null;\n }\n\n const resourceType = props.search.resourceType;\n const typeDef = props.schema.types[resourceType];\n\n const selected = state.search.fields ?? [];\n const available = getFieldsList(typeDef)\n .filter((field) => !selected?.includes(field))\n .sort();\n\n return (\n <Dialog title=\"Fields\" visible={props.visible} onOk={() => props.onOk(state.search)} onCancel={props.onCancel}>\n <div>\n <table style={{ margin: 'auto' }}>\n <thead>\n <tr>\n <th colSpan={2} align=\"center\">\n Available\n </th>\n <th colSpan={2} align=\"center\">\n Selected\n </th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td colSpan={2} align=\"center\">\n <select\n ref={availableRef}\n size={15}\n tabIndex={1}\n style={{ width: '200px' }}\n onKeyDown={(e) => handleAvailableKeyDown(e)}\n onDoubleClick={() => handleAvailableDoubleClick()}\n data-testid=\"available\"\n >\n {available.map((key) => (\n <option key={key} value={key}>\n {buildFieldNameString(key)}\n </option>\n ))}\n </select>\n </td>\n <td colSpan={2} align=\"center\">\n <select\n ref={selectedRef}\n size={15}\n tabIndex={4}\n style={{ width: '200px' }}\n onKeyDown={(e) => handleSelectedKeyDown(e)}\n onDoubleClick={() => handleSelectedDoubleClick()}\n data-testid=\"selected\"\n >\n {selected.map((key) => (\n <option key={key} value={key}>\n {buildFieldNameString(key)}\n </option>\n ))}\n </select>\n </td>\n </tr>\n </tbody>\n <tfoot>\n <tr>\n <td align=\"center\">\n <Button size=\"small\" onClick={onAddField}>\n Add\n </Button>\n </td>\n <td align=\"center\">\n <Button size=\"small\" onClick={onRemoveField}>\n Remove\n </Button>\n </td>\n <td align=\"center\">\n <Button size=\"small\" onClick={onMoveUp}>\n Up\n </Button>\n </td>\n <td align=\"center\">\n <Button size=\"small\" onClick={onMoveDown}>\n Down\n </Button>\n </td>\n </tr>\n </tfoot>\n </table>\n </div>\n </Dialog>\n );\n}\n\n/**\n * Returns a list of fields/columns available for a type.\n * The result is the union of properties and search parameters.\n * @param typeSchema The type definition.\n */\nfunction getFieldsList(typeSchema: TypeSchema): string[] {\n const result = [] as string[];\n const keys = new Set<string>();\n const names = new Set<string>();\n\n // Add properties first\n for (const key of Object.keys(typeSchema.properties)) {\n result.push(key);\n keys.add(key.toLowerCase());\n names.add(buildFieldNameString(key));\n }\n\n // Add search parameters if unique\n if (typeSchema.searchParams) {\n for (const code of Object.keys(typeSchema.searchParams)) {\n const name = buildFieldNameString(code);\n if (!keys.has(code) && !names.has(name)) {\n result.push(code);\n keys.add(code);\n names.add(buildFieldNameString(code));\n }\n }\n }\n\n return result;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SearchFieldEditor.js","sources":["../../src/SearchFieldEditor.tsx"],"sourcesContent":["import { globalSchema, SearchRequest, stringify, TypeSchema } from '@medplum/core';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { Button } from './Button';\nimport { Dialog } from './Dialog';\nimport { buildFieldNameString } from './SearchUtils';\n\ninterface SearchFieldEditorProps {\n visible: boolean;\n search: SearchRequest;\n onOk: (search: SearchRequest) => void;\n onCancel: () => void;\n}\n\nexport function SearchFieldEditor(props: SearchFieldEditorProps): JSX.Element | null {\n const [state, setState] = useState({\n search: JSON.parse(stringify(props.search)) as SearchRequest,\n });\n\n const availableRef = useRef<HTMLSelectElement>(null);\n const selectedRef = useRef<HTMLSelectElement>(null);\n\n useEffect(() => {\n setState({ search: props.search });\n }, [props.search]);\n\n /**\n * Handles a key down event on the \"available\" field.\n * If the user presses enter, it is a shortcut for the \"Add\" button.\n *\n * @param {KeyboardEvent} e The keyboard event.\n */\n function handleAvailableKeyDown(e: React.KeyboardEvent): void {\n if (e.key === 'Enter') {\n onAddField();\n }\n }\n\n /**\n * Handles a double click on the \"available\" field.\n * If the user double clicks an entry, it is a shortcut for the \"Add\" button.\n */\n function handleAvailableDoubleClick(): void {\n onAddField();\n }\n\n /**\n * Handles a key down event on the \"available\" field.\n * If the user presses enter, it is a shortcut for the \"Add\" button.\n *\n * @param {KeyboardEvent} e The keyboard event.\n */\n function handleSelectedKeyDown(e: React.KeyboardEvent): void {\n if (e.key === 'Enter') {\n onRemoveField();\n }\n }\n\n /**\n * Handles a double click on the \"available\" field.\n * If the user double clicks an entry, it is a shortcut for the \"Add\" button.\n */\n function handleSelectedDoubleClick(): void {\n onRemoveField();\n }\n\n /**\n * Handles a click on the \"Add\" button.\n * Moves the \"available\" selection into the \"selected\" list.\n */\n function onAddField(): void {\n const currentField = state.search.fields ?? [];\n const key = availableRef.current?.value;\n if (key) {\n const newFields = [...currentField, key];\n setState({\n search: {\n ...state.search,\n fields: newFields,\n },\n });\n }\n }\n\n /**\n * Handles a click on the \"Remove\" button.\n * Moves the \"selected\" selection into the \"available\" list.\n */\n function onRemoveField(): void {\n const currentField = state.search.fields ?? [];\n const key = selectedRef.current?.value;\n if (key) {\n const newFields = [...currentField];\n newFields.splice(newFields.indexOf(key), 1);\n setState({\n search: {\n ...state.search,\n fields: newFields,\n },\n });\n }\n }\n\n /**\n * Handles a click on the \"Up\" button.\n * Moves the selection up one position in the list.\n */\n function onMoveUp(): void {\n const currentField = state.search.fields ?? [];\n const field = selectedRef.current?.value;\n if (field) {\n const newFields = [...currentField];\n const index = newFields.indexOf(field);\n swapFields(newFields, index, index - 1);\n\n setState({\n search: {\n ...state.search,\n fields: newFields,\n },\n });\n }\n }\n\n /**\n * Handles a click on the \"Down\" button.\n * Moves the selection down one position in the list.\n */\n function onMoveDown(): void {\n const currentField = state.search.fields ?? [];\n const field = selectedRef.current?.value;\n if (field) {\n const newFields = [...currentField];\n const index = newFields.indexOf(field);\n swapFields(newFields, index, index + 1);\n\n setState({\n search: {\n ...state.search,\n fields: newFields,\n },\n });\n }\n }\n\n /**\n * Swaps two fields in the search.\n *\n * @param {number} i The index of the first field.\n * @param {number} j The index of the second field.\n */\n function swapFields(fields: string[], i: number, j: number): void {\n const temp = fields[i];\n fields[i] = fields[j];\n fields[j] = temp;\n }\n\n if (!props.visible) {\n return null;\n }\n\n const resourceType = props.search.resourceType;\n const typeDef = globalSchema.types[resourceType];\n\n const selected = state.search.fields ?? [];\n const available = getFieldsList(typeDef)\n .filter((field) => !selected?.includes(field))\n .sort();\n\n return (\n <Dialog title=\"Fields\" visible={props.visible} onOk={() => props.onOk(state.search)} onCancel={props.onCancel}>\n <div>\n <table style={{ margin: 'auto' }}>\n <thead>\n <tr>\n <th colSpan={2} align=\"center\">\n Available\n </th>\n <th colSpan={2} align=\"center\">\n Selected\n </th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td colSpan={2} align=\"center\">\n <select\n ref={availableRef}\n size={15}\n tabIndex={1}\n style={{ width: '200px' }}\n onKeyDown={(e) => handleAvailableKeyDown(e)}\n onDoubleClick={() => handleAvailableDoubleClick()}\n data-testid=\"available\"\n >\n {available.map((key) => (\n <option key={key} value={key}>\n {buildFieldNameString(key)}\n </option>\n ))}\n </select>\n </td>\n <td colSpan={2} align=\"center\">\n <select\n ref={selectedRef}\n size={15}\n tabIndex={4}\n style={{ width: '200px' }}\n onKeyDown={(e) => handleSelectedKeyDown(e)}\n onDoubleClick={() => handleSelectedDoubleClick()}\n data-testid=\"selected\"\n >\n {selected.map((key) => (\n <option key={key} value={key}>\n {buildFieldNameString(key)}\n </option>\n ))}\n </select>\n </td>\n </tr>\n </tbody>\n <tfoot>\n <tr>\n <td align=\"center\">\n <Button size=\"small\" onClick={onAddField}>\n Add\n </Button>\n </td>\n <td align=\"center\">\n <Button size=\"small\" onClick={onRemoveField}>\n Remove\n </Button>\n </td>\n <td align=\"center\">\n <Button size=\"small\" onClick={onMoveUp}>\n Up\n </Button>\n </td>\n <td align=\"center\">\n <Button size=\"small\" onClick={onMoveDown}>\n Down\n </Button>\n </td>\n </tr>\n </tfoot>\n </table>\n </div>\n </Dialog>\n );\n}\n\n/**\n * Returns a list of fields/columns available for a type.\n * The result is the union of properties and search parameters.\n * @param typeSchema The type definition.\n */\nfunction getFieldsList(typeSchema: TypeSchema): string[] {\n const result = [] as string[];\n const keys = new Set<string>();\n const names = new Set<string>();\n\n // Add properties first\n for (const key of Object.keys(typeSchema.properties)) {\n result.push(key);\n keys.add(key.toLowerCase());\n names.add(buildFieldNameString(key));\n }\n\n // Add search parameters if unique\n if (typeSchema.searchParams) {\n for (const code of Object.keys(typeSchema.searchParams)) {\n const name = buildFieldNameString(code);\n if (!keys.has(code) && !names.has(name)) {\n result.push(code);\n keys.add(code);\n names.add(buildFieldNameString(code));\n }\n }\n }\n\n return result;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -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,4 +1,4 @@
|
|
|
1
|
-
import { stringify } from '@medplum/core';
|
|
1
|
+
import { stringify, globalSchema } from '@medplum/core';
|
|
2
2
|
import React, { useState, useRef, useEffect } from 'react';
|
|
3
3
|
import { Button } from './Button.js';
|
|
4
4
|
import { Dialog } from './Dialog.js';
|
|
@@ -21,9 +21,8 @@ function SearchFilterEditor(props) {
|
|
|
21
21
|
if (!props.visible) {
|
|
22
22
|
return null;
|
|
23
23
|
}
|
|
24
|
-
const schema = props.schema;
|
|
25
24
|
const resourceType = props.search.resourceType;
|
|
26
|
-
const searchParams =
|
|
25
|
+
const searchParams = globalSchema.types[resourceType].searchParams;
|
|
27
26
|
const filters = search.filters || [];
|
|
28
27
|
return (React.createElement(Dialog, { title: "Filters", visible: props.visible, onOk: () => props.onOk(searchRef.current), onCancel: props.onCancel },
|
|
29
28
|
React.createElement("div", { className: "medplum-filter-editor" },
|
|
@@ -42,7 +41,7 @@ function SearchFilterEditor(props) {
|
|
|
42
41
|
React.createElement("tbody", null,
|
|
43
42
|
filters.map((filter, index) => {
|
|
44
43
|
if (index === editingIndex) {
|
|
45
|
-
return (React.createElement(FilterRowInput, { key: `filter-${index}-${filters.length}-input`,
|
|
44
|
+
return (React.createElement(FilterRowInput, { key: `filter-${index}-${filters.length}-input`, resourceType: resourceType, searchParams: searchParams, defaultValue: filter, okText: "Save", onOk: (newFilter) => {
|
|
46
45
|
const newFilters = [...filters];
|
|
47
46
|
newFilters[index] = newFilter;
|
|
48
47
|
setSearch(setFilters(searchRef.current, newFilters));
|
|
@@ -53,7 +52,7 @@ function SearchFilterEditor(props) {
|
|
|
53
52
|
return (React.createElement(FilterRowDisplay, { key: `filter-${index}-${filters.length}-display`, resourceType: resourceType, searchParams: searchParams, filter: filter, onEdit: () => setEditingIndex(index), onDelete: () => setSearch(deleteFilter(searchRef.current, index)) }));
|
|
54
53
|
}
|
|
55
54
|
}),
|
|
56
|
-
React.createElement(FilterRowInput, {
|
|
55
|
+
React.createElement(FilterRowInput, { resourceType: resourceType, searchParams: searchParams, okText: "Add", onOk: onAddFilter }))))));
|
|
57
56
|
}
|
|
58
57
|
function FilterRowDisplay(props) {
|
|
59
58
|
const { filter } = props;
|
|
@@ -90,7 +89,7 @@ function FilterRowInput(props) {
|
|
|
90
89
|
React.createElement("td", null, operators && (React.createElement(Select, { testid: "filter-operation", defaultValue: value.operator, onChange: setFilterOperator },
|
|
91
90
|
React.createElement("option", { value: "" }),
|
|
92
91
|
operators.map((operator) => (React.createElement("option", { key: operator, value: operator }, getOpString(operator))))))),
|
|
93
|
-
React.createElement("td", null, searchParam && value.operator && (React.createElement(SearchFilterValueInput, {
|
|
92
|
+
React.createElement("td", null, searchParam && value.operator && (React.createElement(SearchFilterValueInput, { resourceType: props.resourceType, searchParam: searchParam, defaultValue: value.value, onChange: setFilterValue }))),
|
|
94
93
|
React.createElement("td", null,
|
|
95
94
|
value.code && value.operator && value.value && (React.createElement(Button, { size: "small", onClick: () => {
|
|
96
95
|
props.onOk(valueRef.current);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchFilterEditor.js","sources":["../../src/SearchFilterEditor.tsx"],"sourcesContent":["import { Filter, IndexedStructureDefinition, Operator, SearchRequest, stringify } from '@medplum/core';\nimport { SearchParameter } from '@medplum/fhirtypes';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { Button } from './Button';\nimport { Dialog } from './Dialog';\nimport { SearchFilterValueDisplay } from './SearchFilterValueDisplay';\nimport { SearchFilterValueInput } from './SearchFilterValueInput';\nimport {\n addFilter,\n buildFieldNameString,\n deleteFilter,\n getOpString,\n getSearchOperators,\n setFilters,\n} from './SearchUtils';\nimport { Select } from './Select';\nimport './SearchFilterEditor.css';\n\nexport interface SearchFilterEditorProps {\n schema: IndexedStructureDefinition;\n visible: boolean;\n search: SearchRequest;\n onOk: (search: SearchRequest) => void;\n onCancel: () => void;\n}\n\nexport function SearchFilterEditor(props: SearchFilterEditorProps): JSX.Element | null {\n const [search, setSearch] = useState<SearchRequest>(JSON.parse(stringify(props.search)) as SearchRequest);\n const [editingIndex, setEditingIndex] = useState<number>(-1);\n\n const searchRef = useRef<SearchRequest>(search);\n searchRef.current = search;\n\n useEffect(() => {\n setSearch(JSON.parse(stringify(props.search)) as SearchRequest);\n }, [props.search]);\n\n function onAddFilter(filter: Filter): void {\n setSearch(addFilter(searchRef.current, filter.code, filter.operator, filter.value));\n }\n\n if (!props.visible) {\n return null;\n }\n\n const schema = props.schema;\n const resourceType = props.search.resourceType;\n const searchParams = schema.types[resourceType].searchParams as Record<string, SearchParameter>;\n const filters = search.filters || [];\n\n return (\n <Dialog\n title=\"Filters\"\n visible={props.visible}\n onOk={() => props.onOk(searchRef.current)}\n onCancel={props.onCancel}\n >\n <div className=\"medplum-filter-editor\">\n <table className=\"medplum-filter-editor-table\">\n <colgroup>\n <col style={{ width: 200 }} />\n <col style={{ width: 200 }} />\n <col style={{ width: 380 }} />\n <col style={{ width: 120 }} />\n </colgroup>\n <thead>\n <tr>\n <th>Field</th>\n <th>Operation</th>\n <th>Value</th>\n <th>Actions</th>\n </tr>\n </thead>\n <tbody>\n {filters.map((filter: Filter, index: number) => {\n if (index === editingIndex) {\n return (\n <FilterRowInput\n key={`filter-${index}-${filters.length}-input`}\n schema={schema}\n resourceType={resourceType}\n searchParams={searchParams}\n defaultValue={filter}\n okText=\"Save\"\n onOk={(newFilter: Filter) => {\n const newFilters = [...filters];\n newFilters[index] = newFilter;\n setSearch(setFilters(searchRef.current, newFilters));\n setEditingIndex(-1);\n }}\n onCancel={() => setEditingIndex(-1)}\n />\n );\n } else {\n return (\n <FilterRowDisplay\n key={`filter-${index}-${filters.length}-display`}\n resourceType={resourceType}\n searchParams={searchParams}\n filter={filter}\n onEdit={() => setEditingIndex(index)}\n onDelete={() => setSearch(deleteFilter(searchRef.current, index))}\n />\n );\n }\n })}\n <FilterRowInput\n schema={schema}\n resourceType={resourceType}\n searchParams={searchParams}\n okText=\"Add\"\n onOk={onAddFilter}\n />\n </tbody>\n </table>\n </div>\n </Dialog>\n );\n}\n\ninterface FilterRowDisplayProps {\n readonly searchParams: Record<string, SearchParameter>;\n readonly resourceType: string;\n readonly filter: Filter;\n readonly onEdit: () => void;\n readonly onDelete: () => void;\n}\n\nfunction FilterRowDisplay(props: FilterRowDisplayProps): JSX.Element | null {\n const { filter } = props;\n return (\n <tr>\n <td>{buildFieldNameString(filter.code)}</td>\n <td>{getOpString(filter.operator)}</td>\n <td>\n <SearchFilterValueDisplay resourceType={props.resourceType} filter={filter} />\n </td>\n <td>\n <Button size=\"small\" onClick={props.onEdit}>\n Edit\n </Button>\n <Button size=\"small\" onClick={props.onDelete}>\n Delete\n </Button>\n </td>\n </tr>\n );\n}\n\ninterface FilterRowInputProps {\n schema: IndexedStructureDefinition;\n resourceType: string;\n searchParams: Record<string, SearchParameter>;\n defaultValue?: Filter;\n okText: string;\n onOk: (value: Filter) => void;\n onCancel?: () => void;\n}\n\nfunction FilterRowInput(props: FilterRowInputProps): JSX.Element {\n const [value, setValue] = useState<Filter>(props.defaultValue ?? ({} as Filter));\n const valueRef = useRef<Filter>(value);\n valueRef.current = value;\n\n function setFilterCode(newCode: string): void {\n setValue({ ...valueRef.current, code: newCode });\n }\n\n function setFilterOperator(newOperator: Operator): void {\n setValue({ ...valueRef.current, operator: newOperator });\n }\n\n function setFilterValue(newFilterValue: string): void {\n setValue({ ...valueRef.current, value: newFilterValue });\n }\n\n const searchParam = props.searchParams[value.code];\n const operators = searchParam && getSearchOperators(searchParam);\n\n return (\n <tr>\n <td>\n <Select testid=\"filter-field\" defaultValue={valueRef.current.code} onChange={setFilterCode}>\n <option value=\"\"></option>\n {Object.keys(props.searchParams).map((param) => (\n <option key={param} value={param}>\n {buildFieldNameString(param)}\n </option>\n ))}\n </Select>\n </td>\n <td>\n {operators && (\n <Select\n testid=\"filter-operation\"\n defaultValue={value.operator}\n onChange={setFilterOperator as (newOperator: string) => void}\n >\n <option value=\"\"></option>\n {operators.map((operator) => (\n <option key={operator} value={operator}>\n {getOpString(operator)}\n </option>\n ))}\n </Select>\n )}\n </td>\n <td>\n {searchParam && value.operator && (\n <SearchFilterValueInput\n schema={props.schema}\n resourceType={props.resourceType}\n searchParam={searchParam}\n defaultValue={value.value}\n onChange={setFilterValue}\n />\n )}\n </td>\n <td>\n {value.code && value.operator && value.value && (\n <Button\n size=\"small\"\n onClick={() => {\n props.onOk(valueRef.current);\n setValue({} as Filter);\n }}\n >\n {props.okText}\n </Button>\n )}\n {props.onCancel && (\n <Button size=\"small\" onClick={props.onCancel}>\n Cancel\n </Button>\n )}\n </td>\n </tr>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SearchFilterEditor.js","sources":["../../src/SearchFilterEditor.tsx"],"sourcesContent":["import { Filter, globalSchema, Operator, SearchRequest, stringify } from '@medplum/core';\nimport { SearchParameter } from '@medplum/fhirtypes';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { Button } from './Button';\nimport { Dialog } from './Dialog';\nimport { SearchFilterValueDisplay } from './SearchFilterValueDisplay';\nimport { SearchFilterValueInput } from './SearchFilterValueInput';\nimport {\n addFilter,\n buildFieldNameString,\n deleteFilter,\n getOpString,\n getSearchOperators,\n setFilters,\n} from './SearchUtils';\nimport { Select } from './Select';\nimport './SearchFilterEditor.css';\n\nexport interface SearchFilterEditorProps {\n visible: boolean;\n search: SearchRequest;\n onOk: (search: SearchRequest) => void;\n onCancel: () => void;\n}\n\nexport function SearchFilterEditor(props: SearchFilterEditorProps): JSX.Element | null {\n const [search, setSearch] = useState<SearchRequest>(JSON.parse(stringify(props.search)) as SearchRequest);\n const [editingIndex, setEditingIndex] = useState<number>(-1);\n\n const searchRef = useRef<SearchRequest>(search);\n searchRef.current = search;\n\n useEffect(() => {\n setSearch(JSON.parse(stringify(props.search)) as SearchRequest);\n }, [props.search]);\n\n function onAddFilter(filter: Filter): void {\n setSearch(addFilter(searchRef.current, filter.code, filter.operator, filter.value));\n }\n\n if (!props.visible) {\n return null;\n }\n\n const resourceType = props.search.resourceType;\n const searchParams = globalSchema.types[resourceType].searchParams as Record<string, SearchParameter>;\n const filters = search.filters || [];\n\n return (\n <Dialog\n title=\"Filters\"\n visible={props.visible}\n onOk={() => props.onOk(searchRef.current)}\n onCancel={props.onCancel}\n >\n <div className=\"medplum-filter-editor\">\n <table className=\"medplum-filter-editor-table\">\n <colgroup>\n <col style={{ width: 200 }} />\n <col style={{ width: 200 }} />\n <col style={{ width: 380 }} />\n <col style={{ width: 120 }} />\n </colgroup>\n <thead>\n <tr>\n <th>Field</th>\n <th>Operation</th>\n <th>Value</th>\n <th>Actions</th>\n </tr>\n </thead>\n <tbody>\n {filters.map((filter: Filter, index: number) => {\n if (index === editingIndex) {\n return (\n <FilterRowInput\n key={`filter-${index}-${filters.length}-input`}\n resourceType={resourceType}\n searchParams={searchParams}\n defaultValue={filter}\n okText=\"Save\"\n onOk={(newFilter: Filter) => {\n const newFilters = [...filters];\n newFilters[index] = newFilter;\n setSearch(setFilters(searchRef.current, newFilters));\n setEditingIndex(-1);\n }}\n onCancel={() => setEditingIndex(-1)}\n />\n );\n } else {\n return (\n <FilterRowDisplay\n key={`filter-${index}-${filters.length}-display`}\n resourceType={resourceType}\n searchParams={searchParams}\n filter={filter}\n onEdit={() => setEditingIndex(index)}\n onDelete={() => setSearch(deleteFilter(searchRef.current, index))}\n />\n );\n }\n })}\n <FilterRowInput resourceType={resourceType} searchParams={searchParams} okText=\"Add\" onOk={onAddFilter} />\n </tbody>\n </table>\n </div>\n </Dialog>\n );\n}\n\ninterface FilterRowDisplayProps {\n readonly searchParams: Record<string, SearchParameter>;\n readonly resourceType: string;\n readonly filter: Filter;\n readonly onEdit: () => void;\n readonly onDelete: () => void;\n}\n\nfunction FilterRowDisplay(props: FilterRowDisplayProps): JSX.Element | null {\n const { filter } = props;\n return (\n <tr>\n <td>{buildFieldNameString(filter.code)}</td>\n <td>{getOpString(filter.operator)}</td>\n <td>\n <SearchFilterValueDisplay resourceType={props.resourceType} filter={filter} />\n </td>\n <td>\n <Button size=\"small\" onClick={props.onEdit}>\n Edit\n </Button>\n <Button size=\"small\" onClick={props.onDelete}>\n Delete\n </Button>\n </td>\n </tr>\n );\n}\n\ninterface FilterRowInputProps {\n resourceType: string;\n searchParams: Record<string, SearchParameter>;\n defaultValue?: Filter;\n okText: string;\n onOk: (value: Filter) => void;\n onCancel?: () => void;\n}\n\nfunction FilterRowInput(props: FilterRowInputProps): JSX.Element {\n const [value, setValue] = useState<Filter>(props.defaultValue ?? ({} as Filter));\n const valueRef = useRef<Filter>(value);\n valueRef.current = value;\n\n function setFilterCode(newCode: string): void {\n setValue({ ...valueRef.current, code: newCode });\n }\n\n function setFilterOperator(newOperator: Operator): void {\n setValue({ ...valueRef.current, operator: newOperator });\n }\n\n function setFilterValue(newFilterValue: string): void {\n setValue({ ...valueRef.current, value: newFilterValue });\n }\n\n const searchParam = props.searchParams[value.code];\n const operators = searchParam && getSearchOperators(searchParam);\n\n return (\n <tr>\n <td>\n <Select testid=\"filter-field\" defaultValue={valueRef.current.code} onChange={setFilterCode}>\n <option value=\"\"></option>\n {Object.keys(props.searchParams).map((param) => (\n <option key={param} value={param}>\n {buildFieldNameString(param)}\n </option>\n ))}\n </Select>\n </td>\n <td>\n {operators && (\n <Select\n testid=\"filter-operation\"\n defaultValue={value.operator}\n onChange={setFilterOperator as (newOperator: string) => void}\n >\n <option value=\"\"></option>\n {operators.map((operator) => (\n <option key={operator} value={operator}>\n {getOpString(operator)}\n </option>\n ))}\n </Select>\n )}\n </td>\n <td>\n {searchParam && value.operator && (\n <SearchFilterValueInput\n resourceType={props.resourceType}\n searchParam={searchParam}\n defaultValue={value.value}\n onChange={setFilterValue}\n />\n )}\n </td>\n <td>\n {value.code && value.operator && value.value && (\n <Button\n size=\"small\"\n onClick={() => {\n props.onOk(valueRef.current);\n setValue({} as Filter);\n }}\n >\n {props.okText}\n </Button>\n )}\n {props.onCancel && (\n <Button size=\"small\" onClick={props.onCancel}>\n Cancel\n </Button>\n )}\n </td>\n </tr>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;AAyBM,SAAU,kBAAkB,CAAC,KAA8B,EAAA;IAC/D,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAkB,CAAC,CAAC;IAC1G,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAS,CAAC,CAAC,CAAC,CAAC;AAE7D,IAAA,MAAM,SAAS,GAAG,MAAM,CAAgB,MAAM,CAAC,CAAC;AAChD,IAAA,SAAS,CAAC,OAAO,GAAG,MAAM,CAAC;IAE3B,SAAS,CAAC,MAAK;AACb,QAAA,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAkB,CAAC,CAAC;AAClE,KAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAEnB,SAAS,WAAW,CAAC,MAAc,EAAA;QACjC,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;KACrF;AAED,IAAA,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE;AAClB,QAAA,OAAO,IAAI,CAAC;AACb,KAAA;AAED,IAAA,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC;IAC/C,MAAM,YAAY,GAAG,YAAY,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,YAA+C,CAAC;AACtG,IAAA,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;AAErC,IAAA,QACE,KAAA,CAAA,aAAA,CAAC,MAAM,EAAA,EACL,KAAK,EAAC,SAAS,EACf,OAAO,EAAE,KAAK,CAAC,OAAO,EACtB,IAAI,EAAE,MAAM,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EACzC,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAA;QAExB,KAAK,CAAA,aAAA,CAAA,KAAA,EAAA,EAAA,SAAS,EAAC,uBAAuB,EAAA;YACpC,KAAO,CAAA,aAAA,CAAA,OAAA,EAAA,EAAA,SAAS,EAAC,6BAA6B,EAAA;AAC5C,gBAAA,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,IAAA;AACE,oBAAA,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,EAAI,CAAA;AAC9B,oBAAA,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,EAAI,CAAA;AAC9B,oBAAA,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,EAAI,CAAA;oBAC9B,KAAK,CAAA,aAAA,CAAA,KAAA,EAAA,EAAA,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,GAAI,CACrB;AACX,gBAAA,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA,IAAA;AACE,oBAAA,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA;wBACE,KAAc,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA,EAAA,OAAA,CAAA;wBACd,KAAkB,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA,EAAA,WAAA,CAAA;wBAClB,KAAc,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA,EAAA,OAAA,CAAA;AACd,wBAAA,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA,EAAA,SAAA,CAAgB,CACb,CACC;AACR,gBAAA,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA,IAAA;oBACG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAc,EAAE,KAAa,KAAI;wBAC7C,IAAI,KAAK,KAAK,YAAY,EAAE;AAC1B,4BAAA,QACE,KAAA,CAAA,aAAA,CAAC,cAAc,EAAA,EACb,GAAG,EAAE,CAAA,OAAA,EAAU,KAAK,CAAA,CAAA,EAAI,OAAO,CAAC,MAAM,CAAQ,MAAA,CAAA,EAC9C,YAAY,EAAE,YAAY,EAC1B,YAAY,EAAE,YAAY,EAC1B,YAAY,EAAE,MAAM,EACpB,MAAM,EAAC,MAAM,EACb,IAAI,EAAE,CAAC,SAAiB,KAAI;AAC1B,oCAAA,MAAM,UAAU,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC;AAChC,oCAAA,UAAU,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC;oCAC9B,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;AACrD,oCAAA,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;AACtB,iCAAC,EACD,QAAQ,EAAE,MAAM,eAAe,CAAC,CAAC,CAAC,CAAC,EAAA,CACnC,EACF;AACH,yBAAA;AAAM,6BAAA;4BACL,QACE,KAAC,CAAA,aAAA,CAAA,gBAAgB,EACf,EAAA,GAAG,EAAE,CAAU,OAAA,EAAA,KAAK,CAAI,CAAA,EAAA,OAAO,CAAC,MAAM,UAAU,EAChD,YAAY,EAAE,YAAY,EAC1B,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,eAAe,CAAC,KAAK,CAAC,EACpC,QAAQ,EAAE,MAAM,SAAS,CAAC,YAAY,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,EACjE,CAAA,EACF;AACH,yBAAA;AACH,qBAAC,CAAC;oBACF,KAAC,CAAA,aAAA,CAAA,cAAc,IAAC,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,EAAC,KAAK,EAAC,IAAI,EAAE,WAAW,EAAA,CAAI,CACpG,CACF,CACJ,CACC,EACT;AACJ,CAAC;AAUD,SAAS,gBAAgB,CAAC,KAA4B,EAAA;AACpD,IAAA,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;AACzB,IAAA,QACE,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA;AACE,QAAA,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA,EAAK,oBAAoB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAM;AAC5C,QAAA,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA,EAAK,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAM;AACvC,QAAA,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA;AACE,YAAA,KAAA,CAAA,aAAA,CAAC,wBAAwB,EAAA,EAAC,YAAY,EAAE,KAAK,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAA,CAAI,CAC3E;AACL,QAAA,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA;YACE,KAAC,CAAA,aAAA,CAAA,MAAM,EAAC,EAAA,IAAI,EAAC,OAAO,EAAC,OAAO,EAAE,KAAK,CAAC,MAAM,EAEjC,EAAA,MAAA,CAAA;AACT,YAAA,KAAA,CAAA,aAAA,CAAC,MAAM,EAAA,EAAC,IAAI,EAAC,OAAO,EAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,EAAA,EAAA,QAAA,CAEnC,CACN,CACF,EACL;AACJ,CAAC;AAWD,SAAS,cAAc,CAAC,KAA0B,EAAA;;AAChD,IAAA,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAS,CAAA,EAAA,GAAA,KAAK,CAAC,YAAY,MAAK,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAA,EAAa,CAAC,CAAC;AACjF,IAAA,MAAM,QAAQ,GAAG,MAAM,CAAS,KAAK,CAAC,CAAC;AACvC,IAAA,QAAQ,CAAC,OAAO,GAAG,KAAK,CAAC;IAEzB,SAAS,aAAa,CAAC,OAAe,EAAA;QACpC,QAAQ,CAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,EAAA,EAAM,QAAQ,CAAC,OAAO,KAAE,IAAI,EAAE,OAAO,EAAA,CAAA,CAAG,CAAC;KAClD;IAED,SAAS,iBAAiB,CAAC,WAAqB,EAAA;QAC9C,QAAQ,CAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,EAAA,EAAM,QAAQ,CAAC,OAAO,KAAE,QAAQ,EAAE,WAAW,EAAA,CAAA,CAAG,CAAC;KAC1D;IAED,SAAS,cAAc,CAAC,cAAsB,EAAA;QAC5C,QAAQ,CAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,EAAA,EAAM,QAAQ,CAAC,OAAO,KAAE,KAAK,EAAE,cAAc,EAAA,CAAA,CAAG,CAAC;KAC1D;IAED,MAAM,WAAW,GAAG,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnD,MAAM,SAAS,GAAG,WAAW,IAAI,kBAAkB,CAAC,WAAW,CAAC,CAAC;AAEjE,IAAA,QACE,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA;AACE,QAAA,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA;AACE,YAAA,KAAA,CAAA,aAAA,CAAC,MAAM,EAAC,EAAA,MAAM,EAAC,cAAc,EAAC,YAAY,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,aAAa,EAAA;gBACxF,KAAQ,CAAA,aAAA,CAAA,QAAA,EAAA,EAAA,KAAK,EAAC,EAAE,EAAU,CAAA;AACzB,gBAAA,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,MACzC,KAAQ,CAAA,aAAA,CAAA,QAAA,EAAA,EAAA,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAA,EAC7B,oBAAoB,CAAC,KAAK,CAAC,CACrB,CACV,CAAC,CACK,CACN;AACL,QAAA,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA,EACG,SAAS,KACR,oBAAC,MAAM,EAAA,EACL,MAAM,EAAC,kBAAkB,EACzB,YAAY,EAAE,KAAK,CAAC,QAAQ,EAC5B,QAAQ,EAAE,iBAAkD,EAAA;YAE5D,KAAQ,CAAA,aAAA,CAAA,QAAA,EAAA,EAAA,KAAK,EAAC,EAAE,EAAU,CAAA;YACzB,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,MACtB,KAAQ,CAAA,aAAA,CAAA,QAAA,EAAA,EAAA,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EACnC,EAAA,WAAW,CAAC,QAAQ,CAAC,CACf,CACV,CAAC,CACK,CACV,CACE;AACL,QAAA,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA,EACG,WAAW,IAAI,KAAK,CAAC,QAAQ,KAC5B,KAAA,CAAA,aAAA,CAAC,sBAAsB,EAAA,EACrB,YAAY,EAAE,KAAK,CAAC,YAAY,EAChC,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,KAAK,CAAC,KAAK,EACzB,QAAQ,EAAE,cAAc,EAAA,CACxB,CACH,CACE;AACL,QAAA,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA;YACG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,KAAK,KAC1C,KAAC,CAAA,aAAA,CAAA,MAAM,IACL,IAAI,EAAC,OAAO,EACZ,OAAO,EAAE,MAAK;AACZ,oBAAA,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;oBAC7B,QAAQ,CAAC,EAAY,CAAC,CAAC;AACzB,iBAAC,EAEA,EAAA,KAAK,CAAC,MAAM,CACN,CACV;YACA,KAAK,CAAC,QAAQ,KACb,oBAAC,MAAM,EAAA,EAAC,IAAI,EAAC,OAAO,EAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,aAEnC,CACV,CACE,CACF,EACL;AACJ;;;;"}
|
|
@@ -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;
|
|
@@ -15,7 +15,7 @@ function SearchFilterValueDialog(props) {
|
|
|
15
15
|
return (React.createElement(Dialog, { title: props.title, visible: props.visible, onOk: onOk, onCancel: props.onCancel },
|
|
16
16
|
React.createElement("div", { style: { width: 500 } },
|
|
17
17
|
React.createElement(Form, { onSubmit: onOk },
|
|
18
|
-
React.createElement(SearchFilterValueInput, {
|
|
18
|
+
React.createElement(SearchFilterValueInput, { resourceType: props.resourceType, searchParam: props.searchParam, defaultValue: value, autoFocus: true, onChange: setValue })))));
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export { SearchFilterValueDialog };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchFilterValueDialog.js","sources":["../../src/SearchFilterValueDialog.tsx"],"sourcesContent":["import { Filter
|
|
1
|
+
{"version":3,"file":"SearchFilterValueDialog.js","sources":["../../src/SearchFilterValueDialog.tsx"],"sourcesContent":["import { Filter } from '@medplum/core';\nimport { SearchParameter } from '@medplum/fhirtypes';\nimport React, { useState } from 'react';\nimport { Dialog } from './Dialog';\nimport { Form } from './Form';\nimport { SearchFilterValueInput } from './SearchFilterValueInput';\n\nexport interface SearchFilterValueDialogProps {\n title: string;\n visible: boolean;\n resourceType: string;\n searchParam?: SearchParameter;\n filter?: Filter;\n defaultValue?: string;\n onOk: (filter: Filter) => void;\n onCancel: () => void;\n}\n\nexport function SearchFilterValueDialog(props: SearchFilterValueDialogProps): JSX.Element | null {\n const [value, setValue] = useState<string>(props.defaultValue ?? '');\n\n if (!props.visible || !props.searchParam || !props.filter) {\n return null;\n }\n\n function onOk(): void {\n props.onOk({ ...(props.filter as Filter), value });\n }\n\n return (\n <Dialog title={props.title} visible={props.visible} onOk={onOk} onCancel={props.onCancel}>\n <div style={{ width: 500 }}>\n <Form onSubmit={onOk}>\n <SearchFilterValueInput\n resourceType={props.resourceType}\n searchParam={props.searchParam}\n defaultValue={value}\n autoFocus={true}\n onChange={setValue}\n />\n </Form>\n </div>\n </Dialog>\n );\n}\n"],"names":[],"mappings":";;;;;AAkBM,SAAU,uBAAuB,CAAC,KAAmC,EAAA;;AACzE,IAAA,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAS,CAAA,EAAA,GAAA,KAAK,CAAC,YAAY,MAAI,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAA,EAAE,CAAC,CAAC;AAErE,IAAA,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;AACzD,QAAA,OAAO,IAAI,CAAC;AACb,KAAA;AAED,IAAA,SAAS,IAAI,GAAA;QACX,KAAK,CAAC,IAAI,CAAO,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,EAAA,EAAA,KAAK,CAAC,MAAiB,CAAA,EAAA,EAAE,KAAK,EAAA,CAAA,CAAG,CAAC;KACpD;IAED,QACE,KAAC,CAAA,aAAA,CAAA,MAAM,EAAC,EAAA,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAA;AACtF,QAAA,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,EAAA;AACxB,YAAA,KAAA,CAAA,aAAA,CAAC,IAAI,EAAA,EAAC,QAAQ,EAAE,IAAI,EAAA;AAClB,gBAAA,KAAA,CAAA,aAAA,CAAC,sBAAsB,EAAA,EACrB,YAAY,EAAE,KAAK,CAAC,YAAY,EAChC,WAAW,EAAE,KAAK,CAAC,WAAW,EAC9B,YAAY,EAAE,KAAK,EACnB,SAAS,EAAE,IAAI,EACf,QAAQ,EAAE,QAAQ,EAClB,CAAA,CACG,CACH,CACC,EACT;AACJ;;;;"}
|
|
@@ -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;
|
|
@@ -8,7 +8,7 @@ import { ReferenceInput } from './ReferenceInput.js';
|
|
|
8
8
|
|
|
9
9
|
function SearchFilterValueInput(props) {
|
|
10
10
|
var _a;
|
|
11
|
-
const details = getSearchParameterDetails(props.
|
|
11
|
+
const details = getSearchParameterDetails(props.resourceType, props.searchParam);
|
|
12
12
|
const name = 'filter-value';
|
|
13
13
|
switch (details.type) {
|
|
14
14
|
case SearchParameterType.REFERENCE:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchFilterValueInput.js","sources":["../../src/SearchFilterValueInput.tsx"],"sourcesContent":["import { getSearchParameterDetails,
|
|
1
|
+
{"version":3,"file":"SearchFilterValueInput.js","sources":["../../src/SearchFilterValueInput.tsx"],"sourcesContent":["import { getSearchParameterDetails, SearchParameterType } from '@medplum/core';\nimport { Quantity, Reference, SearchParameter } from '@medplum/fhirtypes';\nimport React from 'react';\nimport { Checkbox } from './Checkbox';\nimport { DateTimeInput } from './DateTimeInput';\nimport { Input } from './Input';\nimport { QuantityInput } from './QuantityInput';\nimport { ReferenceInput } from './ReferenceInput';\n\nexport interface SearchFilterValueInputProps {\n resourceType: string;\n searchParam: SearchParameter;\n defaultValue?: string;\n autoFocus?: boolean;\n onChange: (value: string) => void;\n}\n\nexport function SearchFilterValueInput(props: SearchFilterValueInputProps): JSX.Element | null {\n const details = getSearchParameterDetails(props.resourceType, props.searchParam);\n const name = 'filter-value';\n\n switch (details.type) {\n case SearchParameterType.REFERENCE:\n return (\n <ReferenceInput\n name={name}\n defaultValue={{ reference: props.defaultValue }}\n targetTypes={props.searchParam?.target}\n onChange={(newReference: Reference | undefined) => {\n if (newReference) {\n props.onChange(newReference.reference as string);\n } else {\n props.onChange('');\n }\n }}\n />\n );\n\n case SearchParameterType.BOOLEAN:\n return (\n <Checkbox\n name={name}\n testid={name}\n defaultValue={props.defaultValue === 'true'}\n onChange={(newValue) => props.onChange(newValue.toString())}\n />\n );\n\n case SearchParameterType.DATE:\n return <Input type=\"date\" testid={name} defaultValue={props.defaultValue} onChange={props.onChange} />;\n\n case SearchParameterType.DATETIME:\n return <DateTimeInput testid={name} defaultValue={props.defaultValue} onChange={props.onChange} />;\n\n case SearchParameterType.NUMBER:\n return <Input type=\"number\" defaultValue={props.defaultValue} onChange={props.onChange} />;\n\n case SearchParameterType.QUANTITY:\n return (\n <QuantityInput\n name={name}\n defaultValue={tryParseQuantity(props.defaultValue)}\n onChange={(newQuantity: Quantity | undefined) => {\n if (newQuantity) {\n props.onChange(`${newQuantity.value}`);\n } else {\n props.onChange('');\n }\n }}\n />\n );\n\n default:\n return (\n <Input testid={name} defaultValue={props.defaultValue} autoFocus={props.autoFocus} onChange={props.onChange} />\n );\n }\n}\n\nfunction tryParseQuantity(value: string | undefined): Quantity | undefined {\n if (value) {\n const [valueString, systemString, unitString] = value.split('|');\n if (valueString) {\n return {\n value: parseFloat(valueString),\n system: systemString,\n unit: unitString,\n };\n }\n }\n return undefined;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -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;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchPopupMenu.js","sources":["../../src/SearchPopupMenu.tsx"],"sourcesContent":["import { Filter, IndexedStructureDefinition, Operator, SearchRequest } from '@medplum/core';\nimport { SearchParameter } from '@medplum/fhirtypes';\nimport React from 'react';\nimport { MenuItem } from './MenuItem';\nimport { MenuSeparator } from './MenuSeparator';\nimport { Popup } from './Popup';\nimport {\n addLastMonthFilter,\n addMissingFilter,\n addNextMonthFilter,\n addThisMonthFilter,\n addTodayFilter,\n addTomorrowFilter,\n addYearToDateFilter,\n addYesterdayFilter,\n buildFieldNameString,\n clearFiltersOnField,\n setSort,\n} from './SearchUtils';\nimport { SubMenu } from './SubMenu';\n\nexport interface SearchPopupMenuProps {\n schema: IndexedStructureDefinition;\n search: SearchRequest;\n visible: boolean;\n x: number;\n y: number;\n searchParams?: SearchParameter[];\n onPrompt: (searchParam: SearchParameter, filter: Filter) => void;\n onChange: (definition: SearchRequest) => void;\n onClose: () => void;\n}\n\nexport function SearchPopupMenu(props: SearchPopupMenuProps): JSX.Element | null {\n if (!props.searchParams) {\n return null;\n }\n\n function onSort(searchParam: SearchParameter, desc: boolean): void {\n onChange(setSort(props.search, searchParam.code as string, desc));\n }\n\n function onClear(searchParam: SearchParameter): void {\n onChange(clearFiltersOnField(props.search, searchParam.code as string));\n }\n\n function onPrompt(searchParam: SearchParameter, operator: Operator): void {\n props.onPrompt(searchParam, { code: searchParam.code as string, operator, value: '' });\n }\n\n function onChange(definition: SearchRequest): void {\n props.onChange(definition);\n }\n\n const anchor = { left: props.x, right: props.x, top: props.y, bottom: props.y } as DOMRectReadOnly;\n\n // If there is only one search parameter, then show it directly\n if (props.searchParams.length === 1) {\n return (\n <Popup visible={props.visible} anchor={anchor} autoClose={true} onClose={props.onClose}>\n <SearchParameterSubMenu\n search={props.search}\n searchParam={props.searchParams[0]}\n onSort={onSort}\n onPrompt={onPrompt}\n onChange={onChange}\n onClear={onClear}\n />\n </Popup>\n );\n }\n\n // Otherwise, show a menu, with each search parameter as a sub menu\n return (\n <Popup visible={props.visible} anchor={anchor} autoClose={true} onClose={props.onClose}>\n {props.searchParams.map((searchParam) => (\n <SubMenu key={searchParam.code as string} title={buildFieldNameString(searchParam.code as string)}>\n <SearchParameterSubMenu\n search={props.search}\n searchParam={searchParam}\n onSort={onSort}\n onPrompt={onPrompt}\n onChange={onChange}\n onClear={onClear}\n />\n </SubMenu>\n ))}\n </Popup>\n );\n}\n\ninterface SearchPopupSubMenuProps {\n search: SearchRequest;\n searchParam: SearchParameter;\n onSort: (searchParam: SearchParameter, descending: boolean) => void;\n onPrompt: (searchParam: SearchParameter, operator: Operator) => void;\n onChange: (search: SearchRequest) => void;\n onClear: (searchParam: SearchParameter) => void;\n}\n\nfunction SearchParameterSubMenu(props: SearchPopupSubMenuProps): JSX.Element {\n switch (props.searchParam.type) {\n case 'date':\n return <DateFilterSubMenu {...props} />;\n case 'number':\n case 'quantity':\n return <NumericFilterSubMenu {...props} />;\n case 'reference':\n return <ReferenceFilterSubMenu {...props} />;\n case 'string':\n case 'token':\n case 'uri':\n return <TextFilterSubMenu {...props} />;\n default:\n return <>Unknown search param type: {props.searchParam.type}</>;\n }\n}\n\nfunction DateFilterSubMenu(props: SearchPopupSubMenuProps): JSX.Element {\n const { searchParam } = props;\n const code = searchParam.code as string;\n return (\n <>\n <MenuItem onClick={() => props.onSort(searchParam, false)}>Sort Oldest to Newest</MenuItem>\n <MenuItem onClick={() => props.onSort(searchParam, true)}>Sort Newest to Oldest</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.EQUALS)}>Equals...</MenuItem>\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.NOT_EQUALS)}>Does not equal...</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.ENDS_BEFORE)}>Before...</MenuItem>\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.STARTS_AFTER)}>After...</MenuItem>\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.EQUALS)}>Between...</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onChange(addTomorrowFilter(props.search, code))}>Tomorrow</MenuItem>\n <MenuItem onClick={() => props.onChange(addTodayFilter(props.search, code))}>Today</MenuItem>\n <MenuItem onClick={() => props.onChange(addYesterdayFilter(props.search, code))}>Yesterday</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onChange(addNextMonthFilter(props.search, code))}>Next Month</MenuItem>\n <MenuItem onClick={() => props.onChange(addThisMonthFilter(props.search, code))}>This Month</MenuItem>\n <MenuItem onClick={() => props.onChange(addLastMonthFilter(props.search, code))}>Last Month</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onChange(addYearToDateFilter(props.search, code))}>Year to date</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onChange(addMissingFilter(props.search, code))}>Missing</MenuItem>\n <MenuItem onClick={() => props.onChange(addMissingFilter(props.search, code, false))}>Not missing</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onClear(searchParam)}>Clear filters</MenuItem>\n </>\n );\n}\n\nfunction NumericFilterSubMenu(props: SearchPopupSubMenuProps): JSX.Element {\n const { searchParam } = props;\n const code = searchParam.code as string;\n return (\n <>\n <MenuItem onClick={() => props.onSort(searchParam, false)}>Sort Smallest to Largest</MenuItem>\n <MenuItem onClick={() => props.onSort(searchParam, true)}>Sort Largest to Smallest</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.EQUALS)}>Equals...</MenuItem>\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.NOT_EQUALS)}>Does not equal...</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.GREATER_THAN)}>Greater than...</MenuItem>\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.GREATER_THAN_OR_EQUALS)}>\n Greater than or equal to...\n </MenuItem>\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.LESS_THAN)}>Less than...</MenuItem>\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.LESS_THAN_OR_EQUALS)}>\n Less than or equal to...\n </MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onChange(addMissingFilter(props.search, code))}>Missing</MenuItem>\n <MenuItem onClick={() => props.onChange(addMissingFilter(props.search, code, false))}>Not missing</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onClear(searchParam)}>Clear filters</MenuItem>\n </>\n );\n}\n\nfunction ReferenceFilterSubMenu(props: SearchPopupSubMenuProps): JSX.Element {\n const { searchParam } = props;\n const code = searchParam.code as string;\n return (\n <>\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.EQUALS)}>Equals...</MenuItem>\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.NOT)}>Does not equal...</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onChange(addMissingFilter(props.search, code))}>Missing</MenuItem>\n <MenuItem onClick={() => props.onChange(addMissingFilter(props.search, code, false))}>Not missing</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onClear(searchParam)}>Clear filters</MenuItem>\n </>\n );\n}\n\nfunction TextFilterSubMenu(props: SearchPopupSubMenuProps): JSX.Element {\n const { searchParam } = props;\n const code = searchParam.code as string;\n return (\n <>\n <MenuItem onClick={() => props.onSort(searchParam, false)}>Sort A to Z</MenuItem>\n <MenuItem onClick={() => props.onSort(searchParam, true)}>Sort Z to A</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.EQUALS)}>Equals...</MenuItem>\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.NOT)}>Does not equal...</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.CONTAINS)}>Contains...</MenuItem>\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.EQUALS)}>Does not contain...</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onChange(addMissingFilter(props.search, code))}>Missing</MenuItem>\n <MenuItem onClick={() => props.onChange(addMissingFilter(props.search, code, false))}>Not missing</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onClear(searchParam)}>Clear filters</MenuItem>\n </>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SearchPopupMenu.js","sources":["../../src/SearchPopupMenu.tsx"],"sourcesContent":["import { Filter, Operator, SearchRequest } from '@medplum/core';\nimport { SearchParameter } from '@medplum/fhirtypes';\nimport React from 'react';\nimport { MenuItem } from './MenuItem';\nimport { MenuSeparator } from './MenuSeparator';\nimport { Popup } from './Popup';\nimport {\n addLastMonthFilter,\n addMissingFilter,\n addNextMonthFilter,\n addThisMonthFilter,\n addTodayFilter,\n addTomorrowFilter,\n addYearToDateFilter,\n addYesterdayFilter,\n buildFieldNameString,\n clearFiltersOnField,\n setSort,\n} from './SearchUtils';\nimport { SubMenu } from './SubMenu';\n\nexport interface SearchPopupMenuProps {\n search: SearchRequest;\n visible: boolean;\n x: number;\n y: number;\n searchParams?: SearchParameter[];\n onPrompt: (searchParam: SearchParameter, filter: Filter) => void;\n onChange: (definition: SearchRequest) => void;\n onClose: () => void;\n}\n\nexport function SearchPopupMenu(props: SearchPopupMenuProps): JSX.Element | null {\n if (!props.searchParams) {\n return null;\n }\n\n function onSort(searchParam: SearchParameter, desc: boolean): void {\n onChange(setSort(props.search, searchParam.code as string, desc));\n }\n\n function onClear(searchParam: SearchParameter): void {\n onChange(clearFiltersOnField(props.search, searchParam.code as string));\n }\n\n function onPrompt(searchParam: SearchParameter, operator: Operator): void {\n props.onPrompt(searchParam, { code: searchParam.code as string, operator, value: '' });\n }\n\n function onChange(definition: SearchRequest): void {\n props.onChange(definition);\n }\n\n const anchor = { left: props.x, right: props.x, top: props.y, bottom: props.y } as DOMRectReadOnly;\n\n // If there is only one search parameter, then show it directly\n if (props.searchParams.length === 1) {\n return (\n <Popup visible={props.visible} anchor={anchor} autoClose={true} onClose={props.onClose}>\n <SearchParameterSubMenu\n search={props.search}\n searchParam={props.searchParams[0]}\n onSort={onSort}\n onPrompt={onPrompt}\n onChange={onChange}\n onClear={onClear}\n />\n </Popup>\n );\n }\n\n // Otherwise, show a menu, with each search parameter as a sub menu\n return (\n <Popup visible={props.visible} anchor={anchor} autoClose={true} onClose={props.onClose}>\n {props.searchParams.map((searchParam) => (\n <SubMenu key={searchParam.code as string} title={buildFieldNameString(searchParam.code as string)}>\n <SearchParameterSubMenu\n search={props.search}\n searchParam={searchParam}\n onSort={onSort}\n onPrompt={onPrompt}\n onChange={onChange}\n onClear={onClear}\n />\n </SubMenu>\n ))}\n </Popup>\n );\n}\n\ninterface SearchPopupSubMenuProps {\n search: SearchRequest;\n searchParam: SearchParameter;\n onSort: (searchParam: SearchParameter, descending: boolean) => void;\n onPrompt: (searchParam: SearchParameter, operator: Operator) => void;\n onChange: (search: SearchRequest) => void;\n onClear: (searchParam: SearchParameter) => void;\n}\n\nfunction SearchParameterSubMenu(props: SearchPopupSubMenuProps): JSX.Element {\n switch (props.searchParam.type) {\n case 'date':\n return <DateFilterSubMenu {...props} />;\n case 'number':\n case 'quantity':\n return <NumericFilterSubMenu {...props} />;\n case 'reference':\n return <ReferenceFilterSubMenu {...props} />;\n case 'string':\n case 'token':\n case 'uri':\n return <TextFilterSubMenu {...props} />;\n default:\n return <>Unknown search param type: {props.searchParam.type}</>;\n }\n}\n\nfunction DateFilterSubMenu(props: SearchPopupSubMenuProps): JSX.Element {\n const { searchParam } = props;\n const code = searchParam.code as string;\n return (\n <>\n <MenuItem onClick={() => props.onSort(searchParam, false)}>Sort Oldest to Newest</MenuItem>\n <MenuItem onClick={() => props.onSort(searchParam, true)}>Sort Newest to Oldest</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.EQUALS)}>Equals...</MenuItem>\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.NOT_EQUALS)}>Does not equal...</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.ENDS_BEFORE)}>Before...</MenuItem>\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.STARTS_AFTER)}>After...</MenuItem>\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.EQUALS)}>Between...</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onChange(addTomorrowFilter(props.search, code))}>Tomorrow</MenuItem>\n <MenuItem onClick={() => props.onChange(addTodayFilter(props.search, code))}>Today</MenuItem>\n <MenuItem onClick={() => props.onChange(addYesterdayFilter(props.search, code))}>Yesterday</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onChange(addNextMonthFilter(props.search, code))}>Next Month</MenuItem>\n <MenuItem onClick={() => props.onChange(addThisMonthFilter(props.search, code))}>This Month</MenuItem>\n <MenuItem onClick={() => props.onChange(addLastMonthFilter(props.search, code))}>Last Month</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onChange(addYearToDateFilter(props.search, code))}>Year to date</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onChange(addMissingFilter(props.search, code))}>Missing</MenuItem>\n <MenuItem onClick={() => props.onChange(addMissingFilter(props.search, code, false))}>Not missing</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onClear(searchParam)}>Clear filters</MenuItem>\n </>\n );\n}\n\nfunction NumericFilterSubMenu(props: SearchPopupSubMenuProps): JSX.Element {\n const { searchParam } = props;\n const code = searchParam.code as string;\n return (\n <>\n <MenuItem onClick={() => props.onSort(searchParam, false)}>Sort Smallest to Largest</MenuItem>\n <MenuItem onClick={() => props.onSort(searchParam, true)}>Sort Largest to Smallest</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.EQUALS)}>Equals...</MenuItem>\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.NOT_EQUALS)}>Does not equal...</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.GREATER_THAN)}>Greater than...</MenuItem>\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.GREATER_THAN_OR_EQUALS)}>\n Greater than or equal to...\n </MenuItem>\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.LESS_THAN)}>Less than...</MenuItem>\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.LESS_THAN_OR_EQUALS)}>\n Less than or equal to...\n </MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onChange(addMissingFilter(props.search, code))}>Missing</MenuItem>\n <MenuItem onClick={() => props.onChange(addMissingFilter(props.search, code, false))}>Not missing</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onClear(searchParam)}>Clear filters</MenuItem>\n </>\n );\n}\n\nfunction ReferenceFilterSubMenu(props: SearchPopupSubMenuProps): JSX.Element {\n const { searchParam } = props;\n const code = searchParam.code as string;\n return (\n <>\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.EQUALS)}>Equals...</MenuItem>\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.NOT)}>Does not equal...</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onChange(addMissingFilter(props.search, code))}>Missing</MenuItem>\n <MenuItem onClick={() => props.onChange(addMissingFilter(props.search, code, false))}>Not missing</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onClear(searchParam)}>Clear filters</MenuItem>\n </>\n );\n}\n\nfunction TextFilterSubMenu(props: SearchPopupSubMenuProps): JSX.Element {\n const { searchParam } = props;\n const code = searchParam.code as string;\n return (\n <>\n <MenuItem onClick={() => props.onSort(searchParam, false)}>Sort A to Z</MenuItem>\n <MenuItem onClick={() => props.onSort(searchParam, true)}>Sort Z to A</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.EQUALS)}>Equals...</MenuItem>\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.NOT)}>Does not equal...</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.CONTAINS)}>Contains...</MenuItem>\n <MenuItem onClick={() => props.onPrompt(searchParam, Operator.EQUALS)}>Does not contain...</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onChange(addMissingFilter(props.search, code))}>Missing</MenuItem>\n <MenuItem onClick={() => props.onChange(addMissingFilter(props.search, code, false))}>Not missing</MenuItem>\n <MenuSeparator />\n <MenuItem onClick={() => props.onClear(searchParam)}>Clear filters</MenuItem>\n </>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -16,19 +16,19 @@ function ServiceRequestTimeline(props) {
|
|
|
16
16
|
{
|
|
17
17
|
request: {
|
|
18
18
|
method: 'GET',
|
|
19
|
-
url: `Communication?based-on=${getReferenceString(resource)}`,
|
|
19
|
+
url: `Communication?based-on=${getReferenceString(resource)}&_sort=-_lastUpdated`,
|
|
20
20
|
},
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
request: {
|
|
24
24
|
method: 'GET',
|
|
25
|
-
url: `Media?_count=100&based-on=${getReferenceString(resource)}`,
|
|
25
|
+
url: `Media?_count=100&based-on=${getReferenceString(resource)}&_sort=-_lastUpdated`,
|
|
26
26
|
},
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
29
|
request: {
|
|
30
30
|
method: 'GET',
|
|
31
|
-
url: `DiagnosticReport?based-on=${getReferenceString(resource)}`,
|
|
31
|
+
url: `DiagnosticReport?based-on=${getReferenceString(resource)}&_sort=-_lastUpdated`,
|
|
32
32
|
},
|
|
33
33
|
},
|
|
34
34
|
],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServiceRequestTimeline.js","sources":["../../src/ServiceRequestTimeline.tsx"],"sourcesContent":["import { createReference, getReferenceString, ProfileResource } from '@medplum/core';\nimport { Attachment, Group, Patient, Reference, Resource, ServiceRequest } from '@medplum/fhirtypes';\nimport React from 'react';\nimport { ResourceTimeline } from './ResourceTimeline';\n\nexport interface ServiceRequestTimelineProps {\n serviceRequest: ServiceRequest | Reference<ServiceRequest>;\n}\n\nexport function ServiceRequestTimeline(props: ServiceRequestTimelineProps): JSX.Element {\n return (\n <ResourceTimeline\n value={props.serviceRequest}\n buildSearchRequests={(resource: Resource) => ({\n resourceType: 'Bundle',\n type: 'batch',\n entry: [\n {\n request: {\n method: 'GET',\n url: `${getReferenceString(resource)}/_history`,\n },\n },\n {\n request: {\n method: 'GET',\n url: `Communication?based-on=${getReferenceString(resource)}`,\n },\n },\n {\n request: {\n method: 'GET',\n url: `Media?_count=100&based-on=${getReferenceString(resource)}`,\n },\n },\n {\n request: {\n method: 'GET',\n url: `DiagnosticReport?based-on=${getReferenceString(resource)}`,\n },\n },\n ],\n })}\n createCommunication={(resource: ServiceRequest, sender: ProfileResource, text: string) => ({\n resourceType: 'Communication',\n basedOn: [createReference(resource)],\n subject: resource.subject as Reference<Group | Patient>,\n sender: createReference(sender),\n sent: new Date().toISOString(),\n payload: [{ contentString: text }],\n })}\n createMedia={(resource: ServiceRequest, operator: ProfileResource, content: Attachment) => ({\n resourceType: 'Media',\n basedOn: [createReference(resource)],\n subject: resource.subject,\n operator: createReference(operator),\n issued: new Date().toISOString(),\n content,\n })}\n />\n );\n}\n"],"names":[],"mappings":";;;;AASM,SAAU,sBAAsB,CAAC,KAAkC,EAAA;AACvE,IAAA,QACE,KAAC,CAAA,aAAA,CAAA,gBAAgB,EACf,EAAA,KAAK,EAAE,KAAK,CAAC,cAAc,EAC3B,mBAAmB,EAAE,CAAC,QAAkB,MAAM;AAC5C,YAAA,YAAY,EAAE,QAAQ;AACtB,YAAA,IAAI,EAAE,OAAO;AACb,YAAA,KAAK,EAAE;AACL,gBAAA;AACE,oBAAA,OAAO,EAAE;AACP,wBAAA,MAAM,EAAE,KAAK;AACb,wBAAA,GAAG,EAAE,CAAG,EAAA,kBAAkB,CAAC,QAAQ,CAAC,CAAW,SAAA,CAAA;AAChD,qBAAA;AACF,iBAAA;AACD,gBAAA;AACE,oBAAA,OAAO,EAAE;AACP,wBAAA,MAAM,EAAE,KAAK;AACb,wBAAA,GAAG,EAAE,CAA0B,uBAAA,EAAA,kBAAkB,CAAC,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"ServiceRequestTimeline.js","sources":["../../src/ServiceRequestTimeline.tsx"],"sourcesContent":["import { createReference, getReferenceString, ProfileResource } from '@medplum/core';\nimport { Attachment, Group, Patient, Reference, Resource, ServiceRequest } from '@medplum/fhirtypes';\nimport React from 'react';\nimport { ResourceTimeline } from './ResourceTimeline';\n\nexport interface ServiceRequestTimelineProps {\n serviceRequest: ServiceRequest | Reference<ServiceRequest>;\n}\n\nexport function ServiceRequestTimeline(props: ServiceRequestTimelineProps): JSX.Element {\n return (\n <ResourceTimeline\n value={props.serviceRequest}\n buildSearchRequests={(resource: Resource) => ({\n resourceType: 'Bundle',\n type: 'batch',\n entry: [\n {\n request: {\n method: 'GET',\n url: `${getReferenceString(resource)}/_history`,\n },\n },\n {\n request: {\n method: 'GET',\n url: `Communication?based-on=${getReferenceString(resource)}&_sort=-_lastUpdated`,\n },\n },\n {\n request: {\n method: 'GET',\n url: `Media?_count=100&based-on=${getReferenceString(resource)}&_sort=-_lastUpdated`,\n },\n },\n {\n request: {\n method: 'GET',\n url: `DiagnosticReport?based-on=${getReferenceString(resource)}&_sort=-_lastUpdated`,\n },\n },\n ],\n })}\n createCommunication={(resource: ServiceRequest, sender: ProfileResource, text: string) => ({\n resourceType: 'Communication',\n basedOn: [createReference(resource)],\n subject: resource.subject as Reference<Group | Patient>,\n sender: createReference(sender),\n sent: new Date().toISOString(),\n payload: [{ contentString: text }],\n })}\n createMedia={(resource: ServiceRequest, operator: ProfileResource, content: Attachment) => ({\n resourceType: 'Media',\n basedOn: [createReference(resource)],\n subject: resource.subject,\n operator: createReference(operator),\n issued: new Date().toISOString(),\n content,\n })}\n />\n );\n}\n"],"names":[],"mappings":";;;;AASM,SAAU,sBAAsB,CAAC,KAAkC,EAAA;AACvE,IAAA,QACE,KAAC,CAAA,aAAA,CAAA,gBAAgB,EACf,EAAA,KAAK,EAAE,KAAK,CAAC,cAAc,EAC3B,mBAAmB,EAAE,CAAC,QAAkB,MAAM;AAC5C,YAAA,YAAY,EAAE,QAAQ;AACtB,YAAA,IAAI,EAAE,OAAO;AACb,YAAA,KAAK,EAAE;AACL,gBAAA;AACE,oBAAA,OAAO,EAAE;AACP,wBAAA,MAAM,EAAE,KAAK;AACb,wBAAA,GAAG,EAAE,CAAG,EAAA,kBAAkB,CAAC,QAAQ,CAAC,CAAW,SAAA,CAAA;AAChD,qBAAA;AACF,iBAAA;AACD,gBAAA;AACE,oBAAA,OAAO,EAAE;AACP,wBAAA,MAAM,EAAE,KAAK;AACb,wBAAA,GAAG,EAAE,CAA0B,uBAAA,EAAA,kBAAkB,CAAC,QAAQ,CAAC,CAAsB,oBAAA,CAAA;AAClF,qBAAA;AACF,iBAAA;AACD,gBAAA;AACE,oBAAA,OAAO,EAAE;AACP,wBAAA,MAAM,EAAE,KAAK;AACb,wBAAA,GAAG,EAAE,CAA6B,0BAAA,EAAA,kBAAkB,CAAC,QAAQ,CAAC,CAAsB,oBAAA,CAAA;AACrF,qBAAA;AACF,iBAAA;AACD,gBAAA;AACE,oBAAA,OAAO,EAAE;AACP,wBAAA,MAAM,EAAE,KAAK;AACb,wBAAA,GAAG,EAAE,CAA6B,0BAAA,EAAA,kBAAkB,CAAC,QAAQ,CAAC,CAAsB,oBAAA,CAAA;AACrF,qBAAA;AACF,iBAAA;AACF,aAAA;AACF,SAAA,CAAC,EACF,mBAAmB,EAAE,CAAC,QAAwB,EAAE,MAAuB,EAAE,IAAY,MAAM;AACzF,YAAA,YAAY,EAAE,eAAe;AAC7B,YAAA,OAAO,EAAE,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;YACpC,OAAO,EAAE,QAAQ,CAAC,OAAqC;AACvD,YAAA,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC;AAC/B,YAAA,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;AAC9B,YAAA,OAAO,EAAE,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;AACnC,SAAA,CAAC,EACF,WAAW,EAAE,CAAC,QAAwB,EAAE,QAAyB,EAAE,OAAmB,MAAM;AAC1F,YAAA,YAAY,EAAE,OAAO;AACrB,YAAA,OAAO,EAAE,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;YACpC,OAAO,EAAE,QAAQ,CAAC,OAAO;AACzB,YAAA,QAAQ,EAAE,eAAe,CAAC,QAAQ,CAAC;AACnC,YAAA,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAChC,OAAO;SACR,CAAC,EAAA,CACF,EACF;AACJ;;;;"}
|
|
@@ -6,6 +6,8 @@ export interface AuthenticationFormProps {
|
|
|
6
6
|
readonly scope?: string;
|
|
7
7
|
readonly nonce?: string;
|
|
8
8
|
readonly googleClientId?: string;
|
|
9
|
+
readonly codeChallenge?: string;
|
|
10
|
+
readonly codeChallengeMethod?: string;
|
|
9
11
|
readonly onForgotPassword?: () => void;
|
|
10
12
|
readonly onRegister?: () => void;
|
|
11
13
|
readonly handleAuthResponse: (response: LoginAuthenticationResponse) => void;
|
|
@@ -20,6 +20,8 @@ function AuthenticationForm(props) {
|
|
|
20
20
|
clientId: props.clientId,
|
|
21
21
|
scope: props.scope,
|
|
22
22
|
nonce: props.nonce,
|
|
23
|
+
codeChallenge: props.codeChallenge,
|
|
24
|
+
codeChallengeMethod: props.codeChallengeMethod,
|
|
23
25
|
email: formData.email,
|
|
24
26
|
password: formData.password,
|
|
25
27
|
remember: formData.remember === 'true',
|
|
@@ -41,6 +43,8 @@ function AuthenticationForm(props) {
|
|
|
41
43
|
clientId: props.clientId,
|
|
42
44
|
scope: props.scope,
|
|
43
45
|
nonce: props.nonce,
|
|
46
|
+
codeChallenge: props.codeChallenge,
|
|
47
|
+
codeChallengeMethod: props.codeChallengeMethod,
|
|
44
48
|
googleClientId: response.clientId,
|
|
45
49
|
googleCredential: response.credential,
|
|
46
50
|
})
|