@medplum/react 0.9.26 → 0.9.29

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 (246) hide show
  1. package/dist/cjs/AddressDisplay.d.ts +6 -0
  2. package/dist/cjs/AddressInput.d.ts +8 -0
  3. package/dist/cjs/AnnotationInput.d.ts +8 -0
  4. package/dist/cjs/AttachmentArrayDisplay.d.ts +7 -0
  5. package/dist/cjs/AttachmentArrayInput.d.ts +9 -0
  6. package/dist/cjs/AttachmentDisplay.d.ts +7 -0
  7. package/dist/cjs/AttachmentInput.d.ts +9 -0
  8. package/dist/cjs/Autocomplete.d.ts +20 -0
  9. package/dist/cjs/Avatar.d.ts +12 -0
  10. package/dist/cjs/BackboneElementDisplay.d.ts +9 -0
  11. package/dist/cjs/BackboneElementInput.d.ts +9 -0
  12. package/dist/cjs/Button.d.ts +15 -0
  13. package/dist/cjs/CalendarInput.d.ts +16 -0
  14. package/dist/cjs/Checkbox.d.ts +12 -0
  15. package/dist/cjs/CheckboxFormSection.d.ts +9 -0
  16. package/dist/cjs/CodeInput.d.ts +9 -0
  17. package/dist/cjs/CodeableConceptDisplay.d.ts +6 -0
  18. package/dist/cjs/CodeableConceptInput.d.ts +9 -0
  19. package/dist/cjs/CodingDisplay.d.ts +6 -0
  20. package/dist/cjs/CodingInput.d.ts +9 -0
  21. package/dist/cjs/ContactDetailDisplay.d.ts +6 -0
  22. package/dist/cjs/ContactDetailInput.d.ts +8 -0
  23. package/dist/cjs/ContactPointDisplay.d.ts +6 -0
  24. package/dist/cjs/ContactPointInput.d.ts +8 -0
  25. package/dist/cjs/DateTimeInput.d.ts +23 -0
  26. package/dist/cjs/DefaultResourceTimeline.d.ts +6 -0
  27. package/dist/cjs/DescriptionList.d.ts +12 -0
  28. package/dist/cjs/DiagnosticReportDisplay.d.ts +12 -0
  29. package/dist/cjs/Dialog.d.ts +10 -0
  30. package/dist/cjs/Document.d.ts +7 -0
  31. package/dist/cjs/EncounterTimeline.d.ts +6 -0
  32. package/dist/cjs/ErrorBoundary.d.ts +18 -0
  33. package/dist/cjs/ExtensionInput.d.ts +8 -0
  34. package/dist/cjs/FhirPathDisplay.d.ts +9 -0
  35. package/dist/cjs/FhirPathTable.d.ts +29 -0
  36. package/dist/cjs/FooterLinks.d.ts +6 -0
  37. package/dist/cjs/Form.d.ts +8 -0
  38. package/dist/cjs/FormSection.d.ts +11 -0
  39. package/dist/cjs/FormUtils.d.ts +5 -0
  40. package/dist/cjs/GoogleButton.d.ts +8 -0
  41. package/dist/cjs/Header.d.ts +12 -0
  42. package/dist/cjs/HeaderSearchInput.d.ts +10 -0
  43. package/dist/cjs/HumanNameDisplay.d.ts +8 -0
  44. package/dist/cjs/HumanNameInput.d.ts +8 -0
  45. package/dist/cjs/IdentifierDisplay.d.ts +6 -0
  46. package/dist/cjs/IdentifierInput.d.ts +8 -0
  47. package/dist/cjs/Input.d.ts +22 -0
  48. package/dist/cjs/InputRow.d.ts +7 -0
  49. package/dist/cjs/Loading.d.ts +3 -0
  50. package/dist/cjs/Logo.d.ts +6 -0
  51. package/dist/cjs/MedplumLink.d.ts +13 -0
  52. package/dist/cjs/MedplumProvider.d.ts +34 -0
  53. package/dist/cjs/MenuItem.d.ts +9 -0
  54. package/dist/cjs/MenuSeparator.d.ts +3 -0
  55. package/dist/cjs/PatientTimeline.d.ts +6 -0
  56. package/dist/cjs/PeriodInput.d.ts +8 -0
  57. package/dist/cjs/PlanDefinitionBuilder.d.ts +7 -0
  58. package/dist/cjs/Popup.d.ts +14 -0
  59. package/dist/cjs/QuantityDisplay.d.ts +7 -0
  60. package/dist/cjs/QuantityInput.d.ts +8 -0
  61. package/dist/cjs/QuestionnaireBuilder.d.ts +8 -0
  62. package/dist/cjs/QuestionnaireForm.d.ts +14 -0
  63. package/dist/cjs/QuestionnaireUtils.d.ts +30 -0
  64. package/dist/cjs/RangeDisplay.d.ts +7 -0
  65. package/dist/cjs/RangeInput.d.ts +14 -0
  66. package/dist/cjs/RatioDisplay.d.ts +6 -0
  67. package/dist/cjs/RatioInput.d.ts +14 -0
  68. package/dist/cjs/ReferenceDisplay.d.ts +7 -0
  69. package/dist/cjs/ReferenceInput.d.ts +9 -0
  70. package/dist/cjs/RegisterForm.d.ts +18 -0
  71. package/dist/cjs/RequestGroupDisplay.d.ts +9 -0
  72. package/dist/cjs/ResourceArrayDisplay.d.ts +11 -0
  73. package/dist/cjs/ResourceArrayInput.d.ts +11 -0
  74. package/dist/cjs/ResourceBadge.d.ts +9 -0
  75. package/dist/cjs/ResourceBlame.d.ts +10 -0
  76. package/dist/cjs/ResourceDiff.d.ts +9 -0
  77. package/dist/cjs/ResourceDiffTable.d.ts +9 -0
  78. package/dist/cjs/ResourceForm.d.ts +10 -0
  79. package/dist/cjs/ResourceHistoryTable.d.ts +9 -0
  80. package/dist/cjs/ResourceInput.d.ts +12 -0
  81. package/dist/cjs/ResourceName.d.ts +7 -0
  82. package/dist/cjs/ResourcePropertyDisplay.d.ts +24 -0
  83. package/dist/cjs/ResourcePropertyInput.d.ts +21 -0
  84. package/dist/cjs/ResourceTable.d.ts +7 -0
  85. package/dist/cjs/ResourceTimeline.d.ts +11 -0
  86. package/dist/cjs/Scheduler.d.ts +7 -0
  87. package/dist/cjs/Scrollable.d.ts +9 -0
  88. package/dist/cjs/SearchControl.d.ts +40 -0
  89. package/dist/cjs/SearchControlField.d.ts +41 -0
  90. package/dist/cjs/SearchFieldEditor.d.ts +11 -0
  91. package/dist/cjs/SearchFilterEditor.d.ts +11 -0
  92. package/dist/cjs/SearchFilterValueDialog.d.ts +15 -0
  93. package/dist/cjs/SearchFilterValueDisplay.d.ts +7 -0
  94. package/dist/cjs/SearchFilterValueInput.d.ts +12 -0
  95. package/dist/cjs/SearchPopupMenu.d.ts +15 -0
  96. package/dist/cjs/SearchUtils.d.ts +174 -0
  97. package/dist/cjs/Select.d.ts +16 -0
  98. package/dist/cjs/ServiceRequestTimeline.d.ts +6 -0
  99. package/dist/cjs/SignInForm.d.ts +17 -0
  100. package/dist/cjs/StatusBadge.d.ts +6 -0
  101. package/dist/cjs/SubMenu.d.ts +7 -0
  102. package/dist/cjs/Tab.d.ts +12 -0
  103. package/dist/cjs/TabList.d.ts +10 -0
  104. package/dist/cjs/TabPanel.d.ts +6 -0
  105. package/dist/cjs/TabSwitch.d.ts +6 -0
  106. package/dist/cjs/TextArea.d.ts +18 -0
  107. package/dist/cjs/Timeline.d.ts +17 -0
  108. package/dist/cjs/TimingInput.d.ts +8 -0
  109. package/dist/cjs/TitleBar.d.ts +6 -0
  110. package/dist/cjs/UploadButton.d.ts +7 -0
  111. package/dist/cjs/constants.d.ts +1 -0
  112. package/dist/cjs/index.d.ts +86 -0
  113. package/dist/cjs/index.js +356 -192
  114. package/dist/cjs/index.js.map +1 -1
  115. package/dist/cjs/index.min.js +1 -1
  116. package/dist/cjs/index.min.js.map +1 -1
  117. package/dist/cjs/stories/AddressInput.stories.d.ts +6 -0
  118. package/dist/cjs/stories/AttachmentArrayInput.stories.d.ts +6 -0
  119. package/dist/cjs/stories/AttachmentInput.stories.d.ts +6 -0
  120. package/dist/cjs/stories/Autocomplete.stories.d.ts +9 -0
  121. package/dist/cjs/stories/Avatar.stories.d.ts +10 -0
  122. package/dist/cjs/stories/Button.stories.d.ts +9 -0
  123. package/dist/cjs/stories/CodeableConceptDisplay.stories.d.ts +8 -0
  124. package/dist/cjs/stories/DiagnosticReportDisplay.stories.d.ts +5 -0
  125. package/dist/cjs/stories/Dialog.stories.d.ts +5 -0
  126. package/dist/cjs/stories/EncounterTimeline.stories.d.ts +5 -0
  127. package/dist/cjs/stories/FhirPathDisplay.stories.d.ts +7 -0
  128. package/dist/cjs/stories/FormSection.stories.d.ts +6 -0
  129. package/dist/cjs/stories/Header.stories.d.ts +8 -0
  130. package/dist/cjs/stories/Input.stories.d.ts +6 -0
  131. package/dist/cjs/stories/Loading.stories.d.ts +5 -0
  132. package/dist/cjs/stories/Logo.stories.d.ts +5 -0
  133. package/dist/cjs/stories/PatientTimeline.stories.d.ts +5 -0
  134. package/dist/cjs/stories/PlanDefinitionBuilder.stories.d.ts +5 -0
  135. package/dist/cjs/stories/QuestionnaireBuilder.stories.d.ts +7 -0
  136. package/dist/cjs/stories/QuestionnaireForm.stories.d.ts +11 -0
  137. package/dist/cjs/stories/ReferenceInput.stories.d.ts +6 -0
  138. package/dist/cjs/stories/RegisterForm.stories.d.ts +7 -0
  139. package/dist/cjs/stories/RequestGroupDisplay.stories.d.ts +5 -0
  140. package/dist/cjs/stories/ResourceBlame.stories.d.ts +5 -0
  141. package/dist/cjs/stories/ResourceForm.stories.d.ts +12 -0
  142. package/dist/cjs/stories/ResourceHistoryTable.stories.d.ts +5 -0
  143. package/dist/cjs/stories/ResourceTable.stories.d.ts +7 -0
  144. package/dist/cjs/stories/Scheduler.stories.d.ts +5 -0
  145. package/dist/cjs/stories/SearchControl.stories.d.ts +13 -0
  146. package/dist/cjs/stories/Select.stories.d.ts +6 -0
  147. package/dist/cjs/stories/SignInForm.stories.d.ts +8 -0
  148. package/dist/cjs/stories/StatusBadge.stories.d.ts +5 -0
  149. package/dist/cjs/stories/Tabs.stories.d.ts +6 -0
  150. package/dist/cjs/stories/Timeline.stories.d.ts +5 -0
  151. package/dist/cjs/stories/TimingInput.stories.d.ts +6 -0
  152. package/dist/cjs/stories/UploadButton.stories.d.ts +6 -0
  153. package/dist/cjs/styles.css +135 -130
  154. package/dist/cjs/test.setup.d.ts +1 -0
  155. package/dist/cjs/useResource.d.ts +8 -0
  156. package/dist/cjs/utils/blame.d.ts +8 -0
  157. package/dist/cjs/utils/date.d.ts +6 -0
  158. package/dist/cjs/utils/diff.d.ts +16 -0
  159. package/dist/cjs/utils/dom.d.ts +15 -0
  160. package/dist/cjs/utils/outcomes.d.ts +2 -0
  161. package/dist/cjs/utils/recaptcha.d.ts +12 -0
  162. package/dist/cjs/utils.d.ts +5 -0
  163. package/dist/esm/Autocomplete.d.ts +1 -0
  164. package/dist/esm/Autocomplete.js +4 -8
  165. package/dist/esm/Autocomplete.js.map +1 -1
  166. package/dist/esm/CalendarInput.d.ts +1 -0
  167. package/dist/esm/CalendarInput.js +6 -5
  168. package/dist/esm/CalendarInput.js.map +1 -1
  169. package/dist/esm/CodeableConceptDisplay.js +4 -2
  170. package/dist/esm/CodeableConceptDisplay.js.map +1 -1
  171. package/dist/esm/DateTimeInput.js +1 -3
  172. package/dist/esm/DateTimeInput.js.map +1 -1
  173. package/dist/esm/DiagnosticReportDisplay.js +2 -4
  174. package/dist/esm/DiagnosticReportDisplay.js.map +1 -1
  175. package/dist/esm/FhirPathTable.js +5 -2
  176. package/dist/esm/FhirPathTable.js.map +1 -1
  177. package/dist/esm/GoogleButton.js +1 -1
  178. package/dist/esm/GoogleButton.js.map +1 -1
  179. package/dist/esm/Header.js +7 -3
  180. package/dist/esm/Header.js.map +1 -1
  181. package/dist/esm/PlanDefinitionBuilder.js +108 -39
  182. package/dist/esm/PlanDefinitionBuilder.js.map +1 -1
  183. package/dist/esm/QuestionnaireBuilder.js +1 -1
  184. package/dist/esm/QuestionnaireBuilder.js.map +1 -1
  185. package/dist/esm/QuestionnaireForm.js +5 -1
  186. package/dist/esm/QuestionnaireForm.js.map +1 -1
  187. package/dist/esm/RegisterForm.js +14 -3
  188. package/dist/esm/RegisterForm.js.map +1 -1
  189. package/dist/esm/RequestGroupDisplay.js +3 -4
  190. package/dist/esm/RequestGroupDisplay.js.map +1 -1
  191. package/dist/esm/ResourceArrayInput.js +1 -2
  192. package/dist/esm/ResourceArrayInput.js.map +1 -1
  193. package/dist/esm/ResourceBlame.js +1 -1
  194. package/dist/esm/ResourceBlame.js.map +1 -1
  195. package/dist/esm/ResourceDiffTable.js +1 -1
  196. package/dist/esm/ResourceDiffTable.js.map +1 -1
  197. package/dist/esm/ResourceForm.js +1 -1
  198. package/dist/esm/ResourceForm.js.map +1 -1
  199. package/dist/esm/ResourceHistoryTable.js +6 -4
  200. package/dist/esm/ResourceHistoryTable.js.map +1 -1
  201. package/dist/esm/ResourceInput.d.ts +1 -0
  202. package/dist/esm/ResourceInput.js +4 -3
  203. package/dist/esm/ResourceInput.js.map +1 -1
  204. package/dist/esm/ResourcePropertyDisplay.js +5 -5
  205. package/dist/esm/ResourcePropertyDisplay.js.map +1 -1
  206. package/dist/esm/ResourcePropertyInput.js +3 -0
  207. package/dist/esm/ResourcePropertyInput.js.map +1 -1
  208. package/dist/esm/ResourceTable.js +1 -1
  209. package/dist/esm/ResourceTable.js.map +1 -1
  210. package/dist/esm/ResourceTimeline.js +13 -7
  211. package/dist/esm/ResourceTimeline.js.map +1 -1
  212. package/dist/esm/Scheduler.js +13 -6
  213. package/dist/esm/Scheduler.js.map +1 -1
  214. package/dist/esm/SearchControl.js +5 -2
  215. package/dist/esm/SearchControl.js.map +1 -1
  216. package/dist/esm/SearchFilterValueDisplay.js +2 -2
  217. package/dist/esm/SearchFilterValueDisplay.js.map +1 -1
  218. package/dist/esm/SearchUtils.js +2 -3
  219. package/dist/esm/SearchUtils.js.map +1 -1
  220. package/dist/esm/SignInForm.js +2 -1
  221. package/dist/esm/SignInForm.js.map +1 -1
  222. package/dist/esm/Timeline.js +2 -4
  223. package/dist/esm/Timeline.js.map +1 -1
  224. package/dist/esm/TimingInput.d.ts +8 -0
  225. package/dist/esm/TimingInput.js +90 -0
  226. package/dist/esm/TimingInput.js.map +1 -0
  227. package/dist/esm/index.d.ts +0 -1
  228. package/dist/esm/index.js +0 -1
  229. package/dist/esm/index.js.map +1 -1
  230. package/dist/esm/index.min.js +1 -1
  231. package/dist/esm/index.min.js.map +1 -1
  232. package/dist/esm/stories/Autocomplete.stories.d.ts +1 -0
  233. package/dist/esm/stories/CodeableConceptDisplay.stories.d.ts +8 -0
  234. package/dist/esm/stories/TimingInput.stories.d.ts +6 -0
  235. package/dist/esm/styles.css +135 -130
  236. package/dist/esm/utils/recaptcha.js +10 -4
  237. package/dist/esm/utils/recaptcha.js.map +1 -1
  238. package/package.json +6 -6
  239. package/dist/esm/DateTimeDisplay.d.ts +0 -5
  240. package/dist/esm/DateTimeDisplay.js +0 -11
  241. package/dist/esm/DateTimeDisplay.js.map +0 -1
  242. package/dist/esm/PeriodDisplay.d.ts +0 -6
  243. package/dist/esm/PeriodDisplay.js +0 -16
  244. package/dist/esm/PeriodDisplay.js.map +0 -1
  245. package/tsconfig.cjs.json +0 -7
  246. package/tsconfig.esm.json +0 -7
