@medplum/react 0.9.22 → 0.9.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/index.js CHANGED
@@ -1776,18 +1776,24 @@
1776
1776
  }
1777
1777
 
1778
1778
  function DiagnosticReportDisplay(props) {
1779
- var _a;
1779
+ var _a, _b;
1780
1780
  const diagnosticReport = useResource(props.value);
1781
+ const specimen = useResource((_a = diagnosticReport === null || diagnosticReport === void 0 ? void 0 : diagnosticReport.specimen) === null || _a === void 0 ? void 0 : _a[0]);
1781
1782
  if (!diagnosticReport) {
1782
1783
  return null;
1783
1784
  }
1784
- let textContent = undefined;
1785
+ let textContent = '';
1785
1786
  if (diagnosticReport.presentedForm && diagnosticReport.presentedForm.length > 0) {
1786
1787
  const pf = diagnosticReport.presentedForm[0];
1787
- if (((_a = pf.contentType) === null || _a === void 0 ? void 0 : _a.startsWith('text/plain')) && pf.data) {
1788
+ if (((_b = pf.contentType) === null || _b === void 0 ? void 0 : _b.startsWith('text/plain')) && pf.data) {
1788
1789
  textContent = window.atob(pf.data);
1789
1790
  }
1790
1791
  }
1792
+ if (specimen === null || specimen === void 0 ? void 0 : specimen.note) {
1793
+ for (const note of specimen.note) {
1794
+ textContent += note.text + '\n\n';
1795
+ }
1796
+ }
1791
1797
  return (React__default["default"].createElement("div", { className: "medplum-diagnostic-report" },
1792
1798
  React__default["default"].createElement("h1", null, "Diagnostic Report"),
1793
1799
  React__default["default"].createElement("div", { className: "medplum-diagnostic-report-header" },
@@ -1807,8 +1813,8 @@
1807
1813
  diagnosticReport.status && (React__default["default"].createElement("dl", null,
1808
1814
  React__default["default"].createElement("dt", null, "Status"),
1809
1815
  React__default["default"].createElement("dd", null, core.capitalize(diagnosticReport.status))))),
1810
- textContent && React__default["default"].createElement("pre", null, textContent),
1811
- diagnosticReport.result && React__default["default"].createElement(ObservationTable, { value: diagnosticReport.result })));
1816
+ diagnosticReport.result && React__default["default"].createElement(ObservationTable, { value: diagnosticReport.result }),
1817
+ textContent && React__default["default"].createElement("pre", null, textContent.trim())));
1812
1818
  }
1813
1819
  function ObservationTable(props) {
1814
1820
  var _a;
@@ -4904,6 +4910,179 @@
4904
4910
  return options.map((option) => (Object.assign(Object.assign({}, option), { id: option.id || generateId() })));
4905
4911
  }
4906
4912
 
