diff --git a/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee b/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee index 9449c68af9..b7760b40c5 100644 --- a/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee +++ b/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee @@ -123,8 +123,7 @@ module.exports = DocumentUpdaterHandler = url: url json: lines: docLines - headers: - "x-sl-update-source": source + source: source logger.log project_id:project_id, doc_id: doc_id, source: source, "setting doc in document updater" request.post body, (error, res, body)-> timer.done() diff --git a/services/web/app/coffee/Features/Editor/EditorController.coffee b/services/web/app/coffee/Features/Editor/EditorController.coffee index 678d34630e..c52e712e2f 100644 --- a/services/web/app/coffee/Features/Editor/EditorController.coffee +++ b/services/web/app/coffee/Features/Editor/EditorController.coffee @@ -184,9 +184,9 @@ module.exports = EditorController = replaceFile: (project_id, file_id, fsPath, source, callback = (error) ->)-> ProjectEntityHandler.replaceFile project_id, file_id, fsPath, callback - addFolder: (project_id, folder_id, folderName, callback = (error, folder)->)-> + addFolder: (project_id, folder_id, folderName, source, callback = (error, folder)->)-> folderName = folderName.trim() - logger.log {project_id, folder_id, folderName}, "sending new folder to project" + logger.log {project_id, folder_id, folderName, source}, "sending new folder to project" Metrics.inc "editor.add-folder" ProjectEntityHandler.addFolder project_id, folder_id, folderName, (err, folder, folder_id)=> @p.notifyProjectUsersOfNewFolder project_id, folder_id, folder, (error) -> diff --git a/services/web/app/coffee/Features/Editor/EditorHttpController.coffee b/services/web/app/coffee/Features/Editor/EditorHttpController.coffee index 382cf1be24..86acfb79fe 100644 --- a/services/web/app/coffee/Features/Editor/EditorHttpController.coffee +++ b/services/web/app/coffee/Features/Editor/EditorHttpController.coffee @@ -33,7 +33,7 @@ module.exports = EditorHttpController = project_id = req.params.Project_id name = req.body.name parent_folder_id = req.body.parent_folder_id - EditorController.addFolder project_id, parent_folder_id, name, (error, doc) -> + EditorController.addFolder project_id, parent_folder_id, name, "editor", (error, doc) -> return next(error) if error? res.json doc diff --git a/services/web/app/coffee/Features/Email/EmailBuilder.coffee b/services/web/app/coffee/Features/Email/EmailBuilder.coffee index a17f45634f..5826ab02c8 100644 --- a/services/web/app/coffee/Features/Email/EmailBuilder.coffee +++ b/services/web/app/coffee/Features/Email/EmailBuilder.coffee @@ -11,15 +11,19 @@ templates.welcome = layout: PersonalEmailLayout type:"lifecycle" compiledTemplate: _.template ''' -Hi <%= first_name %>, thanks for signing up to ShareLaTeX. If you ever get lost, you can log in again here. -

-I’m the co-founder of ShareLaTeX and I love talking to our users about our service. Please feel free to get in touch by replying to this email and I will get back to you within a day. +

Hi <%= first_name %>,

+ +

Thanks for signing up to ShareLaTeX! If you ever get lost, you can log in again here.

+ +

If you're new to LaTeX, take a look at our Help Guides and Templates.

- Regards,
Henry
ShareLaTeX Co-founder +

+ +

PS. We love talking to our users about ShareLaTeX. Reply to this email to get in touch us with us directly, whatever the reason. Questions, comments, problems, suggestions, all welcome!

''' templates.canceledSubscription = @@ -27,15 +31,16 @@ templates.canceledSubscription = layout: PersonalEmailLayout type:"lifecycle" compiledTemplate: _.template ''' -Hi <%= first_name %>, +

Hi <%= first_name %>,

-I am sorry to see you cancelled your premium account. I wondered if you would mind giving me some advice on what the site is lacking at the moment? Criticism from our users about what is missing is the best thing for us to help improve the tool. +

I'm sorry to see you cancelled your ShareLaTeX premium account. Would you mind giving me some advice on what the site is lacking at the moment? Feedback from our users is the only way we can improve ShareLaTeX.

-Thank you in advance. +

Thank you in advance.

Henry
ShareLaTeX Co-founder +

''' templates.passwordResetRequested = diff --git a/services/web/app/coffee/Features/Email/Layouts/PersonalEmailLayout.coffee b/services/web/app/coffee/Features/Email/Layouts/PersonalEmailLayout.coffee index 6e95665143..839b5cbd6a 100644 --- a/services/web/app/coffee/Features/Email/Layouts/PersonalEmailLayout.coffee +++ b/services/web/app/coffee/Features/Email/Layouts/PersonalEmailLayout.coffee @@ -10,7 +10,7 @@ module.exports = _.template ''' - + <%= body %> diff --git a/services/web/app/coffee/Features/ThirdPartyDataStore/TpdsController.coffee b/services/web/app/coffee/Features/ThirdPartyDataStore/TpdsController.coffee index aa5e888375..8197f2a110 100644 --- a/services/web/app/coffee/Features/ThirdPartyDataStore/TpdsController.coffee +++ b/services/web/app/coffee/Features/ThirdPartyDataStore/TpdsController.coffee @@ -8,8 +8,9 @@ module.exports = mergeUpdate: (req, res)-> metrics.inc("tpds.merge-update") {filePath, user_id, projectName} = parseParams(req) - logger.log user_id:user_id, filePath:filePath, fullPath:req.params[0], projectName:projectName, "reciving update request from tpds" - tpdsUpdateHandler.newUpdate user_id, projectName, filePath, req, (err)-> + source = req.headers["x-sl-update-source"] or "unknown" + logger.log user_id:user_id, filePath:filePath, fullPath:req.params[0], projectName:projectName, source: source, "reciving update request from tpds" + tpdsUpdateHandler.newUpdate user_id, projectName, filePath, req, source, (err)-> logger.log user_id:user_id, filePath:filePath, fullPath:req.params[0], "sending response that tpdsUpdate has been completed" if err? logger.err err:err, user_id:user_id, filePath:filePath, "error reciving update from tpds" @@ -23,8 +24,9 @@ module.exports = deleteUpdate: (req, res)-> metrics.inc("tpds.delete-update") {filePath, user_id, projectName} = parseParams(req) - logger.log user_id:user_id, filePath:filePath, projectName:projectName, fullPath:req.params[0], "reciving delete request from tpds" - tpdsUpdateHandler.deleteUpdate user_id, projectName, filePath, (err)-> + source = req.headers["x-sl-update-source"] or "unknown" + logger.log user_id:user_id, filePath:filePath, projectName:projectName, fullPath:req.params[0], source: source, "reciving delete request from tpds" + tpdsUpdateHandler.deleteUpdate user_id, projectName, filePath, source, (err)-> if err? logger.err err:err, user_id:user_id, filePath:filePath, "error reciving update from tpds" res.send(500) @@ -36,7 +38,7 @@ module.exports = updateProjectContents: (req, res, next = (error) ->) -> {project_id} = req.params path = "/" + req.params[0] # UpdateMerger expects leading slash - source = req.headers["x-sl-update-source"] + source = req.headers["x-sl-update-source"] or "unknown" logger.log project_id: project_id, path: path, source: source, "received project contents update" UpdateMerger.mergeUpdate project_id, path, req, source, (error) -> return next(error) if error? @@ -46,7 +48,7 @@ module.exports = deleteProjectContents: (req, res, next = (error) ->) -> {project_id} = req.params path = "/" + req.params[0] # UpdateMerger expects leading slash - source = req.headers["x-sl-update-source"] + source = req.headers["x-sl-update-source"] or "unknown" logger.log project_id: project_id, path: path, source: source, "received project contents delete request" UpdateMerger.deleteUpdate project_id, path, source, (error) -> return next(error) if error? diff --git a/services/web/app/coffee/Features/ThirdPartyDataStore/TpdsUpdateHandler.coffee b/services/web/app/coffee/Features/ThirdPartyDataStore/TpdsUpdateHandler.coffee index 416faaaac0..efd34be640 100644 --- a/services/web/app/coffee/Features/ThirdPartyDataStore/TpdsUpdateHandler.coffee +++ b/services/web/app/coffee/Features/ThirdPartyDataStore/TpdsUpdateHandler.coffee @@ -9,7 +9,7 @@ commitMessage = "Before update from Dropbox" module.exports = - newUpdate: (user_id, projectName, path, updateRequest, callback)-> + newUpdate: (user_id, projectName, path, updateRequest, source, callback)-> getOrCreateProject = (cb)=> projectLocator.findUsersProjectByName user_id, projectName, (err, project)=> logger.log user_id:user_id, filePath:path, projectName:projectName, "handling new update from tpds" @@ -22,11 +22,11 @@ module.exports = else cb err, project getOrCreateProject (err, project)-> - updateMerger.mergeUpdate project._id, path, updateRequest, (err)-> + updateMerger.mergeUpdate project._id, path, updateRequest, source, (err)-> callback(err) - deleteUpdate: (user_id, projectName, path, callback)-> + deleteUpdate: (user_id, projectName, path, source, callback)-> logger.log user_id:user_id, filePath:path, "handling delete update from tpds" projectLocator.findUsersProjectByName user_id, projectName, (err, project)-> if !project? @@ -36,7 +36,7 @@ module.exports = logger.log user_id:user_id, filePath:path, projectName:projectName, project_id:project._id, "project found for delete update, path is root so marking project as deleted" return projectDeleter.markAsDeletedByExternalSource project._id, callback else - updateMerger.deleteUpdate project._id, path, (err)-> + updateMerger.deleteUpdate project._id, path, source, (err)-> callback(err) diff --git a/services/web/public/coffee/ide/editor/Document.coffee b/services/web/public/coffee/ide/editor/Document.coffee index b2b2be6dac..deb8f5047c 100644 --- a/services/web/public/coffee/ide/editor/Document.coffee +++ b/services/web/public/coffee/ide/editor/Document.coffee @@ -210,10 +210,10 @@ define [ _bindToShareJsDocEvents: () -> @doc.on "error", (error, meta) => @_onError error, meta - @doc.on "externalUpdate", () => + @doc.on "externalUpdate", (update) => @ide.pushEvent "externalUpdate", doc_id: @doc_id - @trigger "externalUpdate" + @trigger "externalUpdate", update @doc.on "remoteop", () => @ide.pushEvent "remoteop", doc_id: @doc_id diff --git a/services/web/public/coffee/ide/editor/EditorManager.coffee b/services/web/public/coffee/ide/editor/EditorManager.coffee index d190c06be9..fa9ad69498 100644 --- a/services/web/public/coffee/ide/editor/EditorManager.coffee +++ b/services/web/public/coffee/ide/editor/EditorManager.coffee @@ -84,7 +84,8 @@ define [ "Sorry, this file has gone out of sync and we need to do a full refresh. Please let us know if this happens frequently." ) - sharejs_doc.on "externalUpdate", () => + sharejs_doc.on "externalUpdate", (update) => + return if @_ignoreExternalUpdates @ide.showGenericMessageModal( "Document Updated Externally" "This document was just updated externally. Any recent changes you have made may have been overwritten. To see previous versions please look in the history." @@ -98,3 +99,9 @@ define [ getCurrentDocId: () -> @$scope.editor.open_doc_id + + startIgnoringExternalUpdates: () -> + @_ignoreExternalUpdates = true + + stopIgnoringExternalUpdates: () -> + @_ignoreExternalUpdates = false diff --git a/services/web/public/coffee/ide/editor/ShareJsDoc.coffee b/services/web/public/coffee/ide/editor/ShareJsDoc.coffee index 3a1728c9c6..0894bbff7e 100644 --- a/services/web/public/coffee/ide/editor/ShareJsDoc.coffee +++ b/services/web/public/coffee/ide/editor/ShareJsDoc.coffee @@ -57,7 +57,7 @@ define [ @_handleError(error) if message?.meta?.type == "external" - @trigger "externalUpdate" + @trigger "externalUpdate", message catchUp: (updates) -> for update, i in updates diff --git a/services/web/test/UnitTests/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee b/services/web/test/UnitTests/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee index 3b5c4fc54e..e9c144b017 100644 --- a/services/web/test/UnitTests/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee +++ b/services/web/test/UnitTests/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee @@ -227,8 +227,7 @@ describe 'Flushing documents :', -> url: url json: lines: @lines - headers: - "x-sl-update-source": @source + source: @source }) .should.equal true diff --git a/services/web/test/UnitTests/coffee/Editor/EditorControllerTests.coffee b/services/web/test/UnitTests/coffee/Editor/EditorControllerTests.coffee index 8ecf946901..9d15369aa7 100644 --- a/services/web/test/UnitTests/coffee/Editor/EditorControllerTests.coffee +++ b/services/web/test/UnitTests/coffee/Editor/EditorControllerTests.coffee @@ -526,7 +526,7 @@ describe "EditorController", -> it 'should add the folder using the project entity handler', (done)-> mock = sinon.mock(@ProjectEntityHandler).expects("addFolder").withArgs(@project_id, @folder_id, @folderName).callsArg(3) - @EditorController.addFolder @project_id, @folder_id, @folderName, -> + @EditorController.addFolder @project_id, @folder_id, @folderName, @source, -> mock.verify() done() @@ -534,7 +534,7 @@ describe "EditorController", -> @ProjectEntityHandler.addFolder = (project_id, folder_id, folderName, callback)=> callback(null, @folder, @folder_id) mock = sinon.mock(@EditorController.p).expects('notifyProjectUsersOfNewFolder').withArgs(@project_id, @folder_id, @folder).callsArg(3) - @EditorController.addFolder @project_id, @folder_id, @folderName, -> + @EditorController.addFolder @project_id, @folder_id, @folderName, @source, -> mock.verify() done() @@ -547,7 +547,7 @@ describe "EditorController", -> it 'should return the folder in the callback', (done) -> @ProjectEntityHandler.addFolder = (project_id, folder_id, folderName, callback)=> callback(null, @folder, @folder_id) - @EditorController.addFolder @project_id, @folder_id, @folderName, (error, folder) => + @EditorController.addFolder @project_id, @folder_id, @folderName, @source, (error, folder) => folder.should.equal @folder done() diff --git a/services/web/test/UnitTests/coffee/Editor/EditorHttpControllerTests.coffee b/services/web/test/UnitTests/coffee/Editor/EditorHttpControllerTests.coffee index a2081a9464..dda8a5fed8 100644 --- a/services/web/test/UnitTests/coffee/Editor/EditorHttpControllerTests.coffee +++ b/services/web/test/UnitTests/coffee/Editor/EditorHttpControllerTests.coffee @@ -76,12 +76,12 @@ describe "EditorHttpController", -> @req.body = name: @name = "folder-name" parent_folder_id: @parent_folder_id - @EditorController.addFolder = sinon.stub().callsArgWith(3, null, @folder) + @EditorController.addFolder = sinon.stub().callsArgWith(4, null, @folder) @EditorHttpController.addFolder @req, @res it "should call EditorController.addFolder", -> @EditorController.addFolder - .calledWith(@project_id, @parent_folder_id, @name) + .calledWith(@project_id, @parent_folder_id, @name, "editor") .should.equal true it "should send the folder back as JSON", -> diff --git a/services/web/test/UnitTests/coffee/ThirdPartyDataStore/TpdsControllerTests.coffee b/services/web/test/UnitTests/coffee/ThirdPartyDataStore/TpdsControllerTests.coffee index e0b424e571..e43737a478 100644 --- a/services/web/test/UnitTests/coffee/ThirdPartyDataStore/TpdsControllerTests.coffee +++ b/services/web/test/UnitTests/coffee/ThirdPartyDataStore/TpdsControllerTests.coffee @@ -25,9 +25,11 @@ describe 'TpdsController', -> params:{0:path, "user_id":@user_id} session: destroy:-> - @TpdsUpdateHandler.newUpdate = sinon.stub().callsArg(4) + headers: + "x-sl-update-source": @source = "dropbox" + @TpdsUpdateHandler.newUpdate = sinon.stub().callsArg(5) res = send: => - @TpdsUpdateHandler.newUpdate.calledWith(@user_id, "projectName","/here.txt", req).should.equal true + @TpdsUpdateHandler.newUpdate.calledWith(@user_id, "projectName","/here.txt", req, @source).should.equal true done() @TpdsController.mergeUpdate req, res @@ -38,9 +40,11 @@ describe 'TpdsController', -> params:{0:path, "user_id":@user_id} session: destroy:-> - @TpdsUpdateHandler.deleteUpdate = sinon.stub().callsArg(3) + headers: + "x-sl-update-source": @source = "dropbox" + @TpdsUpdateHandler.deleteUpdate = sinon.stub().callsArg(4) res = send: => - @TpdsUpdateHandler.deleteUpdate.calledWith(@user_id, "projectName", "/here.txt").should.equal true + @TpdsUpdateHandler.deleteUpdate.calledWith(@user_id, "projectName", "/here.txt", @source).should.equal true done() @TpdsController.deleteUpdate req, res diff --git a/services/web/test/UnitTests/coffee/ThirdPartyDataStore/TpdsUpdateHandlerTests.coffee b/services/web/test/UnitTests/coffee/ThirdPartyDataStore/TpdsUpdateHandlerTests.coffee index 5ff8b509be..4e2f72779b 100644 --- a/services/web/test/UnitTests/coffee/ThirdPartyDataStore/TpdsUpdateHandlerTests.coffee +++ b/services/web/test/UnitTests/coffee/ThirdPartyDataStore/TpdsUpdateHandlerTests.coffee @@ -7,8 +7,8 @@ describe 'TpdsUpdateHandler', -> beforeEach -> @requestQueuer = {} @updateMerger = - deleteUpdate: (user_id, path, cb)->cb() - mergeUpdate:(user_id, path, update, cb)->cb() + deleteUpdate: (user_id, path, source, cb)->cb() + mergeUpdate:(user_id, path, update, source, cb)->cb() @editorController = {} @project_id = "dsjajilknaksdn" @project = {_id:@project_id, name:"projectNameHere"} @@ -33,15 +33,15 @@ describe 'TpdsUpdateHandler', -> path = "/path/here" update = {} @updateMerger.mergeUpdate = sinon.stub() - @updateMerger.mergeUpdate.withArgs(@project_id, path, update).callsArg(3) - @handler.newUpdate @user_id, @project.name, path, update, => + @updateMerger.mergeUpdate.withArgs(@project_id, path, update, @source).callsArg(4) + @handler.newUpdate @user_id, @project.name, path, update, @source, => @projectCreationHandler.createBlankProject.called.should.equal false done() it 'should create a new project if one does not already exit', (done)-> @projectLocator.findUsersProjectByName = sinon.stub().callsArgWith(2) path = "/" - @handler.newUpdate @user_id, @project.name, path, {}, => + @handler.newUpdate @user_id, @project.name, path, {}, @source, => @projectCreationHandler.createBlankProject.calledWith(@user_id, @project.name).should.equal true done() @@ -49,7 +49,7 @@ describe 'TpdsUpdateHandler', -> @projectLocator.findUsersProjectByName = sinon.stub().callsArgWith(2) @handler._rootDocTimeoutLength = 0 path = "/" - @handler.newUpdate @user_id, @project.name, path, {}, => + @handler.newUpdate @user_id, @project.name, path, {}, @source, => setTimeout (=> @rootDocManager.setRootDocAutomatically.calledWith(@project._id).should.equal true done() @@ -61,16 +61,16 @@ describe 'TpdsUpdateHandler', -> it 'should call deleteEntity in the collaberation manager', (done)-> path = "/delete/this" update = {} - @updateMerger.deleteUpdate = sinon.stub().callsArg(2) + @updateMerger.deleteUpdate = sinon.stub().callsArg(3) - @handler.deleteUpdate @user_id, @project.name, path, => + @handler.deleteUpdate @user_id, @project.name, path, @source, => @projectDeleter.markAsDeletedByExternalSource.calledWith(@project._id).should.equal false - @updateMerger.deleteUpdate.calledWith(@project_id, path).should.equal true + @updateMerger.deleteUpdate.calledWith(@project_id, path, @source).should.equal true done() it 'should mark the project as deleted by external source if path is a single slash', (done)-> path = "/" - @handler.deleteUpdate @user_id, @project.name, path, => + @handler.deleteUpdate @user_id, @project.name, path, @source, => @projectDeleter.markAsDeletedByExternalSource.calledWith(@project._id).should.equal true done()