1
.env
1
.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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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 <Redirect to={WELCOME_PAGE} />;
|
||||
window.location.href = redirectUrl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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, () => {
|
||||
<UnAuthOnlyRoute exact path={REGISTER_PAGE} component={RegistrationPage} />
|
||||
<UnAuthOnlyRoute exact path={RESET_PAGE} component={ForgotPasswordPage} />
|
||||
<Route exact path={PASSWORD_RESET_CONFIRM} component={ResetPasswordPage} />
|
||||
<Route exact path={WELCOME_PAGE} component={WelcomePage} />
|
||||
<Route path={PAGE_NOT_FOUND} component={NotFoundPage} />
|
||||
<Route path="*">
|
||||
<Redirect to={PAGE_NOT_FOUND} />
|
||||
@@ -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,
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
188
src/welcome/WelcomePage.jsx
Normal file
188
src/welcome/WelcomePage.jsx
Normal file
@@ -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 (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>{intl.formatMessage(messages['optional.fields.page.title'],
|
||||
{ siteName: getConfig().SITE_NAME })}
|
||||
</title>
|
||||
</Helmet>
|
||||
<div className="d-flex justify-content-center m-4">
|
||||
<div className="d-flex flex-column">
|
||||
<Form className="mw-500">
|
||||
<p className="mb-4">
|
||||
{ intl.formatMessage(messages['welcome.to.edx'], { username: authenticatedUser.username }) }
|
||||
</p>
|
||||
<hr className="mb-3 border-gray-200" />
|
||||
<h1 className="mb-3 h3">{intl.formatMessage(messages['optional.fields.page.heading'])}</h1>
|
||||
<AuthnValidationFormGroup
|
||||
label={intl.formatMessage(messages['registration.field.education.levels.label'])}
|
||||
for="levelOfEducation"
|
||||
name="levelOfEducation"
|
||||
type="select"
|
||||
key="levelOfEducation"
|
||||
className="mb-3 data-hj-suppress"
|
||||
value={values.levelOfEducation}
|
||||
onChange={(e) => onChangeHandler(e)}
|
||||
selectOptions={getOptions().educationLevelOptions}
|
||||
inputFieldStyle="border-gray-600 custom-select-size"
|
||||
/>
|
||||
<AuthnValidationFormGroup
|
||||
label={intl.formatMessage(messages['registration.year.of.birth.label'])}
|
||||
for="yearOfBirth"
|
||||
name="yearOfBirth"
|
||||
type="select"
|
||||
key="yearOfBirth"
|
||||
value={values.yearOfBirth}
|
||||
className="mb-3 data-hj-suppress"
|
||||
onChange={(e) => onChangeHandler(e)}
|
||||
selectOptions={getOptions().yearOfBirthOptions}
|
||||
inputFieldStyle="border-gray-600 custom-select-size"
|
||||
/>
|
||||
<AuthnValidationFormGroup
|
||||
label={intl.formatMessage(messages['registration.field.gender.options.label'])}
|
||||
for="gender"
|
||||
name="gender"
|
||||
type="select"
|
||||
key="gender"
|
||||
value={values.gender}
|
||||
className="mb-3 data-hj-suppress"
|
||||
onChange={(e) => onChangeHandler(e)}
|
||||
selectOptions={getOptions().genderOptions}
|
||||
inputFieldStyle="border-gray-600 custom-select-size"
|
||||
/>
|
||||
<p>
|
||||
<Hyperlink
|
||||
className="mt-1 text-dark"
|
||||
destination={getConfig().WELCOME_PAGE_SUPPORT_LINK}
|
||||
target="_blank"
|
||||
>
|
||||
{intl.formatMessage(messages['optional.fields.information.link'])}
|
||||
</Hyperlink>
|
||||
</p>
|
||||
<div className="d-flex mt-3">
|
||||
<StatefulButton
|
||||
type="submit"
|
||||
variant="brand"
|
||||
labels={{
|
||||
default: intl.formatMessage(messages['optional.fields.submit.button']),
|
||||
}}
|
||||
onClick={handleSubmit}
|
||||
onMouseDown={(e) => e.preventDefault()}
|
||||
/>
|
||||
<StatefulButton
|
||||
type="submit"
|
||||
variant="link"
|
||||
className="ml-1 text-dark"
|
||||
labels={{
|
||||
default: intl.formatMessage(messages['optional.fields.skip.button']),
|
||||
}}
|
||||
onClick={handleSkip}
|
||||
onMouseDown={(e) => e.preventDefault()}
|
||||
/>
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
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));
|
||||
1
src/welcome/index.js
Normal file
1
src/welcome/index.js
Normal file
@@ -0,0 +1 @@
|
||||
export { default } from './WelcomePage';
|
||||
110
src/welcome/messages.jsx
Normal file
110
src/welcome/messages.jsx
Normal file
@@ -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;
|
||||
Reference in New Issue
Block a user