Merge branch 'master' of github.com:sharelatex/web-sharelatex

This commit is contained in:
Shane Kilkelly 2016-02-03 11:08:58 +00:00
commit 7fceb2b3af
13 changed files with 132 additions and 42 deletions

View file

@ -58,7 +58,7 @@ module.exports = ClsiManager =
return outputFiles return outputFiles
VALID_COMPILERS: ["pdflatex", "latex", "xelatex", "lualatex"] VALID_COMPILERS: ["pdflatex", "latex", "xelatex", "lualatex"]
_buildRequest: (project_id, settingsOverride={}, callback = (error, request) ->) -> _buildRequest: (project_id, options={}, callback = (error, request) ->) ->
Project.findById project_id, {compiler: 1, rootDoc_id: 1, imageName: 1}, (error, project) -> Project.findById project_id, {compiler: 1, rootDoc_id: 1, imageName: 1}, (error, project) ->
return callback(error) if error? return callback(error) if error?
return callback(new Errors.NotFoundError("project does not exist: #{project_id}")) if !project? return callback(new Errors.NotFoundError("project does not exist: #{project_id}")) if !project?
@ -82,7 +82,7 @@ module.exports = ClsiManager =
content: doc.lines.join("\n") content: doc.lines.join("\n")
if project.rootDoc_id? and doc._id.toString() == project.rootDoc_id.toString() if project.rootDoc_id? and doc._id.toString() == project.rootDoc_id.toString()
rootResourcePath = path rootResourcePath = path
if settingsOverride.rootDoc_id? and doc._id.toString() == settingsOverride.rootDoc_id.toString() if options.rootDoc_id? and doc._id.toString() == options.rootDoc_id.toString()
rootResourcePathOverride = path rootResourcePathOverride = path
rootResourcePath = rootResourcePathOverride if rootResourcePathOverride? rootResourcePath = rootResourcePathOverride if rootResourcePathOverride?
@ -101,8 +101,9 @@ module.exports = ClsiManager =
compile: compile:
options: options:
compiler: project.compiler compiler: project.compiler
timeout: settingsOverride.timeout timeout: options.timeout
imageName: project.imageName imageName: project.imageName
draft: !!options.draft
rootResourcePath: rootResourcePath rootResourcePath: rootResourcePath
resources: resources resources: resources
} }

View file

@ -25,6 +25,8 @@ module.exports = CompileController =
options.rootDoc_id = req.body.settingsOverride.rootDoc_id options.rootDoc_id = req.body.settingsOverride.rootDoc_id
if req.body?.compiler if req.body?.compiler
options.compiler = req.body.compiler options.compiler = req.body.compiler
if req.body?.draft
options.draft = req.body.draft
logger.log {options, project_id}, "got compile request" logger.log {options, project_id}, "got compile request"
CompileManager.compile project_id, user_id, options, (error, status, outputFiles, output, limits) -> CompileManager.compile project_id, user_id, options, (error, status, outputFiles, output, limits) ->
return next(error) if error? return next(error) if error?

View file

@ -15,7 +15,7 @@ module.exports = RateLimiterMiddlewear =
### ###
rateLimit: (opts) -> rateLimit: (opts) ->
return (req, res, next) -> return (req, res, next) ->
if req.session.user? if req.session?.user?
user_id = req.session.user._id user_id = req.session.user._id
else else
user_id = req.ip user_id = req.ip

View file

