@oneblink/apps-react 6.10.0-beta.6 → 6.10.0-beta.8
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/components/calendar-bookings/CalendarBookingsCancelForm.d.ts +4 -0
- package/dist/components/calendar-bookings/CalendarBookingsCancelForm.js +28 -0
- package/dist/components/calendar-bookings/CalendarBookingsCancelForm.js.map +1 -0
- package/dist/components/calendar-bookings/CalendarBookingsContainer.d.ts +7 -0
- package/dist/components/calendar-bookings/CalendarBookingsContainer.js +34 -0
- package/dist/components/calendar-bookings/CalendarBookingsContainer.js.map +1 -0
- package/dist/components/calendar-bookings/CalendarBookingsForm.d.ts +7 -0
- package/dist/components/calendar-bookings/CalendarBookingsForm.js +131 -0
- package/dist/components/calendar-bookings/CalendarBookingsForm.js.map +1 -0
- package/dist/components/calendar-bookings/CalendarBookingsProvider.d.ts +13 -0
- package/dist/components/calendar-bookings/CalendarBookingsProvider.js +64 -0
- package/dist/components/calendar-bookings/CalendarBookingsProvider.js.map +1 -0
- package/dist/components/calendar-bookings/CalendarBookingsReschedulingForm.d.ts +4 -0
- package/dist/components/calendar-bookings/CalendarBookingsReschedulingForm.js +37 -0
- package/dist/components/calendar-bookings/CalendarBookingsReschedulingForm.js.map +1 -0
- package/dist/components/calendar-bookings/ErrorModal.d.ts +10 -0
- package/dist/components/calendar-bookings/ErrorModal.js +48 -0
- package/dist/components/calendar-bookings/ErrorModal.js.map +1 -0
- package/dist/components/mfa/MfaDialog.js +1 -1
- package/dist/components/mfa/MfaDialog.js.map +1 -1
- package/dist/components/mfa/MultiFactorAuthentication.d.ts +4 -4
- package/dist/components/mfa/MultiFactorAuthentication.js +10 -10
- package/dist/components/mfa/MultiFactorAuthentication.js.map +1 -1
- package/dist/hooks/{useAppUserMfa.d.ts → useMfa.d.ts} +15 -15
- package/dist/hooks/{useAppUserMfa.js → useMfa.js} +26 -26
- package/dist/hooks/useMfa.js.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/dist/components/LoadingButton.d.ts +0 -7
- package/dist/components/LoadingButton.js +0 -12
- package/dist/components/LoadingButton.js.map +0 -1
- package/dist/hooks/useAppUserMfa.js.map +0 -1
@@ -0,0 +1,28 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { NylasScheduling } from '@nylas/react';
|
3
|
+
import { schedulingService } from '@oneblink/apps';
|
4
|
+
import ErrorMessage from '../messages/ErrorMessage';
|
5
|
+
import CalendarBookingsContainer from './CalendarBookingsContainer';
|
6
|
+
import useCalendarBookings from './CalendarBookingsProvider';
|
7
|
+
function NylasCancelForm({ sessionId, bookingRef, }) {
|
8
|
+
const { setBookingError, themeConfig } = useCalendarBookings();
|
9
|
+
if (!bookingRef) {
|
10
|
+
return (React.createElement(ErrorMessage, { title: "Error Retrieving Data", gutterTop: true },
|
11
|
+
React.createElement("span", { className: "cypress-booking-ref-not-found-error-message" }, "Could not find a calendar booking to cancel")));
|
12
|
+
}
|
13
|
+
return (React.createElement("div", { className: "ob-scheduling-booking-form" },
|
14
|
+
React.createElement(NylasScheduling, { sessionId: sessionId, eventOverrides: {
|
15
|
+
bookedEventInfo: async (event) => {
|
16
|
+
var _a;
|
17
|
+
event.preventDefault();
|
18
|
+
if (event.detail.error) {
|
19
|
+
setBookingError((_a = event.detail.error.message) !== null && _a !== void 0 ? _a : 'Calendar Booking Error');
|
20
|
+
}
|
21
|
+
},
|
22
|
+
}, themeConfig: themeConfig, cancelBookingRef: bookingRef, enableUserFeedback: false, nylasBranding: false })));
|
23
|
+
}
|
24
|
+
function CalendarBookingsCancelForm() {
|
25
|
+
return (React.createElement(CalendarBookingsContainer, { fetchConfiguration: schedulingService.createNylasExistingBookingSession }, (props) => React.createElement(NylasCancelForm, { ...props })));
|
26
|
+
}
|
27
|
+
export default React.memo(CalendarBookingsCancelForm);
|
28
|
+
//# sourceMappingURL=CalendarBookingsCancelForm.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"CalendarBookingsCancelForm.js","sourceRoot":"","sources":["../../../src/components/calendar-bookings/CalendarBookingsCancelForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAClD,OAAO,YAAY,MAAM,0BAA0B,CAAA;AACnD,OAAO,yBAAyB,MAAM,6BAA6B,CAAA;AACnE,OAAO,mBAAmB,MAAM,4BAA4B,CAAA;AAE5D,SAAS,eAAe,CAAC,EACvB,SAAS,EACT,UAAU,GAKX;IACC,MAAM,EAAE,eAAe,EAAE,WAAW,EAAE,GAAG,mBAAmB,EAAE,CAAA;IAE9D,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,CACL,oBAAC,YAAY,IAAC,KAAK,EAAC,uBAAuB,EAAC,SAAS;YACnD,8BAAM,SAAS,EAAC,6CAA6C,kDAEtD,CACM,CAChB,CAAA;IACH,CAAC;IAED,OAAO,CACL,6BAAK,SAAS,EAAC,4BAA4B;QACzC,oBAAC,eAAe,IACd,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE;gBACd,eAAe,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;;oBAC/B,KAAK,CAAC,cAAc,EAAE,CAAA;oBACtB,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;wBACvB,eAAe,CACb,MAAA,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,mCAAI,wBAAwB,CACvD,CAAA;oBACH,CAAC;gBACH,CAAC;aACF,EACD,WAAW,EAAE,WAAW,EACxB,gBAAgB,EAAE,UAAU,EAC5B,kBAAkB,EAAE,KAAK,EACzB,aAAa,EAAE,KAAK,GACpB,CACE,CACP,CAAA;AACH,CAAC;AAED,SAAS,0BAA0B;IACjC,OAAO,CACL,oBAAC,yBAAyB,IACxB,kBAAkB,EAAE,iBAAiB,CAAC,iCAAiC,IAEtE,CAAC,KAAK,EAAE,EAAE,CAAC,oBAAC,eAAe,OAAK,KAAK,GAAI,CAChB,CAC7B,CAAA;AACH,CAAC;AAED,eAAe,KAAK,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAA","sourcesContent":["import React from 'react'\nimport { NylasScheduling } from '@nylas/react'\nimport { schedulingService } from '@oneblink/apps'\nimport ErrorMessage from '../messages/ErrorMessage'\nimport CalendarBookingsContainer from './CalendarBookingsContainer'\nimport useCalendarBookings from './CalendarBookingsProvider'\n\nfunction NylasCancelForm({\n sessionId,\n bookingRef,\n}: Awaited<\n ReturnType<typeof schedulingService.createNylasExistingBookingSession>\n> & {\n submissionId: string\n}) {\n const { setBookingError, themeConfig } = useCalendarBookings()\n\n if (!bookingRef) {\n return (\n <ErrorMessage title=\"Error Retrieving Data\" gutterTop>\n <span className=\"cypress-booking-ref-not-found-error-message\">\n Could not find a calendar booking to cancel\n </span>\n </ErrorMessage>\n )\n }\n\n return (\n <div className=\"ob-scheduling-booking-form\">\n <NylasScheduling\n sessionId={sessionId}\n eventOverrides={{\n bookedEventInfo: async (event) => {\n event.preventDefault()\n if (event.detail.error) {\n setBookingError(\n event.detail.error.message ?? 'Calendar Booking Error',\n )\n }\n },\n }}\n themeConfig={themeConfig}\n cancelBookingRef={bookingRef}\n enableUserFeedback={false}\n nylasBranding={false}\n />\n </div>\n )\n}\n\nfunction CalendarBookingsCancelForm() {\n return (\n <CalendarBookingsContainer\n fetchConfiguration={schedulingService.createNylasExistingBookingSession}\n >\n {(props) => <NylasCancelForm {...props} />}\n </CalendarBookingsContainer>\n )\n}\n\nexport default React.memo(CalendarBookingsCancelForm)\n"]}
|
@@ -0,0 +1,7 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
export default function CalendarBookingsContainer<T>({ fetchConfiguration, children, }: {
|
3
|
+
fetchConfiguration: (submissionId: string, abortSignal: AbortSignal) => Promise<T>;
|
4
|
+
children: (renderProps: {
|
5
|
+
submissionId: string;
|
6
|
+
} & T) => React.ReactNode;
|
7
|
+
}): React.JSX.Element;
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import useQuery from '../../hooks/useQuery';
|
3
|
+
import useLoadDataState from '../../hooks/useLoadDataState';
|
4
|
+
import ErrorMessage from '../messages/ErrorMessage';
|
5
|
+
import { CalendarBookingsProvider } from './CalendarBookingsProvider';
|
6
|
+
import OnLoading from '../renderer/OnLoading';
|
7
|
+
import ErrorModal from './ErrorModal';
|
8
|
+
function CalendarBookingLoader({ submissionId, fetchConfiguration, children, }) {
|
9
|
+
const [nylasSchedulingState, refreshNylasState] = useLoadDataState(React.useCallback(async (abortSignal) => {
|
10
|
+
return await fetchConfiguration(submissionId, abortSignal);
|
11
|
+
}, [fetchConfiguration, submissionId]));
|
12
|
+
if (nylasSchedulingState.status === 'LOADING') {
|
13
|
+
return (React.createElement("div", { className: "has-margin-top-1" },
|
14
|
+
React.createElement("div", { className: "cypress-loading has-text-centered" },
|
15
|
+
React.createElement(OnLoading, { className: "has-text-centered" }))));
|
16
|
+
}
|
17
|
+
if (nylasSchedulingState.status === 'ERROR') {
|
18
|
+
return (React.createElement(ErrorModal, { error: nylasSchedulingState.error, onClose: refreshNylasState }));
|
19
|
+
}
|
20
|
+
return (React.createElement(CalendarBookingsProvider, { refreshNylasState: refreshNylasState }, children({
|
21
|
+
...nylasSchedulingState.result,
|
22
|
+
submissionId,
|
23
|
+
})));
|
24
|
+
}
|
25
|
+
export default function CalendarBookingsContainer({ fetchConfiguration, children, }) {
|
26
|
+
const { submissionId: submissionIdQs } = useQuery();
|
27
|
+
const submissionId = React.useMemo(() => (typeof submissionIdQs === 'string' ? submissionIdQs : undefined), [submissionIdQs]);
|
28
|
+
if (!submissionId) {
|
29
|
+
return (React.createElement(ErrorMessage, { title: "Missing Configuration", gutterTop: true },
|
30
|
+
React.createElement("span", { className: "cypress-scheduling-booking-form-invalid-querystring ob-scheduling-booking-form__invalid-querystring-message" }, "It seems you have navigated here incorrectly. Please go back.")));
|
31
|
+
}
|
32
|
+
return (React.createElement(CalendarBookingLoader, { fetchConfiguration: fetchConfiguration, submissionId: submissionId }, children));
|
33
|
+
}
|
34
|
+
//# sourceMappingURL=CalendarBookingsContainer.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"CalendarBookingsContainer.js","sourceRoot":"","sources":["../../../src/components/calendar-bookings/CalendarBookingsContainer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,QAAQ,MAAM,sBAAsB,CAAA;AAC3C,OAAO,gBAAgB,MAAM,8BAA8B,CAAA;AAC3D,OAAO,YAAY,MAAM,0BAA0B,CAAA;AACnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,SAAS,MAAM,uBAAuB,CAAA;AAC7C,OAAO,UAAU,MAAM,cAAc,CAAA;AAOrC,SAAS,qBAAqB,CAAI,EAChC,YAAY,EACZ,kBAAkB,EAClB,QAAQ,GAKT;IACC,MAAM,CAAC,oBAAoB,EAAE,iBAAiB,CAAC,GAAG,gBAAgB,CAChE,KAAK,CAAC,WAAW,CACf,KAAK,EAAE,WAAW,EAAE,EAAE;QACpB,OAAO,MAAM,kBAAkB,CAAC,YAAY,EAAE,WAAW,CAAC,CAAA;IAC5D,CAAC,EACD,CAAC,kBAAkB,EAAE,YAAY,CAAC,CACnC,CACF,CAAA;IAED,IAAI,oBAAoB,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC9C,OAAO,CACL,6BAAK,SAAS,EAAC,kBAAkB;YAC/B,6BAAK,SAAS,EAAC,mCAAmC;gBAChD,oBAAC,SAAS,IAAC,SAAS,EAAC,mBAAmB,GAAG,CACvC,CACF,CACP,CAAA;IACH,CAAC;IAED,IAAI,oBAAoB,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QAC5C,OAAO,CACL,oBAAC,UAAU,IACT,KAAK,EAAE,oBAAoB,CAAC,KAAK,EACjC,OAAO,EAAE,iBAAiB,GAC1B,CACH,CAAA;IACH,CAAC;IAED,OAAO,CACL,oBAAC,wBAAwB,IAAC,iBAAiB,EAAE,iBAAiB,IAC3D,QAAQ,CAAC;QACR,GAAG,oBAAoB,CAAC,MAAM;QAC9B,YAAY;KACb,CAAC,CACuB,CAC5B,CAAA;AACH,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAAI,EACnD,kBAAkB,EAClB,QAAQ,GAOT;IACC,MAAM,EAAE,YAAY,EAAE,cAAc,EAAE,GAAG,QAAQ,EAAE,CAAA;IAEnD,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAChC,GAAG,EAAE,CAAC,CAAC,OAAO,cAAc,KAAK,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,EACvE,CAAC,cAAc,CAAC,CACjB,CAAA;IAED,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,CACL,oBAAC,YAAY,IAAC,KAAK,EAAC,uBAAuB,EAAC,SAAS;YACnD,8BAAM,SAAS,EAAC,6GAA6G,oEAEtH,CACM,CAChB,CAAA;IACH,CAAC;IAED,OAAO,CACL,oBAAC,qBAAqB,IACpB,kBAAkB,EAAE,kBAAkB,EACtC,YAAY,EAAE,YAAY,IAEzB,QAAQ,CACa,CACzB,CAAA;AACH,CAAC","sourcesContent":["import React from 'react'\nimport useQuery from '../../hooks/useQuery'\nimport useLoadDataState from '../../hooks/useLoadDataState'\nimport ErrorMessage from '../messages/ErrorMessage'\nimport { CalendarBookingsProvider } from './CalendarBookingsProvider'\nimport OnLoading from '../renderer/OnLoading'\nimport ErrorModal from './ErrorModal'\n\ntype FetchConfiguration<T> = (\n submissionId: string,\n abortSignal: AbortSignal,\n) => Promise<T>\n\nfunction CalendarBookingLoader<T>({\n submissionId,\n fetchConfiguration,\n children,\n}: {\n submissionId: string\n fetchConfiguration: FetchConfiguration<T>\n children: (renderProps: { submissionId: string } & T) => React.ReactNode\n}) {\n const [nylasSchedulingState, refreshNylasState] = useLoadDataState<T>(\n React.useCallback(\n async (abortSignal) => {\n return await fetchConfiguration(submissionId, abortSignal)\n },\n [fetchConfiguration, submissionId],\n ),\n )\n\n if (nylasSchedulingState.status === 'LOADING') {\n return (\n <div className=\"has-margin-top-1\">\n <div className=\"cypress-loading has-text-centered\">\n <OnLoading className=\"has-text-centered\" />\n </div>\n </div>\n )\n }\n\n if (nylasSchedulingState.status === 'ERROR') {\n return (\n <ErrorModal\n error={nylasSchedulingState.error}\n onClose={refreshNylasState}\n />\n )\n }\n\n return (\n <CalendarBookingsProvider refreshNylasState={refreshNylasState}>\n {children({\n ...nylasSchedulingState.result,\n submissionId,\n })}\n </CalendarBookingsProvider>\n )\n}\n\nexport default function CalendarBookingsContainer<T>({\n fetchConfiguration,\n children,\n}: {\n fetchConfiguration: (\n submissionId: string,\n abortSignal: AbortSignal,\n ) => Promise<T>\n children: (renderProps: { submissionId: string } & T) => React.ReactNode\n}) {\n const { submissionId: submissionIdQs } = useQuery()\n\n const submissionId = React.useMemo(\n () => (typeof submissionIdQs === 'string' ? submissionIdQs : undefined),\n [submissionIdQs],\n )\n\n if (!submissionId) {\n return (\n <ErrorMessage title=\"Missing Configuration\" gutterTop>\n <span className=\"cypress-scheduling-booking-form-invalid-querystring ob-scheduling-booking-form__invalid-querystring-message\">\n It seems you have navigated here incorrectly. Please go back.\n </span>\n </ErrorMessage>\n )\n }\n\n return (\n <CalendarBookingLoader\n fetchConfiguration={fetchConfiguration}\n submissionId={submissionId}\n >\n {children}\n </CalendarBookingLoader>\n )\n}\n"]}
|
@@ -0,0 +1,7 @@
|
|
1
|
+
import * as React from 'react';
|
2
|
+
import { submissionService } from '@oneblink/apps';
|
3
|
+
declare function CalendarBookingsForm({ onDone, }: {
|
4
|
+
onDone: (formSubmissionResult: submissionService.FormSubmissionResult) => Promise<void>;
|
5
|
+
}): React.JSX.Element;
|
6
|
+
declare const _default: React.MemoExoticComponent<typeof CalendarBookingsForm>;
|
7
|
+
export default _default;
|
@@ -0,0 +1,131 @@
|
|
1
|
+
import * as React from 'react';
|
2
|
+
import { NylasScheduling } from '@nylas/react';
|
3
|
+
import { Collapse, Fade } from '@mui/material';
|
4
|
+
import { schedulingService, } from '@oneblink/apps';
|
5
|
+
import clsx from 'clsx';
|
6
|
+
import { Receipt } from '../receipts';
|
7
|
+
import ErrorModal from './ErrorModal';
|
8
|
+
import OnLoading from '../renderer/OnLoading';
|
9
|
+
import CalendarBookingsContainer from './CalendarBookingsContainer';
|
10
|
+
import useCalendarBookings from './CalendarBookingsProvider';
|
11
|
+
function NylasBookingForm({ submissionId, name, email, configurationId, sessionId, onBookingConfirmed, onDone, }) {
|
12
|
+
const { setBookingError, onTimeSlotConfirmed } = useCalendarBookings();
|
13
|
+
const [{ formSubmissionResult, isRunningPostSubmissionAction, postSubmissionError, isConfirmingBooking, confirmingBookingError, }, setPostSubmissionState,] = React.useState({
|
14
|
+
formSubmissionResult: null,
|
15
|
+
isRunningPostSubmissionAction: false,
|
16
|
+
postSubmissionError: null,
|
17
|
+
isConfirmingBooking: false,
|
18
|
+
confirmingBookingError: null,
|
19
|
+
});
|
20
|
+
const clearPostSubmissionError = React.useCallback(() => {
|
21
|
+
setPostSubmissionState((currentState) => ({
|
22
|
+
...currentState,
|
23
|
+
postSubmissionError: null,
|
24
|
+
}));
|
25
|
+
}, []);
|
26
|
+
const clearConfirmingBookingError = React.useCallback(() => {
|
27
|
+
setPostSubmissionState((currentState) => ({
|
28
|
+
...currentState,
|
29
|
+
confirmingBookingError: null,
|
30
|
+
}));
|
31
|
+
}, []);
|
32
|
+
const executePostSubmissionAction = React.useCallback(async (formSubmissionResult) => {
|
33
|
+
setPostSubmissionState((currentState) => ({
|
34
|
+
...currentState,
|
35
|
+
formSubmissionResult,
|
36
|
+
isRunningPostSubmissionAction: true,
|
37
|
+
postSubmissionError: null,
|
38
|
+
}));
|
39
|
+
try {
|
40
|
+
await onDone({
|
41
|
+
...formSubmissionResult,
|
42
|
+
scheduling: null,
|
43
|
+
});
|
44
|
+
}
|
45
|
+
catch (error) {
|
46
|
+
console.warn('Error while running post submission action', error);
|
47
|
+
setPostSubmissionState((currentState) => ({
|
48
|
+
...currentState,
|
49
|
+
formSubmissionResult,
|
50
|
+
isRunningPostSubmissionAction: false,
|
51
|
+
postSubmissionError: error,
|
52
|
+
}));
|
53
|
+
}
|
54
|
+
}, [onDone]);
|
55
|
+
const handleConfirmedBooking = React.useCallback(async () => {
|
56
|
+
setPostSubmissionState((currentState) => ({
|
57
|
+
...currentState,
|
58
|
+
isConfirmingBooking: true,
|
59
|
+
confirmingBookingError: null,
|
60
|
+
}));
|
61
|
+
try {
|
62
|
+
const formSubmissionResult = await onBookingConfirmed();
|
63
|
+
setPostSubmissionState((currentState) => ({
|
64
|
+
...currentState,
|
65
|
+
formSubmissionResult,
|
66
|
+
}));
|
67
|
+
if (formSubmissionResult.payment) {
|
68
|
+
setTimeout(async () => {
|
69
|
+
executePostSubmissionAction(formSubmissionResult);
|
70
|
+
}, 2000);
|
71
|
+
}
|
72
|
+
else {
|
73
|
+
setPostSubmissionState((currentState) => ({
|
74
|
+
...currentState,
|
75
|
+
isConfirmingBooking: false,
|
76
|
+
formSubmissionResult,
|
77
|
+
}));
|
78
|
+
}
|
79
|
+
}
|
80
|
+
catch (error) {
|
81
|
+
console.warn('Error while handling confirmed booking', error);
|
82
|
+
setPostSubmissionState((currentState) => ({
|
83
|
+
...currentState,
|
84
|
+
isConfirmingBooking: false,
|
85
|
+
confirmingBookingError: error,
|
86
|
+
}));
|
87
|
+
}
|
88
|
+
}, [onBookingConfirmed, executePostSubmissionAction]);
|
89
|
+
return (React.createElement(React.Fragment, null,
|
90
|
+
React.createElement(Collapse, { in: isConfirmingBooking },
|
91
|
+
React.createElement("div", { className: "has-margin-top-1" },
|
92
|
+
React.createElement("div", { className: "cypress-loading has-text-centered" },
|
93
|
+
React.createElement(OnLoading, { className: "has-text-centered" }),
|
94
|
+
React.createElement(Fade, { in: !!(formSubmissionResult === null || formSubmissionResult === void 0 ? void 0 : formSubmissionResult.payment) },
|
95
|
+
React.createElement("span", null, "Redirecting to payment"))))),
|
96
|
+
React.createElement("div", { className: "ob-scheduling-booking-form" },
|
97
|
+
!(formSubmissionResult === null || formSubmissionResult === void 0 ? void 0 : formSubmissionResult.payment) && (React.createElement(NylasScheduling, { eventOverrides: {
|
98
|
+
timeslotConfirmed: onTimeSlotConfirmed,
|
99
|
+
bookedEventInfo: async (event) => {
|
100
|
+
var _a;
|
101
|
+
event.preventDefault();
|
102
|
+
if (event.detail.error) {
|
103
|
+
setBookingError((_a = event.detail.error.message) !== null && _a !== void 0 ? _a : 'Calendar Booking Error');
|
104
|
+
}
|
105
|
+
else {
|
106
|
+
await handleConfirmedBooking();
|
107
|
+
}
|
108
|
+
},
|
109
|
+
}, bookingInfo: {
|
110
|
+
primaryParticipant: {
|
111
|
+
name: name !== null && name !== void 0 ? name : '',
|
112
|
+
email: email !== null && email !== void 0 ? email : '',
|
113
|
+
},
|
114
|
+
additionalFields: {
|
115
|
+
submissionId: {
|
116
|
+
value: submissionId,
|
117
|
+
type: 'text',
|
118
|
+
},
|
119
|
+
},
|
120
|
+
}, enableUserFeedback: false, configurationId: configurationId, sessionId: sessionId, nylasBranding: false })),
|
121
|
+
formSubmissionResult && !formSubmissionResult.payment && (React.createElement(Receipt, { className: "ob-scheduling-receipt", containerClassName: "ob-scheduling-receipt__container" },
|
122
|
+
React.createElement("div", { className: "buttons" },
|
123
|
+
React.createElement("button", { type: "button", className: clsx('is-primary button ob-button ob-scheduling-receipt__button ob-scheduling-receipt__okay-button cypress-scheduling-receipt-okay-button', { 'is-loading': isRunningPostSubmissionAction }), disabled: isRunningPostSubmissionAction, onClick: () => executePostSubmissionAction(formSubmissionResult) }, "Done")))),
|
124
|
+
React.createElement(ErrorModal, { error: postSubmissionError, onClose: clearPostSubmissionError }),
|
125
|
+
React.createElement(ErrorModal, { error: confirmingBookingError, onClose: clearConfirmingBookingError }))));
|
126
|
+
}
|
127
|
+
function CalendarBookingsForm({ onDone, }) {
|
128
|
+
return (React.createElement(CalendarBookingsContainer, { fetchConfiguration: schedulingService.createNylasNewBookingSession }, (props) => React.createElement(NylasBookingForm, { ...props, onDone: onDone })));
|
129
|
+
}
|
130
|
+
export default React.memo(CalendarBookingsForm);
|
131
|
+
//# sourceMappingURL=CalendarBookingsForm.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"CalendarBookingsForm.js","sourceRoot":"","sources":["../../../src/components/calendar-bookings/CalendarBookingsForm.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport { NylasScheduling } from '@nylas/react'\nimport { Collapse, Fade } from '@mui/material'\nimport {\n schedulingService,\n submissionService,\n OneBlinkAppsError,\n} from '@oneblink/apps'\nimport clsx from 'clsx'\nimport { Receipt } from '../receipts'\nimport ErrorModal from './ErrorModal'\nimport OnLoading from '../renderer/OnLoading'\nimport CalendarBookingsContainer from './CalendarBookingsContainer'\nimport useCalendarBookings from './CalendarBookingsProvider'\n\nfunction NylasBookingForm({\n submissionId,\n name,\n email,\n configurationId,\n sessionId,\n onBookingConfirmed,\n onDone,\n}: Awaited<\n ReturnType<typeof schedulingService.createNylasNewBookingSession>\n> & {\n submissionId: string\n onDone: (\n formSubmissionResult: submissionService.FormSubmissionResult,\n ) => Promise<void>\n}) {\n const { setBookingError, onTimeSlotConfirmed } = useCalendarBookings()\n\n const [\n {\n formSubmissionResult,\n isRunningPostSubmissionAction,\n postSubmissionError,\n isConfirmingBooking,\n confirmingBookingError,\n },\n setPostSubmissionState,\n ] = React.useState<{\n formSubmissionResult: submissionService.FormSubmissionResult | null\n isRunningPostSubmissionAction: boolean\n postSubmissionError: OneBlinkAppsError | null\n isConfirmingBooking: boolean\n confirmingBookingError: OneBlinkAppsError | null\n }>({\n formSubmissionResult: null,\n isRunningPostSubmissionAction: false,\n postSubmissionError: null,\n isConfirmingBooking: false,\n confirmingBookingError: null,\n })\n const clearPostSubmissionError = React.useCallback(() => {\n setPostSubmissionState((currentState) => ({\n ...currentState,\n postSubmissionError: null,\n }))\n }, [])\n const clearConfirmingBookingError = React.useCallback(() => {\n setPostSubmissionState((currentState) => ({\n ...currentState,\n confirmingBookingError: null,\n }))\n }, [])\n\n const executePostSubmissionAction = React.useCallback(\n async (formSubmissionResult: submissionService.FormSubmissionResult) => {\n setPostSubmissionState((currentState) => ({\n ...currentState,\n formSubmissionResult,\n isRunningPostSubmissionAction: true,\n postSubmissionError: null,\n }))\n\n try {\n await onDone({\n ...formSubmissionResult,\n scheduling: null,\n })\n } catch (error) {\n console.warn('Error while running post submission action', error)\n setPostSubmissionState((currentState) => ({\n ...currentState,\n formSubmissionResult,\n isRunningPostSubmissionAction: false,\n postSubmissionError: error as OneBlinkAppsError,\n }))\n }\n },\n [onDone],\n )\n\n const handleConfirmedBooking = React.useCallback(async () => {\n setPostSubmissionState((currentState) => ({\n ...currentState,\n isConfirmingBooking: true,\n confirmingBookingError: null,\n }))\n\n try {\n const formSubmissionResult = await onBookingConfirmed()\n setPostSubmissionState((currentState) => ({\n ...currentState,\n formSubmissionResult,\n }))\n if (formSubmissionResult.payment) {\n setTimeout(async () => {\n executePostSubmissionAction(formSubmissionResult)\n }, 2000)\n } else {\n setPostSubmissionState((currentState) => ({\n ...currentState,\n isConfirmingBooking: false,\n formSubmissionResult,\n }))\n }\n } catch (error) {\n console.warn('Error while handling confirmed booking', error)\n setPostSubmissionState((currentState) => ({\n ...currentState,\n isConfirmingBooking: false,\n confirmingBookingError: error as OneBlinkAppsError,\n }))\n }\n }, [onBookingConfirmed, executePostSubmissionAction])\n\n return (\n <>\n <Collapse in={isConfirmingBooking}>\n <div className=\"has-margin-top-1\">\n <div className=\"cypress-loading has-text-centered\">\n <OnLoading className=\"has-text-centered\" />\n <Fade in={!!formSubmissionResult?.payment}>\n <span>Redirecting to payment</span>\n </Fade>\n </div>\n </div>\n </Collapse>\n\n <div className=\"ob-scheduling-booking-form\">\n {!formSubmissionResult?.payment && (\n <NylasScheduling\n eventOverrides={{\n timeslotConfirmed: onTimeSlotConfirmed,\n bookedEventInfo: async (event) => {\n event.preventDefault()\n\n if (event.detail.error) {\n setBookingError(\n event.detail.error.message ?? 'Calendar Booking Error',\n )\n } else {\n await handleConfirmedBooking()\n }\n },\n }}\n bookingInfo={{\n primaryParticipant: {\n name: name ?? '',\n email: email ?? '',\n },\n additionalFields: {\n submissionId: {\n value: submissionId,\n type: 'text',\n },\n },\n }}\n enableUserFeedback={false}\n configurationId={configurationId}\n sessionId={sessionId}\n nylasBranding={false}\n />\n )}\n\n {formSubmissionResult && !formSubmissionResult.payment && (\n <Receipt\n className=\"ob-scheduling-receipt\"\n containerClassName=\"ob-scheduling-receipt__container\"\n >\n <div className=\"buttons\">\n <button\n type=\"button\"\n className={clsx(\n 'is-primary button ob-button ob-scheduling-receipt__button ob-scheduling-receipt__okay-button cypress-scheduling-receipt-okay-button',\n { 'is-loading': isRunningPostSubmissionAction },\n )}\n disabled={isRunningPostSubmissionAction}\n onClick={() =>\n executePostSubmissionAction(formSubmissionResult)\n }\n >\n Done\n </button>\n </div>\n </Receipt>\n )}\n\n <ErrorModal\n error={postSubmissionError}\n onClose={clearPostSubmissionError}\n />\n\n <ErrorModal\n error={confirmingBookingError}\n onClose={clearConfirmingBookingError}\n />\n </div>\n </>\n )\n}\n\nfunction CalendarBookingsForm({\n onDone,\n}: {\n onDone: (\n formSubmissionResult: submissionService.FormSubmissionResult,\n ) => Promise<void>\n}) {\n return (\n <CalendarBookingsContainer\n fetchConfiguration={schedulingService.createNylasNewBookingSession}\n >\n {(props) => <NylasBookingForm {...props} onDone={onDone} />}\n </CalendarBookingsContainer>\n )\n}\n\nexport default React.memo(CalendarBookingsForm)\n"]}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import React, { ComponentProps } from 'react';
|
2
|
+
import { NylasScheduling } from '@nylas/react';
|
3
|
+
type CalendarBookingsContextProps = {
|
4
|
+
setBookingError: (errorString: string) => void;
|
5
|
+
onTimeSlotConfirmed: () => Promise<void>;
|
6
|
+
themeConfig: ComponentProps<typeof NylasScheduling>['themeConfig'];
|
7
|
+
};
|
8
|
+
export declare function CalendarBookingsProvider({ children, refreshNylasState, }: {
|
9
|
+
children: React.ReactNode;
|
10
|
+
refreshNylasState: () => void;
|
11
|
+
}): React.JSX.Element;
|
12
|
+
export default function useCalendarBookings(): CalendarBookingsContextProps;
|
13
|
+
export {};
|
@@ -0,0 +1,64 @@
|
|
1
|
+
import React, { useContext, createContext, useMemo, useCallback, } from 'react';
|
2
|
+
import { Snackbar, Alert, Button, useTheme } from '@mui/material';
|
3
|
+
import Color from 'color';
|
4
|
+
import useBooleanState from '../../hooks/useBooleanState';
|
5
|
+
const CalendarBookingsContext = createContext({
|
6
|
+
setBookingError: () => { },
|
7
|
+
onTimeSlotConfirmed: async () => { },
|
8
|
+
themeConfig: {},
|
9
|
+
});
|
10
|
+
export function CalendarBookingsProvider({ children, refreshNylasState, }) {
|
11
|
+
const [isShowingErrorSnack, showErrorSnack, hideErrorSnack] = useBooleanState(false);
|
12
|
+
const [bookingError, _setBookingError] = React.useState();
|
13
|
+
const setBookingError = useCallback((errorString) => {
|
14
|
+
_setBookingError(errorString);
|
15
|
+
showErrorSnack();
|
16
|
+
}, [showErrorSnack]);
|
17
|
+
/**
|
18
|
+
* The alternative here is to set the submissionId field to multi-line-text
|
19
|
+
* input then use the below css It works because the booking form only has 1
|
20
|
+
* multi-line-text input Unfortunately chrome won't allow :nth-child selectors
|
21
|
+
* on part() selectors ::part(nbf__textarea-component) { display: none; }
|
22
|
+
*/
|
23
|
+
const onTimeSlotConfirmed = React.useCallback(async () => {
|
24
|
+
setTimeout(() => {
|
25
|
+
var _a, _b, _c, _d;
|
26
|
+
const submissionIdInputComponent = (_d = (_c = (_b = (_a = document
|
27
|
+
.querySelector('nylas-scheduling')) === null || _a === void 0 ? void 0 : _a.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('nylas-booking-form')) === null || _c === void 0 ? void 0 : _c.shadowRoot) === null || _d === void 0 ? void 0 : _d.querySelector('#submissionId');
|
28
|
+
if (submissionIdInputComponent) {
|
29
|
+
submissionIdInputComponent.style.display = 'none';
|
30
|
+
}
|
31
|
+
}, 50);
|
32
|
+
}, []);
|
33
|
+
const theme = useTheme();
|
34
|
+
const colorIsLight = useMemo(() => Color(theme.palette.primary.main).isLight(), [theme.palette.primary.main]);
|
35
|
+
const themeConfig = useMemo(() => {
|
36
|
+
const nylasTheme = {
|
37
|
+
'--nylas-info': theme.palette.info.main,
|
38
|
+
'--nylas-success': theme.palette.success.main,
|
39
|
+
'--nylas-warning': theme.palette.warning.main,
|
40
|
+
'--nylas-error': theme.palette.error.main,
|
41
|
+
'--nylas-font-family': theme.typography.fontFamily,
|
42
|
+
'--nylas-font-size': theme.typography.fontSize.toString(),
|
43
|
+
};
|
44
|
+
if (!colorIsLight) {
|
45
|
+
nylasTheme['--nylas-primary'] = theme.palette.primary.main;
|
46
|
+
}
|
47
|
+
return nylasTheme;
|
48
|
+
}, [theme.palette, colorIsLight, theme.typography]);
|
49
|
+
const value = useMemo(() => ({
|
50
|
+
setBookingError,
|
51
|
+
onTimeSlotConfirmed,
|
52
|
+
themeConfig,
|
53
|
+
}), [setBookingError, onTimeSlotConfirmed, themeConfig]);
|
54
|
+
return (React.createElement(CalendarBookingsContext.Provider, { value: value },
|
55
|
+
React.createElement(React.Fragment, null,
|
56
|
+
children,
|
57
|
+
React.createElement(Snackbar, { anchorOrigin: { vertical: 'bottom', horizontal: 'right' }, open: isShowingErrorSnack },
|
58
|
+
React.createElement(Alert, { onClose: hideErrorSnack, severity: 'error', elevation: 6, variant: "filled", action: React.createElement(Button, { color: "inherit", variant: "text", size: "small", onClick: refreshNylasState },
|
59
|
+
React.createElement("b", null, "Start Again")) }, bookingError)))));
|
60
|
+
}
|
61
|
+
export default function useCalendarBookings() {
|
62
|
+
return useContext(CalendarBookingsContext);
|
63
|
+
}
|
64
|
+
//# sourceMappingURL=CalendarBookingsProvider.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"CalendarBookingsProvider.js","sourceRoot":"","sources":["../../../src/components/calendar-bookings/CalendarBookingsProvider.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, {\n useContext,\n createContext,\n useMemo,\n useCallback,\n ComponentProps,\n} from 'react'\nimport { NylasScheduling } from '@nylas/react'\nimport { Snackbar, Alert, Button, useTheme } from '@mui/material'\nimport Color from 'color'\nimport useBooleanState from '../../hooks/useBooleanState'\n\ntype CalendarBookingsContextProps = {\n setBookingError: (errorString: string) => void\n onTimeSlotConfirmed: () => Promise<void>\n themeConfig: ComponentProps<typeof NylasScheduling>['themeConfig']\n}\n\nconst CalendarBookingsContext = createContext<CalendarBookingsContextProps>({\n setBookingError: () => {},\n onTimeSlotConfirmed: async () => {},\n themeConfig: {},\n})\n\nexport function CalendarBookingsProvider({\n children,\n refreshNylasState,\n}: {\n children: React.ReactNode\n refreshNylasState: () => void\n}) {\n const [isShowingErrorSnack, showErrorSnack, hideErrorSnack] =\n useBooleanState(false)\n const [bookingError, _setBookingError] = React.useState<string>()\n\n const setBookingError = useCallback(\n (errorString: string) => {\n _setBookingError(errorString)\n showErrorSnack()\n },\n [showErrorSnack],\n )\n\n /**\n * The alternative here is to set the submissionId field to multi-line-text\n * input then use the below css It works because the booking form only has 1\n * multi-line-text input Unfortunately chrome won't allow :nth-child selectors\n * on part() selectors ::part(nbf__textarea-component) { display: none; }\n */\n const onTimeSlotConfirmed = React.useCallback(async () => {\n setTimeout(() => {\n const submissionIdInputComponent = document\n .querySelector('nylas-scheduling')\n ?.shadowRoot?.querySelector('nylas-booking-form')\n ?.shadowRoot?.querySelector('#submissionId') as HTMLElement | undefined\n\n if (submissionIdInputComponent) {\n submissionIdInputComponent.style.display = 'none'\n }\n }, 50)\n }, [])\n\n const theme = useTheme()\n\n const colorIsLight = useMemo(\n () => Color(theme.palette.primary.main).isLight(),\n [theme.palette.primary.main],\n )\n\n const themeConfig = useMemo(() => {\n const nylasTheme: ComponentProps<typeof NylasScheduling>['themeConfig'] = {\n '--nylas-info': theme.palette.info.main,\n '--nylas-success': theme.palette.success.main,\n '--nylas-warning': theme.palette.warning.main,\n '--nylas-error': theme.palette.error.main,\n '--nylas-font-family': theme.typography.fontFamily,\n '--nylas-font-size': theme.typography.fontSize.toString(),\n }\n\n if (!colorIsLight) {\n nylasTheme['--nylas-primary'] = theme.palette.primary.main\n }\n return nylasTheme\n }, [theme.palette, colorIsLight, theme.typography])\n\n const value = useMemo(\n () => ({\n setBookingError,\n onTimeSlotConfirmed,\n themeConfig,\n }),\n [setBookingError, onTimeSlotConfirmed, themeConfig],\n )\n\n return (\n <CalendarBookingsContext.Provider value={value}>\n <>\n {children}\n <Snackbar\n anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}\n open={isShowingErrorSnack}\n >\n <Alert\n onClose={hideErrorSnack}\n severity={'error'}\n elevation={6}\n variant=\"filled\"\n action={\n <Button\n color=\"inherit\"\n variant=\"text\"\n size=\"small\"\n onClick={refreshNylasState}\n >\n <b>Start Again</b>\n </Button>\n }\n >\n {bookingError}\n </Alert>\n </Snackbar>\n </>\n </CalendarBookingsContext.Provider>\n )\n}\n\nexport default function useCalendarBookings() {\n return useContext(CalendarBookingsContext)\n}\n"]}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { NylasScheduling } from '@nylas/react';
|
3
|
+
import { schedulingService } from '@oneblink/apps';
|
4
|
+
import ErrorMessage from '../messages/ErrorMessage';
|
5
|
+
import CalendarBookingsContainer from './CalendarBookingsContainer';
|
6
|
+
import useCalendarBookings from './CalendarBookingsProvider';
|
7
|
+
function NylasReschedulingForm({ submissionId, name, email, sessionId, bookingRef, }) {
|
8
|
+
const { setBookingError, onTimeSlotConfirmed, themeConfig } = useCalendarBookings();
|
9
|
+
if (!bookingRef) {
|
10
|
+
return (React.createElement(ErrorMessage, { title: "Error Retrieving Data", gutterTop: true },
|
11
|
+
React.createElement("span", { className: "cypress-booking-ref-not-found-error-message" }, "Could not find a calendar booking to reschedule")));
|
12
|
+
}
|
13
|
+
return (React.createElement("div", { className: "ob-scheduling-booking-form" },
|
14
|
+
React.createElement(NylasScheduling, { sessionId: sessionId, eventOverrides: {
|
15
|
+
timeslotConfirmed: onTimeSlotConfirmed,
|
16
|
+
bookedEventInfo: async (event) => {
|
17
|
+
var _a;
|
18
|
+
event.preventDefault();
|
19
|
+
if (event.detail.error) {
|
20
|
+
setBookingError((_a = event.detail.error.message) !== null && _a !== void 0 ? _a : 'Calendar Booking Error');
|
21
|
+
}
|
22
|
+
},
|
23
|
+
}, bookingInfo: {
|
24
|
+
primaryParticipant: {
|
25
|
+
name: name !== null && name !== void 0 ? name : '',
|
26
|
+
email: email !== null && email !== void 0 ? email : '',
|
27
|
+
},
|
28
|
+
additionalFields: {
|
29
|
+
submissionId: { value: submissionId, type: 'text' },
|
30
|
+
},
|
31
|
+
}, themeConfig: themeConfig, enableUserFeedback: false, rescheduleBookingRef: bookingRef, nylasBranding: false })));
|
32
|
+
}
|
33
|
+
function ReschedulingForm() {
|
34
|
+
return (React.createElement(CalendarBookingsContainer, { fetchConfiguration: schedulingService.createNylasExistingBookingSession }, (props) => React.createElement(NylasReschedulingForm, { ...props })));
|
35
|
+
}
|
36
|
+
export default React.memo(ReschedulingForm);
|
37
|
+
//# sourceMappingURL=CalendarBookingsReschedulingForm.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"CalendarBookingsReschedulingForm.js","sourceRoot":"","sources":["../../../src/components/calendar-bookings/CalendarBookingsReschedulingForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAClD,OAAO,YAAY,MAAM,0BAA0B,CAAA;AACnD,OAAO,yBAAyB,MAAM,6BAA6B,CAAA;AACnE,OAAO,mBAAmB,MAAM,4BAA4B,CAAA;AAE5D,SAAS,qBAAqB,CAAC,EAC7B,YAAY,EACZ,IAAI,EACJ,KAAK,EACL,SAAS,EACT,UAAU,GAKX;IACC,MAAM,EAAE,eAAe,EAAE,mBAAmB,EAAE,WAAW,EAAE,GACzD,mBAAmB,EAAE,CAAA;IAEvB,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,CACL,oBAAC,YAAY,IAAC,KAAK,EAAC,uBAAuB,EAAC,SAAS;YACnD,8BAAM,SAAS,EAAC,6CAA6C,sDAEtD,CACM,CAChB,CAAA;IACH,CAAC;IAED,OAAO,CACL,6BAAK,SAAS,EAAC,4BAA4B;QACzC,oBAAC,eAAe,IACd,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE;gBACd,iBAAiB,EAAE,mBAAmB;gBACtC,eAAe,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;;oBAC/B,KAAK,CAAC,cAAc,EAAE,CAAA;oBACtB,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;wBACvB,eAAe,CACb,MAAA,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,mCAAI,wBAAwB,CACvD,CAAA;oBACH,CAAC;gBACH,CAAC;aACF,EACD,WAAW,EAAE;gBACX,kBAAkB,EAAE;oBAClB,IAAI,EAAE,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,EAAE;oBAChB,KAAK,EAAE,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,EAAE;iBACnB;gBACD,gBAAgB,EAAE;oBAChB,YAAY,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE;iBACpD;aACF,EACD,WAAW,EAAE,WAAW,EACxB,kBAAkB,EAAE,KAAK,EACzB,oBAAoB,EAAE,UAAU,EAChC,aAAa,EAAE,KAAK,GACpB,CACE,CACP,CAAA;AACH,CAAC;AAED,SAAS,gBAAgB;IACvB,OAAO,CACL,oBAAC,yBAAyB,IACxB,kBAAkB,EAAE,iBAAiB,CAAC,iCAAiC,IAEtE,CAAC,KAAK,EAAE,EAAE,CAAC,oBAAC,qBAAqB,OAAK,KAAK,GAAI,CACtB,CAC7B,CAAA;AACH,CAAC;AAED,eAAe,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA","sourcesContent":["import React from 'react'\nimport { NylasScheduling } from '@nylas/react'\nimport { schedulingService } from '@oneblink/apps'\nimport ErrorMessage from '../messages/ErrorMessage'\nimport CalendarBookingsContainer from './CalendarBookingsContainer'\nimport useCalendarBookings from './CalendarBookingsProvider'\n\nfunction NylasReschedulingForm({\n submissionId,\n name,\n email,\n sessionId,\n bookingRef,\n}: Awaited<\n ReturnType<typeof schedulingService.createNylasExistingBookingSession>\n> & {\n submissionId: string\n}) {\n const { setBookingError, onTimeSlotConfirmed, themeConfig } =\n useCalendarBookings()\n\n if (!bookingRef) {\n return (\n <ErrorMessage title=\"Error Retrieving Data\" gutterTop>\n <span className=\"cypress-booking-ref-not-found-error-message\">\n Could not find a calendar booking to reschedule\n </span>\n </ErrorMessage>\n )\n }\n\n return (\n <div className=\"ob-scheduling-booking-form\">\n <NylasScheduling\n sessionId={sessionId}\n eventOverrides={{\n timeslotConfirmed: onTimeSlotConfirmed,\n bookedEventInfo: async (event) => {\n event.preventDefault()\n if (event.detail.error) {\n setBookingError(\n event.detail.error.message ?? 'Calendar Booking Error',\n )\n }\n },\n }}\n bookingInfo={{\n primaryParticipant: {\n name: name ?? '',\n email: email ?? '',\n },\n additionalFields: {\n submissionId: { value: submissionId, type: 'text' },\n },\n }}\n themeConfig={themeConfig}\n enableUserFeedback={false}\n rescheduleBookingRef={bookingRef}\n nylasBranding={false}\n />\n </div>\n )\n}\n\nfunction ReschedulingForm() {\n return (\n <CalendarBookingsContainer\n fetchConfiguration={schedulingService.createNylasExistingBookingSession}\n >\n {(props) => <NylasReschedulingForm {...props} />}\n </CalendarBookingsContainer>\n )\n}\n\nexport default React.memo(ReschedulingForm)\n"]}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import * as React from 'react';
|
2
|
+
import { OneBlinkAppsError } from '@oneblink/apps';
|
3
|
+
type Props = {
|
4
|
+
error: OneBlinkAppsError | Error | null;
|
5
|
+
closeButtonLabel?: string;
|
6
|
+
closeButtonClassName?: string;
|
7
|
+
onClose: () => unknown;
|
8
|
+
};
|
9
|
+
declare const _default: React.NamedExoticComponent<Props>;
|
10
|
+
export default _default;
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import * as React from 'react';
|
2
|
+
import clsx from 'clsx';
|
3
|
+
import { OneBlinkAppsError } from '@oneblink/apps';
|
4
|
+
import OneBlinkAppsErrorOriginalMessage from '../renderer/OneBlinkAppsErrorOriginalMessage';
|
5
|
+
import sanitizeHtml from '../../services/sanitize-html';
|
6
|
+
import Modal from '../renderer/Modal';
|
7
|
+
import MaterialIcon from '../MaterialIcon';
|
8
|
+
function ErrorModal({ error, closeButtonLabel, closeButtonClassName, onClose, }) {
|
9
|
+
const displayError = React.useMemo(() => {
|
10
|
+
if (!error)
|
11
|
+
return;
|
12
|
+
let displayError;
|
13
|
+
if (!(error instanceof OneBlinkAppsError)) {
|
14
|
+
displayError = new OneBlinkAppsError(error.message);
|
15
|
+
}
|
16
|
+
else {
|
17
|
+
displayError = error;
|
18
|
+
}
|
19
|
+
return displayError;
|
20
|
+
}, [error]);
|
21
|
+
const sanitizedHtml = React.useMemo(() => {
|
22
|
+
if (!error)
|
23
|
+
return '';
|
24
|
+
return sanitizeHtml(error.message);
|
25
|
+
}, [error]);
|
26
|
+
const handleClose = React.useCallback(async () => {
|
27
|
+
if (!displayError)
|
28
|
+
return;
|
29
|
+
onClose();
|
30
|
+
}, [displayError, onClose]);
|
31
|
+
if (!displayError) {
|
32
|
+
return null;
|
33
|
+
}
|
34
|
+
return (React.createElement(Modal, { isOpen: true, title: displayError.title, className: "cypress-error-modal", cardClassName: clsx({
|
35
|
+
'has-text-centered': displayError.isOffline,
|
36
|
+
}), titleClassName: "cypress-error-title", bodyClassName: "cypress-error-message", actions: React.createElement(React.Fragment, null,
|
37
|
+
React.createElement("button", { type: "button", className: clsx('button ob-button cypress-close-error is-primary', closeButtonClassName), onClick: handleClose, autoFocus: true }, closeButtonLabel || 'Okay')) },
|
38
|
+
React.createElement(React.Fragment, null,
|
39
|
+
React.createElement("div", {
|
40
|
+
// eslint-disable-next-line react/no-danger
|
41
|
+
dangerouslySetInnerHTML: {
|
42
|
+
__html: sanitizedHtml,
|
43
|
+
} }),
|
44
|
+
displayError.isOffline && (React.createElement(MaterialIcon, { className: "has-text-warning icon-x-large" }, "wifi_off")),
|
45
|
+
React.createElement(OneBlinkAppsErrorOriginalMessage, { error: displayError.originalError }))));
|
46
|
+
}
|
47
|
+
export default React.memo(ErrorModal);
|
48
|
+
//# sourceMappingURL=ErrorModal.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"ErrorModal.js","sourceRoot":"","sources":["../../../src/components/calendar-bookings/ErrorModal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAClD,OAAO,gCAAgC,MAAM,8CAA8C,CAAA;AAC3F,OAAO,YAAY,MAAM,8BAA8B,CAAA;AACvD,OAAO,KAAK,MAAM,mBAAmB,CAAA;AACrC,OAAO,YAAY,MAAM,iBAAiB,CAAA;AAS1C,SAAS,UAAU,CAAC,EAClB,KAAK,EACL,gBAAgB,EAChB,oBAAoB,EACpB,OAAO,GACD;IACN,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACtC,IAAI,CAAC,KAAK;YAAE,OAAM;QAClB,IAAI,YAAY,CAAA;QAEhB,IAAI,CAAC,CAAC,KAAK,YAAY,iBAAiB,CAAC,EAAE,CAAC;YAC1C,YAAY,GAAG,IAAI,iBAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QACrD,CAAC;aAAM,CAAC;YACN,YAAY,GAAG,KAAK,CAAA;QACtB,CAAC;QACD,OAAO,YAAY,CAAA;IACrB,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAA;IAEX,MAAM,aAAa,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACvC,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,CAAA;QACrB,OAAO,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACpC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAA;IAEX,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,IAAI,EAAE;QAC/C,IAAI,CAAC,YAAY;YAAE,OAAM;QAEzB,OAAO,EAAE,CAAA;IACX,CAAC,EAAE,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAA;IAE3B,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,CACL,oBAAC,KAAK,IACJ,MAAM,QACN,KAAK,EAAE,YAAY,CAAC,KAAK,EACzB,SAAS,EAAC,qBAAqB,EAC/B,aAAa,EAAE,IAAI,CAAC;YAClB,mBAAmB,EAAE,YAAY,CAAC,SAAS;SAC5C,CAAC,EACF,cAAc,EAAC,qBAAqB,EACpC,aAAa,EAAC,uBAAuB,EACrC,OAAO,EACL;YACE,gCACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,IAAI,CACb,iDAAiD,EACjD,oBAAoB,CACrB,EACD,OAAO,EAAE,WAAW,EACpB,SAAS,UAER,gBAAgB,IAAI,MAAM,CACpB,CACR;QAGL;YACE;gBACE,2CAA2C;gBAC3C,uBAAuB,EAAE;oBACvB,MAAM,EAAE,aAAa;iBACtB,GACD;YACD,YAAY,CAAC,SAAS,IAAI,CACzB,oBAAC,YAAY,IAAC,SAAS,EAAC,+BAA+B,eAExC,CAChB;YACD,oBAAC,gCAAgC,IAAC,KAAK,EAAE,YAAY,CAAC,aAAa,GAAI,CACtE,CACG,CACT,CAAA;AACH,CAAC;AAED,eAAe,KAAK,CAAC,IAAI,CAAQ,UAAU,CAAC,CAAA","sourcesContent":["import * as React from 'react'\nimport clsx from 'clsx'\nimport { OneBlinkAppsError } from '@oneblink/apps'\nimport OneBlinkAppsErrorOriginalMessage from '../renderer/OneBlinkAppsErrorOriginalMessage'\nimport sanitizeHtml from '../../services/sanitize-html'\nimport Modal from '../renderer/Modal'\nimport MaterialIcon from '../MaterialIcon'\n\ntype Props = {\n error: OneBlinkAppsError | Error | null\n closeButtonLabel?: string\n closeButtonClassName?: string\n onClose: () => unknown\n}\n\nfunction ErrorModal({\n error,\n closeButtonLabel,\n closeButtonClassName,\n onClose,\n}: Props) {\n const displayError = React.useMemo(() => {\n if (!error) return\n let displayError\n\n if (!(error instanceof OneBlinkAppsError)) {\n displayError = new OneBlinkAppsError(error.message)\n } else {\n displayError = error\n }\n return displayError\n }, [error])\n\n const sanitizedHtml = React.useMemo(() => {\n if (!error) return ''\n return sanitizeHtml(error.message)\n }, [error])\n\n const handleClose = React.useCallback(async () => {\n if (!displayError) return\n\n onClose()\n }, [displayError, onClose])\n\n if (!displayError) {\n return null\n }\n\n return (\n <Modal\n isOpen\n title={displayError.title}\n className=\"cypress-error-modal\"\n cardClassName={clsx({\n 'has-text-centered': displayError.isOffline,\n })}\n titleClassName=\"cypress-error-title\"\n bodyClassName=\"cypress-error-message\"\n actions={\n <>\n <button\n type=\"button\"\n className={clsx(\n 'button ob-button cypress-close-error is-primary',\n closeButtonClassName,\n )}\n onClick={handleClose}\n autoFocus\n >\n {closeButtonLabel || 'Okay'}\n </button>\n </>\n }\n >\n <>\n <div\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{\n __html: sanitizedHtml,\n }}\n />\n {displayError.isOffline && (\n <MaterialIcon className=\"has-text-warning icon-x-large\">\n wifi_off\n </MaterialIcon>\n )}\n <OneBlinkAppsErrorOriginalMessage error={displayError.originalError} />\n </>\n </Modal>\n )\n}\n\nexport default React.memo<Props>(ErrorModal)\n"]}
|
@@ -6,7 +6,7 @@ import useBooleanState from '../../hooks/useBooleanState';
|
|
6
6
|
import { CopyToClipBoardIconButton } from '../CopyToClipboardIconButton';
|
7
7
|
import SuccessSnackbar from '../SuccessSnackbar';
|
8
8
|
import InputField from '../InputField';
|
9
|
-
import LoadingButton from '
|
9
|
+
import { LoadingButton } from '@mui/lab';
|
10
10
|
function MfaDialog({ onClose, onCompleted, mfaSetup, }) {
|
11
11
|
const [code, setState] = React.useState('');
|
12
12
|
const [hasSuccessfullySaved, showSuccessfullySaved, hideSuccessfullySaved] = useBooleanState(false);
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"MfaDialog.js","sourceRoot":"","sources":["../../../src/components/mfa/MfaDialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EACL,GAAG,EACH,QAAQ,EACR,MAAM,EACN,IAAI,EACJ,IAAI,EACJ,UAAU,EACV,aAAa,EACb,aAAa,EACb,MAAM,GACP,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,eAAe,MAAM,6BAA6B,CAAA;AACzD,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAA;AACxE,OAAO,eAAe,MAAM,oBAAoB,CAAA;AAChD,OAAO,UAAU,MAAM,eAAe,CAAA;AACtC,OAAO,aAAa,MAAM,kBAAkB,CAAA;AAE5C,SAAS,SAAS,CAAC,EACjB,OAAO,EACP,WAAW,EACX,QAAQ,GAKT;IACC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;IAC3C,MAAM,CAAC,oBAAoB,EAAE,qBAAqB,EAAE,qBAAqB,CAAC,GACxE,eAAe,CAAC,KAAK,CAAC,CAAA;IACxB,MAAM,CAAC,mBAAmB,EAAE,cAAc,EAAE,cAAc,CAAC,GACzD,eAAe,CAAC,KAAK,CAAC,CAAA;IAExB,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACrC,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,WAAW,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAA;QACnD,CAAC;IACH,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEd,MAAM,CAAC,QAAQ,EAAE,WAAW,EAAE,UAAU,CAAC,GAAG,eAAe,CAAC,KAAK,CAAC,CAAA;IAClE,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,IAAI,EAAE;QAC9C,WAAW,EAAE,CAAA;QACb,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACvB,OAAM;QACR,CAAC;QAED,MAAM,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,CAAA;QACpC,WAAW,EAAE,CAAA;QACb,UAAU,EAAE,CAAA;QACZ,qBAAqB,EAAE,CAAA;IACzB,CAAC,EAAE;QACD,IAAI;QACJ,QAAQ;QACR,WAAW;QACX,qBAAqB;QACrB,WAAW;QACX,UAAU;KACX,CAAC,CAAA;IAEF,OAAO,CACL,oBAAC,KAAK,CAAC,QAAQ;QACb,oBAAC,MAAM,IAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAC,oBAAoB;YACpE,oBAAC,aAAa,IAAC,QAAQ;gBACrB;oBACE,oBAAC,UAAU,IAAC,OAAO,EAAC,WAAW,EAAC,YAAY,8BAE/B;oBACb,oBAAC,UAAU,IAAC,OAAO,EAAC,OAAO,EAAC,SAAS;;wBACX,GAAG;wBAC3B,oBAAC,IAAI,IACH,IAAI,EAAC,sFAAsF,EAC3F,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,qBAAqB,2BAGpB;wBAAC,GAAG;;wBACP,GAAG;wBACP,oBAAC,IAAI,IACH,IAAI,EAAC,mEAAmE,EACxE,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,qBAAqB,8BAGpB;wBAAC,GAAG;6IAGA;oBACb,oBAAC,UAAU,IAAC,OAAO,EAAC,WAAW,EAAC,YAAY,6BAE/B;oBACb,oBAAC,UAAU,IAAC,OAAO,EAAC,OAAO,EAAC,SAAS,qFAGxB;oBAEb,oBAAC,GAAG,IAAC,YAAY,EAAE,CAAC;wBAClB,oBAAC,IAAI,IAAC,SAAS,QAAC,OAAO,EAAE,CAAC,EAAE,UAAU,EAAC,QAAQ;4BAC7C,oBAAC,IAAI,IAAC,IAAI,QAAC,EAAE,EAAE,KAAK;gCAClB,oBAAC,GAAG,IACF,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,CAAC,EACV,YAAY,EAAE,CAAC,EACf,WAAW,EAAC,SAAS,EACrB,OAAO,EAAC,cAAc;oCAEtB,oBAAC,SAAS,IAAC,KAAK,EAAE,WAAW,IAAI,EAAE,GAAI,CACnC,CACD;4BACP,oBAAC,IAAI,IAAC,IAAI,QAAC,EAAE;gCACX,oBAAC,UAAU,IAAC,OAAO,EAAC,SAAS,EAAC,KAAK,EAAC,gBAAgB;;oCACb,GAAG;oCACxC,oBAAC,IAAI,IAAC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAC,QAAQ,iBAE1C;oCAAC,GAAG;wHAGA,CACR,CACF,CACH;oBAEN,oBAAC,QAAQ,IAAC,EAAE,EAAE,mBAAmB;wBAC/B,oBAAC,GAAG,IAAC,YAAY,EAAE,CAAC;4BAClB,oBAAC,UAAU,IACT,KAAK,EAAC,WAAW,EACjB,KAAK,EAAE,CAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,UAAU,KAAI,EAAE,EACjC,SAAS,QACT,UAAU,EAAE;oCACV,YAAY,EAAE,CACZ,oBAAC,yBAAyB,IACxB,IAAI,EAAE,CAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,UAAU,KAAI,EAAE,GAChC,CACH;iCACF,EACD,UAAU,EACR;oCACE,oBAAC,IAAI,IAAC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAC,QAAQ,iBAE1C;oCAAC,GAAG;4DAEV,GAEL,CACE,CACG;oBAEX,oBAAC,UAAU,IAAC,OAAO,EAAC,WAAW,EAAC,YAAY,uBAE/B;oBACb,oBAAC,UAAU,IAAC,OAAO,EAAC,OAAO,EAAC,SAAS,oEAExB;oBAEb,oBAAC,UAAU,IACT,SAAS,QACT,MAAM,EAAC,MAAM,EACb,IAAI,EAAC,MAAM,EACX,KAAK,EAAC,MAAM,EACZ,SAAS,QACT,WAAW,EAAC,QAAQ,EACpB,OAAO,EAAC,UAAU,EAClB,KAAK,EAAE,IAAI,EACX,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;4BAClB,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAA;4BACnC,QAAQ,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAA;wBAC1B,CAAC,EACD,QAAQ,EAAE,QAAQ,kBACL,iBAAiB,GAC9B,CACD,CACW;YAChB,oBAAC,aAAa;gBACZ,oBAAC,MAAM,IAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,aAEnC;gBACT,oBAAC,aAAa,IACZ,OAAO,EAAC,WAAW,EACnB,KAAK,EAAC,SAAS,EACf,OAAO,EAAE,QAAQ,EACjB,OAAO,EAAE,UAAU,WAGL,CACF,CACT;QAET,oBAAC,eAAe,IACd,IAAI,EAAE,oBAAoB,EAC1B,OAAO,EAAE,qBAAqB,uCAGd,CACH,CAClB,CAAA;AACH,CAAC;AAED,eAAe,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA","sourcesContent":["import * as React from 'react'\nimport { QRCodeSVG } from 'qrcode.react'\nimport {\n Box,\n Collapse,\n Dialog,\n Grid,\n Link,\n Typography,\n DialogContent,\n DialogActions,\n Button,\n} from '@mui/material'\nimport { authService } from '@oneblink/apps'\nimport useBooleanState from '../../hooks/useBooleanState'\nimport { CopyToClipBoardIconButton } from '../CopyToClipboardIconButton'\nimport SuccessSnackbar from '../SuccessSnackbar'\nimport InputField from '../InputField'\nimport LoadingButton from '../LoadingButton'\n\nfunction MfaDialog({\n onClose,\n onCompleted,\n mfaSetup,\n}: {\n onClose: () => void\n onCompleted: () => void\n mfaSetup: Awaited<ReturnType<typeof authService.setupMfa>> | undefined\n}) {\n const [code, setState] = React.useState('')\n const [hasSuccessfullySaved, showSuccessfullySaved, hideSuccessfullySaved] =\n useBooleanState(false)\n const [isShowingSecretCode, showSecretCode, hideSecretCode] =\n useBooleanState(false)\n\n const qrcodeValue = React.useMemo(() => {\n if (mfaSetup) {\n return authService.generateMfaQrCodeUrl(mfaSetup)\n }\n }, [mfaSetup])\n\n const [isSaving, startSaving, stopSaving] = useBooleanState(false)\n const handleSave = React.useCallback(async () => {\n startSaving()\n if (!code || !mfaSetup) {\n return\n }\n\n await mfaSetup.mfaCodeCallback(code)\n onCompleted()\n stopSaving()\n showSuccessfullySaved()\n }, [\n code,\n mfaSetup,\n onCompleted,\n showSuccessfullySaved,\n startSaving,\n stopSaving,\n ])\n\n return (\n <React.Fragment>\n <Dialog open={!!mfaSetup} onClose={onClose} title=\"Complete MFA Setup\">\n <DialogContent dividers>\n <>\n <Typography variant=\"subtitle2\" gutterBottom>\n Authenticator App\n </Typography>\n <Typography variant=\"body2\" paragraph>\n Authenticator apps like{' '}\n <Link\n href=\"https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Google Authenticator\n </Link>{' '}\n and{' '}\n <Link\n href=\"https://www.microsoft.com/en-us/security/mobile-authenticator-app\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Microsoft Authenticator\n </Link>{' '}\n generate one-time passwords that are used as a second factor to\n verify your identity when prompted during sign-in.\n </Typography>\n <Typography variant=\"subtitle2\" gutterBottom>\n Scan the QR code\n </Typography>\n <Typography variant=\"body2\" paragraph>\n Use an authenticator app or browser extension to scan the QR code\n below.\n </Typography>\n\n <Box marginBottom={2}>\n <Grid container spacing={2} alignItems=\"center\">\n <Grid item xs={false}>\n <Box\n border={1}\n padding={2}\n borderRadius={1}\n borderColor=\"divider\"\n display=\"inline-block\"\n >\n <QRCodeSVG value={qrcodeValue || ''} />\n </Box>\n </Grid>\n <Grid item xs>\n <Typography variant=\"caption\" color=\"text.secondary\">\n Having trouble scanning the QR code?{' '}\n <Link onClick={showSecretCode} component=\"button\">\n Click here\n </Link>{' '}\n to display the setup key which can be manually entered in\n your authenticator app.\n </Typography>\n </Grid>\n </Grid>\n </Box>\n\n <Collapse in={isShowingSecretCode}>\n <Box marginBottom={2}>\n <InputField\n label=\"Setup Key\"\n value={mfaSetup?.secretCode || ''}\n fullWidth\n InputProps={{\n endAdornment: (\n <CopyToClipBoardIconButton\n text={mfaSetup?.secretCode || ''}\n />\n ),\n }}\n helperText={\n <>\n <Link onClick={hideSecretCode} component=\"button\">\n Click here\n </Link>{' '}\n to hide the setup key\n </>\n }\n />\n </Box>\n </Collapse>\n\n <Typography variant=\"subtitle2\" gutterBottom>\n Verify App\n </Typography>\n <Typography variant=\"body2\" paragraph>\n Enter the 6-digit code found in your authenticator app.\n </Typography>\n\n <InputField\n autoFocus\n margin=\"none\"\n name=\"code\"\n label=\"Code\"\n fullWidth\n placeholder=\"XXXXXX\"\n variant=\"outlined\"\n value={code}\n onChange={(event) => {\n const newValue = event.target.value\n setState(() => newValue)\n }}\n disabled={isSaving}\n data-cypress=\"mfa-dialog-code\"\n />\n </>\n </DialogContent>\n <DialogActions>\n <Button onClick={onClose} disabled={isSaving}>\n Cancel\n </Button>\n <LoadingButton\n variant=\"contained\"\n color=\"primary\"\n loading={isSaving}\n onClick={handleSave}\n >\n Save\n </LoadingButton>\n </DialogActions>\n </Dialog>\n\n <SuccessSnackbar\n open={hasSuccessfullySaved}\n onClose={hideSuccessfullySaved}\n >\n MFA has been successfully setup.\n </SuccessSnackbar>\n </React.Fragment>\n )\n}\n\nexport default React.memo(MfaDialog)\n"]}
|
1
|
+
{"version":3,"file":"MfaDialog.js","sourceRoot":"","sources":["../../../src/components/mfa/MfaDialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EACL,GAAG,EACH,QAAQ,EACR,MAAM,EACN,IAAI,EACJ,IAAI,EACJ,UAAU,EACV,aAAa,EACb,aAAa,EACb,MAAM,GACP,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,eAAe,MAAM,6BAA6B,CAAA;AACzD,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAA;AACxE,OAAO,eAAe,MAAM,oBAAoB,CAAA;AAChD,OAAO,UAAU,MAAM,eAAe,CAAA;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAExC,SAAS,SAAS,CAAC,EACjB,OAAO,EACP,WAAW,EACX,QAAQ,GAKT;IACC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;IAC3C,MAAM,CAAC,oBAAoB,EAAE,qBAAqB,EAAE,qBAAqB,CAAC,GACxE,eAAe,CAAC,KAAK,CAAC,CAAA;IACxB,MAAM,CAAC,mBAAmB,EAAE,cAAc,EAAE,cAAc,CAAC,GACzD,eAAe,CAAC,KAAK,CAAC,CAAA;IAExB,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACrC,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,WAAW,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAA;QACnD,CAAC;IACH,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEd,MAAM,CAAC,QAAQ,EAAE,WAAW,EAAE,UAAU,CAAC,GAAG,eAAe,CAAC,KAAK,CAAC,CAAA;IAClE,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,IAAI,EAAE;QAC9C,WAAW,EAAE,CAAA;QACb,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACvB,OAAM;QACR,CAAC;QAED,MAAM,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,CAAA;QACpC,WAAW,EAAE,CAAA;QACb,UAAU,EAAE,CAAA;QACZ,qBAAqB,EAAE,CAAA;IACzB,CAAC,EAAE;QACD,IAAI;QACJ,QAAQ;QACR,WAAW;QACX,qBAAqB;QACrB,WAAW;QACX,UAAU;KACX,CAAC,CAAA;IAEF,OAAO,CACL,oBAAC,KAAK,CAAC,QAAQ;QACb,oBAAC,MAAM,IAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAC,oBAAoB;YACpE,oBAAC,aAAa,IAAC,QAAQ;gBACrB;oBACE,oBAAC,UAAU,IAAC,OAAO,EAAC,WAAW,EAAC,YAAY,8BAE/B;oBACb,oBAAC,UAAU,IAAC,OAAO,EAAC,OAAO,EAAC,SAAS;;wBACX,GAAG;wBAC3B,oBAAC,IAAI,IACH,IAAI,EAAC,sFAAsF,EAC3F,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,qBAAqB,2BAGpB;wBAAC,GAAG;;wBACP,GAAG;wBACP,oBAAC,IAAI,IACH,IAAI,EAAC,mEAAmE,EACxE,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,qBAAqB,8BAGpB;wBAAC,GAAG;6IAGA;oBACb,oBAAC,UAAU,IAAC,OAAO,EAAC,WAAW,EAAC,YAAY,6BAE/B;oBACb,oBAAC,UAAU,IAAC,OAAO,EAAC,OAAO,EAAC,SAAS,qFAGxB;oBAEb,oBAAC,GAAG,IAAC,YAAY,EAAE,CAAC;wBAClB,oBAAC,IAAI,IAAC,SAAS,QAAC,OAAO,EAAE,CAAC,EAAE,UAAU,EAAC,QAAQ;4BAC7C,oBAAC,IAAI,IAAC,IAAI,QAAC,EAAE,EAAE,KAAK;gCAClB,oBAAC,GAAG,IACF,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,CAAC,EACV,YAAY,EAAE,CAAC,EACf,WAAW,EAAC,SAAS,EACrB,OAAO,EAAC,cAAc;oCAEtB,oBAAC,SAAS,IAAC,KAAK,EAAE,WAAW,IAAI,EAAE,GAAI,CACnC,CACD;4BACP,oBAAC,IAAI,IAAC,IAAI,QAAC,EAAE;gCACX,oBAAC,UAAU,IAAC,OAAO,EAAC,SAAS,EAAC,KAAK,EAAC,gBAAgB;;oCACb,GAAG;oCACxC,oBAAC,IAAI,IAAC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAC,QAAQ,iBAE1C;oCAAC,GAAG;wHAGA,CACR,CACF,CACH;oBAEN,oBAAC,QAAQ,IAAC,EAAE,EAAE,mBAAmB;wBAC/B,oBAAC,GAAG,IAAC,YAAY,EAAE,CAAC;4BAClB,oBAAC,UAAU,IACT,KAAK,EAAC,WAAW,EACjB,KAAK,EAAE,CAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,UAAU,KAAI,EAAE,EACjC,SAAS,QACT,UAAU,EAAE;oCACV,YAAY,EAAE,CACZ,oBAAC,yBAAyB,IACxB,IAAI,EAAE,CAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,UAAU,KAAI,EAAE,GAChC,CACH;iCACF,EACD,UAAU,EACR;oCACE,oBAAC,IAAI,IAAC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAC,QAAQ,iBAE1C;oCAAC,GAAG;4DAEV,GAEL,CACE,CACG;oBAEX,oBAAC,UAAU,IAAC,OAAO,EAAC,WAAW,EAAC,YAAY,uBAE/B;oBACb,oBAAC,UAAU,IAAC,OAAO,EAAC,OAAO,EAAC,SAAS,oEAExB;oBAEb,oBAAC,UAAU,IACT,SAAS,QACT,MAAM,EAAC,MAAM,EACb,IAAI,EAAC,MAAM,EACX,KAAK,EAAC,MAAM,EACZ,SAAS,QACT,WAAW,EAAC,QAAQ,EACpB,OAAO,EAAC,UAAU,EAClB,KAAK,EAAE,IAAI,EACX,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;4BAClB,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAA;4BACnC,QAAQ,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAA;wBAC1B,CAAC,EACD,QAAQ,EAAE,QAAQ,kBACL,iBAAiB,GAC9B,CACD,CACW;YAChB,oBAAC,aAAa;gBACZ,oBAAC,MAAM,IAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,aAEnC;gBACT,oBAAC,aAAa,IACZ,OAAO,EAAC,WAAW,EACnB,KAAK,EAAC,SAAS,EACf,OAAO,EAAE,QAAQ,EACjB,OAAO,EAAE,UAAU,WAGL,CACF,CACT;QAET,oBAAC,eAAe,IACd,IAAI,EAAE,oBAAoB,EAC1B,OAAO,EAAE,qBAAqB,uCAGd,CACH,CAClB,CAAA;AACH,CAAC;AAED,eAAe,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA","sourcesContent":["import * as React from 'react'\nimport { QRCodeSVG } from 'qrcode.react'\nimport {\n Box,\n Collapse,\n Dialog,\n Grid,\n Link,\n Typography,\n DialogContent,\n DialogActions,\n Button,\n} from '@mui/material'\nimport { authService } from '@oneblink/apps'\nimport useBooleanState from '../../hooks/useBooleanState'\nimport { CopyToClipBoardIconButton } from '../CopyToClipboardIconButton'\nimport SuccessSnackbar from '../SuccessSnackbar'\nimport InputField from '../InputField'\nimport { LoadingButton } from '@mui/lab'\n\nfunction MfaDialog({\n onClose,\n onCompleted,\n mfaSetup,\n}: {\n onClose: () => void\n onCompleted: () => void\n mfaSetup: Awaited<ReturnType<typeof authService.setupMfa>> | undefined\n}) {\n const [code, setState] = React.useState('')\n const [hasSuccessfullySaved, showSuccessfullySaved, hideSuccessfullySaved] =\n useBooleanState(false)\n const [isShowingSecretCode, showSecretCode, hideSecretCode] =\n useBooleanState(false)\n\n const qrcodeValue = React.useMemo(() => {\n if (mfaSetup) {\n return authService.generateMfaQrCodeUrl(mfaSetup)\n }\n }, [mfaSetup])\n\n const [isSaving, startSaving, stopSaving] = useBooleanState(false)\n const handleSave = React.useCallback(async () => {\n startSaving()\n if (!code || !mfaSetup) {\n return\n }\n\n await mfaSetup.mfaCodeCallback(code)\n onCompleted()\n stopSaving()\n showSuccessfullySaved()\n }, [\n code,\n mfaSetup,\n onCompleted,\n showSuccessfullySaved,\n startSaving,\n stopSaving,\n ])\n\n return (\n <React.Fragment>\n <Dialog open={!!mfaSetup} onClose={onClose} title=\"Complete MFA Setup\">\n <DialogContent dividers>\n <>\n <Typography variant=\"subtitle2\" gutterBottom>\n Authenticator App\n </Typography>\n <Typography variant=\"body2\" paragraph>\n Authenticator apps like{' '}\n <Link\n href=\"https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Google Authenticator\n </Link>{' '}\n and{' '}\n <Link\n href=\"https://www.microsoft.com/en-us/security/mobile-authenticator-app\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Microsoft Authenticator\n </Link>{' '}\n generate one-time passwords that are used as a second factor to\n verify your identity when prompted during sign-in.\n </Typography>\n <Typography variant=\"subtitle2\" gutterBottom>\n Scan the QR code\n </Typography>\n <Typography variant=\"body2\" paragraph>\n Use an authenticator app or browser extension to scan the QR code\n below.\n </Typography>\n\n <Box marginBottom={2}>\n <Grid container spacing={2} alignItems=\"center\">\n <Grid item xs={false}>\n <Box\n border={1}\n padding={2}\n borderRadius={1}\n borderColor=\"divider\"\n display=\"inline-block\"\n >\n <QRCodeSVG value={qrcodeValue || ''} />\n </Box>\n </Grid>\n <Grid item xs>\n <Typography variant=\"caption\" color=\"text.secondary\">\n Having trouble scanning the QR code?{' '}\n <Link onClick={showSecretCode} component=\"button\">\n Click here\n </Link>{' '}\n to display the setup key which can be manually entered in\n your authenticator app.\n </Typography>\n </Grid>\n </Grid>\n </Box>\n\n <Collapse in={isShowingSecretCode}>\n <Box marginBottom={2}>\n <InputField\n label=\"Setup Key\"\n value={mfaSetup?.secretCode || ''}\n fullWidth\n InputProps={{\n endAdornment: (\n <CopyToClipBoardIconButton\n text={mfaSetup?.secretCode || ''}\n />\n ),\n }}\n helperText={\n <>\n <Link onClick={hideSecretCode} component=\"button\">\n Click here\n </Link>{' '}\n to hide the setup key\n </>\n }\n />\n </Box>\n </Collapse>\n\n <Typography variant=\"subtitle2\" gutterBottom>\n Verify App\n </Typography>\n <Typography variant=\"body2\" paragraph>\n Enter the 6-digit code found in your authenticator app.\n </Typography>\n\n <InputField\n autoFocus\n margin=\"none\"\n name=\"code\"\n label=\"Code\"\n fullWidth\n placeholder=\"XXXXXX\"\n variant=\"outlined\"\n value={code}\n onChange={(event) => {\n const newValue = event.target.value\n setState(() => newValue)\n }}\n disabled={isSaving}\n data-cypress=\"mfa-dialog-code\"\n />\n </>\n </DialogContent>\n <DialogActions>\n <Button onClick={onClose} disabled={isSaving}>\n Cancel\n </Button>\n <LoadingButton\n variant=\"contained\"\n color=\"primary\"\n loading={isSaving}\n onClick={handleSave}\n >\n Save\n </LoadingButton>\n </DialogActions>\n </Dialog>\n\n <SuccessSnackbar\n open={hasSuccessfullySaved}\n onClose={hideSuccessfullySaved}\n >\n MFA has been successfully setup.\n </SuccessSnackbar>\n </React.Fragment>\n )\n}\n\nexport default React.memo(MfaDialog)\n"]}
|
@@ -8,7 +8,7 @@ type Props = {
|
|
8
8
|
};
|
9
9
|
/**
|
10
10
|
* React Component that provides a mechanism for app users to configure Multi
|
11
|
-
* Factor Authentication. `<
|
11
|
+
* Factor Authentication. `<MfaProvider />` must be provided above this
|
12
12
|
* component in the component tree.
|
13
13
|
*
|
14
14
|
* #### Example
|
@@ -16,7 +16,7 @@ type Props = {
|
|
16
16
|
* ```js
|
17
17
|
* import * as React from 'react'
|
18
18
|
* import {
|
19
|
-
*
|
19
|
+
* MfaProvider,
|
20
20
|
* MultiFactorAuthentication,
|
21
21
|
* } from '@oneblink/apps-react'
|
22
22
|
*
|
@@ -26,9 +26,9 @@ type Props = {
|
|
26
26
|
*
|
27
27
|
* function App() {
|
28
28
|
* return (
|
29
|
-
* <
|
29
|
+
* <MfaProvider>
|
30
30
|
* <Component />
|
31
|
-
* </
|
31
|
+
* </MfaProvider>
|
32
32
|
* )
|
33
33
|
* }
|
34
34
|
*
|
@@ -5,12 +5,12 @@ import ConfirmDialog from '../ConfirmDialog';
|
|
5
5
|
import MfaDialog from './MfaDialog';
|
6
6
|
import ErrorSnackbar from '../ErrorSnackbar';
|
7
7
|
import MaterialIcon from '../MaterialIcon';
|
8
|
-
import
|
8
|
+
import useMfa from '../../hooks/useMfa';
|
9
9
|
import ErrorMessage from '../messages/ErrorMessage';
|
10
10
|
export const LargeIcon = styled(Icon)(({ theme }) => ({
|
11
11
|
fontSize: `${theme.typography.h4.fontSize} !important`,
|
12
12
|
}));
|
13
|
-
function MfaStatus({ isExternalIdentityProviderUser, isLoading, loadingError,
|
13
|
+
function MfaStatus({ isExternalIdentityProviderUser, isLoading, loadingError, loadMfa, isMfaEnabled, }) {
|
14
14
|
if (isExternalIdentityProviderUser)
|
15
15
|
return null;
|
16
16
|
if (isLoading) {
|
@@ -20,7 +20,7 @@ function MfaStatus({ isExternalIdentityProviderUser, isLoading, loadingError, lo
|
|
20
20
|
}
|
21
21
|
if (loadingError) {
|
22
22
|
return (React.createElement("div", null,
|
23
|
-
React.createElement(ErrorMessage, { title: "Error Loading Multi Factor Authentication Configuration", onTryAgain:
|
23
|
+
React.createElement(ErrorMessage, { title: "Error Loading Multi Factor Authentication Configuration", onTryAgain: loadMfa }, loadingError.message)));
|
24
24
|
}
|
25
25
|
if (isMfaEnabled) {
|
26
26
|
return (React.createElement(Chip, { label: "Enabled", icon: React.createElement(MaterialIcon, { color: "success" }, "verified_user") }));
|
@@ -28,7 +28,7 @@ function MfaStatus({ isExternalIdentityProviderUser, isLoading, loadingError, lo
|
|
28
28
|
return (React.createElement(Chip, { label: "Disabled", icon: React.createElement(MaterialIcon, { color: "warning" }, "remove_moderator") }));
|
29
29
|
}
|
30
30
|
function MfaSetup({ ssoSetupUrl, isExternalIdentityProviderUser, }) {
|
31
|
-
const { setupError, isMfaEnabled, isDisablingMfa, isSettingUpMfa, mfaSetup, beginMfaSetup, cancelMfaSetup, completeMfaSetup, clearMfaSetupError, beginDisablingMfa, completeDisablingMfa, cancelDisablingMfa, } =
|
31
|
+
const { setupError, isMfaEnabled, isDisablingMfa, isSettingUpMfa, mfaSetup, beginMfaSetup, cancelMfaSetup, completeMfaSetup, clearMfaSetupError, beginDisablingMfa, completeDisablingMfa, cancelDisablingMfa, } = useMfa();
|
32
32
|
if (ssoSetupUrl) {
|
33
33
|
return (React.createElement(Grid, { item: true },
|
34
34
|
React.createElement(Button, { variant: "outlined", size: "small", component: "a", href: ssoSetupUrl, target: "_blank", rel: "noopener noreferrer", "data-cypress": "configure-mfa-button" }, "Configure MFA")));
|
@@ -57,7 +57,7 @@ function MfaSetup({ ssoSetupUrl, isExternalIdentityProviderUser, }) {
|
|
57
57
|
}
|
58
58
|
/**
|
59
59
|
* React Component that provides a mechanism for app users to configure Multi
|
60
|
-
* Factor Authentication. `<
|
60
|
+
* Factor Authentication. `<MfaProvider />` must be provided above this
|
61
61
|
* component in the component tree.
|
62
62
|
*
|
63
63
|
* #### Example
|
@@ -65,7 +65,7 @@ function MfaSetup({ ssoSetupUrl, isExternalIdentityProviderUser, }) {
|
|
65
65
|
* ```js
|
66
66
|
* import * as React from 'react'
|
67
67
|
* import {
|
68
|
-
*
|
68
|
+
* MfaProvider,
|
69
69
|
* MultiFactorAuthentication,
|
70
70
|
* } from '@oneblink/apps-react'
|
71
71
|
*
|
@@ -75,9 +75,9 @@ function MfaSetup({ ssoSetupUrl, isExternalIdentityProviderUser, }) {
|
|
75
75
|
*
|
76
76
|
* function App() {
|
77
77
|
* return (
|
78
|
-
* <
|
78
|
+
* <MfaProvider>
|
79
79
|
* <Component />
|
80
|
-
* </
|
80
|
+
* </MfaProvider>
|
81
81
|
* )
|
82
82
|
* }
|
83
83
|
*
|
@@ -92,7 +92,7 @@ function MfaSetup({ ssoSetupUrl, isExternalIdentityProviderUser, }) {
|
|
92
92
|
* @group Components
|
93
93
|
*/
|
94
94
|
export default function MultiFactorAuthentication({ ssoSetupUrl, isExternalIdentityProviderUser, }) {
|
95
|
-
const { loadingError, isLoading, isMfaEnabled,
|
95
|
+
const { loadingError, isLoading, isMfaEnabled, loadMfa } = useMfa();
|
96
96
|
return (React.createElement(Grid, { item: true, xs: true, lg: 8 },
|
97
97
|
React.createElement(Box, { padding: 3 },
|
98
98
|
React.createElement(Paper, null,
|
@@ -102,7 +102,7 @@ export default function MultiFactorAuthentication({ ssoSetupUrl, isExternalIdent
|
|
102
102
|
React.createElement(Typography, { variant: "h4", fontWeight: "light" },
|
103
103
|
"Multi Factor Authentication",
|
104
104
|
' ',
|
105
|
-
React.createElement(MfaStatus, {
|
105
|
+
React.createElement(MfaStatus, { loadMfa: loadMfa, isLoading: isLoading, loadingError: loadingError, isMfaEnabled: isMfaEnabled, isExternalIdentityProviderUser: !!isExternalIdentityProviderUser })),
|
106
106
|
React.createElement(Box, { marginY: 1 },
|
107
107
|
React.createElement(Divider, null)),
|
108
108
|
React.createElement(Typography, { variant: "body2", paragraph: true }, "Multi factor authentication (MFA), also known as two factor authentication (2FA), is a best practice that requires a second authentication factor in addition to user name and password sign-in credentials. We strongly recommend enabling MFA to enhance your account security."),
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"MultiFactorAuthentication.js","sourceRoot":"","sources":["../../../src/components/mfa/MultiFactorAuthentication.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport {\n Box,\n Button,\n Chip,\n CircularProgress,\n Divider,\n Grid,\n Icon,\n Paper,\n Tooltip,\n Typography,\n styled,\n} from '@mui/material'\nimport { LoadingButton } from '@mui/lab'\nimport ConfirmDialog from '../ConfirmDialog'\nimport MfaDialog from './MfaDialog'\nimport ErrorSnackbar from '../ErrorSnackbar'\nimport MaterialIcon from '../MaterialIcon'\nimport useAppUserMfa from '../../hooks/useAppUserMfa'\nimport ErrorMessage from '../messages/ErrorMessage'\n\nexport const LargeIcon = styled(Icon)(({ theme }) => ({\n fontSize: `${theme.typography.h4.fontSize} !important`,\n}))\n\ntype Props = {\n ssoSetupUrl?: string\n isExternalIdentityProviderUser?: boolean\n}\n\ntype MfaStatusProps = {\n isExternalIdentityProviderUser: boolean\n isLoading: boolean\n isMfaEnabled: boolean\n loadAppUserMfa: () => void\n loadingError?: Error\n}\n\nfunction MfaStatus({\n isExternalIdentityProviderUser,\n isLoading,\n loadingError,\n loadAppUserMfa,\n isMfaEnabled,\n}: MfaStatusProps) {\n if (isExternalIdentityProviderUser) return null\n\n if (isLoading) {\n return (\n <Box padding={3}>\n <Grid container justifyContent=\"center\">\n <CircularProgress />\n </Grid>\n </Box>\n )\n }\n\n if (loadingError) {\n return (\n <div>\n <ErrorMessage\n title=\"Error Loading Multi Factor Authentication Configuration\"\n onTryAgain={loadAppUserMfa}\n >\n {loadingError.message}\n </ErrorMessage>\n </div>\n )\n }\n\n if (isMfaEnabled) {\n return (\n <Chip\n label=\"Enabled\"\n icon={<MaterialIcon color=\"success\">verified_user</MaterialIcon>}\n />\n )\n }\n\n return (\n <Chip\n label=\"Disabled\"\n icon={<MaterialIcon color=\"warning\">remove_moderator</MaterialIcon>}\n />\n )\n}\n\nfunction MfaSetup({\n ssoSetupUrl,\n isExternalIdentityProviderUser,\n}: {\n ssoSetupUrl: string\n isExternalIdentityProviderUser: boolean\n}) {\n const {\n setupError,\n isMfaEnabled,\n isDisablingMfa,\n isSettingUpMfa,\n mfaSetup,\n beginMfaSetup,\n cancelMfaSetup,\n completeMfaSetup,\n clearMfaSetupError,\n beginDisablingMfa,\n completeDisablingMfa,\n cancelDisablingMfa,\n } = useAppUserMfa()\n\n if (ssoSetupUrl) {\n return (\n <Grid item>\n <Button\n variant=\"outlined\"\n size=\"small\"\n component=\"a\"\n href={ssoSetupUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-cypress=\"configure-mfa-button\"\n >\n Configure MFA\n </Button>\n </Grid>\n )\n }\n\n if (isExternalIdentityProviderUser) {\n return (\n <Grid item>\n <Tooltip title=\"MFA must be configured in your login provider.\">\n <span>\n <Button\n variant=\"outlined\"\n size=\"small\"\n disabled={isExternalIdentityProviderUser}\n data-cypress=\"configure-mfa-button\"\n >\n Configure MFA\n </Button>\n </span>\n </Tooltip>\n </Grid>\n )\n }\n\n return (\n <>\n <Grid item>\n <Button\n variant=\"outlined\"\n size=\"small\"\n disabled={!isMfaEnabled}\n data-cypress=\"disable-mfa-button\"\n onClick={beginDisablingMfa}\n >\n Disable MFA\n </Button>\n <ConfirmDialog\n isOpen={isDisablingMfa}\n onClose={cancelDisablingMfa}\n onConfirm={completeDisablingMfa}\n title=\"Please Confirm\"\n confirmButtonText=\"Disable MFA\"\n confirmButtonIcon={<MaterialIcon>remove_moderator</MaterialIcon>}\n cypress={{\n dialog: 'disable-mfa-dialog',\n confirmButton: 'disable-mfa-dialog-confirm-button',\n cancelButton: 'disable-mfa-dialog-cancel-button',\n error: 'disable-mfa-dialog-error-message',\n }}\n >\n <Typography variant=\"body2\">\n Are you sure want to disable multi factor authentication (MFA)?\n </Typography>\n </ConfirmDialog>\n </Grid>\n\n <Grid item>\n <LoadingButton\n variant=\"contained\"\n size=\"small\"\n loading={isSettingUpMfa}\n disabled={isMfaEnabled}\n onClick={beginMfaSetup}\n data-cypress=\"setup-mfa-button\"\n >\n Setup MFA\n </LoadingButton>\n <MfaDialog\n mfaSetup={mfaSetup}\n onClose={cancelMfaSetup}\n onCompleted={completeMfaSetup}\n />\n </Grid>\n <ErrorSnackbar open={!!setupError} onClose={clearMfaSetupError}>\n <span data-cypress=\"mfa-setup-error-message\">\n {setupError?.message}\n </span>\n </ErrorSnackbar>\n </>\n )\n}\n/**\n * React Component that provides a mechanism for app users to configure Multi\n * Factor Authentication. `<AppUserMfaProvider />` must be provided above this\n * component in the component tree.\n *\n * #### Example\n *\n * ```js\n * import * as React from 'react'\n * import {\n * AppUserMfaProvider,\n * MultiFactorAuthentication,\n * } from '@oneblink/apps-react'\n *\n * function Component() {\n * return <MultiFactorAuthentication />\n * }\n *\n * function App() {\n * return (\n * <AppUserMfaProvider>\n * <Component />\n * </AppUserMfaProvider>\n * )\n * }\n *\n * const root = document.getElementById('root')\n * if (root) {\n * ReactDOM.render(<App />, root)\n * }\n * ```\n *\n * @param props\n * @returns\n * @group Components\n */\nexport default function MultiFactorAuthentication({\n ssoSetupUrl,\n isExternalIdentityProviderUser,\n}: Props) {\n const { loadingError, isLoading, isMfaEnabled, loadAppUserMfa } =\n useAppUserMfa()\n\n return (\n <Grid item xs={true} lg={8}>\n <Box padding={3}>\n <Paper>\n <Box padding={3}>\n <Grid container spacing={2} alignItems=\"center\">\n <Grid item xs>\n <Typography variant=\"h4\" fontWeight=\"light\">\n Multi Factor Authentication{' '}\n <MfaStatus\n loadAppUserMfa={loadAppUserMfa}\n isLoading={isLoading}\n loadingError={loadingError}\n isMfaEnabled={isMfaEnabled}\n isExternalIdentityProviderUser={\n !!isExternalIdentityProviderUser\n }\n />\n </Typography>\n <Box marginY={1}>\n <Divider />\n </Box>\n <Typography variant=\"body2\" paragraph>\n Multi factor authentication (MFA), also known as two factor\n authentication (2FA), is a best practice that requires a\n second authentication factor in addition to user name and\n password sign-in credentials. We strongly recommend enabling\n MFA to enhance your account security.\n </Typography>\n <Grid container justifyContent=\"flex-end\" spacing={1}>\n <MfaSetup\n isExternalIdentityProviderUser={\n !!isExternalIdentityProviderUser\n }\n ssoSetupUrl={ssoSetupUrl || ''}\n />\n </Grid>\n </Grid>\n </Grid>\n </Box>\n </Paper>\n </Box>\n </Grid>\n )\n}\n"]}
|
1
|
+
{"version":3,"file":"MultiFactorAuthentication.js","sourceRoot":"","sources":["../../../src/components/mfa/MultiFactorAuthentication.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport {\n Box,\n Button,\n Chip,\n CircularProgress,\n Divider,\n Grid,\n Icon,\n Paper,\n Tooltip,\n Typography,\n styled,\n} from '@mui/material'\nimport { LoadingButton } from '@mui/lab'\nimport ConfirmDialog from '../ConfirmDialog'\nimport MfaDialog from './MfaDialog'\nimport ErrorSnackbar from '../ErrorSnackbar'\nimport MaterialIcon from '../MaterialIcon'\nimport useMfa from '../../hooks/useMfa'\nimport ErrorMessage from '../messages/ErrorMessage'\n\nexport const LargeIcon = styled(Icon)(({ theme }) => ({\n fontSize: `${theme.typography.h4.fontSize} !important`,\n}))\n\ntype Props = {\n ssoSetupUrl?: string\n isExternalIdentityProviderUser?: boolean\n}\n\ntype MfaStatusProps = {\n isExternalIdentityProviderUser: boolean\n isLoading: boolean\n isMfaEnabled: boolean\n loadMfa: () => void\n loadingError?: Error\n}\n\nfunction MfaStatus({\n isExternalIdentityProviderUser,\n isLoading,\n loadingError,\n loadMfa,\n isMfaEnabled,\n}: MfaStatusProps) {\n if (isExternalIdentityProviderUser) return null\n\n if (isLoading) {\n return (\n <Box padding={3}>\n <Grid container justifyContent=\"center\">\n <CircularProgress />\n </Grid>\n </Box>\n )\n }\n\n if (loadingError) {\n return (\n <div>\n <ErrorMessage\n title=\"Error Loading Multi Factor Authentication Configuration\"\n onTryAgain={loadMfa}\n >\n {loadingError.message}\n </ErrorMessage>\n </div>\n )\n }\n\n if (isMfaEnabled) {\n return (\n <Chip\n label=\"Enabled\"\n icon={<MaterialIcon color=\"success\">verified_user</MaterialIcon>}\n />\n )\n }\n\n return (\n <Chip\n label=\"Disabled\"\n icon={<MaterialIcon color=\"warning\">remove_moderator</MaterialIcon>}\n />\n )\n}\n\nfunction MfaSetup({\n ssoSetupUrl,\n isExternalIdentityProviderUser,\n}: {\n ssoSetupUrl: string\n isExternalIdentityProviderUser: boolean\n}) {\n const {\n setupError,\n isMfaEnabled,\n isDisablingMfa,\n isSettingUpMfa,\n mfaSetup,\n beginMfaSetup,\n cancelMfaSetup,\n completeMfaSetup,\n clearMfaSetupError,\n beginDisablingMfa,\n completeDisablingMfa,\n cancelDisablingMfa,\n } = useMfa()\n\n if (ssoSetupUrl) {\n return (\n <Grid item>\n <Button\n variant=\"outlined\"\n size=\"small\"\n component=\"a\"\n href={ssoSetupUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-cypress=\"configure-mfa-button\"\n >\n Configure MFA\n </Button>\n </Grid>\n )\n }\n\n if (isExternalIdentityProviderUser) {\n return (\n <Grid item>\n <Tooltip title=\"MFA must be configured in your login provider.\">\n <span>\n <Button\n variant=\"outlined\"\n size=\"small\"\n disabled={isExternalIdentityProviderUser}\n data-cypress=\"configure-mfa-button\"\n >\n Configure MFA\n </Button>\n </span>\n </Tooltip>\n </Grid>\n )\n }\n\n return (\n <>\n <Grid item>\n <Button\n variant=\"outlined\"\n size=\"small\"\n disabled={!isMfaEnabled}\n data-cypress=\"disable-mfa-button\"\n onClick={beginDisablingMfa}\n >\n Disable MFA\n </Button>\n <ConfirmDialog\n isOpen={isDisablingMfa}\n onClose={cancelDisablingMfa}\n onConfirm={completeDisablingMfa}\n title=\"Please Confirm\"\n confirmButtonText=\"Disable MFA\"\n confirmButtonIcon={<MaterialIcon>remove_moderator</MaterialIcon>}\n cypress={{\n dialog: 'disable-mfa-dialog',\n confirmButton: 'disable-mfa-dialog-confirm-button',\n cancelButton: 'disable-mfa-dialog-cancel-button',\n error: 'disable-mfa-dialog-error-message',\n }}\n >\n <Typography variant=\"body2\">\n Are you sure want to disable multi factor authentication (MFA)?\n </Typography>\n </ConfirmDialog>\n </Grid>\n\n <Grid item>\n <LoadingButton\n variant=\"contained\"\n size=\"small\"\n loading={isSettingUpMfa}\n disabled={isMfaEnabled}\n onClick={beginMfaSetup}\n data-cypress=\"setup-mfa-button\"\n >\n Setup MFA\n </LoadingButton>\n <MfaDialog\n mfaSetup={mfaSetup}\n onClose={cancelMfaSetup}\n onCompleted={completeMfaSetup}\n />\n </Grid>\n <ErrorSnackbar open={!!setupError} onClose={clearMfaSetupError}>\n <span data-cypress=\"mfa-setup-error-message\">\n {setupError?.message}\n </span>\n </ErrorSnackbar>\n </>\n )\n}\n/**\n * React Component that provides a mechanism for app users to configure Multi\n * Factor Authentication. `<MfaProvider />` must be provided above this\n * component in the component tree.\n *\n * #### Example\n *\n * ```js\n * import * as React from 'react'\n * import {\n * MfaProvider,\n * MultiFactorAuthentication,\n * } from '@oneblink/apps-react'\n *\n * function Component() {\n * return <MultiFactorAuthentication />\n * }\n *\n * function App() {\n * return (\n * <MfaProvider>\n * <Component />\n * </MfaProvider>\n * )\n * }\n *\n * const root = document.getElementById('root')\n * if (root) {\n * ReactDOM.render(<App />, root)\n * }\n * ```\n *\n * @param props\n * @returns\n * @group Components\n */\nexport default function MultiFactorAuthentication({\n ssoSetupUrl,\n isExternalIdentityProviderUser,\n}: Props) {\n const { loadingError, isLoading, isMfaEnabled, loadMfa } =\n useMfa()\n\n return (\n <Grid item xs={true} lg={8}>\n <Box padding={3}>\n <Paper>\n <Box padding={3}>\n <Grid container spacing={2} alignItems=\"center\">\n <Grid item xs>\n <Typography variant=\"h4\" fontWeight=\"light\">\n Multi Factor Authentication{' '}\n <MfaStatus\n loadMfa={loadMfa}\n isLoading={isLoading}\n loadingError={loadingError}\n isMfaEnabled={isMfaEnabled}\n isExternalIdentityProviderUser={\n !!isExternalIdentityProviderUser\n }\n />\n </Typography>\n <Box marginY={1}>\n <Divider />\n </Box>\n <Typography variant=\"body2\" paragraph>\n Multi factor authentication (MFA), also known as two factor\n authentication (2FA), is a best practice that requires a\n second authentication factor in addition to user name and\n password sign-in credentials. We strongly recommend enabling\n MFA to enhance your account security.\n </Typography>\n <Grid container justifyContent=\"flex-end\" spacing={1}>\n <MfaSetup\n isExternalIdentityProviderUser={\n !!isExternalIdentityProviderUser\n }\n ssoSetupUrl={ssoSetupUrl || ''}\n />\n </Grid>\n </Grid>\n </Grid>\n </Box>\n </Paper>\n </Box>\n </Grid>\n )\n}\n"]}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import * as React from 'react';
|
2
2
|
import { authService } from '@oneblink/apps';
|
3
|
-
type
|
3
|
+
type MfaState = {
|
4
4
|
isLoading: boolean;
|
5
5
|
isMfaEnabled: boolean;
|
6
6
|
loadingError?: Error;
|
@@ -9,7 +9,7 @@ type AppUserMfaState = {
|
|
9
9
|
setupError?: Error;
|
10
10
|
mfaSetup?: Awaited<ReturnType<typeof authService.setupMfa>>;
|
11
11
|
};
|
12
|
-
export declare const
|
12
|
+
export declare const MfaContext: React.Context<MfaState & {
|
13
13
|
beginMfaSetup: () => void;
|
14
14
|
cancelMfaSetup: () => void;
|
15
15
|
completeMfaSetup: () => void;
|
@@ -17,7 +17,7 @@ export declare const AppUserMfaContext: React.Context<AppUserMfaState & {
|
|
17
17
|
cancelDisablingMfa: () => void;
|
18
18
|
completeDisablingMfa: () => void;
|
19
19
|
clearMfaSetupError: () => void;
|
20
|
-
|
20
|
+
loadMfa: () => void;
|
21
21
|
}>;
|
22
22
|
/**
|
23
23
|
* React Component that provides the context for the
|
@@ -31,21 +31,21 @@ export declare const AppUserMfaContext: React.Context<AppUserMfaState & {
|
|
31
31
|
* ```js
|
32
32
|
* import * as React from 'react'
|
33
33
|
* import {
|
34
|
-
*
|
34
|
+
* MfaProvider,
|
35
35
|
* useUserMeetsMfaRequirement,
|
36
36
|
* } from '@oneblink/apps-react'
|
37
37
|
*
|
38
38
|
* function Component() {
|
39
39
|
* const { isLoading, userMeetsMfaRequirement } =
|
40
40
|
* useUserMeetsMfaRequirement(true)
|
41
|
-
* // use
|
41
|
+
* // use MFA Requirement details here
|
42
42
|
* }
|
43
43
|
*
|
44
44
|
* function App() {
|
45
45
|
* return (
|
46
|
-
* <
|
46
|
+
* <MfaProvider isExternalIdentityProviderUser={false}>
|
47
47
|
* <Component />
|
48
|
-
* </
|
48
|
+
* </MfaProvider>
|
49
49
|
* )
|
50
50
|
* }
|
51
51
|
*
|
@@ -59,11 +59,11 @@ export declare const AppUserMfaContext: React.Context<AppUserMfaState & {
|
|
59
59
|
* @returns
|
60
60
|
* @group Components
|
61
61
|
*/
|
62
|
-
export declare function
|
62
|
+
export declare function MfaProvider({ children, isExternalIdentityProviderUser, }: {
|
63
63
|
children: React.ReactNode;
|
64
64
|
isExternalIdentityProviderUser: boolean;
|
65
65
|
}): React.JSX.Element;
|
66
|
-
export default function
|
66
|
+
export default function useMfa(): MfaState & {
|
67
67
|
beginMfaSetup: () => void;
|
68
68
|
cancelMfaSetup: () => void;
|
69
69
|
completeMfaSetup: () => void;
|
@@ -71,11 +71,11 @@ export default function useAppUserMfa(): AppUserMfaState & {
|
|
71
71
|
cancelDisablingMfa: () => void;
|
72
72
|
completeDisablingMfa: () => void;
|
73
73
|
clearMfaSetupError: () => void;
|
74
|
-
|
74
|
+
loadMfa: () => void;
|
75
75
|
};
|
76
76
|
/**
|
77
77
|
* React hook to get the state associated to the logged in user's MFA status.
|
78
|
-
* Will throw an Error if used outside of the `<
|
78
|
+
* Will throw an Error if used outside of the `<MfaProvider />`
|
79
79
|
* component.
|
80
80
|
*
|
81
81
|
* Example
|
@@ -83,21 +83,21 @@ export default function useAppUserMfa(): AppUserMfaState & {
|
|
83
83
|
* ```js
|
84
84
|
* import { useUserMeetsMfaRequirement } from '@oneblink/apps-react'
|
85
85
|
*
|
86
|
-
* const
|
86
|
+
* const isMfaRequired = true
|
87
87
|
*
|
88
88
|
* function Component() {
|
89
89
|
* const { isLoading, userMeetsMfaRequirement } =
|
90
|
-
* useUserMeetsMfaRequirement(
|
90
|
+
* useUserMeetsMfaRequirement(isMfaRequired)
|
91
91
|
* }
|
92
92
|
* ```
|
93
93
|
*
|
94
94
|
* @returns
|
95
95
|
* @group Hooks
|
96
96
|
*/
|
97
|
-
export declare function useUserMeetsMfaRequirement(
|
97
|
+
export declare function useUserMeetsMfaRequirement(isMfaRequired: boolean): {
|
98
98
|
isLoading: boolean;
|
99
99
|
loadingError: Error | undefined;
|
100
|
-
|
100
|
+
loadMfa: () => void;
|
101
101
|
userMeetsMfaRequirement: boolean;
|
102
102
|
};
|
103
103
|
export {};
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import * as React from 'react';
|
2
2
|
import { authService } from '@oneblink/apps';
|
3
|
-
export const
|
3
|
+
export const MfaContext = React.createContext({
|
4
4
|
isLoading: true,
|
5
5
|
isMfaEnabled: false,
|
6
6
|
isSettingUpMfa: false,
|
@@ -12,7 +12,7 @@ export const AppUserMfaContext = React.createContext({
|
|
12
12
|
cancelDisablingMfa: () => { },
|
13
13
|
completeDisablingMfa: () => { },
|
14
14
|
clearMfaSetupError: () => { },
|
15
|
-
|
15
|
+
loadMfa: () => { },
|
16
16
|
});
|
17
17
|
/**
|
18
18
|
* React Component that provides the context for the
|
@@ -26,21 +26,21 @@ export const AppUserMfaContext = React.createContext({
|
|
26
26
|
* ```js
|
27
27
|
* import * as React from 'react'
|
28
28
|
* import {
|
29
|
-
*
|
29
|
+
* MfaProvider,
|
30
30
|
* useUserMeetsMfaRequirement,
|
31
31
|
* } from '@oneblink/apps-react'
|
32
32
|
*
|
33
33
|
* function Component() {
|
34
34
|
* const { isLoading, userMeetsMfaRequirement } =
|
35
35
|
* useUserMeetsMfaRequirement(true)
|
36
|
-
* // use
|
36
|
+
* // use MFA Requirement details here
|
37
37
|
* }
|
38
38
|
*
|
39
39
|
* function App() {
|
40
40
|
* return (
|
41
|
-
* <
|
41
|
+
* <MfaProvider isExternalIdentityProviderUser={false}>
|
42
42
|
* <Component />
|
43
|
-
* </
|
43
|
+
* </MfaProvider>
|
44
44
|
* )
|
45
45
|
* }
|
46
46
|
*
|
@@ -54,14 +54,14 @@ export const AppUserMfaContext = React.createContext({
|
|
54
54
|
* @returns
|
55
55
|
* @group Components
|
56
56
|
*/
|
57
|
-
export function
|
57
|
+
export function MfaProvider({ children, isExternalIdentityProviderUser, }) {
|
58
58
|
const [state, setState] = React.useState({
|
59
59
|
isLoading: !isExternalIdentityProviderUser,
|
60
60
|
isMfaEnabled: false,
|
61
61
|
isSettingUpMfa: false,
|
62
62
|
isDisablingMfa: false,
|
63
63
|
});
|
64
|
-
const
|
64
|
+
const loadMfa = React.useCallback(async (abortSignal) => {
|
65
65
|
setState((currentState) => ({
|
66
66
|
...currentState,
|
67
67
|
isLoading: true,
|
@@ -152,14 +152,14 @@ export function AppUserMfaProvider({ children, isExternalIdentityProviderUser, }
|
|
152
152
|
if (isExternalIdentityProviderUser) {
|
153
153
|
return;
|
154
154
|
}
|
155
|
-
|
155
|
+
loadMfa();
|
156
156
|
return () => { };
|
157
|
-
}, [isExternalIdentityProviderUser,
|
157
|
+
}, [isExternalIdentityProviderUser, loadMfa]);
|
158
158
|
const value = React.useMemo(() => {
|
159
159
|
return {
|
160
160
|
...state,
|
161
161
|
clearMfaSetupError,
|
162
|
-
|
162
|
+
loadMfa,
|
163
163
|
beginMfaSetup,
|
164
164
|
cancelMfaSetup,
|
165
165
|
completeMfaSetup,
|
@@ -170,7 +170,7 @@ export function AppUserMfaProvider({ children, isExternalIdentityProviderUser, }
|
|
170
170
|
}, [
|
171
171
|
state,
|
172
172
|
clearMfaSetupError,
|
173
|
-
|
173
|
+
loadMfa,
|
174
174
|
beginMfaSetup,
|
175
175
|
cancelMfaSetup,
|
176
176
|
completeMfaSetup,
|
@@ -178,14 +178,14 @@ export function AppUserMfaProvider({ children, isExternalIdentityProviderUser, }
|
|
178
178
|
cancelDisablingMfa,
|
179
179
|
completeDisablingMfa,
|
180
180
|
]);
|
181
|
-
return (React.createElement(
|
181
|
+
return (React.createElement(MfaContext.Provider, { value: value }, children));
|
182
182
|
}
|
183
|
-
export default function
|
184
|
-
return React.useContext(
|
183
|
+
export default function useMfa() {
|
184
|
+
return React.useContext(MfaContext);
|
185
185
|
}
|
186
186
|
/**
|
187
187
|
* React hook to get the state associated to the logged in user's MFA status.
|
188
|
-
* Will throw an Error if used outside of the `<
|
188
|
+
* Will throw an Error if used outside of the `<MfaProvider />`
|
189
189
|
* component.
|
190
190
|
*
|
191
191
|
* Example
|
@@ -193,36 +193,36 @@ export default function useAppUserMfa() {
|
|
193
193
|
* ```js
|
194
194
|
* import { useUserMeetsMfaRequirement } from '@oneblink/apps-react'
|
195
195
|
*
|
196
|
-
* const
|
196
|
+
* const isMfaRequired = true
|
197
197
|
*
|
198
198
|
* function Component() {
|
199
199
|
* const { isLoading, userMeetsMfaRequirement } =
|
200
|
-
* useUserMeetsMfaRequirement(
|
200
|
+
* useUserMeetsMfaRequirement(isMfaRequired)
|
201
201
|
* }
|
202
202
|
* ```
|
203
203
|
*
|
204
204
|
* @returns
|
205
205
|
* @group Hooks
|
206
206
|
*/
|
207
|
-
export function useUserMeetsMfaRequirement(
|
208
|
-
const context = React.useContext(
|
207
|
+
export function useUserMeetsMfaRequirement(isMfaRequired) {
|
208
|
+
const context = React.useContext(MfaContext);
|
209
209
|
if (!context) {
|
210
|
-
throw new Error(`"useUserMeetsMfaRequirement" hook was used outside of the "<
|
210
|
+
throw new Error(`"useUserMeetsMfaRequirement" hook was used outside of the "<MfaProvider />" component's children.`);
|
211
211
|
}
|
212
|
-
const { isLoading, loadingError,
|
213
|
-
if (!
|
212
|
+
const { isLoading, loadingError, loadMfa, isMfaEnabled } = context;
|
213
|
+
if (!isMfaRequired) {
|
214
214
|
return {
|
215
215
|
isLoading: false,
|
216
216
|
loadingError: undefined,
|
217
217
|
userMeetsMfaRequirement: true,
|
218
|
-
|
218
|
+
loadMfa,
|
219
219
|
};
|
220
220
|
}
|
221
221
|
return {
|
222
222
|
isLoading,
|
223
223
|
loadingError,
|
224
|
-
|
224
|
+
loadMfa,
|
225
225
|
userMeetsMfaRequirement: isMfaEnabled,
|
226
226
|
};
|
227
227
|
}
|
228
|
-
//# sourceMappingURL=
|
228
|
+
//# sourceMappingURL=useMfa.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"useMfa.js","sourceRoot":"","sources":["../../src/hooks/useMfa.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport { authService } from '@oneblink/apps'\n\ntype MfaState = {\n isLoading: boolean\n isMfaEnabled: boolean\n loadingError?: Error\n isSettingUpMfa: boolean\n isDisablingMfa: boolean\n setupError?: Error\n mfaSetup?: Awaited<ReturnType<typeof authService.setupMfa>>\n}\n\nexport const MfaContext = React.createContext<\n MfaState & {\n beginMfaSetup: () => void\n cancelMfaSetup: () => void\n completeMfaSetup: () => void\n beginDisablingMfa: () => void\n cancelDisablingMfa: () => void\n completeDisablingMfa: () => void\n clearMfaSetupError: () => void\n loadMfa: () => void\n }\n>({\n isLoading: true,\n isMfaEnabled: false,\n isSettingUpMfa: false,\n isDisablingMfa: false,\n beginMfaSetup: () => {},\n cancelMfaSetup: () => {},\n completeMfaSetup: () => {},\n beginDisablingMfa: () => {},\n cancelDisablingMfa: () => {},\n completeDisablingMfa: () => {},\n clearMfaSetupError: () => {},\n loadMfa: () => {},\n})\n\n/**\n * React Component that provides the context for the\n * `useUserMeetsMfaRequirement()` hook and `<MultiFactorAuthentication />`\n * component, to be used by components further down your component tree. **It\n * should only be included in your component tree once and ideally at the root\n * of the application.**\n *\n * #### Example\n *\n * ```js\n * import * as React from 'react'\n * import {\n * MfaProvider,\n * useUserMeetsMfaRequirement,\n * } from '@oneblink/apps-react'\n *\n * function Component() {\n * const { isLoading, userMeetsMfaRequirement } =\n * useUserMeetsMfaRequirement(true)\n * // use MFA Requirement details here\n * }\n *\n * function App() {\n * return (\n * <MfaProvider isExternalIdentityProviderUser={false}>\n * <Component />\n * </MfaProvider>\n * )\n * }\n *\n * const root = document.getElementById('root')\n * if (root) {\n * ReactDOM.render(<App />, root)\n * }\n * ```\n *\n * @param props\n * @returns\n * @group Components\n */\nexport function MfaProvider({\n children,\n isExternalIdentityProviderUser,\n}: {\n children: React.ReactNode\n isExternalIdentityProviderUser: boolean\n}) {\n const [state, setState] = React.useState<MfaState>({\n isLoading: !isExternalIdentityProviderUser,\n isMfaEnabled: false,\n isSettingUpMfa: false,\n isDisablingMfa: false,\n })\n\n const loadMfa = React.useCallback(\n async (abortSignal?: AbortSignal) => {\n setState((currentState) => ({\n ...currentState,\n isLoading: true,\n isMfaEnabled: false,\n loadingError: undefined,\n }))\n try {\n const newIsMfaEnabled = await authService.checkIsMfaEnabled()\n if (!abortSignal?.aborted) {\n setState((currentState) => ({\n ...currentState,\n isLoading: false,\n isMfaEnabled: newIsMfaEnabled,\n }))\n }\n } catch (error) {\n setState((currentState) => ({\n ...currentState,\n isLoading: false,\n loadingError: error as Error,\n }))\n }\n },\n [],\n )\n\n const clearMfaSetupError = React.useCallback(() => {\n setState((currentState) => ({\n ...currentState,\n setupError: undefined,\n }))\n }, [])\n\n const cancelMfaSetup = React.useCallback(() => {\n setState((currentState) => ({\n ...currentState,\n mfaSetup: undefined,\n }))\n }, [])\n\n const completeMfaSetup = React.useCallback(() => {\n setState((currentState) => ({\n ...currentState,\n isMfaEnabled: true,\n mfaSetup: undefined,\n }))\n }, [])\n\n const beginMfaSetup = React.useCallback(async () => {\n setState((currentState) => ({\n ...currentState,\n isSettingUpMfa: true,\n mfaSetup: undefined,\n setupError: undefined,\n }))\n try {\n const newMfaSetup = await authService.setupMfa()\n setState((currentState) => ({\n ...currentState,\n isSettingUpMfa: false,\n mfaSetup: newMfaSetup,\n }))\n } catch (error) {\n setState((currentState) => ({\n ...currentState,\n isSettingUpMfa: false,\n setupError: error as Error,\n }))\n }\n }, [])\n\n const beginDisablingMfa = React.useCallback(() => {\n setState((currentState) => ({\n ...currentState,\n isDisablingMfa: true,\n }))\n }, [])\n\n const cancelDisablingMfa = React.useCallback(() => {\n setState((currentState) => ({\n ...currentState,\n isDisablingMfa: false,\n }))\n }, [])\n\n const completeDisablingMfa = React.useCallback(async () => {\n await authService.disableMfa()\n setState((currentState) => ({\n ...currentState,\n isDisablingMfa: false,\n isMfaEnabled: false,\n }))\n }, [])\n\n React.useEffect(() => {\n if (isExternalIdentityProviderUser) {\n return\n }\n\n loadMfa()\n\n return () => {}\n }, [isExternalIdentityProviderUser, loadMfa])\n\n const value = React.useMemo(() => {\n return {\n ...state,\n clearMfaSetupError,\n loadMfa,\n beginMfaSetup,\n cancelMfaSetup,\n completeMfaSetup,\n beginDisablingMfa,\n cancelDisablingMfa,\n completeDisablingMfa,\n }\n }, [\n state,\n clearMfaSetupError,\n loadMfa,\n beginMfaSetup,\n cancelMfaSetup,\n completeMfaSetup,\n beginDisablingMfa,\n cancelDisablingMfa,\n completeDisablingMfa,\n ])\n\n return (\n <MfaContext.Provider value={value}>\n {children}\n </MfaContext.Provider>\n )\n}\n\nexport default function useMfa() {\n return React.useContext(MfaContext)\n}\n\n/**\n * React hook to get the state associated to the logged in user's MFA status.\n * Will throw an Error if used outside of the `<MfaProvider />`\n * component.\n *\n * Example\n *\n * ```js\n * import { useUserMeetsMfaRequirement } from '@oneblink/apps-react'\n *\n * const isMfaRequired = true\n *\n * function Component() {\n * const { isLoading, userMeetsMfaRequirement } =\n * useUserMeetsMfaRequirement(isMfaRequired)\n * }\n * ```\n *\n * @returns\n * @group Hooks\n */\nexport function useUserMeetsMfaRequirement(isMfaRequired: boolean) {\n const context = React.useContext(MfaContext)\n\n if (!context) {\n throw new Error(\n `\"useUserMeetsMfaRequirement\" hook was used outside of the \"<MfaProvider />\" component's children.`,\n )\n }\n\n const { isLoading, loadingError, loadMfa, isMfaEnabled } = context\n\n if (!isMfaRequired) {\n return {\n isLoading: false,\n loadingError: undefined,\n userMeetsMfaRequirement: true,\n loadMfa,\n }\n }\n\n return {\n isLoading,\n loadingError,\n loadMfa,\n userMeetsMfaRequirement: isMfaEnabled,\n }\n}\n"]}
|
package/dist/index.d.ts
CHANGED
@@ -26,6 +26,9 @@ export { default as useGoogleJsApiLoader } from './hooks/useGoogleJsApiLoader';
|
|
26
26
|
export { default as ProgressBar } from './components/renderer/ProgressBar';
|
27
27
|
export { default as PaymentReceipt } from './PaymentReceipt';
|
28
28
|
export { default as PaymentForm } from './components/payments/PaymentForm';
|
29
|
+
export { default as CalendarBookingsForm } from './components/calendar-bookings/CalendarBookingsForm';
|
30
|
+
export { default as CalendarBookingsRescheduleForm } from './components/calendar-bookings/CalendarBookingsReschedulingForm';
|
31
|
+
export { default as CalendarBookingsCancelForm } from './components/calendar-bookings/CalendarBookingsCancelForm';
|
29
32
|
export { default as MultiFactorAuthentication } from './components/mfa/MultiFactorAuthentication';
|
30
|
-
export { default as
|
33
|
+
export { default as useMfa, MfaProvider, useUserMeetsMfaRequirement, } from './hooks/useMfa';
|
31
34
|
export * from './types/form';
|
package/dist/index.js
CHANGED
@@ -26,7 +26,10 @@ export { default as useGoogleJsApiLoader } from './hooks/useGoogleJsApiLoader';
|
|
26
26
|
export { default as ProgressBar } from './components/renderer/ProgressBar';
|
27
27
|
export { default as PaymentReceipt } from './PaymentReceipt';
|
28
28
|
export { default as PaymentForm } from './components/payments/PaymentForm';
|
29
|
+
export { default as CalendarBookingsForm } from './components/calendar-bookings/CalendarBookingsForm';
|
30
|
+
export { default as CalendarBookingsRescheduleForm } from './components/calendar-bookings/CalendarBookingsReschedulingForm';
|
31
|
+
export { default as CalendarBookingsCancelForm } from './components/calendar-bookings/CalendarBookingsCancelForm';
|
29
32
|
export { default as MultiFactorAuthentication } from './components/mfa/MultiFactorAuthentication';
|
30
|
-
export { default as
|
33
|
+
export { default as useMfa, MfaProvider, useUserMeetsMfaRequirement, } from './hooks/useMfa';
|
31
34
|
export * from './types/form';
|
32
35
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,wBAAwB,IAAI,YAAY,EACxC,sBAAsB,GACvB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AACxE,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AACxE,OAAO,EAAE,yBAAyB,EAAE,MAAM,kDAAkD,CAAA;AAC5F,OAAO,EAAE,OAAO,IAAI,mCAAmC,EAAE,MAAM,4DAA4D,CAAA;AAC3H,OAAO,EAAE,OAAO,IAAI,8BAA8B,EAAE,MAAM,uDAAuD,CAAA;AACjH,OAAO,EAAE,OAAO,IAAI,+BAA+B,EAAE,MAAM,wDAAwD,CAAA;AACnH,OAAO,EAAE,OAAO,IAAI,8BAA8B,EAAE,MAAM,uDAAuD,CAAA;AACjH,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAE,MAAM,+CAA+C,CAAA;AAEjG,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAC9D,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACpE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AACtE,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAE,MAAM,gCAAgC,CAAA;AAClF,OAAO,EACL,OAAO,IAAI,YAAY,EACvB,wBAAwB,GACzB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAiB,MAAM,kBAAkB,CAAA;AACrE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,EACL,OAAO,IAAI,OAAO,EAClB,mBAAmB,GAEpB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,OAAO,IAAI,qBAAqB,EAChC,iCAAiC,GAElC,MAAM,+BAA+B,CAAA;AACtC,OAAO,EACL,OAAO,IAAI,SAAS,EACpB,qBAAqB,GAEtB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,OAAO,IAAI,gBAAgB,GAE5B,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AAChF,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AACxE,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAE,MAAM,gCAAgC,CAAA;AAClF,OAAO,EAAE,OAAO,IAAI,8BAA8B,EAAE,MAAM,wCAAwC,CAAA;AAClG,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AAE9E,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,mCAAmC,CAAA;AAC1E,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,mCAAmC,CAAA;AAE1E,OAAO,EAAE,OAAO,IAAI,yBAAyB,EAAE,MAAM,4CAA4C,CAAA;AAEjG,OAAO,EACL,OAAO,IAAI,
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,wBAAwB,IAAI,YAAY,EACxC,sBAAsB,GACvB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AACxE,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AACxE,OAAO,EAAE,yBAAyB,EAAE,MAAM,kDAAkD,CAAA;AAC5F,OAAO,EAAE,OAAO,IAAI,mCAAmC,EAAE,MAAM,4DAA4D,CAAA;AAC3H,OAAO,EAAE,OAAO,IAAI,8BAA8B,EAAE,MAAM,uDAAuD,CAAA;AACjH,OAAO,EAAE,OAAO,IAAI,+BAA+B,EAAE,MAAM,wDAAwD,CAAA;AACnH,OAAO,EAAE,OAAO,IAAI,8BAA8B,EAAE,MAAM,uDAAuD,CAAA;AACjH,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAE,MAAM,+CAA+C,CAAA;AAEjG,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAC9D,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACpE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AACtE,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAE,MAAM,gCAAgC,CAAA;AAClF,OAAO,EACL,OAAO,IAAI,YAAY,EACvB,wBAAwB,GACzB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAiB,MAAM,kBAAkB,CAAA;AACrE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,EACL,OAAO,IAAI,OAAO,EAClB,mBAAmB,GAEpB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,OAAO,IAAI,qBAAqB,EAChC,iCAAiC,GAElC,MAAM,+BAA+B,CAAA;AACtC,OAAO,EACL,OAAO,IAAI,SAAS,EACpB,qBAAqB,GAEtB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,OAAO,IAAI,gBAAgB,GAE5B,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AAChF,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AACxE,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAE,MAAM,gCAAgC,CAAA;AAClF,OAAO,EAAE,OAAO,IAAI,8BAA8B,EAAE,MAAM,wCAAwC,CAAA;AAClG,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AAE9E,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,mCAAmC,CAAA;AAC1E,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,mCAAmC,CAAA;AAE1E,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,qDAAqD,CAAA;AACrG,OAAO,EAAE,OAAO,IAAI,8BAA8B,EAAE,MAAM,iEAAiE,CAAA;AAC3H,OAAO,EAAE,OAAO,IAAI,0BAA0B,EAAE,MAAM,2DAA2D,CAAA;AAEjH,OAAO,EAAE,OAAO,IAAI,yBAAyB,EAAE,MAAM,4CAA4C,CAAA;AAEjG,OAAO,EACL,OAAO,IAAI,MAAM,EACjB,WAAW,EACX,0BAA0B,GAC3B,MAAM,gBAAgB,CAAA;AAEvB,cAAc,cAAc,CAAA","sourcesContent":["export {\n OneBlinkFormBaseProps,\n OneBlinkFormControlledProps,\n OneBlinkFormUncontrolled as OneBlinkForm,\n OneBlinkFormControlled,\n} from './OneBlinkForm'\nexport { default as OneBlinkAutoSaveForm } from './OneBlinkAutoSaveForm'\nexport { default as OneBlinkReadOnlyForm } from './OneBlinkReadOnlyForm'\nexport { OneBlinkFormStoreProvider } from './components/formStore/OneBlinkFormStoreProvider'\nexport { default as OneBlinkFormStoreClearFiltersButton } from './components/formStore/OneBlinkFormStoreClearFiltersButton'\nexport { default as OneBlinkFormStoreColumnsButton } from './components/formStore/OneBlinkFormStoreColumnsButton'\nexport { default as OneBlinkFormStoreDownloadButton } from './components/formStore/OneBlinkFormStoreDownloadButton'\nexport { default as OneBlinkFormStoreRefreshButton } from './components/formStore/OneBlinkFormStoreRefreshButton'\nexport { default as OneBlinkFormStoreTable } from './components/formStore/OneBlinkFormStoreTable'\n\nexport { default as useIsMounted } from './hooks/useIsMounted'\nexport { default as useBooleanState } from './hooks/useBooleanState'\nexport { default as useNullableState } from './hooks/useNullableState'\nexport { default as useClickOutsideElement } from './hooks/useClickOutsideElement'\nexport {\n default as useIsOffline,\n IsOfflineContextProvider,\n} from './hooks/useIsOffline'\nexport { default as useLogin, UseLoginValue } from './hooks/useLogin'\nexport { default as useSignUp } from './hooks/useSignUp'\nexport {\n default as useAuth,\n AuthContextProvider,\n AuthContextValue,\n} from './hooks/useAuth'\nexport {\n default as usePendingSubmissions,\n PendingSubmissionsContextProvider,\n PendingSubmissionsContextValue,\n} from './hooks/usePendingSubmissions'\nexport {\n default as useDrafts,\n DraftsContextProvider,\n DraftsContextValue,\n} from './hooks/useDrafts'\nexport {\n default as useLoadDataState,\n LoadDataState,\n} from './hooks/useLoadDataState'\nexport { default as useLoadResourcesState } from './hooks/useLoadResourcesState'\nexport { default as useLoadDataEffect } from './hooks/useLoadDataEffect'\nexport { default as useFormSubmissionState } from './hooks/useFormSubmissionState'\nexport { default as useFormSubmissionAutoSaveState } from './hooks/useFormSubmissionAutoSaveState'\nexport { default as useGoogleJsApiLoader } from './hooks/useGoogleJsApiLoader'\n\nexport { default as ProgressBar } from './components/renderer/ProgressBar'\nexport { default as PaymentReceipt } from './PaymentReceipt'\nexport { default as PaymentForm } from './components/payments/PaymentForm'\n\nexport { default as CalendarBookingsForm } from './components/calendar-bookings/CalendarBookingsForm'\nexport { default as CalendarBookingsRescheduleForm } from './components/calendar-bookings/CalendarBookingsReschedulingForm'\nexport { default as CalendarBookingsCancelForm } from './components/calendar-bookings/CalendarBookingsCancelForm'\n\nexport { default as MultiFactorAuthentication } from './components/mfa/MultiFactorAuthentication'\n\nexport {\n default as useMfa,\n MfaProvider,\n useUserMeetsMfaRequirement,\n} from './hooks/useMfa'\n\nexport * from './types/form'\n"]}
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@oneblink/apps-react",
|
3
3
|
"description": "Helper functions for OneBlink apps in ReactJS.",
|
4
|
-
"version": "6.10.0-beta.
|
4
|
+
"version": "6.10.0-beta.8",
|
5
5
|
"author": "OneBlink <developers@oneblink.io> (https://oneblink.io)",
|
6
6
|
"bugs": {
|
7
7
|
"url": "https://github.com/oneblink/apps-react/issues"
|
@@ -10,6 +10,7 @@
|
|
10
10
|
"@arcgis/core": "~4.29.10",
|
11
11
|
"@emotion/react": "^11.11.3",
|
12
12
|
"@emotion/styled": "^11.11.0",
|
13
|
+
"@nylas/react": "^1.3.1",
|
13
14
|
"@oneblink/sdk-core": "^7.3.1-beta.1",
|
14
15
|
"@react-google-maps/api": "2.19.2",
|
15
16
|
"blueimp-load-image": "^5.16.0",
|
@@ -1,7 +0,0 @@
|
|
1
|
-
import * as React from 'react';
|
2
|
-
import { Button } from '@mui/material';
|
3
|
-
type Props = {
|
4
|
-
loading: boolean;
|
5
|
-
} & React.ComponentProps<typeof Button>;
|
6
|
-
declare const _default: React.MemoExoticComponent<({ loading, color, disabled, ...props }: Props) => React.JSX.Element>;
|
7
|
-
export default _default;
|
@@ -1,12 +0,0 @@
|
|
1
|
-
import * as React from 'react';
|
2
|
-
import { CircularProgress, Button } from '@mui/material';
|
3
|
-
const LoadingButton = ({ loading, color, disabled, ...props }) => {
|
4
|
-
return (React.createElement(Button, { color: color, disabled: loading || disabled, ...props },
|
5
|
-
React.createElement(React.Fragment, null,
|
6
|
-
React.createElement("span", { style: { opacity: loading ? 0 : undefined } }, props.children),
|
7
|
-
loading && (React.createElement(CircularProgress, { color: color, style: {
|
8
|
-
position: 'absolute',
|
9
|
-
}, size: 24 })))));
|
10
|
-
};
|
11
|
-
export default React.memo(LoadingButton);
|
12
|
-
//# sourceMappingURL=LoadingButton.js.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"LoadingButton.js","sourceRoot":"","sources":["../../src/components/LoadingButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAKxD,MAAM,aAAa,GAAG,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAS,EAAE,EAAE;IACtE,OAAO,CACL,oBAAC,MAAM,IAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,IAAI,QAAQ,KAAM,KAAK;QAC5D;YACE,8BAAM,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,IAC9C,KAAK,CAAC,QAAQ,CACV;YACN,OAAO,IAAI,CACV,oBAAC,gBAAgB,IACf,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE;oBACL,QAAQ,EAAE,UAAU;iBACrB,EACD,IAAI,EAAE,EAAE,GACU,CACrB,CACA,CACI,CACV,CAAA;AACH,CAAC,CAAA;AACD,eAAe,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA","sourcesContent":["import * as React from 'react'\nimport { CircularProgress, Button } from '@mui/material'\n\ntype Props = {\n loading: boolean\n} & React.ComponentProps<typeof Button>\nconst LoadingButton = ({ loading, color, disabled, ...props }: Props) => {\n return (\n <Button color={color} disabled={loading || disabled} {...props}>\n <>\n <span style={{ opacity: loading ? 0 : undefined }}>\n {props.children}\n </span>\n {loading && (\n <CircularProgress\n color={color}\n style={{\n position: 'absolute',\n }}\n size={24}\n ></CircularProgress>\n )}\n </>\n </Button>\n )\n}\nexport default React.memo(LoadingButton)\n"]}
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"useAppUserMfa.js","sourceRoot":"","sources":["../../src/hooks/useAppUserMfa.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAY5C,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC,aAAa,CAWlD;IACA,SAAS,EAAE,IAAI;IACf,YAAY,EAAE,KAAK;IACnB,cAAc,EAAE,KAAK;IACrB,cAAc,EAAE,KAAK;IACrB,aAAa,EAAE,GAAG,EAAE,GAAE,CAAC;IACvB,cAAc,EAAE,GAAG,EAAE,GAAE,CAAC;IACxB,gBAAgB,EAAE,GAAG,EAAE,GAAE,CAAC;IAC1B,iBAAiB,EAAE,GAAG,EAAE,GAAE,CAAC;IAC3B,kBAAkB,EAAE,GAAG,EAAE,GAAE,CAAC;IAC5B,oBAAoB,EAAE,GAAG,EAAE,GAAE,CAAC;IAC9B,kBAAkB,EAAE,GAAG,EAAE,GAAE,CAAC;IAC5B,cAAc,EAAE,GAAG,EAAE,GAAE,CAAC;CACzB,CAAC,CAAA;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,UAAU,kBAAkB,CAAC,EACjC,QAAQ,EACR,8BAA8B,GAI/B;IACC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAkB;QACxD,SAAS,EAAE,CAAC,8BAA8B;QAC1C,YAAY,EAAE,KAAK;QACnB,cAAc,EAAE,KAAK;QACrB,cAAc,EAAE,KAAK;KACtB,CAAC,CAAA;IAEF,MAAM,cAAc,GAAG,KAAK,CAAC,WAAW,CACtC,KAAK,EAAE,WAAyB,EAAE,EAAE;QAClC,QAAQ,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;YAC1B,GAAG,YAAY;YACf,SAAS,EAAE,IAAI;YACf,YAAY,EAAE,KAAK;YACnB,YAAY,EAAE,SAAS;SACxB,CAAC,CAAC,CAAA;QACH,IAAI,CAAC;YACH,MAAM,eAAe,GAAG,MAAM,WAAW,CAAC,iBAAiB,EAAE,CAAA;YAC7D,IAAI,CAAC,CAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,OAAO,CAAA,EAAE,CAAC;gBAC1B,QAAQ,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;oBAC1B,GAAG,YAAY;oBACf,SAAS,EAAE,KAAK;oBAChB,YAAY,EAAE,eAAe;iBAC9B,CAAC,CAAC,CAAA;YACL,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,QAAQ,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;gBAC1B,GAAG,YAAY;gBACf,SAAS,EAAE,KAAK;gBAChB,YAAY,EAAE,KAAc;aAC7B,CAAC,CAAC,CAAA;QACL,CAAC;IACH,CAAC,EACD,EAAE,CACH,CAAA;IAED,MAAM,kBAAkB,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE;QAChD,QAAQ,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;YAC1B,GAAG,YAAY;YACf,UAAU,EAAE,SAAS;SACtB,CAAC,CAAC,CAAA;IACL,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,MAAM,cAAc,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE;QAC5C,QAAQ,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;YAC1B,GAAG,YAAY;YACf,QAAQ,EAAE,SAAS;SACpB,CAAC,CAAC,CAAA;IACL,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,MAAM,gBAAgB,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE;QAC9C,QAAQ,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;YAC1B,GAAG,YAAY;YACf,YAAY,EAAE,IAAI;YAClB,QAAQ,EAAE,SAAS;SACpB,CAAC,CAAC,CAAA;IACL,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,MAAM,aAAa,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,IAAI,EAAE;QACjD,QAAQ,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;YAC1B,GAAG,YAAY;YACf,cAAc,EAAE,IAAI;YACpB,QAAQ,EAAE,SAAS;YACnB,UAAU,EAAE,SAAS;SACtB,CAAC,CAAC,CAAA;QACH,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE,CAAA;YAChD,QAAQ,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;gBAC1B,GAAG,YAAY;gBACf,cAAc,EAAE,KAAK;gBACrB,QAAQ,EAAE,WAAW;aACtB,CAAC,CAAC,CAAA;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,QAAQ,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;gBAC1B,GAAG,YAAY;gBACf,cAAc,EAAE,KAAK;gBACrB,UAAU,EAAE,KAAc;aAC3B,CAAC,CAAC,CAAA;QACL,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,MAAM,iBAAiB,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE;QAC/C,QAAQ,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;YAC1B,GAAG,YAAY;YACf,cAAc,EAAE,IAAI;SACrB,CAAC,CAAC,CAAA;IACL,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,MAAM,kBAAkB,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE;QAChD,QAAQ,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;YAC1B,GAAG,YAAY;YACf,cAAc,EAAE,KAAK;SACtB,CAAC,CAAC,CAAA;IACL,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,MAAM,oBAAoB,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,IAAI,EAAE;QACxD,MAAM,WAAW,CAAC,UAAU,EAAE,CAAA;QAC9B,QAAQ,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;YAC1B,GAAG,YAAY;YACf,cAAc,EAAE,KAAK;YACrB,YAAY,EAAE,KAAK;SACpB,CAAC,CAAC,CAAA;IACL,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,IAAI,8BAA8B,EAAE,CAAC;YACnC,OAAM;QACR,CAAC;QAED,cAAc,EAAE,CAAA;QAEhB,OAAO,GAAG,EAAE,GAAE,CAAC,CAAA;IACjB,CAAC,EAAE,CAAC,8BAA8B,EAAE,cAAc,CAAC,CAAC,CAAA;IAEpD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QAC/B,OAAO;YACL,GAAG,KAAK;YACR,kBAAkB;YAClB,cAAc;YACd,aAAa;YACb,cAAc;YACd,gBAAgB;YAChB,iBAAiB;YACjB,kBAAkB;YAClB,oBAAoB;SACrB,CAAA;IACH,CAAC,EAAE;QACD,KAAK;QACL,kBAAkB;QAClB,cAAc;QACd,aAAa;QACb,cAAc;QACd,gBAAgB;QAChB,iBAAiB;QACjB,kBAAkB;QAClB,oBAAoB;KACrB,CAAC,CAAA;IAEF,OAAO,CACL,oBAAC,iBAAiB,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,IACrC,QAAQ,CACkB,CAC9B,CAAA;AACH,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,aAAa;IACnC,OAAO,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAA;AAC5C,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,0BAA0B,CAAC,oBAA6B;IACtE,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAA;IAEnD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,0GAA0G,CAC3G,CAAA;IACH,CAAC;IAED,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,GAAG,OAAO,CAAA;IAEzE,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC1B,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,YAAY,EAAE,SAAS;YACvB,uBAAuB,EAAE,IAAI;YAC7B,cAAc;SACf,CAAA;IACH,CAAC;IAED,OAAO;QACL,SAAS;QACT,YAAY;QACZ,cAAc;QACd,uBAAuB,EAAE,YAAY;KACtC,CAAA;AACH,CAAC","sourcesContent":["import * as React from 'react'\nimport { authService } from '@oneblink/apps'\n\ntype AppUserMfaState = {\n isLoading: boolean\n isMfaEnabled: boolean\n loadingError?: Error\n isSettingUpMfa: boolean\n isDisablingMfa: boolean\n setupError?: Error\n mfaSetup?: Awaited<ReturnType<typeof authService.setupMfa>>\n}\n\nexport const AppUserMfaContext = React.createContext<\n AppUserMfaState & {\n beginMfaSetup: () => void\n cancelMfaSetup: () => void\n completeMfaSetup: () => void\n beginDisablingMfa: () => void\n cancelDisablingMfa: () => void\n completeDisablingMfa: () => void\n clearMfaSetupError: () => void\n loadAppUserMfa: () => void\n }\n>({\n isLoading: true,\n isMfaEnabled: false,\n isSettingUpMfa: false,\n isDisablingMfa: false,\n beginMfaSetup: () => {},\n cancelMfaSetup: () => {},\n completeMfaSetup: () => {},\n beginDisablingMfa: () => {},\n cancelDisablingMfa: () => {},\n completeDisablingMfa: () => {},\n clearMfaSetupError: () => {},\n loadAppUserMfa: () => {},\n})\n\n/**\n * React Component that provides the context for the\n * `useUserMeetsMfaRequirement()` hook and `<MultiFactorAuthentication />`\n * component, to be used by components further down your component tree. **It\n * should only be included in your component tree once and ideally at the root\n * of the application.**\n *\n * #### Example\n *\n * ```js\n * import * as React from 'react'\n * import {\n * AppUserMfaProvider,\n * useUserMeetsMfaRequirement,\n * } from '@oneblink/apps-react'\n *\n * function Component() {\n * const { isLoading, userMeetsMfaRequirement } =\n * useUserMeetsMfaRequirement(true)\n * // use App User MFA Requirement details here\n * }\n *\n * function App() {\n * return (\n * <AppUserMfaProvider isExternalIdentityProviderUser={false}>\n * <Component />\n * </AppUserMfaProvider>\n * )\n * }\n *\n * const root = document.getElementById('root')\n * if (root) {\n * ReactDOM.render(<App />, root)\n * }\n * ```\n *\n * @param props\n * @returns\n * @group Components\n */\nexport function AppUserMfaProvider({\n children,\n isExternalIdentityProviderUser,\n}: {\n children: React.ReactNode\n isExternalIdentityProviderUser: boolean\n}) {\n const [state, setState] = React.useState<AppUserMfaState>({\n isLoading: !isExternalIdentityProviderUser,\n isMfaEnabled: false,\n isSettingUpMfa: false,\n isDisablingMfa: false,\n })\n\n const loadAppUserMfa = React.useCallback(\n async (abortSignal?: AbortSignal) => {\n setState((currentState) => ({\n ...currentState,\n isLoading: true,\n isMfaEnabled: false,\n loadingError: undefined,\n }))\n try {\n const newIsMfaEnabled = await authService.checkIsMfaEnabled()\n if (!abortSignal?.aborted) {\n setState((currentState) => ({\n ...currentState,\n isLoading: false,\n isMfaEnabled: newIsMfaEnabled,\n }))\n }\n } catch (error) {\n setState((currentState) => ({\n ...currentState,\n isLoading: false,\n loadingError: error as Error,\n }))\n }\n },\n [],\n )\n\n const clearMfaSetupError = React.useCallback(() => {\n setState((currentState) => ({\n ...currentState,\n setupError: undefined,\n }))\n }, [])\n\n const cancelMfaSetup = React.useCallback(() => {\n setState((currentState) => ({\n ...currentState,\n mfaSetup: undefined,\n }))\n }, [])\n\n const completeMfaSetup = React.useCallback(() => {\n setState((currentState) => ({\n ...currentState,\n isMfaEnabled: true,\n mfaSetup: undefined,\n }))\n }, [])\n\n const beginMfaSetup = React.useCallback(async () => {\n setState((currentState) => ({\n ...currentState,\n isSettingUpMfa: true,\n mfaSetup: undefined,\n setupError: undefined,\n }))\n try {\n const newMfaSetup = await authService.setupMfa()\n setState((currentState) => ({\n ...currentState,\n isSettingUpMfa: false,\n mfaSetup: newMfaSetup,\n }))\n } catch (error) {\n setState((currentState) => ({\n ...currentState,\n isSettingUpMfa: false,\n setupError: error as Error,\n }))\n }\n }, [])\n\n const beginDisablingMfa = React.useCallback(() => {\n setState((currentState) => ({\n ...currentState,\n isDisablingMfa: true,\n }))\n }, [])\n\n const cancelDisablingMfa = React.useCallback(() => {\n setState((currentState) => ({\n ...currentState,\n isDisablingMfa: false,\n }))\n }, [])\n\n const completeDisablingMfa = React.useCallback(async () => {\n await authService.disableMfa()\n setState((currentState) => ({\n ...currentState,\n isDisablingMfa: false,\n isMfaEnabled: false,\n }))\n }, [])\n\n React.useEffect(() => {\n if (isExternalIdentityProviderUser) {\n return\n }\n\n loadAppUserMfa()\n\n return () => {}\n }, [isExternalIdentityProviderUser, loadAppUserMfa])\n\n const value = React.useMemo(() => {\n return {\n ...state,\n clearMfaSetupError,\n loadAppUserMfa,\n beginMfaSetup,\n cancelMfaSetup,\n completeMfaSetup,\n beginDisablingMfa,\n cancelDisablingMfa,\n completeDisablingMfa,\n }\n }, [\n state,\n clearMfaSetupError,\n loadAppUserMfa,\n beginMfaSetup,\n cancelMfaSetup,\n completeMfaSetup,\n beginDisablingMfa,\n cancelDisablingMfa,\n completeDisablingMfa,\n ])\n\n return (\n <AppUserMfaContext.Provider value={value}>\n {children}\n </AppUserMfaContext.Provider>\n )\n}\n\nexport default function useAppUserMfa() {\n return React.useContext(AppUserMfaContext)\n}\n\n/**\n * React hook to get the state associated to the logged in user's MFA status.\n * Will throw an Error if used outside of the `<AppUserMfaProvider />`\n * component.\n *\n * Example\n *\n * ```js\n * import { useUserMeetsMfaRequirement } from '@oneblink/apps-react'\n *\n * const isAppUserMfaRequired = true\n *\n * function Component() {\n * const { isLoading, userMeetsMfaRequirement } =\n * useUserMeetsMfaRequirement(isAppUserMfaRequired)\n * }\n * ```\n *\n * @returns\n * @group Hooks\n */\nexport function useUserMeetsMfaRequirement(isAppUserMfaRequired: boolean) {\n const context = React.useContext(AppUserMfaContext)\n\n if (!context) {\n throw new Error(\n `\"useUserMeetsMfaRequirement\" hook was used outside of the \"<AppUserMfaProvider />\" component's children.`,\n )\n }\n\n const { isLoading, loadingError, loadAppUserMfa, isMfaEnabled } = context\n\n if (!isAppUserMfaRequired) {\n return {\n isLoading: false,\n loadingError: undefined,\n userMeetsMfaRequirement: true,\n loadAppUserMfa,\n }\n }\n\n return {\n isLoading,\n loadingError,\n loadAppUserMfa,\n userMeetsMfaRequirement: isMfaEnabled,\n }\n}\n"]}
|