Commit f938f944 authored by Sean McGivern's avatar Sean McGivern

Merge branch 'fixes_for_multiple_issue_assignees' into 'master'

Fix for Follow-up from "Backport of Multiple Assignees feature

Closes #31888

See merge request !11178
parents 20987f4f 22722659
...@@ -60,17 +60,24 @@ module IssuableActions ...@@ -60,17 +60,24 @@ module IssuableActions
end end
def bulk_update_params def bulk_update_params
params.require(:update).permit( permitted_keys = [
:issuable_ids, :issuable_ids,
:assignee_id, :assignee_id,
:milestone_id, :milestone_id,
:state_event, :state_event,
:subscription_event, :subscription_event,
assignee_ids: [],
label_ids: [], label_ids: [],
add_label_ids: [], add_label_ids: [],
remove_label_ids: [] remove_label_ids: []
) ]
if resource_name == 'issue'
permitted_keys << { assignee_ids: [] }
else
permitted_keys.unshift(:assignee_id)
end
params.require(:update).permit(permitted_keys)
end end
def resource_name def resource_name
......
...@@ -67,9 +67,10 @@ module IssuablesHelper ...@@ -67,9 +67,10 @@ module IssuablesHelper
end end
def users_dropdown_label(selected_users) def users_dropdown_label(selected_users)
if selected_users.length == 0 case selected_users.length
when 0
"Unassigned" "Unassigned"
elsif selected_users.length == 1 when 1
selected_users[0].name selected_users[0].name
else else
"#{selected_users[0].name} + #{selected_users.length - 1} more" "#{selected_users[0].name} + #{selected_users.length - 1} more"
......
...@@ -7,7 +7,7 @@ module Issuable ...@@ -7,7 +7,7 @@ module Issuable
ids = params.delete(:issuable_ids).split(",") ids = params.delete(:issuable_ids).split(",")
items = model_class.where(id: ids) items = model_class.where(id: ids)
%i(state_event milestone_id assignee_id assignee_ids add_label_ids remove_label_ids subscription_event).each do |key| permitted_attrs(type).each do |key|
params.delete(key) unless params[key].present? params.delete(key) unless params[key].present?
end end
...@@ -26,5 +26,17 @@ module Issuable ...@@ -26,5 +26,17 @@ module Issuable
success: !items.count.zero? success: !items.count.zero?
} }
end end
private
def permitted_attrs(type)
attrs = %i(state_event milestone_id assignee_id assignee_ids add_label_ids remove_label_ids subscription_event)
if type == 'issue'
attrs.push(:assignee_ids)
else
attrs.push(:assignee_id)
end
end
end end
end end
...@@ -79,7 +79,7 @@ module SystemNoteService ...@@ -79,7 +79,7 @@ module SystemNoteService
text_parts.join(' and ') text_parts.join(' and ')
elsif old_assignees.any? elsif old_assignees.any?
"removed all assignees" "removed assignee"
elsif issue.assignees.any? elsif issue.assignees.any?
"assigned to #{issue.assignees.map(&:to_reference).to_sentence}" "assigned to #{issue.assignees.map(&:to_reference).to_sentence}"
end end
......
- max_render = 3 - max_render = 3
- max = [max_render, issue.assignees.length].min - max = [max_render, issue.assignees.length].min
- issue.assignees.each_with_index do |assignee, index| - issue.assignees.take(max).each do |assignee|
- if index < max
= link_to_member(@project, assignee, name: false, title: "Assigned to :name") = link_to_member(@project, assignee, name: false, title: "Assigned to :name")
- if issue.assignees.length > max_render - if issue.assignees.length > max_render
......
- if issuable.instance_of?(Issue) - if issuable.is_a?(Issue)
#js-vue-sidebar-assignees{ data: { field: "#{issuable.to_ability_name}[assignee_ids]" } } #js-vue-sidebar-assignees{ data: { field: "#{issuable.to_ability_name}[assignee_ids]" } }
- else - else
.sidebar-collapsed-icon.sidebar-collapsed-user{ data: { toggle: "tooltip", placement: "left", container: "body" }, title: (issuable.assignee.name if issuable.assignee) } .sidebar-collapsed-icon.sidebar-collapsed-user{ data: { toggle: "tooltip", placement: "left", container: "body" }, title: (issuable.assignee.name if issuable.assignee) }
...@@ -33,17 +33,17 @@ ...@@ -33,17 +33,17 @@
- options = { toggle_class: 'js-user-search js-author-search', title: 'Assign to', filter: true, dropdown_class: 'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author', placeholder: 'Search users', data: { first_user: (current_user.username if current_user), current_user: true, project_id: (@project.id if @project), author_id: issuable.author_id, field_name: "#{issuable.to_ability_name}[assignee_ids][]", issue_update: issuable_json_path(issuable), ability_name: issuable.to_ability_name, null_user: true } } - options = { toggle_class: 'js-user-search js-author-search', title: 'Assign to', filter: true, dropdown_class: 'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author', placeholder: 'Search users', data: { first_user: (current_user.username if current_user), current_user: true, project_id: (@project.id if @project), author_id: issuable.author_id, field_name: "#{issuable.to_ability_name}[assignee_ids][]", issue_update: issuable_json_path(issuable), ability_name: issuable.to_ability_name, null_user: true } }
- if issuable.instance_of?(Issue)
- if issuable.assignees.length == 0
= hidden_field_tag "#{issuable.to_ability_name}[assignee_ids][]", 0, id: nil
- title = 'Select assignee' - title = 'Select assignee'
- if issuable.is_a?(Issue)
- unless issuable.assignees.any?
= hidden_field_tag "#{issuable.to_ability_name}[assignee_ids][]", 0, id: nil
- options[:toggle_class] += ' js-multiselect js-save-user-data' - options[:toggle_class] += ' js-multiselect js-save-user-data'
- options[:data][:field_name] = "#{issuable.to_ability_name}[assignee_ids][]" - data = { field_name: "#{issuable.to_ability_name}[assignee_ids][]" }
- options[:data][:multi_select] = true - data[:multi_select] = true
- options[:data]['dropdown-title'] = title - data['dropdown-title'] = title
- options[:data]['dropdown-header'] = 'Assignee' - data['dropdown-header'] = 'Assignee'
- options[:data]['max-select'] = 1 - data['max-select'] = 1
- else - options[:data].merge!(data)
- title = 'Select assignee'
= dropdown_tag(title, options: options) = dropdown_tag(title, options: options)
- issue = issuable - issue = issuable
- assignees = issue.assignees
.block.assignee .block.assignee
.sidebar-collapsed-icon.sidebar-collapsed-user{ data: { toggle: "tooltip", placement: "left", container: "body" }, title: (issuable.assignee_list) } .sidebar-collapsed-icon.sidebar-collapsed-user{ data: { toggle: "tooltip", placement: "left", container: "body" }, title: (issuable.assignee_list) }
- if issue.assignees.any? - if assignees.any?
- issue.assignees.each do |assignee| - assignees.each do |assignee|
= link_to_member(@project, assignee, size: 24) = link_to_member(@project, assignee, size: 24)
- else - else
= icon('user', 'aria-hidden': 'true') = icon('user', 'aria-hidden': 'true')
...@@ -12,8 +13,8 @@ ...@@ -12,8 +13,8 @@
- if can_edit_issuable - if can_edit_issuable
= link_to 'Edit', '#', class: 'edit-link pull-right' = link_to 'Edit', '#', class: 'edit-link pull-right'
.value.hide-collapsed .value.hide-collapsed
- if issue.assignees.any? - if assignees.any?
- issue.assignees.each do |assignee| - assignees.each do |assignee|
= link_to_member(@project, assignee, size: 32, extra_class: 'bold') do = link_to_member(@project, assignee, size: 32, extra_class: 'bold') do
%span.username %span.username
= assignee.to_reference = assignee.to_reference
......
...@@ -100,7 +100,7 @@ Example response: ...@@ -100,7 +100,7 @@ Example response:
] ]
``` ```
**Note**: `assignee` column is deprecated, it shows the first assignee only. **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
## List group issues ## List group issues
...@@ -192,7 +192,7 @@ Example response: ...@@ -192,7 +192,7 @@ Example response:
] ]
``` ```
**Note**: `assignee` column is deprecated, it shows the first assignee only. **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
## List project issues ## List project issues
...@@ -284,7 +284,7 @@ Example response: ...@@ -284,7 +284,7 @@ Example response:
] ]
``` ```
**Note**: `assignee` column is deprecated, it shows the first assignee only. **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
## Single issue ## Single issue
...@@ -359,7 +359,7 @@ Example response: ...@@ -359,7 +359,7 @@ Example response:
} }
``` ```
**Note**: `assignee` column is deprecated, it shows the first assignee only. **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
## New issue ## New issue
...@@ -375,7 +375,7 @@ POST /projects/:id/issues ...@@ -375,7 +375,7 @@ POST /projects/:id/issues
| `title` | string | yes | The title of an issue | | `title` | string | yes | The title of an issue |
| `description` | string | no | The description of an issue | | `description` | string | no | The description of an issue |
| `confidential` | boolean | no | Set an issue to be confidential. Default is `false`. | | `confidential` | boolean | no | Set an issue to be confidential. Default is `false`. |
| `assignee_ids` | Array[integer] | no | The ID of a user to assign issue | | `assignee_ids` | Array[integer] | no | The ID of the users to assign issue |
| `milestone_id` | integer | no | The ID of a milestone to assign issue | | `milestone_id` | integer | no | The ID of a milestone to assign issue |
| `labels` | string | no | Comma-separated label names for an issue | | `labels` | string | no | Comma-separated label names for an issue |
| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. `2016-03-11T03:45:40Z` (requires admin or project owner rights) | | `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. `2016-03-11T03:45:40Z` (requires admin or project owner rights) |
...@@ -421,7 +421,7 @@ Example response: ...@@ -421,7 +421,7 @@ Example response:
} }
``` ```
**Note**: `assignee` column is deprecated, it shows the first assignee only. **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
## Edit issue ## Edit issue
...@@ -439,7 +439,7 @@ PUT /projects/:id/issues/:issue_iid ...@@ -439,7 +439,7 @@ PUT /projects/:id/issues/:issue_iid
| `title` | string | no | The title of an issue | | `title` | string | no | The title of an issue |
| `description` | string | no | The description of an issue | | `description` | string | no | The description of an issue |
| `confidential` | boolean | no | Updates an issue to be confidential | | `confidential` | boolean | no | Updates an issue to be confidential |
| `assignee_ids` | Array[integer] | no | The ID of a user to assign the issue to | | `assignee_ids` | Array[integer] | no | The ID of the users to assign the issue to |
| `milestone_id` | integer | no | The ID of a milestone to assign the issue to | | `milestone_id` | integer | no | The ID of a milestone to assign the issue to |
| `labels` | string | no | Comma-separated label names for an issue | | `labels` | string | no | Comma-separated label names for an issue |
| `state_event` | string | no | The state event of an issue. Set `close` to close the issue and `reopen` to reopen it | | `state_event` | string | no | The state event of an issue. Set `close` to close the issue and `reopen` to reopen it |
...@@ -484,7 +484,7 @@ Example response: ...@@ -484,7 +484,7 @@ Example response:
} }
``` ```
**Note**: `assignee` column is deprecated, it shows the first assignee only. **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
## Delete an issue ## Delete an issue
...@@ -570,7 +570,7 @@ Example response: ...@@ -570,7 +570,7 @@ Example response:
} }
``` ```
**Note**: `assignee` column is deprecated, it shows the first assignee only. **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
## Subscribe to an issue ## Subscribe to an issue
...@@ -635,7 +635,7 @@ Example response: ...@@ -635,7 +635,7 @@ Example response:
} }
``` ```
**Note**: `assignee` column is deprecated, it shows the first assignee only. **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
## Unsubscribe from an issue ## Unsubscribe from an issue
...@@ -757,7 +757,7 @@ Example response: ...@@ -757,7 +757,7 @@ Example response:
} }
``` ```
**Note**: `assignee` column is deprecated, it shows the first assignee only. **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
## Set a time estimate for an issue ## Set a time estimate for an issue
......
...@@ -2,11 +2,11 @@ module API ...@@ -2,11 +2,11 @@ module API
module Helpers module Helpers
module CommonHelpers module CommonHelpers
def convert_parameters_from_legacy_format(params) def convert_parameters_from_legacy_format(params)
params.tap do |params|
if params[:assignee_id].present? if params[:assignee_id].present?
params[:assignee_ids] = [params.delete(:assignee_id)] params[:assignee_ids] = [params.delete(:assignee_id)]
end end
end
params
end end
end end
end end
......
...@@ -1124,7 +1124,7 @@ describe API::Issues do ...@@ -1124,7 +1124,7 @@ describe API::Issues do
end end
context 'CE restrictions' do context 'CE restrictions' do
it 'updates an issue with several assignee but only one has been applied' do it 'updates an issue with several assignees but only one has been applied' do
put api("/projects/#{project.id}/issues/#{issue.iid}", user), put api("/projects/#{project.id}/issues/#{issue.iid}", user),
assignee_ids: [user2.id, guest.id] assignee_ids: [user2.id, guest.id]
......
...@@ -62,7 +62,7 @@ describe Issuable::BulkUpdateService, services: true do ...@@ -62,7 +62,7 @@ describe Issuable::BulkUpdateService, services: true do
expect(result[:count]).to eq(1) expect(result[:count]).to eq(1)
end end
it 'updates the assignee to the use ID passed' do it 'updates the assignee to the user ID passed' do
assignee = create(:user) assignee = create(:user)
project.team << [assignee, :developer] project.team << [assignee, :developer]
...@@ -100,7 +100,7 @@ describe Issuable::BulkUpdateService, services: true do ...@@ -100,7 +100,7 @@ describe Issuable::BulkUpdateService, services: true do
expect(result[:count]).to eq(1) expect(result[:count]).to eq(1)
end end
it 'updates the assignee to the use ID passed' do it 'updates the assignee to the user ID passed' do
assignee = create(:user) assignee = create(:user)
project.team << [assignee, :developer] project.team << [assignee, :developer]
expect { bulk_update(issue, assignee_ids: [assignee.id]) } expect { bulk_update(issue, assignee_ids: [assignee.id]) }
......
...@@ -178,7 +178,7 @@ describe SystemNoteService, services: true do ...@@ -178,7 +178,7 @@ describe SystemNoteService, services: true do
end end
it 'builds a correct phrase when assignee removed' do it 'builds a correct phrase when assignee removed' do
expect(build_note([assignee1], [])).to eq 'removed all assignees' expect(build_note([assignee1], [])).to eq 'removed assignee'
end end
it 'builds a correct phrase when assignees changed' do it 'builds a correct phrase when assignees changed' do
......
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