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

M20-51: New Opt-in for Ghostery #444

Merged
@@ -2006,9 +2006,21 @@
"rewards_delete": {
"message": "Delete this reward"
},
"rewards_exclusive": {
"message": "exclusive"
},
"rewards_best_offer": {
"message": "best offer"
},
"rewards_first_prompt": {
"message": "Would you like to continue to your Ghostery Reward?"
},
"rewards_first_prompt_extended": {
"message": "Would you like to receive offers and discounts from trusted Ghostery partners?"
},
"rewards_first_prompt_headline": {
"message": "New Reward discovered!"
},
"rewards_second_prompt": {
"message": "Would you like to opt out of future Ghostery Rewards?"
},
@@ -37,6 +37,58 @@ class Notification extends Component {
}
}

renderOptoutImage() {
return (
<div className="rewards-notification-optout-image-wrapper">
<img
src={chrome.extension.getURL('app/images/rewards/ghostery_O.png')}
/>
</div>
);
}

renderOptoutLink() {
return (
<a
href={this.props.data.textLink.href}
target="_blank"
rel="noopener noreferrer"
onClick={() => this.props.data.textLink.callback()}
>
{this.props.data.textLink.text}
</a>
);
}

renderHeadline() {
return (
<div className="first-prompt-headline">
{t('rewards_first_prompt_headline')}
</div>
);
}

renderLabels() {
return (
<div className="first-prompt-labels">
<img src={chrome.extension.getURL('app/images/rewards/exclusive.svg')} />
<span className="first-prompt-label">{t('rewards_exclusive')}</span>
<img src={chrome.extension.getURL('app/images/rewards/best-offer.svg')} />
<span className="first-prompt-label">{t('rewards_best_offer')}</span>
</div>
);
}

renderClose() {
return (
<div
className="close"
onClick={() => { this.closeNotification(); }}
style={{ backgroundImage: this.closeIcon }}
/>
);
}

