Merge branch 'master' into dcl-olsl760b

This commit is contained in:
Douglas Lovell 2018-08-31 14:04:00 -03:00
commit 404e768d24
22 changed files with 232 additions and 101 deletions

View file

@ -46,11 +46,15 @@ module.exports =
else if err? and err?.message?.indexOf("could not be validated") != -1 else if err? and err?.message?.indexOf("could not be validated") != -1
logger.log {oldEmail, newEmail}, logger.log {oldEmail, newEmail},
"unable to change email in newsletter, user has previously unsubscribed or new email already exist on list" "unable to change email in newsletter, user has previously unsubscribed or new email already exist on list"
return callback(err) return callback()
else if err? and err.message.indexOf("is already a list member") != -1 else if err? and err.message.indexOf("is already a list member") != -1
logger.log {oldEmail, newEmail}, logger.log {oldEmail, newEmail},
"unable to change email in newsletter, new email is already on mailing list" "unable to change email in newsletter, new email is already on mailing list"
return callback() return callback()
else if err? and err?.message?.indexOf("looks fake or invalid") != -1
logger.log {oldEmail, newEmail},
"unable to change email in newsletter, email looks fake to mailchimp"
return callback()
else if err? else if err?
logger.err {err, oldEmail, newEmail}, "error changing email in newsletter" logger.err {err, oldEmail, newEmail}, "error changing email in newsletter"
return callback(err) return callback(err)

View file

@ -18,9 +18,9 @@ module.exports =
jobs = jobs =
partOfGroup: (cb)-> partOfGroup: (cb)->
SubscriptionGroupHandler.isUserPartOfGroup user.id, licence.group_subscription_id, cb SubscriptionGroupHandler.isUserPartOfGroup user._id, licence.group_subscription_id, cb
subscription: (cb)-> subscription: (cb)->
SubscriptionLocator.getUsersSubscription user.id, cb SubscriptionLocator.getUsersSubscription user._id, cb
async.series jobs, (err, results)-> async.series jobs, (err, results)->
{ partOfGroup, subscription } = results { partOfGroup, subscription } = results

View file

@ -15,30 +15,33 @@ planFeatures = require './planFeatures'
module.exports = SubscriptionController = module.exports = SubscriptionController =
plansPage: (req, res, next) -> plansPage: (req, res, next) ->
plans = SubscriptionViewModelBuilder.buildViewModel() if Settings.overleaf? && !req.query.plns
viewName = "subscriptions/plans" res.redirect "#{Settings.overleaf.host}/plans"
if req.query.v? else
viewName = "#{viewName}_#{req.query.v}" plans = SubscriptionViewModelBuilder.buildViewModel()
logger.log viewName:viewName, "showing plans page" viewName = "subscriptions/plans"
currentUser = null if req.query.v?
viewName = "#{viewName}_#{req.query.v}"
logger.log viewName:viewName, "showing plans page"
currentUser = null
GeoIpLookup.getCurrencyCode req.query?.ip || req.ip, (err, recomendedCurrency)-> GeoIpLookup.getCurrencyCode req.query?.ip || req.ip, (err, recomendedCurrency)->
return next(err) if err? return next(err) if err?
render = () -> render = () ->
res.render viewName, res.render viewName,
title: "plans_and_pricing" title: "plans_and_pricing"
plans: plans plans: plans
gaExperiments: Settings.gaExperiments.plansPage gaExperiments: Settings.gaExperiments.plansPage
recomendedCurrency:recomendedCurrency recomendedCurrency:recomendedCurrency
planFeatures: planFeatures planFeatures: planFeatures
user_id = AuthenticationController.getLoggedInUserId(req) user_id = AuthenticationController.getLoggedInUserId(req)
if user_id? if user_id?
UserGetter.getUser user_id, {signUpDate: 1}, (err, user) -> UserGetter.getUser user_id, {signUpDate: 1}, (err, user) ->
return next(err) if err? return next(err) if err?
currentUser = user currentUser = user
render()
else
render() render()
else
render()
#get to show the recurly.js page #get to show the recurly.js page
paymentPage: (req, res, next) -> paymentPage: (req, res, next) ->

View file

