@medplum/react 0.9.30 → 0.9.33
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/QuestionnaireForm.d.ts +1 -0
- package/dist/cjs/Scheduler.d.ts +2 -1
- package/dist/cjs/auth/AuthenticationForm.d.ts +16 -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/cjs/{SignInForm.d.ts → auth/SignInForm.d.ts} +3 -1
- package/dist/cjs/index.d.ts +2 -2
- package/dist/cjs/index.js +700 -678
- 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/styles.css +197 -197
- package/dist/esm/MedplumLink.js +29 -14
- package/dist/esm/MedplumLink.js.map +1 -1
- package/dist/esm/QuestionnaireForm.d.ts +1 -0
- package/dist/esm/QuestionnaireForm.js +1 -1
- package/dist/esm/QuestionnaireForm.js.map +1 -1
- package/dist/esm/ResourceHistoryTable.js +15 -11
- package/dist/esm/ResourceHistoryTable.js.map +1 -1
- package/dist/esm/ResourceTimeline.js +3 -1
- package/dist/esm/ResourceTimeline.js.map +1 -1
- package/dist/esm/Scheduler.d.ts +2 -1
- package/dist/esm/Scheduler.js +18 -24
- package/dist/esm/Scheduler.js.map +1 -1
- package/dist/esm/ServiceRequestTimeline.js +3 -3
- package/dist/esm/ServiceRequestTimeline.js.map +1 -1
- package/dist/esm/auth/AuthenticationForm.d.ts +16 -0
- package/dist/esm/auth/AuthenticationForm.js +71 -0
- 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/{SignInForm.d.ts → auth/SignInForm.d.ts} +3 -1
- package/dist/esm/auth/SignInForm.js +52 -0
- package/dist/esm/auth/SignInForm.js.map +1 -0
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +2 -2
- package/dist/esm/index.min.js +1 -1
- package/dist/esm/index.min.js.map +1 -1
- package/dist/esm/styles.css +197 -197
- package/package.json +21 -23
- package/dist/cjs/RegisterForm.d.ts +0 -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 +0 -167
- package/dist/esm/SignInForm.js.map +0 -1
package/dist/cjs/index.js
CHANGED
|
@@ -329,6 +329,582 @@
|
|
|
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 }, props.children)),
|
|
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
|
+
codeChallenge: props.codeChallenge,
|
|
717
|
+
codeChallengeMethod: props.codeChallengeMethod,
|
|
718
|
+
email: formData.email,
|
|
719
|
+
password: formData.password,
|
|
720
|
+
remember: formData.remember === 'true',
|
|
721
|
+
})
|
|
722
|
+
.then(props.handleAuthResponse)
|
|
723
|
+
.catch(setOutcome);
|
|
724
|
+
} },
|
|
725
|
+
React__default["default"].createElement("div", { className: "medplum-center" }, props.children),
|
|
726
|
+
issues && (React__default["default"].createElement("div", { className: "medplum-input-error" }, issues.map((issue) => {
|
|
727
|
+
var _a, _b;
|
|
728
|
+
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));
|
|
729
|
+
}))),
|
|
730
|
+
googleClientId && (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
731
|
+
React__default["default"].createElement("div", { className: "medplum-signin-google-container" },
|
|
732
|
+
React__default["default"].createElement(GoogleButton, { googleClientId: googleClientId, handleGoogleCredential: (response) => {
|
|
733
|
+
medplum
|
|
734
|
+
.startGoogleLogin({
|
|
735
|
+
projectId: props.projectId,
|
|
736
|
+
clientId: props.clientId,
|
|
737
|
+
scope: props.scope,
|
|
738
|
+
nonce: props.nonce,
|
|
739
|
+
codeChallenge: props.codeChallenge,
|
|
740
|
+
codeChallengeMethod: props.codeChallengeMethod,
|
|
741
|
+
googleClientId: response.clientId,
|
|
742
|
+
googleCredential: response.credential,
|
|
743
|
+
})
|
|
744
|
+
.then(props.handleAuthResponse)
|
|
745
|
+
.catch(setOutcome);
|
|
746
|
+
} })),
|
|
747
|
+
React__default["default"].createElement("div", { className: "medplum-signin-separator" }, "or"))),
|
|
748
|
+
React__default["default"].createElement(FormSection, { title: "Email", htmlFor: "email", outcome: outcome },
|
|
749
|
+
React__default["default"].createElement(Input, { name: "email", type: "email", testid: "email", required: true, autoFocus: true, outcome: outcome })),
|
|
750
|
+
React__default["default"].createElement(FormSection, { title: "Password", htmlFor: "password", outcome: outcome },
|
|
751
|
+
React__default["default"].createElement(Input, { name: "password", type: "password", testid: "password", autoComplete: "off", required: true, outcome: outcome })),
|
|
752
|
+
React__default["default"].createElement("div", { className: "medplum-signin-buttons" },
|
|
753
|
+
(props.onForgotPassword || props.onRegister) && (React__default["default"].createElement("div", null,
|
|
754
|
+
props.onForgotPassword && (React__default["default"].createElement(MedplumLink, { testid: "forgotpassword", onClick: props.onForgotPassword }, "Forgot password")),
|
|
755
|
+
props.onRegister && (React__default["default"].createElement(MedplumLink, { testid: "register", onClick: props.onRegister }, "Register")))),
|
|
756
|
+
React__default["default"].createElement("div", null,
|
|
757
|
+
React__default["default"].createElement("input", { type: "checkbox", id: "remember", name: "remember", value: "true" }),
|
|
758
|
+
React__default["default"].createElement("label", { htmlFor: "remember" }, "Remember me")),
|
|
759
|
+
React__default["default"].createElement("div", null,
|
|
760
|
+
React__default["default"].createElement(Button, { type: "submit", testid: "submit" }, "Sign in")))));
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
const system = {
|
|
764
|
+
resourceType: 'Device',
|
|
765
|
+
id: 'system',
|
|
766
|
+
deviceName: [
|
|
767
|
+
{
|
|
768
|
+
name: 'System',
|
|
769
|
+
},
|
|
770
|
+
],
|
|
771
|
+
};
|
|
772
|
+
/**
|
|
773
|
+
* React Hook to use a FHIR reference.
|
|
774
|
+
* Handles the complexity of resolving references and caching resources.
|
|
775
|
+
* @param value The resource or reference to resource.
|
|
776
|
+
* @returns The resolved resource.
|
|
777
|
+
*/
|
|
778
|
+
function useResource(value) {
|
|
779
|
+
const medplum = useMedplum();
|
|
780
|
+
const [resource, setResource] = React.useState(getInitialResource(medplum, value));
|
|
781
|
+
React.useEffect(() => {
|
|
782
|
+
let subscribed = true;
|
|
783
|
+
if (!resource && value && 'reference' in value && value.reference) {
|
|
784
|
+
medplum
|
|
785
|
+
.readReference(value)
|
|
786
|
+
.then((r) => {
|
|
787
|
+
if (subscribed) {
|
|
788
|
+
setResource(r);
|
|
789
|
+
}
|
|
790
|
+
})
|
|
791
|
+
.catch(() => setResource(undefined));
|
|
792
|
+
}
|
|
793
|
+
return (() => (subscribed = false));
|
|
794
|
+
}, [medplum, resource, value]);
|
|
795
|
+
return resource;
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* Returns the initial resource value based on the input value.
|
|
799
|
+
* If the input value is a resource, returns the resource.
|
|
800
|
+
* If the input value is a reference to system, returns the system resource.
|
|
801
|
+
* If the input value is a reference to a resource available in the cache, returns the resource.
|
|
802
|
+
* Otherwise, returns undefined.
|
|
803
|
+
* @param medplum The medplum client.
|
|
804
|
+
* @param value The resource or reference to resource.
|
|
805
|
+
* @returns An initial resource if available; undefined otherwise.
|
|
806
|
+
*/
|
|
807
|
+
function getInitialResource(medplum, value) {
|
|
808
|
+
if (!value) {
|
|
809
|
+
return undefined;
|
|
810
|
+
}
|
|
811
|
+
if ('resourceType' in value) {
|
|
812
|
+
return value;
|
|
813
|
+
}
|
|
814
|
+
if ('reference' in value) {
|
|
815
|
+
if (value.reference === 'system') {
|
|
816
|
+
return system;
|
|
817
|
+
}
|
|
818
|
+
return medplum.getCachedReference(value);
|
|
819
|
+
}
|
|
820
|
+
return undefined;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
function Avatar(props) {
|
|
824
|
+
var _a, _b;
|
|
825
|
+
const resource = useResource(props.value);
|
|
826
|
+
const className = props.size ? 'medplum-avatar ' + props.size : 'medplum-avatar';
|
|
827
|
+
const text = resource ? core.getDisplayString(resource) : (_a = props.alt) !== null && _a !== void 0 ? _a : '';
|
|
828
|
+
const initials = text && getInitials(text);
|
|
829
|
+
const imageUrl = (_b = (resource && core.getImageSrc(resource))) !== null && _b !== void 0 ? _b : props.src;
|
|
830
|
+
const innerContent = imageUrl ? React__default["default"].createElement("img", { src: imageUrl, alt: text }) : initials;
|
|
831
|
+
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));
|
|
832
|
+
}
|
|
833
|
+
function getInitials(text) {
|
|
834
|
+
return text
|
|
835
|
+
.split(' ')
|
|
836
|
+
.map((n) => n[0])
|
|
837
|
+
.join('');
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
function ChooseProfileForm(props) {
|
|
841
|
+
const medplum = useMedplum();
|
|
842
|
+
return (React__default["default"].createElement("div", null,
|
|
843
|
+
React__default["default"].createElement("div", { className: "medplum-center" },
|
|
844
|
+
React__default["default"].createElement(Logo, { size: 32 }),
|
|
845
|
+
React__default["default"].createElement("h1", null, "Choose profile")),
|
|
846
|
+
props.memberships.map((membership) => {
|
|
847
|
+
var _a, _b, _c;
|
|
848
|
+
return (React__default["default"].createElement("div", { className: "medplum-nav-menu-profile", key: membership.id, onClick: () => {
|
|
849
|
+
medplum
|
|
850
|
+
.post('auth/profile', {
|
|
851
|
+
login: props.login,
|
|
852
|
+
profile: membership.id,
|
|
853
|
+
})
|
|
854
|
+
.then(props.handleAuthResponse)
|
|
855
|
+
.catch(console.log);
|
|
856
|
+
} },
|
|
857
|
+
React__default["default"].createElement("div", { className: "medplum-nav-menu-profile-icon" },
|
|
858
|
+
React__default["default"].createElement(Avatar, { alt: (_a = membership.profile) === null || _a === void 0 ? void 0 : _a.display })),
|
|
859
|
+
React__default["default"].createElement("div", { className: "medplum-nav-menu-profile-label" }, (_b = membership.profile) === null || _b === void 0 ? void 0 :
|
|
860
|
+
_b.display,
|
|
861
|
+
React__default["default"].createElement("div", { className: "medplum-nav-menu-profile-help-text" }, (_c = membership.project) === null || _c === void 0 ? void 0 : _c.display))));
|
|
862
|
+
})));
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
function SignInForm(props) {
|
|
866
|
+
const medplum = useMedplum();
|
|
867
|
+
const [login, setLogin] = React.useState(undefined);
|
|
868
|
+
const [memberships, setMemberships] = React.useState(undefined);
|
|
869
|
+
function handleAuthResponse(response) {
|
|
870
|
+
if (response.login) {
|
|
871
|
+
setLogin(response.login);
|
|
872
|
+
}
|
|
873
|
+
if (response.memberships) {
|
|
874
|
+
setMemberships(response.memberships);
|
|
875
|
+
}
|
|
876
|
+
if (response.code) {
|
|
877
|
+
if (props.onCode) {
|
|
878
|
+
props.onCode(response.code);
|
|
879
|
+
}
|
|
880
|
+
else {
|
|
881
|
+
medplum
|
|
882
|
+
.processCode(response.code)
|
|
883
|
+
.then(() => {
|
|
884
|
+
if (props.onSuccess) {
|
|
885
|
+
props.onSuccess();
|
|
886
|
+
}
|
|
887
|
+
})
|
|
888
|
+
.catch(console.log);
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
return (React__default["default"].createElement(Document, { width: 450 }, (() => {
|
|
893
|
+
if (!login) {
|
|
894
|
+
return (React__default["default"].createElement(AuthenticationForm, { projectId: props.projectId, clientId: props.clientId, scope: props.scope, nonce: props.nonce, googleClientId: props.googleClientId, codeChallenge: props.codeChallenge, codeChallengeMethod: props.codeChallengeMethod, onForgotPassword: props.onForgotPassword, onRegister: props.onRegister, handleAuthResponse: handleAuthResponse }, props.children));
|
|
895
|
+
}
|
|
896
|
+
else if (memberships) {
|
|
897
|
+
return React__default["default"].createElement(ChooseProfileForm, { login: login, memberships: memberships, handleAuthResponse: handleAuthResponse });
|
|
898
|
+
}
|
|
899
|
+
else if (props.projectId === 'new') {
|
|
900
|
+
return React__default["default"].createElement(NewProjectForm, { login: login, handleAuthResponse: handleAuthResponse });
|
|
901
|
+
}
|
|
902
|
+
else {
|
|
903
|
+
return React__default["default"].createElement("div", null, "Success");
|
|
904
|
+
}
|
|
905
|
+
})()));
|
|
906
|
+
}
|
|
907
|
+
|
|
332
908
|
function Autocomplete(props) {
|
|
333
909
|
var _a, _b;
|
|
334
910
|
const inputRef = React.useRef(null);
|
|
@@ -576,138 +1152,33 @@
|
|
|
576
1152
|
* @param option The drop down option.
|
|
577
1153
|
*/
|
|
578
1154
|
function handleDropDownClick(e, option) {
|
|
579
|
-
killEvent(e);
|
|
580
|
-
addOption(option);
|
|
581
|
-
}
|
|
582
|
-
/**
|
|
583
|
-
* Dismisses the drop down menu after a slight delay.
|
|
584
|
-
*/
|
|
585
|
-
function dismissOnDelay() {
|
|
586
|
-
window.setTimeout(() => {
|
|
587
|
-
setDropDownVisible(false);
|
|
588
|
-
}, 200);
|
|
589
|
-
}
|
|
590
|
-
const baseClassName = (_b = props.className) !== null && _b !== void 0 ? _b : 'medplum-autocomplete-container';
|
|
591
|
-
return (React__default["default"].createElement("div", { "data-testid": "autocomplete", className: baseClassName + (focused ? ' focused' : ''), onClick: () => handleClick() },
|
|
592
|
-
React__default["default"].createElement("ul", { onClick: () => handleClick() },
|
|
593
|
-
values.map((value) => (React__default["default"].createElement("li", { key: props.getId(value), "data-testid": "selected", className: "medplum-autocomplete-item choice" }, props.getDisplay(value)))),
|
|
594
|
-
React__default["default"].createElement("li", { className: "medplum-autocomplete-item" },
|
|
595
|
-
React__default["default"].createElement("input", { type: "text", autoFocus: props.autofocus, placeholder: values.length === 0 ? props.placeholder : undefined, autoComplete: "off", autoCapitalize: "off", spellCheck: "true", onFocus: () => handleFocus(), onBlur: () => handleBlur(), onChange: () => handleInput(), onInput: () => handleInput(), onKeyDown: (e) => handleKeyDown(e), ref: inputRef, "data-testid": "input-element" }))),
|
|
596
|
-
dropDownVisible && (React__default["default"].createElement("div", { className: "medplum-autocomplete", "data-testid": "dropdown" },
|
|
597
|
-
options.map((option, index) => (React__default["default"].createElement("div", { key: props.getId(option), className: index === selectedIndex
|
|
598
|
-
? 'medplum-autocomplete-row medplum-autocomplete-active'
|
|
599
|
-
: 'medplum-autocomplete-row', onMouseOver: (e) => handleDropDownHover(e, index), onClick: (e) => handleDropDownClick(e, option) },
|
|
600
|
-
props.getIcon && React__default["default"].createElement("div", { className: "medplum-autocomplete-icon" }, props.getIcon(option)),
|
|
601
|
-
React__default["default"].createElement("div", { className: "medplum-autocomplete-label" },
|
|
602
|
-
props.getDisplay(option),
|
|
603
|
-
props.getHelpText && React__default["default"].createElement("div", { className: "medplum-autocomplete-help-text" }, props.getHelpText(option)))))),
|
|
604
|
-
props.onCreateNew && (React__default["default"].createElement("div", { className: "medplum-autocomplete-row", onClick: props.onCreateNew },
|
|
605
|
-
React__default["default"].createElement("div", { className: "medplum-autocomplete-label" }, "Create new...")))))));
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
function MedplumLink(props) {
|
|
609
|
-
const navigate = reactRouterDom.useNavigate();
|
|
610
|
-
let href = '#';
|
|
611
|
-
if (props.to) {
|
|
612
|
-
if (typeof props.to === 'string') {
|
|
613
|
-
href = props.to;
|
|
614
|
-
}
|
|
615
|
-
else if ('resourceType' in props.to) {
|
|
616
|
-
href = `/${props.to.resourceType}/${props.to.id}`;
|
|
617
|
-
}
|
|
618
|
-
else if ('reference' in props.to) {
|
|
619
|
-
href = `/${props.to.reference}`;
|
|
620
|
-
}
|
|
621
|
-
if (props.suffix) {
|
|
622
|
-
href += '/' + props.suffix;
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
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) => {
|
|
626
|
-
killEvent(e);
|
|
627
|
-
if (props.onClick) {
|
|
628
|
-
props.onClick();
|
|
629
|
-
}
|
|
630
|
-
else if (props.to) {
|
|
631
|
-
navigate(href);
|
|
632
|
-
}
|
|
633
|
-
} }, props.children));
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
const system = {
|
|
637
|
-
resourceType: 'Device',
|
|
638
|
-
id: 'system',
|
|
639
|
-
deviceName: [
|
|
640
|
-
{
|
|
641
|
-
name: 'System',
|
|
642
|
-
},
|
|
643
|
-
],
|
|
644
|
-
};
|
|
645
|
-
/**
|
|
646
|
-
* React Hook to use a FHIR reference.
|
|
647
|
-
* Handles the complexity of resolving references and caching resources.
|
|
648
|
-
* @param value The resource or reference to resource.
|
|
649
|
-
* @returns The resolved resource.
|
|
650
|
-
*/
|
|
651
|
-
function useResource(value) {
|
|
652
|
-
const medplum = useMedplum();
|
|
653
|
-
const [resource, setResource] = React.useState(getInitialResource(medplum, value));
|
|
654
|
-
React.useEffect(() => {
|
|
655
|
-
let subscribed = true;
|
|
656
|
-
if (!resource && value && 'reference' in value && value.reference) {
|
|
657
|
-
medplum
|
|
658
|
-
.readReference(value)
|
|
659
|
-
.then((r) => {
|
|
660
|
-
if (subscribed) {
|
|
661
|
-
setResource(r);
|
|
662
|
-
}
|
|
663
|
-
})
|
|
664
|
-
.catch(() => setResource(undefined));
|
|
665
|
-
}
|
|
666
|
-
return (() => (subscribed = false));
|
|
667
|
-
}, [medplum, resource, value]);
|
|
668
|
-
return resource;
|
|
669
|
-
}
|
|
670
|
-
/**
|
|
671
|
-
* Returns the initial resource value based on the input value.
|
|
672
|
-
* If the input value is a resource, returns the resource.
|
|
673
|
-
* If the input value is a reference to system, returns the system resource.
|
|
674
|
-
* If the input value is a reference to a resource available in the cache, returns the resource.
|
|
675
|
-
* Otherwise, returns undefined.
|
|
676
|
-
* @param medplum The medplum client.
|
|
677
|
-
* @param value The resource or reference to resource.
|
|
678
|
-
* @returns An initial resource if available; undefined otherwise.
|
|
679
|
-
*/
|
|
680
|
-
function getInitialResource(medplum, value) {
|
|
681
|
-
if (!value) {
|
|
682
|
-
return undefined;
|
|
683
|
-
}
|
|
684
|
-
if ('resourceType' in value) {
|
|
685
|
-
return value;
|
|
686
|
-
}
|
|
687
|
-
if ('reference' in value) {
|
|
688
|
-
if (value.reference === 'system') {
|
|
689
|
-
return system;
|
|
690
|
-
}
|
|
691
|
-
return medplum.getCachedReference(value);
|
|
692
|
-
}
|
|
693
|
-
return undefined;
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
function Avatar(props) {
|
|
697
|
-
var _a, _b;
|
|
698
|
-
const resource = useResource(props.value);
|
|
699
|
-
const className = props.size ? 'medplum-avatar ' + props.size : 'medplum-avatar';
|
|
700
|
-
const text = resource ? core.getDisplayString(resource) : (_a = props.alt) !== null && _a !== void 0 ? _a : '';
|
|
701
|
-
const initials = text && getInitials(text);
|
|
702
|
-
const imageUrl = (_b = (resource && core.getImageSrc(resource))) !== null && _b !== void 0 ? _b : props.src;
|
|
703
|
-
const innerContent = imageUrl ? React__default["default"].createElement("img", { src: imageUrl, alt: text }) : initials;
|
|
704
|
-
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));
|
|
705
|
-
}
|
|
706
|
-
function getInitials(text) {
|
|
707
|
-
return text
|
|
708
|
-
.split(' ')
|
|
709
|
-
.map((n) => n[0])
|
|
710
|
-
.join('');
|
|
1155
|
+
killEvent(e);
|
|
1156
|
+
addOption(option);
|
|
1157
|
+
}
|
|
1158
|
+
/**
|
|
1159
|
+
* Dismisses the drop down menu after a slight delay.
|
|
1160
|
+
*/
|
|
1161
|
+
function dismissOnDelay() {
|
|
1162
|
+
window.setTimeout(() => {
|
|
1163
|
+
setDropDownVisible(false);
|
|
1164
|
+
}, 200);
|
|
1165
|
+
}
|
|
1166
|
+
const baseClassName = (_b = props.className) !== null && _b !== void 0 ? _b : 'medplum-autocomplete-container';
|
|
1167
|
+
return (React__default["default"].createElement("div", { "data-testid": "autocomplete", className: baseClassName + (focused ? ' focused' : ''), onClick: () => handleClick() },
|
|
1168
|
+
React__default["default"].createElement("ul", { onClick: () => handleClick() },
|
|
1169
|
+
values.map((value) => (React__default["default"].createElement("li", { key: props.getId(value), "data-testid": "selected", className: "medplum-autocomplete-item choice" }, props.getDisplay(value)))),
|
|
1170
|
+
React__default["default"].createElement("li", { className: "medplum-autocomplete-item" },
|
|
1171
|
+
React__default["default"].createElement("input", { type: "text", autoFocus: props.autofocus, placeholder: values.length === 0 ? props.placeholder : undefined, autoComplete: "off", autoCapitalize: "off", spellCheck: "true", onFocus: () => handleFocus(), onBlur: () => handleBlur(), onChange: () => handleInput(), onInput: () => handleInput(), onKeyDown: (e) => handleKeyDown(e), ref: inputRef, "data-testid": "input-element" }))),
|
|
1172
|
+
dropDownVisible && (React__default["default"].createElement("div", { className: "medplum-autocomplete", "data-testid": "dropdown" },
|
|
1173
|
+
options.map((option, index) => (React__default["default"].createElement("div", { key: props.getId(option), className: index === selectedIndex
|
|
1174
|
+
? 'medplum-autocomplete-row medplum-autocomplete-active'
|
|
1175
|
+
: 'medplum-autocomplete-row', onMouseOver: (e) => handleDropDownHover(e, index), onClick: (e) => handleDropDownClick(e, option) },
|
|
1176
|
+
props.getIcon && React__default["default"].createElement("div", { className: "medplum-autocomplete-icon" }, props.getIcon(option)),
|
|
1177
|
+
React__default["default"].createElement("div", { className: "medplum-autocomplete-label" },
|
|
1178
|
+
props.getDisplay(option),
|
|
1179
|
+
props.getHelpText && React__default["default"].createElement("div", { className: "medplum-autocomplete-help-text" }, props.getHelpText(option)))))),
|
|
1180
|
+
props.onCreateNew && (React__default["default"].createElement("div", { className: "medplum-autocomplete-row", onClick: props.onCreateNew },
|
|
1181
|
+
React__default["default"].createElement("div", { className: "medplum-autocomplete-label" }, "Create new...")))))));
|
|
711
1182
|
}
|
|
712
1183
|
|
|
713
1184
|
function CheckboxFormSection(props) {
|
|
@@ -728,19 +1199,6 @@
|
|
|
728
1199
|
'modifierExtension',
|
|
729
1200
|
];
|
|
730
1201
|
|
|
731
|
-
function FormSection(props) {
|
|
732
|
-
const issues = getIssuesForExpression(props.outcome, props.htmlFor);
|
|
733
|
-
const invalid = issues && issues.length > 0;
|
|
734
|
-
return (React__default["default"].createElement("fieldset", { className: "medplum-form-section" },
|
|
735
|
-
props.title && React__default["default"].createElement("label", { htmlFor: props.htmlFor }, props.title),
|
|
736
|
-
props.description && React__default["default"].createElement("p", null, props.description),
|
|
737
|
-
props.children,
|
|
738
|
-
invalid && (React__default["default"].createElement("div", { id: props.htmlFor + '-errors', className: "medplum-input-error" }, issues === null || issues === void 0 ? void 0 : issues.map((issue) => {
|
|
739
|
-
var _a, _b;
|
|
740
|
-
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));
|
|
741
|
-
})))));
|
|
742
|
-
}
|
|
743
|
-
|
|
744
1202
|
function ResourceForm(props) {
|
|
745
1203
|
const medplum = useMedplum();
|
|
746
1204
|
const defaultValue = useResource(props.defaultValue);
|
|
@@ -1473,31 +1931,6 @@
|
|
|
1473
1931
|
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 })) })));
|
|
1474
1932
|
}
|
|
1475
1933
|
|
|
1476
|
-
/******************************************************************************
|
|
1477
|
-
Copyright (c) Microsoft Corporation.
|
|
1478
|
-
|
|
1479
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
1480
|
-
purpose with or without fee is hereby granted.
|
|
1481
|
-
|
|
1482
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
1483
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
1484
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
1485
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
1486
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
1487
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
1488
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
1489
|
-
***************************************************************************** */
|
|
1490
|
-
|
|
1491
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
1492
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
1493
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
1494
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
1495
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
1496
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
1497
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
1498
|
-
});
|
|
1499
|
-
}
|
|
1500
|
-
|
|
1501
1934
|
function ResourceName(props) {
|
|
1502
1935
|
const resource = useResource(props.value);
|
|
1503
1936
|
if (!resource) {
|
|
@@ -1985,63 +2418,6 @@
|
|
|
1985
2418
|
return React__default["default"].createElement(RangeDisplay, { value: range });
|
|
1986
2419
|
}
|
|
1987
2420
|
|
|
1988
|
-
/**
|
|
1989
|
-
* Parses an HTML form and returns the result as a JavaScript object.
|
|
1990
|
-
* @param form The HTML form element.
|
|
1991
|
-
*/
|
|
1992
|
-
function parseForm(form) {
|
|
1993
|
-
const result = {};
|
|
1994
|
-
for (const element of Array.from(form.elements)) {
|
|
1995
|
-
if (element instanceof HTMLInputElement) {
|
|
1996
|
-
parseInputElement(result, element);
|
|
1997
|
-
}
|
|
1998
|
-
else if (element instanceof HTMLTextAreaElement) {
|
|
1999
|
-
result[element.name] = element.value;
|
|
2000
|
-
}
|
|
2001
|
-
else if (element instanceof HTMLSelectElement) {
|
|
2002
|
-
parseSelectElement(result, element);
|
|
2003
|
-
}
|
|
2004
|
-
}
|
|
2005
|
-
return result;
|
|
2006
|
-
}
|
|
2007
|
-
/**
|
|
2008
|
-
* Parses an HTML input element.
|
|
2009
|
-
* Sets the name/value pair in the result,
|
|
2010
|
-
* but only if the element is enabled and checked.
|
|
2011
|
-
* @param el The input element.
|
|
2012
|
-
* @param result The result builder.
|
|
2013
|
-
*/
|
|
2014
|
-
function parseInputElement(result, el) {
|
|
2015
|
-
if (el.disabled) {
|
|
2016
|
-
// Ignore disabled elements
|
|
2017
|
-
return;
|
|
2018
|
-
}
|
|
2019
|
-
if ((el.type === 'checkbox' || el.type === 'radio') && !el.checked) {
|
|
2020
|
-
// Ignore unchecked radio or checkbox elements
|
|
2021
|
-
return;
|
|
2022
|
-
}
|
|
2023
|
-
result[el.name] = el.value;
|
|
2024
|
-
}
|
|
2025
|
-
/**
|
|
2026
|
-
* Parses an HTML select element.
|
|
2027
|
-
* Sets the name/value pair if one is selected.
|
|
2028
|
-
* @param result The result builder.
|
|
2029
|
-
* @param el The select element.
|
|
2030
|
-
*/
|
|
2031
|
-
function parseSelectElement(result, el) {
|
|
2032
|
-
result[el.name] = el.value;
|
|
2033
|
-
}
|
|
2034
|
-
|
|
2035
|
-
function Form(props) {
|
|
2036
|
-
return (React__default["default"].createElement("form", { style: props.style, "data-testid": props.testid, onSubmit: (e) => {
|
|
2037
|
-
e.preventDefault();
|
|
2038
|
-
const formData = parseForm(e.target);
|
|
2039
|
-
if (props.onSubmit) {
|
|
2040
|
-
props.onSubmit(formData);
|
|
2041
|
-
}
|
|
2042
|
-
} }, props.children));
|
|
2043
|
-
}
|
|
2044
|
-
|
|
2045
2421
|
function Loading() {
|
|
2046
2422
|
return (React__default["default"].createElement("div", { role: "progressbar", "aria-busy": "true", className: "medplum-loading" },
|
|
2047
2423
|
React__default["default"].createElement("div", { className: "medplum-loading-container" },
|
|
@@ -2331,7 +2707,9 @@
|
|
|
2331
2707
|
}
|
|
2332
2708
|
if (bundle.entry) {
|
|
2333
2709
|
for (const entry of bundle.entry) {
|
|
2334
|
-
|
|
2710
|
+
if (entry.resource) {
|
|
2711
|
+
newItems.push(entry.resource);
|
|
2712
|
+
}
|
|
2335
2713
|
}
|
|
2336
2714
|
}
|
|
2337
2715
|
}
|
|
@@ -2518,11 +2896,6 @@
|
|
|
2518
2896
|
}) }));
|
|
2519
2897
|
}
|
|
2520
2898
|
|
|
2521
|
-
function Document(props) {
|
|
2522
|
-
return (React__default["default"].createElement("main", { className: "medplum-document" },
|
|
2523
|
-
React__default["default"].createElement("article", { style: { maxWidth: props.width } }, props.children)));
|
|
2524
|
-
}
|
|
2525
|
-
|
|
2526
2899
|
function EncounterTimeline(props) {
|
|
2527
2900
|
return (React__default["default"].createElement(ResourceTimeline, { value: props.encounter, buildSearchRequests: (resource) => ({
|
|
2528
2901
|
resourceType: 'Bundle',
|
|
@@ -3852,9 +4225,9 @@
|
|
|
3852
4225
|
props.onBulk && (React__default["default"].createElement(Button, { size: "small", onClick: () => props.onBulk(Object.keys(state.selected)) }, "Bulk..."))),
|
|
3853
4226
|
lastResult && (React__default["default"].createElement("div", null,
|
|
3854
4227
|
React__default["default"].createElement("span", { className: "medplum-search-summary" },
|
|
3855
|
-
getStart(search, lastResult.total),
|
|
4228
|
+
getStart$1(search, lastResult.total),
|
|
3856
4229
|
"-",
|
|
3857
|
-
getEnd(search, lastResult.total),
|
|
4230
|
+
getEnd$1(search, lastResult.total),
|
|
3858
4231
|
" of",
|
|
3859
4232
|
' ', (_d = lastResult.total) === null || _d === void 0 ? void 0 :
|
|
3860
4233
|
_d.toLocaleString()),
|
|
@@ -3921,11 +4294,11 @@
|
|
|
3921
4294
|
return (React__default["default"].createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-6 w-6", fill: "none", viewBox: "0 0 24 24", stroke: "rgba(0, 0, 0, 0.3)", strokeWidth: 2 },
|
|
3922
4295
|
React__default["default"].createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M4 6h16M4 12h16m-7 6h7" })));
|
|
3923
4296
|
}
|
|
3924
|
-
function getStart(search, total) {
|
|
4297
|
+
function getStart$1(search, total) {
|
|
3925
4298
|
var _a;
|
|
3926
4299
|
return Math.min(total, ((_a = search.offset) !== null && _a !== void 0 ? _a : 0) + 1);
|
|
3927
4300
|
}
|
|
3928
|
-
function getEnd(search, total) {
|
|
4301
|
+
function getEnd$1(search, total) {
|
|
3929
4302
|
var _a, _b;
|
|
3930
4303
|
return Math.min(total, (((_a = search.offset) !== null && _a !== void 0 ? _a : 0) + 1) * ((_b = search.count) !== null && _b !== void 0 ? _b : core.DEFAULT_SEARCH_COUNT));
|
|
3931
4304
|
}
|
|
@@ -4301,16 +4674,6 @@
|
|
|
4301
4674
|
React__default["default"].createElement(MedplumLink, { to: "/changepassword" }, "Change password"))))));
|
|
4302
4675
|
}
|
|
4303
4676
|
|
|
4304
|
-
function Logo(props) {
|
|
4305
|
-
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 } },
|
|
4306
|
-
React__default["default"].createElement("title", null, "Medplum Logo"),
|
|
4307
|
-
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" }),
|
|
4308
|
-
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" }),
|
|
4309
|
-
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" }),
|
|
4310
|
-
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" }),
|
|
4311
|
-
React__default["default"].createElement("path", { fill: props.fill || '#58b741', d: "M252 48A421 421 0 0057 270l-27-7A176 176 0 01251 43l1 5z" })));
|
|
4312
|
-
}
|
|
4313
|
-
|
|
4314
4677
|
const searches = [
|
|
4315
4678
|
'$/_history',
|
|
4316
4679
|
'Communication?subject=$',
|
|
@@ -4678,7 +5041,7 @@
|
|
|
4678
5041
|
} },
|
|
4679
5042
|
questionnaire.title && React__default["default"].createElement("h1", null, questionnaire.title),
|
|
4680
5043
|
questionnaire.item && React__default["default"].createElement(QuestionnaireFormItemArray, { items: questionnaire.item, onChange: setItems }),
|
|
4681
|
-
React__default["default"].createElement(Button, { type: "submit", size: "large" },
|
|
5044
|
+
React__default["default"].createElement(Button, { type: "submit", size: "large" }, props.submitButtonText || 'OK')));
|
|
4682
5045
|
}
|
|
4683
5046
|
function QuestionnaireFormItemArray(props) {
|
|
4684
5047
|
const [responseItems, setResponseItems] = React.useState(buildInitialResponseItems(props.items));
|
|
@@ -4984,258 +5347,69 @@
|
|
|
4984
5347
|
options.map((option) => {
|
|
4985
5348
|
const [propertyValue, propertyType] = getValueAndType({ type: 'QuestionnaireItemAnswerOption', value: option }, 'value');
|
|
4986
5349
|
return (React__default["default"].createElement("div", { key: option.id, style: {
|
|
4987
|
-
display: 'flex',
|
|
4988
|
-
flexDirection: 'row',
|
|
4989
|
-
justifyContent: 'space-between',
|
|
4990
|
-
alignItems: 'center',
|
|
4991
|
-
width: '80%',
|
|
4992
|
-
} },
|
|
4993
|
-
React__default["default"].createElement("div", null,
|
|
4994
|
-
React__default["default"].createElement(ResourcePropertyInput, { key: option.id, name: "value[x]", property: property, defaultPropertyType: propertyType, defaultValue: propertyValue, onChange: (newValue, propName) => {
|
|
4995
|
-
const newOptions = [...options];
|
|
4996
|
-
const index = newOptions.findIndex((o) => o.id === option.id);
|
|
4997
|
-
newOptions[index] = { id: option.id, [propName]: newValue };
|
|
4998
|
-
props.onChange(newOptions);
|
|
4999
|
-
} })),
|
|
5000
|
-
React__default["default"].createElement("div", null,
|
|
5001
|
-
React__default["default"].createElement("a", { href: "#", onClick: (e) => {
|
|
5002
|
-
killEvent(e);
|
|
5003
|
-
props.onChange(options.filter((o) => o.id !== option.id));
|
|
5004
|
-
} }, "Remove"))));
|
|
5005
|
-
}),
|
|
5006
|
-
React__default["default"].createElement("a", { href: "#", onClick: (e) => {
|
|
5007
|
-
killEvent(e);
|
|
5008
|
-
props.onChange([
|
|
5009
|
-
...options,
|
|
5010
|
-
{
|
|
5011
|
-
id: generateId(),
|
|
5012
|
-
},
|
|
5013
|
-
]);
|
|
5014
|
-
} }, "Add choice")));
|
|
5015
|
-
}
|
|
5016
|
-
let nextLinkId = 1;
|
|
5017
|
-
let nextId = 1;
|
|
5018
|
-
/**
|
|
5019
|
-
* Generates a link ID for an item.
|
|
5020
|
-
* Link IDs are required properties on QuestionnaireItem objects.
|
|
5021
|
-
* @return A unique link ID.
|
|
5022
|
-
*/
|
|
5023
|
-
function generateLinkId(prefix) {
|
|
5024
|
-
return prefix + nextLinkId++;
|
|
5025
|
-
}
|
|
5026
|
-
/**
|
|
5027
|
-
* Generates a unique ID.
|
|
5028
|
-
* React needs unique IDs for components for rendering performance.
|
|
5029
|
-
* All of the important components in the questionnaire builder have id properties for this:
|
|
5030
|
-
* Questionnaire, QuestionnaireItem, and QuestionnaireItemAnswerOption.
|
|
5031
|
-
* @return A unique key.
|
|
5032
|
-
*/
|
|
5033
|
-
function generateId() {
|
|
5034
|
-
return 'id-' + nextId++;
|
|
5035
|
-
}
|
|
5036
|
-
function ensureQuestionnaireKeys(questionnaire) {
|
|
5037
|
-
return Object.assign(Object.assign({}, questionnaire), { id: questionnaire.id || generateId(), item: ensureQuestionnaireItemKeys(questionnaire.item) });
|
|
5038
|
-
}
|
|
5039
|
-
function ensureQuestionnaireItemKeys(items) {
|
|
5040
|
-
if (!items) {
|
|
5041
|
-
return undefined;
|
|
5042
|
-
}
|
|
5043
|
-
return items.map((item) => (Object.assign(Object.assign({}, item), { id: item.id || generateId(), item: ensureQuestionnaireItemKeys(item.item), answerOption: ensureQuestionnaireOptionKeys(item.answerOption) })));
|
|
5044
|
-
}
|
|
5045
|
-
function ensureQuestionnaireOptionKeys(options) {
|
|
5046
|
-
if (!options) {
|
|
5047
|
-
return undefined;
|
|
5048
|
-
}
|
|
5049
|
-
return options.map((option) => (Object.assign(Object.assign({}, option), { id: option.id || generateId() })));
|
|
5050
|
-
}
|
|
5051
|
-
|
|
5052
|
-
/**
|
|
5053
|
-
* Dynamically creates a script tag for the specified JavaScript file.
|
|
5054
|
-
* @param src The JavaScript file URL.
|
|
5055
|
-
*/
|
|
5056
|
-
function createScriptTag(src, onload) {
|
|
5057
|
-
const head = document.getElementsByTagName('head')[0];
|
|
5058
|
-
const script = document.createElement('script');
|
|
5059
|
-
script.async = true;
|
|
5060
|
-
script.src = src;
|
|
5061
|
-
script.onload = onload || null;
|
|
5062
|
-
head.appendChild(script);
|
|
5063
|
-
}
|
|
5064
|
-
|
|
5065
|
-
function GoogleButton(props) {
|
|
5066
|
-
const medplum = useMedplum();
|
|
5067
|
-
const { googleClientId, handleGoogleCredential } = props;
|
|
5068
|
-
const parentRef = React.useRef(null);
|
|
5069
|
-
const [scriptLoaded, setScriptLoaded] = React.useState(typeof google !== 'undefined');
|
|
5070
|
-
const [initialized, setInitialized] = React.useState(false);
|
|
5071
|
-
const [buttonRendered, setButtonRendered] = React.useState(false);
|
|
5072
|
-
React.useEffect(() => {
|
|
5073
|
-
if (typeof google === 'undefined') {
|
|
5074
|
-
createScriptTag('https://accounts.google.com/gsi/client', () => setScriptLoaded(true));
|
|
5075
|
-
return;
|
|
5076
|
-
}
|
|
5077
|
-
if (!initialized) {
|
|
5078
|
-
google.accounts.id.initialize({
|
|
5079
|
-
client_id: googleClientId,
|
|
5080
|
-
callback: handleGoogleCredential,
|
|
5081
|
-
});
|
|
5082
|
-
setInitialized(true);
|
|
5083
|
-
}
|
|
5084
|
-
if (parentRef.current && !buttonRendered) {
|
|
5085
|
-
google.accounts.id.renderButton(parentRef.current, {});
|
|
5086
|
-
setButtonRendered(true);
|
|
5087
|
-
}
|
|
5088
|
-
}, [medplum, googleClientId, initialized, scriptLoaded, parentRef, buttonRendered, handleGoogleCredential]);
|
|
5089
|
-
if (!googleClientId) {
|
|
5090
|
-
return null;
|
|
5091
|
-
}
|
|
5092
|
-
return React__default["default"].createElement("div", { ref: parentRef });
|
|
5093
|
-
}
|
|
5094
|
-
function getGoogleClientId(clientId) {
|
|
5095
|
-
var _a, _b;
|
|
5096
|
-
if (clientId) {
|
|
5097
|
-
return clientId;
|
|
5098
|
-
}
|
|
5099
|
-
const origin = window.location.protocol + '//' + window.location.host;
|
|
5100
|
-
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 : [];
|
|
5101
|
-
if (authorizedOrigins.includes(origin)) {
|
|
5102
|
-
return "921088377005-3j1sa10vr6hj86jgmdfh2l53v3mp7lfi.apps.googleusercontent.com";
|
|
5103
|
-
}
|
|
5104
|
-
return undefined;
|
|
5350
|
+
display: 'flex',
|
|
5351
|
+
flexDirection: 'row',
|
|
5352
|
+
justifyContent: 'space-between',
|
|
5353
|
+
alignItems: 'center',
|
|
5354
|
+
width: '80%',
|
|
5355
|
+
} },
|
|
5356
|
+
React__default["default"].createElement("div", null,
|
|
5357
|
+
React__default["default"].createElement(ResourcePropertyInput, { key: option.id, name: "value[x]", property: property, defaultPropertyType: propertyType, defaultValue: propertyValue, onChange: (newValue, propName) => {
|
|
5358
|
+
const newOptions = [...options];
|
|
5359
|
+
const index = newOptions.findIndex((o) => o.id === option.id);
|
|
5360
|
+
newOptions[index] = { id: option.id, [propName]: newValue };
|
|
5361
|
+
props.onChange(newOptions);
|
|
5362
|
+
} })),
|
|
5363
|
+
React__default["default"].createElement("div", null,
|
|
5364
|
+
React__default["default"].createElement("a", { href: "#", onClick: (e) => {
|
|
5365
|
+
killEvent(e);
|
|
5366
|
+
props.onChange(options.filter((o) => o.id !== option.id));
|
|
5367
|
+
} }, "Remove"))));
|
|
5368
|
+
}),
|
|
5369
|
+
React__default["default"].createElement("a", { href: "#", onClick: (e) => {
|
|
5370
|
+
killEvent(e);
|
|
5371
|
+
props.onChange([
|
|
5372
|
+
...options,
|
|
5373
|
+
{
|
|
5374
|
+
id: generateId(),
|
|
5375
|
+
},
|
|
5376
|
+
]);
|
|
5377
|
+
} }, "Add choice")));
|
|
5105
5378
|
}
|
|
5106
|
-
|
|
5379
|
+
let nextLinkId = 1;
|
|
5380
|
+
let nextId = 1;
|
|
5107
5381
|
/**
|
|
5108
|
-
*
|
|
5109
|
-
*
|
|
5110
|
-
* @
|
|
5382
|
+
* Generates a link ID for an item.
|
|
5383
|
+
* Link IDs are required properties on QuestionnaireItem objects.
|
|
5384
|
+
* @return A unique link ID.
|
|
5111
5385
|
*/
|
|
5112
|
-
function
|
|
5113
|
-
|
|
5114
|
-
createScriptTag('https://www.google.com/recaptcha/api.js?render=' + siteKey);
|
|
5115
|
-
}
|
|
5386
|
+
function generateLinkId(prefix) {
|
|
5387
|
+
return prefix + nextLinkId++;
|
|
5116
5388
|
}
|
|
5117
5389
|
/**
|
|
5118
|
-
*
|
|
5119
|
-
*
|
|
5120
|
-
*
|
|
5390
|
+
* Generates a unique ID.
|
|
5391
|
+
* React needs unique IDs for components for rendering performance.
|
|
5392
|
+
* All of the important components in the questionnaire builder have id properties for this:
|
|
5393
|
+
* Questionnaire, QuestionnaireItem, and QuestionnaireItemAnswerOption.
|
|
5394
|
+
* @return A unique key.
|
|
5121
5395
|
*/
|
|
5122
|
-
function
|
|
5123
|
-
return
|
|
5124
|
-
grecaptcha.ready(() => __awaiter(this, void 0, void 0, function* () {
|
|
5125
|
-
try {
|
|
5126
|
-
resolve(yield grecaptcha.execute(siteKey, { action: 'submit' }));
|
|
5127
|
-
}
|
|
5128
|
-
catch (err) {
|
|
5129
|
-
reject(err);
|
|
5130
|
-
}
|
|
5131
|
-
}));
|
|
5132
|
-
});
|
|
5396
|
+
function generateId() {
|
|
5397
|
+
return 'id-' + nextId++;
|
|
5133
5398
|
}
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
const issues = getIssuesForExpression(outcome, undefined);
|
|
5141
|
-
React.useEffect(() => initRecaptcha(recaptchaSiteKey), [recaptchaSiteKey]);
|
|
5142
|
-
function handleAuthResponse(registerRequest, partialLogin) {
|
|
5143
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
5144
|
-
try {
|
|
5145
|
-
let login;
|
|
5146
|
-
if (props.type === 'patient') {
|
|
5147
|
-
login = yield medplum.startNewPatient(registerRequest, partialLogin);
|
|
5148
|
-
}
|
|
5149
|
-
else {
|
|
5150
|
-
login = yield medplum.startNewProject(registerRequest, partialLogin);
|
|
5151
|
-
}
|
|
5152
|
-
yield medplum.processCode(login.code);
|
|
5153
|
-
props.onSuccess();
|
|
5154
|
-
}
|
|
5155
|
-
catch (err) {
|
|
5156
|
-
setOutcome(err);
|
|
5157
|
-
}
|
|
5158
|
-
});
|
|
5399
|
+
function ensureQuestionnaireKeys(questionnaire) {
|
|
5400
|
+
return Object.assign(Object.assign({}, questionnaire), { id: questionnaire.id || generateId(), item: ensureQuestionnaireItemKeys(questionnaire.item) });
|
|
5401
|
+
}
|
|
5402
|
+
function ensureQuestionnaireItemKeys(items) {
|
|
5403
|
+
if (!items) {
|
|
5404
|
+
return undefined;
|
|
5159
5405
|
}
|
|
5160
|
-
return (
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
firstName: formData.firstName,
|
|
5168
|
-
lastName: formData.lastName,
|
|
5169
|
-
email: formData.email,
|
|
5170
|
-
password: formData.password,
|
|
5171
|
-
remember: formData.remember === 'true',
|
|
5172
|
-
recaptchaSiteKey,
|
|
5173
|
-
recaptchaToken,
|
|
5174
|
-
};
|
|
5175
|
-
const userLogin = yield medplum.startNewUser(registerRequest);
|
|
5176
|
-
yield handleAuthResponse(registerRequest, userLogin);
|
|
5177
|
-
}
|
|
5178
|
-
catch (err) {
|
|
5179
|
-
setOutcome(err);
|
|
5180
|
-
}
|
|
5181
|
-
}) },
|
|
5182
|
-
React__default["default"].createElement("div", { className: "medplum-center" }, props.children),
|
|
5183
|
-
issues && (React__default["default"].createElement("div", { className: "medplum-input-error" }, issues.map((issue) => {
|
|
5184
|
-
var _a, _b;
|
|
5185
|
-
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));
|
|
5186
|
-
}))),
|
|
5187
|
-
googleClientId && (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
5188
|
-
React__default["default"].createElement("div", { className: "medplum-signin-google-container" },
|
|
5189
|
-
React__default["default"].createElement(GoogleButton, { googleClientId: googleClientId, handleGoogleCredential: (response) => __awaiter(this, void 0, void 0, function* () {
|
|
5190
|
-
try {
|
|
5191
|
-
const loginRequest = {
|
|
5192
|
-
googleClientId: response.clientId,
|
|
5193
|
-
googleCredential: response.credential,
|
|
5194
|
-
};
|
|
5195
|
-
const userLogin = yield medplum.startGoogleLogin(loginRequest);
|
|
5196
|
-
const googleClaims = core.parseJWTPayload(loginRequest.googleCredential);
|
|
5197
|
-
const registerRequest = {
|
|
5198
|
-
projectId: props.projectId,
|
|
5199
|
-
firstName: googleClaims.given_name,
|
|
5200
|
-
lastName: googleClaims.family_name,
|
|
5201
|
-
email: googleClaims.email,
|
|
5202
|
-
};
|
|
5203
|
-
yield handleAuthResponse(registerRequest, userLogin);
|
|
5204
|
-
}
|
|
5205
|
-
catch (err) {
|
|
5206
|
-
setOutcome(err);
|
|
5207
|
-
}
|
|
5208
|
-
}) })),
|
|
5209
|
-
React__default["default"].createElement("div", { className: "medplum-signin-separator" }, "or"))),
|
|
5210
|
-
React__default["default"].createElement(FormSection, { title: "First Name", htmlFor: "firstName", outcome: outcome },
|
|
5211
|
-
React__default["default"].createElement(Input, { name: "firstName", type: "text", testid: "firstName", placeholder: "First name", required: true, autoFocus: true, outcome: outcome })),
|
|
5212
|
-
React__default["default"].createElement(FormSection, { title: "Last Name", htmlFor: "lastName", outcome: outcome },
|
|
5213
|
-
React__default["default"].createElement(Input, { name: "lastName", type: "text", testid: "lastName", placeholder: "Last name", required: true, outcome: outcome })),
|
|
5214
|
-
props.type === 'project' && (React__default["default"].createElement(FormSection, { title: "Project Name", htmlFor: "projectName", outcome: outcome },
|
|
5215
|
-
React__default["default"].createElement(Input, { name: "projectName", type: "text", testid: "projectName", placeholder: "My Project", required: true, outcome: outcome }))),
|
|
5216
|
-
React__default["default"].createElement(FormSection, { title: "Email", htmlFor: "email", outcome: outcome },
|
|
5217
|
-
React__default["default"].createElement(Input, { name: "email", type: "email", testid: "email", placeholder: "name@domain.com", required: true, outcome: outcome })),
|
|
5218
|
-
React__default["default"].createElement(FormSection, { title: "Password", htmlFor: "password", outcome: outcome },
|
|
5219
|
-
React__default["default"].createElement(Input, { name: "password", type: "password", testid: "password", autoComplete: "off", required: true, outcome: outcome })),
|
|
5220
|
-
React__default["default"].createElement("p", { style: { fontSize: '12px', color: '#888' } },
|
|
5221
|
-
"By clicking submit you agree to the Medplum ",
|
|
5222
|
-
React__default["default"].createElement("a", { href: "https://www.medplum.com/privacy" }, "Privacy\u00A0Policy"),
|
|
5223
|
-
' and ',
|
|
5224
|
-
React__default["default"].createElement("a", { href: "https://www.medplum.com/terms" }, "Terms\u00A0of\u00A0Service"),
|
|
5225
|
-
"."),
|
|
5226
|
-
React__default["default"].createElement("p", { style: { fontSize: '12px', color: '#888' } },
|
|
5227
|
-
"This site is protected by reCAPTCHA and the Google",
|
|
5228
|
-
' ',
|
|
5229
|
-
React__default["default"].createElement("a", { href: "https://policies.google.com/privacy" }, "Privacy\u00A0Policy"),
|
|
5230
|
-
' and ',
|
|
5231
|
-
React__default["default"].createElement("a", { href: "https://policies.google.com/terms" }, "Terms\u00A0of\u00A0Service"),
|
|
5232
|
-
" apply."),
|
|
5233
|
-
React__default["default"].createElement("div", { className: "medplum-signin-buttons" },
|
|
5234
|
-
React__default["default"].createElement("div", null,
|
|
5235
|
-
React__default["default"].createElement("input", { type: "checkbox", id: "remember", name: "remember", value: "true" }),
|
|
5236
|
-
React__default["default"].createElement("label", { htmlFor: "remember" }, "Remember me")),
|
|
5237
|
-
React__default["default"].createElement("div", null,
|
|
5238
|
-
React__default["default"].createElement(Button, { type: "submit", testid: "submit" }, "Create account"))))));
|
|
5406
|
+
return items.map((item) => (Object.assign(Object.assign({}, item), { id: item.id || generateId(), item: ensureQuestionnaireItemKeys(item.item), answerOption: ensureQuestionnaireOptionKeys(item.answerOption) })));
|
|
5407
|
+
}
|
|
5408
|
+
function ensureQuestionnaireOptionKeys(options) {
|
|
5409
|
+
if (!options) {
|
|
5410
|
+
return undefined;
|
|
5411
|
+
}
|
|
5412
|
+
return options.map((option) => (Object.assign(Object.assign({}, option), { id: option.id || generateId() })));
|
|
5239
5413
|
}
|
|
5240
5414
|
|
|
5241
5415
|
function StatusBadge(props) {
|
|
@@ -5588,19 +5762,23 @@
|
|
|
5588
5762
|
React__default["default"].createElement("th", null, "Author"),
|
|
5589
5763
|
React__default["default"].createElement("th", null, "Date"),
|
|
5590
5764
|
React__default["default"].createElement("th", null, "Version"))),
|
|
5591
|
-
React__default["default"].createElement("tbody", null, (_a = value.entry) === null || _a === void 0 ? void 0 : _a.map((entry) => {
|
|
5592
|
-
var _a, _b;
|
|
5593
|
-
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 }));
|
|
5594
|
-
}))));
|
|
5765
|
+
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 }))))));
|
|
5595
5766
|
}
|
|
5596
5767
|
function HistoryRow(props) {
|
|
5597
5768
|
var _a, _b, _c;
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
React__default["default"].createElement(
|
|
5769
|
+
const { response, resource } = props.entry;
|
|
5770
|
+
if (resource) {
|
|
5771
|
+
return (React__default["default"].createElement("tr", null,
|
|
5772
|
+
React__default["default"].createElement("td", null,
|
|
5773
|
+
React__default["default"].createElement(ResourceBadge, { value: (_a = resource.meta) === null || _a === void 0 ? void 0 : _a.author, link: true })),
|
|
5774
|
+
React__default["default"].createElement("td", null, core.formatDateTime((_b = resource.meta) === null || _b === void 0 ? void 0 : _b.lastUpdated)),
|
|
5775
|
+
React__default["default"].createElement("td", null,
|
|
5776
|
+
React__default["default"].createElement(MedplumLink, { to: getVersionUrl(resource) }, (_c = resource.meta) === null || _c === void 0 ? void 0 : _c.versionId))));
|
|
5777
|
+
}
|
|
5778
|
+
else {
|
|
5779
|
+
return (React__default["default"].createElement("tr", null,
|
|
5780
|
+
React__default["default"].createElement("td", { colSpan: 3 }, core.normalizeErrorString(response === null || response === void 0 ? void 0 : response.outcome))));
|
|
5781
|
+
}
|
|
5604
5782
|
}
|
|
5605
5783
|
function getVersionUrl(resource) {
|
|
5606
5784
|
var _a;
|
|
@@ -5702,22 +5880,23 @@
|
|
|
5702
5880
|
var _a;
|
|
5703
5881
|
const medplum = useMedplum();
|
|
5704
5882
|
const schedule = useResource(props.schedule);
|
|
5883
|
+
const questionnaire = useResource(props.questionnaire);
|
|
5705
5884
|
const [slots, setSlots] = React.useState();
|
|
5706
5885
|
const slotsRef = React.useRef();
|
|
5707
5886
|
slotsRef.current = slots;
|
|
5708
5887
|
const [month, setMonth] = React.useState(getStartMonth());
|
|
5709
5888
|
const [date, setDate] = React.useState();
|
|
5710
5889
|
const [slot, setSlot] = React.useState();
|
|
5711
|
-
const [
|
|
5712
|
-
const [form, setForm] = React.useState();
|
|
5890
|
+
const [response, setResponse] = React.useState();
|
|
5713
5891
|
React.useEffect(() => {
|
|
5714
5892
|
if (schedule) {
|
|
5715
5893
|
setSlots([]);
|
|
5716
5894
|
medplum
|
|
5717
5895
|
.searchResources('Slot', new URLSearchParams([
|
|
5896
|
+
['_count', (30 * 24).toString()],
|
|
5718
5897
|
['schedule', core.getReferenceString(schedule)],
|
|
5719
|
-
['start', 'gt' + month
|
|
5720
|
-
['start', 'lt' +
|
|
5898
|
+
['start', 'gt' + getStart(month)],
|
|
5899
|
+
['start', 'lt' + getEnd(month)],
|
|
5721
5900
|
]))
|
|
5722
5901
|
.then(setSlots)
|
|
5723
5902
|
.catch(console.log);
|
|
@@ -5726,7 +5905,7 @@
|
|
|
5726
5905
|
setSlots(undefined);
|
|
5727
5906
|
}
|
|
5728
5907
|
}, [medplum, schedule, month]);
|
|
5729
|
-
if (!schedule || !slots) {
|
|
5908
|
+
if (!schedule || !slots || !questionnaire) {
|
|
5730
5909
|
return null;
|
|
5731
5910
|
}
|
|
5732
5911
|
const actor = (_a = schedule.actor) === null || _a === void 0 ? void 0 : _a[0];
|
|
@@ -5750,26 +5929,20 @@
|
|
|
5750
5929
|
slotStart.getTime() < date.getTime() + 24 * 3600 * 1000 && (React__default["default"].createElement("div", { key: s.id },
|
|
5751
5930
|
React__default["default"].createElement(Button, { style: { width: 150 }, onClick: () => setSlot(s) }, formatTime(slotStart)))));
|
|
5752
5931
|
}))),
|
|
5753
|
-
date && slot && !
|
|
5754
|
-
|
|
5755
|
-
React__default["default"].createElement(FormSection, { title: "Name", htmlFor: "name" },
|
|
5756
|
-
React__default["default"].createElement(Input, { name: "name" })),
|
|
5757
|
-
React__default["default"].createElement(FormSection, { title: "Email", htmlFor: "email" },
|
|
5758
|
-
React__default["default"].createElement(Input, { name: "email" })),
|
|
5759
|
-
React__default["default"].createElement(Button, { primary: true, onClick: () => setInfo('info') }, "Next"))),
|
|
5760
|
-
date && slot && info && !form && (React__default["default"].createElement("div", null,
|
|
5761
|
-
React__default["default"].createElement("h3", null, "Custom questions"),
|
|
5762
|
-
React__default["default"].createElement(FormSection, { title: "Question 1", htmlFor: "q1" },
|
|
5763
|
-
React__default["default"].createElement(Input, { name: "q1" })),
|
|
5764
|
-
React__default["default"].createElement(FormSection, { title: "Question 2", htmlFor: "q2" },
|
|
5765
|
-
React__default["default"].createElement(Input, { name: "email" })),
|
|
5766
|
-
React__default["default"].createElement(FormSection, { title: "Question 3", htmlFor: "q3" },
|
|
5767
|
-
React__default["default"].createElement(Input, { name: "email" })),
|
|
5768
|
-
React__default["default"].createElement(Button, { primary: true, onClick: () => setForm('form') }, "Next"))),
|
|
5769
|
-
date && slot && info && form && (React__default["default"].createElement("div", null,
|
|
5932
|
+
date && slot && !response && (React__default["default"].createElement(QuestionnaireForm, { questionnaire: questionnaire, submitButtonText: 'Next', onSubmit: setResponse })),
|
|
5933
|
+
date && slot && response && (React__default["default"].createElement("div", null,
|
|
5770
5934
|
React__default["default"].createElement("h3", null, "You're all set!"),
|
|
5771
5935
|
React__default["default"].createElement("p", null, "Check your email for a calendar invite."))))));
|
|
5772
5936
|
}
|
|
5937
|
+
function getStart(month) {
|
|
5938
|
+
return formatSlotInstant(month.getTime());
|
|
5939
|
+
}
|
|
5940
|
+
function getEnd(month) {
|
|
5941
|
+
return formatSlotInstant(month.getTime() + 31 * 24 * 60 * 60 * 1000);
|
|
5942
|
+
}
|
|
5943
|
+
function formatSlotInstant(time) {
|
|
5944
|
+
return new Date(Math.max(Date.now(), time)).toISOString();
|
|
5945
|
+
}
|
|
5773
5946
|
function formatTime(date) {
|
|
5774
5947
|
return date.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' });
|
|
5775
5948
|
}
|
|
@@ -5788,19 +5961,19 @@
|
|
|
5788
5961
|
{
|
|
5789
5962
|
request: {
|
|
5790
5963
|
method: 'GET',
|
|
5791
|
-
url: `Communication?based-on=${core.getReferenceString(resource)}`,
|
|
5964
|
+
url: `Communication?based-on=${core.getReferenceString(resource)}&_sort=-_lastUpdated`,
|
|
5792
5965
|
},
|
|
5793
5966
|
},
|
|
5794
5967
|
{
|
|
5795
5968
|
request: {
|
|
5796
5969
|
method: 'GET',
|
|
5797
|
-
url: `Media?_count=100&based-on=${core.getReferenceString(resource)}`,
|
|
5970
|
+
url: `Media?_count=100&based-on=${core.getReferenceString(resource)}&_sort=-_lastUpdated`,
|
|
5798
5971
|
},
|
|
5799
5972
|
},
|
|
5800
5973
|
{
|
|
5801
5974
|
request: {
|
|
5802
5975
|
method: 'GET',
|
|
5803
|
-
url: `DiagnosticReport?based-on=${core.getReferenceString(resource)}`,
|
|
5976
|
+
url: `DiagnosticReport?based-on=${core.getReferenceString(resource)}&_sort=-_lastUpdated`,
|
|
5804
5977
|
},
|
|
5805
5978
|
},
|
|
5806
5979
|
],
|
|
@@ -5821,157 +5994,6 @@
|
|
|
5821
5994
|
}) }));
|
|
5822
5995
|
}
|
|
5823
5996
|
|
|
5824
|
-
function SignInForm(props) {
|
|
5825
|
-
const medplum = useMedplum();
|
|
5826
|
-
const [login, setLogin] = React.useState(undefined);
|
|
5827
|
-
const [memberships, setMemberships] = React.useState(undefined);
|
|
5828
|
-
function handleAuthResponse(response) {
|
|
5829
|
-
if (response.login) {
|
|
5830
|
-
setLogin(response.login);
|
|
5831
|
-
}
|
|
5832
|
-
if (response.memberships) {
|
|
5833
|
-
setMemberships(response.memberships);
|
|
5834
|
-
}
|
|
5835
|
-
if (response.code) {
|
|
5836
|
-
if (props.onCode) {
|
|
5837
|
-
props.onCode(response.code);
|
|
5838
|
-
}
|
|
5839
|
-
else {
|
|
5840
|
-
medplum
|
|
5841
|
-
.processCode(response.code)
|
|
5842
|
-
.then(() => {
|
|
5843
|
-
if (props.onSuccess) {
|
|
5844
|
-
props.onSuccess();
|
|
5845
|
-
}
|
|
5846
|
-
})
|
|
5847
|
-
.catch(console.log);
|
|
5848
|
-
}
|
|
5849
|
-
}
|
|
5850
|
-
}
|
|
5851
|
-
return (React__default["default"].createElement(Document, { width: 450 }, (() => {
|
|
5852
|
-
if (!login) {
|
|
5853
|
-
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));
|
|
5854
|
-
}
|
|
5855
|
-
else if (memberships) {
|
|
5856
|
-
return React__default["default"].createElement(ProfileForm, { login: login, memberships: memberships, handleAuthResponse: handleAuthResponse });
|
|
5857
|
-
}
|
|
5858
|
-
else if (props.projectId === 'new') {
|
|
5859
|
-
return React__default["default"].createElement(NewProjectForm, { login: login, handleAuthResponse: handleAuthResponse });
|
|
5860
|
-
}
|
|
5861
|
-
else {
|
|
5862
|
-
return React__default["default"].createElement("div", null, "Success");
|
|
5863
|
-
}
|
|
5864
|
-
})()));
|
|
5865
|
-
}
|
|
5866
|
-
function AuthenticationForm(props) {
|
|
5867
|
-
const medplum = useMedplum();
|
|
5868
|
-
const googleClientId = getGoogleClientId(props.googleClientId);
|
|
5869
|
-
const [outcome, setOutcome] = React.useState();
|
|
5870
|
-
const issues = getIssuesForExpression(outcome, undefined);
|
|
5871
|
-
return (React__default["default"].createElement(Form, { style: { maxWidth: 400 }, onSubmit: (formData) => {
|
|
5872
|
-
medplum
|
|
5873
|
-
.startLogin({
|
|
5874
|
-
projectId: props.projectId,
|
|
5875
|
-
clientId: props.clientId,
|
|
5876
|
-
scope: props.scope,
|
|
5877
|
-
nonce: props.nonce,
|
|
5878
|
-
email: formData.email,
|
|
5879
|
-
password: formData.password,
|
|
5880
|
-
remember: formData.remember === 'true',
|
|
5881
|
-
})
|
|
5882
|
-
.then(props.handleAuthResponse)
|
|
5883
|
-
.catch(setOutcome);
|
|
5884
|
-
} },
|
|
5885
|
-
React__default["default"].createElement("div", { className: "medplum-center" }, props.children),
|
|
5886
|
-
issues && (React__default["default"].createElement("div", { className: "medplum-input-error" }, issues.map((issue) => {
|
|
5887
|
-
var _a, _b;
|
|
5888
|
-
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));
|
|
5889
|
-
}))),
|
|
5890
|
-
googleClientId && (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
5891
|
-
React__default["default"].createElement("div", { className: "medplum-signin-google-container" },
|
|
5892
|
-
React__default["default"].createElement(GoogleButton, { googleClientId: googleClientId, handleGoogleCredential: (response) => {
|
|
5893
|
-
medplum
|
|
5894
|
-
.startGoogleLogin({
|
|
5895
|
-
projectId: props.projectId,
|
|
5896
|
-
clientId: props.clientId,
|
|
5897
|
-
scope: props.scope,
|
|
5898
|
-
nonce: props.nonce,
|
|
5899
|
-
googleClientId: response.clientId,
|
|
5900
|
-
googleCredential: response.credential,
|
|
5901
|
-
})
|
|
5902
|
-
.then(props.handleAuthResponse)
|
|
5903
|
-
.catch(setOutcome);
|
|
5904
|
-
} })),
|
|
5905
|
-
React__default["default"].createElement("div", { className: "medplum-signin-separator" }, "or"))),
|
|
5906
|
-
React__default["default"].createElement(FormSection, { title: "Email", htmlFor: "email", outcome: outcome },
|
|
5907
|
-
React__default["default"].createElement(Input, { name: "email", type: "email", testid: "email", required: true, autoFocus: true, outcome: outcome })),
|
|
5908
|
-
React__default["default"].createElement(FormSection, { title: "Password", htmlFor: "password", outcome: outcome },
|
|
5909
|
-
React__default["default"].createElement(Input, { name: "password", type: "password", testid: "password", autoComplete: "off", required: true, outcome: outcome })),
|
|
5910
|
-
React__default["default"].createElement("div", { className: "medplum-signin-buttons" },
|
|
5911
|
-
(props.onForgotPassword || props.onRegister) && (React__default["default"].createElement("div", null,
|
|
5912
|
-
props.onForgotPassword && (React__default["default"].createElement(MedplumLink, { testid: "forgotpassword", onClick: props.onForgotPassword }, "Forgot password")),
|
|
5913
|
-
props.onRegister && (React__default["default"].createElement(MedplumLink, { testid: "register", onClick: props.onRegister }, "Register")))),
|
|
5914
|
-
React__default["default"].createElement("div", null,
|
|
5915
|
-
React__default["default"].createElement("input", { type: "checkbox", id: "remember", name: "remember", value: "true" }),
|
|
5916
|
-
React__default["default"].createElement("label", { htmlFor: "remember" }, "Remember me")),
|
|
5917
|
-
React__default["default"].createElement("div", null,
|
|
5918
|
-
React__default["default"].createElement(Button, { type: "submit", testid: "submit" }, "Sign in")))));
|
|
5919
|
-
}
|
|
5920
|
-
function ProfileForm(props) {
|
|
5921
|
-
const medplum = useMedplum();
|
|
5922
|
-
return (React__default["default"].createElement("div", null,
|
|
5923
|
-
React__default["default"].createElement("div", { className: "medplum-center" },
|
|
5924
|
-
React__default["default"].createElement(Logo, { size: 32 }),
|
|
5925
|
-
React__default["default"].createElement("h1", null, "Choose profile")),
|
|
5926
|
-
props.memberships.map((membership) => {
|
|
5927
|
-
var _a, _b, _c;
|
|
5928
|
-
return (React__default["default"].createElement("div", { className: "medplum-nav-menu-profile", key: membership.id, onClick: () => {
|
|
5929
|
-
medplum
|
|
5930
|
-
.post('auth/profile', {
|
|
5931
|
-
login: props.login,
|
|
5932
|
-
profile: membership.id,
|
|
5933
|
-
})
|
|
5934
|
-
.then(props.handleAuthResponse)
|
|
5935
|
-
.catch(console.log);
|
|
5936
|
-
} },
|
|
5937
|
-
React__default["default"].createElement("div", { className: "medplum-nav-menu-profile-icon" },
|
|
5938
|
-
React__default["default"].createElement(Avatar, { alt: (_a = membership.profile) === null || _a === void 0 ? void 0 : _a.display })),
|
|
5939
|
-
React__default["default"].createElement("div", { className: "medplum-nav-menu-profile-label" }, (_b = membership.profile) === null || _b === void 0 ? void 0 :
|
|
5940
|
-
_b.display,
|
|
5941
|
-
React__default["default"].createElement("div", { className: "medplum-nav-menu-profile-help-text" }, (_c = membership.project) === null || _c === void 0 ? void 0 : _c.display))));
|
|
5942
|
-
})));
|
|
5943
|
-
}
|
|
5944
|
-
function NewProjectForm(props) {
|
|
5945
|
-
const medplum = useMedplum();
|
|
5946
|
-
const [outcome, setOutcome] = React.useState();
|
|
5947
|
-
return (React__default["default"].createElement(Form, { style: { maxWidth: 400 }, onSubmit: (formData) => __awaiter(this, void 0, void 0, function* () {
|
|
5948
|
-
try {
|
|
5949
|
-
const registerRequest = { projectName: formData.projectName };
|
|
5950
|
-
const partialLogin = { login: props.login };
|
|
5951
|
-
const login = yield medplum.startNewProject(registerRequest, partialLogin);
|
|
5952
|
-
props.handleAuthResponse(login);
|
|
5953
|
-
}
|
|
5954
|
-
catch (err) {
|
|
5955
|
-
setOutcome(err);
|
|
5956
|
-
}
|
|
5957
|
-
}) },
|
|
5958
|
-
React__default["default"].createElement("div", { className: "medplum-center" },
|
|
5959
|
-
React__default["default"].createElement(Logo, { size: 32 }),
|
|
5960
|
-
React__default["default"].createElement("h1", null, "Create project")),
|
|
5961
|
-
React__default["default"].createElement(FormSection, { title: "Project Name", htmlFor: "projectName", outcome: outcome },
|
|
5962
|
-
React__default["default"].createElement(Input, { name: "projectName", type: "text", testid: "projectName", placeholder: "My Project", required: true, outcome: outcome })),
|
|
5963
|
-
React__default["default"].createElement("p", { style: { fontSize: '12px', color: '#888' } },
|
|
5964
|
-
"By clicking submit you agree to the Medplum ",
|
|
5965
|
-
React__default["default"].createElement("a", { href: "https://www.medplum.com/privacy" }, "Privacy\u00A0Policy"),
|
|
5966
|
-
' and ',
|
|
5967
|
-
React__default["default"].createElement("a", { href: "https://www.medplum.com/terms" }, "Terms\u00A0of\u00A0Service"),
|
|
5968
|
-
"."),
|
|
5969
|
-
React__default["default"].createElement("div", { className: "medplum-signin-buttons" },
|
|
5970
|
-
React__default["default"].createElement("div", null),
|
|
5971
|
-
React__default["default"].createElement("div", null,
|
|
5972
|
-
React__default["default"].createElement(Button, { type: "submit", testid: "submit" }, "Create project")))));
|
|
5973
|
-
}
|
|
5974
|
-
|
|
5975
5997
|
function Tab(props) {
|
|
5976
5998
|
let className = 'medplum-tab';
|
|
5977
5999
|
if (props.selected) {
|