Skip to main content
Glama
ResourceArrayDisplay.tsx4.77 kB
// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors // SPDX-License-Identifier: Apache-2.0 import { Group, Text } from '@mantine/core'; import type { InternalSchemaElement, SliceDefinitionWithTypes } from '@medplum/core'; import { getPathDisplayName, isPopulated } from '@medplum/core'; import { useMedplum } from '@medplum/react-hooks'; import type { JSX } from 'react'; import { useContext, useEffect, useMemo, useState } from 'react'; import { DescriptionListEntry } from '../DescriptionList/DescriptionList'; import { ElementsContext } from '../ElementsInput/ElementsInput.utils'; import { assignValuesIntoSlices, prepareSlices } from '../ResourceArrayInput/ResourceArrayInput.utils'; import { ResourcePropertyDisplay } from '../ResourcePropertyDisplay/ResourcePropertyDisplay'; import { SliceDisplay } from '../SliceDisplay/SliceDisplay'; const MAX_ARRAY_SIZE = 50; export interface ResourceArrayDisplayProps { /** The path identifies the element and is expressed as a "."-separated list of ancestor elements, beginning with the name of the resource or extension. */ readonly path?: string; readonly property: InternalSchemaElement; readonly propertyType: string; readonly values: any[]; readonly ignoreMissingValues?: boolean; readonly link?: boolean; readonly includeDescriptionListEntry?: boolean; } export function ResourceArrayDisplay(props: ResourceArrayDisplayProps): JSX.Element | null { const { property, propertyType } = props; const medplum = useMedplum(); const values = useMemo<any[]>(() => (Array.isArray(props.values) ? props.values : []), [props.values]); const [loading, setLoading] = useState(true); const [slices, setSlices] = useState<SliceDefinitionWithTypes[]>([]); const [slicedValues, setSlicedValues] = useState<any[][]>(() => [values]); const [valuesLength, setValuesLength] = useState(0); const ctx = useContext(ElementsContext); useEffect(() => { prepareSlices({ medplum, property, }) .then((slices) => { setValuesLength(values.length); setSlices(slices); const limitedValues = values.slice(0, MAX_ARRAY_SIZE); const slicedValues = assignValuesIntoSlices(limitedValues, slices, property.slicing, ctx.profileUrl); setSlicedValues(slicedValues); setLoading(false); }) .catch((reason) => { console.error(reason); setLoading(false); }); }, [medplum, property, ctx.profileUrl, setSlicedValues, values]); if (loading) { return <div>Loading...</div>; } let nonSliceContent: JSX.Element | undefined; const showNonSliceValues = property.type[0]?.code !== 'Extension'; if (showNonSliceValues) { const nonSliceValues = slicedValues[slices.length]; const nonSliceElements = nonSliceValues.map((value, valueIndex) => ( <div key={`${valueIndex}-${nonSliceValues.length}`}> <ResourcePropertyDisplay path={props.path} arrayElement={true} property={property} propertyType={propertyType} value={value} ignoreMissingValues={props.ignoreMissingValues} link={props.link} /> </div> )); if (props.includeDescriptionListEntry) { // Since arrays are responsible for rendering their own DescriptionListEntry, we must find the key if (!isPopulated(props.path)) { throw new Error('props.path is required when includeDescriptionListEntry is true'); } const key = props.path.split('.').pop() as string; nonSliceContent = <DescriptionListEntry term={getPathDisplayName(key)}>{nonSliceElements}</DescriptionListEntry>; } else { nonSliceContent = <>{nonSliceElements}</>; } } return ( <> {slices.map((slice, sliceIndex) => { if (!props.path) { throw new Error(`Displaying a resource property with slices of type ${props.propertyType} requires path`); } let sliceDisplay = ( <SliceDisplay key={slice.name} path={props.path} slice={slice} property={property} value={slicedValues[sliceIndex]} ignoreMissingValues={props.ignoreMissingValues} link={props.link} /> ); if (props.includeDescriptionListEntry) { sliceDisplay = ( <DescriptionListEntry key={slice.name} term={getPathDisplayName(slice.name)}> {sliceDisplay} </DescriptionListEntry> ); } return sliceDisplay; })} {nonSliceContent} {valuesLength > MAX_ARRAY_SIZE && ( <Group justify="right"> <Text>... {valuesLength} total values</Text> </Group> )} </> ); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/medplum/medplum'

If you have feedback or need assistance with the MCP directory API, please join our Discord server