render() {
return (
<div>
@@ -45,12 +97,17 @@ class Notification extends Component {
<div className="rewards-notification-overlay" />
<div className="rewards-popup-container">
<div className={`rewards-notification ${this.props.data.type}`}>
<div className="close" onClick={() => { this.closeNotification(); }} style={{ backgroundImage: this.closeIcon }} />
<div className="notification-text">
{this.props.data.type === 'first-prompt' && this.renderOptoutImage()}
{this.props.data.type !== 'first-prompt' && this.renderClose()}
<div className={`notification-text ${this.props.data.type}`}>
{this.props.data.type === 'first-prompt' && this.renderLabels()}
{this.props.data.type === 'first-prompt' && this.renderHeadline()}
{this.props.data.message}
{' '}
{this.props.data.type === 'first-prompt' && this.renderOptoutLink()}
</div>
{this.props.data.buttons && (
<div className="notification-buttons">
<div className={`notification-buttons ${this.props.data.type}`}>
<button type="button" className="btn" onClick={() => { this.closeNotification(true); }}>
{t('rewards_yes')}
</button>
@@ -59,21 +116,23 @@ class Notification extends Component {
</button>
</div>
)}
{this.props.data.textLink && (
<a
className="notification-text"
href={this.props.data.textLink.href}
target="_blank"
rel="noopener noreferrer"
onClick={() => {
if (this.props.data.textLink.callback) {
this.props.data.textLink.callback();
}
}}
>
{this.props.data.textLink.text}
</a>
)}
{this.props.data.textLink && this.props.data.type !== 'first-prompt'
&& (
<a
className="notification-text"
href={this.props.data.textLink.href}
target="_blank"
rel="noopener noreferrer"
onClick={() => {
if (this.props.data.textLink.callback) {
this.props.data.textLink.callback();
}
}}
>
{this.props.data.textLink.text}
</a>
)
}
</div>
</div>
</div>
@@ -41,6 +41,7 @@ class OfferCard extends Component {
showPrompt: this.props.conf.rewardsPromptAccepted ? false : 1,
showSettings: false,
rewardUI: templateData,
shouldShowCross: this.props.conf.rewardsPromptAccepted,
};

this.iframeEl = window.parent.document.getElementById('ghostery-iframe-container');
@@ -55,6 +56,7 @@ class OfferCard extends Component {
this.closeIcon = `url(${chrome.extension.getURL('app/images/drawer/x.svg')})`;
this.ghostyGrey = `url(${chrome.extension.getURL('app/images/rewards/ghosty-grey.svg')})`;
this.kebabIcon = `url(${chrome.extension.getURL('app/images/rewards/settings-kebab.svg')})`;
this.poweredByMyoffrz = `url(${chrome.extension.getURL('app/images/rewards/powered-by-myoffrz.svg')})`;

this.closeOfferCard = this.closeOfferCard.bind(this);
this.copyCode = this.copyCode.bind(this);
@@ -69,7 +71,7 @@ class OfferCard extends Component {
{
type: 'first-prompt',
buttons: true,
message: t('rewards_first_prompt'),
message: t('rewards_first_prompt_extended'),
textLink: {
href: 'https://www.ghostery.com/faqs/what-is-ghostery-rewards/',
text: t('rewards_learn_more'),
@@ -167,31 +169,32 @@ class OfferCard extends Component {
}

handlePrompt(promptNumber, option) {
const reject = () => {
this.props.actions.sendSignal('offer_first_optout');
sendMessage('ping', 'rewards_first_reject_optout');
this.disableRewards();
this.closeOfferCard();
};
if (promptNumber === 1) {
if (!option) {
sendMessage('ping', 'rewards_first_reject');
this.setState({
showPrompt: 2
});
reject();
return;
}
this.props.actions.messageBackground('rewardsPromptOptedIn');
this.props.actions.sendSignal('offer_first_optin');
sendMessage('ping', 'rewards_first_accept');
} else if (promptNumber === 2) {
if (option) {
this.props.actions.sendSignal('offer_first_optout');
sendMessage('ping', 'rewards_first_reject_optout');
this.disableRewards();
this.closeOfferCard();
reject();
return;
}
this.props.actions.sendSignal('offer_first_optlater');
sendMessage('ping', 'rewards_first_reject_optin');
this.closeOfferCard();
}
this.setState({
showPrompt: false
showPrompt: false,
shouldShowCross: true,
});
this.props.actions.messageBackground('rewardsPromptAccepted');
}
@@ -233,20 +236,26 @@ class OfferCard extends Component {
return t(`rewards_expires_in_${type}`, [count]);
}

renderCross() {
return (
<div
className="reward-card-close"
onClick={() => { this.props.actions.sendSignal('offer_closed_card'); this.closeOfferCard(); }}
style={{ backgroundImage: this.closeIcon }}
/>
);
}

render() {
return (
// @TODO condition for hide class
<div ref={(ref) => { this.offerCardRef = ref; }} className="ghostery-rewards-component">
<div style={{ opacity: 0 }} ref={(ref) => { this.offerCardRef = ref; }} className="ghostery-rewards-component">
{ this.state.closed !== true && (
<div>
<div className="ghostery-reward-card">
<div className="reward-card-header">
<div className="rewards-logo-beta" style={{ backgroundImage: this.betaLogo }} />
<div
className="reward-card-close"
onClick={() => { this.props.actions.sendSignal('offer_closed_card'); this.closeOfferCard(); }}
style={{ backgroundImage: this.closeIcon }}
/>
{this.state.shouldShowCross && this.renderCross()}
</div>
<div className="reward-content">
<div className="reward-content-header">
@@ -315,10 +324,22 @@ class OfferCard extends Component {
<div className="reward-footer">
<div className="reward-feedback">
<div className="reward-smile" />
{this.props.conf.rewardsPromptAccepted &&
<a onClick={this.disableRewardsNotification}>{t('rewards_disable')}</a>
}
<div className="reward-arrow" />
</div>
<div className="reward-ghosty" style={{ backgroundImage: this.ghostyGrey }} />
<a
className="reward-powered-by-myoffrz"
target="_blank"
rel="noopener noreferrer"
href="https://myoffrz.com/en/fuer-nutzer/"
>
<div
className="reward-ghosty"
style={{ backgroundImage: this.poweredByMyoffrz }}
/>
</a>
</div>
</div>
{ this.state.showPrompt === 1 &&
@@ -130,7 +130,6 @@ class RewardsApp {
renderIframe() {
this.rewardsIframe = document.createElement('iframe');
this.rewardsIframe.id = 'ghostery-iframe-container';
this.rewardsIframe.classList.add('hot-dog');
this.rewardsIframe.onload = () => {
this.iframeStyle = document.createElement('link');
this.iframeStyle.rel = 'stylesheet';
@@ -149,7 +148,7 @@ class RewardsApp {
exact
path="/"
render={
() => <HotDog reward={props.reward} port={this.port} actions={props.actions} />
() => <OfferCard reward={props.reward} conf={props.conf} port={this.port} actions={props.actions} />
}
/>
<Route
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="13px" height="12px" viewBox="0 0 13 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="background: #FFFFFF;">
<!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
<title>best-offer-icon13x12</title>
<desc>Created with Sketch.</desc>
<defs>
<polygon id="path-1" points="13.1848266 11.8773227 0.584289551 11.8773227 0.584289551 0.288698125 13.1848266 0.288698125"></polygon>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="best-offer-icon13x12">
<g id="Group-22" transform="translate(-0.388306, -0.287781)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<g id="Clip-21"></g>
<polygon id="Fill-20" fill="#D47B32" mask="url(#mask-2)" points="6.8593406 0.288698125 8.29768439 4.71537631 12.9516153 4.71537631 9.18650404 7.45111965 10.6244519 11.8774019 6.8593406 9.14165859 3.09383338 11.8774019 4.53217717 7.45111965 0.766669948 4.71537631 5.42099682 4.71537631"></polygon>
</g>
</g>
</g>
</svg>
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="13px" height="12px" viewBox="0 0 13 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="background: #FFFFFF;">
<!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
<title>exclusive-icon13x12</title>
<desc>Created with Sketch.</desc>
<defs>
<polygon id="path-1" points="0.332977422 0.202651114 3.91222893 0.202651114 3.91222893 2.79994542 0.332977422 2.79994542"></polygon>
<polygon id="path-3" points="2.13315318e-20 0.202769163 2.13315318e-20 11.0179246 8.5658855 11.0179246 8.5658855 0.202769163"></polygon>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="exclusive-icon13x12">
<g id="Group-28" transform="translate(0.277527, 0.369629)">
<g id="Group-3" transform="translate(7.200810, 0.313421)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<g id="Clip-2"></g>
<path d="M1.26871402,2.4486944 C1.39542015,2.75326131 1.54809711,2.83274777 1.87666736,2.78867607 C2.55505672,2.69856519 3.23344608,2.61160228 3.91222893,2.52385238 L2.51059152,0.202611764 L0.332977422,0.202611764 C0.645414284,0.951043644 0.957064152,1.69986902 1.26871402,2.4486944" id="Fill-1" fill="#DD9C19" mask="url(#mask-2)"></path>
</g>
<path d="M9.33411658,4.13782151 C9.03387813,4.26256016 8.95596567,4.39752973 8.99767638,4.71901703 C9.1113971,5.59415505 9.22511783,6.46929306 9.33765806,7.34443107 L11.8835856,4.11342468 L11.3830571,3.28471935 C10.7003392,3.5692179 10.0168344,3.85332296 9.33411658,4.13782151" id="Fill-4" fill="#DD9C19"></path>
<g id="Group-8" transform="translate(0.511356, 0.313421)">
<mask id="mask-4" fill="white">
<use xlink:href="#path-3"></use>
</mask>
<g id="Clip-7"></g>
<path d="M8.55801555,7.34395831 C8.18655409,6.4530804 7.81587963,5.5622025 7.44520516,4.67132459 C7.32951696,4.39430249 7.16778956,4.30891357 6.86637062,4.3490503 C5.9046632,4.47614993 4.94216879,4.60128207 3.97888738,4.72208574 C3.87933256,4.73467766 3.73649304,4.78032335 3.70147178,4.63590983 C3.669205,4.50330124 3.80929004,4.47614993 3.89861393,4.43837419 C4.79696828,4.06061677 5.69689663,3.68679433 6.59643147,3.31218489 C6.88722598,3.19059422 6.97064741,3.05090268 6.93011719,2.73925281 C6.82033144,1.8932336 6.7093652,1.04800138 6.59879246,0.202769163 L2.17194774,0.202769163 L-0.000157398923,3.79972805 L5.6858787,11.0180427 L8.5658855,7.36245268 C8.56352451,7.35615672 8.56077003,7.34986077 8.55801555,7.34395831" id="Fill-6" fill="#DD9C19" mask="url(#mask-4)"></path>
</g>
</g>
</g>
</g>
</svg>
Binary file not shown.
ProTip! Use n and p to navigate between commits in a pull request.