Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Feature/rewards integration #52

Closed
wants to merge 76 commits into from
Closed
Changes from 1 commit
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
3a01479
Initial commit. Code works on staging with some temp workarounds
Apr 23, 2018
68e3b76
Removing temporary code.
Apr 23, 2018
4959ee1
hot dog
trickpattyFH20 Mar 27, 2018
0b7aba9
init circle
trickpattyFH20 Mar 29, 2018
6d40c48
react hot dog
trickpattyFH20 Mar 29, 2018
993133d
rewards hot dog ui
trickpattyFH20 Mar 30, 2018
a5d0b51
close circle
trickpattyFH20 Mar 30, 2018
9565d2f
routing and offer card
trickpattyFH20 Apr 2, 2018
a1c0870
reward card layout
trickpattyFH20 Apr 2, 2018
234e52d
more offer card styles
trickpattyFH20 Apr 2, 2018
5d68ff1
card footer + copy feedback + styling
trickpattyFH20 Apr 3, 2018
6ad8684
more styles
trickpattyFH20 Apr 3, 2018
bc6d97f
remove purple test style
trickpattyFH20 Apr 4, 2018
4a25316
test rewards postmessage
trickpattyFH20 Apr 4, 2018
dded606
one reward at a time for hot dog and offer card
trickpattyFH20 Apr 5, 2018
1560e23
header + footer + styles
trickpattyFH20 Apr 9, 2018
da5ee6b
react shadow
trickpattyFH20 Apr 13, 2018
ea7eae0
define MainView first
trickpattyFH20 Apr 13, 2018
1c00a47
lint
trickpattyFH20 Apr 16, 2018
d38fad7
add onmessage
trickpattyFH20 Apr 16, 2018
935aa87
fix selector and close button
trickpattyFH20 Apr 16, 2018
200feb3
iframe fallback
trickpattyFH20 Apr 17, 2018
a5ce6f3
fix ff beta logo
trickpattyFH20 Apr 17, 2018
b8b7cc0
data csp compatible images + class for index + text styles
trickpattyFH20 Apr 18, 2018
50fba55
disable rewards notification
trickpattyFH20 Apr 18, 2018
4b5ddf4
fix shadow FOUC
trickpattyFH20 Apr 18, 2018
84e2ec7
click outside settings
trickpattyFH20 Apr 18, 2018
a32a213
settings styles
trickpattyFH20 Apr 20, 2018
a127e39
settings actions
trickpattyFH20 Apr 23, 2018
7531d1a
show ghostery pizza offer
trickpattyFH20 Apr 24, 2018
f951291
fix event listener reward reference
trickpattyFH20 Apr 26, 2018
9f41082
setConfiguration - for DEBUG only
Apr 27, 2018
f61089b
Changing the way browser-core is loaded.
Apr 27, 2018
5a0d612
Merge remote-tracking branch 'upstream/feature/GH-732-hot-dog' into f…
trickpattyFH20 Apr 27, 2018
66b339f
handle signal
trickpattyFH20 Apr 30, 2018
8582711
mark offer read + delete offer
trickpattyFH20 Apr 30, 2018
78b1203
new signals
trickpattyFH20 Apr 30, 2018
5a59a39
refactor to sendSignal
trickpattyFH20 May 1, 2018
ce1b2a3
Create ToggleSlider component. Use it in Setup flow.
IAmThePan Apr 11, 2018
f7a3b16
GH-409 Update Rewards view: rewards list, toggle on/off, reducers, fa…
IAmThePan Apr 16, 2018
c6f4403
GH-409 Update Rewards view: reward details.
IAmThePan Apr 18, 2018
5d8819a
hot dog
trickpattyFH20 Mar 27, 2018
84bc961
Integrate panel rewards with background I
IAmThePan Apr 26, 2018
924241e
Integrate panel rewards with background II. Fix linting errors
IAmThePan Apr 30, 2018
768988a
Integrate panel rewards with Background III. Messages for read, remov…
IAmThePan Apr 30, 2018
11af136
Fix signal bug for content-script rewards
IAmThePan May 1, 2018
0a6e2bc
panel reward signals
trickpattyFH20 May 1, 2018
3526eed
reward prompt flow
trickpattyFH20 May 1, 2018
24b82ad
Finalize design for Rewards Panel
IAmThePan May 2, 2018
09fad40
clean rewards
trickpattyFH20 May 2, 2018
0fb4fd8
rewards conf handling
trickpattyFH20 May 3, 2018
ba44a18
update browser-core package and lock
trickpattyFH20 May 3, 2018
7e6c673
Add translations to Rewards Panel
IAmThePan May 3, 2018
21a6b40
Fix for Ghostery side enabling of offers
May 3, 2018
58e3707
Merge branch 'feature/rewards-integration' of https://github.com/ghos…
May 3, 2018
f92706f
styles. expiration. terms tt
trickpattyFH20 May 3, 2018
98f166d
enable offers by default
trickpattyFH20 May 3, 2018
9a4469c
start button styles
trickpattyFH20 May 3, 2018
e2fe731
Begin tests for the rewards panel
IAmThePan May 3, 2018
d11bfba
More and updated tests for Rewards Panel
IAmThePan May 3, 2018
0319a9c
Fix linting errors
IAmThePan May 3, 2018
089746d
signals
trickpattyFH20 May 4, 2018
f06a248
Add more signals, fix linting errors, fix bug
IAmThePan May 4, 2018
e4ec6c6
Removing offers from ABTest
May 7, 2018
5b43408
style adjustments
trickpattyFH20 May 7, 2018
e1f5105
GH-1051 fix null reward check
trickpattyFH20 May 8, 2018
03eee09
merge
trickpattyFH20 May 8, 2018
cb6aa87
GH-1055 fix - define onload evt first
trickpattyFH20 May 8, 2018
d51f739
button singleton + seen reward on offer card shown
trickpattyFH20 May 9, 2018
7a3e09e
typo
trickpattyFH20 May 9, 2018
55462b1
Removing enable_offers_abtest.
May 9, 2018
a9bc71e
Extra blanks
May 9, 2018
08fe23d
Removing checkbox for EDGE and CLIQZ unconditionally.
May 9, 2018
87caf7b
Restore default manifest state.
May 9, 2018
0957ffd
Update Rewards copy and add styling to non-happy-path Rewards panel
IAmThePan May 10, 2018
f9cd25c
Update test snapshots
IAmThePan May 10, 2018
File filter
Filter file types
Jump to
Jump to file
Failed to load files.

