From 901c4fab12332997b4a6332b9ce950043f8c9c94 Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 7 May 2020 11:42:02 -0400 Subject: [PATCH 01/34] Show premium subscribers a premium badge in simple/detailed views, header, and settings panel --- _locales/en/messages.json | 3 ++ ....svg => plus-badge-icon-expanded-view.svg} | 0 ...gold-plus-icon.svg => plus-badge-icon.svg} | 0 .../premium-badge-icon-expanded-view.svg | 1 + app/images/panel/premium-badge-icon.svg | 1 + app/panel/components/Header.jsx | 27 ++++++++----- app/panel/components/HeaderMenu.jsx | 40 ++++++++++++++----- app/panel/components/Summary.jsx | 18 +++++++-- app/scss/partials/_header.scss | 5 ++- 9 files changed, 70 insertions(+), 25 deletions(-) rename app/images/panel/{gold-plus-icon-expanded-view.svg => plus-badge-icon-expanded-view.svg} (100%) rename app/images/panel/{gold-plus-icon.svg => plus-badge-icon.svg} (100%) create mode 100644 app/images/panel/premium-badge-icon-expanded-view.svg create mode 100644 app/images/panel/premium-badge-icon.svg diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 6b30646c9..6884e60c0 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -2207,6 +2207,9 @@ "ghostery_plus": { "message": "Ghostery Plus" }, + "ghostery_premium": { + "message": "Ghostery Premium" + }, "dollar_sign": { "message": "$" }, diff --git a/app/images/panel/gold-plus-icon-expanded-view.svg b/app/images/panel/plus-badge-icon-expanded-view.svg similarity index 100% rename from app/images/panel/gold-plus-icon-expanded-view.svg rename to app/images/panel/plus-badge-icon-expanded-view.svg diff --git a/app/images/panel/gold-plus-icon.svg b/app/images/panel/plus-badge-icon.svg similarity index 100% rename from app/images/panel/gold-plus-icon.svg rename to app/images/panel/plus-badge-icon.svg diff --git a/app/images/panel/premium-badge-icon-expanded-view.svg b/app/images/panel/premium-badge-icon-expanded-view.svg new file mode 100644 index 000000000..1f6390dc0 --- /dev/null +++ b/app/images/panel/premium-badge-icon-expanded-view.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/images/panel/premium-badge-icon.svg b/app/images/panel/premium-badge-icon.svg new file mode 100644 index 000000000..292b7a5e1 --- /dev/null +++ b/app/images/panel/premium-badge-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/panel/components/Header.jsx b/app/panel/components/Header.jsx index 5f31d701a..cf03476e8 100644 --- a/app/panel/components/Header.jsx +++ b/app/panel/components/Header.jsx @@ -149,8 +149,8 @@ class Header extends React.Component { // TODO check whether this is the message we want to be sending now sendMessage('ping', 'plus_panel_from_badge'); const { user } = this.props; - const subscriber = user && user.subscriptionsPlus; - this.props.history.push(subscriber ? '/subscription/info' : `/subscribe/${!!user}`); + const plusSubscriber = user && user.subscriptionsPlus; + this.props.history.push(plusSubscriber ? '/subscription/info' : `/subscribe/${!!user}`); } /** @@ -176,11 +176,12 @@ class Header extends React.Component { const tabDetailedClassNames = ClassNames('header-tab', { active: is_expert, }); - const subscriber = user && user.subscriptionsPlus; + const premiumSubscriber = user && user.scopes && user.scopes.includes('subscriptions:premium'); + const plusSubscriber = user && user.subscriptionsPlus; const accountLogolink = this.generateAccountLogo(); const badgeClasses = ClassNames('columns', 'shrink', { - 'non-subscriber-badge': !subscriber, - 'gold-subscriber-badge': subscriber + 'non-subscriber-badge': !(plusSubscriber || premiumSubscriber), + 'gold-subscriber-badge': plusSubscriber || premiumSubscriber }); const simpleTab = ( @@ -215,11 +216,17 @@ class Header extends React.Component { ); - const plusUpgradeBannerOrSubscriberBadgeLogolink = ( + let subscriberType; + if (premiumSubscriber) { + subscriberType = 'premium'; + } else if (plusSubscriber) { + subscriberType = 'plus'; + } + const upgradeBannerOrSubscriberBadgeLogolink = (
{ - (subscriber && ) || - + ((premiumSubscriber || plusSubscriber) && ) + || }
); @@ -237,7 +244,7 @@ class Header extends React.Component { const headerMenu = ( {accountLogolink} - {((is_expert && is_expanded) || !showTabs) && plusUpgradeBannerOrSubscriberBadgeLogolink } + {((is_expert && is_expanded) || !showTabs) && upgradeBannerOrSubscriberBadgeLogolink } {headerMenuKebab} { this.state.dropdownOpen && headerMenu } diff --git a/app/panel/components/HeaderMenu.jsx b/app/panel/components/HeaderMenu.jsx index 6467aa295..0f4ac40fc 100644 --- a/app/panel/components/HeaderMenu.jsx +++ b/app/panel/components/HeaderMenu.jsx @@ -154,7 +154,7 @@ class HeaderMenu extends React.Component { clickSubscriber = () => { sendMessage('ping', 'plus_panel_from_menu'); this.props.toggleDropdown(); - this.props.history.push(this.props.subscriber ? '/subscription/info' : `/subscribe/${this.props.loggedIn}`); + this.props.history.push(this.props.subscriberType ? '/subscription/info' : `/subscribe/${this.props.loggedIn}`); } /** @@ -162,9 +162,13 @@ class HeaderMenu extends React.Component { * @return {ReactComponent} ReactComponent instance */ render() { - const { loggedIn, email } = this.props; - const optionClasses = ClassNames({ 'menu-option': this.props.subscriber, 'menu-option-non-subscriber': !this.props.subscriber }); - const iconClasses = ClassNames('menu-icon-container', { subscriber: this.props.subscriber }, { 'non-subscriber': !this.props.subscriber }); + const { loggedIn, email, subscriberType } = this.props; + const optionClasses = ClassNames({ 'menu-option': this.props.subscriberType, 'menu-option-non-subscriber': !this.props.subscriberType }); + const iconClasses = ClassNames('menu-icon-container', { + premiumSubscriber: subscriberType === 'premium', + plusSubscriber: subscriberType === 'plus', + 'non-subscriber': !subscriberType + }); return (
@@ -230,13 +234,27 @@ class HeaderMenu extends React.Component {
  • - - - - - - - { t('ghostery_plus') } + {/* Upselling plus for users who are not logged in */} + {subscriberType !== 'premium' && ( + + + + + + + )} + {subscriberType === 'premium' && ( + + + + + + + + + + )} + {subscriberType === 'premium' ? t('ghostery_premium') : t('ghostery_plus')}
  • diff --git a/app/panel/components/Summary.jsx b/app/panel/components/Summary.jsx index 4b9463999..9b46c0c5f 100644 --- a/app/panel/components/Summary.jsx +++ b/app/panel/components/Summary.jsx @@ -312,6 +312,11 @@ class Summary extends React.Component { return user && user.subscriptionsPlus; } + _isPremiumSubscriber() { + const { user } = this.props; + return user && user.scopes && user.scopes.includes('subscriptions:premium'); + } + _pageHost() { return this.props.pageHost || 'page_host'; } @@ -748,23 +753,30 @@ class Summary extends React.Component { _renderPlusUpgradeBannerOrSubscriberIcon() { const { is_expert, current_theme } = this.props; + const isPremiumSubscriber = this._isPremiumSubscriber(); const isPlusSubscriber = this._isPlusSubscriber(); const upgradeBannerClassNames = ClassNames('UpgradeBanner', { 'UpgradeBanner--normal': !is_expert, 'UpgradeBanner--small': is_expert, }); + let subscriberType; + if (isPremiumSubscriber) { + subscriberType = 'premium'; + } else if (isPlusSubscriber) { + subscriberType = 'plus'; + } return (
    - {isPlusSubscriber && ( + {(isPremiumSubscriber || isPlusSubscriber) && (
    - +
    )} - {!isPlusSubscriber && ( + {(!isPremiumSubscriber && !isPlusSubscriber) && (
    {t('subscription_upgrade_to')} diff --git a/app/scss/partials/_header.scss b/app/scss/partials/_header.scss index 2c29a8281..ead8f6eba 100644 --- a/app/scss/partials/_header.scss +++ b/app/scss/partials/_header.scss @@ -148,12 +148,15 @@ .menu-option { @extend .menu-option-base; - .subscriber { + .plusSubscriber { width: 18px; height: 16px; path {fill: $light-gray;} path.text {fill: #4a4a4a;} } + .premiumSubscriber { + margin-left: -4px; + } &:hover { span {color: $ghosty-blue} .menu-icon {fill: $ghosty-blue; stroke: none;} From f944c6ca558bc2f11f92d997836c51d64296485f Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 7 May 2020 11:42:49 -0400 Subject: [PATCH 02/34] Use api version 2.1.0 to get multiple subscriptions --- src/utils/api.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utils/api.js b/src/utils/api.js index f2e3865f5..64671a0fe 100644 --- a/src/utils/api.js +++ b/src/utils/api.js @@ -154,17 +154,17 @@ class Api { get = (type, id, include = '') => { if (!id) { return Promise.reject(new Error('id is missing')); } - return this._sendAuthenticatedRequest('GET', `/api/v2/${type}/${id}?${include ? `include=${include}` : ''}`); + return this._sendAuthenticatedRequest('GET', `/api/v2.1.0/${type}/${id}?${include ? `include=${include}` : ''}`); } - save = (type, data) => this._sendAuthenticatedRequest('POST', `/api/v2/${type}/`, data) + save = (type, data) => this._sendAuthenticatedRequest('POST', `/api/v2.1.0/${type}/`, data) update = (type, data) => { // TODO check for data.id and fail - this._sendAuthenticatedRequest('PATCH', `/api/v2/${type}/${data.id}`, { data }); + this._sendAuthenticatedRequest('PATCH', `/api/v2.1.0/${type}/${data.id}`, { data }); } - remove = (type, id) => this._sendAuthenticatedRequest('DELETE', `/api/v2/${type}/${id}`) + remove = (type, id) => this._sendAuthenticatedRequest('DELETE', `/api/v2.1.0/${type}/${id}`) } export default Api; From e035e693dd2ce5b8e0343c04b8b0dff2ddc0ae6f Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 7 May 2020 11:55:15 -0400 Subject: [PATCH 03/34] Add hover effect for premium icon in menu --- app/scss/partials/_header.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/scss/partials/_header.scss b/app/scss/partials/_header.scss index ead8f6eba..ad8cdcc96 100644 --- a/app/scss/partials/_header.scss +++ b/app/scss/partials/_header.scss @@ -168,6 +168,9 @@ path {stroke: $ghosty-blue;} path.text {fill: $ghosty-blue;} } + .premiumSubscriber > g > g { + fill: $ghosty-blue; + } } span { color: #ffffff; From 659749bfdd0afc4e38e782714a7ad93361adab88 Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 7 May 2020 11:59:10 -0400 Subject: [PATCH 04/34] Use css as single source of truth for icon colors --- app/panel/components/HeaderMenu.jsx | 2 +- app/scss/partials/_header.scss | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/panel/components/HeaderMenu.jsx b/app/panel/components/HeaderMenu.jsx index 0f4ac40fc..02d0ef313 100644 --- a/app/panel/components/HeaderMenu.jsx +++ b/app/panel/components/HeaderMenu.jsx @@ -246,7 +246,7 @@ class HeaderMenu extends React.Component { {subscriberType === 'premium' && ( - + diff --git a/app/scss/partials/_header.scss b/app/scss/partials/_header.scss index ad8cdcc96..778d30fc6 100644 --- a/app/scss/partials/_header.scss +++ b/app/scss/partials/_header.scss @@ -156,6 +156,9 @@ } .premiumSubscriber { margin-left: -4px; + g > g { + fill: #DEDEDE; + } } &:hover { span {color: $ghosty-blue} From 2a83d4212c93e0d6722847ae43234f3c60f8d142 Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 7 May 2020 19:44:32 -0400 Subject: [PATCH 05/34] Handle case where a user has multiple subscriptions and display Premium > Plus --- src/background.js | 14 +------------- src/classes/Account.js | 20 ++++++++++++-------- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/src/background.js b/src/background.js index e4fbc0e53..f5e9e21ca 100644 --- a/src/background.js +++ b/src/background.js @@ -824,19 +824,7 @@ function onMessageHandler(request, sender, callback) { if (name === 'account.getUserSubscriptionData') { account.getUserSubscriptionData() .then((customer) => { - // TODO temporary fix to handle multiple subscriptions - let sub = customer.subscriptions; - if (!Array.isArray(sub)) { - sub = [sub]; - } - const subscriptionData = sub.reduce((acc, curr) => { - let a = acc; - if (curr.productName.includes('Plus')) { - a = curr; - } - return a; - }, {}); - callback({ subscriptionData }); + callback({ subscriptionData: customer }); }) .catch((err) => { log('Error getting user subscription data:', err); diff --git a/src/classes/Account.js b/src/classes/Account.js index 4dfd48a30..73790f941 100644 --- a/src/classes/Account.js +++ b/src/classes/Account.js @@ -168,14 +168,18 @@ class Account { if (!Array.isArray(sub)) { sub = [sub]; } - const subPlus = sub.reduce((acc, curr) => { - let a = acc; - if (curr.productName.includes('Plus')) { - a = curr; - } - return a; - }, {}); - this._setSubscriptionData(subPlus); + // Display premium info if user has both premium and plus subscriptions + const premiumSubscription = sub.find(subscription => subscription.productName.includes('Ghostery Premium')); + if (premiumSubscription) { + this._setSubscriptionData(premiumSubscription); + return premiumSubscription; + } + + const plusSubscription = sub.find(subscription => subscription.productName.includes('Ghostery Plus')); + if (plusSubscription) { + this._setSubscriptionData(plusSubscription); + return plusSubscription; + } return customer; }) ) From de02e6c91bb68757dda84cad96ce86c5882d423e Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 7 May 2020 20:09:04 -0400 Subject: [PATCH 06/34] Display subscription name --- app/panel/components/Subscription.jsx | 3 ++- app/panel/components/Subscription/SubscriptionInfo.jsx | 9 +++++++-- src/classes/Account.js | 3 +++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/app/panel/components/Subscription.jsx b/app/panel/components/Subscription.jsx index d39afad65..e6368ca36 100644 --- a/app/panel/components/Subscription.jsx +++ b/app/panel/components/Subscription.jsx @@ -54,7 +54,7 @@ class Subscription extends React.Component { const sd = this.props.subscriptionData; if (sd) { const { - planAmount, planInterval, planCurrency, currentPeriodEnd, cancelAtPeriodEnd, status + productName, planAmount, planInterval, planCurrency, currentPeriodEnd, cancelAtPeriodEnd, status } = sd; const plan_ends = cancelAtPeriodEnd ? moment.duration(moment.unix(currentPeriodEnd).diff(moment(new Date()))).days() : ''; let planAmountAdjusted = planAmount; @@ -66,6 +66,7 @@ class Subscription extends React.Component { currency: planCurrency }); return { + productName, plan_amount: amountWithCurrency, plan_interval: planInterval, active: (status === 'active'), diff --git a/app/panel/components/Subscription/SubscriptionInfo.jsx b/app/panel/components/Subscription/SubscriptionInfo.jsx index 8d115b17b..b5c2de57e 100644 --- a/app/panel/components/Subscription/SubscriptionInfo.jsx +++ b/app/panel/components/Subscription/SubscriptionInfo.jsx @@ -38,14 +38,19 @@ function _handleManageClick() { */ const SubscriptionInfo = (props) => { const { - active, plan_amount, plan_interval, charge_date, plan_ends, loading + productName, active, plan_amount, plan_interval, charge_date, plan_ends, loading } = props.subscriptionData; const subscriptionExpiration = (plan_ends > 1) ? t('subscription_days_left', plan_ends.toString()) : t('subscription_one_day_left'); return (
    -

    { t('ghostery_plus') }

    + {productName === 'Ghostery Premium' && ( +

    { t('ghostery_premium') }

    + )} + {productName === 'Ghostery Plus' && ( +

    { t('ghostery_plus') }

    + )} {loading ? (
    ) : ( diff --git a/src/classes/Account.js b/src/classes/Account.js index 73790f941..57ab030c6 100644 --- a/src/classes/Account.js +++ b/src/classes/Account.js @@ -163,11 +163,13 @@ class Account { .then(userID => api.get('stripe/customers', userID, 'cards,subscriptions')) .then((res) => { const customer = build(normalize(res), 'customers', res.data.id); + // TODO temporary fix to handle multiple subscriptions let sub = customer.subscriptions; if (!Array.isArray(sub)) { sub = [sub]; } + // Display premium info if user has both premium and plus subscriptions const premiumSubscription = sub.find(subscription => subscription.productName.includes('Ghostery Premium')); if (premiumSubscription) { @@ -180,6 +182,7 @@ class Account { this._setSubscriptionData(plusSubscription); return plusSubscription; } + return customer; }) ) From 53378f0ecdbb9a5ad71d5e9371c22e2f3cbb2455 Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 7 May 2020 20:18:59 -0400 Subject: [PATCH 07/34] Remove duplicate locale string --- _locales/en/messages.json | 3 --- app/panel/components/HeaderMenu.jsx | 2 +- app/panel/components/Subscription/SubscriptionInfo.jsx | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 6884e60c0..6b30646c9 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -2207,9 +2207,6 @@ "ghostery_plus": { "message": "Ghostery Plus" }, - "ghostery_premium": { - "message": "Ghostery Premium" - }, "dollar_sign": { "message": "$" }, diff --git a/app/panel/components/HeaderMenu.jsx b/app/panel/components/HeaderMenu.jsx index 02d0ef313..1a7b5891e 100644 --- a/app/panel/components/HeaderMenu.jsx +++ b/app/panel/components/HeaderMenu.jsx @@ -254,7 +254,7 @@ class HeaderMenu extends React.Component { )} - {subscriberType === 'premium' ? t('ghostery_premium') : t('ghostery_plus')} + {subscriberType === 'premium' ? t('panel_detail_premium_title') : t('ghostery_plus')}
    diff --git a/app/panel/components/Subscription/SubscriptionInfo.jsx b/app/panel/components/Subscription/SubscriptionInfo.jsx index b5c2de57e..704895df8 100644 --- a/app/panel/components/Subscription/SubscriptionInfo.jsx +++ b/app/panel/components/Subscription/SubscriptionInfo.jsx @@ -46,7 +46,7 @@ const SubscriptionInfo = (props) => {
    {productName === 'Ghostery Premium' && ( -

    { t('ghostery_premium') }

    +

    { t('panel_detail_premium_title') }

    )} {productName === 'Ghostery Plus' && (

    { t('ghostery_plus') }

    From a10bd6c2a46a792b02740b0371b1b07c27161b09 Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 7 May 2020 20:26:07 -0400 Subject: [PATCH 08/34] Handle case where user only has a premium subscription and clicks the subscriber badge icon --- app/panel/components/Header.jsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/panel/components/Header.jsx b/app/panel/components/Header.jsx index cf03476e8..1ba455a3b 100644 --- a/app/panel/components/Header.jsx +++ b/app/panel/components/Header.jsx @@ -145,12 +145,13 @@ class Header extends React.Component { return this.props.is_expert ? '/detail/blocking' : '/'; } - clickUpgradeBannerOrGoldPlusIcon = () => { + clickUpgradeBannerOrSubscriberBadgeIcon = () => { // TODO check whether this is the message we want to be sending now sendMessage('ping', 'plus_panel_from_badge'); const { user } = this.props; const plusSubscriber = user && user.subscriptionsPlus; - this.props.history.push(plusSubscriber ? '/subscription/info' : `/subscribe/${!!user}`); + const premiumSubscriber = user && user.scopes && user.scopes.includes('subscriptions:premium'); + this.props.history.push(plusSubscriber || premiumSubscriber ? '/subscription/info' : `/subscribe/${!!user}`); } /** @@ -223,7 +224,7 @@ class Header extends React.Component { subscriberType = 'plus'; } const upgradeBannerOrSubscriberBadgeLogolink = ( -
    +
    { ((premiumSubscriber || plusSubscriber) && ) || From 7e552d20e637a9c53c9c7b815916883228733e2c Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 7 May 2020 20:40:59 -0400 Subject: [PATCH 09/34] Refactor code --- app/panel/components/Header.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/panel/components/Header.jsx b/app/panel/components/Header.jsx index 1ba455a3b..f07ecf536 100644 --- a/app/panel/components/Header.jsx +++ b/app/panel/components/Header.jsx @@ -177,8 +177,8 @@ class Header extends React.Component { const tabDetailedClassNames = ClassNames('header-tab', { active: is_expert, }); - const premiumSubscriber = user && user.scopes && user.scopes.includes('subscriptions:premium'); const plusSubscriber = user && user.subscriptionsPlus; + const premiumSubscriber = user && user.scopes && user.scopes.includes('subscriptions:premium'); const accountLogolink = this.generateAccountLogo(); const badgeClasses = ClassNames('columns', 'shrink', { 'non-subscriber-badge': !(plusSubscriber || premiumSubscriber), @@ -223,7 +223,7 @@ class Header extends React.Component { } else if (plusSubscriber) { subscriberType = 'plus'; } - const upgradeBannerOrSubscriberBadgeLogolink = ( + const plusUpgradeBannerOrSubscriberBadgeLogolink = (
    { ((premiumSubscriber || plusSubscriber) && ) @@ -267,7 +267,7 @@ class Header extends React.Component {
    {accountLogolink}
    - {((is_expert && is_expanded) || !showTabs) && upgradeBannerOrSubscriberBadgeLogolink } + {((is_expert && is_expanded) || !showTabs) && plusUpgradeBannerOrSubscriberBadgeLogolink } {headerMenuKebab}
    { this.state.dropdownOpen && headerMenu } From 9eb39bd0ad11f7a4569f5f9db2c37ba49311fed0 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 11 May 2020 09:06:49 -0400 Subject: [PATCH 10/34] Refactor subscriber badge css classes, image paths and comments --- app/panel/components/Header.jsx | 17 +++++++++-------- app/panel/components/HeaderMenu.jsx | 2 +- app/scss/partials/_header.scss | 2 +- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/app/panel/components/Header.jsx b/app/panel/components/Header.jsx index f07ecf536..aaf4902b0 100644 --- a/app/panel/components/Header.jsx +++ b/app/panel/components/Header.jsx @@ -182,7 +182,7 @@ class Header extends React.Component { const accountLogolink = this.generateAccountLogo(); const badgeClasses = ClassNames('columns', 'shrink', { 'non-subscriber-badge': !(plusSubscriber || premiumSubscriber), - 'gold-subscriber-badge': plusSubscriber || premiumSubscriber + 'subscriber-badge': plusSubscriber || premiumSubscriber }); const simpleTab = ( @@ -217,16 +217,11 @@ class Header extends React.Component { ); - let subscriberType; - if (premiumSubscriber) { - subscriberType = 'premium'; - } else if (plusSubscriber) { - subscriberType = 'plus'; - } const plusUpgradeBannerOrSubscriberBadgeLogolink = (
    { - ((premiumSubscriber || plusSubscriber) && ) + ((premiumSubscriber) && ) + || ((plusSubscriber) && ) || }
    @@ -242,6 +237,12 @@ class Header extends React.Component {
    ); + let subscriberType; + if (premiumSubscriber) { + subscriberType = 'premium'; + } else if (plusSubscriber) { + subscriberType = 'plus'; + } const headerMenu = (
  • - {/* Upselling plus for users who are not logged in */} + {/* Upselling plus for all users who are not premium subscribers */} {subscriberType !== 'premium' && ( diff --git a/app/scss/partials/_header.scss b/app/scss/partials/_header.scss index 778d30fc6..4bd996894 100644 --- a/app/scss/partials/_header.scss +++ b/app/scss/partials/_header.scss @@ -74,7 +74,7 @@ @extend %pointer; display: block; } - .gold-subscriber-badge { + .subscriber-badge { @extend .base-badge; margin-top: 4px; } From 2d2aa909a366d7d10f786cbf081bf1503ac9effe Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 11 May 2020 09:50:25 -0400 Subject: [PATCH 11/34] Fix account#getUserSubscriptionData behavior --- src/background.js | 14 +++++++++++++- src/classes/Account.js | 3 --- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/background.js b/src/background.js index f5e9e21ca..388cc3dd4 100644 --- a/src/background.js +++ b/src/background.js @@ -824,7 +824,19 @@ function onMessageHandler(request, sender, callback) { if (name === 'account.getUserSubscriptionData') { account.getUserSubscriptionData() .then((customer) => { - callback({ subscriptionData: customer }); + // TODO temporary fix to handle multiple subscriptions + let sub = customer.subscriptions; + if (!Array.isArray(sub)) { + sub = [sub]; + } + + let subscriptionData = sub.find(subscription => subscription.productName.includes('Ghostery Premium')); + if (subscriptionData) { + callback({ subscriptionData }); + } + + subscriptionData = sub.find(subscription => subscription.productName.includes('Ghostery Plus')); + callback({ subscriptionData }); }) .catch((err) => { log('Error getting user subscription data:', err); diff --git a/src/classes/Account.js b/src/classes/Account.js index 57ab030c6..930e3fc22 100644 --- a/src/classes/Account.js +++ b/src/classes/Account.js @@ -174,15 +174,12 @@ class Account { const premiumSubscription = sub.find(subscription => subscription.productName.includes('Ghostery Premium')); if (premiumSubscription) { this._setSubscriptionData(premiumSubscription); - return premiumSubscription; } const plusSubscription = sub.find(subscription => subscription.productName.includes('Ghostery Plus')); if (plusSubscription) { this._setSubscriptionData(plusSubscription); - return plusSubscription; } - return customer; }) ) From 9383ab6e411b1d40ea516d5cb72e5c280f64e1a2 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 11 May 2020 11:24:01 -0400 Subject: [PATCH 12/34] Add subscriptionsPremium property to user object to check if a user has a premium subscription --- app/hub/Views/HomeView/HomeViewContainer.jsx | 14 ++------------ app/panel/components/Header.jsx | 4 ++-- app/panel/components/Panel.jsx | 2 +- app/panel/components/Summary.jsx | 2 +- src/background.js | 1 + src/classes/PanelData.js | 1 + 6 files changed, 8 insertions(+), 16 deletions(-) diff --git a/app/hub/Views/HomeView/HomeViewContainer.jsx b/app/hub/Views/HomeView/HomeViewContainer.jsx index c98e55b78..7d230c3dd 100644 --- a/app/hub/Views/HomeView/HomeViewContainer.jsx +++ b/app/hub/Views/HomeView/HomeViewContainer.jsx @@ -103,21 +103,11 @@ class HomeViewContainer extends Component { */ _handleTryMidnightClick = () => { this._handlePremiumPromoModalClick('premium'); } - /** - * @returns {bool} - * @private - * Is the user a Premium subscriber? - */ - _premiumSubscriber = () => { - const { loggedIn, user } = this.props; - - return loggedIn && (user && user.scopes && user.scopes.includes('subscriptions:premium')); - } - _render() { const { justInstalled } = this.state; const { home, user } = this.props; const isPlus = user && user.subscriptionsPlus || false; + const isPremium = user && user.subscriptionsPremium || false; const { premium_promo_modal_shown, setup_complete, @@ -134,7 +124,7 @@ class HomeViewContainer extends Component { isPlus, }; - const showPromoModal = !premium_promo_modal_shown && !this._premiumSubscriber(); + const showPromoModal = !premium_promo_modal_shown && !isPremium; return (
    diff --git a/app/panel/components/Header.jsx b/app/panel/components/Header.jsx index aaf4902b0..3321fa75a 100644 --- a/app/panel/components/Header.jsx +++ b/app/panel/components/Header.jsx @@ -150,7 +150,7 @@ class Header extends React.Component { sendMessage('ping', 'plus_panel_from_badge'); const { user } = this.props; const plusSubscriber = user && user.subscriptionsPlus; - const premiumSubscriber = user && user.scopes && user.scopes.includes('subscriptions:premium'); + const premiumSubscriber = user && user.subscriptionsPremium; this.props.history.push(plusSubscriber || premiumSubscriber ? '/subscription/info' : `/subscribe/${!!user}`); } @@ -178,7 +178,7 @@ class Header extends React.Component { active: is_expert, }); const plusSubscriber = user && user.subscriptionsPlus; - const premiumSubscriber = user && user.scopes && user.scopes.includes('subscriptions:premium'); + const premiumSubscriber = user && user.subscriptionsPremium; const accountLogolink = this.generateAccountLogo(); const badgeClasses = ClassNames('columns', 'shrink', { 'non-subscriber-badge': !(plusSubscriber || premiumSubscriber), diff --git a/app/panel/components/Panel.jsx b/app/panel/components/Panel.jsx index 77055f519..83fe74849 100644 --- a/app/panel/components/Panel.jsx +++ b/app/panel/components/Panel.jsx @@ -217,7 +217,7 @@ class Panel extends React.Component { _premiumSubscriber = () => { const { loggedIn, user } = this.props; - return loggedIn && (user && user.scopes && user.scopes.includes('subscriptions:premium')); + return loggedIn && (user && user.subscriptionsPremium); } /** diff --git a/app/panel/components/Summary.jsx b/app/panel/components/Summary.jsx index 9b46c0c5f..5720f83cf 100644 --- a/app/panel/components/Summary.jsx +++ b/app/panel/components/Summary.jsx @@ -314,7 +314,7 @@ class Summary extends React.Component { _isPremiumSubscriber() { const { user } = this.props; - return user && user.scopes && user.scopes.includes('subscriptions:premium'); + return user && user.subscriptionsPremium; } _pageHost() { diff --git a/src/background.js b/src/background.js index 388cc3dd4..6596ab53c 100644 --- a/src/background.js +++ b/src/background.js @@ -881,6 +881,7 @@ function onMessageHandler(request, sender, callback) { .then((user) => { if (user) { user.subscriptionsPlus = account.hasScopesUnverified(['subscriptions:plus']); + user.subscriptionsPremium = account.hasScopesUnverified(['subscriptions:premium']); } callback({ user }); }) diff --git a/src/classes/PanelData.js b/src/classes/PanelData.js index 281433511..ce64f454c 100644 --- a/src/classes/PanelData.js +++ b/src/classes/PanelData.js @@ -265,6 +265,7 @@ class PanelData { const currentAccount = conf.account; if (currentAccount && currentAccount.user) { currentAccount.user.subscriptionsPlus = account.hasScopesUnverified(['subscriptions:plus']); + currentAccount.user.subscriptionsPremium = account.hasScopesUnverified(['subscriptions:premium']); } return currentAccount; } From f7b36a9896645b4d1e702a5de35b9ed4c7d6a7d2 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 11 May 2020 12:03:10 -0400 Subject: [PATCH 13/34] Refactor Header component to use subscriptionsPremium property --- app/panel/components/Header.jsx | 9 ++------- app/panel/components/HeaderMenu.jsx | 27 ++++++++++++++++++--------- app/scss/partials/_header.scss | 6 +++--- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/app/panel/components/Header.jsx b/app/panel/components/Header.jsx index 3321fa75a..f7b84aa58 100644 --- a/app/panel/components/Header.jsx +++ b/app/panel/components/Header.jsx @@ -237,16 +237,11 @@ class Header extends React.Component {
    ); - let subscriberType; - if (premiumSubscriber) { - subscriberType = 'premium'; - } else if (plusSubscriber) { - subscriberType = 'plus'; - } const headerMenu = ( { + const { subscriptionsPlus, subscriptionsPremium } = this.props; sendMessage('ping', 'plus_panel_from_menu'); this.props.toggleDropdown(); - this.props.history.push(this.props.subscriberType ? '/subscription/info' : `/subscribe/${this.props.loggedIn}`); + this.props.history.push(subscriptionsPremium || subscriptionsPlus ? '/subscription/info' : `/subscribe/${this.props.loggedIn}`); } /** @@ -162,12 +163,20 @@ class HeaderMenu extends React.Component { * @return {ReactComponent} ReactComponent instance */ render() { - const { loggedIn, email, subscriberType } = this.props; - const optionClasses = ClassNames({ 'menu-option': this.props.subscriberType, 'menu-option-non-subscriber': !this.props.subscriberType }); + const { + loggedIn, + email, + subscriptionsPremium, + subscriptionsPlus + } = this.props; + const optionClasses = ClassNames({ + 'menu-option': subscriptionsPremium || subscriptionsPlus, + 'menu-option-non-subscriber': !subscriptionsPremium || !subscriptionsPlus + }); const iconClasses = ClassNames('menu-icon-container', { - premiumSubscriber: subscriberType === 'premium', - plusSubscriber: subscriberType === 'plus', - 'non-subscriber': !subscriberType + subscriptionsPremium, + subscriptionsPlus: subscriptionsPlus && !subscriptionsPremium, + 'non-subscriber': !subscriptionsPremium && !subscriptionsPlus }); return ( @@ -235,7 +244,7 @@ class HeaderMenu extends React.Component {
  • {/* Upselling plus for all users who are not premium subscribers */} - {subscriberType !== 'premium' && ( + {!subscriptionsPremium && ( @@ -243,7 +252,7 @@ class HeaderMenu extends React.Component { )} - {subscriberType === 'premium' && ( + {subscriptionsPremium && ( @@ -254,7 +263,7 @@ class HeaderMenu extends React.Component { )} - {subscriberType === 'premium' ? t('panel_detail_premium_title') : t('ghostery_plus')} + {subscriptionsPremium ? t('panel_detail_premium_title') : t('ghostery_plus')}
  • diff --git a/app/scss/partials/_header.scss b/app/scss/partials/_header.scss index 4bd996894..2eaaad57b 100644 --- a/app/scss/partials/_header.scss +++ b/app/scss/partials/_header.scss @@ -148,13 +148,13 @@ .menu-option { @extend .menu-option-base; - .plusSubscriber { + .subscriptionsPlus { width: 18px; height: 16px; path {fill: $light-gray;} path.text {fill: #4a4a4a;} } - .premiumSubscriber { + .subscriptionsPremium { margin-left: -4px; g > g { fill: #DEDEDE; @@ -171,7 +171,7 @@ path {stroke: $ghosty-blue;} path.text {fill: $ghosty-blue;} } - .premiumSubscriber > g > g { + .subscriptionsPremium > g > g { fill: $ghosty-blue; } } From f545e7bc07d5957452501897cc633748561e12f7 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 11 May 2020 12:09:15 -0400 Subject: [PATCH 14/34] Add newline --- app/panel/components/Summary.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/app/panel/components/Summary.jsx b/app/panel/components/Summary.jsx index 5720f83cf..a5cefea1c 100644 --- a/app/panel/components/Summary.jsx +++ b/app/panel/components/Summary.jsx @@ -314,6 +314,7 @@ class Summary extends React.Component { _isPremiumSubscriber() { const { user } = this.props; + return user && user.subscriptionsPremium; } From 2fcc8627bc7cce5fbddc1ae8696220518ef638f0 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 11 May 2020 12:18:37 -0400 Subject: [PATCH 15/34] Refactor svg template literal --- app/panel/components/Summary.jsx | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/app/panel/components/Summary.jsx b/app/panel/components/Summary.jsx index a5cefea1c..0d7313164 100644 --- a/app/panel/components/Summary.jsx +++ b/app/panel/components/Summary.jsx @@ -760,19 +760,21 @@ class Summary extends React.Component { 'UpgradeBanner--normal': !is_expert, 'UpgradeBanner--small': is_expert, }); - let subscriberType; - if (isPremiumSubscriber) { - subscriberType = 'premium'; - } else if (isPlusSubscriber) { - subscriberType = 'plus'; - } return (
    - {(isPremiumSubscriber || isPlusSubscriber) && ( + {(isPremiumSubscriber) && ( +
    +
    + +
    +
    + )} + + {(!isPremiumSubscriber && isPlusSubscriber) && (
    - +
    )} From ef91547d7bb8c1d362a365750488856f92d8c47a Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 11 May 2020 22:56:32 -0400 Subject: [PATCH 16/34] Refactor account#getUserSubscriptionData to return an array of subscriptions, and the background handler to return the highest tier subscription --- app/panel/components/HeaderMenu.jsx | 2 +- src/background.js | 19 +++++++------------ src/classes/Account.js | 10 ++++++++-- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/app/panel/components/HeaderMenu.jsx b/app/panel/components/HeaderMenu.jsx index e5f4fce96..e030d59af 100644 --- a/app/panel/components/HeaderMenu.jsx +++ b/app/panel/components/HeaderMenu.jsx @@ -243,7 +243,7 @@ class HeaderMenu extends React.Component {
  • - {/* Upselling plus for all users who are not premium subscribers */} + {/* Show premium icon to premium users and plus icon to basic and plus users */} {!subscriptionsPremium && ( diff --git a/src/background.js b/src/background.js index 6596ab53c..dbf5b7445 100644 --- a/src/background.js +++ b/src/background.js @@ -823,20 +823,15 @@ function onMessageHandler(request, sender, callback) { } if (name === 'account.getUserSubscriptionData') { account.getUserSubscriptionData() - .then((customer) => { - // TODO temporary fix to handle multiple subscriptions - let sub = customer.subscriptions; - if (!Array.isArray(sub)) { - sub = [sub]; - } + .then((subscriptions) => { + // Return highest tier subscription from array + const premiumSubscription = subscriptions.find(subscription => subscription.productName.includes('Ghostery Premium')); + if (premiumSubscription) callback({ premiumSubscription }); - let subscriptionData = sub.find(subscription => subscription.productName.includes('Ghostery Premium')); - if (subscriptionData) { - callback({ subscriptionData }); - } + const plusSubscription = subscriptions.find(subscription => subscription.productName.includes('Ghostery Plus')); + if (plusSubscription) callback({ plusSubscription }); - subscriptionData = sub.find(subscription => subscription.productName.includes('Ghostery Plus')); - callback({ subscriptionData }); + callback({}); }) .catch((err) => { log('Error getting user subscription data:', err); diff --git a/src/classes/Account.js b/src/classes/Account.js index 930e3fc22..357fb00ab 100644 --- a/src/classes/Account.js +++ b/src/classes/Account.js @@ -158,6 +158,9 @@ class Account { }) ) + /** + * @return {array} All subscriptions the user has, empty if none + */ getUserSubscriptionData = () => ( this._getUserID() .then(userID => api.get('stripe/customers', userID, 'cards,subscriptions')) @@ -170,17 +173,20 @@ class Account { sub = [sub]; } - // Display premium info if user has both premium and plus subscriptions + const subscriptions = []; + const premiumSubscription = sub.find(subscription => subscription.productName.includes('Ghostery Premium')); if (premiumSubscription) { this._setSubscriptionData(premiumSubscription); + subscriptions.push(premiumSubscription); } const plusSubscription = sub.find(subscription => subscription.productName.includes('Ghostery Plus')); if (plusSubscription) { + subscriptions.push(plusSubscription); this._setSubscriptionData(plusSubscription); } - return customer; + return subscriptions; }) ) From 4fc3f53a392d9d3e049c20b2050468c66e34842f Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 12 May 2020 09:38:32 -0400 Subject: [PATCH 17/34] Pass object that allows destructuring of subscriptionData --- src/background.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/background.js b/src/background.js index dbf5b7445..b77846ab7 100644 --- a/src/background.js +++ b/src/background.js @@ -826,10 +826,10 @@ function onMessageHandler(request, sender, callback) { .then((subscriptions) => { // Return highest tier subscription from array const premiumSubscription = subscriptions.find(subscription => subscription.productName.includes('Ghostery Premium')); - if (premiumSubscription) callback({ premiumSubscription }); + if (premiumSubscription) callback({ subscriptionData: premiumSubscription }); const plusSubscription = subscriptions.find(subscription => subscription.productName.includes('Ghostery Plus')); - if (plusSubscription) callback({ plusSubscription }); + if (plusSubscription) callback({ subscriptionData: plusSubscription }); callback({}); }) From 2a9ffcbba5a30310a0f31a53ea558bd6eabaf006 Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 12 May 2020 12:04:36 -0400 Subject: [PATCH 18/34] Add return statement after callbacks --- src/background.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/background.js b/src/background.js index b77846ab7..8747acaa7 100644 --- a/src/background.js +++ b/src/background.js @@ -826,10 +826,16 @@ function onMessageHandler(request, sender, callback) { .then((subscriptions) => { // Return highest tier subscription from array const premiumSubscription = subscriptions.find(subscription => subscription.productName.includes('Ghostery Premium')); - if (premiumSubscription) callback({ subscriptionData: premiumSubscription }); + if (premiumSubscription) { + callback({ subscriptionData: premiumSubscription }); + return; + } const plusSubscription = subscriptions.find(subscription => subscription.productName.includes('Ghostery Plus')); - if (plusSubscription) callback({ subscriptionData: plusSubscription }); + if (plusSubscription) { + callback({ subscriptionData: plusSubscription }); + return; + } callback({}); }) From f120d4d1ab35bdfab5816826215a459278638fa3 Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 12 May 2020 12:10:33 -0400 Subject: [PATCH 19/34] Add guard to account#_setSubscriptionData to prevent overriding premium subscription --- src/classes/Account.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/classes/Account.js b/src/classes/Account.js index 357fb00ab..d3ffda0a3 100644 --- a/src/classes/Account.js +++ b/src/classes/Account.js @@ -184,7 +184,9 @@ class Account { const plusSubscription = sub.find(subscription => subscription.productName.includes('Ghostery Plus')); if (plusSubscription) { subscriptions.push(plusSubscription); - this._setSubscriptionData(plusSubscription); + if (!premiumSubscription) { + this._setSubscriptionData(plusSubscription); + } } return subscriptions; }) From 7fe5a2408e43d7f00fd3e72c64094d3758f47442 Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 12 May 2020 13:41:02 -0400 Subject: [PATCH 20/34] Give user subscriptionsPlus bool if they have either plus or premium scope --- src/background.js | 3 ++- src/classes/PanelData.js | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/background.js b/src/background.js index 8747acaa7..366c2480f 100644 --- a/src/background.js +++ b/src/background.js @@ -881,7 +881,8 @@ function onMessageHandler(request, sender, callback) { account.getUser(message) .then((user) => { if (user) { - user.subscriptionsPlus = account.hasScopesUnverified(['subscriptions:plus']); + user.subscriptionsPlus = account.hasScopesUnverified(['subscriptions:plus']) + || account.hasScopesUnverified(['subscriptions:premium']); user.subscriptionsPremium = account.hasScopesUnverified(['subscriptions:premium']); } callback({ user }); diff --git a/src/classes/PanelData.js b/src/classes/PanelData.js index ce64f454c..c671bbc4b 100644 --- a/src/classes/PanelData.js +++ b/src/classes/PanelData.js @@ -264,7 +264,8 @@ class PanelData { _getCurrentAccount() { const currentAccount = conf.account; if (currentAccount && currentAccount.user) { - currentAccount.user.subscriptionsPlus = account.hasScopesUnverified(['subscriptions:plus']); + currentAccount.user.subscriptionsPlus = account.hasScopesUnverified(['subscriptions:plus']) + || account.hasScopesUnverified(['subscriptions:premium']); currentAccount.user.subscriptionsPremium = account.hasScopesUnverified(['subscriptions:premium']); } return currentAccount; From 33c506a2a7b2014bd18e07460ff056dad5f55fb1 Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 12 May 2020 13:45:36 -0400 Subject: [PATCH 21/34] Rename subscriptionsPlus and subscriptionsPremium to plusAccess and premiumAccess --- app/hub/Views/HomeView/HomeViewContainer.jsx | 8 +++---- app/hub/Views/PlusView/PlusViewContainer.jsx | 6 ++--- app/panel/components/Detail.jsx | 2 +- app/panel/components/Header.jsx | 12 +++++----- app/panel/components/HeaderMenu.jsx | 24 ++++++++++---------- app/panel/components/Panel.jsx | 4 ++-- app/panel/components/Stats.jsx | 6 ++--- app/panel/components/Summary.jsx | 4 ++-- app/scss/partials/_header.scss | 6 ++--- src/background.js | 4 ++-- src/classes/PanelData.js | 4 ++-- 11 files changed, 40 insertions(+), 40 deletions(-) diff --git a/app/hub/Views/HomeView/HomeViewContainer.jsx b/app/hub/Views/HomeView/HomeViewContainer.jsx index 7d230c3dd..81caf36c6 100644 --- a/app/hub/Views/HomeView/HomeViewContainer.jsx +++ b/app/hub/Views/HomeView/HomeViewContainer.jsx @@ -106,8 +106,8 @@ class HomeViewContainer extends Component { _render() { const { justInstalled } = this.state; const { home, user } = this.props; - const isPlus = user && user.subscriptionsPlus || false; - const isPremium = user && user.subscriptionsPremium || false; + const isPlus = user && user.plusAccess || false; + const isPremium = user && user.premiumAccess || false; const { premium_promo_modal_shown, setup_complete, @@ -164,7 +164,7 @@ HomeViewContainer.propTypes = { }), user: PropTypes.shape({ email: PropTypes.string, - subscriptionsPlus: PropTypes.bool, + plusAccess: PropTypes.bool, }), actions: PropTypes.shape({ getHomeProps: PropTypes.func.isRequired, @@ -184,7 +184,7 @@ HomeViewContainer.defaultProps = { }, user: { email: '', - subscriptionsPlus: false, + plusAccess: false, }, }; diff --git a/app/hub/Views/PlusView/PlusViewContainer.jsx b/app/hub/Views/PlusView/PlusViewContainer.jsx index 5d8332ddc..668d0b842 100644 --- a/app/hub/Views/PlusView/PlusViewContainer.jsx +++ b/app/hub/Views/PlusView/PlusViewContainer.jsx @@ -44,7 +44,7 @@ class PlusViewContainer extends Component { */ render() { const childProps = { - isPlus: this.props.user && this.props.user.subscriptionsPlus || false, + isPlus: this.props.user && this.props.user.plusAccess || false, onPlusClick: this._sendPlusPing, }; @@ -56,7 +56,7 @@ class PlusViewContainer extends Component { PlusViewContainer.propTypes = { user: PropTypes.shape({ email: PropTypes.string, - subscriptionsPlus: PropTypes.bool, + plusAccess: PropTypes.bool, }), actions: PropTypes.shape({ sendPing: PropTypes.func.isRequired, @@ -68,7 +68,7 @@ PlusViewContainer.propTypes = { PlusViewContainer.defaultProps = { user: { email: false, - subscriptionsPlus: false, + plusAccess: false, }, }; diff --git a/app/panel/components/Detail.jsx b/app/panel/components/Detail.jsx index dfb9bf494..8dc0838fd 100644 --- a/app/panel/components/Detail.jsx +++ b/app/panel/components/Detail.jsx @@ -80,7 +80,7 @@ class Detail extends React.Component {
    diff --git a/app/panel/components/Header.jsx b/app/panel/components/Header.jsx index f7b84aa58..782bb83cf 100644 --- a/app/panel/components/Header.jsx +++ b/app/panel/components/Header.jsx @@ -149,8 +149,8 @@ class Header extends React.Component { // TODO check whether this is the message we want to be sending now sendMessage('ping', 'plus_panel_from_badge'); const { user } = this.props; - const plusSubscriber = user && user.subscriptionsPlus; - const premiumSubscriber = user && user.subscriptionsPremium; + const plusSubscriber = user && user.plusAccess; + const premiumSubscriber = user && user.premiumAccess; this.props.history.push(plusSubscriber || premiumSubscriber ? '/subscription/info' : `/subscribe/${!!user}`); } @@ -177,8 +177,8 @@ class Header extends React.Component { const tabDetailedClassNames = ClassNames('header-tab', { active: is_expert, }); - const plusSubscriber = user && user.subscriptionsPlus; - const premiumSubscriber = user && user.subscriptionsPremium; + const plusSubscriber = user && user.plusAccess; + const premiumSubscriber = user && user.premiumAccess; const accountLogolink = this.generateAccountLogo(); const badgeClasses = ClassNames('columns', 'shrink', { 'non-subscriber-badge': !(plusSubscriber || premiumSubscriber), @@ -240,8 +240,8 @@ class Header extends React.Component { const headerMenu = ( { - const { subscriptionsPlus, subscriptionsPremium } = this.props; + const { plusAccess, premiumAccess } = this.props; sendMessage('ping', 'plus_panel_from_menu'); this.props.toggleDropdown(); - this.props.history.push(subscriptionsPremium || subscriptionsPlus ? '/subscription/info' : `/subscribe/${this.props.loggedIn}`); + this.props.history.push(premiumAccess || plusAccess ? '/subscription/info' : `/subscribe/${this.props.loggedIn}`); } /** @@ -166,17 +166,17 @@ class HeaderMenu extends React.Component { const { loggedIn, email, - subscriptionsPremium, - subscriptionsPlus + premiumAccess, + plusAccess } = this.props; const optionClasses = ClassNames({ - 'menu-option': subscriptionsPremium || subscriptionsPlus, - 'menu-option-non-subscriber': !subscriptionsPremium || !subscriptionsPlus + 'menu-option': premiumAccess || plusAccess, + 'menu-option-non-subscriber': !premiumAccess || !plusAccess }); const iconClasses = ClassNames('menu-icon-container', { - subscriptionsPremium, - subscriptionsPlus: subscriptionsPlus && !subscriptionsPremium, - 'non-subscriber': !subscriptionsPremium && !subscriptionsPlus + premiumAccess, + plusAccess: plusAccess && !premiumAccess, + 'non-subscriber': !premiumAccess && !plusAccess }); return ( @@ -244,7 +244,7 @@ class HeaderMenu extends React.Component {
  • {/* Show premium icon to premium users and plus icon to basic and plus users */} - {!subscriptionsPremium && ( + {!premiumAccess && ( @@ -252,7 +252,7 @@ class HeaderMenu extends React.Component { )} - {subscriptionsPremium && ( + {premiumAccess && ( @@ -263,7 +263,7 @@ class HeaderMenu extends React.Component { )} - {subscriptionsPremium ? t('panel_detail_premium_title') : t('ghostery_plus')} + {premiumAccess ? t('panel_detail_premium_title') : t('ghostery_plus')}
  • diff --git a/app/panel/components/Panel.jsx b/app/panel/components/Panel.jsx index 83fe74849..4e78a5ed6 100644 --- a/app/panel/components/Panel.jsx +++ b/app/panel/components/Panel.jsx @@ -217,7 +217,7 @@ class Panel extends React.Component { _premiumSubscriber = () => { const { loggedIn, user } = this.props; - return loggedIn && (user && user.subscriptionsPremium); + return loggedIn && (user && user.premiumAccess); } /** @@ -228,7 +228,7 @@ class Panel extends React.Component { _plusSubscriber = () => { const { loggedIn, user } = this.props; - return loggedIn && (user && user.subscriptionsPlus); + return loggedIn && (user && user.plusAccess); } /** diff --git a/app/panel/components/Stats.jsx b/app/panel/components/Stats.jsx index 8ec7ac7c7..bcd096597 100644 --- a/app/panel/components/Stats.jsx +++ b/app/panel/components/Stats.jsx @@ -329,7 +329,7 @@ class Stats extends React.Component { monthlyAverageData: clearData, dailyAverageData: clearData, showResetModal: false, - showPitchModal: (!this.props.user || !this.props.user.subscriptionsPlus), + showPitchModal: (!this.props.user || !this.props.user.plusAccess), }; return clearOrDemoState; } @@ -517,7 +517,7 @@ class Stats extends React.Component { return selectionData; } - _isPlus = props => props.user && props.user.subscriptionsPlus; + _isPlus = props => props.user && props.user.plusAccess; /** * Render the the Stats View @@ -529,7 +529,7 @@ class Stats extends React.Component { return ( g { fill: #DEDEDE; @@ -171,7 +171,7 @@ path {stroke: $ghosty-blue;} path.text {fill: $ghosty-blue;} } - .subscriptionsPremium > g > g { + .premiumAccess > g > g { fill: $ghosty-blue; } } diff --git a/src/background.js b/src/background.js index 366c2480f..d7fe9ef53 100644 --- a/src/background.js +++ b/src/background.js @@ -881,9 +881,9 @@ function onMessageHandler(request, sender, callback) { account.getUser(message) .then((user) => { if (user) { - user.subscriptionsPlus = account.hasScopesUnverified(['subscriptions:plus']) + user.plusAccess = account.hasScopesUnverified(['subscriptions:plus']) || account.hasScopesUnverified(['subscriptions:premium']); - user.subscriptionsPremium = account.hasScopesUnverified(['subscriptions:premium']); + user.premiumAccess = account.hasScopesUnverified(['subscriptions:premium']); } callback({ user }); }) diff --git a/src/classes/PanelData.js b/src/classes/PanelData.js index c671bbc4b..3a99b8b5e 100644 --- a/src/classes/PanelData.js +++ b/src/classes/PanelData.js @@ -264,9 +264,9 @@ class PanelData { _getCurrentAccount() { const currentAccount = conf.account; if (currentAccount && currentAccount.user) { - currentAccount.user.subscriptionsPlus = account.hasScopesUnverified(['subscriptions:plus']) + currentAccount.user.plusAccess = account.hasScopesUnverified(['subscriptions:plus']) || account.hasScopesUnverified(['subscriptions:premium']); - currentAccount.user.subscriptionsPremium = account.hasScopesUnverified(['subscriptions:premium']); + currentAccount.user.premiumAccess = account.hasScopesUnverified(['subscriptions:premium']); } return currentAccount; } From 0586ff56e469cff0391ec3f7ad841e0014c519e9 Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 12 May 2020 15:08:52 -0400 Subject: [PATCH 22/34] Set subscription property on user object with highest tier subscription in account#getUserSubscriptionData --- src/classes/Account.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/classes/Account.js b/src/classes/Account.js index d3ffda0a3..4548f728a 100644 --- a/src/classes/Account.js +++ b/src/classes/Account.js @@ -177,8 +177,8 @@ class Account { const premiumSubscription = sub.find(subscription => subscription.productName.includes('Ghostery Premium')); if (premiumSubscription) { - this._setSubscriptionData(premiumSubscription); subscriptions.push(premiumSubscription); + this._setSubscriptionData(premiumSubscription); } const plusSubscription = sub.find(subscription => subscription.productName.includes('Ghostery Plus')); @@ -188,6 +188,7 @@ class Account { this._setSubscriptionData(plusSubscription); } } + return subscriptions; }) ) @@ -488,12 +489,22 @@ class Account { } _setSubscriptionData = (data) => { + const currentAccount = conf.account; + // TODO: Change this so that we aren't writing over data if (!conf.paid_subscription && data) { conf.paid_subscription = true; dispatcher.trigger('conf.save.paid_subscription'); } - conf.account.subscriptionData = data || null; + currentAccount.subscriptionData = data || null; + + if (data.productName.includes('Ghostery Premium')) { + currentAccount.user.subscription = 'premium'; + } else if (data.productName.includes('Ghostery Plus')) { + currentAccount.user.subscription = 'plus'; + } else { + currentAccount.user.subscription = ''; + } dispatcher.trigger('conf.save.account'); } From a77797c019be34bcab87c87a62ff61f7b5f2799a Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 12 May 2020 16:04:49 -0400 Subject: [PATCH 23/34] Refactor menu upsell icon to use user.subscriber instead of plusAccess/premiumAccess --- app/panel/components/Header.jsx | 5 +++-- app/panel/components/HeaderMenu.jsx | 19 +++++++++---------- app/scss/partials/_header.scss | 6 +++--- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/app/panel/components/Header.jsx b/app/panel/components/Header.jsx index 782bb83cf..0871aec54 100644 --- a/app/panel/components/Header.jsx +++ b/app/panel/components/Header.jsx @@ -177,8 +177,8 @@ class Header extends React.Component { const tabDetailedClassNames = ClassNames('header-tab', { active: is_expert, }); - const plusSubscriber = user && user.plusAccess; - const premiumSubscriber = user && user.premiumAccess; + const plusSubscriber = user && user.subscription === 'plus'; + const premiumSubscriber = user && user.subscription === 'premium'; const accountLogolink = this.generateAccountLogo(); const badgeClasses = ClassNames('columns', 'shrink', { 'non-subscriber-badge': !(plusSubscriber || premiumSubscriber), @@ -240,6 +240,7 @@ class Header extends React.Component { const headerMenu = ( @@ -244,7 +243,7 @@ class HeaderMenu extends React.Component {
  • {/* Show premium icon to premium users and plus icon to basic and plus users */} - {!premiumAccess && ( + {subscriber !== 'premium' && ( @@ -252,7 +251,7 @@ class HeaderMenu extends React.Component { )} - {premiumAccess && ( + {subscriber === 'premium' && ( @@ -263,7 +262,7 @@ class HeaderMenu extends React.Component { )} - {premiumAccess ? t('panel_detail_premium_title') : t('ghostery_plus')} + {subscriber === 'premium' ? t('panel_detail_premium_title') : t('ghostery_plus')}
  • diff --git a/app/scss/partials/_header.scss b/app/scss/partials/_header.scss index 9775f5d57..0a49a6a55 100644 --- a/app/scss/partials/_header.scss +++ b/app/scss/partials/_header.scss @@ -148,13 +148,13 @@ .menu-option { @extend .menu-option-base; - .plusAccess { + .plus { width: 18px; height: 16px; path {fill: $light-gray;} path.text {fill: #4a4a4a;} } - .premiumAccess { + .premium { margin-left: -4px; g > g { fill: #DEDEDE; @@ -171,7 +171,7 @@ path {stroke: $ghosty-blue;} path.text {fill: $ghosty-blue;} } - .premiumAccess > g > g { + .premium > g > g { fill: $ghosty-blue; } } From 181676405f437840dab3dda1b66f19b9a8ecb377 Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 12 May 2020 18:50:28 -0400 Subject: [PATCH 24/34] test --- src/background.js | 8 +++++++- src/classes/Account.js | 22 ++++++++++++++++------ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/background.js b/src/background.js index d7fe9ef53..beacd61aa 100644 --- a/src/background.js +++ b/src/background.js @@ -882,9 +882,15 @@ function onMessageHandler(request, sender, callback) { .then((user) => { if (user) { user.plusAccess = account.hasScopesUnverified(['subscriptions:plus']) - || account.hasScopesUnverified(['subscriptions:premium']); + || account.hasScopesUnverified(['subscriptions:premium']); user.premiumAccess = account.hasScopesUnverified(['subscriptions:premium']); + + // const currentAccount = conf.account; + // if (currentAccount.user) { + // user.subscription = currentAccount.user.subscription; + // } } + console.log('the user is: ', user); callback({ user }); }) .catch((err) => { diff --git a/src/classes/Account.js b/src/classes/Account.js index 4548f728a..e981db874 100644 --- a/src/classes/Account.js +++ b/src/classes/Account.js @@ -140,6 +140,12 @@ class Account { .then(userID => api.get('users', userID)) .then((res) => { const user = build(normalize(res), 'users', res.data.id); + const currentAccount = conf.account; + console.log('currentAccount.user: ', currentAccount.user); + if (currentAccount.user) { + user.subscription = currentAccount.user.subscription; + } + console.log('user: ', user); this._setAccountUserInfo(user); return user; }) @@ -498,13 +504,17 @@ class Account { } currentAccount.subscriptionData = data || null; - if (data.productName.includes('Ghostery Premium')) { - currentAccount.user.subscription = 'premium'; - } else if (data.productName.includes('Ghostery Plus')) { - currentAccount.user.subscription = 'plus'; - } else { - currentAccount.user.subscription = ''; + if (currentAccount.user) { + console.log('here'); + if (data.productName.includes('Ghostery Premium')) { + currentAccount.subscription = 'premium'; + } else if (data.productName.includes('Ghostery Plus')) { + currentAccount.subscription = 'plus'; + } else { + currentAccount.subscription = ''; + } } + console.log(currentAccount.user); dispatcher.trigger('conf.save.account'); } From 0847e49576d42ec6b36a417c8b716d9116393008 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 13 May 2020 07:54:51 -0400 Subject: [PATCH 25/34] Refactor Header logo and menu icon to use subscription instead of premiumAccess and plusAccess --- app/panel/components/Header.jsx | 22 +++++++++++----------- app/panel/components/HeaderMenu.jsx | 4 ++-- src/background.js | 6 ------ src/classes/Account.js | 8 -------- 4 files changed, 13 insertions(+), 27 deletions(-) diff --git a/app/panel/components/Header.jsx b/app/panel/components/Header.jsx index 0871aec54..1c2ffb354 100644 --- a/app/panel/components/Header.jsx +++ b/app/panel/components/Header.jsx @@ -149,9 +149,9 @@ class Header extends React.Component { // TODO check whether this is the message we want to be sending now sendMessage('ping', 'plus_panel_from_badge'); const { user } = this.props; - const plusSubscriber = user && user.plusAccess; - const premiumSubscriber = user && user.premiumAccess; - this.props.history.push(plusSubscriber || premiumSubscriber ? '/subscription/info' : `/subscribe/${!!user}`); + const hasPlusAccess = user && user.plusAccess; + const hasPremiumAccess = user && user.premiumAccess; + this.props.history.push(hasPlusAccess || hasPremiumAccess ? '/subscription/info' : `/subscribe/${!!user}`); } /** @@ -177,12 +177,12 @@ class Header extends React.Component { const tabDetailedClassNames = ClassNames('header-tab', { active: is_expert, }); - const plusSubscriber = user && user.subscription === 'plus'; - const premiumSubscriber = user && user.subscription === 'premium'; + const hasPlusAccess = user && user.subscription === 'plus'; + const hasPremiumAccess = user && user.subscription === 'premium'; const accountLogolink = this.generateAccountLogo(); const badgeClasses = ClassNames('columns', 'shrink', { - 'non-subscriber-badge': !(plusSubscriber || premiumSubscriber), - 'subscriber-badge': plusSubscriber || premiumSubscriber + 'non-subscriber-badge': !(hasPlusAccess || hasPremiumAccess), + 'subscriber-badge': hasPlusAccess || hasPremiumAccess }); const simpleTab = ( @@ -220,8 +220,8 @@ class Header extends React.Component { const plusUpgradeBannerOrSubscriberBadgeLogolink = (
    { - ((premiumSubscriber) && ) - || ((plusSubscriber) && ) + ((hasPremiumAccess) && ) + || ((hasPlusAccess) && ) || }
    @@ -241,8 +241,8 @@ class Header extends React.Component { { - const { plusAccess, premiumAccess } = this.props; + const { hasPlusAccess, hasPremiumAccess } = this.props; sendMessage('ping', 'plus_panel_from_menu'); this.props.toggleDropdown(); - this.props.history.push(premiumAccess || plusAccess ? '/subscription/info' : `/subscribe/${this.props.loggedIn}`); + this.props.history.push(hasPremiumAccess || hasPlusAccess ? '/subscription/info' : `/subscribe/${this.props.loggedIn}`); } /** diff --git a/src/background.js b/src/background.js index beacd61aa..ae5b3a17b 100644 --- a/src/background.js +++ b/src/background.js @@ -884,13 +884,7 @@ function onMessageHandler(request, sender, callback) { user.plusAccess = account.hasScopesUnverified(['subscriptions:plus']) || account.hasScopesUnverified(['subscriptions:premium']); user.premiumAccess = account.hasScopesUnverified(['subscriptions:premium']); - - // const currentAccount = conf.account; - // if (currentAccount.user) { - // user.subscription = currentAccount.user.subscription; - // } } - console.log('the user is: ', user); callback({ user }); }) .catch((err) => { diff --git a/src/classes/Account.js b/src/classes/Account.js index e981db874..0969077b8 100644 --- a/src/classes/Account.js +++ b/src/classes/Account.js @@ -140,12 +140,6 @@ class Account { .then(userID => api.get('users', userID)) .then((res) => { const user = build(normalize(res), 'users', res.data.id); - const currentAccount = conf.account; - console.log('currentAccount.user: ', currentAccount.user); - if (currentAccount.user) { - user.subscription = currentAccount.user.subscription; - } - console.log('user: ', user); this._setAccountUserInfo(user); return user; }) @@ -505,7 +499,6 @@ class Account { currentAccount.subscriptionData = data || null; if (currentAccount.user) { - console.log('here'); if (data.productName.includes('Ghostery Premium')) { currentAccount.subscription = 'premium'; } else if (data.productName.includes('Ghostery Plus')) { @@ -514,7 +507,6 @@ class Account { currentAccount.subscription = ''; } } - console.log(currentAccount.user); dispatcher.trigger('conf.save.account'); } From d25d313b538b8ae3fc1456262ce0705f72796a64 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 13 May 2020 08:08:28 -0400 Subject: [PATCH 26/34] Rename subscriber variable to subscription --- app/panel/components/Header.jsx | 2 +- app/panel/components/HeaderMenu.jsx | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/panel/components/Header.jsx b/app/panel/components/Header.jsx index 1c2ffb354..8299121fe 100644 --- a/app/panel/components/Header.jsx +++ b/app/panel/components/Header.jsx @@ -240,7 +240,7 @@ class Header extends React.Component { const headerMenu = ( @@ -243,7 +243,7 @@ class HeaderMenu extends React.Component {
  • {/* Show premium icon to premium users and plus icon to basic and plus users */} - {subscriber !== 'premium' && ( + {subscription !== 'premium' && ( @@ -251,7 +251,7 @@ class HeaderMenu extends React.Component { )} - {subscriber === 'premium' && ( + {subscription === 'premium' && ( @@ -262,7 +262,7 @@ class HeaderMenu extends React.Component { )} - {subscriber === 'premium' ? t('panel_detail_premium_title') : t('ghostery_plus')} + {subscription === 'premium' ? t('panel_detail_premium_title') : t('ghostery_plus')}
  • From c9ad1de30e94c37f53cd1bcb8efae0e4023151ae Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 13 May 2020 08:50:28 -0400 Subject: [PATCH 27/34] Refactor subscriber badge to use plusAccess and premiumAccess on click, and user.subscription for UI --- app/panel/components/Summary.jsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/panel/components/Summary.jsx b/app/panel/components/Summary.jsx index 6bd44c6b3..cbde11c3b 100644 --- a/app/panel/components/Summary.jsx +++ b/app/panel/components/Summary.jsx @@ -215,7 +215,7 @@ class Summary extends React.Component { clickUpgradeBannerOrGoldPlusIcon() { sendMessage('ping', 'plus_panel_from_badge'); - this.props.history.push(this._isPlusSubscriber() ? '/subscription/info' : `/subscribe/${!!this.props.user}`); + this.props.history.push(this._hasPremiumAccess() || this._hasPlusAccess() ? '/subscription/info' : `/subscribe/${!!this.props.user}`); } /** @@ -306,13 +306,13 @@ class Summary extends React.Component { } } - _isPlusSubscriber() { + _hasPlusAccess() { const { user } = this.props; return user && user.plusAccess; } - _isPremiumSubscriber() { + _hasPremiumAccess() { const { user } = this.props; return user && user.premiumAccess; @@ -752,10 +752,10 @@ class Summary extends React.Component { * @return {JSX} JSX for rendering the plus upgrade banner or subscriber icon */ _renderPlusUpgradeBannerOrSubscriberIcon() { - const { is_expert, current_theme } = this.props; + const { is_expert, current_theme, user } = this.props; - const isPremiumSubscriber = this._isPremiumSubscriber(); - const isPlusSubscriber = this._isPlusSubscriber(); + const isPremiumSubscriber = user.subscription === 'premium'; + const isPlusSubscriber = user.subscription === 'plus'; const upgradeBannerClassNames = ClassNames('UpgradeBanner', { 'UpgradeBanner--normal': !is_expert, 'UpgradeBanner--small': is_expert, @@ -763,7 +763,7 @@ class Summary extends React.Component { return (
    - {(isPremiumSubscriber) && ( + {isPremiumSubscriber && (
    @@ -771,7 +771,7 @@ class Summary extends React.Component {
    )} - {(!isPremiumSubscriber && isPlusSubscriber) && ( + {isPlusSubscriber && (
    From 6398be16b8ce7140c8aaf138ec0b5d711741ba70 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 13 May 2020 09:10:40 -0400 Subject: [PATCH 28/34] Check if user object exists before accessing subscription property --- app/panel/components/Summary.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/panel/components/Summary.jsx b/app/panel/components/Summary.jsx index cbde11c3b..af3dffdcb 100644 --- a/app/panel/components/Summary.jsx +++ b/app/panel/components/Summary.jsx @@ -754,8 +754,8 @@ class Summary extends React.Component { _renderPlusUpgradeBannerOrSubscriberIcon() { const { is_expert, current_theme, user } = this.props; - const isPremiumSubscriber = user.subscription === 'premium'; - const isPlusSubscriber = user.subscription === 'plus'; + const isPremiumSubscriber = (user && user.subscription === 'premium') || false; + const isPlusSubscriber = (user && user.subscription === 'plus') || false; const upgradeBannerClassNames = ClassNames('UpgradeBanner', { 'UpgradeBanner--normal': !is_expert, 'UpgradeBanner--small': is_expert, From eb337bc4e879da9f533b815254a6877591f92f96 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 13 May 2020 11:25:06 -0400 Subject: [PATCH 29/34] Display UI elements basedd off user scope --- app/panel/components/Header.jsx | 5 ++--- app/panel/components/HeaderMenu.jsx | 23 +++++++++++++---------- app/panel/components/Summary.jsx | 10 +++++----- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/app/panel/components/Header.jsx b/app/panel/components/Header.jsx index 8299121fe..4a2ab5fd7 100644 --- a/app/panel/components/Header.jsx +++ b/app/panel/components/Header.jsx @@ -177,8 +177,8 @@ class Header extends React.Component { const tabDetailedClassNames = ClassNames('header-tab', { active: is_expert, }); - const hasPlusAccess = user && user.subscription === 'plus'; - const hasPremiumAccess = user && user.subscription === 'premium'; + const hasPlusAccess = user && user.plusAccess; + const hasPremiumAccess = user && user.premiumAccess; const accountLogolink = this.generateAccountLogo(); const badgeClasses = ClassNames('columns', 'shrink', { 'non-subscriber-badge': !(hasPlusAccess || hasPremiumAccess), @@ -240,7 +240,6 @@ class Header extends React.Component { const headerMenu = ( { - const { hasPlusAccess, hasPremiumAccess } = this.props; + const { user } = this.props; + const { hasPlusAccess, hasPremiumAccess } = user; sendMessage('ping', 'plus_panel_from_menu'); this.props.toggleDropdown(); this.props.history.push(hasPremiumAccess || hasPlusAccess ? '/subscription/info' : `/subscribe/${this.props.loggedIn}`); @@ -166,16 +167,18 @@ class HeaderMenu extends React.Component { const { loggedIn, email, - subscription + user } = this.props; + const hasPlusAccess = user && user.hasPlusAccess; + const hasPremiumAccess = user && user.hasPremiumAccess; const optionClasses = ClassNames({ - 'menu-option': subscription, - 'menu-option-non-subscriber': !subscription + 'menu-option': hasPlusAccess || hasPremiumAccess, + 'menu-option-non-subscriber': !(hasPlusAccess || hasPremiumAccess) }); const iconClasses = ClassNames('menu-icon-container', { - premium: subscription === 'premium', - plus: subscription === 'plus', - 'non-subscriber': !subscription + premium: hasPremiumAccess, + plus: !hasPremiumAccess && hasPlusAccess, + 'non-subscriber': !(hasPremiumAccess || hasPlusAccess) }); return ( @@ -243,7 +246,7 @@ class HeaderMenu extends React.Component {
  • {/* Show premium icon to premium users and plus icon to basic and plus users */} - {subscription !== 'premium' && ( + {!hasPremiumAccess && ( @@ -251,7 +254,7 @@ class HeaderMenu extends React.Component { )} - {subscription === 'premium' && ( + {hasPremiumAccess && ( @@ -262,7 +265,7 @@ class HeaderMenu extends React.Component { )} - {subscription === 'premium' ? t('panel_detail_premium_title') : t('ghostery_plus')} + {hasPremiumAccess ? t('panel_detail_premium_title') : t('ghostery_plus')}
  • diff --git a/app/panel/components/Summary.jsx b/app/panel/components/Summary.jsx index af3dffdcb..84da9b6ab 100644 --- a/app/panel/components/Summary.jsx +++ b/app/panel/components/Summary.jsx @@ -754,8 +754,8 @@ class Summary extends React.Component { _renderPlusUpgradeBannerOrSubscriberIcon() { const { is_expert, current_theme, user } = this.props; - const isPremiumSubscriber = (user && user.subscription === 'premium') || false; - const isPlusSubscriber = (user && user.subscription === 'plus') || false; + const hasPremiumAccess = user && user.premiumAccess; + const hasPlusAccess = user && user.plusAccess; const upgradeBannerClassNames = ClassNames('UpgradeBanner', { 'UpgradeBanner--normal': !is_expert, 'UpgradeBanner--small': is_expert, @@ -763,7 +763,7 @@ class Summary extends React.Component { return (
    - {isPremiumSubscriber && ( + {hasPremiumAccess && (
    @@ -771,7 +771,7 @@ class Summary extends React.Component {
    )} - {isPlusSubscriber && ( + {hasPlusAccess && !hasPremiumAccess && (
    @@ -779,7 +779,7 @@ class Summary extends React.Component {
    )} - {(!isPremiumSubscriber && !isPlusSubscriber) && ( + {(!hasPlusAccess && !hasPremiumAccess) && (
    {t('subscription_upgrade_to')} From 3d51fd0e44e48d25635ca8e41b22828f8a83d5e8 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 13 May 2020 11:25:30 -0400 Subject: [PATCH 30/34] Remove unused subscription property on user --- src/classes/Account.js | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/classes/Account.js b/src/classes/Account.js index 0969077b8..c77e94218 100644 --- a/src/classes/Account.js +++ b/src/classes/Account.js @@ -489,24 +489,11 @@ class Account { } _setSubscriptionData = (data) => { - const currentAccount = conf.account; - // TODO: Change this so that we aren't writing over data if (!conf.paid_subscription && data) { conf.paid_subscription = true; dispatcher.trigger('conf.save.paid_subscription'); } - currentAccount.subscriptionData = data || null; - - if (currentAccount.user) { - if (data.productName.includes('Ghostery Premium')) { - currentAccount.subscription = 'premium'; - } else if (data.productName.includes('Ghostery Plus')) { - currentAccount.subscription = 'plus'; - } else { - currentAccount.subscription = ''; - } - } dispatcher.trigger('conf.save.account'); } From 23e5eb73ac0fc4aa362b9cbaccf9aa40ddaf97ed Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 13 May 2020 11:44:57 -0400 Subject: [PATCH 31/34] Base menu icon off of plusAccess and premiumAccess --- app/hub/Views/PlusView/PlusViewContainer.jsx | 3 ++- app/panel/components/Detail.jsx | 9 +++++---- app/panel/components/HeaderMenu.jsx | 21 ++++++++++---------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/app/hub/Views/PlusView/PlusViewContainer.jsx b/app/hub/Views/PlusView/PlusViewContainer.jsx index 668d0b842..2737380ec 100644 --- a/app/hub/Views/PlusView/PlusViewContainer.jsx +++ b/app/hub/Views/PlusView/PlusViewContainer.jsx @@ -43,8 +43,9 @@ class PlusViewContainer extends Component { * @return {JSX} JSX for rendering the Plus View of the Hub app */ render() { + const { user } = this.props; const childProps = { - isPlus: this.props.user && this.props.user.plusAccess || false, + isPlus: user && user.plusAccess || false, onPlusClick: this._sendPlusPing, }; diff --git a/app/panel/components/Detail.jsx b/app/panel/components/Detail.jsx index 8dc0838fd..3846924d7 100644 --- a/app/panel/components/Detail.jsx +++ b/app/panel/components/Detail.jsx @@ -60,13 +60,14 @@ class Detail extends React.Component { * @return {ReactComponent} ReactComponent instance */ render() { + const { is_expanded, user, history } = this.props; const condensedToggleClassNames = ClassNames('condensed-toggle', { - condensed: this.props.is_expanded, + condensed: is_expanded, }); - const activeTab = this.props.history.location.pathname.includes('rewards') ? 'rewards' : 'blocking'; + const activeTab = history.location.pathname.includes('rewards') ? 'rewards' : 'blocking'; const contentDetailsClassNames = ClassNames({ - expanded: this.props.is_expanded, + expanded: is_expanded, rewardsView: activeTab === 'rewards', }); @@ -80,7 +81,7 @@ class Detail extends React.Component {
    diff --git a/app/panel/components/HeaderMenu.jsx b/app/panel/components/HeaderMenu.jsx index e09f7d357..bfbaeac74 100644 --- a/app/panel/components/HeaderMenu.jsx +++ b/app/panel/components/HeaderMenu.jsx @@ -167,10 +167,9 @@ class HeaderMenu extends React.Component { const { loggedIn, email, - user + hasPremiumAccess, + hasPlusAccess } = this.props; - const hasPlusAccess = user && user.hasPlusAccess; - const hasPremiumAccess = user && user.hasPremiumAccess; const optionClasses = ClassNames({ 'menu-option': hasPlusAccess || hasPremiumAccess, 'menu-option-non-subscriber': !(hasPlusAccess || hasPremiumAccess) @@ -246,14 +245,6 @@ class HeaderMenu extends React.Component {
  • {/* Show premium icon to premium users and plus icon to basic and plus users */} - {!hasPremiumAccess && ( - - - - - - - )} {hasPremiumAccess && ( @@ -265,6 +256,14 @@ class HeaderMenu extends React.Component { )} + {!hasPremiumAccess && ( + + + + + + + )} {hasPremiumAccess ? t('panel_detail_premium_title') : t('ghostery_plus')}
  • From 49eb749fb1beef5186adb708494076990a58a66a Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 13 May 2020 13:10:22 -0400 Subject: [PATCH 32/34] Refactor isPlus to hasPlusAccess, destructure some things, and save subscriptionData in account#setSubscriptionData --- app/panel/components/Panel.jsx | 12 ++++++------ app/panel/components/Stats.jsx | 19 ++++++++++--------- src/classes/Account.js | 1 + 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/app/panel/components/Panel.jsx b/app/panel/components/Panel.jsx index 4e78a5ed6..9d5a98fbb 100644 --- a/app/panel/components/Panel.jsx +++ b/app/panel/components/Panel.jsx @@ -214,7 +214,7 @@ class Panel extends React.Component { * @private * Is the user a Premium subscriber? */ - _premiumSubscriber = () => { + _hasPremiumAccess = () => { const { loggedIn, user } = this.props; return loggedIn && (user && user.premiumAccess); @@ -225,7 +225,7 @@ class Panel extends React.Component { * @private * Is the user a Plus subscriber? */ - _plusSubscriber = () => { + _hasPlusAccess = () => { const { loggedIn, user } = this.props; return loggedIn && (user && user.plusAccess); @@ -237,17 +237,17 @@ class Panel extends React.Component { * Renders the Premium promo modal */ _renderPremiumPromoModal = () => { - if (this._premiumSubscriber()) return null; + if (this._hasPremiumAccess()) return null; sendMessage('promoModals.sawPremiumPromo', {}); - const isPlus = this._plusSubscriber(); + const hasPlusAccess = this.hasPlusAccess(); return ( ); @@ -278,7 +278,7 @@ class Panel extends React.Component { * Renders the Plus promo modal if the user is not already an subscriber */ _renderPlusPromoModal = () => { - if (this._plusSubscriber() || this._premiumSubscriber()) { return null; } + if (this._hasPlusAccess() || this._hasPremiumAccess()) { return null; } sendMessage('promoModals.sawPlusPromo', {}); diff --git a/app/panel/components/Stats.jsx b/app/panel/components/Stats.jsx index bcd096597..bfab2f720 100644 --- a/app/panel/components/Stats.jsx +++ b/app/panel/components/Stats.jsx @@ -31,7 +31,7 @@ class Stats extends React.Component { */ componentDidMount() { sendMessage('ping', 'hist_stats_panel'); - if (!this._isPlus(this.props)) { + if (!this._hasPlusAccess(this.props)) { // eslint-disable-next-line this.setState(this._reset(true)); return; @@ -43,8 +43,8 @@ class Stats extends React.Component { * Lifecycle event */ UNSAFE_componentWillReceiveProps(nextProps) { - const nextPlus = this._isPlus(nextProps); - const thisPlus = this._isPlus(this.props); + const nextPlus = this._hasPlusAccess(nextProps); + const thisPlus = this._hasPlusAccess(this.props); if (nextPlus !== thisPlus) { if (nextPlus) { this._init(); @@ -153,7 +153,7 @@ class Stats extends React.Component { * @param {Object} event click event */ selectView = (event) => { - if (!this._isPlus(this.props)) { + if (!this._hasPlusAccess(this.props)) { return; } const state = Object.assign({}, this.state); @@ -177,7 +177,7 @@ class Stats extends React.Component { * @param {Object} event click event */ selectType = (event) => { - if (!this._isPlus(this.props)) { + if (!this._hasPlusAccess(this.props)) { return; } const state = Object.assign({}, this.state); @@ -227,7 +227,7 @@ class Stats extends React.Component { * @param {Object} event click event */ selectTimeframe = (e) => { - if (!this._isPlus(this.props)) { + if (!this._hasPlusAccess(this.props)) { return; } const state = Object.assign({}, this.state); @@ -256,7 +256,7 @@ class Stats extends React.Component { } resetStats = () => { - if (!this._isPlus(this.props)) { + if (!this._hasPlusAccess(this.props)) { return; } this.setState({ showResetModal: true }); @@ -291,6 +291,7 @@ class Stats extends React.Component { } _reset = (demo) => { + const { user } = this.props; const demoData = [ { date: '2018-12-28', amount: 300, index: 0 }, { date: '2018-12-29', amount: 450, index: 1 }, @@ -329,7 +330,7 @@ class Stats extends React.Component { monthlyAverageData: clearData, dailyAverageData: clearData, showResetModal: false, - showPitchModal: (!this.props.user || !this.props.user.plusAccess), + showPitchModal: (!user || !user.plusAccess), }; return clearOrDemoState; } @@ -517,7 +518,7 @@ class Stats extends React.Component { return selectionData; } - _isPlus = props => props.user && props.user.plusAccess; + _hasPlusAccess = props => props.user && props.user.plusAccess; /** * Render the the Stats View diff --git a/src/classes/Account.js b/src/classes/Account.js index c77e94218..59d00f788 100644 --- a/src/classes/Account.js +++ b/src/classes/Account.js @@ -494,6 +494,7 @@ class Account { conf.paid_subscription = true; dispatcher.trigger('conf.save.paid_subscription'); } + conf.account.subscriptionData = data || null; dispatcher.trigger('conf.save.account'); } From 47f1cd510e3c2e248a3c2cefe8da12bd7a568059 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 13 May 2020 15:33:42 -0400 Subject: [PATCH 33/34] Use panel#hasPlusAccess() directly --- app/panel/components/Panel.jsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/panel/components/Panel.jsx b/app/panel/components/Panel.jsx index 9d5a98fbb..1334abe3f 100644 --- a/app/panel/components/Panel.jsx +++ b/app/panel/components/Panel.jsx @@ -241,13 +241,11 @@ class Panel extends React.Component { sendMessage('promoModals.sawPremiumPromo', {}); - const hasPlusAccess = this.hasPlusAccess(); - return ( ); From ead09300b7699ece8a0de831ed5766e59b33bd44 Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 14 May 2020 12:16:49 -0400 Subject: [PATCH 34/34] Fix menu icon link --- app/panel/components/HeaderMenu.jsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/panel/components/HeaderMenu.jsx b/app/panel/components/HeaderMenu.jsx index bfbaeac74..d5c04581c 100644 --- a/app/panel/components/HeaderMenu.jsx +++ b/app/panel/components/HeaderMenu.jsx @@ -152,11 +152,10 @@ class HeaderMenu extends React.Component { * Handle click on Subscriber menu item. */ clickSubscriber = () => { - const { user } = this.props; - const { hasPlusAccess, hasPremiumAccess } = user; + const { hasPremiumAccess, hasPlusAccess } = this.props; sendMessage('ping', 'plus_panel_from_menu'); this.props.toggleDropdown(); - this.props.history.push(hasPremiumAccess || hasPlusAccess ? '/subscription/info' : `/subscribe/${this.props.loggedIn}`); + this.props.history.push(hasPlusAccess || hasPremiumAccess ? '/subscription/info' : '/subscribe/false'); } /**