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:
commit
bdb6f1e6fa
|
@ -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()
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -62,7 +62,7 @@ class @MilestoneSelect
|
|||
title: 'Upcoming'
|
||||
)
|
||||
|
||||
if extraOptions.length > 2
|
||||
if extraOptions.length > 0
|
||||
extraOptions.push 'divider'
|
||||
|
||||
callback(extraOptions.concat(data))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
position: absolute;
|
||||
top: 50%;
|
||||
right: 6px;
|
||||
margin-top: -4px;
|
||||
margin-top: -6px;
|
||||
color: $dropdown-toggle-icon-color;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
|
|
@ -324,6 +324,10 @@
|
|||
.issuable-form-select-holder {
|
||||
display: inline-block;
|
||||
width: 250px;
|
||||
|
||||
.dropdown-menu-toggle {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.table-holder {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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'
|
||||
|
||||
|
|
Loading…
Reference in New Issue