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() {
$input.attr('id', this.options.inputId);
}
if (this.options.inputMeta) {
$input.attr('data-meta', selectedObject[this.options.inputMeta]);
}
return this.dropdown.before($input);
};
......
......@@ -52,40 +52,86 @@ import eventHub from './sidebar/event_hub';
$collapsedSidebar = $block.find('.sidebar-collapsed-user');
$loading = $block.find('.block-loading').fadeOut();
if ($block[0]) {
$block[0].addEventListener('assignYourself', () => {
// Remove unassigned selected from the DOM
const unassignedSelected = $dropdown.closest('.selectbox')
.find("input[name='" + ($dropdown.data('field-name')) + "'][value=0]");
if (unassignedSelected) {
unassignedSelected.remove();
}
var assignYourself = function () {
const unassignedSelected = $dropdown.closest('.selectbox')
.find("input[name='" + ($dropdown.data('field-name')) + "'][value=0]");
if (unassignedSelected) {
unassignedSelected.remove();
}
// Save current selected user to the DOM
const input = document.createElement('input');
input.type = 'hidden';
input.name = $dropdown.data('field-name');
// Save current selected user to the DOM
const input = document.createElement('input');
input.type = 'hidden';
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;
}
$dropdown.before(input);
});
$dropdown.before(input);
}
var getSelected = function() {
if ($block[0]) {
$block[0].addEventListener('assignYourself', assignYourself);
}
var getSelectedUserInputs = function() {
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))
.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) => {
e.preventDefault();
$(e.currentTarget).hide();
const $input = $(`input[name="${$dropdown.data('field-name')}"]`);
$input.val(gon.current_user_id);
selectedId = $input.val();
$dropdown.find('.dropdown-toggle-text').text(gon.current_user_fullname).removeClass('is-default');
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')}"]`);
$input.val(gon.current_user_id);
selectedId = $input.val();
$dropdown.find('.dropdown-toggle-text').text(gon.current_user_fullname).removeClass('is-default');
}
});
$block.on('click', '.js-assign-yourself', (e) => {
......@@ -243,6 +289,10 @@ import eventHub from './sidebar/event_hub';
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.text) {
return selected.text;
......@@ -259,15 +309,19 @@ import eventHub from './sidebar/event_hub';
eventHub.$emit('sidebar.saveAssignees');
}
$selectbox.hide();
// Recalculate where .value is because vue might have changed it
$block = $selectbox.closest('.block');
$value = $block.find('.value');
// display:block overrides the hide-collapse rule
return $value.css('display', '');
if (!$dropdown.data('always-show-selectbox')) {
$selectbox.hide();
// Recalculate where .value is because vue might have changed it
$block = $selectbox.closest('.block');
$value = $block.find('.value');
// display:block overrides the hide-collapse rule
$value.css('display', '');
}
},
multiSelect: $dropdown.hasClass('js-multiselect'),
inputMeta: $dropdown.data('input-meta'),
clicked: function(options) {
const { $el, e, isMarking } = options;
const user = options.selectedObj;
......@@ -322,6 +376,12 @@ import eventHub from './sidebar/event_hub';
// User unselected
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;
......
......@@ -63,6 +63,16 @@ module IssuablesHelper
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)
return default_label if user_id.nil?
return "Unassigned" if user_id == "0"
......
......@@ -13,11 +13,22 @@
- if issuable.is_a?(Issue)
= 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) }
.issuable-form-select-holder
= form.hidden_field :assignee_ids
.issuable-form-select-holder.selectbox
- 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",
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"} })
= dropdown_tag(users_dropdown_label(issuable.assignees), options: options)
= link_to 'Assign to me', '#', class: "assign-to-me-link #{'hide' if issuable.assignee_ids.split(', ').include?(current_user.id)}"
- else
= 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