mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -05:00
Merge pull request #3203 from overleaf/hb-new-personal-plan
New personal plan GitOrigin-RevId: bd96e86bef35b618f492625c3a9ea41328390374
This commit is contained in:
parent
acd51e88c8
commit
8eab5a5f6f
8 changed files with 253 additions and 68 deletions
|
@ -6,6 +6,7 @@ module.exports = [
|
|||
value: 'str',
|
||||
plans: {
|
||||
free: '1',
|
||||
personal: '1',
|
||||
coll: '10',
|
||||
prof: 'unlimited'
|
||||
},
|
||||
|
@ -17,6 +18,7 @@ module.exports = [
|
|||
info: 'unlimited_private_info',
|
||||
plans: {
|
||||
free: true,
|
||||
personal: true,
|
||||
coll: true,
|
||||
prof: true
|
||||
},
|
||||
|
@ -28,6 +30,7 @@ module.exports = [
|
|||
info: 'realtime_collab_info',
|
||||
plans: {
|
||||
free: true,
|
||||
personal: true,
|
||||
coll: true,
|
||||
prof: true
|
||||
},
|
||||
|
@ -39,6 +42,7 @@ module.exports = [
|
|||
info: 'hundreds_templates_info',
|
||||
plans: {
|
||||
free: true,
|
||||
personal: true,
|
||||
coll: true,
|
||||
prof: true
|
||||
},
|
||||
|
@ -50,39 +54,30 @@ module.exports = [
|
|||
info: 'latex_editor_info',
|
||||
plans: {
|
||||
free: true,
|
||||
personal: true,
|
||||
coll: true,
|
||||
prof: true
|
||||
},
|
||||
student: true
|
||||
},
|
||||
{
|
||||
feature: 'compile_timeout',
|
||||
value: 'str',
|
||||
plans: {
|
||||
free: '1 min',
|
||||
personal: '4 mins',
|
||||
coll: '4 mins',
|
||||
prof: '4 mins'
|
||||
},
|
||||
student: '4 mins'
|
||||
},
|
||||
{
|
||||
feature: 'realtime_track_changes',
|
||||
value: 'bool',
|
||||
info: 'realtime_track_changes_info',
|
||||
plans: {
|
||||
free: false,
|
||||
coll: true,
|
||||
prof: true
|
||||
},
|
||||
student: true
|
||||
},
|
||||
{
|
||||
feature: 'reference_search',
|
||||
value: 'bool',
|
||||
info: 'reference_search_info',
|
||||
plans: {
|
||||
free: false,
|
||||
coll: true,
|
||||
prof: true
|
||||
},
|
||||
student: true
|
||||
},
|
||||
{
|
||||
feature: 'reference_sync',
|
||||
info: 'reference_sync_info',
|
||||
value: 'bool',
|
||||
plans: {
|
||||
free: false,
|
||||
personal: false,
|
||||
coll: true,
|
||||
prof: true
|
||||
},
|
||||
|
@ -94,6 +89,31 @@ module.exports = [
|
|||
info: 'full_doc_history_info',
|
||||
plans: {
|
||||
free: false,
|
||||
personal: true,
|
||||
coll: true,
|
||||
prof: true
|
||||
},
|
||||
student: true
|
||||
},
|
||||
{
|
||||
feature: 'reference_search',
|
||||
value: 'bool',
|
||||
info: 'reference_search_info',
|
||||
plans: {
|
||||
free: false,
|
||||
personal: true,
|
||||
coll: true,
|
||||
prof: true
|
||||
},
|
||||
student: true
|
||||
},
|
||||
{
|
||||
feature: 'reference_sync',
|
||||
info: 'reference_sync_info',
|
||||
value: 'bool',
|
||||
plans: {
|
||||
free: false,
|
||||
personal: true,
|
||||
coll: true,
|
||||
prof: true
|
||||
},
|
||||
|
@ -105,6 +125,7 @@ module.exports = [
|
|||
info: 'dropbox_integration_info',
|
||||
plans: {
|
||||
free: false,
|
||||
personal: true,
|
||||
coll: true,
|
||||
prof: true
|
||||
},
|
||||
|
@ -116,6 +137,7 @@ module.exports = [
|
|||
info: 'github_integration_info',
|
||||
plans: {
|
||||
free: false,
|
||||
personal: true,
|
||||
coll: true,
|
||||
prof: true
|
||||
},
|
||||
|
@ -126,6 +148,7 @@ module.exports = [
|
|||
value: 'bool',
|
||||
plans: {
|
||||
free: false,
|
||||
personal: true,
|
||||
coll: true,
|
||||
prof: true
|
||||
},
|
||||
|
|
|
@ -6,6 +6,13 @@ mixin btn_buy_collaborator(location)
|
|||
)
|
||||
span(ng-show="ui.view != 'annual'") #{translate("start_free_trial")}
|
||||
span(ng-show="ui.view == 'annual'") #{translate("buy_now")}
|
||||
mixin btn_buy_personal(location)
|
||||
a.btn.btn-primary(
|
||||
ng-href="/user/subscription/new?planCode={{ getPersonalPlanCode() }}¤cy={{currencyCode}}&itm_campaign=plans&itm_content=" + location,
|
||||
ng-click="signUpNowClicked('personal','" + location + "')"
|
||||
)
|
||||
span(ng-show="ui.view != 'annual'") #{translate("start_free_trial")}
|
||||
span(ng-show="ui.view == 'annual'") #{translate("buy_now")}
|
||||
mixin btn_buy_free(location)
|
||||
a.btn.btn-primary(
|
||||
href="/register"
|
||||
|
@ -74,6 +81,19 @@ mixin features_free(location)
|
|||
li
|
||||
br
|
||||
+btn_buy_free(location)
|
||||
mixin features_personal(location)
|
||||
ul.list-unstyled
|
||||
li #{translate("one_collaborator")}
|
||||
li
|
||||
li
|
||||
strong #{translate('premium_features')}
|
||||
li #{translate('sync_dropbox_github')}
|
||||
li #{translate('full_doc_history')}
|
||||
li + #{translate('more').toLowerCase()}
|
||||
li(class="hidden-xs hidden-sm")
|
||||
li
|
||||
br
|
||||
+btn_buy_personal(location)
|
||||
mixin features_premium
|
||||
li
|
||||
li
|
||||
|
@ -100,6 +120,13 @@ mixin features_student(location, plan)
|
|||
+btn_buy_student(location, plan)
|
||||
|
||||
//- Prices
|
||||
mixin price_personal
|
||||
span(ng-if="ui.view == 'monthly'")
|
||||
| {{plans[currencyCode]['personal']['monthly']}}
|
||||
span.small /mo
|
||||
span(ng-if="ui.view == 'annual'")
|
||||
| {{plans[currencyCode]['personal']['annual']}}
|
||||
span.small /yr
|
||||
mixin price_collaborator
|
||||
span(ng-if="ui.view == 'monthly'")
|
||||
| {{plans[currencyCode]['collaborator']['monthly']}}
|
||||
|
@ -154,7 +181,7 @@ mixin plan_switch(location)
|
|||
a.btn.btn-default-outline(
|
||||
href="#"
|
||||
ng-click="switchToStudent($event,'" + location + "')"
|
||||
) #{translate("half_price_student")}
|
||||
) #{translate("special_price_student")}
|
||||
|
||||
mixin allCardsAndControls(controlsRowSpaced, listLocation)
|
||||
- var location = listLocation ? 'card_' + listLocation : 'card'
|
||||
|
@ -173,8 +200,9 @@ mixin allCardsAndControls(controlsRowSpaced, listLocation)
|
|||
.card-header
|
||||
h2 #{translate("personal")}
|
||||
h5.tagline #{translate("tagline_personal")}
|
||||
.circle #{translate("free")}
|
||||
+features_free(location)
|
||||
.circle
|
||||
+price_personal
|
||||
+features_personal(location)
|
||||
.col-md-4
|
||||
.card.card-highlighted
|
||||
.best-value
|
||||
|
@ -198,8 +226,8 @@ mixin allCardsAndControls(controlsRowSpaced, listLocation)
|
|||
.col-md-4
|
||||
.card.card-first
|
||||
.card-header
|
||||
h2 #{translate("personal")}
|
||||
h5.tagline #{translate("tagline_personal")}
|
||||
h2 #{translate("free")}
|
||||
h5.tagline #{translate("tagline_free")}
|
||||
.circle #{translate("free")}
|
||||
+features_free(location)
|
||||
|
||||
|
@ -209,4 +237,4 @@ mixin allCardsAndControls(controlsRowSpaced, listLocation)
|
|||
|
||||
.col-md-4
|
||||
.card.card-last
|
||||
+card_student_monthly(location)
|
||||
+card_student_monthly(location)
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
|
||||
//- Features Tables
|
||||
mixin table_premium
|
||||
table.card.plans-table
|
||||
table.card.plans-table.plans-table-main
|
||||
tr
|
||||
th
|
||||
th #{translate("free")}
|
||||
th #{translate("personal")}
|
||||
th #{translate("collaborator")}
|
||||
.outer.outer-top
|
||||
|
@ -15,6 +16,8 @@ mixin table_premium
|
|||
tr
|
||||
td #{translate("price")}
|
||||
td #{translate("free")}
|
||||
td
|
||||
+price_personal
|
||||
td
|
||||
+price_collaborator
|
||||
td
|
||||
|
@ -42,6 +45,8 @@ mixin table_premium
|
|||
td
|
||||
td
|
||||
+btn_buy_free('table')
|
||||
td
|
||||
+btn_buy_personal('table')
|
||||
td
|
||||
+btn_buy_collaborator('table')
|
||||
.outer.outer-btm
|
||||
|
@ -60,10 +65,10 @@ mixin table_cell_student(feature)
|
|||
span.sr-only Feature not included
|
||||
|
||||
mixin table_student
|
||||
table.card.plans-table
|
||||
table.card.plans-table.plans-table-student
|
||||
tr
|
||||
th
|
||||
th #{translate("personal")}
|
||||
th #{translate("free")}
|
||||
th #{translate("student")} (#{translate("annual")})
|
||||
.outer.outer-top
|
||||
.outer-content
|
||||
|
|
|
@ -18,4 +18,4 @@ mixin printPlan(plan)
|
|||
|
||||
mixin printPlans(plans)
|
||||
each plan in plans
|
||||
+printPlan(plan)
|
||||
+printPlan(plan)
|
||||
|
|
|
@ -47,7 +47,7 @@ block content
|
|||
div(ng-if="trialLength")
|
||||
span !{translate("first_few_days_free", {trialLen:'{{trialLength}}'})}
|
||||
span(ng-if="coupon.discountMonths && coupon.discountRate") - {{coupon.discountMonths}} #{translate("month")}s {{coupon.discountRate}}% Off
|
||||
|
||||
|
||||
div(ng-if="price")
|
||||
- var priceAngularExp = "<strong>{{ availableCurrencies[currencyCode]['symbol'] }}{{ price.total }}</strong>";
|
||||
span(ng-if="!coupon.singleUse && monthlyBilling")
|
||||
|
@ -235,7 +235,7 @@ block content
|
|||
- priceBreakdownAngularExp += " + " ;
|
||||
- priceBreakdownAngularExp += "{{availableCurrencies[currencyCode]['symbol']}}{{ price.tax }} tax)";
|
||||
hr.thin
|
||||
span
|
||||
span
|
||||
| Total:
|
||||
|
|
||||
span(ng-if="!coupon.singleUse && monthlyBilling")
|
||||
|
@ -283,7 +283,7 @@ block content
|
|||
a.btn-primary.btn.plansPageStudentLink(
|
||||
href,
|
||||
ng-click="switchToStudent()"
|
||||
) #{translate("half_price_student")}
|
||||
) #{translate("special_price_student")}
|
||||
|
||||
.card.card-first
|
||||
.paymentPageFeatures
|
||||
|
@ -295,7 +295,10 @@ block content
|
|||
- var collaboratorCount = 'Unlimited'
|
||||
else
|
||||
- var collaboratorCount = plan.features.collaborators
|
||||
| #{translate("collabs_per_proj", {collabcount:collaboratorCount})}
|
||||
if plan.features.collaborators == 1
|
||||
| #{translate("collabs_per_proj_single", {collabcount:collaboratorCount})}
|
||||
else
|
||||
| #{translate("collabs_per_proj", {collabcount:collaboratorCount})}
|
||||
p #{translate("work_on_single_version")}. #{translate("view_collab_edits")} in real time.
|
||||
|
||||
h3 #{translate("full_doc_history")}
|
||||
|
|
|
@ -38,6 +38,7 @@ block content
|
|||
|
||||
.row.row-spaced-large.text-centered
|
||||
.col-xs-12
|
||||
p.text-centered !{translate('also_provides_free_plan', { appName:'{{settings.appName}}', registerLinkOpen: '<a href="/register">', registerLinkClose: '</a>' })}
|
||||
i.fa.fa-cc-mastercard.fa-2x(aria-hidden="true")
|
||||
span.sr-only Mastercard accepted
|
||||
i.fa.fa-cc-visa.fa-2x(aria-hidden="true")
|
||||
|
|
|
@ -16,6 +16,10 @@ App.factory('MultiCurrencyPricing', function() {
|
|||
monthly: '$8',
|
||||
annual: '$80'
|
||||
},
|
||||
personal: {
|
||||
monthly: '$10',
|
||||
annual: '$120'
|
||||
},
|
||||
collaborator: {
|
||||
monthly: '$15',
|
||||
annual: '$180'
|
||||
|
@ -32,6 +36,10 @@ App.factory('MultiCurrencyPricing', function() {
|
|||
monthly: '€7',
|
||||
annual: '€70'
|
||||
},
|
||||
personal: {
|
||||
monthly: '€9',
|
||||
annual: '€108'
|
||||
},
|
||||
collaborator: {
|
||||
monthly: '€14',
|
||||
annual: '€168'
|
||||
|
@ -48,6 +56,10 @@ App.factory('MultiCurrencyPricing', function() {
|
|||
monthly: '£6',
|
||||
annual: '£60'
|
||||
},
|
||||
personal: {
|
||||
monthly: '£8',
|
||||
annual: '£96'
|
||||
},
|
||||
collaborator: {
|
||||
monthly: '£12',
|
||||
annual: '£144'
|
||||
|
@ -64,6 +76,10 @@ App.factory('MultiCurrencyPricing', function() {
|
|||
monthly: '60 kr',
|
||||
annual: '600 kr'
|
||||
},
|
||||
personal: {
|
||||
monthly: '73 kr',
|
||||
annual: '876 kr'
|
||||
},
|
||||
collaborator: {
|
||||
monthly: '110 kr',
|
||||
annual: '1320 kr'
|
||||
|
@ -79,6 +95,10 @@ App.factory('MultiCurrencyPricing', function() {
|
|||
monthly: '$9',
|
||||
annual: '$90'
|
||||
},
|
||||
personal: {
|
||||
monthly: '$11',
|
||||
annual: '$132'
|
||||
},
|
||||
collaborator: {
|
||||
monthly: '$17',
|
||||
annual: '$204'
|
||||
|
@ -95,6 +115,10 @@ App.factory('MultiCurrencyPricing', function() {
|
|||
monthly: '60 kr',
|
||||
annual: '600 kr'
|
||||
},
|
||||
personal: {
|
||||
monthly: '73 kr',
|
||||
annual: '876 kr'
|
||||
},
|
||||
collaborator: {
|
||||
monthly: '110 kr',
|
||||
annual: '1320 kr'
|
||||
|
@ -111,6 +135,10 @@ App.factory('MultiCurrencyPricing', function() {
|
|||
monthly: '50 kr',
|
||||
annual: '500 kr'
|
||||
},
|
||||
personal: {
|
||||
monthly: '60 kr',
|
||||
annual: '720 kr'
|
||||
},
|
||||
collaborator: {
|
||||
monthly: '90 kr',
|
||||
annual: '1080 kr'
|
||||
|
@ -127,6 +155,10 @@ App.factory('MultiCurrencyPricing', function() {
|
|||
monthly: '$10',
|
||||
annual: '$100'
|
||||
},
|
||||
personal: {
|
||||
monthly: '$12',
|
||||
annual: '$144'
|
||||
},
|
||||
collaborator: {
|
||||
monthly: '$18',
|
||||
annual: '$216'
|
||||
|
@ -143,6 +175,10 @@ App.factory('MultiCurrencyPricing', function() {
|
|||
monthly: '$10',
|
||||
annual: '$100'
|
||||
},
|
||||
personal: {
|
||||
monthly: '$12',
|
||||
annual: '$144'
|
||||
},
|
||||
collaborator: {
|
||||
monthly: '$18',
|
||||
annual: '$216'
|
||||
|
@ -159,6 +195,10 @@ App.factory('MultiCurrencyPricing', function() {
|
|||
monthly: 'Fr 8',
|
||||
annual: 'Fr 80'
|
||||
},
|
||||
personal: {
|
||||
monthly: 'Fr 10',
|
||||
annual: 'Fr 120'
|
||||
},
|
||||
collaborator: {
|
||||
monthly: 'Fr 15',
|
||||
annual: 'Fr 180'
|
||||
|
@ -175,6 +215,10 @@ App.factory('MultiCurrencyPricing', function() {
|
|||
monthly: '$12',
|
||||
annual: '$120'
|
||||
},
|
||||
personal: {
|
||||
monthly: '$13',
|
||||
annual: '$156'
|
||||
},
|
||||
collaborator: {
|
||||
monthly: '$20',
|
||||
annual: '$240'
|
||||
|
@ -224,6 +268,15 @@ App.controller('PlansController', function(
|
|||
}
|
||||
}
|
||||
|
||||
$scope.getPersonalPlanCode = function() {
|
||||
const { view } = $scope.ui
|
||||
if (view === 'annual') {
|
||||
return 'paid-personal-annual'
|
||||
} else {
|
||||
return `paid-personal${$scope.planQueryString}`
|
||||
}
|
||||
}
|
||||
|
||||
$scope.signUpNowClicked = function(plan, location) {
|
||||
if ($scope.ui.view === 'annual') {
|
||||
plan = `${plan}_annual`
|
||||
|
|
|
@ -288,20 +288,6 @@
|
|||
border-bottom: 0;
|
||||
padding: 18px;
|
||||
}
|
||||
/* highlighted column */
|
||||
td:nth-child(3) {
|
||||
position: relative;
|
||||
/* keep here position here, otherwise messes up border on safari when there is a bg color */
|
||||
&:before {
|
||||
/* needed for safafi */
|
||||
border-top: 1px solid @border-color-base;
|
||||
content: '';
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
td:first-child {
|
||||
border: 0;
|
||||
}
|
||||
|
@ -316,13 +302,6 @@
|
|||
color: @gray-med;
|
||||
}
|
||||
|
||||
/* highlighted column */
|
||||
td:nth-child(3),
|
||||
th:nth-child(3) {
|
||||
background-color: white;
|
||||
border-left: @border-width-base solid @border-color-base;
|
||||
border-right: @border-width-base solid @border-color-base;
|
||||
}
|
||||
.outer {
|
||||
left: -@border-width-base;
|
||||
right: -@border-width-base;
|
||||
|
@ -357,20 +336,22 @@
|
|||
}
|
||||
}
|
||||
|
||||
/* highlight rows on hover */
|
||||
tr:hover {
|
||||
td {
|
||||
background-color: @table-hover-bg;
|
||||
@media (min-width: @screen-sm-min) {
|
||||
/* highlight rows on hover */
|
||||
tr:hover {
|
||||
td {
|
||||
background-color: @table-hover-bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
tr:first-child:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
tr:last-child:hover {
|
||||
background-color: transparent;
|
||||
td {
|
||||
tr:first-child:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
tr:last-child:hover {
|
||||
background-color: transparent;
|
||||
td {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* tooltip */
|
||||
|
@ -411,4 +392,95 @@
|
|||
font-size: @font-size-small;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: @screen-xs-max) {
|
||||
tbody,
|
||||
thead {
|
||||
display: block;
|
||||
}
|
||||
tr {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: space-around;
|
||||
}
|
||||
th {
|
||||
font-size: 12px;
|
||||
}
|
||||
/* hide the first column header */
|
||||
tr:first-child {
|
||||
th:first-child {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
/* make the first column into a row */
|
||||
td:first-child {
|
||||
text-align: center;
|
||||
background: @gray-lightest;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.plans-table-main {
|
||||
td:nth-child(4),
|
||||
th:nth-child(4) {
|
||||
background-color: white;
|
||||
border-left: @border-width-base solid @border-color-base;
|
||||
border-right: @border-width-base solid @border-color-base;
|
||||
}
|
||||
tr:last-child {
|
||||
/* highlighted column */
|
||||
td:nth-child(4) {
|
||||
position: relative;
|
||||
/* keep here position here, otherwise messes up border on safari when there is a bg color */
|
||||
&:before {
|
||||
/* needed for safafi */
|
||||
border-top: 1px solid @border-color-base;
|
||||
content: '';
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: @screen-xs-max) {
|
||||
td,
|
||||
th {
|
||||
display: block;
|
||||
width: 25%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.plans-table-student {
|
||||
td:nth-child(3),
|
||||
th:nth-child(3) {
|
||||
background-color: white;
|
||||
border-left: @border-width-base solid @border-color-base;
|
||||
border-right: @border-width-base solid @border-color-base;
|
||||
}
|
||||
tr:last-child {
|
||||
/* highlighted column */
|
||||
td:nth-child(3) {
|
||||
position: relative;
|
||||
/* keep here position here, otherwise messes up border on safari when there is a bg color */
|
||||
&:before {
|
||||
/* needed for safafi */
|
||||
border-top: 1px solid @border-color-base;
|
||||
content: '';
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: @screen-xs-max) {
|
||||
td,
|
||||
th {
|
||||
display: block;
|
||||
width: 33.3%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue