@medplum/react 0.9.22 → 0.9.23

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,163 @@
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
+ */
4972
+ function initRecaptcha() {
4973
+ if (typeof grecaptcha === 'undefined') {
4974
+ createScriptTag('https://www.google.com/recaptcha/api.js?render=' + process.env.RECAPTCHA_SITE_KEY);
4975
+ }
4976
+ }
4977
+ /**
4978
+ * Starts a request to generate a recapcha token.
4979
+ * @returns Promise to a recaptcha token for the current user.
4980
+ */
4981
+ function getRecaptcha() {
4982
+ return new Promise((resolve) => {
4983
+ grecaptcha.ready(() => {
4984
+ grecaptcha.execute(process.env.RECAPTCHA_SITE_KEY, { action: 'submit' }).then(resolve);
4985
+ });
4986
+ });
4987
+ }
4988
+
4989
+ function RegisterForm(props) {
4990
+ const medplum = useMedplum();
4991
+ const googleClientId = getGoogleClientId(props.googleClientId);
4992
+ const [outcome, setOutcome] = React.useState();
4993
+ const issues = getIssuesForExpression(outcome, undefined);
4994
+ React.useEffect(initRecaptcha, []);
4995
+ function handleAuthResponse(registerRequest, partialLogin) {
4996
+ return __awaiter(this, void 0, void 0, function* () {
4997
+ try {
4998
+ let login;
4999
+ if (props.type === 'patient') {
5000
+ login = yield medplum.startNewPatient(registerRequest, partialLogin);
5001
+ }
5002
+ else {
5003
+ login = yield medplum.startNewProject(registerRequest, partialLogin);
5004
+ }
5005
+ yield medplum.processCode(login.code);
5006
+ props.onSuccess();
5007
+ }
5008
+ catch (err) {
5009
+ setOutcome(err);
5010
+ }
5011
+ });
5012
+ }
5013
+ return (React__default["default"].createElement(Document, { width: 450 },
5014
+ React__default["default"].createElement(Form, { style: { maxWidth: 400 }, onSubmit: (formData) => __awaiter(this, void 0, void 0, function* () {
5015
+ try {
5016
+ const recaptchaToken = yield getRecaptcha();
5017
+ const registerRequest = Object.assign(Object.assign({}, formData), { recaptchaToken });
5018
+ const userLogin = yield medplum.startNewUser(registerRequest);
5019
+ handleAuthResponse(registerRequest, userLogin);
5020
+ }
5021
+ catch (err) {
5022
+ setOutcome(err);
5023
+ }
5024
+ }) },
5025
+ React__default["default"].createElement("div", { className: "medplum-center" }, props.children),
5026
+ issues && (React__default["default"].createElement("div", { className: "medplum-input-error" }, issues.map((issue) => {
5027
+ var _a, _b;
5028
+ 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));
5029
+ }))),
5030
+ googleClientId && (React__default["default"].createElement(React__default["default"].Fragment, null,
5031
+ React__default["default"].createElement("div", { className: "medplum-signin-google-container" },
5032
+ React__default["default"].createElement(GoogleButton, { googleClientId: googleClientId, handleGoogleCredential: (response) => __awaiter(this, void 0, void 0, function* () {
5033
+ try {
5034
+ const loginRequest = {
5035
+ googleClientId: response.clientId,
5036
+ googleCredential: response.credential,
5037
+ };
5038
+ const userLogin = yield medplum.startGoogleLogin(loginRequest);
5039
+ const googleClaims = core.parseJWTPayload(loginRequest.googleCredential);
5040
+ const registerRequest = {
5041
+ firstName: googleClaims.given_name,
5042
+ lastName: googleClaims.family_name,
5043
+ email: googleClaims.email,
5044
+ };
5045
+ handleAuthResponse(registerRequest, userLogin);
5046
+ }
5047
+ catch (err) {
5048
+ setOutcome(err);
5049
+ }
5050
+ }) })),
5051
+ React__default["default"].createElement("div", { className: "medplum-signin-separator" }, "or"))),
5052
+ React__default["default"].createElement(FormSection, { title: "First Name", htmlFor: "firstName", outcome: outcome },
5053
+ React__default["default"].createElement(Input, { name: "firstName", type: "text", testid: "firstName", placeholder: "First name", required: true, autoFocus: true, outcome: outcome })),
5054
+ React__default["default"].createElement(FormSection, { title: "Last Name", htmlFor: "lastName", outcome: outcome },
5055
+ React__default["default"].createElement(Input, { name: "lastName", type: "text", testid: "lastName", placeholder: "Last name", required: true, outcome: outcome })),
5056
+ props.type === 'project' && (React__default["default"].createElement(FormSection, { title: "Project Name", htmlFor: "projectName", outcome: outcome },
5057
+ React__default["default"].createElement(Input, { name: "projectName", type: "text", testid: "projectName", placeholder: "My Project", required: true, outcome: outcome }))),
5058
+ React__default["default"].createElement(FormSection, { title: "Email", htmlFor: "email", outcome: outcome },
5059
+ React__default["default"].createElement(Input, { name: "email", type: "email", testid: "email", placeholder: "name@domain.com", required: true, outcome: outcome })),
5060
+ React__default["default"].createElement(FormSection, { title: "Password", htmlFor: "password", outcome: outcome },
5061
+ React__default["default"].createElement(Input, { name: "password", type: "password", testid: "password", autoComplete: "off", required: true, outcome: outcome })),
5062
+ React__default["default"].createElement("div", { className: "medplum-signin-buttons" },
5063
+ React__default["default"].createElement("div", null,
5064
+ React__default["default"].createElement("input", { type: "checkbox", id: "remember", name: "remember", value: "true" }),
5065
+ React__default["default"].createElement("label", { htmlFor: "remember" }, "Remember me")),
5066
+ React__default["default"].createElement("div", null,
5067
+ React__default["default"].createElement(Button, { type: "submit", testid: "submit" }, "Create account"))))));
5068
+ }
5069
+
4907
5070
  function StatusBadge(props) {
4908
5071
  return React__default["default"].createElement("span", { className: `medplum-status medplum-status-${props.status}` }, props.status);
4909
5072
  }
