diff --git a/services/web/app/coffee/Features/Compile/ClsiManager.coffee b/services/web/app/coffee/Features/Compile/ClsiManager.coffee index 3fda07a246..568d806e99 100755 --- a/services/web/app/coffee/Features/Compile/ClsiManager.coffee +++ b/services/web/app/coffee/Features/Compile/ClsiManager.coffee @@ -36,6 +36,13 @@ module.exports = ClsiManager = outputFiles = ClsiManager._parseOutputFiles(project_id, response?.compile?.outputFiles) callback(null, response?.compile?.status, outputFiles, clsiServerId) + stopCompile: (project_id, user_id, options, callback = (error) ->) -> + compilerUrl = @_getCompilerUrl(options?.compileGroup, project_id, user_id, "compile/stop") + opts = + url:compilerUrl + method:"POST" + ClsiManager._makeRequest project_id, opts, callback + deleteAuxFiles: (project_id, user_id, options, callback = (error) ->) -> compilerUrl = @_getCompilerUrl(options?.compileGroup, project_id, user_id) opts = diff --git a/services/web/app/coffee/Features/Compile/CompileController.coffee b/services/web/app/coffee/Features/Compile/CompileController.coffee index a790948db5..6163fd315b 100755 --- a/services/web/app/coffee/Features/Compile/CompileController.coffee +++ b/services/web/app/coffee/Features/Compile/CompileController.coffee @@ -41,6 +41,15 @@ module.exports = CompileController = validationProblems:validationProblems } + stopCompile: (req, res, next = (error) ->) -> + project_id = req.params.Project_id + AuthenticationController.getLoggedInUserId req, (error, user_id) -> + return next(error) if error? + logger.log {project_id:project_id, user_id:user_id}, "stop compile request" + CompileManager.stopCompile project_id, user_id, (error) -> + return next(error) if error? + res.status(200).send() + _compileAsUser: (req, callback) -> # callback with user_id if per-user, undefined otherwise if not Settings.disablePerUserCompiles diff --git a/services/web/app/coffee/Features/Compile/CompileManager.coffee b/services/web/app/coffee/Features/Compile/CompileManager.coffee index c561576525..24a051f9f3 100755 --- a/services/web/app/coffee/Features/Compile/CompileManager.coffee +++ b/services/web/app/coffee/Features/Compile/CompileManager.coffee @@ -44,6 +44,12 @@ module.exports = CompileManager = logger.log files: outputFiles, "output files" callback(null, status, outputFiles, clsiServerId, limits, validationProblems) + + stopCompile: (project_id, user_id, callback = (error) ->) -> + CompileManager.getProjectCompileLimits project_id, (error, limits) -> + return callback(error) if error? + ClsiManager.stopCompile project_id, user_id, limits, callback + deleteAuxFiles: (project_id, user_id, callback = (error) ->) -> CompileManager.getProjectCompileLimits project_id, (error, limits) -> return callback(error) if error? diff --git a/services/web/app/coffee/router.coffee b/services/web/app/coffee/router.coffee index 40792ed540..51e2c1ee0b 100644 --- a/services/web/app/coffee/router.coffee +++ b/services/web/app/coffee/router.coffee @@ -105,6 +105,8 @@ module.exports = class Router webRouter.post '/project/:Project_id/settings/admin', AuthorizationMiddlewear.ensureUserCanAdminProject, ProjectController.updateProjectAdminSettings webRouter.post '/project/:Project_id/compile', AuthorizationMiddlewear.ensureUserCanReadProject, CompileController.compile + webRouter.post '/project/:Project_id/compile/stop', AuthorizationMiddlewear.ensureUserCanReadProject, CompileController.stopCompile + # Used by the web download buttons, adds filename header webRouter.get '/project/:Project_id/output/output.pdf', AuthorizationMiddlewear.ensureUserCanReadProject, CompileController.downloadPdf # Used by the pdf viewers @@ -127,6 +129,17 @@ module.exports = class Router next() ), AuthorizationMiddlewear.ensureUserCanReadProject, CompileController.getFileFromClsi + # direct url access to output files for user but no build, to retrieve files when build fails + webRouter.get /^\/project\/([^\/]*)\/user\/([0-9a-f-]+)\/output\/(.*)$/, + ((req, res, next) -> + params = + "Project_id": req.params[0] + "user_id": req.params[1] + "file": req.params[2] + req.params = params + next() + ), AuthorizationMiddlewear.ensureUserCanReadProject, CompileController.getFileFromClsi + # direct url access to output files for a specific user and build (query string not required) webRouter.get /^\/project\/([^\/]*)\/user\/([0-9a-f]+)\/build\/([0-9a-f-]+)\/output\/(.*)$/, ((req, res, next) -> diff --git a/services/web/app/views/project/editor/pdf.jade b/services/web/app/views/project/editor/pdf.jade index f9d02e8557..5862e82db0 100644 --- a/services/web/app/views/project/editor/pdf.jade +++ b/services/web/app/views/project/editor/pdf.jade @@ -36,6 +36,14 @@ div.full-size.pdf(ng-controller="PdfController") i.fa.fa-fw(ng-class="{'fa-check': draft}") |  #{translate("fast")}  span.subdued [draft] + a( + href + ng-click="stop()" + ng-show="pdf.compiling", + tooltip="#{translate('stop_compile')}" + tooltip-placement="bottom" + ) + i.fa.fa-stop() a.log-btn( href ng-click="toggleLogs()" @@ -239,7 +247,11 @@ div.full-size.pdf(ng-controller="PdfController") .alert.alert-danger(ng-show="pdf.tooRecentlyCompiled") strong #{translate("server_error")} span #{translate("too_recently_compiled")} - + + .alert.alert-danger(ng-show="pdf.compileTerminated") + strong #{translate("terminated")}. + span #{translate("compile_terminated_by_user")} + .alert.alert-danger(ng-show="pdf.timedout") p strong #{translate("timedout")}. diff --git a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee index 195083b118..dbdd137b57 100644 --- a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee +++ b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee @@ -94,6 +94,7 @@ define [ $scope.pdf.tooRecentlyCompiled = false $scope.pdf.renderingError = false $scope.pdf.projectTooLarge = false + $scope.pdf.compileTerminated = false # make a cache to look up files by name fileByPath = {} @@ -104,6 +105,11 @@ define [ if response.status == "timedout" $scope.pdf.view = 'errors' $scope.pdf.timedout = true + fetchLogs(fileByPath['output.log'], fileByPath['output.blg']) + else if response.status == "terminated" + $scope.pdf.view = 'errors' + $scope.pdf.compileTerminated = true + fetchLogs(fileByPath['output.log'], fileByPath['output.blg']) else if response.status == "autocompile-backoff" $scope.pdf.view = 'uncompiled' else if response.status == "project-too-large" @@ -294,6 +300,18 @@ define [ ide.$scope.recompileViaKey = () -> $scope.recompile { keyShortcut: true } + $scope.stop = () -> + return if !$scope.pdf.compiling + + $http { + url: "/project/#{$scope.project_id}/compile/stop" + method: "POST" + params: + clsiserverid:ide.clsiServerId + headers: + "X-Csrf-Token": window.csrfToken + } + $scope.clearCache = () -> $http { url: "/project/#{$scope.project_id}/output"