Merge branch 'gl-dropdown-issuable-form' into 'master'

GL dropdowns in issuable form

## What does this MR do?

Changed all the issuable dropdown menus over to user GL dropdowns. This brings the dropdowns to be inline with the issuable filter dropdowns and allows for labels to be created whilst creating/editing an issuable.

## What are the relevant issue numbers?

Closes #12574 

## Screenshots (if relevant)


See merge request !4970
This commit is contained in:
Jacob Schatz 2016-07-15 02:29:10 +00:00
commit bdb6f1e6fa
16 changed files with 72 additions and 65 deletions

View File

@ -39,6 +39,8 @@ class Dispatcher
shortcut_handler = new ShortcutsNavigation()
new GLForm($('.issue-form'))
new IssuableForm($('.issue-form'))
new LabelsSelect()
new MilestoneSelect()
when 'projects:merge_requests:new', 'projects:merge_requests:edit'
new Diff()
shortcut_handler = new ShortcutsNavigation()

View File

@ -184,20 +184,22 @@ class @LabelsSelect
.value()
if $dropdown.hasClass 'js-extra-options'
if showNo
data.unshift(
id: 0
title: 'No Label'
)
extraData = []
if showAny
data.unshift(
extraData.push(
isAny: true
title: 'Any Label'
)
if data.length > 2
data.splice 2, 0, 'divider'
if showNo
extraData.push(
id: 0
title: 'No Label'
)
if extraData.length
extraData.push 'divider'
data = extraData.concat(data)
callback data
@ -287,6 +289,12 @@ class @LabelsSelect
defaultLabel
fieldName: $dropdown.data('field-name')
id: (label) ->
if $dropdown.hasClass('js-issuable-form-dropdown')
if label.id is 0
return
else
return label.id
if $dropdown.hasClass("js-filter-submit") and not label.isAny?
label.title
else
@ -300,6 +308,9 @@ class @LabelsSelect
$selectbox.hide()
# display:block overrides the hide-collapse rule
$value.removeAttr('style')
return if $dropdown.hasClass('js-issuable-form-dropdown')
if $dropdown.hasClass 'js-multiselect'
if $dropdown.hasClass('js-filter-submit') and (isIssueIndex or isMRIndex)
selectedLabels = $dropdown
@ -321,7 +332,7 @@ class @LabelsSelect
clicked: (label) ->
_this.enableBulkLabelDropdown()
if $dropdown.hasClass('js-filter-bulk-update')
if $dropdown.hasClass('js-filter-bulk-update') or $dropdown.hasClass('js-issuable-form-dropdown')
return
page = $('body').data 'page'

View File

@ -62,7 +62,7 @@ class @MilestoneSelect
title: 'Upcoming'
)
if extraOptions.length > 2
if extraOptions.length > 0
extraOptions.push 'divider'
callback(extraOptions.concat(data))

View File

@ -151,11 +151,13 @@ class @UsersSelect
# display:block overrides the hide-collapse rule
$value.css('display', '')
clicked: (user) ->
clicked: (user, $el, e) ->
page = $('body').data 'page'
isIssueIndex = page is 'projects:issues:index'
isMRIndex = page is page is 'projects:merge_requests:index'
if $dropdown.hasClass('js-filter-bulk-update')
if $dropdown.hasClass('js-filter-bulk-update') or $dropdown.hasClass('js-issuable-form-dropdown')
e.preventDefault()
selectedId = user.id
return
if $dropdown.hasClass('js-filter-submit') and (isIssueIndex or isMRIndex)
@ -168,7 +170,8 @@ class @UsersSelect
.closest('.selectbox')
.find("input[name='#{$dropdown.data('field-name')}']").val()
assignTo(selected)
id: (user) ->
user.id
renderRow: (user) ->
username = if user.username then "@#{user.username}" else ""
avatar = if user.avatar_url then user.avatar_url else false

View File

@ -56,7 +56,7 @@
position: absolute;
top: 50%;
right: 6px;
margin-top: -4px;
margin-top: -6px;
color: $dropdown-toggle-icon-color;
font-size: 10px;
}

View File

