Commit 48eca938 authored by Clement Ho's avatar Clement Ho

[skip ci] add multiple assignees to create issue page

parent 89ab47cd
...@@ -732,6 +732,10 @@ GitLabDropdown = (function() { ...@@ -732,6 +732,10 @@ GitLabDropdown = (function() {
$input.attr('id', this.options.inputId); $input.attr('id', this.options.inputId);
} }
if (this.options.inputMeta) {
$input.attr('data-meta', selectedObject[this.options.inputMeta]);
}
return this.dropdown.before($input); return this.dropdown.before($input);
}; };
......
...@@ -52,9 +52,8 @@ import eventHub from './sidebar/event_hub'; ...@@ -52,9 +52,8 @@ import eventHub from './sidebar/event_hub';
$collapsedSidebar = $block.find('.sidebar-collapsed-user'); $collapsedSidebar = $block.find('.sidebar-collapsed-user');
$loading = $block.find('.block-loading').fadeOut(); $loading = $block.find('.block-loading').fadeOut();
if ($block[0]) {
$block[0].addEventListener('assignYourself', () => { var assignYourself = function () {
// Remove unassigned selected from the DOM
const unassignedSelected = $dropdown.closest('.selectbox') const unassignedSelected = $dropdown.closest('.selectbox')
.find("input[name='" + ($dropdown.data('field-name')) + "'][value=0]"); .find("input[name='" + ($dropdown.data('field-name')) + "'][value=0]");
...@@ -66,26 +65,73 @@ import eventHub from './sidebar/event_hub'; ...@@ -66,26 +65,73 @@ import eventHub from './sidebar/event_hub';
const input = document.createElement('input'); const input = document.createElement('input');
input.type = 'hidden'; input.type = 'hidden';
input.name = $dropdown.data('field-name'); input.name = $dropdown.data('field-name');
const currentUserInfo = $dropdown.data('currentUserInfo');
if (currentUserInfo) {
input.value = currentUserInfo.id;
input.dataset.meta = currentUserInfo.name;
} else if (_this.currentUser) {
input.value = _this.currentUser.id; input.value = _this.currentUser.id;
}
$dropdown.before(input); $dropdown.before(input);
});
} }
var getSelected = function() { if ($block[0]) {
$block[0].addEventListener('assignYourself', assignYourself);
}
var getSelectedUserInputs = function() {
return $selectbox return $selectbox
.find(`input[name="${$dropdown.data('field-name')}"]`) .find(`input[name="${$dropdown.data('field-name')}"]`);
}
var getSelected = function() {
return getSelectedUserInputs()
.map((index, input) => parseInt(input.value, 10)) .map((index, input) => parseInt(input.value, 10))
.get(); .get();
}; };
var getMultiSelectDropdownTitle = function(selectedUser, isSelected) {
const selectedUsers = getSelected()
.filter(u => u !== 0);
const firstUser = getSelectedUserInputs()
.map((index, input) => ({
name: input.dataset.meta,
value: parseInt(input.value, 10),
}))
.filter(u => u.id !== 0)
.get(0);
if (selectedUsers.length === 0) {
return 'Unassigned';
} else if (selectedUsers.length === 1) {
return firstUser.name;
} else if (isSelected) {
let otherSelected = selectedUsers.filter(s => s !== selectedUser.id);
return `${selectedUser.name} + ${otherSelected.length} more`;
} else {
return `${firstUser.name} + ${selectedUsers.length - 1} more`;
}
}
$('.assign-to-me-link').on('click', (e) => { $('.assign-to-me-link').on('click', (e) => {
e.preventDefault(); e.preventDefault();
$(e.currentTarget).hide(); $(e.currentTarget).hide();
if ($dropdown.data('multiSelect')) {
assignYourself();
const currentUserInfo = $dropdown.data('currentUserInfo');
$dropdown.find('.dropdown-toggle-text').text(getMultiSelectDropdownTitle(currentUserInfo)).removeClass('is-default');
} else {
const $input = $(`input[name="${$dropdown.data('field-name')}"]`); const $input = $(`input[name="${$dropdown.data('field-name')}"]`);
$input.val(gon.current_user_id); $input.val(gon.current_user_id);
selectedId = $input.val(); selectedId = $input.val();
$dropdown.find('.dropdown-toggle-text').text(gon.current_user_fullname).removeClass('is-default'); $dropdown.find('.dropdown-toggle-text').text(gon.current_user_fullname).removeClass('is-default');
}
}); });
$block.on('click', '.js-assign-yourself', (e) => { $block.on('click', '.js-assign-yourself', (e) => {
...@@ -243,6 +289,10 @@ import eventHub from './sidebar/event_hub'; ...@@ -243,6 +289,10 @@ import eventHub from './sidebar/event_hub';
this.processData(inputValue, users, callback); this.processData(inputValue, users, callback);
} }
if (this.multiSelect) {
return getMultiSelectDropdownTitle(selected, $(el).hasClass('is-active'));
}
if (selected && 'id' in selected && $(el).hasClass('is-active')) { if (selected && 'id' in selected && $(el).hasClass('is-active')) {
if (selected.text) { if (selected.text) {
return selected.text; return selected.text;
...@@ -259,15 +309,19 @@ import eventHub from './sidebar/event_hub'; ...@@ -259,15 +309,19 @@ import eventHub from './sidebar/event_hub';
eventHub.$emit('sidebar.saveAssignees'); eventHub.$emit('sidebar.saveAssignees');
} }
if (!$dropdown.data('always-show-selectbox')) {
$selectbox.hide(); $selectbox.hide();
// Recalculate where .value is because vue might have changed it // Recalculate where .value is because vue might have changed it
$block = $selectbox.closest('.block'); $block = $selectbox.closest('.block');
$value = $block.find('.value'); $value = $block.find('.value');
// display:block overrides the hide-collapse rule // display:block overrides the hide-collapse rule
return $value.css('display', ''); $value.css('display', '');
}
}, },
multiSelect: $dropdown.hasClass('js-multiselect'), multiSelect: $dropdown.hasClass('js-multiselect'),
inputMeta: $dropdown.data('input-meta'),
clicked: function(options) { clicked: function(options) {
const { $el, e, isMarking } = options; const { $el, e, isMarking } = options;
const user = options.selectedObj; const user = options.selectedObj;
...@@ -322,6 +376,12 @@ import eventHub from './sidebar/event_hub'; ...@@ -322,6 +376,12 @@ import eventHub from './sidebar/event_hub';
// User unselected // User unselected
eventHub.$emit('sidebar.removeAssignee', user); eventHub.$emit('sidebar.removeAssignee', user);
} }
if (getSelected().find(u => u === gon.current_user_id)) {
$('.assign-to-me-link').hide();
} else {
$('.assign-to-me-link').show();
}
} }
var isIssueIndex, isMRIndex, page, selected; var isIssueIndex, isMRIndex, page, selected;
......
...@@ -63,6 +63,16 @@ module IssuablesHelper ...@@ -63,6 +63,16 @@ module IssuablesHelper
end end
end end
def users_dropdown_label(selected_users)
if selected_users.length == 0
"Unassigned"
elsif selected_users.length == 1
selected_users[0].name
else
"#{selected_users[0].name} + #{selected_users.length - 1} more"
end
end
def user_dropdown_label(user_id, default_label) def user_dropdown_label(user_id, default_label)
return default_label if user_id.nil? return default_label if user_id.nil?
return "Unassigned" if user_id == "0" return "Unassigned" if user_id == "0"
......
...@@ -13,11 +13,22 @@ ...@@ -13,11 +13,22 @@
- if issuable.is_a?(Issue) - if issuable.is_a?(Issue)
= form.label :assignee_ids, "Assignee", class: "control-label #{"col-lg-4" if has_due_date}" = form.label :assignee_ids, "Assignee", class: "control-label #{"col-lg-4" if has_due_date}"
.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 .issuable-form-select-holder.selectbox
= form.hidden_field :assignee_ids - issuable.assignees.each do |assignee|
= hidden_field_tag "#{issuable.to_ability_name}[assignee_ids][]", assignee.id, id: nil, data: { meta: assignee.name }
- options = { toggle_class: "js-user-search js-author-search", title: 'Select assignee', 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), null_user: true, current_user: true, project_id: issuable.project.try(:id), field_name: "#{issuable.class.model_name.param_key}[assignee_ids][]", default_label: "Assignee"} }
- options[:toggle_class] += ' js-multiselect js-save-user-data'
- options[:title] = 'Select assignee(s)'
- options[:data][:multi_select] = true
- options[:data]['input-meta'] = 'name'
- options[:data]['dropdown-header'] = 'Assignee(s)'
- options[:data]['always-show-selectbox'] = true
- options[:data][:current_user_info] = current_user.to_json(only: [:id, :name])
= dropdown_tag(user_dropdown_label(issuable.assignee_ids, "Assignee"), options: { toggle_class: "js-dropdown-keep-input js-user-search js-issuable-form-dropdown js-assignee-search", title: "Select assignee", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-assignee js-filter-submit", = dropdown_tag(users_dropdown_label(issuable.assignees), options: options)
placeholder: "Search assignee", data: { first_user: current_user.try(:username), null_user: true, current_user: true, project_id: issuable.project.try(:id), selected: issuable.assignee_ids, field_name: "#{issuable.class.model_name.param_key}[assignee_ids]", default_label: "Assignee"} })
= link_to 'Assign to me', '#', class: "assign-to-me-link #{'hide' if issuable.assignee_ids.split(', ').include?(current_user.id)}" = link_to 'Assign to me', '#', class: "assign-to-me-link #{'hide' if issuable.assignee_ids.split(', ').include?(current_user.id)}"
- else - else
= form.label :assignee_id, "Assignee", class: "control-label #{"col-lg-4" if has_due_date}" = form.label :assignee_id, "Assignee", class: "control-label #{"col-lg-4" if has_due_date}"
......
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