1
0
Fork 0
mirror of https://github.com/overleaf/overleaf.git synced 2025-04-11 04:35:13 +00:00

Show group subscription status on subscription dashboard page

Conflicts:
	app/views/subscriptions/dashboard.jade
This commit is contained in:
James Allen 2014-08-07 15:29:06 +01:00
parent 06c83dfcfa
commit b367c4a968
11 changed files with 131 additions and 147 deletions

View file

@ -10,6 +10,7 @@ Project = require('../../models/Project').Project
User = require('../../models/User').User
TagsHandler = require("../Tags/TagsHandler")
SubscriptionLocator = require("../Subscription/SubscriptionLocator")
LimitationsManager = require("../Subscription/LimitationsManager")
_ = require("underscore")
Settings = require("settings-sharelatex")
SecurityManager = require("../../managers/SecurityManager")
@ -123,8 +124,8 @@ module.exports = ProjectController =
TagsHandler.getAllTags user_id, cb
projects: (cb)->
Project.findAllUsersProjects user_id, 'name lastUpdated publicAccesLevel archived owner_ref', cb
subscription: (cb)->
SubscriptionLocator.getUsersSubscription user_id, cb
hasSubscription: (cb)->
LimitationsManager.userHasSubscriptionOrIsGroupMember req.session.user, cb
}, (err, results)->
if err?
logger.err err:err, "error getting data for project list page"
@ -140,7 +141,7 @@ module.exports = ProjectController =
priority_title: true
projects: projects
tags: tags
hasSubscription: !!results.subscription
hasSubscription: results.hasSubscription
}
if Settings?.algolia?.app_id? and Settings?.algolia?.read_only_api_key?

View file

@ -29,11 +29,13 @@ module.exports =
else
callback null, true
userHasSubscriptionOrFreeTrial: (user, callback = (err, hasSubscriptionOrTrial, subscription)->) ->
@userHasSubscription user, (err, hasSubscription, subscription)=>
@userHasFreeTrial user, (err, hasFreeTrial)=>
logger.log user_id:user._id, subscription:subscription, hasFreeTrial:hasFreeTrial, hasSubscription:hasSubscription, "checking if user has subscription or free trial"
callback err, hasFreeTrial or hasSubscription, subscription
userHasSubscriptionOrIsGroupMember: (user, callback = (err, hasSubscriptionOrIsMember)->) ->
@userHasSubscription user, (err, hasSubscription)=>
return callback(err) if err?
@userIsMemberOfGroupSubscription user, (err, isMember)=>
return callback(err) if err?
logger.log user_id:user._id, isMember:isMember, hasSubscription:hasSubscription, "checking if user has subscription or is group member"
callback err, isMember or hasSubscription
userHasSubscription: (user, callback = (err, hasSubscription, subscription)->) ->
logger.log user_id:user._id, "checking if user has subscription"
@ -43,11 +45,12 @@ module.exports =
hasValidSubscription = subscription? and subscription.recurlySubscription_id?
logger.log user:user, hasValidSubscription:hasValidSubscription, subscription:subscription, "checking if user has subscription"
callback err, hasValidSubscription, subscription
userHasFreeTrial: (user, callback = (err, hasFreeTrial, subscription)->) ->
logger.log user_id:user._id, "checking if user has free trial"
SubscriptionLocator.getUsersSubscription user, (err, subscription)->
callback err, subscription? and subscription.freeTrial? and subscription.freeTrial.expiresAt?, subscription
userIsMemberOfGroupSubscription: (user, callback = (error, isMember, subscriptions) ->) ->
logger.log user_id: user._ud, "checking is user is member of subscription groups"
SubscriptionLocator.getMemberSubscriptions user._id, (err, subscriptions = []) ->
return callback(err) if err?
callback err, subscriptions.length > 0, subscriptions
hasGroupMembersLimitReached: (user_id, callback)->
SubscriptionLocator.getUsersSubscription user_id, (err, subscription)->

View file

@ -64,19 +64,20 @@ module.exports = SubscriptionController =
userSubscriptionPage: (req, res, next) ->
SecurityManager.getCurrentUser req, (error, user) =>
return next(error) if error?
LimitationsManager.userHasSubscriptionOrFreeTrial user, (err, hasSubOrFreeTrial)->
if !hasSubOrFreeTrial
LimitationsManager.userHasSubscriptionOrIsGroupMember user, (err, hasSubOrIsGroupMember)->
if !hasSubOrIsGroupMember
logger.log user: user, "redirecting to plans"
res.redirect "/user/subscription/plans"
else
SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel user, (error, subscription) ->
SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel user, (error, subscription, groups) ->
return next(error) if error?
logger.log user: user, subscription:subscription, hasSubOrFreeTrial:hasSubOrFreeTrial, "showing subscription dashboard"
logger.log user: user, subscription:subscription, hasSubOrIsGroupMember:hasSubOrIsGroupMember, "showing subscription dashboard"
plans = SubscriptionViewModelBuilder.buildViewModel()
res.render "subscriptions/dashboard",
title: "your_subscription"
plans: plans
subscription: subscription
groups: groups
subscriptionTabActive: true

