mirror of
https://github.com/overleaf/overleaf.git
synced 2025-04-23 08:47:51 +00:00
Merge and fix external forms
This commit is contained in:
commit
aa8969c652
14 changed files with 157 additions and 1114 deletions
services/web
app
coffee/Features/Project
views
public
coffee
js/libs
stylesheets/components
test/UnitTests/coffee/User
|
@ -102,14 +102,25 @@ module.exports = ProjectController =
|
|||
projects = ProjectController._buildProjectList results.projects[0], results.projects[1], results.projects[2]
|
||||
ProjectController._injectProjectOwners projects, (error, projects) ->
|
||||
return next(error) if error?
|
||||
res.render 'project/list', {
|
||||
|
||||
viewModel = {
|
||||
title:'Your Projects'
|
||||
priority_title: true
|
||||
projects: projects
|
||||
tags: tags
|
||||
}
|
||||
|
||||
if Settings?.algolia?.institutions?.app_id? and Settings?.algolia?.institutions?.api_key?
|
||||
viewModel.showUserDetailsArea = true
|
||||
viewModel.algolia_api_key = Settings.algolia.institutions.api_key
|
||||
viewModel.algolia_app_id = Settings.algolia.institutions.app_id
|
||||
else
|
||||
viewModel.showUserDetailsArea = false
|
||||
|
||||
res.render 'project/list', viewModel
|
||||
timer.done()
|
||||
|
||||
|
||||
loadEditor: (req, res, next)->
|
||||
timer = new metrics.Timer("load-editor")
|
||||
if !Settings.editorIsOpen
|
||||
|
|
|
@ -31,8 +31,10 @@ html(itemscope, itemtype='http://schema.org/Product')
|
|||
script(type="text/javascript").
|
||||
window.csrfToken = "#{csrfToken}";
|
||||
|
||||
script(src=jsPath+'libs/jquery.js')
|
||||
script(src=jsPath+'libs/angular-1.2.17.js')
|
||||
script(src=jsPath+'libs/moment-2.4.0.js')
|
||||
script(src=jsPath+'libs/underscore-1.3.3.js')
|
||||
block scripts
|
||||
|
||||
- if (typeof(bodyClasses) == "undefined")
|
||||
|
|
|
@ -6,12 +6,18 @@ block scripts
|
|||
projects: !{JSON.stringify(projects)},
|
||||
tags: !{JSON.stringify(tags)}
|
||||
};
|
||||
window.algolia = {
|
||||
institutions: {
|
||||
app_id: '#{algolia_app_id}',
|
||||
api_key: '#{algolia_api_key}'
|
||||
}
|
||||
};
|
||||
|
||||
block content
|
||||
.content.content-alt(ng-controller="ProjectPageController")
|
||||
.container
|
||||
.row
|
||||
.col-md-2
|
||||
.col-md-3
|
||||
#newProject.dropdown
|
||||
a.btn.btn-primary.dropdown-toggle(
|
||||
href="#",
|
||||
|
@ -80,7 +86,66 @@ block content
|
|||
.row-spaced
|
||||
a(href="/user/bonus").btn.btn-info Upgrade Account
|
||||
|
||||
.col-md-10
|
||||
- if (showUserDetailsArea)
|
||||
.row-spaced#userProfileInformation(ng-cloak)
|
||||
div(ng-controller="UpdateForm").userProfileInformationArea
|
||||
div(ng-hide="hidePersonalInfoSection").alert.alert-info
|
||||
div(ng-show="percentComplete >= 100")
|
||||
h4 100% complete, well done!
|
||||
div(ng-hide="percentComplete >= 100")
|
||||
h4 Your profile is
|
||||
strong {{percentComplete}}%
|
||||
| complete
|
||||
|
||||
.progress
|
||||
.bar.bar-success(ng-style="{'width' : (percentComplete+'%')}")
|
||||
|
||||
button#completeUserProfileInformation.btn.btn-primary(
|
||||
ng-hide="formVisable",
|
||||
ng-click="showForm()"
|
||||
) Complete now
|
||||
|
||||
div(ng-show="formVisable")
|
||||
form(enctype='multipart/form-data', method='post')
|
||||
.form-group
|
||||
input.form-control(
|
||||
type='text',
|
||||
name='first_name',
|
||||
ng-model="userInfoForm.first_name",
|
||||
ng-blur="sendUpdate()",
|
||||
placeholder="First Name",
|
||||
focus-input="formVisable"
|
||||
)
|
||||
.form-group
|
||||
input.form-control(
|
||||
type='text',
|
||||
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-9
|
||||
.container-fluid
|
||||
.row
|
||||
.col-md-12
|
||||
|
|
|
@ -8,14 +8,22 @@ block content
|
|||
.card
|
||||
.page-header
|
||||
h1 Login
|
||||
.messageArea
|
||||
form.validate#loginForm(enctype='multipart/form-data', method='post')
|
||||
form(async-form="login", action='/login')
|
||||
input(name='_csrf', type='hidden', value=csrfToken)
|
||||
input(name='redir', type='hidden', value=redir)
|
||||
form-messages
|
||||
.form-group
|
||||
input#email.email.required.form-control(type='email', autofocus="autofocus", name='email', placeholder='email@example.com')
|
||||
input.form-control(
|
||||
type='email',
|
||||
name='email',
|
||||
placeholder='email@example.com'
|
||||
)
|
||||
.form-group
|
||||
input#password.required.form-control(type='password', name='password', placeholder='********')
|
||||
input.form-control(
|
||||
type='password',
|
||||
name='password',
|
||||
placeholder='********'
|
||||
)
|
||||
.actions
|
||||
button.btn-primary.btn#login(type='submit') Login
|
||||
a#passwordReset.pull-right(href='/user/password/reset') Forgot your password?
|
||||
button.btn-primary.btn(type='submit') Login
|
||||
a.pull-right(href='/user/password/reset') Forgot your password?
|
||||
|
|
|
@ -9,10 +9,20 @@ block content
|
|||
.page-header
|
||||
h1 Password Reset
|
||||
.messageArea
|
||||
form.validate#passwordReset(method='post')
|
||||
form(
|
||||
async-form="password-reset-request",
|
||||
action="/user/password/reset"
|
||||
)
|
||||
input(type="hidden", name="_csrf", value=csrfToken)
|
||||
form-messages
|
||||
.alert.alert-success(ng-show="success")
|
||||
| You have been sent an email to complete your password reset.
|
||||
.form-group
|
||||
label(for='email') Please enter your email address
|
||||
input.email.required.form-control(type='email', name='email', placeholder='email@example.com')
|
||||
input.form-control(
|
||||
type='email',
|
||||
name='email',
|
||||
placeholder='email@example.com'
|
||||
)
|
||||
.actions
|
||||
button.btn.btn-primary.btn.btn-large(type='submit') Request password reset
|
||||
button.btn.btn-primary(type='submit') Request password reset
|
||||
|
|
|
@ -18,16 +18,16 @@ block content
|
|||
.card
|
||||
.page-header
|
||||
h1 Register
|
||||
.messageArea
|
||||
form#registerFormShort(method="post")
|
||||
form(async-form="register", action="/register")
|
||||
input(name='_csrf', type='hidden', value=csrfToken)
|
||||
input(name='redir', type='hidden', value=redir)
|
||||
form-messages
|
||||
.form-group
|
||||
label(for='email') Email
|
||||
input#email.email.required.form-control(type='email', name='email', value='#{new_email}')
|
||||
input.form-control(type='email', name='email', value='#{new_email}')
|
||||
.form-group
|
||||
label(for='password') Password
|
||||
input#password.required.form-control(type='password', name='password')
|
||||
input.form-control(type='password', name='password')
|
||||
.actions
|
||||
button#registerButton.btn-primary.btn(type='submit') Register
|
||||
button.btn-primary.btn(type='submit') Register
|
||||
|
||||
|
|
|
@ -8,11 +8,26 @@ block content
|
|||
.card
|
||||
.page-header
|
||||
h1 Reset your password
|
||||
.messageArea
|
||||
form.validate#setPasswordReset(method='post')
|
||||
form(
|
||||
async-form="password-reset",
|
||||
action="/user/password/set"
|
||||
)
|
||||
input(type="hidden", name="_csrf", value=csrfToken)
|
||||
form-messages
|
||||
.alert.alert-success(ng-show="success")
|
||||
| Your password has been reset.
|
||||
a(href='/login') Login here
|
||||
|
||||
.form-group
|
||||
input.password.required.form-control(type='password', name='password', placeholder='new password')
|
||||
input(type="hidden", name="passwordResetToken", value=passwordResetToken)
|
||||
input.form-control(
|
||||
type='password',
|
||||
name='password',
|
||||
placeholder='new password'
|
||||
)
|
||||
input(
|
||||
type="hidden",
|
||||
name="passwordResetToken",
|
||||
value=passwordResetToken
|
||||
)
|
||||
.actions
|
||||
button.btn.btn-primary.btn.btn-large(type='submit') Set new password
|
||||
button.btn.btn-primary(type='submit') Set new password
|
|
@ -1,5 +1,6 @@
|
|||
define [
|
||||
"project-list"
|
||||
"user-details"
|
||||
"directives/asyncForm"
|
||||
], () ->
|
||||
angular.bootstrap(document.body, ["SharelatexApp"])
|
|
@ -2,8 +2,8 @@ define [
|
|||
"base"
|
||||
"../libs/algolia"
|
||||
], (App, algolia)->
|
||||
App.factory "Institutions", ->
|
||||
new AlgoliaSearch("SK53GL4JLY", "1606ccef5b70ac44680b61e6b0285126").initIndex("institutions")
|
||||
app.factory "Institutions", ->
|
||||
new AlgoliaSearch(window.algolia.institutions.app_id, window.algolia.institutions.api_key).initIndex("institutions")
|
||||
|
||||
App.directive "focusInput", ($timeout) ->
|
||||
return (scope, element, attr) ->
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
require [
|
||||
"libs/jquery.storage"
|
||||
"libs/bootstrap"
|
||||
], ()->
|
||||
$('tr.clickable').click (event)->
|
||||
window.location = $(event.target).closest('tr').attr("href")
|
||||
|
||||
$('.dropdown-toggle').dropdown()
|
||||
# $('.tabs').tab('show')
|
||||
|
||||
$(".carousel").carousel()
|
||||
|
||||
$("#scribtexModal").modal()
|
||||
|
||||
return
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
define [
|
||||
"libs/bootstrap"
|
||||
"forms"
|
||||
], ()->
|
||||
$(document).ready ()->
|
File diff suppressed because it is too large
Load diff
|
@ -296,6 +296,16 @@ input[type="checkbox"],
|
|||
.form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg);
|
||||
}
|
||||
|
||||
// .form-control.ng-invalid {
|
||||
// border-color: @state-danger-text;
|
||||
// .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work
|
||||
// &:focus {
|
||||
// border-color: darken(@state-danger-text, 10%);
|
||||
// @shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@state-danger-text, 20%);
|
||||
// .box-shadow(@shadow);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// Static form control text
|
||||
//
|
||||
|
|
|
@ -18,10 +18,14 @@ describe "UserInfoController", ->
|
|||
updatePersonalInfo: sinon.stub()
|
||||
@sanitizer = escape:(v)->v
|
||||
sinon.spy @sanitizer, "escape"
|
||||
@UserGetter = {}
|
||||
|
||||
|
||||
@UserInfoController = SandboxedModule.require modulePath, requires:
|
||||
"./UserGetter": @UserGetter = {}
|
||||
"./UserGetter": @UserGetter
|
||||
"./UserUpdater": @UserUpdater
|
||||
"./UserDeleter": @UserDeleter
|
||||
"logger-sharelatex": log:->
|
||||
"sanitizer":@sanitizer
|
||||
|
||||
@req = new MockRequest()
|
||||
|
@ -33,7 +37,9 @@ describe "UserInfoController", ->
|
|||
@user =
|
||||
_id: ObjectId()
|
||||
@req.user = @user
|
||||
@req.session.user = @user
|
||||
@UserInfoController.sendFormattedPersonalInfo = sinon.stub()
|
||||
@UserGetter.getUser = sinon.stub().callsArgWith(2, null, @user)
|
||||
@UserInfoController.getLoggedInUsersPersonalInfo(@req, @res, @next)
|
||||
|
||||
it "should call sendFormattedPersonalInfo", ->
|
||||
|
@ -105,6 +111,8 @@ describe "UserInfoController", ->
|
|||
email: "doug@sharelatex.com"
|
||||
password: "should-not-get-included"
|
||||
signUpDate: new Date()
|
||||
role:"student"
|
||||
institution:"sheffield"
|
||||
@UserInfoController._formatPersonalInfo @user, (error, info) =>
|
||||
expect(info).to.deep.equal {
|
||||
id: @user._id.toString()
|
||||
|
@ -112,6 +120,8 @@ describe "UserInfoController", ->
|
|||
last_name: @user.last_name
|
||||
email: @user.email
|
||||
signUpDate: @user.signUpDate
|
||||
role: @user.role
|
||||
institution: @user.institution
|
||||
}
|
||||
|
||||
describe "setPersonalInfo", ->
|
||||
|
|
Loading…
Add table
Reference in a new issue