Merge branch 'master-redesign' into master-redesign-templates-and-blog

Conflicts:
	public/coffee/app/main.coffee
This commit is contained in:
Henry Oswald 2014-07-08 11:14:56 +01:00
commit 6dc9d32104
27 changed files with 1902 additions and 787 deletions

View file

@ -123,6 +123,8 @@ module.exports = ProjectController =
TagsHandler.getAllTags user_id, cb TagsHandler.getAllTags user_id, cb
projects: (cb)-> projects: (cb)->
Project.findAllUsersProjects user_id, 'name lastUpdated publicAccesLevel archived owner_ref', cb Project.findAllUsersProjects user_id, 'name lastUpdated publicAccesLevel archived owner_ref', cb
subscription: (cb)->
SubscriptionLocator.getUsersSubscription user_id, cb
}, (err, results)-> }, (err, results)->
if err? if err?
logger.err err:err, "error getting data for project list page" logger.err err:err, "error getting data for project list page"
@ -138,6 +140,7 @@ module.exports = ProjectController =
priority_title: true priority_title: true
projects: projects projects: projects
tags: tags tags: tags
hasSubscription: !!results.subscription
} }
if Settings?.algolia?.institutions?.app_id? and Settings?.algolia?.institutions?.api_key? if Settings?.algolia?.institutions?.app_id? and Settings?.algolia?.institutions?.api_key?

View file

@ -15,17 +15,15 @@ module.exports = SubscriptionController =
plansPage: (req, res, next) -> plansPage: (req, res, next) ->
plans = SubscriptionViewModelBuilder.buildViewModel() plans = SubscriptionViewModelBuilder.buildViewModel()
if !req.session.user? if !req.session.user?
for plan in plans baseUrl = "/register?redir="
plan.href = "/register?redir=#{plan.href}" else
baseUrl = ""
viewName = "subscriptions/plans" viewName = "subscriptions/plans"
if req.query.variant?
viewName += "-#{req.query.variant}"
logger.log viewName:viewName, "showing plans page" logger.log viewName:viewName, "showing plans page"
res.render viewName, res.render viewName,
title: "Plans and Pricing" title: "Plans and Pricing"
plans: plans plans: plans
gaExperimentCode: gaExperimentCode baseUrl: baseUrl
#get to show the recurly.js page #get to show the recurly.js page
paymentPage: (req, res, next) -> paymentPage: (req, res, next) ->
@ -168,22 +166,3 @@ module.exports = SubscriptionController =
return next(error) if error? return next(error) if error?
req.body = body req.body = body
next() next()
gaExperimentCode = '''
<!-- Google Analytics Content Experiment code -->
<script>function utmx_section(){}function utmx(){}(function(){var
k='51652689-2',d=document,l=d.location,c=d.cookie;
if(l.search.indexOf('utm_expid='+k)>0)return;
function f(n){if(c){var i=c.indexOf(n+'=');if(i>-1){var j=c.
indexOf(';',i);return escape(c.substring(i+n.length+1,j<0?c.
length:j))}}}var x=f('__utmx'),xx=f('__utmxx'),h=l.hash;d.write(
'<sc'+'ript src="'+'http'+(l.protocol=='https:'?'s://ssl':
'://www')+'.google-analytics.com/ga_exp.js?'+'utmxkey='+k+
'&utmx='+(x?x:'')+'&utmxx='+(xx?xx:'')+'&utmxtime='+new Date().
valueOf()+(h?'&utmxhash='+escape(h.substr(1)):'')+
'" type="text/javascript" charset="utf-8"><\/sc'+'ript>')})();
</script><script>utmx('url','A/B');</script>
<!-- End of Google Analytics Content Experiment code -->
'''

View file

@ -9,7 +9,7 @@ block content
h1 About us h1 About us
h2 Meet the team behind your favourite online LaTeX editor. h2 Meet the team behind your favourite online LaTeX editor.
p.team-profile p.team-profile
span.img-container span.img-container.img-circle
img(src='/img/about/henry_oswald.jpg') img(src='/img/about/henry_oswald.jpg')
strong Henry Oswald strong Henry Oswald
| built an experimental LaTeX editor in 2011 which later became ShareLaTeX. He is a trained software engineer who lives in London. | built an experimental LaTeX editor in 2011 which later became ShareLaTeX. He is a trained software engineer who lives in London.
@ -18,7 +18,7 @@ block content
a(href='https://twitter.com/henryoswald') Follow me on Twitter a(href='https://twitter.com/henryoswald') Follow me on Twitter
| . | .
p.team-profile p.team-profile
span.img-container span.img-container.img-circle
img(src='/img/about/james_allen.jpg') img(src='/img/about/james_allen.jpg')
strong James Allen strong James Allen
| started working with Henry early in 2012 and finished his PhD in theoretical physics early in 2013. James began working on | started working with Henry early in 2012 and finished his PhD in theoretical physics early in 2013. James began working on

View file

@ -3,9 +3,6 @@ html(itemscope, itemtype='http://schema.org/Product')
block vars block vars
head head
- if (typeof(gaExperimentCode) !== "undefined" && gaExperimentCode)
#{gaExperimentCode}
- if (typeof(priority_title) !== "undefined" && priority_title) - if (typeof(priority_title) !== "undefined" && priority_title)
title= title + ' - Online LaTeX Editor ShareLaTeX' title= title + ' - Online LaTeX Editor ShareLaTeX'
- else - else

View file

@ -26,17 +26,17 @@ block content
ul.dropdown-menu(role="menu") ul.dropdown-menu(role="menu")
li li
a( a(
href="#", href,
ng-click="openCreateProjectModal()" ng-click="openCreateProjectModal()"
) Blank Project ) Blank Project
li li
a( a(
href="#", href,
ng-click="openCreateProjectModal('example')" ng-click="openCreateProjectModal('example')"
) Example Project ) Example Project
li li
a( a(
href="#", href,
ng-click="openUploadProjectModal()" ng-click="openUploadProjectModal()"
) Upload Project ) Upload Project
li.divider li.divider
@ -55,7 +55,8 @@ block content
a.menu-indent(href="/templates/bibliographies") Bibliographies a.menu-indent(href="/templates/bibliographies") Bibliographies
li li
a.menu-indent(href="/templates") View All » a.menu-indent(href="/templates") View All »
.row-spaced
.row-spaced(ng-if="projects.length > 0", ng-cloak)
ul.list-unstyled.folders-menu( ul.list-unstyled.folders-menu(
ng-controller="TagListController" ng-controller="TagListController"
) )
@ -67,7 +68,7 @@ block content
a(href, ng-click="filterProjects('shared')") Shared projects a(href, ng-click="filterProjects('shared')") Shared projects
li(ng-class="{active: (filter == 'archived')}") li(ng-class="{active: (filter == 'archived')}")
a(href, ng-click="filterProjects('archived')") Deleted projects a(href, ng-click="filterProjects('archived')") Deleted projects
li li(ng-if="tags.length > 0")
h2 Folders h2 Folders
li( li(
ng-repeat="tag in tags | filter:nonEmpty", ng-repeat="tag in tags | filter:nonEmpty",
@ -85,68 +86,40 @@ block content
| {{tag.name}} | {{tag.name}}
span.subdued ({{tag.project_ids.length}}) span.subdued ({{tag.project_ids.length}})
-if (settings.enableSubscriptions) .row-spaced(ng-if="projects.length == 0", ng-cloak)
.row-spaced .first-project
a(href="/user/bonus").btn.btn-info Upgrade Account div
i.fa.fa-arrow-up.fa-2x
div
strong Create your first project!
- if (showUserDetailsArea) - if (showUserDetailsArea)
.row-spaced#userProfileInformation(ng-cloak) .row-spaced#userProfileInformation(ng-if="projects.length > 0", ng-cloak)
div(ng-controller="UpdateForm").userProfileInformationArea div(ng-controller="UserProfileController")
div(ng-hide="hidePersonalInfoSection").alert.alert-info hr(ng-show="percentComplete < 100")
div(ng-show="percentComplete >= 100") .text-centered.user-profile(ng-show="percentComplete < 100")
h4 100% complete, well done!
div(ng-hide="percentComplete >= 100")
h4 Your profile is
strong {{percentComplete}}%
| complete
.progress .progress
.progress-bar.progress-bar-info(ng-style="{'width' : (percentComplete+'%')}") .progress-bar.progress-bar-info(ng-style="{'width' : (percentComplete+'%')}")
button#completeUserProfileInformation.btn.btn-primary( p.small
ng-hide="formVisable", | Your profile is
ng-click="showForm()" strong {{percentComplete}}%
) Complete now | complete
div(ng-show="formVisable") button#completeUserProfileInformation.btn.btn-info(
form(enctype='multipart/form-data', method='post') ng-hide="formVisable",
.form-group ng-click="openUserProfileModal()"
input.form-control( ) Complete
type='text',
name='first_name', -if (settings.enableSubscriptions && !hasSubscription)
ng-model="userInfoForm.first_name", .row-spaced(ng-if="projects.length > 0", ng-cloak).text-centered
ng-blur="sendUpdate()", hr
placeholder="First Name", p.small You are using the free version of ShareLaTeX.
select-when="formVisable" p
) a(href="/user/subscription/plans").btn.btn-primary Upgrade
.form-group p.small
input.form-control( | or unlock some free bonus features by
type='text', a(href="/user/bonus") sharing ShareLaTeX.
name='last_name',
ng-model="userInfoForm.last_name",
ng-blur="sendUpdate()",
placeholder='Last Name'
)
.form-group#institution_auto_complete
autocomplete(
ng-model="userInfoForm.institution",
data="institutions",
ng-blur="sendUpdate()",
on-type="updateInstitutionsList",
attr-placeholder="Institution",
attr-inputclass="form-control"
)
.form-group
input.form-control(
type='text',
name='role',
ng-model="userInfoForm.role",
placeholder='Role',
ng-blur="sendUpdate()",
list="_roles"
)
datalist#_roles
option(ng-repeat='role in roles') {{role}}
.col-md-10 .col-md-10
.container-fluid .container-fluid
@ -258,52 +231,59 @@ block content
.row.row-spaced .row.row-spaced
.col-md-12 .col-md-12
.card.card-thin .card.card-thin
- if (projects.length > 0) ul.list-unstyled.project-list.structured-list(
ul.list-unstyled.project-list(select-all-list, ng-cloak) select-all-list,
li.container-fluid ng-if="projects.length > 0",
.row ng-cloak
.col-md-6 )
input.select-all( li.container-fluid
select-all, .row
type="checkbox" .col-md-6
) input.select-all(
span.title TITLE select-all,
.col-md-2 type="checkbox"
span.owner OWNER )
.col-md-4 | TITLE
span.last-modified LAST MODIFIED .col-md-2
li.project_entry.container-fluid( | OWNER
ng-repeat="project in visibleProjects | orderBy:'lastUpdated':true", .col-md-4
ng-controller="ProjectListItemController" | LAST MODIFIED
) li.project_entry.container-fluid(
.row ng-repeat="project in visibleProjects | orderBy:'lastUpdated':true",
.col-md-6 ng-controller="ProjectListItemController"
input.select-item( )
select-individual, .row
type="checkbox", .col-md-6
ng-model="project.selected" input.select-item(
) select-individual,
span.title type="checkbox",
a.projectName(href="/project/{{project.id}}") {{project.name}} ng-model="project.selected"
span )
span.label.label-default(ng-repeat='tag in project.tags') span.title
| {{tag.name}} a.projectName(href="/project/{{project.id}}") {{project.name}}
.col-md-2 span
span.owner {{ownerName()}} span.label.label-default(ng-repeat='tag in project.tags')
.col-md-4 | {{tag.name}}
span.last-modified.isoDate {{project.lastUpdated | formatDate}} .col-md-2
- else span.owner {{ownerName()}}
.row .col-md-4
.span12 span.last-modified.isoDate {{project.lastUpdated | formatDate}}
.welcome li(
h1 ng-if="visibleProjects.length == 0",
i.fa.fa-arrow-left ng-cloak
| Welcome! Follow the arrow to get started )
p New to LaTeX? Start by having a look at our .row
a(href="/templates") templates .col-md-12.text-centered
| or small No projects
a(href="/learn") help guides div.welcome.text-centered(ng-if="projects.length == 0", ng-cloak)
| . h2 Welcome to ShareLaTeX!
p New to LaTeX? Start by having a look at our
a(href="/templates") templates
| or
a(href="/learn") help guides
| ,
br
| or create your first project on the left.
script(type='text/ng-template', id='newTagModalTemplate') script(type='text/ng-template', id='newTagModalTemplate')
.modal-header .modal-header
@ -436,3 +416,51 @@ block content
span Upload a zipped project span Upload a zipped project
.modal-footer .modal-footer
button.btn.btn-default(ng-click="cancel()") Cancel button.btn.btn-default(ng-click="cancel()") Cancel
script(type="text/ng-template", id="userProfileModalTemplate")
.modal-header
h3 Your Profile
.modal-body
form(enctype='multipart/form-data', method='post')
.form-group
label(for="first_name") First Name
input.form-control(
type='text',
name='first_name',
ng-model="userInfoForm.first_name",
ng-blur="sendUpdate()",
placeholder="First Name",
select-when="formVisable"
)
.form-group
label(for="last_name") Last Name
input.form-control(
type='text',
name='last_name',
ng-model="userInfoForm.last_name",
ng-blur="sendUpdate()",
placeholder='Last Name'
)
.form-group#institution_auto_complete
label(for="institution") Institution
autocomplete(
ng-model="userInfoForm.institution",
name="institution",
data="institutions",
ng-blur="sendUpdate()",
on-type="updateInstitutionsList",
attr-placeholder="Institution",
attr-inputclass="form-control"
)
.form-group
label(for="role") Role
input.form-control(
type='text',
name='role',
ng-model="userInfoForm.role",
placeholder='Role',
ng-blur="sendUpdate()",
typeahead="role for role in roles | filter:$viewValue"
)
.modal-footer
button.btn.btn-info(ng-click="done()") Done

