Skip to main content
Glama
InvitePage.tsx5.49 kB
// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors // SPDX-License-Identifier: Apache-2.0 import { Checkbox, Group, List, NativeSelect, Stack, Text, TextInput, Title } from '@mantine/core'; import { showNotification } from '@mantine/notifications'; import type { InviteRequest } from '@medplum/core'; import { isOperationOutcome, normalizeErrorString, normalizeOperationOutcome } from '@medplum/core'; import type { AccessPolicy, OperationOutcome, Project, ProjectMembership, Reference } from '@medplum/fhirtypes'; import { Form, FormSection, MedplumLink, ResourceInput, SubmitButton, getErrorsForInput, useMedplum, } from '@medplum/react'; import type { JSX } from 'react'; import { useCallback, useState } from 'react'; import { AccessPolicyInput } from './AccessPolicyInput'; export function InvitePage(): JSX.Element { const medplum = useMedplum(); const [project, setProject] = useState<Project | undefined>(medplum.getProject()); const [accessPolicy, setAccessPolicy] = useState<Reference<AccessPolicy>>(); const [outcome, setOutcome] = useState<OperationOutcome>(); const [emailSent, setEmailSent] = useState(false); const [result, setResult] = useState<ProjectMembership | undefined>(undefined); const handleSubmit = useCallback( (formData: Record<string, string>): Promise<void> => { const body = { resourceType: formData.resourceType as 'Practitioner' | 'Patient' | 'RelatedPerson', firstName: formData.firstName, lastName: formData.lastName, email: formData.email, sendEmail: formData.sendEmail === 'on', accessPolicy, admin: formData.isAdmin === 'on', scope: formData.isProjectScoped === 'on' ? 'project' : 'server', mfaRequired: formData.mfaRequired === 'on', }; return medplum .invite(project?.id as string, body as InviteRequest) .then((response: ProjectMembership | OperationOutcome) => { medplum.invalidateSearches('Patient'); medplum.invalidateSearches('Practitioner'); medplum.invalidateSearches('ProjectMembership'); if (isOperationOutcome(response)) { setOutcome(response); } else { setResult(response); } setEmailSent(body.sendEmail ?? false); showNotification({ color: 'green', message: 'Invite success' }); }) .catch((err) => { showNotification({ color: 'red', message: normalizeErrorString(err), autoClose: false }); setOutcome(normalizeOperationOutcome(err)); }); }, [medplum, project, accessPolicy] ); return ( <Form onSubmit={handleSubmit}> {!result && !outcome && ( <Stack> <Title>Invite new member</Title> {medplum.isSuperAdmin() && ( <FormSection title="Project" htmlFor="project" outcome={outcome}> <ResourceInput<Project> resourceType="Project" name="project" defaultValue={project} onChange={setProject} /> </FormSection> )} <NativeSelect name="resourceType" label="Role" defaultValue="Practitioner" data={['Practitioner', 'Patient', 'RelatedPerson']} error={getErrorsForInput(outcome, 'resourceType')} /> <TextInput name="firstName" label="First Name" required={true} autoFocus={true} error={getErrorsForInput(outcome, 'firstName')} /> <TextInput name="lastName" label="Last Name" required={true} error={getErrorsForInput(outcome, 'lastName')} /> <TextInput name="email" type="email" label="Email" required={true} error={getErrorsForInput(outcome, 'email')} /> <FormSection title="Access Policy" htmlFor="accessPolicy" outcome={outcome}> <AccessPolicyInput name="accessPolicy" onChange={setAccessPolicy} /> </FormSection> <Checkbox name="sendEmail" label="Send email" defaultChecked={true} /> <Checkbox name="isAdmin" label="Admin" /> <Checkbox name="isProjectScoped" label="Project scoped" /> <Checkbox name="mfaRequired" label="MFA required" /> <Group justify="flex-end"> <SubmitButton>Invite</SubmitButton> </Group> </Stack> )} {outcome && ( <div data-testid="success"> <p>User created, email couldn't be sent</p> <p>Could not send email. Make sure you have AWS SES set up.</p> <p> Click <MedplumLink to="/admin/project">here</MedplumLink> to return to the project admin page. </p> </div> )} {result && ( <div data-testid="success"> <Text>User created</Text> {emailSent && <Text>Email sent</Text>} <List> <List.Item> <MedplumLink to={result as ProjectMembership}>Go to new membership</MedplumLink> </List.Item> <List.Item> <MedplumLink to={result.profile}>Go to new profile</MedplumLink> </List.Item> <List.Item> <MedplumLink to="/admin/users">Back to users list</MedplumLink> </List.Item> </List> </div> )} </Form> ); }

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