Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ghostery Plus & Insights Promo Modals #464

Merged
merged 13 commits into from Oct 28, 2019
Merged
Changes from 1 commit
Commits
File filter
Filter file types
Jump to
Jump to file
Failed to load files.

Always

Just for now

Next

GH-1777 and GH-1776 Plus Promo modals (#458)

* Show plus promo modal on first view of Home view of each Hub session

* Stub out intro hub plus promo modal layout and implement its buttons

* Remove some unnecessary plus promo modal related CSS

* Continue adding styling for plus promo modal

* Continue styling plus promo modal

* Refactor plus promo modal CSS to improve alignment of elements

* Continue CSS work for plus promo modal

* Implement recommended gold banner in plus promo modal

* Update and tweak plus promo modal design

* Fix path bug in i18n-checker tool. Consolidate redundant entries in messages. Add check icon to plus promo modal. Modify plus promo modal css.

* Additional consolidation of redundant and unused entries in messages

* Factor plus promo modal rendering out to shared component. Implement rendering in panel. Implement display context CSS adjustments.

* Move Plus Promo modal rendering to a PlusPromoModal shared component. Begin to implement conditional panel display logic

* Create ModalPromos background class responsible for modal promo related business logic and state management

* Add local state to Panel to make sure component rerenders after user dismisses promo panel. Send record of promo interaction to background

* Make PromoModals code more robust

* Factor PlusPromoModal rendering out to helper in Panel. Extend conditional rendering logic to account for upgrade version of modal

* Mark PromoModals methods as static. Refine PlusPromoModal implementation and add debug code

* Add logic to hide plus promo modal from Insights subscribers. Cleanup and comments.

* Clean up. Finish string localization in PlusPromoModal

* Pull non-shared upgrade version of plus promo modal out of shared PlusPromoModal component and into Panel to simplify

* Remove debug console statement
  • Loading branch information
wlycdgr committed Oct 16, 2019
commit b3856d21996de357aa638f658517cee304d7c33c

Large diffs are not rendered by default.

@@ -74,7 +74,7 @@ class OfferCard extends Component {
message: t('rewards_first_prompt_extended'),
textLink: {
href: 'https://www.ghostery.com/faqs/what-is-ghostery-rewards/',
text: t('rewards_learn_more'),
text: t('learn_more'),
callback: () => {
this.props.actions.sendSignal('offer_first_learn');
sendMessage('ping', 'rewards_first_learn_more');
@@ -73,7 +73,7 @@ const CreateAccountView = (props) => {
<div className="CreateAccountView--addPaddingTop row align-center-middle">
<div className="columns small-12 medium-5">
<label htmlFor="create-account-email" className="CreateAccountView__inputLabel">
{t('hub_create_account_label_email')}
{t('email_colon')}
</label>
<input
id="create-account-email"
@@ -87,13 +87,13 @@ const CreateAccountView = (props) => {
/>
{emailError && (
<div className="CreateAccountView__inputError">
{t('hub_create_account_label_email_invalid')}
{t('please_enter_a_valid_email')}
</div>
)}
</div>
<div className="columns small-12 medium-5">
<label htmlFor="create-account-confirmEmail" className="CreateAccountView__inputLabel">
{t('hub_create_account_label_email_confirm')}
{t('confirm_email_colon')}
</label>
<input
id="create-account-confirmEmail"
@@ -107,7 +107,7 @@ const CreateAccountView = (props) => {
/>
{confirmEmailError && (
<div className="CreateAccountView__inputError">
{t('hub_create_account_label_email_confirm_invalid')}
{t('your_emails_do_not_match')}
</div>
)}
</div>
@@ -147,7 +147,7 @@ const CreateAccountView = (props) => {
<div className="row align-center-middle">
<div className="columns small-12 medium-5">
<label htmlFor="create-account-password" className="CreateAccountView__inputLabel">
{t('hub_create_account_label_password')}
{t('password_colon')}
</label>
<input
id="create-account-password"
@@ -214,7 +214,7 @@ const CreateAccountView = (props) => {
<div className="CreateAccountView--addPaddingTop row align-center">
<div className="CreateAccountView__submit columns small-12 medium-10 flex-container flex-dir-row-reverse">
<button type="submit" className="CreateAccountView__button button success">
{ t('hub_create_account_button_submit') }
{ t('create_account') }
</button>
</div>
</div>
@@ -40,7 +40,7 @@ exports[`app/hub/Views/CreateAccount component Snapshot tests with react-test-re
className="CreateAccountView__inputLabel"
htmlFor="create-account-email"
>
hub_create_account_label_email
email_colon
</label>
<input
autoComplete="off"
@@ -60,7 +60,7 @@ exports[`app/hub/Views/CreateAccount component Snapshot tests with react-test-re
className="CreateAccountView__inputLabel"
htmlFor="create-account-confirmEmail"
>
hub_create_account_label_email_confirm
confirm_email_colon
</label>
<input
autoComplete="off"
@@ -128,7 +128,7 @@ exports[`app/hub/Views/CreateAccount component Snapshot tests with react-test-re
className="CreateAccountView__inputLabel"
htmlFor="create-account-password"
>
hub_create_account_label_password
password_colon
</label>
<input
autoComplete="off"
@@ -240,7 +240,7 @@ exports[`app/hub/Views/CreateAccount component Snapshot tests with react-test-re
className="CreateAccountView__button button success"
type="submit"
>
hub_create_account_button_submit
create_account
</button>
</div>
</div>
@@ -288,7 +288,7 @@ exports[`app/hub/Views/CreateAccount component Snapshot tests with react-test-re
className="CreateAccountView__inputLabel"
htmlFor="create-account-email"
>
hub_create_account_label_email
email_colon
</label>
<input
autoComplete="off"
@@ -303,7 +303,7 @@ exports[`app/hub/Views/CreateAccount component Snapshot tests with react-test-re
<div
className="CreateAccountView__inputError"
>
hub_create_account_label_email_invalid
please_enter_a_valid_email
</div>
</div>
<div
@@ -313,7 +313,7 @@ exports[`app/hub/Views/CreateAccount component Snapshot tests with react-test-re
className="CreateAccountView__inputLabel"
htmlFor="create-account-confirmEmail"
>
hub_create_account_label_email_confirm
confirm_email_colon
</label>
<input
autoComplete="off"
@@ -328,7 +328,7 @@ exports[`app/hub/Views/CreateAccount component Snapshot tests with react-test-re
<div
className="CreateAccountView__inputError"
>
hub_create_account_label_email_confirm_invalid
your_emails_do_not_match
</div>
</div>
</div>
@@ -386,7 +386,7 @@ exports[`app/hub/Views/CreateAccount component Snapshot tests with react-test-re
className="CreateAccountView__inputLabel"
htmlFor="create-account-password"
>
hub_create_account_label_password
password_colon
</label>
<input
autoComplete="off"
@@ -508,7 +508,7 @@ exports[`app/hub/Views/CreateAccount component Snapshot tests with react-test-re
className="CreateAccountView__button button success"
type="submit"
>
hub_create_account_button_submit
create_account
</button>
</div>
</div>
@@ -106,7 +106,7 @@ const HomeView = (props) => {
</a>
) : (
<NavLink to="/create-account">
{t('hub_home_subheader_create_account')}
{t('create_account')}
</NavLink>
)}
</div>
@@ -120,15 +120,15 @@ const HomeView = (props) => {
{t('hub_home_feature_tutorial_text')}
</div>
<NavLink to="/tutorial" className={tutorialButtonClassNames}>
{tutorial_complete ? t('hub_home_feature_tutorial_button_alt') : t('hub_home_feature_tutorial_button')}
{tutorial_complete ? t('hub_home_feature_tutorial_button_alt') : t('start')}
</NavLink>
</div>
<div className="HomeView__dividerVertical column shrink show-for-large" />
<div className="HomeView__dividerHorizontal hide-for-large" />
<div className={setupFeatureClassNames}>
<div className="HomeView__featureIcon" />
<div className="HomeView__featureTitle">
{t('hub_home_feature_setup_title')}
{t('customize_setup')}
</div>
<div className="HomeView__featureText flex-child-grow">
{t('hub_home_feature_setup_text')}
@@ -146,7 +146,7 @@ const HomeView = (props) => {
<div className="HomeView__featureIcon columns shrink feature-plus show-for-large" />
<div className="columns flex-container align-center-middle">
<NavLink to="/plus" className="HomeView__featureButton button primary">
{isPlus ? t('hub_home_feature_supporter_button_alt') : t('hub_home_feature_supporter_button')}
{isPlus ? t('Aready_Subscribed') : t('get_ghostery_plus')}
</NavLink>
</div>
</div>
@@ -154,16 +154,16 @@

// Firefox Font Size Override and Image Size Override
@-moz-document url-prefix() {
.HomeView--firefoxFontSize {
font-size: 75%;
}
.HomeView--firefoxFontSize {
font-size: 75%;
}
.HomeView--firefoxImageSize {
height: 113.875px;
}
@media only screen and (max-width: 740px) {
.HomeView--firefoxImageSize {
height: 113.875px;
}
@media only screen and (max-width: 740px) {
.HomeView--firefoxImageSize {
min-width: 126px !important;
max-width: 146px !important;
}
min-width: 126px !important;
max-width: 146px !important;
}
}
}
@@ -12,7 +12,7 @@
*/

import { log, sendMessageInPromise } from '../../utils';
import { GET_HOME_PROPS, SET_METRICS } from './HomeViewConstants';
import { GET_HOME_PROPS, MARK_PLUS_PROMO_MODAL_SHOWN, SET_METRICS } from './HomeViewConstants';

export function getHomeProps() {
return function(dispatch) {
@@ -39,3 +39,9 @@ export function setMetrics(actionData) {
});
};
}

export function markPlusPromoModalShown() {
return {
type: MARK_PLUS_PROMO_MODAL_SHOWN,
};
}
@@ -13,4 +13,5 @@

// Home View
export const GET_HOME_PROPS = 'GET_HOME_PROPS';
export const MARK_PLUS_PROMO_MODAL_SHOWN = 'MARK_PLUS_PROMO_MODAL_SHOWN';
export const SET_METRICS = 'SET_METRICS';
@@ -15,6 +15,8 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import QueryString from 'query-string';
import HomeView from './HomeView';
import { PlusPromoModal } from '../../../shared-components';
import { sendMessage } from '../../utils';

/**
* @class Implement the Home View for the Ghostery Hub
@@ -27,32 +29,52 @@ class HomeViewContainer extends Component {

const { justInstalled } = QueryString.parse(window.location.search);
this.state = {
getUserResolved: false,
justInstalled: justInstalled === 'true',
};

const title = t('hub_home_page_title');
window.document.title = title;

props.actions.getHomeProps();
props.actions.getUser();

// Prevent flickering in of user's email if getUser() returns after initial render,
// as well as flickering of plus promo modal if user is already a subscriber
props.actions.getUser()
.then(() => {
this.setState({
getUserResolved: true,
});
});
}

/**
* Function to handle toggling Metrics Opt-In
*/
* @private
* Function to handle toggling Metrics Opt-In
*/
_handleToggleMetrics = () => {
const enable_metrics = !this.props.home.enable_metrics;
this.props.actions.setMetrics({ enable_metrics });
}

/**
* React's required render function. Returns JSX
* @return {JSX} JSX for rendering the Home View of the Hub app
* @private
* Function to handle clicks on Select Plus and Select Basic in the Plus Promo Modal
*/
render() {
_handlePlusPromoModalClicks = () => {
// GH-1777
// we want to show the Plus Promo modal once per Hub visit - not every time the user returns to the Home view
this.props.actions.markPlusPromoModalShown();

sendMessage('SET_PLUS_PROMO_MODAL_SEEN', {});
}

_render() {
const { justInstalled } = this.state;
const { home, user } = this.props;
const isPlus = user && user.subscriptionsPlus || false;
const {
plus_promo_modal_shown,
setup_complete,
tutorial_complete,
enable_metrics,
@@ -64,38 +86,60 @@ class HomeViewContainer extends Component {
enable_metrics,
changeMetrics: this._handleToggleMetrics,
email: user ? user.email : '',
isPlus: user && user.subscriptionsPlus || false,
isPlus,
};

return <HomeView {...childProps} />;
return (
<div className="full-height">
<PlusPromoModal
show={!isPlus && !plus_promo_modal_shown}
location="hub"
clickHandler={this._handlePlusPromoModalClicks}
/>
<HomeView {...childProps} />
</div>
);
}

/**
* React's required render function. Returns JSX
* @return {JSX} JSX for rendering the Home View of the Hub app
*/
render() {
const { getUserResolved } = this.state;

return (getUserResolved ? this._render() : null);
}
}

// PropTypes ensure we pass required props of the correct type
// Note: isRequired is not needed when a prop has a default value
HomeViewContainer.propTypes = {
home: PropTypes.shape({
enable_metrics: PropTypes.bool,
plus_promo_modal_shown: PropTypes.bool,
setup_complete: PropTypes.bool,
tutorial_complete: PropTypes.bool,
enable_metrics: PropTypes.bool,
}),
user: PropTypes.shape({
email: PropTypes.string,
subscriptionsPlus: PropTypes.bool,
}),
actions: PropTypes.shape({
getHomeProps: PropTypes.func.isRequired,
setMetrics: PropTypes.func.isRequired,
getUser: PropTypes.func.isRequired,
markPlusPromoModalShown: PropTypes.func.isRequired,
setMetrics: PropTypes.func.isRequired,
}).isRequired,
};

// Default props used on the Home View
HomeViewContainer.defaultProps = {
home: {
enable_metrics: false,
plus_promo_modal_shown: false,
setup_complete: false,
tutorial_complete: false,
enable_metrics: false,
},
user: {
email: '',
@@ -11,7 +11,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0
*/

import { GET_HOME_PROPS, SET_METRICS } from './HomeViewConstants';
import { GET_HOME_PROPS, MARK_PLUS_PROMO_MODAL_SHOWN, SET_METRICS } from './HomeViewConstants';

const initialState = {};

@@ -31,6 +31,13 @@ function HomeViewReducer(state = initialState, action) {
}),
});
}
case MARK_PLUS_PROMO_MODAL_SHOWN: {
return Object.assign({}, state, {
home: Object.assign({}, state.home, {
plus_promo_modal_shown: true,
})
});
}
case SET_METRICS: {
const { enable_metrics } = action.data;
return Object.assign({}, state, {
ProTip! Use n and p to navigate between commits in a pull request.