diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 6c124f92..c77efdb8 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -21,6 +21,18 @@ def sort head :ok end + def duplicate + original = Project.includes(stories: :estimates).find(params[:id]) + duplicate = original.dup + duplicate.title = "Copy of #{original.title}" + duplicate.save + + original.stories.each { |x| duplicate.stories.create(x.dup.attributes) } + + flash[:success] = 'Project created!' + redirect_to "/projects/#{duplicate.id}" + end + def create @project = Project.new(projects_params) if @project.save diff --git a/app/views/projects/show.html.erb b/app/views/projects/show.html.erb index 2dbbc598..1e2c4533 100644 --- a/app/views/projects/show.html.erb +++ b/app/views/projects/show.html.erb @@ -65,6 +65,8 @@ <%= link_to 'Add Sub-Project', project_new_sub_project_path(@project.id), id:"subproject", class: "button magenta" %> <% end %> + <%= link_to 'Clone Project', duplicate_project_path(@project.id), method: :post, disable_with: 'Cloning...', class: "button magenta" %> + <%= link_to "Generate Action Plan", project_action_plan_path(@project.id), class: "button" %> <% if current_user.admin? %> <%= link_to "View Report", project_report_path(@project.id), class: "button" %> diff --git a/config/routes.rb b/config/routes.rb index 62831e3a..d2ecb55e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -16,6 +16,7 @@ resources :projects do patch :sort, on: :member get :new_sub_project + post :duplicate, on: :member resource :report do get 'download', to: 'reports#download' diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index e6ea3efe..c48605e3 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -132,4 +132,44 @@ expect(project.reload.title).to eq "New Project Title" end end + + describe 'duplicate' do + context 'with a project' do + before do + post :duplicate, params: { id: project.id } + end + + it 'creates a duplicate project' do + expect(Project.last.title).to eq "Copy of #{project.title}" + end + + it 'redirects to new project' do + expect(response).to redirect_to "/projects/#{Project.last.id}" + end + + it 'adds a success message' do + expect(flash[:success]).to be_present + end + end + + context 'with stories' do + it 'creates a duplicate project with matching stories' do + story = project.stories.create({ title: 'Story 1' }) + + post :duplicate, params: { id: project.id } + + expect(Project.last.stories.first.id).not_to eq story.id + expect(Project.last.stories.first.title).to eq story.title + end + + it 'creates stories without estimates' do + story = project.stories.create({ title: 'Story 1' }) + story.estimates.create({ best_case_points: 1, worst_case_points: 3 }) + + post :duplicate, params: { id: project.id } + + expect(Project.last.stories.first.estimates).to be_empty + end + end + end end diff --git a/spec/features/projects_manage_spec.rb b/spec/features/projects_manage_spec.rb index 618db0ff..7295bf37 100644 --- a/spec/features/projects_manage_spec.rb +++ b/spec/features/projects_manage_spec.rb @@ -21,6 +21,13 @@ expect(Project.count).to eq 1 end + it "allows me to clone a project" do + visit project_path(id: project.id) + click_link "Clone Project" + expect(Project.count).to eq 2 + expect(Project.last.title).to eq "Copy of #{project.title}" + end + it "allows me to edit a project" do visit project_path(id: project.id) click_link "Edit or Delete Project"