@@ -5477,62 +5640,6 @@
5477
5640
  }) }));
5478
5641
  }
5479
5642
 
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
5643
  function SignInForm(props) {
5537
5644
  const medplum = useMedplum();
5538
5645
  const [login, setLogin] = React.useState(undefined);
@@ -5574,6 +5681,7 @@
5574
5681
  }
5575
5682
  function AuthenticationForm(props) {
5576
5683
  const medplum = useMedplum();
5684
+ const googleClientId = getGoogleClientId(props.googleClientId);
5577
5685
  const [outcome, setOutcome] = React.useState();
5578
5686
  const issues = getIssuesForExpression(outcome, undefined);
5579
5687
  return (React__default["default"].createElement(Form, { style: { maxWidth: 400 }, onSubmit: (formData) => {
@@ -5594,6 +5702,21 @@
5594
5702
  var _a, _b;
5595
5703
  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
5704
  }))),
5705
+ googleClientId && (React__default["default"].createElement(React__default["default"].Fragment, null,
5706
+ React__default["default"].createElement("div", { className: "medplum-signin-google-container" },
5707
+ React__default["default"].createElement(GoogleButton, { googleClientId: googleClientId, handleGoogleCredential: (response) => {
5708
+ medplum
5709
+ .startGoogleLogin({
5710
+ clientId: props.clientId,
5711
+ scope: props.scope,
5712
+ nonce: props.nonce,
5713
+ googleClientId: response.clientId,
5714
+ googleCredential: response.credential,
5715
+ })
5716
+ .then(props.handleAuthResponse)
5717
+ .catch(setOutcome);
5718
+ } })),
5719
+ React__default["default"].createElement("div", { className: "medplum-signin-separator" }, "or"))),
5597
5720
  React__default["default"].createElement(FormSection, { title: "Email", htmlFor: "email", outcome: outcome },
5598
5721
  React__default["default"].createElement(Input, { name: "email", type: "email", testid: "email", required: true, autoFocus: true, outcome: outcome })),
5599
5722
  React__default["default"].createElement(FormSection, { title: "Password", htmlFor: "password", outcome: outcome },
@@ -5606,20 +5729,7 @@
5606
5729
  React__default["default"].createElement("input", { type: "checkbox", id: "remember", name: "remember", value: "true" }),
5607
5730
  React__default["default"].createElement("label", { htmlFor: "remember" }, "Remember me")),
5608
5731
  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
- } }))));
5732
+ React__default["default"].createElement(Button, { type: "submit", testid: "submit" }, "Sign in")))));
5623
5733
  }
5624
5734
  function ProfileForm(props) {
5625
5735
  const medplum = useMedplum();
@@ -5744,6 +5854,7 @@
5744
5854
  exports.RangeDisplay = RangeDisplay;
5745
5855
  exports.RangeInput = RangeInput;
5746
5856
  exports.ReferenceInput = ReferenceInput;
5857
+ exports.RegisterForm = RegisterForm;
5747
5858
  exports.RequestGroupDisplay = RequestGroupDisplay;
5748
5859
  exports.ResourceArrayDisplay = ResourceArrayDisplay;
5749
5860
  exports.ResourceArrayInput = ResourceArrayInput;
@@ -5802,11 +5913,13 @@
5802
5913
  exports.deleteFilter = deleteFilter;
5803
5914
  exports.formatRangeString = formatRangeString;
5804
5915
  exports.getOpString = getOpString;
5916
+ exports.getRecaptcha = getRecaptcha;
5805
5917
  exports.getSearchOperators = getSearchOperators;
5806
5918
  exports.getSortField = getSortField;
5807
5919
  exports.getTimeString = getTimeString;
5808
5920
  exports.getValueAndType = getValueAndType;
5809
5921
  exports.hasFilterOnField = hasFilterOnField;
5922
+ exports.initRecaptcha = initRecaptcha;
5810
5923
  exports.isChoiceQuestion = isChoiceQuestion;
5811
5924
  exports.isSortDescending = isSortDescending;
5812
5925
  exports.movePage = movePage;