@medplum/react 2.0.17 → 2.0.19

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.
Files changed (204) hide show
  1. package/dist/cjs/index.cjs +310 -147
  2. package/dist/cjs/index.cjs.map +1 -1
  3. package/dist/cjs/index.min.cjs +1 -1
  4. package/dist/esm/AppShell/AppShell.mjs +1 -1
  5. package/dist/esm/AppShell/AppShell.mjs.map +1 -1
  6. package/dist/esm/AppShell/Navbar.mjs +90 -32
  7. package/dist/esm/AppShell/Navbar.mjs.map +1 -1
  8. package/dist/esm/BookmarkDialog/BookmarkDialog.mjs +49 -0
  9. package/dist/esm/BookmarkDialog/BookmarkDialog.mjs.map +1 -0
  10. package/dist/esm/DefaultResourceTimeline/DefaultResourceTimeline.mjs +6 -1
  11. package/dist/esm/DefaultResourceTimeline/DefaultResourceTimeline.mjs.map +1 -1
  12. package/dist/esm/PatientTimeline/PatientTimeline.mjs +10 -7
  13. package/dist/esm/PatientTimeline/PatientTimeline.mjs.map +1 -1
  14. package/dist/esm/SearchControl/SearchUtils.mjs +1 -0
  15. package/dist/esm/SearchControl/SearchUtils.mjs.map +1 -1
  16. package/dist/esm/SearchFilterEditor/SearchFilterEditor.mjs +1 -1
  17. package/dist/esm/SearchFilterEditor/SearchFilterEditor.mjs.map +1 -1
  18. package/dist/esm/SearchFilterValueDisplay/SearchFilterValueDisplay.mjs +3 -2
  19. package/dist/esm/SearchFilterValueDisplay/SearchFilterValueDisplay.mjs.map +1 -1
  20. package/dist/esm/ServiceRequestTimeline/ServiceRequestTimeline.mjs +7 -4
  21. package/dist/esm/ServiceRequestTimeline/ServiceRequestTimeline.mjs.map +1 -1
  22. package/dist/esm/ValueSetAutocomplete/ValueSetAutocomplete.mjs +3 -0
  23. package/dist/esm/ValueSetAutocomplete/ValueSetAutocomplete.mjs.map +1 -1
  24. package/dist/esm/auth/AuthenticationForm.mjs +1 -1
  25. package/dist/esm/auth/AuthenticationForm.mjs.map +1 -1
  26. package/dist/esm/index.min.mjs +1 -1
  27. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs +2 -1
  28. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs.map +1 -1
  29. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/defaultAttributes.mjs +1 -1
  30. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/defaultAttributes.mjs.map +1 -1
  31. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconAdjustmentsHorizontal.mjs +2 -1
  32. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconAdjustmentsHorizontal.mjs.map +1 -1
  33. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconAlertCircle.mjs +2 -1
  34. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconAlertCircle.mjs.map +1 -1
  35. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBleach.mjs +2 -1
  36. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBleach.mjs.map +1 -1
  37. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBleachOff.mjs +2 -1
  38. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBleachOff.mjs.map +1 -1
  39. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBoxMultiple.mjs +2 -1
  40. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBoxMultiple.mjs.map +1 -1
  41. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBracketsContain.mjs +2 -1
  42. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBracketsContain.mjs.map +1 -1
  43. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBucket.mjs +2 -1
  44. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBucket.mjs.map +1 -1
  45. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBucketOff.mjs +2 -1
  46. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBucketOff.mjs.map +1 -1
  47. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCalendar.mjs +2 -1
  48. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCalendar.mjs.map +1 -1
  49. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.mjs +2 -1
  50. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.mjs.map +1 -1
  51. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCheckbox.mjs +2 -1
  52. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCheckbox.mjs.map +1 -1
  53. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconChevronDown.mjs +2 -1
  54. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconChevronDown.mjs.map +1 -1
  55. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCircleMinus.mjs +2 -1
  56. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCircleMinus.mjs.map +1 -1
  57. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCirclePlus.mjs +2 -1
  58. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCirclePlus.mjs.map +1 -1
  59. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCloudUpload.mjs +2 -1
  60. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCloudUpload.mjs.map +1 -1
  61. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconColumns.mjs +2 -1
  62. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconColumns.mjs.map +1 -1
  63. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCurrencyDollar.mjs +2 -1
  64. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCurrencyDollar.mjs.map +1 -1
  65. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconDots.mjs +2 -1
  66. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconDots.mjs.map +1 -1
  67. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEdit.mjs +2 -1
  68. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEdit.mjs.map +1 -1
  69. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEqual.mjs +2 -1
  70. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEqual.mjs.map +1 -1
  71. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEqualNot.mjs +2 -1
  72. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEqualNot.mjs.map +1 -1
  73. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFileAlert.mjs +2 -1
  74. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFileAlert.mjs.map +1 -1
  75. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFilePlus.mjs +2 -1
  76. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFilePlus.mjs.map +1 -1
  77. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFilter.mjs +2 -1
  78. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFilter.mjs.map +1 -1
  79. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconListDetails.mjs +2 -1
  80. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconListDetails.mjs.map +1 -1
  81. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconLogout.mjs +4 -2
  82. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconLogout.mjs.map +1 -1
  83. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMathGreater.mjs +2 -1
  84. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMathGreater.mjs.map +1 -1
  85. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMathLower.mjs +2 -1
  86. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMathLower.mjs.map +1 -1
  87. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMessage.mjs +2 -1
  88. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMessage.mjs.map +1 -1
  89. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconPin.mjs +2 -1
  90. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconPin.mjs.map +1 -1
  91. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconPinnedOff.mjs +2 -1
  92. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconPinnedOff.mjs.map +1 -1
  93. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconPlus.mjs +14 -0
  94. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconPlus.mjs.map +1 -0
  95. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSearch.mjs +2 -1
  96. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSearch.mjs.map +1 -1
  97. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSettings.mjs +2 -1
  98. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSettings.mjs.map +1 -1
  99. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSortAscending.mjs +2 -1
  100. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSortAscending.mjs.map +1 -1
  101. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSortDescending.mjs +2 -1
  102. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSortDescending.mjs.map +1 -1
  103. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSquare.mjs +2 -1
  104. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSquare.mjs.map +1 -1
  105. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSwitchHorizontal.mjs +2 -1
  106. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSwitchHorizontal.mjs.map +1 -1
  107. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconTableExport.mjs +2 -1
  108. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconTableExport.mjs.map +1 -1
  109. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconTrash.mjs +2 -1
  110. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconTrash.mjs.map +1 -1
  111. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconX.mjs +2 -1
  112. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconX.mjs.map +1 -1
  113. package/dist/types/AddressDisplay/AddressDisplay.d.ts +1 -0
  114. package/dist/types/AddressInput/AddressInput.d.ts +1 -0
  115. package/dist/types/AnnotationInput/AnnotationInput.d.ts +1 -0
  116. package/dist/types/AppShell/AppShell.d.ts +1 -0
  117. package/dist/types/AppShell/HeaderSearchInput.d.ts +1 -0
  118. package/dist/types/AppShell/Navbar.d.ts +2 -0
  119. package/dist/types/AsyncAutocomplete/AsyncAutocomplete.d.ts +1 -0
  120. package/dist/types/AttachmentArrayDisplay/AttachmentArrayDisplay.d.ts +1 -0
  121. package/dist/types/AttachmentArrayInput/AttachmentArrayInput.d.ts +1 -0
  122. package/dist/types/AttachmentDisplay/AttachmentDisplay.d.ts +1 -0
  123. package/dist/types/AttachmentInput/AttachmentInput.d.ts +1 -0
  124. package/dist/types/BackboneElementDisplay/BackboneElementDisplay.d.ts +1 -0
  125. package/dist/types/BackboneElementInput/BackboneElementInput.d.ts +1 -0
  126. package/dist/types/BookmarkDialog/BookmarkDialog.d.ts +9 -0
  127. package/dist/types/CalendarInput/CalendarInput.d.ts +1 -0
  128. package/dist/types/CodeInput/CodeInput.d.ts +1 -0
  129. package/dist/types/CodeableConceptDisplay/CodeableConceptDisplay.d.ts +1 -0
  130. package/dist/types/CodeableConceptInput/CodeableConceptInput.d.ts +1 -0
  131. package/dist/types/CodingDisplay/CodingDisplay.d.ts +1 -0
  132. package/dist/types/CodingInput/CodingInput.d.ts +1 -0
  133. package/dist/types/ContactDetailDisplay/ContactDetailDisplay.d.ts +1 -0
  134. package/dist/types/ContactDetailInput/ContactDetailInput.d.ts +1 -0
  135. package/dist/types/ContactPointDisplay/ContactPointDisplay.d.ts +1 -0
  136. package/dist/types/ContactPointInput/ContactPointInput.d.ts +1 -0
  137. package/dist/types/Container/Container.d.ts +1 -0
  138. package/dist/types/DateTimeInput/DateTimeInput.d.ts +1 -0
  139. package/dist/types/DefaultResourceTimeline/DefaultResourceTimeline.d.ts +1 -0
  140. package/dist/types/DiagnosticReportDisplay/DiagnosticReportDisplay.d.ts +1 -0
  141. package/dist/types/Document/Document.d.ts +1 -0
  142. package/dist/types/EncounterTimeline/EncounterTimeline.d.ts +1 -0
  143. package/dist/types/ExtensionInput/ExtensionInput.d.ts +1 -0
  144. package/dist/types/FhirPathDisplay/FhirPathDisplay.d.ts +1 -0
  145. package/dist/types/GoogleButton/GoogleButton.d.ts +1 -0
  146. package/dist/types/HumanNameDisplay/HumanNameDisplay.d.ts +1 -0
  147. package/dist/types/HumanNameInput/HumanNameInput.d.ts +1 -0
  148. package/dist/types/IdentifierDisplay/IdentifierDisplay.d.ts +1 -0
  149. package/dist/types/IdentifierInput/IdentifierInput.d.ts +1 -0
  150. package/dist/types/Loading/Loading.d.ts +1 -0
  151. package/dist/types/Logo/Logo.d.ts +1 -0
  152. package/dist/types/MoneyDisplay/MoneyDisplay.d.ts +1 -0
  153. package/dist/types/MoneyInput/MoneyInput.d.ts +1 -0
  154. package/dist/types/NoteDisplay/NoteDisplay.d.ts +1 -0
  155. package/dist/types/OperationOutcomeAlert/OperationOutcomeAlert.d.ts +1 -0
  156. package/dist/types/Panel/Panel.d.ts +1 -0
  157. package/dist/types/PatientTimeline/PatientTimeline.d.ts +1 -0
  158. package/dist/types/PeriodInput/PeriodInput.d.ts +1 -0
  159. package/dist/types/PlanDefinitionBuilder/PlanDefinitionBuilder.d.ts +1 -0
  160. package/dist/types/QuantityDisplay/QuantityDisplay.d.ts +1 -0
  161. package/dist/types/QuantityInput/QuantityInput.d.ts +1 -0
  162. package/dist/types/QuestionnaireBuilder/QuestionnaireBuilder.d.ts +1 -0
  163. package/dist/types/QuestionnaireForm/QuestionnaireForm.d.ts +1 -0
  164. package/dist/types/RangeDisplay/RangeDisplay.d.ts +1 -0
  165. package/dist/types/RangeInput/RangeInput.d.ts +1 -0
  166. package/dist/types/RatioDisplay/RatioDisplay.d.ts +1 -0
  167. package/dist/types/RatioInput/RatioInput.d.ts +1 -0
  168. package/dist/types/ReferenceDisplay/ReferenceDisplay.d.ts +1 -0
  169. package/dist/types/ReferenceInput/ReferenceInput.d.ts +1 -0
  170. package/dist/types/ReferenceRangeEditor/ReferenceRangeEditor.d.ts +1 -0
  171. package/dist/types/RequestGroupDisplay/RequestGroupDisplay.d.ts +1 -0
  172. package/dist/types/ResourceArrayDisplay/ResourceArrayDisplay.d.ts +1 -0
  173. package/dist/types/ResourceArrayInput/ResourceArrayInput.d.ts +1 -0
  174. package/dist/types/ResourceAvatar/ResourceAvatar.d.ts +1 -0
  175. package/dist/types/ResourceBadge/ResourceBadge.d.ts +1 -0
  176. package/dist/types/ResourceBlame/ResourceBlame.d.ts +1 -0
  177. package/dist/types/ResourceDiff/ResourceDiff.d.ts +1 -0
  178. package/dist/types/ResourceDiffTable/ResourceDiffTable.d.ts +1 -0
  179. package/dist/types/ResourceForm/ResourceForm.d.ts +1 -0
  180. package/dist/types/ResourceHistoryTable/ResourceHistoryTable.d.ts +1 -0
  181. package/dist/types/ResourceInput/ResourceInput.d.ts +1 -0
  182. package/dist/types/ResourceName/ResourceName.d.ts +1 -0
  183. package/dist/types/ResourcePropertyDisplay/ResourcePropertyDisplay.d.ts +1 -0
  184. package/dist/types/ResourcePropertyInput/ResourcePropertyInput.d.ts +1 -0
  185. package/dist/types/ResourceTable/ResourceTable.d.ts +1 -0
  186. package/dist/types/ResourceTimeline/ResourceTimeline.d.ts +1 -0
  187. package/dist/types/Scheduler/Scheduler.d.ts +1 -0
  188. package/dist/types/SearchControl/SearchUtils.d.ts +1 -0
  189. package/dist/types/SearchExportDialog/SearchExportDialog.d.ts +1 -0
  190. package/dist/types/SearchFieldEditor/SearchFieldEditor.d.ts +1 -0
  191. package/dist/types/SearchFilterEditor/SearchFilterEditor.d.ts +1 -0
  192. package/dist/types/SearchFilterValueDialog/SearchFilterValueDialog.d.ts +1 -0
  193. package/dist/types/SearchFilterValueDisplay/SearchFilterValueDisplay.d.ts +1 -0
  194. package/dist/types/SearchFilterValueInput/SearchFilterValueInput.d.ts +1 -0
  195. package/dist/types/SearchPopupMenu/SearchPopupMenu.d.ts +1 -0
  196. package/dist/types/ServiceRequestTimeline/ServiceRequestTimeline.d.ts +1 -0
  197. package/dist/types/StatusBadge/StatusBadge.d.ts +1 -0
  198. package/dist/types/TimingInput/TimingInput.d.ts +1 -0
  199. package/dist/types/ValueSetAutocomplete/ValueSetAutocomplete.d.ts +1 -0
  200. package/dist/types/auth/ChooseProfileForm.d.ts +1 -0
  201. package/dist/types/auth/ChooseScopeForm.d.ts +1 -0
  202. package/dist/types/auth/MfaForm.d.ts +1 -0
  203. package/dist/types/auth/NewProjectForm.d.ts +1 -0
  204. package/package.json +13 -13