@ -324,6 +324,10 @@
.issuable-form-select-holder {
display: inline-block;
width: 250px;
.dropdown-menu-toggle {
width: 100%;
}
}
.table-holder {

View File

@ -9,7 +9,7 @@ module IssuablesHelper
def multi_label_name(current_labels, default_label)
# current_labels may be a string from before
if current_labels.is_a?(Array)
if current_labels.is_a?(Array) && current_labels.any?
if current_labels.count > 1
"#{current_labels[0]} +#{current_labels.count - 1} more"
else

View File

@ -21,10 +21,10 @@
placeholder: "Search assignee", data: { any_user: "Any Assignee", first_user: (current_user.username if current_user), null_user: true, current_user: true, project_id: (@project.id if @project), selected: params[:assignee_id], field_name: "assignee_id", default_label: "Assignee" } })
.filter-item.inline.milestone-filter
= render "shared/issuable/milestone_dropdown"
= render "shared/issuable/milestone_dropdown", selected: params[:milestone_title], name: :milestone_title, show_any: true, show_upcoming: true
.filter-item.inline.labels-filter
= render "shared/issuable/label_dropdown"
= render "shared/issuable/label_dropdown", selected: params[:label_name], data_options: { field_name: "label_name[]" }
.pull-right
= render 'shared/sort_dropdown'

View File

