diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee index b685cb2ea8..767a897a18 100644 --- a/services/web/app/coffee/Features/Project/ProjectController.coffee +++ b/services/web/app/coffee/Features/Project/ProjectController.coffee @@ -18,8 +18,15 @@ module.exports = deleteProject: (req, res) -> project_id = req.params.Project_id - logger.log project_id:project_id, "received request to delete project" - projectDeleter.archiveProject project_id, (err)-> + forever = req.query?.forever? + logger.log project_id: project_id, forever: forever, "received request to delete project" + + if forever + doDelete = projectDeleter.deleteProject + else + doDelete = projectDeleter.archiveProject + + doDelete project_id, (err)-> if err? res.send 500 else diff --git a/services/web/app/coffee/Features/Project/ProjectDeleter.coffee b/services/web/app/coffee/Features/Project/ProjectDeleter.coffee index 434c94294f..f9974261cd 100644 --- a/services/web/app/coffee/Features/Project/ProjectDeleter.coffee +++ b/services/web/app/coffee/Features/Project/ProjectDeleter.coffee @@ -5,7 +5,7 @@ tagsHandler = require("../Tags/TagsHandler") async = require("async") FileStoreHandler = require("../FileStore/FileStoreHandler") -module.exports = +module.exports = ProjectDeleter = markAsDeletedByExternalSource : (project_id, callback)-> logger.log project_id:project_id, "marking project as deleted by external data source" @@ -20,6 +20,12 @@ module.exports = logger.log owner_id:owner_id, "deleting users projects" Project.remove owner_ref:owner_id, callback + deleteProject: (project_id, callback = (error) ->) -> + # archiveProject takes care of the clean-up + ProjectDeleter.archiveProject project_id, (error) -> + logger.log project_id: project_id, "deleting project" + Project.remove _id: project_id, callback + archiveProject: (project_id, callback = (error) ->)-> logger.log project_id:project_id, "deleting project" Project.findById project_id, (err, project)=> diff --git a/services/web/app/views/modals.jade b/services/web/app/views/modals.jade index d383a4e1d7..4b19853548 100644 --- a/services/web/app/views/modals.jade +++ b/services/web/app/views/modals.jade @@ -1,4 +1,4 @@ -#deleteEntityModal(style='display: none') +#archiveEntityModal(style='display: none') .modal .modal-header h3 Delete Project @@ -6,6 +6,21 @@ span.message Are you sure you want to delete strong.name Project | ? + .modal-footer + button.btn.btn-danger.confirm Delete + button.btn.cancel No + +#deleteEntityModal(style='display: none') + .modal + .modal-header + h3 Delete Project + .modal-body + p Are you sure you want to delete + strong.name Project + | ? + + p + strong It will not be possible to recover your project once deleted. .modal-footer button.btn.btn-danger.confirm Delete Forever button.btn.cancel No diff --git a/services/web/app/views/project/archived.jade b/services/web/app/views/project/archived.jade index f50442ce50..4c3e5e8394 100644 --- a/services/web/app/views/project/archived.jade +++ b/services/web/app/views/project/archived.jade @@ -5,8 +5,10 @@ block content -each project in projects - project_id = project._id.toString() .project_entry(id=project_id) - .btn-group.project-actions + .project-actions a.btn(href='/project/'+project_id+'/restore', data-csrf=csrfToken, data-id=project_id).restoreProject Restore + | + a.btn.btn-danger(href='/project/'+project_id+'?forever=true', data-csrf=csrfToken, data-name=project.name, data-id=project_id).deleteProject Delete Forever .projectName #{project.name} include ../general/sidebar diff --git a/services/web/app/views/project/list.jade b/services/web/app/views/project/list.jade index b72cb094ba..903bfcc60b 100644 --- a/services/web/app/views/project/list.jade +++ b/services/web/app/views/project/list.jade @@ -33,7 +33,7 @@ block content li a(href='/project/'+project_id+'/rename', data-name=project.name, data-id=project_id, data-csrf=csrfToken).renameProject Rename li - a(href='/project/'+project_id, data-name=project.name, data-id=project_id, data-csrf=csrfToken).deleteProject Delete + a(href='/project/'+project_id, data-name=project.name, data-id=project_id, data-csrf=csrfToken).archiveProject Delete -else li a(href='/project/'+project_id+'/leave', data-name=project.name, data-id=project_id, data-csrf=csrfToken).leaveProject Leave diff --git a/services/web/public/coffee/list.coffee b/services/web/public/coffee/list.coffee index a08a94a729..aa6e66810b 100644 --- a/services/web/public/coffee/list.coffee +++ b/services/web/public/coffee/list.coffee @@ -79,6 +79,35 @@ require [ $modal.find('.cancel').click (e)-> $modal.modal('hide') + $('.archiveProject').click (event)-> + event.preventDefault() + $modal = $('#archiveEntityModal') + $confirm = $modal.find('.confirm') + $modal.modal({backdrop:true, show:true, keyboard:true}) + name = $(@).data("name") + id = $(@).data("id") + + $modal.find(".name").text(name) + + href = this.href + self = @ + $confirm.on 'click', (e) => + $.ajax + url: href + type:'DELETE' + data: + _csrf: $(@).data("csrf") + success: (data)-> + $modal.modal('hide') + if data.message + new Message data + else + $("##{id}").fadeOut(1000) + $modal.on 'hide', -> + $confirm.off 'click' + $modal.find('.cancel').click (e)-> + $modal.modal('hide') + $('.renameProject').click (event)-> event.preventDefault() $modal = $('#renameProjectModal') diff --git a/services/web/test/UnitTests/coffee/Project/ProjectControllerTests.coffee b/services/web/test/UnitTests/coffee/Project/ProjectControllerTests.coffee index 380cd7e1c0..34df344e86 100644 --- a/services/web/test/UnitTests/coffee/Project/ProjectControllerTests.coffee +++ b/services/web/test/UnitTests/coffee/Project/ProjectControllerTests.coffee @@ -18,8 +18,9 @@ describe "ProjectController", -> url:"chat.com" siteUrl: "mysite.com" @ProjectDeleter = - archiveProject: sinon.stub().callsArgWith(1) - restoreProject: sinon.stub().callsArgWith(1) + archiveProject: sinon.stub().callsArg(1) + deleteProject: sinon.stub().callsArg(1) + restoreProject: sinon.stub().callsArg(1) findArchivedProjects: sinon.stub() @ProjectDuplicator = duplicate: sinon.stub().callsArgWith(3, null, {_id:@project_id}) @@ -70,13 +71,21 @@ describe "ProjectController", -> jsPath:"js path here" describe "deleteProject", -> - it "should tell the project deleter", (done)-> + it "should tell the project deleter to archive when forever=false", (done)-> @res.send = (code)=> @ProjectDeleter.archiveProject.calledWith(@project_id).should.equal true code.should.equal 200 done() @ProjectController.deleteProject @req, @res + it "should tell the project deleter to delete when forever=true", (done)-> + @req.query = forever: "true" + @res.send = (code)=> + @ProjectDeleter.deleteProject.calledWith(@project_id).should.equal true + code.should.equal 200 + done() + @ProjectController.deleteProject @req, @res + describe "restoreProject", -> it "should tell the project deleter", (done)-> @res.send = (code)=> diff --git a/services/web/test/UnitTests/coffee/Project/ProjectDeleterTests.coffee b/services/web/test/UnitTests/coffee/Project/ProjectDeleterTests.coffee index 931f7d89c4..77c37c7f14 100644 --- a/services/web/test/UnitTests/coffee/Project/ProjectDeleterTests.coffee +++ b/services/web/test/UnitTests/coffee/Project/ProjectDeleterTests.coffee @@ -55,6 +55,22 @@ describe 'Project deleter', -> @Project.remove.calledWith(owner_ref:user_id).should.equal true done() + describe "deleteProject", -> + beforeEach (done) -> + @project_id = "mock-project-id-123" + @deleter.archiveProject = sinon.stub().callsArg(1) + + @deleter.deleteProject @project_id, done + + it "should archive the project to clean it up", -> + @deleter.archiveProject + .calledWith(@project_id) + .should.equal true + + it "should remove the project from Mongo", -> + @Project.remove + .calledWith(_id: @project_id) + .should.equal true describe "archiveProject", -> beforeEach ->