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()