Commit 0fd3ed99 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch '6-6-5-patch' into '6-6-stable'

6.6.5 patch

* adds ability to reopen mr
* adds ability to remove issue assignee
* removes close button from diff comment form
parents 42e34aec e9358f5a
v 6.6.5
- Added option to remove issue assignee on project issue page and issue edit page (Jason Blanchard)
v 6.6.4 v 6.6.4
- Add missing html escape for highlighted code blocks in comments, issues - Add missing html escape for highlighted code blocks in comments, issues
......
...@@ -10,6 +10,16 @@ ...@@ -10,6 +10,16 @@
query: (query) -> query: (query) ->
Api.projectUsers project_id, query.term, (users) -> Api.projectUsers project_id, query.term, (users) ->
data = { results: users } data = { results: users }
nullUser = {
name: 'Unassigned',
avatar: null,
username: 'none',
id: ''
}
data.results.unshift(nullUser)
query.callback(data) query.callback(data)
initSelection: (element, callback) -> initSelection: (element, callback) ->
...@@ -35,8 +45,13 @@ ...@@ -35,8 +45,13 @@
else else
avatar = gon.relative_url_root + "/assets/no_avatar.png" avatar = gon.relative_url_root + "/assets/no_avatar.png"
if user.id == ''
avatarMarkup = ''
else
avatarMarkup = "<div class='user-image'><img class='avatar s24' src='#{avatar}'></div>"
"<div class='user-result'> "<div class='user-result'>
<div class='user-image'><img class='avatar s24' src='#{avatar}'></div> #{avatarMarkup}
<div class='user-name'>#{user.name}</div> <div class='user-name'>#{user.name}</div>
<div class='user-username'>#{user.username}</div> <div class='user-username'>#{user.username}</div>
</div>" </div>"
......
...@@ -89,3 +89,11 @@ ...@@ -89,3 +89,11 @@
.merge-request-form-info { .merge-request-form-info {
padding-top: 15px; padding-top: 15px;
} }
// hide mr close link for inline diff comment form
.merge-request {
.file .close-mr-link,
.file .reopen-mr-link {
display: none;
}
}
...@@ -131,7 +131,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -131,7 +131,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
def automerge def automerge
return access_denied! unless allowed_to_merge? return access_denied! unless allowed_to_merge?
if @merge_request.opened? && @merge_request.can_be_merged? if @merge_request.open? && @merge_request.can_be_merged?
@merge_request.should_remove_source_branch = params[:should_remove_source_branch] @merge_request.should_remove_source_branch = params[:should_remove_source_branch]
@merge_request.automerge!(current_user, params[:merge_commit_message]) @merge_request.automerge!(current_user, params[:merge_commit_message])
@status = true @status = true
...@@ -226,7 +226,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -226,7 +226,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@merge_request_diff = @merge_request.merge_request_diff @merge_request_diff = @merge_request.merge_request_diff
@allowed_to_merge = allowed_to_merge? @allowed_to_merge = allowed_to_merge?
@show_merge_controls = @merge_request.opened? && @commits.any? && @allowed_to_merge @show_merge_controls = @merge_request.open? && @commits.any? && @allowed_to_merge
end end
def allowed_to_merge? def allowed_to_merge?
......
...@@ -23,7 +23,8 @@ module Issuable ...@@ -23,7 +23,8 @@ module Issuable
scope :assigned, -> { where("assignee_id IS NOT NULL") } scope :assigned, -> { where("assignee_id IS NOT NULL") }
scope :unassigned, -> { where("assignee_id IS NULL") } scope :unassigned, -> { where("assignee_id IS NULL") }
scope :of_projects, ->(ids) { where(project_id: ids) } scope :of_projects, ->(ids) { where(project_id: ids) }
scope :opened, -> { with_state(:opened, :reopened) }
scope :closed, -> { with_state(:closed) }
delegate :name, delegate :name,
:email, :email,
......
...@@ -28,8 +28,6 @@ class Issue < ActiveRecord::Base ...@@ -28,8 +28,6 @@ class Issue < ActiveRecord::Base
scope :of_group, ->(group) { where(project_id: group.project_ids) } scope :of_group, ->(group) { where(project_id: group.project_ids) }
scope :of_user_team, ->(team) { where(project_id: team.project_ids, assignee_id: team.member_ids) } scope :of_user_team, ->(team) { where(project_id: team.project_ids, assignee_id: team.member_ids) }
scope :opened, -> { with_state(:opened, :reopened) }
scope :closed, -> { with_state(:closed) }
attr_accessible :title, :assignee_id, :position, :description, attr_accessible :title, :assignee_id, :position, :description,
:milestone_id, :label_list, :author_id_of_changes, :milestone_id, :label_list, :author_id_of_changes,
...@@ -50,9 +48,7 @@ class Issue < ActiveRecord::Base ...@@ -50,9 +48,7 @@ class Issue < ActiveRecord::Base
end end
state :opened state :opened
state :reopened state :reopened
state :closed state :closed
end end
......
...@@ -100,8 +100,6 @@ class MergeRequest < ActiveRecord::Base ...@@ -100,8 +100,6 @@ class MergeRequest < ActiveRecord::Base
scope :of_group, ->(group) { where("source_project_id in (:group_project_ids) OR target_project_id in (:group_project_ids)", group_project_ids: group.project_ids) } scope :of_group, ->(group) { where("source_project_id in (:group_project_ids) OR target_project_id in (:group_project_ids)", group_project_ids: group.project_ids) }
scope :of_user_team, ->(team) { where("(source_project_id in (:team_project_ids) OR target_project_id in (:team_project_ids) AND assignee_id in (:team_member_ids))", team_project_ids: team.project_ids, team_member_ids: team.member_ids) } scope :of_user_team, ->(team) { where("(source_project_id in (:team_project_ids) OR target_project_id in (:team_project_ids) AND assignee_id in (:team_member_ids))", team_project_ids: team.project_ids, team_member_ids: team.member_ids) }
scope :opened, -> { with_state(:opened) }
scope :closed, -> { with_state(:closed) }
scope :merged, -> { with_state(:merged) } scope :merged, -> { with_state(:merged) }
scope :by_branch, ->(branch_name) { where("(source_branch LIKE :branch) OR (target_branch LIKE :branch)", branch: branch_name) } scope :by_branch, ->(branch_name) { where("(source_branch LIKE :branch) OR (target_branch LIKE :branch)", branch: branch_name) }
scope :cared, ->(user) { where('assignee_id = :user OR author_id = :user', user: user.id) } scope :cared, ->(user) { where('assignee_id = :user OR author_id = :user', user: user.id) }
...@@ -160,6 +158,10 @@ class MergeRequest < ActiveRecord::Base ...@@ -160,6 +158,10 @@ class MergeRequest < ActiveRecord::Base
MergeRequests::AutoMergeService.new.execute(self, current_user, commit_message) MergeRequests::AutoMergeService.new.execute(self, current_user, commit_message)
end end
def open?
opened? || reopened?
end
def mr_and_commit_notes def mr_and_commit_notes
# Fetch comments only from last 100 commits # Fetch comments only from last 100 commits
commits_for_notes_limit = 100 commits_for_notes_limit = 100
......
...@@ -22,6 +22,8 @@ class MergeRequestObserver < ActivityObserver ...@@ -22,6 +22,8 @@ class MergeRequestObserver < ActivityObserver
create_event(merge_request, Event::REOPENED) create_event(merge_request, Event::REOPENED)
create_note(merge_request) create_note(merge_request)
execute_hooks(merge_request) execute_hooks(merge_request)
merge_request.reload_code
merge_request.mark_as_unchecked
end end
def after_update(merge_request) def after_update(merge_request)
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
= render "projects/merge_requests/show/mr_title" = render "projects/merge_requests/show/mr_title"
= render "projects/merge_requests/show/how_to_merge" = render "projects/merge_requests/show/how_to_merge"
= render "projects/merge_requests/show/mr_box" = render "projects/merge_requests/show/mr_box"
- if @merge_request.opened? - if @merge_request.open?
- if @merge_request.source_branch_exists? && @merge_request.target_branch_exists? - if @merge_request.source_branch_exists? && @merge_request.target_branch_exists?
= render "projects/merge_requests/show/mr_accept" = render "projects/merge_requests/show/mr_accept"
- else - else
...@@ -24,9 +24,10 @@ ...@@ -24,9 +24,10 @@
- content_for :note_actions do - content_for :note_actions do
- if can?(current_user, :modify_merge_request, @merge_request) - if can?(current_user, :modify_merge_request, @merge_request)
- unless @merge_request.closed? - unless @merge_request.closed? || @merge_request.merged?
= link_to 'Close', project_merge_request_path(@project, @merge_request, merge_request: {state_event: :close }), method: :put, class: "btn grouped btn-close", title: "Close merge request" = link_to 'Close', project_merge_request_path(@project, @merge_request, merge_request: {state_event: :close }), method: :put, class: "btn grouped btn-close close-mr-link", title: "Close merge request"
- if @merge_request.closed?
= link_to 'Reopen', project_merge_request_path(@project, @merge_request, merge_request: {state_event: :reopen }), method: :put, class: "btn grouped btn-reopen reopen-mr-link", title: "Close merge request"
.notes.tab-content.voting_notes#notes{ class: (controller.action_name == 'show') ? "" : "hide" } .notes.tab-content.voting_notes#notes{ class: (controller.action_name == 'show') ? "" : "hide" }
= render "projects/notes/notes_with_form" = render "projects/notes/notes_with_form"
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
%i.icon-ok %i.icon-ok
Merged by #{link_to_member(@project, @merge_request.merge_event.author)} Merged by #{link_to_member(@project, @merge_request.merge_event.author)}
#{time_ago_with_tooltip(@merge_request.merge_event.created_at)}. #{time_ago_with_tooltip(@merge_request.merge_event.created_at)}.
- if !@closes_issues.empty? && @merge_request.opened? - if !@closes_issues.empty? && @merge_request.open?
.alert.alert-info.alert-info .alert.alert-info.alert-info
%span %span
%i.icon-ok %i.icon-ok
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
%span.pull-right %span.pull-right
- if can?(current_user, :modify_merge_request, @merge_request) - if can?(current_user, :modify_merge_request, @merge_request)
- if @merge_request.opened? - if @merge_request.open?
.left.btn-group .btn-group.pull-left
%a.btn.grouped.dropdown-toggle{ data: {toggle: :dropdown} } %a.btn.grouped.dropdown-toggle{ data: {toggle: :dropdown} }
%i.icon-download-alt %i.icon-download-alt
Download as Download as
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
= link_to edit_project_merge_request_path(@project, @merge_request), class: "btn grouped", id:"edit_merge_request" do = link_to edit_project_merge_request_path(@project, @merge_request), class: "btn grouped", id:"edit_merge_request" do
%i.icon-edit %i.icon-edit
Edit Edit
- if @merge_request.closed?
= link_to 'Reopen', project_merge_request_path(@project, @merge_request, merge_request: {state_event: :reopen }), method: :put, class: "btn grouped btn-reopen reopen-mr-link", title: "Close merge request"
.votes-holder.hidden-sm.hidden-xs .votes-holder.hidden-sm.hidden-xs
#votes= render 'votes/votes_block', votable: @merge_request #votes= render 'votes/votes_block', votable: @merge_request
......
...@@ -29,6 +29,13 @@ Feature: Project Merge Requests ...@@ -29,6 +29,13 @@ Feature: Project Merge Requests
And I click link "Close" And I click link "Close"
Then I should see closed merge request "Bug NS-04" Then I should see closed merge request "Bug NS-04"
Scenario: I reopen merge request page
Given I click link "Bug NS-04"
And I click link "Close"
Then I should see closed merge request "Bug NS-04"
When I click link "Reopen"
Then I should see reopened merge request "Bug NS-04"
Scenario: I submit new unassigned merge request Scenario: I submit new unassigned merge request
Given I click link "New Merge Request" Given I click link "New Merge Request"
And I submit new merge request "Wiki Feature" And I submit new merge request "Wiki Feature"
......
...@@ -170,6 +170,18 @@ class ProjectMergeRequests < Spinach::FeatureSteps ...@@ -170,6 +170,18 @@ class ProjectMergeRequests < Spinach::FeatureSteps
end end
end end
step 'I click link "Reopen"' do
within '.page-title' do
click_link "Reopen"
end
end
step 'I should see reopened merge request "Bug NS-04"' do
within '.state-label' do
page.should have_content "Open"
end
end
def project def project
@project ||= Project.find_by!(name: "Shop") @project ||= Project.find_by!(name: "Shop")
end end
......
...@@ -43,6 +43,31 @@ describe "Issues" do ...@@ -43,6 +43,31 @@ describe "Issues" do
page.should have_content project.name page.should have_content project.name
end end
end end
end
describe "Editing issue assignee" do
let!(:issue) do
create(:issue,
author: @user,
assignee: @user,
project: project)
end
it 'allows user to select unasigned', :js => true do
visit edit_project_issue_path(project, issue)
page.should have_content "Assign to #{@user.name}"
page.first('#s2id_issue_assignee_id').click
sleep 2 # wait for ajax stuff to complete
page.first('.user-result').click
click_button "Save changes"
page.should have_content "Assignee: Select assignee"
issue.reload.assignee.should be_nil
end
end end
describe "Filter issue" do describe "Filter issue" do
...@@ -245,6 +270,28 @@ describe "Issues" do ...@@ -245,6 +270,28 @@ describe "Issues" do
page.should have_content milestone.title page.should have_content milestone.title
end end
end end
describe 'removing assignee' do
let(:user2) { create(:user) }
before :each do
issue.assignee = user2
issue.save
end
it 'allows user to remove assignee', :js => true do
visit project_issue_path(project, issue)
page.should have_content "Assignee: #{user2.name}"
page.first('#s2id_issue_assignee_id').click
sleep 2 # wait for ajax stuff to complete
page.first('.user-result').click
page.should have_content "Assignee: Unassigned"
sleep 2 # wait for ajax stuff to complete
issue.reload.assignee.should be_nil
end
end
end end
def first_issue def first_issue
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment