From 3ee3cb24d44e8a9a1284fbd0944b9fcfb938c494 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 24 Jun 2015 18:07:29 -0400 Subject: [PATCH] Allow user to filter by Issues/Merge Requests without a Milestone --- app/finders/issuable_finder.rb | 9 ++++- app/helpers/milestones_helper.rb | 2 + app/models/no_milestone.rb | 13 +++++++ app/views/shared/issuable/_filter.html.haml | 8 +++- .../issues/filter_by_milestone_spec.rb | 38 +++++++++++++++++++ .../filter_by_milestone_spec.rb | 38 +++++++++++++++++++ 6 files changed, 104 insertions(+), 4 deletions(-) create mode 100644 app/models/no_milestone.rb create mode 100644 spec/features/issues/filter_by_milestone_spec.rb create mode 100644 spec/features/merge_requests/filter_by_milestone_spec.rb diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb index 2eccc0ee31f..872c63d82bd 100644 --- a/app/finders/issuable_finder.rb +++ b/app/finders/issuable_finder.rb @@ -76,7 +76,7 @@ class IssuableFinder return @milestones if defined?(@milestones) @milestones = - if milestones? && params[:milestone_title] != NONE + if milestones? && params[:milestone_title] != NoMilestone.title Milestone.where(title: params[:milestone_title]) else nil @@ -183,7 +183,12 @@ class IssuableFinder def by_milestone(items) if milestones? - items = items.where(milestone_id: milestones.try(:pluck, :id)) + # `milestone_title` will still be present when "No Milestone" is selected + if params[:milestone_title] != NoMilestone.title + items = items.where(milestone_id: milestones.try(:pluck, :id)) + else + items = items.where(milestone_id: NoMilestone.id) + end end items diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb index 93e33ebefd8..3dedc405365 100644 --- a/app/helpers/milestones_helper.rb +++ b/app/helpers/milestones_helper.rb @@ -29,6 +29,8 @@ module MilestonesHelper end.active grouped_milestones = Milestones::GroupService.new(milestones).execute + grouped_milestones.unshift(NoMilestone) + options_from_collection_for_select(grouped_milestones, 'title', 'title', params[:milestone_title]) end end diff --git a/app/models/no_milestone.rb b/app/models/no_milestone.rb new file mode 100644 index 00000000000..0c7418b5e29 --- /dev/null +++ b/app/models/no_milestone.rb @@ -0,0 +1,13 @@ +# NoMilestone +# +# Represents a "No Milestone" state used for filtering Issues and Merge Requests +# that have no milestone assigned. +class NoMilestone + def self.id + nil + end + + def self.title + 'No Milestone' + end +end diff --git a/app/views/shared/issuable/_filter.html.haml b/app/views/shared/issuable/_filter.html.haml index a829782fc4f..0e8da8de723 100644 --- a/app/views/shared/issuable/_filter.html.haml +++ b/app/views/shared/issuable/_filter.html.haml @@ -43,11 +43,15 @@ placeholder: 'Author', class: 'trigger-submit', any_user: true, first_user: true) .filter-item.inline.milestone-filter - = select_tag('milestone_title', projects_milestones_options, class: "select2 trigger-submit", prompt: 'Milestone') + = select_tag('milestone_title', projects_milestones_options, + class: 'select2 trigger-submit', include_blank: true, + data: {placeholder: 'Milestone'}) - if @project .filter-item.inline.labels-filter - = select_tag('label_name', project_labels_options(@project), class: "select2 trigger-submit", prompt: 'Label') + = select_tag('label_name', project_labels_options(@project), + class: 'select2 trigger-submit', include_blank: true, + data: {placeholder: 'Label'}) .pull-right = render 'shared/sort_dropdown' diff --git a/spec/features/issues/filter_by_milestone_spec.rb b/spec/features/issues/filter_by_milestone_spec.rb new file mode 100644 index 00000000000..ad8adf4d372 --- /dev/null +++ b/spec/features/issues/filter_by_milestone_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +feature 'Issue filtering by Milestone' do + include Select2Helper + + let(:project) { create(:empty_project) } + + before do + login_as(:admin) + end + + scenario 'User filters by Issues without a Milestone', js: true do + create(:issue, project: project) + + visit_issues + filter_by_milestone(NoMilestone.title) + + expect(page).to have_css('.issue-title', count: 1) + end + + scenario 'User filters by Issues with a specific Milestone', js: true do + milestone = create(:milestone, project: project) + create(:issue, project: project, milestone: milestone) + + visit_issues + filter_by_milestone(milestone.title) + + expect(page).to have_css('.issue-title', count: 1) + end + + def visit_issues + visit namespace_project_issues_path(project.namespace, project) + end + + def filter_by_milestone(title) + select2(title, from: '#milestone_title') + end +end diff --git a/spec/features/merge_requests/filter_by_milestone_spec.rb b/spec/features/merge_requests/filter_by_milestone_spec.rb new file mode 100644 index 00000000000..56a9603f139 --- /dev/null +++ b/spec/features/merge_requests/filter_by_milestone_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +feature 'Merge Request filtering by Milestone' do + include Select2Helper + + let(:project) { create(:project) } + + before do + login_as(:admin) + end + + scenario 'User filters by Merge Requests without a Milestone', js: true do + create(:merge_request, :simple, source_project: project) + + visit_merge_requests + filter_by_milestone(NoMilestone.title) + + expect(page).to have_css('.merge-request-title', count: 1) + end + + scenario 'User filters by Merge Requests with a specific Milestone', js: true do + milestone = create(:milestone, project: project) + create(:merge_request, :simple, source_project: project, milestone: milestone) + + visit_merge_requests + filter_by_milestone(milestone.title) + + expect(page).to have_css('.merge-request-title', count: 1) + end + + def visit_merge_requests + visit namespace_project_merge_requests_path(project.namespace, project) + end + + def filter_by_milestone(title) + select2(title, from: '#milestone_title') + end +end