Add support for destroying project milestones
Closes https://github.com/gitlabhq/gitlabhq/issues/1504
This commit is contained in:
		
							parent
							
								
									c4c41007ad
								
							
						
					
					
						commit
						df2bb60f90
					
				|  | @ -1,5 +1,8 @@ | ||||||
| Please view this file on the master branch, on stable branches it's out of date. | Please view this file on the master branch, on stable branches it's out of date. | ||||||
| 
 | 
 | ||||||
|  | v 7.14.0 (unreleased) | ||||||
|  |   - Add support for destroying project milestones (Stan Hu) | ||||||
|  | 
 | ||||||
| v 7.13.0 (unreleased) | v 7.13.0 (unreleased) | ||||||
|   - Only enable HSTS header for HTTPS and port 443 (Stan Hu) |   - Only enable HSTS header for HTTPS and port 443 (Stan Hu) | ||||||
|   - Fix user autocomplete for unauthenticated users accessing public projects (Stan Hu) |   - Fix user autocomplete for unauthenticated users accessing public projects (Stan Hu) | ||||||
|  |  | ||||||
|  | @ -64,7 +64,12 @@ class Projects::MilestonesController < Projects::ApplicationController | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def destroy |   def destroy | ||||||
|     return access_denied! unless can?(current_user, :admin_milestone, @milestone) |     return access_denied! unless can?(current_user, :admin_milestone, @project) | ||||||
|  | 
 | ||||||
|  |     update_params = { milestone: nil } | ||||||
|  |     @milestone.issues.each do |issue| | ||||||
|  |       Issues::UpdateService.new(@project, current_user, update_params).execute(issue) | ||||||
|  |     end | ||||||
| 
 | 
 | ||||||
|     @milestone.destroy |     @milestone.destroy | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -5,6 +5,10 @@ | ||||||
|         %i.fa.fa-pencil-square-o |         %i.fa.fa-pencil-square-o | ||||||
|         Edit |         Edit | ||||||
|       = link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, milestone, milestone: {state_event: :close }), method: :put, remote: true, class: "btn btn-sm btn-close" |       = link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, milestone, milestone: {state_event: :close }), method: :put, remote: true, class: "btn btn-sm btn-close" | ||||||
|  |       = link_to namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-sm btn-remove" do | ||||||
|  |         %i.fa.fa-trash-o | ||||||
|  |         Remove | ||||||
|  | 
 | ||||||
|   %h4 |   %h4 | ||||||
|     = link_to_gfm truncate(milestone.title, length: 100), namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone) |     = link_to_gfm truncate(milestone.title, length: 100), namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone) | ||||||
|     - if milestone.expired? and not milestone.closed? |     - if milestone.expired? and not milestone.closed? | ||||||
|  |  | ||||||
|  | @ -19,6 +19,9 @@ | ||||||
|         = link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-close btn-grouped" |         = link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-close btn-grouped" | ||||||
|       - else |       - else | ||||||
|         = link_to 'Reopen Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :activate }), method: :put, class: "btn btn-reopen btn-grouped" |         = link_to 'Reopen Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :activate }), method: :put, class: "btn btn-reopen btn-grouped" | ||||||
|  |       = link_to namespace_project_milestone_path(@project.namespace, @project, @milestone), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-grouped btn-remove" do | ||||||
|  |         %i.fa.fa-trash-o | ||||||
|  |         Remove | ||||||
| 
 | 
 | ||||||
| %hr | %hr | ||||||
| - if @milestone.issues.any? && @milestone.can_be_closed? | - if @milestone.issues.any? && @milestone.can_be_closed? | ||||||
|  |  | ||||||
|  | @ -481,7 +481,7 @@ Gitlab::Application.routes.draw do | ||||||
|           end |           end | ||||||
|         end |         end | ||||||
| 
 | 
 | ||||||
|         resources :milestones, except: [:destroy], constraints: { id: /\d+/ } do |         resources :milestones, constraints: { id: /\d+/ } do | ||||||
|           member do |           member do | ||||||
|             put :sort_issues |             put :sort_issues | ||||||
|             put :sort_merge_requests |             put :sort_merge_requests | ||||||
|  |  | ||||||
|  | @ -17,6 +17,10 @@ Feature: Project Issues Milestones | ||||||
|     And I submit new milestone "v2.3" |     And I submit new milestone "v2.3" | ||||||
|     Then I should see milestone "v2.3" |     Then I should see milestone "v2.3" | ||||||
| 
 | 
 | ||||||
|  |   Scenario: I delete new milestone | ||||||
|  |     Given I click link to remove milestone "v2.2" | ||||||
|  |     And I should see no milestones | ||||||
|  | 
 | ||||||
|   @javascript |   @javascript | ||||||
|   Scenario: Listing closed issues |   Scenario: Listing closed issues | ||||||
|     Given the milestone has open and closed issues |     Given the milestone has open and closed issues | ||||||
|  |  | ||||||
|  | @ -56,4 +56,12 @@ class Spinach::Features::ProjectIssuesMilestones < Spinach::FeatureSteps | ||||||
|   step 'I should see 3 issues' do |   step 'I should see 3 issues' do | ||||||
|     expect(page).to have_selector('#tab-issues li.issue-row', count: 4) |     expect(page).to have_selector('#tab-issues li.issue-row', count: 4) | ||||||
|   end |   end | ||||||
|  | 
 | ||||||
|  |   step 'I click link to remove milestone "v2.2"' do | ||||||
|  |     click_link 'Remove' | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   step 'I should see no milestones' do | ||||||
|  |     expect(page).to have_content('No milestones to show') | ||||||
|  |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -0,0 +1,28 @@ | ||||||
|  | require 'spec_helper' | ||||||
|  | 
 | ||||||
|  | describe Projects::MilestonesController do | ||||||
|  |   let(:project) { create(:project) } | ||||||
|  |   let(:user)    { create(:user) } | ||||||
|  |   let(:milestone) { create(:milestone, project: project) } | ||||||
|  |   let(:issue) { create(:issue, project: project, milestone: milestone) } | ||||||
|  | 
 | ||||||
|  |   before do | ||||||
|  |     sign_in(user) | ||||||
|  |     project.team << [user, :master] | ||||||
|  |     controller.instance_variable_set(:@project, project) | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   describe "#destroy" do | ||||||
|  |     it "should remove milestone" do | ||||||
|  |       expect(issue.milestone_id).to eq(milestone.id) | ||||||
|  |       delete :destroy, namespace_id: project.namespace.id, project_id: project.id, id: milestone.id, format: :js | ||||||
|  |       expect(response).to be_success | ||||||
|  |       expect { Milestone.find(milestone.id) }.to raise_exception(ActiveRecord::RecordNotFound) | ||||||
|  |       issue.reload | ||||||
|  |       expect(issue.milestone_id).to eq(nil) | ||||||
|  |       # Check system note left for milestone removal | ||||||
|  |       last_note = project.issues.find(issue.id).notes[-1].note | ||||||
|  |       expect(last_note).to eq('Milestone removed') | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
		Loading…
	
		Reference in New Issue