@@ -28,7 +28,7 @@ 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, { menus: props.menus, closeNavbar: closeNavbar }) : undefined },
31
+ }, padding: 0, fixed: true, header: profile && React.createElement(Header, { logo: props.logo, version: props.version, navbarToggle: toggleNavbar }), navbar: profile && navbarOpen ? (React.createElement(Navbar, { menus: props.menus, closeNavbar: closeNavbar, displayAddBookmark: props.displayAddBookmark })) : undefined },
32
32
  React.createElement(ErrorBoundary, null,
33
33
  React.createElement(Suspense, { fallback: React.createElement(Loading, null) }, props.children))));
34
34
  }
@@ -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 version?: string;\n menus?: NavbarMenu[];\n children: React.ReactNode;\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 logo={props.logo} version={props.version} navbarToggle={toggleNavbar} />}\n navbar={profile && navbarOpen ? <Navbar menus={props.menus} closeNavbar={closeNavbar} /> : undefined}\n >\n <ErrorBoundary>\n <Suspense fallback={<Loading />}>{props.children}</Suspense>\n </ErrorBoundary>\n </MantineAppShell>\n );\n}\n"],"names":["MantineAppShell"],"mappings":";;;;;;;;AAeM,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;SACF,EACD,OAAO,EAAE,CAAC,EACV,KAAK,EAAE,IAAI,EACX,MAAM,EAAE,OAAO,IAAI,KAAA,CAAA,aAAA,CAAC,MAAM,EAAC,EAAA,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,YAAY,EAAE,YAAY,EAAA,CAAI,EACnG,MAAM,EAAE,OAAO,IAAI,UAAU,GAAG,KAAA,CAAA,aAAA,CAAC,MAAM,EAAA,EAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,WAAW,EAAE,WAAW,EAAI,CAAA,GAAG,SAAS,EAAA;AAEpG,QAAA,KAAA,CAAA,aAAA,CAAC,aAAa,EAAA,IAAA;AACZ,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;;;;"}
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 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 logo={props.logo} version={props.version} navbarToggle={toggleNavbar} />}\n navbar={\n profile && navbarOpen ? (\n <Navbar menus={props.menus} closeNavbar={closeNavbar} displayAddBookmark={props.displayAddBookmark} />\n ) : undefined\n }\n >\n <ErrorBoundary>\n <Suspense fallback={<Loading />}>{props.children}</Suspense>\n </ErrorBoundary>\n </MantineAppShell>\n );\n}\n"],"names":["MantineAppShell"],"mappings":";;;;;;;;AAgBM,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,EAAE,OAAO,IAAI,oBAAC,MAAM,EAAA,EAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,YAAY,EAAE,YAAY,EAAI,CAAA,EACnG,MAAM,EACJ,OAAO,IAAI,UAAU,IACnB,KAAA,CAAA,aAAA,CAAC,MAAM,EAAA,EAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,kBAAkB,EAAE,KAAK,CAAC,kBAAkB,EAAI,CAAA,IACpG,SAAS,EAAA;AAGf,QAAA,KAAA,CAAA,aAAA,CAAC,aAAa,EAAA,IAAA;AACZ,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;;;;"}
@@ -1,9 +1,11 @@
1
- import { createStyles, Navbar as Navbar$1, Text, Space } from '@mantine/core';
2
- import React from 'react';
1
+ import { createStyles, Navbar as Navbar$1, ScrollArea, Text, Button, Space } from '@mantine/core';
2
+ import React, { useState } from 'react';
3
3
  import { useLocation, useSearchParams } from 'react-router-dom';
4
+ import { BookmarkDialog } from '../BookmarkDialog/BookmarkDialog.mjs';
4
5
  import { CodeInput } from '../CodeInput/CodeInput.mjs';
5
6
  import { MedplumLink } from '../MedplumLink/MedplumLink.mjs';
6
7
  import { useMedplumNavigate } from '../MedplumProvider/MedplumProvider.mjs';
8
+ import IconPlus from '../node_modules/@tabler/icons-react/dist/esm/icons/IconPlus.mjs';
7
9
 
