From 5102f35dc2c4add89076b3a90da8923b9ad69686 Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Mon, 16 Sep 2019 13:53:50 -0400 Subject: [PATCH 01/27] Show plus promo modal on first view of Home view of each Hub session --- app/hub/Views/HomeView/HomeViewActions.js | 8 +++- app/hub/Views/HomeView/HomeViewConstants.js | 1 + app/hub/Views/HomeView/HomeViewContainer.jsx | 49 ++++++++++++++++++-- app/hub/Views/HomeView/HomeViewReducer.js | 9 +++- 4 files changed, 60 insertions(+), 7 deletions(-) diff --git a/app/hub/Views/HomeView/HomeViewActions.js b/app/hub/Views/HomeView/HomeViewActions.js index 20f3c5057..3de1b1976 100644 --- a/app/hub/Views/HomeView/HomeViewActions.js +++ b/app/hub/Views/HomeView/HomeViewActions.js @@ -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, + }; +} diff --git a/app/hub/Views/HomeView/HomeViewConstants.js b/app/hub/Views/HomeView/HomeViewConstants.js index 02218a87b..2defff14b 100644 --- a/app/hub/Views/HomeView/HomeViewConstants.js +++ b/app/hub/Views/HomeView/HomeViewConstants.js @@ -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'; diff --git a/app/hub/Views/HomeView/HomeViewContainer.jsx b/app/hub/Views/HomeView/HomeViewContainer.jsx index b3660cf85..802bcfd39 100644 --- a/app/hub/Views/HomeView/HomeViewContainer.jsx +++ b/app/hub/Views/HomeView/HomeViewContainer.jsx @@ -14,7 +14,9 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import QueryString from 'query-string'; +import { NavLink } from 'react-router-dom'; import HomeView from './HomeView'; +import { Modal } from '../../../shared-components'; /** * @class Implement the Home View for the Ghostery Hub @@ -28,6 +30,7 @@ class HomeViewContainer extends Component { const { justInstalled } = QueryString.parse(window.location.search); this.state = { justInstalled: justInstalled === 'true', + showPlusPromoModal: !props.home.plus_promo_modal_shown, }; const title = t('hub_home_page_title'); @@ -45,12 +48,38 @@ class HomeViewContainer extends Component { this.props.actions.setMetrics({ enable_metrics }); } + _dismissModal = () => { + this.setState({ + showPlusPromoModal: false, + }); + this.props.actions.markPlusPromoModalShown(); + } + + _renderModalChildren = () => ( +
+
+
+ {t('hub_setup_enter_modal_text')} +
+
+ Select Basic +
+
+
+ + {t('hub_setup_modal_button_no')} + +
+
+
+ ); + /** * React's required render function. Returns JSX * @return {JSX} JSX for rendering the Home View of the Hub app */ render() { - const { justInstalled } = this.state; + const { justInstalled, showPlusPromoModal } = this.state; const { home, user } = this.props; const { setup_complete, @@ -67,7 +96,14 @@ class HomeViewContainer extends Component { isPlus: user && user.subscriptionsPlus || false, }; - return ; + return ( +
+ + {this._renderModalChildren()} + + +
+ ); } } @@ -75,9 +111,10 @@ class HomeViewContainer extends Component { // 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, @@ -85,17 +122,19 @@ HomeViewContainer.propTypes = { }), 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: '', diff --git a/app/hub/Views/HomeView/HomeViewReducer.js b/app/hub/Views/HomeView/HomeViewReducer.js index e14aaa559..f60c13123 100644 --- a/app/hub/Views/HomeView/HomeViewReducer.js +++ b/app/hub/Views/HomeView/HomeViewReducer.js @@ -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, { From e1c1f54fd19fd090327fa099b25d867f1d335527 Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Mon, 16 Sep 2019 18:27:58 -0400 Subject: [PATCH 02/27] Stub out intro hub plus promo modal layout and implement its buttons --- app/hub/Views/HomeView/HomeView.scss | 45 ++++++++++++ app/hub/Views/HomeView/HomeViewContainer.jsx | 77 ++++++++++++++------ 2 files changed, 98 insertions(+), 24 deletions(-) diff --git a/app/hub/Views/HomeView/HomeView.scss b/app/hub/Views/HomeView/HomeView.scss index 00fbf9b47..86f1d26e8 100644 --- a/app/hub/Views/HomeView/HomeView.scss +++ b/app/hub/Views/HomeView/HomeView.scss @@ -152,6 +152,51 @@ } } +.PlusPromoModal__content { + position: relative; + width: 646px; + height: 553px; + background-color: #f7f7f7; + border: 1px solid #930194; + z-index: 10; +} + +.PlusPromoModal__thanks-for-download { + padding-top: 38px; + font-size: 24px; + font-weight: bold; +} + +.PlusPromoModal__choose-your-plan { + padding-top: 10px; + font-size: 18px; + font-weight: 500; +} + +.PlusPromoModal__option-boxes-container { + width: 100%; +} + +.PlusPromoModal__basic-box { + float: left; + margin-left: 55px; + width: 240px; + height: 298px; + border: solid 3px #1dafed; + background-color: #ffffff; +} + +.PlusPromoModal__plus-box { + float: right; + margin-right: 55px; + width: 240px; + height: 298px; + border-style: solid; + border-width: 3px; + border-image-source: linear-gradient(39deg, #f2daa2, #eab968); + border-image-slice: 1; +} + // Firefox Font Size Override and Image Size Override @-moz-document url-prefix() { .HomeView--firefoxFontSize { diff --git a/app/hub/Views/HomeView/HomeViewContainer.jsx b/app/hub/Views/HomeView/HomeViewContainer.jsx index 802bcfd39..717de1893 100644 --- a/app/hub/Views/HomeView/HomeViewContainer.jsx +++ b/app/hub/Views/HomeView/HomeViewContainer.jsx @@ -29,58 +29,77 @@ class HomeViewContainer extends Component { const { justInstalled } = QueryString.parse(window.location.search); this.state = { + getUserResolved: false, justInstalled: justInstalled === 'true', - showPlusPromoModal: !props.home.plus_promo_modal_shown, + plusPromoModalShown: props.home.plus_promo_modal_shown, }; 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 }); } + /** + * @private + * Dismisses the Plus promo modal if user opts to stick with the basic plan + */ _dismissModal = () => { this.setState({ - showPlusPromoModal: false, + plusPromoModalShown: true, }); this.props.actions.markPlusPromoModalShown(); } _renderModalChildren = () => ( -
-
-
- {t('hub_setup_enter_modal_text')} +
+
+ Thanks for downloading Ghostery! +
+
+ Choose your privacy plan
-
- Select Basic +
+
+ Ghostery Basic +
+
+ Ghostery Plus +
-
-
- - {t('hub_setup_modal_button_no')} - +
+
+ Select Basic
+ + Select Plus +
); - /** - * React's required render function. Returns JSX - * @return {JSX} JSX for rendering the Home View of the Hub app - */ - render() { - const { justInstalled, showPlusPromoModal } = this.state; + _render() { + const { justInstalled, plusPromoModalShown } = this.state; const { home, user } = this.props; + const isPlus = user && user.subscriptionsPlus || false; const { setup_complete, tutorial_complete, @@ -93,18 +112,28 @@ class HomeViewContainer extends Component { enable_metrics, changeMetrics: this._handleToggleMetrics, email: user ? user.email : '', - isPlus: user && user.subscriptionsPlus || false, + isPlus, }; return (
- + {this._renderModalChildren()}
); } + + /** + * 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 From 64869a597d7d386e9f4ecf786ae7b405f5522451 Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Tue, 17 Sep 2019 09:59:39 -0400 Subject: [PATCH 03/27] Remove some unnecessary plus promo modal related CSS --- app/hub/Views/HomeView/HomeView.scss | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/hub/Views/HomeView/HomeView.scss b/app/hub/Views/HomeView/HomeView.scss index 86f1d26e8..fbc1e4f04 100644 --- a/app/hub/Views/HomeView/HomeView.scss +++ b/app/hub/Views/HomeView/HomeView.scss @@ -173,10 +173,6 @@ font-weight: 500; } -.PlusPromoModal__option-boxes-container { - width: 100%; -} - .PlusPromoModal__basic-box { float: left; margin-left: 55px; From 5289bb96edd5a1b4a80e14d27d786f3468de2599 Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Tue, 17 Sep 2019 16:49:05 -0400 Subject: [PATCH 04/27] Continue adding styling for plus promo modal --- app/hub/Views/HomeView/HomeView.scss | 39 ++++++++++++++++++++ app/hub/Views/HomeView/HomeViewContainer.jsx | 18 +++++++-- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/app/hub/Views/HomeView/HomeView.scss b/app/hub/Views/HomeView/HomeView.scss index fbc1e4f04..19e5b99b0 100644 --- a/app/hub/Views/HomeView/HomeView.scss +++ b/app/hub/Views/HomeView/HomeView.scss @@ -173,6 +173,33 @@ font-weight: 500; } +.PlusPromoModal__option-header { + margin-top: 10px; + font-size: 19px; + font-weight: bold; + text-align: center; +} + +.PlusPromoModal__price-text { + text-align: center; +} + +.PlusPromoModal__currency-sign { + font-size: 30px; + font-weight: bold; +} + +.PlusPromoModal__amount { + vertical-align: middle; + font-size: 58px; +} + +.PlusPromoModal__per-month { + vertical-align: sub; + font-size: 18px; + font-weight: bold; +} + .PlusPromoModal__basic-box { float: left; margin-left: 55px; @@ -180,6 +207,12 @@ height: 298px; border: solid 3px #1dafed; background-color: #ffffff; + + .PlusPromoModal__option-header, + .PlusPromoModal__price-text, + .PlusPromoModal__amount { + color: #1dafed; + } } .PlusPromoModal__plus-box { @@ -191,6 +224,12 @@ border-width: 3px; border-image-source: linear-gradient(39deg, #f2daa2, #eab968); border-image-slice: 1; + + .PlusPromoModal__option-header, + .PlusPromoModal__price-text, + .PlusPromoModal__amount { + color: #ebbf73; + } } // Firefox Font Size Override and Image Size Override diff --git a/app/hub/Views/HomeView/HomeViewContainer.jsx b/app/hub/Views/HomeView/HomeViewContainer.jsx index 717de1893..c1ee9db24 100644 --- a/app/hub/Views/HomeView/HomeViewContainer.jsx +++ b/app/hub/Views/HomeView/HomeViewContainer.jsx @@ -69,7 +69,7 @@ class HomeViewContainer extends Component { this.props.actions.markPlusPromoModalShown(); } - _renderModalChildren = () => ( + _renderPlusPromoModal = () => (
Thanks for downloading Ghostery! @@ -79,10 +79,20 @@ class HomeViewContainer extends Component {
- Ghostery Basic +
Ghostery Basic
+
+ $ + 0 + per month +
- Ghostery Plus +
Ghostery Plus
+
+ $ + 2 + per month +
@@ -118,7 +128,7 @@ class HomeViewContainer extends Component { return (
- {this._renderModalChildren()} + {this._renderPlusPromoModal()}
From ce1fac9a9dd89890fbdb0f8e5613765ba82f7b89 Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Wed, 18 Sep 2019 11:32:24 -0400 Subject: [PATCH 05/27] Continue styling plus promo modal --- app/hub/Views/HomeView/HomeView.scss | 18 ++++++++++++++++++ app/hub/Views/HomeView/HomeViewContainer.jsx | 20 +++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/app/hub/Views/HomeView/HomeView.scss b/app/hub/Views/HomeView/HomeView.scss index 19e5b99b0..8040ccd5e 100644 --- a/app/hub/Views/HomeView/HomeView.scss +++ b/app/hub/Views/HomeView/HomeView.scss @@ -200,6 +200,11 @@ font-weight: bold; } +.PlusPromoModal__option-boxes-container { + margin-top: 37px; + margin-bottom: 30px; +} + .PlusPromoModal__basic-box { float: left; margin-left: 55px; @@ -232,6 +237,19 @@ } } +.PlusPromoModal__option-description-item { + font-size: 16px; + text-align: center; + color: #333333; +} + +.PlusPromoModal__button-container { + width: 98.6%; + margin: 0 auto; + height: 72px; + background-color: #e7ecee; +} + // Firefox Font Size Override and Image Size Override @-moz-document url-prefix() { .HomeView--firefoxFontSize { diff --git a/app/hub/Views/HomeView/HomeViewContainer.jsx b/app/hub/Views/HomeView/HomeViewContainer.jsx index c1ee9db24..2857a7885 100644 --- a/app/hub/Views/HomeView/HomeViewContainer.jsx +++ b/app/hub/Views/HomeView/HomeViewContainer.jsx @@ -77,7 +77,7 @@ class HomeViewContainer extends Component {
Choose your privacy plan
-
+
Ghostery Basic
@@ -85,6 +85,18 @@ class HomeViewContainer extends Component { 0 per month
+
+

+ Protection for + + one + + browser +

+

Blocks Ads

+

Blocks Trackers

+

Fast Browsing

+
Ghostery Plus
@@ -93,6 +105,12 @@ class HomeViewContainer extends Component { 2 per month
+
+

Ghostery Basic

+

Historical Tracker Stats

+

Priority Support

+

New Color Themes

+
From 361debe71f6100fe32ad3748141ec57a153de2bc Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Fri, 20 Sep 2019 09:46:25 -0400 Subject: [PATCH 06/27] Refactor plus promo modal CSS to improve alignment of elements --- app/hub/Views/HomeView/HomeView.scss | 78 +++++++++++++------ app/hub/Views/HomeView/HomeViewContainer.jsx | 80 +++++++++++--------- 2 files changed, 97 insertions(+), 61 deletions(-) diff --git a/app/hub/Views/HomeView/HomeView.scss b/app/hub/Views/HomeView/HomeView.scss index 8040ccd5e..0ad3b3145 100644 --- a/app/hub/Views/HomeView/HomeView.scss +++ b/app/hub/Views/HomeView/HomeView.scss @@ -173,6 +173,18 @@ font-weight: 500; } +.PlusPromoModal__options-container { + width: 100%; + display: flex; + justify-content: space-around; +} + +.PlusPromoModal__option-container { + display: flex; + justify-content: center; + flex-direction: column; +} + .PlusPromoModal__option-header { margin-top: 10px; font-size: 19px; @@ -205,28 +217,22 @@ margin-bottom: 30px; } -.PlusPromoModal__basic-box { - float: left; - margin-left: 55px; +.PlusPromoModal__option-description-box { width: 240px; height: 298px; - border: solid 3px #1dafed; - background-color: #ffffff; + border-style: solid; + border-width: 3px; + background-color: #FFFFFF; +} - .PlusPromoModal__option-header, - .PlusPromoModal__price-text, - .PlusPromoModal__amount { - color: #1dafed; - } +.PlusPromoModal__option-description-box--basic { + border-color: #1dafed; + color: #1dafed; } .PlusPromoModal__plus-box { float: right; margin-right: 55px; - width: 240px; - height: 298px; - border-style: solid; - border-width: 3px; border-image-source: linear-gradient(39deg, #f2daa2, #eab968); border-image-slice: 1; @@ -248,20 +254,44 @@ margin: 0 auto; height: 72px; background-color: #e7ecee; + display: flex; + justify-content: space-around; + align-items: center; + + .PlusPromoModal__button { + background-color: white; + color: #2cbcf4; + border: solid 2px #15b4f2; + } +} + +.PlusPromoModal__button { + margin: 0; + font-size: 12px; + font-weight: 500; + width: 135px; + background-color: white; + height: 40px; + align-items: center; + display: flex; + justify-content: center; + color: #2cbcf4; + border: solid 2px #15b4f2; + box-shadow: none; } // 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; } } +} diff --git a/app/hub/Views/HomeView/HomeViewContainer.jsx b/app/hub/Views/HomeView/HomeViewContainer.jsx index 2857a7885..26928aa2e 100644 --- a/app/hub/Views/HomeView/HomeViewContainer.jsx +++ b/app/hub/Views/HomeView/HomeViewContainer.jsx @@ -77,50 +77,56 @@ class HomeViewContainer extends Component {
Choose your privacy plan
-
-
-
Ghostery Basic
-
- $ - 0 - per month -
-
-

- Protection for - +

+
+
+
Ghostery Basic
+
+ $ + 0 + per month +
+
+

+ Protection for + one - - browser -

-

Blocks Ads

-

Blocks Trackers

-

Fast Browsing

+ + browser +

+

Blocks Ads

+

Blocks Trackers

+

Fast Browsing

+
+
+
+
+ Select Basic +
-
-
Ghostery Plus
-
- $ - 2 - per month +
+
+
Ghostery Plus
+
+ $ + 2 + per month +
+
+

Ghostery Basic

+

Historical Tracker Stats

+

Priority Support

+

New Color Themes

+
-
-

Ghostery Basic

-

Historical Tracker Stats

-

Priority Support

-

New Color Themes

+
-
-
- Select Basic -
- - Select Plus - -
); From a60d6b458966dfc268512f13b8b64b30e7c36cd3 Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Fri, 20 Sep 2019 18:04:03 -0400 Subject: [PATCH 07/27] Continue CSS work for plus promo modal --- app/hub/Views/HomeView/HomeView.scss | 69 ++++++++++---------- app/hub/Views/HomeView/HomeViewContainer.jsx | 20 +++--- 2 files changed, 43 insertions(+), 46 deletions(-) diff --git a/app/hub/Views/HomeView/HomeView.scss b/app/hub/Views/HomeView/HomeView.scss index 0ad3b3145..0deb40690 100644 --- a/app/hub/Views/HomeView/HomeView.scss +++ b/app/hub/Views/HomeView/HomeView.scss @@ -174,15 +174,34 @@ } .PlusPromoModal__options-container { - width: 100%; + height: 100%; + margin-top: 32px; display: flex; - justify-content: space-around; } .PlusPromoModal__option-container { display: flex; - justify-content: center; + width: 50%; + align-items: center; flex-direction: column; + justify-content: space-between; +} + +.PlusPromoModal__option-description-box { + width: 240px; + height: 298px; + border-style: solid; + border-width: 3px; + background-color: #FFFFFF; + + &.basic { + border-color: #1dafed; + } + + &.plus { + border-image-source: linear-gradient(39deg, #f2daa2, #eab968); + border-image-slice: 1; + } } .PlusPromoModal__option-header { @@ -190,10 +209,16 @@ font-size: 19px; font-weight: bold; text-align: center; + + &.basic { color: #1dafed; } + &.plus { color: #ebbf73; } } .PlusPromoModal__price-text { text-align: center; + + &.basic { color: #1dafed; } + &.plus { color: #ebbf73; } } .PlusPromoModal__currency-sign { @@ -212,37 +237,6 @@ font-weight: bold; } -.PlusPromoModal__option-boxes-container { - margin-top: 37px; - margin-bottom: 30px; -} - -.PlusPromoModal__option-description-box { - width: 240px; - height: 298px; - border-style: solid; - border-width: 3px; - background-color: #FFFFFF; -} - -.PlusPromoModal__option-description-box--basic { - border-color: #1dafed; - color: #1dafed; -} - -.PlusPromoModal__plus-box { - float: right; - margin-right: 55px; - border-image-source: linear-gradient(39deg, #f2daa2, #eab968); - border-image-slice: 1; - - .PlusPromoModal__option-header, - .PlusPromoModal__price-text, - .PlusPromoModal__amount { - color: #ebbf73; - } -} - .PlusPromoModal__option-description-item { font-size: 16px; text-align: center; @@ -250,14 +244,17 @@ } .PlusPromoModal__button-container { - width: 98.6%; - margin: 0 auto; + width: 100%; + margin-bottom: 3px; height: 72px; background-color: #e7ecee; display: flex; justify-content: space-around; align-items: center; + &.left { margin-left: 3px; } + &.right { margin-right: 3px; } + .PlusPromoModal__button { background-color: white; color: #2cbcf4; diff --git a/app/hub/Views/HomeView/HomeViewContainer.jsx b/app/hub/Views/HomeView/HomeViewContainer.jsx index 26928aa2e..7228058a0 100644 --- a/app/hub/Views/HomeView/HomeViewContainer.jsx +++ b/app/hub/Views/HomeView/HomeViewContainer.jsx @@ -78,10 +78,10 @@ class HomeViewContainer extends Component { Choose your privacy plan
-
-
-
Ghostery Basic
-
+
+
+
Ghostery Basic
+
$ 0 per month @@ -99,16 +99,16 @@ class HomeViewContainer extends Component {

Fast Browsing

-
+
Select Basic
-
-
-
Ghostery Plus
-
+
+
+
Ghostery Plus
+
$ 2 per month @@ -120,7 +120,7 @@ class HomeViewContainer extends Component {

New Color Themes

-
+
Select Plus From 4f8422931512e02f8d36bb8207c5e0a42098adc8 Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Mon, 23 Sep 2019 10:18:16 -0400 Subject: [PATCH 08/27] Implement recommended gold banner in plus promo modal --- app/hub/Views/HomeView/HomeView.scss | 19 ++++++++++++++++++- app/hub/Views/HomeView/HomeViewContainer.jsx | 4 ++++ app/images/hub/home/recommended-banner.svg | 13 +++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 app/images/hub/home/recommended-banner.svg diff --git a/app/hub/Views/HomeView/HomeView.scss b/app/hub/Views/HomeView/HomeView.scss index 0deb40690..22be9116f 100644 --- a/app/hub/Views/HomeView/HomeView.scss +++ b/app/hub/Views/HomeView/HomeView.scss @@ -157,7 +157,7 @@ width: 646px; height: 553px; background-color: #f7f7f7; - border: 1px solid #930194; + border: 1.9px solid #930194; z-index: 10; } @@ -199,11 +199,28 @@ } &.plus { + position: relative; // so that the recommended banner is positioned relative to this element border-image-source: linear-gradient(39deg, #f2daa2, #eab968); border-image-slice: 1; } } +.PlusPromoModal__recommended-banner { + position: absolute; + left: -30px; + top: -30px; +} + +.PlusPromoModal__recommended-banner-text { + position: relative; + left: 14px; + top: -46px; + transform: rotate(-13deg); + color: white; + font-size: 16px; + font-weight: bold; +} + .PlusPromoModal__option-header { margin-top: 10px; font-size: 19px; diff --git a/app/hub/Views/HomeView/HomeViewContainer.jsx b/app/hub/Views/HomeView/HomeViewContainer.jsx index 7228058a0..0e5ae94ac 100644 --- a/app/hub/Views/HomeView/HomeViewContainer.jsx +++ b/app/hub/Views/HomeView/HomeViewContainer.jsx @@ -107,6 +107,10 @@ class HomeViewContainer extends Component {
+
+ +
Recommended
+
Ghostery Plus
$ diff --git a/app/images/hub/home/recommended-banner.svg b/app/images/hub/home/recommended-banner.svg new file mode 100644 index 000000000..4777a7728 --- /dev/null +++ b/app/images/hub/home/recommended-banner.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file From 5cb13d57ec7e527e9fcec14f2ee7eac918e4a603 Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Fri, 27 Sep 2019 15:56:37 -0400 Subject: [PATCH 09/27] Update and tweak plus promo modal design --- app/hub/Views/HomeView/HomeView.scss | 89 ++++++++++++-------- app/hub/Views/HomeView/HomeViewContainer.jsx | 34 +++----- app/scss/hub.scss | 1 + app/scss/partials/_fonts.scss | 7 +- 4 files changed, 74 insertions(+), 57 deletions(-) diff --git a/app/hub/Views/HomeView/HomeView.scss b/app/hub/Views/HomeView/HomeView.scss index 22be9116f..d587e2629 100644 --- a/app/hub/Views/HomeView/HomeView.scss +++ b/app/hub/Views/HomeView/HomeView.scss @@ -161,35 +161,44 @@ z-index: 10; } +.PlusPromoModal__buttons-background { + background-color: #e7ecee; + position: absolute; + bottom: 3px; + width: 99%; + height: 72px; + z-index: -1; +} + .PlusPromoModal__thanks-for-download { - padding-top: 38px; - font-size: 24px; + padding-top: 30px; + font-size: 26px; font-weight: bold; } .PlusPromoModal__choose-your-plan { padding-top: 10px; font-size: 18px; - font-weight: 500; + font-weight: bold; } .PlusPromoModal__options-container { height: 100%; - margin-top: 32px; + margin-top: 44px; display: flex; + justify-content: space-evenly; } .PlusPromoModal__option-container { display: flex; - width: 50%; align-items: center; flex-direction: column; - justify-content: space-between; } .PlusPromoModal__option-description-box { width: 240px; height: 298px; + margin-bottom: 45px; border-style: solid; border-width: 3px; background-color: #FFFFFF; @@ -213,18 +222,19 @@ .PlusPromoModal__recommended-banner-text { position: relative; - left: 14px; - top: -46px; - transform: rotate(-13deg); + left: 18px; + top: -47px; + transform: rotate(-15deg); color: white; font-size: 16px; font-weight: bold; } .PlusPromoModal__option-header { - margin-top: 10px; + margin-top: 20px; font-size: 19px; font-weight: bold; + letter-spacing: -0.5px; text-align: center; &.basic { color: #1dafed; } @@ -232,6 +242,7 @@ } .PlusPromoModal__price-text { + line-height: 1.3; text-align: center; &.basic { color: #1dafed; } @@ -245,6 +256,7 @@ .PlusPromoModal__amount { vertical-align: middle; + font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 58px; } @@ -258,40 +270,47 @@ font-size: 16px; text-align: center; color: #333333; -} -.PlusPromoModal__button-container { - width: 100%; - margin-bottom: 3px; - height: 72px; - background-color: #e7ecee; - display: flex; - justify-content: space-around; - align-items: center; - - &.left { margin-left: 3px; } - &.right { margin-right: 3px; } - - .PlusPromoModal__button { - background-color: white; - color: #2cbcf4; - border: solid 2px #15b4f2; + &.bold { + font-weight: bold; + color: #4a4a4a; } } .PlusPromoModal__button { margin: 0; - font-size: 12px; - font-weight: 500; - width: 135px; - background-color: white; - height: 40px; - align-items: center; + font-size: 11px; + font-weight: 600; + letter-spacing: 0.5px; display: flex; + align-items: center; justify-content: center; - color: #2cbcf4; - border: solid 2px #15b4f2; box-shadow: none; + + &.basic { + width: 135px; + height: 40px; + border: solid 2px #15b4f2; + background-color: white; + color: #2cbcf4; + } + &.basic:hover { + background-color: #2cbcf4; + color: white; + } + + &.plus { + width: 163px; + height: 38px; + border: none; + background-image: linear-gradient(to bottom, #2fdbfa, #15b4f2); + color: white; + font-weight: 600; + letter-spacing: 0.5px; + } + &.plus:hover { + background-image: linear-gradient(to bottom, #1fcbea, #05a4e2); + } } // Firefox Font Size Override and Image Size Override diff --git a/app/hub/Views/HomeView/HomeViewContainer.jsx b/app/hub/Views/HomeView/HomeViewContainer.jsx index 0e5ae94ac..51743392a 100644 --- a/app/hub/Views/HomeView/HomeViewContainer.jsx +++ b/app/hub/Views/HomeView/HomeViewContainer.jsx @@ -14,7 +14,6 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import QueryString from 'query-string'; -import { NavLink } from 'react-router-dom'; import HomeView from './HomeView'; import { Modal } from '../../../shared-components'; @@ -71,6 +70,7 @@ class HomeViewContainer extends Component { _renderPlusPromoModal = () => (
+
Thanks for downloading Ghostery!
@@ -84,25 +84,18 @@ class HomeViewContainer extends Component {
$ 0 + per month
-

- Protection for - - one - - browser -

+

Protection for this browser

Blocks Ads

Blocks Trackers

Fast Browsing

-
-
- Select Basic -
+
+ Select Basic
@@ -115,20 +108,19 @@ class HomeViewContainer extends Component {
$ 2 + per month
-

Ghostery Basic

-

Historical Tracker Stats

-

Priority Support

-

New Color Themes

+

All basic features, plus:

+

Historical Tracker Stats

+

Priority Support

+

New Color Themes

- + + Select Plus +
diff --git a/app/scss/hub.scss b/app/scss/hub.scss index 1faa03903..0c55b41a4 100644 --- a/app/scss/hub.scss +++ b/app/scss/hub.scss @@ -53,6 +53,7 @@ html, body, #root { @import './partials/_hub_mixins'; @import './partials/_hub_svgs'; @import './partials/_shared_components_svgs'; +@import './partials/_fonts'; // Imports from ../hub directory @import '../hub/Views/SideNavigationView/SideNavigationView.scss'; diff --git a/app/scss/partials/_fonts.scss b/app/scss/partials/_fonts.scss index 0317018f2..919880895 100644 --- a/app/scss/partials/_fonts.scss +++ b/app/scss/partials/_fonts.scss @@ -8,7 +8,7 @@ * https://www.ghostery.com/ * * Copyright 2019 Ghostery, Inc. All rights reserved. - * + * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0 @@ -182,3 +182,8 @@ src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(../fonts/opensans-semibold-latin.woff2) format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; } + +@font-face { + font-family: Roboto; + src: local(Roboto), url(../fonts/roboto-all-charsets.woff2) format('woff2'), url(../fonts/roboto-all-charsets.woff) format('woff'); +} From f6d32981bdf01ea83e77a1f09d4e2498ad41f8be Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Tue, 1 Oct 2019 14:26:01 -0400 Subject: [PATCH 10/27] Fix path bug in i18n-checker tool. Consolidate redundant entries in messages. Add check icon to plus promo modal. Modify plus promo modal css. --- _locales/en/messages.json | 325 +++++++----------- app/content-scripts/rewards/OfferCard.jsx | 2 +- .../CreateAccountView/CreateAccountView.jsx | 12 +- app/hub/Views/HomeView/HomeView.jsx | 8 +- app/hub/Views/HomeView/HomeView.scss | 15 +- app/hub/Views/HomeView/HomeViewContainer.jsx | 43 ++- app/hub/Views/LogInView/LogInView.jsx | 8 +- app/hub/Views/PlusView/PlusView.jsx | 22 +- app/hub/Views/RewardsView/RewardsView.jsx | 2 +- .../SetupAntiSuiteViewContainer.jsx | 4 +- .../SetupBlockingDropdown.jsx | 2 +- .../SetupBlockingViewContainer.jsx | 2 +- .../SetupDoneView/SetupDoneViewContainer.jsx | 10 +- .../SetupHumanWebViewContainer.jsx | 4 +- .../SideNavigationViewContainer.jsx | 10 +- .../TutorialAntiSuiteView.jsx | 8 +- .../TutorialAntiSuiteViewContainer.jsx | 4 +- .../TutorialBlockingView.jsx | 4 +- .../TutorialBlockingViewContainer.jsx | 4 +- .../TutorialLayoutView/TutorialLayoutView.jsx | 4 +- .../TutorialLayoutViewContainer.jsx | 4 +- .../TutorialTrackerListViewContainer.jsx | 4 +- .../TutorialTrustView/TutorialTrustView.jsx | 8 +- .../TutorialTrustViewContainer.jsx | 4 +- .../TutorialVideoViewContainer.jsx | 2 +- app/images/hub/home/check-icon.svg | 12 + .../BuildingBlocks/CliqzFeature.jsx | 2 +- app/panel/components/CreateAccount.jsx | 12 +- app/panel/components/DetailMenu.jsx | 2 +- app/panel/components/ForgotPassword.jsx | 2 +- app/panel/components/Header.jsx | 6 +- app/panel/components/HeaderMenu.jsx | 6 +- app/panel/components/Help.jsx | 2 +- app/panel/components/Login.jsx | 6 +- app/panel/components/Rewards.jsx | 2 +- app/panel/components/StatsView.jsx | 2 +- app/panel/components/Subscribe.jsx | 2 +- .../Subscription/PrioritySupport.jsx | 2 +- .../Subscription/SubscriptionInfo.jsx | 6 +- .../Subscription/SubscriptionMenu.jsx | 4 +- app/panel/components/Summary.jsx | 2 +- app/panel/reducers/panel.js | 2 +- tools/i18n-checker.js | 14 +- 43 files changed, 271 insertions(+), 330 deletions(-) create mode 100644 app/images/hub/home/check-icon.svg diff --git a/_locales/en/messages.json b/_locales/en/messages.json index c3659b390..b3cf7ba65 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -394,12 +394,6 @@ } } }, - "email_confirm_field_label": { - "message": "Confirm Email:" - }, - "email_field_label": { - "message": "Email:" - }, "error_email_forgot": { "message": "Hmm, I can’t find that email. Maybe try another?" }, @@ -409,12 +403,6 @@ "forgot_password_message": { "message": "Forgot your password? Hey, it happens to everyone. We'll email you instructions to reset your password." }, - "invalid_email_confirmation": { - "message": "Your emails do not match." - }, - "invalid_email_create": { - "message": "Please enter a valid email." - }, "invalid_email_forgot": { "message": "Sorry, you have to enter a real email address." }, @@ -532,9 +520,6 @@ "description": "as in '5 (trackers) WHITELISTED'", "message": "Whitelisted" }, - "panel_create_account": { - "message": "Create Account" - }, "panel_email_verification_sent": { "message": "$BOLD_HTML_STARTS$ Success! $BOLD_HTML_END$ An account verification email has been sent to $EMAIL$", "placeholders": { @@ -568,9 +553,6 @@ "panel_help_questions_header": { "message": "Questions and Comments" }, - "panel_help_support": { - "message": "Support" - }, "panel_help_setup": { "message": "Set Up Ghostery" }, @@ -623,15 +605,6 @@ "panel_menu_about": { "message": "About" }, - "panel_menu_ghostery_subscriber": { - "message": "Ghostery Plus" - }, - "panel_menu_signin": { - "message": "Sign in" - }, - "panel_menu_signout": { - "message": "Sign out" - }, "global_settings_saved": { "message": "Global Settings Saved" }, @@ -691,9 +664,6 @@ "panel_signin_success_title": { "message": "Congrats! Your Ghostery account is ready to go." }, - "panel_title_create_account": { - "message": "Create Account" - }, "panel_tracker_found_sources_title": { "message": "Detected tracker URLs:" }, @@ -739,15 +709,9 @@ "panel_detail_menu_rewards_title": { "message": "Rewards" }, - "panel_detail_menu_stats_title": { - "message": "Historical stats" - }, "panel_detail_menu_premium_title": { "message": "Premium" }, - "panel_detail_learn_more": { - "message": "Learn More" - }, "panel_detail_history_title": { "message": "History" }, @@ -802,27 +766,15 @@ "notification_library_update_link": { "message": "Check out what's new" }, - "panel_header_sign_in": { - "message": "Sign In" - }, "panel_header_verify_account": { "message": "Verify Account" }, - "panel_header_simple_view": { - "message": "Simple View" - }, - "panel_header_detailed_view": { - "message": "Detailed View" - }, "password_characters_requirements": { "message": "Only these special characters are allowed: !@#$%^&*=+()<>{}[];:,./?" }, "password_field_label": { "message": "Password" }, - "create_password_field_label": { - "message": "Password:" - }, "password_requirements": { "message": "Use between 8 and 50 characters." }, @@ -1171,12 +1123,6 @@ "drawer_status_enable_smart_block": { "message": "Smart Blocking is" }, - "drawer_on": { - "message": "On" - }, - "drawer_off": { - "message": "Off" - }, "blocking_unblock_all": { "message": "Unblock All" }, @@ -1294,12 +1240,6 @@ "tooltip_resume": { "message": "Resume Ghostery" }, - "tooltip_expert": { - "message": "Detailed View" - }, - "tooltip_simple": { - "message": "Simple View" - }, "license_module": { "message": "Module" }, @@ -1350,30 +1290,15 @@ "hub_side_navigation_home": { "message": "Home" }, - "hub_side_navigation_setup": { - "message": "Customize Setup" - }, "hub_side_navigation_tutorial": { "message": "Take a Tutorial" }, - "hub_side_navigation_supporter": { - "message": "Get Ghostery Plus" - }, "hub_side_navigation_rewards": { "message": "Try Ghostery Rewards" }, "hub_side_navigation_products": { "message": "See More Ghostery Products" }, - "hub_side_navigation_create_account": { - "message": "Create Account" - }, - "hub_side_navigation_log_in": { - "message": "Sign In" - }, - "hub_side_navigation_log_out": { - "message": "Sign Out" - }, "hub_home_page_title": { "message": "Ghostery Hub - Home" }, @@ -1404,24 +1329,15 @@ "hub_home_subheader_optimize": { "message": "Optimize your Ghostery experience" }, - "hub_home_subheader_create_account": { - "message": "Create Account" - }, "hub_home_feature_tutorial_title": { "message": "Take a Tutorial" }, "hub_home_feature_tutorial_text": { "message": "Walk through Ghostery's main features." }, - "hub_home_feature_tutorial_button": { - "message": "Start" - }, "hub_home_feature_tutorial_button_alt": { "message": "Tutorial Complete" }, - "hub_home_feature_setup_title": { - "message": "Customize Setup" - }, "hub_home_feature_setup_text": { "message": "Edit your settings and blocking preferences." }, @@ -1434,12 +1350,6 @@ "hub_home_feature_supporter_text": { "message": "Upgrade to Ghostery Plus and unlock special features." }, - "hub_home_feature_supporter_button": { - "message": "Get Ghostery Plus" - }, - "hub_home_feature_supporter_button_alt": { - "message": "Already Subscribed" - }, "hub_setup_page_title": { "message": "Ghostery Hub - Setup" }, @@ -1475,15 +1385,6 @@ "hub_setup_exit_flow": { "message": "Exit Custom Setup" }, - "hub_setup_nav_previous": { - "message": "Previous" - }, - "hub_setup_nav_next": { - "message": "Next" - }, - "hub_setup_nav_done": { - "message": "Done" - }, "hub_setup_enter_modal_text": { "message": "Entering custom setup will override your previous Ghostery settings. Do you want to continue?" }, @@ -1581,18 +1482,9 @@ "hub_setup_feature_tutorial_description": { "message": "Walk through Ghostery's main features." }, - "hub_setup_feature_tutorial_button": { - "message": "Start" - }, - "hub_setup_feature_supporter_title": { - "message": "Get Ghostery Plus" - }, "hub_setup_feature_supporter_description": { "message": "Support Ghostery and unlock special perks." }, - "hub_setup_feature_supporter_button": { - "message": "Support" - }, "hub_setup_feature_products_title": { "message": "See more Ghostery Products" }, @@ -1626,21 +1518,6 @@ "hub_tutorial_exit_flow": { "message": "Exit Tutorial" }, - "hub_tutorial_nav_previous": { - "message": "Previous" - }, - "hub_tutorial_nav_next": { - "message": "Next" - }, - "hub_tutorial_nav_done": { - "message": "Done" - }, - "hub_tutorial_simple_view": { - "message": "Simple View" - }, - "hub_tutorial_detailed_view": { - "message": "Detailed View" - }, "hub_tutorial_detailed_expanded_view": { "message": "Detailed Expanded View" }, @@ -1746,9 +1623,6 @@ "hub_rewards_header_description": { "message": "Our new Rewards feature offers a powerful, completely private new way to receive real discounts online. Turn it on and check it out!" }, - "hub_rewards_header_learn_more": { - "message": "Learn More" - }, "hub_rewards_experience_title": { "message": "A Smarter Shopping Experience" }, @@ -1779,12 +1653,6 @@ "hub_supporter_header_description": { "message": "Show your support and unlock special perks!" }, - "hub_supporter_button_text": { - "message": "Get Ghostery Plus" - }, - "hub_supporter_button_text_alt": { - "message": "Already Subscribed" - }, "hub_supporter_price": { "message": "$SUP_START$$$SUP_END$$SPAN_START$2$SPAN_END$ per month", "placeholders": { @@ -1802,15 +1670,9 @@ } } }, - "hub_supporter_perk_themes_title": { - "message": "New Themes" - }, "hub_supporter_perk_themes_description": { "message": "Customize the Ghostery colors - try our Midnight theme!" }, - "hub_supporter_perk_stats_title": { - "message": "Historical Blocking Stats" - }, "hub_supporter_perk_stats_description": { "message": "View your blocking statistics and see how Ghostery is working for you" }, @@ -1823,21 +1685,12 @@ "hub_supporter_manifesto": { "message": "We strive to deliver the best privacy protection services to our users free of cost. While we do not charge for our privacy suite, you may choose to support us through a small monthly subscription. Join us in our mission by upgrading to Ghostery Plus - and unlock cool perks along the way!" }, - "hub_supporter_feature_theme_title": { - "message": "New Themes" - }, "hub_supporter_feature_theme_description": { "message": "Customize the Ghostery colors for a new visual experience! Introduced through popular request. Check out our special Midnight theme, and more to come." }, - "hub_supporter_feature_stats_title": { - "message": "Historical Blocking Stats" - }, "hub_supporter_feature_stats_description": { "message": "View historical blocking results with graphs and statistics to reveal trends and learn how Ghostery has affected your browsing." }, - "hub_supporter_feature_support_title": { - "message": "Priority Support" - }, "hub_supporter_feature_support_description": { "message": "Need assistance? Find a broken page? Have your questions answered and issues resolved fast with our Priority help desk service, accessible only when signed in with a Plus account." }, @@ -1859,15 +1712,6 @@ "hub_login_header_title": { "message": "Sign in to your account." }, - "hub_login_label_email": { - "message": "Email:" - }, - "hub_login_label_password": { - "message": "Password:" - }, - "hub_login_label_email_invalid": { - "message": "Please enter a valid email." - }, "hub_login_label_password_invalid": { "message": "Use between 8 and 50 characters." }, @@ -1877,9 +1721,6 @@ "hub_login_link_create_account": { "message": "Sign up." }, - "hub_login_button_submit": { - "message": "Sign In" - }, "hub_login_toast_success": { "message": "Sign in successful! Your account settings have been imported." }, @@ -1889,27 +1730,12 @@ "hub_create_account_header_title": { "message": "Would you like to create a Ghostery account to sync settings across browsers and devices?" }, - "hub_create_account_label_email": { - "message": "Email:" - }, - "hub_create_account_label_email_confirm": { - "message": "Confirm Email:" - }, "hub_create_account_label_first_name": { "message": "First Name (Optional):" }, "hub_create_account_label_email_last_name": { "message": "Last Name (Optional):" }, - "hub_create_account_label_password": { - "message": "Password:" - }, - "hub_create_account_label_email_invalid": { - "message": "Please enter a valid email." - }, - "hub_create_account_label_email_confirm_invalid": { - "message": "Your emails do not match." - }, "hub_create_account_label_password_invalid": { "message": "Only these special characters are allowed: !@#$%^&*=+()<>{}[];:,./?" }, @@ -1925,9 +1751,6 @@ "hub_create_account_link_login": { "message": "Sign in here." }, - "hub_create_account_button_submit": { - "message": "Create Account" - }, "hub_create_account_toast_success": { "message": "Account Successfully Created" }, @@ -2059,9 +1882,6 @@ "rewards_code_copied_toast_notification": { "message": "Rewards code copied!" }, - "rewards_learn_more": { - "message": "Learn More" - }, "offers_hub_copy_btn": { "message": "Copy code" }, @@ -2080,30 +1900,15 @@ "subscription_themes": { "message": "Ghostery Themes" }, - "subscription_info_title": { - "message": "Ghostery Plus" - }, "subscription_themes_title": { "message": "Themes" }, - "subscription_priority_support_title": { - "message": "Priority Support" - }, - "subscription_priority_support": { - "message": "Priority Support" - }, - "subscription_history_stats": { - "message": "Historical Stats" - }, "subscribe_pitch": { "message": "While Ghostery is free, you can choose to support us through a small subscription of $2 per month in exchange for cool perks, such as color themes, priority help service, and more. Join our mission and subscribe!" }, "subscribe_pitch_learn_more": { "message": "Learn more" }, - "subscribe_pitch_button_label": { - "message": "Get Ghostery Plus!" - }, "subscribe_pitch_sign_here": { "message": "Already a subscriber? Sign in here" }, @@ -2125,9 +1930,6 @@ "subscription_themes_tooltip": { "message": "Change the color scheme of Ghostery!" }, - "subscription_tracker_stats": { - "message": "Historical Stats" - }, "subscription_charge_date" : { "message": "Next Payment Date" }, @@ -2237,9 +2039,6 @@ "panel_stats_pitch_modal_sign_in": { "message": "Sign in here" }, - "panel_stats_pitch_modal_subscribe": { - "message": "Get Ghostery Plus!" - }, "panel_stats_pitch_modal_tooltip": { "message": "Erase all statistics history up until this point in time." }, @@ -2261,12 +2060,6 @@ "ads": { "message": "ads" }, - "cliqz_feature_status_on": { - "message": "On" - }, - "cliqz_feature_status_off": { - "message": "Off" - }, "create_account_form_legal_consent_checkbox_label": { "message": "I accept the $LINK_TERMS_START$Terms and Conditions$LINK_END$, the $LINK_LICENSE_START$Public License Agreement$LINK_END$, and consent to data practices found in the $LINK_PRIVACY_START$Privacy Policy$LINK_END$.", "placeholders": { @@ -2295,5 +2088,123 @@ }, "unknown_description": { "message": "Unknown trackers scrubbed by Anti-Tracking" + }, + "thanks_for_downloading_ghostery": { + "message": "Thanks for downloading Ghostery!" + }, + "choose_your_privacy_plan": { + "message": "Choose your privacy plan" + }, + "ghostery_basic": { + "message": "Ghostery Basic" + }, + "ghostery_plus": { + "message": "Ghostery Plus" + }, + "locale_appropriate_currency_icon": { + "message": "$$", + "description": "Use '$$' to mean '$'. '$' has a special meaning in the code and the first '$' tells the browser to ignore the special meaning of the second '$' and print it literally." + }, + "plus_monthly_subscription_price_number": { + "message": "2" + }, + "per_month": { + "message": "per month" + }, + "protection_for_this_browser": { + "message": "Protection for this browser" + }, + "blocks_ads": { + "message": "Blocks Ads" + }, + "blocks_trackers": { + "message": "Blocks Trackers" + }, + "fast_browsing": { + "message": "Fast Browsing" + }, + "select_basic": { + "message": "Select Basic" + }, + "recommended": { + "message": "Recommended" + }, + "get_ghostery_plus": { + "message": "Get Ghostery Plus" + }, + "get_ghostery_plus_bang": { + "message": "Get Ghostery Plus!" + }, + "already_subscribed": { + "message": "Already Subscribed" + }, + "new_themes": { + "message": "New Themes" + }, + "historical_blocking_stats": { + "message": "Historical Blocking Stats" + }, + "sign_in": { + "message": "Sign In" + }, + "sign_out": { + "message": "Sign Out" + }, + "create_account": { + "message": "Create Account" + }, + "email_colon": { + "message": "Email:" + }, + "confirm_email_colon": { + "message": "Confirm Email:" + }, + "next": { + "message": "Next" + }, + "previous": { + "message": "Previous" + }, + "done": { + "message": "Done" + }, + "simple_view": { + "message": "Simple View" + }, + "detailed_view": { + "message": "Detailed View" + }, + "support": { + "message": "Support" + }, + "start": { + "message": "Start" + }, + "password_colon": { + "message": "Password:" + }, + "please_enter_a_valid_email": { + "message": "Please enter a valid email." + }, + "your_email_do_not_match": { + "message": "Your emails do not match." + }, + "customize_setup": { + "message": "Customize Setup" + }, + "learn_more": { + "message": "Learn More" + }, + "historical_stats": { + "message": "Historical Stats" + }, + "priority_support": { + "message": "Priority Support" + }, + "on": { + "message": "On" + }, + "off": { + "message": "Off" } } diff --git a/app/content-scripts/rewards/OfferCard.jsx b/app/content-scripts/rewards/OfferCard.jsx index 9e26138b5..c97e906e9 100644 --- a/app/content-scripts/rewards/OfferCard.jsx +++ b/app/content-scripts/rewards/OfferCard.jsx @@ -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'); diff --git a/app/hub/Views/CreateAccountView/CreateAccountView.jsx b/app/hub/Views/CreateAccountView/CreateAccountView.jsx index 432463ee7..9bd342680 100644 --- a/app/hub/Views/CreateAccountView/CreateAccountView.jsx +++ b/app/hub/Views/CreateAccountView/CreateAccountView.jsx @@ -73,7 +73,7 @@ const CreateAccountView = (props) => {
{ /> {emailError && (
- {t('hub_create_account_label_email_invalid')} + {t('please_enter_a_valid_email')}
)}
{ /> {confirmEmailError && (
- {t('hub_create_account_label_email_confirm_invalid')} + {t('your_emails_do_not_match')}
)}
@@ -147,7 +147,7 @@ const CreateAccountView = (props) => {
{
diff --git a/app/hub/Views/HomeView/HomeView.jsx b/app/hub/Views/HomeView/HomeView.jsx index b22261ce3..e19d54d45 100644 --- a/app/hub/Views/HomeView/HomeView.jsx +++ b/app/hub/Views/HomeView/HomeView.jsx @@ -106,7 +106,7 @@ const HomeView = (props) => { ) : ( - {t('hub_home_subheader_create_account')} + {t('create_account')} )}
@@ -120,7 +120,7 @@ const HomeView = (props) => { {t('hub_home_feature_tutorial_text')}
- {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')}
@@ -128,7 +128,7 @@ const HomeView = (props) => {
- {t('hub_home_feature_setup_title')} + {t('customize_setup')}
{t('hub_home_feature_setup_text')} @@ -146,7 +146,7 @@ const HomeView = (props) => {
- {isPlus ? t('hub_home_feature_supporter_button_alt') : t('hub_home_feature_supporter_button')} + {isPlus ? t('Aready_Subscribed') : t('get_ghostery_plus')}
diff --git a/app/hub/Views/HomeView/HomeView.scss b/app/hub/Views/HomeView/HomeView.scss index d587e2629..e8ac4227b 100644 --- a/app/hub/Views/HomeView/HomeView.scss +++ b/app/hub/Views/HomeView/HomeView.scss @@ -271,12 +271,21 @@ text-align: center; color: #333333; - &.bold { - font-weight: bold; - color: #4a4a4a; + &.italic { + font-style: italic; } } +.PlusPromoModal__check-icon { + padding-right: 5px; + margin-top: -18px; +} + +.PlusPromoModal__plus-option-description-item-container { + display: flex; + justify-content: center; +} + .PlusPromoModal__button { margin: 0; font-size: 11px; diff --git a/app/hub/Views/HomeView/HomeViewContainer.jsx b/app/hub/Views/HomeView/HomeViewContainer.jsx index 51743392a..54c63194a 100644 --- a/app/hub/Views/HomeView/HomeViewContainer.jsx +++ b/app/hub/Views/HomeView/HomeViewContainer.jsx @@ -72,50 +72,59 @@ class HomeViewContainer extends Component {
- Thanks for downloading Ghostery! + {t('thanks_for_downloading_ghostery')}
- Choose your privacy plan + {t('choose_your_privacy_plan')}
-
Ghostery Basic
+
{t('ghostery_basic')}
- $ + {t('locale_appropriate_currency_icon')} 0 - per month + {t('per_month')}
-

Protection for this browser

-

Blocks Ads

-

Blocks Trackers

-

Fast Browsing

+

{t('protection_for_this_browser')}

+

{t('blocks_ads')}

+

{t('blocks_trackers')}

+

{t('fast_browsing')}

- Select Basic + {t('select_basic')}
-
Recommended
+
{t('recommended')}
Ghostery Plus
- $ - 2 + {t('locale_appropriate_currency_icon')} + {t('plus_monthly_subscription_price_number')} per month
-

All basic features, plus:

-

Historical Tracker Stats

-

Priority Support

-

New Color Themes

+

All basic features, plus:

+
+ +

Historical Tracker Stats

+
+
+ +

Priority Support

+
+
+ +

New Color Themes

+
diff --git a/app/hub/Views/LogInView/LogInView.jsx b/app/hub/Views/LogInView/LogInView.jsx index 2147985b6..6e76b3462 100644 --- a/app/hub/Views/LogInView/LogInView.jsx +++ b/app/hub/Views/LogInView/LogInView.jsx @@ -56,7 +56,7 @@ const LogInView = (props) => {
{ /> {emailError && (
- {t('hub_login_label_email_invalid')} + {t('please_enter_a_valid_email')}
)} {
diff --git a/app/hub/Views/PlusView/PlusView.jsx b/app/hub/Views/PlusView/PlusView.jsx index 9f6d0d89c..6457f84fe 100644 --- a/app/hub/Views/PlusView/PlusView.jsx +++ b/app/hub/Views/PlusView/PlusView.jsx @@ -36,11 +36,11 @@ class PlusView extends Component { return isPlus ? (
- {t('hub_supporter_button_text_alt')} + {t('already_subscribed')}
) : (
- {t('hub_supporter_button_text')} + {t('get_ghostery_plus')} ); } @@ -74,7 +74,7 @@ class PlusView extends Component {
- {t('hub_supporter_perk_themes_title')} + {t('new_themes')}
{t('hub_supporter_perk_themes_description')} @@ -83,7 +83,7 @@ class PlusView extends Component {
- {t('hub_supporter_perk_stats_title')} + {t('historical_blocking_stats')}
{t('hub_supporter_perk_stats_description')} @@ -110,7 +110,7 @@ class PlusView extends Component {
- {t('hub_supporter_feature_theme_title')} + {t('new_themes')}
{t('hub_supporter_feature_theme_description')} @@ -121,7 +121,7 @@ class PlusView extends Component { {t('hub_supporter_feature_theme_title')}
@@ -139,12 +139,12 @@ class PlusView extends Component { {t('hub_supporter_feature_stats_title')}
- {t('hub_supporter_feature_stats_title')} + {t('historical_blocking_stats')}
{t('hub_supporter_feature_stats_description')} @@ -155,7 +155,7 @@ class PlusView extends Component { {t('hub_supporter_feature_stats_title')}
@@ -171,7 +171,7 @@ class PlusView extends Component {
- {t('hub_supporter_feature_support_title')} + {t('priority_support')}
{t('hub_supporter_feature_support_description')} @@ -182,7 +182,7 @@ class PlusView extends Component { {t('hub_supporter_feature_support_title')}
diff --git a/app/hub/Views/RewardsView/RewardsView.jsx b/app/hub/Views/RewardsView/RewardsView.jsx index 345922a29..7dbe50a43 100644 --- a/app/hub/Views/RewardsView/RewardsView.jsx +++ b/app/hub/Views/RewardsView/RewardsView.jsx @@ -46,7 +46,7 @@ class RewardsView extends Component {
diff --git a/app/hub/Views/SetupViews/SetupAntiSuiteView/SetupAntiSuiteViewContainer.jsx b/app/hub/Views/SetupViews/SetupAntiSuiteView/SetupAntiSuiteViewContainer.jsx index 08302f49b..b497bb5b3 100644 --- a/app/hub/Views/SetupViews/SetupAntiSuiteView/SetupAntiSuiteViewContainer.jsx +++ b/app/hub/Views/SetupViews/SetupAntiSuiteView/SetupAntiSuiteViewContainer.jsx @@ -36,8 +36,8 @@ class SetupAntiSuiteViewContainer extends Component { hrefPrev: `/setup/${index - 1}`, hrefNext: `/setup/${index + 1}`, hrefDone: '/', - textPrev: t('hub_setup_nav_previous'), - textNext: t('hub_setup_nav_next'), + textPrev: t('previous'), + textNext: t('next'), textDone: t('hub_setup_exit_flow'), }); diff --git a/app/hub/Views/SetupViews/SetupBlockingDropdown/SetupBlockingDropdown.jsx b/app/hub/Views/SetupViews/SetupBlockingDropdown/SetupBlockingDropdown.jsx index f876ad30b..1944171e1 100644 --- a/app/hub/Views/SetupViews/SetupBlockingDropdown/SetupBlockingDropdown.jsx +++ b/app/hub/Views/SetupViews/SetupBlockingDropdown/SetupBlockingDropdown.jsx @@ -80,7 +80,7 @@ class SetupBlockingDropdown extends Component {
- {t('hub_setup_nav_done')} + {t('done')}
diff --git a/app/hub/Views/SetupViews/SetupBlockingView/SetupBlockingViewContainer.jsx b/app/hub/Views/SetupViews/SetupBlockingView/SetupBlockingViewContainer.jsx index fdc2e5124..e1b7ac71c 100644 --- a/app/hub/Views/SetupViews/SetupBlockingView/SetupBlockingViewContainer.jsx +++ b/app/hub/Views/SetupViews/SetupBlockingView/SetupBlockingViewContainer.jsx @@ -40,7 +40,7 @@ class SetupBlockingViewContainer extends Component { hrefNext: `/setup/${index + 1}`, hrefDone: '/', textPrev: false, - textNext: t('hub_setup_nav_next'), + textNext: t('next'), textDone: t('hub_setup_exit_flow'), }); diff --git a/app/hub/Views/SetupViews/SetupDoneView/SetupDoneViewContainer.jsx b/app/hub/Views/SetupViews/SetupDoneView/SetupDoneViewContainer.jsx index 1416b0388..3ee04fcb9 100644 --- a/app/hub/Views/SetupViews/SetupDoneView/SetupDoneViewContainer.jsx +++ b/app/hub/Views/SetupViews/SetupDoneView/SetupDoneViewContainer.jsx @@ -33,8 +33,8 @@ class SetupDoneViewContainer extends Component { hrefPrev: `/setup/${index - 1}`, hrefNext: '/', hrefDone: '/', - textPrev: t('hub_setup_nav_previous'), - textNext: t('hub_setup_nav_done'), + textPrev: t('previous'), + textNext: t('done'), textDone: t('hub_setup_exit_flow'), }); @@ -56,14 +56,14 @@ class SetupDoneViewContainer extends Component { id: 'tutorial', title: t('hub_setup_feature_tutorial_title'), description: t('hub_setup_feature_tutorial_description'), - buttonText: t('hub_setup_feature_tutorial_button'), + buttonText: t('start'), buttonHref: '/tutorial/1', }, { id: 'plus', - title: t('hub_setup_feature_supporter_title'), + title: t('get_ghostery_plus'), description: t('hub_setup_feature_supporter_description'), - buttonText: t('hub_setup_feature_supporter_button'), + buttonText: t('support'), buttonHref: '/plus', }, { diff --git a/app/hub/Views/SetupViews/SetupHumanWebView/SetupHumanWebViewContainer.jsx b/app/hub/Views/SetupViews/SetupHumanWebView/SetupHumanWebViewContainer.jsx index c7dc7ee8f..3e6415082 100644 --- a/app/hub/Views/SetupViews/SetupHumanWebView/SetupHumanWebViewContainer.jsx +++ b/app/hub/Views/SetupViews/SetupHumanWebView/SetupHumanWebViewContainer.jsx @@ -33,8 +33,8 @@ class SetupHumanWebViewContainer extends Component { hrefPrev: `/setup/${index - 1}`, hrefNext: `/setup/${index + 1}`, hrefDone: '/', - textPrev: t('hub_setup_nav_previous'), - textNext: t('hub_setup_nav_next'), + textPrev: t('previous'), + textNext: t('next'), textDone: t('hub_setup_exit_flow'), }); diff --git a/app/hub/Views/SideNavigationView/SideNavigationViewContainer.jsx b/app/hub/Views/SideNavigationView/SideNavigationViewContainer.jsx index f3526640f..7bd78abcf 100644 --- a/app/hub/Views/SideNavigationView/SideNavigationViewContainer.jsx +++ b/app/hub/Views/SideNavigationView/SideNavigationViewContainer.jsx @@ -49,21 +49,21 @@ class SideNavigationViewContainer extends Component { const menuItems = [ { href: '/', icon: 'home', text: t('hub_side_navigation_home') }, - { href: '/setup', icon: 'setup', text: t('hub_side_navigation_setup') }, + { href: '/setup', icon: 'setup', text: t('customize_setup') }, { href: '/tutorial', icon: 'tutorial', text: t('hub_side_navigation_tutorial') }, - { href: '/plus', icon: 'plus', text: t('hub_side_navigation_supporter') }, + { href: '/plus', icon: 'plus', text: t('get_ghostery_plus') }, ...(IS_CLIQZ ? [] : [{ href: '/rewards', icon: 'rewards', text: t('hub_side_navigation_rewards') }]), { href: '/products', icon: 'products', text: t('hub_side_navigation_products') } ]; const bottomItems = user ? [ { id: 'email', href: `https://account.${globals.GHOSTERY_DOMAIN}.com/`, text: user.email }, - { id: 'logout', text: t('hub_side_navigation_log_out'), clickHandler: this._handleLogoutClick }, + { id: 'logout', text: t('sign_out'), clickHandler: this._handleLogoutClick }, ] : [ - { id: 'create-account', href: '/create-account', text: t('hub_side_navigation_create_account') }, + { id: 'create-account', href: '/create-account', text: t('create_account') }, { id: 'log-id', href: '/log-in', - text: t('hub_side_navigation_log_in'), + text: t('sign_in'), icon: 'profile', }, ]; diff --git a/app/hub/Views/TutorialViews/TutorialAntiSuiteView/TutorialAntiSuiteView.jsx b/app/hub/Views/TutorialViews/TutorialAntiSuiteView/TutorialAntiSuiteView.jsx index ed5776b48..2d442232a 100644 --- a/app/hub/Views/TutorialViews/TutorialAntiSuiteView/TutorialAntiSuiteView.jsx +++ b/app/hub/Views/TutorialViews/TutorialAntiSuiteView/TutorialAntiSuiteView.jsx @@ -22,20 +22,20 @@ const TutorialAntiSuiteView = () => (
- {t('hub_tutorial_simple_view')} + {t('simple_view')}
{t('hub_tutorial_simple_view')}
- {t('hub_tutorial_detailed_view')} + {t('detailed_view')}
{t('hub_tutorial_detailed_view')}
diff --git a/app/hub/Views/TutorialViews/TutorialAntiSuiteView/TutorialAntiSuiteViewContainer.jsx b/app/hub/Views/TutorialViews/TutorialAntiSuiteView/TutorialAntiSuiteViewContainer.jsx index bd8a4af68..a08f8708c 100644 --- a/app/hub/Views/TutorialViews/TutorialAntiSuiteView/TutorialAntiSuiteViewContainer.jsx +++ b/app/hub/Views/TutorialViews/TutorialAntiSuiteView/TutorialAntiSuiteViewContainer.jsx @@ -33,8 +33,8 @@ class TutorialAntiSuiteViewContainer extends Component { hrefPrev: `/tutorial/${index - 1}`, hrefNext: '/', hrefDone: '/', - textPrev: t('hub_tutorial_nav_previous'), - textNext: t('hub_tutorial_nav_done'), + textPrev: t('previous'), + textNext: t('done'), textDone: t('hub_tutorial_exit_flow'), }); diff --git a/app/hub/Views/TutorialViews/TutorialBlockingView/TutorialBlockingView.jsx b/app/hub/Views/TutorialViews/TutorialBlockingView/TutorialBlockingView.jsx index eb3d9e4a7..ca0199702 100644 --- a/app/hub/Views/TutorialViews/TutorialBlockingView/TutorialBlockingView.jsx +++ b/app/hub/Views/TutorialViews/TutorialBlockingView/TutorialBlockingView.jsx @@ -22,12 +22,12 @@ const TutorialBlockingView = () => (
- {t('hub_tutorial_detailed_view')} + {t('detailed_view')}
{t('hub_tutorial_detailed_view')}
{t('hub_tutorial_detailed_expanded_view')} diff --git a/app/hub/Views/TutorialViews/TutorialBlockingView/TutorialBlockingViewContainer.jsx b/app/hub/Views/TutorialViews/TutorialBlockingView/TutorialBlockingViewContainer.jsx index d85fc5dfd..246ac22d1 100644 --- a/app/hub/Views/TutorialViews/TutorialBlockingView/TutorialBlockingViewContainer.jsx +++ b/app/hub/Views/TutorialViews/TutorialBlockingView/TutorialBlockingViewContainer.jsx @@ -33,8 +33,8 @@ class TutorialBlockingViewContainer extends Component { hrefPrev: `/tutorial/${index - 1}`, hrefNext: `/tutorial/${index + 1}`, hrefDone: '/', - textPrev: t('hub_tutorial_nav_previous'), - textNext: t('hub_tutorial_nav_next'), + textPrev: t('previous'), + textNext: t('next'), textDone: t('hub_tutorial_exit_flow'), }); } diff --git a/app/hub/Views/TutorialViews/TutorialLayoutView/TutorialLayoutView.jsx b/app/hub/Views/TutorialViews/TutorialLayoutView/TutorialLayoutView.jsx index f869c252e..56a7bac57 100644 --- a/app/hub/Views/TutorialViews/TutorialLayoutView/TutorialLayoutView.jsx +++ b/app/hub/Views/TutorialViews/TutorialLayoutView/TutorialLayoutView.jsx @@ -24,12 +24,12 @@ const TutorialLayoutView = () => ( {t('hub_tutorial_simple_view')} {t('hub_tutorial_detailed_view')}
diff --git a/app/hub/Views/TutorialViews/TutorialLayoutView/TutorialLayoutViewContainer.jsx b/app/hub/Views/TutorialViews/TutorialLayoutView/TutorialLayoutViewContainer.jsx index e8e276dea..407bf8fa9 100644 --- a/app/hub/Views/TutorialViews/TutorialLayoutView/TutorialLayoutViewContainer.jsx +++ b/app/hub/Views/TutorialViews/TutorialLayoutView/TutorialLayoutViewContainer.jsx @@ -33,8 +33,8 @@ class TutorialLayoutViewContainer extends Component { hrefPrev: `/tutorial/${index - 1}`, hrefNext: `/tutorial/${index + 1}`, hrefDone: '/', - textPrev: t('hub_tutorial_nav_previous'), - textNext: t('hub_tutorial_nav_next'), + textPrev: t('previous'), + textNext: t('next'), textDone: t('hub_tutorial_exit_flow'), }); } diff --git a/app/hub/Views/TutorialViews/TutorialTrackerListView/TutorialTrackerListViewContainer.jsx b/app/hub/Views/TutorialViews/TutorialTrackerListView/TutorialTrackerListViewContainer.jsx index f09f35815..b59c40b1d 100644 --- a/app/hub/Views/TutorialViews/TutorialTrackerListView/TutorialTrackerListViewContainer.jsx +++ b/app/hub/Views/TutorialViews/TutorialTrackerListView/TutorialTrackerListViewContainer.jsx @@ -33,8 +33,8 @@ class TutorialTrackerListViewContainer extends Component { hrefPrev: `/tutorial/${index - 1}`, hrefNext: `/tutorial/${index + 1}`, hrefDone: '/', - textPrev: t('hub_tutorial_nav_previous'), - textNext: t('hub_tutorial_nav_next'), + textPrev: t('previous'), + textNext: t('next'), textDone: t('hub_tutorial_exit_flow'), }); } diff --git a/app/hub/Views/TutorialViews/TutorialTrustView/TutorialTrustView.jsx b/app/hub/Views/TutorialViews/TutorialTrustView/TutorialTrustView.jsx index 31c66ff5a..605aaa9cb 100644 --- a/app/hub/Views/TutorialViews/TutorialTrustView/TutorialTrustView.jsx +++ b/app/hub/Views/TutorialViews/TutorialTrustView/TutorialTrustView.jsx @@ -22,20 +22,20 @@ const TutorialTrustView = () => (
- {t('hub_tutorial_simple_view')} + {t('simple_view')}
{t('hub_tutorial_simple_view')}
- {t('hub_tutorial_detailed_view')} + {t('detailed_view')}
{t('hub_tutorial_detailed_view')}
diff --git a/app/hub/Views/TutorialViews/TutorialTrustView/TutorialTrustViewContainer.jsx b/app/hub/Views/TutorialViews/TutorialTrustView/TutorialTrustViewContainer.jsx index 373233096..f48598ad0 100644 --- a/app/hub/Views/TutorialViews/TutorialTrustView/TutorialTrustViewContainer.jsx +++ b/app/hub/Views/TutorialViews/TutorialTrustView/TutorialTrustViewContainer.jsx @@ -33,8 +33,8 @@ class TutorialTrustViewContainer extends Component { hrefPrev: `/tutorial/${index - 1}`, hrefNext: `/tutorial/${index + 1}`, hrefDone: '/', - textPrev: t('hub_tutorial_nav_previous'), - textNext: t('hub_tutorial_nav_next'), + textPrev: t('previous'), + textNext: t('next'), textDone: t('hub_tutorial_exit_flow'), }); } diff --git a/app/hub/Views/TutorialViews/TutorialVideoView/TutorialVideoViewContainer.jsx b/app/hub/Views/TutorialViews/TutorialVideoView/TutorialVideoViewContainer.jsx index 65b4a5ee2..a6af3c5ce 100644 --- a/app/hub/Views/TutorialViews/TutorialVideoView/TutorialVideoViewContainer.jsx +++ b/app/hub/Views/TutorialViews/TutorialVideoView/TutorialVideoViewContainer.jsx @@ -34,7 +34,7 @@ class TutorialVideoViewContainer extends Component { hrefNext: `/tutorial/${index + 1}`, hrefDone: '/', textPrev: false, - textNext: t('hub_tutorial_nav_next'), + textNext: t('next'), textDone: t('hub_tutorial_exit_flow'), }); } diff --git a/app/images/hub/home/check-icon.svg b/app/images/hub/home/check-icon.svg new file mode 100644 index 000000000..7e2e16aad --- /dev/null +++ b/app/images/hub/home/check-icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/app/panel/components/BuildingBlocks/CliqzFeature.jsx b/app/panel/components/BuildingBlocks/CliqzFeature.jsx index 72cfe1372..093ebf0b1 100644 --- a/app/panel/components/BuildingBlocks/CliqzFeature.jsx +++ b/app/panel/components/BuildingBlocks/CliqzFeature.jsx @@ -51,7 +51,7 @@ class CliqzFeature extends React.Component { } _getStatus(active) { - return active ? t('cliqz_feature_status_on') : t('cliqz_feature_status_off'); + return active ? t('on') : t('off'); } _getTooltipBodyText(active, isTooltipBody, type) { diff --git a/app/panel/components/CreateAccount.jsx b/app/panel/components/CreateAccount.jsx index db5fe2f4a..8c615c5f5 100644 --- a/app/panel/components/CreateAccount.jsx +++ b/app/panel/components/CreateAccount.jsx @@ -152,21 +152,21 @@ class CreateAccount extends React.Component {

- { t('invalid_email_create') } + { t('please_enter_a_valid_email') }

-

{ t('invalid_email_confirmation') }

+

{ t('your_emails_do_not_match') }

@@ -194,7 +194,7 @@ class CreateAccount extends React.Component {
@@ -240,7 +240,7 @@ class CreateAccount extends React.Component {
diff --git a/app/panel/components/DetailMenu.jsx b/app/panel/components/DetailMenu.jsx index ecec07c98..9443029d5 100644 --- a/app/panel/components/DetailMenu.jsx +++ b/app/panel/components/DetailMenu.jsx @@ -74,7 +74,7 @@ class DetailMenu extends React.Component { - { t('panel_detail_menu_stats_title') } + { t('historical_stats') }
diff --git a/app/panel/components/ForgotPassword.jsx b/app/panel/components/ForgotPassword.jsx index f187ff21d..b1d0f7bbe 100644 --- a/app/panel/components/ForgotPassword.jsx +++ b/app/panel/components/ForgotPassword.jsx @@ -83,7 +83,7 @@ class ForgotPassword extends React.Component {
diff --git a/app/panel/components/Header.jsx b/app/panel/components/Header.jsx index 8768b72c2..a8be9d5ff 100644 --- a/app/panel/components/Header.jsx +++ b/app/panel/components/Header.jsx @@ -101,7 +101,7 @@ class Header extends React.Component { let text = ''; let handleOnClick = null; if (!loggedIn) { - text = t('panel_header_sign_in'); + text = t('sign_in'); handleOnClick = this.handleSignin; } else if (loggedIn && user && !user.emailValidated) { text = t('panel_header_verify_account'); @@ -186,7 +186,7 @@ class Header extends React.Component { const simpleTab = (
- {t('panel_header_simple_view')} + {t('simple_view')}
); @@ -194,7 +194,7 @@ class Header extends React.Component { const detailedTab = (
- {t('panel_header_detailed_view')} + {t('detailed_view')}
); diff --git a/app/panel/components/HeaderMenu.jsx b/app/panel/components/HeaderMenu.jsx index 5b0dcc2d7..bc03910c0 100644 --- a/app/panel/components/HeaderMenu.jsx +++ b/app/panel/components/HeaderMenu.jsx @@ -236,7 +236,7 @@ class HeaderMenu extends React.Component { - { t('panel_menu_ghostery_subscriber') } + { t('ghostery_plus') }
@@ -251,10 +251,10 @@ class HeaderMenu extends React.Component { { email }
- { t('panel_menu_signin') } + { t('sign_in') }
- { t('panel_menu_signout') } + { t('sign_out') }
diff --git a/app/panel/components/Help.jsx b/app/panel/components/Help.jsx index 057a47736..c436a5b06 100644 --- a/app/panel/components/Help.jsx +++ b/app/panel/components/Help.jsx @@ -33,7 +33,7 @@ const Help = () => {

{ t('panel_help_questions_header') }

{t('panel_help_faq')} {t('panel_help_feedback')} - { t('panel_help_support') } + { t('support') }

{ t('panel_help_contact_header') }

diff --git a/app/panel/components/Login.jsx b/app/panel/components/Login.jsx index 4ea3c807d..d92dbe856 100644 --- a/app/panel/components/Login.jsx +++ b/app/panel/components/Login.jsx @@ -99,7 +99,7 @@ class Login extends React.Component {
@@ -121,7 +121,7 @@ class Login extends React.Component {
@@ -136,7 +136,7 @@ class Login extends React.Component { { t('panel_forgot_password') }
- { t('panel_create_account') } + { t('create_account') }
diff --git a/app/panel/components/Rewards.jsx b/app/panel/components/Rewards.jsx index 5e727215e..1e547e385 100644 --- a/app/panel/components/Rewards.jsx +++ b/app/panel/components/Rewards.jsx @@ -224,7 +224,7 @@ class Rewards extends React.Component {
{ t('panel_detail_rewards_cliqz_text') }

- { t('panel_detail_learn_more') } + { t('learn_more') }
); diff --git a/app/panel/components/StatsView.jsx b/app/panel/components/StatsView.jsx index 312d8fa20..e850cac14 100644 --- a/app/panel/components/StatsView.jsx +++ b/app/panel/components/StatsView.jsx @@ -196,7 +196,7 @@ const StatsView = (props) => {
-
{t('panel_stats_pitch_modal_subscribe')}
+
{t('Get_Ghostery_Plus_bang')}
{ !loggedIn && (
diff --git a/app/panel/components/Subscribe.jsx b/app/panel/components/Subscribe.jsx index dab8ecd5f..e21fdf240 100644 --- a/app/panel/components/Subscribe.jsx +++ b/app/panel/components/Subscribe.jsx @@ -40,7 +40,7 @@ const Subscribe = (props) => { {t('subscribe_pitch_learn_more')}
- {t('subscribe_pitch_button_label')} + {t('Get_Ghostery_Plus_bang')}
{(loggedIn === 'false') && ( diff --git a/app/panel/components/Subscription/PrioritySupport.jsx b/app/panel/components/Subscription/PrioritySupport.jsx index 57b63ec52..94ddd15aa 100644 --- a/app/panel/components/Subscription/PrioritySupport.jsx +++ b/app/panel/components/Subscription/PrioritySupport.jsx @@ -24,7 +24,7 @@ const PrioritySupport = () => (
-

{ t('subscription_priority_support_title') }

+

{ t('priority_support') }

{ t('subscription_support') }
diff --git a/app/panel/components/Subscription/SubscriptionInfo.jsx b/app/panel/components/Subscription/SubscriptionInfo.jsx index 3090992c8..93c1161a4 100644 --- a/app/panel/components/Subscription/SubscriptionInfo.jsx +++ b/app/panel/components/Subscription/SubscriptionInfo.jsx @@ -45,7 +45,7 @@ const SubscriptionInfo = (props) => {
-

{ t('subscription_info_title') }

+

{ t('ghostery_plus') }

{loading ? (
) : ( @@ -75,8 +75,8 @@ const SubscriptionInfo = (props) => {
  • {t('subscription_midnight_theme')}
  • -
  • {t('subscription_tracker_stats')}
  • -
  • {t('subscription_priority_support')}
  • +
  • {t('historical_stats')}
  • +
  • {t('priority_support')}
diff --git a/app/panel/components/Subscription/SubscriptionMenu.jsx b/app/panel/components/Subscription/SubscriptionMenu.jsx index b718e67be..279ac3322 100644 --- a/app/panel/components/Subscription/SubscriptionMenu.jsx +++ b/app/panel/components/Subscription/SubscriptionMenu.jsx @@ -33,13 +33,13 @@ const SubscriptionMenu = () => (
  • - { t('subscription_priority_support') } + { t('priority_support') }
  • - { t('subscription_history_stats') } + { t('historical_stats') }
  • diff --git a/app/panel/components/Summary.jsx b/app/panel/components/Summary.jsx index 063f607be..32f03e328 100644 --- a/app/panel/components/Summary.jsx +++ b/app/panel/components/Summary.jsx @@ -707,7 +707,7 @@ class Summary extends React.Component { return (
    - +
    ); } diff --git a/app/panel/reducers/panel.js b/app/panel/reducers/panel.js index 194f16c73..20b873259 100644 --- a/app/panel/reducers/panel.js +++ b/app/panel/reducers/panel.js @@ -139,7 +139,7 @@ export default (state = initialState, action) => { errorText = t('email_address_in_use'); break; case '10080': - errorText = t('invalid_email_confirmation'); + errorText = t('your_emails_do_not_match'); break; default: errorText = t('server_error_message'); diff --git a/tools/i18n-checker.js b/tools/i18n-checker.js index dbf91e0af..0f5d96f36 100644 --- a/tools/i18n-checker.js +++ b/tools/i18n-checker.js @@ -24,7 +24,7 @@ const oboe = require('oboe'); const LOCALES_FOLDER = './_locales'; const GATHER_FILE_PATHS_EXCEPTIONS = ['.DS_Store']; const LANG_FILES_COUNT = 14; -const DEFAULT_LOCALE_PATH = '../_locales/en/messages.json'; +const DEFAULT_LOCALE_PATH = './_locales/en/messages.json'; const DUPLICATE_TOKENS_FILE = './tools/i18n_results/duplicate_tokens.txt'; const MISSING_TOKENS_FILE = './tools/i18n_results/missing_tokens.txt'; const EXTRA_TOKENS_FILE = './tools/i18n_results/extra_tokens.txt'; @@ -175,7 +175,7 @@ function findMissingKeys(paths) { let hasMissingKeys = false; const missingKeys = {}; paths.forEach((path) => { - const localeJson = jsonfile.readFileSync(`.${path}`); + const localeJson = jsonfile.readFileSync(`${path}`); const locale = path.match(/_locales\/(.*)\/messages.json/)[1]; missingKeys[locale] = []; Object.keys(defaultLocaleJson).forEach((key) => { @@ -210,7 +210,7 @@ function findExtraKeys(paths) { let hasExtraKeys = false; const extraKeys = {}; paths.forEach((path) => { - const localeJson = jsonfile.readFileSync(`.${path}`); + const localeJson = jsonfile.readFileSync(`${path}`); const locale = path.match(/_locales\/(.*)\/messages.json/)[1]; extraKeys[locale] = []; Object.keys(localeJson).forEach((key) => { @@ -243,7 +243,7 @@ function findMalformedKeys(paths) { let hasMalformedKeys = false; const malformedKeys = {}; paths.forEach((path) => { - const localeJson = jsonfile.readFileSync(`.${path}`); + const localeJson = jsonfile.readFileSync(`${path}`); const locale = path.match(/_locales\/(.*)\/messages.json/)[1]; malformedKeys[locale] = []; Object.keys(localeJson).forEach((key) => { @@ -278,7 +278,7 @@ function findMissingPlaceholders(paths) { let hasMissingPlaceholders = false; const missingPlaceholders = {}; paths.forEach((path) => { - const localeJson = jsonfile.readFileSync(`.${path}`); + const localeJson = jsonfile.readFileSync(`${path}`); const locale = path.match(/_locales\/(.*)\/messages.json/)[1]; missingPlaceholders[locale] = []; Object.keys(defaultLocaleJson).forEach((key) => { @@ -322,7 +322,7 @@ function findExtraPlaceholders(paths) { let hasExtraPlaceholders = false; const extraPlaceholders = {}; paths.forEach((path) => { - const localeJson = jsonfile.readFileSync(`.${path}`); + const localeJson = jsonfile.readFileSync(`${path}`); const locale = path.match(/_locales\/(.*)\/messages.json/)[1]; extraPlaceholders[locale] = []; Object.keys(localeJson).forEach((key) => { @@ -364,7 +364,7 @@ function findMalformedPlaceholders(paths) { let hasMalformedPlaceholders = false; const malformedPlaceholders = []; paths.forEach((path) => { - const localeJson = jsonfile.readFileSync(`.${path}`); + const localeJson = jsonfile.readFileSync(`${path}`); const locale = path.match(/_locales\/(.*)\/messages.json/)[1]; malformedPlaceholders[locale] = []; Object.keys(localeJson).forEach((key) => { From 4b16723dae69d97324e269dfcec270e98ae445ce Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Wed, 2 Oct 2019 16:02:30 -0400 Subject: [PATCH 11/27] Additional consolidation of redundant and unused entries in messages --- _locales/en/messages.json | 159 +++--------------- .../Views/LogInView/LogInViewContainer.jsx | 2 +- .../SetupAntiSuiteViewContainer.jsx | 10 +- .../TutorialAntiSuiteView.jsx | 10 +- .../BuildingBlocks/CliqzFeature.jsx | 48 +++++- app/panel/reducers/panel.js | 2 +- 6 files changed, 76 insertions(+), 155 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index b3cf7ba65..ea62f9a66 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -22,16 +22,9 @@ } } }, - "all": { - "description": "Default setting in the 'filter by type' dropdown for the tag browser. Doesn't filter anything out. Should read as 'Show all'.", - "message": "all" - }, "banner_check_your_email_title": { "message": "Please check your email shortly for a link to reset your password." }, - "banner_no_such_account_message": { - "message": "Looks like we can't find this email and password combo. Give it another shot." - }, "banner_email_not_in_system_message": { "message": "Sorry, that email isn't in our system." }, @@ -41,10 +34,6 @@ "blacklist_error_whitelist_url": { "message": "This site has been removed from your Trusted Sites list and added to your Restricted Sites list" }, - "blocked": { - "description": "Select this to show only blocked (checked) tags in the tag browser. Should read as 'Show blocked'.", - "message": "blocked" - }, "blocked_redirect_action_always_title": { "description": "Title for the 'Allow always and reload' button on the blocked redirect page.", "message": "Always allow and reload." @@ -375,25 +364,6 @@ } } }, - "copyright": { - "description": "Copyright message, shown in page footers.", - "message": "$C$ $YEAR$ $GHOSTERY$, a part of $COMPANY_ADDRESS$", - "placeholders": { - "c": { - "content": "©" - }, - "company_address": { - "content": "$1", - "example": "GHOSTERY, Inc., Such-and-such Street, Such-and-such Floor, New York, NY, Zip Code" - }, - "ghostery": { - "content": "Ghostery" - }, - "year": { - "content": "2015" - } - } - }, "error_email_forgot": { "message": "Hmm, I can’t find that email. Maybe try another?" }, @@ -415,15 +385,6 @@ "password_field_label_required": { "message": "Password required." }, - "name": { - "description": "The title of this extension (Ghostery).", - "message": "$EXTENSION_NAME$ – Privacy Ad Blocker", - "placeholders": { - "extension_name": { - "content": "Ghostery" - } - } - }, "none": { "description": "Used to say that this item does not belong to any of the groups, as in \"Groups: None\" (as opposed to \"Groups: Group A, Group B, Group C\").", "message": "None" @@ -1078,51 +1039,6 @@ "blocking_category_tracker_found": { "message": "Found" }, - "drawer_title_enable_anti_tracking": { - "message": "Enhanced Anti-Tracking" - }, - "drawer_tooltip_enable_anti_tracking": { - "message": "Anonymize unblocked and unknown trackers for greater browsing protection" - }, - "drawer_label_enable_anti_tracking": { - "message": "Trackers Anonymized" - }, - "drawer_desc_enable_anti_tracking": { - "message": "Private data points have been removed." - }, - "drawer_status_enable_anti_tracking": { - "message": "Anti-Tracking is" - }, - "drawer_title_enable_ad_block": { - "message": "Enhanced Ad Blocking" - }, - "drawer_tooltip_enable_ad_block": { - "message": "Block advertisements on websites you visit" - }, - "drawer_label_enable_ad_block": { - "message": "Ads Blocked" - }, - "drawer_desc_enable_ad_block": { - "message": "Ad spots have been blocked." - }, - "drawer_status_enable_ad_block": { - "message": "Ad Blocking is" - }, - "drawer_title_enable_smart_block": { - "message": "Smart Blocking" - }, - "drawer_tooltip_enable_smart_block": { - "message": "Automatically block and unblock trackers to optimize page performance" - }, - "drawer_label_enable_smart_block": { - "message": "Trackers Adjusted" - }, - "drawer_desc_enable_smart_block": { - "message": "Trackers have been temporarily blocked or unblocked." - }, - "drawer_status_enable_smart_block": { - "message": "Smart Blocking is" - }, "blocking_unblock_all": { "message": "Unblock All" }, @@ -1192,34 +1108,16 @@ "alert_site_restricted_off": { "message": "Site no longer blacklisted." }, - "tooltip_anti_track": { - "message": "Enhanced Anti-Tracking" - }, - "tooltip_anti_track_body": { - "message": "Anonymize personal data for greater protection." - }, - "tooltip_anti_track_body_on": { + "tooltip_anti_track_on": { "message": "Personal data points anonymized." }, "tooltip_body_in_cliqz": { "message": "Feature already active in Cliqz by default." }, - "tooltip_ad_block": { - "message": "Enhanced Ad Blocking" - }, - "tooltip_ad_block_body": { - "message": "Block advertisements." - }, - "tooltip_ad_block_body_on": { + "tooltip_ad_block_on": { "message": "Advertisements have been blocked." }, - "tooltip_smart_block": { - "message": "Smart Blocking" - }, - "tooltip_smart_block_body": { - "message": "Automatically block and unblock trackers to optimize page performance." - }, - "tooltip_smart_block_body_on": { + "tooltip_smart_block_on": { "message": "Tracker blocking adjusted to optimize page performance." }, "tooltip_trust": { @@ -1421,24 +1319,9 @@ "hub_setup_blocking_description_custom": { "message": "Choose which trackers to block" }, - "hub_setup_antisuite_name_antitracking": { - "message": "Enhanced Anti-Tracking" - }, "hub_setup_antisuite_description_antitracking": { "message": "Anonymize unblocked and unknown trackers for greater browsing protection." }, - "hub_setup_adblock_name_adblocking": { - "message": "Enhanced Ad Blocking" - }, - "hub_setup_adblock_description_adblocking": { - "message": "Block advertisements on websites you visit." - }, - "hub_setup_smartblocking_name_smartblocking": { - "message": "Smart Blocking" - }, - "hub_setup_smartblocking_description_smartblocking": { - "message": "Automatically block and unblock trackers to optimize page performance." - }, "hub_setup_feature_already_active": { "message": "This feature is already active in Cliqz by default. $LINK_LM_START$Learn More$LINK_LM_END$", "placeholders": { @@ -1569,24 +1452,9 @@ "hub_tutorial_antisuite_title": { "message": "Get extra protection and automated control with our enhanced privacy features:" }, - "hub_tutorial_antisuite_antitracking_title": { - "message": "Enhanced Anti-Tracking" - }, "hub_tutorial_antisuite_antitracking_description": { "message": "Remove data points that websites can use to identify you." }, - "hub_tutorial_antisuite_adblocking_title": { - "message": "Enhanced Ad Blocking" - }, - "hub_tutorial_antisuite_adblocking_description": { - "message": "Block advertisements on the pages you visit." - }, - "hub_tutorial_antisuite_smartblocking_title": { - "message": "Smart Blocking" - }, - "hub_tutorial_antisuite_smartblocking_description": { - "message": "Automatically block and unblock trackers to optimize page performance." - }, "hub_products_page_title" : { "message": "Ghostery Hub - Try Other Ghostery Products" }, @@ -1724,9 +1592,6 @@ "hub_login_toast_success": { "message": "Sign in successful! Your account settings have been imported." }, - "hub_login_toast_error": { - "message": "Looks like we can't find this email and password combo. Give it another shot." - }, "hub_create_account_header_title": { "message": "Would you like to create a Ghostery account to sync settings across browsers and devices?" }, @@ -2206,5 +2071,23 @@ }, "off": { "message": "Off" + }, + "enhanced_ad_blocking": { + "message": "Enhanced Ad Blocking" + }, + "smart_blocking": { + "message": "Smart Blocking" + }, + "smart_blocking_DESC": { + "message": "Automatically block and unblock trackers to optimize page performance." + }, + "ad_blocking_DESC": { + "message": "Block advertisements on the pages you visit." + }, + "anti_tracking_DESC": { + "message": "Anonymize personal data for greater protection." + }, + "no_such_email_password_combo": { + "message": "Looks like we can't find this email and password combo. Give it another shot." } } diff --git a/app/hub/Views/LogInView/LogInViewContainer.jsx b/app/hub/Views/LogInView/LogInViewContainer.jsx index b5d9c616a..fb9cd1289 100644 --- a/app/hub/Views/LogInView/LogInViewContainer.jsx +++ b/app/hub/Views/LogInView/LogInViewContainer.jsx @@ -109,7 +109,7 @@ class LogInViewContainer extends Component { this.props.history.push('/'); } else { this.props.actions.setToast({ - toastMessage: t('hub_login_toast_error'), + toastMessage: t('no_such_email_password_combo'), toastClass: 'alert' }); } diff --git a/app/hub/Views/SetupViews/SetupAntiSuiteView/SetupAntiSuiteViewContainer.jsx b/app/hub/Views/SetupViews/SetupAntiSuiteView/SetupAntiSuiteViewContainer.jsx index b497bb5b3..42c9f03fe 100644 --- a/app/hub/Views/SetupViews/SetupAntiSuiteView/SetupAntiSuiteViewContainer.jsx +++ b/app/hub/Views/SetupViews/SetupAntiSuiteView/SetupAntiSuiteViewContainer.jsx @@ -103,7 +103,7 @@ class SetupAntiSuiteViewContainer extends Component { const features = [ { id: 'anti-tracking', - name: t('hub_setup_antisuite_name_antitracking'), + name: t('enhanced_anti_tracking'), enabled: anti_tracking_enabled, locked: IS_CLIQZ, toggle: IS_CLIQZ ? @@ -113,20 +113,20 @@ class SetupAntiSuiteViewContainer extends Component { }, { id: 'ad-block', - name: t('hub_setup_adblock_name_adblocking'), + name: t('enhanced_ad_blocking'), enabled: ad_block_enabled, locked: IS_CLIQZ, toggle: IS_CLIQZ ? () => {} : () => this._handleToggle('ad-block'), - description: IS_CLIQZ ? t('hub_setup_feature_already_active') : t('hub_setup_adblock_description_adblocking'), + description: IS_CLIQZ ? t('hub_setup_feature_already_active') : t('ad_blocking_DESC'), }, { id: 'smart-blocking', - name: t('hub_setup_smartblocking_name_smartblocking'), + name: t('smart_blocking'), enabled: enable_smart_block, toggle: () => this._handleToggle('smart-blocking'), - description: t('hub_setup_smartblocking_description_smartblocking'), + description: t('smart_blocking_DESC'), } ]; diff --git a/app/hub/Views/TutorialViews/TutorialAntiSuiteView/TutorialAntiSuiteView.jsx b/app/hub/Views/TutorialViews/TutorialAntiSuiteView/TutorialAntiSuiteView.jsx index 2d442232a..5b4ec4e55 100644 --- a/app/hub/Views/TutorialViews/TutorialAntiSuiteView/TutorialAntiSuiteView.jsx +++ b/app/hub/Views/TutorialViews/TutorialAntiSuiteView/TutorialAntiSuiteView.jsx @@ -48,7 +48,7 @@ const TutorialAntiSuiteView = () => (
    - {t('hub_tutorial_antisuite_antitracking_title')} + {t('enhanced_anti_tracking')}
    {t('hub_tutorial_antisuite_antitracking_description')} @@ -59,10 +59,10 @@ const TutorialAntiSuiteView = () => (
    - {t('hub_tutorial_antisuite_adblocking_title')} + {t('enhanced_ad_blocking')}
    - {t('hub_tutorial_antisuite_adblocking_description')} + {t('ad_blocking_DESC')}
    @@ -70,10 +70,10 @@ const TutorialAntiSuiteView = () => (
    - {t('hub_tutorial_antisuite_smartblocking_title')} + {t('smart_blocking')}
    - {t('hub_tutorial_antisuite_smartblocking_description')} + {t('smart_blocking_DESC')}
    diff --git a/app/panel/components/BuildingBlocks/CliqzFeature.jsx b/app/panel/components/BuildingBlocks/CliqzFeature.jsx index 093ebf0b1..b699e387a 100644 --- a/app/panel/components/BuildingBlocks/CliqzFeature.jsx +++ b/app/panel/components/BuildingBlocks/CliqzFeature.jsx @@ -57,13 +57,44 @@ class CliqzFeature extends React.Component { _getTooltipBodyText(active, isTooltipBody, type) { if (!isTooltipBody) return false; - return active ? - t(`tooltip_${type}_body_on`) : - t(`tooltip_${type}_body`); + if (active) { + switch (type) { + case 'ad_block': + return t('tooltip_ad_block_on'); + case 'anti_track': + return t('tooltip_anti_track_on'); + case 'smart_block': + return t('tooltip_smart_block_on'); + default: + return false; + } + } else { + switch (type) { + case 'ad_block': + return t('ad_blocking_DESC'); + case 'anti_track': + return t('anti_tracking_DESC'); + case 'smart_block': + return t('smart_blocking_DESC'); + default: + return false; + } + } } _getTooltipHeaderText(isTooltipHeader, type) { - return isTooltipHeader ? t(`tooltip_${type}`) : false; + if (!isTooltipHeader) return false; + + switch (type) { + case 'ad_block': + return t('enhanced_ad_blocking'); + case 'anti_track': + return t('enhanced_anti_tracking'); + case 'smart_block': + return t('smart_blocking'); + default: + return false; + } } _getAlertText(active, type) { @@ -103,7 +134,14 @@ class CliqzFeature extends React.Component { const iconClassNames = ClassNames('CliqzFeature__icon', cssTypeName, 'g-tooltip'); const featureType = type === 'anti_track' ? 'anti_tracking' : type; - const featureName = t(`drawer_title_enable_${featureType}`); + let featureName; + if (featureType === 'anti_tracking') { + featureName = t('enhanced_anti_tracking'); + } else if (featureType === 'ad_block') { + featureName = t('enhanced_ad_blocking'); + } else if (featureType === 'smart_block') { + featureName = t('smart_blocking'); + } return (
    diff --git a/app/panel/reducers/panel.js b/app/panel/reducers/panel.js index 20b873259..b249b6e70 100644 --- a/app/panel/reducers/panel.js +++ b/app/panel/reducers/panel.js @@ -108,7 +108,7 @@ export default (state = initialState, action) => { switch (err.code) { case '10050': case '10110': - errorText = t('banner_no_such_account_message'); + errorText = t('no_such_email_password_combo'); break; default: errorText = t('server_error_message'); From 569382ef1230330c0151b5815e54916ac433f558 Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Sun, 6 Oct 2019 16:42:57 -0400 Subject: [PATCH 12/27] Factor plus promo modal rendering out to shared component. Implement rendering in panel. Implement display context CSS adjustments. --- _locales/en/messages.json | 12 ++ .../CreateAccountView.test.jsx.snap | 20 +- app/hub/Views/HomeView/HomeView.scss | 170 --------------- app/hub/Views/HomeView/HomeViewContainer.jsx | 71 +------ .../__snapshots__/HomeView.test.jsx.snap | 12 +- .../__snapshots__/LogInView.test.jsx.snap | 14 +- .../__snapshots__/PlusView.test.jsx.snap | 68 +++--- .../__snapshots__/RewardsView.test.jsx.snap | 2 +- .../SetupBlockingDropdown.test.jsx.snap | 2 +- .../TutorialAntiSuiteView.test.jsx.snap | 18 +- .../TutorialBlockingView.test.jsx.snap | 4 +- .../TutorialLayoutView.test.jsx.snap | 4 +- .../TutorialTrustView.test.jsx.snap | 8 +- app/panel/components/Panel.jsx | 8 + app/scss/panel.scss | 3 + app/shared-components/Modal/Modal.jsx | 99 +++++++++ app/shared-components/Modal/Modal.scss | 200 ++++++++++++++++++ 17 files changed, 400 insertions(+), 315 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index ea62f9a66..2aee9c844 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -385,6 +385,15 @@ "password_field_label_required": { "message": "Password required." }, + "name": { + "description": "The title of this extension (Ghostery).", + "message": "$EXTENSION_NAME$ – Privacy Ad Blocker", + "placeholders": { + "extension_name": { + "content": "Ghostery" + } + } + }, "none": { "description": "Used to say that this item does not belong to any of the groups, as in \"Groups: None\" (as opposed to \"Groups: Group A, Group B, Group C\").", "message": "None" @@ -1960,6 +1969,9 @@ "choose_your_privacy_plan": { "message": "Choose your privacy plan" }, + "choose_your_ghostery_privacy_plan": { + "message": "Choose your Ghostery privacy plan" + }, "ghostery_basic": { "message": "Ghostery Basic" }, diff --git a/app/hub/Views/CreateAccountView/__tests__/__snapshots__/CreateAccountView.test.jsx.snap b/app/hub/Views/CreateAccountView/__tests__/__snapshots__/CreateAccountView.test.jsx.snap index 61e4288d1..d1f69a18d 100644 --- a/app/hub/Views/CreateAccountView/__tests__/__snapshots__/CreateAccountView.test.jsx.snap +++ b/app/hub/Views/CreateAccountView/__tests__/__snapshots__/CreateAccountView.test.jsx.snap @@ -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 - hub_create_account_label_email_confirm + confirm_email_colon - hub_create_account_label_password + password_colon - hub_create_account_button_submit + create_account
    @@ -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 - hub_create_account_label_email_invalid + please_enter_a_valid_email
    - hub_create_account_label_email_confirm + confirm_email_colon - hub_create_account_label_email_confirm_invalid + your_emails_do_not_match
    @@ -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 - hub_create_account_button_submit + create_account
    diff --git a/app/hub/Views/HomeView/HomeView.scss b/app/hub/Views/HomeView/HomeView.scss index e8ac4227b..7a228b9cc 100644 --- a/app/hub/Views/HomeView/HomeView.scss +++ b/app/hub/Views/HomeView/HomeView.scss @@ -152,176 +152,6 @@ } } -.PlusPromoModal__content { - position: relative; - width: 646px; - height: 553px; - background-color: #f7f7f7; - border: 1.9px solid #930194; - z-index: 10; -} - -.PlusPromoModal__buttons-background { - background-color: #e7ecee; - position: absolute; - bottom: 3px; - width: 99%; - height: 72px; - z-index: -1; -} - -.PlusPromoModal__thanks-for-download { - padding-top: 30px; - font-size: 26px; - font-weight: bold; -} - -.PlusPromoModal__choose-your-plan { - padding-top: 10px; - font-size: 18px; - font-weight: bold; -} - -.PlusPromoModal__options-container { - height: 100%; - margin-top: 44px; - display: flex; - justify-content: space-evenly; -} - -.PlusPromoModal__option-container { - display: flex; - align-items: center; - flex-direction: column; -} - -.PlusPromoModal__option-description-box { - width: 240px; - height: 298px; - margin-bottom: 45px; - border-style: solid; - border-width: 3px; - background-color: #FFFFFF; - - &.basic { - border-color: #1dafed; - } - - &.plus { - position: relative; // so that the recommended banner is positioned relative to this element - border-image-source: linear-gradient(39deg, #f2daa2, #eab968); - border-image-slice: 1; - } -} - -.PlusPromoModal__recommended-banner { - position: absolute; - left: -30px; - top: -30px; -} - -.PlusPromoModal__recommended-banner-text { - position: relative; - left: 18px; - top: -47px; - transform: rotate(-15deg); - color: white; - font-size: 16px; - font-weight: bold; -} - -.PlusPromoModal__option-header { - margin-top: 20px; - font-size: 19px; - font-weight: bold; - letter-spacing: -0.5px; - text-align: center; - - &.basic { color: #1dafed; } - &.plus { color: #ebbf73; } -} - -.PlusPromoModal__price-text { - line-height: 1.3; - text-align: center; - - &.basic { color: #1dafed; } - &.plus { color: #ebbf73; } -} - -.PlusPromoModal__currency-sign { - font-size: 30px; - font-weight: bold; -} - -.PlusPromoModal__amount { - vertical-align: middle; - font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 58px; -} - -.PlusPromoModal__per-month { - vertical-align: sub; - font-size: 18px; - font-weight: bold; -} - -.PlusPromoModal__option-description-item { - font-size: 16px; - text-align: center; - color: #333333; - - &.italic { - font-style: italic; - } -} - -.PlusPromoModal__check-icon { - padding-right: 5px; - margin-top: -18px; -} - -.PlusPromoModal__plus-option-description-item-container { - display: flex; - justify-content: center; -} - -.PlusPromoModal__button { - margin: 0; - font-size: 11px; - font-weight: 600; - letter-spacing: 0.5px; - display: flex; - align-items: center; - justify-content: center; - box-shadow: none; - - &.basic { - width: 135px; - height: 40px; - border: solid 2px #15b4f2; - background-color: white; - color: #2cbcf4; - } - &.basic:hover { - background-color: #2cbcf4; - color: white; - } - - &.plus { - width: 163px; - height: 38px; - border: none; - background-image: linear-gradient(to bottom, #2fdbfa, #15b4f2); - color: white; - font-weight: 600; - letter-spacing: 0.5px; - } - &.plus:hover { - background-image: linear-gradient(to bottom, #1fcbea, #05a4e2); - } -} - // Firefox Font Size Override and Image Size Override @-moz-document url-prefix() { .HomeView--firefoxFontSize { diff --git a/app/hub/Views/HomeView/HomeViewContainer.jsx b/app/hub/Views/HomeView/HomeViewContainer.jsx index 54c63194a..fc8ddbd43 100644 --- a/app/hub/Views/HomeView/HomeViewContainer.jsx +++ b/app/hub/Views/HomeView/HomeViewContainer.jsx @@ -59,7 +59,7 @@ class HomeViewContainer extends Component { /** * @private - * Dismisses the Plus promo modal if user opts to stick with the basic plan + * Dismisses the Plus promo modal when user clicks either the Select Plus or Select Basic button */ _dismissModal = () => { this.setState({ @@ -68,73 +68,6 @@ class HomeViewContainer extends Component { this.props.actions.markPlusPromoModalShown(); } - _renderPlusPromoModal = () => ( -
    -
    -
    - {t('thanks_for_downloading_ghostery')} -
    -
    - {t('choose_your_privacy_plan')} -
    -
    -
    -
    -
    {t('ghostery_basic')}
    -
    - {t('locale_appropriate_currency_icon')} - 0 - - {t('per_month')} -
    -
    -

    {t('protection_for_this_browser')}

    -

    {t('blocks_ads')}

    -

    {t('blocks_trackers')}

    -

    {t('fast_browsing')}

    -
    -
    -
    - {t('select_basic')} -
    -
    -
    -
    -
    - -
    {t('recommended')}
    -
    -
    Ghostery Plus
    -
    - {t('locale_appropriate_currency_icon')} - {t('plus_monthly_subscription_price_number')} - - per month -
    -
    -

    All basic features, plus:

    -
    - -

    Historical Tracker Stats

    -
    -
    - -

    Priority Support

    -
    -
    - -

    New Color Themes

    -
    -
    -
    - - Select Plus - -
    -
    -
    - ); - _render() { const { justInstalled, plusPromoModalShown } = this.state; const { home, user } = this.props; @@ -157,7 +90,7 @@ class HomeViewContainer extends Component { return (
    - {this._renderPlusPromoModal()} + {Modal.renderPlusPromo('inHub', this._dismissModal)}
    diff --git a/app/hub/Views/HomeView/__tests__/__snapshots__/HomeView.test.jsx.snap b/app/hub/Views/HomeView/__tests__/__snapshots__/HomeView.test.jsx.snap index 1b14914b8..808de5ec5 100644 --- a/app/hub/Views/HomeView/__tests__/__snapshots__/HomeView.test.jsx.snap +++ b/app/hub/Views/HomeView/__tests__/__snapshots__/HomeView.test.jsx.snap @@ -75,7 +75,7 @@ exports[`app/hub/Views/HomeView component Snapshot tests with react-test-rendere href="/create-account" onClick={[Function]} > - hub_home_subheader_create_account + create_account
    - hub_home_feature_tutorial_button + start
    - hub_home_feature_setup_title + customize_setup
    - hub_home_feature_supporter_button + get_ghostery_plus
    @@ -295,7 +295,7 @@ exports[`app/hub/Views/HomeView component Snapshot tests with react-test-rendere
    - hub_home_feature_setup_title + customize_setup
    - hub_home_feature_supporter_button_alt + Aready_Subscribed
    diff --git a/app/hub/Views/LogInView/__tests__/__snapshots__/LogInView.test.jsx.snap b/app/hub/Views/LogInView/__tests__/__snapshots__/LogInView.test.jsx.snap index 82823ec9d..d6b6f0e0f 100644 --- a/app/hub/Views/LogInView/__tests__/__snapshots__/LogInView.test.jsx.snap +++ b/app/hub/Views/LogInView/__tests__/__snapshots__/LogInView.test.jsx.snap @@ -40,7 +40,7 @@ exports[`app/hub/Views/LogIn component Snapshot tests with react-test-renderer l className="LogInView__inputLabel" htmlFor="login-email" > - hub_login_label_email + email_colon - hub_login_label_password + password_colon - hub_login_button_submit + sign_in
    @@ -140,7 +140,7 @@ exports[`app/hub/Views/LogIn component Snapshot tests with react-test-renderer l className="LogInView__inputLabel" htmlFor="login-email" > - hub_login_label_email + email_colon - hub_login_label_email_invalid + please_enter_a_valid_email
    - hub_login_button_submit + sign_in
    diff --git a/app/hub/Views/PlusView/__tests__/__snapshots__/PlusView.test.jsx.snap b/app/hub/Views/PlusView/__tests__/__snapshots__/PlusView.test.jsx.snap index dff7f3f49..c673637ca 100644 --- a/app/hub/Views/PlusView/__tests__/__snapshots__/PlusView.test.jsx.snap +++ b/app/hub/Views/PlusView/__tests__/__snapshots__/PlusView.test.jsx.snap @@ -29,7 +29,7 @@ exports[`app/hub/Views/PlusView component Snapshot tests with react-test-rendere
    - hub_supporter_button_text_alt + already_subscribed
    - hub_supporter_perk_themes_title + new_themes
    - hub_supporter_perk_stats_title + historical_blocking_stats
    - hub_supporter_feature_theme_title + new_themes
    - hub_supporter_button_text_alt + already_subscribed
    hub_supporter_feature_theme_title @@ -157,7 +157,7 @@ exports[`app/hub/Views/PlusView component Snapshot tests with react-test-rendere
    - hub_supporter_button_text_alt + already_subscribed
    hub_supporter_feature_stats_title @@ -186,7 +186,7 @@ exports[`app/hub/Views/PlusView component Snapshot tests with react-test-rendere
    - hub_supporter_feature_stats_title + historical_blocking_stats
    - hub_supporter_button_text_alt + already_subscribed
    hub_supporter_feature_stats_title @@ -221,7 +221,7 @@ exports[`app/hub/Views/PlusView component Snapshot tests with react-test-rendere
    - hub_supporter_button_text_alt + already_subscribed
    - hub_supporter_feature_support_title + priority_support
    - hub_supporter_button_text_alt + already_subscribed
    hub_supporter_feature_support_title @@ -276,7 +276,7 @@ exports[`app/hub/Views/PlusView component Snapshot tests with react-test-rendere
    - hub_supporter_button_text_alt + already_subscribed
    - hub_supporter_button_text_alt + already_subscribed
    - hub_supporter_button_text + get_ghostery_plus
    - hub_supporter_perk_themes_title + new_themes
    - hub_supporter_perk_stats_title + historical_blocking_stats
    - hub_supporter_feature_theme_title + new_themes
    - hub_supporter_button_text + get_ghostery_plus
    hub_supporter_feature_theme_title @@ -502,7 +502,7 @@ exports[`app/hub/Views/PlusView component Snapshot tests with react-test-rendere rel="noopener noreferrer" target="_blank" > - hub_supporter_button_text + get_ghostery_plus
    hub_supporter_feature_stats_title @@ -531,7 +531,7 @@ exports[`app/hub/Views/PlusView component Snapshot tests with react-test-rendere
    - hub_supporter_feature_stats_title + historical_blocking_stats
    - hub_supporter_button_text + get_ghostery_plus
    hub_supporter_feature_stats_title @@ -574,7 +574,7 @@ exports[`app/hub/Views/PlusView component Snapshot tests with react-test-rendere rel="noopener noreferrer" target="_blank" > - hub_supporter_button_text + get_ghostery_plus
    - hub_supporter_feature_support_title + priority_support
    - hub_supporter_button_text + get_ghostery_plus
    hub_supporter_feature_support_title @@ -637,7 +637,7 @@ exports[`app/hub/Views/PlusView component Snapshot tests with react-test-rendere rel="noopener noreferrer" target="_blank" > - hub_supporter_button_text + get_ghostery_plus
    - hub_supporter_button_text + get_ghostery_plus
    - hub_rewards_header_learn_more + learn_more
    diff --git a/app/hub/Views/SetupViews/SetupBlockingDropdown/__tests__/__snapshots__/SetupBlockingDropdown.test.jsx.snap b/app/hub/Views/SetupViews/SetupBlockingDropdown/__tests__/__snapshots__/SetupBlockingDropdown.test.jsx.snap index 0fe67c4a8..1bbb9a35c 100644 --- a/app/hub/Views/SetupViews/SetupBlockingDropdown/__tests__/__snapshots__/SetupBlockingDropdown.test.jsx.snap +++ b/app/hub/Views/SetupViews/SetupBlockingDropdown/__tests__/__snapshots__/SetupBlockingDropdown.test.jsx.snap @@ -14,7 +14,7 @@ exports[`app/hub/Views/SetupViews/SetupBlockingDropdown component Snapshot tests className="button success" onClick={[Function]} > - hub_setup_nav_done + done
    diff --git a/app/hub/Views/TutorialViews/TutorialAntiSuiteView/__test__/__snapshots__/TutorialAntiSuiteView.test.jsx.snap b/app/hub/Views/TutorialViews/TutorialAntiSuiteView/__test__/__snapshots__/TutorialAntiSuiteView.test.jsx.snap index a99bef9d4..83a6fdc3e 100644 --- a/app/hub/Views/TutorialViews/TutorialAntiSuiteView/__test__/__snapshots__/TutorialAntiSuiteView.test.jsx.snap +++ b/app/hub/Views/TutorialViews/TutorialAntiSuiteView/__test__/__snapshots__/TutorialAntiSuiteView.test.jsx.snap @@ -10,20 +10,20 @@ exports[`app/hub/Views/TutorialViews/TutorialAntiSuiteView component Snapshot te
    - hub_tutorial_simple_view + simple_view
    hub_tutorial_simple_view
    - hub_tutorial_detailed_view + detailed_view
    hub_tutorial_detailed_view @@ -49,7 +49,7 @@ exports[`app/hub/Views/TutorialViews/TutorialAntiSuiteView component Snapshot te
    - hub_tutorial_antisuite_antitracking_title + enhanced_anti_tracking
    - hub_tutorial_antisuite_adblocking_title + enhanced_ad_blocking
    - hub_tutorial_antisuite_adblocking_description + ad_blocking_DESC
    @@ -87,12 +87,12 @@ exports[`app/hub/Views/TutorialViews/TutorialAntiSuiteView component Snapshot te
    - hub_tutorial_antisuite_smartblocking_title + smart_blocking
    - hub_tutorial_antisuite_smartblocking_description + smart_blocking_DESC
    diff --git a/app/hub/Views/TutorialViews/TutorialBlockingView/__tests__/__snapshots__/TutorialBlockingView.test.jsx.snap b/app/hub/Views/TutorialViews/TutorialBlockingView/__tests__/__snapshots__/TutorialBlockingView.test.jsx.snap index a86a12011..f314105f1 100644 --- a/app/hub/Views/TutorialViews/TutorialBlockingView/__tests__/__snapshots__/TutorialBlockingView.test.jsx.snap +++ b/app/hub/Views/TutorialViews/TutorialBlockingView/__tests__/__snapshots__/TutorialBlockingView.test.jsx.snap @@ -10,10 +10,10 @@ exports[`app/hub/Views/TutorialViews/TutorialBlockingView component Snapshot tes
    - hub_tutorial_detailed_view + detailed_view
    hub_tutorial_detailed_view diff --git a/app/hub/Views/TutorialViews/TutorialLayoutView/__tests__/__snapshots__/TutorialLayoutView.test.jsx.snap b/app/hub/Views/TutorialViews/TutorialLayoutView/__tests__/__snapshots__/TutorialLayoutView.test.jsx.snap index 4bfd63c38..1b7dcb048 100644 --- a/app/hub/Views/TutorialViews/TutorialLayoutView/__tests__/__snapshots__/TutorialLayoutView.test.jsx.snap +++ b/app/hub/Views/TutorialViews/TutorialLayoutView/__tests__/__snapshots__/TutorialLayoutView.test.jsx.snap @@ -8,12 +8,12 @@ exports[`app/hub/Views/TutorialViews/TutorialLayoutView component Snapshot tests className="columns small-10 medium-8 large-6 small-offset-1" > hub_tutorial_simple_view hub_tutorial_detailed_view diff --git a/app/hub/Views/TutorialViews/TutorialTrustView/__tests__/__snapshots__/TutorialTrustView.test.jsx.snap b/app/hub/Views/TutorialViews/TutorialTrustView/__tests__/__snapshots__/TutorialTrustView.test.jsx.snap index a472a37fe..27e9a3973 100644 --- a/app/hub/Views/TutorialViews/TutorialTrustView/__tests__/__snapshots__/TutorialTrustView.test.jsx.snap +++ b/app/hub/Views/TutorialViews/TutorialTrustView/__tests__/__snapshots__/TutorialTrustView.test.jsx.snap @@ -10,20 +10,20 @@ exports[`app/hub/Views/TutorialViews/TutorialTrustView component Snapshot tests
    - hub_tutorial_simple_view + simple_view
    hub_tutorial_simple_view
    - hub_tutorial_detailed_view + detailed_view
    hub_tutorial_detailed_view diff --git a/app/panel/components/Panel.jsx b/app/panel/components/Panel.jsx index 684d21b4d..d84776225 100644 --- a/app/panel/components/Panel.jsx +++ b/app/panel/components/Panel.jsx @@ -13,6 +13,7 @@ import React from 'react'; import Header from '../containers/HeaderContainer'; +import Modal from '../../shared-components/Modal'; import { DynamicUIPortContext } from '../contexts/DynamicUIPortContext'; import { sendMessage } from '../utils/msg'; import { setTheme } from '../utils/utils'; @@ -193,6 +194,10 @@ class Panel extends React.Component { return false; } + _plusPromoClickHandlerPlaceholder = () => { + console.error('IVZ Panfel#_plusPromoClickHandlerPlaceholder'); + } + /** * React's required render function. Returns JSX * @return {JSX} JSX for rendering the Panel @@ -207,6 +212,9 @@ class Panel extends React.Component { return (
    + + {Modal.renderPlusPromo('inPanel', this._plusPromoClickHandlerPlaceholder)} +
    diff --git a/app/scss/panel.scss b/app/scss/panel.scss index c37affeec..2e82bc249 100644 --- a/app/scss/panel.scss +++ b/app/scss/panel.scss @@ -73,3 +73,6 @@ html body { @import './partials/_subscribe'; @import './partials/_stats'; @import './partials/_stats_graph'; + +// Imports from ../shared-components directory +@import '../shared-components/Modal/Modal.scss'; diff --git a/app/shared-components/Modal/Modal.jsx b/app/shared-components/Modal/Modal.jsx index 108ce320f..bf0d2b158 100644 --- a/app/shared-components/Modal/Modal.jsx +++ b/app/shared-components/Modal/Modal.jsx @@ -13,6 +13,7 @@ import React from 'react'; import PropTypes from 'prop-types'; +import ClassNames from 'classnames'; /** * A Functional React component for a Modal @@ -32,6 +33,104 @@ const Modal = props => (
    ); +Modal.renderPlusPromo = (location, clickHandler) => { + const isInHub = location === 'inHub'; + const isInPanel = location === 'inPanel'; + + const locationClassName = { + 'in-hub': isInHub, + 'in-panel': isInPanel + }; + const contentClassNames = ClassNames( + 'PlusPromoModal__content', + 'flex-container', + 'flex-dir-column', + 'align-middle', + locationClassName + ); + const chooseYourPlanClassNames = ClassNames( + 'PlusPromoModal__choose-your-plan', + locationClassName + ); + const recommendedBannerClassNames = ClassNames( + 'PlusPromoModal__recommended-banner', + locationClassName + ); + const optionDescriptionBoxClassNames = ClassNames( + 'PlusPromoModal__option-description-box', + locationClassName + ); + + return ( +
    +
    + {isInHub && ( +
    + {t('thanks_for_downloading_ghostery')} +
    + )} +
    + {isInHub ? t('choose_your_privacy_plan') : t('choose_your_ghostery_privacy_plan')} +
    +
    +
    +
    +
    {t('ghostery_basic')}
    +
    + {t('locale_appropriate_currency_icon')} + 0 + + {t('per_month')} +
    +
    +
    {t('protection_for_this_browser')}
    +
    {t('blocks_ads')}
    +
    {t('blocks_trackers')}
    +
    {t('fast_browsing')}
    +
    +
    +
    + {t('select_basic')} +
    +
    +
    +
    +
    + +
    {t('recommended')}
    +
    +
    Ghostery Plus
    +
    + {t('locale_appropriate_currency_icon')} + {t('plus_monthly_subscription_price_number')} + + per month +
    +
    +
    All basic features, plus:
    +
    + +
    Historical Tracker Stats
    +
    +
    + +
    Priority Support
    +
    +
    + +
    New Color Themes
    +
    +
    +
    + + Select Plus + +
    +
    +
    + ); +}; + // PropTypes ensure we pass required props of the correct type Modal.propTypes = { show: PropTypes.bool.isRequired, diff --git a/app/shared-components/Modal/Modal.scss b/app/shared-components/Modal/Modal.scss index 518bcb9fe..f8c3ba7db 100644 --- a/app/shared-components/Modal/Modal.scss +++ b/app/shared-components/Modal/Modal.scss @@ -24,3 +24,203 @@ background-color: rgba(#000000, 0.25); z-index: 9; } + +.PlusPromoModal__content { + position: relative; + background-color: #f7f7f7; + border: 1.9px solid #930194; + z-index: 10; + + &.in-hub { + width: 646px; + height: 553px; + } + + &.in-panel { + width: 556px; + height: 471px; + } +} + +.PlusPromoModal__buttons-background { + background-color: #e7ecee; + position: absolute; + bottom: 3px; + width: 99%; + height: 72px; + z-index: -1; +} + +.PlusPromoModal__thanks-for-download { + padding-top: 30px; + font-size: 26px; + font-weight: bold; +} + +.PlusPromoModal__choose-your-plan { + font-size: 18px; + font-weight: bold; + + &.in-hub { padding-top: 10px; } + &.in-panel { padding-top: 17px; } +} + +.PlusPromoModal__options-container { + height: 100%; + margin-top: 44px; + display: flex; + justify-content: space-evenly; +} + +.PlusPromoModal__option-container { + display: flex; + align-items: center; + flex-direction: column; +} + +.PlusPromoModal__option-description-box { + border-style: solid; + border-width: 3px; + background-color: #FFFFFF; + + &.basic { + border-color: #1dafed; + } + + &.plus { + position: relative; // so that the recommended banner is positioned relative to this element + border-image-source: linear-gradient(39deg, #f2daa2, #eab968); + border-image-slice: 1; + } + + &.in-hub { + margin-bottom: 45px; + width: 240px; + height: 298px; + } + + &.in-panel { + margin-bottom: 30px; + width: 221px; + height: 294px; + } +} + +.PlusPromoModal__recommended-banner { + position: absolute; + + &.in-hub { + left: -30px; + top: -30px; + } + + &.in-panel { + left: -10px; + top: -32px; + } +} + +.PlusPromoModal__recommended-banner-text { + position: relative; + left: 18px; + top: -47px; + transform: rotate(-15deg); + color: white; + font-size: 16px; + font-weight: bold; +} + +.PlusPromoModal__option-header { + margin-top: 20px; + font-size: 19px; + font-weight: bold; + letter-spacing: -0.5px; + text-align: center; + + &.basic { color: #1dafed; } + &.plus { color: #ebbf73; } +} + +.PlusPromoModal__price-text { + line-height: 1.3; + text-align: center; + + &.basic { color: #1dafed; } + &.plus { color: #ebbf73; } +} + +.PlusPromoModal__currency-sign { + font-size: 30px; + font-weight: bold; +} + +.PlusPromoModal__amount { + vertical-align: middle; + font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 58px; +} + +.PlusPromoModal__per-month { + vertical-align: sub; + font-size: 18px; + font-weight: bold; +} + +.PlusPromoModal__option-description-item { + padding-bottom: 15px; + font-size: 16px; + text-align: center; + color: #333333; + + &.italic { + font-style: italic; + } +} + +.PlusPromoModal__check-icon { + padding-right: 5px; + margin-top: -18px; +} + +.PlusPromoModal__plus-option-description-item-container { + display: flex; + justify-content: center; +} + +.PlusPromoModal__button { + margin: 0; + font-size: 11px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; + display: flex; + align-items: center; + justify-content: center; + box-shadow: none; + + &.basic { + width: 135px; + height: 40px; + border: solid 2px #15b4f2; + background-color: white; + color: #2cbcf4; + } + &.basic:hover { + background-color: #2cbcf4; + color: white; + } + + &.plus { + width: 163px; + height: 38px; + border: none; + background-image: linear-gradient(to bottom, #2fdbfa, #15b4f2); + color: white; + font-weight: 600; + letter-spacing: 0.5px; + } + &.plus:hover { + background-image: linear-gradient(to bottom, #1fcbea, #05a4e2); + } +} + From 509f9eb6e6dd787103a791eefb2c902bf4f4c90f Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Mon, 7 Oct 2019 12:23:57 -0400 Subject: [PATCH 13/27] Move Plus Promo modal rendering to a PlusPromoModal shared component. Begin to implement conditional panel display logic --- app/hub/Views/HomeView/HomeViewContainer.jsx | 19 +- app/hub/utils/index.js | 8 +- app/panel/components/Panel.jsx | 14 +- app/scss/hub.scss | 1 + app/scss/panel.scss | 1 + app/shared-components/Modal/Modal.jsx | 99 --------- app/shared-components/Modal/Modal.scss | 200 ------------------ .../PlusPromoModal/PlusPromoModal.jsx | 138 ++++++++++++ .../PlusPromoModal/PlusPromoModal.scss | 200 ++++++++++++++++++ app/shared-components/PlusPromoModal/index.js | 16 ++ app/shared-components/index.js | 2 + src/background.js | 4 + src/classes/ConfData.js | 1 + src/classes/PanelData.js | 3 +- 14 files changed, 390 insertions(+), 316 deletions(-) create mode 100644 app/shared-components/PlusPromoModal/PlusPromoModal.jsx create mode 100644 app/shared-components/PlusPromoModal/PlusPromoModal.scss create mode 100644 app/shared-components/PlusPromoModal/index.js diff --git a/app/hub/Views/HomeView/HomeViewContainer.jsx b/app/hub/Views/HomeView/HomeViewContainer.jsx index fc8ddbd43..42bf75371 100644 --- a/app/hub/Views/HomeView/HomeViewContainer.jsx +++ b/app/hub/Views/HomeView/HomeViewContainer.jsx @@ -15,7 +15,8 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import QueryString from 'query-string'; import HomeView from './HomeView'; -import { Modal } from '../../../shared-components'; +import { PlusPromoModal } from '../../../shared-components'; +import { sendMessage } from '../../utils'; /** * @class Implement the Home View for the Ghostery Hub @@ -30,7 +31,6 @@ class HomeViewContainer extends Component { this.state = { getUserResolved: false, justInstalled: justInstalled === 'true', - plusPromoModalShown: props.home.plus_promo_modal_shown, }; const title = t('hub_home_page_title'); @@ -62,17 +62,16 @@ class HomeViewContainer extends Component { * Dismisses the Plus promo modal when user clicks either the Select Plus or Select Basic button */ _dismissModal = () => { - this.setState({ - plusPromoModalShown: true, - }); this.props.actions.markPlusPromoModalShown(); + sendMessage('SET_PLUS_PROMO_MODAL_SEEN', {}); } _render() { - const { justInstalled, plusPromoModalShown } = this.state; + 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, @@ -89,9 +88,11 @@ class HomeViewContainer extends Component { return (
    - - {Modal.renderPlusPromo('inHub', this._dismissModal)} - +
    ); diff --git a/app/hub/utils/index.js b/app/hub/utils/index.js index 0766b4f07..156704369 100644 --- a/app/hub/utils/index.js +++ b/app/hub/utils/index.js @@ -14,10 +14,14 @@ // Imports utilities from elsewhere in the codebase to reduce duplicate code import { log } from '../../../src/utils/common'; -import { sendMessageInPromise as importedSMIP } from '../../panel/utils/msg'; +import { sendMessage as importedSM, sendMessageInPromise as importedSMIP } from '../../panel/utils/msg'; const sendMessageInPromise = function(name, message) { return importedSMIP(name, message, 'ghostery-hub'); }; -export { log, sendMessageInPromise }; +const sendMessage = function(name, message) { + return importedSM(name, message, 'ghostery-hub'); +}; + +export { log, sendMessage, sendMessageInPromise }; diff --git a/app/panel/components/Panel.jsx b/app/panel/components/Panel.jsx index d84776225..7cfad3e55 100644 --- a/app/panel/components/Panel.jsx +++ b/app/panel/components/Panel.jsx @@ -13,7 +13,7 @@ import React from 'react'; import Header from '../containers/HeaderContainer'; -import Modal from '../../shared-components/Modal'; +import { PlusPromoModal } from '../../shared-components'; import { DynamicUIPortContext } from '../contexts/DynamicUIPortContext'; import { sendMessage } from '../utils/msg'; import { setTheme } from '../utils/utils'; @@ -195,7 +195,7 @@ class Panel extends React.Component { } _plusPromoClickHandlerPlaceholder = () => { - console.error('IVZ Panfel#_plusPromoClickHandlerPlaceholder'); + console.error('IVZ Panel#_plusPromoClickHandlerPlaceholder'); } /** @@ -210,11 +210,15 @@ class Panel extends React.Component { const notificationText = this.props.notificationShown && this.renderNotification(); + const { plusPromoModalSeen } = this.props; + return (
    - - {Modal.renderPlusPromo('inPanel', this._plusPromoClickHandlerPlaceholder)} - +
    diff --git a/app/scss/hub.scss b/app/scss/hub.scss index 0c55b41a4..a59365f96 100644 --- a/app/scss/hub.scss +++ b/app/scss/hub.scss @@ -76,6 +76,7 @@ html, body, #root { // Imports from ../shared-components directory @import '../shared-components/ExitButton/ExitButton.scss'; @import '../shared-components/Modal/Modal.scss'; +@import '../shared-components/PlusPromoModal/PlusPromoModal.scss'; @import '../shared-components/SteppedNavigation/SteppedNavigation.scss'; @import '../shared-components/ToastMessage/ToastMessage.scss'; @import '../shared-components/ToggleCheckbox/ToggleCheckbox.scss'; diff --git a/app/scss/panel.scss b/app/scss/panel.scss index 2e82bc249..f7e6e1952 100644 --- a/app/scss/panel.scss +++ b/app/scss/panel.scss @@ -76,3 +76,4 @@ html body { // Imports from ../shared-components directory @import '../shared-components/Modal/Modal.scss'; +@import '../shared-components/PlusPromoModal/PlusPromoModal.scss'; diff --git a/app/shared-components/Modal/Modal.jsx b/app/shared-components/Modal/Modal.jsx index bf0d2b158..108ce320f 100644 --- a/app/shared-components/Modal/Modal.jsx +++ b/app/shared-components/Modal/Modal.jsx @@ -13,7 +13,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import ClassNames from 'classnames'; /** * A Functional React component for a Modal @@ -33,104 +32,6 @@ const Modal = props => (
    ); -Modal.renderPlusPromo = (location, clickHandler) => { - const isInHub = location === 'inHub'; - const isInPanel = location === 'inPanel'; - - const locationClassName = { - 'in-hub': isInHub, - 'in-panel': isInPanel - }; - const contentClassNames = ClassNames( - 'PlusPromoModal__content', - 'flex-container', - 'flex-dir-column', - 'align-middle', - locationClassName - ); - const chooseYourPlanClassNames = ClassNames( - 'PlusPromoModal__choose-your-plan', - locationClassName - ); - const recommendedBannerClassNames = ClassNames( - 'PlusPromoModal__recommended-banner', - locationClassName - ); - const optionDescriptionBoxClassNames = ClassNames( - 'PlusPromoModal__option-description-box', - locationClassName - ); - - return ( -
    -
    - {isInHub && ( -
    - {t('thanks_for_downloading_ghostery')} -
    - )} -
    - {isInHub ? t('choose_your_privacy_plan') : t('choose_your_ghostery_privacy_plan')} -
    -
    -
    -
    -
    {t('ghostery_basic')}
    -
    - {t('locale_appropriate_currency_icon')} - 0 - - {t('per_month')} -
    -
    -
    {t('protection_for_this_browser')}
    -
    {t('blocks_ads')}
    -
    {t('blocks_trackers')}
    -
    {t('fast_browsing')}
    -
    -
    -
    - {t('select_basic')} -
    -
    -
    -
    -
    - -
    {t('recommended')}
    -
    -
    Ghostery Plus
    -
    - {t('locale_appropriate_currency_icon')} - {t('plus_monthly_subscription_price_number')} - - per month -
    -
    -
    All basic features, plus:
    -
    - -
    Historical Tracker Stats
    -
    -
    - -
    Priority Support
    -
    -
    - -
    New Color Themes
    -
    -
    -
    - - Select Plus - -
    -
    -
    - ); -}; - // PropTypes ensure we pass required props of the correct type Modal.propTypes = { show: PropTypes.bool.isRequired, diff --git a/app/shared-components/Modal/Modal.scss b/app/shared-components/Modal/Modal.scss index f8c3ba7db..518bcb9fe 100644 --- a/app/shared-components/Modal/Modal.scss +++ b/app/shared-components/Modal/Modal.scss @@ -24,203 +24,3 @@ background-color: rgba(#000000, 0.25); z-index: 9; } - -.PlusPromoModal__content { - position: relative; - background-color: #f7f7f7; - border: 1.9px solid #930194; - z-index: 10; - - &.in-hub { - width: 646px; - height: 553px; - } - - &.in-panel { - width: 556px; - height: 471px; - } -} - -.PlusPromoModal__buttons-background { - background-color: #e7ecee; - position: absolute; - bottom: 3px; - width: 99%; - height: 72px; - z-index: -1; -} - -.PlusPromoModal__thanks-for-download { - padding-top: 30px; - font-size: 26px; - font-weight: bold; -} - -.PlusPromoModal__choose-your-plan { - font-size: 18px; - font-weight: bold; - - &.in-hub { padding-top: 10px; } - &.in-panel { padding-top: 17px; } -} - -.PlusPromoModal__options-container { - height: 100%; - margin-top: 44px; - display: flex; - justify-content: space-evenly; -} - -.PlusPromoModal__option-container { - display: flex; - align-items: center; - flex-direction: column; -} - -.PlusPromoModal__option-description-box { - border-style: solid; - border-width: 3px; - background-color: #FFFFFF; - - &.basic { - border-color: #1dafed; - } - - &.plus { - position: relative; // so that the recommended banner is positioned relative to this element - border-image-source: linear-gradient(39deg, #f2daa2, #eab968); - border-image-slice: 1; - } - - &.in-hub { - margin-bottom: 45px; - width: 240px; - height: 298px; - } - - &.in-panel { - margin-bottom: 30px; - width: 221px; - height: 294px; - } -} - -.PlusPromoModal__recommended-banner { - position: absolute; - - &.in-hub { - left: -30px; - top: -30px; - } - - &.in-panel { - left: -10px; - top: -32px; - } -} - -.PlusPromoModal__recommended-banner-text { - position: relative; - left: 18px; - top: -47px; - transform: rotate(-15deg); - color: white; - font-size: 16px; - font-weight: bold; -} - -.PlusPromoModal__option-header { - margin-top: 20px; - font-size: 19px; - font-weight: bold; - letter-spacing: -0.5px; - text-align: center; - - &.basic { color: #1dafed; } - &.plus { color: #ebbf73; } -} - -.PlusPromoModal__price-text { - line-height: 1.3; - text-align: center; - - &.basic { color: #1dafed; } - &.plus { color: #ebbf73; } -} - -.PlusPromoModal__currency-sign { - font-size: 30px; - font-weight: bold; -} - -.PlusPromoModal__amount { - vertical-align: middle; - font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 58px; -} - -.PlusPromoModal__per-month { - vertical-align: sub; - font-size: 18px; - font-weight: bold; -} - -.PlusPromoModal__option-description-item { - padding-bottom: 15px; - font-size: 16px; - text-align: center; - color: #333333; - - &.italic { - font-style: italic; - } -} - -.PlusPromoModal__check-icon { - padding-right: 5px; - margin-top: -18px; -} - -.PlusPromoModal__plus-option-description-item-container { - display: flex; - justify-content: center; -} - -.PlusPromoModal__button { - margin: 0; - font-size: 11px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.5px; - display: flex; - align-items: center; - justify-content: center; - box-shadow: none; - - &.basic { - width: 135px; - height: 40px; - border: solid 2px #15b4f2; - background-color: white; - color: #2cbcf4; - } - &.basic:hover { - background-color: #2cbcf4; - color: white; - } - - &.plus { - width: 163px; - height: 38px; - border: none; - background-image: linear-gradient(to bottom, #2fdbfa, #15b4f2); - color: white; - font-weight: 600; - letter-spacing: 0.5px; - } - &.plus:hover { - background-image: linear-gradient(to bottom, #1fcbea, #05a4e2); - } -} - diff --git a/app/shared-components/PlusPromoModal/PlusPromoModal.jsx b/app/shared-components/PlusPromoModal/PlusPromoModal.jsx new file mode 100644 index 000000000..3ee37bdd1 --- /dev/null +++ b/app/shared-components/PlusPromoModal/PlusPromoModal.jsx @@ -0,0 +1,138 @@ +/** + * Plus Promo Modal Component + * renders Plus Promo inside of the shared Modal component + * + * Ghostery Browser Extension + * https://www.ghostery.com/ + * + * Copyright 2019 Ghostery, Inc. All rights reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0 + */ + +import React from 'react'; +import PropTypes from 'prop-types'; +import ClassNames from 'classnames'; +import Modal from '../Modal/Modal'; + +/** + * A Functional React component for a Plus Promo Modal + * @return {JSX} JSX for rendering a Plus Promo Modal + * @memberof SharedComponents + */ +const PlusPromoModal = (props) => { + const { show, location, clickHandler } = props; + + const isInHub = location === 'hub'; + + const locationClassName = { + 'in-hub': isInHub, + 'in-panel': location === 'panel' + }; + const contentClassNames = ClassNames( + 'PlusPromoModal__content', + 'flex-container', + 'flex-dir-column', + 'align-middle', + locationClassName + ); + const optionsContainerClassNames = ClassNames( + 'PlusPromoModal__options-container', + 'full-width', + locationClassName + ); + const chooseYourPlanClassNames = ClassNames( + 'PlusPromoModal__choose-your-plan', + locationClassName + ); + const recommendedBannerClassNames = ClassNames( + 'PlusPromoModal__recommended-banner', + locationClassName + ); + const optionDescriptionBoxClassNames = ClassNames( + 'PlusPromoModal__option-description-box', + locationClassName + ); + + return ( + +
    +
    + {isInHub && ( +
    + {t('thanks_for_downloading_ghostery')} +
    + )} +
    + {isInHub ? t('choose_your_privacy_plan') : t('choose_your_ghostery_privacy_plan')} +
    +
    +
    +
    +
    {t('ghostery_basic')}
    +
    + {t('locale_appropriate_currency_icon')} + 0 + + {t('per_month')} +
    +
    +
    {t('protection_for_this_browser')}
    +
    {t('blocks_ads')}
    +
    {t('blocks_trackers')}
    +
    {t('fast_browsing')}
    +
    +
    +
    + {t('select_basic')} +
    +
    +
    +
    +
    + +
    {t('recommended')}
    +
    +
    Ghostery Plus
    +
    + {t('locale_appropriate_currency_icon')} + {t('plus_monthly_subscription_price_number')} + + per month +
    +
    +
    All basic features, plus:
    +
    + +
    Historical Tracker Stats
    +
    +
    + +
    Priority Support
    +
    +
    + +
    New Color Themes
    +
    +
    +
    + + Select Plus + +
    +
    +
    + + ); +}; + +// PropTypes ensure we pass required props of the correct type +PlusPromoModal.propTypes = { + show: PropTypes.bool.isRequired, + location: PropTypes.string.isRequired, + clickHandler: PropTypes.func.isRequired, +}; + +export default PlusPromoModal; diff --git a/app/shared-components/PlusPromoModal/PlusPromoModal.scss b/app/shared-components/PlusPromoModal/PlusPromoModal.scss new file mode 100644 index 000000000..7aea1c077 --- /dev/null +++ b/app/shared-components/PlusPromoModal/PlusPromoModal.scss @@ -0,0 +1,200 @@ +.PlusPromoModal__content { + position: relative; + background-color: #f7f7f7; + border: 1.9px solid #930194; + z-index: 10; + + &.in-hub { + width: 646px; + height: 553px; + } + + &.in-panel { + width: 556px; + height: 471px; + } +} + +.PlusPromoModal__buttons-background { + background-color: #e7ecee; + position: absolute; + bottom: 3px; + width: 99%; + height: 72px; + z-index: -1; +} + +.PlusPromoModal__thanks-for-download { + padding-top: 30px; + font-size: 26px; + font-weight: bold; +} + +.PlusPromoModal__choose-your-plan { + font-size: 18px; + font-weight: bold; + + &.in-hub { padding-top: 10px; } + &.in-panel { padding-top: 17px; } +} + +.PlusPromoModal__options-container { + height: 100%; + margin-top: 44px; + display: flex; + + &.in-hub { justify-content: space-evenly; } + &.in-panel { justify-content: space-around; } +} + +.PlusPromoModal__option-container { + display: flex; + align-items: center; + flex-direction: column; +} + +.PlusPromoModal__option-description-box { + border-style: solid; + border-width: 3px; + background-color: #FFFFFF; + + &.basic { + border-color: #1dafed; + } + + &.plus { + position: relative; // so that the recommended banner is positioned relative to this element + border-image-source: linear-gradient(39deg, #f2daa2, #eab968); + border-image-slice: 1; + } + + &.in-hub { + margin-bottom: 45px; + width: 240px; + height: 298px; + } + + &.in-panel { + margin-bottom: 30px; + width: 221px; + height: 294px; + } +} + +.PlusPromoModal__recommended-banner { + position: absolute; + + &.in-hub { + left: -30px; + top: -30px; + } + + &.in-panel { + left: -10px; + top: -32px; + } +} + +.PlusPromoModal__recommended-banner-text { + position: relative; + left: 18px; + top: -47px; + transform: rotate(-15deg); + color: white; + font-size: 16px; + font-weight: bold; +} + +.PlusPromoModal__option-header { + margin-top: 20px; + font-size: 19px; + font-weight: bold; + letter-spacing: -0.5px; + text-align: center; + + &.basic { color: #1dafed; } + &.plus { color: #ebbf73; } +} + +.PlusPromoModal__price-text { + line-height: 1.3; + text-align: center; + + &.basic { color: #1dafed; } + &.plus { color: #ebbf73; } +} + +.PlusPromoModal__currency-sign { + font-size: 30px; + font-weight: bold; +} + +.PlusPromoModal__amount { + vertical-align: middle; + font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 58px; +} + +.PlusPromoModal__per-month { + vertical-align: sub; + font-size: 18px; + font-weight: bold; +} + +.PlusPromoModal__option-description-item { + padding-bottom: 15px; + font-size: 16px; + text-align: center; + color: #333333; + + &.italic { + font-style: italic; + } +} + +.PlusPromoModal__check-icon { + padding-right: 5px; + margin-top: -18px; +} + +.PlusPromoModal__plus-option-description-item-container { + display: flex; + justify-content: center; +} + +.PlusPromoModal__button { + margin: 0; + font-size: 11px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; + display: flex; + align-items: center; + justify-content: center; + box-shadow: none; + + &.basic { + width: 135px; + height: 40px; + border: solid 2px #15b4f2; + background-color: white; + color: #2cbcf4; + } + &.basic:hover { + background-color: #2cbcf4; + color: white; + } + + &.plus { + width: 163px; + height: 38px; + border: none; + background-image: linear-gradient(to bottom, #2fdbfa, #15b4f2); + color: white; + font-weight: 600; + letter-spacing: 0.5px; + } + &.plus:hover { + background-image: linear-gradient(to bottom, #1fcbea, #05a4e2); + } +} diff --git a/app/shared-components/PlusPromoModal/index.js b/app/shared-components/PlusPromoModal/index.js new file mode 100644 index 000000000..da26a8b7e --- /dev/null +++ b/app/shared-components/PlusPromoModal/index.js @@ -0,0 +1,16 @@ +/** + * Point of entry index.js file for Plus Promo Modal Component + * + * Ghostery Browser Extension + * https://www.ghostery.com/ + * + * Copyright 2019 Ghostery, Inc. All rights reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0 + */ + +import PlusPromoModal from './PlusPromoModal'; + +export default PlusPromoModal; diff --git a/app/shared-components/index.js b/app/shared-components/index.js index 7910b2ef5..a7fe2f139 100644 --- a/app/shared-components/index.js +++ b/app/shared-components/index.js @@ -17,6 +17,7 @@ import ExitButton from './ExitButton'; import Modal from './Modal'; +import PlusPromoModal from './PlusPromoModal'; import SteppedNavigation from './SteppedNavigation'; import ToastMessage from './ToastMessage'; import ToggleCheckbox from './ToggleCheckbox'; @@ -25,6 +26,7 @@ import ToggleSwitch from './ToggleSwitch'; export { ExitButton, Modal, + PlusPromoModal, SteppedNavigation, ToastMessage, ToggleCheckbox, diff --git a/src/background.js b/src/background.js index de12238b3..e84c26439 100644 --- a/src/background.js +++ b/src/background.js @@ -541,6 +541,10 @@ function handleRewards(name, message, callback) { */ function handleGhosteryHub(name, message, callback) { switch (name) { + case 'SET_PLUS_PROMO_MODAL_SEEN': + // TODO move this to a Promos class? + conf.plus_promo_modal_last_seen = Date.now(); + break; case 'SEND_PING': { const { type } = message; metrics.ping(type); diff --git a/src/classes/ConfData.js b/src/classes/ConfData.js index 121c77ef2..40237eab2 100644 --- a/src/classes/ConfData.js +++ b/src/classes/ConfData.js @@ -123,6 +123,7 @@ class ConfData { _initProperty('notify_library_updates', false); _initProperty('notify_upgrade_updates', true); _initProperty('paid_subscription', false); + _initProperty('plus_promo_modal_last_seen', null); _initProperty('rewards_accepted', false); _initProperty('rewards_opted_in', false); _initProperty('settings_last_imported', 0); diff --git a/src/classes/PanelData.js b/src/classes/PanelData.js index 006738f2e..55815a3c6 100644 --- a/src/classes/PanelData.js +++ b/src/classes/PanelData.js @@ -351,7 +351,7 @@ class PanelData { const { id: tab_id } = this._activeTab; const { current_theme, enable_ad_block, enable_anti_tracking, enable_smart_block, - enable_offers, is_expanded, is_expert, language, reload_banner_status, + enable_offers, is_expanded, is_expert, language, plus_promo_modal_last_seen, reload_banner_status, trackers_banner_status, } = conf; @@ -365,6 +365,7 @@ class PanelData { is_expert, is_android: globals.BROWSER_INFO.os === 'android', language, + plusPromoModalSeen: !!plus_promo_modal_last_seen, reload_banner_status, tab_id, trackers_banner_status, From 833fdff4c489990ed21e91c8aa62669db08ebef0 Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Mon, 7 Oct 2019 16:32:14 -0400 Subject: [PATCH 14/27] Create ModalPromos background class responsible for modal promo related business logic and state management --- app/panel/components/Panel.jsx | 4 +-- src/background.js | 4 +-- src/classes/ConfData.js | 2 +- src/classes/ModalPromos.js | 49 ++++++++++++++++++++++++++++++++++ src/classes/PanelData.js | 3 ++- 5 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 src/classes/ModalPromos.js diff --git a/app/panel/components/Panel.jsx b/app/panel/components/Panel.jsx index 7cfad3e55..c65be6fb1 100644 --- a/app/panel/components/Panel.jsx +++ b/app/panel/components/Panel.jsx @@ -210,12 +210,12 @@ class Panel extends React.Component { const notificationText = this.props.notificationShown && this.renderNotification(); - const { plusPromoModalSeen } = this.props; + const { isTimeForAnotherPlusPromo } = this.props; return (
    diff --git a/src/background.js b/src/background.js index e84c26439..9c6c3192a 100644 --- a/src/background.js +++ b/src/background.js @@ -42,6 +42,7 @@ import metrics from './classes/Metrics'; import rewards from './classes/Rewards'; import account from './classes/Account'; import GhosteryModule from './classes/Module'; +import modalPromos from './classes/ModalPromos'; // utilities import { allowAllwaysC2P } from './utils/click2play'; @@ -542,8 +543,7 @@ function handleRewards(name, message, callback) { function handleGhosteryHub(name, message, callback) { switch (name) { case 'SET_PLUS_PROMO_MODAL_SEEN': - // TODO move this to a Promos class? - conf.plus_promo_modal_last_seen = Date.now(); + modalPromos.recordPlusPromoSighting(); break; case 'SEND_PING': { const { type } = message; diff --git a/src/classes/ConfData.js b/src/classes/ConfData.js index 40237eab2..d8c23c8af 100644 --- a/src/classes/ConfData.js +++ b/src/classes/ConfData.js @@ -123,7 +123,7 @@ class ConfData { _initProperty('notify_library_updates', false); _initProperty('notify_upgrade_updates', true); _initProperty('paid_subscription', false); - _initProperty('plus_promo_modal_last_seen', null); + _initProperty('plus_promo_modal_last_seen', 0); _initProperty('rewards_accepted', false); _initProperty('rewards_opted_in', false); _initProperty('settings_last_imported', 0); diff --git a/src/classes/ModalPromos.js b/src/classes/ModalPromos.js new file mode 100644 index 000000000..7f12df555 --- /dev/null +++ b/src/classes/ModalPromos.js @@ -0,0 +1,49 @@ +/** + * ModalPromos Class + * + * Ghostery Browser Extension + * https://www.ghostery.com/ + * + * Copyright 2019 Ghostery, Inc. All rights reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0 + */ + +import conf from './Conf'; + +const DAYS_BETWEEN_PROMOS = { + plus: 30 +}; +const MSECS_IN_DAY = 1000 * 60 * 60 * 24; // msecs-in-sec * secs-in-min * mins-in-hour * hours-in-day + +/** + * Class for handling the business logic for the display of modal promos (Plus, Insights, etc...) + * @memberOf BackgroundClasses + */ +class ModalPromos { + recordPlusPromoSighting() { + this._recordPromoSighting('plus'); + } + + isTimeForAnotherPlusPromo() { + return this._isTimeForAnotherPlusPromo('plus'); + } + + _isTimeForAnotherPlusPromo(promoType) { + const lastSeenTime = conf[`${promoType}_promo_modal_last_seen`]; + + return ( + (Date.now() - lastSeenTime) > + (MSECS_IN_DAY * DAYS_BETWEEN_PROMOS[promoType]) + ); + } + + _recordPromoSighting(promoType) { + conf[`${promoType}_promo_modal_last_seen`] = Date.now(); + } +} + +// return the class as a singleton +export default new ModalPromos(); diff --git a/src/classes/PanelData.js b/src/classes/PanelData.js index 55815a3c6..9d3053d90 100644 --- a/src/classes/PanelData.js +++ b/src/classes/PanelData.js @@ -27,6 +27,7 @@ import tabInfo from './TabInfo'; import rewards from './Rewards'; import account from './Account'; import dispatcher from './Dispatcher'; +import modalPromos from './ModalPromos'; import { getCliqzGhosteryBugs, sendCliqzModuleCounts } from '../utils/cliqzModulesData'; import { getActiveTab, flushChromeMemoryCache, processUrl } from '../utils/utils'; import { objectEntries, log } from '../utils/common'; @@ -365,7 +366,7 @@ class PanelData { is_expert, is_android: globals.BROWSER_INFO.os === 'android', language, - plusPromoModalSeen: !!plus_promo_modal_last_seen, + isTimeForAnotherPlusPromo: modalPromos.isTimeForAnotherPlusPromo(), reload_banner_status, tab_id, trackers_banner_status, From 9e80640c89490e1be2229e6cf887405849ed05e9 Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Tue, 8 Oct 2019 12:01:40 -0400 Subject: [PATCH 15/27] Add local state to Panel to make sure component rerenders after user dismisses promo panel. Send record of promo interaction to background --- app/panel/components/Panel.jsx | 12 ++++++++++-- src/background.js | 8 ++++++-- src/classes/PanelData.js | 2 +- src/classes/{ModalPromos.js => PromoModals.js} | 8 ++++---- 4 files changed, 21 insertions(+), 9 deletions(-) rename src/classes/{ModalPromos.js => PromoModals.js} (85%) diff --git a/app/panel/components/Panel.jsx b/app/panel/components/Panel.jsx index c65be6fb1..4618509ba 100644 --- a/app/panel/components/Panel.jsx +++ b/app/panel/components/Panel.jsx @@ -29,6 +29,10 @@ class Panel extends React.Component { this.closeNotification = this.closeNotification.bind(this); this.clickReloadBanner = this.clickReloadBanner.bind(this); this.filterTrackers = this.filterTrackers.bind(this); + + this.state = { + plusPromoModalShown: false, + }; } /** @@ -195,7 +199,10 @@ class Panel extends React.Component { } _plusPromoClickHandlerPlaceholder = () => { - console.error('IVZ Panel#_plusPromoClickHandlerPlaceholder'); + sendMessage('promoModals.sawPlusPromo', {}); + this.setState({ + plusPromoModalShown: true + }); } /** @@ -210,12 +217,13 @@ class Panel extends React.Component { const notificationText = this.props.notificationShown && this.renderNotification(); + const { plusPromoModalShown } = this.state; const { isTimeForAnotherPlusPromo } = this.props; return (
    diff --git a/src/background.js b/src/background.js index 9c6c3192a..c1f9b4683 100644 --- a/src/background.js +++ b/src/background.js @@ -42,7 +42,7 @@ import metrics from './classes/Metrics'; import rewards from './classes/Rewards'; import account from './classes/Account'; import GhosteryModule from './classes/Module'; -import modalPromos from './classes/ModalPromos'; +import promoModals from './classes/PromoModals'; // utilities import { allowAllwaysC2P } from './utils/click2play'; @@ -543,7 +543,7 @@ function handleRewards(name, message, callback) { function handleGhosteryHub(name, message, callback) { switch (name) { case 'SET_PLUS_PROMO_MODAL_SEEN': - modalPromos.recordPlusPromoSighting(); + promoModals.recordPlusPromoSighting(); break; case 'SEND_PING': { const { type } = message; @@ -1078,6 +1078,10 @@ function onMessageHandler(request, sender, callback) { }); return true; } + if (name === 'promoModals.sawPlusPromo') { + promoModals.recordPlusPromoSighting(); + return true; + } } /** diff --git a/src/classes/PanelData.js b/src/classes/PanelData.js index 9d3053d90..65fb55026 100644 --- a/src/classes/PanelData.js +++ b/src/classes/PanelData.js @@ -27,7 +27,7 @@ import tabInfo from './TabInfo'; import rewards from './Rewards'; import account from './Account'; import dispatcher from './Dispatcher'; -import modalPromos from './ModalPromos'; +import modalPromos from './PromoModals'; import { getCliqzGhosteryBugs, sendCliqzModuleCounts } from '../utils/cliqzModulesData'; import { getActiveTab, flushChromeMemoryCache, processUrl } from '../utils/utils'; import { objectEntries, log } from '../utils/common'; diff --git a/src/classes/ModalPromos.js b/src/classes/PromoModals.js similarity index 85% rename from src/classes/ModalPromos.js rename to src/classes/PromoModals.js index 7f12df555..b8650c9fb 100644 --- a/src/classes/ModalPromos.js +++ b/src/classes/PromoModals.js @@ -1,5 +1,5 @@ /** - * ModalPromos Class + * PromoModals Class * * Ghostery Browser Extension * https://www.ghostery.com/ @@ -19,10 +19,10 @@ const DAYS_BETWEEN_PROMOS = { const MSECS_IN_DAY = 1000 * 60 * 60 * 24; // msecs-in-sec * secs-in-min * mins-in-hour * hours-in-day /** - * Class for handling the business logic for the display of modal promos (Plus, Insights, etc...) + * Class for handling the business logic for the display of promo modals (Plus, Insights, etc...) * @memberOf BackgroundClasses */ -class ModalPromos { +class PromoModals { recordPlusPromoSighting() { this._recordPromoSighting('plus'); } @@ -46,4 +46,4 @@ class ModalPromos { } // return the class as a singleton -export default new ModalPromos(); +export default new PromoModals(); From b03e3120730938063f8f308163458572553c5981 Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Tue, 8 Oct 2019 12:34:26 -0400 Subject: [PATCH 16/27] Make PromoModals code more robust --- app/panel/components/Panel.jsx | 6 ++++-- src/classes/ConfData.js | 2 +- src/classes/PanelData.js | 3 ++- src/classes/PromoModals.js | 28 ++++++++++++++++++---------- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/app/panel/components/Panel.jsx b/app/panel/components/Panel.jsx index 4618509ba..a75d82b76 100644 --- a/app/panel/components/Panel.jsx +++ b/app/panel/components/Panel.jsx @@ -218,12 +218,14 @@ class Panel extends React.Component { const notificationText = this.props.notificationShown && this.renderNotification(); const { plusPromoModalShown } = this.state; - const { isTimeForAnotherPlusPromo } = this.props; + const { isTimeForAPlusPromo } = this.props; + + const show = !plusPromoModalShown && isTimeForAPlusPromo; return (
    diff --git a/src/classes/ConfData.js b/src/classes/ConfData.js index d8c23c8af..40237eab2 100644 --- a/src/classes/ConfData.js +++ b/src/classes/ConfData.js @@ -123,7 +123,7 @@ class ConfData { _initProperty('notify_library_updates', false); _initProperty('notify_upgrade_updates', true); _initProperty('paid_subscription', false); - _initProperty('plus_promo_modal_last_seen', 0); + _initProperty('plus_promo_modal_last_seen', null); _initProperty('rewards_accepted', false); _initProperty('rewards_opted_in', false); _initProperty('settings_last_imported', 0); diff --git a/src/classes/PanelData.js b/src/classes/PanelData.js index 65fb55026..8b95d8f8c 100644 --- a/src/classes/PanelData.js +++ b/src/classes/PanelData.js @@ -366,7 +366,8 @@ class PanelData { is_expert, is_android: globals.BROWSER_INFO.os === 'android', language, - isTimeForAnotherPlusPromo: modalPromos.isTimeForAnotherPlusPromo(), + isTimeForAPlusPromo: modalPromos.isTimeForAPlusPromo(), + haveSeenAPlusPromo: modalPromos.haveSeenAPlusPromo(), reload_banner_status, tab_id, trackers_banner_status, diff --git a/src/classes/PromoModals.js b/src/classes/PromoModals.js index b8650c9fb..f0ae5760b 100644 --- a/src/classes/PromoModals.js +++ b/src/classes/PromoModals.js @@ -18,30 +18,38 @@ const DAYS_BETWEEN_PROMOS = { }; const MSECS_IN_DAY = 1000 * 60 * 60 * 24; // msecs-in-sec * secs-in-min * mins-in-hour * hours-in-day +const PLUS = 'plus'; +const PROMO_MODAL_LAST_SEEN = 'promo_modal_last_seen'; + /** * Class for handling the business logic for the display of promo modals (Plus, Insights, etc...) * @memberOf BackgroundClasses */ class PromoModals { - recordPlusPromoSighting() { - this._recordPromoSighting('plus'); - } + haveSeenAPlusPromo() { return this._haveSeenAPromo(PLUS); } + + isTimeForAPlusPromo() { return this._isTimeForAPromo(PLUS); } - isTimeForAnotherPlusPromo() { - return this._isTimeForAnotherPlusPromo('plus'); + recordPlusPromoSighting() { this._recordPromoSighting(PLUS); } + + _haveSeenAPromo(type) { + const lastSeenTime = conf[`${type}_${PROMO_MODAL_LAST_SEEN}`]; + return (lastSeenTime !== null); } - _isTimeForAnotherPlusPromo(promoType) { - const lastSeenTime = conf[`${promoType}_promo_modal_last_seen`]; + _isTimeForAPromo(type) { + const lastSeenTime = conf[`${type}_${PROMO_MODAL_LAST_SEEN}`]; + + if (lastSeenTime === null) { return true; } return ( (Date.now() - lastSeenTime) > - (MSECS_IN_DAY * DAYS_BETWEEN_PROMOS[promoType]) + (MSECS_IN_DAY * DAYS_BETWEEN_PROMOS[type]) ); } - _recordPromoSighting(promoType) { - conf[`${promoType}_promo_modal_last_seen`] = Date.now(); + _recordPromoSighting(type) { + conf[`${type}_${PROMO_MODAL_LAST_SEEN}`] = Date.now(); } } From a1270cc5199b1d238fdd7815e03a6a3138a6cb45 Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Tue, 8 Oct 2019 12:43:22 -0400 Subject: [PATCH 17/27] Factor PlusPromoModal rendering out to helper in Panel. Extend conditional rendering logic to account for upgrade version of modal --- app/panel/components/Panel.jsx | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/app/panel/components/Panel.jsx b/app/panel/components/Panel.jsx index a75d82b76..2201a7375 100644 --- a/app/panel/components/Panel.jsx +++ b/app/panel/components/Panel.jsx @@ -205,6 +205,24 @@ class Panel extends React.Component { }); } + _renderPlusPromoModal = () => { + const { plusPromoModalShown } = this.state; + const { haveSeenAPlusPromo, isTimeForAPlusPromo } = this.props; + + if (plusPromoModalShown || !isTimeForAPlusPromo) return null; + + const version = haveSeenAPlusPromo ? 'upgrade' : 'initial'; + + return ( + + ); + } + /** * React's required render function. Returns JSX * @return {JSX} JSX for rendering the Panel @@ -217,18 +235,9 @@ class Panel extends React.Component { const notificationText = this.props.notificationShown && this.renderNotification(); - const { plusPromoModalShown } = this.state; - const { isTimeForAPlusPromo } = this.props; - - const show = !plusPromoModalShown && isTimeForAPlusPromo; - return (
    - + {this._renderPlusPromoModal()}
    From cac56c12b945be4e71e3c0708b89270d220d9440 Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Tue, 8 Oct 2019 15:48:58 -0400 Subject: [PATCH 18/27] Mark PromoModals methods as static. Refine PlusPromoModal implementation and add debug code --- app/hub/Views/HomeView/HomeViewContainer.jsx | 1 + app/panel/components/Panel.jsx | 4 +- .../PlusPromoModal/PlusPromoModal.jsx | 57 +++++++++++++++++-- src/classes/PanelData.js | 6 +- src/classes/PromoModals.js | 29 +++++----- 5 files changed, 71 insertions(+), 26 deletions(-) diff --git a/app/hub/Views/HomeView/HomeViewContainer.jsx b/app/hub/Views/HomeView/HomeViewContainer.jsx index 42bf75371..a13d98f63 100644 --- a/app/hub/Views/HomeView/HomeViewContainer.jsx +++ b/app/hub/Views/HomeView/HomeViewContainer.jsx @@ -92,6 +92,7 @@ class HomeViewContainer extends Component { show={!isPlus && !plus_promo_modal_shown} location="hub" clickHandler={this._dismissModal} + version={PlusPromoModal.INITIAL} />
    diff --git a/app/panel/components/Panel.jsx b/app/panel/components/Panel.jsx index 2201a7375..15980b430 100644 --- a/app/panel/components/Panel.jsx +++ b/app/panel/components/Panel.jsx @@ -207,11 +207,11 @@ class Panel extends React.Component { _renderPlusPromoModal = () => { const { plusPromoModalShown } = this.state; - const { haveSeenAPlusPromo, isTimeForAPlusPromo } = this.props; + const { haveSeenInitialPlusPromo, isTimeForAPlusPromo } = this.props; if (plusPromoModalShown || !isTimeForAPlusPromo) return null; - const version = haveSeenAPlusPromo ? 'upgrade' : 'initial'; + const version = haveSeenInitialPlusPromo ? PlusPromoModal.UPGRADE : PlusPromoModal.INITIAL; return ( { +// TODO refactor to reduce duplication alongside implementing _renderUpgradeVersion for GH-1813 +function _renderInitialVersion(props) { const { show, location, clickHandler } = props; const isInHub = location === 'hub'; @@ -126,13 +122,62 @@ const PlusPromoModal = (props) => {
    ); +} + +// TODO flesh out this stub for https://cliqztix.atlassian.net/browse/GH-1813 +function _renderUpgradeVersion(props) { + const { clickHandler, location, show } = props; + + const isInHub = location === 'hub'; + + const locationClassName = { + 'in-hub': isInHub, + 'in-panel': location === 'panel' + }; + const contentClassNames = ClassNames( + 'PlusPromoModal__content', + 'flex-container', + 'flex-dir-column', + 'align-middle', + locationClassName + ); + + return ( + +
    +
    [Upgrade version of the Plus Promo modal]
    +
    + Dismiss +
    +
    +
    + ); +} + +/** + * A Functional React component for a Plus Promo Modal + * @return {JSX} JSX for rendering a Plus Promo Modal + * @memberof SharedComponents + */ +const PlusPromoModal = (props) => { + const { version } = props; + + if (version === PlusPromoModal.INITIAL) { return _renderInitialVersion(props); } + + if (version === PlusPromoModal.UPGRADE) { return _renderUpgradeVersion(props); } + + return null; }; +PlusPromoModal.UPGRADE = 1; +PlusPromoModal.INITIAL = 2; + // PropTypes ensure we pass required props of the correct type PlusPromoModal.propTypes = { show: PropTypes.bool.isRequired, location: PropTypes.string.isRequired, clickHandler: PropTypes.func.isRequired, + version: PropTypes.oneOf([PlusPromoModal.UPGRADE, PlusPromoModal.INITIAL]).isRequired, }; export default PlusPromoModal; diff --git a/src/classes/PanelData.js b/src/classes/PanelData.js index 8b95d8f8c..427301a18 100644 --- a/src/classes/PanelData.js +++ b/src/classes/PanelData.js @@ -27,7 +27,7 @@ import tabInfo from './TabInfo'; import rewards from './Rewards'; import account from './Account'; import dispatcher from './Dispatcher'; -import modalPromos from './PromoModals'; +import promoModals from './PromoModals'; import { getCliqzGhosteryBugs, sendCliqzModuleCounts } from '../utils/cliqzModulesData'; import { getActiveTab, flushChromeMemoryCache, processUrl } from '../utils/utils'; import { objectEntries, log } from '../utils/common'; @@ -366,8 +366,8 @@ class PanelData { is_expert, is_android: globals.BROWSER_INFO.os === 'android', language, - isTimeForAPlusPromo: modalPromos.isTimeForAPlusPromo(), - haveSeenAPlusPromo: modalPromos.haveSeenAPlusPromo(), + isTimeForAPlusPromo: promoModals.isTimeForAPlusPromo(), + haveSeenInitialPlusPromo: promoModals.haveSeenInitialPlusPromo(), reload_banner_status, tab_id, trackers_banner_status, diff --git a/src/classes/PromoModals.js b/src/classes/PromoModals.js index f0ae5760b..fd583954f 100644 --- a/src/classes/PromoModals.js +++ b/src/classes/PromoModals.js @@ -12,12 +12,12 @@ */ import conf from './Conf'; +import globals from './Globals'; const DAYS_BETWEEN_PROMOS = { - plus: 30 + plus: globals.DEBUG ? 0.00025 : 30, }; -const MSECS_IN_DAY = 1000 * 60 * 60 * 24; // msecs-in-sec * secs-in-min * mins-in-hour * hours-in-day - +const MSECS_IN_DAY = 86400000; // 1000 msecs-in-sec * 60 secs-in-min * 60 mins-in-hour * 24 hours-in-day const PLUS = 'plus'; const PROMO_MODAL_LAST_SEEN = 'promo_modal_last_seen'; @@ -26,18 +26,16 @@ const PROMO_MODAL_LAST_SEEN = 'promo_modal_last_seen'; * @memberOf BackgroundClasses */ class PromoModals { - haveSeenAPlusPromo() { return this._haveSeenAPromo(PLUS); } - - isTimeForAPlusPromo() { return this._isTimeForAPromo(PLUS); } - - recordPlusPromoSighting() { this._recordPromoSighting(PLUS); } - - _haveSeenAPromo(type) { - const lastSeenTime = conf[`${type}_${PROMO_MODAL_LAST_SEEN}`]; + static haveSeenInitialPlusPromo() { + const lastSeenTime = conf[`${PLUS}_${PROMO_MODAL_LAST_SEEN}`]; return (lastSeenTime !== null); } - _isTimeForAPromo(type) { + static isTimeForAPlusPromo() { return this._isTimeForAPromo(PLUS); } + + static recordPlusPromoSighting() { this._recordPromoSighting(PLUS); } + + static _isTimeForAPromo(type) { const lastSeenTime = conf[`${type}_${PROMO_MODAL_LAST_SEEN}`]; if (lastSeenTime === null) { return true; } @@ -48,10 +46,11 @@ class PromoModals { ); } - _recordPromoSighting(type) { + static _recordPromoSighting(type) { conf[`${type}_${PROMO_MODAL_LAST_SEEN}`] = Date.now(); } } -// return the class as a singleton -export default new PromoModals(); +// the class is simply a namespace for some static methods, +// as we do not need to maintain any state +export default PromoModals; From be05ce95efe58a128a5a5c30432c19d313fa6715 Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Wed, 9 Oct 2019 10:12:12 -0400 Subject: [PATCH 19/27] Add logic to hide plus promo modal from Insights subscribers. Cleanup and comments. --- app/hub/Views/HomeView/HomeViewContainer.jsx | 9 ++++++--- app/panel/components/Panel.jsx | 12 +++++++++--- src/classes/PanelData.js | 2 +- src/classes/PromoModals.js | 3 ++- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/app/hub/Views/HomeView/HomeViewContainer.jsx b/app/hub/Views/HomeView/HomeViewContainer.jsx index a13d98f63..7bf676826 100644 --- a/app/hub/Views/HomeView/HomeViewContainer.jsx +++ b/app/hub/Views/HomeView/HomeViewContainer.jsx @@ -59,10 +59,13 @@ class HomeViewContainer extends Component { /** * @private - * Dismisses the Plus promo modal when user clicks either the Select Plus or Select Basic button + * Function to handle clicks on Select Plus and Select Basic in the Plus Promo Modal */ - _dismissModal = () => { + _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', {}); } @@ -91,7 +94,7 @@ class HomeViewContainer extends Component { diff --git a/app/panel/components/Panel.jsx b/app/panel/components/Panel.jsx index 15980b430..303e48f56 100644 --- a/app/panel/components/Panel.jsx +++ b/app/panel/components/Panel.jsx @@ -198,7 +198,8 @@ class Panel extends React.Component { return false; } - _plusPromoClickHandlerPlaceholder = () => { + _handlePlusPromoModalClicks = () => { + // TODO send appropriate metrics ping(s) for GH-1775 sendMessage('promoModals.sawPlusPromo', {}); this.setState({ plusPromoModalShown: true @@ -207,7 +208,10 @@ class Panel extends React.Component { _renderPlusPromoModal = () => { const { plusPromoModalShown } = this.state; - const { haveSeenInitialPlusPromo, isTimeForAPlusPromo } = this.props; + const { account, haveSeenInitialPlusPromo, isTimeForAPlusPromo } = this.props; + + if (account && account.user && account.user.subscriptionsPlus) return null; // don't show the promo to Plus subscribers! + if (account && account.user && account.user.scopes && account.user.scopes.includes('subscriptions:insights')) return null; // don't show the promo to Insights subscribers, either if (plusPromoModalShown || !isTimeForAPlusPromo) return null; @@ -217,7 +221,7 @@ class Panel extends React.Component { ); @@ -233,6 +237,8 @@ class Panel extends React.Component { return null; } + console.error('IVZ this.props in Panel#render:', this.props); + const notificationText = this.props.notificationShown && this.renderNotification(); return ( diff --git a/src/classes/PanelData.js b/src/classes/PanelData.js index 427301a18..117c9e7f9 100644 --- a/src/classes/PanelData.js +++ b/src/classes/PanelData.js @@ -352,7 +352,7 @@ class PanelData { const { id: tab_id } = this._activeTab; const { current_theme, enable_ad_block, enable_anti_tracking, enable_smart_block, - enable_offers, is_expanded, is_expert, language, plus_promo_modal_last_seen, reload_banner_status, + enable_offers, is_expanded, is_expert, language, reload_banner_status, trackers_banner_status, } = conf; diff --git a/src/classes/PromoModals.js b/src/classes/PromoModals.js index fd583954f..ddcd04ed2 100644 --- a/src/classes/PromoModals.js +++ b/src/classes/PromoModals.js @@ -22,7 +22,7 @@ const PLUS = 'plus'; const PROMO_MODAL_LAST_SEEN = 'promo_modal_last_seen'; /** - * Class for handling the business logic for the display of promo modals (Plus, Insights, etc...) + * Static 'namespace' class for handling the business logic for the display of promo modals (Plus, Insights, etc...) * @memberOf BackgroundClasses */ class PromoModals { @@ -35,6 +35,7 @@ class PromoModals { static recordPlusPromoSighting() { this._recordPromoSighting(PLUS); } + // TODO integrate the Insights promo modal into the "has it been long enough since last modal?" logic here static _isTimeForAPromo(type) { const lastSeenTime = conf[`${type}_${PROMO_MODAL_LAST_SEEN}`]; From ee361ad528c6e036a62f647e5190b9130b681343 Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Wed, 9 Oct 2019 11:42:28 -0400 Subject: [PATCH 20/27] Clean up. Finish string localization in PlusPromoModal --- _locales/en/messages.json | 15 ++++++++++--- app/panel/components/Stats.jsx | 4 ++-- .../PlusPromoModal/PlusPromoModal.jsx | 22 +++++++++---------- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 2aee9c844..8492aa2ea 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1848,9 +1848,6 @@ "panel_stats_menu_daily": { "message": "Daily" }, - "panel_stats_header_title": { - "message": "Historical Tracker Stats" - }, "panel_stats_header_title_monthly": { "message": "Historical Tracker Stats (Monthly Avg.)" }, @@ -2003,6 +2000,9 @@ "select_basic": { "message": "Select Basic" }, + "select_plus": { + "message": "Select Plus" + }, "recommended": { "message": "Recommended" }, @@ -2101,5 +2101,14 @@ }, "no_such_email_password_combo": { "message": "Looks like we can't find this email and password combo. Give it another shot." + }, + "all_basic_features_plus_COLON": { + "message": "All basic features, plus:" + }, + "historical_tracker_stats": { + "message": "Historical Tracker Stats" + }, + "new_color_themes": { + "message": "New Color Themes" } } diff --git a/app/panel/components/Stats.jsx b/app/panel/components/Stats.jsx index 117230c8f..b4028171b 100644 --- a/app/panel/components/Stats.jsx +++ b/app/panel/components/Stats.jsx @@ -106,13 +106,13 @@ class Stats extends React.Component { getSummaryTitle = (type) => { switch (type) { case 'cumulative': - return t('panel_stats_header_title'); + return t('historical_tracker_stats'); case 'monthly': return t('panel_stats_header_title_monthly'); case 'daily': return t('panel_stats_header_title_daily'); default: - return t('panel_stats_header_title'); + return t('historical_tracker_stats'); } } diff --git a/app/shared-components/PlusPromoModal/PlusPromoModal.jsx b/app/shared-components/PlusPromoModal/PlusPromoModal.jsx index fd0965a44..5eac29713 100644 --- a/app/shared-components/PlusPromoModal/PlusPromoModal.jsx +++ b/app/shared-components/PlusPromoModal/PlusPromoModal.jsx @@ -17,7 +17,6 @@ import PropTypes from 'prop-types'; import ClassNames from 'classnames'; import Modal from '../Modal/Modal'; -// TODO refactor to reduce duplication alongside implementing _renderUpgradeVersion for GH-1813 function _renderInitialVersion(props) { const { show, location, clickHandler } = props; @@ -52,6 +51,7 @@ function _renderInitialVersion(props) { locationClassName ); + // TODO refactor for clarity & concision alongside implementing _renderUpgradeVersion for GH-1813 return (
    @@ -91,31 +91,31 @@ function _renderInitialVersion(props) {
    {t('recommended')}
    -
    Ghostery Plus
    +
    {t('ghostery_plus')}
    {t('locale_appropriate_currency_icon')} {t('plus_monthly_subscription_price_number')} - per month + {t('per month')}
    -
    All basic features, plus:
    +
    {t('all_basic_features_plus_COLON')}
    -
    Historical Tracker Stats
    +
    {t('historical_tracker_stats')}
    -
    Priority Support
    +
    {t('priority_support')}
    -
    New Color Themes
    +
    {t('new_color_themes')}
    - Select Plus + {t('select_plus')}
    @@ -169,15 +169,15 @@ const PlusPromoModal = (props) => { return null; }; -PlusPromoModal.UPGRADE = 1; -PlusPromoModal.INITIAL = 2; +PlusPromoModal.INITIAL = 1; +PlusPromoModal.UPGRADE = 2; // PropTypes ensure we pass required props of the correct type PlusPromoModal.propTypes = { show: PropTypes.bool.isRequired, location: PropTypes.string.isRequired, clickHandler: PropTypes.func.isRequired, - version: PropTypes.oneOf([PlusPromoModal.UPGRADE, PlusPromoModal.INITIAL]).isRequired, + version: PropTypes.oneOf([PlusPromoModal.INITIAL, PlusPromoModal.UPGRADE]).isRequired, }; export default PlusPromoModal; From e19e5abcfa1142693f1c3c94638c73902361221c Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Wed, 16 Oct 2019 10:37:04 -0400 Subject: [PATCH 21/27] Add gold ghostie badge svg. Begin fleshing out upgrade plus promo modal design --- app/images/hub/home/gold-ghostie-badge.svg | 25 +++++++++++ .../PlusPromoModal/PlusPromoModal.jsx | 10 +++-- .../PlusPromoModal/PlusPromoModal.scss | 41 ++++++++++++++++--- 3 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 app/images/hub/home/gold-ghostie-badge.svg diff --git a/app/images/hub/home/gold-ghostie-badge.svg b/app/images/hub/home/gold-ghostie-badge.svg new file mode 100644 index 000000000..a6cba7a4d --- /dev/null +++ b/app/images/hub/home/gold-ghostie-badge.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/shared-components/PlusPromoModal/PlusPromoModal.jsx b/app/shared-components/PlusPromoModal/PlusPromoModal.jsx index 5eac29713..515db6dbf 100644 --- a/app/shared-components/PlusPromoModal/PlusPromoModal.jsx +++ b/app/shared-components/PlusPromoModal/PlusPromoModal.jsx @@ -31,6 +31,7 @@ function _renderInitialVersion(props) { 'flex-container', 'flex-dir-column', 'align-middle', + 'initial', locationClassName ); const optionsContainerClassNames = ClassNames( @@ -139,15 +140,18 @@ function _renderUpgradeVersion(props) { 'flex-container', 'flex-dir-column', 'align-middle', - locationClassName + 'upgrade', + locationClassName, ); return (
    -
    [Upgrade version of the Plus Promo modal]
    + +
    Upgrade your Ghostery experience
    +
    Unlock historical tracker insights, priority support access, and new color themes by upgrading to Ghostery Plus for only $2 per month.
    - Dismiss + Upgrade to Plus
    diff --git a/app/shared-components/PlusPromoModal/PlusPromoModal.scss b/app/shared-components/PlusPromoModal/PlusPromoModal.scss index 7aea1c077..de113c20a 100644 --- a/app/shared-components/PlusPromoModal/PlusPromoModal.scss +++ b/app/shared-components/PlusPromoModal/PlusPromoModal.scss @@ -1,17 +1,46 @@ +.PlusPromoModal__gold-ghostie-badge { + margin-top: 21px; + margin-bottom: 16px; +} + +.PlusPromoModal__header { + font-size: 20px; + font-weight: bold; + margin-bottom: 10px; +} + +.PlusPromoModal__description { + width: 350px; + text-align: center; + font-size: 14px; + margin-bottom: 5px; + + &.cta { + font-weight: bold; + } +} + .PlusPromoModal__content { position: relative; background-color: #f7f7f7; border: 1.9px solid #930194; z-index: 10; - &.in-hub { - width: 646px; - height: 553px; + &.initial { + &.in-hub { + width: 646px; + height: 553px; + } + + &.in-panel { + width: 556px; + height: 471px; + } } - &.in-panel { - width: 556px; - height: 471px; + &.upgrade { + width: 434px; + height: 410px; } } From 80d75fbaa7004465e00f30fd9dc246b2df03ab11 Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Wed, 16 Oct 2019 12:27:25 -0400 Subject: [PATCH 22/27] Pull non-shared upgrade version of plus promo modal out of shared PlusPromoModal component and into Panel to simplify --- app/hub/Views/HomeView/HomeViewContainer.jsx | 1 - app/panel/components/Panel.jsx | 26 ++++++++++- .../PlusPromoModal/PlusPromoModal.jsx | 44 +------------------ 3 files changed, 26 insertions(+), 45 deletions(-) diff --git a/app/hub/Views/HomeView/HomeViewContainer.jsx b/app/hub/Views/HomeView/HomeViewContainer.jsx index 7bf676826..fd11d3081 100644 --- a/app/hub/Views/HomeView/HomeViewContainer.jsx +++ b/app/hub/Views/HomeView/HomeViewContainer.jsx @@ -95,7 +95,6 @@ class HomeViewContainer extends Component { show={!isPlus && !plus_promo_modal_shown} location="hub" clickHandler={this._handlePlusPromoModalClicks} - version={PlusPromoModal.INITIAL} />
    diff --git a/app/panel/components/Panel.jsx b/app/panel/components/Panel.jsx index 303e48f56..b5eb67f27 100644 --- a/app/panel/components/Panel.jsx +++ b/app/panel/components/Panel.jsx @@ -12,11 +12,13 @@ */ import React from 'react'; +import ClassNames from 'classnames'; import Header from '../containers/HeaderContainer'; import { PlusPromoModal } from '../../shared-components'; import { DynamicUIPortContext } from '../contexts/DynamicUIPortContext'; import { sendMessage } from '../utils/msg'; import { setTheme } from '../utils/utils'; +import Modal from '../../shared-components/Modal'; /** * @class Implement base view with functionality common to all views. * @memberof PanelClasses @@ -206,6 +208,27 @@ class Panel extends React.Component { }); } + _renderPlusPromoUpgradeModal() { + const contentClassNames = ClassNames( + 'PlusPromoModal__content', + 'flex-container', + 'flex-dir-column', + 'align-middle', + 'panel' + ); + + return ( + +
    +
    [Upgrade version of the Plus Promo modal]
    +
    + Dismiss +
    +
    +
    + ); + } + _renderPlusPromoModal = () => { const { plusPromoModalShown } = this.state; const { account, haveSeenInitialPlusPromo, isTimeForAPlusPromo } = this.props; @@ -217,12 +240,13 @@ class Panel extends React.Component { const version = haveSeenInitialPlusPromo ? PlusPromoModal.UPGRADE : PlusPromoModal.INITIAL; + if (haveSeenInitialPlusPromo) { return this._renderPlusPromoUpgradeModal(); } + return ( ); } diff --git a/app/shared-components/PlusPromoModal/PlusPromoModal.jsx b/app/shared-components/PlusPromoModal/PlusPromoModal.jsx index 5eac29713..4b55a6bba 100644 --- a/app/shared-components/PlusPromoModal/PlusPromoModal.jsx +++ b/app/shared-components/PlusPromoModal/PlusPromoModal.jsx @@ -124,60 +124,18 @@ function _renderInitialVersion(props) { ); } -// TODO flesh out this stub for https://cliqztix.atlassian.net/browse/GH-1813 -function _renderUpgradeVersion(props) { - const { clickHandler, location, show } = props; - - const isInHub = location === 'hub'; - - const locationClassName = { - 'in-hub': isInHub, - 'in-panel': location === 'panel' - }; - const contentClassNames = ClassNames( - 'PlusPromoModal__content', - 'flex-container', - 'flex-dir-column', - 'align-middle', - locationClassName - ); - - return ( - -
    -
    [Upgrade version of the Plus Promo modal]
    -
    - Dismiss -
    -
    -
    - ); -} - /** * A Functional React component for a Plus Promo Modal * @return {JSX} JSX for rendering a Plus Promo Modal * @memberof SharedComponents */ -const PlusPromoModal = (props) => { - const { version } = props; - - if (version === PlusPromoModal.INITIAL) { return _renderInitialVersion(props); } - - if (version === PlusPromoModal.UPGRADE) { return _renderUpgradeVersion(props); } - - return null; -}; - -PlusPromoModal.INITIAL = 1; -PlusPromoModal.UPGRADE = 2; +const PlusPromoModal = props => _renderInitialVersion(props); // PropTypes ensure we pass required props of the correct type PlusPromoModal.propTypes = { show: PropTypes.bool.isRequired, location: PropTypes.string.isRequired, clickHandler: PropTypes.func.isRequired, - version: PropTypes.oneOf([PlusPromoModal.INITIAL, PlusPromoModal.UPGRADE]).isRequired, }; export default PlusPromoModal; From 811a19f2675351ff6756a150d7a95f0107a8e0db Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Fri, 18 Oct 2019 16:28:33 -0400 Subject: [PATCH 23/27] Flesh out upgrade promo modal UI and styles --- app/panel/components/Panel.jsx | 12 ++-- .../PlusPromoModal/PlusPromoModal.jsx | 6 +- .../PlusPromoModal/PlusPromoModal.scss | 66 ++++++++++++++----- 3 files changed, 61 insertions(+), 23 deletions(-) diff --git a/app/panel/components/Panel.jsx b/app/panel/components/Panel.jsx index 86120b541..85483943d 100644 --- a/app/panel/components/Panel.jsx +++ b/app/panel/components/Panel.jsx @@ -214,18 +214,24 @@ class Panel extends React.Component { 'flex-container', 'flex-dir-column', 'align-middle', - 'panel' + 'panel', + 'upgrade' ); return (
    +
    Upgrade your Ghostery experience
    Unlock historical tracker insights, priority support access, and new color themes by upgrading to Ghostery Plus for only $2 per month.
    -
    +
    Upgrade to Plus
    +
    +
    Already a subscriber? Sign In
    +
    No thanks, maybe later
    +
    ); @@ -240,8 +246,6 @@ class Panel extends React.Component { if (plusPromoModalShown || !isTimeForAPlusPromo) return null; - const version = haveSeenInitialPlusPromo ? PlusPromoModal.UPGRADE : PlusPromoModal.INITIAL; - if (haveSeenInitialPlusPromo) { return this._renderPlusPromoUpgradeModal(); } return ( diff --git a/app/shared-components/PlusPromoModal/PlusPromoModal.jsx b/app/shared-components/PlusPromoModal/PlusPromoModal.jsx index 92d5298e9..ecfe82dd2 100644 --- a/app/shared-components/PlusPromoModal/PlusPromoModal.jsx +++ b/app/shared-components/PlusPromoModal/PlusPromoModal.jsx @@ -56,7 +56,7 @@ function _renderInitialVersion(props) { return (
    -
    +
    {isInHub && (
    {t('thanks_for_downloading_ghostery')} @@ -82,7 +82,7 @@ function _renderInitialVersion(props) {
    {t('fast_browsing')}
    -
    +
    {t('select_basic')}
    @@ -115,7 +115,7 @@ function _renderInitialVersion(props) {
    - + {t('select_plus')}
    diff --git a/app/shared-components/PlusPromoModal/PlusPromoModal.scss b/app/shared-components/PlusPromoModal/PlusPromoModal.scss index de113c20a..2ec7235d6 100644 --- a/app/shared-components/PlusPromoModal/PlusPromoModal.scss +++ b/app/shared-components/PlusPromoModal/PlusPromoModal.scss @@ -1,23 +1,24 @@ +$standard-font-family: Roboto, "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; + .PlusPromoModal__gold-ghostie-badge { margin-top: 21px; margin-bottom: 16px; } .PlusPromoModal__header { + margin-bottom: 10px; font-size: 20px; font-weight: bold; - margin-bottom: 10px; + font-family: $standard-font-family; } .PlusPromoModal__description { + margin-bottom: 5px; width: 350px; text-align: center; - font-size: 14px; - margin-bottom: 5px; - - &.cta { - font-weight: bold; - } + font-size: 18px; + font-weight: 500; + font-family: $standard-font-family } .PlusPromoModal__content { @@ -51,6 +52,9 @@ width: 99%; height: 72px; z-index: -1; + + &.initial { height: 72px; } + &.upgrade { height: 107px; } } .PlusPromoModal__thanks-for-download { @@ -192,22 +196,26 @@ } .PlusPromoModal__button { - margin: 0; - font-size: 11px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.5px; + border-radius: 3px; display: flex; - align-items: center; justify-content: center; - box-shadow: none; + align-items: center; + font-weight: bold; + font-family: $standard-font-family; + letter-spacing: 0.5px; + text-transform: uppercase; + cursor: pointer; + transition: background-color 0.25s ease-out, color 0.25s ease-out; + -webkit-appearance: none; &.basic { + font-size: 11px; width: 135px; height: 40px; border: solid 2px #15b4f2; background-color: white; color: #2cbcf4; + box-shadow: none; } &.basic:hover { background-color: #2cbcf4; @@ -215,15 +223,41 @@ } &.plus { + font-size: 11px; width: 163px; height: 38px; border: none; background-image: linear-gradient(to bottom, #2fdbfa, #15b4f2); color: white; - font-weight: 600; - letter-spacing: 0.5px; + box-shadow: none; } &.plus:hover { background-image: linear-gradient(to bottom, #1fcbea, #05a4e2); } + + &.upgrade { + font-size: 13px; + width: 176px; + height: 36px; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.24), 0 0 2px 0 rgba(0, 0, 0, 0.12); + background-color: #1dafed; + color: white; + } + &.upgrade:hover { + background-color: #0698d6; + } +} + +.PlusPromoModal__text-link-container { + width: 100%; + display: flex; + justify-content: space-between; +} + +.PlusPromoModal__text-link { + margin-left: 10px; + margin-right: 10px; + font-size: 15px; + font-family: $standard-font-family; + color: #4a4a4a; } From 2e4f06065ce5fa586d9bcae356de8da15e97c72c Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Mon, 21 Oct 2019 11:37:42 -0400 Subject: [PATCH 24/27] Implement panel to tab link for the upgrade to plus button --- app/panel/components/BuildingBlocks/PanelToTabLink.jsx | 6 ++++-- app/panel/components/Panel.jsx | 7 +++++-- app/shared-components/PlusPromoModal/PlusPromoModal.scss | 5 +++++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/app/panel/components/BuildingBlocks/PanelToTabLink.jsx b/app/panel/components/BuildingBlocks/PanelToTabLink.jsx index 32748e1b1..286827c53 100644 --- a/app/panel/components/BuildingBlocks/PanelToTabLink.jsx +++ b/app/panel/components/BuildingBlocks/PanelToTabLink.jsx @@ -19,10 +19,12 @@ import { handleClickOnNewTabLink } from '../../utils/msg'; * @memberof PanelBuildingBlocks */ const PanelToTabLink = (props) => { - const { href, children } = props; + const { className, href, children } = props; + + const classes = className || ''; return ( - {children} + {children} ); }; diff --git a/app/panel/components/Panel.jsx b/app/panel/components/Panel.jsx index 85483943d..db9e034b0 100644 --- a/app/panel/components/Panel.jsx +++ b/app/panel/components/Panel.jsx @@ -15,6 +15,7 @@ import React from 'react'; import ClassNames from 'classnames'; import Header from '../containers/HeaderContainer'; import { PlusPromoModal } from '../../shared-components'; +import PanelToTabLink from './BuildingBlocks/PanelToTabLink'; import { DynamicUIPortContext } from '../contexts/DynamicUIPortContext'; import { sendMessage } from '../utils/msg'; import { setTheme } from '../utils/utils'; @@ -225,8 +226,10 @@ class Panel extends React.Component {
    Upgrade your Ghostery experience
    Unlock historical tracker insights, priority support access, and new color themes by upgrading to Ghostery Plus for only $2 per month.
    -
    - Upgrade to Plus +
    + + Upgrade to Plus +
    Already a subscriber? Sign In
    diff --git a/app/shared-components/PlusPromoModal/PlusPromoModal.scss b/app/shared-components/PlusPromoModal/PlusPromoModal.scss index 2ec7235d6..c741f6e2f 100644 --- a/app/shared-components/PlusPromoModal/PlusPromoModal.scss +++ b/app/shared-components/PlusPromoModal/PlusPromoModal.scss @@ -246,6 +246,11 @@ $standard-font-family: Roboto, "Open Sans", "Helvetica Neue", Helvetica, Arial, &.upgrade:hover { background-color: #0698d6; } + + .button-text { + color: white; + text-decoration: none; + } } .PlusPromoModal__text-link-container { From c246530d673a7f594c18a7cfae7e4fa06db877c4 Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Mon, 21 Oct 2019 12:16:21 -0400 Subject: [PATCH 25/27] Add no thanks link click handling --- app/panel/components/Panel.jsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/panel/components/Panel.jsx b/app/panel/components/Panel.jsx index db9e034b0..281083dbb 100644 --- a/app/panel/components/Panel.jsx +++ b/app/panel/components/Panel.jsx @@ -209,6 +209,13 @@ class Panel extends React.Component { }); } + _handleNoThanksClick = () => { + sendMessage('promoModals.sawPlusPromo', {}); + this.setState({ + plusPromoModalShown: true + }); + } + _renderPlusPromoUpgradeModal() { const contentClassNames = ClassNames( 'PlusPromoModal__content', @@ -233,7 +240,7 @@ class Panel extends React.Component {
    Already a subscriber? Sign In
    -
    No thanks, maybe later
    +
    No thanks, maybe later
    From 49161bf3035f4e16e8ddadc31b341754337837aa Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Mon, 21 Oct 2019 16:31:29 -0400 Subject: [PATCH 26/27] Localization-proof upgrade modal CSS. Finalize UI and display logic. --- _locales/en/messages.json | 23 +++++++-- app/panel/components/Panel.jsx | 48 ++++++++++++++----- app/panel/components/Subscribe.jsx | 2 +- .../PlusPromoModal/PlusPromoModal.scss | 16 ++++++- 4 files changed, 72 insertions(+), 17 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 356f3efc8..cbd4ca906 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1786,9 +1786,6 @@ "subscribe_pitch_learn_more": { "message": "Learn more" }, - "subscribe_pitch_sign_here": { - "message": "Already a subscriber? Sign in here" - }, "subscription_midnight_theme": { "message": "Midnight Theme" }, @@ -2113,5 +2110,25 @@ }, "new_color_themes": { "message": "New Color Themes" + }, + "upgrade_cta_TEXT": { + "message": "Unlock historical tracker insights, priority support access, and new color themes by upgrading to Ghostery Plus for only $2 per month.", + "description": "Body text in a non-responsive modal. Character limit: 135." + }, + "upgrade_your_ghostery_experience": { + "message": "Upgrade your Ghostery experience", + "description": "Header text for a non-responsive modal. Character limit: 40." + }, + "upgrade_to_plus": { + "message": "Upgrade to Plus", + "description": "Button text in a non-responsive modal. Character limit: 35." + }, + "no_thanks_maybe_later": { + "message": "No thanks, maybe later", + "description": "Text link in a non-responsive modal. Character limit: 25." + }, + "already_subscribed_sign_in": { + "message": "Already subscribed? Sign In", + "description": "Character limit: 30." } } diff --git a/app/panel/components/Panel.jsx b/app/panel/components/Panel.jsx index 281083dbb..bee64535c 100644 --- a/app/panel/components/Panel.jsx +++ b/app/panel/components/Panel.jsx @@ -216,7 +216,15 @@ class Panel extends React.Component { }); } - _renderPlusPromoUpgradeModal() { + _handleSubscriberSignInClick = () => { + sendMessage('promoModals.sawPlusPromo', {}); + this.setState({ + plusPromoModalShown: true + }); + this.props.history.push('/login'); + } + + _renderPlusPromoUpgradeModal(signedIn) { const contentClassNames = ClassNames( 'PlusPromoModal__content', 'flex-container', @@ -231,16 +239,29 @@ class Panel extends React.Component {
    -
    Upgrade your Ghostery experience
    -
    Unlock historical tracker insights, priority support access, and new color themes by upgrading to Ghostery Plus for only $2 per month.
    -
    +
    + {t('upgrade_your_ghostery_experience')} +
    +
    + {t('upgrade_cta_TEXT')} +
    +
    - Upgrade to Plus + {t('upgrade_to_plus')}
    -
    Already a subscriber? Sign In
    -
    No thanks, maybe later
    + { + !signedIn && + ( +
    + {t('already_subscribed_sign_in')} +
    + ) + } +
    + {t('no_thanks_maybe_later')} +
    @@ -251,12 +272,17 @@ class Panel extends React.Component { const { plusPromoModalShown } = this.state; const { account, haveSeenInitialPlusPromo, isTimeForAPlusPromo } = this.props; - if (account && account.user && account.user.subscriptionsPlus) return null; // don't show the promo to Plus subscribers! - if (account && account.user && account.user.scopes && account.user.scopes.includes('subscriptions:insights')) return null; // don't show the promo to Insights subscribers, either - + // The business logic that controls how often promo modals should be shown lives in src/classes/PromoModals if (plusPromoModalShown || !isTimeForAPlusPromo) return null; - if (haveSeenInitialPlusPromo) { return this._renderPlusPromoUpgradeModal(); } + // Check account status + const signedIn = account && account.user; + const plusSubscriber = signedIn && account.user.subscriptionsPlus; + const insightsSubscriber = signedIn && account.user.scopes && account.user.scopes.includes('subscriptions:insights'); + + if (plusSubscriber || insightsSubscriber) return null; + + if (haveSeenInitialPlusPromo) { return this._renderPlusPromoUpgradeModal(signedIn); } return ( {
    {(loggedIn === 'false') && ( - {t('subscribe_pitch_sign_here')} + {t('already_subscribed_sign_in')} )}
    diff --git a/app/shared-components/PlusPromoModal/PlusPromoModal.scss b/app/shared-components/PlusPromoModal/PlusPromoModal.scss index c741f6e2f..310d80ac7 100644 --- a/app/shared-components/PlusPromoModal/PlusPromoModal.scss +++ b/app/shared-components/PlusPromoModal/PlusPromoModal.scss @@ -195,6 +195,14 @@ $standard-font-family: Roboto, "Open Sans", "Helvetica Neue", Helvetica, Arial, justify-content: center; } +.PlusPromoModal__button-container { + width: 100%; + display: flex; + justify-content: center; + position: absolute; + bottom: 50px; +} + .PlusPromoModal__button { border-radius: 3px; display: flex; @@ -237,7 +245,6 @@ $standard-font-family: Roboto, "Open Sans", "Helvetica Neue", Helvetica, Arial, &.upgrade { font-size: 13px; - width: 176px; height: 36px; box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.24), 0 0 2px 0 rgba(0, 0, 0, 0.12); background-color: #1dafed; @@ -248,15 +255,18 @@ $standard-font-family: Roboto, "Open Sans", "Helvetica Neue", Helvetica, Arial, } .button-text { + padding: 0px 20px 0px; color: white; text-decoration: none; } } .PlusPromoModal__text-link-container { + position: absolute; + bottom: 10px; width: 100%; display: flex; - justify-content: space-between; + justify-content: space-evenly; } .PlusPromoModal__text-link { @@ -265,4 +275,6 @@ $standard-font-family: Roboto, "Open Sans", "Helvetica Neue", Helvetica, Arial, font-size: 15px; font-family: $standard-font-family; color: #4a4a4a; + text-decoration: underline; + cursor: pointer; } From 05291b5370ef1a68e8e103d0e0188cca666a0977 Mon Sep 17 00:00:00 2001 From: wlycdgr Date: Wed, 23 Oct 2019 15:45:53 -0400 Subject: [PATCH 27/27] Implement ability to turn off promotions from inside plus upgrade promo modal --- _locales/en/messages.json | 8 ++++---- app/panel/components/Panel.jsx | 3 ++- src/background.js | 4 ++++ src/classes/PromoModals.js | 2 ++ 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index cbd4ca906..38040eacb 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -2123,12 +2123,12 @@ "message": "Upgrade to Plus", "description": "Button text in a non-responsive modal. Character limit: 35." }, - "no_thanks_maybe_later": { - "message": "No thanks, maybe later", - "description": "Text link in a non-responsive modal. Character limit: 25." + "no_thanks_turn_promos_off": { + "message": "No thanks, turn promos off", + "description": "Text link in a non-responsive modal. Character limit: 28." }, "already_subscribed_sign_in": { "message": "Already subscribed? Sign In", - "description": "Character limit: 30." + "description": "Character limit: 28." } } diff --git a/app/panel/components/Panel.jsx b/app/panel/components/Panel.jsx index bee64535c..97c2d4489 100644 --- a/app/panel/components/Panel.jsx +++ b/app/panel/components/Panel.jsx @@ -211,6 +211,7 @@ class Panel extends React.Component { _handleNoThanksClick = () => { sendMessage('promoModals.sawPlusPromo', {}); + sendMessage('promoModals.turnOffPromos', {}); this.setState({ plusPromoModalShown: true }); @@ -260,7 +261,7 @@ class Panel extends React.Component { ) }
    - {t('no_thanks_maybe_later')} + {t('no_thanks_turn_promos_off')}
    diff --git a/src/background.js b/src/background.js index c1f9b4683..a80e7888e 100644 --- a/src/background.js +++ b/src/background.js @@ -1082,6 +1082,10 @@ function onMessageHandler(request, sender, callback) { promoModals.recordPlusPromoSighting(); return true; } + if (name === 'promoModals.turnOffPromos') { + promoModals.turnOffPromos(); + return true; + } } /** diff --git a/src/classes/PromoModals.js b/src/classes/PromoModals.js index ddcd04ed2..5509d9960 100644 --- a/src/classes/PromoModals.js +++ b/src/classes/PromoModals.js @@ -35,6 +35,8 @@ class PromoModals { static recordPlusPromoSighting() { this._recordPromoSighting(PLUS); } + static turnOffPromos() { conf.notify_promotions = false; } + // TODO integrate the Insights promo modal into the "has it been long enough since last modal?" logic here static _isTimeForAPromo(type) { const lastSeenTime = conf[`${type}_${PROMO_MODAL_LAST_SEEN}`];