@medplum/react 0.9.28 → 0.9.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/AddressDisplay.d.ts +6 -0
- package/dist/cjs/AddressInput.d.ts +8 -0
- package/dist/cjs/AnnotationInput.d.ts +8 -0
- package/dist/cjs/AttachmentArrayDisplay.d.ts +7 -0
- package/dist/cjs/AttachmentArrayInput.d.ts +9 -0
- package/dist/cjs/AttachmentDisplay.d.ts +7 -0
- package/dist/cjs/AttachmentInput.d.ts +9 -0
- package/dist/cjs/Autocomplete.d.ts +20 -0
- package/dist/cjs/Avatar.d.ts +12 -0
- package/dist/cjs/BackboneElementDisplay.d.ts +9 -0
- package/dist/cjs/BackboneElementInput.d.ts +9 -0
- package/dist/cjs/Button.d.ts +15 -0
- package/dist/cjs/CalendarInput.d.ts +16 -0
- package/dist/cjs/Checkbox.d.ts +12 -0
- package/dist/cjs/CheckboxFormSection.d.ts +9 -0
- package/dist/cjs/CodeInput.d.ts +9 -0
- package/dist/cjs/CodeableConceptDisplay.d.ts +6 -0
- package/dist/cjs/CodeableConceptInput.d.ts +9 -0
- package/dist/cjs/CodingDisplay.d.ts +6 -0
- package/dist/cjs/CodingInput.d.ts +9 -0
- package/dist/cjs/ContactDetailDisplay.d.ts +6 -0
- package/dist/cjs/ContactDetailInput.d.ts +8 -0
- package/dist/cjs/ContactPointDisplay.d.ts +6 -0
- package/dist/cjs/ContactPointInput.d.ts +8 -0
- package/dist/cjs/DateTimeInput.d.ts +23 -0
- package/dist/cjs/DefaultResourceTimeline.d.ts +6 -0
- package/dist/cjs/DescriptionList.d.ts +12 -0
- package/dist/cjs/DiagnosticReportDisplay.d.ts +12 -0
- package/dist/cjs/Dialog.d.ts +10 -0
- package/dist/cjs/Document.d.ts +7 -0
- package/dist/cjs/EncounterTimeline.d.ts +6 -0
- package/dist/cjs/ErrorBoundary.d.ts +18 -0
- package/dist/cjs/ExtensionInput.d.ts +8 -0
- package/dist/cjs/FhirPathDisplay.d.ts +9 -0
- package/dist/cjs/FhirPathTable.d.ts +29 -0
- package/dist/cjs/FooterLinks.d.ts +6 -0
- package/dist/cjs/Form.d.ts +8 -0
- package/dist/cjs/FormSection.d.ts +11 -0
- package/dist/cjs/FormUtils.d.ts +5 -0
- package/dist/cjs/GoogleButton.d.ts +8 -0
- package/dist/cjs/Header.d.ts +12 -0
- package/dist/cjs/HeaderSearchInput.d.ts +10 -0
- package/dist/cjs/HumanNameDisplay.d.ts +8 -0
- package/dist/cjs/HumanNameInput.d.ts +8 -0
- package/dist/cjs/IdentifierDisplay.d.ts +6 -0
- package/dist/cjs/IdentifierInput.d.ts +8 -0
- package/dist/cjs/Input.d.ts +22 -0
- package/dist/cjs/InputRow.d.ts +7 -0
- package/dist/cjs/Loading.d.ts +3 -0
- package/dist/cjs/Logo.d.ts +6 -0
- package/dist/cjs/MedplumLink.d.ts +13 -0
- package/dist/cjs/MedplumProvider.d.ts +34 -0
- package/dist/cjs/MenuItem.d.ts +9 -0
- package/dist/cjs/MenuSeparator.d.ts +3 -0
- package/dist/cjs/PatientTimeline.d.ts +6 -0
- package/dist/cjs/PeriodInput.d.ts +8 -0
- package/dist/cjs/PlanDefinitionBuilder.d.ts +7 -0
- package/dist/cjs/Popup.d.ts +14 -0
- package/dist/cjs/QuantityDisplay.d.ts +7 -0
- package/dist/cjs/QuantityInput.d.ts +8 -0
- package/dist/cjs/QuestionnaireBuilder.d.ts +8 -0
- package/dist/cjs/QuestionnaireForm.d.ts +14 -0
- package/dist/cjs/QuestionnaireUtils.d.ts +30 -0
- package/dist/cjs/RangeDisplay.d.ts +7 -0
- package/dist/cjs/RangeInput.d.ts +14 -0
- package/dist/cjs/RatioDisplay.d.ts +6 -0
- package/dist/cjs/RatioInput.d.ts +14 -0
- package/dist/cjs/ReferenceDisplay.d.ts +7 -0
- package/dist/cjs/ReferenceInput.d.ts +9 -0
- package/dist/cjs/RequestGroupDisplay.d.ts +9 -0
- package/dist/cjs/ResourceArrayDisplay.d.ts +11 -0
- package/dist/cjs/ResourceArrayInput.d.ts +11 -0
- package/dist/cjs/ResourceBadge.d.ts +9 -0
- package/dist/cjs/ResourceBlame.d.ts +10 -0
- package/dist/cjs/ResourceDiff.d.ts +9 -0
- package/dist/cjs/ResourceDiffTable.d.ts +9 -0
- package/dist/cjs/ResourceForm.d.ts +10 -0
- package/dist/cjs/ResourceHistoryTable.d.ts +9 -0
- package/dist/cjs/ResourceInput.d.ts +12 -0
- package/dist/cjs/ResourceName.d.ts +7 -0
- package/dist/cjs/ResourcePropertyDisplay.d.ts +24 -0
- package/dist/cjs/ResourcePropertyInput.d.ts +21 -0
- package/dist/cjs/ResourceTable.d.ts +7 -0
- package/dist/cjs/ResourceTimeline.d.ts +11 -0
- package/dist/cjs/Scheduler.d.ts +7 -0
- package/dist/cjs/Scrollable.d.ts +9 -0
- package/dist/cjs/SearchControl.d.ts +40 -0
- package/dist/cjs/SearchControlField.d.ts +41 -0
- package/dist/cjs/SearchFieldEditor.d.ts +11 -0
- package/dist/cjs/SearchFilterEditor.d.ts +11 -0
- package/dist/cjs/SearchFilterValueDialog.d.ts +15 -0
- package/dist/cjs/SearchFilterValueDisplay.d.ts +7 -0
- package/dist/cjs/SearchFilterValueInput.d.ts +12 -0
- package/dist/cjs/SearchPopupMenu.d.ts +15 -0
- package/dist/cjs/SearchUtils.d.ts +174 -0
- package/dist/cjs/Select.d.ts +16 -0
- package/dist/cjs/ServiceRequestTimeline.d.ts +6 -0
- package/dist/cjs/StatusBadge.d.ts +6 -0
- package/dist/cjs/SubMenu.d.ts +7 -0
- package/dist/cjs/Tab.d.ts +12 -0
- package/dist/cjs/TabList.d.ts +10 -0
- package/dist/cjs/TabPanel.d.ts +6 -0
- package/dist/cjs/TabSwitch.d.ts +6 -0
- package/dist/cjs/TextArea.d.ts +18 -0
- package/dist/cjs/Timeline.d.ts +17 -0
- package/dist/cjs/TimingInput.d.ts +8 -0
- package/dist/cjs/TitleBar.d.ts +6 -0
- package/dist/cjs/UploadButton.d.ts +7 -0
- package/dist/cjs/auth/AuthenticationForm.d.ts +14 -0
- package/dist/cjs/auth/ChooseProfileForm.d.ts +8 -0
- package/dist/cjs/auth/NewProjectForm.d.ts +7 -0
- package/dist/cjs/auth/NewUserForm.d.ts +10 -0
- package/dist/cjs/auth/RegisterForm.d.ts +12 -0
- package/dist/{esm → cjs/auth}/SignInForm.d.ts +1 -1
- package/dist/cjs/constants.d.ts +1 -0
- package/dist/cjs/index.d.ts +87 -0
- package/dist/cjs/index.js +660 -565
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/index.min.js +1 -1
- package/dist/cjs/index.min.js.map +1 -1
- package/dist/cjs/stories/AddressInput.stories.d.ts +6 -0
- package/dist/cjs/stories/AttachmentArrayInput.stories.d.ts +6 -0
- package/dist/cjs/stories/AttachmentInput.stories.d.ts +6 -0
- package/dist/cjs/stories/Autocomplete.stories.d.ts +9 -0
- package/dist/cjs/stories/Avatar.stories.d.ts +10 -0
- package/dist/cjs/stories/Button.stories.d.ts +9 -0
- package/dist/cjs/stories/CodeableConceptDisplay.stories.d.ts +8 -0
- package/dist/cjs/stories/DiagnosticReportDisplay.stories.d.ts +5 -0
- package/dist/cjs/stories/Dialog.stories.d.ts +5 -0
- package/dist/cjs/stories/EncounterTimeline.stories.d.ts +5 -0
- package/dist/cjs/stories/FhirPathDisplay.stories.d.ts +7 -0
- package/dist/cjs/stories/FormSection.stories.d.ts +6 -0
- package/dist/cjs/stories/Header.stories.d.ts +8 -0
- package/dist/cjs/stories/Input.stories.d.ts +6 -0
- package/dist/cjs/stories/Loading.stories.d.ts +5 -0
- package/dist/cjs/stories/Logo.stories.d.ts +5 -0
- package/dist/cjs/stories/PatientTimeline.stories.d.ts +5 -0
- package/dist/cjs/stories/PlanDefinitionBuilder.stories.d.ts +5 -0
- package/dist/cjs/stories/QuestionnaireBuilder.stories.d.ts +7 -0
- package/dist/cjs/stories/QuestionnaireForm.stories.d.ts +11 -0
- package/dist/cjs/stories/ReferenceInput.stories.d.ts +6 -0
- package/dist/cjs/stories/RegisterForm.stories.d.ts +7 -0
- package/dist/cjs/stories/RequestGroupDisplay.stories.d.ts +5 -0
- package/dist/cjs/stories/ResourceBlame.stories.d.ts +5 -0
- package/dist/cjs/stories/ResourceForm.stories.d.ts +12 -0
- package/dist/cjs/stories/ResourceHistoryTable.stories.d.ts +5 -0
- package/dist/cjs/stories/ResourceTable.stories.d.ts +7 -0
- package/dist/cjs/stories/Scheduler.stories.d.ts +5 -0
- package/dist/cjs/stories/SearchControl.stories.d.ts +13 -0
- package/dist/cjs/stories/Select.stories.d.ts +6 -0
- package/dist/cjs/stories/SignInForm.stories.d.ts +8 -0
- package/dist/cjs/stories/StatusBadge.stories.d.ts +5 -0
- package/dist/cjs/stories/Tabs.stories.d.ts +6 -0
- package/dist/cjs/stories/Timeline.stories.d.ts +5 -0
- package/dist/cjs/stories/TimingInput.stories.d.ts +6 -0
- package/dist/cjs/stories/UploadButton.stories.d.ts +6 -0
- package/dist/cjs/styles.css +248 -247
- package/dist/cjs/test.setup.d.ts +1 -0
- package/dist/cjs/useResource.d.ts +8 -0
- package/dist/cjs/utils/blame.d.ts +8 -0
- package/dist/cjs/utils/date.d.ts +6 -0
- package/dist/cjs/utils/diff.d.ts +16 -0
- package/dist/cjs/utils/dom.d.ts +15 -0
- package/dist/cjs/utils/outcomes.d.ts +2 -0
- package/dist/cjs/utils/recaptcha.d.ts +12 -0
- package/dist/cjs/utils.d.ts +5 -0
- package/dist/esm/Autocomplete.js +1 -0
- package/dist/esm/Autocomplete.js.map +1 -1
- package/dist/esm/CalendarInput.d.ts +1 -0
- package/dist/esm/CalendarInput.js +6 -5
- package/dist/esm/CalendarInput.js.map +1 -1
- package/dist/esm/CodeInput.js +1 -1
- package/dist/esm/CodeInput.js.map +1 -1
- package/dist/esm/CodeableConceptInput.js +1 -1
- package/dist/esm/CodeableConceptInput.js.map +1 -1
- package/dist/esm/CodingInput.js +1 -1
- package/dist/esm/CodingInput.js.map +1 -1
- package/dist/esm/FhirPathTable.js +5 -2
- package/dist/esm/FhirPathTable.js.map +1 -1
- package/dist/esm/GoogleButton.js +1 -1
- package/dist/esm/GoogleButton.js.map +1 -1
- package/dist/esm/Header.js +7 -3
- package/dist/esm/Header.js.map +1 -1
- package/dist/esm/MedplumLink.js +29 -14
- package/dist/esm/MedplumLink.js.map +1 -1
- package/dist/esm/PlanDefinitionBuilder.js +1 -1
- package/dist/esm/PlanDefinitionBuilder.js.map +1 -1
- package/dist/esm/QuestionnaireBuilder.js +1 -1
- package/dist/esm/QuestionnaireBuilder.js.map +1 -1
- package/dist/esm/QuestionnaireForm.js +2 -1
- package/dist/esm/QuestionnaireForm.js.map +1 -1
- package/dist/esm/RequestGroupDisplay.js +1 -1
- package/dist/esm/RequestGroupDisplay.js.map +1 -1
- package/dist/esm/ResourceBlame.js +1 -1
- package/dist/esm/ResourceBlame.js.map +1 -1
- package/dist/esm/ResourceDiffTable.js +1 -1
- package/dist/esm/ResourceDiffTable.js.map +1 -1
- package/dist/esm/ResourceForm.js +1 -1
- package/dist/esm/ResourceForm.js.map +1 -1
- package/dist/esm/ResourceHistoryTable.js +19 -12
- package/dist/esm/ResourceHistoryTable.js.map +1 -1
- package/dist/esm/ResourceTable.js +1 -1
- package/dist/esm/ResourceTable.js.map +1 -1
- package/dist/esm/ResourceTimeline.js +16 -8
- package/dist/esm/ResourceTimeline.js.map +1 -1
- package/dist/esm/Scheduler.js +13 -6
- package/dist/esm/Scheduler.js.map +1 -1
- package/dist/esm/SearchControl.js +5 -2
- package/dist/esm/SearchControl.js.map +1 -1
- package/dist/esm/auth/AuthenticationForm.d.ts +14 -0
- package/dist/esm/{SignInForm.js → auth/AuthenticationForm.js} +12 -75
- package/dist/esm/auth/AuthenticationForm.js.map +1 -0
- package/dist/esm/auth/ChooseProfileForm.d.ts +8 -0
- package/dist/esm/auth/ChooseProfileForm.js +32 -0
- package/dist/esm/auth/ChooseProfileForm.js.map +1 -0
- package/dist/esm/auth/NewProjectForm.d.ts +7 -0
- package/dist/esm/auth/NewProjectForm.js +42 -0
- package/dist/esm/auth/NewProjectForm.js.map +1 -0
- package/dist/esm/auth/NewUserForm.d.ts +10 -0
- package/dist/esm/auth/NewUserForm.js +87 -0
- package/dist/esm/auth/NewUserForm.js.map +1 -0
- package/dist/esm/auth/RegisterForm.d.ts +12 -0
- package/dist/esm/auth/RegisterForm.js +39 -0
- package/dist/esm/auth/RegisterForm.js.map +1 -0
- package/dist/esm/auth/SignInForm.d.ts +17 -0
- package/dist/esm/auth/SignInForm.js +52 -0
- package/dist/esm/auth/SignInForm.js.map +1 -0
- package/dist/esm/index.d.ts +3 -2
- package/dist/esm/index.js +3 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.min.js +1 -1
- package/dist/esm/index.min.js.map +1 -1
- package/dist/esm/styles.css +248 -247
- package/dist/esm/utils/recaptcha.js +10 -4
- package/dist/esm/utils/recaptcha.js.map +1 -1
- package/package.json +16 -18
- package/dist/esm/RegisterForm.d.ts +0 -18
- package/dist/esm/RegisterForm.js +0 -121
- package/dist/esm/RegisterForm.js.map +0 -1
- package/dist/esm/SignInForm.js.map +0 -1
package/dist/cjs/index.js
CHANGED
|
@@ -329,6 +329,578 @@
|
|
|
329
329
|
return React__default["default"].createElement(UploadButton, { onUpload: setValueWrapper });
|
|
330
330
|
}
|
|
331
331
|
|
|
332
|
+
function Document(props) {
|
|
333
|
+
return (React__default["default"].createElement("main", { className: "medplum-document" },
|
|
334
|
+
React__default["default"].createElement("article", { style: { maxWidth: props.width } }, props.children)));
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/******************************************************************************
|
|
338
|
+
Copyright (c) Microsoft Corporation.
|
|
339
|
+
|
|
340
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
341
|
+
purpose with or without fee is hereby granted.
|
|
342
|
+
|
|
343
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
344
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
345
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
346
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
347
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
348
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
349
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
350
|
+
***************************************************************************** */
|
|
351
|
+
|
|
352
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
353
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
354
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
355
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
356
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
357
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
358
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Parses an HTML form and returns the result as a JavaScript object.
|
|
364
|
+
* @param form The HTML form element.
|
|
365
|
+
*/
|
|
366
|
+
function parseForm(form) {
|
|
367
|
+
const result = {};
|
|
368
|
+
for (const element of Array.from(form.elements)) {
|
|
369
|
+
if (element instanceof HTMLInputElement) {
|
|
370
|
+
parseInputElement(result, element);
|
|
371
|
+
}
|
|
372
|
+
else if (element instanceof HTMLTextAreaElement) {
|
|
373
|
+
result[element.name] = element.value;
|
|
374
|
+
}
|
|
375
|
+
else if (element instanceof HTMLSelectElement) {
|
|
376
|
+
parseSelectElement(result, element);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
return result;
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Parses an HTML input element.
|
|
383
|
+
* Sets the name/value pair in the result,
|
|
384
|
+
* but only if the element is enabled and checked.
|
|
385
|
+
* @param el The input element.
|
|
386
|
+
* @param result The result builder.
|
|
387
|
+
*/
|
|
388
|
+
function parseInputElement(result, el) {
|
|
389
|
+
if (el.disabled) {
|
|
390
|
+
// Ignore disabled elements
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
if ((el.type === 'checkbox' || el.type === 'radio') && !el.checked) {
|
|
394
|
+
// Ignore unchecked radio or checkbox elements
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
result[el.name] = el.value;
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Parses an HTML select element.
|
|
401
|
+
* Sets the name/value pair if one is selected.
|
|
402
|
+
* @param result The result builder.
|
|
403
|
+
* @param el The select element.
|
|
404
|
+
*/
|
|
405
|
+
function parseSelectElement(result, el) {
|
|
406
|
+
result[el.name] = el.value;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
function Form(props) {
|
|
410
|
+
return (React__default["default"].createElement("form", { style: props.style, "data-testid": props.testid, onSubmit: (e) => {
|
|
411
|
+
e.preventDefault();
|
|
412
|
+
const formData = parseForm(e.target);
|
|
413
|
+
if (props.onSubmit) {
|
|
414
|
+
props.onSubmit(formData);
|
|
415
|
+
}
|
|
416
|
+
} }, props.children));
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
function FormSection(props) {
|
|
420
|
+
const issues = getIssuesForExpression(props.outcome, props.htmlFor);
|
|
421
|
+
const invalid = issues && issues.length > 0;
|
|
422
|
+
return (React__default["default"].createElement("fieldset", { className: "medplum-form-section" },
|
|
423
|
+
props.title && React__default["default"].createElement("label", { htmlFor: props.htmlFor }, props.title),
|
|
424
|
+
props.description && React__default["default"].createElement("p", null, props.description),
|
|
425
|
+
props.children,
|
|
426
|
+
invalid && (React__default["default"].createElement("div", { id: props.htmlFor + '-errors', className: "medplum-input-error" }, issues === null || issues === void 0 ? void 0 : issues.map((issue) => {
|
|
427
|
+
var _a, _b;
|
|
428
|
+
return (React__default["default"].createElement("div", { "data-testid": "text-field-error", key: (_a = issue.details) === null || _a === void 0 ? void 0 : _a.text }, (_b = issue.details) === null || _b === void 0 ? void 0 : _b.text));
|
|
429
|
+
})))));
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
function Logo(props) {
|
|
433
|
+
return (React__default["default"].createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 491 491", style: { width: props.size, height: props.size } },
|
|
434
|
+
React__default["default"].createElement("title", null, "Medplum Logo"),
|
|
435
|
+
React__default["default"].createElement("path", { fill: props.fill || '#ad7136', d: "M282 67c6-16 16-29 29-40L289 0c-22 17-37 41-43 68l17 23 19-24z" }),
|
|
436
|
+
React__default["default"].createElement("path", { fill: props.fill || '#654b87', d: "M311 63c-17 0-33 4-48 11-16-7-32-11-49-11-87 0-158 96-158 214s71 214 158 214c17 0 33-4 49-11 15 7 31 11 48 11 87 0 158-96 158-214S398 63 311 63z" }),
|
|
437
|
+
React__default["default"].createElement("path", { fill: props.fill || '#463068', d: "M231 489l-17 2c-87 0-158-96-158-214S127 63 214 63l17 1c-39 12-70 102-70 213s31 201 70 212z" }),
|
|
438
|
+
React__default["default"].createElement("path", { fill: props.fill || '#70d65b', d: "M207 220a176 176 0 01-177 43A176 176 0 01251 43l1 5c17 59 2 125-45 172z" }),
|
|
439
|
+
React__default["default"].createElement("path", { fill: props.fill || '#58b741', d: "M252 48A421 421 0 0057 270l-27-7A176 176 0 01251 43l1 5z" })));
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
function NewProjectForm(props) {
|
|
443
|
+
const medplum = useMedplum();
|
|
444
|
+
const [outcome, setOutcome] = React.useState();
|
|
445
|
+
return (React__default["default"].createElement(Form, { style: { maxWidth: 400 }, onSubmit: (formData) => __awaiter(this, void 0, void 0, function* () {
|
|
446
|
+
try {
|
|
447
|
+
props.handleAuthResponse(yield medplum.startNewProject({
|
|
448
|
+
login: props.login,
|
|
449
|
+
projectName: formData.projectName,
|
|
450
|
+
}));
|
|
451
|
+
}
|
|
452
|
+
catch (err) {
|
|
453
|
+
setOutcome(err);
|
|
454
|
+
}
|
|
455
|
+
}) },
|
|
456
|
+
React__default["default"].createElement("div", { className: "medplum-center" },
|
|
457
|
+
React__default["default"].createElement(Logo, { size: 32 }),
|
|
458
|
+
React__default["default"].createElement("h1", null, "Create project")),
|
|
459
|
+
React__default["default"].createElement(FormSection, { title: "Project Name", htmlFor: "projectName", outcome: outcome },
|
|
460
|
+
React__default["default"].createElement(Input, { name: "projectName", type: "text", testid: "projectName", placeholder: "My Project", required: true, outcome: outcome })),
|
|
461
|
+
React__default["default"].createElement("p", { style: { fontSize: '12px', color: '#888' } },
|
|
462
|
+
"By clicking submit you agree to the Medplum ",
|
|
463
|
+
React__default["default"].createElement("a", { href: "https://www.medplum.com/privacy" }, "Privacy\u00A0Policy"),
|
|
464
|
+
' and ',
|
|
465
|
+
React__default["default"].createElement("a", { href: "https://www.medplum.com/terms" }, "Terms\u00A0of\u00A0Service"),
|
|
466
|
+
"."),
|
|
467
|
+
React__default["default"].createElement("div", { className: "medplum-signin-buttons" },
|
|
468
|
+
React__default["default"].createElement("div", null),
|
|
469
|
+
React__default["default"].createElement("div", null,
|
|
470
|
+
React__default["default"].createElement(Button, { type: "submit", testid: "submit" }, "Create project")))));
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Dynamically creates a script tag for the specified JavaScript file.
|
|
475
|
+
* @param src The JavaScript file URL.
|
|
476
|
+
*/
|
|
477
|
+
function createScriptTag(src, onload) {
|
|
478
|
+
const head = document.getElementsByTagName('head')[0];
|
|
479
|
+
const script = document.createElement('script');
|
|
480
|
+
script.async = true;
|
|
481
|
+
script.src = src;
|
|
482
|
+
script.onload = onload || null;
|
|
483
|
+
head.appendChild(script);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
function GoogleButton(props) {
|
|
487
|
+
const medplum = useMedplum();
|
|
488
|
+
const { googleClientId, handleGoogleCredential } = props;
|
|
489
|
+
const parentRef = React.useRef(null);
|
|
490
|
+
const [scriptLoaded, setScriptLoaded] = React.useState(typeof google !== 'undefined');
|
|
491
|
+
const [initialized, setInitialized] = React.useState(false);
|
|
492
|
+
const [buttonRendered, setButtonRendered] = React.useState(false);
|
|
493
|
+
React.useEffect(() => {
|
|
494
|
+
if (typeof google === 'undefined') {
|
|
495
|
+
createScriptTag('https://accounts.google.com/gsi/client', () => setScriptLoaded(true));
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
if (!initialized) {
|
|
499
|
+
google.accounts.id.initialize({
|
|
500
|
+
client_id: googleClientId,
|
|
501
|
+
callback: handleGoogleCredential,
|
|
502
|
+
});
|
|
503
|
+
setInitialized(true);
|
|
504
|
+
}
|
|
505
|
+
if (parentRef.current && !buttonRendered) {
|
|
506
|
+
google.accounts.id.renderButton(parentRef.current, {});
|
|
507
|
+
setButtonRendered(true);
|
|
508
|
+
}
|
|
509
|
+
}, [medplum, googleClientId, initialized, scriptLoaded, parentRef, buttonRendered, handleGoogleCredential]);
|
|
510
|
+
if (!googleClientId) {
|
|
511
|
+
return null;
|
|
512
|
+
}
|
|
513
|
+
return React__default["default"].createElement("div", { ref: parentRef });
|
|
514
|
+
}
|
|
515
|
+
function getGoogleClientId(clientId) {
|
|
516
|
+
var _a, _b;
|
|
517
|
+
if (clientId) {
|
|
518
|
+
return clientId;
|
|
519
|
+
}
|
|
520
|
+
const origin = window.location.protocol + '//' + window.location.host;
|
|
521
|
+
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 : [];
|
|
522
|
+
if (authorizedOrigins.includes(origin)) {
|
|
523
|
+
return "921088377005-3j1sa10vr6hj86jgmdfh2l53v3mp7lfi.apps.googleusercontent.com";
|
|
524
|
+
}
|
|
525
|
+
return undefined;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Dynamically loads the recaptcha script.
|
|
530
|
+
* We do not want to load the script on page load unless the user needs it.
|
|
531
|
+
* @param siteKey The reCAPTCHA site key, available from the reCAPTCHA admin page.
|
|
532
|
+
*/
|
|
533
|
+
function initRecaptcha(siteKey) {
|
|
534
|
+
if (typeof grecaptcha === 'undefined') {
|
|
535
|
+
createScriptTag('https://www.google.com/recaptcha/api.js?render=' + siteKey);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Starts a request to generate a recapcha token.
|
|
540
|
+
* @param siteKey The reCAPTCHA site key, available from the reCAPTCHA admin page.
|
|
541
|
+
* @returns Promise to a recaptcha token for the current user.
|
|
542
|
+
*/
|
|
543
|
+
function getRecaptcha(siteKey) {
|
|
544
|
+
return new Promise((resolve, reject) => {
|
|
545
|
+
grecaptcha.ready(() => __awaiter(this, void 0, void 0, function* () {
|
|
546
|
+
try {
|
|
547
|
+
resolve(yield grecaptcha.execute(siteKey, { action: 'submit' }));
|
|
548
|
+
}
|
|
549
|
+
catch (err) {
|
|
550
|
+
reject(err);
|
|
551
|
+
}
|
|
552
|
+
}));
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
function NewUserForm(props) {
|
|
557
|
+
const googleClientId = getGoogleClientId(props.googleClientId);
|
|
558
|
+
const recaptchaSiteKey = props.recaptchaSiteKey;
|
|
559
|
+
const medplum = useMedplum();
|
|
560
|
+
const [outcome, setOutcome] = React.useState();
|
|
561
|
+
const issues = getIssuesForExpression(outcome, undefined);
|
|
562
|
+
React.useEffect(() => initRecaptcha(recaptchaSiteKey), [recaptchaSiteKey]);
|
|
563
|
+
return (React__default["default"].createElement(Form, { style: { maxWidth: 400 }, onSubmit: (formData) => __awaiter(this, void 0, void 0, function* () {
|
|
564
|
+
try {
|
|
565
|
+
const recaptchaToken = yield getRecaptcha(recaptchaSiteKey);
|
|
566
|
+
props.handleAuthResponse(yield medplum.startNewUser({
|
|
567
|
+
projectId: props.projectId,
|
|
568
|
+
firstName: formData.firstName,
|
|
569
|
+
lastName: formData.lastName,
|
|
570
|
+
email: formData.email,
|
|
571
|
+
password: formData.password,
|
|
572
|
+
remember: formData.remember === 'true',
|
|
573
|
+
recaptchaSiteKey,
|
|
574
|
+
recaptchaToken,
|
|
575
|
+
}));
|
|
576
|
+
}
|
|
577
|
+
catch (err) {
|
|
578
|
+
setOutcome(err);
|
|
579
|
+
}
|
|
580
|
+
}) },
|
|
581
|
+
React__default["default"].createElement("div", { className: "medplum-center" }, props.children),
|
|
582
|
+
issues && (React__default["default"].createElement("div", { className: "medplum-input-error" }, issues.map((issue) => {
|
|
583
|
+
var _a, _b;
|
|
584
|
+
return (React__default["default"].createElement("div", { "data-testid": "text-field-error", key: (_a = issue.details) === null || _a === void 0 ? void 0 : _a.text }, (_b = issue.details) === null || _b === void 0 ? void 0 : _b.text));
|
|
585
|
+
}))),
|
|
586
|
+
googleClientId && (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
587
|
+
React__default["default"].createElement("div", { className: "medplum-signin-google-container" },
|
|
588
|
+
React__default["default"].createElement(GoogleButton, { googleClientId: googleClientId, handleGoogleCredential: (response) => __awaiter(this, void 0, void 0, function* () {
|
|
589
|
+
try {
|
|
590
|
+
props.handleAuthResponse(yield medplum.startGoogleLogin({
|
|
591
|
+
googleClientId: response.clientId,
|
|
592
|
+
googleCredential: response.credential,
|
|
593
|
+
createUser: true,
|
|
594
|
+
}));
|
|
595
|
+
}
|
|
596
|
+
catch (err) {
|
|
597
|
+
setOutcome(err);
|
|
598
|
+
}
|
|
599
|
+
}) })),
|
|
600
|
+
React__default["default"].createElement("div", { className: "medplum-signin-separator" }, "or"))),
|
|
601
|
+
React__default["default"].createElement(FormSection, { title: "First Name", htmlFor: "firstName", outcome: outcome },
|
|
602
|
+
React__default["default"].createElement(Input, { name: "firstName", type: "text", testid: "firstName", placeholder: "First name", required: true, autoFocus: true, outcome: outcome })),
|
|
603
|
+
React__default["default"].createElement(FormSection, { title: "Last Name", htmlFor: "lastName", outcome: outcome },
|
|
604
|
+
React__default["default"].createElement(Input, { name: "lastName", type: "text", testid: "lastName", placeholder: "Last name", required: true, outcome: outcome })),
|
|
605
|
+
React__default["default"].createElement(FormSection, { title: "Email", htmlFor: "email", outcome: outcome },
|
|
606
|
+
React__default["default"].createElement(Input, { name: "email", type: "email", testid: "email", placeholder: "name@domain.com", required: true, outcome: outcome })),
|
|
607
|
+
React__default["default"].createElement(FormSection, { title: "Password", htmlFor: "password", outcome: outcome },
|
|
608
|
+
React__default["default"].createElement(Input, { name: "password", type: "password", testid: "password", autoComplete: "off", required: true, outcome: outcome })),
|
|
609
|
+
React__default["default"].createElement("p", { style: { fontSize: '12px', color: '#888' } },
|
|
610
|
+
"By clicking submit you agree to the Medplum ",
|
|
611
|
+
React__default["default"].createElement("a", { href: "https://www.medplum.com/privacy" }, "Privacy\u00A0Policy"),
|
|
612
|
+
' and ',
|
|
613
|
+
React__default["default"].createElement("a", { href: "https://www.medplum.com/terms" }, "Terms\u00A0of\u00A0Service"),
|
|
614
|
+
"."),
|
|
615
|
+
React__default["default"].createElement("p", { style: { fontSize: '12px', color: '#888' } },
|
|
616
|
+
"This site is protected by reCAPTCHA and the Google",
|
|
617
|
+
' ',
|
|
618
|
+
React__default["default"].createElement("a", { href: "https://policies.google.com/privacy" }, "Privacy\u00A0Policy"),
|
|
619
|
+
' and ',
|
|
620
|
+
React__default["default"].createElement("a", { href: "https://policies.google.com/terms" }, "Terms\u00A0of\u00A0Service"),
|
|
621
|
+
" apply."),
|
|
622
|
+
React__default["default"].createElement("div", { className: "medplum-signin-buttons" },
|
|
623
|
+
React__default["default"].createElement("div", null,
|
|
624
|
+
React__default["default"].createElement("input", { type: "checkbox", id: "remember", name: "remember", value: "true" }),
|
|
625
|
+
React__default["default"].createElement("label", { htmlFor: "remember" }, "Remember me")),
|
|
626
|
+
React__default["default"].createElement("div", null,
|
|
627
|
+
React__default["default"].createElement(Button, { type: "submit", testid: "submit" }, "Create account")))));
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
function RegisterForm(props) {
|
|
631
|
+
const { type, projectId, googleClientId, recaptchaSiteKey, onSuccess } = props;
|
|
632
|
+
const medplum = useMedplum();
|
|
633
|
+
const [login, setLogin] = React.useState(undefined);
|
|
634
|
+
const [outcome, setOutcome] = React.useState();
|
|
635
|
+
React.useEffect(() => {
|
|
636
|
+
if (type === 'patient' && login) {
|
|
637
|
+
medplum
|
|
638
|
+
.startNewPatient({ login, projectId: projectId })
|
|
639
|
+
.then((response) => medplum.processCode(response.code))
|
|
640
|
+
.then(() => onSuccess())
|
|
641
|
+
.catch((err) => setOutcome(err));
|
|
642
|
+
}
|
|
643
|
+
}, [medplum, type, projectId, login, onSuccess]);
|
|
644
|
+
function handleAuthResponse(response) {
|
|
645
|
+
if (response.code) {
|
|
646
|
+
medplum
|
|
647
|
+
.processCode(response.code)
|
|
648
|
+
.then(() => onSuccess())
|
|
649
|
+
.catch(console.log);
|
|
650
|
+
}
|
|
651
|
+
else if (response.login) {
|
|
652
|
+
setLogin(response.login);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
return (React__default["default"].createElement(Document, { width: 450 },
|
|
656
|
+
outcome && React__default["default"].createElement("pre", null, JSON.stringify(outcome, null, 2)),
|
|
657
|
+
!login && (React__default["default"].createElement(NewUserForm, { projectId: projectId, googleClientId: googleClientId, recaptchaSiteKey: recaptchaSiteKey, handleAuthResponse: handleAuthResponse })),
|
|
658
|
+
login && type === 'project' && React__default["default"].createElement(NewProjectForm, { login: login, handleAuthResponse: handleAuthResponse })));
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
function MedplumLink(props) {
|
|
662
|
+
const navigate = reactRouterDom.useNavigate();
|
|
663
|
+
let href = getHref(props.to);
|
|
664
|
+
if (props.suffix) {
|
|
665
|
+
href += '/' + props.suffix;
|
|
666
|
+
}
|
|
667
|
+
return (React__default["default"].createElement("a", { href: href, id: props.id, "aria-label": props.label, "data-testid": props.testid || 'link', className: props.className, onClick: (e) => {
|
|
668
|
+
killEvent(e);
|
|
669
|
+
if (props.onClick) {
|
|
670
|
+
props.onClick();
|
|
671
|
+
}
|
|
672
|
+
else if (props.to) {
|
|
673
|
+
navigate(href);
|
|
674
|
+
}
|
|
675
|
+
} }, props.children));
|
|
676
|
+
}
|
|
677
|
+
function getHref(to) {
|
|
678
|
+
if (to) {
|
|
679
|
+
if (typeof to === 'string') {
|
|
680
|
+
return getStringHref(to);
|
|
681
|
+
}
|
|
682
|
+
else if ('resourceType' in to) {
|
|
683
|
+
return getResourceHref(to);
|
|
684
|
+
}
|
|
685
|
+
else if ('reference' in to) {
|
|
686
|
+
return getReferenceHref(to);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
return '#';
|
|
690
|
+
}
|
|
691
|
+
function getStringHref(to) {
|
|
692
|
+
if (to.startsWith('http://') || to.startsWith('https://') || to.startsWith('/')) {
|
|
693
|
+
return to;
|
|
694
|
+
}
|
|
695
|
+
return '/' + to;
|
|
696
|
+
}
|
|
697
|
+
function getResourceHref(to) {
|
|
698
|
+
return `/${to.resourceType}/${to.id}`;
|
|
699
|
+
}
|
|
700
|
+
function getReferenceHref(to) {
|
|
701
|
+
return `/${to.reference}`;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
function AuthenticationForm(props) {
|
|
705
|
+
const medplum = useMedplum();
|
|
706
|
+
const googleClientId = getGoogleClientId(props.googleClientId);
|
|
707
|
+
const [outcome, setOutcome] = React.useState();
|
|
708
|
+
const issues = getIssuesForExpression(outcome, undefined);
|
|
709
|
+
return (React__default["default"].createElement(Form, { style: { maxWidth: 400 }, onSubmit: (formData) => {
|
|
710
|
+
medplum
|
|
711
|
+
.startLogin({
|
|
712
|
+
projectId: props.projectId,
|
|
713
|
+
clientId: props.clientId,
|
|
714
|
+
scope: props.scope,
|
|
715
|
+
nonce: props.nonce,
|
|
716
|
+
email: formData.email,
|
|
717
|
+
password: formData.password,
|
|
718
|
+
remember: formData.remember === 'true',
|
|
719
|
+
})
|
|
720
|
+
.then(props.handleAuthResponse)
|
|
721
|
+
.catch(setOutcome);
|
|
722
|
+
} },
|
|
723
|
+
React__default["default"].createElement("div", { className: "medplum-center" }, props.children),
|
|
724
|
+
issues && (React__default["default"].createElement("div", { className: "medplum-input-error" }, issues.map((issue) => {
|
|
725
|
+
var _a, _b;
|
|
726
|
+
return (React__default["default"].createElement("div", { "data-testid": "text-field-error", key: (_a = issue.details) === null || _a === void 0 ? void 0 : _a.text }, (_b = issue.details) === null || _b === void 0 ? void 0 : _b.text));
|
|
727
|
+
}))),
|
|
728
|
+
googleClientId && (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
729
|
+
React__default["default"].createElement("div", { className: "medplum-signin-google-container" },
|
|
730
|
+
React__default["default"].createElement(GoogleButton, { googleClientId: googleClientId, handleGoogleCredential: (response) => {
|
|
731
|
+
medplum
|
|
732
|
+
.startGoogleLogin({
|
|
733
|
+
projectId: props.projectId,
|
|
734
|
+
clientId: props.clientId,
|
|
735
|
+
scope: props.scope,
|
|
736
|
+
nonce: props.nonce,
|
|
737
|
+
googleClientId: response.clientId,
|
|
738
|
+
googleCredential: response.credential,
|
|
739
|
+
})
|
|
740
|
+
.then(props.handleAuthResponse)
|
|
741
|
+
.catch(setOutcome);
|
|
742
|
+
} })),
|
|
743
|
+
React__default["default"].createElement("div", { className: "medplum-signin-separator" }, "or"))),
|
|
744
|
+
React__default["default"].createElement(FormSection, { title: "Email", htmlFor: "email", outcome: outcome },
|
|
745
|
+
React__default["default"].createElement(Input, { name: "email", type: "email", testid: "email", required: true, autoFocus: true, outcome: outcome })),
|
|
746
|
+
React__default["default"].createElement(FormSection, { title: "Password", htmlFor: "password", outcome: outcome },
|
|
747
|
+
React__default["default"].createElement(Input, { name: "password", type: "password", testid: "password", autoComplete: "off", required: true, outcome: outcome })),
|
|
748
|
+
React__default["default"].createElement("div", { className: "medplum-signin-buttons" },
|
|
749
|
+
(props.onForgotPassword || props.onRegister) && (React__default["default"].createElement("div", null,
|
|
750
|
+
props.onForgotPassword && (React__default["default"].createElement(MedplumLink, { testid: "forgotpassword", onClick: props.onForgotPassword }, "Forgot password")),
|
|
751
|
+
props.onRegister && (React__default["default"].createElement(MedplumLink, { testid: "register", onClick: props.onRegister }, "Register")))),
|
|
752
|
+
React__default["default"].createElement("div", null,
|
|
753
|
+
React__default["default"].createElement("input", { type: "checkbox", id: "remember", name: "remember", value: "true" }),
|
|
754
|
+
React__default["default"].createElement("label", { htmlFor: "remember" }, "Remember me")),
|
|
755
|
+
React__default["default"].createElement("div", null,
|
|
756
|
+
React__default["default"].createElement(Button, { type: "submit", testid: "submit" }, "Sign in")))));
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
const system = {
|
|
760
|
+
resourceType: 'Device',
|
|
761
|
+
id: 'system',
|
|
762
|
+
deviceName: [
|
|
763
|
+
{
|
|
764
|
+
name: 'System',
|
|
765
|
+
},
|
|
766
|
+
],
|
|
767
|
+
};
|
|
768
|
+
/**
|
|
769
|
+
* React Hook to use a FHIR reference.
|
|
770
|
+
* Handles the complexity of resolving references and caching resources.
|
|
771
|
+
* @param value The resource or reference to resource.
|
|
772
|
+
* @returns The resolved resource.
|
|
773
|
+
*/
|
|
774
|
+
function useResource(value) {
|
|
775
|
+
const medplum = useMedplum();
|
|
776
|
+
const [resource, setResource] = React.useState(getInitialResource(medplum, value));
|
|
777
|
+
React.useEffect(() => {
|
|
778
|
+
let subscribed = true;
|
|
779
|
+
if (!resource && value && 'reference' in value && value.reference) {
|
|
780
|
+
medplum
|
|
781
|
+
.readReference(value)
|
|
782
|
+
.then((r) => {
|
|
783
|
+
if (subscribed) {
|
|
784
|
+
setResource(r);
|
|
785
|
+
}
|
|
786
|
+
})
|
|
787
|
+
.catch(() => setResource(undefined));
|
|
788
|
+
}
|
|
789
|
+
return (() => (subscribed = false));
|
|
790
|
+
}, [medplum, resource, value]);
|
|
791
|
+
return resource;
|
|
792
|
+
}
|
|
793
|
+
/**
|
|
794
|
+
* Returns the initial resource value based on the input value.
|
|
795
|
+
* If the input value is a resource, returns the resource.
|
|
796
|
+
* If the input value is a reference to system, returns the system resource.
|
|
797
|
+
* If the input value is a reference to a resource available in the cache, returns the resource.
|
|
798
|
+
* Otherwise, returns undefined.
|
|
799
|
+
* @param medplum The medplum client.
|
|
800
|
+
* @param value The resource or reference to resource.
|
|
801
|
+
* @returns An initial resource if available; undefined otherwise.
|
|
802
|
+
*/
|
|
803
|
+
function getInitialResource(medplum, value) {
|
|
804
|
+
if (!value) {
|
|
805
|
+
return undefined;
|
|
806
|
+
}
|
|
807
|
+
if ('resourceType' in value) {
|
|
808
|
+
return value;
|
|
809
|
+
}
|
|
810
|
+
if ('reference' in value) {
|
|
811
|
+
if (value.reference === 'system') {
|
|
812
|
+
return system;
|
|
813
|
+
}
|
|
814
|
+
return medplum.getCachedReference(value);
|
|
815
|
+
}
|
|
816
|
+
return undefined;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
function Avatar(props) {
|
|
820
|
+
var _a, _b;
|
|
821
|
+
const resource = useResource(props.value);
|
|
822
|
+
const className = props.size ? 'medplum-avatar ' + props.size : 'medplum-avatar';
|
|
823
|
+
const text = resource ? core.getDisplayString(resource) : (_a = props.alt) !== null && _a !== void 0 ? _a : '';
|
|
824
|
+
const initials = text && getInitials(text);
|
|
825
|
+
const imageUrl = (_b = (resource && core.getImageSrc(resource))) !== null && _b !== void 0 ? _b : props.src;
|
|
826
|
+
const innerContent = imageUrl ? React__default["default"].createElement("img", { src: imageUrl, alt: text }) : initials;
|
|
827
|
+
return (React__default["default"].createElement("div", { className: className, style: { backgroundColor: props.color }, "data-testid": "avatar" }, props.link && resource ? React__default["default"].createElement(MedplumLink, { to: resource }, innerContent) : innerContent));
|
|
828
|
+
}
|
|
829
|
+
function getInitials(text) {
|
|
830
|
+
return text
|
|
831
|
+
.split(' ')
|
|
832
|
+
.map((n) => n[0])
|
|
833
|
+
.join('');
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
function ChooseProfileForm(props) {
|
|
837
|
+
const medplum = useMedplum();
|
|
838
|
+
return (React__default["default"].createElement("div", null,
|
|
839
|
+
React__default["default"].createElement("div", { className: "medplum-center" },
|
|
840
|
+
React__default["default"].createElement(Logo, { size: 32 }),
|
|
841
|
+
React__default["default"].createElement("h1", null, "Choose profile")),
|
|
842
|
+
props.memberships.map((membership) => {
|
|
843
|
+
var _a, _b, _c;
|
|
844
|
+
return (React__default["default"].createElement("div", { className: "medplum-nav-menu-profile", key: membership.id, onClick: () => {
|
|
845
|
+
medplum
|
|
846
|
+
.post('auth/profile', {
|
|
847
|
+
login: props.login,
|
|
848
|
+
profile: membership.id,
|
|
849
|
+
})
|
|
850
|
+
.then(props.handleAuthResponse)
|
|
851
|
+
.catch(console.log);
|
|
852
|
+
} },
|
|
853
|
+
React__default["default"].createElement("div", { className: "medplum-nav-menu-profile-icon" },
|
|
854
|
+
React__default["default"].createElement(Avatar, { alt: (_a = membership.profile) === null || _a === void 0 ? void 0 : _a.display })),
|
|
855
|
+
React__default["default"].createElement("div", { className: "medplum-nav-menu-profile-label" }, (_b = membership.profile) === null || _b === void 0 ? void 0 :
|
|
856
|
+
_b.display,
|
|
857
|
+
React__default["default"].createElement("div", { className: "medplum-nav-menu-profile-help-text" }, (_c = membership.project) === null || _c === void 0 ? void 0 : _c.display))));
|
|
858
|
+
})));
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
function SignInForm(props) {
|
|
862
|
+
const medplum = useMedplum();
|
|
863
|
+
const [login, setLogin] = React.useState(undefined);
|
|
864
|
+
const [memberships, setMemberships] = React.useState(undefined);
|
|
865
|
+
function handleAuthResponse(response) {
|
|
866
|
+
if (response.login) {
|
|
867
|
+
setLogin(response.login);
|
|
868
|
+
}
|
|
869
|
+
if (response.memberships) {
|
|
870
|
+
setMemberships(response.memberships);
|
|
871
|
+
}
|
|
872
|
+
if (response.code) {
|
|
873
|
+
if (props.onCode) {
|
|
874
|
+
props.onCode(response.code);
|
|
875
|
+
}
|
|
876
|
+
else {
|
|
877
|
+
medplum
|
|
878
|
+
.processCode(response.code)
|
|
879
|
+
.then(() => {
|
|
880
|
+
if (props.onSuccess) {
|
|
881
|
+
props.onSuccess();
|
|
882
|
+
}
|
|
883
|
+
})
|
|
884
|
+
.catch(console.log);
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
return (React__default["default"].createElement(Document, { width: 450 }, (() => {
|
|
889
|
+
if (!login) {
|
|
890
|
+
return (React__default["default"].createElement(AuthenticationForm, { projectId: props.projectId, clientId: props.clientId, scope: props.scope, nonce: props.nonce, googleClientId: props.googleClientId, onForgotPassword: props.onForgotPassword, onRegister: props.onRegister, handleAuthResponse: handleAuthResponse }, props.children));
|
|
891
|
+
}
|
|
892
|
+
else if (memberships) {
|
|
893
|
+
return React__default["default"].createElement(ChooseProfileForm, { login: login, memberships: memberships, handleAuthResponse: handleAuthResponse });
|
|
894
|
+
}
|
|
895
|
+
else if (props.projectId === 'new') {
|
|
896
|
+
return React__default["default"].createElement(NewProjectForm, { login: login, handleAuthResponse: handleAuthResponse });
|
|
897
|
+
}
|
|
898
|
+
else {
|
|
899
|
+
return React__default["default"].createElement("div", null, "Success");
|
|
900
|
+
}
|
|
901
|
+
})()));
|
|
902
|
+
}
|
|
903
|
+
|
|
332
904
|
function Autocomplete(props) {
|
|
333
905
|
var _a, _b;
|
|
334
906
|
const inputRef = React.useRef(null);
|
|
@@ -392,6 +964,7 @@
|
|
|
392
964
|
}
|
|
393
965
|
}
|
|
394
966
|
function handleBlur() {
|
|
967
|
+
tryAddOption();
|
|
395
968
|
setFocused(false);
|
|
396
969
|
dismissOnDelay();
|
|
397
970
|
}
|
|
@@ -604,111 +1177,6 @@
|
|
|
604
1177
|
React__default["default"].createElement("div", { className: "medplum-autocomplete-label" }, "Create new...")))))));
|
|
605
1178
|
}
|
|
606
1179
|
|
|
607
|
-
function MedplumLink(props) {
|
|
608
|
-
const navigate = reactRouterDom.useNavigate();
|
|
609
|
-
let href = '#';
|
|
610
|
-
if (props.to) {
|
|
611
|
-
if (typeof props.to === 'string') {
|
|
612
|
-
href = props.to;
|
|
613
|
-
}
|
|
614
|
-
else if ('resourceType' in props.to) {
|
|
615
|
-
href = `/${props.to.resourceType}/${props.to.id}`;
|
|
616
|
-
}
|
|
617
|
-
else if ('reference' in props.to) {
|
|
618
|
-
href = `/${props.to.reference}`;
|
|
619
|
-
}
|
|
620
|
-
if (props.suffix) {
|
|
621
|
-
href += '/' + props.suffix;
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
return (React__default["default"].createElement("a", { href: href, id: props.id, "aria-label": props.label, "data-testid": props.testid || 'link', className: props.className, onClick: (e) => {
|
|
625
|
-
killEvent(e);
|
|
626
|
-
if (props.onClick) {
|
|
627
|
-
props.onClick();
|
|
628
|
-
}
|
|
629
|
-
else if (props.to) {
|
|
630
|
-
navigate(href);
|
|
631
|
-
}
|
|
632
|
-
} }, props.children));
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
const system = {
|
|
636
|
-
resourceType: 'Device',
|
|
637
|
-
id: 'system',
|
|
638
|
-
deviceName: [
|
|
639
|
-
{
|
|
640
|
-
name: 'System',
|
|
641
|
-
},
|
|
642
|
-
],
|
|
643
|
-
};
|
|
644
|
-
/**
|
|
645
|
-
* React Hook to use a FHIR reference.
|
|
646
|
-
* Handles the complexity of resolving references and caching resources.
|
|
647
|
-
* @param value The resource or reference to resource.
|
|
648
|
-
* @returns The resolved resource.
|
|
649
|
-
*/
|
|
650
|
-
function useResource(value) {
|
|
651
|
-
const medplum = useMedplum();
|
|
652
|
-
const [resource, setResource] = React.useState(getInitialResource(medplum, value));
|
|
653
|
-
React.useEffect(() => {
|
|
654
|
-
let subscribed = true;
|
|
655
|
-
if (!resource && value && 'reference' in value && value.reference) {
|
|
656
|
-
medplum
|
|
657
|
-
.readReference(value)
|
|
658
|
-
.then((r) => {
|
|
659
|
-
if (subscribed) {
|
|
660
|
-
setResource(r);
|
|
661
|
-
}
|
|
662
|
-
})
|
|
663
|
-
.catch(() => setResource(undefined));
|
|
664
|
-
}
|
|
665
|
-
return (() => (subscribed = false));
|
|
666
|
-
}, [medplum, resource, value]);
|
|
667
|
-
return resource;
|
|
668
|
-
}
|
|
669
|
-
/**
|
|
670
|
-
* Returns the initial resource value based on the input value.
|
|
671
|
-
* If the input value is a resource, returns the resource.
|
|
672
|
-
* If the input value is a reference to system, returns the system resource.
|
|
673
|
-
* If the input value is a reference to a resource available in the cache, returns the resource.
|
|
674
|
-
* Otherwise, returns undefined.
|
|
675
|
-
* @param medplum The medplum client.
|
|
676
|
-
* @param value The resource or reference to resource.
|
|
677
|
-
* @returns An initial resource if available; undefined otherwise.
|
|
678
|
-
*/
|
|
679
|
-
function getInitialResource(medplum, value) {
|
|
680
|
-
if (!value) {
|
|
681
|
-
return undefined;
|
|
682
|
-
}
|
|
683
|
-
if ('resourceType' in value) {
|
|
684
|
-
return value;
|
|
685
|
-
}
|
|
686
|
-
if ('reference' in value) {
|
|
687
|
-
if (value.reference === 'system') {
|
|
688
|
-
return system;
|
|
689
|
-
}
|
|
690
|
-
return medplum.getCachedReference(value);
|
|
691
|
-
}
|
|
692
|
-
return undefined;
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
function Avatar(props) {
|
|
696
|
-
var _a, _b;
|
|
697
|
-
const resource = useResource(props.value);
|
|
698
|
-
const className = props.size ? 'medplum-avatar ' + props.size : 'medplum-avatar';
|
|
699
|
-
const text = resource ? core.getDisplayString(resource) : (_a = props.alt) !== null && _a !== void 0 ? _a : '';
|
|
700
|
-
const initials = text && getInitials(text);
|
|
701
|
-
const imageUrl = (_b = (resource && core.getImageSrc(resource))) !== null && _b !== void 0 ? _b : props.src;
|
|
702
|
-
const innerContent = imageUrl ? React__default["default"].createElement("img", { src: imageUrl, alt: text }) : initials;
|
|
703
|
-
return (React__default["default"].createElement("div", { className: className, style: { backgroundColor: props.color }, "data-testid": "avatar" }, props.link && resource ? React__default["default"].createElement(MedplumLink, { to: resource }, innerContent) : innerContent));
|
|
704
|
-
}
|
|
705
|
-
function getInitials(text) {
|
|
706
|
-
return text
|
|
707
|
-
.split(' ')
|
|
708
|
-
.map((n) => n[0])
|
|
709
|
-
.join('');
|
|
710
|
-
}
|
|
711
|
-
|
|
712
1180
|
function CheckboxFormSection(props) {
|
|
713
1181
|
return (React__default["default"].createElement("div", { className: "medplum-checkbox-form-section" },
|
|
714
1182
|
React__default["default"].createElement("div", { className: "medplum-checkbox-form-section-checkbox-container" }, props.children),
|
|
@@ -727,19 +1195,6 @@
|
|
|
727
1195
|
'modifierExtension',
|
|
728
1196
|
];
|
|
729
1197
|
|
|
730
|
-
function FormSection(props) {
|
|
731
|
-
const issues = getIssuesForExpression(props.outcome, props.htmlFor);
|
|
732
|
-
const invalid = issues && issues.length > 0;
|
|
733
|
-
return (React__default["default"].createElement("fieldset", { className: "medplum-form-section" },
|
|
734
|
-
props.title && React__default["default"].createElement("label", { htmlFor: props.htmlFor }, props.title),
|
|
735
|
-
props.description && React__default["default"].createElement("p", null, props.description),
|
|
736
|
-
props.children,
|
|
737
|
-
invalid && (React__default["default"].createElement("div", { id: props.htmlFor + '-errors', className: "medplum-input-error" }, issues === null || issues === void 0 ? void 0 : issues.map((issue) => {
|
|
738
|
-
var _a, _b;
|
|
739
|
-
return (React__default["default"].createElement("div", { "data-testid": "text-field-error", key: (_a = issue.details) === null || _a === void 0 ? void 0 : _a.text }, (_b = issue.details) === null || _b === void 0 ? void 0 : _b.text));
|
|
740
|
-
})))));
|
|
741
|
-
}
|
|
742
|
-
|
|
743
1198
|
function ResourceForm(props) {
|
|
744
1199
|
const medplum = useMedplum();
|
|
745
1200
|
const defaultValue = useResource(props.defaultValue);
|
|
@@ -748,7 +1203,7 @@
|
|
|
748
1203
|
React.useEffect(() => {
|
|
749
1204
|
if (defaultValue) {
|
|
750
1205
|
setValue(JSON.parse(JSON.stringify(defaultValue)));
|
|
751
|
-
medplum.requestSchema(defaultValue.resourceType).then(setSchema);
|
|
1206
|
+
medplum.requestSchema(defaultValue.resourceType).then(setSchema).catch(console.log);
|
|
752
1207
|
}
|
|
753
1208
|
}, [medplum, defaultValue]);
|
|
754
1209
|
if (!schema || !value) {
|
|
@@ -1106,7 +1561,7 @@
|
|
|
1106
1561
|
return medplum.searchValueSet(system, input).then((valueSet) => {
|
|
1107
1562
|
return valueSet.expansion.contains.map(valueSetElementToCodeableConcept);
|
|
1108
1563
|
});
|
|
1109
|
-
}, buildUnstructured: buildUnstructured, getId: getId, getDisplay: getDisplay, name: props.name, defaultValue: defaultValue, onChange: (values) => {
|
|
1564
|
+
}, buildUnstructured: buildUnstructured, getId: getId, getDisplay: getDisplay, name: props.name, defaultValue: defaultValue, loadOnFocus: true, onChange: (values) => {
|
|
1110
1565
|
if (props.onChange) {
|
|
1111
1566
|
props.onChange(values[0]);
|
|
1112
1567
|
}
|
|
@@ -1154,7 +1609,7 @@
|
|
|
1154
1609
|
contains.forEach((e) => (cachedDisplayValues[e.code] = e.display));
|
|
1155
1610
|
return contains.map((e) => e.code);
|
|
1156
1611
|
});
|
|
1157
|
-
}, buildUnstructured: (str) => str, getId: (item) => item, getDisplay: (item) => React__default["default"].createElement(React__default["default"].Fragment, null, cachedDisplayValues[item] || item), name: props.name, defaultValue: defaultValue, onChange: (values) => {
|
|
1612
|
+
}, buildUnstructured: (str) => str, getId: (item) => item, getDisplay: (item) => React__default["default"].createElement(React__default["default"].Fragment, null, cachedDisplayValues[item] || item), name: props.name, defaultValue: defaultValue, loadOnFocus: true, onChange: (values) => {
|
|
1158
1613
|
if (props.onChange) {
|
|
1159
1614
|
props.onChange(values[0]);
|
|
1160
1615
|
}
|
|
@@ -1177,7 +1632,7 @@
|
|
|
1177
1632
|
display: e.display,
|
|
1178
1633
|
}));
|
|
1179
1634
|
});
|
|
1180
|
-
}, buildUnstructured: (str) => ({ code: str }), getId: (item) => item.code, getDisplay: (item) => React__default["default"].createElement(CodingDisplay, { value: item }), name: props.name, defaultValue: defaultValue, onChange: (values) => {
|
|
1635
|
+
}, buildUnstructured: (str) => ({ code: str }), getId: (item) => item.code, getDisplay: (item) => React__default["default"].createElement(CodingDisplay, { value: item }), name: props.name, defaultValue: defaultValue, loadOnFocus: true, onChange: (values) => {
|
|
1181
1636
|
if (props.onChange) {
|
|
1182
1637
|
props.onChange(values[0]);
|
|
1183
1638
|
}
|
|
@@ -1472,31 +1927,6 @@
|
|
|
1472
1927
|
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 })) })));
|
|
1473
1928
|
}
|
|
1474
1929
|
|
|
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
|
-
|
|
1500
1930
|
function ResourceName(props) {
|
|
1501
1931
|
const resource = useResource(props.value);
|
|
1502
1932
|
if (!resource) {
|
|
@@ -1978,67 +2408,10 @@
|
|
|
1978
2408
|
}
|
|
1979
2409
|
function ReferenceRangeDisplay(props) {
|
|
1980
2410
|
const range = props.value && props.value.length > 0 && props.value[0];
|
|
1981
|
-
if (!range) {
|
|
1982
|
-
return null;
|
|
1983
|
-
}
|
|
1984
|
-
return React__default["default"].createElement(RangeDisplay, { value: range });
|
|
1985
|
-
}
|
|
1986
|
-
|
|
1987
|
-
/**
|
|
1988
|
-
* Parses an HTML form and returns the result as a JavaScript object.
|
|
1989
|
-
* @param form The HTML form element.
|
|
1990
|
-
*/
|
|
1991
|
-
function parseForm(form) {
|
|
1992
|
-
const result = {};
|
|
1993
|
-
for (const element of Array.from(form.elements)) {
|
|
1994
|
-
if (element instanceof HTMLInputElement) {
|
|
1995
|
-
parseInputElement(result, element);
|
|
1996
|
-
}
|
|
1997
|
-
else if (element instanceof HTMLTextAreaElement) {
|
|
1998
|
-
result[element.name] = element.value;
|
|
1999
|
-
}
|
|
2000
|
-
else if (element instanceof HTMLSelectElement) {
|
|
2001
|
-
parseSelectElement(result, element);
|
|
2002
|
-
}
|
|
2003
|
-
}
|
|
2004
|
-
return result;
|
|
2005
|
-
}
|
|
2006
|
-
/**
|
|
2007
|
-
* Parses an HTML input element.
|
|
2008
|
-
* Sets the name/value pair in the result,
|
|
2009
|
-
* but only if the element is enabled and checked.
|
|
2010
|
-
* @param el The input element.
|
|
2011
|
-
* @param result The result builder.
|
|
2012
|
-
*/
|
|
2013
|
-
function parseInputElement(result, el) {
|
|
2014
|
-
if (el.disabled) {
|
|
2015
|
-
// Ignore disabled elements
|
|
2016
|
-
return;
|
|
2017
|
-
}
|
|
2018
|
-
if ((el.type === 'checkbox' || el.type === 'radio') && !el.checked) {
|
|
2019
|
-
// Ignore unchecked radio or checkbox elements
|
|
2020
|
-
return;
|
|
2021
|
-
}
|
|
2022
|
-
result[el.name] = el.value;
|
|
2023
|
-
}
|
|
2024
|
-
/**
|
|
2025
|
-
* Parses an HTML select element.
|
|
2026
|
-
* Sets the name/value pair if one is selected.
|
|
2027
|
-
* @param result The result builder.
|
|
2028
|
-
* @param el The select element.
|
|
2029
|
-
*/
|
|
2030
|
-
function parseSelectElement(result, el) {
|
|
2031
|
-
result[el.name] = el.value;
|
|
2032
|
-
}
|
|
2033
|
-
|
|
2034
|
-
function Form(props) {
|
|
2035
|
-
return (React__default["default"].createElement("form", { style: props.style, "data-testid": props.testid, onSubmit: (e) => {
|
|
2036
|
-
e.preventDefault();
|
|
2037
|
-
const formData = parseForm(e.target);
|
|
2038
|
-
if (props.onSubmit) {
|
|
2039
|
-
props.onSubmit(formData);
|
|
2040
|
-
}
|
|
2041
|
-
} }, props.children));
|
|
2411
|
+
if (!range) {
|
|
2412
|
+
return null;
|
|
2413
|
+
}
|
|
2414
|
+
return React__default["default"].createElement(RangeDisplay, { value: range });
|
|
2042
2415
|
}
|
|
2043
2416
|
|
|
2044
2417
|
function Loading() {
|
|
@@ -2056,7 +2429,7 @@
|
|
|
2056
2429
|
const medplum = useMedplum();
|
|
2057
2430
|
const [schema, setSchema] = React.useState();
|
|
2058
2431
|
React.useEffect(() => {
|
|
2059
|
-
medplum.requestSchema(props.original.resourceType).then(setSchema);
|
|
2432
|
+
medplum.requestSchema(props.original.resourceType).then(setSchema).catch(console.log);
|
|
2060
2433
|
}, [medplum, props.original.resourceType]);
|
|
2061
2434
|
if (!schema) {
|
|
2062
2435
|
return null;
|
|
@@ -2109,7 +2482,7 @@
|
|
|
2109
2482
|
const [schema, setSchema] = React.useState();
|
|
2110
2483
|
React.useEffect(() => {
|
|
2111
2484
|
if (value) {
|
|
2112
|
-
medplum.requestSchema(value.resourceType).then(setSchema);
|
|
2485
|
+
medplum.requestSchema(value.resourceType).then(setSchema).catch(console.log);
|
|
2113
2486
|
}
|
|
2114
2487
|
}, [medplum, value]);
|
|
2115
2488
|
if (!schema || !value) {
|
|
@@ -2307,7 +2680,7 @@
|
|
|
2307
2680
|
setHistory({});
|
|
2308
2681
|
return;
|
|
2309
2682
|
}
|
|
2310
|
-
medplum.executeBatch(buildSearchRequests(resource)).then(handleBatchResponse);
|
|
2683
|
+
medplum.executeBatch(buildSearchRequests(resource)).then(handleBatchResponse).catch(console.log);
|
|
2311
2684
|
}, [medplum, resource, buildSearchRequests]);
|
|
2312
2685
|
React.useEffect(() => {
|
|
2313
2686
|
loadTimeline();
|
|
@@ -2330,7 +2703,9 @@
|
|
|
2330
2703
|
}
|
|
2331
2704
|
if (bundle.entry) {
|
|
2332
2705
|
for (const entry of bundle.entry) {
|
|
2333
|
-
|
|
2706
|
+
if (entry.resource) {
|
|
2707
|
+
newItems.push(entry.resource);
|
|
2708
|
+
}
|
|
2334
2709
|
}
|
|
2335
2710
|
}
|
|
2336
2711
|
}
|
|
@@ -2358,9 +2733,12 @@
|
|
|
2358
2733
|
// Encounter not loaded yet
|
|
2359
2734
|
return;
|
|
2360
2735
|
}
|
|
2361
|
-
medplum
|
|
2736
|
+
medplum
|
|
2737
|
+
.createResource(props.createCommunication(resource, sender, contentString))
|
|
2738
|
+
.then((result) => {
|
|
2362
2739
|
addResources([result]);
|
|
2363
|
-
})
|
|
2740
|
+
})
|
|
2741
|
+
.catch(console.log);
|
|
2364
2742
|
}
|
|
2365
2743
|
/**
|
|
2366
2744
|
* Adds a Media resource to the timeline.
|
|
@@ -2371,18 +2749,21 @@
|
|
|
2371
2749
|
// Encounter not loaded yet
|
|
2372
2750
|
return;
|
|
2373
2751
|
}
|
|
2374
|
-
medplum
|
|
2752
|
+
medplum
|
|
2753
|
+
.createResource(props.createMedia(resource, sender, attachment))
|
|
2754
|
+
.then((result) => {
|
|
2375
2755
|
addResources([result]);
|
|
2376
|
-
})
|
|
2756
|
+
})
|
|
2757
|
+
.catch(console.log);
|
|
2377
2758
|
}
|
|
2378
2759
|
function setPriority(communication, priority) {
|
|
2379
2760
|
return medplum.updateResource(Object.assign(Object.assign({}, communication), { priority }));
|
|
2380
2761
|
}
|
|
2381
2762
|
function onPin(communication) {
|
|
2382
|
-
setPriority(communication, 'stat').then(loadTimeline);
|
|
2763
|
+
setPriority(communication, 'stat').then(loadTimeline).catch(console.log);
|
|
2383
2764
|
}
|
|
2384
2765
|
function onUnpin(communication) {
|
|
2385
|
-
setPriority(communication, 'routine').then(loadTimeline);
|
|
2766
|
+
setPriority(communication, 'routine').then(loadTimeline).catch(console.log);
|
|
2386
2767
|
}
|
|
2387
2768
|
function onDetails(timelineItem) {
|
|
2388
2769
|
navigate(`/${timelineItem.resourceType}/${timelineItem.id}`);
|
|
@@ -2511,11 +2892,6 @@
|
|
|
2511
2892
|
}) }));
|
|
2512
2893
|
}
|
|
2513
2894
|
|
|
2514
|
-
function Document(props) {
|
|
2515
|
-
return (React__default["default"].createElement("main", { className: "medplum-document" },
|
|
2516
|
-
React__default["default"].createElement("article", { style: { maxWidth: props.width } }, props.children)));
|
|
2517
|
-
}
|
|
2518
|
-
|
|
2519
2895
|
function EncounterTimeline(props) {
|
|
2520
2896
|
return (React__default["default"].createElement(ResourceTimeline, { value: props.encounter, buildSearchRequests: (resource) => ({
|
|
2521
2897
|
resourceType: 'Bundle',
|
|
@@ -3807,11 +4183,14 @@
|
|
|
3807
4183
|
}
|
|
3808
4184
|
}
|
|
3809
4185
|
React.useEffect(() => {
|
|
3810
|
-
medplum
|
|
4186
|
+
medplum
|
|
4187
|
+
.requestSchema(props.search.resourceType)
|
|
4188
|
+
.then((newSchema) => {
|
|
3811
4189
|
// The schema could have the same object identity,
|
|
3812
4190
|
// so need to use the spread operator to kick React re-render.
|
|
3813
4191
|
setSchema(Object.assign({}, newSchema));
|
|
3814
|
-
})
|
|
4192
|
+
})
|
|
4193
|
+
.catch(console.log);
|
|
3815
4194
|
}, [medplum, props.search.resourceType]);
|
|
3816
4195
|
const typeSchema = (_a = schema === null || schema === void 0 ? void 0 : schema.types) === null || _a === void 0 ? void 0 : _a[props.search.resourceType];
|
|
3817
4196
|
if (!typeSchema) {
|
|
@@ -3995,11 +4374,14 @@
|
|
|
3995
4374
|
}
|
|
3996
4375
|
}
|
|
3997
4376
|
React.useEffect(() => {
|
|
3998
|
-
medplum
|
|
4377
|
+
medplum
|
|
4378
|
+
.requestSchema(props.resourceType)
|
|
4379
|
+
.then((newSchema) => {
|
|
3999
4380
|
// The schema could have the same object identity,
|
|
4000
4381
|
// so need to use the spread operator to kick React re-render.
|
|
4001
4382
|
setSchema(Object.assign({}, newSchema));
|
|
4002
|
-
})
|
|
4383
|
+
})
|
|
4384
|
+
.catch(console.log);
|
|
4003
4385
|
}, [medplum, props.resourceType]);
|
|
4004
4386
|
const typeSchema = (_a = schema === null || schema === void 0 ? void 0 : schema.types) === null || _a === void 0 ? void 0 : _a[props.resourceType];
|
|
4005
4387
|
if (!typeSchema) {
|
|
@@ -4241,9 +4623,13 @@
|
|
|
4241
4623
|
logins.map((login) => {
|
|
4242
4624
|
var _a, _b, _c, _d;
|
|
4243
4625
|
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: () => {
|
|
4244
|
-
medplum
|
|
4245
|
-
|
|
4246
|
-
|
|
4626
|
+
medplum
|
|
4627
|
+
.setActiveLogin(login)
|
|
4628
|
+
.then(() => {
|
|
4629
|
+
setUserMenuVisible(false);
|
|
4630
|
+
window.location.reload();
|
|
4631
|
+
})
|
|
4632
|
+
.catch(console.log);
|
|
4247
4633
|
} },
|
|
4248
4634
|
React__default["default"].createElement("div", { className: "medplum-nav-menu-profile-icon" },
|
|
4249
4635
|
React__default["default"].createElement(Avatar, null)),
|
|
@@ -4284,16 +4670,6 @@
|
|
|
4284
4670
|
React__default["default"].createElement(MedplumLink, { to: "/changepassword" }, "Change password"))))));
|
|
4285
4671
|
}
|
|
4286
4672
|
|
|
4287
|
-
function Logo(props) {
|
|
4288
|
-
return (React__default["default"].createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 491 491", style: { width: props.size, height: props.size } },
|
|
4289
|
-
React__default["default"].createElement("title", null, "Medplum Logo"),
|
|
4290
|
-
React__default["default"].createElement("path", { fill: props.fill || '#ad7136', d: "M282 67c6-16 16-29 29-40L289 0c-22 17-37 41-43 68l17 23 19-24z" }),
|
|
4291
|
-
React__default["default"].createElement("path", { fill: props.fill || '#654b87', d: "M311 63c-17 0-33 4-48 11-16-7-32-11-49-11-87 0-158 96-158 214s71 214 158 214c17 0 33-4 49-11 15 7 31 11 48 11 87 0 158-96 158-214S398 63 311 63z" }),
|
|
4292
|
-
React__default["default"].createElement("path", { fill: props.fill || '#463068', d: "M231 489l-17 2c-87 0-158-96-158-214S127 63 214 63l17 1c-39 12-70 102-70 213s31 201 70 212z" }),
|
|
4293
|
-
React__default["default"].createElement("path", { fill: props.fill || '#70d65b', d: "M207 220a176 176 0 01-177 43A176 176 0 01251 43l1 5c17 59 2 125-45 172z" }),
|
|
4294
|
-
React__default["default"].createElement("path", { fill: props.fill || '#58b741', d: "M252 48A421 421 0 0057 270l-27-7A176 176 0 01251 43l1 5z" })));
|
|
4295
|
-
}
|
|
4296
|
-
|
|
4297
4673
|
const searches = [
|
|
4298
4674
|
'$/_history',
|
|
4299
4675
|
'Communication?subject=$',
|
|
@@ -4344,7 +4720,7 @@
|
|
|
4344
4720
|
const valueRef = React.useRef();
|
|
4345
4721
|
valueRef.current = value;
|
|
4346
4722
|
React.useEffect(() => {
|
|
4347
|
-
medplum.requestSchema('PlanDefinition').then(setSchema);
|
|
4723
|
+
medplum.requestSchema('PlanDefinition').then(setSchema).catch(console.log);
|
|
4348
4724
|
}, [medplum]);
|
|
4349
4725
|
React.useEffect(() => {
|
|
4350
4726
|
setValue(ensurePlanDefinitionKeys(defaultValue !== null && defaultValue !== void 0 ? defaultValue : { resourceType: 'PlanDefinition' }));
|
|
@@ -4640,7 +5016,7 @@
|
|
|
4640
5016
|
const questionnaire = useResource(props.questionnaire);
|
|
4641
5017
|
const [response, setResponse] = React.useState();
|
|
4642
5018
|
React.useEffect(() => {
|
|
4643
|
-
medplum.requestSchema('Questionnaire').then(setSchema);
|
|
5019
|
+
medplum.requestSchema('Questionnaire').then(setSchema).catch(console.log);
|
|
4644
5020
|
}, [medplum]);
|
|
4645
5021
|
React.useEffect(() => {
|
|
4646
5022
|
setResponse(questionnaire ? buildInitialResponse(questionnaire) : undefined);
|
|
@@ -4683,6 +5059,7 @@
|
|
|
4683
5059
|
return (React__default["default"].createElement(CheckboxFormSection, { key: item.linkId, title: item.text, htmlFor: item.linkId },
|
|
4684
5060
|
React__default["default"].createElement(Checkbox, { name: item.linkId, defaultValue: initial === null || initial === void 0 ? void 0 : initial.valueBoolean, onChange: (newValue) => setResponseItem(index, {
|
|
4685
5061
|
linkId: item.linkId,
|
|
5062
|
+
text: item.text,
|
|
4686
5063
|
answer: [{ valueBoolean: newValue }],
|
|
4687
5064
|
}) })));
|
|
4688
5065
|
}
|
|
@@ -4845,7 +5222,7 @@
|
|
|
4845
5222
|
setSelectedKey(undefined);
|
|
4846
5223
|
}
|
|
4847
5224
|
React.useEffect(() => {
|
|
4848
|
-
medplum.requestSchema('Questionnaire').then(setSchema);
|
|
5225
|
+
medplum.requestSchema('Questionnaire').then(setSchema).catch(console.log);
|
|
4849
5226
|
}, [medplum]);
|
|
4850
5227
|
React.useEffect(() => {
|
|
4851
5228
|
setValue(ensureQuestionnaireKeys(defaultValue !== null && defaultValue !== void 0 ? defaultValue : { resourceType: 'Questionnaire' }));
|
|
@@ -5031,190 +5408,6 @@
|
|
|
5031
5408
|
return options.map((option) => (Object.assign(Object.assign({}, option), { id: option.id || generateId() })));
|
|
5032
5409
|
}
|
|
5033
5410
|
|
|
5034
|
-
/**
|
|
5035
|
-
* Dynamically creates a script tag for the specified JavaScript file.
|
|
5036
|
-
* @param src The JavaScript file URL.
|
|
5037
|
-
*/
|
|
5038
|
-
function createScriptTag(src, onload) {
|
|
5039
|
-
const head = document.getElementsByTagName('head')[0];
|
|
5040
|
-
const script = document.createElement('script');
|
|
5041
|
-
script.async = true;
|
|
5042
|
-
script.src = src;
|
|
5043
|
-
script.onload = onload || null;
|
|
5044
|
-
head.appendChild(script);
|
|
5045
|
-
}
|
|
5046
|
-
|
|
5047
|
-
function GoogleButton(props) {
|
|
5048
|
-
const medplum = useMedplum();
|
|
5049
|
-
const { googleClientId, handleGoogleCredential } = props;
|
|
5050
|
-
const parentRef = React.useRef(null);
|
|
5051
|
-
const [scriptLoaded, setScriptLoaded] = React.useState(typeof google !== 'undefined');
|
|
5052
|
-
const [initialized, setInitialized] = React.useState(false);
|
|
5053
|
-
const [buttonRendered, setButtonRendered] = React.useState(false);
|
|
5054
|
-
React.useEffect(() => {
|
|
5055
|
-
if (typeof google === 'undefined') {
|
|
5056
|
-
createScriptTag('https://accounts.google.com/gsi/client', () => setScriptLoaded(true));
|
|
5057
|
-
return;
|
|
5058
|
-
}
|
|
5059
|
-
if (!initialized) {
|
|
5060
|
-
google.accounts.id.initialize({
|
|
5061
|
-
client_id: googleClientId,
|
|
5062
|
-
callback: handleGoogleCredential,
|
|
5063
|
-
});
|
|
5064
|
-
setInitialized(true);
|
|
5065
|
-
}
|
|
5066
|
-
if (parentRef.current && !buttonRendered) {
|
|
5067
|
-
google.accounts.id.renderButton(parentRef.current, {});
|
|
5068
|
-
setButtonRendered(true);
|
|
5069
|
-
}
|
|
5070
|
-
}, [medplum, googleClientId, initialized, scriptLoaded, parentRef, buttonRendered, handleGoogleCredential]);
|
|
5071
|
-
if (!googleClientId) {
|
|
5072
|
-
return null;
|
|
5073
|
-
}
|
|
5074
|
-
return React__default["default"].createElement("div", { ref: parentRef });
|
|
5075
|
-
}
|
|
5076
|
-
function getGoogleClientId(clientId) {
|
|
5077
|
-
var _a, _b;
|
|
5078
|
-
if (clientId) {
|
|
5079
|
-
return clientId;
|
|
5080
|
-
}
|
|
5081
|
-
const origin = window.location.protocol + '//' + window.location.host;
|
|
5082
|
-
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 : [];
|
|
5083
|
-
if (authorizedOrigins.includes(origin)) {
|
|
5084
|
-
return "921088377005-3j1sa10vr6hj86jgmdfh2l53v3mp7lfi.apps.googleusercontent.com";
|
|
5085
|
-
}
|
|
5086
|
-
return undefined;
|
|
5087
|
-
}
|
|
5088
|
-
|
|
5089
|
-
/**
|
|
5090
|
-
* Dynamically loads the recaptcha script.
|
|
5091
|
-
* We do not want to load the script on page load unless the user needs it.
|
|
5092
|
-
* @param siteKey The reCAPTCHA site key, available from the reCAPTCHA admin page.
|
|
5093
|
-
*/
|
|
5094
|
-
function initRecaptcha(siteKey) {
|
|
5095
|
-
if (typeof grecaptcha === 'undefined') {
|
|
5096
|
-
createScriptTag('https://www.google.com/recaptcha/api.js?render=' + siteKey);
|
|
5097
|
-
}
|
|
5098
|
-
}
|
|
5099
|
-
/**
|
|
5100
|
-
* Starts a request to generate a recapcha token.
|
|
5101
|
-
* @param siteKey The reCAPTCHA site key, available from the reCAPTCHA admin page.
|
|
5102
|
-
* @returns Promise to a recaptcha token for the current user.
|
|
5103
|
-
*/
|
|
5104
|
-
function getRecaptcha(siteKey) {
|
|
5105
|
-
return new Promise((resolve) => {
|
|
5106
|
-
grecaptcha.ready(() => {
|
|
5107
|
-
grecaptcha.execute(siteKey, { action: 'submit' }).then(resolve);
|
|
5108
|
-
});
|
|
5109
|
-
});
|
|
5110
|
-
}
|
|
5111
|
-
|
|
5112
|
-
function RegisterForm(props) {
|
|
5113
|
-
const medplum = useMedplum();
|
|
5114
|
-
const googleClientId = getGoogleClientId(props.googleClientId);
|
|
5115
|
-
const recaptchaSiteKey = props.recaptchaSiteKey;
|
|
5116
|
-
const [outcome, setOutcome] = React.useState();
|
|
5117
|
-
const issues = getIssuesForExpression(outcome, undefined);
|
|
5118
|
-
React.useEffect(() => initRecaptcha(recaptchaSiteKey), [recaptchaSiteKey]);
|
|
5119
|
-
function handleAuthResponse(registerRequest, partialLogin) {
|
|
5120
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
5121
|
-
try {
|
|
5122
|
-
let login;
|
|
5123
|
-
if (props.type === 'patient') {
|
|
5124
|
-
login = yield medplum.startNewPatient(registerRequest, partialLogin);
|
|
5125
|
-
}
|
|
5126
|
-
else {
|
|
5127
|
-
login = yield medplum.startNewProject(registerRequest, partialLogin);
|
|
5128
|
-
}
|
|
5129
|
-
yield medplum.processCode(login.code);
|
|
5130
|
-
props.onSuccess();
|
|
5131
|
-
}
|
|
5132
|
-
catch (err) {
|
|
5133
|
-
setOutcome(err);
|
|
5134
|
-
}
|
|
5135
|
-
});
|
|
5136
|
-
}
|
|
5137
|
-
return (React__default["default"].createElement(Document, { width: 450 },
|
|
5138
|
-
React__default["default"].createElement(Form, { style: { maxWidth: 400 }, onSubmit: (formData) => __awaiter(this, void 0, void 0, function* () {
|
|
5139
|
-
try {
|
|
5140
|
-
const recaptchaToken = yield getRecaptcha(recaptchaSiteKey);
|
|
5141
|
-
const registerRequest = {
|
|
5142
|
-
projectId: props.projectId,
|
|
5143
|
-
projectName: formData.projectName,
|
|
5144
|
-
firstName: formData.firstName,
|
|
5145
|
-
lastName: formData.lastName,
|
|
5146
|
-
email: formData.email,
|
|
5147
|
-
password: formData.password,
|
|
5148
|
-
remember: formData.remember === 'true',
|
|
5149
|
-
recaptchaSiteKey,
|
|
5150
|
-
recaptchaToken,
|
|
5151
|
-
};
|
|
5152
|
-
const userLogin = yield medplum.startNewUser(registerRequest);
|
|
5153
|
-
handleAuthResponse(registerRequest, userLogin);
|
|
5154
|
-
}
|
|
5155
|
-
catch (err) {
|
|
5156
|
-
setOutcome(err);
|
|
5157
|
-
}
|
|
5158
|
-
}) },
|
|
5159
|
-
React__default["default"].createElement("div", { className: "medplum-center" }, props.children),
|
|
5160
|
-
issues && (React__default["default"].createElement("div", { className: "medplum-input-error" }, issues.map((issue) => {
|
|
5161
|
-
var _a, _b;
|
|
5162
|
-
return (React__default["default"].createElement("div", { "data-testid": "text-field-error", key: (_a = issue.details) === null || _a === void 0 ? void 0 : _a.text }, (_b = issue.details) === null || _b === void 0 ? void 0 : _b.text));
|
|
5163
|
-
}))),
|
|
5164
|
-
googleClientId && (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
5165
|
-
React__default["default"].createElement("div", { className: "medplum-signin-google-container" },
|
|
5166
|
-
React__default["default"].createElement(GoogleButton, { googleClientId: googleClientId, handleGoogleCredential: (response) => __awaiter(this, void 0, void 0, function* () {
|
|
5167
|
-
try {
|
|
5168
|
-
const loginRequest = {
|
|
5169
|
-
googleClientId: response.clientId,
|
|
5170
|
-
googleCredential: response.credential,
|
|
5171
|
-
};
|
|
5172
|
-
const userLogin = yield medplum.startGoogleLogin(loginRequest);
|
|
5173
|
-
const googleClaims = core.parseJWTPayload(loginRequest.googleCredential);
|
|
5174
|
-
const registerRequest = {
|
|
5175
|
-
projectId: props.projectId,
|
|
5176
|
-
firstName: googleClaims.given_name,
|
|
5177
|
-
lastName: googleClaims.family_name,
|
|
5178
|
-
email: googleClaims.email,
|
|
5179
|
-
};
|
|
5180
|
-
handleAuthResponse(registerRequest, userLogin);
|
|
5181
|
-
}
|
|
5182
|
-
catch (err) {
|
|
5183
|
-
setOutcome(err);
|
|
5184
|
-
}
|
|
5185
|
-
}) })),
|
|
5186
|
-
React__default["default"].createElement("div", { className: "medplum-signin-separator" }, "or"))),
|
|
5187
|
-
React__default["default"].createElement(FormSection, { title: "First Name", htmlFor: "firstName", outcome: outcome },
|
|
5188
|
-
React__default["default"].createElement(Input, { name: "firstName", type: "text", testid: "firstName", placeholder: "First name", required: true, autoFocus: true, outcome: outcome })),
|
|
5189
|
-
React__default["default"].createElement(FormSection, { title: "Last Name", htmlFor: "lastName", outcome: outcome },
|
|
5190
|
-
React__default["default"].createElement(Input, { name: "lastName", type: "text", testid: "lastName", placeholder: "Last name", required: true, outcome: outcome })),
|
|
5191
|
-
props.type === 'project' && (React__default["default"].createElement(FormSection, { title: "Project Name", htmlFor: "projectName", outcome: outcome },
|
|
5192
|
-
React__default["default"].createElement(Input, { name: "projectName", type: "text", testid: "projectName", placeholder: "My Project", required: true, outcome: outcome }))),
|
|
5193
|
-
React__default["default"].createElement(FormSection, { title: "Email", htmlFor: "email", outcome: outcome },
|
|
5194
|
-
React__default["default"].createElement(Input, { name: "email", type: "email", testid: "email", placeholder: "name@domain.com", required: true, outcome: outcome })),
|
|
5195
|
-
React__default["default"].createElement(FormSection, { title: "Password", htmlFor: "password", outcome: outcome },
|
|
5196
|
-
React__default["default"].createElement(Input, { name: "password", type: "password", testid: "password", autoComplete: "off", required: true, outcome: outcome })),
|
|
5197
|
-
React__default["default"].createElement("p", { style: { fontSize: '12px', color: '#888' } },
|
|
5198
|
-
"By clicking submit you agree to the Medplum ",
|
|
5199
|
-
React__default["default"].createElement("a", { href: "https://www.medplum.com/privacy" }, "Privacy\u00A0Policy"),
|
|
5200
|
-
' and ',
|
|
5201
|
-
React__default["default"].createElement("a", { href: "https://www.medplum.com/terms" }, "Terms\u00A0of\u00A0Service"),
|
|
5202
|
-
"."),
|
|
5203
|
-
React__default["default"].createElement("p", { style: { fontSize: '12px', color: '#888' } },
|
|
5204
|
-
"This site is protected by reCAPTCHA and the Google",
|
|
5205
|
-
' ',
|
|
5206
|
-
React__default["default"].createElement("a", { href: "https://policies.google.com/privacy" }, "Privacy\u00A0Policy"),
|
|
5207
|
-
' and ',
|
|
5208
|
-
React__default["default"].createElement("a", { href: "https://policies.google.com/terms" }, "Terms\u00A0of\u00A0Service"),
|
|
5209
|
-
" apply."),
|
|
5210
|
-
React__default["default"].createElement("div", { className: "medplum-signin-buttons" },
|
|
5211
|
-
React__default["default"].createElement("div", null,
|
|
5212
|
-
React__default["default"].createElement("input", { type: "checkbox", id: "remember", name: "remember", value: "true" }),
|
|
5213
|
-
React__default["default"].createElement("label", { htmlFor: "remember" }, "Remember me")),
|
|
5214
|
-
React__default["default"].createElement("div", null,
|
|
5215
|
-
React__default["default"].createElement(Button, { type: "submit", testid: "submit" }, "Create account"))))));
|
|
5216
|
-
}
|
|
5217
|
-
|
|
5218
5411
|
function StatusBadge(props) {
|
|
5219
5412
|
return React__default["default"].createElement("span", { className: `medplum-status medplum-status-${props.status}` }, props.status);
|
|
5220
5413
|
}
|
|
@@ -5227,7 +5420,7 @@
|
|
|
5227
5420
|
const [responseBundle, setResponseBundle] = React.useState();
|
|
5228
5421
|
React.useEffect(() => {
|
|
5229
5422
|
if (requestGroup && !startedLoading) {
|
|
5230
|
-
medplum.executeBatch(buildBatchRequest(requestGroup)).then(setResponseBundle);
|
|
5423
|
+
medplum.executeBatch(buildBatchRequest(requestGroup)).then(setResponseBundle).catch(console.log);
|
|
5231
5424
|
setStartedLoading(true);
|
|
5232
5425
|
}
|
|
5233
5426
|
}, [medplum, requestGroup, startedLoading]);
|
|
@@ -5472,7 +5665,7 @@
|
|
|
5472
5665
|
const [value, setValue] = React.useState(props.history);
|
|
5473
5666
|
React.useEffect(() => {
|
|
5474
5667
|
if (!props.history && props.resourceType && props.id) {
|
|
5475
|
-
medplum.readHistory(props.resourceType, props.id).then(
|
|
5668
|
+
medplum.readHistory(props.resourceType, props.id).then(setValue).catch(console.log);
|
|
5476
5669
|
}
|
|
5477
5670
|
}, [medplum, props.history, props.resourceType, props.id]);
|
|
5478
5671
|
if (!value) {
|
|
@@ -5550,7 +5743,10 @@
|
|
|
5550
5743
|
const [value, setValue] = React.useState(props.history);
|
|
5551
5744
|
React.useEffect(() => {
|
|
5552
5745
|
if (!props.history && props.resourceType && props.id) {
|
|
5553
|
-
medplum
|
|
5746
|
+
medplum
|
|
5747
|
+
.readHistory(props.resourceType, props.id)
|
|
5748
|
+
.then(setValue)
|
|
5749
|
+
.catch(console.log);
|
|
5554
5750
|
}
|
|
5555
5751
|
}, [medplum, props.history, props.resourceType, props.id]);
|
|
5556
5752
|
if (!value) {
|
|
@@ -5562,19 +5758,23 @@
|
|
|
5562
5758
|
React__default["default"].createElement("th", null, "Author"),
|
|
5563
5759
|
React__default["default"].createElement("th", null, "Date"),
|
|
5564
5760
|
React__default["default"].createElement("th", null, "Version"))),
|
|
5565
|
-
React__default["default"].createElement("tbody", null, (_a = value.entry) === null || _a === void 0 ? void 0 : _a.map((entry) => {
|
|
5566
|
-
var _a, _b;
|
|
5567
|
-
return (React__default["default"].createElement(HistoryRow, { key: (_b = (_a = entry.resource) === null || _a === void 0 ? void 0 : _a.meta) === null || _b === void 0 ? void 0 : _b.versionId, version: entry.resource }));
|
|
5568
|
-
}))));
|
|
5761
|
+
React__default["default"].createElement("tbody", null, (_a = value.entry) === null || _a === void 0 ? void 0 : _a.map((entry, index) => (React__default["default"].createElement(HistoryRow, { key: 'entry-' + index, entry: entry }))))));
|
|
5569
5762
|
}
|
|
5570
5763
|
function HistoryRow(props) {
|
|
5571
5764
|
var _a, _b, _c;
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
React__default["default"].createElement(
|
|
5765
|
+
const { response, resource } = props.entry;
|
|
5766
|
+
if (resource) {
|
|
5767
|
+
return (React__default["default"].createElement("tr", null,
|
|
5768
|
+
React__default["default"].createElement("td", null,
|
|
5769
|
+
React__default["default"].createElement(ResourceBadge, { value: (_a = resource.meta) === null || _a === void 0 ? void 0 : _a.author, link: true })),
|
|
5770
|
+
React__default["default"].createElement("td", null, core.formatDateTime((_b = resource.meta) === null || _b === void 0 ? void 0 : _b.lastUpdated)),
|
|
5771
|
+
React__default["default"].createElement("td", null,
|
|
5772
|
+
React__default["default"].createElement(MedplumLink, { to: getVersionUrl(resource) }, (_c = resource.meta) === null || _c === void 0 ? void 0 : _c.versionId))));
|
|
5773
|
+
}
|
|
5774
|
+
else {
|
|
5775
|
+
return (React__default["default"].createElement("tr", null,
|
|
5776
|
+
React__default["default"].createElement("td", { colSpan: 3 }, core.normalizeErrorString(response === null || response === void 0 ? void 0 : response.outcome))));
|
|
5777
|
+
}
|
|
5578
5778
|
}
|
|
5579
5779
|
function getVersionUrl(resource) {
|
|
5580
5780
|
var _a;
|
|
@@ -5590,12 +5790,14 @@
|
|
|
5590
5790
|
return date.toLocaleString('default', { month: 'long' }) + ' ' + date.getFullYear();
|
|
5591
5791
|
}
|
|
5592
5792
|
function CalendarInput(props) {
|
|
5793
|
+
const { onChangeMonth, onClick } = props;
|
|
5593
5794
|
const [month, setMonth] = React.useState(getStartMonth);
|
|
5594
5795
|
function moveMonth(delta) {
|
|
5595
5796
|
setMonth((currMonth) => {
|
|
5596
|
-
const
|
|
5597
|
-
|
|
5598
|
-
|
|
5797
|
+
const newMonth = new Date(currMonth.getTime());
|
|
5798
|
+
newMonth.setMonth(currMonth.getMonth() + delta);
|
|
5799
|
+
onChangeMonth(newMonth);
|
|
5800
|
+
return newMonth;
|
|
5599
5801
|
});
|
|
5600
5802
|
}
|
|
5601
5803
|
const grid = React.useMemo(() => buildGrid(month, props.slots), [month, props.slots]);
|
|
@@ -5615,7 +5817,7 @@
|
|
|
5615
5817
|
React__default["default"].createElement("th", null, "THU"),
|
|
5616
5818
|
React__default["default"].createElement("th", null, "FRI"),
|
|
5617
5819
|
React__default["default"].createElement("th", null, "SAT"))),
|
|
5618
|
-
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: () =>
|
|
5820
|
+
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()))))))))))));
|
|
5619
5821
|
}
|
|
5620
5822
|
function getStartMonth() {
|
|
5621
5823
|
const result = new Date();
|
|
@@ -5634,7 +5836,6 @@
|
|
|
5634
5836
|
while (d.getMonth() === startDate.getMonth()) {
|
|
5635
5837
|
row.push({
|
|
5636
5838
|
date: new Date(d.getTime()),
|
|
5637
|
-
// available: isAvailable(d),
|
|
5638
5839
|
available: isDayAvailable(d, slots),
|
|
5639
5840
|
});
|
|
5640
5841
|
if (d.getDay() === 6) {
|
|
@@ -5678,20 +5879,27 @@
|
|
|
5678
5879
|
const [slots, setSlots] = React.useState();
|
|
5679
5880
|
const slotsRef = React.useRef();
|
|
5680
5881
|
slotsRef.current = slots;
|
|
5882
|
+
const [month, setMonth] = React.useState(getStartMonth());
|
|
5681
5883
|
const [date, setDate] = React.useState();
|
|
5682
5884
|
const [slot, setSlot] = React.useState();
|
|
5683
5885
|
const [info, setInfo] = React.useState();
|
|
5684
5886
|
const [form, setForm] = React.useState();
|
|
5685
5887
|
React.useEffect(() => {
|
|
5686
5888
|
if (schedule) {
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5889
|
+
setSlots([]);
|
|
5890
|
+
medplum
|
|
5891
|
+
.searchResources('Slot', new URLSearchParams([
|
|
5892
|
+
['schedule', core.getReferenceString(schedule)],
|
|
5893
|
+
['start', 'gt' + month.toISOString()],
|
|
5894
|
+
['start', 'lt' + new Date(month.getTime() + 31 * 24 * 60 * 60 * 1000).toISOString()],
|
|
5895
|
+
]))
|
|
5896
|
+
.then(setSlots)
|
|
5897
|
+
.catch(console.log);
|
|
5690
5898
|
}
|
|
5691
5899
|
else {
|
|
5692
5900
|
setSlots(undefined);
|
|
5693
5901
|
}
|
|
5694
|
-
}, [medplum, schedule]);
|
|
5902
|
+
}, [medplum, schedule, month]);
|
|
5695
5903
|
if (!schedule || !slots) {
|
|
5696
5904
|
return null;
|
|
5697
5905
|
}
|
|
@@ -5707,7 +5915,7 @@
|
|
|
5707
5915
|
React__default["default"].createElement("div", { className: "medplum-calendar-selection-pane" },
|
|
5708
5916
|
!date && (React__default["default"].createElement("div", null,
|
|
5709
5917
|
React__default["default"].createElement("h3", null, "Select date"),
|
|
5710
|
-
React__default["default"].createElement(CalendarInput, { slots: slots, onClick: setDate }))),
|
|
5918
|
+
React__default["default"].createElement(CalendarInput, { slots: slots, onChangeMonth: setMonth, onClick: setDate }))),
|
|
5711
5919
|
date && !slot && (React__default["default"].createElement("div", null,
|
|
5712
5920
|
React__default["default"].createElement("h3", null, "Select time"),
|
|
5713
5921
|
slots.map((s) => {
|
|
@@ -5787,121 +5995,6 @@
|
|
|
5787
5995
|
}) }));
|
|
5788
5996
|
}
|
|
5789
5997
|
|
|
5790
|
-
function SignInForm(props) {
|
|
5791
|
-
const medplum = useMedplum();
|
|
5792
|
-
const [login, setLogin] = React.useState(undefined);
|
|
5793
|
-
const [memberships, setMemberships] = React.useState(undefined);
|
|
5794
|
-
function handleAuthResponse(response) {
|
|
5795
|
-
if (response.login) {
|
|
5796
|
-
setLogin(response.login);
|
|
5797
|
-
}
|
|
5798
|
-
if (response.memberships) {
|
|
5799
|
-
setMemberships(response.memberships);
|
|
5800
|
-
}
|
|
5801
|
-
if (response.code) {
|
|
5802
|
-
if (props.onCode) {
|
|
5803
|
-
props.onCode(response.code);
|
|
5804
|
-
}
|
|
5805
|
-
else {
|
|
5806
|
-
medplum
|
|
5807
|
-
.processCode(response.code)
|
|
5808
|
-
.then(() => {
|
|
5809
|
-
if (props.onSuccess) {
|
|
5810
|
-
props.onSuccess();
|
|
5811
|
-
}
|
|
5812
|
-
})
|
|
5813
|
-
.catch(console.log);
|
|
5814
|
-
}
|
|
5815
|
-
}
|
|
5816
|
-
}
|
|
5817
|
-
return (React__default["default"].createElement(Document, { width: 450 }, (() => {
|
|
5818
|
-
if (!login) {
|
|
5819
|
-
return (React__default["default"].createElement(AuthenticationForm, { clientId: props.clientId, scope: props.scope, nonce: props.nonce, googleClientId: props.googleClientId, onForgotPassword: props.onForgotPassword, onRegister: props.onRegister, handleAuthResponse: handleAuthResponse }, props.children));
|
|
5820
|
-
}
|
|
5821
|
-
else if (memberships) {
|
|
5822
|
-
return React__default["default"].createElement(ProfileForm, { login: login, memberships: memberships, handleAuthResponse: handleAuthResponse });
|
|
5823
|
-
}
|
|
5824
|
-
else {
|
|
5825
|
-
return React__default["default"].createElement("div", null, "Success");
|
|
5826
|
-
}
|
|
5827
|
-
})()));
|
|
5828
|
-
}
|
|
5829
|
-
function AuthenticationForm(props) {
|
|
5830
|
-
const medplum = useMedplum();
|
|
5831
|
-
const googleClientId = getGoogleClientId(props.googleClientId);
|
|
5832
|
-
const [outcome, setOutcome] = React.useState();
|
|
5833
|
-
const issues = getIssuesForExpression(outcome, undefined);
|
|
5834
|
-
return (React__default["default"].createElement(Form, { style: { maxWidth: 400 }, onSubmit: (formData) => {
|
|
5835
|
-
medplum
|
|
5836
|
-
.startLogin({
|
|
5837
|
-
clientId: props.clientId,
|
|
5838
|
-
scope: props.scope,
|
|
5839
|
-
nonce: props.nonce,
|
|
5840
|
-
email: formData.email,
|
|
5841
|
-
password: formData.password,
|
|
5842
|
-
remember: formData.remember === 'true',
|
|
5843
|
-
})
|
|
5844
|
-
.then(props.handleAuthResponse)
|
|
5845
|
-
.catch(setOutcome);
|
|
5846
|
-
} },
|
|
5847
|
-
React__default["default"].createElement("div", { className: "medplum-center" }, props.children),
|
|
5848
|
-
issues && (React__default["default"].createElement("div", { className: "medplum-input-error" }, issues.map((issue) => {
|
|
5849
|
-
var _a, _b;
|
|
5850
|
-
return (React__default["default"].createElement("div", { "data-testid": "text-field-error", key: (_a = issue.details) === null || _a === void 0 ? void 0 : _a.text }, (_b = issue.details) === null || _b === void 0 ? void 0 : _b.text));
|
|
5851
|
-
}))),
|
|
5852
|
-
googleClientId && (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
5853
|
-
React__default["default"].createElement("div", { className: "medplum-signin-google-container" },
|
|
5854
|
-
React__default["default"].createElement(GoogleButton, { googleClientId: googleClientId, handleGoogleCredential: (response) => {
|
|
5855
|
-
medplum
|
|
5856
|
-
.startGoogleLogin({
|
|
5857
|
-
clientId: props.clientId,
|
|
5858
|
-
scope: props.scope,
|
|
5859
|
-
nonce: props.nonce,
|
|
5860
|
-
googleClientId: response.clientId,
|
|
5861
|
-
googleCredential: response.credential,
|
|
5862
|
-
})
|
|
5863
|
-
.then(props.handleAuthResponse)
|
|
5864
|
-
.catch(setOutcome);
|
|
5865
|
-
} })),
|
|
5866
|
-
React__default["default"].createElement("div", { className: "medplum-signin-separator" }, "or"))),
|
|
5867
|
-
React__default["default"].createElement(FormSection, { title: "Email", htmlFor: "email", outcome: outcome },
|
|
5868
|
-
React__default["default"].createElement(Input, { name: "email", type: "email", testid: "email", required: true, autoFocus: true, outcome: outcome })),
|
|
5869
|
-
React__default["default"].createElement(FormSection, { title: "Password", htmlFor: "password", outcome: outcome },
|
|
5870
|
-
React__default["default"].createElement(Input, { name: "password", type: "password", testid: "password", autoComplete: "off", required: true, outcome: outcome })),
|
|
5871
|
-
React__default["default"].createElement("div", { className: "medplum-signin-buttons" },
|
|
5872
|
-
(props.onForgotPassword || props.onRegister) && (React__default["default"].createElement("div", null,
|
|
5873
|
-
props.onForgotPassword && (React__default["default"].createElement(MedplumLink, { testid: "forgotpassword", onClick: props.onForgotPassword }, "Forgot password")),
|
|
5874
|
-
props.onRegister && (React__default["default"].createElement(MedplumLink, { testid: "register", onClick: props.onRegister }, "Register")))),
|
|
5875
|
-
React__default["default"].createElement("div", null,
|
|
5876
|
-
React__default["default"].createElement("input", { type: "checkbox", id: "remember", name: "remember", value: "true" }),
|
|
5877
|
-
React__default["default"].createElement("label", { htmlFor: "remember" }, "Remember me")),
|
|
5878
|
-
React__default["default"].createElement("div", null,
|
|
5879
|
-
React__default["default"].createElement(Button, { type: "submit", testid: "submit" }, "Sign in")))));
|
|
5880
|
-
}
|
|
5881
|
-
function ProfileForm(props) {
|
|
5882
|
-
const medplum = useMedplum();
|
|
5883
|
-
return (React__default["default"].createElement("div", null,
|
|
5884
|
-
React__default["default"].createElement("div", { className: "medplum-center" },
|
|
5885
|
-
React__default["default"].createElement(Logo, { size: 32 }),
|
|
5886
|
-
React__default["default"].createElement("h1", null, "Choose profile")),
|
|
5887
|
-
props.memberships.map((membership) => {
|
|
5888
|
-
var _a, _b, _c;
|
|
5889
|
-
return (React__default["default"].createElement("div", { className: "medplum-nav-menu-profile", key: membership.id, onClick: () => {
|
|
5890
|
-
medplum
|
|
5891
|
-
.post('auth/profile', {
|
|
5892
|
-
login: props.login,
|
|
5893
|
-
profile: membership.id,
|
|
5894
|
-
})
|
|
5895
|
-
.then(props.handleAuthResponse);
|
|
5896
|
-
} },
|
|
5897
|
-
React__default["default"].createElement("div", { className: "medplum-nav-menu-profile-icon" },
|
|
5898
|
-
React__default["default"].createElement(Avatar, { alt: (_a = membership.profile) === null || _a === void 0 ? void 0 : _a.display })),
|
|
5899
|
-
React__default["default"].createElement("div", { className: "medplum-nav-menu-profile-label" }, (_b = membership.profile) === null || _b === void 0 ? void 0 :
|
|
5900
|
-
_b.display,
|
|
5901
|
-
React__default["default"].createElement("div", { className: "medplum-nav-menu-profile-help-text" }, (_c = membership.project) === null || _c === void 0 ? void 0 : _c.display))));
|
|
5902
|
-
})));
|
|
5903
|
-
}
|
|
5904
|
-
|
|
5905
5998
|
function Tab(props) {
|
|
5906
5999
|
let className = 'medplum-tab';
|
|
5907
6000
|
if (props.selected) {
|
|
@@ -5968,6 +6061,8 @@
|
|
|
5968
6061
|
exports.ContactPointInput = ContactPointInput;
|
|
5969
6062
|
exports.DateTimeInput = DateTimeInput;
|
|
5970
6063
|
exports.DefaultResourceTimeline = DefaultResourceTimeline;
|
|
6064
|
+
exports.DescriptionList = DescriptionList;
|
|
6065
|
+
exports.DescriptionListEntry = DescriptionListEntry;
|
|
5971
6066
|
exports.DiagnosticReportDisplay = DiagnosticReportDisplay;
|
|
5972
6067
|
exports.Document = Document;
|
|
5973
6068
|
exports.ElementDefinitionInputSelector = ElementDefinitionInputSelector;
|