View file

@ -12,3 +12,6 @@ module.exports =
logger.log user_id:user_id, "getting users subscription"
Subscription.findOne admin_id:user_id, callback
getMemberSubscriptions: (user_id, callback) ->
logger.log user_id: user_id, "getting users group subscriptions"
Subscription.find(member_ids: user_id).populate("admin_id").exec callback

View file

@ -8,32 +8,25 @@ _ = require("underscore")
module.exports =
buildUsersSubscriptionViewModel: (user, callback) ->
SubscriptionLocator.getUsersSubscription user, (err, subscription)->
LimitationsManager.userHasFreeTrial user, (err, hasFreeTrial)->
LimitationsManager.userHasSubscription user, (err, hasSubscription)->
if hasSubscription
return callback(error) if error?
plan = PlansLocator.findLocalPlanInSettings(subscription.planCode)
RecurlyWrapper.getSubscription subscription.recurlySubscription_id, (err, recurlySubscription)->
callback null,
name: plan.name
nextPaymentDueAt: SubscriptionFormatters.formatDate(recurlySubscription.current_period_ends_at)
state: recurlySubscription.state
price: SubscriptionFormatters.formatPrice recurlySubscription.unit_amount_in_cents
planCode: subscription.planCode
groupPlan: subscription.groupPlan
else if hasFreeTrial
plan = PlansLocator.findLocalPlanInSettings(subscription.freeTrial.planCode)
callback null,
name: plan.name
state: "free-trial"
planCode: plan.planCode
groupPlan: subscription.groupPlan
expiresAt: SubscriptionFormatters.formatDate(subscription.freeTrial.expiresAt)
else
callback "User has no subscription"
buildUsersSubscriptionViewModel: (user, callback = (error, subscription, groups) ->) ->
SubscriptionLocator.getUsersSubscription user, (err, subscription) ->
return callback(err) if err?
SubscriptionLocator.getMemberSubscriptions user, (err, memberSubscriptions = []) ->
return callback(err) if err?
if subscription?
return callback(error) if error?
plan = PlansLocator.findLocalPlanInSettings(subscription.planCode)
RecurlyWrapper.getSubscription subscription.recurlySubscription_id, (err, recurlySubscription)->
callback null, {
name: plan.name
nextPaymentDueAt: SubscriptionFormatters.formatDate(recurlySubscription.current_period_ends_at)
state: recurlySubscription.state
price: SubscriptionFormatters.formatPrice recurlySubscription.unit_amount_in_cents
planCode: subscription.planCode
groupPlan: subscription.groupPlan
}, memberSubscriptions
else
callback null, null, memberSubscriptions
buildViewModel : ->
plans = Settings.plans

View file

