Skip to content
This repository has been archived by the owner on Apr 3, 2019. It is now read-only.

[WIP] Connect another service #6764

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added app/images/connect_another_service/lockbox.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/images/connect_another_service/monitor.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/images/connect_another_service/notes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/images/connect_another_service/pocket.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/images/connect_another_service/screenshots.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions app/images/open_in_new.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions app/scripts/lib/experiment.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const STARTUP_EXPERIMENTS = {
* after the app has started.
*/
const MANUAL_EXPERIMENTS = {
'connectAnotherService': BaseExperiment,
'emailFirst': BaseExperiment,
// For now, the send SMS experiment only needs to log "enrolled", so
// no special experiment is created.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* 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/. */

/**
* Should the user be part of the Connect Another Service
*/
'use strict';

const BaseGroupingRule = require('./base');

module.exports = class ConnectAnotherServiceGroupingRule extends BaseGroupingRule {
constructor() {
super();
this.name = 'connectAnotherService';
this.ROLLOUT_RATE = 0.0;
}

choose(subject = {}) {
if (! subject.account || ! subject.uniqueUserId || ! subject.userAgent) {
return false;
}

const {
canSignIn,
isFirefoxAndroid,
isFirefoxIos,
isOtherAndroid,
isOtherIos,
} = subject.userAgent;

if (this.isTestEmail(subject.account.get('email'))) {
return true;
} else if (! canSignIn && (isFirefoxAndroid || isFirefoxIos || isOtherAndroid || isOtherIos)) {
if (this.bernoulliTrial(this.ROLLOUT_RATE, subject.uniqueUserId)) {
return true;
}
}

return false;
}
};
1 change: 1 addition & 0 deletions app/scripts/lib/experiments/grouping-rules/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const experimentGroupingRules = [
require('./send-sms-install-link'),
require('./sentry'),
require('./token-code'),
require('./connect-another-service'),
].map(ExperimentGroupingRule => new ExperimentGroupingRule());

class ExperimentChoiceIndex {
Expand Down
2 changes: 2 additions & 0 deletions app/scripts/lib/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import Complete#View from '../views/complete_sign_up';
import ConfirmResetPasswordView from '../views/confirm_reset_password';
import ConfirmView from '../views/confirm';
import ConnectAnotherDeviceView from '../views/connect_another_device';
import ConnectAnotherServiceView from '../views/connect_another_service';
import CookiesDisabledView from '../views/cookies_disabled';
import DeleteAccountView from '../views/settings/delete_account';
import DisplayNameView from '../views/settings/display_name';
Expand Down Expand Up @@ -108,6 +109,7 @@ const Router = Backbone.Router.extend({
'confirm_signin(/)': createViewHandler(ConfirmView, { type: VerificationReasons.SIGN_IN }),
'connect_another_device(/)': createViewHandler(ConnectAnotherDeviceView),
'connect_another_device/why(/)': createChildViewHandler(WhyConnectAnotherDeviceView, ConnectAnotherDeviceView),
'connect_another_service(/)': createViewHandler(ConnectAnotherServiceView),
'cookies_disabled(/)': createViewHandler(CookiesDisabledView),
'force_auth(/)': createViewHandler(ForceAuthView),
'legal(/)': createViewHandler('legal'),
Expand Down
31 changes: 31 additions & 0 deletions app/scripts/templates/connect_another_service.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<div id="main-content" class="card connect-another-service">
<header id="fxa-connect-another-service-header"><h1>{{#t}}Connect another service{{/t}}</h1></header>

{{#showSuccessMessage}}
{{#is#}}
<div class="success success-not-authenticated visible">{{#t}}Email verified{{/t}}</div>
{{/is#}}
{{#isSignIn}}
<div class="success success-not-authenticated visible">{{#t}}Sign-in confirmed{{/t}}</div>
{{/isSignIn}}
{{/showSuccessMessage}}

<p>Do more with your Firefox Account with these new services.</p>

{{#connect-services}}
<div class="connect-service">
<div class="image-container">
<div class="image" data="{{name}}"></div>
</div>
<div class="content">
<div class="service-name">{{name}}</div>
<div class="service-description">{{description}}</div>
</div>
<div class="service-links">
<a class="open-link" target="_blank" href="{{link}}" data-service="{{name}}">
<div class="open-icon"/>
</a>
</div>
</div>
{{/connect-services}}
</div>
11 changes: 10 additions & 1 deletion app/scripts/views/connect_another_device.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ define(function (require, exports, module) {

const Cocktail = require('cocktail');
const ConnectAnotherDeviceMixin = require('./mixins/connect-another-device-mixin');
const ConnectAnotherServiceExperimentMixin = require('./mixins/connect-another-service-experiment-mixin');
const ExperimentMixin = require('./mixins/experiment-mixin');
const FlowEventsMixin = require('./mixins/flow-events-mixin');
const FormView = require('./form');
Expand Down Expand Up @@ -59,6 +60,13 @@ define(function (require, exports, module) {
if (country) {
return this.replaceCurrentPageWithSmsScreen(account, country, this._showSuccessMessage());
}

// Check to see if user is in the ConnectAnotherService Experiment and
// navigate to page.
if (this.isInConnectAnotherServiceExperiment()) {
return this.replaceCurrentPageWithAppsScreen(account, this._showSuccessMessage());
}

});
}

Expand Down Expand Up @@ -271,7 +279,8 @@ define(function (require, exports, module) {
}),
SyncAuthMixin,
UserAgentMixin,
VerificationReasonMixin
VerificationReasonMixin,
ConnectAnotherServiceExperimentMixin,
);

module.exports = ConnectAnotherDeviceView;
Expand Down
115 changes: 115 additions & 0 deletions app/scripts/views/connect_another_service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/* 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 Cocktail from 'cocktail';
import BaseView from './base';
import Template from 'templates/connect_another_service.mustache';
import UserAgentMixin from '../lib/user-agent-mixin';
import VerificationReasonMixin from './mixins/verification-reason-mixin';

const SERVICES = [
{
description: 'A Secure Notepad App.',
image: 'notes',
links: {
android: 'https://play.google.com/store/apps/details?id=org.mozilla.testpilot.notes&hl=en',
},
name: 'Notes',
},
{
description: 'Save articles, videos and stories from any publication, page or app.',
image: 'pocket',
links: {
android: 'https://getpocket.com/ff_signin?s=pocket&t=login',
ios: 'https://getpocket.com/ff_signin?s=pocket&t=login'
},
name: 'Pocket',
},
{
description: 'Take your passwords everywhere with Firefox Lockbox.',
image: 'lockbox',
links: {
ios: 'https://itunes.apple.com/us/app/firefox-lockbox/id1314000270?mt=8',
},
name: 'Lockbox',
},
{
description: 'Detects threats against your online accounts.',
image: 'monitor',
links: {
website: 'https://monitor.firefox.com/',
},
name: 'Monitor',
},
{
description: 'Screenshots made simple.',
image: 'screenshots',
links: {
website: 'https://screenshots.firefox.com/',
},
name: 'Screenshots',
}
];


const View = BaseView.extend({
className: 'connect-another-service',
template: Template,

events: {
'click .open-link': '_logLinkMetrics',
},

setInitialContext(context) {
const services = this._filterServices();
const isSignIn = this.isSignIn();
const is# = this.is#();
const showSuccessMessage = this._showSuccessMessage();

context.set({
'connect-services': services,
isSignIn,
is#,
showSuccessMessage
});
},

_filterServices() {
const userAgent = this.getUserAgent();

const supportedServices = SERVICES.filter((service) => {
if (service.links.android && (userAgent.isFirefoxAndroid() || userAgent.isAndroid())) {
service.link = service.links.android;
return service;
} else if (service.links.ios && (userAgent.isFirefoxIos() || userAgent.isIos())) {
service.link = service.links.ios;
return service;
} else if (service.links.website) {
service.link = service.links.website;
return service;
}
});

return supportedServices;
},

_showSuccessMessage() {
return !! this.model.get('showSuccessMessage') ||
!! this.getSearchParam('showSuccessMessage');
},

_logLinkMetrics(event) {
const service = this.$(event.currentTarget).attr('data-service');
this.logViewEvent(`clicked.${service}`);
},
});


Cocktail.mixin(
View,
UserAgentMixin,
VerificationReasonMixin,
);

module.exports = View;
10 changes: 10 additions & 0 deletions app/scripts/views/mixins/connect-another-device-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,16 @@ define(function(require, exports, module) {
this.replaceCurrentPage('sms', { account, country, showSuccessMessage, type });
},

/**
* Replace the current page with the connect app screen.
*
* @param {Object} account
* @param {Boolean} showSuccessMessage
*/
replaceCurrentPageWithAppsScreen (account, showSuccessMessage) {
this.replaceCurrentPage('connect_another_service', { account, showSuccessMessage });
},

/**
* Get the country to send an sms to if `account` is eligible for SMS?
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/* 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/. */

/**
* An ConnectAnotherServiceExperimentMixin factory.
*
* @mixin ConnectAnotherServiceExperimentMixin
*/
'use strict';

const ExperimentMixin = require('./experiment-mixin');
const UserAgentMixin = require('../../lib/user-agent-mixin');
const EXPERIMENT_NAME = 'connectAnotherService';

/**
* Creates the mixin
*
* @returns {Object} mixin
*/
module.exports = {
dependsOn: [
ExperimentMixin,
UserAgentMixin
],

beforeRender() {
if (this.isInConnectAnotherServiceExperiment()) {
const experimentGroup = this.getConnectAnotherServiceExperimentGroup();
this.createExperiment(EXPERIMENT_NAME, experimentGroup);
}
},

/**
* Get the experiment group
*
* @returns {String}
*/
getConnectAnotherServiceExperimentGroup() {
return this.getExperimentGroup(EXPERIMENT_NAME, this._getExperimentSubject());
},


/**
* Is the user in the experiment?
*
* @returns {Boolean}
*/
isInConnectAnotherServiceExperiment() {
return this.isInExperiment(EXPERIMENT_NAME, this._getExperimentSubject());
},

/**
* Get the experiment choice subject
*
* @returns {Object}
* @private
*/
_getExperimentSubject() {
const subject = {
account: this.model.get('account'),
clientId: this.relier.get('clientId'),
userAgent: this.getContext()
};
return subject;
}
};
1 change: 1 addition & 0 deletions app/styles/_modules.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@import '../../node_modules/jquery-modal/jquery.modal';
@import 'modules/iframe';
@import 'modules/branding';
@import 'modules/connect-another-service';
@import 'modules/tooltip';
@import 'modules/input-row';
@import 'modules/select-row';
Expand Down
Loading