package/dist/cjs/index.js CHANGED
@@ -333,7 +333,7 @@
333
333
  var _a, _b;
334
334
  const inputRef = React.useRef(null);
335
335
  const [focused, setFocused] = React.useState(false);
336
- const [lastValue, setLastValue] = React.useState('');
336
+ const [lastValue, setLastValue] = React.useState(undefined);
337
337
  const [timer, setTimer] = React.useState();
338
338
  const [dropDownVisible, setDropDownVisible] = React.useState(false);
339
339
  const [values, setValues] = React.useState((_a = props.defaultValue) !== null && _a !== void 0 ? _a : []);
@@ -387,6 +387,9 @@
387
387
  }
388
388
  function handleFocus() {
389
389
  setFocused(true);
390
+ if (props.loadOnFocus) {
391
+ handleInput();
392
+ }
390
393
  }
391
394
  function handleBlur() {
392
395
  setFocused(false);
@@ -526,13 +529,6 @@
526
529
  // Nothing has changed, move on
527
530
  return;
528
531
  }
529
- if (!value) {
530
- setDropDownVisible(false);
531
- setLastValue('');
532
- setOptions([]);
533
- setSelectedIndex(-1);
534
- return;
535
- }
536
532
  setLastValue(value);
537
533
  const newAbortController = new AbortController();
538
534
  setAbortController(newAbortController);
@@ -752,7 +748,7 @@
752
748
  React.useEffect(() => {
753
749
  if (defaultValue) {
754
750
  setValue(JSON.parse(JSON.stringify(defaultValue)));
755
- medplum.requestSchema(defaultValue.resourceType).then(setSchema);
751
+ medplum.requestSchema(defaultValue.resourceType).then(setSchema).catch(console.log);
756
752
  }
757
753
  }, [medplum, defaultValue]);
758
754
  if (!schema || !value) {
@@ -845,8 +841,10 @@
845
841
  if (value.text) {
846
842
  return React__default["default"].createElement(React__default["default"].Fragment, null, value.text);
847
843
  }
848
- if (value.coding && value.coding.length > 0) {
849
- return React__default["default"].createElement(CodingDisplay, { value: value.coding[0] });
844
+ if (value.coding) {
845
+ return (React__default["default"].createElement(React__default["default"].Fragment, null, value.coding.map((coding, index) => (React__default["default"].createElement(React__default["default"].Fragment, { key: 'coding-' + index },
846
+ index > 0 && React__default["default"].createElement(React__default["default"].Fragment, null, ', '),
847
+ React__default["default"].createElement(CodingDisplay, { value: coding }))))));
850
848
  }
851
849
  return null;
852
850
  }
@@ -888,13 +886,6 @@
888
886
  _a.map((telecom, index) => (React__default["default"].createElement(ContactPointDisplay, { key: 'telecom-' + index, value: telecom })))));
