Merge branch 'master' into master-redesign

Conflicts:
	public/stylesheets/less/trackchanges.less
This commit is contained in:
James Allen
2014-06-06 15:10:57 +01:00
30 changed files with 355 additions and 55 deletions
+8 -3
View File
@@ -8,8 +8,8 @@ logger = require "logger-sharelatex"
url = require("url")
module.exports = ClsiManager =
sendRequest: (project_id, callback = (error, success) ->) ->
ClsiManager._buildRequest project_id, (error, req) ->
sendRequest: (project_id, settingsOverride = {}, callback = (error, success) ->) ->
ClsiManager._buildRequest project_id, settingsOverride, (error, req) ->
return callback(error) if error?
logger.log project_id: project_id, "sending compile to CLSI"
ClsiManager._postToClsi project_id, req, (error, response) ->
@@ -52,7 +52,7 @@ module.exports = ClsiManager =
return outputFiles
VALID_COMPILERS: ["pdflatex", "latex", "xelatex", "lualatex"]
_buildRequest: (project_id, callback = (error, request) ->) ->
_buildRequest: (project_id, settingsOverride={}, callback = (error, request) ->) ->
Project.findById project_id, {compiler: 1, rootDoc_id: 1}, (error, project) ->
return callback(error) if error?
return callback(new Errors.NotFoundError("project does not exist: #{project_id}")) if !project?
@@ -67,6 +67,7 @@ module.exports = ClsiManager =
resources = []
rootResourcePath = null
rootResourcePathOverride = null
for path, doc of docs
path = path.replace(/^\//, "") # Remove leading /
@@ -75,6 +76,10 @@ module.exports = ClsiManager =
content: doc.lines.join("\n")
if project.rootDoc_id? and doc._id.toString() == project.rootDoc_id.toString()
rootResourcePath = path
if settingsOverride.rootDoc_id? and doc._id.toString() == settingsOverride.rootDoc_id.toString()
rootResourcePathOverride = path
rootResourcePath = rootResourcePathOverride if rootResourcePathOverride?
for path, file of files
path = path.replace(/^\//, "") # Remove leading /
+3 -1
View File
@@ -11,9 +11,11 @@ module.exports = CompileController =
compile: (req, res, next = (error) ->) ->
project_id = req.params.Project_id
isAutoCompile = !!req.query?.auto_compile
settingsOverride = req.body?.settingsOverride ? {};
logger.log "root doc overriden" if settingsOverride.rootDoc_id?
AuthenticationController.getLoggedInUserId req, (error, user_id) ->
return next(error) if error?
CompileManager.compile project_id, user_id, { isAutoCompile }, (error, status, outputFiles) ->
CompileManager.compile project_id, user_id, { isAutoCompile, settingsOverride }, (error, status, outputFiles) ->
return next(error) if error?
res.contentType("application/json")
res.send 200, JSON.stringify {
+2 -2
View File
@@ -25,12 +25,12 @@ module.exports = CompileManager =
return callback(error) if error?
if recentlyCompiled
return callback new Error("project was recently compiled so not continuing")
CompileManager._ensureRootDocumentIsSet project_id, (error) ->
return callback(error) if error?
DocumentUpdaterHandler.flushProjectToMongo project_id, (error) ->
return callback(error) if error?
ClsiManager.sendRequest project_id, (error, status, outputFiles) ->
ClsiManager.sendRequest project_id, opt.settingsOverride, (error, status, outputFiles) ->
return callback(error) if error?
logger.log files: outputFiles, "output files"
callback(null, status, outputFiles)
@@ -30,9 +30,14 @@ module.exports = DocstoreManager =
logger.error err: error, project_id: project_id, "error getting all docs from docstore"
callback(error)
getDoc: (project_id, doc_id, callback = (error, lines, rev) ->) ->
logger.log project_id: project_id, doc_id: doc_id, "getting doc in docstore api"
getDoc: (project_id, doc_id, options = {}, callback = (error, lines, rev) ->) ->
if typeof(options) == "function"
callback = options
options = {}
logger.log project_id: project_id, doc_id: doc_id, options: options, "getting doc in docstore api"
url = "#{settings.apis.docstore.url}/project/#{project_id}/doc/#{doc_id}"
if options.include_deleted
url += "?include_deleted=true"
request.get {
url: url
json: true
@@ -0,0 +1,21 @@
ProjectEntityHandler = require "../Project/ProjectEntityHandler"
logger = require "logger-sharelatex"
EditorRealTimeController = require "./EditorRealTimeController"
module.exports = EditorHttpController =
restoreDoc: (req, res, next) ->
project_id = req.params.Project_id
doc_id = req.params.doc_id
name = req.body.name
if !name?
return res.send 400 # Malformed request
logger.log project_id: project_id, doc_id: doc_id, "restoring doc"
ProjectEntityHandler.restoreDoc project_id, doc_id, name, (err, doc, folder_id) =>
return next(error) if error?
EditorRealTimeController.emitToRoom(project_id, 'reciveNewDoc', folder_id, doc)
res.json {
doc_id: doc._id
}
@@ -15,6 +15,7 @@ module.exports = ProjectEditorHandler =
description: project.description
spellCheckLanguage: project.spellCheckLanguage
deletedByExternalDataSource : project.deletedByExternalDataSource || false
deletedDocs: project.deletedDocs
if options.includeUsers
result.features =
@@ -111,8 +111,11 @@ module.exports = ProjectEntityHandler =
logger.log sl_req_id: sl_req_id, project_id: project_id, "removing root doc"
Project.update {_id:project_id}, {$unset: {rootDoc_id: true}}, {}, callback
getDoc: (project_id, doc_id, callback = (error, lines, rev) ->) ->
DocstoreManager.getDoc project_id, doc_id, callback
getDoc: (project_id, doc_id, options = {}, callback = (error, lines, rev) ->) ->
if typeof(options) == "function"
callback = options
options = {}
DocstoreManager.getDoc project_id, doc_id, options, callback
addDoc: (project_or_id, folder_id, docName, docLines, sl_req_id, callback = (error, doc, folder_id) ->)=>
{callback, sl_req_id} = slReqIdHelper.getCallbackAndReqId(callback, sl_req_id)
@@ -135,6 +138,13 @@ module.exports = ProjectEntityHandler =
return callback(err) if err?
callback(null, doc, folder_id)
restoreDoc: (project_id, doc_id, name, callback = (error, doc, folder_id) ->) ->
# getDoc will return the deleted doc's lines, but we don't actually remove
# the deleted doc, just create a new one from its lines.
ProjectEntityHandler.getDoc project_id, doc_id, include_deleted: true, (error, lines) ->
return callback(error) if error?
ProjectEntityHandler.addDoc project_id, null, name, lines, callback
addFile: (project_or_id, folder_id, fileName, path, sl_req_id, callback = (error, fileRef, folder_id) ->)->
{callback, sl_req_id} = slReqIdHelper.getCallbackAndReqId(callback, sl_req_id)
Project.getProject project_or_id, "", (err, project) ->
@@ -10,7 +10,8 @@ module.exports = ProjectRootDocManager =
root_doc_id = null
for path, doc of docs
for line in doc.lines || []
if Path.extname(path).match(/\.R?tex$/) and line.match(/\\documentclass/)
match = line.match /(.*)\\documentclass/ # no lookbehind in js regexp :(
if Path.extname(path).match(/\.R?tex$/) and match and !match[1].match /%/
root_doc_id = doc._id
if root_doc_id?
ProjectEntityHandler.setRootDoc project_id, root_doc_id, sl_req_id, callback
+3
View File
@@ -7,6 +7,7 @@ SpellingController = require('./Features/Spelling/SpellingController')
SecurityManager = require('./managers/SecurityManager')
AuthorizationManager = require('./Features/Security/AuthorizationManager')
EditorController = require("./Features/Editor/EditorController")
EditorHttpController = require("./Features/Editor/EditorHttpController")
EditorUpdatesController = require("./Features/Editor/EditorUpdatesController")
Settings = require('settings-sharelatex')
TpdsController = require('./Features/ThirdPartyDataStore/TpdsController')
@@ -125,6 +126,8 @@ module.exports = class Router
app.get "/project/:Project_id/doc/:doc_id/diff", SecurityManager.requestCanAccessProject, TrackChangesController.proxyToTrackChangesApi
app.post "/project/:Project_id/doc/:doc_id/version/:version_id/restore", SecurityManager.requestCanAccessProject, TrackChangesController.proxyToTrackChangesApi
app.post "/project/:Project_id/doc/:doc_id/restore", SecurityManager.requestCanAccessProject, EditorHttpController.restoreDoc
app.post '/project/:project_id/leave', AuthenticationController.requireLogin(), CollaboratorsController.removeSelfFromProject
app.get '/project/:Project_id/collaborators', SecurityManager.requestCanAccessProject(allow_auth_token: true), CollaboratorsController.getCollaborators
+14 -2
View File
@@ -82,6 +82,12 @@
.dropdown-caret
i.icon-chevron-down
.entity-label.label.label-success
script(type="text/template")#deletedDocsFolderTemplate
.entity-list-item.entity-deleted-docs-folder(class="entity-{{ type }}", entity-type="{{ type }}", id="{{ id }}")
.clickable.js-clickable
span.name {{ name }}
.entity-label.label.label-success
script(type="text/template")#entityListTemplate
.contents
@@ -386,8 +392,14 @@
script(type='text/template')#trackChangesDiffTemplate
.track-changes-diff-toolbar.btn-toolbar
.number-of-changes {{ changes }} in <strong>{{ name }}</strong>
a(href="#").restore.btn.btn-small.btn-danger Restore to before these changes
.change-info
.number-of-changes {{ changes }} in <strong>{{ name }}</strong>
a(href="#").restore.btn.btn-small.btn-danger Restore to before these changes
.deleted-info(style="display:none;")
strong {{ name }}
.controls
span This file has been deleted
a(href="#").restore-deleted.btn.btn-small.btn-success Restore
.track-changes-diff-editor
script(type='text/template')#changeListItemTemplate
@@ -0,0 +1,29 @@
define [
"file-tree/FolderView"
], (FolderView) ->
DeletedDocsFolderView = FolderView.extend
template: $("#deletedDocsFolderTemplate").html()
render: () ->
@$el.append(Mustache.to_html @template, @model.attributes)
@_bindToDomElements()
@hideRenameBox()
@hideToggle()
@renderEntries()
@showEntries()
return @
onClick: () ->
e.preventDefault()
onToggle: () ->
e.preventDefault()
getContextMenuEntries: () -> null
hideToggle: () ->
@$(".js-toggle").hide()
@@ -112,6 +112,7 @@ define [
showContextMenu: (position) ->
entries = @getContextMenuEntries()
return if !entries?
@manager.trigger "contextmenu:beforeshow", @model, entries
@@ -3,11 +3,13 @@ define [
"models/File"
"models/Folder"
"file-tree/FileTreeView"
"file-tree/FolderView"
"file-tree/DeletedDocsFolderView"
"utils/Effects"
"utils/Modal"
"libs/backbone"
"libs/jquery.storage"
], (Doc, File, Folder, FileTreeView, Effects, Modal) ->
], (Doc, File, Folder, FileTreeView, FolderView, DeletedDocsFolderView, Effects, Modal) ->
class FileTreeManager
constructor: (@ide) ->
_.extend(@, Backbone.Events)
@@ -37,6 +39,13 @@ define [
populateFileTree: () ->
@view.bindToRootFolder(@project.get("rootFolder"))
if @deletedDocsView?
@deletedDocsView.$el.remove()
@deletedDocsView = new DeletedDocsFolderView(model: @project.get("deletedDocs"), manager: @)
@deletedDocsView.render()
$("#sections").append(@deletedDocsView.$el)
@hideDeletedDocs()
listenForUpdates: () ->
@ide.socket.on 'reciveNewDoc', (folder_id, doc) =>
@@ -100,8 +109,12 @@ define [
@ide.sideBarView.deselectAll()
@views[entity_id]?.select()
getEntity: (entity_id) ->
@views[entity_id]?.model
getEntity: (entity_id, options = {include_deleted: false}) ->
model = @views[entity_id]?.model
if !model? or (model.get("deleted") and !options.include_deleted)
return
else
return model
getSelectedEntity: () -> @getEntity(@selected_entity_id)
getSelectedEntityId: () -> @getSelectedEntity()?.id
@@ -283,6 +296,19 @@ define [
entity.set("deleted", true)
entity.collection?.remove(entity)
delete @views[entity_id]
# Do this after the remove so that it's never in two places at once
# and so that it doesn't get reset by deleting from @views
if entity.get("type") == "doc"
@project.get("deletedDocs").get("children").add entity
setLabels: (labels) ->
@view.setLabels(labels)
@deletedDocsView.setLabels(labels)
showDeletedDocs: () ->
if @project.get("deletedDocs").get("children").length > 0
@deletedDocsView.$el.show()
hideDeletedDocs: () ->
@deletedDocsView.$el.hide()
@@ -9,3 +9,4 @@ define [
attributes =
id: rawAttributes._id
name: rawAttributes.name
deleted: !!rawAttributes.deleted
@@ -20,11 +20,11 @@ define [
id: rawAttributes._id
name: rawAttributes.name
children = []
for childFolder in rawAttributes.folders
for childFolder in rawAttributes.folders or []
children.push new Folder(childFolder, parse: true)
for file in rawAttributes.fileRefs
for file in rawAttributes.fileRefs or []
children.push new File(file, parse: true)
for doc in rawAttributes.docs
for doc in rawAttributes.docs or []
children.push new Doc(doc, parse: true)
attributes.children = new FolderChildren(children)
return attributes
@@ -2,8 +2,9 @@ define [
"models/User"
"models/ProjectMemberList"
"models/Folder"
"models/Doc"
"libs/backbone"
], (User, ProjectMemberList, Folder) ->
], (User, ProjectMemberList, Folder, Doc) ->
Project = Backbone.Model.extend
initialize: ->
@on "change:ide", (project, ide) =>
@@ -39,6 +40,15 @@ define [
member = User.findOrBuild rawMember._id, rawMember
members.add member
for doc in rawAttributes.deletedDocs
doc.deleted = true
attributes.deletedDocs = new Folder({
_id: "deleted-docs-folder"
name: "Deleted documents"
docs: rawAttributes.deletedDocs
}, parse: true)
return attributes
bindToRootDocId: ->
+6 -1
View File
@@ -204,7 +204,12 @@ define [
recompilePdf: () ->
@options.manager.trigger "compile:pdf"
@options.manager.refreshPdf()
rootDocOverride_id = null
for line in @ide.editor.getLines()
match = line.match /(.*)\\documentclass/
if match and !match[1].match /%/
rootDocOverride_id = @ide.editor.getCurrentDocId()
@options.manager.refreshPdf {rootDocOverride_id}
toggleFlatViewButton: () -> @$("#flatViewButton").button("toggle")
toggleSplitViewButton: () -> @$("#splitViewButton").button("toggle")
@@ -143,7 +143,7 @@ define [
@view.onCompiling()
@syncButtonsView?.hide()
@compiling = true
@_doCompile opts.isAutoCompile, (error, status, outputFiles) =>
@_doCompile opts, (error, status, outputFiles) =>
@compiling = false
doneCompiling()
@@ -172,16 +172,19 @@ define [
if outputFiles?
@view.showOutputFileDownloadLinks(outputFiles)
_doCompile: (isAutoCompile, callback = (error, status, outputFiles) ->) ->
_doCompile: (opts, callback = (error, status, outputFiles) ->) ->
url = "/project/#{@ide.project_id}/compile"
if isAutoCompile
if opts.isAutoCompile
url += "?auto_compile=true"
$.ajax(
url: url
type: "POST"
headers:
"X-CSRF-Token": window.csrfToken
contentType: "application/json; charset=utf-8"
dataType: 'json'
data: JSON.stringify settingsOverride:
rootDoc_id: opts.rootDocOverride_id ? null
success: (body, status, response) ->
callback null, body.status, body.outputFiles
error: (error) ->
@@ -10,17 +10,23 @@ define [
template: $("#trackChangesDiffTemplate").html()
events:
"click .restore": () ->
console.log "click"
"click .restore": (e) ->
e.preventDefault()
@trigger "restore"
"click .restore-deleted": (e) ->
e.preventDefault()
@$("a.restore-deleted").attr("disabled", true)
@$("a.restore-deleted").text("Restoring...")
@trigger "restore-deleted"
initialize: () ->
@model.on "change:diff", () => @render()
if !@model.get("doc").get("deleted")
@model.on "change:diff", () => @render()
@model.fetch()
else
@render()
render: ->
diff = @model.get("diff")
return unless diff?
changes = @getNumberOfChanges()
html = Mustache.to_html @template, {
changes: "#{changes} change#{if changes == 1 then "" else "s"}"
@@ -28,18 +34,26 @@ define [
}
@$el.html(html)
if !@model.get("from")? or !@model.get("to")? or changes == 0
@$(".restore").hide()
if @model.get("doc").get("deleted")
@$(".change-info").hide()
@$(".deleted-info").show()
else
diff = @model.get("diff")
return unless diff?
if !@model.get("from")? or !@model.get("to")? or changes == 0
@$(".restore").hide()
@createAceEditor()
@aceEditor.setValue(@getPlainDiffContent())
@aceEditor.clearSelection()
@$ace = $(@aceEditor.renderer.container).find(".ace_scroller")
@insertMarkers()
@insertNameTag()
@insertMoreChangeLabels()
@bindToScrollEvents()
@scrollToFirstChange()
@createAceEditor()
@aceEditor.setValue(@getPlainDiffContent())
@aceEditor.clearSelection()
@$ace = $(@aceEditor.renderer.container).find(".ace_scroller")
@insertMarkers()
@insertNameTag()
@insertMoreChangeLabels()
@bindToScrollEvents()
@scrollToFirstChange()
return @
remove: () ->
@@ -71,6 +71,9 @@ define [
@ide.mainAreaManager.change "trackChanges"
@ide.editor.disable()
@ide.fileViewManager.disable()
@ide.fileTreeManager.showDeletedDocs()
@enable()
showUpgradeView: () ->
@@ -93,6 +96,7 @@ define [
@ide.fileTreeManager.openDoc(@doc_id)
@ide.tabManager.show "code"
@resetLabels()
@ide.fileTreeManager.hideDeletedDocs()
autoSelectDiff: () ->
if @changes.models.length == 0
@@ -160,7 +164,7 @@ define [
@diffView.remove()
if !@diff.get("doc")?
console.log "This document has been deleted. What should we do?"
console.log "This document does not exist. What should we do?"
return
@diffView = new DiffView(
@@ -171,7 +175,14 @@ define [
@diffView.on "restore", () =>
@restoreDiff(@diff)
@diff.fetch()
@diffView.on "restore-deleted", () =>
@restoreDeletedDoc @diff.get("doc"), (error, doc_id) =>
return if error? or !doc_id?
setTimeout () =>
# Give doc a chance to appear in file tree via socket.io
@hide()
@ide.fileTreeManager.openDoc(doc_id)
, 1000
@ide.fileTreeManager.selectEntity(@doc_id)
@@ -217,6 +228,21 @@ define [
}]
})
restoreDeletedDoc: (doc, callback) ->
$.ajax {
url: "/project/#{@project_id}/doc/#{doc.get("id")}/restore"
type: "POST"
dataType: "json"
data:
name: doc.get("name")
headers:
"X-CSRF-Token": window.csrfToken
success: (body, status, response) ->
callback(null, body?.doc_id)
error: (error) ->
callback(error)
}
enable: () ->
@enabled = true
@@ -21,6 +21,6 @@ define [
toV: data.toV
# TODO: We should not use a global reference here, but
# it's hard to get @ide into Backbone at this point.
entity: ide.fileTreeManager.getEntity(doc_id)
entity: ide.fileTreeManager.getEntity(doc_id, include_deleted: true)
return model
@@ -5,7 +5,7 @@ define [
Diff = Backbone.Model.extend
initialize: (attributes, options) ->
@ide = options.ide
@set "doc", @ide.fileTreeManager.getEntity(@get("doc_id"))
@set "doc", @ide.fileTreeManager.getEntity(@get("doc_id"), include_deleted: true)
url: () ->
url = "/project/#{@get("project_id")}/doc/#{@get("doc_id")}/diff"
@@ -414,6 +414,14 @@ body.editor {
}
}
.entity-deleted-docs-folder {
margin-top: 16px;
span.name {
padding: 6px;
border-bottom: 1px solid #ccc;
}
}
.entity-list {
padding-left: 0px;
}
@@ -24,7 +24,7 @@ describe "ClsiManager", ->
describe "sendRequest", ->
beforeEach ->
@ClsiManager._buildRequest = sinon.stub().callsArgWith(1, null, @request = "mock-request")
@ClsiManager._buildRequest = sinon.stub().callsArgWith(2, null, @request = "mock-request")
describe "with a successful compile", ->
beforeEach ->
@@ -39,7 +39,7 @@ describe "ClsiManager", ->
type: "log"
}]
})
@ClsiManager.sendRequest @project_id, @callback
@ClsiManager.sendRequest @project_id, {}, @callback
it "should build the request", ->
@ClsiManager._buildRequest
@@ -67,7 +67,7 @@ describe "ClsiManager", ->
compile:
status: @status = "failure"
})
@ClsiManager.sendRequest @project_id, @callback
@ClsiManager.sendRequest @project_id, {}, @callback
it "should call the callback with a failure statue", ->
@callback.calledWith(null, @status).should.equal true
@@ -121,7 +121,7 @@ describe "ClsiManager", ->
describe "with a valid project", ->
beforeEach (done) ->
@ClsiManager._buildRequest @project_id, (error, request) =>
@ClsiManager._buildRequest @project_id, null, (error, request) =>
@request = request
done()
@@ -159,10 +159,32 @@ describe "ClsiManager", ->
}]
)
describe "when root doc override is valid", ->
beforeEach (done) ->
@ClsiManager._buildRequest @project_id, {rootDoc_id:"mock-doc-id-2"}, (error, request) =>
@request = request
done()
it "should change root path", ->
@request.compile.rootResourcePath.should.equal "chapters/chapter1.tex"
describe "when root doc override is invalid", ->
beforeEach (done) ->
@ClsiManager._buildRequest @project_id, {rootDoc_id:"invalid-id"}, (error, request) =>
@request = request
done()
it "should fallback to default root doc", ->
@request.compile.rootResourcePath.should.equal "main.tex"
describe "when the project has an invalid compiler", ->
beforeEach (done) ->
@project.compiler = "context"
@ClsiManager._buildRequest @project, (error, request) =>
@ClsiManager._buildRequest @project, null, (error, request) =>
@request = request
done()
@@ -172,7 +194,7 @@ describe "ClsiManager", ->
describe "when there is no valid root document", ->
beforeEach (done) ->
@project.rootDoc_id = "not-valid"
@ClsiManager._buildRequest @project, (@error, @request) =>
@ClsiManager._buildRequest @project, null, (@error, @request) =>
done()
it "should return an error", ->
@@ -44,7 +44,7 @@ describe "CompileController", ->
it "should do the compile without the auto compile flag", ->
@CompileManager.compile
.calledWith(@project_id, @user_id, { isAutoCompile: false })
.calledWith(@project_id, @user_id, { isAutoCompile: false, settingsOverride:{} })
.should.equal true
it "should set the content-type of the response to application/json", ->
@@ -71,7 +71,7 @@ describe "CompileController", ->
it "should do the compile with the auto compile flag", ->
@CompileManager.compile
.calledWith(@project_id, @user_id, { isAutoCompile: true })
.calledWith(@project_id, @user_id, { isAutoCompile: true, settingsOverride:{} })
.should.equal true
describe "downloadPdf", ->
@@ -36,7 +36,7 @@ describe "CompileManager", ->
@CompileManager._checkIfRecentlyCompiled = sinon.stub().callsArgWith(2, null, false)
@CompileManager._ensureRootDocumentIsSet = sinon.stub().callsArgWith(1, null)
@DocumentUpdaterHandler.flushProjectToMongo = sinon.stub().callsArgWith(1, null)
@ClsiManager.sendRequest = sinon.stub().callsArgWith(1, null, @status = "mock-status")
@ClsiManager.sendRequest = sinon.stub().callsArgWith(2, null, @status = "mock-status")
describe "succesfully", ->
beforeEach ->
@@ -131,6 +131,22 @@ describe "DocstoreManager", ->
}, "error getting doc from docstore")
.should.equal true
describe "with include_deleted=true", ->
beforeEach ->
@request.get = sinon.stub().callsArgWith(1, null, statusCode: 204, @doc)
@DocstoreManager.getDoc @project_id, @doc_id, include_deleted: true, @callback
it "should get the doc from the docstore api (including deleted)", ->
@request.get
.calledWith({
url: "#{@settings.apis.docstore.url}/project/#{@project_id}/doc/#{@doc_id}?include_deleted=true"
json: true
})
.should.equal true
it "should call the callback with the lines, version and rev", ->
@callback.calledWith(null, @lines, @rev).should.equal true
describe "getAllDocs", ->
describe "with a successful response code", ->
beforeEach ->
@@ -0,0 +1,46 @@
SandboxedModule = require('sandboxed-module')
sinon = require('sinon')
require('chai').should()
modulePath = require('path').join __dirname, '../../../../app/js/Features/Editor/EditorHttpController'
describe "EditorHttpController", ->
beforeEach ->
@EditorHttpController = SandboxedModule.require modulePath, requires:
'../Project/ProjectEntityHandler' : @ProjectEntityHandler = {}
"./EditorRealTimeController": @EditorRealTimeController = {}
"logger-sharelatex": @logger = { log: sinon.stub(), error: sinon.stub() }
@project_id = "mock-project-id"
@doc_id = "mock-doc-id"
@req = {}
@res =
send: sinon.stub()
json: sinon.stub()
describe "restoreDoc", ->
beforeEach ->
@req.params =
Project_id: @project_id
doc_id: @doc_id
@req.body =
name: @name = "doc-name"
@ProjectEntityHandler.restoreDoc = sinon.stub().callsArgWith(3, null,
@doc = { "mock": "doc", _id: @new_doc_id = "new-doc-id" }
@folder_id = "mock-folder-id"
)
@EditorRealTimeController.emitToRoom = sinon.stub()
@EditorHttpController.restoreDoc @req, @res
it "should restore the doc", ->
@ProjectEntityHandler.restoreDoc
.calledWith(@project_id, @doc_id, @name)
.should.equal true
it "should the real-time clients about the new doc", ->
@EditorRealTimeController.emitToRoom
.calledWith(@project_id, 'reciveNewDoc', @folder_id, @doc)
.should.equal true
it "should return the new doc id", ->
@res.json
.calledWith(doc_id: @new_doc_id)
.should.equal true
@@ -55,6 +55,10 @@ describe "ProjectEditorHandler", ->
last_name : "Write"
email : "read-write@sharelatex.com"
}]
deletedDocs: [{
_id: "deleted-doc-id"
name: "main.tex"
}]
@handler = SandboxedModule.require modulePath
describe "buildProjectModelView", ->
@@ -85,6 +89,10 @@ describe "ProjectEditorHandler", ->
@result.owner.first_name.should.equal "Owner"
@result.owner.last_name.should.equal "ShareLaTeX"
@result.owner.privileges.should.equal "owner"
it "should include the deletedDocs", ->
should.exist @result.deletedDocs
@result.deletedDocs.should.equal @project.deletedDocs
it "should gather readOnly_refs and collaberators_refs into a list of members", ->
findMember = (id) =>
@@ -286,7 +286,7 @@ describe 'ProjectEntityHandler', ->
beforeEach ->
@lines = ["mock", "doc", "lines"]
@rev = 5
@DocstoreManager.getDoc = sinon.stub().callsArgWith(2, null, @lines, @rev)
@DocstoreManager.getDoc = sinon.stub().callsArgWith(3, null, @lines, @rev)
@ProjectEntityHandler.getDoc project_id, doc_id, @callback
it "should call the docstore", ->
@@ -339,6 +339,31 @@ describe 'ProjectEntityHandler', ->
.calledWith(project_id, @doc._id.toString(), @lines)
.should.equal true
describe "restoreDoc", ->
beforeEach ->
@name = "doc-name"
@lines = ['1234','abc']
@doc = { "mock": "doc" }
@folder_id = "mock-folder-id"
@callback = sinon.stub()
@ProjectEntityHandler.getDoc = sinon.stub().callsArgWith(3, null, @lines)
@ProjectEntityHandler.addDoc = sinon.stub().callsArgWith(4, null, @doc, @folder_id)
@ProjectEntityHandler.restoreDoc project_id, doc_id, @name, @callback
it 'should get the doc lines', ->
@ProjectEntityHandler.getDoc
.calledWith(project_id, doc_id, include_deleted: true)
.should.equal true
it "should add a new doc with these doc lines", ->
@ProjectEntityHandler.addDoc
.calledWith(project_id, null, @name, @lines)
.should.equal true
it "should call the callback with the new folder and doc", ->
@callback.calledWith(null, @doc, @folder_id).should.equal true
describe 'adding file', ->
fileName = "something.jpg"
beforeEach ->