@medplum/react 0.9.21 → 0.9.24
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 +361 -75
- 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 +109 -36
- package/dist/esm/index.js +360 -78
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.min.js +1 -1
- package/dist/esm/index.min.js.map +1 -1
- package/dist/esm/styles.css +109 -36
- package/dist/types/RegisterForm.d.ts +17 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/stories/RegisterForm.stories.d.ts +7 -0
- package/dist/types/utils/recaptcha.d.ts +10 -0
- package/package.json +12 -12
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 =
|
|
1785
|
+
let textContent = '';
|
|
1785
1786
|
if (diagnosticReport.presentedForm && diagnosticReport.presentedForm.length > 0) {
|
|
1786
1787
|
const pf = diagnosticReport.presentedForm[0];
|
|
1787
|
-
if (((
|
|
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
|
-
|
|
1811
|
-
|
|
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,176 @@
|
|
|
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("p", { style: { fontSize: '12px', color: '#888' } },
|
|
5063
|
+
"By clicking submit you agree to the Medplum ",
|
|
5064
|
+
React__default["default"].createElement("a", { href: "https://www.medplum.com/privacy" }, "Privacy\u00A0Policy"),
|
|
5065
|
+
' and ',
|
|
5066
|
+
React__default["default"].createElement("a", { href: "https://www.medplum.com/terms" }, "Terms\u00A0of\u00A0Service"),
|
|
5067
|
+
"."),
|
|
5068
|
+
React__default["default"].createElement("p", { style: { fontSize: '12px', color: '#888' } },
|
|
5069
|
+
"This site is protected by reCAPTCHA and the Google",
|
|
5070
|
+
' ',
|
|
5071
|
+
React__default["default"].createElement("a", { href: "https://policies.google.com/privacy" }, "Privacy\u00A0Policy"),
|
|
5072
|
+
' and ',
|
|
5073
|
+
React__default["default"].createElement("a", { href: "https://policies.google.com/terms" }, "Terms\u00A0of\u00A0Service"),
|
|
5074
|
+
" apply."),
|
|
5075
|
+
React__default["default"].createElement("div", { className: "medplum-signin-buttons" },
|
|
5076
|
+
React__default["default"].createElement("div", null,
|
|
5077
|
+
React__default["default"].createElement("input", { type: "checkbox", id: "remember", name: "remember", value: "true" }),
|
|
5078
|
+
React__default["default"].createElement("label", { htmlFor: "remember" }, "Remember me")),
|
|
5079
|
+
React__default["default"].createElement("div", null,
|
|
5080
|
+
React__default["default"].createElement(Button, { type: "submit", testid: "submit" }, "Create account"))))));
|
|
5081
|
+
}
|
|
5082
|
+
|
|
4907
5083
|
function StatusBadge(props) {
|
|
4908
5084
|
return React__default["default"].createElement("span", { className: `medplum-status medplum-status-${props.status}` }, props.status);
|
|
4909
5085
|
}
|
|
@@ -5271,6 +5447,165 @@
|
|
|
5271
5447
|
return `/${resource.resourceType}/${resource.id}/_history/${(_a = resource.meta) === null || _a === void 0 ? void 0 : _a.versionId}`;
|
|
5272
5448
|
}
|
|
5273
5449
|
|
|
5450
|
+
/**
|
|
5451
|
+
* Returns a month display string (e.g. "January 2020").
|
|
5452
|
+
* @param date Any date within the month.
|
|
5453
|
+
* @returns The month display string (e.g. "January 2020")
|
|
5454
|
+
*/
|
|
5455
|
+
function getMonthString(date) {
|
|
5456
|
+
return date.toLocaleString('default', { month: 'long' }) + ' ' + date.getFullYear();
|
|
5457
|
+
}
|
|
5458
|
+
function CalendarInput(props) {
|
|
5459
|
+
const [month, setMonth] = React.useState(getStartMonth);
|
|
5460
|
+
function moveMonth(delta) {
|
|
5461
|
+
setMonth((currMonth) => {
|
|
5462
|
+
const prevMonth = new Date(currMonth.getTime());
|
|
5463
|
+
prevMonth.setMonth(currMonth.getMonth() + delta);
|
|
5464
|
+
return prevMonth;
|
|
5465
|
+
});
|
|
5466
|
+
}
|
|
5467
|
+
const grid = React.useMemo(() => buildGrid(month, props.slots), [month, props.slots]);
|
|
5468
|
+
return (React__default["default"].createElement("div", null,
|
|
5469
|
+
React__default["default"].createElement(InputRow, null,
|
|
5470
|
+
React__default["default"].createElement("p", { style: { flex: 1 } }, getMonthString(month)),
|
|
5471
|
+
React__default["default"].createElement("p", null,
|
|
5472
|
+
React__default["default"].createElement(Button, { label: "Previous month", onClick: () => moveMonth(-1) }, "<"),
|
|
5473
|
+
React__default["default"].createElement(Button, { label: "Next month", onClick: () => moveMonth(1) }, ">"))),
|
|
5474
|
+
React__default["default"].createElement("table", { className: "medplum-calendar-table" },
|
|
5475
|
+
React__default["default"].createElement("thead", null,
|
|
5476
|
+
React__default["default"].createElement("tr", null,
|
|
5477
|
+
React__default["default"].createElement("th", null, "SUN"),
|
|
5478
|
+
React__default["default"].createElement("th", null, "MON"),
|
|
5479
|
+
React__default["default"].createElement("th", null, "TUE"),
|
|
5480
|
+
React__default["default"].createElement("th", null, "WED"),
|
|
5481
|
+
React__default["default"].createElement("th", null, "THU"),
|
|
5482
|
+
React__default["default"].createElement("th", null, "FRI"),
|
|
5483
|
+
React__default["default"].createElement("th", null, "SAT"))),
|
|
5484
|
+
React__default["default"].createElement("tbody", null, grid.map((week, weekIndex) => (React__default["default"].createElement("tr", { key: 'week-' + weekIndex }, week.map((day, dayIndex) => (React__default["default"].createElement("td", { key: 'day-' + dayIndex }, day && (React__default["default"].createElement("button", { disabled: !day.available, onClick: () => props.onClick(day.date) }, day.date.getDate()))))))))))));
|
|
5485
|
+
}
|
|
5486
|
+
function getStartMonth() {
|
|
5487
|
+
const result = new Date();
|
|
5488
|
+
result.setDate(1);
|
|
5489
|
+
result.setHours(0, 0, 0, 0);
|
|
5490
|
+
return result;
|
|
5491
|
+
}
|
|
5492
|
+
function buildGrid(startDate, slots) {
|
|
5493
|
+
const d = new Date(startDate.getFullYear(), startDate.getMonth());
|
|
5494
|
+
const grid = [];
|
|
5495
|
+
let row = [];
|
|
5496
|
+
// Fill leading empty days
|
|
5497
|
+
for (let i = 0; i < d.getDay(); i++) {
|
|
5498
|
+
row.push(undefined);
|
|
5499
|
+
}
|
|
5500
|
+
while (d.getMonth() === startDate.getMonth()) {
|
|
5501
|
+
row.push({
|
|
5502
|
+
date: new Date(d.getTime()),
|
|
5503
|
+
// available: isAvailable(d),
|
|
5504
|
+
available: isDayAvailable(d, slots),
|
|
5505
|
+
});
|
|
5506
|
+
if (d.getDay() === 6) {
|
|
5507
|
+
grid.push(row);
|
|
5508
|
+
row = [];
|
|
5509
|
+
}
|
|
5510
|
+
d.setDate(d.getDate() + 1);
|
|
5511
|
+
}
|
|
5512
|
+
// Fill trailing empty days
|
|
5513
|
+
if (d.getDay() !== 0) {
|
|
5514
|
+
for (let i = d.getDay(); i < 7; i++) {
|
|
5515
|
+
row.push(undefined);
|
|
5516
|
+
}
|
|
5517
|
+
grid.push(row);
|
|
5518
|
+
}
|
|
5519
|
+
return grid;
|
|
5520
|
+
}
|
|
5521
|
+
/**
|
|
5522
|
+
* Returns true if the given date is available for booking.
|
|
5523
|
+
* @param day The day to check.
|
|
5524
|
+
* @param slots The list of available slots.
|
|
5525
|
+
* @returns True if there are any available slots for the day.
|
|
5526
|
+
*/
|
|
5527
|
+
function isDayAvailable(day, slots) {
|
|
5528
|
+
// Note that slot start and end time may or may not be in UTC.
|
|
5529
|
+
for (const slot of slots) {
|
|
5530
|
+
const slotStart = new Date(slot.start);
|
|
5531
|
+
if (slotStart.getFullYear() === day.getFullYear() &&
|
|
5532
|
+
slotStart.getMonth() === day.getMonth() &&
|
|
5533
|
+
slotStart.getDate() === day.getDate()) {
|
|
5534
|
+
return true;
|
|
5535
|
+
}
|
|
5536
|
+
}
|
|
5537
|
+
return false;
|
|
5538
|
+
}
|
|
5539
|
+
|
|
5540
|
+
function Scheduler(props) {
|
|
5541
|
+
var _a;
|
|
5542
|
+
const medplum = useMedplum();
|
|
5543
|
+
const schedule = useResource(props.schedule);
|
|
5544
|
+
const [slots, setSlots] = React.useState();
|
|
5545
|
+
const slotsRef = React.useRef();
|
|
5546
|
+
slotsRef.current = slots;
|
|
5547
|
+
const [date, setDate] = React.useState();
|
|
5548
|
+
const [slot, setSlot] = React.useState();
|
|
5549
|
+
const [info, setInfo] = React.useState();
|
|
5550
|
+
const [form, setForm] = React.useState();
|
|
5551
|
+
React.useEffect(() => {
|
|
5552
|
+
if (schedule) {
|
|
5553
|
+
medplum.search('Slot', 'schedule=' + core.getReferenceString(schedule)).then((bundle) => {
|
|
5554
|
+
setSlots(bundle.entry.map((entry) => entry.resource));
|
|
5555
|
+
});
|
|
5556
|
+
}
|
|
5557
|
+
else {
|
|
5558
|
+
setSlots(undefined);
|
|
5559
|
+
}
|
|
5560
|
+
}, [medplum, schedule]);
|
|
5561
|
+
if (!schedule || !slots) {
|
|
5562
|
+
return null;
|
|
5563
|
+
}
|
|
5564
|
+
const actor = (_a = schedule.actor) === null || _a === void 0 ? void 0 : _a[0];
|
|
5565
|
+
return (React__default["default"].createElement("div", { className: "medplum-calendar-container", "data-testid": "scheduler" },
|
|
5566
|
+
React__default["default"].createElement("div", { className: "medplum-calendar-info-pane" },
|
|
5567
|
+
actor && React__default["default"].createElement(Avatar, { value: actor, size: "large" }),
|
|
5568
|
+
actor && (React__default["default"].createElement("h1", null,
|
|
5569
|
+
React__default["default"].createElement(ResourceName, { value: actor }))),
|
|
5570
|
+
React__default["default"].createElement("p", null, "1 hour"),
|
|
5571
|
+
date && React__default["default"].createElement("p", null, date.toLocaleDateString()),
|
|
5572
|
+
slot && React__default["default"].createElement("p", null, formatTime(new Date(slot.start)))),
|
|
5573
|
+
React__default["default"].createElement("div", { className: "medplum-calendar-selection-pane" },
|
|
5574
|
+
!date && (React__default["default"].createElement("div", null,
|
|
5575
|
+
React__default["default"].createElement("h3", null, "Select date"),
|
|
5576
|
+
React__default["default"].createElement(CalendarInput, { slots: slots, onClick: setDate }))),
|
|
5577
|
+
date && !slot && (React__default["default"].createElement("div", null,
|
|
5578
|
+
React__default["default"].createElement("h3", null, "Select time"),
|
|
5579
|
+
slots.map((s) => {
|
|
5580
|
+
const slotStart = new Date(s.start);
|
|
5581
|
+
return (slotStart.getTime() > date.getTime() &&
|
|
5582
|
+
slotStart.getTime() < date.getTime() + 24 * 3600 * 1000 && (React__default["default"].createElement("div", { key: s.id },
|
|
5583
|
+
React__default["default"].createElement(Button, { style: { width: 150 }, onClick: () => setSlot(s) }, formatTime(slotStart)))));
|
|
5584
|
+
}))),
|
|
5585
|
+
date && slot && !info && (React__default["default"].createElement("div", null,
|
|
5586
|
+
React__default["default"].createElement("h3", null, "Enter your info"),
|
|
5587
|
+
React__default["default"].createElement(FormSection, { title: "Name", htmlFor: "name" },
|
|
5588
|
+
React__default["default"].createElement(Input, { name: "name" })),
|
|
5589
|
+
React__default["default"].createElement(FormSection, { title: "Email", htmlFor: "email" },
|
|
5590
|
+
React__default["default"].createElement(Input, { name: "email" })),
|
|
5591
|
+
React__default["default"].createElement(Button, { primary: true, onClick: () => setInfo('info') }, "Next"))),
|
|
5592
|
+
date && slot && info && !form && (React__default["default"].createElement("div", null,
|
|
5593
|
+
React__default["default"].createElement("h3", null, "Custom questions"),
|
|
5594
|
+
React__default["default"].createElement(FormSection, { title: "Question 1", htmlFor: "q1" },
|
|
5595
|
+
React__default["default"].createElement(Input, { name: "q1" })),
|
|
5596
|
+
React__default["default"].createElement(FormSection, { title: "Question 2", htmlFor: "q2" },
|
|
5597
|
+
React__default["default"].createElement(Input, { name: "email" })),
|
|
5598
|
+
React__default["default"].createElement(FormSection, { title: "Question 3", htmlFor: "q3" },
|
|
5599
|
+
React__default["default"].createElement(Input, { name: "email" })),
|
|
5600
|
+
React__default["default"].createElement(Button, { primary: true, onClick: () => setForm('form') }, "Next"))),
|
|
5601
|
+
date && slot && info && form && (React__default["default"].createElement("div", null,
|
|
5602
|
+
React__default["default"].createElement("h3", null, "You're all set!"),
|
|
5603
|
+
React__default["default"].createElement("p", null, "Check your email for a calendar invite."))))));
|
|
5604
|
+
}
|
|
5605
|
+
function formatTime(date) {
|
|
5606
|
+
return date.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' });
|
|
5607
|
+
}
|
|
5608
|
+
|
|
5274
5609
|
function ServiceRequestTimeline(props) {
|
|
5275
5610
|
return (React__default["default"].createElement(ResourceTimeline, { value: props.serviceRequest, buildSearchRequests: (resource) => ({
|
|
5276
5611
|
resourceType: 'Bundle',
|
|
@@ -5318,62 +5653,6 @@
|
|
|
5318
5653
|
}) }));
|
|
5319
5654
|
}
|
|
5320
5655
|
|
|
5321
|
-
/**
|
|
5322
|
-
* Dynamically creates a script tag for the specified JavaScript file.
|
|
5323
|
-
* @param src The JavaScript file URL.
|
|
5324
|
-
*/
|
|
5325
|
-
function createScriptTag(src, onload) {
|
|
5326
|
-
const head = document.getElementsByTagName('head')[0];
|
|
5327
|
-
const script = document.createElement('script');
|
|
5328
|
-
script.async = true;
|
|
5329
|
-
script.src = src;
|
|
5330
|
-
script.onload = onload || null;
|
|
5331
|
-
head.appendChild(script);
|
|
5332
|
-
}
|
|
5333
|
-
|
|
5334
|
-
function GoogleButton(props) {
|
|
5335
|
-
const medplum = useMedplum();
|
|
5336
|
-
const { handleGoogleCredential } = props;
|
|
5337
|
-
const googleClientId = getGoogleClientId(props.googleClientId);
|
|
5338
|
-
const parentRef = React.useRef(null);
|
|
5339
|
-
const [scriptLoaded, setScriptLoaded] = React.useState(typeof google !== 'undefined');
|
|
5340
|
-
const [initialized, setInitialized] = React.useState(false);
|
|
5341
|
-
const [buttonRendered, setButtonRendered] = React.useState(false);
|
|
5342
|
-
React.useEffect(() => {
|
|
5343
|
-
if (typeof google === 'undefined') {
|
|
5344
|
-
createScriptTag('https://accounts.google.com/gsi/client', () => setScriptLoaded(true));
|
|
5345
|
-
return;
|
|
5346
|
-
}
|
|
5347
|
-
if (!initialized) {
|
|
5348
|
-
google.accounts.id.initialize({
|
|
5349
|
-
client_id: googleClientId,
|
|
5350
|
-
callback: handleGoogleCredential,
|
|
5351
|
-
});
|
|
5352
|
-
setInitialized(true);
|
|
5353
|
-
}
|
|
5354
|
-
if (parentRef.current && !buttonRendered) {
|
|
5355
|
-
google.accounts.id.renderButton(parentRef.current, {});
|
|
5356
|
-
setButtonRendered(true);
|
|
5357
|
-
}
|
|
5358
|
-
}, [medplum, googleClientId, initialized, scriptLoaded, parentRef, buttonRendered, handleGoogleCredential]);
|
|
5359
|
-
if (!googleClientId) {
|
|
5360
|
-
return null;
|
|
5361
|
-
}
|
|
5362
|
-
return React__default["default"].createElement("div", { ref: parentRef });
|
|
5363
|
-
}
|
|
5364
|
-
function getGoogleClientId(clientId) {
|
|
5365
|
-
var _a, _b;
|
|
5366
|
-
if (clientId) {
|
|
5367
|
-
return clientId;
|
|
5368
|
-
}
|
|
5369
|
-
const origin = window.location.protocol + '//' + window.location.host;
|
|
5370
|
-
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 : [];
|
|
5371
|
-
if (authorizedOrigins.includes(origin)) {
|
|
5372
|
-
return "921088377005-3j1sa10vr6hj86jgmdfh2l53v3mp7lfi.apps.googleusercontent.com";
|
|
5373
|
-
}
|
|
5374
|
-
return undefined;
|
|
5375
|
-
}
|
|
5376
|
-
|
|
5377
5656
|
function SignInForm(props) {
|
|
5378
5657
|
const medplum = useMedplum();
|
|
5379
5658
|
const [login, setLogin] = React.useState(undefined);
|
|
@@ -5415,6 +5694,7 @@
|
|
|
5415
5694
|
}
|
|
5416
5695
|
function AuthenticationForm(props) {
|
|
5417
5696
|
const medplum = useMedplum();
|
|
5697
|
+
const googleClientId = getGoogleClientId(props.googleClientId);
|
|
5418
5698
|
const [outcome, setOutcome] = React.useState();
|
|
5419
5699
|
const issues = getIssuesForExpression(outcome, undefined);
|
|
5420
5700
|
return (React__default["default"].createElement(Form, { style: { maxWidth: 400 }, onSubmit: (formData) => {
|
|
@@ -5435,6 +5715,21 @@
|
|
|
5435
5715
|
var _a, _b;
|
|
5436
5716
|
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));
|
|
5437
5717
|
}))),
|
|
5718
|
+
googleClientId && (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
5719
|
+
React__default["default"].createElement("div", { className: "medplum-signin-google-container" },
|
|
5720
|
+
React__default["default"].createElement(GoogleButton, { googleClientId: googleClientId, handleGoogleCredential: (response) => {
|
|
5721
|
+
medplum
|
|
5722
|
+
.startGoogleLogin({
|
|
5723
|
+
clientId: props.clientId,
|
|
5724
|
+
scope: props.scope,
|
|
5725
|
+
nonce: props.nonce,
|
|
5726
|
+
googleClientId: response.clientId,
|
|
5727
|
+
googleCredential: response.credential,
|
|
5728
|
+
})
|
|
5729
|
+
.then(props.handleAuthResponse)
|
|
5730
|
+
.catch(setOutcome);
|
|
5731
|
+
} })),
|
|
5732
|
+
React__default["default"].createElement("div", { className: "medplum-signin-separator" }, "or"))),
|
|
5438
5733
|
React__default["default"].createElement(FormSection, { title: "Email", htmlFor: "email", outcome: outcome },
|
|
5439
5734
|
React__default["default"].createElement(Input, { name: "email", type: "email", testid: "email", required: true, autoFocus: true, outcome: outcome })),
|
|
5440
5735
|
React__default["default"].createElement(FormSection, { title: "Password", htmlFor: "password", outcome: outcome },
|
|
@@ -5447,20 +5742,7 @@
|
|
|
5447
5742
|
React__default["default"].createElement("input", { type: "checkbox", id: "remember", name: "remember", value: "true" }),
|
|
5448
5743
|
React__default["default"].createElement("label", { htmlFor: "remember" }, "Remember me")),
|
|
5449
5744
|
React__default["default"].createElement("div", null,
|
|
5450
|
-
React__default["default"].createElement(Button, { type: "submit", testid: "submit" }, "Sign in")))
|
|
5451
|
-
React__default["default"].createElement("div", { className: "medplum-signin-google-container" },
|
|
5452
|
-
React__default["default"].createElement(GoogleButton, { googleClientId: props.googleClientId, handleGoogleCredential: (response) => {
|
|
5453
|
-
medplum
|
|
5454
|
-
.startGoogleLogin({
|
|
5455
|
-
clientId: props.clientId,
|
|
5456
|
-
scope: props.scope,
|
|
5457
|
-
nonce: props.nonce,
|
|
5458
|
-
googleClientId: response.clientId,
|
|
5459
|
-
googleCredential: response.credential,
|
|
5460
|
-
})
|
|
5461
|
-
.then(props.handleAuthResponse)
|
|
5462
|
-
.catch(setOutcome);
|
|
5463
|
-
} }))));
|
|
5745
|
+
React__default["default"].createElement(Button, { type: "submit", testid: "submit" }, "Sign in")))));
|
|
5464
5746
|
}
|
|
5465
5747
|
function ProfileForm(props) {
|
|
5466
5748
|
const medplum = useMedplum();
|
|
@@ -5585,6 +5867,7 @@
|
|
|
5585
5867
|
exports.RangeDisplay = RangeDisplay;
|
|
5586
5868
|
exports.RangeInput = RangeInput;
|
|
5587
5869
|
exports.ReferenceInput = ReferenceInput;
|
|
5870
|
+
exports.RegisterForm = RegisterForm;
|
|
5588
5871
|
exports.RequestGroupDisplay = RequestGroupDisplay;
|
|
5589
5872
|
exports.ResourceArrayDisplay = ResourceArrayDisplay;
|
|
5590
5873
|
exports.ResourceArrayInput = ResourceArrayInput;
|
|
@@ -5599,6 +5882,7 @@
|
|
|
5599
5882
|
exports.ResourcePropertyInput = ResourcePropertyInput;
|
|
5600
5883
|
exports.ResourceTable = ResourceTable;
|
|
5601
5884
|
exports.ResourceTimeline = ResourceTimeline;
|
|
5885
|
+
exports.Scheduler = Scheduler;
|
|
5602
5886
|
exports.Scrollable = Scrollable;
|
|
5603
5887
|
exports.SearchChangeEvent = SearchChangeEvent;
|
|
5604
5888
|
exports.SearchClickEvent = SearchClickEvent;
|
|
@@ -5642,11 +5926,13 @@
|
|
|
5642
5926
|
exports.deleteFilter = deleteFilter;
|
|
5643
5927
|
exports.formatRangeString = formatRangeString;
|
|
5644
5928
|
exports.getOpString = getOpString;
|
|
5929
|
+
exports.getRecaptcha = getRecaptcha;
|
|
5645
5930
|
exports.getSearchOperators = getSearchOperators;
|
|
5646
5931
|
exports.getSortField = getSortField;
|
|
5647
5932
|
exports.getTimeString = getTimeString;
|
|
5648
5933
|
exports.getValueAndType = getValueAndType;
|
|
5649
5934
|
exports.hasFilterOnField = hasFilterOnField;
|
|
5935
|
+
exports.initRecaptcha = initRecaptcha;
|
|
5650
5936
|
exports.isChoiceQuestion = isChoiceQuestion;
|
|
5651
5937
|
exports.isSortDescending = isSortDescending;
|
|
5652
5938
|
exports.movePage = movePage;
|