diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 8170e57da..c23068f07 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -2130,6 +2130,9 @@ "subscription_submit_issue": { "message": "Submit Issue" }, + "subscription_upgrade_to": { + "message": "Upgrade to" + }, "panel_stats_menu_cumulative": { "message": "Cumulative" }, diff --git a/app/images/panel/gold-plus-icon-expanded-view.svg b/app/images/panel/gold-plus-icon-expanded-view.svg new file mode 100644 index 000000000..06d4f74ea --- /dev/null +++ b/app/images/panel/gold-plus-icon-expanded-view.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/images/panel/gold-plus-icon.svg b/app/images/panel/gold-plus-icon.svg new file mode 100644 index 000000000..ca28de312 --- /dev/null +++ b/app/images/panel/gold-plus-icon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/app/images/panel/green-upgrade-banner-expanded-view.svg b/app/images/panel/green-upgrade-banner-expanded-view.svg new file mode 100644 index 000000000..511276171 --- /dev/null +++ b/app/images/panel/green-upgrade-banner-expanded-view.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/app/images/panel/green-upgrade-banner.svg b/app/images/panel/green-upgrade-banner.svg new file mode 100644 index 000000000..cc2d1951b --- /dev/null +++ b/app/images/panel/green-upgrade-banner.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/app/images/panel/upgrade-banner-plus.svg b/app/images/panel/upgrade-banner-plus.svg new file mode 100644 index 000000000..4fad53948 --- /dev/null +++ b/app/images/panel/upgrade-banner-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/panel/components/Header.jsx b/app/panel/components/Header.jsx index a84527b91..61dc8aba8 100644 --- a/app/panel/components/Header.jsx +++ b/app/panel/components/Header.jsx @@ -95,7 +95,7 @@ class Header extends React.Component { }); } - generateLink = () => { + generateAccountLogo = () => { const { loggedIn, user } = this.props; let text = ''; @@ -145,10 +145,12 @@ class Header extends React.Component { return this.props.is_expert ? '/detail/blocking' : '/'; } - clickBadge = () => { + clickUpgradeBannerOrGoldPlusIcon = () => { + // TODO check whether this is the message we want to be sending now sendMessage('ping', 'plus_panel_from_badge'); - const subscriber = this.props.user && this.props.user.subscriptionsPlus; - this.props.history.push(subscriber ? '/subscription/info' : `/subscribe/${!!this.props.user}`); + const { user } = this.props; + const subscriber = user && user.subscriptionsPlus; + this.props.history.push(subscriber ? '/subscription/info' : `/subscribe/${!!user}`); } /** @@ -156,83 +158,111 @@ class Header extends React.Component { * @return {JSX} JSX for rendering the Header Component of the panel */ render() { - const { pathname } = this.props.location; + const { + is_expanded, + is_expert, + location, + loggedIn, + user, + } = this.props; + const { pathname } = location; const showTabs = pathname === '/' || pathname.startsWith('/detail'); const headerArrowClasses = ClassNames('back-arrow', { 'show-back-arrow': (pathname !== '/' && !pathname.startsWith('/detail')), }); const tabSimpleClassNames = ClassNames('header-tab', { - active: !this.props.is_expert, + active: !is_expert, }); const tabDetailedClassNames = ClassNames('header-tab', { - active: this.props.is_expert, + active: is_expert, }); - const { loggedIn, user } = this.props; - const subscriber = this.props.user && this.props.user.subscriptionsPlus; - const rightLink = this.generateLink(); + const subscriber = user && user.subscriptionsPlus; + const accountLogolink = this.generateAccountLogo(); const badgeClasses = ClassNames('columns', 'shrink', { 'non-subscriber-badge': !subscriber, - 'subscriber-badge': subscriber + 'gold-subscriber-badge': subscriber }); + const simpleTab = ( +
+ + {t('panel_header_simple_view')} + +
+ ); + + const detailedTab = ( +
+ + {t('panel_header_detailed_view')} + +
+ ); + + const tabs = ( +
+ {simpleTab} + {detailedTab} +
+ ); + + const backArrowAndGhostieLogo = ( + + + + + + + ); + + const plusUpgradeBannerOrSubscriberBadgeLogolink = ( +
+ { + (subscriber && ) || + + } +
+ ); + + const headerMenuKebab = ( +
{ this.kebab = node; }}> + + + + + +
+ ); + + const headerMenu = ( + + ); + return (
- { showTabs && ( -
-
- - {t('panel_header_simple_view')} - -
-
- - {t('panel_header_detailed_view')} - -
-
- )} + { showTabs && tabs }
- - - - - - + { backArrowAndGhostieLogo }
- {rightLink} -
-
- - - - - - -
-
{ this.kebab = node; }}> - - - - - + {accountLogolink}
+ {((is_expert && is_expanded) || !showTabs) && plusUpgradeBannerOrSubscriberBadgeLogolink } + {headerMenuKebab}
- { this.state.dropdownOpen && - - } + { this.state.dropdownOpen && headerMenu }
diff --git a/app/panel/components/Summary.jsx b/app/panel/components/Summary.jsx index f3ceb7183..66da4f713 100644 --- a/app/panel/components/Summary.jsx +++ b/app/panel/components/Summary.jsx @@ -12,6 +12,7 @@ */ import React from 'react'; +import ReactSVG from 'react-svg'; import ClassNames from 'classnames'; import Tooltip from './Tooltip'; import NavButton from './BuildingBlocks/NavButton'; @@ -281,6 +282,17 @@ class Summary extends React.Component { this.props.actions.toggleCliqzFeature(feature, status); } + /** + * Handles clicking on the green upgrade banner or gold subscriber badge + */ + clickUpgradeBannerOrGoldPlusIcon = () => { + // 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}`); + } + /** * React's required render function. Returns JSX * @return {JSX} JSX for rendering the Summary View of the panel @@ -299,7 +311,9 @@ class Summary extends React.Component { paused_blocking, sitePolicy, trackerCounts, + user } = this.props; + const plusSubscriber = user && user.subscriptionsPlus; const showCondensed = is_expert && is_expanded; const antiTrackUnsafe = enable_anti_tracking && antiTracking && antiTracking.totalUnsafeCount || 0; const adBlockBlocked = enable_ad_block && adBlock && adBlock.totalCount || 0; @@ -346,126 +360,158 @@ class Summary extends React.Component { invisible: hidePageHost }); - return ( -
- {abPause && ( -
- + const pauseButtonComponent = ( + ); + + const pauseButton = ( +
+ pauseButtonComponent +
+ ); + + const totalTrackersFound = ( +
+ + {this.props.trackerCounts.allowed + this.props.trackerCounts.blocked + antiTrackUnsafe + adBlockBlocked || 0} + + +
+ ); + + const donut = ( +
+ +
+ ); + + const totalTrackersBlocked = ( +
+ {t('trackers_blocked')} + + {trackersBlockedCount} + +
+ ); + + const pageLoadTime = ( +
+ {t('page_load')} + + {this.state.trackerLatencyTotal ? `${this.state.trackerLatencyTotal} ${t('settings_seconds')}` : '-'} + +
+ ); + + // Trust, Restrict, Pause + const ghosteryFeatures = ( +
+ + + {!abPause && pauseButtonComponent} +
+ ); + + // Enhanced Anti-Tracking, Enhanced Ad Blocking, Smart Blocking + const cliqzFeatures = ( +
+ +
+ ); + + const statsNavButton = ( +
+ + +
+ ); + + const plusUpgradeBannerOrSubscriberIcon = ( +
+ {plusSubscriber && + + } + + {!plusSubscriber && +
+ {t('subscription_upgrade_to')} +
- )} + } +
+ ); - {this.state.disableBlocking && !showCondensed && ( - - )} + return ( +
+ {abPause && pauseButton} - {abPause && !this.state.disableBlocking && is_expert && !showCondensed && ( + {!showCondensed && this.state.disableBlocking && ()} + {!showCondensed && abPause && !this.state.disableBlocking && is_expert && (
{pageHost}
)} - - {!this.state.disableBlocking && !showCondensed && ( -
- -
- )} - {!this.state.disableBlocking && showCondensed && ( -
- - {this.props.trackerCounts.allowed + this.props.trackerCounts.blocked + antiTrackUnsafe + adBlockBlocked || 0} - - -
- )} - - {!this.state.disableBlocking && (!abPause || !is_expert) && !showCondensed && ( + {!showCondensed && !this.state.disableBlocking && donut} + {!showCondensed && !this.state.disableBlocking && (!abPause || !is_expert) && (
{pageHost}
)} - {!this.state.disableBlocking && ( + {showCondensed && !this.state.disableBlocking && totalTrackersFound} + + {!this.state.disableBlocking &&
-
- {t('trackers_blocked')} - - {trackersBlockedCount} - -
-
- {t('page_load')} - - {this.state.trackerLatencyTotal ? `${this.state.trackerLatencyTotal} ${t('settings_seconds')}` : '-'} - -
+ {totalTrackersBlocked} + {pageLoadTime}
- )} + } - {this.state.disableBlocking && is_expert && showCondensed && ( + {showCondensed && this.state.disableBlocking && is_expert && (
)} -
- - - {!abPause && ( - - )} -
- -
- -
+ {ghosteryFeatures} + {cliqzFeatures} + {statsNavButton} -
- - -
+ {!showCondensed && plusUpgradeBannerOrSubscriberIcon}
); } diff --git a/app/panel/containers/HeaderContainer.js b/app/panel/containers/HeaderContainer.js index a957e6ccb..5d375a4ea 100644 --- a/app/panel/containers/HeaderContainer.js +++ b/app/panel/containers/HeaderContainer.js @@ -26,8 +26,9 @@ import { logout } from '../../Account/AccountActions'; * @todo We are not using ownProps, so we better not specify it explicitly, * in this case it won't be passed by React (see https://github.com/reactjs/react-redux/blob/master/docs/api.md). */ -const mapStateToProps = state => Object.assign({}, state.header, state.account, { +const mapStateToProps = state => Object.assign({}, state.account, { // get properties from panel redux store + is_expanded: state.panel.is_expanded, is_expert: state.panel.is_expert, language: state.panel.language, tab_id: state.panel.tab_id, diff --git a/app/panel/containers/SummaryContainer.js b/app/panel/containers/SummaryContainer.js index 09aadbe26..826400617 100644 --- a/app/panel/containers/SummaryContainer.js +++ b/app/panel/containers/SummaryContainer.js @@ -29,6 +29,7 @@ const mapStateToProps = state => Object.assign({}, state.summary, state.panel, { is_expanded: state.panel.is_expanded, is_expert: state.panel.is_expert, tab_id: state.panel.tab_id, + user: state.account.user }); /** * Bind Summary view component action creators using Redux's bindActionCreators diff --git a/app/scss/partials/_header.scss b/app/scss/partials/_header.scss index 08600cb03..2c29a8281 100644 --- a/app/scss/partials/_header.scss +++ b/app/scss/partials/_header.scss @@ -72,20 +72,15 @@ } .base-badge { @extend %pointer; - width: 38px; - height: 36px; display: block; - margin-left: 10px; } - .subscriber-badge { + .gold-subscriber-badge { @extend .base-badge; - path {fill: $white;} - path.text {fill: $ghosty-blue;} + margin-top: 4px; } .non-subscriber-badge { @extend .base-badge; - path {fill: #d3af36;} - path.text {fill: #ffffff;} + margin-left: 6px; } .header-kebab { @extend %pointer; diff --git a/app/scss/partials/_summary.scss b/app/scss/partials/_summary.scss index d1c71daa1..0b37a9f76 100644 --- a/app/scss/partials/_summary.scss +++ b/app/scss/partials/_summary.scss @@ -15,28 +15,42 @@ position: absolute; height: 479px; width: 100%; - &.expert { width: 235px; } + + &.expert { + width: 235px; + padding-top: 15px; + } + &.expert.condensed { width: 66px; + padding-top: 0; background-color: #f9f6f6; } - .clickable { cursor: pointer; } - .not-clickable { cursor: not-allowed; } + .clickable { + cursor: pointer; + } + + .not-clickable { + cursor: not-allowed; + } &.ab-pause .pause-button-container { padding: 10px 0 0 10px; text-align: left; } + &.ab-pause .sub-component.pause-button { .button-pause { font-size: 11px; } } + &.expert.ab-pause .pause-button-container { padding: 10px 0 0 0; text-align: center; } + &.expert.condensed.ab-pause .pause-button-container { padding: 0; text-align: left; @@ -48,17 +62,21 @@ font-size: 11px; font-weight: 600; margin-bottom: 36px; + &.invisible { visibility: hidden; } } + &.ab-pause .page-host { margin-bottom: 30px; } + &.expert .page-host { margin-top: 20px; margin-bottom: 20px; } + &.expert.ab-pause .page-host { margin-top: 8px; margin-bottom: 8px; @@ -69,18 +87,21 @@ height: 120px; width: 120px; } + &.ab-pause .donut-graph-container { - margin-top: 0px; + margin-top: 0; margin-bottom: 30px; } + &.expert .donut-graph-container { height: 94px; width: 94px; margin-top: 21px; margin-bottom: 20px; } + &.expert.ab-pause .donut-graph-container { - margin-top: 0px; + margin-top: 0; margin-bottom: 16px; } @@ -92,6 +113,7 @@ font-weight: 600; margin: 18px 0; } + &.expert.condensed.ab-pause .total-tracker-count { margin: 13px 0; } @@ -103,10 +125,22 @@ line-height: 21px; font-weight: 600; margin-bottom: 40px; - .blocked-trackers .value { color: #e74055; } - .page-load .value { color: #ffc063; } - .page-load.fast .value { color: #9ecc42; } - .page-load.slow .value { color: #e74055; } + + .blocked-trackers .value { + color: #e74055; + } + + .page-load .value { + color: #ffc063; + } + + .page-load.fast .value { + color: #9ecc42; + } + + .page-load.slow .value { + color: #e74055; + } .blocked-trackers, .page-load { @@ -114,8 +148,10 @@ padding: 0 20px; } } + &.expert .page-stats { margin-bottom: 21px; + .blocked-trackers, .page-load { display: block; @@ -124,52 +160,72 @@ overflow-x: hidden; } } + &.expert.ab-pause .page-stats { margin-bottom: 16px; } + &.expert.condensed .page-stats { div { text-align: center; padding: 0; margin: 21px 0; } - .text { display: none; } + + .text { + display: none; + } } + &.expert.condensed.ab-pause .page-stats { margin-bottom: 0; - div { margin: 13px 0; } + + div { + margin: 13px 0; + } } .not-scanned-expert-condensed-space-taker { height: 162px; } + &.ab-pause .not-scanned-expert-condensed-space-taker { height: 130px; } .ghostery-features-container { text-align: center; + .ghostery-features, .pause-button { display: inline-block; } } + &.ab-pause .ghostery-features-container { margin-bottom: 22px; - .ghostery-features { display: block; } + + .ghostery-features { + display: block; + } } + &.expert.ab-pause .ghostery-features-container { - margin-bottom: 16px; + margin-bottom: 16px; } + &.expert.condensed.ab-pause .ghostery-features-container { margin-bottom: -8px; } + .ghostery-features-container .button-restrict { margin: 12px 28px; } + &.expert.condensed .ghostery-features-container .button-restrict { margin: 0; } + &.ab-pause .ghostery-features-container .button-restrict { margin: 0; } @@ -177,23 +233,29 @@ .cliqz-features-container { text-align: center; } + &.expert .cliqz-features-container { margin-top: 10px; margin-bottom: 6px; } + &.expert.ab-pause .cliqz-features-container { margin-top: 0; margin-bottom: 16px; } + &.expert.condensed.ab-pause .cliqz-features-container { margin-top: 14px; } + &.expert.condensed .cliqz-features-container { margin-bottom: 0; + .cliqz-feature:last-of-type { margin-bottom: 0; } } + .stats-button { position: absolute; right: 0; @@ -202,4 +264,53 @@ border: 1px lightgray solid; border-radius: 5px 0 0 5px; } + + .upgrade-banner-container { + @extend %pointer; + position: absolute; + top: 10px; + background: url("../../app/images/panel/green-upgrade-banner.svg"); + background-size: 100% 23px; + height: 23px; + } + + &.expert .upgrade-banner-container { + background-size: 100% 20px; + height: 20px; + } + + .upgrade-banner-text { + display: inline-block; + font-family: "Open Sans", "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + font-weight: bold; + color: white; + + font-size: 12px; + vertical-align: sub; + padding: 0 4px 0 10px; + } + + &.expert .upgrade-banner-text { + font-size: 10px; + vertical-align: baseline; + padding-left: 8px; + } + + .upgrade-banner-plus { + display: inline-block; + padding-right: 18px; + + vertical-align: sub; + } + + &.expert .upgrade-banner-plus { + vertical-align: middle; + } + + .gold-plus-icon { + @extend %pointer; + position: absolute; + left: 10px; + top: 11px; + } } diff --git a/app/scss/partials/_summary_expert.scss b/app/scss/partials/_summary_expert.scss deleted file mode 100644 index 7c7a20f81..000000000 --- a/app/scss/partials/_summary_expert.scss +++ /dev/null @@ -1,103 +0,0 @@ -/** - * Summary Expert Panel Sass - * - * 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 - */ - -#content-summary.expert { - width: 232px; - .tracker-category-wheel { - path { - cursor: pointer; - } - margin-top: 20px; - #categories-donut { - height: 94px; - width: 94px; - .donut-text { - font-size: 11px; - .categories-donut-count { - font-size: 24px; - } - } - } - } - #tracker-host { - margin-top: 9px; - } - .info { - display: table; - width: 100%; - font-size: 12px; - margin: 9px auto 9px; - > .columns { - flex: none; - max-width: none; - width: 100%; - text-align: center; - } - .alert-info { - display: table-header-group; - } - .alert-info, - .block-info { - @extend %pointer; - } - .block-info, - .alert-info { - padding-top: 10px; - } - .load-info { - padding-top: 10px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } - .tracker-count-alerts { - width: 100%; - text-align: center; - } - } - #controls { - padding-bottom: 8px; - .blocking-controls { - margin: 7px; - } - #cliqz-controls { - width: 173px; - margin-top: 0; - } - #ghostery-controls { - padding-top: 22px; - margin-top: 0; - .button { - .title, .select-title, .undo { - text-align: left; - margin-left: 40px; - } - } - .columns { - width: 100%; - max-width: none; - flex: none; - } - button { - margin: 0 0 14px 0; - } - } - } - .toggleExpert { - background-image: url('../images/panel/icon-simple-mode.svg'); - height: 14px; - left: 11px; - top: 11px; - width: 22px; - } -} diff --git a/app/scss/partials/_summary_expert_collapsed.scss b/app/scss/partials/_summary_expert_collapsed.scss deleted file mode 100644 index 9858e97c5..000000000 --- a/app/scss/partials/_summary_expert_collapsed.scss +++ /dev/null @@ -1,127 +0,0 @@ -/** - * Summary Expert Expanded Panel Sass - * - * 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 - */ - -#content-summary.expanded.expert { - width: 70px; - background-color: #F9F6F6; - .columns { - padding-left: 0; - padding-right: 0; - } - .toggleExpert { - position: static; - padding: 30px 0; - margin: 0; - width: 100%; - background-position: center; - } - .tracker-count-total-expanded-expert { - text-align: center; - color: #4a4a4a; - width: 100%; - font-size: 24px; - font-weight: 700; - display: inline-block; - } - #tracker-host { - display: none; - } - .info { - font-size: 14px; - .text { - display: none; - } - } - #controls { - padding-bottom: 0; - .blocking-controls { - border: 0; - border-top: 1px solid #ccc; - border-collapse: collapse; - } - .blocking-controls, .cliqz-controls { - width: 100%; - height: 40px; - margin: 0; - padding: 0; - border-radius: 0px; - text-align: center; - svg { - float: none !important; - margin: 0px; - } - > div { - position: static; - margin: 0 auto; - } - } - #cliqz-controls { - height: auto; - width: 100%; - border: none; - > .row { - max-width: 100%; - margin: 0; - } - .columns { - width: 100%; - max-width: none; - flex: none; - } - button { - height: 30px; - width: 30px; - background-size: auto 20px; - margin: 0 0 15px 0; - } - } - #ghostery-controls { - padding-top: 0; - > .row { - max-width: 100%; - margin: 0; - > .columns { - padding: 0; - } - } - button { - border: 0; - border-radius: 0; - border-top: 1px solid #ccc; - margin: 0; - position: relative; - height: 40px; - &.blocking-controls {width: 100%;} - &.active:hover .undo, .title, .select-title { - display: none; - } - .icon { - margin: 0 auto; - left: 0; - right: 0; - } - &.controls-pause .icon { - margin: 0px 20px; - left: 0; - &.resume { - margin: 6px 14px; - } - } - &.select-button.right-button { - border-left: 1px solid #ccc; - } - } - .select-button {width: 100%;} - } - } -} diff --git a/manifest.json b/manifest.json index d109d8f58..775223489 100644 --- a/manifest.json +++ b/manifest.json @@ -12,6 +12,8 @@ "version": "8.3.3", "version_name": "8.3.3", "default_locale": "en", + "debug": true, + "log": true, "description": "__MSG_short_description__", "icons": { "16": "app/images/icon16.png", @@ -100,4 +102,4 @@ "app/images/*", "dist/css/rewards_styles.css" ] -} \ No newline at end of file +}