Always

Just for now

GH-409 Update Rewards view: rewards list, toggle on/off, reducers, fa…
…ke actions.
  • Loading branch information
IAmThePan committed May 1, 2018
commit f7a3b160d6a41e601d8532da65427d96d12e4023
@@ -0,0 +1,92 @@
/**
* Rewards Action creators
*
* Ghostery Browser Extension
* https://www.ghostery.com/
*
* Copyright 2018 Ghostery, Inc. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0
*/

import {
GET_REWARDS_ACTIVE,
REMOVE_REWARD_ID,
SHOW_NOTIFICATION,
TOGGLE_REWARDS_ACTIVE
} from '../constants/constants';

/**
* Fetch active rewards. Will eventually fetch from background during the initial
* load, but currently fakes an async call by using setTimeout and default datal.
* @return {Object} dispatch
*/
export function getActiveRewards() {
return function (dispatch) {
return new Promise((resolve, reject) => {
const dateNow = new Date();
return setTimeout(() => {
dispatch({
type: GET_REWARDS_ACTIVE,
data: [
{
id: 0,
unread: true,
text: '2 Free Audio Books',
expires: (new Date()).setDate(dateNow.getDate() + 14),
},
{
id: 1,
unread: true,
text: 'Save $150',
expires: (new Date()).setDate(dateNow.getDate() + 30),
},
{
id: 2,
unread: true,
text: 'Save $75',
expires: (new Date()).setDate(dateNow.getDate() + 60),
},
],
});
}, 125);
});
};
}