4913
+ /**
4914
+ * Dynamically creates a script tag for the specified JavaScript file.
4915
+ * @param src The JavaScript file URL.
4916
+ */
4917
+ function createScriptTag(src, onload) {
4918
+ const head = document.getElementsByTagName('head')[0];
4919
+ const script = document.createElement('script');
4920
+ script.async = true;
4921
+ script.src = src;
4922
+ script.onload = onload || null;
4923
+ head.appendChild(script);
4924
+ }
4925
+
4926
+ function GoogleButton(props) {
4927
+ const medplum = useMedplum();
4928
+ const { googleClientId, handleGoogleCredential } = props;
4929
+ const parentRef = React.useRef(null);
4930
+ const [scriptLoaded, setScriptLoaded] = React.useState(typeof google !== 'undefined');
4931
+ const [initialized, setInitialized] = React.useState(false);
4932
+ const [buttonRendered, setButtonRendered] = React.useState(false);
4933
+ React.useEffect(() => {
4934
+ if (typeof google === 'undefined') {
4935
+ createScriptTag('https://accounts.google.com/gsi/client', () => setScriptLoaded(true));
4936
+ return;
4937
+ }
4938
+ if (!initialized) {
4939
+ google.accounts.id.initialize({
4940
+ client_id: googleClientId,
4941
+ callback: handleGoogleCredential,
4942
+ });
4943
+ setInitialized(true);
4944
+ }
4945
+ if (parentRef.current && !buttonRendered) {
4946
+ google.accounts.id.renderButton(parentRef.current, {});
4947
+ setButtonRendered(true);
4948
+ }
4949
+ }, [medplum, googleClientId, initialized, scriptLoaded, parentRef, buttonRendered, handleGoogleCredential]);
4950
+ if (!googleClientId) {
4951
+ return null;
4952
+ }
4953
+ return React__default["default"].createElement("div", { ref: parentRef });
4954
+ }
4955
+ function getGoogleClientId(clientId) {
4956
+ var _a, _b;
4957
+ if (clientId) {
4958
+ return clientId;
4959
+ }
4960
+ const origin = window.location.protocol + '//' + window.location.host;
4961
+ const authorizedOrigins = (_b = (_a = "http://localhost:3000,http://localhost:6006,https://app.medplum.com,https://docs.medplum.com") === null || _a === void 0 ? void 0 : _a.split(',')) !== null && _b !== void 0 ? _b : [];
4962
+ if (authorizedOrigins.includes(origin)) {
4963
+ return "921088377005-3j1sa10vr6hj86jgmdfh2l53v3mp7lfi.apps.googleusercontent.com";
4964
+ }
4965
+ return undefined;
4966
+ }
4967
+
4968
+ /**
4969
+ * Dynamically loads the recaptcha script.
4970
+ * We do not want to load the script on page load unless the user needs it.
4971
+ * @param siteKey The reCAPTCHA site key, available from the reCAPTCHA admin page.
4972
+ */
4973
+ function initRecaptcha(siteKey) {
4974
+ if (typeof grecaptcha === 'undefined') {
4975
+ createScriptTag('https://www.google.com/recaptcha/api.js?render=' + siteKey);
4976
+ }
4977
+ }
4978
+ /**
4979
+ * Starts a request to generate a recapcha token.
4980
+ * @param siteKey The reCAPTCHA site key, available from the reCAPTCHA admin page.
4981
+ * @returns Promise to a recaptcha token for the current user.
4982
+ */
4983
+ function getRecaptcha(siteKey) {
4984
+ return new Promise((resolve) => {
4985
+ grecaptcha.ready(() => {
4986
+ grecaptcha.execute(siteKey, { action: 'submit' }).then(resolve);
4987
+ });
4988
+ });
4989
+ }
4990
+
4991
+ function RegisterForm(props) {
4992
+ const medplum = useMedplum();
4993
+ const googleClientId = getGoogleClientId(props.googleClientId);
4994
+ const recaptchaSiteKey = props.recaptchaSiteKey;
4995
+ const [outcome, setOutcome] = React.useState();
4996
+ const issues = getIssuesForExpression(outcome, undefined);
4997
+ React.useEffect(() => initRecaptcha(recaptchaSiteKey), [recaptchaSiteKey]);
4998
+ function handleAuthResponse(registerRequest, partialLogin) {
4999
+ return __awaiter(this, void 0, void 0, function* () {
5000
+ try {
5001
+ let login;
5002
+ if (props.type === 'patient') {
5003
+ login = yield medplum.startNewPatient(registerRequest, partialLogin);
5004
+ }
5005
+ else {
5006
+ login = yield medplum.startNewProject(registerRequest, partialLogin);
5007
+ }
5008
+ yield medplum.processCode(login.code);
5009
+ props.onSuccess();
5010
+ }
5011
+ catch (err) {
5012
+ setOutcome(err);
5013
+ }
5014
+ });
5015
+ }
5016
+ return (React__default["default"].createElement(Document, { width: 450 },
5017
+ React__default["default"].createElement(Form, { style: { maxWidth: 400 }, onSubmit: (formData) => __awaiter(this, void 0, void 0, function* () {
5018
+ try {
5019
+ const recaptchaToken = yield getRecaptcha(recaptchaSiteKey);
5020
+ const registerRequest = Object.assign(Object.assign({}, formData), { recaptchaToken });
5021
+ const userLogin = yield medplum.startNewUser(registerRequest);
5022
+ handleAuthResponse(registerRequest, userLogin);
5023
+ }
5024
+ catch (err) {
5025
+ setOutcome(err);
5026
+ }
5027
+ }) },
5028
+ React__default["default"].createElement("div", { className: "medplum-center" }, props.children),
5029
+ issues && (React__default["default"].createElement("div", { className: "medplum-input-error" }, issues.map((issue) => {
5030
+ var _a, _b;
5031
+ 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));
5032
+ }))),
5033
+ googleClientId && (React__default["default"].createElement(React__default["default"].Fragment, null,
5034
+ React__default["default"].createElement("div", { className: "medplum-signin-google-container" },
5035
+ React__default["default"].createElement(GoogleButton, { googleClientId: googleClientId, handleGoogleCredential: (response) => __awaiter(this, void 0, void 0, function* () {
5036
+ try {
5037
+ const loginRequest = {
5038
+ googleClientId: response.clientId,
5039
+ googleCredential: response.credential,
5040
+ };
5041
+ const userLogin = yield medplum.startGoogleLogin(loginRequest);
5042
+ const googleClaims = core.parseJWTPayload(loginRequest.googleCredential);
5043
+ const registerRequest = {
5044
+ firstName: googleClaims.given_name,
5045
+ lastName: googleClaims.family_name,
5046
+ email: googleClaims.email,
5047
+ };
5048
+ handleAuthResponse(registerRequest, userLogin);
5049
+ }
5050
+ catch (err) {
5051
+ setOutcome(err);
5052
+ }
5053
+ }) })),
5054
+ React__default["default"].createElement("div", { className: "medplum-signin-separator" }, "or"))),
5055
+ React__default["default"].createElement(FormSection, { title: "First Name", htmlFor: "firstName", outcome: outcome },
5056
+ React__default["default"].createElement(Input, { name: "firstName", type: "text", testid: "firstName", placeholder: "First name", required: true, autoFocus: true, outcome: outcome })),
5057
+ React__default["default"].createElement(FormSection, { title: "Last Name", htmlFor: "lastName", outcome: outcome },
5058
+ React__default["default"].createElement(Input, { name: "lastName", type: "text", testid: "lastName", placeholder: "Last name", required: true, outcome: outcome })),
5059
+ props.type === 'project' && (React__default["default"].createElement(FormSection, { title: "Project Name", htmlFor: "projectName", outcome: outcome },
5060
+ React__default["default"].createElement(Input, { name: "projectName", type: "text", testid: "projectName", placeholder: "My Project", required: true, outcome: outcome }))),
5061
+ React__default["default"].createElement(FormSection, { title: "Email", htmlFor: "email", outcome: outcome },
5062
+ React__default["default"].createElement(Input, { name: "email", type: "email", testid: "email", placeholder: "name@domain.com", required: true, outcome: outcome })),
5063
+ React__default["default"].createElement(FormSection, { title: "Password", htmlFor: "password", outcome: outcome },
5064
+ React__default["default"].createElement(Input, { name: "password", type: "password", testid: "password", autoComplete: "off", required: true, outcome: outcome })),
5065
+ React__default["default"].createElement("p", { style: { fontSize: '12px', color: '#888' } },
5066
+ "By clicking submit you agree to the Medplum ",
5067
+ React__default["default"].createElement("a", { href: "https://www.medplum.com/privacy" }, "Privacy\u00A0Policy"),
5068
+ ' and ',
5069
+ React__default["default"].createElement("a", { href: "https://www.medplum.com/terms" }, "Terms\u00A0of\u00A0Service"),
5070
+ "."),
5071
+ React__default["default"].createElement("p", { style: { fontSize: '12px', color: '#888' } },
5072
+ "This site is protected by reCAPTCHA and the Google",
5073
+ ' ',
5074
+ React__default["default"].createElement("a", { href: "https://policies.google.com/privacy" }, "Privacy\u00A0Policy"),
5075
+ ' and ',
5076
+ React__default["default"].createElement("a", { href: "https://policies.google.com/terms" }, "Terms\u00A0of\u00A0Service"),
5077
+ " apply."),
5078
+ React__default["default"].createElement("div", { className: "medplum-signin-buttons" },
5079
+ React__default["default"].createElement("div", null,
5080
+ React__default["default"].createElement("input", { type: "checkbox", id: "remember", name: "remember", value: "true" }),
5081
+ React__default["default"].createElement("label", { htmlFor: "remember" }, "Remember me")),
5082
+ React__default["default"].createElement("div", null,
5083
+ React__default["default"].createElement(Button, { type: "submit", testid: "submit" }, "Create account"))))));
5084
+ }
5085
+
4907
5086
  function StatusBadge(props) {
4908
5087
  return React__default["default"].createElement("span", { className: `medplum-status medplum-status-${props.status}` }, props.status);
4909
5088
  }