889
887
  }
890
888
 
891
- function DateTimeDisplay(props) {
892
- if (!props.value) {
893
- return null;
894
- }
895
- return React__default["default"].createElement(React__default["default"].Fragment, null, new Date(props.value).toLocaleString());
896
- }
897
-
898
889
  function HumanNameDisplay(props) {
899
890
  const name = props.value;
900
891
  if (!name) {
@@ -911,17 +902,6 @@
911
902
  _b.value));
912
903
  }
913
904
 
914
- function PeriodDisplay(props) {
915
- const value = props.value;
916
- if (!value || (!value.start && !value.end)) {
917
- return null;
918
- }
919
- return (React__default["default"].createElement("span", null,
920
- React__default["default"].createElement(DateTimeDisplay, { value: value.start }),
921
- "-",
922
- React__default["default"].createElement(DateTimeDisplay, { value: value.end })));
923
- }
924
-
925
905
  function QuantityDisplay(props) {
926
906
  return React__default["default"].createElement(React__default["default"].Fragment, null, formatQuantityString(props.value));
927
907
  }
@@ -1023,7 +1003,7 @@
1023
1003
  return React__default["default"].createElement(ReferenceDisplay, { value: { reference: value }, link: props.link });
1024
1004
  case core.PropertyType.dateTime:
1025
1005
  case core.PropertyType.instant:
1026
- return React__default["default"].createElement(DateTimeDisplay, { value: value });
1006
+ return React__default["default"].createElement("div", null, core.formatDateTime(value));
1027
1007
  case core.PropertyType.markdown:
1028
1008
  return React__default["default"].createElement("pre", null, value);
1029
1009
  case core.PropertyType.Address:
@@ -1045,7 +1025,7 @@
1045
1025
  case core.PropertyType.Identifier:
1046
1026
  return React__default["default"].createElement(IdentifierDisplay, { value: value });
1047
1027
  case core.PropertyType.Period:
1048
- return React__default["default"].createElement(PeriodDisplay, { value: value });
1028
+ return React__default["default"].createElement("div", null, core.formatPeriod(value));
1049
1029
  case core.PropertyType.Quantity:
1050
1030
  return React__default["default"].createElement(QuantityDisplay, { value: value });
1051
1031
  case core.PropertyType.Range:
@@ -1054,6 +1034,8 @@
1054
1034
  return React__default["default"].createElement(RatioDisplay, { value: value });
1055
1035
  case core.PropertyType.Reference:
1056
1036
  return React__default["default"].createElement(ReferenceDisplay, { value: value, link: props.link });
1037
+ case core.PropertyType.Timing:
1038
+ return React__default["default"].createElement("div", null, core.formatTiming(value));
1057
1039
  default:
1058
1040
  if (!(property === null || property === void 0 ? void 0 : property.path)) {
1059
1041
  throw Error(`Displaying property of type ${props.propertyType} requires element definition path`);
@@ -1313,7 +1295,7 @@
1313
1295
  // See: https://developer.mozilla.org/en-US/docs/Web/HTML/Date_and_time_formats#local_date_and_time_strings
1314
1296
  // See: https://stackoverflow.com/a/60368477
1315
1297
  const date = new Date(isoString);
1316
- if (!isValidDate(date)) {
1298
+ if (!core.isValidDate(date)) {
1317
1299
  // If the input string was malformed, return an empty string.
1318
1300
  return '';
1319
1301
  }
@@ -1332,15 +1314,12 @@
1332
1314
  // JavaScript's Date() constructor defaults to the local time zone.
1333
1315
  // The Date() constructor will throw if the value is malformed.
1334
1316
  const date = new Date(localString);
1335
- if (!isValidDate(date)) {
1317
+ if (!core.isValidDate(date)) {
1336
1318
  // If the input string was malformed, return an empty string.
1337
1319
  return '';
1338
1320
  }
1339
1321
  return date.toISOString();
1340
1322
  }
1341
- function isValidDate(date) {
1342
- return date instanceof Date && !isNaN(date.getTime());
1343
- }
1344
1323
 
1345
1324
  function TextArea(props) {
1346
1325
  const className = 'medplum-textarea' + (props.monospace ? ' monospace' : '');
@@ -1493,6 +1472,31 @@
1493
1472
  React__default["default"].createElement(QuantityInput, { name: props.name + '-denominator', defaultValue: value === null || value === void 0 ? void 0 : value.denominator, onChange: (v) => setValueWrapper(Object.assign(Object.assign({}, value), { denominator: v })) })));
1494
1473
  }
1495
1474
 
1475
+ /******************************************************************************
1476
+ Copyright (c) Microsoft Corporation.
1477
+
1478
+ Permission to use, copy, modify, and/or distribute this software for any
1479
+ purpose with or without fee is hereby granted.
1480
+
1481
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
1482
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1483
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
1484
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
1485
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
1486
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1487
+ PERFORMANCE OF THIS SOFTWARE.
1488
+ ***************************************************************************** */
1489
+
1490
+ function __awaiter(thisArg, _arguments, P, generator) {
1491
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
1492
+ return new (P || (P = Promise))(function (resolve, reject) {
1493
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
1494
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
1495
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
1496
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
1497
+ });
1498
+ }
1499
+
1496
1500
  function ResourceName(props) {
1497
1501
  const resource = useResource(props.value);
1498
1502
  if (!resource) {
@@ -1517,18 +1521,18 @@
1517
1521
  props.onChange(newValue);
1518
1522
  }
1519
1523
  }
1520
- return (React__default["default"].createElement(Autocomplete, { loadOptions: (input) => {
1524
+ return (React__default["default"].createElement(Autocomplete, { loadOptions: (input) => __awaiter(this, void 0, void 0, function* () {
1521
1525
  return medplum
1522
1526
  .search(resourceTypeRef.current, 'name=' + encodeURIComponent(input) + '&_count=10')
1523
1527
  .then((bundle) => bundle.entry.map((entry) => entry.resource));
1524
- }, getId: (item) => {
1528
+ }), getId: (item) => {
1525
1529
  return item.id;
1526
1530
  }, getIcon: (item) => React__default["default"].createElement(Avatar, { value: item }), getDisplay: (item) => React__default["default"].createElement(ResourceName, { value: item }), getHelpText: (item) => {
1527
1531
  if (item.resourceType === 'Patient' && item.birthDate) {
1528
1532
  return 'DoB: ' + item.birthDate;
1529
1533
  }
1530
1534
  return undefined;
1531
- }, name: props.name, defaultValue: value ? [value] : undefined, className: props.className, placeholder: props.placeholder, onChange: (items) => {
1535
+ }, name: props.name, defaultValue: value ? [value] : undefined, className: props.className, placeholder: props.placeholder, loadOnFocus: props.loadOnFocus, onChange: (items) => {
1532
1536
  setValueWrapper(items.length > 0 ? items[0] : undefined);
1533
1537
  } }));
1534
1538
  }
@@ -1567,8 +1571,7 @@
1567
1571
  }
1568
1572
 
1569
1573
  function ResourceArrayInput(props) {
1570
- var _a;
1571
- const [values, setValues] = React.useState((_a = props.defaultValue) !== null && _a !== void 0 ? _a : []);
1574
+ const [values, setValues] = React.useState(props.defaultValue && Array.isArray(props.defaultValue) ? props.defaultValue : []);
1572
1575
  const valuesRef = React.useRef();
1573
1576
  valuesRef.current = values;
1574
1577
  function setValuesWrapper(newValues) {
@@ -1607,6 +1610,120 @@
1607
1610
  } }, "Add"))))));
1608
1611
  }
1609
1612
 
