Merge pull request #2998 from overleaf/as-beta-page-updates

Update beta program page to include feedback survey link

GitOrigin-RevId: 549cd2be01b8f64d952d0347c8c102d0d2efae24
This commit is contained in:
Alasdair Smith 2020-07-14 14:24:25 +01:00 committed by Copybot
parent d4d6e2c45d
commit 2556fded1e
4 changed files with 66 additions and 97 deletions

View file

@ -1,60 +1,47 @@
/* eslint-disable
camelcase,
no-unused-vars,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
let BetaProgramController
const BetaProgramHandler = require('./BetaProgramHandler')
const UserGetter = require('../User/UserGetter')
const Settings = require('settings-sharelatex')
const logger = require('logger-sharelatex')
const AuthenticationController = require('../Authentication/AuthenticationController')
module.exports = BetaProgramController = {
const BetaProgramController = {
optIn(req, res, next) {
const user_id = AuthenticationController.getLoggedInUserId(req)
logger.log({ user_id }, 'user opting in to beta program')
if (user_id == null) {
const userId = AuthenticationController.getLoggedInUserId(req)
logger.log({ userId }, 'user opting in to beta program')
if (userId == null) {
return next(new Error('no user id in session'))
}
return BetaProgramHandler.optIn(user_id, function(err) {
BetaProgramHandler.optIn(userId, function(err) {
if (err) {
return next(err)
}
return res.redirect('/beta/participate')
res.redirect('/beta/participate')
})
},
optOut(req, res, next) {
const user_id = AuthenticationController.getLoggedInUserId(req)
logger.log({ user_id }, 'user opting out of beta program')
if (user_id == null) {
const userId = AuthenticationController.getLoggedInUserId(req)
logger.log({ userId }, 'user opting out of beta program')
if (userId == null) {
return next(new Error('no user id in session'))
}
return BetaProgramHandler.optOut(user_id, function(err) {
BetaProgramHandler.optOut(userId, function(err) {
if (err) {
return next(err)
}
return res.redirect('/beta/participate')
res.redirect('/beta/participate')
})
},
optInPage(req, res, next) {
const user_id = AuthenticationController.getLoggedInUserId(req)
logger.log({ user_id }, 'showing beta participation page for user')
return UserGetter.getUser(user_id, function(err, user) {
const userId = AuthenticationController.getLoggedInUserId(req)
logger.log({ user_id: userId }, 'showing beta participation page for user')
UserGetter.getUser(userId, function(err, user) {
if (err) {
logger.warn({ err, user_id }, 'error fetching user')
logger.warn({ err, userId }, 'error fetching user')
return next(err)
}
return res.render('beta_program/opt_in', {
res.render('beta_program/opt_in', {
title: 'sharelatex_beta_program',
user,
languages: Settings.languages
@ -62,3 +49,5 @@ module.exports = BetaProgramController = {
})
}
}
module.exports = BetaProgramController

View file

@ -1,7 +1,7 @@
extends ../layout
block content
.content.content-alt
main.content.content-alt
.container.beta-opt-in-wrapper
.row
.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2
@ -13,29 +13,44 @@ block content
.container-fluid
.row
.col-md-12
p.text-centered #{translate("beta_program_benefits")}
p.text-centered
| #{translate("beta_program_badge_description")}
span.beta-feature-badge
if user.betaProgram
p #{translate("beta_program_already_participating")}.
p #{translate("thank_you_for_being_part_of_our_beta_program")}.
else
p #{translate("beta_program_benefits")}
p #[strong How it works:]
ul
li #{translate("beta_program_badge_description")}#[span(aria-label=translate("beta_feature_badge") role="img").beta-feature-badge]
li #{translate("you_will_be_able_to_contact_us_any_time_to_share_your_feedback")}.
li #{translate("we_may_also_contact_you_from_time_to_time_by_email_with_a_survey")}.
li #{translate("you_can_opt_in_and_out_of_the_program_at_any_time_on_this_page")}.
.row.text-centered
.col-md-12
if user.betaProgram
p #{translate("beta_program_already_participating")}
form(id="beta-program-opt-out", method="post", action="/beta/opt-out", novalidate)
input(type="hidden", name="_csrf", value=csrfToken)
.form-group
input(type="hidden", name="_csrf", value=csrfToken)
button.btn.btn-primary(
a(
href="https://forms.gle/CFEsmvZQTAwHCd3X9"
target="_blank"
rel="noopener noreferrer"
).btn.btn-primary.btn-lg #{translate("give_feedback")}
.form-group
button.btn.btn-info.btn-sm(
type="submit"
)
span #{translate("beta_program_opt_out_action")}
.form-group
a(href="/project").btn.btn-info #{translate("back_to_your_projects")}
a(href="/project").btn.btn-link.btn-sm #{translate("back_to_your_projects")}
else
form(id="beta-program-opt-in", method="post", action="/beta/opt-in", novalidate)
input(type="hidden", name="_csrf", value=csrfToken)
.form-group
input(type="hidden", name="_csrf", value=csrfToken)
button.btn.btn-primary(
type="submit"
)
span #{translate("beta_program_opt_in_action")}
.form-group
a(href="/project").btn.btn-link.btn-sm #{translate("back_to_your_projects")}

View file

@ -1,7 +1,3 @@
.beta-opt-in-wrapper {
min-height: 400px;
}
.beta-opt-in {
.form-group {
margin-top: 15px;

View file

@ -1,26 +1,12 @@
/* eslint-disable
max-len,
mocha/no-identical-title,
no-return-assign,
no-unused-vars,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
const should = require('chai').should()
require('chai').should()
const SandboxedModule = require('sandboxed-module')
const assert = require('assert')
const path = require('path')
const sinon = require('sinon')
const modulePath = path.join(
__dirname,
'../../../../app/src/Features/BetaProgram/BetaProgramController'
)
const { expect } = require('chai')
describe('BetaProgramController', function() {
beforeEach(function() {
@ -67,130 +53,113 @@ describe('BetaProgramController', function() {
redirect: sinon.stub(),
render: sinon.stub()
}
return (this.next = sinon.stub())
this.next = sinon.stub()
})
describe('optIn', function() {
beforeEach(function() {
return this.BetaProgramHandler.optIn.callsArgWith(1, null)
this.BetaProgramHandler.optIn.callsArgWith(1, null)
})
it("should redirect to '/beta/participate'", function() {
this.BetaProgramController.optIn(this.req, this.res, this.next)
this.res.redirect.callCount.should.equal(1)
return this.res.redirect.firstCall.args[0].should.equal(
'/beta/participate'
)
this.res.redirect.firstCall.args[0].should.equal('/beta/participate')
})
it('should not call next with an error', function() {
this.BetaProgramController.optIn(this.req, this.res, this.next)
return this.next.callCount.should.equal(0)
})
it('should not call next with an error', function() {
this.BetaProgramController.optIn(this.req, this.res, this.next)
return this.next.callCount.should.equal(0)
this.next.callCount.should.equal(0)
})
it('should call BetaProgramHandler.optIn', function() {
this.BetaProgramController.optIn(this.req, this.res, this.next)
return this.BetaProgramHandler.optIn.callCount.should.equal(1)
this.BetaProgramHandler.optIn.callCount.should.equal(1)
})
describe('when BetaProgramHandler.opIn produces an error', function() {
beforeEach(function() {
return this.BetaProgramHandler.optIn.callsArgWith(1, new Error('woops'))
this.BetaProgramHandler.optIn.callsArgWith(1, new Error('woops'))
})
it("should not redirect to '/beta/participate'", function() {
this.BetaProgramController.optIn(this.req, this.res, this.next)
return this.res.redirect.callCount.should.equal(0)
this.res.redirect.callCount.should.equal(0)
})
it('should produce an error', function() {
this.BetaProgramController.optIn(this.req, this.res, this.next)
this.next.callCount.should.equal(1)
return this.next.firstCall.args[0].should.be.instanceof(Error)
this.next.firstCall.args[0].should.be.instanceof(Error)
})
})
})
describe('optOut', function() {
beforeEach(function() {
return this.BetaProgramHandler.optOut.callsArgWith(1, null)
this.BetaProgramHandler.optOut.callsArgWith(1, null)
})
it("should redirect to '/beta/participate'", function() {
this.BetaProgramController.optOut(this.req, this.res, this.next)
this.res.redirect.callCount.should.equal(1)
return this.res.redirect.firstCall.args[0].should.equal(
'/beta/participate'
)
this.res.redirect.firstCall.args[0].should.equal('/beta/participate')
})
it('should not call next with an error', function() {
this.BetaProgramController.optOut(this.req, this.res, this.next)
return this.next.callCount.should.equal(0)
})
it('should not call next with an error', function() {
this.BetaProgramController.optOut(this.req, this.res, this.next)
return this.next.callCount.should.equal(0)
this.next.callCount.should.equal(0)
})
it('should call BetaProgramHandler.optOut', function() {
this.BetaProgramController.optOut(this.req, this.res, this.next)
return this.BetaProgramHandler.optOut.callCount.should.equal(1)
this.BetaProgramHandler.optOut.callCount.should.equal(1)
})
describe('when BetaProgramHandler.optOut produces an error', function() {
beforeEach(function() {
return this.BetaProgramHandler.optOut.callsArgWith(
1,
new Error('woops')
)
this.BetaProgramHandler.optOut.callsArgWith(1, new Error('woops'))
})
it("should not redirect to '/beta/participate'", function() {
this.BetaProgramController.optOut(this.req, this.res, this.next)
return this.res.redirect.callCount.should.equal(0)
this.res.redirect.callCount.should.equal(0)
})
it('should produce an error', function() {
this.BetaProgramController.optOut(this.req, this.res, this.next)
this.next.callCount.should.equal(1)
return this.next.firstCall.args[0].should.be.instanceof(Error)
this.next.firstCall.args[0].should.be.instanceof(Error)
})
})
})
describe('optInPage', function() {
beforeEach(function() {
return this.UserGetter.getUser.callsArgWith(1, null, this.user)
this.UserGetter.getUser.callsArgWith(1, null, this.user)
})
it('should render the opt-in page', function() {
this.BetaProgramController.optInPage(this.req, this.res, this.next)
this.res.render.callCount.should.equal(1)
const { args } = this.res.render.firstCall
return args[0].should.equal('beta_program/opt_in')
args[0].should.equal('beta_program/opt_in')
})
describe('when UserGetter.getUser produces an error', function() {
beforeEach(function() {
return this.UserGetter.getUser.callsArgWith(1, new Error('woops'))
this.UserGetter.getUser.callsArgWith(1, new Error('woops'))
})
it('should not render the opt-in page', function() {
this.BetaProgramController.optInPage(this.req, this.res, this.next)
return this.res.render.callCount.should.equal(0)
this.res.render.callCount.should.equal(0)
})
it('should produce an error', function() {
this.BetaProgramController.optInPage(this.req, this.res, this.next)
this.next.callCount.should.equal(1)
return this.next.firstCall.args[0].should.be.instanceof(Error)
this.next.firstCall.args[0].should.be.instanceof(Error)
})
})
})