@@ -63,11 +86,13 @@ const BaseComponent = ({ children, showWelcomeBanner }) => {
};
BaseComponent.defaultProps = {
+ isRegistrationPage: false,
showWelcomeBanner: false,
};
BaseComponent.propTypes = {
children: PropTypes.node.isRequired,
+ isRegistrationPage: PropTypes.bool,
showWelcomeBanner: PropTypes.bool,
};
diff --git a/src/base-component/DiscountBanner.jsx b/src/base-component/DiscountBanner.jsx
new file mode 100644
index 00000000..a5c03fca
--- /dev/null
+++ b/src/base-component/DiscountBanner.jsx
@@ -0,0 +1,46 @@
+import React, { useState } from 'react';
+
+import ClipboardJS from 'clipboard';
+
+import { FormattedMessage } from '@edx/frontend-platform/i18n';
+import { faCut } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+
+import { PageBanner } from '@edx/paragon';
+
+export default function DiscountExperimentBanner() {
+ const [show, setShow] = useState(true);
+ new ClipboardJS('.copyIcon'); // eslint-disable-line no-new
+
+ return (
+ <>
+
{ setShow(false); }}
+ >
+
+
+ 15% off ,
+ }}
+ />
+
+
+ EDXWELCOME
+
+
+
+
+ >
+ );
+}
diff --git a/src/base-component/LargeLayout.jsx b/src/base-component/LargeLayout.jsx
index 30c292e8..5a5dd69d 100644
--- a/src/base-component/LargeLayout.jsx
+++ b/src/base-component/LargeLayout.jsx
@@ -1,17 +1,18 @@
import React from 'react';
+import PropTypes from 'prop-types';
import { getConfig } from '@edx/frontend-platform';
import { Hyperlink, Image } from '@edx/paragon';
import LargeScreenLeftLayout from './LargeLeftLayout';
-const LargeLayout = () => (
+const LargeLayout = ({ experimentName, isRegistrationPage }) => (
-
+
);
+LargeLayout.defaultProps = {
+ experimentName: '',
+ isRegistrationPage: false,
+};
+
+LargeLayout.propTypes = {
+ experimentName: PropTypes.string,
+ isRegistrationPage: PropTypes.bool,
+};
+
export default LargeLayout;
diff --git a/src/base-component/LargeLeftLayout.jsx b/src/base-component/LargeLeftLayout.jsx
index 79f4b32c..a8dd7223 100644
--- a/src/base-component/LargeLeftLayout.jsx
+++ b/src/base-component/LargeLeftLayout.jsx
@@ -1,30 +1,71 @@
import React from 'react';
+import classNames from 'classnames';
+
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { getConfig } from '@edx/frontend-platform';
+import PropTypes from 'prop-types';
+import ClipboardJS from 'clipboard';
+
+import { faCut } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import messages from './messages';
const LargeLeftLayout = (props) => {
- const { intl } = props;
-
+ const { intl, isRegistrationPage, experimentName } = props;
+ new ClipboardJS('.copyIcon'); // eslint-disable-line no-new
return (
-
);
};
LargeLeftLayout.propTypes = {
intl: intlShape.isRequired,
+ experimentName: PropTypes.string,
+ isRegistrationPage: PropTypes.bool,
+};
+
+LargeLeftLayout.defaultProps = {
+ experimentName: '',
+ isRegistrationPage: false,
};
export default injectIntl(LargeLeftLayout);
diff --git a/src/base-component/MediumLayout.jsx b/src/base-component/MediumLayout.jsx
index 6c0137e4..10105d3c 100644
--- a/src/base-component/MediumLayout.jsx
+++ b/src/base-component/MediumLayout.jsx
@@ -1,31 +1,74 @@
import React from 'react';
+import classNames from 'classnames';
+
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { getConfig } from '@edx/frontend-platform';
import { Hyperlink, Image } from '@edx/paragon';
+import PropTypes from 'prop-types';
+import ClipboardJS from 'clipboard';
+
+import { faCut } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import messages from './messages';
const MediumLayout = (props) => {
- const { intl } = props;
+ const { intl, isRegistrationPage, experimentName } = props;
+ new ClipboardJS('.copyIcon'); // eslint-disable-line no-new
return (
-
+
-
+
-
- {intl.formatMessage(messages['start.learning'])}
-
- {intl.formatMessage(messages['with.site.name'], { siteName: getConfig().SITE_NAME })}
-
-
+
+
+ {intl.formatMessage(messages['start.learning'])}
+
+
+ {intl.formatMessage(messages['with.site.name'], { siteName: getConfig().SITE_NAME })}
+
+
+ {experimentName === 'variation1' && isRegistrationPage ? (
+
+
+ Get 15% off your first verified
certificate* with code
+
+
+ EDXWELCOME
+
+
+
+ ) : null}
+
+
@@ -40,6 +83,13 @@ const MediumLayout = (props) => {
MediumLayout.propTypes = {
intl: intlShape.isRequired,
+ experimentName: PropTypes.string,
+ isRegistrationPage: PropTypes.bool,
+};
+
+MediumLayout.defaultProps = {
+ experimentName: '',
+ isRegistrationPage: false,
};
export default injectIntl(MediumLayout);
diff --git a/src/base-component/SmallLayout.jsx b/src/base-component/SmallLayout.jsx
index 9a4379bc..693a18d5 100644
--- a/src/base-component/SmallLayout.jsx
+++ b/src/base-component/SmallLayout.jsx
@@ -1,14 +1,22 @@
import React from 'react';
+import classNames from 'classnames';
+
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { getConfig } from '@edx/frontend-platform';
import { Hyperlink, Image } from '@edx/paragon';
+import PropTypes from 'prop-types';
+
+import ClipboardJS from 'clipboard';
+
+import { faCut } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import messages from './messages';
const SmallLayout = (props) => {
- const { intl } = props;
-
+ const { intl, isRegistrationPage, experimentName } = props;
+ new ClipboardJS('.copyIcon'); // eslint-disable-line no-new
return (
<>
@@ -16,16 +24,41 @@ const SmallLayout = (props) => {
-
+
-
- {intl.formatMessage(messages['start.learning'])}
-
-
- {intl.formatMessage(messages['with.site.name'], { siteName: getConfig().SITE_NAME })}
-
-
+
+
+ {intl.formatMessage(messages['start.learning'])}
+
+
+ {intl.formatMessage(messages['with.site.name'], { siteName: getConfig().SITE_NAME })}
+
+
+ {(experimentName === 'variation1' && isRegistrationPage) ? (
+
+ Get 15% off your first verified
certificate* with code
+
+ EDXWELCOME
+
+
+
+ ) : null}
+
>
@@ -34,6 +67,14 @@ const SmallLayout = (props) => {
SmallLayout.propTypes = {
intl: intlShape.isRequired,
+ experimentName: PropTypes.string,
+ isRegistrationPage: PropTypes.bool,
+};
+
+SmallLayout.defaultProps = {
+ experimentName: '',
+ isRegistrationPage: false,
+
};
export default injectIntl(SmallLayout);
diff --git a/src/common-components/Logistration.jsx b/src/common-components/Logistration.jsx
index bb47abc7..48600c6a 100644
--- a/src/common-components/Logistration.jsx
+++ b/src/common-components/Logistration.jsx
@@ -52,7 +52,7 @@ const Logistration = (props) => {
);
return (
-
+
{institutionLogin
? (
diff --git a/src/login/tests/LoginPage.test.jsx b/src/login/tests/LoginPage.test.jsx
index 8e2aad1f..28a2affb 100644
--- a/src/login/tests/LoginPage.test.jsx
+++ b/src/login/tests/LoginPage.test.jsx
@@ -145,7 +145,7 @@ describe('LoginPage', () => {
it('should match default button state', () => {
const loginPage = mount(reduxWrapper(
));
- expect(loginPage.find('button[type="submit"] span').first().text()).toEqual('Sign in');
+ expect(loginPage.find('button[type="submit"] span').first().text()).toEqual(' Sign in ');
});
it('should match pending button state', () => {
@@ -160,7 +160,7 @@ describe('LoginPage', () => {
const loginPage = mount(reduxWrapper(
));
const button = loginPage.find('button[type="submit"] span').first();
- expect(button.find('.sr-only').text()).toEqual('pending');
+ expect(button.find('.sr-only').text()).toEqual(' pending ');
});
it('should show forgot password link', () => {
diff --git a/src/register/RegistrationPage.jsx b/src/register/RegistrationPage.jsx
index bf833d44..deb7a56f 100644
--- a/src/register/RegistrationPage.jsx
+++ b/src/register/RegistrationPage.jsx
@@ -657,6 +657,13 @@ class RegistrationPage extends React.Component {
thirdPartyAuthApiStatus,
intl)}
+ {(this.state.optimizelyExperimentName === 'variation1' || this.state.optimizelyExperimentName === 'variation2')
+ ? (
+
+ {intl.formatMessage(messages['certificate.msg'])}
+
+ )
+ : null}
>
);
diff --git a/src/register/messages.jsx b/src/register/messages.jsx
index e9927a9a..30cc9feb 100644
--- a/src/register/messages.jsx
+++ b/src/register/messages.jsx
@@ -270,6 +270,11 @@ const messages = defineMessages({
defaultMessage: 'Did you mean',
description: 'Did you mean alert suggestion',
},
+ 'certificate.msg': {
+ id: 'certificate.msg',
+ defaultMessage: '*Offer not eligible for GTx’s Analytics: Essential Tools and Methods MicroMasters Program, ColumbiaX’s Corporate Finance Professional Certificate Program, or courses or programs offered by Wharton, and NYIF.',
+ description: 'Text for the 15% discount experiment',
+ },
});
export default messages;
diff --git a/src/register/tests/RegistrationPage.test.jsx b/src/register/tests/RegistrationPage.test.jsx
index da71fd18..46f23fc8 100644
--- a/src/register/tests/RegistrationPage.test.jsx
+++ b/src/register/tests/RegistrationPage.test.jsx
@@ -405,7 +405,7 @@ describe('RegistrationPage', () => {
it('should match default button state', () => {
const registrationPage = mount(reduxWrapper());
- expect(registrationPage.find('button[type="submit"] span').first().text()).toEqual('Create an account');
+ expect(registrationPage.find('button[type="submit"] span').first().text()).toEqual(' Create an account ');
});
it('should match pending button state', () => {
@@ -420,7 +420,7 @@ describe('RegistrationPage', () => {
const registrationPage = mount(reduxWrapper());
const button = registrationPage.find('button[type="submit"] span').first();
- expect(button.find('.sr-only').text()).toEqual('pending');
+ expect(button.find('.sr-only').text()).toEqual(' pending ');
});
it('should show single sign on provider button', () => {