1613
+ function Dialog(props) {
1614
+ const [x, setX] = React.useState(100);
1615
+ const [y, setY] = React.useState(100);
1616
+ if (!props.visible) {
1617
+ return null;
1618
+ }
1619
+ function handleMouseDown(downEvent) {
1620
+ killEvent(downEvent);
1621
+ const dragX = downEvent.clientX - x;
1622
+ const dragY = downEvent.clientY - y;
1623
+ function handleMouseMove(moveEvent) {
1624
+ killEvent(moveEvent);
1625
+ setX(moveEvent.clientX - dragX);
1626
+ setY(moveEvent.clientY - dragY);
1627
+ }
1628
+ function handleMouseUp(upEvent) {
1629
+ killEvent(upEvent);
1630
+ document.removeEventListener('mouseup', handleMouseUp, true);
1631
+ document.removeEventListener('mousemove', handleMouseMove, true);
1632
+ }
1633
+ document.addEventListener('mouseup', handleMouseUp, true);
1634
+ document.addEventListener('mousemove', handleMouseMove, true);
1635
+ }
1636
+ return (React__default["default"].createElement(React__default["default"].Fragment, null,
1637
+ React__default["default"].createElement("div", { className: "modal-dialog-bg" }),
1638
+ React__default["default"].createElement("div", { className: "modal-dialog", "data-testid": "dialog", tabIndex: 0, style: { left: x + 'px', top: y + 'px' } },
1639
+ React__default["default"].createElement("div", { className: "modal-dialog-title", onMouseDown: (e) => handleMouseDown(e) },
1640
+ React__default["default"].createElement("span", { className: "modal-dialog-title-text" }, props.title),
1641
+ React__default["default"].createElement("span", { className: "modal-dialog-title-close", tabIndex: 0, onClick: props.onCancel },
1642
+ React__default["default"].createElement("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor" },
1643
+ React__default["default"].createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" })))),
1644
+ React__default["default"].createElement("div", { className: "modal-dialog-content" }, props.children),
1645
+ React__default["default"].createElement("div", { className: "modal-dialog-buttons" },
1646
+ React__default["default"].createElement(Button, { testid: "dialog-ok", onClick: props.onOk }, "OK"),
1647
+ React__default["default"].createElement(Button, { testid: "dialog-cancel", onClick: props.onCancel }, "Cancel")))));
1648
+ }
1649
+
1650
+ const daysOfWeek = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
1651
+ function TimingInput(props) {
1652
+ const [value, setValue] = React.useState(props.defaultValue || {});
1653
+ const [open, setOpen] = React.useState(false);
1654
+ const valueRef = React.useRef();
1655
+ valueRef.current = value;
1656
+ return (React__default["default"].createElement(React__default["default"].Fragment, null,
1657
+ React__default["default"].createElement(InputRow, null,
1658
+ React__default["default"].createElement("span", null, core.formatTiming(valueRef.current) || 'No repeat'),
1659
+ React__default["default"].createElement(Button, { onClick: () => setOpen(true) }, "Edit")),
1660
+ React__default["default"].createElement(TimingEditorDialog, { visible: open, defaultValue: valueRef.current, onOk: (newValue) => {
1661
+ if (props.onChange) {
1662
+ props.onChange(newValue);
1663
+ }
1664
+ setValue(newValue);
1665
+ setOpen(false);
1666
+ }, onCancel: () => setOpen(false) })));
1667
+ }
1668
+ function TimingEditorDialog(props) {
1669
+ var _a, _b;
1670
+ const [value, setValue] = React.useState(props.defaultValue || {});
1671
+ const valueRef = React.useRef();
1672
+ valueRef.current = value;
1673
+ function setStart(newStart) {
1674
+ setValue(Object.assign(Object.assign({}, valueRef.current), { event: [newStart] }));
1675
+ }
1676
+ function setRepeat(repeat) {
1677
+ setValue(Object.assign(Object.assign({}, valueRef.current), { repeat }));
1678
+ }
1679
+ function setPeriod(newPeriod) {
1680
+ var _a;
1681
+ setRepeat(Object.assign(Object.assign({}, (_a = valueRef.current) === null || _a === void 0 ? void 0 : _a.repeat), { period: newPeriod }));
1682
+ }
1683
+ function setPeriodUnit(newPeriodUnit) {
1684
+ var _a;
1685
+ setRepeat(Object.assign(Object.assign({}, (_a = valueRef.current) === null || _a === void 0 ? void 0 : _a.repeat), { periodUnit: newPeriodUnit }));
1686
+ }
1687
+ function setDayOfWeek(day, enabled) {
1688
+ if (enabled) {
1689
+ addDayOfWeek(day);
1690
+ }
1691
+ else {
1692
+ removeDayOfWeek(day);
1693
+ }
1694
+ }
1695
+ function addDayOfWeek(day) {
1696
+ var _a, _b, _c;
1697
+ const existing = ((_b = (_a = valueRef.current) === null || _a === void 0 ? void 0 : _a.repeat) === null || _b === void 0 ? void 0 : _b.dayOfWeek) || [];
1698
+ if (!existing.includes(day)) {
1699
+ setRepeat(Object.assign(Object.assign({}, (_c = valueRef.current) === null || _c === void 0 ? void 0 : _c.repeat), { dayOfWeek: [...existing, day] }));
1700
+ }
1701
+ }
1702
+ function removeDayOfWeek(day) {
1703
+ var _a, _b, _c;
1704
+ const existing = ((_b = (_a = valueRef.current) === null || _a === void 0 ? void 0 : _a.repeat) === null || _b === void 0 ? void 0 : _b.dayOfWeek) || [];
1705
+ if (existing.includes(day)) {
1706
+ setRepeat(Object.assign(Object.assign({}, (_c = valueRef.current) === null || _c === void 0 ? void 0 : _c.repeat), { dayOfWeek: existing.filter((d) => d !== day) }));
1707
+ }
1708
+ }
1709
+ return (React__default["default"].createElement(Dialog, { title: "Timing", visible: props.visible, onOk: () => props.onOk(value), onCancel: () => props.onCancel() },
1710
+ React__default["default"].createElement("div", { style: { padding: '5px 20px', textAlign: 'left' } },
1711
+ React__default["default"].createElement(FormSection, { title: "Starts on", htmlFor: 'timing-dialog-start' },
1712
+ React__default["default"].createElement(DateTimeInput, { name: 'timing-dialog-start', onChange: (newValue) => setStart(newValue) })),
1713
+ React__default["default"].createElement(FormSection, { title: "Repeat every", htmlFor: 'timing-dialog-period' },
1714
+ React__default["default"].createElement(InputRow, null,
1715
+ React__default["default"].createElement(Input, { type: "number", step: 1, name: 'timing-dialog-period', defaultValue: (_a = value === null || value === void 0 ? void 0 : value.repeat) === null || _a === void 0 ? void 0 : _a.period, onChange: (newValue) => setPeriod(parseInt(newValue)) }),
1716
+ React__default["default"].createElement(Select, { name: 'timing-dialog-periodUnit', defaultValue: (_b = value === null || value === void 0 ? void 0 : value.repeat) === null || _b === void 0 ? void 0 : _b.periodUnit, onChange: (newValue) => setPeriodUnit(newValue) },
1717
+ React__default["default"].createElement("option", { value: "d" }, "day"),
1718
+ React__default["default"].createElement("option", { value: "wk" }, "week"),
1719
+ React__default["default"].createElement("option", { value: "mo" }, "month"),
1720
+ React__default["default"].createElement("option", { value: "a" }, "year")))),
1721
+ React__default["default"].createElement(FormSection, { title: "Repeat on" },
1722
+ React__default["default"].createElement(InputRow, null, daysOfWeek.map((day) => (React__default["default"].createElement(React__default["default"].Fragment, { key: day },
1723
+ React__default["default"].createElement("label", { htmlFor: 'timing-dialog-repeat-' + day }, day.charAt(0).toUpperCase()),
1724
+ React__default["default"].createElement(Checkbox, { name: 'timing-dialog-repeat-' + day, onChange: (newValue) => setDayOfWeek(day, newValue) })))))))));
1725
+ }
1726
+
1610
1727
  function ResourcePropertyInput(props) {
1611
1728
  var _a, _b, _c;
1612
1729
  const property = props.property;
@@ -1719,6 +1836,8 @@
1719
1836
  return React__default["default"].createElement(RatioInput, { name: name, defaultValue: value, onChange: props.onChange });
1720
1837
  case core.PropertyType.Reference:
1721
1838
  return (React__default["default"].createElement(ReferenceInput, { name: name, defaultValue: value, targetTypes: getTargetTypes(property), onChange: props.onChange }));
1839
+ case core.PropertyType.Timing:
1840
+ return React__default["default"].createElement(TimingInput, { name: name, defaultValue: value, onChange: props.onChange });
1722
1841
  default:
1723
1842
  return (React__default["default"].createElement(BackboneElementInput, { typeName: core.buildTypeName((_a = property.path) === null || _a === void 0 ? void 0 : _a.split('.')), defaultValue: value, onChange: props.onChange, outcome: props.outcome }));
1724
1843
  }
@@ -1808,8 +1927,7 @@
1808
1927
  React__default["default"].createElement(ResourceBadge, { value: interpreter, link: true }))))),
1809
1928
  diagnosticReport.issued && (React__default["default"].createElement("dl", null,
1810
1929
  React__default["default"].createElement("dt", null, "Issued"),
1811
- React__default["default"].createElement("dd", null,
1812
- React__default["default"].createElement(DateTimeDisplay, { value: diagnosticReport.issued })))),
1930
+ React__default["default"].createElement("dd", null, core.formatDateTime(diagnosticReport.issued)))),
1813
1931
  diagnosticReport.status && (React__default["default"].createElement("dl", null,
1814
1932
  React__default["default"].createElement("dt", null, "Status"),
1815
1933
  React__default["default"].createElement("dd", null, core.capitalize(diagnosticReport.status))))),
@@ -1938,7 +2056,7 @@
1938
2056
  const medplum = useMedplum();
1939
2057
  const [schema, setSchema] = React.useState();
1940
2058
  React.useEffect(() => {
1941
- medplum.requestSchema(props.original.resourceType).then(setSchema);
2059
+ medplum.requestSchema(props.original.resourceType).then(setSchema).catch(console.log);
1942
2060
  }, [medplum, props.original.resourceType]);