@ -9,11 +9,7 @@ module.exports =
apply: (webRouter, privateApiRouter, publicApiRouter) -> apply: (webRouter, privateApiRouter, publicApiRouter) ->
return unless Settings.enableSubscriptions return unless Settings.enableSubscriptions
if Settings.overleaf? webRouter.get '/user/subscription/plans', SubscriptionController.plansPage
webRouter.get '/user/subscription/plans', (req, res) ->
res.redirect "#{Settings.overleaf.host}/plans"
else
webRouter.get '/user/subscription/plans', SubscriptionController.plansPage
webRouter.get '/user/subscription', AuthenticationController.requireLogin(), SubscriptionController.userSubscriptionPage webRouter.get '/user/subscription', AuthenticationController.requireLogin(), SubscriptionController.userSubscriptionPage

View file

@ -112,7 +112,8 @@ module.exports = UserUpdater =
else if res.n == 0 # TODO: Check n or nMatched? else if res.n == 0 # TODO: Check n or nMatched?
return callback(new Error('Default email does not belong to user')) return callback(new Error('Default email does not belong to user'))
else else
NewsletterManager.changeEmail oldEmail, email, callback NewsletterManager.changeEmail oldEmail, email, ->
callback()

View file

@ -6,7 +6,7 @@
.row .row
.col-md-6 .col-md-6
h3 #{translate("faq_how_free_trial_works_question")} h3 #{translate("faq_how_free_trial_works_question")}
p #{translate('faq_how_free_trial_works_answer', { len:'{{trial_len}}' })} p #{translate('faq_how_does_free_trial_works_answer', { appName:'{{settings.appName}}', len:'{{trial_len}}' })}
.col-md-6 .col-md-6
h3 #{translate('faq_change_plans_question')} h3 #{translate('faq_change_plans_question')}
p #{translate('faq_change_plans_answer')} p #{translate('faq_change_plans_answer')}
@ -16,11 +16,18 @@
p #{translate('faq_do_collab_need_premium_answer')} p #{translate('faq_do_collab_need_premium_answer')}
.col-md-6 .col-md-6
h3 #{translate('faq_need_more_collab_question')} h3 #{translate('faq_need_more_collab_question')}
p !{translate('faq_need_more_collab_answer', { referFriendsLink: '<a href="/user/bonus">' + translate('referring_your_friends') + '</a>'})} if settings.overleaf
p !{translate('faq_need_more_collab_answer', { referFriendsLink: translate('referring_your_friends') })}
else
p !{translate('faq_need_more_collab_answer', { referFriendsLink: '<a href="/user/bonus">' + translate('referring_your_friends') + '</a>'})}
.row .row
.col-md-6 .col-md-6
h3 #{translate('faq_purchase_more_licenses_question')} h3 #{translate('faq_purchase_more_licenses_question')}
p !{translate('faq_purchase_more_licenses_answer', { groupLink: '<a href="/i/university/groups">' + translate('discounted_group_accounts') + '</a>' })} if settings.overleaf
p !{translate('faq_purchase_more_licenses_answer', { groupLink: translate('discounted_group_accounts') })}&nbsp;
a(href, ng-click="openGroupPlanModal()") #{translate("get_in_touch_for_details")}
else
p !{translate('faq_purchase_more_licenses_answer', { groupLink: '<a href="/i/university/groups">' + translate('discounted_group_accounts') + '</a>' })}
.col-md-6 .col-md-6
h3 #{translate('faq_monthly_or_annual_question')} h3 #{translate('faq_monthly_or_annual_question')}
p #{translate('faq_monthly_or_annual_answer')} p #{translate('faq_monthly_or_annual_answer')}
@ -30,4 +37,7 @@
p #{translate('faq_how_to_pay_answer')} p #{translate('faq_how_to_pay_answer')}
.col-md-6 .col-md-6
h3 #{translate('faq_pay_by_invoice_question')} h3 #{translate('faq_pay_by_invoice_question')}
p !{translate('faq_pay_by_invoice_answer', { groupLink: '<a href="/i/university/groups">' + translate('discounted_group_accounts') + '</a>' })} if settings.overleaf
p !{translate('faq_pay_by_invoice_answer', { groupLink: translate('discounted_group_accounts') })}
else
p !{translate('faq_pay_by_invoice_answer', { groupLink: '<a href="/i/university/groups">' + translate('discounted_group_accounts') + '</a>' })}