View file

@ -1,104 +1,106 @@
extends ../layout extends ../layout
block content block content
.container.bonus.box .content.content-alt
.row .container.bonus
.span8.offset2 .row
.page-header .col-md-8.col-md-offset-2
h1 Recommend ShareLaTeX. Get free stuff. .card
.container-fluid
.row
.col-md-12
.page-header
h1 Help us spread the word about ShareLaTeX.
.row .row
.span6.offset3 .col-md-10.col-md-offset-1
h2 Help us spread the word about ShareLaTeX. h2 Share ShareLaTeX with your friends and colleagues and unlock the rewards below
.row .row
.span4.offset4.bonus-banner .col-md-8.col-md-offset-2.bonus-banner
.bonus-top .bonus-top
.row .row
.span4.offset4.bonus-banner .col-md-8.col-md-offset-2.bonus-banner
.title .title
a(href='https://twitter.com/share?text=is%20trying%20out%20the%20online%20LaTeX%20Editor%20ShareLaTeX&url=#{encodeURIComponent(buildReferalUrl("t"))}&counturl=https://www.sharelatex.com', target="_blank").twitter Tweet a(href='https://twitter.com/share?text=is%20trying%20out%20the%20online%20LaTeX%20Editor%20ShareLaTeX&url=#{encodeURIComponent(buildReferalUrl("t"))}&counturl=https://www.sharelatex.com', target="_blank").twitter Tweet
.row .row
.span4.offset4.bonus-banner .col-md-8.col-md-offset-2.bonus-banner
.title .title
a(href='#', onclick='postToFeed(); return false;').facebook Post on Facebook a(href='#', onclick='postToFeed(); return false;').facebook Post on Facebook
.row .row
.span4.offset4.bonus-banner .col-md-8.col-md-offset-2.bonus-banner
.title .title
a(href="https://plus.google.com/share?url=#{encodeURIComponent(buildReferalUrl("gp"))}", onclick="javascript:window.open(this.href, '', 'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=600,width=600');return false;").google-plus Share us on Google+ a(href="https://plus.google.com/share?url=#{encodeURIComponent(buildReferalUrl('gp'))}", onclick="javascript:window.open(this.href, '', 'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=600,width=600');return false;").google-plus Share us on Google+
.row .row
.span4.offset4.bonus-banner .col-md-8.col-md-offset-2.bonus-banner
.title .title
a(href='mailto:?subject=Online LaTeX editor you may like &body=Hey, I have been using the online LaTeX editor ShareLaTeX recently and thought you might like to check it out. #{encodeURIComponent(buildReferalUrl("e"))}', title='Share by Email').email Email us to your friends a(href='mailto:?subject=Online LaTeX editor you may like &body=Hey, I have been using the online LaTeX editor ShareLaTeX recently and thought you might like to check it out. #{encodeURIComponent(buildReferalUrl("e"))}', title='Share by Email').email Email us to your friends
.row .row
.span4.offset4.bonus-banner .col-md-8.col-md-offset-2.bonus-banner
.title .title
a(href='#link-modal', data-toggle="modal").link Link to us from your website a(href='#link-modal', data-toggle="modal").link Link to us from your website
.row .row
.span4.offset4.bonus-banner .col-md-10.col-md-offset-1.bonus-banner
h2.direct-link Direct Link h2.direct-link Direct Link
.well #{buildReferalUrl("d")} pre.text-centered #{buildReferalUrl("d")}
.row.ab-bonus .row.ab-bonus
.span6.offset3 .col-md-10.col-md-offset-1.bonus-banner
p.thanks When someone starts using ShareLaTeX after your recommendation we'll give you some <strong>free stuff</strong> to say thanks! Check your progress below. p.thanks When someone starts using ShareLaTeX after your recommendation we'll give you some <strong>free stuff</strong> to say thanks! Check your progress below.
.row.ab-bonus .row.ab-bonus
.span6.offset3(style="position: relative; height: 30px; margin-top: 20px;") .col-md-10.col-md-offset-1.bonus-banner(style="position: relative; height: 30px; margin-top: 20px;")
- for (var i = 0; i <= 10; i++) { - for (var i = 0; i <= 10; i++) {
- if (refered_user_count == i) - if (refered_user_count == i)
.number(style="left: #{i}0%").active #{i} .number(style="left: #{i}0%").active #{i}
- else - else
.number(style="left: #{i}0%") #{i} .number(style="left: #{i}0%") #{i}
- } - }
.row.ab-bonus .row.ab-bonus
.span6.offset3 .col-md-10.col-md-offset-1.bonus-banner
.progress(style="height: 25px") .progress
- if (refered_user_count == 0) - if (refered_user_count == 0)
div(style="text-align: center; padding: 4px;") Spread the word and fill this bar up div(style="text-align: center; padding: 4px;") Spread the word and fill this bar up
.bar(style="width: #{refered_user_count}0%") .progress-bar.progress-bar-info(style="width: #{refered_user_count}0%")
.row.ab-bonus .row.ab-bonus
.span6.offset3(style="position: relative; height: 70px;") .col-md-10.col-md-offset-1.bonus-banner(style="position: relative; height: 70px;")
.perk(style="left: 10%;", class = refered_user_count >= 1 ? "active" : "") One free collaborator .perk(style="left: 10%;", class = refered_user_count >= 1 ? "active" : "") One free collaborator
.perk(style="left: 30%;", class = refered_user_count >= 3 ? "active" : "") Three free collaborators .perk(style="left: 30%;", class = refered_user_count >= 3 ? "active" : "") Three free collaborators
.perk(style="left: 60%;", class = refered_user_count >= 6 ? "active" : "") Free Dropbox and History .perk(style="left: 60%;", class = refered_user_count >= 6 ? "active" : "") Free Dropbox and History
.perk(style="left: 90%;", class = refered_user_count >= 9 ? "active" : "") Free Professional account .perk(style="left: 90%;", class = refered_user_count >= 9 ? "active" : "") Free Professional account
.row.ab-bonus .row.ab-bonus
.span6.offset3 .col-md-10.col-md-offset-1.bonus-banner
- if (refered_user_count == 0) - if (refered_user_count == 0)
p.thanks You've not introduced anyone to ShareLaTeX yet. Get sharing! p.thanks You've not introduced anyone to ShareLaTeX yet. Get sharing!
- else if (refered_user_count == 1) - else if (refered_user_count == 1)
p.thanks You've introduced <strong>#{refered_user_count}</strong> person to ShareLaTeX. Good job, but can you get some more? p.thanks You've introduced <strong>#{refered_user_count}</strong> person to ShareLaTeX. Good job, but can you get some more?
- else - else
p.thanks You've introduced <strong>#{refered_user_count}</strong> people to ShareLaTeX. Good job! p.thanks You've introduced <strong>#{refered_user_count}</strong> people to ShareLaTeX. Good job!
#link-modal.modal.hide #link-modal.modal.hide
.modal-header .modal-header
h3 Link to ShareLaTeX h3 Link to ShareLaTeX
.modal-body .modal-body
p You can link to ShareLaTeX with the following HTML: p You can link to ShareLaTeX with the following HTML:
p p
textarea(readonly=true) textarea(readonly=true)
<a href="#{buildReferalUrl("d")}">Online LaTeX Editor ShareLaTeX</a> <a href="#{buildReferalUrl("d")}">Online LaTeX Editor ShareLaTeX</a>
p Thanks! p Thanks!
.modal-footer .modal-footer
button.btn(data-dismiss="modal") Close button.btn(data-dismiss="modal") Close
include ../general/social-footer
include ../general/small-footer
script(type='text/javascript', src='//platform.twitter.com/widgets.js') script(type='text/javascript', src='//platform.twitter.com/widgets.js')
script(src='https://connect.facebook.net/en_US/all.js') script(src='https://connect.facebook.net/en_US/all.js')
script(type='text/javascript') script(type='text/javascript').
FB.init({appId: "148710621956179", status: true, cookie: true}); FB.init({appId: "148710621956179", status: true, cookie: true});
function postToFeed() { function postToFeed() {
@ -121,7 +123,7 @@ block content
FB.ui(obj, callback); FB.ui(obj, callback);
} }
script(type="text/javascript") script(type="text/javascript").
$(function() { $(function() {
$(".twitter").click(function() { $(".twitter").click(function() {
ga('send', 'event', 'referal-button', 'clicked', "twitter") ga('send', 'event', 'referal-button', 'clicked', "twitter")

View file

@ -7,12 +7,6 @@ mixin printPlan(plan)
tr tr
td td
strong #{plan.name} strong #{plan.name}
td
ul
-for benefit in plan.featureDescription
li #{benefit.text} &nbsp;
if benefit.comingSoon
span.label.label-info coming soon
td td
-if (plan.annual) -if (plan.annual)
| $#{plan.price / 100} / year | $#{plan.price / 100} / year
@ -20,67 +14,71 @@ mixin printPlan(plan)
| $#{plan.price / 100} / month | $#{plan.price / 100} / month
td td
-if (subscription.state == "free-trial") -if (subscription.state == "free-trial")
a(href="/user/subscription/new?planCode=#{plan.planCode}").btn.btn-primary Subscribe to this plan a(href="/user/subscription/new?planCode=#{plan.planCode}").btn.btn-success Subscribe to this plan
-else if (plan.planCode == subscription.planCode) -else if (plan.planCode == subscription.planCode)
button.btn.disabled Your plan button.btn.disabled Your plan
-else -else
form(action="/user/subscription/update",method="post") form(action="/user/subscription/update",method="post")
input(type="hidden", name="_csrf", value=csrfToken) input(type="hidden", name="_csrf", value=csrfToken)
input(type="hidden",name="plan_code",value="#{plan.planCode}") input(type="hidden",name="plan_code",value="#{plan.planCode}")
input(type="submit",value="Change to this plan").btn.btn-primary input(type="submit",value="Change to this plan").btn.btn-success
mixin printPlans(plans) mixin printPlans(plans)
-each plan in plans -each plan in plans
mixin printPlan(plan) mixin printPlan(plan)
block content block content
include ../general/sidebar .content.content-alt
.container
.row
.col-md-8.col-md-offset-2
.card
.page-header
h1 Your Subscription
case subscription.state
when "free-trial"
p You are currently using a free trial which expires on <strong>#{subscription.expiresAt}</strong>.
p Choose a plan below to subscribe to.
when "active"
p You are currently subscribed to the <strong>#{subscription.name}</strong> plan.
a(href, ng-click="changePlan = true") Change Plan.
p The next payment of <strong>#{subscription.price}</strong> will be collected on <strong>#{subscription.nextPaymentDueAt}</strong>
p.pull-right
.content-with-navigation-sidebar p: form(action="/user/subscription/cancel",method="post")
.box input(type="hidden", name="_csrf", value=csrfToken)
.row-fluid a(href="/user/subscription/billing-details/edit").btn.btn-info Update your billing details
.span12 | &nbsp;
.page-header input(type="submit", value="Cancel your subscription").btn.btn-primary#cancelSubscription
h1 Your Subscription when "canceled"
p: case subscription.state p You are currently subscribed to the <strong>#{subscription.name}</strong> plan.
when "free-trial" p Your subscription has been canceled and will terminate on <strong>#{subscription.nextPaymentDueAt}</strong>. No further payments will be taken.
p You are currently using a free trial which expires on <strong>#{subscription.expiresAt}</strong>. p: form(action="/user/subscription/reactivate",method="post")
p Choose a plan below to subscribe to. input(type="hidden", name="_csrf", value=csrfToken)
when "active" input(type="submit",value="Reactivate your subscription").btn.btn-success
p You are currently subscribed to the <strong>#{subscription.name}</strong> plan. when "expired"
p The next payment of <strong>#{subscription.price}</strong> will be collected on <strong>#{subscription.nextPaymentDueAt}</strong> p Your subscription has expired.
form(action="/user/subscription/cancel",method="post") a(href="/user/subscription/plans") Create New Subscription
input(type="hidden", name="_csrf", value=csrfToken) default
input(type="submit",value="Cancel your subscription").btn.btn-danger#cancelSubscription p There is a problem with your subscription. Please contact us for more information.
p: a(href="/user/subscription/billing-details/edit").btn.btn-primary Update your billing details
when "canceled"
p You are currently subscribed to the <strong>#{subscription.name}</strong> plan.
p Your subscription has been canceled and will terminate on <strong>#{subscription.nextPaymentDueAt}</strong>. No further payments will be taken.
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 Your subscription has expired.
a(href="/user/subscription/plans") Create New Subscription
default
p There is a problem with your subscription. Please contact us for more information.
-if(subscription.groupPlan) -if(subscription.groupPlan)
a(href="/subscription/group").btn.btn-success Manage Group a(href="/subscription/group").btn.btn-success Manage Group
hr
h2 Change plan div(ng-show="changePlan", ng-cloak)
p: table.table hr
tr h2 Change plan
th Name p: table.table
th Features tr
th Price th Name
th th Price
mixin printPlans(plans.studentAccounts) th
mixin printPlans(plans.individualMonthlyPlans) mixin printPlans(plans.studentAccounts)
mixin printPlans(plans.individualAnnualPlans) mixin printPlans(plans.individualMonthlyPlans)
mixin printPlans(plans.individualAnnualPlans)
script(type="text/javascript") script(type="text/javascript").
$('#cancelSubscription').on("click", function() { $('#cancelSubscription').on("click", function() {
ga('send', 'event', 'subscription-funnel', 'cancelation') ga('send', 'event', 'subscription-funnel', 'cancelation')
}) })

View file

@ -4,11 +4,18 @@ block content
- locals.supressDefaultJs = true - locals.supressDefaultJs = true
script(data-main=jsPath+'main.js', src=jsPath+'libs/require.js', baseurl=jsPath) script(data-main=jsPath+'main.js', src=jsPath+'libs/require.js', baseurl=jsPath)
script(src=jsPath+'libs/recurly.min.js') script(src=jsPath+'libs/recurly.min.js')
link(rel='stylesheet', href='/recurly/recurly.css')
#billingDetailsForm.box Loading billing details form... .content.content-alt
.container
.row
.col-md-6.col-md-offset-3
.card
.page-header
h1.text-centered Update Your Billing Details
#billingDetailsForm Loading billing details form...
script(type="text/javascript")
script(type="text/javascript").
Recurly.config(!{recurlyConfig}) Recurly.config(!{recurlyConfig})
Recurly.buildBillingInfoUpdateForm({ Recurly.buildBillingInfoUpdateForm({
target : "#billingDetailsForm", target : "#billingDetailsForm",
@ -17,6 +24,5 @@ block content
accountCode : "#{user.id}" accountCode : "#{user.id}"
}); });
include ../general/small-footer

View file

@ -1,52 +1,84 @@
extends ../layout extends ../layout
block content block content
.container.box .content.content-alt
.row .container
.span12 .row
.page-header .col-md-10.col-md-offset-1
h2 Group Admin .card(ng-controller="GroupMembersController")
.page-header
.pull-right(ng-cloak)
small(ng-show="selectedUsers.length == 0") You have added <strong>{{ users.length }}</strong> of <strong>{{ groupSize }}</strong> available members
a.btn.btn-danger(
href,
ng-show="selectedUsers.length > 0"
ng-click="removeMembers()"
) Remove from group
h1 Group Account
div You are allowed up to .row-spaced-small
strong #{subscription.membersLimit} ul.list-unstyled.structured-list(
| members in this group select-all-list,
ng-cloak
)
li.container-fluid
.row
.col-md-5
input.select-all(
select-all,
type="checkbox"
)
span.email EMAIL
.col-md-5
span.name NAME
.col-md-2
span.registered REGISTERED
li.container-fluid(
ng-repeat="user in users | orderBy:'email':true",
ng-controller="GroupMemberListItemController"
)
.row
.col-md-5
input.select-item(
select-individual,
type="checkbox",
ng-model="user.selected"
)
span.email {{ user.email }}
.col-md-5
span.name {{ user.first_name }} {{ user.last_name }}
.col-md-2
span.registered
i.fa.fa-check.text-success(ng-show="!user.holdingAccount")
i.fa.fa-times(ng-show="user.holdingAccount")
li(
ng-if="users.length == 0",
ng-cloak
)
.row
.col-md-12.text-centered
small No members
table.table-striped.table.table-striped div(ng-if="users.length < groupSize", ng-cloak)
thead hr
tr p
th .small Add more members
input(type="checkbox").select-all form.form
th email .row
th Name .col-xs-6
th Registered input.form-control(
name="email",
type="text",
placeholder="jane@example.com, joe@example.com",
ng-model="inputs.emails",
on-enter="addMembers()"
)
.col-xs-6
button.btn.btn-primary(ng-click="addMembers()") Add
tbody#userList script(type="text/javascript").
-each user in users window.users = !{JSON.stringify(users)};
tr window.groupSize = #{subscription.membersLimit};
td
input(type="checkbox").select-one
td #{user.email}
td #{user.first_name} #{user.last_name}
td #{!user.holdingAccount}
td
input(type="hidden", name="user_id", value=user._id).user_id {{user._id}}
div
button.btn.btn-danger#deleteUsers Delete Selected
div &nbsp;
div
form.well.form-inline#addUserToGroup
div
input(name="_csrf", type="hidden", value=csrfToken)
input(name="email", type="email", placeholder="someone@email.com")#newEmail.email.input-large &nbsp;
button.btn.btn-primary.addUser Add
div &nbsp;
div Add multiple emails seperated with commas or space.
- locals.supressDefaultJs = true
script(data-main='/js/SubscriptionGroupsManager.js', src='/js/libs/require.js')

View file

@ -4,15 +4,21 @@ block content
- locals.supressDefaultJs = true - locals.supressDefaultJs = true
script(data-main=jsPath+'main.js', src=jsPath+'libs/require.js', baseurl=jsPath) script(data-main=jsPath+'main.js', src=jsPath+'libs/require.js', baseurl=jsPath)
script(src=jsPath+'libs/recurly.min.js') script(src=jsPath+'libs/recurly.min.js')
link(rel='stylesheet', href='/recurly/recurly.css')
#subscribeForm.box Loading subscription form... .content.content-alt
.container
.row
.col-md-6.col-md-offset-3
.card
.page-header
h1.text-centered New Subscription
#subscribeForm Loading subscription form...
script(type="text/javascript") script(type="text/javascript")
ga('send', 'event', 'pageview', 'payment_form', "#{plan_code}") ga('send', 'event', 'pageview', 'payment_form', "#{plan_code}")
script(type="text/javascript") script(type="text/javascript").
Recurly.config(!{recurlyConfig}) Recurly.config(!{recurlyConfig})
var recurlySubscriptionFormConfig = !{subscriptionFormOptions} var recurlySubscriptionFormConfig = !{subscriptionFormOptions}
recurlySubscriptionFormConfig.successHandler = function(){ recurlySubscriptionFormConfig.successHandler = function(){
@ -22,5 +28,3 @@ block content
Recurly.buildSubscriptionForm(recurlySubscriptionFormConfig); Recurly.buildSubscriptionForm(recurlySubscriptionFormConfig);
include ../general/small-footer

View file

@ -1,168 +0,0 @@
extends ../layout
mixin liSection(feature)
| #{feature.text}
-if(feature.comingSoon)
span.label.label-info coming soon
-if(feature.beta)
span.label.label-warning beta
mixin plan(plan, cssClass, monthly)
.pricing-table
ul(class=cssClass)
li.pricing-header-row-1
.package-title
h2.no-bold #{plan.name}
li.pricing-header-row-2
.package-price
if plan.price == 0
h1.free Free forever
else
h1.no-bold
| $#{plan.price/100}
if monthly
span.cents /month
else
span.cents /year
- var odd = false
- if(plan.planCode != "personal")
li.pricing-content-row-even
mixin liSection({text:"30 day free trial"})
-each feature in plan.featureDescription
- odd = !odd
- if(odd)
li.pricing-content-row-odd
mixin liSection(feature)
- else
li.pricing-content-row-even
mixin liSection(feature)
- if(plan.planCode == "personal")
li.pricing-content-row-even
mixin liSection({text:""})
li.pricing-footer
- var href = '/user/subscription/new?planCode='+plan.planCode
- planIsPersonal = plan.planCode.indexOf("personal") != -1
- userNotLoggedIn = session && !session.user
-if(planIsPersonal)
- href = "/register"
-else if(userNotLoggedIn)
- href = "/register?redir="+href
a.btn.btn-success(href='#{href}').sign_up_now
| Sign Up Now!
block content
.container
.row
.span12.span-box
.page-header
h1 Choose your plan
blockquote.quote.pull-right
p
| This is one of the most useful resources I have ever found on the Internet.
br
| Fantastic execution and thoughtful attention to detail make this product shine!
small Benjamin Shepherd, Waterloo University
.row
.span12
.offset3
ul.nav.nav-pills.pricing-pills
li.active
a(href="#", data-target=".monthly-pricing", data-toggle="tab") Monthly
li
a(href="#", data-target=".annual-pricing", data-toggle="tab") Annual
li
a(href="#", data-target=".student-pricing", data-toggle="tab") Half price student plans
.row
.span12
.page-header
h2 Individual Plans
.pricing-steelblue.pricing-row
.tab-content
.tab-pane.active.monthly-pricing
.row
.span6.offset3.tagline.freeTrialBlurb
h1 Start your risk free <strong>30 day</strong> trial
.row
.span4
mixin plan(plans.personalAccount, "", true)
.span4
mixin plan(plans.allPlans['collaborator_free_trial'], "big", true)
.span4
mixin plan(plans.allPlans['professional_free_trial'], "", true)
.tab-pane.annual-pricing
.row
.span6.offset3.tagline.freeTrialBlurb
h1 Start your risk free <strong>30 day</strong> trial
.span4
mixin plan(plans.personalAccount, "", true)
.span4
mixin plan(plans.allPlans['collaborator-annual_free_trial'], "big", false)
.span4
mixin plan(plans.allPlans['prof-ann_free_trial'], "", false)
.tab-pane.student-pricing
.row
.span6.offset3.tagline.freeTrialBlurb
h1 Start your risk free <strong>30 day</strong> trial
.span4
mixin plan(plans.personalAccount, "", true)
.span4
mixin plan(plans.allPlans['student_free_trial'], "big", true)
.span4
mixin plan(plans.allPlans['stud-ann_free_trial'], "", false)
.pricing-steelblue.pricing-row
.tab-content
.tab-pane.active.monthly-pricing
.page-header
h2 Group Plans
.row
.span12.tagline
p Improve the workflow of your research group by unlocking ShareLaTeX's premium features for everyone on your team
.row
.span4
mixin plan(plans.groupMonthlyPlans[0], "", true)
.span4
mixin plan(plans.groupMonthlyPlans[1], "big", true)
.span4
mixin plan(plans.groupMonthlyPlans[2], "", true)
.tab-pane.annual-pricing
.page-header
h2 Group Plans
.row
.span12.tagline
p Improve the workflow of your research group by unlocking ShareLaTeX's premium features for everyone on your team
.row
.span4
mixin plan(plans.groupAnnualPlans[0], "", false)
.span4
mixin plan(plans.groupAnnualPlans[1], "big", false)
.span4
mixin plan(plans.groupAnnualPlans[2], "", false)
.tab-pane.student-pricing
.row
.span6.offset3
.alert.alert-info(style="color: #333")
h3 Want to use ShareLaTeX for free?
p Tell your university or department about our
a(href="/university") site licenses
| and use of all our
| features for free as a student or member of staff.
include ../general/small-footer
link(rel='stylesheet', href='/brand/plans.css?fingerprint='+fingerprint('/brand/plans.css'))

View file

@ -1,166 +1,210 @@
extends ../layout extends ../layout
mixin liSection(feature)
| #{feature.text}
-if(feature.comingSoon)
span.label.label-info coming soon
-if(feature.beta)
span.label.label-warning beta
mixin plan(plan, cssClass, monthly)
.pricing-table
ul(class=cssClass)
li.pricing-header-row-1
.package-title
h2.no-bold #{plan.name}
li.pricing-header-row-2
.package-price
if plan.price == 0
h1.free Free forever
else
h1.no-bold
| $#{plan.price/100}
if monthly
span.cents /month
else
span.cents /year
- var odd = true
-each feature in plan.featureDescription
- odd = !odd
- if(odd)
li.pricing-content-row-odd
mixin liSection(feature)
- else
li.pricing-content-row-even
mixin liSection(feature)
li.pricing-footer
- var href = '/user/subscription/new?planCode='+plan.planCode
- planIsPersonal = plan.planCode.indexOf("personal") != -1
- userNotLoggedIn = session && !session.user
-if(planIsPersonal)
- href = "/register"
-else if(userNotLoggedIn)
- href = "/register?redir="+href
a.btn.btn-success(href='#{href}', ga_PlanType=plan.planCode).sign_up_now
| Sign Up Now!
block content block content
.container .content-alt
.row .content.plans(ng-controller="PlansController")
.span12.span-box .container
.page-header .row
h1 Choose your plan .col-md-12
blockquote.quote.pull-right .page-header.centered.plans-header.text-centered
p h1 Start Your 30-Day Free Trial Today
| This is one of the most useful resources I have ever found on the Internet.
br
| Fantastic execution and thoughtful attention to detail make this product shine!
small Benjamin Shepherd, Waterloo University
.row .row
.span12 .col-md-12
.offset3 p.text-centered ShareLaTeX is the world's easiest to use LaTeX editor. You'll stay up to date with your collaborators, keep track of all changes to your work, and use our LaTeX environment from anywhere in the world.
ul.nav.nav-pills.pricing-pills
li.active .row(ng-cloak)
a(href="#", data-target=".monthly-pricing", data-toggle="tab") Monthly .col-md-12
li ul.nav.nav-pills
a(href="#", data-target=".annual-pricing", data-toggle="tab") Annual li(ng-class="{'active': ui.view == 'monthly'}")
li a(
a(href="#", data-target=".student-pricing", data-toggle="tab") Half price student plans href,
ng-click="ui.view = 'monthly'"
) Monthly
li(ng-class="{'active': ui.view == 'annual'}")
a(
href
ng-click="ui.view = 'annual'"
) Annual
li(ng-class="{'active': ui.view == 'student'}")
a(
href,
ng-click="ui.view = 'student'"
) Half Price Student Plans
.row(ng-cloak)
.col-md-12
.card-group.text-centered(ng-if="ui.view == 'monthly' || ui.view == 'annual'")
.card
.card-header
h2 Personal
.circle Free
ul.list-unstyled
li Only one extra collaborator per<br/> project
li &nbsp;
li
br
a.btn.btn-primary(href="/register") Sign up now!
.card.highlighted
.card-header
h2 Collaborator
.circle
span(ng-if="ui.view == 'monthly'")
| $15
span.small / mo
span(ng-if="ui.view == 'annual'")
| $180
span.small / yr
ul.list-unstyled
li 10 extra collaborators per project
li Full document history
li Sync to Dropbox
li
br
a.btn.btn-primary(
ng-href="#{baseUrl}/user/subscription/new?planCode=collaborator{{ ui.view == 'annual' && '_annual' || ''}}"
) Sign up now!
.card
.card-header
h2 Professional
.circle
span(ng-if="ui.view == 'monthly'")
| $30
span.small / mo
span(ng-if="ui.view == 'annual'")
| $360
span.small / yr
ul.list-unstyled
li Unlimited collaborators per project
li Full document history
li Sync to Dropbox
li
br
a.btn.btn-primary(
ng-href="#{baseUrl}/user/subscription/new?planCode=professional{{ ui.view == 'annual' && '_annual' || ''}}"
) Sign up now!
.card-group.text-centered(ng-if="ui.view == 'student'")
.card
.card-header
h2 Personal
.circle Free
ul.list-unstyled
li Only one extra collaborator per<br/> project
li &nbsp;
li
br
a.btn.btn-primary(href="/register") Sign up now!
.card.highlighted
.card-header
h2 Student
.circle
span
| $8
span.small / mo
ul.list-unstyled
li 6 extra collaborators per project
li Full document history
li Sync to Dropbox
li
br
a.btn.btn-primary(
ng-href="#{baseUrl}/user/subscription/new?planCode=student"
) Sign up now!
.card
.card-header
h2 Student (Annual)
.circle
span
| $80
span.small / yr
ul.list-unstyled
li 6 extra collaborators per project
li Full document history
li Sync to Dropbox
li
br
a.btn.btn-primary(
ng-href="#{baseUrl}/user/subscription/new?planCode=student_annual"
) Sign up now!
.row(ng-cloak)
p.text-centered Choose the plan that works for you with our 30-day money-back guarantee. Cancel at any time.
.row .row
.span12 .col-md-12
.page-header .page-header.plans-header.plans-subheader.text-centered
h2 Individual Plans h2 Enjoy all of these great features
.col-md-4
.pricing-steelblue.pricing-row .card.features.text-centered
.tab-content i.fa.fa-file-text-o.fa-5x
.tab-pane.active.monthly-pricing h4 Unlimited projects
.row p Create as much as you like.
.span12.tagline .col-md-4
p An online LaTeX editor for collaborating on the <strong>same LaTeX project and editing together in real-time</strong>. Youll never go out of sync with your collaborators again, or lose track of any changes. .card.features.text-centered
.row i.fa.fa-clock-o.fa-5x
.span4 h4 Full document history
mixin plan(plans.personalAccount, "", true) p Never lose a step, we've got your back.
.span4 .col-md-4
mixin plan(plans.allPlans['collaborator'], "big", true) .card.features.text-centered
.span4 i.fa.fa-dropbox.fa-5x
mixin plan(plans.allPlans['professional'], "", true) h4 Sync to Dropbox
p Access your projects everywhere.
.tab-pane.annual-pricing
.row
.span12.tagline
p Collaborate on the <strong>same LaTeX project and edit together in real-time</strong>. Youll never go out of sync with your collaborators again, or lose track of any changes.
.span4
mixin plan(plans.personalAccount, "", true)
.span4
mixin plan(plans.allPlans['collaborator-annual'], "big", false)
.span4
mixin plan(plans.allPlans['professional-annual'], "", false)
.tab-pane.student-pricing
.row
.span8.offset2.tagline
p Getting started and working with <strong>LaTeX has never been so easy.</strong> Start creating beautiful work now.
.span4
mixin plan(plans.personalAccount, "", true)
.span4
mixin plan(plans.allPlans['student'], "big", true)
.span4
mixin plan(plans.allPlans['student-annual'], "", false)
.row
.span12.ab-guarantee-shown(style="text-align: center;")
h2 30 day money back guarantee, cancel anytime.
.pricing-steelblue.pricing-row
.tab-content
.tab-pane.active.monthly-pricing
.page-header
h2 Group Plans
.row
.span12.tagline
p Improve the workflow of your research group by unlocking ShareLaTeX's premium features for everyone on your team
.row
.span4
mixin plan(plans.groupMonthlyPlans[0], "", true)
.span4
mixin plan(plans.groupMonthlyPlans[1], "big", true)
.span4
mixin plan(plans.groupMonthlyPlans[2], "", true)
.tab-pane.annual-pricing
.page-header
h2 Group Plans
.row
.span12.tagline
p Improve the workflow of your research group by unlocking ShareLaTeX's premium features for everyone on your team
.row
.span4
mixin plan(plans.groupAnnualPlans[0], "", false)
.span4
mixin plan(plans.groupAnnualPlans[1], "big", false)
.span4
mixin plan(plans.groupAnnualPlans[2], "", false)
.tab-pane.student-pricing
.row
.span6.offset3
.alert.alert-info(style="color: #333")
h3 Want to use ShareLaTeX for free?
p Tell your university or department about our
a(href="/university") site licenses
| and use of all our
| features for free as a student or member of staff.
include ../general/small-footer
link(rel='stylesheet', href='/brand/plans.css?fingerprint='+fingerprint('/brand/plans.css'))
.row(ng-if="ui.view == 'monthly' || ui.view == 'annual'", ng-cloak)
.col-md-12
.page-header.plans-header.plans-subheader.text-centered
h2 Group Plans
p Improve the workflow of your research group by using ShareLaTeX with everyone on your team
.row(ng-if="ui.view == 'monthly' || ui.view == 'annual'", ng-cloak)
.col-md-12
.card-group.text-centered
.card
.card-header
h2 Group
.circle
span(ng-if="ui.view == 'monthly'")
| $50
span.small / mo
span(ng-if="ui.view == 'annual'")
| $500
span.small / yr
ul.list-unstyled
li 5 group members
li.small All the advantages of the Professional account for each team member
li
br
a.btn.btn-primary(href="#{baseUrl}/user/subscription/new?planCode=group_5_members{{ ui.view == 'annual' && '_annual' || ''}}") Sign up now!
.card.highlighted
.card-header
h2 Research Lab
.circle
span(ng-if="ui.view == 'monthly'")
| $90
span.small / mo
span(ng-if="ui.view == 'annual'")
| $900
span.small / yr
ul.list-unstyled
li 10 group members
li.small All the advantages of the Professional account for each team member
li
br
a.btn.btn-primary(href="#{baseUrl}/user/subscription/new?planCode=group_10_members{{ ui.view == 'annual' && '_annual' || ''}}") Sign up now!
.card
.card-header
h2 Department
.circle
span(ng-if="ui.view == 'monthly'")
| $170
span.small / mo
span(ng-if="ui.view == 'annual'")
| $1700
span.small / yr
ul.list-unstyled
li 20 group members
li.small All the advantages of the Professional account for each team member
li
br
a.btn.btn-primary(href="#{baseUrl}/user/subscription/new?planCode=group_20_members{{ ui.view == 'annual' && '_annual' || ''}}") Sign up now!

View file

@ -1,33 +1,36 @@
extends ../layout extends ../layout
block content block content
link(href='http://fonts.googleapis.com/css?family=Just+Another+Hand', rel='stylesheet', type='text/css') .content.content-alt
.container .container
.row .row
div &nbsp; .col-md-8.col-md-offset-2
.span8.offset2.span-box .card
.page-header .page-header
h2 Thanks for subscribing! h2 Thanks for subscribing!
.alert.alert-success .alert.alert-success
p Your card will be charged soon. p Your card will be charged soon.
p The next payment of <strong>#{subscription.price}</strong> will be collected on <strong>#{subscription.nextPaymentDueAt}</strong>, if you do not want to be charged again p The next payment of <strong>#{subscription.price}</strong> will be collected on <strong>#{subscription.nextPaymentDueAt}</strong>.
a(href="/user/subscription") click here to cancel. p If you do not want to be charged again
div a(href="/user/subscription") click here to cancel.
p
- if (subscription.groupPlan == true)
a.btn.btn-success.btn-large(href="/subscription/group") Add your first group members now
div.letter-from-founders
p Thank you for subscribing to the #{subscription.name} plan. It's support from people like yourself that allows ShareLaTeX to continue to grow and improve.
p If there is anything you ever need please feel free to contact us directly at p
a(href='mailto:support@sharelatex.com') support@sharelatex.com - if (subscription.groupPlan == true)
| - it goes straight to both our inboxes. a.btn.btn-success.btn-large(href="/subscription/group") Add your first group members now
p Regards, p.letter-from-founders
br p Thank you for subscribing to the #{subscription.name} plan. It's support from people like yourself that allows ShareLaTeX to continue to grow and improve.
| Henry and James
.portraits p If there is anything you ever need please feel free to contact us directly at
img(src="/img/about/henry_oswald.jpg") a(href='mailto:support@sharelatex.com') support@sharelatex.com
&nbsp; | . It goes straight to both our inboxes.
img(src="/img/about/james_allen.jpg") p Regards,
div br
a.btn.btn-primary(href="/project") < Back to your projects | Henry and James
.portraits
span.img-circle
img(src="/img/about/henry_oswald.jpg")
&nbsp;
span.img-circle
img(src="/img/about/james_allen.jpg")
p
a.btn.btn-primary(href="/project") &lt; Back to your projects

View file

@ -0,0 +1,67 @@
define [
"base"
], (App) ->
App.directive "selectAllList", () ->
return {
controller: ["$scope", ($scope) ->
# Selecting or deselecting all should apply to all projects
selectAll = () ->
$scope.$broadcast "select-all:select"
deselectAll = () ->
$scope.$broadcast "select-all:deselect"
clearSelectAllState = () ->
$scope.$broadcast "select-all:clear"
return {
clearSelectAllState: clearSelectAllState
selectAll: selectAll
deselectAll: deselectAll
}
]
link: (scope, element, attrs) ->
}
App.directive "selectAll", () ->
return {
require: "^selectAllList"
link: (scope, element, attrs, selectAllListController) ->
scope.$on "select-all:clear", () ->
element.prop("checked", false)
element.change () ->
if element.is(":checked")
selectAllListController.selectAll()
else
selectAllListController.deselectAll()
return true
}
App.directive "selectIndividual", () ->
return {
require: "^selectAllList"
scope: {
ngModel: "="
}
link: (scope, element, attrs, selectAllListController) ->
ignoreChanges = false
scope.$watch "ngModel", (value) ->
if value? and !ignoreChanges
selectAllListController.clearSelectAllState()
scope.$on "select-all:select", () ->
ignoreChanges = true
scope.$apply () ->
scope.ngModel = true
ignoreChanges = false
scope.$on "select-all:deselect", () ->
ignoreChanges = true
scope.$apply () ->
scope.ngModel = false
ignoreChanges = false
}

View file

@ -3,12 +3,15 @@ define [
"main/user-details" "main/user-details"
"main/account-settings" "main/account-settings"
"main/templates" "main/templates"
"main/plans"
"main/group-members"
"directives/asyncForm" "directives/asyncForm"
"directives/stopPropagation" "directives/stopPropagation"
"directives/focus" "directives/focus"
"directives/equals" "directives/equals"
"directives/fineUpload" "directives/fineUpload"
"directives/onEnter" "directives/onEnter"
"directives/selectAll"
"filters/formatDate" "filters/formatDate"
], () -> ], () ->
angular.bootstrap(document.body, ["SharelatexApp"]) angular.bootstrap(document.body, ["SharelatexApp"])

View file

@ -0,0 +1,54 @@
define [
"base"
], (App) ->
App.controller "GroupMembersController", ($scope, queuedHttp) ->
$scope.users = window.users
$scope.groupSize = window.groupSize
$scope.selectedUsers = []
$scope.inputs =
emails: ""
parseEmails = (emailsString)->
regexBySpaceOrComma = /[\s,]+/
emails = emailsString.split(regexBySpaceOrComma)
emails = _.map emails, (email)->
email = email.trim()
emails = _.select emails, (email)->
email.indexOf("@") != -1
return emails
$scope.addMembers = () ->
emails = parseEmails($scope.inputs.emails)
for email in emails
queuedHttp
.post("/subscription/group/user", {
email: email,
_csrf: window.csrfToken
})
.success (data) ->
$scope.users.push data.user if data.user?
$scope.inputs.emails = ""
$scope.removeMembers = () ->
for user in $scope.selectedUsers
do (user) ->
queuedHttp({
method: "DELETE",
url: "/subscription/group/user/#{user._id}"
headers:
"X-Csrf-Token": window.csrfToken
})
.success () ->
index = $scope.users.indexOf(user)
return if index == -1
$scope.users.splice(index, 1)
$scope.selectedUsers = []
$scope.updateSelectedUsers = () ->
$scope.selectedUsers = $scope.users.filter (user) -> user.selected
App.controller "GroupMemberListItemController", ($scope) ->
$scope.$watch "user.selected", (value) ->
if value?
$scope.updateSelectedUsers()

View file

@ -0,0 +1,6 @@
define [
"base"
], (App) ->
App.controller "PlansController", ($scope) ->
$scope.ui =
view: "monthly"

View file

@ -1,71 +1,6 @@
define [ define [
"base" "base"
], (App) -> ], (App) ->
App.directive "selectAllList", () ->
return {
controller: ["$scope", ($scope) ->
# Selecting or deselecting all should apply to all projects
selectAll = () ->
$scope.$broadcast "select-all:select"
deselectAll = () ->
$scope.$broadcast "select-all:deselect"
clearSelectAllState = () ->
$scope.$broadcast "select-all:clear"
return {
clearSelectAllState: clearSelectAllState
selectAll: selectAll
deselectAll: deselectAll
}
]
link: (scope, element, attrs) ->
}
App.directive "selectAll", () ->
return {
require: "^selectAllList"
link: (scope, element, attrs, selectAllListController) ->
scope.$on "select-all:clear", () ->
element.prop("checked", false)
element.change () ->
if element.is(":checked")
selectAllListController.selectAll()
else
selectAllListController.deselectAll()
return true
}
App.directive "selectIndividual", () ->
return {
require: "^selectAllList"
scope: {
ngModel: "="
}
link: (scope, element, attrs, selectAllListController) ->
ignoreChanges = false
scope.$watch "ngModel", (value) ->
if value? and !ignoreChanges
selectAllListController.clearSelectAllState()
scope.$on "select-all:select", () ->
ignoreChanges = true
scope.$apply () ->
scope.ngModel = true
ignoreChanges = false
scope.$on "select-all:deselect", () ->
ignoreChanges = true
scope.$apply () ->
scope.ngModel = false
ignoreChanges = false
}
App.factory "queuedHttp", ["$http", "$q", ($http, $q) -> App.factory "queuedHttp", ["$http", "$q", ($http, $q) ->
pendingRequests = [] pendingRequests = []
inflight = false inflight = false

View file

@ -5,12 +5,8 @@ define [
app.factory "Institutions", -> app.factory "Institutions", ->
new AlgoliaSearch(window.algolia.institutions.app_id, window.algolia.institutions.api_key).initIndex("institutions") new AlgoliaSearch(window.algolia.institutions.app_id, window.algolia.institutions.api_key).initIndex("institutions")
App.controller "UpdateForm", ($scope, $http, Institutions)-> App.controller "UserProfileController", ($scope, $modal, $http)->
$scope.institutions = [] $scope.institutions = []
$scope.formVisable = false
$scope.hidePersonalInfoSection = true
$scope.roles = ["Student", "Post-graduate student", "Post-doctoral researcher", "Lecturer", "Professor"]
$http.get("/user/personal_info").success (data)-> $http.get("/user/personal_info").success (data)->
$scope.userInfoForm = $scope.userInfoForm =
first_name: data.first_name || "" first_name: data.first_name || ""
@ -19,23 +15,33 @@ define [
institution: data.institution || "" institution: data.institution || ""
_csrf : window.csrfToken _csrf : window.csrfToken
if getPercentComplete() != 100
$scope.percentComplete = getPercentComplete()
$scope.hidePersonalInfoSection = false
$scope.showForm = -> $scope.showForm = ->
$scope.formVisable = true $scope.formVisable = true
$scope.getPercentComplete = ->
results = _.filter $scope.userInfoForm, (value)-> !value? or value?.length != 0
results.length * 20
$scope.$watch "userInfoForm", (value) ->
if value?
$scope.percentComplete = $scope.getPercentComplete()
, true
$scope.openUserProfileModal = () ->
$modal.open {
templateUrl: "userProfileModalTemplate"
controller: "UserProfileModalController"
scope: $scope
}
App.controller "UserProfileModalController", ($scope, $modalInstance, $http, Institutions) ->
$scope.roles = ["Student", "Post-graduate student", "Post-doctoral researcher", "Lecturer", "Professor"]
$scope.sendUpdate = -> $scope.sendUpdate = ->
request = $http.post "/user/settings", $scope.userInfoForm request = $http.post "/user/settings", $scope.userInfoForm
request.success (data, status)-> request.success (data, status)->
request.error (data, status)-> request.error (data, status)->
console.log "the request failed" console.log "the request failed"
$scope.percentComplete = getPercentComplete()
getPercentComplete = ->
results = _.filter $scope.userInfoForm, (value)-> !value? or value?.length != 0
results.length * 20
$scope.updateInstitutionsList = (inputVal)-> $scope.updateInstitutionsList = (inputVal)->
@ -48,3 +54,5 @@ define [
$scope.institutions = _.map response.hits, (institution)-> $scope.institutions = _.map response.hits, (institution)->
"#{institution.name} (#{institution.domain})" "#{institution.name} (#{institution.domain})"
$scope.done = () ->
$modalInstance.close()

View file

@ -1,7 +1,6 @@
.recurly { .recurly {
display: block; display: block;
position: relative; position: relative;
width: 500px;
} }
.recurly .cost, .recurly .cost,
.recurly .discount { .recurly .discount {

View file

@ -1,14 +1,8 @@
.team-profile { .team-profile {
clear: both; clear: both;
.img-container { .img-container {
border-radius: 50%;
float: left; float: left;
height: @line-height-computed * 4;
overflow: hidden; overflow: hidden;
margin: (@line-height-computed / 2) @line-height-computed @line-height-computed (@line-height-computed / 2); margin: (@line-height-computed / 2) @line-height-computed @line-height-computed (@line-height-computed / 2);
width: @line-height-computed * 4;
}
img {
margin-top: -10px;
} }
} }

View file

@ -1,3 +1,15 @@
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
display: none !important; display: none !important;
} }
.img-circle {
display: inline-block;
overflow: hidden;
border-radius: 50%;
width: @line-height-computed * 4;
height: @line-height-computed * 4;
img {
margin-top: -10px;
}
}

View file

@ -0,0 +1,130 @@
.bonus {
margin-top: 15px;
.page-header h1 {
text-align: center;
}
h2 {
text-align: center;
font-size: 20px;
line-height: 28px;
margin-bottom: @line-height-computed;
margin-top: 0;
&.direct-link {
margin-top: @line-height-computed;
}
}
.bonus-banner {
.bonus-top {
border-bottom: 1px solid lighten(@blue, 40%);
}
.title {
a {
display: block;
font-size: 18px;
padding: 20px 62px;
background-color: white;
border-bottom: 1px solid lighten(@blue, 40%);
color: @blue;
&:hover {
background-color: lighten(@blue, 45%);
}
}
}
a.twitter {
background-image: url(/img/social/twitter-32.png);
background-repeat: no-repeat;
background-position: 16px center;
}
a.facebook {
background-image: url(/img/social/facebook-32.png);
background-repeat: no-repeat;
background-position: 16px center;
}
a.email {
background-image: url(/img/social/mail-32.png);
background-repeat: no-repeat;
background-position: 16px center;
}
a.google-plus {
background-image: url(//www.gstatic.com/images/icons/gplus-32.png);
background-repeat: no-repeat;
background-position: 16px center;
}
a.link {
background-image: url(/img/social/link-32.png);
background-repeat: no-repeat;
background-position: 16px center;
}
h2.direct-link {
}
}
p.thanks {
font-size: 18px;
line-height: 28px;
margin-top: 10px;
text-align: center;
}
.number {
position: absolute;
margin-left: -13px;
width: 26px;
padding: 3px 0;
text-align: center;
background-color: #ddd;
&.active {
background-color: @blue;
color: white;
}
border-radius: 3px;
}
.progress {
margin-top: @line-height-computed / 2;
margin-left: -15px;
margin-right: -15px;
height: 30px;
}
.perk {
position: absolute;
background-color: #ddd;
border-radius: 5px;
text-align: center;
padding: 5px 5px;
width: 100px;
margin-left: -50px;
font-size: 14px;
&:before {
border-bottom: 8px solid #ddd;
border-left: 8px solid transparent;
border-right: 8px solid transparent;
content: '';
position: absolute;
left: 42px;
top: -8px;
}
&.active {
color: white;
background-color: @blue;
&:before {
border-bottom: 8px solid @blue;
}
}
}
}
#link-modal {
.modal-body{
text-align: center;
}
textarea {
width: 95%;
margin-bottom: 0;
}
}

View file

@ -0,0 +1,124 @@
.plans {
p {
color: @gray-dark;
margin-bottom: @line-height-computed;
}
.plans-header{
h1, h2, p {
text-shadow: 0 -1px 1px white;
}
h1, h2 {
color: @red;
}
p {
margin-bottom: 0;
}
}
.plans-subheader {
margin-bottom: @line-height-computed;
}
.card.features {
margin-top: @line-height-computed;
i {
color: @red;
}
p {
margin: 0;
}
}
.card {
background-color: white;
border-radius: 3px;
-webkit-box-shadow: 0 2px 4px rgba(0,0,0,0.1);
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
margin: @line-height-computed 0;
padding: @line-height-computed;
.card-header {
border-bottom: 1px solid @gray-lighter;
padding-bottom: @line-height-computed;
margin-bottom: @line-height-computed;
h2 {
margin: 0;
}
}
.circle {
font-size: 1.5rem;
font-weight: 700;
padding: 38px 18px;
margin: 0 auto @line-height-computed;
text-shadow: 0 -1px 1px darken(@link-color, 10%);
width: 120px;
height: 120px;
small {
margin-top: @line-height-computed / 2;
}
}
&.first {
margin-top: 0;
}
&.card-thin {
padding: @line-height-computed / 4;
}
}
.card-group {
margin: @line-height-computed 0;
.card {
border-radius: 0;
display: inline-block;
margin: 0;
&:first-child {
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
}
&:last-child {
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
}
width: 300px;
}
.highlighted {
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
margin-top: -@line-height-computed * 2;
padding-top: @line-height-computed * 2;
padding-bottom: @line-height-computed * 2;
position: relative;
z-index: 10;
}
}
> .card-group > .card {
padding-left: 1rem;
padding-right: 1rem;
}
.circle {
border-radius: 50%;
background-color: @red;
color: white;
padding: @line-height-computed / 2;
margin-bottom: @line-height-computed;
white-space: nowrap;
span.small {
color: rgba(255, 255, 255, 0.75);
font-size: @font-size-base * .8;
}
}
ul.nav-pills {
text-align: center;
margin-bottom: @line-height-computed;
li {
float: none;
display: inline-block;
a {
background-color: darken(@gray-lightest, 5%);
}
&.active {
a {
background-color: @link-color;
}
}
}
> li + li {
margin-left: @line-height-computed / 2;
}
}
}

View file

@ -1,16 +1,31 @@
.project-header { .project-header {
.btn-group > .btn { .btn-group > .btn {
padding-left: @line-height-base / 2; padding-left: @line-height-base / 2;
padding-right: @line-height-base / 2; padding-right: @line-height-base / 2;
} }
} }
.project-search { .project-search {
margin: @line-height-base 0; margin: @line-height-base 0;
} }
.project-tools { .project-tools {
display: inline; display: inline;
}
.first-project {
width: 127px;
text-align: center;
}
.user-profile {
.progress {
height: @line-height-computed / 2;
margin-bottom: @line-height-computed / 4;
}
p {
margin-bottom: @line-height-computed / 4;
}
} }
ul.folders-menu { ul.folders-menu {
@ -25,7 +40,7 @@ ul.folders-menu {
color: #333; color: #333;
padding: (@line-height-computed / 4); padding: (@line-height-computed / 4);
} }
} }
li.active { li.active {
//border-right: 4px solid @red; //border-right: 4px solid @red;
a { a {
@ -53,16 +68,16 @@ form.project-search {
} }
} }
ul.project-list { ul.structured-list {
list-style-type: none; list-style-type: none;
margin: 0; margin: 0;
overflow: hidden; overflow: hidden;
overflow-y: scroll; overflow-y: auto;
li { li {
border-bottom: 1px solid @gray-lightest; border-bottom: 1px solid @gray-lightest;
padding: (@line-height-computed / 4) 0; padding: (@line-height-computed / 4) 0;
&:first-child { &:first-child {
.last-modified, .owner { .header {
font-size: 1rem; font-size: 1rem;
} }
} }
@ -86,6 +101,11 @@ ul.project-list {
.select-item, .select-all { .select-item, .select-all {
margin-left: @line-height-computed / 4; margin-left: @line-height-computed / 4;
} }
}
}
ul.project-list {
li {
.last-modified, .owner { .last-modified, .owner {
font-size: .8rem; font-size: .8rem;
} }
@ -109,3 +129,54 @@ ul.project-list {
} }
} }
} }
#institution_auto_complete {
ul>li{
list-style:none;
}
.autocomplete {
width: 100%;
position: relative;
}
.autocomplete ul {
position: absolute;
top: 100%;
left: 0;
z-index: @zindex-dropdown;
float: left;
min-width: 160px;
padding: 5px 0;
margin: 2px 0 0; // override default ul
list-style: none;
font-size: @font-size-base;
background-color: @dropdown-bg;
border: 1px solid @dropdown-fallback-border; // IE8 fallback
border: 1px solid @dropdown-border;
border-radius: @border-radius-base;
.box-shadow(0 6px 12px rgba(0,0,0,.175));
background-clip: padding-box;
// Links within the dropdown menu
> li {
display: block;
padding: 3px 20px;
clear: both;
font-weight: normal;
line-height: @line-height-base;
color: @dropdown-link-color;
white-space: nowrap; // prevent links from randomly breaking onto new lines
}
> li.active {
text-decoration: none;
color: @dropdown-link-hover-color;
background-color: @dropdown-link-hover-bg;
}
}
.autocomplete .highlight {
font-weight: 700;
}
}

View file

@ -0,0 +1,781 @@
.recurly {
display: block;
position: relative;
box-sizing: content-box;
* {
box-sizing: content-box;
}
.due_now {
display: none;
}
}
.recurly .cost,
.recurly .discount {
font-size: 16px;
text-align: right;
}
.recurly .subscription {
border-radius: 9px 9px 0 0;
text-shadow: 0 1px 0 #fff;
padding-top: 20px;
overflow: hidden;
}
.recurly .plan {
color: #333;
overflow: hidden;
position: relative;
zoom: 1;
font-family: @font-family-serif;
}
.recurly .plan .name {
float: left;
font-size: 32px;
min-width: 200px;
padding-left: 20px;
padding-right: 40px;
}
.recurly .plan .quantity.field {
clear: none;
width: 60px;
margin: 4px 0;
}
.recurly .plan .quantity.field input[type=text] {
width: 48px;
}
.recurly .plan .quantity.field:before {
content: "\d7";
height: 48px;
line-height: 30px;
position: absolute;
right: 100%;
width: 40px;
font-size: 20px;
text-align: center;
vertical-align: middle;
z-index: 1337;
color: #666;
}
.recurly .plan .recurring_cost {
float: right;
text-align: right;
padding-right: 20px;
}
.recurly .plan .recurring_cost .cost {
font-size: 32px;
}
.recurly .plan .recurring_cost .interval {
font-size: 12px;
padding-bottom: 20px;
}
.recurly .free_trial {
clear: left;
float: left;
font-size: 13px;
height: 22px;
margin: 0;
position: absolute;
top: 35px;
left: 20px;
font-style: italic;
}
.recurly .setup_fee {
clear: both;
background: url("/recurly/images/dash.png") repeat-x 1px top;
overflow: hidden;
padding-top: 20px;
}
.recurly .setup_fee .title {
float: left;
padding-left: 20px;
font-weight: bold;
font-size: 16px;
}
.recurly .setup_fee .cost {
float: right;
padding-right: 20px;
}
.recurly .vat {
height: 24px;
padding: 20px 20px;
display: none;
background: url("/recurly/images/dash.png") repeat-x 1px top;
}
.recurly .vat.applicable {
display: block;
}
.recurly .vat .title {
font-size: 16px;
font-weight: normal;
float: left;
}
.recurly .vat .cost {
float: right;
font-size: 18px;
}
.recurly .add_ons {
clear: both;
}
.recurly .add_ons.any {
margin: 20px 10px;
}
.recurly .add_ons .add_on {
background: #ecedee;
background: -webkit-linear-gradient(top, #ecedee, #e5e6e7);
background: -moz-linear-gradient(top, #ecedee, #e5e6e7);
background: -o-linear-gradient(top, #ecedee, #e5e6e7);
background: linear-gradient(top, #ecedee, #e5e6e7);
margin: 0;
height: 43px;
line-height: 42px;
vertical-align: middle;
position: relative;
clear: both;
overflow: hidden;
border-top: 1px solid #ccc;
border-left: 1px solid #ccc;
border-right: 1px solid #ccc;
text-shadow: 0 1px 0 #fff;
color: #999;
font-weight: 300;
font-size: 16px;
zoom: 1;
cursor: default;
}
.recurly .add_ons .add_on.first {
border-top-left-radius: 10px;
border-top-right-radius: 10px;
}
.recurly .add_ons .add_on.last {
border-bottom: 1px solid #ccc;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
}
.recurly .add_ons .add_on .name {
font-size: inherit;
font-weight: inherit;
font-style: italic;
color: inherit;
width: 200px;
margin-left: 9px;
margin-right: 20px;
position: absolute;
left: 0;
top: 0;
}
.recurly .add_ons .add_on .quantity.field {
position: absolute;
top: 4px;
left: 249px;
width: 60px;
display: none;
}
.recurly .add_ons .add_on .quantity.field input[type=text] {
width: 48px;
}
.recurly .add_ons .add_on .quantity.field:before {
content: "\d7";
height: 48px;
line-height: 30px;
position: absolute;
right: 100%;
width: 40px;
font-size: 20px;
text-align: center;
vertical-align: middle;
z-index: 1337;
color: #666;
}
.recurly .add_ons .add_on .cost {
font-size: inherit;
line-height: inherit;
vertical-align: middle;
position: absolute;
right: 10px;
}
.recurly .add_ons .add_on:hover {
background: -webkit-linear-gradient(top, #f0f0f0 0%, #dfdfdf 50%, #d5d5d5 50%, #e0e0e0 100%);
background: -moz-linear-gradient(top, #f0f0f0 0%, #dfdfdf 50%, #d5d5d5 50%, #e0e0e0 100%);
background: -o-linear-gradient(top, #f0f0f0 0%, #dfdfdf 50%, #d5d5d5 50%, #e0e0e0 100%);
background: linear-gradient(top, #f0f0f0 0%, #dfdfdf 50%, #d5d5d5 50%, #e0e0e0 100%);
box-shadow: inset 0 1px 0 #fff;
text-shadow: none;
color: #111;
}
.recurly .add_ons .add_on:active,
.recurly .add_ons .add_on.selected {
color: #111;
background: -webkit-linear-gradient(top, #f0f0f0, #fff);
background: -moz-linear-gradient(top, #f0f0f0, #fff);
background: -o-linear-gradient(top, #f0f0f0, #fff);
background: linear-gradient(top, #f0f0f0, #fff);
width: auto;
box-shadow: inset 0 1px 4px 0 rgba(0,0,0,0.07);
text-shadow: none;
}
.recurly .add_ons .add_on.selected {
background: #fff url("/recurly/images/check.png") no-repeat 10px center;
}
.recurly .add_ons .add_on.selected .name {
padding-left: 24px;
}
.recurly .add_ons .add_on.selected:hover {
background: #fcf5f0 url("/recurly/images/uncheck.png") no-repeat 10px center;
}
.recurly .add_ons .add_on.selected .quantity {
display: block;
}
.recurly .coupon {
clear: both;
overflow: hidden;
height: 34px;
color: #333;
padding: 20px 20px;
position: relative;
background: url("/recurly/images/dash.png") repeat-x 1px top;
}
.recurly .coupon .check {
width: 26px;
height: 26px;
float: left;
border-radius: 15px 15px 15px 15px;
background: #70ccf8;
border: 1px solid #0090c9;
margin: 3px 0 1px 10px;
box-shadow: inset 0 1px 0 0 rgba(255,255,255,0.35), 0 1px 1px 0 rgba(0,0,0,0.10);
background: #43bef9 url("/recurly/images/coupon_check.png") no-repeat center center;
background: url("/recurly/images/coupon_check.png") no-repeat center center, -webkit-linear-gradient(top, #71CDFA 0%, #43BEF9 50%, #00B1F6 50%, #71CEFB 100%);
background: url("/recurly/images/coupon_check.png") no-repeat center center, -moz-linear-gradient(top, #71CDFA 0%, #43BEF9 50%, #00B1F6 50%, #71CEFB 100%);
background: url("/recurly/images/coupon_check.png") no-repeat center center, -o-linear-gradient(top, #71CDFA 0%, #43BEF9 50%, #00B1F6 50%, #71CEFB 100%);
background: url("/recurly/images/coupon_check.png") no-repeat center center linear-gradient(top, #71CDFA 0%, #43BEF9 50%, #00B1F6 50%, #71CEFB 100%);
}
.recurly .coupon .check:hover {
background: url("/recurly/images/coupon_check.png") no-repeat center center, -webkit-linear-gradient(top, #71CDFA 0%, #43BEF9 50%, #00B1F6 50%, #71CEFB 100%);
background: url("/recurly/images/coupon_check.png") no-repeat center center, -moz-linear-gradient(top, #71CDFA 0%, #43BEF9 50%, #00B1F6 50%, #71CEFB 100%);
background: url("/recurly/images/coupon_check.png") no-repeat center center, -o-linear-gradient(top, #71CDFA 0%, #43BEF9 50%, #00B1F6 50%, #71CEFB 100%);
background: url("/recurly/images/coupon_check.png") no-repeat center center linear-gradient(top, #71CDFA 0%, #43BEF9 50%, #00B1F6 50%, #71CEFB 100%);
box-shadow: inset 0 1px 0 0 rgba(255,255,255,0.75), 0 1px 1px 0 rgba(0,0,0,0.10);
}
.recurly .coupon .check:active {
background: url("/recurly/images/coupon_check.png") no-repeat center center, -webkit-linear-gradient(top, #f0f0f0, #fff);
background: url("/recurly/images/coupon_check.png") no-repeat center center, -moz-linear-gradient(top, #f0f0f0, #fff);
background: url("/recurly/images/coupon_check.png") no-repeat center center, -o-linear-gradient(top, #f0f0f0, #fff);
background: url("/recurly/images/coupon_check.png") no-repeat center center linear-gradient(top, #f0f0f0, #fff);
box-shadow: inset 0 3px 3px 0 rgba(0,0,0,0.03);
border: 1px solid #999;
}
.recurly .coupon.checking .check {
background: #f0f0f0 url("/recurly/images/coupon_checking.gif") no-repeat center center;
box-shadow: inset 0 3px 3px 0 rgba(0,0,0,0.03);
border: 1px solid #999;
}
.recurly .coupon.invalid .coupon_code {
border-color: #a55;
background: #fee;
color: #311;
}
.recurly .coupon .coupon_code .error {
left: 300px;
}
.recurly .coupon .description {
float: left;
margin-left: 20px;
height: 34px;
line-height: 34px;
vertical-align: middle;
font-size: 14.4px;
}
.recurly .coupon .discount {
float: right;
height: 34px;
line-height: 34px;
vertical-align: middle;
}
.recurly .error {
padding: 5px;
line-height: 22px;
vertical-align: middle;
color: #000;
text-shadow: 0 1px 0 #fec;
background: #ffc;
border: 1px solid #ba1;
box-shadow: 3px 5px 5px 0 rgba(0,0,0,0.10);
border-radius: 5px;
font-size: 13px;
}
.recurly .server_errors {
color: #fff;
text-shadow: 0 1px 0 #000;
margin: 0 20px;
opacity: 0;
}
.recurly .server_errors .error {
padding-left: 26px;
background: rgba(240,250,0,0.50) url("/recurly/images/error.png") no-repeat 5px 9px;
}
.recurly .server_errors.any {
opacity: 1;
-webkit-transition: opacity 0.5s linear;
-moz-transition: opacity 0.5s linear;
margin: 20px 20px;
margin-bottom: 0;
}
.recurly .contact_info,
.recurly .billing_info,
.recurly .accept_tos {
position: relative;
padding: 20px 20px;
overflow: hidden;
zoom: 1;
}
.recurly .title {
font-size: 16px;
height: 20px;
font-weight: bold;
padding-bottom: 20px;
color: #404041;
text-shadow: 0 1px 0 #fff;
float: left;
}
.recurly .credit_card,
.recurly .paypal {
clear: both;
}
.recurly .payment_method {
margin-bottom: 20px;
width: 300px;
}
.recurly .payment_method .payment_option {
float: right;
}
.recurly .payment_method .payment_option input[type=radio] {
margin-right: 10px;
display: none;
}
.recurly .payment_method.multiple {
height: 34px;
clear: both;
}
.recurly .payment_method.multiple input[type=radio] {
display: block;
float: left;
height: 29px;
}
.recurly .payment_method.multiple .card_option {
float: left;
}
.recurly .payment_method.multiple .paypal_option {
float: right;
}
.recurly .payment_method.multiple .logo,
.recurly .payment_method.multiple .accepted_cards {
opacity: 0.5;
}
.recurly .payment_method.multiple .payment_option:hover .logo,
.recurly .payment_method.multiple .payment_option.selected .logo,
.recurly .payment_method.multiple .payment_option:hover .accepted_cards,
.recurly .payment_method.multiple .payment_option.selected .accepted_cards {
cursor: pointer;
opacity: 1;
}
.recurly .payment_method .payment_option {
line-height: 32px;
display: block;
height: 32px;
line-height: 34px;
}
.recurly .payment_method .payment_option .title {
margin: 0;
font-size: 12px;
}
.recurly .payment_method .payment_option .icon {
float: left;
width: 24px;
height: 34px;
margin: 0 5px;
}
.recurly .payment_method .payment_option.card_option {
border-radius: 5px 0 0 5px;
border-right: none;
}
.recurly .payment_method .payment_option.card_option .icon {
width: 42px;
background: url("/recurly/images/credit_cards/generic.png") no-repeat 0 center;
}
.recurly .payment_method .payment_option.paypal_option {
border-radius: 0 5px 5px 0;
float: right;
}
.recurly .payment_method .payment_option.paypal_option .logo {
height: 24px;
width: 90px;
display: inline-block;
vertical-align: middle;
background: url("/recurly/images/paypal_logo.png") no-repeat 0 center;
}
.recurly .paypal_message {
width: 300px;
font-style: italic;
margin-bottom: 10px;
}
.recurly .contact_info {
background: url("/recurly/images/dash.png") repeat-x 1px bottom;
}
.recurly .accept_tos {
background: url("/recurly/images/dash.png") repeat-x 1px top;
overflow: visible;
}
.recurly .accept_tos input[type=checkbox] {
display: inline;
line-height: 34px;
vertical-align: middle;
}
.recurly .accept_tos label {
margin: 0 0 0 5px;
display: inline;
line-height: 34px;
vertical-align: middle;
}
.recurly .accept_tos .field .error {
display: block;
position: static;
}
.recurly .field {
display: inline;
float: left;
clear: left;
width: 300px;
height: 34px;
margin-bottom: 20px;
position: relative;
}
.recurly .field input[type=text] {
width: 288px;
}
.recurly .field.company_name {
margin-bottom: 0;
}
.recurly .field .error {
min-width: 128px;
white-space: nowrap;
position: absolute;
top: 0;
left: 100%;
margin-left: 20px;
z-index: 1337;
}
.recurly .field .placeholder {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
padding-left: 9px;
font-size: 16px;
font-weight: normal;
line-height: 34px;
vertical-align: middle;
color: #999;
cursor: text;
overflow: hidden;
white-space: nowrap;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
font-weight: 300;
}
.recurly .field.focus .placeholder {
color: #ccc;
}
.recurly .field.invalid .placeholder {
color: #a77;
}
.recurly .field.coupon_code {
width: 140px;
}
.recurly .field.coupon_code input[type=text] {
width: 128px;
}
.recurly .field.first_name {
clear: left;
width: 140px;
}
.recurly .field.first_name input[type=text] {
width: 128px;
}
.recurly .field.first_name .error {
left: 300px;
}
.recurly .field.last_name {
width: 140px;
margin-left: 20px;
margin-left: 20px;
clear: none;
clear: none;
}
.recurly .field.last_name input[type=text] {
width: 128px;
}
.recurly .field.card_number {
width: 220px;
}
.recurly .field.card_number input[type=text] {
width: 208px;
}
.recurly .field.card_number .error {
left: 300px;
}
.recurly .field.cvv {
width: 60px;
margin-left: 20px;
margin-left: 20px;
clear: none;
clear: none;
}
.recurly .field.cvv input[type=text] {
width: 48px;
}
.recurly .field.expires {
width: 300px;
}
.recurly .field.expires input[type=text] {
width: 288px;
}
.recurly .field.expires .title {
float: left;
font-size: 13px;
line-height: 24px;
vertical-align: middle;
width: 59px;
}
.recurly .field.expires .month {
float: left;
width: 120px;
margin-left: 0;
}
.recurly .field.expires .month input[type=text] {
width: 108px;
}
.recurly .field.expires .year {
float: left;
margin-left: 1px;
width: 60px;
}
.recurly .field.expires .year input[type=text] {
width: 48px;
}
.recurly .field.state {
width: 180px;
}
.recurly .field.state input[type=text] {
width: 168px;
}
.recurly .field.state .error {
left: 300px;
}
.recurly .field.zip {
width: 100px;
margin-left: 20px;
margin-left: 20px;
clear: none;
clear: none;
}
.recurly .field.zip input[type=text] {
width: 88px;
}
.recurly .field.vat_number {
width: 140px;
display: none;
}
.recurly .field.vat_number input[type=text] {
width: 128px;
}
.recurly .field.vat_number.applicable {
display: block;
}
.recurly .only_zipstreet .zip.field,
.recurly .only_zip .zip.field {
margin-left: 0;
clear: left;
}
.recurly .accepted_cards {
display: inline-block;
height: 34px;
overflow: hidden;
}
.recurly .card {
background-position: right top;
background-repeat: no-repeat;
text-indent: -3000px;
width: 32px;
height: 32px;
margin: 0;
padding: 0;
display: inline-block;
}
.recurly .card.mastercard {
background-image: url("/recurly/images/credit_cards/mastercard.png");
}
.recurly .card.american_express {
background-image: url("/recurly/images/credit_cards/american_express.png");
}
.recurly .card.visa {
background-image: url("/recurly/images/credit_cards/visa.png");
}
.recurly .card.discover {
background-image: url("/recurly/images/credit_cards/discover.png");
}
.recurly .card.jcb {
background-image: url("/recurly/images/credit_cards/jcb.png");
}
.recurly .card.laser {
background-image: url("/recurly/images/credit_cards/laser.png");
}
.recurly .card.diners_club {
background-image: url("/recurly/images/credit_cards/diners_club.png");
}
.recurly .card.maestro {
background-image: url("/recurly/images/credit_cards/maestro.png");
}
.recurly .card.no_match {
opacity: 0.5;
}
.recurly input[type=text],
.recurly select {
vertical-align: middle;
color: #000;
}
.recurly input[type=text].invalid,
.recurly select.invalid {
border-color: #a55;
background: #fee;
color: #311;
}
.recurly input[type=text] {
display: block;
background: #fff;
border: 1px solid #a0a0a5;
box-shadow: inset 0 2px 3px rgba(0,0,0,0.10);
font-size: 16px;
font-family: inherit;
padding: 5px;
height: 22px;
}
.recurly input[type=text][disabled] {
background: #eee;
}
.recurly input[type=checkbox] {
color: #f00;
}
.recurly select {
color: inherit;
font-family: inherit;
width: 100%;
}
.recurly select > option {
color: inherit;
}
.recurly .due_now {
background: url("/recurly/images/due_now.png") no-repeat top left;
clear: both;
color: #2a3a3c;
height: 70px;
line-height: 67px;
vertical-align: middle;
padding: 0 25px;
width: 460px;
position: relative;
left: -5px;
text-shadow: 0 1px 0 rgba(255,255,255,0.50);
}
.recurly .due_now .title {
float: left;
font-size: 29px;
position: relative;
}
.recurly .due_now .cost {
color: #fff;
float: right;
font-size: 33px;
font-weight: bold;
letter-spacing: 1px;
margin: 0;
position: relative;
text-shadow: 0px 1px 1px rgba(0,0,0,0.90);
}
.recurly .footer {
border-radius: 0px 0px 9px 9px;
margin: 0px;
padding: 20px;
}
.recurly.submitting .footer {
background: url("/recurly/images/submitting.gif") no-repeat 180px 28px;
}
.recurly button.submit {
.btn;
.btn-lg;
.btn-primary;
}
// .recurly button.submit:hover {
// color: #451;
// }
// .recurly button.submit:active {
// top: 2px;
// color: #302106;
// text-shadow: rgba(255,255,255,0.57) 0 -1px 0;
// outline: none;
// background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#ce7b00), to(#fecd00));
// background: -moz-linear-gradient(top, #ce7b00, #fecd00);
// box-shadow: rgba(255,255,255,0.69) 0px -1px 0px inset, rgba(0,0,0,0.26) 0px 2px 3px;
// }
// .recurly button.submit[disabled] {
// position: relative;
// height: 46px;
// max-width: 600px;
// padding: 0 10px;
// font-weight: 700;
// color: #555;
// text-shadow: rgba(255,255,255,0.57) 0 1px 0;
// text-align: center;
// opacity: 0.75;
// border: 1px solid #767674;
// background: #e7a500;
// -moz-border-radius: 10px;
// -webkit-border-radius: 10px;
// border-radius: 10px;
// -webkit-user-select: none;
// -moz-user-select: -moz-none;
// outline: none;
// background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#dbd9d2), to(#999));
// background: -moz-linear-gradient(top, #dbd9d2, #999);
// -webkit-background-clip: padding-box;
// -webkit-box-shadow: rgba(255,255,255,0.69) 0px 1px 0px inset, rgba(0,0,0,0.26) 0px 2px 3px;
// box-shadow: rgba(255,255,255,0.70) 0px 1px 0px inset, rgba(0,0,0,0.27) 0px 2px 3px;
// }
.iefail {
background: #666;
padding: 10px;
position: absolute;
top: -1%;
left: -1%;
height: 102%;
width: 102%;
z-index: 9999;
}
.iefail .chromeframe {
background: #fff;
border: 1px solid #ccc;
padding: 10px;
}
.iefail .chromeframe p {
text-align: center;
}
.iefail .chromeframe p.blast {
font-size: 1.3em;
font-weight: bold;
}
.iefail .chromeframe p a {
color: #4183c4;
text-transform: capitalize;
}

View file

@ -16,7 +16,7 @@
@import "components/forms.less"; @import "components/forms.less";
@import "components/buttons.less"; @import "components/buttons.less";
@import "components/card.less"; @import "components/card.less";
@import "components/code.less"; //@import "components/code.less";
@import "components/component-animations.less"; @import "components/component-animations.less";
//@import "components/glyphicons.less"; //@import "components/glyphicons.less";
@import "components/dropdowns.less"; @import "components/dropdowns.less";
@ -25,19 +25,19 @@
@import "components/navs.less"; @import "components/navs.less";
@import "components/navbar.less"; @import "components/navbar.less";
@import "components/footer.less"; @import "components/footer.less";
@import "components/breadcrumbs.less"; //@import "components/breadcrumbs.less";
@import "components/pagination.less"; //@import "components/pagination.less";
@import "components/pager.less"; //@import "components/pager.less";
@import "components/labels.less"; @import "components/labels.less";
@import "components/badges.less"; //@import "components/badges.less";
@import "components/jumbotron.less"; //@import "components/jumbotron.less";
@import "components/thumbnails.less"; //@import "components/thumbnails.less";
@import "components/alerts.less"; @import "components/alerts.less";
@import "components/progress-bars.less"; @import "components/progress-bars.less";
@import "components/media.less"; // @import "components/media.less";
@import "components/list-group.less"; // @import "components/list-group.less";
@import "components/panels.less"; // @import "components/panels.less";
@import "components/wells.less"; // @import "components/wells.less";
@import "components/close.less"; @import "components/close.less";
@import "components/fineupload.less"; @import "components/fineupload.less";
@ -58,3 +58,6 @@
@import "app/project-list.less"; @import "app/project-list.less";
@import "app/editor.less"; @import "app/editor.less";
@import "app/homepage.less"; @import "app/homepage.less";
@import "app/plans.less";
@import "app/recurly.less";
@import "app/bonus.less";