Commit 7997bbbf authored by Clement Ho's avatar Clement Ho

Backport MR from EE

parent 7911f1c0
...@@ -468,8 +468,8 @@ GitLabDropdown = (function() { ...@@ -468,8 +468,8 @@ GitLabDropdown = (function() {
// Process the data to make sure rendered data // Process the data to make sure rendered data
// matches the correct layout // matches the correct layout
if (this.fullData && hasMultiSelect && this.options.processData) {
const inputValue = this.filterInput.val(); const inputValue = this.filterInput.val();
if (this.fullData && hasMultiSelect && this.options.processData && inputValue.length === 0) {
this.options.processData.call(this.options, inputValue, this.filteredFullData(), this.parseData.bind(this)); this.options.processData.call(this.options, inputValue, this.filteredFullData(), this.parseData.bind(this));
} }
...@@ -740,6 +740,12 @@ GitLabDropdown = (function() { ...@@ -740,6 +740,12 @@ GitLabDropdown = (function() {
$input.attr('id', this.options.inputId); $input.attr('id', this.options.inputId);
} }
if (this.options.multiSelect) {
Object.keys(selectedObject).forEach((attribute) => {
$input.attr(`data-${attribute}`, selectedObject[attribute]);
});
}
if (this.options.inputMeta) { if (this.options.inputMeta) {
$input.attr('data-meta', selectedObject[this.options.inputMeta]); $input.attr('data-meta', selectedObject[this.options.inputMeta]);
} }
......
...@@ -35,6 +35,7 @@ function UsersSelect(currentUser, els) { ...@@ -35,6 +35,7 @@ function UsersSelect(currentUser, els) {
options.showCurrentUser = $dropdown.data('current-user'); options.showCurrentUser = $dropdown.data('current-user');
options.todoFilter = $dropdown.data('todo-filter'); options.todoFilter = $dropdown.data('todo-filter');
options.todoStateFilter = $dropdown.data('todo-state-filter'); options.todoStateFilter = $dropdown.data('todo-state-filter');
options.perPage = $dropdown.data('per-page');
showNullUser = $dropdown.data('null-user'); showNullUser = $dropdown.data('null-user');
defaultNullUser = $dropdown.data('null-user-default'); defaultNullUser = $dropdown.data('null-user-default');
showMenuAbove = $dropdown.data('showMenuAbove'); showMenuAbove = $dropdown.data('showMenuAbove');
...@@ -214,7 +215,36 @@ function UsersSelect(currentUser, els) { ...@@ -214,7 +215,36 @@ function UsersSelect(currentUser, els) {
glDropdown.options.processData(term, users, callback); glDropdown.options.processData(term, users, callback);
}.bind(this)); }.bind(this));
}, },
processData: function(term, users, callback) { processData: function(term, data, callback) {
let users = data;
// Only show assigned user list when there is no search term
if ($dropdown.hasClass('js-multiselect') && term.length === 0) {
const selectedInputs = getSelectedUserInputs();
// Potential duplicate entries when dealing with issue board
// because issue board is also managed by vue
const selectedUsers = _.uniq(selectedInputs, false, a => a.value)
.filter((input) => {
const userId = parseInt(input.value, 10);
const inUsersArray = users.find(u => u.id === userId);
return !inUsersArray && userId !== 0;
})
.map((input) => {
const userId = parseInt(input.value, 10);
const { avatarUrl, avatar_url, name, username } = input.dataset;
return {
avatar_url: avatarUrl || avatar_url,
id: userId,
name,
username,
};
});
users = data.concat(selectedUsers);
}
let anyUser; let anyUser;
let index; let index;
let j; let j;
...@@ -645,7 +675,7 @@ UsersSelect.prototype.users = function(query, options, callback) { ...@@ -645,7 +675,7 @@ UsersSelect.prototype.users = function(query, options, callback) {
url: url, url: url,
data: { data: {
search: query, search: query,
per_page: 20, per_page: options.perPage || 20,
active: true, active: true,
project_id: options.projectId || null, project_id: options.projectId || null,
group_id: options.groupId || null, group_id: options.groupId || null,
......
...@@ -9,7 +9,7 @@ class AutocompleteController < ApplicationController ...@@ -9,7 +9,7 @@ class AutocompleteController < ApplicationController
@users = @users.where.not(id: params[:skip_users]) if params[:skip_users].present? @users = @users.where.not(id: params[:skip_users]) if params[:skip_users].present?
@users = @users.active @users = @users.active
@users = @users.reorder(:name) @users = @users.reorder(:name)
@users = @users.page(params[:page]) @users = @users.page(params[:page]).per(params[:per_page])
if params[:todo_filter].present? && current_user if params[:todo_filter].present? && current_user
@users = @users.todo_authors(current_user.id, params[:todo_state_filter]) @users = @users.todo_authors(current_user.id, params[:todo_state_filter])
......
...@@ -14,7 +14,10 @@ ...@@ -14,7 +14,10 @@
name: "issue[assignee_ids][]", name: "issue[assignee_ids][]",
":value" => "assignee.id", ":value" => "assignee.id",
"v-if" => "issue.assignees", "v-if" => "issue.assignees",
"v-for" => "assignee in issue.assignees" } "v-for" => "assignee in issue.assignees",
":data-avatar_url" => "assignee.avatar",
":data-name" => "assignee.name",
":data-username" => "assignee.username" }
.dropdown .dropdown
%button.dropdown-menu-toggle.js-user-search.js-author-search.js-multiselect.js-save-user-data.js-issue-board-sidebar{ type: "button", ref: "assigneeDropdown", data: { toggle: "dropdown", field_name: "issue[assignee_ids][]", first_user: (current_user.username if current_user), current_user: "true", project_id: @project.id, null_user: "true", multi_select: "true", 'max-select' => 1, dropdown: { header: 'Assignee' } }, %button.dropdown-menu-toggle.js-user-search.js-author-search.js-multiselect.js-save-user-data.js-issue-board-sidebar{ type: "button", ref: "assigneeDropdown", data: { toggle: "dropdown", field_name: "issue[assignee_ids][]", first_user: (current_user.username if current_user), current_user: "true", project_id: @project.id, null_user: "true", multi_select: "true", 'max-select' => 1, dropdown: { header: 'Assignee' } },
":data-issuable-id" => "issue.id", ":data-issuable-id" => "issue.id",
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
.selectbox.hide-collapsed .selectbox.hide-collapsed
- issuable.assignees.each do |assignee| - issuable.assignees.each do |assignee|
= hidden_field_tag "#{issuable.to_ability_name}[assignee_ids][]", assignee.id, id: nil = hidden_field_tag "#{issuable.to_ability_name}[assignee_ids][]", assignee.id, id: nil, data: { avatar_url: assignee.avatar_url, name: assignee.name, username: assignee.username }
- 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 } }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
.col-sm-10{ class: ("col-lg-8" if has_due_date) } .col-sm-10{ class: ("col-lg-8" if has_due_date) }
.issuable-form-select-holder.selectbox .issuable-form-select-holder.selectbox
- issuable.assignees.each do |assignee| - issuable.assignees.each do |assignee|
= hidden_field_tag "#{issuable.to_ability_name}[assignee_ids][]", assignee.id, id: nil, data: { meta: assignee.name } = hidden_field_tag "#{issuable.to_ability_name}[assignee_ids][]", assignee.id, id: nil, data: { meta: assignee.name, avatar_url: assignee.avatar_url, name: assignee.name, username: assignee.username }
- if issuable.assignees.length === 0 - if issuable.assignees.length === 0
= hidden_field_tag "#{issuable.to_ability_name}[assignee_ids][]", 0, id: nil, data: { meta: '' } = hidden_field_tag "#{issuable.to_ability_name}[assignee_ids][]", 0, id: nil, data: { meta: '' }
......
...@@ -97,6 +97,20 @@ describe AutocompleteController do ...@@ -97,6 +97,20 @@ describe AutocompleteController do
it { expect(body.size).to eq User.count } it { expect(body.size).to eq User.count }
end end
context 'limited users per page' do
let(:per_page) { 2 }
before do
sign_in(user)
get(:users, per_page: per_page)
end
let(:body) { JSON.parse(response.body) }
it { expect(body).to be_kind_of(Array) }
it { expect(body.size).to eq per_page }
end
context 'unauthenticated user' do context 'unauthenticated user' do
let(:public_project) { create(:project, :public) } let(:public_project) { create(:project, :public) }
let(:body) { JSON.parse(response.body) } let(:body) { JSON.parse(response.body) }
......
...@@ -3,6 +3,7 @@ require 'rails_helper' ...@@ -3,6 +3,7 @@ require 'rails_helper'
describe 'New/edit issue', :feature, :js do describe 'New/edit issue', :feature, :js do
include GitlabRoutingHelper include GitlabRoutingHelper
include ActionView::Helpers::JavaScriptHelper include ActionView::Helpers::JavaScriptHelper
include FormHelper
let!(:project) { create(:project) } let!(:project) { create(:project) }
let!(:user) { create(:user)} let!(:user) { create(:user)}
...@@ -23,6 +24,67 @@ describe 'New/edit issue', :feature, :js do ...@@ -23,6 +24,67 @@ describe 'New/edit issue', :feature, :js do
visit new_namespace_project_issue_path(project.namespace, project) visit new_namespace_project_issue_path(project.namespace, project)
end end
describe 'shorten users API pagination limit' do
before do
allow_any_instance_of(FormHelper).to receive(:issue_dropdown_options).and_wrap_original do |original, *args|
issuable = *args[0]
has_multiple_assignees = *args[1]
options = {
toggle_class: 'js-user-search js-assignee-search js-multiselect js-save-user-data',
title: 'Select assignee',
filter: true,
dropdown_class: 'dropdown-menu-user dropdown-menu-selectable dropdown-menu-assignee',
placeholder: 'Search users',
data: {
per_page: 1,
null_user: true,
current_user: true,
project_id: project.try(:id),
field_name: "issue[assignee_ids][]",
default_label: 'Assignee',
'max-select': 1,
'dropdown-header': 'Assignee',
multi_select: true,
'input-meta': 'name',
'always-show-selectbox': true,
}
}
if has_multiple_assignees
options[:title] = 'Select assignee(s)'
options[:data][:'dropdown-header'] = 'Assignee(s)'
options[:data].delete(:'max-select')
end
options
end
visit new_namespace_project_issue_path(project.namespace, project)
click_button 'Unassigned'
wait_for_requests
end
it 'should display selected users even if they are not part of the original API call' do
find('.dropdown-input-field').native.send_keys user2.name
page.within '.dropdown-menu-user' do
expect(page).to have_content user2.name
click_link user2.name
end
find('.js-dropdown-input-clear').click
page.within '.dropdown-menu-user' do
expect(page).to have_content user.name
expect(find('.dropdown-menu-user a.is-active').first(:xpath, '..')['data-user-id']).to eq(user2.id.to_s)
end
end
end
describe 'single assignee' do describe 'single assignee' do
before do before do
click_button 'Unassigned' click_button 'Unassigned'
......
...@@ -57,6 +57,23 @@ feature 'Issue Sidebar', feature: true do ...@@ -57,6 +57,23 @@ feature 'Issue Sidebar', feature: true do
expect(page.find('.dropdown-menu-user-link.is-active')).to have_content(user.name) expect(page.find('.dropdown-menu-user-link.is-active')).to have_content(user.name)
end end
end end
it 'keeps your filtered term after filtering and dismissing the dropdown' do
find('.dropdown-input-field').native.send_keys user2.name
wait_for_requests
page.within '.dropdown-menu-user' do
expect(page).not_to have_content 'Unassigned'
click_link user2.name
end
find('.js-right-sidebar').click
find('.block.assignee .edit-link').click
expect(page.all('.dropdown-menu-user li').length).to eq(1)
expect(find('.dropdown-input-field').value).to eq(user2.name)
end
end end
context 'as a allowed user' do context 'as a allowed user' 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