/**
* Removes a reward from the rewards list
* @param {Int} id The ID of the reward we want to remove.
* @return {Object}
*/
export function removeReward(id) {
return {
type: REMOVE_REWARD_ID,
data: { id }
};
}

/**
* Toggles Rewards on/off
* @return {Object}
*/
export function toggleRewardsActive() {
return {
type: TOGGLE_REWARDS_ACTIVE
};
}

/**
* Display notification messages on Panel (status, needsReload). Also used to persist
* the needsReload messages if the panel is closed before the page is refreshed.
* @param {Object} data
* @return {Object}
*/
export function showNotification(data) {
return {
type: SHOW_NOTIFICATION,
data,
};
}
@@ -0,0 +1,92 @@
/**
* Reward List Item Component
*
* Ghostery Browser Extension
* https://www.ghostery.com/
*
* Copyright 2018 Ghostery, Inc. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0
*/

import React, { Component } from 'react';
import ClassNames from 'classnames';
import { computeTimeDelta } from '../../utils/utils';

/**
* @class Implements a single reward for the Rewards Panel
* @memberof PanelClasses
*/
class RewardListItem extends React.Component {
constructor(props) {
super(props);
this.state = {};

// Event Bindings
this.clickCloseButton = this.clickCloseButton.bind(this);
}

/**
* Handle clicking on the close button
*/
clickCloseButton() {
const { id } = this.props;
this.props.clickCloseButton(id);
}

/**
* Helper render function for the expires text.
* @return {JSX} JSX for the Rewards Items List
*/
renderExpiresText() {
const { expires } = this.props;
const delta = computeTimeDelta(new Date(expires), new Date());

return `Expires in ${delta.count} ${delta.type}`;
}

/**
* React's required render function. Returns JSX
* @return {JSX} JSX for rendering a Reward within the Rewards List
*/
render() {
const { unread, text } = this.props;
const itemClassName = ClassNames('RewardListItem', 'row', {
'RewardListItem--unread': unread,
clickable: true,
});
const closeButtonClassNames = ClassNames({
'RewardsPanel--send-right': true,
'RewardListItem--add-padding': true,
'align-self-top': true,
clickable: true,
});

return (
<div className={itemClassName}>
<div className="small-12 columns">
<div className="flex-container align-middle full-height">
<div className="RewardListItem__image_container flex-container align-center">
<svg height="50" width="95" fill="none" stroke="#4a4a4a" strokeWidth="2">
<path d="M0,0L95,50M95,0L0,50" />
</svg>
</div>
<div>
<div>{ text }</div>
<div>{ this.renderExpiresText() }</div>
</div>
<div className={closeButtonClassNames} onClick={this.clickCloseButton}>
<svg height="12" width="12" fill="none" stroke="#9b9b9b" strokeWidth="2" strokeLinecap="round">
<path d="M2,2L10,10M2,10L10,2" />
</svg>
</div>
</div>
</div>
</div>
);
}
}

export default RewardListItem;
@@ -24,7 +24,7 @@ class ToggleSlider extends React.Component {
super(props);
this.state = {
checked: this.props.isChecked,
}
};

