Browse Source

Merge branch 'bg-support-main-file-for-templates'

Brian Gough 8 years ago
parent
commit
5947294016

+ 6 - 0
services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee

@@ -65,6 +65,12 @@ module.exports = ProjectEntityHandler = self =
 						files.push({path: path.join(folderPath, file.name), file:file})
 			callback null, docs, files
 
+	getAllDocPathsFromProjectById: (project_id, callback) ->
+		ProjectGetter.getProjectWithoutDocLines project_id, (err, project) ->
+			return callback(err) if err?
+			return callback(Errors.NotFoundError("no project")) if !project?
+			self.getAllDocPathsFromProject project, callback
+
 	getAllDocPathsFromProject: (project, callback) ->
 		logger.log project:project, "getting all docs for project"
 		self._getAllFoldersFromProject project, (err, folders = {}) ->

+ 24 - 0
services/web/app/coffee/Features/Project/ProjectRootDocManager.coffee

@@ -31,3 +31,27 @@ module.exports = ProjectRootDocManager =
 					ProjectEntityUpdateHandler.setRootDoc project_id, root_doc_id, callback
 				else
 					callback()
+
+	setRootDocFromName: (project_id, rootDocName, callback = (error) ->) ->
+		ProjectEntityHandler.getAllDocPathsFromProjectById project_id, (error, docPaths) ->
+			return callback(error) if error?
+			# strip off leading and trailing quotes from rootDocName
+			rootDocName = rootDocName.replace(/^\'|\'$/g,"")
+			# prepend a slash for the root folder if not present
+			rootDocName = "/#{rootDocName}" if rootDocName[0] isnt '/'
+			# find the root doc from the filename
+			root_doc_id = null
+			for doc_id, path of docPaths
+				# docpaths have a leading / so allow matching "folder/filename" and "/folder/filename"
+				if path == rootDocName
+					root_doc_id = doc_id
+			# try a basename match if there was no match 
+			if !root_doc_id
+				for doc_id, path of docPaths
+					if Path.basename(path) == Path.basename(rootDocName) 
+						root_doc_id = doc_id
+			# set the root doc id if we found a match
+			if root_doc_id?
+				ProjectEntityUpdateHandler.setRootDoc project_id, root_doc_id, callback
+			else
+				callback()

+ 19 - 9
services/web/app/coffee/Features/Templates/TemplatesController.coffee

@@ -2,6 +2,7 @@ path = require('path')
 Project = require('../../../js/models/Project').Project
 ProjectUploadManager = require('../../../js/Features/Uploads/ProjectUploadManager')
 ProjectOptionsHandler = require('../../../js/Features/Project/ProjectOptionsHandler')
+ProjectRootDocManager = require('../../../js/Features/Project/ProjectRootDocManager')
 AuthenticationController = require('../../../js/Features/Authentication/AuthenticationController')
 settings = require('settings-sharelatex')
 fs = require('fs')
@@ -24,6 +25,7 @@ module.exports = TemplatesController =
 		data.templateId = templateId
 		data.name = req.query.templateName
 		data.compiler = req.query.latexEngine
+		data.mainFile = req.query.mainFile
 		res.render path.resolve(__dirname, "../../../views/project/editor/new_from_template"), data
 
 	createProjectFromV1Template: (req, res)->
@@ -43,6 +45,7 @@ module.exports = TemplatesController =
 				currentUserId: currentUserId,
 				compiler: req.body.compiler
 				docId: req.body.docId
+				mainFile: req.body.mainFile
 				templateId: req.body.templateId
 				templateVersionId: req.body.templateVersionId
 				image: 'wl_texlive:2018.1'
@@ -65,15 +68,16 @@ module.exports = TemplatesController =
 					return res.sendStatus 500
 				setCompiler project._id, options.compiler, ->
 					setImage project._id, options.image, ->
-						fs.unlink dumpPath, ->
-						delete req.session.templateData
-						conditions = {_id:project._id}
-						update = {
-							fromV1TemplateId:options.templateId,
-							fromV1TemplateVersionId:options.templateVersionId
-						}
-						Project.update conditions, update, {}, (err)->
-							res.redirect "/project/#{project._id}"
+						setMainFile project._id, options.mainFile, ->
+							fs.unlink dumpPath, ->
+							delete req.session.templateData
+							conditions = {_id:project._id}
+							update = {
+								fromV1TemplateId:options.templateId,
+								fromV1TemplateVersionId:options.templateVersionId
+							}
+							Project.update conditions, update, {}, (err)->
+								res.redirect "/project/#{project._id}"
 
 setCompiler = (project_id, compiler, callback)->
 	if compiler?
@@ -86,3 +90,9 @@ setImage = (project_id, imageName, callback)->
 		ProjectOptionsHandler.setImageName project_id, imageName, callback
 	else
 		callback()
+
+setMainFile = (project_id, mainFile, callback) ->
+	if mainFile?
+		ProjectRootDocManager.setRootDocFromName project_id, mainFile, callback
+	else
+		callback()

+ 1 - 0
services/web/app/views/project/editor/new_from_template.pug

@@ -24,3 +24,4 @@ block content
     input(type="hidden" name="templateVersionId" value=templateVersionId)
     input(type="hidden" name="templateName" value=name)
     input(type="hidden" name="compiler" value=compiler)
+    input(type="hidden" name="mainFile" value=mainFile)

+ 90 - 0
services/web/test/unit/coffee/Project/ProjectRootDocManagerTests.coffee

@@ -75,3 +75,93 @@ describe 'ProjectRootDocManager', ->
 			it "should not set the root doc to the doc containing a documentclass", ->
 				@ProjectEntityUpdateHandler.setRootDoc.called.should.equal false
 
+	describe "setRootDocFromName", ->
+		describe "when there is a suitable root doc", ->
+			beforeEach (done)->
+				@docPaths =
+					"doc-id-1": "/chapter1.tex"
+					"doc-id-2": "/main.tex"
+					"doc-id-3": "/nested/chapter1a.tex"
+					"doc-id-4": "/nested/chapter1b.tex"
+				@ProjectEntityHandler.getAllDocPathsFromProjectById = sinon.stub().callsArgWith(1, null, @docPaths)
+				@ProjectEntityUpdateHandler.setRootDoc = sinon.stub().callsArgWith(2)
+				@ProjectRootDocManager.setRootDocFromName @project_id, '/main.tex', done
+
+			it "should check the docs of the project", ->
+				@ProjectEntityHandler.getAllDocPathsFromProjectById.calledWith(@project_id)
+					.should.equal true
+
+			it "should set the root doc to main.tex", ->
+				@ProjectEntityUpdateHandler.setRootDoc.calledWith(@project_id, "doc-id-2")
+					.should.equal true
+
+		describe "when there is a suitable root doc but the leading slash is missing", ->
+			beforeEach (done)->
+				@docPaths =
+					"doc-id-1": "/chapter1.tex"
+					"doc-id-2": "/main.tex"
+					"doc-id-3": "/nested/chapter1a.tex"
+					"doc-id-4": "/nested/chapter1b.tex"
+				@ProjectEntityHandler.getAllDocPathsFromProjectById = sinon.stub().callsArgWith(1, null, @docPaths)
+				@ProjectEntityUpdateHandler.setRootDoc = sinon.stub().callsArgWith(2)
+				@ProjectRootDocManager.setRootDocFromName @project_id, 'main.tex', done
+
+			it "should check the docs of the project", ->
+				@ProjectEntityHandler.getAllDocPathsFromProjectById.calledWith(@project_id)
+					.should.equal true
+
+			it "should set the root doc to main.tex", ->
+				@ProjectEntityUpdateHandler.setRootDoc.calledWith(@project_id, "doc-id-2")
+					.should.equal true
+
+		describe "when there is a suitable root doc with a basename match", ->
+			beforeEach (done)->
+				@docPaths =
+					"doc-id-1": "/chapter1.tex"
+					"doc-id-2": "/main.tex"
+					"doc-id-3": "/nested/chapter1a.tex"
+					"doc-id-4": "/nested/chapter1b.tex"
+				@ProjectEntityHandler.getAllDocPathsFromProjectById = sinon.stub().callsArgWith(1, null, @docPaths)
+				@ProjectEntityUpdateHandler.setRootDoc = sinon.stub().callsArgWith(2)
+				@ProjectRootDocManager.setRootDocFromName @project_id, 'chapter1a.tex', done
+
+			it "should check the docs of the project", ->
+				@ProjectEntityHandler.getAllDocPathsFromProjectById.calledWith(@project_id)
+					.should.equal true
+
+			it "should set the root doc using the basename", ->
+				@ProjectEntityUpdateHandler.setRootDoc.calledWith(@project_id, "doc-id-3")
+					.should.equal true
+
+		describe "when there is a suitable root doc but the filename is in quotes", ->
+			beforeEach (done)->
+				@docPaths =
+					"doc-id-1": "/chapter1.tex"
+					"doc-id-2": "/main.tex"
+					"doc-id-3": "/nested/chapter1a.tex"
+					"doc-id-4": "/nested/chapter1b.tex"
+				@ProjectEntityHandler.getAllDocPathsFromProjectById = sinon.stub().callsArgWith(1, null, @docPaths)
+				@ProjectEntityUpdateHandler.setRootDoc = sinon.stub().callsArgWith(2)
+				@ProjectRootDocManager.setRootDocFromName @project_id, "'main.tex'", done
+
+			it "should check the docs of the project", ->
+				@ProjectEntityHandler.getAllDocPathsFromProjectById.calledWith(@project_id)
+					.should.equal true
+
+			it "should set the root doc to main.tex", ->
+				@ProjectEntityUpdateHandler.setRootDoc.calledWith(@project_id, "doc-id-2")
+					.should.equal true
+
+		describe "when there is no suitable root doc", ->
+			beforeEach (done)->
+				@docPaths =
+					"doc-id-1": "/chapter1.tex"
+					"doc-id-2": "/main.tex"
+					"doc-id-3": "/nested/chapter1a.tex"
+					"doc-id-4": "/nested/chapter1b.tex"
+				@ProjectEntityHandler.getAllDocPathsFromProjectById = sinon.stub().callsArgWith(1, null, @docPaths)
+				@ProjectEntityUpdateHandler.setRootDoc = sinon.stub().callsArgWith(2)
+				@ProjectRootDocManager.setRootDocFromName @project_id, "other.tex", done
+
+			it "should not set the root doc", ->
+				@ProjectEntityUpdateHandler.setRootDoc.called.should.equal false

+ 4 - 0
services/web/test/unit/coffee/Templates/TemplatesControllerTests.coffee

@@ -27,6 +27,9 @@ describe 'TemplatesController', ->
 			setImageName:sinon.stub().callsArgWith(2)
 		}
 		@uuid = "1234"
+		@ProjectRootDocManager = {
+			setRootDocFromName: sinon.stub().callsArgWith(2)
+		}
 		@ProjectDetailsHandler =
 			getProjectDescription:sinon.stub()
 		@Project =
@@ -34,6 +37,7 @@ describe 'TemplatesController', ->
 		@controller = SandboxedModule.require modulePath, requires:
 			'../../../js/Features/Uploads/ProjectUploadManager':@ProjectUploadManager
 			'../../../js/Features/Project/ProjectOptionsHandler':@ProjectOptionsHandler
+			'../../../js/Features/Project/ProjectRootDocManager':@ProjectRootDocManager
 			'../../../js/Features/Authentication/AuthenticationController': @AuthenticationController = {getLoggedInUserId: sinon.stub()}
 			'./TemplatesPublisher':@TemplatesPublisher
 			"logger-sharelatex":