@ -59,38 +59,24 @@
= f.label :assignee_id, "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
= users_select_tag("#{issuable.class.model_name.param_key}[assignee_id]",
placeholder: 'Select assignee', class: 'custom-form-control', null_user: true,
selected: issuable.assignee_id, project: @target_project || @project,
first_user: true, current_user: true, include_blank: true)
%div
= link_to 'Assign to me', '#', class: 'assign-to-me-link prepend-top-5 inline'
- project = @target_project || @project
- if issuable.assignee_id
= hidden_field_tag("#{issuable.class.model_name.param_key}[assignee_id]", issuable.assignee_id)
= dropdown_tag(user_dropdown_label(issuable.assignee_id, "Assignee"), options: { toggle_class: "js-user-search js-issuable-form-dropdown js-assignee-search", title: "Filter by 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.username if current_user), null_user: true, current_user: true, project_id: (project.id if project), selected: issuable.assignee_id, field_name: "#{issuable.class.model_name.param_key}[assignee_id]", default_label: "Assignee" } })
.form-group.issue-milestone
= f.label :milestone_id, "Milestone", class: "control-label #{"col-lg-4" if has_due_date}"
.col-sm-10{ class: ("col-lg-8" if has_due_date) }
- if milestone_options(issuable).present?
.issuable-form-select-holder
= f.select(:milestone_id, milestone_options(issuable),
{ include_blank: true }, { class: 'select2', data: { placeholder: 'Select milestone' } })
- else
.prepend-top-10
%span.light No open milestones available.
- if can? current_user, :admin_milestone, issuable.project
%div
= link_to 'Create new milestone', new_namespace_project_milestone_path(issuable.project.namespace, issuable.project), target: :blank, class: "prepend-top-5 inline"
.issuable-form-select-holder
= render "shared/issuable/milestone_dropdown", selected: issuable.milestone_id, name: "#{issuable.class.model_name.param_key}[milestone_id]", show_any: false, show_upcoming: false
.form-group
- has_labels = issuable.project.labels.any?
- selected_labels = issuable.label_ids.any? ? issuable.label_ids : nil
- label_dropdown_toggle = issuable.labels.map { |label| label.title }
= f.label :label_ids, "Labels", class: "control-label #{"col-lg-4" if has_due_date}"
.col-sm-10{ class: "#{"col-lg-8" if has_due_date} #{'issuable-form-padding-top' if !has_labels}" }
- if has_labels
.issuable-form-select-holder
= f.collection_select :label_ids, issuable.project.labels.all, :id, :name,
{ selected: issuable.label_ids }, multiple: true, class: 'select2', data: { placeholder: "Select labels" }
- else
%span.light No labels yet.
- if can? current_user, :admin_label, issuable.project
%div
= link_to 'Create new label', new_namespace_project_label_path(issuable.project.namespace, issuable.project), target: :blank, class: "prepend-top-5 inline"
.issuable-form-select-holder
= render "shared/issuable/label_dropdown", classes: ["js-issuable-form-dropdown"], selected: selected_labels, selected_toggle: label_dropdown_toggle, data_options: { field_name: "#{issuable.class.model_name.param_key}[label_ids][]", show_any: "false" }
- if has_due_date
.col-lg-6
.form-group

View File

@ -4,19 +4,21 @@
- show_footer = local_assigns.fetch(:show_footer, true)
- data_options = local_assigns.fetch(:data_options, {})
- classes = local_assigns.fetch(:classes, [])
- dropdown_data = {toggle: 'dropdown', field_name: 'label_name[]', show_no: "true", show_any: "true", selected: params[:label_name], project_id: @project.try(:id), labels: labels_filter_path, default_label: "Label"}
- selected = local_assigns.fetch(:selected, nil)
- selected_toggle = local_assigns.fetch(:selected_toggle, nil)
- dropdown_data = {toggle: 'dropdown', field_name: "label_name[]", show_no: "true", show_any: "true", selected: selected, project_id: @project.try(:id), labels: labels_filter_path, default_label: "Label"}
- dropdown_data.merge!(data_options)
- classes << 'js-extra-options' if extra_options
- classes << 'js-filter-submit' if filter_submit
- if params[:label_name].present?
- if params[:label_name].respond_to?('any?')
- params[:label_name].each do |label|
= hidden_field_tag "label_name[]", label, id: nil
- if selected.present?
- if selected.respond_to?('any?')
- selected.each do |label|
= hidden_field_tag data_options[:field_name], label, id: nil
.dropdown
%button.dropdown-menu-toggle.js-label-select.js-multiselect{class: classes.join(' '), type: "button", data: dropdown_data}
%span.dropdown-toggle-text
= h(multi_label_name(params[:label_name], "Label"))
= h(multi_label_name(selected_toggle || selected, "Label"))
= icon('chevron-down')
.dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable
= render partial: "shared/issuable/label_page_default", locals: { title: "Filter by label", show_footer: show_footer, show_create: show_create }

View File

@ -1,7 +1,7 @@
- if params[:milestone_title].present?
= hidden_field_tag(:milestone_title, params[:milestone_title])
= dropdown_tag(milestone_dropdown_label(params[:milestone_title]), options: { title: "Filter by milestone", toggle_class: 'js-milestone-select js-filter-submit', filter: true, dropdown_class: "dropdown-menu-selectable",
placeholder: "Search milestones", footer_content: @project.present?, data: { show_no: true, show_any: true, show_upcoming: true, field_name: "milestone_title", selected: params[:milestone_title], project_id: @project.try(:id), milestones: milestones_filter_dropdown_path, default_label: "Milestone" } }) do
- if selected.present?
= hidden_field_tag(name, selected)
= dropdown_tag(milestone_dropdown_label(selected), options: { title: "Filter by milestone", toggle_class: 'js-milestone-select js-filter-submit', filter: true, dropdown_class: "dropdown-menu-selectable",
placeholder: "Search milestones", footer_content: @project.present?, data: { show_no: true, show_any: show_any, show_upcoming: show_upcoming, field_name: name, selected: selected, project_id: @project.try(:id), milestones: milestones_filter_dropdown_path, default_label: "Milestone" } }) do
- if @project
%ul.dropdown-footer-list
- if can? current_user, :admin_milestone, @project

View File

@ -37,6 +37,7 @@ Feature: Project Issues
And I submit new issue "500 error on profile"
Then I should see issue "500 error on profile"
@javascript
Scenario: I submit new unassigned issue with labels
Given project "Shop" has labels: "bug", "feature", "enhancement"
And I click link "New Issue"

View File

@ -135,19 +135,17 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps
end
step 'I click "Assign to" dropdown"' do
first('.ajax-users-select').click
click_button 'Assignee'
end
step 'I should see the target project ID in the input selector' do
expect(page).to have_selector("input[data-project-id=\"#{@project.id}\"]")
expect(find('.js-assignee-search')["data-project-id"]).to eq "#{@project.id}"
end
step 'I should see the users from the target project ID' do
expect(page).to have_selector('.user-result', visible: true, count: 3)
users = page.all('.user-name')
expect(users[0].text).to eq 'Unassigned'
expect(users[1].text).to eq current_user.name
expect(users[2].text).to eq @project.users.first.name
expect(page).to have_content 'Unassigned'
expect(page).to have_content current_user.name
expect(page).to have_content @project.users.first.name
end
# Verify a link is generated against the correct project

View File

@ -82,7 +82,8 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps
step 'I submit new issue "500 error on profile" with label \'bug\'' do
fill_in "issue_title", with: "500 error on profile"
select 'bug', from: "Labels"
click_button "Label"
click_link "bug"
click_button "Submit issue"
end

View File

@ -55,7 +55,7 @@ feature 'issue move to another project' do
first('.select2-choice').click
end
fill_in('s2id_autogen2_search', with: new_project_search.name)
fill_in('s2id_autogen1_search', with: new_project_search.name)
page.within '.select2-drop' do
expect(page).to have_content(new_project_search.name)

View File

@ -50,9 +50,8 @@ describe 'Issues', feature: true do
expect(page).to have_content "Assignee #{@user.name}"
first('#s2id_issue_assignee_id').click
sleep 2 # wait for ajax stuff to complete
first('.user-result').click
first('.js-user-search').click
click_link 'Unassigned'
click_button 'Save changes'