// Event Bindings
this._handleChange = this._handleChange.bind(this);
@@ -45,7 +45,7 @@ class ToggleSlider extends React.Component {
* property in the parent. Or it can just set the state directly.
*/
_handleChange(event) {
if (typeof this.props.onChange === "function") {
if (typeof this.props.onChange === 'function') {
this.props.onChange(event);
} else {
this.setState({
@@ -59,19 +59,21 @@ class ToggleSlider extends React.Component {
* @return {JSX} JSX for rendering the Toggle Slider used throghout the extension
*/
render() {
const labelClassNames = ClassNames('switch', {
const compClassNames = ClassNames('ToggleSlider', this.props.className);
const labelClassNames = ClassNames('ToggleSlider__switch', {
disabled: this.props.isDisabled,
});

return (
<div className="sub-component toggle-slider">
<div className={compClassNames}>
<label className={labelClassNames}>
<input type="checkbox"
<input
type="checkbox"
onChange={this._handleChange}
checked={this.state.checked}
/>
<span className="slider" />
<span className="slider-circle" />
<span className="ToggleSlider__slider" />
<span className="ToggleSlider__slider_circle" />
</label>
</div>
);
@@ -17,12 +17,14 @@ import GhosteryFeatures from './GhosteryFeatures';
import NotScanned from './NotScanned';
import PauseButton from './PauseButton';
import ToggleSlider from './ToggleSlider';
import RewardListItem from './RewardListItem';

export {
CliqzFeatures,
DonutGraph,
GhosteryFeatures,
NotScanned,
PauseButton,
ToggleSlider
ToggleSlider,
RewardListItem
};
@@ -19,7 +19,7 @@ import Summary from '../containers/SummaryContainer';
import Blocking from '../containers/BlockingContainer';
import History from './History';
import Performance from './Performance';
import Rewards from './Rewards';
import Rewards from '../containers/RewardsContainer';
import Premium from './Premium';
/**
* @class Implement wrapper of the detailed (expert) mode view.
@@ -12,58 +12,100 @@
*/

import React, { Component } from 'react';
import { sendMessage } from '../utils/msg';
import { ToggleSlider, RewardListItem } from './BuildingBlocks';

/**
* @class Implement Rewards view which opens from a button in
* the footer of the detailed view. See DetailMenu.jsx.
* @class The Rewards Panel shows offers generated by Ghostery Rewards.
* The panel is opened from a button in the Detailed View's footer.
* See DetailMenu.jsx.
* @memberof PanelClasses
*/
class Rewards extends React.Component {
constructor(props) {
super(props);

// event bindings
this.openNewTab = this.openNewTab.bind(this);
this.toggleRewards = this.toggleRewards.bind(this);
this.removeReward = this.removeReward.bind(this);
}

/**
* Lifecycle event
*/
componentDidMount() {
if (this.props.rewardsActive && !this.props.rewards) {
this.props.actions.getActiveRewards();
}
}

/**
* Open informational page from 'Learn More' button on the view.
* Handles toggling rewards on/off
*/
openNewTab() {
sendMessage('openNewTab', {
url: 'https:\/\/www.ghostery.com/faqs/what-new-ghostery-features-can-we-expect-in-the-future/',
become_active: true,
toggleRewards() {
const { rewardsActive } = this.props;
this.props.actions.showNotification({
text: `Ghostery Rewards is ${rewardsActive ? 'OFF' : 'ON'}`,
classes: 'purple',
});
sendMessage('ping', 'rewards_learn');
window.close();
this.props.actions.toggleRewardsActive();
}

/**
* Handles removing a reward from the Rewards array
* @param {Int} id the ID of the reward
*/
removeReward(id) {
this.props.actions.removeReward(id);
}

/**
* Helper render function for the list of Rewards Items
* @return {JSX} JSX for the Rewards Items List
*/
renderRewardListItems() {
const { rewards, rewardsActive } = this.props;
if (!rewardsActive) {
return <span>Rewards Not Active</span>;
} else if (!rewards) {
return <span>Loading Rewards ...</span>;
} else if (rewards.length === 0) {
return <span>No Rewards Were Found</span>;
}

const rewardsList = rewards.map((reward, index) => (
<RewardListItem
index={index}
id={reward.id}
key={reward.id}
unread={reward.unread}
text={reward.text}
expires={reward.expires}
clickCloseButton={this.removeReward}
/>
));
return <div className="scroll-content">{ rewardsList }</div>;
}

/**
* Render Rewards view.
* @return {ReactComponent} ReactComponent instance
* React's required render function. Returns JSX
* @return {JSX} JSX for rendering the Rewards portion of the Detailed View
*/
render() {
const { rewardsActive } = this.props;
return (
<div id="rewards-panel" className="coming-soon">
<div className="detail-header">{ t('panel_detail_rewards_title') }</div>
<div className="row align-center">
<div className="small-10 columns text-center">
<div className="detail-icon">
<svg width="31" height="27" viewBox="0 0 31 27">
<g className="fill" fillRule="evenodd">
<path d="M6.7 15.905h2.62v-3.172H6.7v3.172zm2.378-4.408l.038.1c1.064-.072 2.145-.05 3.188-.242 1.234-.226 1.7-1.528 1.036-2.585-.575-.912-2.043-1.098-2.632-.276-.502.7-.9 1.48-1.324 2.237-.133.24-.206.51-.306.767zm-2.102.078c-.16-.53-1.05-2.256-1.413-2.753-.043-.06-.088-.122-.136-.18-.837-1.04-2.424-.81-2.932.422-.38.918.16 2.087 1.054 2.282 1.122.244 2.266.158 3.426.23zm3.41 4.313h4.58v-3.16h-4.58v3.16zm-9.317.02h4.59v-3.183H1.07v3.182zm5.623 9.526H9.31V16.96H6.693v8.474zm3.7.044H14.2v-8.523h-3.807v8.523zm-8.56-.044h3.823V16.95H1.833v8.484zM.805 17.01c-.675-.178-.813-.087-.805-1.052.01-1.183.002-2.366.003-3.55 0-.555.15-.703.707-.703h1.167c.08 0 .16-.01.216-.014-.198-.346-.433-.662-.566-1.015-.483-1.285.086-2.736 1.28-3.358 1.243-.646 2.71-.282 3.52.89.616.893 1.09 1.864 1.52 2.858.04.097.09.194.16.346.1-.21.182-.372.253-.536.39-.89.802-1.767 1.362-2.567.487-.695 1.107-1.168 1.975-1.28 1.41-.182 2.77.826 3.004 2.235.137.824-.07 1.554-.548 2.223l-.153.21c.082.012.14.03.2.03.45-.004.898-.006 1.345-.013.335-.006.55.184.552.518.005 1.395.003 2.79 0 4.184 0 .283-.175.468-.464.508-.1.015-.2.017-.326.028v8.703c0 .102.002.204-.005.304-.027.346-.15.48-.493.533-.11.016-.22.016-.33.016H1.624c-.07 0-.137.002-.204-.002-.464-.027-.615-.182-.615-.65V17.01zM22.364 5.91V3.626C22.364 1.624 23.996 0 26 0c2.008 0 3.636 1.634 3.636 3.627V5.91h.37c.548 0 .994.454.994.995v5.28c0 .55-.456.997-.995.997h-8.01c-.55 0-.995-.455-.995-.996v-5.28c0-.55.456-.997.995-.997h.37zm.606.026l6.06.026V3.637c0-1.674-1.356-3.03-3.03-3.03-1.674 0-3.03 1.357-3.03 3.032v2.296z" />
</g>
</svg>
</div>
<div className="row align-center">
<div className="small-8 columns">
<div className="detail-text">{ t('panel_detail_rewards_text') }</div>
</div>
</div>
<hr />
<div className="button small hollow" onClick={this.openNewTab}>
{ t('panel_detail_learn_more') }
</div>
</div>
<div className="RewardsPanel">
<div className="RewardsPanel__header flex-container align-center-middle">
<span className="RewardsPanel__title">{ t('panel_detail_rewards_title') }</span>
<span className="RewardsPanel--send-right flex-container align-middle">
<span>{rewardsActive ? 'ON ' : 'OFF '}</span>
<ToggleSlider
className="RewardsPanel--add-padding RewardsPanel--inline-block"
isChecked={rewardsActive}
onChange={this.toggleRewards}
/>
</span>
</div>
{ this.renderRewardListItems() }
</div>
);
}
ProTip! Use n and p to navigate between commits in a pull request.