@ -35,48 +35,54 @@ block content
.card
.page-header
h1 #{translate("your_subscription")}
case subscription.state
when "free-trial"
p #{translate("on_free_trial_expiring_at", {expiresAt:"<strong>#{subscription.expiresAt}</strong>"})}
p #{translate("choose_a_plan_below")}
when "active"
p #{translate("currently_subscribed_to_plan", {planName:"<strong>#{subscription.name}</strong>"})}
a(href, ng-click="changePlan = true") #{translate("change_plan")}.
p #{translate("next_payment_of_x_collectected_on_y", {paymentAmmount:"<strong>#{subscription.price}</strong>", collectionDate:"<strong>#{subscription.nextPaymentDueAt}</strong>"})}
p.pull-right
-if (subscription)
case subscription.state
when "free-trial"
p !{translate("on_free_trial_expiring_at", {expiresAt:"<strong>" + subscription.expiresAt + "</strong>"})}
p !{translate("choose_a_plan_below")}
when "active"
p !{translate("currently_subscribed_to_plan", {planName:"<strong>" + subscription.name + "</strong>"})}
a(href, ng-click="changePlan = true") !{translate("change_plan")}.
p !{translate("next_payment_of_x_collectected_on_y", {paymentAmmount:"<strong>" + subscription.price + "</strong>", collectionDate:"<strong>" + subscription.nextPaymentDueAt + "</strong>"})}
p.pull-right
p: form(action="/user/subscription/cancel",method="post")
input(type="hidden", name="_csrf", value=csrfToken)
a(href="/user/subscription/billing-details/edit").btn.btn-info #{translate("update_your_billing_details")}
| &nbsp;
input(type="submit", value="Cancel your subscription").btn.btn-primary#cancelSubscription
when "canceled"
p #{translate("currently_subscribed_to_plan", {planName:"<strong>#{subscription.name}</strong>"})}
p #{translate("subscription_canceled_and_terminate_on_x", {terminateDate:"<strong>#{subscription.nextPaymentDueAt}</strong>"})}
p: form(action="/user/subscription/reactivate",method="post")
input(type="hidden", name="_csrf", value=csrfToken)
input(type="submit",value="Reactivate your subscription").btn.btn-success
when "expired"
p #{translate("your_subscription_has_expired")}
a(href="/user/subscription/plans") #{translate("create_new_subscription")}
default
p #{translate("problem_with_subscription_contact_us")}
p: form(action="/user/subscription/cancel",method="post")
input(type="hidden", name="_csrf", value=csrfToken)
a(href="/user/subscription/billing-details/edit").btn.btn-info #{translate("update_your_billing_details")}
| &nbsp;
input(type="submit", value="Cancel your subscription").btn.btn-primary#cancelSubscription
when "canceled"
p !{translate("currently_subscribed_to_plan", {planName:"<strong>" + subscription.name + "</strong>"})}
p !{translate("subscription_canceled_and_terminate_on_x", {terminateDate:"<strong>" + subscription.nextPaymentDueAt + "</strong>"})}
p: form(action="/user/subscription/reactivate",method="post")
input(type="hidden", name="_csrf", value=csrfToken)
input(type="submit",value="Reactivate your subscription").btn.btn-success
when "expired"
p !{translate("your_subscription_has_expired")}
a(href="/user/subscription/plans") !{translate("create_new_subscription")}
default
p !{translate("problem_with_subscription_contact_us")}
-if(subscription.groupPlan)
a(href="/subscription/group").btn.btn-success #{translate("manage_group")}
-if(subscription.groupPlan)
a(href="/subscription/group").btn.btn-success !{translate("manage_group")}
div(ng-show="changePlan", ng-cloak)
div(ng-show="changePlan", ng-cloak)
hr
h2 !{translate("change_plan")}
p: table.table
tr
th !{translate("name")}
th !{translate("price")}
th
mixin printPlans(plans.studentAccounts)
mixin printPlans(plans.individualMonthlyPlans)
mixin printPlans(plans.individualAnnualPlans)
-if (subscription && groups.length > 0)
hr
h2 #{translate("change_plan")}
p: table.table
tr
th #{translate("name")}
th #{translate("price")}
th
mixin printPlans(plans.studentAccounts)
mixin printPlans(plans.individualMonthlyPlans)
mixin printPlans(plans.individualAnnualPlans)
each groupSubscription in groups
p !{translate("member_of_group_subscription", {admin_email: "<strong>" + groupSubscription.admin_id.email + "</strong>"})}
script(type="text/javascript").
$('#cancelSubscription').on("click", function() {

View file

@ -8,7 +8,7 @@ block content
.card(ng-controller="GroupMembersController")
.page-header
.pull-right(ng-cloak)
small(ng-show="selectedUsers.length == 0") #{translate("you_have_added_x_of_group_size_y", {addedUsersSize:"<strong>{{ users.length }}</strong>", groupSize:"<strong>{{ groupSize }}</strong>"})}
small(ng-show="selectedUsers.length == 0") !{translate("you_have_added_x_of_group_size_y", {addedUsersSize:"<strong>{{ users.length }}</strong>", groupSize:"<strong>{{ groupSize }}</strong>"})}
a.btn.btn-danger(
href,
ng-show="selectedUsers.length > 0"

View file

@ -29,6 +29,8 @@ describe "ProjectController", ->
createBasicProject: sinon.stub().callsArgWith(2, null, {_id:@project_id})
@SubscriptionLocator =
getUsersSubscription: sinon.stub()
@LimitationsManager =
userHasSubscriptionOrIsGroupMember: sinon.stub()
@TagsHandler =
getAllTags: sinon.stub()
@ProjectModel =
@ -50,6 +52,7 @@ describe "ProjectController", ->
"./ProjectCreationHandler": @ProjectCreationHandler
"../Editor/EditorController": @EditorController
"../Subscription/SubscriptionLocator": @SubscriptionLocator
"../Subscription/LimitationsManager": @LimitationsManager
"../Tags/TagsHandler":@TagsHandler
'../../models/Project': Project:@ProjectModel
"../../models/User":User:@UserModel
@ -199,7 +202,7 @@ describe "ProjectController", ->
fields.should.equal 'first_name last_name'
callback null, @users[id]
@SubscriptionLocator.getUsersSubscription.callsArgWith(1, null, {})
@LimitationsManager.userHasSubscriptionOrIsGroupMember.callsArgWith(1, null, false)
@TagsHandler.getAllTags.callsArgWith(1, null, @tags, {})
@ProjectModel.findAllUsersProjects.callsArgWith(2, null, @projects, @collabertions, @readOnly)

View file

@ -126,87 +126,60 @@ describe "LimitationsManager", ->
it "should return the subscription", (done)->
stubbedSubscription = {freeTrial:{}, token:""}
@SubscriptionLocator.getUsersSubscription.callsArgWith(1, null, stubbedSubscription)
@LimitationsManager.userHasSubscription @user, (err, hasSubOrFreeTrial, subscription)->
@LimitationsManager.userHasSubscription @user, (err, hasSubOrIsGroupMember, subscription)->
subscription.should.deep.equal stubbedSubscription
done()
describe "userHasFreeTrial", ->
describe "userIsMemberOfGroupSubscription", ->
beforeEach ->
@SubscriptionLocator.getUsersSubscription = sinon.stub()
@SubscriptionLocator.getMemberSubscriptions = sinon.stub()
it "should return true if the free trial is set", (done)->
@SubscriptionLocator.getUsersSubscription.callsArgWith(1, null, freeTrial:{expiresAt : "1234"})
@LimitationsManager.userHasFreeTrial @user, (err, hasFreeTrial)->
hasFreeTrial.should.equal true
it "should return false if there are no groups subcriptions", (done)->
@SubscriptionLocator.getMemberSubscriptions.callsArgWith(1, null, [])
@LimitationsManager.userIsMemberOfGroupSubscription @user, (err, isMember)->
isMember.should.equal false
done()
it "should return false if the free trial is not set", (done)->
@SubscriptionLocator.getUsersSubscription.callsArgWith(1, null, {freeTrial:{}})
@LimitationsManager.userHasFreeTrial @user, (err, hasFreeTrial)->
hasFreeTrial.should.equal false
it "should return true if there are no groups subcriptions", (done)->
@SubscriptionLocator.getMemberSubscriptions.callsArgWith(1, null, subscriptions = ["mock-subscription"])
@LimitationsManager.userIsMemberOfGroupSubscription @user, (err, isMember, retSubscriptions)->
isMember.should.equal true
retSubscriptions.should.equal subscriptions
done()
it "should return false if the free trial is not there", (done)->
@SubscriptionLocator.getUsersSubscription.callsArgWith(1, null, {})
@LimitationsManager.userHasFreeTrial @user, (err, hasFreeTrial)->
hasFreeTrial.should.equal false
done()
it "should return false if the free trial is undefined", (done)->
@SubscriptionLocator.getUsersSubscription.callsArgWith(1)
@LimitationsManager.userHasFreeTrial @user, (err, hasFreeTrial)->
hasFreeTrial.should.equal false
done()
it "should return the subscription", (done)->
stubbedSubscription = {freeTrial:{}, token:""}
@SubscriptionLocator.getUsersSubscription.callsArgWith(1, null, stubbedSubscription)
@LimitationsManager.userHasFreeTrial @user, (err, hasSubOrFreeTrial, subscription)->
subscription.should.deep.equal stubbedSubscription
done()
describe "userHasSubscriptionOrFreeTrial", ->
describe "userHasSubscriptionOrIsGroupMember", ->
beforeEach ->
@hasFreeTrial = true
@hasSubscription = true
@LimitationsManager.userHasFreeTrial = sinon.stub().callsArgWith(1, null, @hasFreeTrial)
@LimitationsManager.userHasSubscription = sinon.stub().callsArgWith(1, null, @hasSubscription)
@LimitationsManager.userIsMemberOfGroupSubscription = sinon.stub()
@LimitationsManager.userHasSubscription = sinon.stub()
it "should return true if both are true", (done)->
@hasFreeTrial = true
@hasSubscription = true
@LimitationsManager.userHasSubscriptionOrFreeTrial @user, (err, hasSubOrFreeTrial)->
hasSubOrFreeTrial.should.equal true
@LimitationsManager.userIsMemberOfGroupSubscription.callsArgWith(1, null, true)
@LimitationsManager.userHasSubscription.callsArgWith(1, null, true)
@LimitationsManager.userHasSubscriptionOrIsGroupMember @user, (err, hasSubOrIsGroupMember)->
hasSubOrIsGroupMember.should.equal true
done()
it "should return true if one is true", (done)->
@hasFreeTrial = false
@hasSubscription = true
@LimitationsManager.userHasSubscriptionOrFreeTrial @user, (err, hasSubOrFreeTrial)->
hasSubOrFreeTrial.should.equal true
@LimitationsManager.userIsMemberOfGroupSubscription.callsArgWith(1, null, true)
@LimitationsManager.userHasSubscription.callsArgWith(1, null, false)
@LimitationsManager.userHasSubscriptionOrIsGroupMember @user, (err, hasSubOrIsGroupMember)->
hasSubOrIsGroupMember.should.equal true
done()
it "should return true if other is true", (done)->
@hasFreeTrial = true
@hasSubscription = false
@LimitationsManager.userHasSubscriptionOrFreeTrial @user, (err, hasSubOrFreeTrial)->
hasSubOrFreeTrial.should.equal true
@LimitationsManager.userIsMemberOfGroupSubscription.callsArgWith(1, null, false)
@LimitationsManager.userHasSubscription.callsArgWith(1, null, true)
@LimitationsManager.userHasSubscriptionOrIsGroupMember @user, (err, hasSubOrIsGroupMember)->
hasSubOrIsGroupMember.should.equal true
done()
it "should return false if both are false", (done)->
@hasSubscription = false
@hasFreeTrial = false
@LimitationsManager.userHasSubscriptionOrFreeTrial @user, (err, hasSubOrFreeTrial)->
hasSubOrFreeTrial.should.equal true
@LimitationsManager.userIsMemberOfGroupSubscription.callsArgWith(1, null, false)
@LimitationsManager.userHasSubscription.callsArgWith(1, null, false)
@LimitationsManager.userHasSubscriptionOrIsGroupMember @user, (err, hasSubOrIsGroupMember)->
hasSubOrIsGroupMember.should.equal false
done()
it "should return the subscription", (done)->
stubbedSubscription = {freeTrial:{}, token:""}
@LimitationsManager.userHasSubscription = sinon.stub().callsArgWith(1, null, null, stubbedSubscription)
@LimitationsManager.userHasSubscriptionOrFreeTrial @user, (err, hasSubOrFreeTrial, subscription)->
subscription.should.deep.equal stubbedSubscription
done()
describe "hasGroupMembersLimitReached", ->
beforeEach ->

View file

@ -38,7 +38,7 @@ describe "Subscription controller sanboxed", ->
findLocalPlanInSettings: sinon.stub()
@LimitationsManager =
userHasSubscriptionOrFreeTrial: sinon.stub()
userHasSubscriptionOrIsGroupMember: sinon.stub()
userHasSubscription : sinon.stub()
@RecurlyWrapper =
@ -140,7 +140,7 @@ describe "Subscription controller sanboxed", ->
describe "with a user without a subscription", ->
beforeEach (done) ->
@res.callback = done
@LimitationsManager.userHasSubscriptionOrFreeTrial.callsArgWith(1, null, false)
@LimitationsManager.userHasSubscriptionOrIsGroupMember.callsArgWith(1, null, false)
@SubscriptionController.userSubscriptionPage @req, @res
it "should redirect to the plans page", ->
@ -151,7 +151,7 @@ describe "Subscription controller sanboxed", ->
beforeEach (done) ->
@res.callback = done
@SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel.callsArgWith(1, null, @activeRecurlySubscription)
@LimitationsManager.userHasSubscriptionOrFreeTrial.callsArgWith(1, null, true)
@LimitationsManager.userHasSubscriptionOrIsGroupMember.callsArgWith(1, null, true)
@SubscriptionController.userSubscriptionPage @req, @res
it "should render the dashboard", (done)->
@ -166,7 +166,7 @@ describe "Subscription controller sanboxed", ->
beforeEach (done) ->
@res.callback = done
@SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel.callsArgWith(1, null, @activeRecurlySubscription)
@LimitationsManager.userHasSubscriptionOrFreeTrial.callsArgWith(1, null, true)
@LimitationsManager.userHasSubscriptionOrIsGroupMember.callsArgWith(1, null, true)
@SubscriptionController.userSubscriptionPage @req, @res
it "should render the dashboard", ->

View file

@ -14,6 +14,7 @@ describe "Subscription Locator Tests", ->
@subscription = {hello:"world"}
@Subscription =
findOne: sinon.stub()
find: sinon.stub()
@SubscriptionLocator = SandboxedModule.require modulePath, requires:
'../../models/Subscription': Subscription:@Subscription
"logger-sharelatex": log:->