@medplum/react 2.0.20 → 2.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +51 -29
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.min.cjs +1 -1
- package/dist/esm/AppShell/AppShell.mjs +2 -2
- package/dist/esm/AppShell/AppShell.mjs.map +1 -1
- package/dist/esm/AppShell/Header.mjs +1 -1
- package/dist/esm/AppShell/Header.mjs.map +1 -1
- package/dist/esm/AppShell/HeaderSearchInput.mjs +1 -1
- package/dist/esm/AppShell/HeaderSearchInput.mjs.map +1 -1
- package/dist/esm/AsyncAutocomplete/AsyncAutocomplete.mjs +2 -1
- package/dist/esm/AsyncAutocomplete/AsyncAutocomplete.mjs.map +1 -1
- package/dist/esm/GoogleButton/GoogleButton.mjs +2 -2
- package/dist/esm/GoogleButton/GoogleButton.mjs.map +1 -1
- package/dist/esm/MedplumProvider/MedplumProvider.mjs +8 -0
- package/dist/esm/MedplumProvider/MedplumProvider.mjs.map +1 -1
- package/dist/esm/ResourceTimeline/ResourceTimeline.mjs +1 -1
- package/dist/esm/ResourceTimeline/ResourceTimeline.mjs.map +1 -1
- package/dist/esm/SearchControl/SearchControl.mjs +1 -1
- package/dist/esm/SearchControl/SearchControl.mjs.map +1 -1
- package/dist/esm/Timeline/Timeline.mjs +2 -1
- package/dist/esm/Timeline/Timeline.mjs.map +1 -1
- package/dist/esm/ValueSetAutocomplete/ValueSetAutocomplete.mjs +11 -5
- package/dist/esm/ValueSetAutocomplete/ValueSetAutocomplete.mjs.map +1 -1
- package/dist/esm/auth/SignInForm.mjs +8 -4
- package/dist/esm/auth/SignInForm.mjs.map +1 -1
- package/dist/esm/index.min.mjs +1 -1
- package/dist/esm/utils/date.mjs +9 -6
- package/dist/esm/utils/date.mjs.map +1 -1
- package/dist/types/AppShell/Header.d.ts +2 -0
- package/dist/types/AppShell/HeaderSearchInput.d.ts +1 -0
- package/dist/types/Timeline/Timeline.d.ts +1 -0
- package/package.json +1 -1
|
@@ -28,8 +28,8 @@ function AppShell(props) {
|
|
|
28
28
|
main: {
|
|
29
29
|
background: theme.colorScheme === 'dark' ? theme.colors.dark[8] : theme.colors.gray[0],
|
|
30
30
|
},
|
|
31
|
-
}, padding: 0, fixed: true, header: profile && React.createElement(Header, { logo: props.logo, version: props.version, navbarToggle: toggleNavbar }), navbar: profile && navbarOpen ? (React.createElement(Navbar, { pathname: props.pathname, searchParams: props.searchParams, menus: props.menus, closeNavbar: closeNavbar, displayAddBookmark: props.displayAddBookmark })) : undefined },
|
|
32
|
-
React.createElement(ErrorBoundary,
|
|
31
|
+
}, padding: 0, fixed: true, header: profile && (React.createElement(Header, { pathname: props.pathname, searchParams: props.searchParams, logo: props.logo, version: props.version, navbarToggle: toggleNavbar })), navbar: profile && navbarOpen ? (React.createElement(Navbar, { pathname: props.pathname, searchParams: props.searchParams, menus: props.menus, closeNavbar: closeNavbar, displayAddBookmark: props.displayAddBookmark })) : undefined },
|
|
32
|
+
React.createElement(ErrorBoundary, { key: `${props.pathname}?${props.searchParams?.toString()}` },
|
|
33
33
|
React.createElement(Suspense, { fallback: React.createElement(Loading, null) }, props.children))));
|
|
34
34
|
}
|
|
35
35
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppShell.mjs","sources":["../../../src/AppShell/AppShell.tsx"],"sourcesContent":["import { AppShell as MantineAppShell, useMantineTheme } from '@mantine/core';\nimport React, { Suspense, useState } from 'react';\nimport { ErrorBoundary } from '../ErrorBoundary/ErrorBoundary';\nimport { Loading } from '../Loading/Loading';\nimport { useMedplum, useMedplumProfile } from '../MedplumProvider/MedplumProvider';\nimport { Header } from './Header';\nimport { Navbar, NavbarMenu } from './Navbar';\n\nexport interface AppShellProps {\n logo: React.ReactNode;\n pathname?: string;\n searchParams?: URLSearchParams;\n version?: string;\n menus?: NavbarMenu[];\n children: React.ReactNode;\n displayAddBookmark?: boolean;\n}\n\nexport function AppShell(props: AppShellProps): JSX.Element {\n const theme = useMantineTheme();\n const [navbarOpen, setNavbarOpen] = useState(localStorage['navbarOpen'] === 'true');\n const medplum = useMedplum();\n const profile = useMedplumProfile();\n\n function setNavbarOpenWrapper(open: boolean): void {\n localStorage['navbarOpen'] = open.toString();\n setNavbarOpen(open);\n }\n\n function closeNavbar(): void {\n setNavbarOpenWrapper(false);\n }\n\n function toggleNavbar(): void {\n setNavbarOpenWrapper(!navbarOpen);\n }\n\n if (medplum.isLoading()) {\n return <Loading />;\n }\n\n return (\n <MantineAppShell\n styles={{\n main: {\n background: theme.colorScheme === 'dark' ? theme.colors.dark[8] : theme.colors.gray[0],\n },\n }}\n padding={0}\n fixed={true}\n header={profile && <Header
|
|
1
|
+
{"version":3,"file":"AppShell.mjs","sources":["../../../src/AppShell/AppShell.tsx"],"sourcesContent":["import { AppShell as MantineAppShell, useMantineTheme } from '@mantine/core';\nimport React, { Suspense, useState } from 'react';\nimport { ErrorBoundary } from '../ErrorBoundary/ErrorBoundary';\nimport { Loading } from '../Loading/Loading';\nimport { useMedplum, useMedplumProfile } from '../MedplumProvider/MedplumProvider';\nimport { Header } from './Header';\nimport { Navbar, NavbarMenu } from './Navbar';\n\nexport interface AppShellProps {\n logo: React.ReactNode;\n pathname?: string;\n searchParams?: URLSearchParams;\n version?: string;\n menus?: NavbarMenu[];\n children: React.ReactNode;\n displayAddBookmark?: boolean;\n}\n\nexport function AppShell(props: AppShellProps): JSX.Element {\n const theme = useMantineTheme();\n const [navbarOpen, setNavbarOpen] = useState(localStorage['navbarOpen'] === 'true');\n const medplum = useMedplum();\n const profile = useMedplumProfile();\n\n function setNavbarOpenWrapper(open: boolean): void {\n localStorage['navbarOpen'] = open.toString();\n setNavbarOpen(open);\n }\n\n function closeNavbar(): void {\n setNavbarOpenWrapper(false);\n }\n\n function toggleNavbar(): void {\n setNavbarOpenWrapper(!navbarOpen);\n }\n\n if (medplum.isLoading()) {\n return <Loading />;\n }\n\n return (\n <MantineAppShell\n styles={{\n main: {\n background: theme.colorScheme === 'dark' ? theme.colors.dark[8] : theme.colors.gray[0],\n },\n }}\n padding={0}\n fixed={true}\n header={\n profile && (\n <Header\n pathname={props.pathname}\n searchParams={props.searchParams}\n logo={props.logo}\n version={props.version}\n navbarToggle={toggleNavbar}\n />\n )\n }\n navbar={\n profile && navbarOpen ? (\n <Navbar\n pathname={props.pathname}\n searchParams={props.searchParams}\n menus={props.menus}\n closeNavbar={closeNavbar}\n displayAddBookmark={props.displayAddBookmark}\n />\n ) : undefined\n }\n >\n <ErrorBoundary key={`${props.pathname}?${props.searchParams?.toString()}`}>\n <Suspense fallback={<Loading />}>{props.children}</Suspense>\n </ErrorBoundary>\n </MantineAppShell>\n );\n}\n"],"names":["MantineAppShell"],"mappings":";;;;;;;;AAkBM,SAAU,QAAQ,CAAC,KAAoB,EAAA;AAC3C,IAAA,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;AAChC,IAAA,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,YAAY,CAAC,YAAY,CAAC,KAAK,MAAM,CAAC,CAAC;AACpF,IAAA,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;AAC7B,IAAA,MAAM,OAAO,GAAG,iBAAiB,EAAE,CAAC;IAEpC,SAAS,oBAAoB,CAAC,IAAa,EAAA;QACzC,YAAY,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC7C,aAAa,CAAC,IAAI,CAAC,CAAC;KACrB;AAED,IAAA,SAAS,WAAW,GAAA;QAClB,oBAAoB,CAAC,KAAK,CAAC,CAAC;KAC7B;AAED,IAAA,SAAS,YAAY,GAAA;AACnB,QAAA,oBAAoB,CAAC,CAAC,UAAU,CAAC,CAAC;KACnC;AAED,IAAA,IAAI,OAAO,CAAC,SAAS,EAAE,EAAE;QACvB,OAAO,KAAA,CAAA,aAAA,CAAC,OAAO,EAAA,IAAA,CAAG,CAAC;AACpB,KAAA;AAED,IAAA,QACE,KAAA,CAAA,aAAA,CAACA,UAAe,EAAA,EACd,MAAM,EAAE;AACN,YAAA,IAAI,EAAE;gBACJ,UAAU,EAAE,KAAK,CAAC,WAAW,KAAK,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AACvF,aAAA;AACF,SAAA,EACD,OAAO,EAAE,CAAC,EACV,KAAK,EAAE,IAAI,EACX,MAAM,EACJ,OAAO,KACL,KAAC,CAAA,aAAA,CAAA,MAAM,IACL,QAAQ,EAAE,KAAK,CAAC,QAAQ,EACxB,YAAY,EAAE,KAAK,CAAC,YAAY,EAChC,IAAI,EAAE,KAAK,CAAC,IAAI,EAChB,OAAO,EAAE,KAAK,CAAC,OAAO,EACtB,YAAY,EAAE,YAAY,EAC1B,CAAA,CACH,EAEH,MAAM,EACJ,OAAO,IAAI,UAAU,IACnB,KAAA,CAAA,aAAA,CAAC,MAAM,EACL,EAAA,QAAQ,EAAE,KAAK,CAAC,QAAQ,EACxB,YAAY,EAAE,KAAK,CAAC,YAAY,EAChC,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,WAAW,EAAE,WAAW,EACxB,kBAAkB,EAAE,KAAK,CAAC,kBAAkB,EAAA,CAC5C,IACA,SAAS,EAAA;AAGf,QAAA,KAAA,CAAA,aAAA,CAAC,aAAa,EAAA,EAAC,GAAG,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAA,CAAA,EAAI,KAAK,CAAC,YAAY,EAAE,QAAQ,EAAE,CAAE,CAAA,EAAA;AACvE,YAAA,KAAA,CAAA,aAAA,CAAC,QAAQ,EAAA,EAAC,QAAQ,EAAE,oBAAC,OAAO,EAAA,IAAA,CAAG,EAAG,EAAA,KAAK,CAAC,QAAQ,CAAY,CAC9C,CACA,EAClB;AACJ;;;;"}
|
|
@@ -49,7 +49,7 @@ function Header(props) {
|
|
|
49
49
|
React.createElement(Group, { position: "apart" },
|
|
50
50
|
React.createElement(Group, { spacing: "xs" },
|
|
51
51
|
React.createElement(UnstyledButton, { className: classes.logoButton, onClick: props.navbarToggle }, props.logo),
|
|
52
|
-
React.createElement(HeaderSearchInput,
|
|
52
|
+
React.createElement(HeaderSearchInput, { pathname: props.pathname, searchParams: props.searchParams })),
|
|
53
53
|
React.createElement(Menu, { width: 260, shadow: "xl", position: "bottom-end", transitionProps: { transition: 'pop-top-right' }, opened: userMenuOpened, onClose: () => setUserMenuOpened(false) },
|
|
54
54
|
React.createElement(Menu.Target, null,
|
|
55
55
|
React.createElement(UnstyledButton, { className: cx(classes.user, { [classes.userActive]: userMenuOpened }), onClick: () => setUserMenuOpened((o) => !o) },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Header.mjs","sources":["../../../src/AppShell/Header.tsx"],"sourcesContent":["import { Avatar, createStyles, Group, Header as MantineHeader, Menu, Stack, Text, UnstyledButton } from '@mantine/core';\nimport { formatHumanName, getReferenceString, ProfileResource } from '@medplum/core';\nimport { HumanName } from '@medplum/fhirtypes';\nimport { IconChevronDown, IconLogout, IconSettings, IconSwitchHorizontal } from '@tabler/icons-react';\nimport React, { useState } from 'react';\nimport { HumanNameDisplay } from '../HumanNameDisplay/HumanNameDisplay';\nimport { useMedplumContext } from '../MedplumProvider/MedplumProvider';\nimport { ResourceAvatar } from '../ResourceAvatar/ResourceAvatar';\nimport { HeaderSearchInput } from './HeaderSearchInput';\n\nconst useStyles = createStyles((theme) => ({\n logoButton: {\n padding: `${theme.spacing.xs} ${theme.spacing.sm}`,\n borderRadius: theme.radius.sm,\n transition: 'background-color 100ms ease',\n\n '&:hover': {\n backgroundColor: theme.fn.lighten(\n theme.fn.variant({ variant: 'filled', color: theme.primaryColor }).background as string,\n 0.8\n ),\n },\n },\n\n user: {\n padding: `${theme.spacing.xs} ${theme.spacing.sm}`,\n borderRadius: theme.radius.sm,\n transition: 'background-color 100ms ease',\n\n '&:hover': {\n backgroundColor: theme.fn.lighten(\n theme.fn.variant({ variant: 'filled', color: theme.primaryColor }).background as string,\n 0.8\n ),\n },\n },\n\n userName: {\n fontWeight: 500,\n lineHeight: 1,\n marginRight: 3,\n\n [theme.fn.smallerThan('xs')]: {\n display: 'none',\n },\n },\n\n userActive: {\n backgroundColor: theme.fn.lighten(\n theme.fn.variant({ variant: 'filled', color: theme.primaryColor }).background as string,\n 0.8\n ),\n },\n}));\n\ninterface HeaderProps {\n logo: React.ReactNode;\n version?: string;\n navbarToggle: () => void;\n}\n\nexport function Header(props: HeaderProps): JSX.Element {\n const context = useMedplumContext();\n const { medplum, profile, navigate } = context;\n const logins = medplum.getLogins();\n const { classes, cx } = useStyles();\n const [userMenuOpened, setUserMenuOpened] = useState(false);\n\n return (\n <MantineHeader height={60} p={8} style={{ zIndex: 101 }}>\n <Group position=\"apart\">\n <Group spacing=\"xs\">\n <UnstyledButton className={classes.logoButton} onClick={props.navbarToggle}>\n {props.logo}\n </UnstyledButton>\n <HeaderSearchInput />\n </Group>\n\n <Menu\n width={260}\n shadow=\"xl\"\n position=\"bottom-end\"\n transitionProps={{ transition: 'pop-top-right' }}\n opened={userMenuOpened}\n onClose={() => setUserMenuOpened(false)}\n >\n <Menu.Target>\n <UnstyledButton\n className={cx(classes.user, { [classes.userActive]: userMenuOpened })}\n onClick={() => setUserMenuOpened((o) => !o)}\n >\n <Group spacing={7}>\n <ResourceAvatar value={profile} radius=\"xl\" size={24} />\n <Text size=\"sm\" className={classes.userName}>\n {formatHumanName(profile?.name?.[0] as HumanName)}\n </Text>\n <IconChevronDown size={12} stroke={1.5} />\n </Group>\n </UnstyledButton>\n </Menu.Target>\n <Menu.Dropdown>\n <Stack align=\"center\" p=\"xl\">\n <ResourceAvatar size=\"xl\" radius={100} value={context.profile} />\n <HumanNameDisplay value={context.profile?.name?.[0] as HumanName} />\n <Text color=\"dimmed\" size=\"xs\">\n {medplum.getActiveLogin()?.project?.display}\n </Text>\n </Stack>\n {logins.length > 1 && <Menu.Divider />}\n {logins.map(\n (login) =>\n login.profile?.reference !== getReferenceString(context.profile as ProfileResource) && (\n <Menu.Item\n key={login.profile?.reference}\n onClick={() => {\n medplum\n .setActiveLogin(login)\n .then(() => window.location.reload())\n .catch(console.log);\n }}\n >\n <Group>\n <Avatar radius=\"xl\" />\n <div style={{ flex: 1 }}>\n <Text size=\"sm\" weight={500}>\n {login.profile?.display}\n </Text>\n <Text color=\"dimmed\" size=\"xs\">\n {login.project?.display}\n </Text>\n </div>\n </Group>\n </Menu.Item>\n )\n )}\n <Menu.Divider />\n <Menu.Item icon={<IconSwitchHorizontal size={14} stroke={1.5} />} onClick={() => navigate('/signin')}>\n Add another account\n </Menu.Item>\n <Menu.Item\n icon={<IconSettings size={14} stroke={1.5} />}\n onClick={() => navigate(`/${getReferenceString(profile as ProfileResource)}`)}\n >\n Account settings\n </Menu.Item>\n <Menu.Item\n icon={<IconLogout size={14} stroke={1.5} />}\n onClick={async () => {\n await medplum.signOut();\n navigate('/signin');\n }}\n >\n Sign out\n </Menu.Item>\n <Text size=\"xs\" color=\"dimmed\" align=\"center\">\n {props.version}\n </Text>\n </Menu.Dropdown>\n </Menu>\n </Group>\n </MantineHeader>\n );\n}\n"],"names":["MantineHeader"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Header.mjs","sources":["../../../src/AppShell/Header.tsx"],"sourcesContent":["import { Avatar, createStyles, Group, Header as MantineHeader, Menu, Stack, Text, UnstyledButton } from '@mantine/core';\nimport { formatHumanName, getReferenceString, ProfileResource } from '@medplum/core';\nimport { HumanName } from '@medplum/fhirtypes';\nimport { IconChevronDown, IconLogout, IconSettings, IconSwitchHorizontal } from '@tabler/icons-react';\nimport React, { useState } from 'react';\nimport { HumanNameDisplay } from '../HumanNameDisplay/HumanNameDisplay';\nimport { useMedplumContext } from '../MedplumProvider/MedplumProvider';\nimport { ResourceAvatar } from '../ResourceAvatar/ResourceAvatar';\nimport { HeaderSearchInput } from './HeaderSearchInput';\n\nconst useStyles = createStyles((theme) => ({\n logoButton: {\n padding: `${theme.spacing.xs} ${theme.spacing.sm}`,\n borderRadius: theme.radius.sm,\n transition: 'background-color 100ms ease',\n\n '&:hover': {\n backgroundColor: theme.fn.lighten(\n theme.fn.variant({ variant: 'filled', color: theme.primaryColor }).background as string,\n 0.8\n ),\n },\n },\n\n user: {\n padding: `${theme.spacing.xs} ${theme.spacing.sm}`,\n borderRadius: theme.radius.sm,\n transition: 'background-color 100ms ease',\n\n '&:hover': {\n backgroundColor: theme.fn.lighten(\n theme.fn.variant({ variant: 'filled', color: theme.primaryColor }).background as string,\n 0.8\n ),\n },\n },\n\n userName: {\n fontWeight: 500,\n lineHeight: 1,\n marginRight: 3,\n\n [theme.fn.smallerThan('xs')]: {\n display: 'none',\n },\n },\n\n userActive: {\n backgroundColor: theme.fn.lighten(\n theme.fn.variant({ variant: 'filled', color: theme.primaryColor }).background as string,\n 0.8\n ),\n },\n}));\n\ninterface HeaderProps {\n pathname?: string;\n searchParams?: URLSearchParams;\n logo: React.ReactNode;\n version?: string;\n navbarToggle: () => void;\n}\n\nexport function Header(props: HeaderProps): JSX.Element {\n const context = useMedplumContext();\n const { medplum, profile, navigate } = context;\n const logins = medplum.getLogins();\n const { classes, cx } = useStyles();\n const [userMenuOpened, setUserMenuOpened] = useState(false);\n\n return (\n <MantineHeader height={60} p={8} style={{ zIndex: 101 }}>\n <Group position=\"apart\">\n <Group spacing=\"xs\">\n <UnstyledButton className={classes.logoButton} onClick={props.navbarToggle}>\n {props.logo}\n </UnstyledButton>\n <HeaderSearchInput pathname={props.pathname} searchParams={props.searchParams} />\n </Group>\n\n <Menu\n width={260}\n shadow=\"xl\"\n position=\"bottom-end\"\n transitionProps={{ transition: 'pop-top-right' }}\n opened={userMenuOpened}\n onClose={() => setUserMenuOpened(false)}\n >\n <Menu.Target>\n <UnstyledButton\n className={cx(classes.user, { [classes.userActive]: userMenuOpened })}\n onClick={() => setUserMenuOpened((o) => !o)}\n >\n <Group spacing={7}>\n <ResourceAvatar value={profile} radius=\"xl\" size={24} />\n <Text size=\"sm\" className={classes.userName}>\n {formatHumanName(profile?.name?.[0] as HumanName)}\n </Text>\n <IconChevronDown size={12} stroke={1.5} />\n </Group>\n </UnstyledButton>\n </Menu.Target>\n <Menu.Dropdown>\n <Stack align=\"center\" p=\"xl\">\n <ResourceAvatar size=\"xl\" radius={100} value={context.profile} />\n <HumanNameDisplay value={context.profile?.name?.[0] as HumanName} />\n <Text color=\"dimmed\" size=\"xs\">\n {medplum.getActiveLogin()?.project?.display}\n </Text>\n </Stack>\n {logins.length > 1 && <Menu.Divider />}\n {logins.map(\n (login) =>\n login.profile?.reference !== getReferenceString(context.profile as ProfileResource) && (\n <Menu.Item\n key={login.profile?.reference}\n onClick={() => {\n medplum\n .setActiveLogin(login)\n .then(() => window.location.reload())\n .catch(console.log);\n }}\n >\n <Group>\n <Avatar radius=\"xl\" />\n <div style={{ flex: 1 }}>\n <Text size=\"sm\" weight={500}>\n {login.profile?.display}\n </Text>\n <Text color=\"dimmed\" size=\"xs\">\n {login.project?.display}\n </Text>\n </div>\n </Group>\n </Menu.Item>\n )\n )}\n <Menu.Divider />\n <Menu.Item icon={<IconSwitchHorizontal size={14} stroke={1.5} />} onClick={() => navigate('/signin')}>\n Add another account\n </Menu.Item>\n <Menu.Item\n icon={<IconSettings size={14} stroke={1.5} />}\n onClick={() => navigate(`/${getReferenceString(profile as ProfileResource)}`)}\n >\n Account settings\n </Menu.Item>\n <Menu.Item\n icon={<IconLogout size={14} stroke={1.5} />}\n onClick={async () => {\n await medplum.signOut();\n navigate('/signin');\n }}\n >\n Sign out\n </Menu.Item>\n <Text size=\"xs\" color=\"dimmed\" align=\"center\">\n {props.version}\n </Text>\n </Menu.Dropdown>\n </Menu>\n </Group>\n </MantineHeader>\n );\n}\n"],"names":["MantineHeader"],"mappings":"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"}
|
|
@@ -52,7 +52,7 @@ function HeaderSearchInput(props) {
|
|
|
52
52
|
navigate(`/${getReferenceString(item[0])}`);
|
|
53
53
|
}
|
|
54
54
|
}, [navigate]);
|
|
55
|
-
return (React.createElement(AsyncAutocomplete, { key: props.pathname
|
|
55
|
+
return (React.createElement(AsyncAutocomplete, { key: `${props.pathname}?${props.searchParams}`, size: "sm", radius: "md", className: classes.searchInput, icon: React.createElement(IconSearch, { size: 16 }), placeholder: "Search", itemComponent: ItemComponent, toKey: toKey, toOption: toOption, onChange: handleSelect, loadOptions: loadData, maxSelectedValues: 0, clearSearchOnChange: true, clearable: false }));
|
|
56
56
|
}
|
|
57
57
|
const ItemComponent = forwardRef(({ resource, ...others }, ref) => {
|
|
58
58
|
let helpText = undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeaderSearchInput.mjs","sources":["../../../src/AppShell/HeaderSearchInput.tsx"],"sourcesContent":["import { createStyles, Group, Text } from '@mantine/core';\nimport { formatHumanName, getDisplayString, getReferenceString, isUUID } from '@medplum/core';\nimport { Patient, ServiceRequest } from '@medplum/fhirtypes';\nimport { IconSearch } from '@tabler/icons-react';\nimport React, { forwardRef, useCallback } from 'react';\nimport { AsyncAutocomplete, AsyncAutocompleteOption } from '../AsyncAutocomplete/AsyncAutocomplete';\nimport { useMedplum, useMedplumNavigate } from '../MedplumProvider/MedplumProvider';\nimport { ResourceAvatar } from '../ResourceAvatar/ResourceAvatar';\n\nexport type HeaderSearchTypes = Patient | ServiceRequest;\n\nconst useStyles = createStyles(() => {\n return {\n searchInput: {\n input: {\n width: 220,\n transition: 'width 0.2s',\n },\n 'input:focus': {\n width: 400,\n },\n '@media (max-width: 800px)': {\n input: {\n width: 150,\n },\n 'input:focus': {\n width: 150,\n },\n },\n },\n };\n});\n\ninterface SearchGraphQLResponse {\n readonly data: {\n readonly Patients1: Patient[] | undefined;\n readonly Patients2: Patient[] | undefined;\n readonly ServiceRequestList: ServiceRequest[] | undefined;\n };\n}\n\nfunction toKey(resource: HeaderSearchTypes): string {\n return resource.id as string;\n}\n\nfunction toOption(resource: HeaderSearchTypes): AsyncAutocompleteOption<HeaderSearchTypes> {\n return {\n value: resource.id as string,\n label: getDisplayString(resource),\n resource,\n };\n}\n\nexport interface HeaderSearchInputProps {\n pathname?: string;\n}\n\nexport function HeaderSearchInput(props: HeaderSearchInputProps): JSX.Element {\n const { classes } = useStyles();\n const navigate = useMedplumNavigate();\n const medplum = useMedplum();\n\n const loadData = useCallback(\n async (input: string, signal: AbortSignal): Promise<HeaderSearchTypes[]> => {\n const query = buildGraphQLQuery(input);\n const options = { signal };\n const response = (await medplum.graphql(query, undefined, undefined, options)) as SearchGraphQLResponse;\n return getResourcesFromResponse(response, input);\n },\n [medplum]\n );\n\n const handleSelect = useCallback(\n (item: HeaderSearchTypes[]): void => {\n if (item.length > 0) {\n navigate(`/${getReferenceString(item[0])}`);\n }\n },\n [navigate]\n );\n\n return (\n <AsyncAutocomplete\n key={props.pathname}\n size=\"sm\"\n radius=\"md\"\n className={classes.searchInput}\n icon={<IconSearch size={16} />}\n placeholder=\"Search\"\n itemComponent={ItemComponent}\n toKey={toKey}\n toOption={toOption}\n onChange={handleSelect}\n loadOptions={loadData}\n />\n );\n}\n\nconst ItemComponent = forwardRef<HTMLDivElement, any>(\n ({ resource, ...others }: AsyncAutocompleteOption<HeaderSearchTypes>, ref) => {\n let helpText: string | undefined = undefined;\n\n if (resource.resourceType === 'Patient') {\n helpText = resource.birthDate;\n } else if (resource.resourceType === 'ServiceRequest') {\n helpText = resource.subject?.display;\n }\n\n return (\n <div ref={ref} {...others}>\n <Group noWrap>\n <ResourceAvatar value={resource} />\n <div>\n <Text>{getDisplayString(resource)}</Text>\n <Text size=\"xs\" color=\"dimmed\">\n {helpText}\n </Text>\n </div>\n </Group>\n </div>\n );\n }\n);\n\nfunction buildGraphQLQuery(input: string): string {\n const escaped = JSON.stringify(input);\n if (isUUID(input)) {\n return `{\n Patients1: PatientList(_id: ${escaped}, _count: 1) {\n resourceType\n id\n identifier {\n system\n value\n }\n name {\n given\n family\n }\n birthDate\n }\n ServiceRequestList(_id: ${escaped}, _count: 1) {\n resourceType\n id\n identifier {\n system\n value\n }\n subject {\n display\n }\n }\n }`.replace(/\\s+/g, ' ');\n }\n return `{\n Patients1: PatientList(name: ${escaped}, _count: 5) {\n resourceType\n id\n identifier {\n system\n value\n }\n name {\n given\n family\n }\n birthDate\n }\n Patients2: PatientList(identifier: ${escaped}, _count: 5) {\n resourceType\n id\n identifier {\n system\n value\n }\n name {\n given\n family\n }\n birthDate\n }\n ServiceRequestList(identifier: ${escaped}, _count: 5) {\n resourceType\n id\n identifier {\n system\n value\n }\n subject {\n display\n }\n }\n }`.replace(/\\s+/g, ' ');\n}\n\n/**\n * Returns a de-duped and sorted list of resources from the search response.\n * The search request is actually 3+ separate searches, which can include duplicates.\n * This function combines the results, de-dupes, and sorts by relevance.\n * @param response The response from a search query.\n * @param query The user entered search query.\n * @returns The resources to display in the autocomplete.\n */\nfunction getResourcesFromResponse(response: SearchGraphQLResponse, query: string): HeaderSearchTypes[] {\n const resources = [];\n if (response.data.Patients1) {\n resources.push(...response.data.Patients1);\n }\n if (response.data.Patients2) {\n resources.push(...response.data.Patients2);\n }\n if (response.data.ServiceRequestList) {\n resources.push(...response.data.ServiceRequestList);\n }\n return sortByRelevance(dedupeResources(resources), query).slice(0, 5);\n}\n\n/**\n * Removes duplicate resources from an array by ID.\n * @param resources The array of resources with possible duplicates.\n * @returns The array of resources with no duplicates.\n */\nfunction dedupeResources(resources: HeaderSearchTypes[]): HeaderSearchTypes[] {\n const ids = new Set<string>();\n const result = [];\n\n for (const resource of resources) {\n if (!ids.has(resource.id as string)) {\n ids.add(resource.id as string);\n result.push(resource);\n }\n }\n\n return result;\n}\n\n/**\n * Sorts an array of resources by relevance.\n * @param resources The candidate resources.\n * @param query The user entered search string.\n * @returns The sorted array of resources.\n */\nfunction sortByRelevance(resources: HeaderSearchTypes[], query: string): HeaderSearchTypes[] {\n return resources.sort((a: HeaderSearchTypes, b: HeaderSearchTypes) => {\n return getResourceScore(b, query) - getResourceScore(a, query);\n });\n}\n\n/**\n * Calculates a relevance score of a candidate resource.\n * Higher scores are better.\n * @param resource The candidate resource.\n * @param query The user entered search string.\n * @returns The relevance score of the candidate resource.\n */\nfunction getResourceScore(resource: HeaderSearchTypes, query: string): number {\n let bestScore = 0;\n\n if (resource.identifier) {\n for (const identifier of resource.identifier) {\n bestScore = Math.max(bestScore, getStringScore(identifier.value, query));\n }\n }\n\n if (resource.resourceType === 'Patient' && resource.name) {\n for (const name of resource.name) {\n bestScore = Math.max(bestScore, getStringScore(formatHumanName(name), query));\n }\n }\n\n return bestScore;\n}\n\n/**\n * Calculates a relevance score of a candidate display string.\n * Higher scores are better.\n * @param str The candidate display string.\n * @param query The user entered search string.\n * @returns The relevance score of the candidate string.\n */\nfunction getStringScore(str: string | undefined, query: string): number {\n if (!str) {\n return 0;\n }\n const index = str.toLowerCase().indexOf(query.toLowerCase());\n if (index < 0) {\n return 0;\n }\n return 100 - index;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"HeaderSearchInput.mjs","sources":["../../../src/AppShell/HeaderSearchInput.tsx"],"sourcesContent":["import { createStyles, Group, Text } from '@mantine/core';\nimport { formatHumanName, getDisplayString, getReferenceString, isUUID } from '@medplum/core';\nimport { Patient, ServiceRequest } from '@medplum/fhirtypes';\nimport { IconSearch } from '@tabler/icons-react';\nimport React, { forwardRef, useCallback } from 'react';\nimport { AsyncAutocomplete, AsyncAutocompleteOption } from '../AsyncAutocomplete/AsyncAutocomplete';\nimport { useMedplum, useMedplumNavigate } from '../MedplumProvider/MedplumProvider';\nimport { ResourceAvatar } from '../ResourceAvatar/ResourceAvatar';\n\nexport type HeaderSearchTypes = Patient | ServiceRequest;\n\nconst useStyles = createStyles(() => {\n return {\n searchInput: {\n input: {\n width: 220,\n transition: 'width 0.2s',\n },\n 'input:focus': {\n width: 400,\n },\n '@media (max-width: 800px)': {\n input: {\n width: 150,\n },\n 'input:focus': {\n width: 150,\n },\n },\n },\n };\n});\n\ninterface SearchGraphQLResponse {\n readonly data: {\n readonly Patients1: Patient[] | undefined;\n readonly Patients2: Patient[] | undefined;\n readonly ServiceRequestList: ServiceRequest[] | undefined;\n };\n}\n\nfunction toKey(resource: HeaderSearchTypes): string {\n return resource.id as string;\n}\n\nfunction toOption(resource: HeaderSearchTypes): AsyncAutocompleteOption<HeaderSearchTypes> {\n return {\n value: resource.id as string,\n label: getDisplayString(resource),\n resource,\n };\n}\n\nexport interface HeaderSearchInputProps {\n pathname?: string;\n searchParams?: URLSearchParams;\n}\n\nexport function HeaderSearchInput(props: HeaderSearchInputProps): JSX.Element {\n const { classes } = useStyles();\n const navigate = useMedplumNavigate();\n const medplum = useMedplum();\n\n const loadData = useCallback(\n async (input: string, signal: AbortSignal): Promise<HeaderSearchTypes[]> => {\n const query = buildGraphQLQuery(input);\n const options = { signal };\n const response = (await medplum.graphql(query, undefined, undefined, options)) as SearchGraphQLResponse;\n return getResourcesFromResponse(response, input);\n },\n [medplum]\n );\n\n const handleSelect = useCallback(\n (item: HeaderSearchTypes[]): void => {\n if (item.length > 0) {\n navigate(`/${getReferenceString(item[0])}`);\n }\n },\n [navigate]\n );\n\n return (\n <AsyncAutocomplete\n key={`${props.pathname}?${props.searchParams}`}\n size=\"sm\"\n radius=\"md\"\n className={classes.searchInput}\n icon={<IconSearch size={16} />}\n placeholder=\"Search\"\n itemComponent={ItemComponent}\n toKey={toKey}\n toOption={toOption}\n onChange={handleSelect}\n loadOptions={loadData}\n maxSelectedValues={0}\n clearSearchOnChange\n clearable={false}\n />\n );\n}\n\nconst ItemComponent = forwardRef<HTMLDivElement, any>(\n ({ resource, ...others }: AsyncAutocompleteOption<HeaderSearchTypes>, ref) => {\n let helpText: string | undefined = undefined;\n\n if (resource.resourceType === 'Patient') {\n helpText = resource.birthDate;\n } else if (resource.resourceType === 'ServiceRequest') {\n helpText = resource.subject?.display;\n }\n\n return (\n <div ref={ref} {...others}>\n <Group noWrap>\n <ResourceAvatar value={resource} />\n <div>\n <Text>{getDisplayString(resource)}</Text>\n <Text size=\"xs\" color=\"dimmed\">\n {helpText}\n </Text>\n </div>\n </Group>\n </div>\n );\n }\n);\n\nfunction buildGraphQLQuery(input: string): string {\n const escaped = JSON.stringify(input);\n if (isUUID(input)) {\n return `{\n Patients1: PatientList(_id: ${escaped}, _count: 1) {\n resourceType\n id\n identifier {\n system\n value\n }\n name {\n given\n family\n }\n birthDate\n }\n ServiceRequestList(_id: ${escaped}, _count: 1) {\n resourceType\n id\n identifier {\n system\n value\n }\n subject {\n display\n }\n }\n }`.replace(/\\s+/g, ' ');\n }\n return `{\n Patients1: PatientList(name: ${escaped}, _count: 5) {\n resourceType\n id\n identifier {\n system\n value\n }\n name {\n given\n family\n }\n birthDate\n }\n Patients2: PatientList(identifier: ${escaped}, _count: 5) {\n resourceType\n id\n identifier {\n system\n value\n }\n name {\n given\n family\n }\n birthDate\n }\n ServiceRequestList(identifier: ${escaped}, _count: 5) {\n resourceType\n id\n identifier {\n system\n value\n }\n subject {\n display\n }\n }\n }`.replace(/\\s+/g, ' ');\n}\n\n/**\n * Returns a de-duped and sorted list of resources from the search response.\n * The search request is actually 3+ separate searches, which can include duplicates.\n * This function combines the results, de-dupes, and sorts by relevance.\n * @param response The response from a search query.\n * @param query The user entered search query.\n * @returns The resources to display in the autocomplete.\n */\nfunction getResourcesFromResponse(response: SearchGraphQLResponse, query: string): HeaderSearchTypes[] {\n const resources = [];\n if (response.data.Patients1) {\n resources.push(...response.data.Patients1);\n }\n if (response.data.Patients2) {\n resources.push(...response.data.Patients2);\n }\n if (response.data.ServiceRequestList) {\n resources.push(...response.data.ServiceRequestList);\n }\n return sortByRelevance(dedupeResources(resources), query).slice(0, 5);\n}\n\n/**\n * Removes duplicate resources from an array by ID.\n * @param resources The array of resources with possible duplicates.\n * @returns The array of resources with no duplicates.\n */\nfunction dedupeResources(resources: HeaderSearchTypes[]): HeaderSearchTypes[] {\n const ids = new Set<string>();\n const result = [];\n\n for (const resource of resources) {\n if (!ids.has(resource.id as string)) {\n ids.add(resource.id as string);\n result.push(resource);\n }\n }\n\n return result;\n}\n\n/**\n * Sorts an array of resources by relevance.\n * @param resources The candidate resources.\n * @param query The user entered search string.\n * @returns The sorted array of resources.\n */\nfunction sortByRelevance(resources: HeaderSearchTypes[], query: string): HeaderSearchTypes[] {\n return resources.sort((a: HeaderSearchTypes, b: HeaderSearchTypes) => {\n return getResourceScore(b, query) - getResourceScore(a, query);\n });\n}\n\n/**\n * Calculates a relevance score of a candidate resource.\n * Higher scores are better.\n * @param resource The candidate resource.\n * @param query The user entered search string.\n * @returns The relevance score of the candidate resource.\n */\nfunction getResourceScore(resource: HeaderSearchTypes, query: string): number {\n let bestScore = 0;\n\n if (resource.identifier) {\n for (const identifier of resource.identifier) {\n bestScore = Math.max(bestScore, getStringScore(identifier.value, query));\n }\n }\n\n if (resource.resourceType === 'Patient' && resource.name) {\n for (const name of resource.name) {\n bestScore = Math.max(bestScore, getStringScore(formatHumanName(name), query));\n }\n }\n\n return bestScore;\n}\n\n/**\n * Calculates a relevance score of a candidate display string.\n * Higher scores are better.\n * @param str The candidate display string.\n * @param query The user entered search string.\n * @returns The relevance score of the candidate string.\n */\nfunction getStringScore(str: string | undefined, query: string): number {\n if (!str) {\n return 0;\n }\n const index = str.toLowerCase().indexOf(query.toLowerCase());\n if (index < 0) {\n return 0;\n }\n return 100 - index;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AsyncAutocomplete.mjs","sources":["../../../src/AsyncAutocomplete/AsyncAutocomplete.tsx"],"sourcesContent":["import { Loader, MultiSelect, MultiSelectProps, SelectItem } from '@mantine/core';\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { killEvent } from '../utils/dom';\n\nexport interface AsyncAutocompleteOption<T> extends SelectItem {\n resource: T;\n}\n\nexport interface AsyncAutocompleteProps<T>\n extends Omit<MultiSelectProps, 'data' | 'defaultValue' | 'loadOptions' | 'onChange' | 'onCreate' | 'searchable'> {\n defaultValue?: T | T[];\n toKey: (item: T) => string;\n toOption: (item: T) => AsyncAutocompleteOption<T>;\n loadOptions: (input: string, signal: AbortSignal) => Promise<T[]>;\n onChange: (item: T[]) => void;\n onCreate?: (input: string) => T;\n creatable?: boolean;\n}\n\nexport function AsyncAutocomplete<T>(props: AsyncAutocompleteProps<T>): JSX.Element {\n const { defaultValue, toKey, toOption, loadOptions, onChange, onCreate, creatable, ...rest } = props;\n const defaultItems = toDefaultItems(defaultValue);\n const inputRef = useRef<HTMLInputElement>(null);\n const [lastValue, setLastValue] = useState<string | undefined>(undefined);\n const [timer, setTimer] = useState<number>();\n const [abortController, setAbortController] = useState<AbortController>();\n const [autoSubmit, setAutoSubmit] = useState<boolean>();\n const [options, setOptions] = useState<AsyncAutocompleteOption<T>[]>(defaultItems?.map(toOption));\n\n const lastValueRef = useRef<string>();\n lastValueRef.current = lastValue;\n\n const timerRef = useRef<number>();\n timerRef.current = timer;\n\n const abortControllerRef = useRef<AbortController>();\n abortControllerRef.current = abortController;\n\n const autoSubmitRef = useRef<boolean>();\n autoSubmitRef.current = autoSubmit;\n\n const optionsRef = useRef<AsyncAutocompleteOption<T>[]>();\n optionsRef.current = options;\n\n const handleTimer = useCallback((): void => {\n setTimer(undefined);\n\n const value = inputRef.current?.value?.trim() || '';\n if (value === lastValueRef.current) {\n // Nothing has changed, move on\n return;\n }\n\n setLastValue(value);\n\n const newAbortController = new AbortController();\n setAbortController(newAbortController);\n\n loadOptions(value, newAbortController.signal)\n .then((newValues: T[]) => {\n if (!newAbortController.signal.aborted) {\n setOptions(newValues.map(toOption));\n setAbortController(undefined);\n if (autoSubmitRef.current) {\n if (newValues.length > 0) {\n onChange(newValues.slice(0, 1));\n }\n setAutoSubmit(false);\n }\n }\n })\n .catch(console.log);\n }, [loadOptions, onChange, toOption]);\n\n const handleSearchChange = useCallback((): void => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n setAbortController(undefined);\n }\n\n if (timerRef.current !== undefined) {\n window.clearTimeout(timerRef.current);\n }\n\n const newTimer = window.setTimeout(() => handleTimer(), 100);\n setTimer(newTimer);\n }, [handleTimer]);\n\n const handleChange = useCallback(\n (values: string[]): void => {\n const result: T[] = [];\n for (const value of values) {\n let item = optionsRef.current?.find((option) => option.value === value)?.resource;\n if (!item && creatable !== false) {\n item = (onCreate as (input: string) => T)(value);\n }\n\n if (item) result.push(item);\n }\n onChange(result);\n },\n [creatable, onChange, onCreate]\n );\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent): void => {\n if (e.key === 'Enter') {\n if (!timerRef.current && !abortControllerRef.current) {\n killEvent(e);\n if (optionsRef.current && optionsRef.current.length > 0) {\n setOptions(optionsRef.current.slice(0, 1));\n handleChange([optionsRef.current[0].value]);\n }\n } else {\n // The user pressed enter, but we don't have results yet.\n // We need to wait for the results to come in.\n setAutoSubmit(true);\n }\n }\n },\n [handleChange]\n );\n\n const handleCreate = useCallback(\n (input: string): AsyncAutocompleteOption<T> => {\n const option = toOption((onCreate as (input: string) => T)(input));\n setOptions([...(optionsRef.current as AsyncAutocompleteOption<T>[]), option]);\n return option;\n },\n [onCreate, setOptions, toOption]\n );\n\n const handleFilter = useCallback((_value: string, selected: boolean) => !selected, []);\n\n useEffect(() => {\n return () => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n };\n }, []);\n\n return (\n <MultiSelect\n {...rest}\n ref={inputRef}\n defaultValue={defaultItems.map(toKey)}\n searchable\n onKeyDown={handleKeyDown}\n onSearchChange={handleSearchChange}\n data={options}\n onFocus={handleTimer}\n onChange={handleChange}\n onCreate={handleCreate}\n rightSectionWidth={40}\n rightSection={abortController ? <Loader size={16} /> : null}\n filter={handleFilter}\n creatable\n />\n );\n}\n\nfunction toDefaultItems<T>(defaultValue: T | T[] | undefined): T[] {\n if (!defaultValue) {\n return [];\n }\n if (Array.isArray(defaultValue)) {\n return defaultValue;\n }\n return [defaultValue];\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AsyncAutocomplete.mjs","sources":["../../../src/AsyncAutocomplete/AsyncAutocomplete.tsx"],"sourcesContent":["import { Loader, MultiSelect, MultiSelectProps, SelectItem } from '@mantine/core';\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { killEvent } from '../utils/dom';\n\nexport interface AsyncAutocompleteOption<T> extends SelectItem {\n resource: T;\n}\n\nexport interface AsyncAutocompleteProps<T>\n extends Omit<MultiSelectProps, 'data' | 'defaultValue' | 'loadOptions' | 'onChange' | 'onCreate' | 'searchable'> {\n defaultValue?: T | T[];\n toKey: (item: T) => string;\n toOption: (item: T) => AsyncAutocompleteOption<T>;\n loadOptions: (input: string, signal: AbortSignal) => Promise<T[]>;\n onChange: (item: T[]) => void;\n onCreate?: (input: string) => T;\n creatable?: boolean;\n}\n\nexport function AsyncAutocomplete<T>(props: AsyncAutocompleteProps<T>): JSX.Element {\n const { defaultValue, toKey, toOption, loadOptions, onChange, onCreate, creatable, ...rest } = props;\n const defaultItems = toDefaultItems(defaultValue);\n const inputRef = useRef<HTMLInputElement>(null);\n const [lastValue, setLastValue] = useState<string | undefined>(undefined);\n const [timer, setTimer] = useState<number>();\n const [abortController, setAbortController] = useState<AbortController>();\n const [autoSubmit, setAutoSubmit] = useState<boolean>();\n const [options, setOptions] = useState<AsyncAutocompleteOption<T>[]>(defaultItems?.map(toOption));\n\n const lastValueRef = useRef<string>();\n lastValueRef.current = lastValue;\n\n const timerRef = useRef<number>();\n timerRef.current = timer;\n\n const abortControllerRef = useRef<AbortController>();\n abortControllerRef.current = abortController;\n\n const autoSubmitRef = useRef<boolean>();\n autoSubmitRef.current = autoSubmit;\n\n const optionsRef = useRef<AsyncAutocompleteOption<T>[]>();\n optionsRef.current = options;\n\n const handleTimer = useCallback((): void => {\n setTimer(undefined);\n\n const value = inputRef.current?.value?.trim() || '';\n if (value === lastValueRef.current) {\n // Nothing has changed, move on\n return;\n }\n\n setLastValue(value);\n\n const newAbortController = new AbortController();\n setAbortController(newAbortController);\n\n loadOptions(value, newAbortController.signal)\n .then((newValues: T[]) => {\n if (!newAbortController.signal.aborted) {\n setOptions(newValues.map(toOption));\n setAbortController(undefined);\n if (autoSubmitRef.current) {\n if (newValues.length > 0) {\n onChange(newValues.slice(0, 1));\n }\n setAutoSubmit(false);\n }\n }\n })\n .catch(console.log);\n }, [loadOptions, onChange, toOption]);\n\n const handleSearchChange = useCallback((): void => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n setAbortController(undefined);\n }\n\n if (timerRef.current !== undefined) {\n window.clearTimeout(timerRef.current);\n }\n\n const newTimer = window.setTimeout(() => handleTimer(), 100);\n setTimer(newTimer);\n }, [handleTimer]);\n\n const handleChange = useCallback(\n (values: string[]): void => {\n const result: T[] = [];\n for (const value of values) {\n let item = optionsRef.current?.find((option) => option.value === value)?.resource;\n if (!item && creatable !== false) {\n item = (onCreate as (input: string) => T)(value);\n }\n\n if (item) {\n result.push(item);\n }\n }\n onChange(result);\n },\n [creatable, onChange, onCreate]\n );\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent): void => {\n if (e.key === 'Enter') {\n if (!timerRef.current && !abortControllerRef.current) {\n killEvent(e);\n if (optionsRef.current && optionsRef.current.length > 0) {\n setOptions(optionsRef.current.slice(0, 1));\n handleChange([optionsRef.current[0].value]);\n }\n } else {\n // The user pressed enter, but we don't have results yet.\n // We need to wait for the results to come in.\n setAutoSubmit(true);\n }\n }\n },\n [handleChange]\n );\n\n const handleCreate = useCallback(\n (input: string): AsyncAutocompleteOption<T> => {\n const option = toOption((onCreate as (input: string) => T)(input));\n setOptions([...(optionsRef.current as AsyncAutocompleteOption<T>[]), option]);\n return option;\n },\n [onCreate, setOptions, toOption]\n );\n\n const handleFilter = useCallback((_value: string, selected: boolean) => !selected, []);\n\n useEffect(() => {\n return () => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n };\n }, []);\n\n return (\n <MultiSelect\n {...rest}\n ref={inputRef}\n defaultValue={defaultItems.map(toKey)}\n searchable\n onKeyDown={handleKeyDown}\n onSearchChange={handleSearchChange}\n data={options}\n onFocus={handleTimer}\n onChange={handleChange}\n onCreate={handleCreate}\n rightSectionWidth={40}\n rightSection={abortController ? <Loader size={16} /> : null}\n filter={handleFilter}\n creatable\n />\n );\n}\n\nfunction toDefaultItems<T>(defaultValue: T | T[] | undefined): T[] {\n if (!defaultValue) {\n return [];\n }\n if (Array.isArray(defaultValue)) {\n return defaultValue;\n }\n return [defaultValue];\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -37,9 +37,9 @@ function getGoogleClientId(clientId) {
|
|
|
37
37
|
}
|
|
38
38
|
if (typeof window !== 'undefined') {
|
|
39
39
|
const origin = window.location.protocol + '//' + window.location.host;
|
|
40
|
-
const authorizedOrigins = "
|
|
40
|
+
const authorizedOrigins = "undefined"?.split(',') ?? [];
|
|
41
41
|
if (authorizedOrigins.includes(origin)) {
|
|
42
|
-
return "
|
|
42
|
+
return "undefined";
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
return undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GoogleButton.mjs","sources":["../../../src/GoogleButton/GoogleButton.tsx"],"sourcesContent":["import { GoogleCredentialResponse } from '@medplum/core';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { useMedplum } from '../MedplumProvider/MedplumProvider';\nimport { createScriptTag } from '../utils/script';\n\ninterface GoogleApi {\n accounts: {\n id: {\n initialize: (args: any) => void;\n renderButton: (parent: HTMLElement, args: any) => void;\n };\n };\n}\n\ndeclare const google: GoogleApi;\n\nexport interface GoogleButtonProps {\n readonly googleClientId?: string;\n readonly handleGoogleCredential: (response: GoogleCredentialResponse) => void;\n}\n\nexport function GoogleButton(props: GoogleButtonProps): JSX.Element | null {\n const medplum = useMedplum();\n const { googleClientId, handleGoogleCredential } = props;\n const parentRef = useRef<HTMLDivElement>(null);\n const [scriptLoaded, setScriptLoaded] = useState<boolean>(typeof google !== 'undefined');\n const [initialized, setInitialized] = useState<boolean>(false);\n const [buttonRendered, setButtonRendered] = useState<boolean>(false);\n\n useEffect(() => {\n if (typeof google === 'undefined') {\n createScriptTag('https://accounts.google.com/gsi/client', () => setScriptLoaded(true));\n return;\n }\n\n if (!initialized) {\n google.accounts.id.initialize({\n client_id: googleClientId,\n callback: handleGoogleCredential,\n });\n setInitialized(true);\n }\n\n if (parentRef.current && !buttonRendered) {\n google.accounts.id.renderButton(parentRef.current, {});\n setButtonRendered(true);\n }\n }, [medplum, googleClientId, initialized, scriptLoaded, parentRef, buttonRendered, handleGoogleCredential]);\n\n if (!googleClientId) {\n return null;\n }\n\n return <div ref={parentRef} />;\n}\n\nexport function getGoogleClientId(clientId: string | undefined): string | undefined {\n if (clientId) {\n return clientId;\n }\n\n if (typeof window !== 'undefined') {\n const origin = window.location.protocol + '//' + window.location.host;\n const authorizedOrigins = process.env.GOOGLE_AUTH_ORIGINS?.split(',') ?? [];\n if (authorizedOrigins.includes(origin)) {\n return process.env.GOOGLE_CLIENT_ID;\n }\n }\n\n return undefined;\n}\n"],"names":[],"mappings":";;;;AAqBM,SAAU,YAAY,CAAC,KAAwB,EAAA;AACnD,IAAA,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;AAC7B,IAAA,MAAM,EAAE,cAAc,EAAE,sBAAsB,EAAE,GAAG,KAAK,CAAC;AACzD,IAAA,MAAM,SAAS,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;AAC/C,IAAA,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAU,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC;IACzF,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;IAC/D,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;IAErE,SAAS,CAAC,MAAK;AACb,QAAA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;YACjC,eAAe,CAAC,wCAAwC,EAAE,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;YACvF,OAAO;AACR,SAAA;QAED,IAAI,CAAC,WAAW,EAAE;AAChB,YAAA,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,UAAU,CAAC;AAC5B,gBAAA,SAAS,EAAE,cAAc;AACzB,gBAAA,QAAQ,EAAE,sBAAsB;AACjC,aAAA,CAAC,CAAC;YACH,cAAc,CAAC,IAAI,CAAC,CAAC;AACtB,SAAA;AAED,QAAA,IAAI,SAAS,CAAC,OAAO,IAAI,CAAC,cAAc,EAAE;AACxC,YAAA,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YACvD,iBAAiB,CAAC,IAAI,CAAC,CAAC;AACzB,SAAA;AACH,KAAC,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,sBAAsB,CAAC,CAAC,CAAC;IAE5G,IAAI,CAAC,cAAc,EAAE;AACnB,QAAA,OAAO,IAAI,CAAC;AACb,KAAA;AAED,IAAA,OAAO,KAAK,CAAA,aAAA,CAAA,KAAA,EAAA,EAAA,GAAG,EAAE,SAAS,GAAI,CAAC;AACjC,CAAC;AAEK,SAAU,iBAAiB,CAAC,QAA4B,EAAA;AAC5D,IAAA,IAAI,QAAQ,EAAE;AACZ,QAAA,OAAO,QAAQ,CAAC;AACjB,KAAA;AAED,IAAA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;AACjC,QAAA,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,GAAG,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;AACtE,QAAA,MAAM,iBAAiB,GAAG,
|
|
1
|
+
{"version":3,"file":"GoogleButton.mjs","sources":["../../../src/GoogleButton/GoogleButton.tsx"],"sourcesContent":["import { GoogleCredentialResponse } from '@medplum/core';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { useMedplum } from '../MedplumProvider/MedplumProvider';\nimport { createScriptTag } from '../utils/script';\n\ninterface GoogleApi {\n accounts: {\n id: {\n initialize: (args: any) => void;\n renderButton: (parent: HTMLElement, args: any) => void;\n };\n };\n}\n\ndeclare const google: GoogleApi;\n\nexport interface GoogleButtonProps {\n readonly googleClientId?: string;\n readonly handleGoogleCredential: (response: GoogleCredentialResponse) => void;\n}\n\nexport function GoogleButton(props: GoogleButtonProps): JSX.Element | null {\n const medplum = useMedplum();\n const { googleClientId, handleGoogleCredential } = props;\n const parentRef = useRef<HTMLDivElement>(null);\n const [scriptLoaded, setScriptLoaded] = useState<boolean>(typeof google !== 'undefined');\n const [initialized, setInitialized] = useState<boolean>(false);\n const [buttonRendered, setButtonRendered] = useState<boolean>(false);\n\n useEffect(() => {\n if (typeof google === 'undefined') {\n createScriptTag('https://accounts.google.com/gsi/client', () => setScriptLoaded(true));\n return;\n }\n\n if (!initialized) {\n google.accounts.id.initialize({\n client_id: googleClientId,\n callback: handleGoogleCredential,\n });\n setInitialized(true);\n }\n\n if (parentRef.current && !buttonRendered) {\n google.accounts.id.renderButton(parentRef.current, {});\n setButtonRendered(true);\n }\n }, [medplum, googleClientId, initialized, scriptLoaded, parentRef, buttonRendered, handleGoogleCredential]);\n\n if (!googleClientId) {\n return null;\n }\n\n return <div ref={parentRef} />;\n}\n\nexport function getGoogleClientId(clientId: string | undefined): string | undefined {\n if (clientId) {\n return clientId;\n }\n\n if (typeof window !== 'undefined') {\n const origin = window.location.protocol + '//' + window.location.host;\n const authorizedOrigins = process.env.GOOGLE_AUTH_ORIGINS?.split(',') ?? [];\n if (authorizedOrigins.includes(origin)) {\n return process.env.GOOGLE_CLIENT_ID;\n }\n }\n\n return undefined;\n}\n"],"names":[],"mappings":";;;;AAqBM,SAAU,YAAY,CAAC,KAAwB,EAAA;AACnD,IAAA,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;AAC7B,IAAA,MAAM,EAAE,cAAc,EAAE,sBAAsB,EAAE,GAAG,KAAK,CAAC;AACzD,IAAA,MAAM,SAAS,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;AAC/C,IAAA,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAU,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC;IACzF,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;IAC/D,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;IAErE,SAAS,CAAC,MAAK;AACb,QAAA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;YACjC,eAAe,CAAC,wCAAwC,EAAE,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;YACvF,OAAO;AACR,SAAA;QAED,IAAI,CAAC,WAAW,EAAE;AAChB,YAAA,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,UAAU,CAAC;AAC5B,gBAAA,SAAS,EAAE,cAAc;AACzB,gBAAA,QAAQ,EAAE,sBAAsB;AACjC,aAAA,CAAC,CAAC;YACH,cAAc,CAAC,IAAI,CAAC,CAAC;AACtB,SAAA;AAED,QAAA,IAAI,SAAS,CAAC,OAAO,IAAI,CAAC,cAAc,EAAE;AACxC,YAAA,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YACvD,iBAAiB,CAAC,IAAI,CAAC,CAAC;AACzB,SAAA;AACH,KAAC,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,sBAAsB,CAAC,CAAC,CAAC;IAE5G,IAAI,CAAC,cAAc,EAAE;AACnB,QAAA,OAAO,IAAI,CAAC;AACb,KAAA;AAED,IAAA,OAAO,KAAK,CAAA,aAAA,CAAA,KAAA,EAAA,EAAA,GAAG,EAAE,SAAS,GAAI,CAAC;AACjC,CAAC;AAEK,SAAU,iBAAiB,CAAC,QAA4B,EAAA;AAC5D,IAAA,IAAI,QAAQ,EAAE;AACZ,QAAA,OAAO,QAAQ,CAAC;AACjB,KAAA;AAED,IAAA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;AACjC,QAAA,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,GAAG,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;AACtE,QAAA,MAAM,iBAAiB,GAAG,WAA+B,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;AAC5E,QAAA,IAAI,iBAAiB,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;AACtC,YAAA,OAAO,WAA4B,CAAC;AACrC,SAAA;AACF,KAAA;AAED,IAAA,OAAO,SAAS,CAAC;AACnB;;;;"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { showNotification } from '@mantine/notifications';
|
|
1
2
|
import React, { createContext, useState, useEffect, useContext } from 'react';
|
|
2
3
|
|
|
3
4
|
const reactContext = createContext(undefined);
|
|
@@ -25,6 +26,13 @@ function MedplumProvider(props) {
|
|
|
25
26
|
medplum.addEventListener('change', eventListener);
|
|
26
27
|
return () => medplum.removeEventListeneer('change', eventListener);
|
|
27
28
|
}, [medplum, state]);
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
function eventListener() {
|
|
31
|
+
showNotification({ color: 'red', message: 'No connection to server', autoClose: false });
|
|
32
|
+
}
|
|
33
|
+
medplum.addEventListener('offline', eventListener);
|
|
34
|
+
return () => medplum.removeEventListeneer('offline', eventListener);
|
|
35
|
+
}, [medplum]);
|
|
28
36
|
const medplumContext = {
|
|
29
37
|
...state,
|
|
30
38
|
medplum,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MedplumProvider.mjs","sources":["../../../src/MedplumProvider/MedplumProvider.tsx"],"sourcesContent":["import { MedplumClient, ProfileResource } from '@medplum/core';\nimport React, { createContext, useContext, useEffect, useState } from 'react';\n\nconst reactContext = createContext(undefined as MedplumContext | undefined);\n\nexport type MepdlumNavigateFunction = (path: string) => void;\n\nexport interface MedplumProviderProps {\n medplum: MedplumClient;\n navigate?: MepdlumNavigateFunction;\n children: React.ReactNode;\n}\n\nexport interface MedplumContext {\n medplum: MedplumClient;\n navigate: MepdlumNavigateFunction;\n profile?: ProfileResource;\n loading: boolean;\n}\n\n/**\n * The MedplumProvider component provides Medplum context state.\n *\n * Medplum context includes:\n * 1) medplum - Medplum client library\n * 2) profile - The current user profile (if signed in)\n */\nexport function MedplumProvider(props: MedplumProviderProps): JSX.Element {\n const medplum = props.medplum;\n const navigate = props.navigate || defaultNavigate;\n\n const [state, setState] = useState({\n profile: medplum.getProfile(),\n loading: false,\n });\n\n useEffect(() => {\n function eventListener(): void {\n setState({\n ...state,\n profile: medplum.getProfile(),\n });\n }\n\n medplum.addEventListener('change', eventListener);\n return () => medplum.removeEventListeneer('change', eventListener);\n }, [medplum, state]);\n\n const medplumContext = {\n ...state,\n medplum,\n navigate,\n };\n\n return <reactContext.Provider value={medplumContext}>{props.children}</reactContext.Provider>;\n}\n\n/**\n * Returns the MedplumContext instance.\n */\nexport function useMedplumContext(): MedplumContext {\n return useContext(reactContext) as MedplumContext;\n}\n\n/**\n * Returns the MedplumClient instance.\n * This is a shortcut for useMedplumContext().medplum.\n */\nexport function useMedplum(): MedplumClient {\n return useMedplumContext().medplum;\n}\n\n/**\n * Returns the Medplum navigate function.\n * @returns The Medplum navigate function.\n */\nexport function useMedplumNavigate(): MepdlumNavigateFunction {\n return useMedplumContext().navigate;\n}\n\n/**\n * Returns the current Medplum user profile (if signed in).\n * This is a shortcut for useMedplumContext().profile.\n * @returns The current user profile.\n */\nexport function useMedplumProfile(): ProfileResource | undefined {\n return useMedplumContext().profile;\n}\n\n/**\n * The default \"navigate\" function which simply uses window.location.href.\n * @param path The path to navigate to.\n */\nfunction defaultNavigate(path: string): void {\n window.location.assign(path);\n}\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MedplumProvider.mjs","sources":["../../../src/MedplumProvider/MedplumProvider.tsx"],"sourcesContent":["import { MedplumClient, ProfileResource } from '@medplum/core';\nimport { showNotification } from '@mantine/notifications';\nimport React, { createContext, useContext, useEffect, useState } from 'react';\n\nconst reactContext = createContext(undefined as MedplumContext | undefined);\n\nexport type MepdlumNavigateFunction = (path: string) => void;\n\nexport interface MedplumProviderProps {\n medplum: MedplumClient;\n navigate?: MepdlumNavigateFunction;\n children: React.ReactNode;\n}\n\nexport interface MedplumContext {\n medplum: MedplumClient;\n navigate: MepdlumNavigateFunction;\n profile?: ProfileResource;\n loading: boolean;\n}\n\n/**\n * The MedplumProvider component provides Medplum context state.\n *\n * Medplum context includes:\n * 1) medplum - Medplum client library\n * 2) profile - The current user profile (if signed in)\n */\nexport function MedplumProvider(props: MedplumProviderProps): JSX.Element {\n const medplum = props.medplum;\n const navigate = props.navigate || defaultNavigate;\n\n const [state, setState] = useState({\n profile: medplum.getProfile(),\n loading: false,\n });\n\n useEffect(() => {\n function eventListener(): void {\n setState({\n ...state,\n profile: medplum.getProfile(),\n });\n }\n\n medplum.addEventListener('change', eventListener);\n return () => medplum.removeEventListeneer('change', eventListener);\n }, [medplum, state]);\n\n useEffect(() => {\n function eventListener(): void {\n showNotification({ color: 'red', message: 'No connection to server', autoClose: false });\n }\n medplum.addEventListener('offline', eventListener);\n return () => medplum.removeEventListeneer('offline', eventListener);\n }, [medplum]);\n\n const medplumContext = {\n ...state,\n medplum,\n navigate,\n };\n\n return <reactContext.Provider value={medplumContext}>{props.children}</reactContext.Provider>;\n}\n\n/**\n * Returns the MedplumContext instance.\n */\nexport function useMedplumContext(): MedplumContext {\n return useContext(reactContext) as MedplumContext;\n}\n\n/**\n * Returns the MedplumClient instance.\n * This is a shortcut for useMedplumContext().medplum.\n */\nexport function useMedplum(): MedplumClient {\n return useMedplumContext().medplum;\n}\n\n/**\n * Returns the Medplum navigate function.\n * @returns The Medplum navigate function.\n */\nexport function useMedplumNavigate(): MepdlumNavigateFunction {\n return useMedplumContext().navigate;\n}\n\n/**\n * Returns the current Medplum user profile (if signed in).\n * This is a shortcut for useMedplumContext().profile.\n * @returns The current user profile.\n */\nexport function useMedplumProfile(): ProfileResource | undefined {\n return useMedplumContext().profile;\n}\n\n/**\n * The default \"navigate\" function which simply uses window.location.href.\n * @param path The path to navigate to.\n */\nfunction defaultNavigate(path: string): void {\n window.location.assign(path);\n}\n"],"names":[],"mappings":";;;AAIA,MAAM,YAAY,GAAG,aAAa,CAAC,SAAuC,CAAC,CAAC;AAiB5E;;;;;;AAMG;AACG,SAAU,eAAe,CAAC,KAA2B,EAAA;AACzD,IAAA,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;AAC9B,IAAA,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,eAAe,CAAC;AAEnD,IAAA,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC;AACjC,QAAA,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;AAC7B,QAAA,OAAO,EAAE,KAAK;AACf,KAAA,CAAC,CAAC;IAEH,SAAS,CAAC,MAAK;AACb,QAAA,SAAS,aAAa,GAAA;AACpB,YAAA,QAAQ,CAAC;AACP,gBAAA,GAAG,KAAK;AACR,gBAAA,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;AAC9B,aAAA,CAAC,CAAC;SACJ;AAED,QAAA,OAAO,CAAC,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QAClD,OAAO,MAAM,OAAO,CAAC,oBAAoB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;AACrE,KAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;IAErB,SAAS,CAAC,MAAK;AACb,QAAA,SAAS,aAAa,GAAA;AACpB,YAAA,gBAAgB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,yBAAyB,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;SAC1F;AACD,QAAA,OAAO,CAAC,gBAAgB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QACnD,OAAO,MAAM,OAAO,CAAC,oBAAoB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;AACtE,KAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;AAEd,IAAA,MAAM,cAAc,GAAG;AACrB,QAAA,GAAG,KAAK;QACR,OAAO;QACP,QAAQ;KACT,CAAC;AAEF,IAAA,OAAO,KAAC,CAAA,aAAA,CAAA,YAAY,CAAC,QAAQ,EAAC,EAAA,KAAK,EAAE,cAAc,EAAG,EAAA,KAAK,CAAC,QAAQ,CAAyB,CAAC;AAChG,CAAC;AAED;;AAEG;SACa,iBAAiB,GAAA;AAC/B,IAAA,OAAO,UAAU,CAAC,YAAY,CAAmB,CAAC;AACpD,CAAC;AAED;;;AAGG;SACa,UAAU,GAAA;AACxB,IAAA,OAAO,iBAAiB,EAAE,CAAC,OAAO,CAAC;AACrC,CAAC;AAED;;;AAGG;SACa,kBAAkB,GAAA;AAChC,IAAA,OAAO,iBAAiB,EAAE,CAAC,QAAQ,CAAC;AACtC,CAAC;AAED;;;;AAIG;SACa,iBAAiB,GAAA;AAC/B,IAAA,OAAO,iBAAiB,EAAE,CAAC,OAAO,CAAC;AACrC,CAAC;AAED;;;AAGG;AACH,SAAS,eAAe,CAAC,IAAY,EAAA;AACnC,IAAA,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC/B;;;;"}
|
|
@@ -269,7 +269,7 @@ function CommunicationTimelineItem(props) {
|
|
|
269
269
|
const { classes } = useStyles();
|
|
270
270
|
const routine = !props.resource.priority || props.resource.priority === 'routine';
|
|
271
271
|
const className = routine ? undefined : classes.pinnedComment;
|
|
272
|
-
return (React.createElement(TimelineItem, { resource: props.resource, profile: props.resource.sender, padding: true, className: className, popupMenuItems: React.createElement(TimelineItemPopupMenu, { ...props }) },
|
|
272
|
+
return (React.createElement(TimelineItem, { resource: props.resource, profile: props.resource.sender, dateTime: props.resource.sent, padding: true, className: className, popupMenuItems: React.createElement(TimelineItemPopupMenu, { ...props }) },
|
|
273
273
|
React.createElement("p", null, props.resource.payload?.[0]?.contentString)));
|
|
274
274
|
}
|
|
275
275
|
function MediaTimelineItem(props) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResourceTimeline.mjs","sources":["../../../src/ResourceTimeline/ResourceTimeline.tsx"],"sourcesContent":["import { ActionIcon, Center, createStyles, Group, Loader, Menu, ScrollArea, TextInput } from '@mantine/core';\nimport { showNotification, updateNotification } from '@mantine/notifications';\nimport { getReferenceString, MedplumClient, normalizeErrorString, ProfileResource } from '@medplum/core';\nimport {\n Attachment,\n AuditEvent,\n Bundle,\n BundleEntry,\n Communication,\n DiagnosticReport,\n Media,\n Reference,\n Resource,\n ResourceType,\n} from '@medplum/fhirtypes';\nimport {\n IconCheck,\n IconCloudUpload,\n IconEdit,\n IconFileAlert,\n IconListDetails,\n IconMessage,\n IconPin,\n IconPinnedOff,\n IconTrash,\n} from '@tabler/icons-react';\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { AttachmentButton } from '../AttachmentButton/AttachmentButton';\nimport { AttachmentDisplay } from '../AttachmentDisplay/AttachmentDisplay';\nimport { DiagnosticReportDisplay } from '../DiagnosticReportDisplay/DiagnosticReportDisplay';\nimport { Form } from '../Form/Form';\nimport { useMedplum, useMedplumNavigate } from '../MedplumProvider/MedplumProvider';\nimport { Panel } from '../Panel/Panel';\nimport { ResourceAvatar } from '../ResourceAvatar/ResourceAvatar';\nimport { ResourceDiffTable } from '../ResourceDiffTable/ResourceDiffTable';\nimport { ResourceTable } from '../ResourceTable/ResourceTable';\nimport { Timeline, TimelineItem } from '../Timeline/Timeline';\nimport { useResource } from '../useResource/useResource';\nimport { sortByDateAndPriority } from '../utils/date';\n\nconst useStyles = createStyles((theme) => ({\n pinnedComment: {\n backgroundColor: theme.colors.blue[0],\n },\n}));\n\nexport interface ResourceTimelineProps<T extends Resource> {\n value: T | Reference<T>;\n loadTimelineResources: (\n medplum: MedplumClient,\n resourceType: ResourceType,\n id: string\n ) => Promise<PromiseSettledResult<Bundle>[]>;\n createCommunication?: (resource: T, sender: ProfileResource, text: string) => Communication;\n createMedia?: (resource: T, operator: ProfileResource, attachment: Attachment) => Media;\n}\n\nexport function ResourceTimeline<T extends Resource>(props: ResourceTimelineProps<T>): JSX.Element {\n const medplum = useMedplum();\n const navigate = useMedplumNavigate();\n const sender = medplum.getProfile() as ProfileResource;\n const inputRef = useRef<HTMLInputElement>(null);\n const resource = useResource(props.value);\n const [history, setHistory] = useState<Bundle>();\n const [items, setItems] = useState<Resource[]>([]);\n const loadTimelineResources = props.loadTimelineResources;\n\n const itemsRef = useRef<Resource[]>(items);\n itemsRef.current = items;\n\n /**\n * Sorts and sets the items.\n *\n * Sorting is primarily a function of meta.lastUpdated, but there are special cases.\n * When displaying connected resources, for example a Communication in the context of an Encounter,\n * the Communication.sent time is used rather than Communication.meta.lastUpdated.\n *\n * Other examples of special cases:\n * - DiagnosticReport.issued\n * - Media.issued\n * - Observation.issued\n * - DocumentReference.date\n *\n * See \"sortByDateAndPriority()\" for more details.\n */\n const sortAndSetItems = useCallback(\n (newItmes: Resource[]): void => {\n sortByDateAndPriority(newItmes, resource);\n newItmes.reverse();\n setItems(newItmes);\n },\n [resource]\n );\n\n /**\n * Handles a batch request response.\n * @param batchResponse The batch response.\n */\n const handleBatchResponse = useCallback(\n (batchResponse: PromiseSettledResult<Bundle>[]): void => {\n const newItems = [];\n\n for (const settledResult of batchResponse) {\n if (settledResult.status !== 'fulfilled') {\n // User may not have access to all resource types\n continue;\n }\n\n const bundle = settledResult.value;\n if (bundle.type === 'history') {\n setHistory(bundle);\n }\n\n if (bundle.entry) {\n for (const entry of bundle.entry) {\n newItems.push(entry.resource as Resource);\n }\n }\n }\n\n sortAndSetItems(newItems);\n },\n [sortAndSetItems]\n );\n\n /**\n * Adds an array of resources to the timeline.\n * @param resource Resource to add.\n */\n const addResource = useCallback(\n (resource: Resource): void => sortAndSetItems([...itemsRef.current, resource]),\n [sortAndSetItems]\n );\n\n /**\n * Loads the timeline.\n */\n const loadTimeline = useCallback(() => {\n let resourceType: ResourceType;\n let id: string;\n if ('resourceType' in props.value) {\n resourceType = props.value.resourceType;\n id = props.value.id as string;\n } else {\n [resourceType, id] = props.value.reference?.split('/') as [ResourceType, string];\n }\n loadTimelineResources(medplum, resourceType, id).then(handleBatchResponse).catch(console.log);\n }, [medplum, props.value, loadTimelineResources, handleBatchResponse]);\n\n useEffect(() => loadTimeline(), [loadTimeline]);\n\n /**\n * Adds a Communication resource to the timeline.\n * @param contentString The comment content.\n */\n function createComment(contentString: string): void {\n if (!resource || !props.createCommunication) {\n // Encounter not loaded yet\n return;\n }\n medplum\n .createResource(props.createCommunication(resource, sender, contentString))\n .then((result) => addResource(result))\n .catch(console.log);\n }\n\n /**\n * Adds a Media resource to the timeline.\n * @param attachment The media attachment.\n */\n function createMedia(attachment: Attachment): void {\n if (!resource || !props.createMedia) {\n // Encounter not loaded yet\n return;\n }\n medplum\n .createResource(props.createMedia(resource, sender, attachment))\n .then((result) => addResource(result))\n .then(() =>\n updateNotification({\n id: 'upload-notification',\n color: 'teal',\n title: 'Upload complete',\n message: '',\n icon: <IconCheck size={16} />,\n autoClose: 2000,\n })\n )\n .catch((reason) =>\n updateNotification({\n id: 'upload-notification',\n color: 'red',\n title: 'Upload error',\n message: normalizeErrorString(reason),\n icon: <IconFileAlert size={16} />,\n autoClose: 2000,\n })\n );\n }\n\n function setPriority(\n communication: Communication,\n priority: 'routine' | 'urgent' | 'asap' | 'stat'\n ): Promise<Communication> {\n return medplum.updateResource({ ...communication, priority });\n }\n\n function onPin(communication: Communication): void {\n setPriority(communication, 'stat').then(loadTimeline).catch(console.log);\n }\n\n function onUnpin(communication: Communication): void {\n setPriority(communication, 'routine').then(loadTimeline).catch(console.log);\n }\n\n function onDetails(timelineItem: Resource): void {\n navigate(`/${timelineItem.resourceType}/${timelineItem.id}`);\n }\n\n function onEdit(timelineItem: Resource): void {\n navigate(`/${timelineItem.resourceType}/${timelineItem.id}/edit`);\n }\n\n function onDelete(timelineItem: Resource): void {\n navigate(`/${timelineItem.resourceType}/${timelineItem.id}/delete`);\n }\n\n function onVersionDetails(version: Resource): void {\n navigate(`/${version.resourceType}/${version.id}/_history/${version.meta?.versionId}`);\n }\n\n function onUploadStart(): void {\n showNotification({\n id: 'upload-notification',\n loading: true,\n title: 'Initializing upload...',\n message: 'Please wait...',\n autoClose: false,\n withCloseButton: false,\n });\n }\n\n function onUploadProgress(e: ProgressEvent): void {\n updateNotification({\n id: 'upload-notification',\n loading: true,\n title: 'Uploading...',\n message: getProgressMessage(e),\n autoClose: false,\n withCloseButton: false,\n });\n }\n\n if (!resource) {\n return (\n <Center style={{ width: '100%', height: '100%' }}>\n <Loader />\n </Center>\n );\n }\n\n return (\n <Timeline>\n {props.createCommunication && (\n <Panel>\n <Form\n testid=\"timeline-form\"\n onSubmit={(formData: Record<string, string>) => {\n createComment(formData.text);\n\n const input = inputRef.current;\n if (input) {\n input.value = '';\n input.focus();\n }\n }}\n >\n <Group spacing=\"xs\" noWrap style={{ width: '100%' }}>\n <ResourceAvatar value={sender} />\n <TextInput\n name=\"text\"\n ref={inputRef}\n placeholder=\"Add comment\"\n style={{ width: '100%', maxWidth: 300 }}\n />\n <ActionIcon type=\"submit\" radius=\"xl\" color=\"blue\" variant=\"filled\">\n <IconMessage size={16} />\n </ActionIcon>\n <AttachmentButton\n onUpload={createMedia}\n onUploadStart={onUploadStart}\n onUploadProgress={onUploadProgress}\n >\n {(props) => (\n <ActionIcon {...props} radius=\"xl\" color=\"blue\" variant=\"filled\">\n <IconCloudUpload size={16} />\n </ActionIcon>\n )}\n </AttachmentButton>\n </Group>\n </Form>\n </Panel>\n )}\n {items.map((item) => {\n if (!item) {\n // TODO: Handle null history items for deleted versions.\n return null;\n }\n const key = `${item.resourceType}/${item.id}/${item.meta?.versionId}`;\n if (item.resourceType === resource.resourceType && item.id === resource.id) {\n return (\n <HistoryTimelineItem\n key={key}\n history={history as Bundle<Resource>}\n resource={item}\n onDetails={onVersionDetails}\n />\n );\n }\n switch (item.resourceType) {\n case 'AuditEvent':\n return <AuditEventTimelineItem key={key} resource={item} onDetails={onDetails} />;\n case 'Communication':\n return (\n <CommunicationTimelineItem\n key={key}\n resource={item}\n onPin={item.priority !== 'stat' ? onPin : undefined}\n onUnpin={item.priority === 'stat' ? onUnpin : undefined}\n onDetails={onDetails}\n onEdit={onEdit}\n onDelete={onDelete}\n />\n );\n case 'DiagnosticReport':\n return (\n <DiagnosticReportTimelineItem\n key={key}\n resource={item}\n onDetails={onDetails}\n onEdit={onEdit}\n onDelete={onDelete}\n />\n );\n case 'Media':\n return (\n <MediaTimelineItem key={key} resource={item} onDetails={onDetails} onEdit={onEdit} onDelete={onDelete} />\n );\n default:\n return (\n <TimelineItem key={key} resource={item} padding={true}>\n <ResourceTable value={item} ignoreMissingValues={true} />\n </TimelineItem>\n );\n }\n })}\n </Timeline>\n );\n}\n\ninterface BaseTimelineItemProps<T extends Resource> {\n resource: T;\n onPin?: (resource: T) => void;\n onUnpin?: (resource: T) => void;\n onDetails?: (resource: T) => void;\n onEdit?: (resource: T) => void;\n onDelete?: (resource: T) => void;\n}\n\nfunction TimelineItemPopupMenu<T extends Resource>(props: BaseTimelineItemProps<T>): JSX.Element {\n return (\n <Menu.Dropdown>\n <Menu.Label>Resource</Menu.Label>\n {props.onPin && (\n <Menu.Item\n icon={<IconPin size={14} />}\n onClick={() => (props.onPin as (resource: T) => void)(props.resource)}\n aria-label={`Pin ${getReferenceString(props.resource)}`}\n >\n Pin\n </Menu.Item>\n )}\n {props.onUnpin && (\n <Menu.Item\n icon={<IconPinnedOff size={14} />}\n onClick={() => (props.onUnpin as (resource: T) => void)(props.resource)}\n aria-label={`Unpin ${getReferenceString(props.resource)}`}\n >\n Unpin\n </Menu.Item>\n )}\n {props.onDetails && (\n <Menu.Item\n icon={<IconListDetails size={14} />}\n onClick={() => (props.onDetails as (resource: T) => void)(props.resource)}\n aria-label={`Details ${getReferenceString(props.resource)}`}\n >\n Details\n </Menu.Item>\n )}\n {props.onEdit && (\n <Menu.Item\n icon={<IconEdit size={14} />}\n onClick={() => (props.onEdit as (resource: T) => void)(props.resource)}\n aria-label={`Edit ${getReferenceString(props.resource)}`}\n >\n Edit\n </Menu.Item>\n )}\n {props.onDelete && (\n <>\n <Menu.Divider />\n <Menu.Label>Danger zone</Menu.Label>\n <Menu.Item\n color=\"red\"\n icon={<IconTrash size={14} />}\n onClick={() => (props.onDelete as (resource: T) => void)(props.resource)}\n aria-label={`Delete ${getReferenceString(props.resource)}`}\n >\n Delete\n </Menu.Item>\n </>\n )}\n </Menu.Dropdown>\n );\n}\n\ninterface HistoryTimelineItemProps extends BaseTimelineItemProps<Resource> {\n history: Bundle;\n}\n\nfunction HistoryTimelineItem(props: HistoryTimelineItemProps): JSX.Element {\n const previous = getPrevious(props.history, props.resource);\n if (previous) {\n return (\n <TimelineItem resource={props.resource} padding={true} popupMenuItems={<TimelineItemPopupMenu {...props} />}>\n <ResourceDiffTable original={previous} revised={props.resource} />\n </TimelineItem>\n );\n } else {\n return (\n <TimelineItem resource={props.resource} padding={true} popupMenuItems={<TimelineItemPopupMenu {...props} />}>\n <h3>Created</h3>\n <ResourceTable value={props.resource} ignoreMissingValues forceUseInput />\n </TimelineItem>\n );\n }\n}\n\nfunction getPrevious(history: Bundle, version: Resource): Resource | undefined {\n const entries = history.entry as BundleEntry[];\n const index = entries.findIndex((entry) => entry.resource?.meta?.versionId === version.meta?.versionId);\n if (index >= entries.length - 1) {\n return undefined;\n }\n return entries[index + 1].resource;\n}\n\nfunction CommunicationTimelineItem(props: BaseTimelineItemProps<Communication>): JSX.Element {\n const { classes } = useStyles();\n const routine = !props.resource.priority || props.resource.priority === 'routine';\n const className = routine ? undefined : classes.pinnedComment;\n return (\n <TimelineItem\n resource={props.resource}\n profile={props.resource.sender}\n padding={true}\n className={className}\n popupMenuItems={<TimelineItemPopupMenu {...props} />}\n >\n <p>{props.resource.payload?.[0]?.contentString}</p>\n </TimelineItem>\n );\n}\n\nfunction MediaTimelineItem(props: BaseTimelineItemProps<Media>): JSX.Element {\n const contentType = props.resource.content?.contentType;\n const padding =\n contentType &&\n !contentType.startsWith('image/') &&\n !contentType.startsWith('video/') &&\n contentType !== 'application/pdf';\n return (\n <TimelineItem resource={props.resource} padding={!!padding} popupMenuItems={<TimelineItemPopupMenu {...props} />}>\n <AttachmentDisplay value={props.resource.content} />\n </TimelineItem>\n );\n}\n\nfunction AuditEventTimelineItem(props: BaseTimelineItemProps<AuditEvent>): JSX.Element {\n return (\n <TimelineItem resource={props.resource} padding={true} popupMenuItems={<TimelineItemPopupMenu {...props} />}>\n <ScrollArea>\n <pre>{props.resource.outcomeDesc}</pre>\n </ScrollArea>\n </TimelineItem>\n );\n}\n\nfunction DiagnosticReportTimelineItem(props: BaseTimelineItemProps<DiagnosticReport>): JSX.Element {\n return (\n <TimelineItem resource={props.resource} padding={true} popupMenuItems={<TimelineItemPopupMenu {...props} />}>\n <DiagnosticReportDisplay value={props.resource} />\n </TimelineItem>\n );\n}\n\nfunction getProgressMessage(e: ProgressEvent): string {\n if (e.lengthComputable) {\n const percent = (100 * e.loaded) / e.total;\n return `Uploaded: ${formatFileSize(e.loaded)} / ${formatFileSize(e.total)} ${percent.toFixed(2)}%`;\n }\n return `Uploaded: ${formatFileSize(e.loaded)}`;\n}\n\nfunction formatFileSize(bytes: number): string {\n if (bytes === 0) {\n return '0.00 B';\n }\n const e = Math.floor(Math.log(bytes) / Math.log(1024));\n return (bytes / Math.pow(1024, e)).toFixed(2) + ' ' + ' KMGTP'.charAt(e) + 'B';\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ResourceTimeline.mjs","sources":["../../../src/ResourceTimeline/ResourceTimeline.tsx"],"sourcesContent":["import { ActionIcon, Center, createStyles, Group, Loader, Menu, ScrollArea, TextInput } from '@mantine/core';\nimport { showNotification, updateNotification } from '@mantine/notifications';\nimport { getReferenceString, MedplumClient, normalizeErrorString, ProfileResource } from '@medplum/core';\nimport {\n Attachment,\n AuditEvent,\n Bundle,\n BundleEntry,\n Communication,\n DiagnosticReport,\n Media,\n Reference,\n Resource,\n ResourceType,\n} from '@medplum/fhirtypes';\nimport {\n IconCheck,\n IconCloudUpload,\n IconEdit,\n IconFileAlert,\n IconListDetails,\n IconMessage,\n IconPin,\n IconPinnedOff,\n IconTrash,\n} from '@tabler/icons-react';\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { AttachmentButton } from '../AttachmentButton/AttachmentButton';\nimport { AttachmentDisplay } from '../AttachmentDisplay/AttachmentDisplay';\nimport { DiagnosticReportDisplay } from '../DiagnosticReportDisplay/DiagnosticReportDisplay';\nimport { Form } from '../Form/Form';\nimport { useMedplum, useMedplumNavigate } from '../MedplumProvider/MedplumProvider';\nimport { Panel } from '../Panel/Panel';\nimport { ResourceAvatar } from '../ResourceAvatar/ResourceAvatar';\nimport { ResourceDiffTable } from '../ResourceDiffTable/ResourceDiffTable';\nimport { ResourceTable } from '../ResourceTable/ResourceTable';\nimport { Timeline, TimelineItem } from '../Timeline/Timeline';\nimport { useResource } from '../useResource/useResource';\nimport { sortByDateAndPriority } from '../utils/date';\n\nconst useStyles = createStyles((theme) => ({\n pinnedComment: {\n backgroundColor: theme.colors.blue[0],\n },\n}));\n\nexport interface ResourceTimelineProps<T extends Resource> {\n value: T | Reference<T>;\n loadTimelineResources: (\n medplum: MedplumClient,\n resourceType: ResourceType,\n id: string\n ) => Promise<PromiseSettledResult<Bundle>[]>;\n createCommunication?: (resource: T, sender: ProfileResource, text: string) => Communication;\n createMedia?: (resource: T, operator: ProfileResource, attachment: Attachment) => Media;\n}\n\nexport function ResourceTimeline<T extends Resource>(props: ResourceTimelineProps<T>): JSX.Element {\n const medplum = useMedplum();\n const navigate = useMedplumNavigate();\n const sender = medplum.getProfile() as ProfileResource;\n const inputRef = useRef<HTMLInputElement>(null);\n const resource = useResource(props.value);\n const [history, setHistory] = useState<Bundle>();\n const [items, setItems] = useState<Resource[]>([]);\n const loadTimelineResources = props.loadTimelineResources;\n\n const itemsRef = useRef<Resource[]>(items);\n itemsRef.current = items;\n\n /**\n * Sorts and sets the items.\n *\n * Sorting is primarily a function of meta.lastUpdated, but there are special cases.\n * When displaying connected resources, for example a Communication in the context of an Encounter,\n * the Communication.sent time is used rather than Communication.meta.lastUpdated.\n *\n * Other examples of special cases:\n * - DiagnosticReport.issued\n * - Media.issued\n * - Observation.issued\n * - DocumentReference.date\n *\n * See \"sortByDateAndPriority()\" for more details.\n */\n const sortAndSetItems = useCallback(\n (newItmes: Resource[]): void => {\n sortByDateAndPriority(newItmes, resource);\n newItmes.reverse();\n setItems(newItmes);\n },\n [resource]\n );\n\n /**\n * Handles a batch request response.\n * @param batchResponse The batch response.\n */\n const handleBatchResponse = useCallback(\n (batchResponse: PromiseSettledResult<Bundle>[]): void => {\n const newItems = [];\n\n for (const settledResult of batchResponse) {\n if (settledResult.status !== 'fulfilled') {\n // User may not have access to all resource types\n continue;\n }\n\n const bundle = settledResult.value;\n if (bundle.type === 'history') {\n setHistory(bundle);\n }\n\n if (bundle.entry) {\n for (const entry of bundle.entry) {\n newItems.push(entry.resource as Resource);\n }\n }\n }\n\n sortAndSetItems(newItems);\n },\n [sortAndSetItems]\n );\n\n /**\n * Adds an array of resources to the timeline.\n * @param resource Resource to add.\n */\n const addResource = useCallback(\n (resource: Resource): void => sortAndSetItems([...itemsRef.current, resource]),\n [sortAndSetItems]\n );\n\n /**\n * Loads the timeline.\n */\n const loadTimeline = useCallback(() => {\n let resourceType: ResourceType;\n let id: string;\n if ('resourceType' in props.value) {\n resourceType = props.value.resourceType;\n id = props.value.id as string;\n } else {\n [resourceType, id] = props.value.reference?.split('/') as [ResourceType, string];\n }\n loadTimelineResources(medplum, resourceType, id).then(handleBatchResponse).catch(console.log);\n }, [medplum, props.value, loadTimelineResources, handleBatchResponse]);\n\n useEffect(() => loadTimeline(), [loadTimeline]);\n\n /**\n * Adds a Communication resource to the timeline.\n * @param contentString The comment content.\n */\n function createComment(contentString: string): void {\n if (!resource || !props.createCommunication) {\n // Encounter not loaded yet\n return;\n }\n medplum\n .createResource(props.createCommunication(resource, sender, contentString))\n .then((result) => addResource(result))\n .catch(console.log);\n }\n\n /**\n * Adds a Media resource to the timeline.\n * @param attachment The media attachment.\n */\n function createMedia(attachment: Attachment): void {\n if (!resource || !props.createMedia) {\n // Encounter not loaded yet\n return;\n }\n medplum\n .createResource(props.createMedia(resource, sender, attachment))\n .then((result) => addResource(result))\n .then(() =>\n updateNotification({\n id: 'upload-notification',\n color: 'teal',\n title: 'Upload complete',\n message: '',\n icon: <IconCheck size={16} />,\n autoClose: 2000,\n })\n )\n .catch((reason) =>\n updateNotification({\n id: 'upload-notification',\n color: 'red',\n title: 'Upload error',\n message: normalizeErrorString(reason),\n icon: <IconFileAlert size={16} />,\n autoClose: 2000,\n })\n );\n }\n\n function setPriority(\n communication: Communication,\n priority: 'routine' | 'urgent' | 'asap' | 'stat'\n ): Promise<Communication> {\n return medplum.updateResource({ ...communication, priority });\n }\n\n function onPin(communication: Communication): void {\n setPriority(communication, 'stat').then(loadTimeline).catch(console.log);\n }\n\n function onUnpin(communication: Communication): void {\n setPriority(communication, 'routine').then(loadTimeline).catch(console.log);\n }\n\n function onDetails(timelineItem: Resource): void {\n navigate(`/${timelineItem.resourceType}/${timelineItem.id}`);\n }\n\n function onEdit(timelineItem: Resource): void {\n navigate(`/${timelineItem.resourceType}/${timelineItem.id}/edit`);\n }\n\n function onDelete(timelineItem: Resource): void {\n navigate(`/${timelineItem.resourceType}/${timelineItem.id}/delete`);\n }\n\n function onVersionDetails(version: Resource): void {\n navigate(`/${version.resourceType}/${version.id}/_history/${version.meta?.versionId}`);\n }\n\n function onUploadStart(): void {\n showNotification({\n id: 'upload-notification',\n loading: true,\n title: 'Initializing upload...',\n message: 'Please wait...',\n autoClose: false,\n withCloseButton: false,\n });\n }\n\n function onUploadProgress(e: ProgressEvent): void {\n updateNotification({\n id: 'upload-notification',\n loading: true,\n title: 'Uploading...',\n message: getProgressMessage(e),\n autoClose: false,\n withCloseButton: false,\n });\n }\n\n if (!resource) {\n return (\n <Center style={{ width: '100%', height: '100%' }}>\n <Loader />\n </Center>\n );\n }\n\n return (\n <Timeline>\n {props.createCommunication && (\n <Panel>\n <Form\n testid=\"timeline-form\"\n onSubmit={(formData: Record<string, string>) => {\n createComment(formData.text);\n\n const input = inputRef.current;\n if (input) {\n input.value = '';\n input.focus();\n }\n }}\n >\n <Group spacing=\"xs\" noWrap style={{ width: '100%' }}>\n <ResourceAvatar value={sender} />\n <TextInput\n name=\"text\"\n ref={inputRef}\n placeholder=\"Add comment\"\n style={{ width: '100%', maxWidth: 300 }}\n />\n <ActionIcon type=\"submit\" radius=\"xl\" color=\"blue\" variant=\"filled\">\n <IconMessage size={16} />\n </ActionIcon>\n <AttachmentButton\n onUpload={createMedia}\n onUploadStart={onUploadStart}\n onUploadProgress={onUploadProgress}\n >\n {(props) => (\n <ActionIcon {...props} radius=\"xl\" color=\"blue\" variant=\"filled\">\n <IconCloudUpload size={16} />\n </ActionIcon>\n )}\n </AttachmentButton>\n </Group>\n </Form>\n </Panel>\n )}\n {items.map((item) => {\n if (!item) {\n // TODO: Handle null history items for deleted versions.\n return null;\n }\n const key = `${item.resourceType}/${item.id}/${item.meta?.versionId}`;\n if (item.resourceType === resource.resourceType && item.id === resource.id) {\n return (\n <HistoryTimelineItem\n key={key}\n history={history as Bundle<Resource>}\n resource={item}\n onDetails={onVersionDetails}\n />\n );\n }\n switch (item.resourceType) {\n case 'AuditEvent':\n return <AuditEventTimelineItem key={key} resource={item} onDetails={onDetails} />;\n case 'Communication':\n return (\n <CommunicationTimelineItem\n key={key}\n resource={item}\n onPin={item.priority !== 'stat' ? onPin : undefined}\n onUnpin={item.priority === 'stat' ? onUnpin : undefined}\n onDetails={onDetails}\n onEdit={onEdit}\n onDelete={onDelete}\n />\n );\n case 'DiagnosticReport':\n return (\n <DiagnosticReportTimelineItem\n key={key}\n resource={item}\n onDetails={onDetails}\n onEdit={onEdit}\n onDelete={onDelete}\n />\n );\n case 'Media':\n return (\n <MediaTimelineItem key={key} resource={item} onDetails={onDetails} onEdit={onEdit} onDelete={onDelete} />\n );\n default:\n return (\n <TimelineItem key={key} resource={item} padding={true}>\n <ResourceTable value={item} ignoreMissingValues={true} />\n </TimelineItem>\n );\n }\n })}\n </Timeline>\n );\n}\n\ninterface BaseTimelineItemProps<T extends Resource> {\n resource: T;\n onPin?: (resource: T) => void;\n onUnpin?: (resource: T) => void;\n onDetails?: (resource: T) => void;\n onEdit?: (resource: T) => void;\n onDelete?: (resource: T) => void;\n}\n\nfunction TimelineItemPopupMenu<T extends Resource>(props: BaseTimelineItemProps<T>): JSX.Element {\n return (\n <Menu.Dropdown>\n <Menu.Label>Resource</Menu.Label>\n {props.onPin && (\n <Menu.Item\n icon={<IconPin size={14} />}\n onClick={() => (props.onPin as (resource: T) => void)(props.resource)}\n aria-label={`Pin ${getReferenceString(props.resource)}`}\n >\n Pin\n </Menu.Item>\n )}\n {props.onUnpin && (\n <Menu.Item\n icon={<IconPinnedOff size={14} />}\n onClick={() => (props.onUnpin as (resource: T) => void)(props.resource)}\n aria-label={`Unpin ${getReferenceString(props.resource)}`}\n >\n Unpin\n </Menu.Item>\n )}\n {props.onDetails && (\n <Menu.Item\n icon={<IconListDetails size={14} />}\n onClick={() => (props.onDetails as (resource: T) => void)(props.resource)}\n aria-label={`Details ${getReferenceString(props.resource)}`}\n >\n Details\n </Menu.Item>\n )}\n {props.onEdit && (\n <Menu.Item\n icon={<IconEdit size={14} />}\n onClick={() => (props.onEdit as (resource: T) => void)(props.resource)}\n aria-label={`Edit ${getReferenceString(props.resource)}`}\n >\n Edit\n </Menu.Item>\n )}\n {props.onDelete && (\n <>\n <Menu.Divider />\n <Menu.Label>Danger zone</Menu.Label>\n <Menu.Item\n color=\"red\"\n icon={<IconTrash size={14} />}\n onClick={() => (props.onDelete as (resource: T) => void)(props.resource)}\n aria-label={`Delete ${getReferenceString(props.resource)}`}\n >\n Delete\n </Menu.Item>\n </>\n )}\n </Menu.Dropdown>\n );\n}\n\ninterface HistoryTimelineItemProps extends BaseTimelineItemProps<Resource> {\n history: Bundle;\n}\n\nfunction HistoryTimelineItem(props: HistoryTimelineItemProps): JSX.Element {\n const previous = getPrevious(props.history, props.resource);\n if (previous) {\n return (\n <TimelineItem resource={props.resource} padding={true} popupMenuItems={<TimelineItemPopupMenu {...props} />}>\n <ResourceDiffTable original={previous} revised={props.resource} />\n </TimelineItem>\n );\n } else {\n return (\n <TimelineItem resource={props.resource} padding={true} popupMenuItems={<TimelineItemPopupMenu {...props} />}>\n <h3>Created</h3>\n <ResourceTable value={props.resource} ignoreMissingValues forceUseInput />\n </TimelineItem>\n );\n }\n}\n\nfunction getPrevious(history: Bundle, version: Resource): Resource | undefined {\n const entries = history.entry as BundleEntry[];\n const index = entries.findIndex((entry) => entry.resource?.meta?.versionId === version.meta?.versionId);\n if (index >= entries.length - 1) {\n return undefined;\n }\n return entries[index + 1].resource;\n}\n\nfunction CommunicationTimelineItem(props: BaseTimelineItemProps<Communication>): JSX.Element {\n const { classes } = useStyles();\n const routine = !props.resource.priority || props.resource.priority === 'routine';\n const className = routine ? undefined : classes.pinnedComment;\n return (\n <TimelineItem\n resource={props.resource}\n profile={props.resource.sender}\n dateTime={props.resource.sent}\n padding={true}\n className={className}\n popupMenuItems={<TimelineItemPopupMenu {...props} />}\n >\n <p>{props.resource.payload?.[0]?.contentString}</p>\n </TimelineItem>\n );\n}\n\nfunction MediaTimelineItem(props: BaseTimelineItemProps<Media>): JSX.Element {\n const contentType = props.resource.content?.contentType;\n const padding =\n contentType &&\n !contentType.startsWith('image/') &&\n !contentType.startsWith('video/') &&\n contentType !== 'application/pdf';\n return (\n <TimelineItem resource={props.resource} padding={!!padding} popupMenuItems={<TimelineItemPopupMenu {...props} />}>\n <AttachmentDisplay value={props.resource.content} />\n </TimelineItem>\n );\n}\n\nfunction AuditEventTimelineItem(props: BaseTimelineItemProps<AuditEvent>): JSX.Element {\n return (\n <TimelineItem resource={props.resource} padding={true} popupMenuItems={<TimelineItemPopupMenu {...props} />}>\n <ScrollArea>\n <pre>{props.resource.outcomeDesc}</pre>\n </ScrollArea>\n </TimelineItem>\n );\n}\n\nfunction DiagnosticReportTimelineItem(props: BaseTimelineItemProps<DiagnosticReport>): JSX.Element {\n return (\n <TimelineItem resource={props.resource} padding={true} popupMenuItems={<TimelineItemPopupMenu {...props} />}>\n <DiagnosticReportDisplay value={props.resource} />\n </TimelineItem>\n );\n}\n\nfunction getProgressMessage(e: ProgressEvent): string {\n if (e.lengthComputable) {\n const percent = (100 * e.loaded) / e.total;\n return `Uploaded: ${formatFileSize(e.loaded)} / ${formatFileSize(e.total)} ${percent.toFixed(2)}%`;\n }\n return `Uploaded: ${formatFileSize(e.loaded)}`;\n}\n\nfunction formatFileSize(bytes: number): string {\n if (bytes === 0) {\n return '0.00 B';\n }\n const e = Math.floor(Math.log(bytes) / Math.log(1024));\n return (bytes / Math.pow(1024, e)).toFixed(2) + ' ' + ' KMGTP'.charAt(e) + 'B';\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -93,7 +93,7 @@ function SearchControl(props) {
|
|
|
93
93
|
useEffect(() => {
|
|
94
94
|
setOutcome(undefined);
|
|
95
95
|
medplum
|
|
96
|
-
.search(search.resourceType, formatSearchQuery({ ...search, total: 'estimate', fields: undefined }))
|
|
96
|
+
.search(search.resourceType, formatSearchQuery({ ...search, total: search.total ?? 'estimate', fields: undefined }))
|
|
97
97
|
.then((response) => {
|
|
98
98
|
setState({ ...stateRef.current, searchResponse: response });
|
|
99
99
|
if (onLoad) {
|