diff --git a/services/web/app/coffee/Features/Editor/EditorController.coffee b/services/web/app/coffee/Features/Editor/EditorController.coffee index 19e9d98da5..b3bbba555c 100644 --- a/services/web/app/coffee/Features/Editor/EditorController.coffee +++ b/services/web/app/coffee/Features/Editor/EditorController.coffee @@ -140,16 +140,6 @@ module.exports = EditorController = if callback? callback() - setCompiler : (project_id, compiler, callback = ()->)-> - ProjectOptionsHandler.setCompiler project_id, compiler, (err)-> - logger.log compiler:compiler, project_id:project_id, "setting compiler" - callback() - - setSpellCheckLanguage : (project_id, languageCode, callback = ()->)-> - ProjectOptionsHandler.setSpellCheckLanguage project_id, languageCode, (err)-> - logger.log languageCode:languageCode, project_id:project_id, "setting languageCode for spell check" - callback() - setDoc: (project_id, doc_id, docLines, sl_req_id, callback = (err)->)-> {callback, sl_req_id} = slReqIdHelper.getCallbackAndReqId(callback, sl_req_id) DocumentUpdaterHandler.setDocument project_id, doc_id, docLines, (err)=> @@ -253,21 +243,37 @@ module.exports = EditorController = EditorRealTimeController.emitToRoom project_id, 'reciveEntityMove', entity_id, folder_id callback?() - renameProject: (project_id, newName, callback)-> + renameProject: (project_id, newName, callback = (err) ->) -> newName = sanitize.escape(newName) ProjectDetailsHandler.renameProject project_id, newName, => EditorRealTimeController.emitToRoom project_id, 'projectNameUpdated', newName - callback?() + callback() - setPublicAccessLevel : (project_id, newAccessLevel, callback)-> - ProjectDetailsHandler.setPublicAccessLevel project_id, newAccessLevel, => + setCompiler : (project_id, compiler, callback = (err) ->) -> + ProjectOptionsHandler.setCompiler project_id, compiler, (err) -> + return callback(err) if err? + logger.log compiler:compiler, project_id:project_id, "setting compiler" + EditorRealTimeController.emitToRoom project_id, 'compilerUpdated', compiler + callback() + + setSpellCheckLanguage : (project_id, languageCode, callback = (err) ->) -> + ProjectOptionsHandler.setSpellCheckLanguage project_id, languageCode, (err) -> + return callback(err) if err? + logger.log languageCode:languageCode, project_id:project_id, "setting languageCode for spell check" + EditorRealTimeController.emitToRoom project_id, 'spellCheckLanguageUpdated', languageCode + callback() + + setPublicAccessLevel : (project_id, newAccessLevel, callback = (err) ->) -> + ProjectDetailsHandler.setPublicAccessLevel project_id, newAccessLevel, (err) -> + return callback(err) if err? EditorRealTimeController.emitToRoom project_id, 'publicAccessLevelUpdated', newAccessLevel - callback?() + callback() - setRootDoc: (project_id, newRootDocID, callback)-> - ProjectEntityHandler.setRootDoc project_id, newRootDocID, () => + setRootDoc: (project_id, newRootDocID, callback = (err) ->) -> + ProjectEntityHandler.setRootDoc project_id, newRootDocID, (err) -> + return callback(err) if err? EditorRealTimeController.emitToRoom project_id, 'rootDocUpdated', newRootDocID - callback?() + callback() p: diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index 63dc83354d..5c3393bdbb 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -17,6 +17,35 @@ fs = require "fs" module.exports = ProjectController = + updateProjectSettings: (req, res, next) -> + project_id = req.params.Project_id + + jobs = [] + + if req.body.compiler? + jobs.push (callback) -> + editorController.setCompiler project_id, req.body.compiler, callback + + if req.body.name? + jobs.push (callback) -> + editorController.renameProject project_id, req.body.name, callback + + if req.body.spellCheckLanguage? + jobs.push (callback) -> + editorController.setSpellCheckLanguage project_id, req.body.spellCheckLanguage, callback + + if req.body.rootDocId? + jobs.push (callback) -> + editorController.setRootDoc project_id, req.body.rootDocId, callback + + if req.body.publicAccessLevel? + jobs.push (callback) -> + editorController.setPublicAccessLevel project_id, req.body.publicAccessLevel, callback + + async.series jobs, (error) -> + return next(error) if error? + res.send(204) + deleteProject: (req, res) -> project_id = req.params.Project_id forever = req.query?.forever? @@ -183,10 +212,7 @@ module.exports = ProjectController = theme : user.ace.theme fontSize : user.ace.fontSize autoComplete: user.ace.autoComplete - spellCheckLanguage: user.ace.spellCheckLanguage pdfViewer : user.ace.pdfViewer - docPositions: {} - oldHistory: !!user.featureSwitches?.oldHistory }) sharelatexObject : JSON.stringify({ siteUrl: Settings.siteUrl, diff --git a/services/web/app/coffee/router.coffee b/services/web/app/coffee/router.coffee index 287ba8e4c8..43d59ad48c 100644 --- a/services/web/app/coffee/router.coffee +++ b/services/web/app/coffee/router.coffee @@ -87,6 +87,8 @@ module.exports = class Router app.get '/Project/:Project_id', SecurityManager.requestCanAccessProject, ProjectController.loadEditor app.get '/Project/:Project_id/file/:File_id', SecurityManager.requestCanAccessProject, FileStoreController.getFile + app.post '/project/:Project_id/settings', SecurityManager.requestCanModifyProject, ProjectController.updateProjectSettings + app.post '/project/:Project_id/doc', SecurityManager.requestCanModifyProject, EditorHttpController.addDoc app.post '/project/:Project_id/folder', SecurityManager.requestCanModifyProject, EditorHttpController.addFolder @@ -247,14 +249,6 @@ module.exports = class Router AuthorizationManager.ensureClientCanAdminProject client, (error, project_id) => EditorController.removeUserFromProject(project_id, user_id, callback) - client.on 'setSpellCheckLanguage', (compiler, callback)-> - AuthorizationManager.ensureClientCanEditProject client, (error, project_id) => - EditorController.setSpellCheckLanguage project_id, compiler, callback - - client.on 'setCompiler', (compiler, callback)-> - AuthorizationManager.ensureClientCanEditProject client, (error, project_id) => - EditorController.setCompiler project_id, compiler, callback - client.on 'leaveDoc', (doc_id, callback)-> AuthorizationManager.ensureClientCanViewProject client, (error, project_id) => EditorController.leaveDoc(client, project_id, doc_id, callback) @@ -263,38 +257,6 @@ module.exports = class Router AuthorizationManager.ensureClientCanViewProject client, (error, project_id) => EditorController.joinDoc(client, project_id, args...) - client.on 'addDoc', (folder_id, docName, callback)-> - AuthorizationManager.ensureClientCanEditProject client, (error, project_id) => - EditorController.addDoc(project_id, folder_id, docName, [""], callback) - - client.on 'addFolder', (folder_id, folderName, callback)-> - AuthorizationManager.ensureClientCanEditProject client, (error, project_id) => - EditorController.addFolder(project_id, folder_id, folderName, callback) - - client.on 'deleteEntity', (entity_id, entityType, callback)-> - AuthorizationManager.ensureClientCanEditProject client, (error, project_id) => - EditorController.deleteEntity(project_id, entity_id, entityType, callback) - - client.on 'renameEntity', (entity_id, entityType, newName, callback)-> - AuthorizationManager.ensureClientCanEditProject client, (error, project_id) => - EditorController.renameEntity(project_id, entity_id, entityType, newName, callback) - - client.on 'moveEntity', (entity_id, folder_id, entityType, callback)-> - AuthorizationManager.ensureClientCanEditProject client, (error, project_id) => - EditorController.moveEntity(project_id, entity_id, folder_id, entityType, callback) - - client.on 'setProjectName', (newName, callback)-> - AuthorizationManager.ensureClientCanEditProject client, (error, project_id) => - EditorController.renameProject(project_id, newName, callback) - - client.on 'setRootDoc', (newRootDocID, callback)-> - AuthorizationManager.ensureClientCanEditProject client, (error, project_id) => - EditorController.setRootDoc(project_id, newRootDocID, callback) - - client.on 'setPublicAccessLevel', (newAccessLevel, callback)-> - AuthorizationManager.ensureClientCanAdminProject client, (error, project_id) => - EditorController.setPublicAccessLevel(project_id, newAccessLevel, callback) - # Deprecated and can be removed after deploying. client.on 'pdfProject', (opts, callback)-> AuthorizationManager.ensureClientCanViewProject client, (error, project_id) => diff --git a/services/web/app/views/project/editor.jade b/services/web/app/views/project/editor.jade index 543176724c..1fe9fd8806 100644 --- a/services/web/app/views/project/editor.jade +++ b/services/web/app/views/project/editor.jade @@ -38,7 +38,31 @@ block content ng-cloak ) h4 Settings - form + form + .form-controls + label(for="compiler") Compiler + select.form-control( + name="compiler" + ng-model="project.compiler" + ) + option(value='pdflatex') pdfLaTeX + option(value='latex') LaTeX + option(value='xelatex') XeLaTeX + option(value='lualatex') LuaLaTeX + + .form-controls + label(for="spellCheckLanguage") Spell Check + select.form-control( + name="spellCheckLanguage" + ng-model="project.spellCheckLanguage" + ) + option(value="") Off + optgroup(label="Language") + for language in languages + option( + value=language.code + )= language.name + .form-controls label(for="autoComplete") Auto-Complete input.form-control( diff --git a/services/web/config/settings.defaults.coffee b/services/web/config/settings.defaults.coffee index 77ffb73793..30f16cf417 100644 --- a/services/web/config/settings.defaults.coffee +++ b/services/web/config/settings.defaults.coffee @@ -136,7 +136,8 @@ module.exports = # You must have the corresponding aspell package installed to # be able to use a language. languages: [ - {name: "English", code: "en"} + {name: "English", code: "en"}, + {name: "French", code: "fr"} ] # Email support diff --git a/services/web/public/coffee/app/ide/settings/SettingsManager.coffee b/services/web/public/coffee/app/ide/settings/SettingsManager.coffee index 6e9f4abdf9..4a64ce0752 100644 --- a/services/web/public/coffee/app/ide/settings/SettingsManager.coffee +++ b/services/web/public/coffee/app/ide/settings/SettingsManager.coffee @@ -19,10 +19,37 @@ define [], () -> @saveSettings({mode: mode}) @$scope.$watch "settings.autoComplete", (autoComplete, oldAutoComplete) => - console.log "autoComplete", autoComplete if autoComplete != oldAutoComplete @saveSettings({autoComplete: autoComplete}) + @$scope.$watch "project.spellCheckLanguage", (language, oldLanguage) => + return if @ignoreUpdates + if oldLanguage? and language != oldLanguage + @saveProjectSettings({spellCheckLanguage: language}) + # Also set it as the default for the user + @saveSettings({spellCheckLanguage: language}) + + @$scope.$watch "project.compiler", (compiler, oldCompiler) => + return if @ignoreUpdates + if oldCompiler? and compiler != oldCompiler + @saveProjectSettings({compiler: compiler}) + + @ide.socket.on "compilerUpdated", (compiler) => + @ignoreUpdates = true + @$scope.$apply () => + @$scope.project.compiler = compiler + delete @ignoreUpdates + + @ide.socket.on "spellCheckLanguageUpdated", (languageCode) => + @ignoreUpdates = true + @$scope.$apply () => + @$scope.project.spellCheckLanguage = languageCode + delete @ignoreUpdates + saveSettings: (data) -> data._csrf = window.csrfToken @ide.$http.post "/user/settings", data + + saveProjectSettings: (data) -> + data._csrf = window.csrfToken + @ide.$http.post "/project/#{@ide.project_id}/settings", data diff --git a/services/web/public/coffee/app/main/project-list.coffee b/services/web/public/coffee/app/main/project-list.coffee index 009eea9a5b..d0cdd7d6ff 100644 --- a/services/web/public/coffee/app/main/project-list.coffee +++ b/services/web/public/coffee/app/main/project-list.coffee @@ -43,7 +43,7 @@ define [ deferred.reject(errorArgs...) pendingRequests.push doRequest - processRequests() + processPendingRequests() return promise diff --git a/services/web/public/coffee/app/main/user-details.coffee b/services/web/public/coffee/app/main/user-details.coffee index 9b95a798a1..ce6258f16d 100644 --- a/services/web/public/coffee/app/main/user-details.coffee +++ b/services/web/public/coffee/app/main/user-details.coffee @@ -1,6 +1,6 @@ define [ "base" - "../libs/algolia" + "../../libs/algolia" ], (App, algolia)-> app.factory "Institutions", -> new AlgoliaSearch(window.algolia.institutions.app_id, window.algolia.institutions.api_key).initIndex("institutions") diff --git a/services/web/test/UnitTests/coffee/Editor/EditorControllerTests.coffee b/services/web/test/UnitTests/coffee/Editor/EditorControllerTests.coffee index cccae79394..8f4ad5bb6f 100644 --- a/services/web/test/UnitTests/coffee/Editor/EditorControllerTests.coffee +++ b/services/web/test/UnitTests/coffee/Editor/EditorControllerTests.coffee @@ -349,8 +349,11 @@ describe "EditorController", -> describe "updating compiler used for project", -> it "should send the new compiler and project id to the project options handler", (done)-> compiler = "latex" - @EditorController.setCompiler @project_id, compiler, (err)=> + @EditorRealTimeController.emitToRoom = sinon.stub() + @EditorController.setCompiler @project_id, compiler, (err) => @ProjectOptionsHandler.setCompiler.calledWith(@project_id, compiler).should.equal true + console.log @EditorRealTimeController.emitToRoom.args + @EditorRealTimeController.emitToRoom.calledWith(@project_id, "compilerUpdated", compiler).should.equal true done() @ProjectOptionsHandler.setCompiler.args[0][2]() @@ -358,8 +361,11 @@ describe "EditorController", -> describe "updating language code used for project", -> it "should send the new languageCode and project id to the project options handler", (done)-> languageCode = "fr" - @EditorController.setSpellCheckLanguage @project_id, languageCode, (err)=> + @EditorRealTimeController.emitToRoom = sinon.stub() + @EditorController.setSpellCheckLanguage @project_id, languageCode, (err) => @ProjectOptionsHandler.setSpellCheckLanguage.calledWith(@project_id, languageCode).should.equal true + console.log @EditorRealTimeController.emitToRoom.args + @EditorRealTimeController.emitToRoom.calledWith(@project_id, "spellCheckLanguageUpdated", languageCode).should.equal true done() @ProjectOptionsHandler.setSpellCheckLanguage.args[0][2]() @@ -687,9 +693,8 @@ describe "EditorController", -> describe "setPublicAccessLevel", -> beforeEach -> - @err = "errro" @newAccessLevel = "public" - @ProjectDetailsHandler.setPublicAccessLevel = sinon.stub().callsArgWith(2, @err) + @ProjectDetailsHandler.setPublicAccessLevel = sinon.stub().callsArgWith(2, null) @EditorRealTimeController.emitToRoom = sinon.stub() it "should call the EditorController", (done)-> @@ -705,9 +710,8 @@ describe "EditorController", -> describe "setRootDoc", -> beforeEach -> - @err = "errro" @newRootDocID = "21312321321" - @ProjectEntityHandler.setRootDoc = sinon.stub().callsArgWith(2, @err) + @ProjectEntityHandler.setRootDoc = sinon.stub().callsArgWith(2, null) @EditorRealTimeController.emitToRoom = sinon.stub() it "should call the ProjectEntityHandler", (done)-> diff --git a/services/web/test/UnitTests/coffee/Project/ProjectControllerTests.coffee b/services/web/test/UnitTests/coffee/Project/ProjectControllerTests.coffee index 600b4cf886..c931753a1d 100644 --- a/services/web/test/UnitTests/coffee/Project/ProjectControllerTests.coffee +++ b/services/web/test/UnitTests/coffee/Project/ProjectControllerTests.coffee @@ -70,6 +70,67 @@ describe "ProjectController", -> locals: jsPath:"js path here" + describe "updateProjectSettings", -> + it "should update the name", (done) -> + @EditorController.renameProject = sinon.stub().callsArg(2) + @req.body = + name: @name = "New name" + @res.send = (code) => + @EditorController.renameProject + .calledWith(@project_id, @name) + .should.equal true + code.should.equal 204 + done() + @ProjectController.updateProjectSettings @req, @res + + it "should update the compiler", (done) -> + @EditorController.setCompiler = sinon.stub().callsArg(2) + @req.body = + compiler: @compiler = "pdflatex" + @res.send = (code) => + @EditorController.setCompiler + .calledWith(@project_id, @compiler) + .should.equal true + code.should.equal 204 + done() + @ProjectController.updateProjectSettings @req, @res + + it "should update the spell check language", (done) -> + @EditorController.setSpellCheckLanguage = sinon.stub().callsArg(2) + @req.body = + spellCheckLanguage: @languageCode = "fr" + @res.send = (code) => + @EditorController.setSpellCheckLanguage + .calledWith(@project_id, @languageCode) + .should.equal true + code.should.equal 204 + done() + @ProjectController.updateProjectSettings @req, @res + + it "should update the public access level", (done) -> + @EditorController.setPublicAccessLevel = sinon.stub().callsArg(2) + @req.body = + publicAccessLevel: @publicAccessLevel = "readonly" + @res.send = (code) => + @EditorController.setPublicAccessLevel + .calledWith(@project_id, @publicAccessLevel) + .should.equal true + code.should.equal 204 + done() + @ProjectController.updateProjectSettings @req, @res + + it "should update the root doc", (done) -> + @EditorController.setRootDoc = sinon.stub().callsArg(2) + @req.body = + rootDocId: @rootDocId = "root-doc-id" + @res.send = (code) => + @EditorController.setRootDoc + .calledWith(@project_id, @rootDocId) + .should.equal true + code.should.equal 204 + done() + @ProjectController.updateProjectSettings @req, @res + describe "deleteProject", -> it "should tell the project deleter to archive when forever=false", (done)-> @res.send = (code)=>