@ -1,16 +1,34 @@
div.full-size.pdf(ng-controller="PdfController") div.full-size.pdf(ng-controller="PdfController")
.toolbar.toolbar-tall .toolbar.toolbar-tall
a.btn.btn-info( .btn-group(dropdown)
href, a.btn.btn-info(
ng-disabled="pdf.compiling", href,
ng-click="recompile()" ng-disabled="pdf.compiling",
) ng-click="recompile()"
i.fa.fa-refresh(
ng-class="{'fa-spin': pdf.compiling }"
) )
|    i.fa.fa-refresh(
span(ng-show="!pdf.compiling") #{translate("recompile")} ng-class="{'fa-spin': pdf.compiling }"
span(ng-show="pdf.compiling") #{translate("compiling")}... )
|   
span(ng-show="!pdf.compiling") #{translate("recompile")}
span(ng-show="pdf.compiling") #{translate("compiling")}...
a.btn.btn-info.dropdown-toggle(
href,
ng-disabled="pdf.compiling",
dropdown-toggle
)
span.caret
ul.dropdown-menu.dropdown-menu-right
li.dropdown-header #{translate("compile_mode")}
li
a(href, ng-click="draft = false")
i.fa.fa-fw(ng-class="{'fa-check': !draft}")
|  #{translate("normal")}
li
a(href, ng-click="draft = true")
i.fa.fa-fw(ng-class="{'fa-check': draft}")
|  #{translate("fast")} 
span.subdued [draft]
a.log-btn( a.log-btn(
href href
ng-click="toggleLogs()" ng-click="toggleLogs()"

View file

@ -106,6 +106,8 @@ module.exports =
url: "http://localhost:3036" url: "http://localhost:3036"
sixpack: sixpack:
url: "" url: ""
references:
url: "http://localhost:3040"
templates: templates:
user_id: process.env.TEMPLATES_USER_ID or "5395eb7aad1f29a88756c7f2" user_id: process.env.TEMPLATES_USER_ID or "5395eb7aad1f29a88756c7f2"

View file

@ -12,6 +12,11 @@ define [
$scope.$on "pdf:error:display", () -> $scope.$on "pdf:error:display", () ->
$scope.pdf.error = true $scope.pdf.error = true
$scope.draft = localStorage("draft:#{$scope.project_id}") or false
$scope.$watch "draft", (new_value, old_value) ->
if new_value? and old_value != new_value
localStorage("draft:#{$scope.project_id}", new_value)
sendCompileRequest = (options = {}) -> sendCompileRequest = (options = {}) ->
url = "/project/#{$scope.project_id}/compile" url = "/project/#{$scope.project_id}/compile"
@ -19,6 +24,7 @@ define [
url += "?auto_compile=true" url += "?auto_compile=true"
return $http.post url, { return $http.post url, {
rootDoc_id: options.rootDocOverride_id or null rootDoc_id: options.rootDocOverride_id or null
draft: $scope.draft
_csrf: window.csrfToken _csrf: window.csrfToken
} }
@ -103,8 +109,8 @@ define [
doc = ide.editorManager.getCurrentDocValue() doc = ide.editorManager.getCurrentDocValue()
return null if !doc? return null if !doc?
for line in doc.split("\n") for line in doc.split("\n")
match = line.match /(.*)\\documentclass/ match = line.match /^[^%]*\\documentclass/
if match and !match[1].match /%/ if match
return ide.editorManager.getCurrentDocId() return ide.editorManager.getCurrentDocId()
return null return null

View file

@ -5,13 +5,21 @@ define [
App.controller 'UniverstiesContactController', ($scope, $modal) -> App.controller 'UniverstiesContactController', ($scope, $modal) ->
$scope.form = {} $scope.form = {}
$scope.sent = false
$scope.sending = false
$scope.contactUs = -> $scope.contactUs = ->
if !$scope.form.email?
console.log "email not set"
return
$scope.sending = true
params = params =
name: $scope.form.name || $scope.form.email name: $scope.form.name || $scope.form.email
email: $scope.form.email email: $scope.form.email
labels: $scope.form.type labels: $scope.form.source
message: "Please contact me with more details" message: "Please contact me with more details"
subject: $scope.form.subject subject: $scope.form.subject
about : "#{$scope.form.position || ''} #{$scope.form.university || ''} #{$scope.form.source || ''}" about : "#{$scope.form.position || ''} #{$scope.form.university || ''}"
Groove.createTicket params, (err, json)-> Groove.createTicket params, (err, json)->
$scope.sent = true
$scope.$apply()

View file

@ -2,7 +2,7 @@
height: 40px; height: 40px;
border-bottom: 1px solid @toolbar-border-color; border-bottom: 1px solid @toolbar-border-color;
a { > a, .toolbar-right > a {
position: relative; position: relative;
.label { .label {
position: absolute; position: absolute;
@ -13,7 +13,7 @@
} }
} }
a:not(.btn) { > a:not(.btn), .toolbar-right > a:not(.btn) {
display: inline-block; display: inline-block;
color: @gray-light; color: @gray-light;
padding: 4px 10px 5px; padding: 4px 10px 5px;
@ -90,27 +90,36 @@
&.toolbar-small { &.toolbar-small {
height: 32px; height: 32px;
a { > a, .toolbar-right > a {
padding: 4px 2px 2px; padding: 4px 2px 2px;
margin: 0; margin: 0;
}
> a {
margin-left: 6px; margin-left: 6px;
} }
.toolbar-right { .toolbar-right > a {
a { margin-left: 0;
margin-left: 0; margin-right: 6px;
margin-right: 6px;
}
} }
} }
&.toolbar-tall { &.toolbar-tall {
height: 58px; height: 58px;
padding-top: 10px; padding-top: 10px;
a.btn { > a, .toolbar-right > a {
padding: 4px 10px 5px;
}
> a.btn, .toolbar-right > a.btn {
margin: 0 (@line-height-computed / 2); margin: 0 (@line-height-computed / 2);
} }
a { .btn-group {
padding: 4px 10px 5px; margin: 0 (@line-height-computed / 2);
> a {
margin: 0;
}
> .btn-group {
margin: 0;
}
} }
} }
@ -135,7 +144,7 @@
&.toolbar-header { &.toolbar-header {
box-shadow: none; box-shadow: none;
} }
a:not(.btn) { > a:not(.btn) {
color: @gray; color: @gray;
&:hover { &:hover {
color: @gray-light; color: @gray-light;

View file

@ -66,6 +66,7 @@
.btn-group > .btn:last-child:not(:first-child), .btn-group > .btn:last-child:not(:first-child),
.btn-group > .dropdown-toggle:not(:first-child) { .btn-group > .dropdown-toggle:not(:first-child) {
.border-left-radius(0); .border-left-radius(0);
border-left: none;
} }
// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group) // Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)

View file

@ -67,6 +67,9 @@
line-height: @line-height-base; line-height: @line-height-base;
color: @dropdown-link-color; color: @dropdown-link-color;
white-space: nowrap; // prevent links from randomly breaking onto new lines white-space: nowrap; // prevent links from randomly breaking onto new lines
.subdued {
color: #7a7a7a
}
} }
} }
@ -77,6 +80,9 @@
text-decoration: none; text-decoration: none;
color: @dropdown-link-hover-color; color: @dropdown-link-hover-color;
background-color: @dropdown-link-hover-bg; background-color: @dropdown-link-hover-bg;
.subdued {
color: @dropdown-link-hover-color;
}
} }
} }

View file

@ -166,6 +166,7 @@ describe "ClsiManager", ->
compiler: @compiler compiler: @compiler
timeout : 100 timeout : 100
imageName: @image imageName: @image
draft: false
rootResourcePath: "main.tex" rootResourcePath: "main.tex"
resources: [{ resources: [{
path: "main.tex" path: "main.tex"
@ -220,6 +221,12 @@ describe "ClsiManager", ->
it "should return an error", -> it "should return an error", ->
expect(@error).to.exist expect(@error).to.exist
describe "with the draft option", ->
it "should add the draft option into the request", (done) ->
@ClsiManager._buildRequest @project_id, {timeout:100, draft: true}, (error, request) =>
request.compile.options.draft.should.equal true
done()
describe '_postToClsi', -> describe '_postToClsi', ->

View file

@ -43,14 +43,15 @@ describe "CompileController", ->
@res = new MockResponse() @res = new MockResponse()
describe "compile", -> describe "compile", ->
beforeEach ->
@req.params =
Project_id: @project_id
@req.session = {}
@AuthenticationController.getLoggedInUserId = sinon.stub().callsArgWith(1, null, @user_id = "mock-user-id")
@CompileManager.compile = sinon.stub().callsArgWith(3, null, @status = "success", @outputFiles = ["mock-output-files"])
describe "when not an auto compile", -> describe "when not an auto compile", ->
beforeEach -> beforeEach ->
@req.params =
Project_id: @project_id
@req.session = {}
@AuthenticationController.getLoggedInUserId = sinon.stub().callsArgWith(1, null, @user_id = "mock-user-id")
@CompileManager.compile = sinon.stub().callsArgWith(3, null, @status = "success", @outputFiles = ["mock-output-files"], @output = "mock-output")
@CompileController.compile @req, @res, @next @CompileController.compile @req, @res, @next
it "should look up the user id", -> it "should look up the user id", ->
@ -77,18 +78,25 @@ describe "CompileController", ->
describe "when an auto compile", -> describe "when an auto compile", ->
beforeEach -> beforeEach ->
@req.params =
Project_id: @project_id
@req.query = @req.query =
auto_compile: "true" auto_compile: "true"
@AuthenticationController.getLoggedInUserId = sinon.stub().callsArgWith(1, null, @user_id = "mock-user-id")
@CompileManager.compile = sinon.stub().callsArgWith(3, null, @status = "success", @outputFiles = ["mock-output-files"])
@CompileController.compile @req, @res, @next @CompileController.compile @req, @res, @next
it "should do the compile with the auto compile flag", -> it "should do the compile with the auto compile flag", ->
@CompileManager.compile @CompileManager.compile
.calledWith(@project_id, @user_id, { isAutoCompile: true }) .calledWith(@project_id, @user_id, { isAutoCompile: true })
.should.equal true .should.equal true
describe "with the draft attribute", ->
beforeEach ->
@req.body =
draft: true
@CompileController.compile @req, @res, @next
it "should do the compile without the draft compile flag", ->
@CompileManager.compile
.calledWith(@project_id, @user_id, { isAutoCompile: false, draft: true })
.should.equal true
describe "downloadPdf", -> describe "downloadPdf", ->
beforeEach -> beforeEach ->

View file

@ -10,7 +10,6 @@ describe "RateLimiterMiddlewear", ->
"logger-sharelatex": @logger = {warn: sinon.stub()} "logger-sharelatex": @logger = {warn: sinon.stub()}
@req = @req =
params: {} params: {}
session: {}
@res = @res =
status: sinon.stub() status: sinon.stub()
write: sinon.stub() write: sinon.stub()
@ -30,9 +29,30 @@ describe "RateLimiterMiddlewear", ->
doc_id: @doc_id = "doc-id" doc_id: @doc_id = "doc-id"
} }
describe "when there is no session", ->
beforeEach ->
@RateLimiter.addCount = sinon.stub().callsArgWith(1, null, true)
@req.ip = @ip = "1.2.3.4"
@rateLimiter(@req, @res, @next)
it "should call the rate limiter backend with the ip address", ->
@RateLimiter.addCount
.calledWith({
endpointName: "test-endpoint"
timeInterval: 42
throttle: 12
subjectName: "#{@project_id}:#{@doc_id}:#{@ip}"
})
.should.equal true
it "should pass on to next()", ->
describe "when under the rate limit with logged in user", -> describe "when under the rate limit with logged in user", ->
beforeEach -> beforeEach ->
@req.session.user = { _id: @user_id = "user-id" } @req.session =
user :
_id: @user_id = "user-id"
@RateLimiter.addCount = sinon.stub().callsArgWith(1, null, true) @RateLimiter.addCount = sinon.stub().callsArgWith(1, null, true)
@rateLimiter(@req, @res, @next) @rateLimiter(@req, @res, @next)
@ -70,7 +90,9 @@ describe "RateLimiterMiddlewear", ->
describe "when over the rate limit", -> describe "when over the rate limit", ->
beforeEach -> beforeEach ->
@req.session.user = { _id: @user_id = "user-id" } @req.session =
user :
_id: @user_id = "user-id"
@RateLimiter.addCount = sinon.stub().callsArgWith(1, null, false) @RateLimiter.addCount = sinon.stub().callsArgWith(1, null, false)
@rateLimiter(@req, @res, @next) @rateLimiter(@req, @res, @next)