1943
2061
  if (!schema) {
1944
2062
  return null;
@@ -1991,7 +2109,7 @@
1991
2109
  const [schema, setSchema] = React.useState();
1992
2110
  React.useEffect(() => {
1993
2111
  if (value) {
1994
- medplum.requestSchema(value.resourceType).then(setSchema);
2112
+ medplum.requestSchema(value.resourceType).then(setSchema).catch(console.log);
1995
2113
  }
1996
2114
  }, [medplum, value]);
1997
2115
  if (!schema || !value) {
@@ -2104,8 +2222,7 @@
2104
2222
  React__default["default"].createElement("div", { className: "medplum-timeline-item-title" },
2105
2223
  React__default["default"].createElement(ResourceName, { value: author, link: true }),
2106
2224
  React__default["default"].createElement("div", { className: "medplum-timeline-item-subtitle" },
2107
- React__default["default"].createElement(MedplumLink, { to: props.resource },
2108
- React__default["default"].createElement(DateTimeDisplay, { value: (_c = props.resource.meta) === null || _c === void 0 ? void 0 : _c.lastUpdated })),
2225
+ React__default["default"].createElement(MedplumLink, { to: props.resource }, core.formatDateTime((_c = props.resource.meta) === null || _c === void 0 ? void 0 : _c.lastUpdated)),
2109
2226
  React__default["default"].createElement("span", null, "\u00B7"),
2110
2227
  React__default["default"].createElement(MedplumLink, { to: props.resource }, props.resource.resourceType))),
2111
2228
  props.popupMenuItems && (React__default["default"].createElement("div", { className: "medplum-timeline-item-actions" },
@@ -2190,7 +2307,7 @@
2190
2307
  setHistory({});
2191
2308
  return;
2192
2309
  }
2193
- medplum.executeBatch(buildSearchRequests(resource)).then(handleBatchResponse);
2310
+ medplum.executeBatch(buildSearchRequests(resource)).then(handleBatchResponse).catch(console.log);
2194
2311
  }, [medplum, resource, buildSearchRequests]);
2195
2312
  React.useEffect(() => {
2196
2313
  loadTimeline();
@@ -2241,9 +2358,12 @@
2241
2358
  // Encounter not loaded yet
2242
2359
  return;
2243
2360
  }
2244
- medplum.createResource(props.createCommunication(resource, sender, contentString)).then((result) => {
2361
+ medplum
2362
+ .createResource(props.createCommunication(resource, sender, contentString))
2363
+ .then((result) => {
2245
2364
  addResources([result]);
2246
- });
2365
+ })
2366
+ .catch(console.log);
2247
2367
  }
2248
2368
  /**
2249
2369
  * Adds a Media resource to the timeline.
@@ -2254,18 +2374,21 @@
2254
2374
  // Encounter not loaded yet
2255
2375
  return;
2256
2376
  }
2257
- medplum.createResource(props.createMedia(resource, sender, attachment)).then((result) => {
2377
+ medplum
2378
+ .createResource(props.createMedia(resource, sender, attachment))
2379
+ .then((result) => {
2258
2380
  addResources([result]);
2259
- });
2381
+ })
2382
+ .catch(console.log);
2260
2383
  }
2261
2384
  function setPriority(communication, priority) {
2262
2385
  return medplum.updateResource(Object.assign(Object.assign({}, communication), { priority }));
2263
2386
  }
2264
2387
  function onPin(communication) {
2265
- setPriority(communication, 'stat').then(loadTimeline);
2388
+ setPriority(communication, 'stat').then(loadTimeline).catch(console.log);
2266
2389
  }
2267
2390
  function onUnpin(communication) {
2268
- setPriority(communication, 'routine').then(loadTimeline);
2391
+ setPriority(communication, 'routine').then(loadTimeline).catch(console.log);
2269
2392
  }
2270
2393
  function onDetails(timelineItem) {
2271
2394
  navigate(`/${timelineItem.resourceType}/${timelineItem.id}`);
@@ -2551,43 +2674,6 @@
2551
2674
  return { name };
2552
2675
  }
2553
2676
 
2554
- function Dialog(props) {
2555
- const [x, setX] = React.useState(100);
2556
- const [y, setY] = React.useState(100);
2557
- if (!props.visible) {
2558
- return null;
2559
- }
2560
- function handleMouseDown(downEvent) {
2561
- killEvent(downEvent);
2562
- const dragX = downEvent.clientX - x;
2563
- const dragY = downEvent.clientY - y;
2564
- function handleMouseMove(moveEvent) {
2565
- killEvent(moveEvent);
2566
- setX(moveEvent.clientX - dragX);
2567
- setY(moveEvent.clientY - dragY);
2568
- }
2569
- function handleMouseUp(upEvent) {
2570
- killEvent(upEvent);
2571
- document.removeEventListener('mouseup', handleMouseUp, true);
2572
- document.removeEventListener('mousemove', handleMouseMove, true);
2573
- }
2574
- document.addEventListener('mouseup', handleMouseUp, true);
2575
- document.addEventListener('mousemove', handleMouseMove, true);
2576
- }
2577
- return (React__default["default"].createElement(React__default["default"].Fragment, null,
2578
- React__default["default"].createElement("div", { className: "modal-dialog-bg" }),
2579
- React__default["default"].createElement("div", { className: "modal-dialog", "data-testid": "dialog", tabIndex: 0, style: { left: x + 'px', top: y + 'px' } },
2580
- React__default["default"].createElement("div", { className: "modal-dialog-title", onMouseDown: (e) => handleMouseDown(e) },
2581
- React__default["default"].createElement("span", { className: "modal-dialog-title-text" }, props.title),
2582
- React__default["default"].createElement("span", { className: "modal-dialog-title-close", tabIndex: 0, onClick: props.onCancel },
2583
- React__default["default"].createElement("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor" },
2584
- React__default["default"].createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" })))),
2585
- React__default["default"].createElement("div", { className: "modal-dialog-content" }, props.children),
2586
- React__default["default"].createElement("div", { className: "modal-dialog-buttons" },
2587
- React__default["default"].createElement(Button, { testid: "dialog-ok", onClick: props.onOk }, "OK"),
2588
- React__default["default"].createElement(Button, { testid: "dialog-cancel", onClick: props.onCancel }, "Cancel")))));
2589
- }
2590
-
2591
2677
  const searchParamToOperators = {
2592
2678
  string: [core.Operator.EQUALS, core.Operator.NOT, core.Operator.CONTAINS, core.Operator.EXACT],
2593
2679
  fulltext: [core.Operator.EQUALS, core.Operator.NOT, core.Operator.CONTAINS, core.Operator.EXACT],
@@ -3023,7 +3109,7 @@
3023
3109
  return (_a = resource.meta) === null || _a === void 0 ? void 0 : _a.versionId;
3024
3110
  }
3025
3111
  if (key === '_lastUpdated') {
3026
- return React__default["default"].createElement(DateTimeDisplay, { value: (_b = resource.meta) === null || _b === void 0 ? void 0 : _b.lastUpdated });
3112
+ return core.formatDateTime((_b = resource.meta) === null || _b === void 0 ? void 0 : _b.lastUpdated);
3027
3113
  }
3028
3114
  // Priority 1: ElementDefinition by exact match
3029
3115
  if (field.elementDefinition && `${resource.resourceType}.${field.name}` === field.elementDefinition.path) {
@@ -3263,7 +3349,7 @@
3263
3349
  return React__default["default"].createElement(ResourceName, { value: { reference: filter.value } });
3264
3350
  }
3265
3351
  if (props.filter.code === '_lastUpdated' || (searchParam === null || searchParam === void 0 ? void 0 : searchParam.type) === 'datetime') {
3266
- return React__default["default"].createElement(DateTimeDisplay, { value: filter.value });
3352
+ return React__default["default"].createElement(React__default["default"].Fragment, null, core.formatDateTime(filter.value));
3267
3353
  }
3268
3354
  return React__default["default"].createElement(React__default["default"].Fragment, null, filter.value);
3269
3355
  }
@@ -3727,11 +3813,14 @@
3727
3813
  }
3728
3814
  }
3729
3815
  React.useEffect(() => {
3730
- medplum.requestSchema(props.search.resourceType).then((newSchema) => {
3816
+ medplum
3817
+ .requestSchema(props.search.resourceType)
3818
+ .then((newSchema) => {
3731
3819
  // The schema could have the same object identity,
3732
3820
  // so need to use the spread operator to kick React re-render.
3733
3821
  setSchema(Object.assign({}, newSchema));
3734
- });
3822
+ })
3823
+ .catch(console.log);
3735
3824
  }, [medplum, props.search.resourceType]);
3736
3825
  const typeSchema = (_a = schema === null || schema === void 0 ? void 0 : schema.types) === null || _a === void 0 ? void 0 : _a[props.search.resourceType];
3737
3826
  if (!typeSchema) {
@@ -3915,11 +4004,14 @@
3915
4004
  }
3916
4005
  }
3917
4006
  React.useEffect(() => {
3918
- medplum.requestSchema(props.resourceType).then((newSchema) => {
4007
+ medplum
4008
+ .requestSchema(props.resourceType)
4009
+ .then((newSchema) => {
3919
4010
  // The schema could have the same object identity,
3920
4011
  // so need to use the spread operator to kick React re-render.
3921
4012
  setSchema(Object.assign({}, newSchema));
3922
- });
4013
+ })
4014
+ .catch(console.log);
3923
4015
  }, [medplum, props.resourceType]);
3924
4016
  const typeSchema = (_a = schema === null || schema === void 0 ? void 0 : schema.types) === null || _a === void 0 ? void 0 : _a[props.resourceType];
3925
4017
  if (!typeSchema) {
@@ -3951,31 +4043,6 @@
3951
4043
  return React__default["default"].createElement("div", { className: "medplum-footer" }, props.children);
3952
4044
  }
3953
4045
 
3954
- /******************************************************************************
3955
- Copyright (c) Microsoft Corporation.
3956
-
3957
- Permission to use, copy, modify, and/or distribute this software for any
3958
- purpose with or without fee is hereby granted.
3959
-
3960
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
3961
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
3962
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
3963
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
3964
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
3965
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
3966
- PERFORMANCE OF THIS SOFTWARE.
3967
- ***************************************************************************** */
3968
-
3969
- function __awaiter(thisArg, _arguments, P, generator) {
3970
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3971
- return new (P || (P = Promise))(function (resolve, reject) {
3972
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
3973
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
3974
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
3975
- step((generator = generator.apply(thisArg, _arguments || [])).next());
3976
- });
3977
- }
3978
-
3979
4046
  function HeaderSearchInput(props) {
3980
4047
  const medplum = useMedplum();
3981
4048
  return (React__default["default"].createElement(Autocomplete, { loadOptions: (input, signal) => __awaiter(this, void 0, void 0, function* () {
@@ -4186,9 +4253,13 @@
4186
4253
  logins.map((login) => {
4187
4254
  var _a, _b, _c, _d;
4188
4255
  return ((_a = login.profile) === null || _a === void 0 ? void 0 : _a.reference) !== core.getReferenceString(context.profile) && (React__default["default"].createElement("div", { className: "medplum-nav-menu-profile", key: (_b = login.profile) === null || _b === void 0 ? void 0 : _b.reference, onClick: () => {
4189
- medplum.setActiveLogin(login);
4190
- setUserMenuVisible(false);
4191
- window.location.reload();
4256
+ medplum
4257
+ .setActiveLogin(login)
4258
+ .then(() => {
4259
+ setUserMenuVisible(false);
4260
+ window.location.reload();
4261
+ })
4262
+ .catch(console.log);
4192
4263
  } },
4193
4264
  React__default["default"].createElement("div", { className: "medplum-nav-menu-profile-icon" },
4194
4265
  React__default["default"].createElement(Avatar, null)),
@@ -4274,14 +4345,33 @@
4274
4345
  }
4275
4346
 
4276
4347
  function PlanDefinitionBuilder(props) {
4348
+ const medplum = useMedplum();
4277
4349
  const defaultValue = useResource(props.value);
4350
+ const [schema, setSchema] = React.useState(undefined);
4351
+ const [selectedKey, setSelectedKey] = React.useState();
4352
+ const [hoverKey, setHoverKey] = React.useState();
4278
4353
  const [value, setValue] = React.useState();
4354
+ function handleDocumentMouseOver() {
4355
+ setHoverKey(undefined);
4356
+ }
4357
+ function handleDocumentClick() {
4358
+ setSelectedKey(undefined);
4359
+ }
4279
4360
  const valueRef = React.useRef();
4280
4361
  valueRef.current = value;
4362
+ React.useEffect(() => {
4363
+ medplum.requestSchema('PlanDefinition').then(setSchema).catch(console.log);
4364
+ }, [medplum]);
4281
4365
  React.useEffect(() => {
4282
4366
  setValue(ensurePlanDefinitionKeys(defaultValue !== null && defaultValue !== void 0 ? defaultValue : { resourceType: 'PlanDefinition' }));
4367
+ document.addEventListener('mouseover', handleDocumentMouseOver);
4368
+ document.addEventListener('click', handleDocumentClick);
4369
+ return () => {
4370
+ document.removeEventListener('mouseover', handleDocumentMouseOver);
4371
+ document.removeEventListener('click', handleDocumentClick);
4372
+ };
4283
4373
  }, [defaultValue]);
4284
- if (!value) {
4374
+ if (!schema || !value) {
4285
4375
  return null;
4286
4376
  }
4287
4377
  function changeProperty(property, newValue) {
@@ -4289,9 +4379,9 @@
4289
4379
  }
4290
4380
  return (React__default["default"].createElement("div", { className: "medplum-questionnaire-builder" },
4291
4381
  React__default["default"].createElement(Form, { testid: "questionnaire-form", onSubmit: () => props.onSubmit(value) },
4292
- React__default["default"].createElement(FormSection, { title: "Plan Title", description: "The display name of the 'Plan', something that can be ordered.", htmlFor: "title" },
4382
+ React__default["default"].createElement(FormSection, { title: "Plan Title", htmlFor: "title" },
4293
4383
  React__default["default"].createElement(Input, { defaultValue: value.title, onChange: (newValue) => changeProperty('title', newValue) })),
4294
- React__default["default"].createElement(ActionArrayBuilder, { actions: value.action || [], onChange: (x) => changeProperty('action', x) }),
4384
+ React__default["default"].createElement(ActionArrayBuilder, { actions: value.action || [], selectedKey: selectedKey, setSelectedKey: setSelectedKey, hoverKey: hoverKey, setHoverKey: setHoverKey, onChange: (x) => changeProperty('action', x) }),
4295
4385
  React__default["default"].createElement(Button, { type: "submit", size: "large" }, "Save"))));
4296
4386
  }
4297
4387
  function ActionArrayBuilder(props) {
@@ -4302,75 +4392,102 @@
4302
4392
  }
4303
4393
  function addAction(addedAction) {
4304
4394
  props.onChange([...actionsRef.current, addedAction]);
4395
+ props.setSelectedKey(addedAction.id);
4305
4396
  }
4306
4397
  function removeAction(removedAction) {
4307
4398
  props.onChange(actionsRef.current.filter((i) => i !== removedAction));
4308
4399
  }
4309
4400
  return (React__default["default"].createElement("div", { className: "section" },
4310
- props.actions.map((i) => (React__default["default"].createElement("div", { key: i.id },
4311
- React__default["default"].createElement(ActionBuilder, { action: i, onChange: changeAction, onRemove: () => removeAction(i) })))),
4401
+ props.actions.map((action) => (React__default["default"].createElement("div", { key: action.id },
4402
+ React__default["default"].createElement(ActionBuilder, { action: action, selectedKey: props.selectedKey, setSelectedKey: props.setSelectedKey, hoverKey: props.hoverKey, setHoverKey: props.setHoverKey, onChange: changeAction, onRemove: () => removeAction(action) })))),
4312
4403
  React__default["default"].createElement("div", { className: "bottom-actions" },
4313
4404
  React__default["default"].createElement("a", { href: "#", onClick: (e) => {
4314
- e.preventDefault();
4405
+ killEvent(e);
4315
4406
  addAction({ id: generateId$1() });
4316
4407
  } }, "Add action"))));
4317
4408
  }
4318
4409
  function ActionBuilder(props) {
4319
4410
  const { action } = props;
4320
- const [actionType, setActionType] = React.useState(getInitialActionType(action));
4321
- const actionRef = React.useRef();
4322
- actionRef.current = props.action;
4411
+ const actionType = getInitialActionType(action);
4412
+ const editing = props.selectedKey === props.action.id;
4413
+ const hovering = props.hoverKey === props.action.id;
4414
+ function onClick(e) {
4415
+ e.stopPropagation();
4416
+ props.setSelectedKey(props.action.id);
4417
+ }
4418
+ function onHover(e) {
4419
+ killEvent(e);
4420
+ props.setHoverKey(props.action.id);
4421
+ }
4422
+ const className = editing ? 'section editing' : hovering ? 'section hovering' : 'section';
4423
+ return (React__default["default"].createElement("div", { "data-testid": action.id, className: className, onClick: onClick, onMouseOver: onHover },
4424
+ editing ? (React__default["default"].createElement(ActionEditor, { action: action, actionType: actionType, onChange: props.onChange, selectedKey: props.selectedKey, setSelectedKey: props.setSelectedKey, hoverKey: props.hoverKey, setHoverKey: props.setHoverKey, onRemove: props.onRemove })) : (React__default["default"].createElement(ActionDisplay, { action: action, actionType: actionType })),
4425
+ React__default["default"].createElement("div", { className: "bottom-actions" },
4426
+ React__default["default"].createElement("a", { href: "#", onClick: (e) => {
4427
+ e.preventDefault();
4428
+ props.onRemove();
4429
+ } }, "Remove"))));
4430
+ }
4431
+ const timingProperty = {
4432
+ path: 'PlanDefinition.action.timing[x]',
4433
+ min: 0,
4434
+ max: '1',
4435
+ type: [{ code: 'dateTime' }, { code: 'Period' }, { code: 'Range' }, { code: 'Timing' }],
4436
+ };
4437
+ function ActionDisplay(props) {
4438
+ const { action, actionType } = props;
4439
+ const [propertyValue, propertyType] = getActionTiming(action);
4440
+ return (React__default["default"].createElement("div", null,
4441
+ React__default["default"].createElement("div", null,
4442
+ action.title || 'Untitled',
4443
+ " ",
4444
+ actionType && `(${actionType})`),
4445
+ action.definitionCanonical && (React__default["default"].createElement("div", null,
4446
+ React__default["default"].createElement(ReferenceDisplay, { value: { reference: action.definitionCanonical } }))),
4447
+ propertyValue && (React__default["default"].createElement("div", null,
4448
+ React__default["default"].createElement(ResourcePropertyDisplay, { property: timingProperty, propertyType: propertyType, value: propertyValue })))));
4449
+ }
4450
+ function ActionEditor(props) {
4451
+ const { action } = props;
4452
+ const [actionType, setActionType] = React.useState(props.actionType);
4323
4453
  function changeProperty(property, value) {
4324
- props.onChange(Object.assign(Object.assign({}, actionRef.current), { [property]: value }));
4454
+ props.onChange(Object.assign(Object.assign({}, action), { [property]: value }));
4325
4455
  }
4326
- return (React__default["default"].createElement("div", { className: "section" },
4327
- React__default["default"].createElement(FormSection, { title: "Action Title", description: "The name of the action, an operational task to be completed.", htmlFor: `actionTitle-${action.id}` },
4456
+ return (React__default["default"].createElement(React__default["default"].Fragment, null,
4457
+ React__default["default"].createElement(FormSection, { title: "Title", htmlFor: `actionTitle-${action.id}` },
4328
4458
  React__default["default"].createElement(Input, { name: `actionTitle-${action.id}`, defaultValue: action.title, onChange: (newValue) => changeProperty('title', newValue) })),
4329
- React__default["default"].createElement(FormSection, { title: "Action Type", description: "The type of the action to be performed.", htmlFor: `actionType-${action.id}` },
4459
+ React__default["default"].createElement(FormSection, { title: "Type of Action", description: "The type of the action to be performed.", htmlFor: `actionType-${action.id}` },
4330
4460
  React__default["default"].createElement(Select, { name: `actionType-${action.id}`, defaultValue: actionType, onChange: setActionType },
4331
4461
  React__default["default"].createElement("option", null),
4332
4462
  React__default["default"].createElement("option", { value: "appointment" }, "Appointment"),
4333
- React__default["default"].createElement("option", { value: "documentation" }, "Documentation"),
4334
4463
  React__default["default"].createElement("option", { value: "lab" }, "Lab"),
4335
4464
  React__default["default"].createElement("option", { value: "questionnaire" }, "Questionnaire"),
4336
- React__default["default"].createElement("option", { value: "shipping" }, "Shipping"),
4337
4465
  React__default["default"].createElement("option", { value: "task" }, "Task"))),
4338
- action.action && action.action.length > 0 && (React__default["default"].createElement(ActionArrayBuilder, { actions: action.action, onChange: (x) => changeProperty('action', x) })),
4466
+ action.action && action.action.length > 0 && (React__default["default"].createElement(ActionArrayBuilder, { actions: action.action, selectedKey: props.selectedKey, setSelectedKey: props.setSelectedKey, hoverKey: props.hoverKey, setHoverKey: props.setHoverKey, onChange: (x) => changeProperty('action', x) })),
4339
4467
  (() => {
4340
4468
  switch (actionType) {
4341
4469
  case 'appointment':
4342
- return React__default["default"].createElement("div", null, "Appointment details");
4343
- case 'documentation':
4344
- return React__default["default"].createElement("div", null, "Documentation details");
4470
+ return (React__default["default"].createElement(ActionResourceTypeBuilder, { title: "Appointment", description: "The subject must schedule an appointment from the schedule.", resourceType: "Schedule", action: action, onChange: props.onChange }));
4345
4471
  case 'lab':
4346
- return React__default["default"].createElement(LabActionBuilder, { action: action, onChange: props.onChange });
4472
+ return (React__default["default"].createElement(ActionResourceTypeBuilder, { title: "Lab", description: "The subject must complete the following lab panel.", resourceType: "ActivityDefinition", action: action, onChange: props.onChange }));
4347
4473
  case 'questionnaire':
4348
- return React__default["default"].createElement(QuestionnaireActionBuilder, { action: action, onChange: props.onChange });
4349
- case 'shipping':
4350
- return React__default["default"].createElement("div", null, "Shipping details");
4474
+ return (React__default["default"].createElement(ActionResourceTypeBuilder, { title: "Questionnaire", description: "The subject must complete the selected questionnaire.", resourceType: "Questionnaire", action: action, onChange: props.onChange }));
4351
4475
  case 'task':
4352
- return React__default["default"].createElement("div", null, "Task details");
4476
+ return (React__default["default"].createElement(ActionResourceTypeBuilder, { title: "Task", description: "The subject must complete the following task.", resourceType: "ActivityDefinition", action: action, onChange: props.onChange }));
4353
4477
  default:
4354
4478
  return null;
4355
4479
  }
4356
4480
  })(),
4357
- React__default["default"].createElement("div", { className: "bottom-actions" },
4358
- React__default["default"].createElement("a", { href: "#", onClick: (e) => {
4359
- e.preventDefault();
4360
- props.onRemove();
4361
- } }, "Remove"))));
4481
+ React__default["default"].createElement(FormSection, { title: "Timing", description: "When the action should take place.", htmlFor: 'timing-' + action.id },
4482
+ React__default["default"].createElement(ActionTimingInput, { name: 'timing-' + action.id, action: action, onChange: props.onChange }))));
4362
4483
  }
4363
- function LabActionBuilder(props) {
4364
- return (React__default["default"].createElement(FormSection, { title: "Lab Details", description: "Choose observations definitions", htmlFor: props.action.id },
4365
- React__default["default"].createElement("a", { href: "#", onClick: () => props.onChange(props.action) }, "Add")));
4366
- }
4367
- function QuestionnaireActionBuilder(props) {
4484
+ function ActionResourceTypeBuilder(props) {
4368
4485
  const { id, definitionCanonical } = props.action;
4369
- const questionnaireRef = (definitionCanonical === null || definitionCanonical === void 0 ? void 0 : definitionCanonical.startsWith('Questionnaire/'))
4486
+ const reference = (definitionCanonical === null || definitionCanonical === void 0 ? void 0 : definitionCanonical.startsWith(props.resourceType + '/'))
4370
4487
  ? { reference: definitionCanonical }
4371
4488
  : undefined;
4372
- return (React__default["default"].createElement(FormSection, { title: "Questionnaire", description: "Choose questionnaire", htmlFor: id },
4373
- React__default["default"].createElement(ResourceInput, { name: id, resourceType: "Questionnaire", defaultValue: questionnaireRef, onChange: (newValue) => {
4489
+ return (React__default["default"].createElement(FormSection, { title: props.title, description: props.description, htmlFor: id },
4490
+ React__default["default"].createElement(ResourceInput, { name: id, resourceType: props.resourceType, defaultValue: reference, loadOnFocus: true, onChange: (newValue) => {
4374
4491
  if (newValue) {
4375
4492
  props.onChange(Object.assign(Object.assign({}, props.action), { definitionCanonical: core.getReferenceString(newValue) }));
4376
4493
  }
@@ -4379,13 +4496,30 @@
4379
4496
  }
4380
4497
  } })));
4381
4498
  }
4499
+ function ActionTimingInput(props) {
4500
+ const value = props.action;
4501
+ const key = 'timing';
4502
+ const [propertyValue, propertyType] = getActionTiming(value);
4503
+ return (React__default["default"].createElement(ResourcePropertyInput, { property: timingProperty, name: "timing[x]", defaultValue: propertyValue, defaultPropertyType: propertyType, onChange: (newValue, propName) => {
4504
+ props.onChange(setPropertyValue(value, key, propName !== null && propName !== void 0 ? propName : key, timingProperty, newValue));
4505
+ } }));
4506
+ }
4382
4507
  function getInitialActionType(action) {
4383
- var _a;
4384
- if ((_a = action.definitionCanonical) === null || _a === void 0 ? void 0 : _a.startsWith('Questionnaire/')) {
4508
+ var _a, _b, _c;
4509
+ if ((_a = action.definitionCanonical) === null || _a === void 0 ? void 0 : _a.startsWith('Schedule')) {
4510
+ return 'appointment';
4511
+ }
4512
+ if ((_b = action.definitionCanonical) === null || _b === void 0 ? void 0 : _b.startsWith('Questionnaire/')) {
4385
4513
  return 'questionnaire';
4386
4514
  }
4515
+ if ((_c = action.definitionCanonical) === null || _c === void 0 ? void 0 : _c.startsWith('ActivityDefinition/')) {
4516
+ return 'task';
4517
+ }
4387
4518
  return undefined;
4388
4519
  }
4520
+ function getActionTiming(action) {
4521
+ return getValueAndType({ type: 'PlanDefinitionAction', value: action }, 'timing');
4522
+ }
4389
4523
  let nextId$1 = 1;
4390
4524
  /**
4391
4525
  * Generates a unique ID.
@@ -4522,7 +4656,7 @@
4522
4656
  const questionnaire = useResource(props.questionnaire);
4523
4657
  const [response, setResponse] = React.useState();
4524
4658
  React.useEffect(() => {
4525
- medplum.requestSchema('Questionnaire').then(setSchema);
4659
+ medplum.requestSchema('Questionnaire').then(setSchema).catch(console.log);
4526
4660
  }, [medplum]);
4527
4661
  React.useEffect(() => {
4528
4662
  setResponse(questionnaire ? buildInitialResponse(questionnaire) : undefined);
@@ -4565,6 +4699,7 @@
4565
4699
  return (React__default["default"].createElement(CheckboxFormSection, { key: item.linkId, title: item.text, htmlFor: item.linkId },
4566
4700
  React__default["default"].createElement(Checkbox, { name: item.linkId, defaultValue: initial === null || initial === void 0 ? void 0 : initial.valueBoolean, onChange: (newValue) => setResponseItem(index, {
4567
4701
  linkId: item.linkId,
4702
+ text: item.text,
4568
4703
  answer: [{ valueBoolean: newValue }],
4569
4704
  }) })));
4570
4705
  }
@@ -4586,12 +4721,14 @@
4586
4721
  function onChangeItem(newResponseItems) {
4587
4722
  props.onChange({
4588
4723
  linkId: item.linkId,
4724
+ text: item.text,
4589
4725
  item: newResponseItems,
4590
4726
  });
4591
4727
  }
4592
4728
  function onChangeAnswer(newResponseAnswer) {
4593
4729
  props.onChange({
4594
4730
  linkId: item.linkId,
4731
+ text: item.text,
4595
4732
  answer: [newResponseAnswer],
4596
4733
  });
4597
4734
  }
@@ -4692,6 +4829,7 @@
4692
4829
  var _a, _b;
4693
4830
  return {
4694
4831
  linkId: item.linkId,
4832
+ text: item.text,
4695
4833
  item: buildInitialResponseItems(item.item),
4696
4834
  answer: (_b = (_a = item.initial) === null || _a === void 0 ? void 0 : _a.map(buildInitialResponseAnswer)) !== null && _b !== void 0 ? _b : [],
4697
4835
  };
@@ -4724,7 +4862,7 @@
4724
4862
  setSelectedKey(undefined);
4725
4863
  }
4726
4864
  React.useEffect(() => {
4727
- medplum.requestSchema('Questionnaire').then(setSchema);
4865
+ medplum.requestSchema('Questionnaire').then(setSchema).catch(console.log);
4728
4866
  }, [medplum]);
4729
4867
  React.useEffect(() => {
4730
4868
  setValue(ensureQuestionnaireKeys(defaultValue !== null && defaultValue !== void 0 ? defaultValue : { resourceType: 'Questionnaire' }));
@@ -4958,7 +5096,7 @@
4958
5096
  return clientId;
4959
5097
  }
4960
5098
  const origin = window.location.protocol + '//' + window.location.host;
4961
- const authorizedOrigins = (_b = (_a = "http://localhost:3000,http://localhost:6006,https://app.medplum.com,https://docs.medplum.com") === null || _a === void 0 ? void 0 : _a.split(',')) !== null && _b !== void 0 ? _b : [];
5099
+ const authorizedOrigins = (_b = (_a = "http://localhost:3000,http://127.0.0.1:3000,http://localhost:6006,http://127.0.0.1:6006,https://app.medplum.com,https://docs.medplum.com") === null || _a === void 0 ? void 0 : _a.split(',')) !== null && _b !== void 0 ? _b : [];
4962
5100
  if (authorizedOrigins.includes(origin)) {
4963
5101
  return "921088377005-3j1sa10vr6hj86jgmdfh2l53v3mp7lfi.apps.googleusercontent.com";
4964
5102
  }
@@ -4981,10 +5119,15 @@
4981
5119
  * @returns Promise to a recaptcha token for the current user.
4982
5120
  */
4983
5121
  function getRecaptcha(siteKey) {
4984
- return new Promise((resolve) => {
4985
- grecaptcha.ready(() => {
4986
- grecaptcha.execute(siteKey, { action: 'submit' }).then(resolve);
4987
- });
5122
+ return new Promise((resolve, reject) => {
5123
+ grecaptcha.ready(() => __awaiter(this, void 0, void 0, function* () {
5124
+ try {
5125
+ resolve(yield grecaptcha.execute(siteKey, { action: 'submit' }));
5126
+ }
5127
+ catch (err) {
5128
+ reject(err);
5129
+ }
5130
+ }));
4988
5131
  });
4989
5132
  }
4990
5133
 
@@ -5017,9 +5160,19 @@
5017
5160
  React__default["default"].createElement(Form, { style: { maxWidth: 400 }, onSubmit: (formData) => __awaiter(this, void 0, void 0, function* () {
5018
5161
  try {
5019
5162
  const recaptchaToken = yield getRecaptcha(recaptchaSiteKey);
5020
- const registerRequest = Object.assign(Object.assign({}, formData), { recaptchaToken });
5163
+ const registerRequest = {
5164
+ projectId: props.projectId,
5165
+ projectName: formData.projectName,
5166
+ firstName: formData.firstName,
5167
+ lastName: formData.lastName,
5168
+ email: formData.email,
5169
+ password: formData.password,
5170
+ remember: formData.remember === 'true',
5171
+ recaptchaSiteKey,
5172
+ recaptchaToken,
5173
+ };
5021
5174
  const userLogin = yield medplum.startNewUser(registerRequest);
5022
- handleAuthResponse(registerRequest, userLogin);
5175
+ yield handleAuthResponse(registerRequest, userLogin);
5023
5176
  }
5024
5177
  catch (err) {
5025
5178
  setOutcome(err);
@@ -5041,11 +5194,12 @@
5041
5194
  const userLogin = yield medplum.startGoogleLogin(loginRequest);
5042
5195
  const googleClaims = core.parseJWTPayload(loginRequest.googleCredential);
5043
5196
  const registerRequest = {
5197
+ projectId: props.projectId,
5044
5198
  firstName: googleClaims.given_name,
5045
5199
  lastName: googleClaims.family_name,
5046
5200
  email: googleClaims.email,
5047
5201
  };
5048
- handleAuthResponse(registerRequest, userLogin);
5202
+ yield handleAuthResponse(registerRequest, userLogin);
5049
5203
  }
5050
5204
  catch (err) {
5051
5205
  setOutcome(err);
@@ -5095,7 +5249,7 @@
5095
5249
  const [responseBundle, setResponseBundle] = React.useState();
5096
5250
  React.useEffect(() => {
5097
5251
  if (requestGroup && !startedLoading) {
5098
- medplum.executeBatch(buildBatchRequest(requestGroup)).then(setResponseBundle);
5252
+ medplum.executeBatch(buildBatchRequest(requestGroup)).then(setResponseBundle).catch(console.log);
5099
5253
  setStartedLoading(true);
5100
5254
  }
5101
5255
  }, [medplum, requestGroup, startedLoading]);
@@ -5115,7 +5269,7 @@
5115
5269
  "Last edited by\u00A0",
5116
5270
  React__default["default"].createElement(ResourceName, { value: (_e = task === null || task === void 0 ? void 0 : task.meta) === null || _e === void 0 ? void 0 : _e.author }),
5117
5271
  "\u00A0on\u00A0",
5118
- React__default["default"].createElement(DateTimeDisplay, { value: (_f = task === null || task === void 0 ? void 0 : task.meta) === null || _f === void 0 ? void 0 : _f.lastUpdated })),
5272
+ core.formatDateTime((_f = task === null || task === void 0 ? void 0 : task.meta) === null || _f === void 0 ? void 0 : _f.lastUpdated)),
5119
5273
  React__default["default"].createElement("div", null,
5120
5274
  "Status: ",
5121
5275
  React__default["default"].createElement(StatusBadge, { status: (task === null || task === void 0 ? void 0 : task.status) || 'unknown' }))),
@@ -5340,7 +5494,7 @@
5340
5494
  const [value, setValue] = React.useState(props.history);
5341
5495
  React.useEffect(() => {
5342
5496
  if (!props.history && props.resourceType && props.id) {
5343
- medplum.readHistory(props.resourceType, props.id).then((result) => setValue(result));
5497
+ medplum.readHistory(props.resourceType, props.id).then(setValue).catch(console.log);
5344
5498
  }
5345
5499
  }, [medplum, props.history, props.resourceType, props.id]);
5346
5500
  if (!value) {
@@ -5418,7 +5572,10 @@
5418
5572
  const [value, setValue] = React.useState(props.history);
5419
5573
  React.useEffect(() => {
5420
5574
  if (!props.history && props.resourceType && props.id) {
5421
- medplum.readHistory(props.resourceType, props.id).then((result) => setValue(result));
5575
+ medplum
5576
+ .readHistory(props.resourceType, props.id)
5577
+ .then(setValue)
5578
+ .catch(console.log);
5422
5579
  }
5423
5580
  }, [medplum, props.history, props.resourceType, props.id]);
5424
5581
  if (!value) {
@@ -5440,8 +5597,7 @@
5440
5597
  return (React__default["default"].createElement("tr", null,
5441
5598
  React__default["default"].createElement("td", null,
5442
5599
  React__default["default"].createElement(ResourceBadge, { value: (_a = props.version.meta) === null || _a === void 0 ? void 0 : _a.author, link: true })),
5443
- React__default["default"].createElement("td", null,
5444
- React__default["default"].createElement(DateTimeDisplay, { value: (_b = props.version.meta) === null || _b === void 0 ? void 0 : _b.lastUpdated })),
5600
+ React__default["default"].createElement("td", null, core.formatDateTime((_b = props.version.meta) === null || _b === void 0 ? void 0 : _b.lastUpdated)),
5445
5601
  React__default["default"].createElement("td", null,
5446
5602
  React__default["default"].createElement(MedplumLink, { to: getVersionUrl(props.version) }, (_c = props.version.meta) === null || _c === void 0 ? void 0 : _c.versionId))));
5447
5603
  }
@@ -5459,12 +5615,14 @@
5459
5615
  return date.toLocaleString('default', { month: 'long' }) + ' ' + date.getFullYear();
5460
5616
  }
5461
5617
  function CalendarInput(props) {
5618
+ const { onChangeMonth, onClick } = props;
5462
5619
  const [month, setMonth] = React.useState(getStartMonth);
5463
5620
  function moveMonth(delta) {
5464
5621
  setMonth((currMonth) => {
5465
- const prevMonth = new Date(currMonth.getTime());
5466
- prevMonth.setMonth(currMonth.getMonth() + delta);
5467
- return prevMonth;
5622
+ const newMonth = new Date(currMonth.getTime());
5623
+ newMonth.setMonth(currMonth.getMonth() + delta);
5624
+ onChangeMonth(newMonth);
5625
+ return newMonth;
5468
5626
  });
5469
5627
  }
5470
5628
  const grid = React.useMemo(() => buildGrid(month, props.slots), [month, props.slots]);
@@ -5484,7 +5642,7 @@
5484
5642
  React__default["default"].createElement("th", null, "THU"),
5485
5643
  React__default["default"].createElement("th", null, "FRI"),
5486
5644
  React__default["default"].createElement("th", null, "SAT"))),
5487
- React__default["default"].createElement("tbody", null, grid.map((week, weekIndex) => (React__default["default"].createElement("tr", { key: 'week-' + weekIndex }, week.map((day, dayIndex) => (React__default["default"].createElement("td", { key: 'day-' + dayIndex }, day && (React__default["default"].createElement("button", { disabled: !day.available, onClick: () => props.onClick(day.date) }, day.date.getDate()))))))))))));
5645
+ React__default["default"].createElement("tbody", null, grid.map((week, weekIndex) => (React__default["default"].createElement("tr", { key: 'week-' + weekIndex }, week.map((day, dayIndex) => (React__default["default"].createElement("td", { key: 'day-' + dayIndex }, day && (React__default["default"].createElement("button", { disabled: !day.available, onClick: () => onClick(day.date) }, day.date.getDate()))))))))))));
5488
5646
  }
5489
5647
  function getStartMonth() {
5490
5648
  const result = new Date();
@@ -5503,7 +5661,6 @@
5503
5661
  while (d.getMonth() === startDate.getMonth()) {
5504
5662
  row.push({
5505
5663
  date: new Date(d.getTime()),
5506
- // available: isAvailable(d),
5507
5664
  available: isDayAvailable(d, slots),
5508
5665
  });
5509
5666
  if (d.getDay() === 6) {
@@ -5547,20 +5704,27 @@
5547
5704
  const [slots, setSlots] = React.useState();
5548
5705
  const slotsRef = React.useRef();
5549
5706
  slotsRef.current = slots;
5707
+ const [month, setMonth] = React.useState(getStartMonth());
5550
5708
  const [date, setDate] = React.useState();
5551
5709
  const [slot, setSlot] = React.useState();
5552
5710
  const [info, setInfo] = React.useState();
5553
5711
  const [form, setForm] = React.useState();
5554
5712
  React.useEffect(() => {
5555
5713
  if (schedule) {
5556
- medplum.search('Slot', 'schedule=' + core.getReferenceString(schedule)).then((bundle) => {
5557
- setSlots(bundle.entry.map((entry) => entry.resource));
5558
- });
5714
+ setSlots([]);
5715
+ medplum
5716
+ .searchResources('Slot', new URLSearchParams([
5717
+ ['schedule', core.getReferenceString(schedule)],
5718
+ ['start', 'gt' + month.toISOString()],
5719
+ ['start', 'lt' + new Date(month.getTime() + 31 * 24 * 60 * 60 * 1000).toISOString()],
5720
+ ]))
5721
+ .then(setSlots)
5722
+ .catch(console.log);
5559
5723
  }
5560
5724
  else {
5561
5725
  setSlots(undefined);
5562
5726
  }
5563
- }, [medplum, schedule]);
5727
+ }, [medplum, schedule, month]);
5564
5728
  if (!schedule || !slots) {
5565
5729
  return null;
5566
5730
  }
@@ -5576,7 +5740,7 @@
5576
5740
  React__default["default"].createElement("div", { className: "medplum-calendar-selection-pane" },
5577
5741
  !date && (React__default["default"].createElement("div", null,
5578
5742
  React__default["default"].createElement("h3", null, "Select date"),
5579
- React__default["default"].createElement(CalendarInput, { slots: slots, onClick: setDate }))),
5743
+ React__default["default"].createElement(CalendarInput, { slots: slots, onChangeMonth: setMonth, onClick: setDate }))),
5580
5744
  date && !slot && (React__default["default"].createElement("div", null,
5581
5745
  React__default["default"].createElement("h3", null, "Select time"),
5582
5746
  slots.map((s) => {
@@ -5761,7 +5925,8 @@
5761
5925
  login: props.login,
5762
5926
  profile: membership.id,
5763
5927
  })
5764
- .then(props.handleAuthResponse);
5928
+ .then(props.handleAuthResponse)
5929
+ .catch(console.log);
5765
5930
  } },
5766
5931
  React__default["default"].createElement("div", { className: "medplum-nav-menu-profile-icon" },
5767
5932
  React__default["default"].createElement(Avatar, { alt: (_a = membership.profile) === null || _a === void 0 ? void 0 : _a.display })),
@@ -5835,7 +6000,6 @@
5835
6000
  exports.ContactDetailInput = ContactDetailInput;
5836
6001
  exports.ContactPointDisplay = ContactPointDisplay;
5837
6002
  exports.ContactPointInput = ContactPointInput;
5838
- exports.DateTimeDisplay = DateTimeDisplay;
5839
6003
  exports.DateTimeInput = DateTimeInput;
5840
6004
  exports.DefaultResourceTimeline = DefaultResourceTimeline;
5841
6005
  exports.DiagnosticReportDisplay = DiagnosticReportDisplay;