From a8eb5916ebb527e4dfc8433a65141e4e5d55bf32 Mon Sep 17 00:00:00 2001 From: Mubbshar Anwar <78487564+mubbsharanwar@users.noreply.github.com> Date: Tue, 1 Jun 2021 17:46:52 +0500 Subject: [PATCH] Add welcome page (#302) Add welcome page for A/B testing VAN-514 --- .env | 1 + .env.development | 1 + .env.test | 1 + .../RedirectLogistration.jsx | 2 + src/data/constants.js | 1 + src/index.jsx | 5 +- src/welcome/WelcomePage.jsx | 188 ++++++++++++++++++ src/welcome/index.js | 1 + src/welcome/messages.jsx | 110 ++++++++++ 9 files changed, 309 insertions(+), 1 deletion(-) create mode 100644 src/welcome/WelcomePage.jsx create mode 100644 src/welcome/index.js create mode 100644 src/welcome/messages.jsx diff --git a/.env b/.env index 63ad0390..6651a3f5 100644 --- a/.env +++ b/.env @@ -19,3 +19,4 @@ LOGIN_ISSUE_SUPPORT_LINK=null REGISTRATION_OPTIONAL_FIELDS=null USER_SURVEY_COOKIE_NAME=null COOKIE_DOMAIN=null +WELCOME_PAGE_SUPPORT_LINK=null diff --git a/.env.development b/.env.development index 54cd540b..eca6f764 100644 --- a/.env.development +++ b/.env.development @@ -26,3 +26,4 @@ PRIVACY_POLICY='http://localhost:18000/privacy' REGISTRATION_OPTIONAL_FIELDS='gender,goals,level_of_education,year_of_birth' USER_SURVEY_COOKIE_NAME='openedx-user-survey-type' COOKIE_DOMAIN='localhost' +WELCOME_PAGE_SUPPORT_LINK='http://localhost:1999/welcome' diff --git a/.env.test b/.env.test index 7013d71b..2f0945b3 100644 --- a/.env.test +++ b/.env.test @@ -19,3 +19,4 @@ SITE_NAME='edX' USER_INFO_COOKIE_NAME='edx-user-info' LOGIN_ISSUE_SUPPORT_LINK='https://login-issue-support-url.com' USER_SURVEY_COOKIE_NAME='openedx-user-survey-type' +WELCOME_PAGE_SUPPORT_LINK='http://localhost:1999/welcome' diff --git a/src/common-components/RedirectLogistration.jsx b/src/common-components/RedirectLogistration.jsx index a5c52c71..ee742ffd 100644 --- a/src/common-components/RedirectLogistration.jsx +++ b/src/common-components/RedirectLogistration.jsx @@ -14,6 +14,8 @@ function RedirectLogistration(props) { if (finishAuthUrl && !redirectUrl.includes(finishAuthUrl)) { window.location.href = getConfig().LMS_BASE_URL + finishAuthUrl; } else { + // use this component to redirect WelcomePage after successful registration + // return ; window.location.href = redirectUrl; } } diff --git a/src/data/constants.js b/src/data/constants.js index a8e1342e..45f2bfb0 100644 --- a/src/data/constants.js +++ b/src/data/constants.js @@ -2,6 +2,7 @@ export const LOGIN_PAGE = '/login'; export const REGISTER_PAGE = '/register'; export const RESET_PAGE = '/reset'; +export const WELCOME_PAGE = '/welcome'; export const DEFAULT_REDIRECT_URL = '/dashboard'; export const PASSWORD_RESET_CONFIRM = '/password_reset_confirm/:token/'; export const PAGE_NOT_FOUND = '/notfound'; diff --git a/src/index.jsx b/src/index.jsx index 2e8a7df2..3c3e4f5d 100755 --- a/src/index.jsx +++ b/src/index.jsx @@ -15,13 +15,14 @@ import configureStore from './data/configureStore'; import { RegistrationPage } from './register'; import { LoginPage } from './login'; import { - LOGIN_PAGE, PAGE_NOT_FOUND, REGISTER_PAGE, RESET_PAGE, PASSWORD_RESET_CONFIRM, + LOGIN_PAGE, PAGE_NOT_FOUND, REGISTER_PAGE, RESET_PAGE, PASSWORD_RESET_CONFIRM, WELCOME_PAGE, } from './data/constants'; import ForgotPasswordPage from './forgot-password'; import { HeaderLayout, UnAuthOnlyRoute, registerIcons, NotFoundPage, } from './common-components'; import ResetPasswordPage from './reset-password'; +import WelcomePage from './welcome'; import appMessages from './i18n'; import './index.scss'; @@ -40,6 +41,7 @@ subscribe(APP_READY, () => { + @@ -67,6 +69,7 @@ initialize({ REGISTRATION_OPTIONAL_FIELDS: process.env.REGISTRATION_OPTIONAL_FIELDS || '', USER_SURVEY_COOKIE_NAME: process.env.USER_SURVEY_COOKIE_NAME || null, COOKIE_DOMAIN: process.env.COOKIE_DOMAIN, + WELCOME_PAGE_SUPPORT_LINK: process.env.WELCOME_PAGE_SUPPORT_LINK || null, }); }, }, diff --git a/src/welcome/WelcomePage.jsx b/src/welcome/WelcomePage.jsx new file mode 100644 index 00000000..616dec7c --- /dev/null +++ b/src/welcome/WelcomePage.jsx @@ -0,0 +1,188 @@ +import React, { useState, useEffect } from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import { Helmet } from 'react-helmet'; + +import { getConfig } from '@edx/frontend-platform'; +import { + ensureAuthenticatedUser, hydrateAuthenticatedUser, getAuthenticatedUser, +} from '@edx/frontend-platform/auth'; +import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; +import { + Form, + StatefulButton, + Hyperlink, +} from '@edx/paragon'; + +import messages from './messages'; + +import { EDUCATION_LEVELS, GENDER_OPTIONS, YEAR_OF_BIRTH_OPTIONS } from '../register/data/constants'; +import { registrationRequestSelector } from '../register/data/selectors'; +import { AuthnValidationFormGroup } from '../common-components'; +import { DEFAULT_REDIRECT_URL } from '../data/constants'; + +const WelcomePage = (props) => { + const { intl, registrationResult } = props; + const [values, setValues] = useState({}); + const [ready, setReady] = useState(false); + const DASHBOARD_URL = getConfig().LMS_BASE_URL.concat(DEFAULT_REDIRECT_URL); + + useEffect(() => { + ensureAuthenticatedUser(DASHBOARD_URL).then(() => { + hydrateAuthenticatedUser().then(() => { + setReady(true); + }); + }); + }, []); + + const authenticatedUser = getAuthenticatedUser(); + + if (!registrationResult.redirectUrl) { + global.location.assign(DASHBOARD_URL); + return null; + } + + if (!ready) { + return null; + } + + const getOptions = () => ({ + yearOfBirthOptions: [{ + value: '', + label: intl.formatMessage(messages['registration.year.of.birth.label']), + }].concat(YEAR_OF_BIRTH_OPTIONS), + educationLevelOptions: EDUCATION_LEVELS.map(key => ({ + value: key, + label: intl.formatMessage(messages[`registration.field.education.levels.${key || 'label'}`]), + })), + genderOptions: GENDER_OPTIONS.map(key => ({ + value: key, + label: intl.formatMessage(messages[`registration.field.gender.options.${key || 'label'}`]), + })), + }); + + const handleSubmit = (e) => { + e.preventDefault(); + if (registrationResult.success) { + window.location.href = registrationResult.redirectUrl; + } + return null; + }; + + const handleSkip = (e) => { + e.preventDefault(); + window.location.href = registrationResult.redirectUrl; + return null; + }; + const onChangeHandler = (e) => { + setValues({ ...values, [e.target.name]: e.target.value }); + }; + + return ( + <> + + {intl.formatMessage(messages['optional.fields.page.title'], + { siteName: getConfig().SITE_NAME })} + + +
+
+
+

+ { intl.formatMessage(messages['welcome.to.edx'], { username: authenticatedUser.username }) } +

+
+

{intl.formatMessage(messages['optional.fields.page.heading'])}

+ onChangeHandler(e)} + selectOptions={getOptions().educationLevelOptions} + inputFieldStyle="border-gray-600 custom-select-size" + /> + onChangeHandler(e)} + selectOptions={getOptions().yearOfBirthOptions} + inputFieldStyle="border-gray-600 custom-select-size" + /> + onChangeHandler(e)} + selectOptions={getOptions().genderOptions} + inputFieldStyle="border-gray-600 custom-select-size" + /> +