View file

@ -1,20 +1,23 @@
//- Buy Buttons //- Buy Buttons
mixin btn_buy_collaborator(location) mixin btn_buy_collaborator(location)
a.btn.btn-info( a.btn(
class=settings.overleaf ? 'btn-primary' : 'btn-info'
ng-href="/user/subscription/new?planCode={{ getCollaboratorPlanCode() }}&currency={{currencyCode}}", ng-href="/user/subscription/new?planCode={{ getCollaboratorPlanCode() }}&currency={{currencyCode}}",
ng-click="signUpNowClicked('collaborator','" + location + "')" ng-click="signUpNowClicked('collaborator','" + location + "')"
) )
span(ng-show="ui.view != 'annual'") #{translate("start_free_trial")} span(ng-show="ui.view != 'annual'") #{translate("start_free_trial")}
span(ng-show="ui.view == 'annual'") #{translate("buy_now")} span(ng-show="ui.view == 'annual'") #{translate("buy_now")}
mixin btn_buy_free(location) mixin btn_buy_free(location)
a.btn.btn-info( a.btn(
class=settings.overleaf ? 'btn-primary' : 'btn-info'
href="/register" href="/register"
style=(getLoggedInUserId() === null ? "" : "visibility: hidden") style=(getLoggedInUserId() === null ? "" : "visibility: hidden")
ng-click="signUpNowClicked('free','" + location + "')" ng-click="signUpNowClicked('free','" + location + "')"
) )
span.text-capitalize #{translate('get_started_now')} span.text-capitalize #{translate('get_started_now')}
mixin btn_buy_professional(location) mixin btn_buy_professional(location)
a.btn.btn-info( a.btn(
class=settings.overleaf ? 'btn-primary' : 'btn-info'
ng-href="/user/subscription/new?planCode=professional{{ ui.view == 'annual' && '-annual' || planQueryString}}&currency={{currencyCode}}" ng-href="/user/subscription/new?planCode=professional{{ ui.view == 'annual' && '-annual' || planQueryString}}&currency={{currencyCode}}"
ng-click="signUpNowClicked('professional','" + location + "')" ng-click="signUpNowClicked('professional','" + location + "')"
) )
@ -22,13 +25,15 @@ mixin btn_buy_professional(location)
span(ng-show="ui.view == 'annual'") #{translate("buy_now")} span(ng-show="ui.view == 'annual'") #{translate("buy_now")}
mixin btn_buy_student(location, plan) mixin btn_buy_student(location, plan)
if plan == 'annual' if plan == 'annual'
a.btn.btn-info( a.btn(
class=settings.overleaf ? 'btn-primary' : 'btn-info'
ng-href="/user/subscription/new?planCode=student-annual&currency={{currencyCode}}", ng-href="/user/subscription/new?planCode=student-annual&currency={{currencyCode}}",
ng-click="signUpNowClicked('student-annual','" + location + "')" ng-click="signUpNowClicked('student-annual','" + location + "')"
) #{translate("buy_now")} ) #{translate("buy_now")}
else else
//- planQueryString will contain _free_trial_7_days //- planQueryString will contain _free_trial_7_days
a.btn.btn-info( a.btn(
class=settings.overleaf ? 'btn-primary' : 'btn-info'
ng-href="/user/subscription/new?planCode=student{{planQueryString}}&currency={{currencyCode}}", ng-href="/user/subscription/new?planCode=student{{planQueryString}}&currency={{currencyCode}}",
ng-click="signUpNowClicked('student-monthly','" + location + "')" ng-click="signUpNowClicked('student-monthly','" + location + "')"
) #{translate("start_free_trial")} ) #{translate("start_free_trial")}

View file

@ -0,0 +1,25 @@
.row.row-spaced-large
.col-md-12
.page-header.plans-header.plans-subheader.text-centered
h2 #{translate('in_good_company')}
.row
.col-md-6
div
.row
.col-md-3
.circle-img
img(src=buildImgPath('advocates/erdogmus.jpg') alt="Professor Erdogmus")
.col-md-9
blockquote
p The ability to track changes and the real-time collaborative nature is what sets ShareLaTeX apart.
footer Professor Erdogmus, Northeastern University
.col-md-6
div
.row
.col-md-3
.circle-img
img(src=buildImgPath('advocates/henderson.jpg') alt="Rob Henderson")
.col-md-9
blockquote
p ShareLaTeX has proven to be a powerful and robust collaboration tool that is widely used in our School.
footer Rob Henderson, School Of Informatics And Computing - Indiana University

View file

@ -14,7 +14,7 @@ block content
.container(ng-controller="NewSubscriptionController" ng-cloak) .container(ng-controller="NewSubscriptionController" ng-cloak)
.row.card-group .row.card-group
.col-md-5.col-md-push-4 .col-md-5.col-md-push-4
.card.card-highlighted .card.card-highlighted(class=settings.overleaf ? 'card-border' : '')
.page-header .page-header
.row .row
.col-xs-9 .col-xs-9
@ -250,12 +250,13 @@ block content
hr hr
p.small.text-center We're confident that you'll love #{settings.appName}, but if not you can cancel anytime. We'll give you your money back, no questions asked, if you let us know within 30 days. p.small.text-center We're confident that you'll love #{settings.appName}, but if not you can cancel anytime. We'll give you your money back, no questions asked, if you let us know within 30 days.
hr if !settings.overleaf
span &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; hr
a(href="https://www.positivessl.com" style="font-family: arial; font-size: 10px; color: #212121; text-decoration: none;") span &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
img(src="https://www.positivessl.com/images-new/PositiveSSL_tl_trans.png" alt="SSL Certificate" title="SSL Certificate" border="0") a(href="https://www.positivessl.com" style="font-family: arial; font-size: 10px; color: #212121; text-decoration: none;")
div(style="font-family: arial;font-weight:bold;font-size:15px;color:#86BEE0;") img(src="https://www.positivessl.com/images-new/PositiveSSL_tl_trans.png" alt="SSL Certificate" title="SSL Certificate" border="0")
a(href="https://www.positivessl.com" style="color:#86BEE0; text-decoration: none;") div(style="font-family: arial;font-weight:bold;font-size:15px;color:#86BEE0;")
a(href="https://www.positivessl.com" style="color:#86BEE0; text-decoration: none;")
script(type="text/javascript"). script(type="text/javascript").

View file

@ -15,7 +15,7 @@ block content
.row .row
.col-md-12 .col-md-12
.page-header.centered.plans-header.text-centered .page-header.centered.plans-header.text-centered
h1.text-capitalize #{translate('instant_access')} h1.text-capitalize #{translate('get_instant_access_to')} #{settings.appName}
.row .row
.col-md-8.col-md-offset-2 .col-md-8.col-md-offset-2
p.text-centered #{translate("sl_benefits_plans")} p.text-centered #{translate("sl_benefits_plans")}
@ -89,7 +89,13 @@ block content
span #{translate('reduce_costs_group_licenses')} span #{translate('reduce_costs_group_licenses')}
br br
br br
a.btn.btn-info(href="/i/university/groups") #{translate('find_out_more')} if settings.overleaf
a.btn.btn-default(
href
ng-click="openGroupPlanModal()"
) #{translate('find_out_more')}
else
a.btn.btn-info(href="/i/university/groups") #{translate('find_out_more')}
div div
.row.row-spaced-large .row.row-spaced-large
@ -107,31 +113,8 @@ block content
.col-sm-12(ng-if="ui.view == 'student'") .col-sm-12(ng-if="ui.view == 'student'")
+table_student +table_student
.row.row-spaced-large if !settings.overleaf
.col-md-12 include _plans_quotes
.page-header.plans-header.plans-subheader.text-centered
h2 #{translate('in_good_company')}
.row
.col-md-6
div
.row
.col-md-3
.circle-img
img(src=buildImgPath('advocates/erdogmus.jpg') alt="Professor Erdogmus")
.col-md-9
blockquote
p The ability to track changes and the real-time collaborative nature is what sets ShareLaTeX apart.
footer Professor Erdogmus, Northeastern University
.col-md-6
div
.row
.col-md-3
.circle-img
img(src=buildImgPath('advocates/henderson.jpg') alt="Rob Henderson")
.col-md-9
blockquote
p ShareLaTeX has proven to be a powerful and robust collaboration tool that is widely used in our School.
footer Rob Henderson, School Of Informatics And Computing - Indiana University
include _plans_faq include _plans_faq
@ -139,8 +122,13 @@ block content
.col-md-12 .col-md-12
.plans-header.plans-subheader.text-centered .plans-header.plans-subheader.text-centered
h2 #{translate('still_have_questions')} h2 #{translate('still_have_questions')}
button.btn.btn-info.btn-header.text-capitalize(ng-controller="ContactGeneralModal" ng-click="openModal()") #{translate('get_in_touch')} button.btn.btn-header.text-capitalize(
class=settings.overleaf ? 'btn-default' : 'btn-info'
ng-controller="ContactGeneralModal"
ng-click="openModal()"
) #{translate('get_in_touch')}
!= moduleIncludes("contactModalGeneral", locals) != moduleIncludes("contactModalGeneral", locals)
.row.row-spaced .row.row-spaced
include _modal_group_inquiry

View file

@ -202,6 +202,8 @@ script(type="text/ng-template", id="affiliationFormTpl")
) {{ $select.selected.name }} ) {{ $select.selected.name }}
ui-select-choices( ui-select-choices(
repeat="university in $ctrl.universities | filter: $select.search" repeat="university in $ctrl.universities | filter: $select.search"
refresh="$ctrl.handleFreeformInputChange($select, 'name');"
refresh-delay="10"
) )
span( span(
ng-bind="university.name" ng-bind="university.name"
@ -219,6 +221,8 @@ script(type="text/ng-template", id="affiliationFormTpl")
) {{ $select.selected }} ) {{ $select.selected }}
ui-select-choices( ui-select-choices(
repeat="role in $ctrl.roles | filter: $select.search" repeat="role in $ctrl.roles | filter: $select.search"
refresh="$ctrl.handleFreeformInputChange($select);"
refresh-delay="10"
) )
span( span(
ng-bind="role" ng-bind="role"
@ -237,6 +241,8 @@ script(type="text/ng-template", id="affiliationFormTpl")
) {{ $select.selected }} ) {{ $select.selected }}
ui-select-choices( ui-select-choices(
repeat="department in $ctrl.departments | filter: $select.search" repeat="department in $ctrl.departments | filter: $select.search"
refresh="$ctrl.handleFreeformInputChange($select);"
refresh-delay="10"
) )
span( span(
ng-bind="department" ng-bind="department"

View file

@ -11,6 +11,18 @@ define [
ctrl.addUniversityToSelection = (universityName) -> ctrl.addUniversityToSelection = (universityName) ->
{ name: universityName, isUserSuggested: true } { name: universityName, isUserSuggested: true }
ctrl.handleFreeformInputChange = ($select, propertyToMatch) ->
if !$select.search? or $select.search == ""
return
resultingItem = $select.search
if $select.tagging?.fct?
resultingItem = $select.tagging.fct $select.search
if propertyToMatch?
matchingItem = _.find $select.items, (item) -> item[propertyToMatch] == $select.search
if matchingItem?
resultingItem = matchingItem
$select.searchInput.scope().$broadcast "uis:select", resultingItem
# Populates the countries dropdown # Populates the countries dropdown
UserAffiliationsDataService UserAffiliationsDataService
.getCountries() .getCountries()

View file

@ -0,0 +1,14 @@
.plans {
blockquote {
footer{
/* accessibility fix */
color: @ol-blue-gray-3;
}
}
.plans-header{
h1, h2 {
color: @gray-dark;
}
}
}

View file

@ -4,8 +4,9 @@
margin-bottom: @line-height-computed; margin-bottom: @line-height-computed;
} }
.best-value { .best-value {
color: @red; color: @brand-secondary;
line-height: @line-height-computed; line-height: @line-height-computed;
text-transform: capitalize;
} }
blockquote { blockquote {
footer{ footer{
@ -20,6 +21,22 @@
text-shadow: 0 0 0; text-shadow: 0 0 0;
} }
.card .btn { white-space:normal; } .card .btn { white-space:normal; }
.card.features {
margin-top: @line-height-computed;
i {
color: @red;
}
p {
margin: 0;
}
}
.btn-header {
font-family: @font-family-sans-serif;
margin-left: 10px;
margin-top: -10px;
text-shadow: 0 0 0;
}
.card .btn { white-space:normal; }
.card-group { .card-group {
.card-highlighted { .card-highlighted {
padding-top: @line-height-computed * 2; padding-top: @line-height-computed * 2;
@ -27,10 +44,10 @@
} }
} }
.card-first, .card-last { .card-first, .card-last {
background: @white-med; background: @plans-non-highlighted;
} }
.card-highlighted { .card-highlighted {
border: @highlight-border solid @gray-lighter; border: @border-width-base solid @border-color-base;
padding-top: 10px!important; padding-top: 10px!important;
.best-value { .best-value {
margin-bottom: 15px; margin-bottom: 15px;
@ -51,7 +68,7 @@
width: 120px; width: 120px;
height: 120px; height: 120px;
border-radius: 50%; border-radius: 50%;
background-color: @red; background-color: @brand-secondary;
color: white; color: white;
white-space: nowrap; white-space: nowrap;
span.small { span.small {
@ -148,10 +165,8 @@
Plans Test Plans Test
*/ */
@best-val-height: 35px; @best-val-height: 35px;
@highlight-border: 3px; @border-width-base: 3px;
@highlight-color: #d3584b;
@gray-med: #6d6d6d; @gray-med: #6d6d6d;
@white-med: #fdfdfd;
/* Media Queries */ /* Media Queries */
@media (max-width: @screen-sm-max) { @media (max-width: @screen-sm-max) {
@ -192,7 +207,7 @@
*/ */
.plans-table { .plans-table {
border: 1px solid @gray-lighter; border: 1px solid @gray-lighter;
background-color: @white-med; background-color: @plans-non-highlighted;
margin: @best-val-height 0 15px 0; margin: @best-val-height 0 15px 0;
table-layout: fixed; table-layout: fixed;
width: 100%; width: 100%;
@ -215,8 +230,8 @@
border-top: 0; border-top: 0;
font-family: @headings-font-family; font-family: @headings-font-family;
font-size: @font-size-h2; font-size: @font-size-h2;
font-weight: @headings-font-weight; font-weight: @headings-font-weight;
line-height: @headings-line-height; line-height: @headings-line-height;
padding: 18px; padding: 18px;
} }
@ -246,13 +261,13 @@
border-bottom: 0; border-bottom: 0;
padding: 18px; padding: 18px;
} }
/* highlighted column */ /* highlighted column */
td:nth-child(3) { td:nth-child(3) {
position: relative; position: relative;
/* keep here position here, otherwise messes up border on safari when there is a bg color */ /* keep here position here, otherwise messes up border on safari when there is a bg color */
&:before { &:before {
/* needed for safafi */ /* needed for safafi */
border-top: 1px solid @gray-lighter; border-top: 1px solid @border-color-base;
content: ''; content: '';
left: 0; left: 0;
position: absolute; position: absolute;
@ -277,17 +292,17 @@
/* highlighted column */ /* highlighted column */
td:nth-child(3), th:nth-child(3) { td:nth-child(3), th:nth-child(3) {
background-color: white; background-color: white;
border-left: @highlight-border solid @gray-lighter; border-left: @border-width-base solid @border-color-base;
border-right: @highlight-border solid @gray-lighter; border-right: @border-width-base solid @border-color-base;
} }
.outer { .outer {
left: -@highlight-border; left: -@border-width-base;
right: -@highlight-border; right: -@border-width-base;
position: absolute; position: absolute;
.outer-content { .outer-content {
background: white; background: white;
border: @highlight-border solid @gray-lighter; border: @border-width-base solid @border-color-base;
border-radius: @border-radius-base; border-radius: @border-radius-base;
font-size: @font-size-base; font-size: @font-size-base;
font-family: @font-family-sans-serif; font-family: @font-family-sans-serif;
@ -317,7 +332,7 @@
/* highlight rows on hover */ /* highlight rows on hover */
tr:hover { tr:hover {
td { td {
background-color: @gray-lightest; background-color: @table-hover-bg;
} }
} }
tr:first-child:hover { tr:first-child:hover {
@ -332,7 +347,7 @@
/* tooltip */ /* tooltip */
sup { sup {
color: @red; color: @brand-secondary;
cursor: pointer; cursor: pointer;
margin-left: 5px; margin-left: 5px;
} }

View file

@ -44,16 +44,16 @@
border: solid 1px @gray-lighter; border: solid 1px @gray-lighter;
border-radius: @border-radius-large 0 0 @border-radius-large; border-radius: @border-radius-large 0 0 @border-radius-large;
padding: (@line-height-computed / 2); padding: (@line-height-computed / 2);
color: @gray; color: @btn-switch-color;
&:hover, &:hover,
&:focus { &:focus {
color: @gray; color: @btn-switch-color;
text-decoration: none; text-decoration: none;
} }
&:hover { &:hover {
color: @gray-dark; color: @btn-switch-hover-color;
} }
& + & { & + & {
@ -62,12 +62,12 @@
} }
&-selected { &-selected {
color: @link-color; color: @link-active-color;
box-shadow: inset 0 -2px 0 0; box-shadow: inset 0 -2px 0 0;
&:hover, &:hover,
&:focus { &:focus {
color: @link-color; color: @link-active-color;
} }
} }
} }

View file

@ -50,4 +50,8 @@
border-bottom-right-radius: @border-radius-base; border-bottom-right-radius: @border-radius-base;
} }
} }
}
.card-border {
border: @border-width-base solid @border-color-base;
} }

View file

@ -0,0 +1,7 @@
.nav-pills {
> li {
> a {
border-radius: @btn-border-radius-base;
}
}
}

View file

@ -123,8 +123,14 @@
// Links rendered as pills // Links rendered as pills
> a { > a {
border-radius: @nav-pills-border-radius; border-radius: @nav-pills-border-radius;
border: 2px solid @link-color; border: 2px solid @nav-pills-link-color;
color: @nav-pills-link-color;
padding: 8px 13px; padding: 8px 13px;
&:hover,
&:focus {
background-color: @nav-pills-link-hover-bg;
border: 2px solid @nav-pills-link-hover-bg;
}
} }
+ li { + li {
margin-left: 2px; margin-left: 2px;
@ -136,6 +142,7 @@
&:hover, &:hover,
&:focus { &:focus {
color: @nav-pills-active-link-hover-color; color: @nav-pills-active-link-hover-color;
border: 2px solid @nav-pills-active-link-hover-bg;
background-color: @nav-pills-active-link-hover-bg; background-color: @nav-pills-active-link-hover-bg;
} }
} }
@ -247,4 +254,4 @@
margin-top: -1px; margin-top: -1px;
// Remove the top rounded corners here since there is a hard edge above the menu // Remove the top rounded corners here since there is a hard edge above the menu
.border-top-radius(0); .border-top-radius(0);
} }

View file

@ -13,6 +13,7 @@
//** Global textual link color. //** Global textual link color.
@link-color: @brand-primary; @link-color: @brand-primary;
@link-active-color: @link-color;
//** Link hover color set via `darken()` function. //** Link hover color set via `darken()` function.
@link-hover-color: darken(@link-color, 15%); @link-hover-color: darken(@link-color, 15%);
@ -87,6 +88,12 @@
@border-radius-base: 3px; @border-radius-base: 3px;
@border-radius-large: 5px; @border-radius-large: 5px;
@border-radius-small: 2px; @border-radius-small: 2px;
@border-width-base: 3px;
@border-color-base: @gray-lighter;
@btn-switch-color: @gray;
@btn-switch-hover-color: @gray-dark;
//** Global color for active items (e.g., navs or dropdowns). //** Global color for active items (e.g., navs or dropdowns).
@component-active-color: #fff; @component-active-color: #fff;
//** Global background color for active items (e.g., navs or dropdowns). //** Global background color for active items (e.g., navs or dropdowns).
@ -370,6 +377,9 @@
@nav-tabs-justified-active-link-border-color: @body-bg; @nav-tabs-justified-active-link-border-color: @body-bg;
//== Pills //== Pills
@nav-pills-link-color: @link-color;
@nav-pills-link-hover-color: @nav-link-hover-bg;
@nav-pills-link-hover-bg: @nav-link-hover-bg;
@nav-pills-border-radius: @border-radius-base; @nav-pills-border-radius: @border-radius-base;
@nav-pills-active-link-hover-bg: @component-active-bg; @nav-pills-active-link-hover-bg: @component-active-bg;
@nav-pills-active-link-hover-color: @component-active-color; @nav-pills-active-link-hover-color: @component-active-color;
@ -412,6 +422,10 @@
@pager-disabled-color: @pagination-disabled-color; @pager-disabled-color: @pagination-disabled-color;
// Plans
@table-hover-bg: @gray-lightest;
@plans-non-highlighted: #fdfdfd;
//== Jumbotron //== Jumbotron
// //
//## //##

View file

@ -34,14 +34,22 @@
@navbar-default-border : transparent; @navbar-default-border : transparent;
@navbar-brand-image-url : url(/img/ol-brand/overleaf-white.svg); @navbar-brand-image-url : url(/img/ol-brand/overleaf-white.svg);
@navbar-default-link-bg : transparent; @navbar-default-link-bg : transparent;
@nav-pills-active-link-hover-bg: @ol-dark-green;
@nav-pills-link-color : @btn-default-bg;
@nav-pills-link-hover-bg : darken(@ol-blue-gray-4, 8%); // match button-variant mixin
// Backgrounds // Backgrounds
@body-bg : #FFF; @body-bg : #FFF;
@content-alt-bg-color : @ol-blue-gray-1; @content-alt-bg-color : @ol-blue-gray-1;
// Border
@border-color-base: @ol-blue-gray-2;
// Typography // Typography
@text-small-color : @ol-type-color; @text-small-color : @ol-type-color;
@text-color : @ol-type-color; @text-color : @ol-type-color;
@link-color : @ol-blue; @link-color : @ol-blue;
@link-active-color : @ol-dark-green;
@link-hover-color : @ol-dark-blue; @link-hover-color : @ol-dark-blue;
// Button colors and sizing // Button colors and sizing
@ -68,6 +76,9 @@
@btn-info-bg : @ol-blue; @btn-info-bg : @ol-blue;
@btn-info-border : transparent; @btn-info-border : transparent;
@btn-switch-color : @ol-blue-gray-4;
@btn-switch-hover-color : darken(@ol-blue-gray-4, 8%);
// Padding // Padding
@padding-xs-horizontal : 8px; @padding-xs-horizontal : 8px;
@ -308,6 +319,10 @@
@log-line-no-color : #FFF; @log-line-no-color : #FFF;
@log-hints-color : @ol-blue-gray-4; @log-hints-color : @ol-blue-gray-4;
// Plans
@table-hover-bg : @ol-blue-gray-0;
@plans-non-highlighted : white;
// Portals // Portals
@black-alpha-strong : rgba(0,0,0,0.8); @black-alpha-strong : rgba(0,0,0,0.8);
@ -360,6 +375,7 @@
@purple: #7a43b6; @purple: #7a43b6;
@brand-primary: @ol-green; @brand-primary: @ol-green;
@brand-secondary: @ol-dark-green;
@brand-success: @green; @brand-success: @green;
@brand-info: @ol-blue; @brand-info: @ol-blue;
@brand-warning: @orange; @brand-warning: @orange;

View file

@ -20,6 +20,7 @@
@purple: #7a43b6; @purple: #7a43b6;
@brand-primary: @red; @brand-primary: @red;
@brand-secondary: @red;
@brand-success: @green; @brand-success: @green;
@brand-info: @blue; @brand-info: @blue;
@brand-warning: @orange; @brand-warning: @orange;

View file

@ -8,6 +8,7 @@
@import "_ol_style_includes.less"; @import "_ol_style_includes.less";
@import "components/embed-responsive.less"; @import "components/embed-responsive.less";
@import "components/icons.less"; @import "components/icons.less";
@import "components/navs-ol.less";
@import "components/pagination.less"; @import "components/pagination.less";
@import "components/publish-modal.less"; @import "components/publish-modal.less";
@ -15,4 +16,5 @@
@import "app/about.less"; @import "app/about.less";
@import "app/blog-posts.less"; @import "app/blog-posts.less";
@import "app/cms-page.less"; @import "app/cms-page.less";
@import "app/plans-ol.less";
@import "app/portals.less"; @import "app/portals.less";