@@ -5477,62 +5656,6 @@
5477
5656
  }) }));
5478
5657
  }
5479
5658
 
5480
- /**
5481
- * Dynamically creates a script tag for the specified JavaScript file.
5482
- * @param src The JavaScript file URL.
5483
- */
5484
- function createScriptTag(src, onload) {
5485
- const head = document.getElementsByTagName('head')[0];
5486
- const script = document.createElement('script');
5487
- script.async = true;
5488
- script.src = src;
5489
- script.onload = onload || null;
5490
- head.appendChild(script);
5491
- }
5492
-
5493
- function GoogleButton(props) {
5494
- const medplum = useMedplum();
5495
- const { handleGoogleCredential } = props;
5496
- const googleClientId = getGoogleClientId(props.googleClientId);
5497
- const parentRef = React.useRef(null);
5498
- const [scriptLoaded, setScriptLoaded] = React.useState(typeof google !== 'undefined');
5499
- const [initialized, setInitialized] = React.useState(false);
5500
- const [buttonRendered, setButtonRendered] = React.useState(false);
5501
- React.useEffect(() => {
5502
- if (typeof google === 'undefined') {
5503
- createScriptTag('https://accounts.google.com/gsi/client', () => setScriptLoaded(true));
5504
- return;
5505
- }
5506
- if (!initialized) {
5507
- google.accounts.id.initialize({
5508
- client_id: googleClientId,
5509
- callback: handleGoogleCredential,
5510
- });
5511
- setInitialized(true);
5512
- }
5513
- if (parentRef.current && !buttonRendered) {
5514
- google.accounts.id.renderButton(parentRef.current, {});
5515
- setButtonRendered(true);
5516
- }
5517
- }, [medplum, googleClientId, initialized, scriptLoaded, parentRef, buttonRendered, handleGoogleCredential]);
5518
- if (!googleClientId) {
5519
- return null;
5520
- }
5521
- return React__default["default"].createElement("div", { ref: parentRef });
5522
- }
5523
- function getGoogleClientId(clientId) {
5524
- var _a, _b;
5525
- if (clientId) {
5526
- return clientId;
5527
- }
5528
- const origin = window.location.protocol + '//' + window.location.host;
5529
- 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 : [];
5530
- if (authorizedOrigins.includes(origin)) {
5531
- return "921088377005-3j1sa10vr6hj86jgmdfh2l53v3mp7lfi.apps.googleusercontent.com";
5532
- }
5533
- return undefined;
5534
- }
5535
-
5536
5659
  function SignInForm(props) {
5537
5660
  const medplum = useMedplum();
5538
5661
  const [login, setLogin] = React.useState(undefined);
@@ -5574,6 +5697,7 @@
5574
5697
  }
5575
5698
  function AuthenticationForm(props) {
5576
5699
  const medplum = useMedplum();
5700
+ const googleClientId = getGoogleClientId(props.googleClientId);
5577
5701
  const [outcome, setOutcome] = React.useState();
5578
5702
  const issues = getIssuesForExpression(outcome, undefined);
5579
5703
  return (React__default["default"].createElement(Form, { style: { maxWidth: 400 }, onSubmit: (formData) => {
@@ -5594,6 +5718,21 @@
5594
5718
  var _a, _b;
5595
5719
  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));
5596
5720
  }))),
5721
+ googleClientId && (React__default["default"].createElement(React__default["default"].Fragment, null,
5722
+ React__default["default"].createElement("div", { className: "medplum-signin-google-container" },
5723
+ React__default["default"].createElement(GoogleButton, { googleClientId: googleClientId, handleGoogleCredential: (response) => {
5724
+ medplum
5725
+ .startGoogleLogin({
5726
+ clientId: props.clientId,
5727
+ scope: props.scope,
5728
+ nonce: props.nonce,
5729
+ googleClientId: response.clientId,
5730
+ googleCredential: response.credential,
5731
+ })
5732
+ .then(props.handleAuthResponse)
5733
+ .catch(setOutcome);
5734
+ } })),
5735
+ React__default["default"].createElement("div", { className: "medplum-signin-separator" }, "or"))),
5597
5736
  React__default["default"].createElement(FormSection, { title: "Email", htmlFor: "email", outcome: outcome },
5598
5737
  React__default["default"].createElement(Input, { name: "email", type: "email", testid: "email", required: true, autoFocus: true, outcome: outcome })),