+ + {intl.formatMessage(messages['optional.fields.information.link'])} + +

+
+ e.preventDefault()} + /> + e.preventDefault()} + /> +
+ +
+
+ + ); +}; + +WelcomePage.propTypes = { + intl: intlShape.isRequired, + registrationResult: PropTypes.shape({ + redirectUrl: PropTypes.string, + success: PropTypes.bool, + }), +}; + +WelcomePage.defaultProps = { + registrationResult: {}, +}; + +const mapStateToProps = state => { + const registrationResult = registrationRequestSelector(state); + return { registrationResult }; +}; + +export default connect( + mapStateToProps, +)(injectIntl(WelcomePage)); diff --git a/src/welcome/index.js b/src/welcome/index.js new file mode 100644 index 00000000..b031301e --- /dev/null +++ b/src/welcome/index.js @@ -0,0 +1 @@ +export { default } from './WelcomePage'; diff --git a/src/welcome/messages.jsx b/src/welcome/messages.jsx new file mode 100644 index 00000000..d3244f2a --- /dev/null +++ b/src/welcome/messages.jsx @@ -0,0 +1,110 @@ +import { defineMessages } from '@edx/frontend-platform/i18n'; + +const messages = defineMessages({ + 'optional.fields.page.title': { + id: 'optional.fields.page.title', + defaultMessage: 'Optional Fields | {siteName}', + description: 'optional fields page title', + }, + 'optional.fields.page.heading': { + id: 'optional.fields.page.heading', + defaultMessage: 'Support education research by providing additional information.', + description: 'The page heading for the optional fields page.', + }, + 'welcome.to.edx': { + id: 'welcome.to.edx', + defaultMessage: 'Welcome to edX, {username}!', + description: 'Welcome message on the optional fields page.', + }, + 'registration.field.gender.options.label': { + id: 'registration.field.gender.options.label', + defaultMessage: 'Gender (optional)', + description: 'Placeholder for the gender options dropdown', + }, + 'registration.field.gender.options.f': { + id: 'registration.field.gender.options.f', + defaultMessage: 'Female', + description: 'The label for the female gender option.', + }, + 'registration.field.gender.options.m': { + id: 'registration.field.gender.options.m', + defaultMessage: 'Male', + description: 'The label for the male gender option.', + }, + 'registration.field.gender.options.o': { + id: 'registration.field.gender.options.o', + defaultMessage: 'Other/Prefer not to say', + description: 'The label for catch-all gender option.', + }, + 'registration.field.education.levels.label': { + id: 'registration.field.education.levels.label', + defaultMessage: 'Highest level of education completed (optional)', + description: 'Placeholder for the education levels dropdown.', + }, + 'registration.field.education.levels.p': { + id: 'registration.field.education.levels.p', + defaultMessage: 'Doctorate', + description: 'Selected by the user if their highest level of education is a doctorate degree.', + }, + 'registration.field.education.levels.m': { + id: 'registration.field.education.levels.m', + defaultMessage: "Master's or professional degree", + description: "Selected by the user if their highest level of education is a master's or professional degree from a college or university.", + }, + 'registration.field.education.levels.b': { + id: 'registration.field.education.levels.b', + defaultMessage: "Bachelor's degree", + description: "Selected by the user if their highest level of education is a four year college or university bachelor's degree.", + }, + 'registration.field.education.levels.a': { + id: 'registration.field.education.levels.a', + defaultMessage: "Associate's degree", + description: "Selected by the user if their highest level of education is an associate's degree. 1-2 years of college or university.", + }, + 'registration.field.education.levels.hs': { + id: 'registration.field.education.levels.hs', + defaultMessage: 'Secondary/high school', + description: 'Selected by the user if their highest level of education is secondary or high school. 9-12 years of education.', + }, + 'registration.field.education.levels.jhs': { + id: 'registration.field.education.levels.jhs', + defaultMessage: 'Junior secondary/junior high/middle school', + description: 'Selected by the user if their highest level of education is junior or middle school. 6-8 years of education.', + }, + 'registration.field.education.levels.el': { + id: 'registration.field.education.levels.el', + defaultMessage: 'Elementary/primary school', + description: 'Selected by the user if their highest level of education is elementary or primary school. 1-5 years of education.', + }, + 'registration.field.education.levels.none': { + id: 'registration.field.education.levels.none', + defaultMessage: 'No formal education', + description: 'Selected by the user to describe their education.', + }, + 'registration.field.education.levels.other': { + id: 'registration.field.education.levels.other', + defaultMessage: 'Other education', + description: 'Selected by the user if they have a type of education not described by the other choices.', + }, + 'registration.year.of.birth.label': { + id: 'registration.year.of.birth.label', + defaultMessage: 'Year of birth (optional)', + description: 'Placeholder for the year of birth options dropdown', + }, + 'optional.fields.information.link': { + id: 'optional.fields.information.link', + defaultMessage: 'Learn more about how we use this information.', + description: 'Optional fields page information link', + }, + 'optional.fields.submit.button': { + id: 'optional.fields.submit.button', + defaultMessage: 'Submit', + description: 'Submit button text', + }, + 'optional.fields.skip.button': { + id: 'optional.fields.skip.button', + defaultMessage: 'Skip for now', + description: 'Skip button text', + }, +}); +export default messages;