diff options
author | Sean McGivern <sean@mcgivern.me.uk> | 2017-09-01 10:47:32 +0000 |
---|---|---|
committer | Sean McGivern <sean@mcgivern.me.uk> | 2017-09-01 10:47:32 +0000 |
commit | 10854ad8256c605343e8f56b5bf46f7e27b90524 (patch) | |
tree | 9a9f102cf746e01d1abcfbdf9f6af03c292d59af | |
parent | aeb005fcf82660b4e37ef37856219db6b961627e (diff) | |
parent | 7e71f958ac721f5c36c20a5366c1e46adce4c67d (diff) | |
download | gitlab-ce-10854ad8256c605343e8f56b5bf46f7e27b90524.tar.gz |
Merge branch 'move-action' into 'master'
Merge request to address /move functionality.
See merge request !13436
-rw-r--r-- | app/services/issuable_base_service.rb | 1 | ||||
-rw-r--r-- | app/services/issues/update_service.rb | 13 | ||||
-rw-r--r-- | app/services/quick_actions/interpret_service.rb | 18 | ||||
-rw-r--r-- | changelogs/unreleased/move-action.yml | 4 | ||||
-rw-r--r-- | doc/user/project/quick_actions.md | 1 | ||||
-rw-r--r-- | spec/features/issues/user_uses_slash_commands_spec.rb | 109 | ||||
-rw-r--r-- | spec/services/issues/update_service_spec.rb | 20 | ||||
-rw-r--r-- | spec/services/quick_actions/interpret_service_spec.rb | 10 |
8 files changed, 175 insertions, 1 deletions
diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb index 1486db046b5..7679389faf6 100644 --- a/app/services/issuable_base_service.rb +++ b/app/services/issuable_base_service.rb @@ -56,6 +56,7 @@ class IssuableBaseService < BaseService params.delete(:assignee_id) params.delete(:due_date) params.delete(:canonical_issue_id) + params.delete(:project) end filter_assignee(issuable) diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb index 8d918ccc635..deb4990eb4f 100644 --- a/app/services/issues/update_service.rb +++ b/app/services/issues/update_service.rb @@ -6,7 +6,7 @@ module Issues handle_move_between_iids(issue) filter_spam_check_params change_issue_duplicate(issue) - update(issue) + move_issue_to_new_project(issue) || update(issue) end def before_update(issue) @@ -74,6 +74,17 @@ module Issues end end + def move_issue_to_new_project(issue) + target_project = params.delete(:target_project) + + return unless target_project && + issue.can_move?(current_user, target_project) && + target_project != issue.project + + update(issue) + Issues::MoveService.new(project, current_user).execute(issue, target_project) + end + private def get_issue_if_allowed(project, iid) diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb index c7832c47e1a..9cdb9935bea 100644 --- a/app/services/quick_actions/interpret_service.rb +++ b/app/services/quick_actions/interpret_service.rb @@ -505,6 +505,24 @@ module QuickActions end end + desc 'Move this issue to another project.' + explanation do |path_to_project| + "Moves this issue to #{path_to_project}." + end + params 'path/to/project' + condition do + issuable.is_a?(Issue) && + issuable.persisted? && + current_user.can?(:"admin_#{issuable.to_ability_name}", project) + end + command :move do |target_project_path| + target_project = Project.find_by_full_path(target_project_path) + + if target_project.present? + @updates[:target_project] = target_project + end + end + def extract_users(params) return [] if params.nil? diff --git a/changelogs/unreleased/move-action.yml b/changelogs/unreleased/move-action.yml new file mode 100644 index 00000000000..65eceae3ef9 --- /dev/null +++ b/changelogs/unreleased/move-action.yml @@ -0,0 +1,4 @@ +--- +title: Allow users to move issues to other projects using a / command +merge_request: 13436 +author: Manolis Mavrofidis diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md index ce4dd4e99d5..6a5d2d40927 100644 --- a/doc/user/project/quick_actions.md +++ b/doc/user/project/quick_actions.md @@ -38,3 +38,4 @@ do. | `/award :emoji:` | Toggle award for :emoji: | | `/board_move ~column` | Move issue to column on the board | | `/duplicate #issue` | Closes this issue and marks it as a duplicate of another issue | +| `/move path/to/project` | Moves issue to another project | diff --git a/spec/features/issues/user_uses_slash_commands_spec.rb b/spec/features/issues/user_uses_slash_commands_spec.rb index 4b63cc844f3..9261acda9dc 100644 --- a/spec/features/issues/user_uses_slash_commands_spec.rb +++ b/spec/features/issues/user_uses_slash_commands_spec.rb @@ -155,5 +155,114 @@ feature 'Issues > User uses quick actions', js: true do end end end + + describe 'move the issue to another project' do + let(:issue) { create(:issue, project: project) } + + context 'when the project is valid', js: true do + let(:target_project) { create(:project, :public) } + + before do + target_project.team << [user, :master] + sign_in(user) + visit project_issue_path(project, issue) + end + + it 'moves the issue' do + write_note("/move #{target_project.full_path}") + + expect(page).to have_content 'Commands applied' + expect(issue.reload).to be_closed + + visit project_issue_path(target_project, issue) + + expect(page).to have_content 'Issues 1' + end + end + + context 'when the project is valid but the user not authorized', js: true do + let(:project_unauthorized) {create(:project, :public)} + + before do + sign_in(user) + visit project_issue_path(project, issue) + end + + it 'does not move the issue' do + write_note("/move #{project_unauthorized.full_path}") + + expect(page).not_to have_content 'Commands applied' + expect(issue.reload).to be_open + end + end + + context 'when the project is invalid', js: true do + before do + sign_in(user) + visit project_issue_path(project, issue) + end + + it 'does not move the issue' do + write_note("/move not/valid") + + expect(page).not_to have_content 'Commands applied' + expect(issue.reload).to be_open + end + end + + context 'when the user issues multiple commands', js: true do + let(:target_project) { create(:project, :public) } + let(:milestone) { create(:milestone, title: '1.0', project: project) } + let(:target_milestone) { create(:milestone, title: '1.0', project: target_project) } + let(:bug) { create(:label, project: project, title: 'bug') } + let(:wontfix) { create(:label, project: project, title: 'wontfix') } + let(:bug_target) { create(:label, project: target_project, title: 'bug') } + let(:wontfix_target) { create(:label, project: target_project, title: 'wontfix') } + + before do + target_project.team << [user, :master] + sign_in(user) + visit project_issue_path(project, issue) + end + + it 'applies the commands to both issues and moves the issue' do + write_note("/label ~#{bug.title} ~#{wontfix.title}\n/milestone %\"#{milestone.title}\"\n/move #{target_project.full_path}") + + expect(page).to have_content 'Commands applied' + expect(issue.reload).to be_closed + + visit project_issue_path(target_project, issue) + + expect(page).to have_content 'bug' + expect(page).to have_content 'wontfix' + expect(page).to have_content '1.0' + + visit project_issue_path(project, issue) + expect(page).to have_content 'Closed' + expect(page).to have_content 'bug' + expect(page).to have_content 'wontfix' + expect(page).to have_content '1.0' + end + + it 'moves the issue and applies the commands to both issues' do + write_note("/move #{target_project.full_path}\n/label ~#{bug.title} ~#{wontfix.title}\n/milestone %\"#{milestone.title}\"") + + expect(page).to have_content 'Commands applied' + expect(issue.reload).to be_closed + + visit project_issue_path(target_project, issue) + + expect(page).to have_content 'bug' + expect(page).to have_content 'wontfix' + expect(page).to have_content '1.0' + + visit project_issue_path(project, issue) + expect(page).to have_content 'Closed' + expect(page).to have_content 'bug' + expect(page).to have_content 'wontfix' + expect(page).to have_content '1.0' + end + end + end end end diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb index 34fb16edc84..2176469aba6 100644 --- a/spec/services/issues/update_service_spec.rb +++ b/spec/services/issues/update_service_spec.rb @@ -510,6 +510,26 @@ describe Issues::UpdateService, :mailer do end end + context 'move issue to another project' do + let(:target_project) { create(:project) } + + context 'valid project' do + before do + target_project.team << [user, :master] + end + + it 'calls the move service with the proper issue and project' do + move_stub = class_double("Issues::MoveService").as_stubbed_const + allow(Issues::MoveService).to receive(:new).and_return(move_stub) + allow(move_stub).to receive(:execute).with(issue, target_project).and_return(issue) + + expect(move_stub).to receive(:execute).with(issue, target_project) + + update_issue(target_project: target_project) + end + end + end + include_examples 'issuable update service' do let(:open_issuable) { issue } let(:closed_issuable) { create(:closed_issue, project: project) } diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb index 30fa0ee6873..6926ac85de3 100644 --- a/spec/services/quick_actions/interpret_service_spec.rb +++ b/spec/services/quick_actions/interpret_service_spec.rb @@ -1147,5 +1147,15 @@ describe QuickActions::InterpretService do expect(explanations).to eq(["Moves issue to ~#{bug.id} column in the board."]) end end + + describe 'move issue to another project command' do + let(:content) { '/move test/project' } + + it 'includes the project name' do + _, explanations = service.explain(content, issue) + + expect(explanations).to eq(["Moves this issue to test/project."]) + end + end end end |