8
10
  const useStyles = createStyles((theme) => {
9
11
  return {
@@ -54,6 +56,10 @@ const useStyles = createStyles((theme) => {
54
56
  function Navbar(props) {
55
57
  const { classes } = useStyles();
56
58
  const navigate = useMedplumNavigate();
59
+ const location = useLocation();
60
+ const [searchParams] = useSearchParams();
61
+ const activeLink = getActiveLink(location.pathname, searchParams, props.menus);
62
+ const [bookmarkDialogVisible, setBookmarkDialogVisible] = useState(false);
57
63
  function onLinkClick(e, to) {
58
64
  e.stopPropagation();
59
65
  e.preventDefault();
@@ -67,46 +73,98 @@ function Navbar(props) {
67
73
  navigate(`/${resourceType}`);
68
74
  }
69
75
  }
70
- return (React.createElement(Navbar$1, { width: { sm: 250 }, p: "xs" },
71
- React.createElement(Navbar$1.Section, null,
72
- React.createElement(CodeInput, { key: window.location.pathname, name: "resourceType", placeholder: "Resource Type", property: {
73
- binding: {
74
- valueSet: 'http://hl7.org/fhir/ValueSet/resource-types',
75
- },
76
- }, onChange: (newValue) => navigateResourceType(newValue), creatable: false, maxSelectedValues: 0, clearSearchOnChange: true, clearable: false })),
77
- props.menus && (React.createElement(Navbar$1.Section, { grow: true }, props.menus.map((menu) => (React.createElement(React.Fragment, { key: `menu-${menu.title}` },
78
- React.createElement(Text, { className: classes.menuTitle }, menu.title),
79
- menu.links?.map((link) => (React.createElement(NavbarLink, { key: link.href, to: link.href, onClick: (e) => onLinkClick(e, link.href) },
80
- React.createElement(NavLinkIcon, { to: link.href, icon: link.icon }),
81
- React.createElement("span", null, link.label)))))))))));
76
+ return (React.createElement(React.Fragment, null,
77
+ React.createElement(Navbar$1, { width: { sm: 250 }, p: "xs" },
78
+ React.createElement(ScrollArea, null,
79
+ React.createElement(Navbar$1.Section, { mb: "sm" },
80
+ React.createElement(CodeInput, { key: window.location.pathname, name: "resourceType", placeholder: "Resource Type", property: {
81
+ binding: {
82
+ valueSet: 'http://hl7.org/fhir/ValueSet/resource-types',
83
+ },
84
+ }, onChange: (newValue) => navigateResourceType(newValue), creatable: false, maxSelectedValues: 0, clearSearchOnChange: true, clearable: false })),
85
+ React.createElement(Navbar$1.Section, { grow: true },
86
+ props.menus?.map((menu) => (React.createElement(React.Fragment, { key: `menu-${menu.title}` },
87
+ React.createElement(Text, { className: classes.menuTitle }, menu.title),
88
+ menu.links?.map((link) => (React.createElement(NavbarLink, { key: link.href, to: link.href, active: link.href === activeLink?.href, onClick: (e) => onLinkClick(e, link.href) },
89
+ React.createElement(NavLinkIcon, { to: link.href, icon: link.icon }),
90
+ React.createElement("span", null, link.label))))))),
91
+ props.displayAddBookmark && (React.createElement(Button, { variant: "subtle", size: "xs", mt: "xl", leftIcon: React.createElement(IconPlus, { size: "0.75rem" }), onClick: () => setBookmarkDialogVisible(true) }, "Add Bookmark"))))),
92
+ React.createElement(BookmarkDialog, { visible: bookmarkDialogVisible, onOk: () => setBookmarkDialogVisible(false), onCancel: () => setBookmarkDialogVisible(false) })));
82
93
  }
83
94
  function NavbarLink(props) {
84
95
  const { classes, cx } = useStyles();
85
- const location = useLocation();
86
- const [searchParams] = useSearchParams();
87
- const toUrl = new URL(props.to, window.location.protocol + '//' + window.location.host);
88
- const isActive = location.pathname === toUrl.pathname && matchesParams(searchParams, toUrl);
89
- return (React.createElement(MedplumLink, { onClick: props.onClick, to: props.to, className: cx(classes.link, { [classes.linkActive]: isActive }) }, props.children));
96
+ return (React.createElement(MedplumLink, { onClick: props.onClick, to: props.to, className: cx(classes.link, { [classes.linkActive]: props.active }) }, props.children));
97
+ }
98
+ function NavLinkIcon(props) {
99
+ if (props.icon) {
100
+ return props.icon;
101
+ }
102
+ return React.createElement(Space, { w: 30 });
90
103
  }
91
104
  /**
92
- * Returns true if the search params match.
93
- * @param searchParams The current search params.
94
- * @param toUrl The destination URL of the link.
95
- * @returns True if the search params match.
105
+ * Returns the best "active" link for the menu.
106
+ * In most cases, the navbar links are simple, and an exact match can determine which link is active.
107
+ * However, we ignore some search parameters to support pagination.
108
+ * But we cannot ignore all search parameters, to support separate links based on search filters.
109
+ * So in the end, we use a simple scoring system based on the number of matching query search params.
110
+ * @param currentPathname The web browser current pathname.
111
+ * @param currentSearchParams The web browser current search parameters.
112
+ * @param menus Collection of navbar menus and links.
113
+ * @returns The active link if one is found.
96
114
  */
97
- function matchesParams(searchParams, toUrl) {
98
- for (const [key, value] of toUrl.searchParams.entries()) {
99
- if (searchParams.get(key) !== value) {
100
- return false;
115
+ function getActiveLink(currentPathname, currentSearchParams, menus) {
116
+ let bestLink = undefined;
117
+ let bestScore = 0;
118
+ if (menus) {
119
+ for (const menu of menus) {
120
+ if (menu.links) {
121
+ for (const link of menu.links) {
122
+ const score = getLinkScore(currentPathname, currentSearchParams, link.href);
123
+ if (score > bestScore) {
124
+ bestScore = score;
125
+ bestLink = link;
126
+ }
127
+ }
128
+ }
101
129
  }
102
130
  }
103
- return true;
131
+ return bestLink;
104
132
  }
105
- function NavLinkIcon(props) {
106
- if (props.icon) {
107
- return props.icon;
133
+ /**
134
+ * Calculates a score for a link.
135
+ * Zero means "does not match at all".
136
+ * One means "matches the pathname only".
137
+ * Additional increases for each matching search parameter.
138
+ * Ignores pagination parameters "_count" and "_offset".
139
+ * @param currentPathname The web browser current pathname.
140
+ * @param currentSearchParams The web browser current search parameters.
141
+ * @param linkHref A candidate link href.
142
+ * @returns The link score.
143
+ */
144
+ function getLinkScore(currentPathname, currentSearchParams, linkHref) {
145
+ const linkUrl = new URL(linkHref, 'https://example.com');
146
+ if (currentPathname !== linkUrl.pathname) {
147
+ return 0;
108
148
  }
109
- return React.createElement(Space, { w: 30 });
149
+ const ignoredParams = ['_count', '_offset'];
150
+ for (const [key, value] of linkUrl.searchParams.entries()) {
151
+ if (ignoredParams.includes(key)) {
152
+ continue;
153
+ }
154
+ if (currentSearchParams.get(key) !== value) {
155
+ return 0;
156
+ }
157
+ }
158
+ let count = 1;
159
+ for (const [key, value] of currentSearchParams.entries()) {
160
+ if (ignoredParams.includes(key)) {
161
+ continue;
162
+ }
163
+ if (linkUrl.searchParams.get(key) === value) {
164
+ count++;
165
+ }
166
+ }
167
+ return count;
110
168
  }
111
169
 
112
170
  export { Navbar };
@@ -1 +1 @@
1
- {"version":3,"file":"Navbar.mjs","sources":["../../../src/AppShell/Navbar.tsx"],"sourcesContent":["import { createStyles, Navbar as MantineNavbar, Space, Text } from '@mantine/core';\nimport React from 'react';\nimport { useLocation, useSearchParams } from 'react-router-dom';\nimport { CodeInput } from '../CodeInput/CodeInput';\nimport { MedplumLink } from '../MedplumLink/MedplumLink';\nimport { useMedplumNavigate } from '../MedplumProvider/MedplumProvider';\n\nconst useStyles = createStyles((theme) => {\n return {\n menuTitle: {\n margin: '20px 0 4px 6px',\n fontSize: '9px',\n fontWeight: 'normal',\n textTransform: 'uppercase',\n letterSpacing: '2px',\n },\n\n link: {\n ...theme.fn.focusStyles(),\n display: 'flex',\n alignItems: 'center',\n textDecoration: 'none',\n fontSize: theme.fontSizes.sm,\n color: theme.colorScheme === 'dark' ? theme.colors.dark[1] : theme.colors.gray[7],\n padding: `8px 12px`,\n borderRadius: theme.radius.sm,\n fontWeight: 500,\n\n '&:hover': {\n backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[0],\n color: theme.colorScheme === 'dark' ? theme.white : theme.black,\n textDecoration: 'none',\n\n [`& svg`]: {\n color: theme.colorScheme === 'dark' ? theme.white : theme.black,\n },\n },\n\n '& svg': {\n color: theme.colorScheme === 'dark' ? theme.colors.dark[2] : theme.colors.gray[6],\n marginRight: theme.spacing.sm,\n strokeWidth: 1.5,\n width: 18,\n height: 18,\n },\n },\n\n linkActive: {\n '&, &:hover': {\n backgroundColor: theme.fn.variant({ variant: 'light', color: theme.primaryColor }).background,\n color: theme.fn.variant({ variant: 'light', color: theme.primaryColor }).color,\n [`& svg`]: {\n color: theme.fn.variant({ variant: 'light', color: theme.primaryColor }).color,\n },\n },\n },\n };\n});\n\nexport interface NavbarLink {\n icon?: JSX.Element;\n label?: string;\n href: string;\n}\n\nexport interface NavbarMenu {\n title?: string;\n links?: NavbarLink[];\n}\n\nexport interface NavbarProps {\n menus?: NavbarMenu[];\n closeNavbar: () => void;\n}\n\nexport function Navbar(props: NavbarProps): JSX.Element {\n const { classes } = useStyles();\n const navigate = useMedplumNavigate();\n\n function onLinkClick(e: React.SyntheticEvent, to: string): void {\n e.stopPropagation();\n e.preventDefault();\n navigate(to);\n if (window.innerWidth < 768) {\n props.closeNavbar();\n }\n }\n\n function navigateResourceType(resourceType: string | undefined): void {\n if (resourceType) {\n navigate(`/${resourceType}`);\n }\n }\n\n return (\n <MantineNavbar width={{ sm: 250 }} p=\"xs\">\n <MantineNavbar.Section>\n <CodeInput\n key={window.location.pathname}\n name=\"resourceType\"\n placeholder=\"Resource Type\"\n property={{\n binding: {\n valueSet: 'http://hl7.org/fhir/ValueSet/resource-types',\n },\n }}\n onChange={(newValue) => navigateResourceType(newValue)}\n creatable={false}\n maxSelectedValues={0}\n clearSearchOnChange={true}\n clearable={false}\n />\n </MantineNavbar.Section>\n {props.menus && (\n <MantineNavbar.Section grow>\n {props.menus.map((menu) => (\n <React.Fragment key={`menu-${menu.title}`}>\n <Text className={classes.menuTitle}>{menu.title}</Text>\n {menu.links?.map((link) => (\n <NavbarLink key={link.href} to={link.href} onClick={(e) => onLinkClick(e, link.href)}>\n <NavLinkIcon to={link.href} icon={link.icon} />\n <span>{link.label}</span>\n </NavbarLink>\n ))}\n </React.Fragment>\n ))}\n </MantineNavbar.Section>\n )}\n </MantineNavbar>\n );\n}\n\ninterface NavbarLinkProps {\n to: string;\n onClick: React.MouseEventHandler;\n children: React.ReactNode;\n}\n\nfunction NavbarLink(props: NavbarLinkProps): JSX.Element {\n const { classes, cx } = useStyles();\n const location = useLocation();\n const [searchParams] = useSearchParams();\n const toUrl = new URL(props.to, window.location.protocol + '//' + window.location.host);\n const isActive = location.pathname === toUrl.pathname && matchesParams(searchParams, toUrl);\n\n return (\n <MedplumLink onClick={props.onClick} to={props.to} className={cx(classes.link, { [classes.linkActive]: isActive })}>\n {props.children}\n </MedplumLink>\n );\n}\n\n/**\n * Returns true if the search params match.\n * @param searchParams The current search params.\n * @param toUrl The destination URL of the link.\n * @returns True if the search params match.\n */\nfunction matchesParams(searchParams: URLSearchParams, toUrl: URL): boolean {\n for (const [key, value] of toUrl.searchParams.entries()) {\n if (searchParams.get(key) !== value) {\n return false;\n }\n }\n return true;\n}\n\ninterface NavLinkIconProps {\n to: string;\n icon?: JSX.Element;\n}\n\nfunction NavLinkIcon(props: NavLinkIconProps): JSX.Element {\n if (props.icon) {\n return props.icon;\n }\n return <Space w={30} />;\n}\n"],"names":["MantineNavbar"],"mappings":"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"}
1
+ {"version":3,"file":"Navbar.mjs","sources":["../../../src/AppShell/Navbar.tsx"],"sourcesContent":["import { Button, createStyles, Navbar as MantineNavbar, ScrollArea, Space, Text } from '@mantine/core';\nimport { IconPlus } from '@tabler/icons-react';\nimport React, { useState } from 'react';\nimport { useLocation, useSearchParams } from 'react-router-dom';\nimport { BookmarkDialog } from '../BookmarkDialog/BookmarkDialog';\nimport { CodeInput } from '../CodeInput/CodeInput';\nimport { MedplumLink } from '../MedplumLink/MedplumLink';\nimport { useMedplumNavigate } from '../MedplumProvider/MedplumProvider';\n\nconst useStyles = createStyles((theme) => {\n return {\n menuTitle: {\n margin: '20px 0 4px 6px',\n fontSize: '9px',\n fontWeight: 'normal',\n textTransform: 'uppercase',\n letterSpacing: '2px',\n },\n\n link: {\n ...theme.fn.focusStyles(),\n display: 'flex',\n alignItems: 'center',\n textDecoration: 'none',\n fontSize: theme.fontSizes.sm,\n color: theme.colorScheme === 'dark' ? theme.colors.dark[1] : theme.colors.gray[7],\n padding: `8px 12px`,\n borderRadius: theme.radius.sm,\n fontWeight: 500,\n\n '&:hover': {\n backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[0],\n color: theme.colorScheme === 'dark' ? theme.white : theme.black,\n textDecoration: 'none',\n\n [`& svg`]: {\n color: theme.colorScheme === 'dark' ? theme.white : theme.black,\n },\n },\n\n '& svg': {\n color: theme.colorScheme === 'dark' ? theme.colors.dark[2] : theme.colors.gray[6],\n marginRight: theme.spacing.sm,\n strokeWidth: 1.5,\n width: 18,\n height: 18,\n },\n },\n\n linkActive: {\n '&, &:hover': {\n backgroundColor: theme.fn.variant({ variant: 'light', color: theme.primaryColor }).background,\n color: theme.fn.variant({ variant: 'light', color: theme.primaryColor }).color,\n [`& svg`]: {\n color: theme.fn.variant({ variant: 'light', color: theme.primaryColor }).color,\n },\n },\n },\n };\n});\n\nexport interface NavbarLink {\n icon?: JSX.Element;\n label?: string;\n href: string;\n}\n\nexport interface NavbarMenu {\n title?: string;\n links?: NavbarLink[];\n}\n\nexport interface NavbarProps {\n menus?: NavbarMenu[];\n closeNavbar: () => void;\n displayAddBookmark?: boolean;\n}\n\nexport function Navbar(props: NavbarProps): JSX.Element {\n const { classes } = useStyles();\n const navigate = useMedplumNavigate();\n const location = useLocation();\n const [searchParams] = useSearchParams();\n const activeLink = getActiveLink(location.pathname, searchParams, props.menus);\n const [bookmarkDialogVisible, setBookmarkDialogVisible] = useState(false);\n\n function onLinkClick(e: React.SyntheticEvent, to: string): void {\n e.stopPropagation();\n e.preventDefault();\n navigate(to);\n if (window.innerWidth < 768) {\n props.closeNavbar();\n }\n }\n\n function navigateResourceType(resourceType: string | undefined): void {\n if (resourceType) {\n navigate(`/${resourceType}`);\n }\n }\n\n return (\n <>\n <MantineNavbar width={{ sm: 250 }} p=\"xs\">\n <ScrollArea>\n <MantineNavbar.Section mb=\"sm\">\n <CodeInput\n key={window.location.pathname}\n name=\"resourceType\"\n placeholder=\"Resource Type\"\n property={{\n binding: {\n valueSet: 'http://hl7.org/fhir/ValueSet/resource-types',\n },\n }}\n onChange={(newValue) => navigateResourceType(newValue)}\n creatable={false}\n maxSelectedValues={0}\n clearSearchOnChange={true}\n clearable={false}\n />\n </MantineNavbar.Section>\n <MantineNavbar.Section grow>\n {props.menus?.map((menu) => (\n <React.Fragment key={`menu-${menu.title}`}>\n <Text className={classes.menuTitle}>{menu.title}</Text>\n {menu.links?.map((link) => (\n <NavbarLink\n key={link.href}\n to={link.href}\n active={link.href === activeLink?.href}\n onClick={(e) => onLinkClick(e, link.href)}\n >\n <NavLinkIcon to={link.href} icon={link.icon} />\n <span>{link.label}</span>\n </NavbarLink>\n ))}\n </React.Fragment>\n ))}\n {props.displayAddBookmark && (\n <Button\n variant=\"subtle\"\n size=\"xs\"\n mt=\"xl\"\n leftIcon={<IconPlus size=\"0.75rem\" />}\n onClick={() => setBookmarkDialogVisible(true)}\n >\n Add Bookmark\n </Button>\n )}\n </MantineNavbar.Section>\n </ScrollArea>\n </MantineNavbar>\n <BookmarkDialog\n visible={bookmarkDialogVisible}\n onOk={() => setBookmarkDialogVisible(false)}\n onCancel={() => setBookmarkDialogVisible(false)}\n />\n </>\n );\n}\n\ninterface NavbarLinkProps {\n to: string;\n active: boolean;\n onClick: React.MouseEventHandler;\n children: React.ReactNode;\n}\n\nfunction NavbarLink(props: NavbarLinkProps): JSX.Element {\n const { classes, cx } = useStyles();\n return (\n <MedplumLink\n onClick={props.onClick}\n to={props.to}\n className={cx(classes.link, { [classes.linkActive]: props.active })}\n >\n {props.children}\n </MedplumLink>\n );\n}\n\ninterface NavLinkIconProps {\n to: string;\n icon?: JSX.Element;\n}\n\nfunction NavLinkIcon(props: NavLinkIconProps): JSX.Element {\n if (props.icon) {\n return props.icon;\n }\n return <Space w={30} />;\n}\n\n/**\n * Returns the best \"active\" link for the menu.\n * In most cases, the navbar links are simple, and an exact match can determine which link is active.\n * However, we ignore some search parameters to support pagination.\n * But we cannot ignore all search parameters, to support separate links based on search filters.\n * So in the end, we use a simple scoring system based on the number of matching query search params.\n * @param currentPathname The web browser current pathname.\n * @param currentSearchParams The web browser current search parameters.\n * @param menus Collection of navbar menus and links.\n * @returns The active link if one is found.\n */\nfunction getActiveLink(\n currentPathname: string,\n currentSearchParams: URLSearchParams,\n menus: NavbarMenu[] | undefined\n): NavbarLink | undefined {\n let bestLink = undefined;\n let bestScore = 0;\n\n if (menus) {\n for (const menu of menus) {\n if (menu.links) {\n for (const link of menu.links) {\n const score = getLinkScore(currentPathname, currentSearchParams, link.href);\n if (score > bestScore) {\n bestScore = score;\n bestLink = link;\n }\n }\n }\n }\n }\n\n return bestLink;\n}\n\n/**\n * Calculates a score for a link.\n * Zero means \"does not match at all\".\n * One means \"matches the pathname only\".\n * Additional increases for each matching search parameter.\n * Ignores pagination parameters \"_count\" and \"_offset\".\n * @param currentPathname The web browser current pathname.\n * @param currentSearchParams The web browser current search parameters.\n * @param linkHref A candidate link href.\n * @returns The link score.\n */\nfunction getLinkScore(currentPathname: string, currentSearchParams: URLSearchParams, linkHref: string): number {\n const linkUrl = new URL(linkHref, 'https://example.com');\n if (currentPathname !== linkUrl.pathname) {\n return 0;\n }\n const ignoredParams = ['_count', '_offset'];\n for (const [key, value] of linkUrl.searchParams.entries()) {\n if (ignoredParams.includes(key)) {\n continue;\n }\n if (currentSearchParams.get(key) !== value) {\n return 0;\n }\n }\n let count = 1;\n for (const [key, value] of currentSearchParams.entries()) {\n if (ignoredParams.includes(key)) {\n continue;\n }\n if (linkUrl.searchParams.get(key) === value) {\n count++;\n }\n }\n return count;\n}\n"],"names":["MantineNavbar"],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ import { Modal, Stack, TextInput, Group, Button, NativeSelect } from '@mantine/core';
2
+ import { showNotification } from '@mantine/notifications';
3
+ import { deepClone, normalizeErrorString } from '@medplum/core';
4
+ import React from 'react';
5
+ import { useLocation } from 'react-router-dom';
6
+ import { Form } from '../Form/Form.mjs';
7
+ import { useMedplum } from '../MedplumProvider/MedplumProvider.mjs';
8
+
9
+ function BookmarkDialog(props) {
10
+ const medplum = useMedplum();
11
+ const config = medplum.getUserConfiguration();
12
+ const location = useLocation();
13
+ function submitHandler(formData) {
14
+ const { menuname, bookmarkname: name } = formData;
15
+ const target = location.pathname + location.search;
16
+ const newConfig = deepClone(config);
17
+ const menu = newConfig?.menu?.find(({ title }) => title === menuname);
18
+ menu?.link?.push({ name, target });
19
+ medplum
20
+ .updateResource(newConfig)
21
+ .then((res) => {
22
+ // refresh current config menu
23
+ config.menu = res.menu;
24
+ medplum.dispatchEvent({ type: 'change' });
25
+ showNotification({ color: 'green', message: 'Success' });
26
+ props.onOk();
27
+ })
28
+ .catch((err) => {
29
+ showNotification({ color: 'red', message: normalizeErrorString(err) });
30
+ });
31
+ }
32
+ return (React.createElement(Modal, { title: "Add Bookmark", closeButtonProps: { 'aria-label': 'Close' }, opened: props.visible, onClose: props.onCancel },
33
+ React.createElement(Form, { onSubmit: submitHandler },
34
+ React.createElement(Stack, null,
35
+ React.createElement(SelectMenu, { config: config }),
36
+ React.createElement(TextInput, { label: "Bookmark Name", type: "text", name: "bookmarkname", placeholder: "bookmark name", withAsterisk: true }),
37
+ React.createElement(Group, { position: "right" },
38
+ React.createElement(Button, { mt: "sm", type: "submit" }, "OK"))))));
39
+ }
40
+ function SelectMenu(props) {
41
+ function userConfigToMenu(config) {
42
+ return config?.menu?.map((menu) => menu.title);
43
+ }
44
+ const menus = userConfigToMenu(props.config);
45
+ return (React.createElement(NativeSelect, { name: "menuname", defaultValue: menus?.[0], label: "Select Menu Option", placeholder: "Menu", data: menus, withAsterisk: true }));
46
+ }
47
+
48
+ export { BookmarkDialog };
49
+ //# sourceMappingURL=BookmarkDialog.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BookmarkDialog.mjs","sources":["../../../src/BookmarkDialog/BookmarkDialog.tsx"],"sourcesContent":["import { Button, Group, Modal, NativeSelect, Stack, TextInput } from '@mantine/core';\nimport { showNotification } from '@mantine/notifications';\nimport { deepClone, normalizeErrorString } from '@medplum/core';\nimport { UserConfiguration } from '@medplum/fhirtypes';\nimport React from 'react';\nimport { useLocation } from 'react-router-dom';\nimport { Form } from '../Form/Form';\nimport { useMedplum } from '../MedplumProvider/MedplumProvider';\n\ninterface BookmarkDialogProps {\n visible: boolean;\n onOk: () => void;\n onCancel: () => void;\n defaultValue?: string;\n}\nexport function BookmarkDialog(props: BookmarkDialogProps): JSX.Element | null {\n const medplum = useMedplum();\n const config = medplum.getUserConfiguration() as UserConfiguration;\n const location = useLocation();\n function submitHandler(formData: Record<string, string>): void {\n const { menuname, bookmarkname: name } = formData;\n const target = location.pathname + location.search;\n const newConfig = deepClone(config) as UserConfiguration;\n const menu = newConfig?.menu?.find(({ title }) => title === menuname);\n\n menu?.link?.push({ name, target });\n medplum\n .updateResource(newConfig)\n .then((res) => {\n // refresh current config menu\n config.menu = res.menu;\n medplum.dispatchEvent({ type: 'change' });\n showNotification({ color: 'green', message: 'Success' });\n props.onOk();\n })\n .catch((err: any) => {\n showNotification({ color: 'red', message: normalizeErrorString(err) });\n });\n }\n\n return (\n <Modal\n title=\"Add Bookmark\"\n closeButtonProps={{ 'aria-label': 'Close' }}\n opened={props.visible}\n onClose={props.onCancel}\n >\n <Form onSubmit={submitHandler}>\n <Stack>\n <SelectMenu config={config}></SelectMenu>\n <TextInput label=\"Bookmark Name\" type=\"text\" name=\"bookmarkname\" placeholder=\"bookmark name\" withAsterisk />\n <Group position=\"right\">\n <Button mt=\"sm\" type=\"submit\">\n OK\n </Button>\n </Group>\n </Stack>\n </Form>\n </Modal>\n );\n}\n\ninterface SelectMenuProps {\n config: UserConfiguration | undefined;\n}\n\nfunction SelectMenu(props: SelectMenuProps): JSX.Element {\n function userConfigToMenu(config: UserConfiguration | undefined): string[] {\n return config?.menu?.map((menu) => menu.title) as [];\n }\n const menus = userConfigToMenu(props.config);\n\n return (\n <NativeSelect\n name=\"menuname\"\n defaultValue={menus?.[0]}\n label=\"Select Menu Option\"\n placeholder=\"Menu\"\n data={menus}\n withAsterisk\n />\n );\n}\n"],"names":[],"mappings":"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"}
@@ -3,7 +3,12 @@ import { ResourceTimeline } from '../ResourceTimeline/ResourceTimeline.mjs';
3
3
 
4
4
  function DefaultResourceTimeline(props) {
5
5
  return (React.createElement(ResourceTimeline, { value: props.resource, loadTimelineResources: async (medplum, resourceType, id) => {
6
- return Promise.allSettled([medplum.readHistory(resourceType, id)]);
6
+ const ref = `${resourceType}/${id}`;
7
+ const _count = 100;
8
+ return Promise.allSettled([
9
+ medplum.readHistory(resourceType, id),
10
+ medplum.search('Task', { _filter: `based-on eq ${ref} or focus eq ${ref} or subject eq ${ref}`, _count }),
11
+ ]);
7
12
  } }));
8
13
  }
9
14
 
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultResourceTimeline.mjs","sources":["../../../src/DefaultResourceTimeline/DefaultResourceTimeline.tsx"],"sourcesContent":["import { MedplumClient } from '@medplum/core';\nimport { Reference, Resource, ResourceType } from '@medplum/fhirtypes';\nimport React from 'react';\nimport { ResourceTimeline } from '../ResourceTimeline/ResourceTimeline';\n\nexport interface DefaultResourceTimelineProps {\n resource: Resource | Reference;\n}\n\nexport function DefaultResourceTimeline(props: DefaultResourceTimelineProps): JSX.Element {\n return (\n <ResourceTimeline\n value={props.resource}\n loadTimelineResources={async (medplum: MedplumClient, resourceType: ResourceType, id: string) => {\n return Promise.allSettled([medplum.readHistory(resourceType, id)]);\n }}\n />\n );\n}\n"],"names":[],"mappings":";;;AASM,SAAU,uBAAuB,CAAC,KAAmC,EAAA;IACzE,QACE,oBAAC,gBAAgB,EAAA,EACf,KAAK,EAAE,KAAK,CAAC,QAAQ,EACrB,qBAAqB,EAAE,OAAO,OAAsB,EAAE,YAA0B,EAAE,EAAU,KAAI;AAC9F,YAAA,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;SACpE,EAAA,CACD,EACF;AACJ;;;;"}
1
+ {"version":3,"file":"DefaultResourceTimeline.mjs","sources":["../../../src/DefaultResourceTimeline/DefaultResourceTimeline.tsx"],"sourcesContent":["import { MedplumClient } from '@medplum/core';\nimport { Reference, Resource, ResourceType } from '@medplum/fhirtypes';\nimport React from 'react';\nimport { ResourceTimeline } from '../ResourceTimeline/ResourceTimeline';\n\nexport interface DefaultResourceTimelineProps {\n resource: Resource | Reference;\n}\n\nexport function DefaultResourceTimeline(props: DefaultResourceTimelineProps): JSX.Element {\n return (\n <ResourceTimeline\n value={props.resource}\n loadTimelineResources={async (medplum: MedplumClient, resourceType: ResourceType, id: string) => {\n const ref = `${resourceType}/${id}`;\n const _count = 100;\n return Promise.allSettled([\n medplum.readHistory(resourceType, id),\n medplum.search('Task', { _filter: `based-on eq ${ref} or focus eq ${ref} or subject eq ${ref}`, _count }),\n ]);\n }}\n />\n );\n}\n"],"names":[],"mappings":";;;AASM,SAAU,uBAAuB,CAAC,KAAmC,EAAA;IACzE,QACE,oBAAC,gBAAgB,EAAA,EACf,KAAK,EAAE,KAAK,CAAC,QAAQ,EACrB,qBAAqB,EAAE,OAAO,OAAsB,EAAE,YAA0B,EAAE,EAAU,KAAI;AAC9F,YAAA,MAAM,GAAG,GAAG,CAAA,EAAG,YAAY,CAAI,CAAA,EAAA,EAAE,EAAE,CAAC;YACpC,MAAM,MAAM,GAAG,GAAG,CAAC;YACnB,OAAO,OAAO,CAAC,UAAU,CAAC;AACxB,gBAAA,OAAO,CAAC,WAAW,CAAC,YAAY,EAAE,EAAE,CAAC;AACrC,gBAAA,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAA,YAAA,EAAe,GAAG,CAAA,aAAA,EAAgB,GAAG,CAAkB,eAAA,EAAA,GAAG,EAAE,EAAE,MAAM,EAAE,CAAC;AAC1G,aAAA,CAAC,CAAC;SACJ,EAAA,CACD,EACF;AACJ;;;;"}
@@ -3,15 +3,18 @@ import React, { useCallback } from 'react';
3
3
  import { ResourceTimeline } from '../ResourceTimeline/ResourceTimeline.mjs';
4
4
 
5
5
  function PatientTimeline(props) {
6
- const loadTimelineResources = useCallback((medplum, _resourceType, id) => {
6
+ const loadTimelineResources = useCallback((medplum, resourceType, id) => {
7
+ const ref = `${resourceType}/${id}`;
8
+ const _count = 100;
7
9
  return Promise.allSettled([
8
10
  medplum.readHistory('Patient', id),
9
- medplum.search('Communication', 'subject=Patient/' + id),
10
- medplum.search('Device', 'patient=Patient/' + id),
11
- medplum.search('DeviceRequest', 'patient=Patient/' + id),
12
- medplum.search('DiagnosticReport', 'subject=Patient/' + id),
13
- medplum.search('Media', 'subject=Patient/' + id),
14
- medplum.search('ServiceRequest', 'subject=Patient/' + id),
11
+ medplum.search('Communication', { subject: ref, _count }),
12
+ medplum.search('Device', { patient: ref, _count }),
13
+ medplum.search('DeviceRequest', { patient: ref, _count }),
14
+ medplum.search('DiagnosticReport', { subject: ref, _count }),
15
+ medplum.search('Media', { subject: ref, _count }),
16
+ medplum.search('ServiceRequest', { subject: ref, _count }),
17
+ medplum.search('Task', { subject: ref, _count }),
15
18
  ]);
16
19
  }, []);
17
20
  return (React.createElement(ResourceTimeline, { value: props.patient, loadTimelineResources: loadTimelineResources, createCommunication: (resource, sender, text) => ({
@@ -1 +1 @@
1
- {"version":3,"file":"PatientTimeline.mjs","sources":["../../../src/PatientTimeline/PatientTimeline.tsx"],"sourcesContent":["import { createReference, MedplumClient, ProfileResource } from '@medplum/core';\nimport { Attachment, Patient, Reference, ResourceType } from '@medplum/fhirtypes';\nimport React, { useCallback } from 'react';\nimport { ResourceTimeline } from '../ResourceTimeline/ResourceTimeline';\n\nexport interface PatientTimelineProps {\n patient: Patient | Reference<Patient>;\n}\n\nexport function PatientTimeline(props: PatientTimelineProps): JSX.Element {\n const loadTimelineResources = useCallback((medplum: MedplumClient, _resourceType: ResourceType, id: string) => {\n return Promise.allSettled([\n medplum.readHistory('Patient', id),\n medplum.search('Communication', 'subject=Patient/' + id),\n medplum.search('Device', 'patient=Patient/' + id),\n medplum.search('DeviceRequest', 'patient=Patient/' + id),\n medplum.search('DiagnosticReport', 'subject=Patient/' + id),\n medplum.search('Media', 'subject=Patient/' + id),\n medplum.search('ServiceRequest', 'subject=Patient/' + id),\n ]);\n }, []);\n\n return (\n <ResourceTimeline\n value={props.patient}\n loadTimelineResources={loadTimelineResources}\n createCommunication={(resource: Patient, sender: ProfileResource, text: string) => ({\n resourceType: 'Communication',\n status: 'completed',\n subject: createReference(resource),\n sender: createReference(sender),\n sent: new Date().toISOString(),\n payload: [{ contentString: text }],\n })}\n createMedia={(resource: Patient, operator: ProfileResource, content: Attachment) => ({\n resourceType: 'Media',\n status: 'completed',\n subject: createReference(resource),\n operator: createReference(operator),\n issued: new Date().toISOString(),\n content,\n })}\n />\n );\n}\n"],"names":[],"mappings":";;;;AASM,SAAU,eAAe,CAAC,KAA2B,EAAA;IACzD,MAAM,qBAAqB,GAAG,WAAW,CAAC,CAAC,OAAsB,EAAE,aAA2B,EAAE,EAAU,KAAI;QAC5G,OAAO,OAAO,CAAC,UAAU,CAAC;AACxB,YAAA,OAAO,CAAC,WAAW,CAAC,SAAS,EAAE,EAAE,CAAC;YAClC,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,kBAAkB,GAAG,EAAE,CAAC;YACxD,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,kBAAkB,GAAG,EAAE,CAAC;YACjD,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,kBAAkB,GAAG,EAAE,CAAC;YACxD,OAAO,CAAC,MAAM,CAAC,kBAAkB,EAAE,kBAAkB,GAAG,EAAE,CAAC;YAC3D,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,kBAAkB,GAAG,EAAE,CAAC;YAChD,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,kBAAkB,GAAG,EAAE,CAAC;AAC1D,SAAA,CAAC,CAAC;KACJ,EAAE,EAAE,CAAC,CAAC;IAEP,QACE,KAAC,CAAA,aAAA,CAAA,gBAAgB,EACf,EAAA,KAAK,EAAE,KAAK,CAAC,OAAO,EACpB,qBAAqB,EAAE,qBAAqB,EAC5C,mBAAmB,EAAE,CAAC,QAAiB,EAAE,MAAuB,EAAE,IAAY,MAAM;AAClF,YAAA,YAAY,EAAE,eAAe;AAC7B,YAAA,MAAM,EAAE,WAAW;AACnB,YAAA,OAAO,EAAE,eAAe,CAAC,QAAQ,CAAC;AAClC,YAAA,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC;AAC/B,YAAA,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;AAC9B,YAAA,OAAO,EAAE,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;AACnC,SAAA,CAAC,EACF,WAAW,EAAE,CAAC,QAAiB,EAAE,QAAyB,EAAE,OAAmB,MAAM;AACnF,YAAA,YAAY,EAAE,OAAO;AACrB,YAAA,MAAM,EAAE,WAAW;AACnB,YAAA,OAAO,EAAE,eAAe,CAAC,QAAQ,CAAC;AAClC,YAAA,QAAQ,EAAE,eAAe,CAAC,QAAQ,CAAC;AACnC,YAAA,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAChC,OAAO;SACR,CAAC,EAAA,CACF,EACF;AACJ;;;;"}
1
+ {"version":3,"file":"PatientTimeline.mjs","sources":["../../../src/PatientTimeline/PatientTimeline.tsx"],"sourcesContent":["import { createReference, MedplumClient, ProfileResource } from '@medplum/core';\nimport { Attachment, Patient, Reference, ResourceType } from '@medplum/fhirtypes';\nimport React, { useCallback } from 'react';\nimport { ResourceTimeline } from '../ResourceTimeline/ResourceTimeline';\n\nexport interface PatientTimelineProps {\n patient: Patient | Reference<Patient>;\n}\n\nexport function PatientTimeline(props: PatientTimelineProps): JSX.Element {\n const loadTimelineResources = useCallback((medplum: MedplumClient, resourceType: ResourceType, id: string) => {\n const ref = `${resourceType}/${id}`;\n const _count = 100;\n return Promise.allSettled([\n medplum.readHistory('Patient', id),\n medplum.search('Communication', { subject: ref, _count }),\n medplum.search('Device', { patient: ref, _count }),\n medplum.search('DeviceRequest', { patient: ref, _count }),\n medplum.search('DiagnosticReport', { subject: ref, _count }),\n medplum.search('Media', { subject: ref, _count }),\n medplum.search('ServiceRequest', { subject: ref, _count }),\n medplum.search('Task', { subject: ref, _count }),\n ]);\n }, []);\n\n return (\n <ResourceTimeline\n value={props.patient}\n loadTimelineResources={loadTimelineResources}\n createCommunication={(resource: Patient, sender: ProfileResource, text: string) => ({\n resourceType: 'Communication',\n status: 'completed',\n subject: createReference(resource),\n sender: createReference(sender),\n sent: new Date().toISOString(),\n payload: [{ contentString: text }],\n })}\n createMedia={(resource: Patient, operator: ProfileResource, content: Attachment) => ({\n resourceType: 'Media',\n status: 'completed',\n subject: createReference(resource),\n operator: createReference(operator),\n issued: new Date().toISOString(),\n content,\n })}\n />\n );\n}\n"],"names":[],"mappings":";;;;AASM,SAAU,eAAe,CAAC,KAA2B,EAAA;IACzD,MAAM,qBAAqB,GAAG,WAAW,CAAC,CAAC,OAAsB,EAAE,YAA0B,EAAE,EAAU,KAAI;AAC3G,QAAA,MAAM,GAAG,GAAG,CAAA,EAAG,YAAY,CAAI,CAAA,EAAA,EAAE,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,GAAG,CAAC;QACnB,OAAO,OAAO,CAAC,UAAU,CAAC;AACxB,YAAA,OAAO,CAAC,WAAW,CAAC,SAAS,EAAE,EAAE,CAAC;AAClC,YAAA,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AACzD,YAAA,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AAClD,YAAA,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AACzD,YAAA,OAAO,CAAC,MAAM,CAAC,kBAAkB,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AAC5D,YAAA,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AACjD,YAAA,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AAC1D,YAAA,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AACjD,SAAA,CAAC,CAAC;KACJ,EAAE,EAAE,CAAC,CAAC;IAEP,QACE,KAAC,CAAA,aAAA,CAAA,gBAAgB,EACf,EAAA,KAAK,EAAE,KAAK,CAAC,OAAO,EACpB,qBAAqB,EAAE,qBAAqB,EAC5C,mBAAmB,EAAE,CAAC,QAAiB,EAAE,MAAuB,EAAE,IAAY,MAAM;AAClF,YAAA,YAAY,EAAE,eAAe;AAC7B,YAAA,MAAM,EAAE,WAAW;AACnB,YAAA,OAAO,EAAE,eAAe,CAAC,QAAQ,CAAC;AAClC,YAAA,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC;AAC/B,YAAA,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;AAC9B,YAAA,OAAO,EAAE,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;AACnC,SAAA,CAAC,EACF,WAAW,EAAE,CAAC,QAAiB,EAAE,QAAyB,EAAE,OAAmB,MAAM;AACnF,YAAA,YAAY,EAAE,OAAO;AACrB,YAAA,MAAM,EAAE,WAAW;AACnB,YAAA,OAAO,EAAE,eAAe,CAAC,QAAQ,CAAC;AAClC,YAAA,QAAQ,EAAE,eAAe,CAAC,QAAQ,CAAC;AACnC,YAAA,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAChC,OAAO;SACR,CAAC,EAAA,CACF,EACF;AACJ;;;;"}
@@ -67,6 +67,7 @@ const operatorNames = {
67
67
  'of-type': 'of type',
68
68
  missing: 'missing',
69
69
  identifier: 'identifier',
70
+ iterate: 'iterate',
70
71
  };
71
72
  /**
72
73
  * Sets the array of filters.
@@ -1 +1 @@
1
- {"version":3,"file":"SearchUtils.mjs","sources":["../../../src/SearchControl/SearchUtils.tsx"],"sourcesContent":["import {\n capitalize,\n DEFAULT_SEARCH_COUNT,\n evalFhirPathTyped,\n Filter,\n formatDateTime,\n Operator,\n PropertyType,\n SearchRequest,\n} from '@medplum/core';\nimport { ElementDefinition, Resource, SearchParameter } from '@medplum/fhirtypes';\nimport React from 'react';\nimport { getValueAndType, ResourcePropertyDisplay } from '../ResourcePropertyDisplay/ResourcePropertyDisplay';\nimport { SearchControlField } from './SearchControlField';\n\nconst searchParamToOperators: Record<string, Operator[]> = {\n string: [Operator.EQUALS, Operator.NOT, Operator.CONTAINS, Operator.EXACT],\n fulltext: [Operator.EQUALS, Operator.NOT, Operator.CONTAINS, Operator.EXACT],\n token: [Operator.EQUALS, Operator.NOT],\n reference: [Operator.EQUALS, Operator.NOT],\n numeric: [\n Operator.EQUALS,\n Operator.NOT_EQUALS,\n Operator.GREATER_THAN,\n Operator.LESS_THAN,\n Operator.GREATER_THAN_OR_EQUALS,\n Operator.LESS_THAN_OR_EQUALS,\n ],\n quantity: [\n Operator.EQUALS,\n Operator.NOT_EQUALS,\n Operator.GREATER_THAN,\n Operator.LESS_THAN,\n Operator.GREATER_THAN_OR_EQUALS,\n Operator.LESS_THAN_OR_EQUALS,\n ],\n date: [\n Operator.EQUALS,\n Operator.NOT_EQUALS,\n Operator.GREATER_THAN,\n Operator.LESS_THAN,\n Operator.GREATER_THAN_OR_EQUALS,\n Operator.LESS_THAN_OR_EQUALS,\n Operator.STARTS_AFTER,\n Operator.ENDS_BEFORE,\n Operator.APPROXIMATELY,\n ],\n datetime: [\n Operator.EQUALS,\n Operator.NOT_EQUALS,\n Operator.GREATER_THAN,\n Operator.LESS_THAN,\n Operator.GREATER_THAN_OR_EQUALS,\n Operator.LESS_THAN_OR_EQUALS,\n Operator.STARTS_AFTER,\n Operator.ENDS_BEFORE,\n Operator.APPROXIMATELY,\n ],\n};\n\nconst operatorNames: Record<Operator, string> = {\n eq: 'equals',\n ne: 'not equals',\n gt: 'greater than',\n lt: 'less than',\n ge: 'greater than or equals',\n le: 'less than or equals',\n sa: 'starts after',\n eb: 'ends before',\n ap: 'approximately',\n contains: 'contains',\n exact: 'exact',\n text: 'text',\n not: 'not',\n above: 'above',\n below: 'below',\n in: 'in',\n 'not-in': 'not in',\n 'of-type': 'of type',\n missing: 'missing',\n identifier: 'identifier',\n};\n\n/**\n * Sets the array of filters.\n *\n * @param {Array} filters The new filters.\n */\nexport function setFilters(definition: SearchRequest, filters: Filter[]): SearchRequest {\n return {\n ...definition,\n filters: filters,\n offset: 0,\n name: undefined,\n };\n}\n\n/**\n * Clears all of the filters.\n */\nexport function clearFilters(definition: SearchRequest): SearchRequest {\n return setFilters(definition, []);\n}\n\n/**\n * Clears all of the filters on a certain field.\n *\n * @param {string} code The field key name to clear filters.\n */\nexport function clearFiltersOnField(definition: SearchRequest, code: string): SearchRequest {\n return setFilters(\n definition,\n (definition.filters || []).filter((f) => f.code !== code)\n );\n}\n\n/**\n * Adds a filter.\n *\n * @param {string} field The field key name.\n * @param {Operator} op The operation key name.\n * @param {?string} value The filter value.\n * @param {boolean=} opt_clear Optional flag to clear filters on the field.\n */\nexport function addFilter(\n definition: SearchRequest,\n field: string,\n op: Operator,\n value?: string,\n opt_clear?: boolean\n): SearchRequest {\n if (opt_clear) {\n definition = clearFiltersOnField(definition, field);\n }\n\n const nextFilters: Filter[] = [];\n if (definition.filters) {\n nextFilters.push(...definition.filters);\n }\n nextFilters.push({ code: field, operator: op, value: value || '' });\n\n return setFilters(definition, nextFilters);\n}\n\n/**\n * Adds a field.\n *\n * @param {string} field The field key name.\n */\nexport function addField(definition: SearchRequest, field: string): SearchRequest {\n if (definition.fields && definition.fields.includes(field)) {\n return definition;\n }\n const newFields = [];\n if (definition.fields) {\n newFields.push(...definition.fields);\n }\n newFields.push(field);\n return {\n ...definition,\n fields: newFields,\n name: undefined,\n };\n}\n\n/**\n * Deletes a filter at the specified index.\n *\n * @param {number} index The filter index.\n */\nexport function deleteFilter(definition: SearchRequest, index: number): SearchRequest {\n if (!definition.filters) {\n return definition;\n }\n const newFilters = [...definition.filters];\n newFilters.splice(index, 1);\n return {\n ...definition,\n filters: newFilters,\n name: undefined,\n };\n}\n\n/**\n * Adds a filter that constrains the specified field to \"yesterday\".\n *\n * @param {string} field The field key name.\n */\nexport function addYesterdayFilter(definition: SearchRequest, field: string): SearchRequest {\n return addDayFilter(definition, field, -1);\n}\n\n/**\n * Adds a filter that constrains the specified field to \"today\".\n *\n * @param {string} field The field key name.\n */\nexport function addTodayFilter(definition: SearchRequest, field: string): SearchRequest {\n return addDayFilter(definition, field, 0);\n}\n\n/**\n * Adds a filter that constrains the specified field to \"tomorrow\".\n *\n * @param {string} field The field key name.\n */\nexport function addTomorrowFilter(definition: SearchRequest, field: string): SearchRequest {\n return addDayFilter(definition, field, 1);\n}\n\n/**\n * Adds a filter that constrains the specified field to a day.\n * The day is specified as a delta from the current day.\n * \"Today\" would be 0.\n * \"Yesterday\" would be -1.\n * \"Tomorrow\" would be 1.\n *\n * @param {string} field The field key name.\n * @param {number} delta The number of days from this day.\n */\nfunction addDayFilter(definition: SearchRequest, field: string, delta: number): SearchRequest {\n const startTime = new Date();\n startTime.setDate(startTime.getDate() + delta);\n startTime.setHours(0, 0, 0, 0);\n\n const endTime = new Date(startTime.getTime());\n endTime.setDate(endTime.getDate() + 1);\n endTime.setTime(endTime.getTime() - 1);\n\n return addDateFilterBetween(definition, field, startTime, endTime);\n}\n\n/**\n * Adds a filter that constrains the specified field to \"last month\".\n *\n * @param {string} field The field key name.\n */\nexport function addLastMonthFilter(definition: SearchRequest, field: string): SearchRequest {\n return addMonthFilter(definition, field, -1);\n}\n\n/**\n * Adds a filter that constrains the specified field to \"this month\".\n *\n * @param {string} field The field key name.\n */\nexport function addThisMonthFilter(definition: SearchRequest, field: string): SearchRequest {\n return addMonthFilter(definition, field, 0);\n}\n\n/**\n * Adds a filter that constrains the specified field to \"next month\".\n *\n * @param {string} field The field key name.\n */\nexport function addNextMonthFilter(definition: SearchRequest, field: string): SearchRequest {\n return addMonthFilter(definition, field, 1);\n}\n\n/**\n * Adds a filter that constrains the specified field to a month.\n * The month is specified as a delta from the current month.\n * \"This month\" would be 0.\n * \"Last month\" would be -1.\n * \"Next month\" would be 1.\n *\n * @param {string} field The field key name.\n * @param {number} delta The number of months from this month.\n */\nfunction addMonthFilter(definition: SearchRequest, field: string, delta: number): SearchRequest {\n const startTime = new Date();\n startTime.setMonth(startTime.getMonth() + delta);\n startTime.setDate(1);\n startTime.setHours(0, 0, 0, 0);\n\n const endTime = new Date(startTime.getTime());\n endTime.setMonth(endTime.getMonth() + 1);\n endTime.setDate(1);\n endTime.setHours(0, 0, 0, 0);\n endTime.setTime(endTime.getTime() - 1);\n\n return addDateFilterBetween(definition, field, startTime, endTime);\n}\n\n/**\n * Adds a filter that constrains the specified field to the year to date.\n *\n * @param {string} field The field key name.\n */\nexport function addYearToDateFilter(definition: SearchRequest, field: string): SearchRequest {\n const startTime = new Date();\n startTime.setMonth(0);\n startTime.setDate(1);\n startTime.setHours(0, 0, 0, 0);\n\n const endTime = new Date();\n\n return addDateFilterBetween(definition, field, startTime, endTime);\n}\n\n/**\n * Adds a filter for a date between two dates (inclusive of both dates).\n *\n * @param {string} field The field key name.\n * @param {Date} d1 The start date.\n * @param {Date} d2 The end date.\n */\nexport function addDateFilterBetween(definition: SearchRequest, field: string, d1: Date, d2: Date): SearchRequest {\n definition = clearFiltersOnField(definition, field);\n definition = addDateFilterImpl(definition, field, Operator.GREATER_THAN_OR_EQUALS, d1);\n definition = addDateFilterImpl(definition, field, Operator.LESS_THAN_OR_EQUALS, d2);\n return definition;\n}\n\n/**\n * Adds a filter for a date before a certain date/time.\n *\n * @param {string} field The field key name.\n * @param {Operator} op The date/time operation.\n * @param {Date} value The date.\n */\nfunction addDateFilterImpl(definition: SearchRequest, field: string, op: Operator, value: Date): SearchRequest {\n return addFilter(definition, field, op, value.toISOString());\n}\n\n/**\n * Adds a filter that constrains the specified field to \"missing\".\n *\n * @param {string} field The field key name.\n */\nexport function addMissingFilter(definition: SearchRequest, field: string, value = true): SearchRequest {\n return addFilter(definition, field, Operator.MISSING, value.toString());\n}\n\n/**\n * Sets the offset (starting at zero).\n *\n * @param {number} offset The offset number.\n */\nexport function setOffset(definition: SearchRequest, offset: number): SearchRequest {\n if (definition.offset === offset) {\n return definition;\n }\n return {\n ...definition,\n offset,\n name: undefined,\n };\n}\n\n/**\n * Creates a new search request with the search offset at the specified page.\n * @param definition The search definition.\n * @param page The new page number\n * @return The new search definition.\n */\nexport function setPage(definition: SearchRequest, page: number): SearchRequest {\n const count = definition.count ?? DEFAULT_SEARCH_COUNT;\n const newOffset = (page - 1) * count;\n return setOffset(definition, newOffset);\n}\n\n/**\n * Sorts the search by the specified key, and optional direction.\n * Direction defaults to ascending ('asc') if not specified.\n *\n * @param {string} sortField The sort key.\n */\nexport function setSort(definition: SearchRequest, sort: string, desc?: boolean): SearchRequest {\n if (sort === getSortField(definition) && desc !== undefined && desc === isSortDescending(definition)) {\n return definition;\n }\n return {\n ...definition,\n sortRules: [\n {\n code: sort,\n descending: !!desc,\n },\n ],\n name: undefined,\n };\n}\n\n/**\n * Toggles the sort of the search by key.\n * If the search is already sorted by the key, reverses the direction.\n * If the search is not sorted by the key, sort in ascending order.\n *\n * @param {string} key The field key name.\n */\nexport function toggleSort(definition: SearchRequest, key: string): SearchRequest {\n let desc = false;\n if (getSortField(definition) === key) {\n desc = !isSortDescending(definition);\n }\n return setSort(definition, key, desc);\n}\n\nexport function getSortField(definition: SearchRequest): string | undefined {\n const sortRules = definition.sortRules;\n if (!sortRules || sortRules.length === 0) {\n return undefined;\n }\n const field = sortRules[0].code;\n return field.startsWith('-') ? field.substr(1) : field;\n}\n\nexport function isSortDescending(definition: SearchRequest): boolean {\n const sortRules = definition.sortRules;\n if (!sortRules || sortRules.length === 0) {\n return false;\n }\n return !!sortRules[0].descending;\n}\n\n/**\n * Returns a list of operators for a search parameter.\n * @param searchParam The search parameter.\n * @returns The list of operators that can be used for the search parameter.\n */\nexport function getSearchOperators(searchParam: SearchParameter): Operator[] | undefined {\n return searchParamToOperators[searchParam.type as string];\n}\n\n/**\n * Returns a string representing the operation.\n *\n * @param {string} op The operation code.\n * @return {string} A display string for the operation.\n */\nexport function getOpString(op: Operator): string {\n return operatorNames[op] ?? '';\n}\n\n/**\n * Returns a field display name.\n * @param key The field key.\n * @returns The field display name.\n */\nexport function buildFieldNameString(key: string): string {\n let tmp = key;\n\n // If dot separated, only the last part\n if (tmp.includes('.')) {\n tmp = tmp.split('.').pop() as string;\n }\n\n // Special case for ID\n if (tmp === 'id') {\n return 'ID';\n }\n\n // Special case for Version ID\n if (tmp === 'versionId') {\n return 'Version ID';\n }\n\n // Remove choice of type\n tmp = tmp.replace('[x]', '');\n\n // Convert camel case to space separated\n tmp = tmp.replace(/([A-Z])/g, ' $1');\n\n // Convert dashes and underscores to spaces\n tmp = tmp.replace(/[-_]/g, ' ');\n\n // Normalize whitespace to single space character\n tmp = tmp.replace(/\\s+/g, ' ');\n\n // Trim\n tmp = tmp.trim();\n\n // Capitalize the first letter of each word\n return tmp.split(/\\s/).map(capitalize).join(' ');\n}\n\n/**\n * Returns a fragment to be displayed in the search table for the value.\n * @param resource The parent resource.\n * @param key The search code or FHIRPath expression.\n * @returns The fragment to display.\n */\nexport function renderValue(resource: Resource, field: SearchControlField): string | JSX.Element | null | undefined {\n const key = field.name;\n if (key === 'id') {\n return resource.id;\n }\n\n if (key === 'meta.versionId') {\n return resource.meta?.versionId;\n }\n\n if (key === '_lastUpdated') {\n return formatDateTime(resource.meta?.lastUpdated);\n }\n\n // Priority 1: ElementDefinition by exact match\n if (field.elementDefinition && `${resource.resourceType}.${field.name}` === field.elementDefinition.path) {\n return renderPropertyValue(resource, field.elementDefinition);\n }\n\n // Priority 2: SearchParameter by exact match\n if (field.searchParams && field.searchParams.length === 1 && field.name === field.searchParams[0].code) {\n return renderSearchParameterValue(resource, field.searchParams[0], field.elementDefinition);\n }\n\n // We don't know how to render this field definition\n return null;\n}\n\n/**\n * Returns a fragment to be displayed in the search table for a resource property.\n * @param resource The parent resource.\n * @param elementDefinition The property element definition.\n * @returns A React element or null.\n */\nfunction renderPropertyValue(resource: Resource, elementDefinition: ElementDefinition): JSX.Element | null {\n const path = elementDefinition.path?.split('.')?.pop()?.replaceAll('[x]', '') || '';\n const [value, propertyType] = getValueAndType({ type: resource.resourceType, value: resource }, path);\n if (!value) {\n return null;\n }\n\n return (\n <ResourcePropertyDisplay\n property={elementDefinition}\n propertyType={propertyType}\n value={value}\n maxWidth={200}\n ignoreMissingValues={true}\n link={false}\n />\n );\n}\n\n/**\n * Returns a fragment to be displayed in the search table for a search parameter.\n * @param resource The parent resource.\n * @param searchParam The search parameter.\n * @param elementDefinition Optional element definition.\n * @returns A React element or null.\n */\nfunction renderSearchParameterValue(\n resource: Resource,\n searchParam: SearchParameter,\n elementDefinition: ElementDefinition | undefined\n): JSX.Element | null {\n const value = evalFhirPathTyped(searchParam.expression as string, [{ type: resource.resourceType, value: resource }]);\n if (!value || value.length === 0) {\n return null;\n }\n\n if (elementDefinition) {\n return (\n <ResourcePropertyDisplay\n propertyType={value[0].type as PropertyType}\n value={value[0].value}\n maxWidth={200}\n ignoreMissingValues={true}\n link={false}\n />\n );\n }\n\n return (\n <>\n {value.map((v, index) => (\n <span key={`${index}-${value.length}`}>\n {typeof v === 'object' ? JSON.stringify(v) : (v as string | number)}\n </span>\n ))}\n </>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SearchUtils.mjs","sources":["../../../src/SearchControl/SearchUtils.tsx"],"sourcesContent":["import {\n capitalize,\n DEFAULT_SEARCH_COUNT,\n evalFhirPathTyped,\n Filter,\n formatDateTime,\n Operator,\n PropertyType,\n SearchRequest,\n} from '@medplum/core';\nimport { ElementDefinition, Resource, SearchParameter } from '@medplum/fhirtypes';\nimport React from 'react';\nimport { getValueAndType, ResourcePropertyDisplay } from '../ResourcePropertyDisplay/ResourcePropertyDisplay';\nimport { SearchControlField } from './SearchControlField';\n\nconst searchParamToOperators: Record<string, Operator[]> = {\n string: [Operator.EQUALS, Operator.NOT, Operator.CONTAINS, Operator.EXACT],\n fulltext: [Operator.EQUALS, Operator.NOT, Operator.CONTAINS, Operator.EXACT],\n token: [Operator.EQUALS, Operator.NOT],\n reference: [Operator.EQUALS, Operator.NOT],\n numeric: [\n Operator.EQUALS,\n Operator.NOT_EQUALS,\n Operator.GREATER_THAN,\n Operator.LESS_THAN,\n Operator.GREATER_THAN_OR_EQUALS,\n Operator.LESS_THAN_OR_EQUALS,\n ],\n quantity: [\n Operator.EQUALS,\n Operator.NOT_EQUALS,\n Operator.GREATER_THAN,\n Operator.LESS_THAN,\n Operator.GREATER_THAN_OR_EQUALS,\n Operator.LESS_THAN_OR_EQUALS,\n ],\n date: [\n Operator.EQUALS,\n Operator.NOT_EQUALS,\n Operator.GREATER_THAN,\n Operator.LESS_THAN,\n Operator.GREATER_THAN_OR_EQUALS,\n Operator.LESS_THAN_OR_EQUALS,\n Operator.STARTS_AFTER,\n Operator.ENDS_BEFORE,\n Operator.APPROXIMATELY,\n ],\n datetime: [\n Operator.EQUALS,\n Operator.NOT_EQUALS,\n Operator.GREATER_THAN,\n Operator.LESS_THAN,\n Operator.GREATER_THAN_OR_EQUALS,\n Operator.LESS_THAN_OR_EQUALS,\n Operator.STARTS_AFTER,\n Operator.ENDS_BEFORE,\n Operator.APPROXIMATELY,\n ],\n};\n\nconst operatorNames: Record<Operator, string> = {\n eq: 'equals',\n ne: 'not equals',\n gt: 'greater than',\n lt: 'less than',\n ge: 'greater than or equals',\n le: 'less than or equals',\n sa: 'starts after',\n eb: 'ends before',\n ap: 'approximately',\n contains: 'contains',\n exact: 'exact',\n text: 'text',\n not: 'not',\n above: 'above',\n below: 'below',\n in: 'in',\n 'not-in': 'not in',\n 'of-type': 'of type',\n missing: 'missing',\n identifier: 'identifier',\n iterate: 'iterate',\n};\n\n/**\n * Sets the array of filters.\n *\n * @param {Array} filters The new filters.\n */\nexport function setFilters(definition: SearchRequest, filters: Filter[]): SearchRequest {\n return {\n ...definition,\n filters: filters,\n offset: 0,\n name: undefined,\n };\n}\n\n/**\n * Clears all of the filters.\n */\nexport function clearFilters(definition: SearchRequest): SearchRequest {\n return setFilters(definition, []);\n}\n\n/**\n * Clears all of the filters on a certain field.\n *\n * @param {string} code The field key name to clear filters.\n */\nexport function clearFiltersOnField(definition: SearchRequest, code: string): SearchRequest {\n return setFilters(\n definition,\n (definition.filters || []).filter((f) => f.code !== code)\n );\n}\n\n/**\n * Adds a filter.\n *\n * @param {string} field The field key name.\n * @param {Operator} op The operation key name.\n * @param {?string} value The filter value.\n * @param {boolean=} opt_clear Optional flag to clear filters on the field.\n */\nexport function addFilter(\n definition: SearchRequest,\n field: string,\n op: Operator,\n value?: string,\n opt_clear?: boolean\n): SearchRequest {\n if (opt_clear) {\n definition = clearFiltersOnField(definition, field);\n }\n\n const nextFilters: Filter[] = [];\n if (definition.filters) {\n nextFilters.push(...definition.filters);\n }\n nextFilters.push({ code: field, operator: op, value: value || '' });\n\n return setFilters(definition, nextFilters);\n}\n\n/**\n * Adds a field.\n *\n * @param {string} field The field key name.\n */\nexport function addField(definition: SearchRequest, field: string): SearchRequest {\n if (definition.fields && definition.fields.includes(field)) {\n return definition;\n }\n const newFields = [];\n if (definition.fields) {\n newFields.push(...definition.fields);\n }\n newFields.push(field);\n return {\n ...definition,\n fields: newFields,\n name: undefined,\n };\n}\n\n/**\n * Deletes a filter at the specified index.\n *\n * @param {number} index The filter index.\n */\nexport function deleteFilter(definition: SearchRequest, index: number): SearchRequest {\n if (!definition.filters) {\n return definition;\n }\n const newFilters = [...definition.filters];\n newFilters.splice(index, 1);\n return {\n ...definition,\n filters: newFilters,\n name: undefined,\n };\n}\n\n/**\n * Adds a filter that constrains the specified field to \"yesterday\".\n *\n * @param {string} field The field key name.\n */\nexport function addYesterdayFilter(definition: SearchRequest, field: string): SearchRequest {\n return addDayFilter(definition, field, -1);\n}\n\n/**\n * Adds a filter that constrains the specified field to \"today\".\n *\n * @param {string} field The field key name.\n */\nexport function addTodayFilter(definition: SearchRequest, field: string): SearchRequest {\n return addDayFilter(definition, field, 0);\n}\n\n/**\n * Adds a filter that constrains the specified field to \"tomorrow\".\n *\n * @param {string} field The field key name.\n */\nexport function addTomorrowFilter(definition: SearchRequest, field: string): SearchRequest {\n return addDayFilter(definition, field, 1);\n}\n\n/**\n * Adds a filter that constrains the specified field to a day.\n * The day is specified as a delta from the current day.\n * \"Today\" would be 0.\n * \"Yesterday\" would be -1.\n * \"Tomorrow\" would be 1.\n *\n * @param {string} field The field key name.\n * @param {number} delta The number of days from this day.\n */\nfunction addDayFilter(definition: SearchRequest, field: string, delta: number): SearchRequest {\n const startTime = new Date();\n startTime.setDate(startTime.getDate() + delta);\n startTime.setHours(0, 0, 0, 0);\n\n const endTime = new Date(startTime.getTime());\n endTime.setDate(endTime.getDate() + 1);\n endTime.setTime(endTime.getTime() - 1);\n\n return addDateFilterBetween(definition, field, startTime, endTime);\n}\n\n/**\n * Adds a filter that constrains the specified field to \"last month\".\n *\n * @param {string} field The field key name.\n */\nexport function addLastMonthFilter(definition: SearchRequest, field: string): SearchRequest {\n return addMonthFilter(definition, field, -1);\n}\n\n/**\n * Adds a filter that constrains the specified field to \"this month\".\n *\n * @param {string} field The field key name.\n */\nexport function addThisMonthFilter(definition: SearchRequest, field: string): SearchRequest {\n return addMonthFilter(definition, field, 0);\n}\n\n/**\n * Adds a filter that constrains the specified field to \"next month\".\n *\n * @param {string} field The field key name.\n */\nexport function addNextMonthFilter(definition: SearchRequest, field: string): SearchRequest {\n return addMonthFilter(definition, field, 1);\n}\n\n/**\n * Adds a filter that constrains the specified field to a month.\n * The month is specified as a delta from the current month.\n * \"This month\" would be 0.\n * \"Last month\" would be -1.\n * \"Next month\" would be 1.\n *\n * @param {string} field The field key name.\n * @param {number} delta The number of months from this month.\n */\nfunction addMonthFilter(definition: SearchRequest, field: string, delta: number): SearchRequest {\n const startTime = new Date();\n startTime.setMonth(startTime.getMonth() + delta);\n startTime.setDate(1);\n startTime.setHours(0, 0, 0, 0);\n\n const endTime = new Date(startTime.getTime());\n endTime.setMonth(endTime.getMonth() + 1);\n endTime.setDate(1);\n endTime.setHours(0, 0, 0, 0);\n endTime.setTime(endTime.getTime() - 1);\n\n return addDateFilterBetween(definition, field, startTime, endTime);\n}\n\n/**\n * Adds a filter that constrains the specified field to the year to date.\n *\n * @param {string} field The field key name.\n */\nexport function addYearToDateFilter(definition: SearchRequest, field: string): SearchRequest {\n const startTime = new Date();\n startTime.setMonth(0);\n startTime.setDate(1);\n startTime.setHours(0, 0, 0, 0);\n\n const endTime = new Date();\n\n return addDateFilterBetween(definition, field, startTime, endTime);\n}\n\n/**\n * Adds a filter for a date between two dates (inclusive of both dates).\n *\n * @param {string} field The field key name.\n * @param {Date} d1 The start date.\n * @param {Date} d2 The end date.\n */\nexport function addDateFilterBetween(definition: SearchRequest, field: string, d1: Date, d2: Date): SearchRequest {\n definition = clearFiltersOnField(definition, field);\n definition = addDateFilterImpl(definition, field, Operator.GREATER_THAN_OR_EQUALS, d1);\n definition = addDateFilterImpl(definition, field, Operator.LESS_THAN_OR_EQUALS, d2);\n return definition;\n}\n\n/**\n * Adds a filter for a date before a certain date/time.\n *\n * @param {string} field The field key name.\n * @param {Operator} op The date/time operation.\n * @param {Date} value The date.\n */\nfunction addDateFilterImpl(definition: SearchRequest, field: string, op: Operator, value: Date): SearchRequest {\n return addFilter(definition, field, op, value.toISOString());\n}\n\n/**\n * Adds a filter that constrains the specified field to \"missing\".\n *\n * @param {string} field The field key name.\n */\nexport function addMissingFilter(definition: SearchRequest, field: string, value = true): SearchRequest {\n return addFilter(definition, field, Operator.MISSING, value.toString());\n}\n\n/**\n * Sets the offset (starting at zero).\n *\n * @param {number} offset The offset number.\n */\nexport function setOffset(definition: SearchRequest, offset: number): SearchRequest {\n if (definition.offset === offset) {\n return definition;\n }\n return {\n ...definition,\n offset,\n name: undefined,\n };\n}\n\n/**\n * Creates a new search request with the search offset at the specified page.\n * @param definition The search definition.\n * @param page The new page number\n * @return The new search definition.\n */\nexport function setPage(definition: SearchRequest, page: number): SearchRequest {\n const count = definition.count ?? DEFAULT_SEARCH_COUNT;\n const newOffset = (page - 1) * count;\n return setOffset(definition, newOffset);\n}\n\n/**\n * Sorts the search by the specified key, and optional direction.\n * Direction defaults to ascending ('asc') if not specified.\n *\n * @param {string} sortField The sort key.\n */\nexport function setSort(definition: SearchRequest, sort: string, desc?: boolean): SearchRequest {\n if (sort === getSortField(definition) && desc !== undefined && desc === isSortDescending(definition)) {\n return definition;\n }\n return {\n ...definition,\n sortRules: [\n {\n code: sort,\n descending: !!desc,\n },\n ],\n name: undefined,\n };\n}\n\n/**\n * Toggles the sort of the search by key.\n * If the search is already sorted by the key, reverses the direction.\n * If the search is not sorted by the key, sort in ascending order.\n *\n * @param {string} key The field key name.\n */\nexport function toggleSort(definition: SearchRequest, key: string): SearchRequest {\n let desc = false;\n if (getSortField(definition) === key) {\n desc = !isSortDescending(definition);\n }\n return setSort(definition, key, desc);\n}\n\nexport function getSortField(definition: SearchRequest): string | undefined {\n const sortRules = definition.sortRules;\n if (!sortRules || sortRules.length === 0) {\n return undefined;\n }\n const field = sortRules[0].code;\n return field.startsWith('-') ? field.substr(1) : field;\n}\n\nexport function isSortDescending(definition: SearchRequest): boolean {\n const sortRules = definition.sortRules;\n if (!sortRules || sortRules.length === 0) {\n return false;\n }\n return !!sortRules[0].descending;\n}\n\n/**\n * Returns a list of operators for a search parameter.\n * @param searchParam The search parameter.\n * @returns The list of operators that can be used for the search parameter.\n */\nexport function getSearchOperators(searchParam: SearchParameter): Operator[] | undefined {\n return searchParamToOperators[searchParam.type as string];\n}\n\n/**\n * Returns a string representing the operation.\n *\n * @param {string} op The operation code.\n * @return {string} A display string for the operation.\n */\nexport function getOpString(op: Operator): string {\n return operatorNames[op] ?? '';\n}\n\n/**\n * Returns a field display name.\n * @param key The field key.\n * @returns The field display name.\n */\nexport function buildFieldNameString(key: string): string {\n let tmp = key;\n\n // If dot separated, only the last part\n if (tmp.includes('.')) {\n tmp = tmp.split('.').pop() as string;\n }\n\n // Special case for ID\n if (tmp === 'id') {\n return 'ID';\n }\n\n // Special case for Version ID\n if (tmp === 'versionId') {\n return 'Version ID';\n }\n\n // Remove choice of type\n tmp = tmp.replace('[x]', '');\n\n // Convert camel case to space separated\n tmp = tmp.replace(/([A-Z])/g, ' $1');\n\n // Convert dashes and underscores to spaces\n tmp = tmp.replace(/[-_]/g, ' ');\n\n // Normalize whitespace to single space character\n tmp = tmp.replace(/\\s+/g, ' ');\n\n // Trim\n tmp = tmp.trim();\n\n // Capitalize the first letter of each word\n return tmp.split(/\\s/).map(capitalize).join(' ');\n}\n\n/**\n * Returns a fragment to be displayed in the search table for the value.\n * @param resource The parent resource.\n * @param key The search code or FHIRPath expression.\n * @returns The fragment to display.\n */\nexport function renderValue(resource: Resource, field: SearchControlField): string | JSX.Element | null | undefined {\n const key = field.name;\n if (key === 'id') {\n return resource.id;\n }\n\n if (key === 'meta.versionId') {\n return resource.meta?.versionId;\n }\n\n if (key === '_lastUpdated') {\n return formatDateTime(resource.meta?.lastUpdated);\n }\n\n // Priority 1: ElementDefinition by exact match\n if (field.elementDefinition && `${resource.resourceType}.${field.name}` === field.elementDefinition.path) {\n return renderPropertyValue(resource, field.elementDefinition);\n }\n\n // Priority 2: SearchParameter by exact match\n if (field.searchParams && field.searchParams.length === 1 && field.name === field.searchParams[0].code) {\n return renderSearchParameterValue(resource, field.searchParams[0], field.elementDefinition);\n }\n\n // We don't know how to render this field definition\n return null;\n}\n\n/**\n * Returns a fragment to be displayed in the search table for a resource property.\n * @param resource The parent resource.\n * @param elementDefinition The property element definition.\n * @returns A React element or null.\n */\nfunction renderPropertyValue(resource: Resource, elementDefinition: ElementDefinition): JSX.Element | null {\n const path = elementDefinition.path?.split('.')?.pop()?.replaceAll('[x]', '') || '';\n const [value, propertyType] = getValueAndType({ type: resource.resourceType, value: resource }, path);\n if (!value) {\n return null;\n }\n\n return (\n <ResourcePropertyDisplay\n property={elementDefinition}\n propertyType={propertyType}\n value={value}\n maxWidth={200}\n ignoreMissingValues={true}\n link={false}\n />\n );\n}\n\n/**\n * Returns a fragment to be displayed in the search table for a search parameter.\n * @param resource The parent resource.\n * @param searchParam The search parameter.\n * @param elementDefinition Optional element definition.\n * @returns A React element or null.\n */\nfunction renderSearchParameterValue(\n resource: Resource,\n searchParam: SearchParameter,\n elementDefinition: ElementDefinition | undefined\n): JSX.Element | null {\n const value = evalFhirPathTyped(searchParam.expression as string, [{ type: resource.resourceType, value: resource }]);\n if (!value || value.length === 0) {\n return null;\n }\n\n if (elementDefinition) {\n return (\n <ResourcePropertyDisplay\n propertyType={value[0].type as PropertyType}\n value={value[0].value}\n maxWidth={200}\n ignoreMissingValues={true}\n link={false}\n />\n );\n }\n\n return (\n <>\n {value.map((v, index) => (\n <span key={`${index}-${value.length}`}>\n {typeof v === 'object' ? JSON.stringify(v) : (v as string | number)}\n </span>\n ))}\n </>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -20,7 +20,7 @@ function SearchFilterEditor(props) {
20
20
  return null;
21
21
  }
22
22
  const resourceType = props.search.resourceType;
23
- const searchParams = globalSchema.types[resourceType].searchParams;
23
+ const searchParams = globalSchema.types[resourceType].searchParams ?? {};
24
24
  const filters = search.filters || [];
25
25
  return (React.createElement(Modal, { title: "Filters", closeButtonProps: { 'aria-label': 'Close' }, size: 900, opened: props.visible, onClose: props.onCancel },
26
26
  React.createElement("div", null,