diff --git a/example/onboarding-example/index.jsx b/example/onboarding-example/index.jsx index 33be69f6..b660196b 100644 --- a/example/onboarding-example/index.jsx +++ b/example/onboarding-example/index.jsx @@ -4,7 +4,7 @@ import { Button, Container, useToggle } from '@openedx/paragon'; import getAllPossibleQueryParams from '../../src/data/utils'; import { - ResetPasswordComponent, SignInComponent, SignUpComponent, + ResetPasswordComponent, SignInComponent, SignUpComponent, WelcomePageComponent, } from '../../src/onboarding-component'; import './index.scss'; @@ -16,6 +16,7 @@ import './index.scss'; const OnBoardingExampleContainer = () => { const [isSignUpFormOpen, setSignUpFormOpen, setSignUpFormClose] = useToggle(false); const [isSignInFormOpen, setSignInFormOpen, setSignInFormClose] = useToggle(false); + const [isWelcomeFormOpen, setWelcomeFormOpen, setWelcomeFormClose] = useToggle(false); const [isResetPasswordFormOpen, setResetPasswordFormOpen, setResetPasswordFormClose] = useToggle(false); const queryParam = getAllPossibleQueryParams(); @@ -24,13 +25,18 @@ const OnBoardingExampleContainer = () => { const url = new URL(window.location.href); const path = url.pathname; - if (path === '/login' || path === '/register' || path.startsWith('/password_reset_confirm')) { + if (path === '/login' + || path === '/register' + || path === '/welcome' + || path.startsWith('/password_reset_confirm')) { const searchParams = new URLSearchParams(url.search); if (path === '/login') { searchParams.set('authMode', 'Login'); } else if (path === '/register') { searchParams.set('authMode', 'Register'); + } else if (path === '/welcome') { + searchParams.set('authMode', 'Welcome'); } else if (path.startsWith('/password_reset_confirm')) { searchParams.set('authMode', 'PasswordResetConfirm'); @@ -50,10 +56,12 @@ const OnBoardingExampleContainer = () => { setSignInFormOpen(); } else if (queryParam?.authMode === 'Register') { setSignUpFormOpen(); + } else if (queryParam?.authMode === 'Welcome') { + setWelcomeFormOpen(); } else if (queryParam?.authMode === 'PasswordResetConfirm') { setResetPasswordFormOpen(); } - }, [setSignInFormOpen, setSignUpFormOpen, setResetPasswordFormOpen, queryParam?.authMode]); + }, [setSignInFormOpen, setSignUpFormOpen, setResetPasswordFormOpen, queryParam?.authMode, setWelcomeFormOpen]); return ( <> @@ -83,6 +91,10 @@ const OnBoardingExampleContainer = () => { isOpen={isSignInFormOpen} context={{}} /> + state.register.registrationFields); + // temporary code for testing + const registrationParams = { + // ...registrationFields, + totalRegistrationTime: 0, + app_name: 'onboarding-component', + marketing_emails_opt_in: false, + }; + if (!provider) { return null; } + const prepareFinalUrl = (url, paramKey, paramValue) => { + const urlObj = new URL(url, getConfig().LMS_BASE_URL); + urlObj.searchParams.set(paramKey, paramValue); + return urlObj.toString(); + }; + const { id: providerId, name: providerName, @@ -52,8 +66,14 @@ export const SocialAuthButton = forwardRef(({ if (!isLoginForm) { setCookie('marketingEmailsOptIn', registrationFields?.marketingEmailsOptIn); } + // const url = updateNextQueryParam(e.currentTarget.dataset.providerUrl); const url = e.currentTarget.dataset.providerUrl; - window.location.href = getConfig().LMS_BASE_URL + url; + // eslint-disable-next-line max-len + // const finalUrl = prepareFinalUrl(url, 'marketing_emails_opt_in', registrationFields?.marketingEmailsOptIn.toString()); + + const finalUrl = prepareFinalUrl(url, 'registration_params', JSON.stringify(registrationParams)); + console.log('final url = ', finalUrl); + window.location.href = finalUrl; }; return ( diff --git a/src/data/constants.js b/src/data/constants.js index cebe2edb..90d2062f 100644 --- a/src/data/constants.js +++ b/src/data/constants.js @@ -5,7 +5,7 @@ export const FORGOT_PASSWORD_FORM = 'forgot-password'; export const RESET_PASSWORD_FORM = 'reset-password'; export const PROGRESSIVE_PROFILING_FORM = 'progressive-profiling'; export const ENTERPRISE_LOGIN = 'enterprise-login'; -export const VALID_FORMS = [LOGIN_FORM, REGISTRATION_FORM, RESET_PASSWORD_FORM]; +export const VALID_FORMS = [LOGIN_FORM, REGISTRATION_FORM, RESET_PASSWORD_FORM, PROGRESSIVE_PROFILING_FORM]; // Common States export const DEFAULT_STATE = 'default'; @@ -30,6 +30,7 @@ export const ENTERPRISE_LOGIN_URL = '/enterprise/login'; export const VALID_AUTH_PARAMS = [ 'course_id', 'enrollment_action', 'course_mode', 'email_opt_in', 'purchase_workflow', 'next', 'tpa_hint', 'account_activation_status', 'authMode', 'password_reset_token', + 'from_tpa_pipeline', ]; export const AUTH_MODE = 'authMode'; diff --git a/src/forms/common-components/AuthenticatedRedirection.jsx b/src/forms/common-components/AuthenticatedRedirection.jsx index c67d2eb3..73992fe5 100644 --- a/src/forms/common-components/AuthenticatedRedirection.jsx +++ b/src/forms/common-components/AuthenticatedRedirection.jsx @@ -31,17 +31,17 @@ const AuthenticatedRedirection = ({ redirectToProgressiveProfilingForm = false, success = false, isLinkTracked = false, + shouldUseRedirectUrl = false, }) => { const dispatch = useDispatch(); if (success) { let finalRedirectUrl = ''; - // If we're in a third party auth pipeline, we must complete the pipeline // once user has successfully logged in. Otherwise, redirect to the specified redirect url. // Note: For multiple enterprise use case, we need to make sure that user first visits the // enterprise selection page and then complete the auth workflow - if (finishAuthUrl && !redirectUrl.includes(finishAuthUrl)) { + if (!shouldUseRedirectUrl && finishAuthUrl && !redirectUrl.includes(finishAuthUrl)) { finalRedirectUrl = getConfig().LMS_BASE_URL + finishAuthUrl; } else { finalRedirectUrl = redirectUrl; @@ -58,8 +58,10 @@ const AuthenticatedRedirection = ({ } if (isLinkTracked) { + console.log('oct1 before redirect', { finalRedirectUrl }); setTimeout(() => { window.location.href = finalRedirectUrl; }, LINK_TIMEOUT); } else { + console.log('oct2 before redirect', { finalRedirectUrl }); window.location.href = finalRedirectUrl; } } @@ -73,6 +75,7 @@ AuthenticatedRedirection.propTypes = { redirectUrl: PropTypes.string, redirectToProgressiveProfilingForm: PropTypes.bool, isLinkTracked: PropTypes.bool, + shouldUseRedirectUrl: PropTypes.bool, }; export default AuthenticatedRedirection; diff --git a/src/forms/progressive-profiling-popup/index.jsx b/src/forms/progressive-profiling-popup/index.jsx index 0d43fcc4..32055eec 100644 --- a/src/forms/progressive-profiling-popup/index.jsx +++ b/src/forms/progressive-profiling-popup/index.jsx @@ -3,9 +3,11 @@ import React, { } from 'react'; import { getConfig, snakeCaseObject } from '@edx/frontend-platform'; +import { identifyAuthenticatedUser } from '@edx/frontend-platform/analytics'; import { AxiosJwtAuthService, - configure as configureAuth, + configure as configureAuth, fetchAuthenticatedUser, + getAuthenticatedUser, } from '@edx/frontend-platform/auth'; import { getCountryList, getLocale, useIntl } from '@edx/frontend-platform/i18n'; import { getLoggingService } from '@edx/frontend-platform/logging'; @@ -26,7 +28,7 @@ import { } from '../../data/constants'; import { getCountryCookieValue } from '../../data/cookies'; import { useDispatch, useSelector } from '../../data/storeHooks'; -import { moveScrollToTop } from '../../data/utils'; +import getAllPossibleQueryParams, { moveScrollToTop } from '../../data/utils'; import { setCurrentOpenedForm } from '../../onboarding-component/data/reducers'; import { trackProgressiveProfilingPageViewed, @@ -47,6 +49,7 @@ import './index.scss'; const ProgressiveProfilingForm = () => { const { formatMessage } = useIntl(); const dispatch = useDispatch(); + const queryParams = useMemo(() => getAllPossibleQueryParams(), []); const countryFieldRef = useRef(null); @@ -55,15 +58,39 @@ const ProgressiveProfilingForm = () => { const submitState = useSelector(state => state.progressiveProfiling.submitState); const subjectsList = useSelector(state => state.progressiveProfiling.subjectsList); - const redirectUrl = useSelector(state => state.progressiveProfiling.redirectUrl); + const redirectURL = useSelector(state => state.progressiveProfiling.redirectUrl); const authContextCountryCode = useSelector(state => state.commonData.thirdPartyAuthContext.countryCode); const finishAuthUrl = useSelector(state => state.commonData.thirdPartyAuthContext.finishAuthUrl); - const authenticatedUser = useSelector(state => state.register.registrationResult.authenticatedUser); + const authUser = useSelector(state => state.register.registrationResult.authenticatedUser); + const [redirectUrl, setRedirectUrl] = React.useState(redirectURL); const [formData, setFormData] = useState({}); const [formErrors, setFormErrors] = useState({}); const [autoFilledCountry, setAutoFilledCountry] = useState({ value: '', displayText: '' }); const [skipButtonState, setSkipButtonState] = useState(DEFAULT_STATE); + const [authConfigured, setAuthConfigured] = useState(false); + const [authenticatedUser, setAuthenticatedUser] = useState(authUser); + const [isUserFetchingCompleted, setIsUserFetchingCompleted] = useState(false); + const isRedirectedFromSSOPipeline = !!queryParams?.from_tpa_pipeline && !!queryParams?.next; + + // const loadAuthenticatedUser = () => { + // if (queryParams?.from_tpa_pipeline) { + // return getAuthenticatedUser(); + // } + // return authUser; + // }; + // const authenticatedUser = loadAuthenticatedUser(); + + useEffect(() => { + if (isRedirectedFromSSOPipeline) { + console.log({ queryParams, url: `${getConfig().LMS_BASE_URL}${queryParams?.next}` }); + setRedirectUrl(`${getConfig().LMS_BASE_URL}${queryParams?.next}`); + } + }, [queryParams]); + + console.log('authUser = ', authUser); + console.log('getAuthenticatedUser = ', getAuthenticatedUser()); + // console.log('authenticatedUser = ', loadAuthenticatedUser()); useEffect(() => { let countryCode = null; @@ -85,14 +112,41 @@ const ProgressiveProfilingForm = () => { }, [authContextCountryCode, autoFilledCountry, countryCookieValue, countryList, formatMessage]); useEffect(() => { - if (authenticatedUser === null) { - dispatch(setCurrentOpenedForm(LOGIN_FORM)); + console.log('1. inside configure auth useEffect', { authConfigured }); + if (!authConfigured) { + console.log('1.1 inside configure auth useEffect INSIDE', { authConfigured }); + configureAuth(AxiosJwtAuthService, { loggingService: getLoggingService(), config: getConfig() }); + setAuthConfigured(true); } + }, [authConfigured]); + + useEffect(() => { + console.log('2. inside fetch user useEffect', { authConfigured }); + if (authConfigured) { + console.log('2.1 inside fetch user useEffect INSIDE', { authConfigured }); + fetchAuthenticatedUser({ forceRefresh: !!getAuthenticatedUser() }).then((user) => { + console.log('inside fetchAuthenticatedUser success', { user }); + setAuthenticatedUser(user); + setIsUserFetchingCompleted(true); + }).catch(() => setIsUserFetchingCompleted(true)); + } + }, [authConfigured]); + + useEffect(() => { if (authenticatedUser?.userId) { - configureAuth(AxiosJwtAuthService, { loggingService: getLoggingService(), config: getConfig() }); + setAuthConfigured(true); + identifyAuthenticatedUser(authenticatedUser?.userId); trackProgressiveProfilingPageViewed(); } - }, [authenticatedUser, dispatch]); + }, [authenticatedUser]); + + useEffect(() => { + console.log('EXIT inside returning to Login useEffect', { isUserFetchingCompleted, authenticatedUser }); + if (isUserFetchingCompleted && !authenticatedUser) { + console.log('EXIT inside returning to Login useEffect inside if', { isUserFetchingCompleted, authenticatedUser }); + dispatch(setCurrentOpenedForm(LOGIN_FORM)); + } + }, [isUserFetchingCompleted, authenticatedUser, dispatch]); const hasFormErrors = () => { let error = false; @@ -185,8 +239,11 @@ const ProgressiveProfilingForm = () => { setSkipButtonState(FAILURE_STATE); moveScrollToTop(countryFieldRef); } else if (hasCountry) { - // link tracker - trackProgressiveProfilingSkipLinkClick(redirectUrl)(e); + let finalRedirectUrl = redirectUrl; + if (!isRedirectedFromSSOPipeline && finishAuthUrl && !redirectUrl.includes(finishAuthUrl)) { + finalRedirectUrl = getConfig().LMS_BASE_URL + finishAuthUrl; + } + trackProgressiveProfilingSkipLinkClick(finalRedirectUrl)(e); } }; @@ -197,6 +254,7 @@ const ProgressiveProfilingForm = () => { redirectUrl={redirectUrl} finishAuthUrl={finishAuthUrl} isLinkTracked + // shouldUseRedirectUrl={isRedirectedFromSSOPipeline} />

{ onBlurHandler={onFieldBlur} /> -

- {formatMessage(messages.progressiveProfilingDataCollectionTitle)} -

- - - + {/*

*/} + {/* {formatMessage(messages.progressiveProfilingDataCollectionTitle)} */} + {/*

*/} + {/* */} + {/* */} + {/* */} { - state.registrationFields = payload; + state.registrationFields = { + ...state.registrationFields, + ...payload, + }; }, backupRegistrationForm: (state, { payload }) => { state.registrationFormData = payload; diff --git a/src/forms/registration-popup/data/utils.js b/src/forms/registration-popup/data/utils.js index 9176c5c5..deaa51b8 100644 --- a/src/forms/registration-popup/data/utils.js +++ b/src/forms/registration-popup/data/utils.js @@ -50,4 +50,7 @@ const isFormValid = ( return { isValid, fieldErrors, emailSuggestion }; }; +// const preparePayload = (formFields, totalRegistrationTime, currentProvider, isLoginSSOIntent, backendCountryCode, ) => { +// +// } export default isFormValid; diff --git a/src/onboarding-component/index.jsx b/src/onboarding-component/index.jsx index 6b79758b..e3fd4ea0 100644 --- a/src/onboarding-component/index.jsx +++ b/src/onboarding-component/index.jsx @@ -107,7 +107,7 @@ export const OnBoardingComponent = ({ if (context) { validatedContext = validateContextData(context); } - if (isAuthenticatedUser) { + if (isAuthenticatedUser && [REGISTRATION_FORM, LOGIN_FORM].includes(formToRender)) { const queryParamString = objectToQueryString({ ...validatedContext, ...queryParams }); const formUrl = formToRender === REGISTRATION_FORM ? 'register' : formToRender; window.location.href = `${getConfig().LMS_BASE_URL}/${formUrl}?${queryParamString}`; @@ -133,6 +133,7 @@ export const OnBoardingComponent = ({ return ; } if (currentForm === PROGRESSIVE_PROFILING_FORM) { + console.log('getForm'); return ; } if (currentForm === REGISTRATION_FORM) { @@ -232,3 +233,7 @@ export const SignUpComponent = (props) => ( export const ResetPasswordComponent = (props) => ( ); + +export const WelcomePageComponent = (props) => ( + +);