5599
5738
  React__default["default"].createElement(FormSection, { title: "Password", htmlFor: "password", outcome: outcome },
@@ -5606,20 +5745,7 @@
5606
5745
  React__default["default"].createElement("input", { type: "checkbox", id: "remember", name: "remember", value: "true" }),
5607
5746
  React__default["default"].createElement("label", { htmlFor: "remember" }, "Remember me")),
5608
5747
  React__default["default"].createElement("div", null,
5609
- React__default["default"].createElement(Button, { type: "submit", testid: "submit" }, "Sign in"))),
5610
- React__default["default"].createElement("div", { className: "medplum-signin-google-container" },
5611
- React__default["default"].createElement(GoogleButton, { googleClientId: props.googleClientId, handleGoogleCredential: (response) => {
5612
- medplum
5613
- .startGoogleLogin({
5614
- clientId: props.clientId,
5615
- scope: props.scope,
5616
- nonce: props.nonce,
5617
- googleClientId: response.clientId,
5618
- googleCredential: response.credential,
5619
- })
5620
- .then(props.handleAuthResponse)
5621
- .catch(setOutcome);
5622
- } }))));
5748
+ React__default["default"].createElement(Button, { type: "submit", testid: "submit" }, "Sign in")))));
5623
5749
  }
5624
5750
  function ProfileForm(props) {
5625
5751
  const medplum = useMedplum();
@@ -5727,6 +5853,7 @@
5727
5853
  exports.HumanNameInput = HumanNameInput;
5728
5854
  exports.IdentifierInput = IdentifierInput;
5729
5855
  exports.Input = Input;
5856
+ exports.InputRow = InputRow;
5730
5857
  exports.Loading = Loading;
5731
5858
  exports.Logo = Logo;
5732
5859
  exports.MedplumLink = MedplumLink;
@@ -5744,6 +5871,7 @@
5744
5871
  exports.RangeDisplay = RangeDisplay;
5745
5872
  exports.RangeInput = RangeInput;
5746
5873
  exports.ReferenceInput = ReferenceInput;
5874
+ exports.RegisterForm = RegisterForm;
5747
5875
  exports.RequestGroupDisplay = RequestGroupDisplay;
5748
5876
  exports.ResourceArrayDisplay = ResourceArrayDisplay;
5749
5877
  exports.ResourceArrayInput = ResourceArrayInput;
@@ -5802,11 +5930,13 @@
5802
5930
  exports.deleteFilter = deleteFilter;
5803
5931
  exports.formatRangeString = formatRangeString;
5804
5932
  exports.getOpString = getOpString;
5933
+ exports.getRecaptcha = getRecaptcha;
5805
5934
  exports.getSearchOperators = getSearchOperators;
5806
5935
  exports.getSortField = getSortField;
5807
5936
  exports.getTimeString = getTimeString;
5808
5937
  exports.getValueAndType = getValueAndType;
5809
5938
  exports.hasFilterOnField = hasFilterOnField;
5939
+ exports.initRecaptcha = initRecaptcha;
5810
5940
  exports.isChoiceQuestion = isChoiceQuestion;
5811
5941
  exports.isSortDescending = isSortDescending;
5812
5942
  exports.movePage = movePage;