Commit dfbbc806 authored by Stan Hu's avatar Stan Hu

Support filtering by "Any" milestone or issue and fix "No Milestone" and "No Label" filters

Closes #2619

Closes https://github.com/gitlabhq/gitlabhq/issues/9631
parent cc8c91a1
......@@ -2,6 +2,7 @@ Please view this file on the master branch, on stable branches it's out of date.
v 8.1.0 (unreleased)
- Add support for creating directories from Files page (Stan Hu)
- Support filtering by "Any" milestone or issue and fix "No Milestone" and "No Label" filters (Stan Hu)
- Fix bug where transferring a project would result in stale commit links (Stan Hu)
- Include full path of source and target branch names in New Merge Request page (Stan Hu)
- Add user preference to view activities as default dashboard (Stan Hu)
......
......@@ -72,11 +72,15 @@ def milestones?
params[:milestone_title].present?
end
def no_milestones?
milestones? && params[:milestone_title] == Milestone::None.title
end
def milestones
return @milestones if defined?(@milestones)
@milestones =
if milestones? && params[:milestone_title] != Milestone::None.title
if milestones?
Milestone.where(title: params[:milestone_title])
else
nil
......@@ -183,7 +187,11 @@ def sort(items)
def by_milestone(items)
if milestones?
items = items.where(milestone_id: milestones.try(:pluck, :id))
if no_milestones?
items = items.where(milestone_id: [-1, nil])
else
items = items.where(milestone_id: milestones.try(:pluck, :id))
end
end
items
......@@ -207,13 +215,19 @@ def by_author(items)
def by_label(items)
if params[:label_name].present?
label_names = params[:label_name].split(",")
if params[:label_name] == Label::None.title
item_ids = LabelLink.where(target_type: klass.name).pluck(:target_id)
item_ids = LabelLink.joins(:label).
where('labels.title in (?)', label_names).
where(target_type: klass.name).pluck(:target_id)
items = items.where('id NOT IN (?)', item_ids)
else
label_names = params[:label_name].split(",")
item_ids = LabelLink.joins(:label).
where('labels.title in (?)', label_names).
where(target_type: klass.name).pluck(:target_id)
items = items.where(id: item_ids)
items = items.where(id: item_ids)
end
end
items
......
......@@ -93,7 +93,9 @@ def text_color_for_bg(bg_color)
end
def project_labels_options(project)
options_from_collection_for_select(project.labels, 'name', 'name', params[:label_name])
labels = project.labels.to_a
labels.unshift(Label::None)
options_from_collection_for_select(labels, 'name', 'name', params[:label_name])
end
# Required for Gitlab::Markdown::LabelReferenceFilter
......
......@@ -12,6 +12,9 @@
class Label < ActiveRecord::Base
include Referable
# Represents a "No Label" state used for filtering Issues and Merge
# Requests that have no label assigned.
None = Struct.new(:title, :name).new('No Label', 'No Label')
DEFAULT_COLOR = '#428BCA'
......
......@@ -39,13 +39,13 @@
.filter-item.inline.milestone-filter
= select_tag('milestone_title', projects_milestones_options,
class: 'select2 trigger-submit', include_blank: true,
class: 'select2 trigger-submit', include_blank: 'Any',
data: {placeholder: 'Milestone'})
- if @project
.filter-item.inline.labels-filter
= select_tag('label_name', project_labels_options(@project),
class: 'select2 trigger-submit', include_blank: true,
class: 'select2 trigger-submit', include_blank: 'Any',
data: {placeholder: 'Label'})
.pull-right
......
......@@ -6,9 +6,11 @@
let(:project1) { create(:project) }
let(:project2) { create(:project) }
let(:milestone) { create(:milestone, project: project1) }
let(:label) { create(:label, project: project2) }
let(:issue1) { create(:issue, author: user, assignee: user, project: project1, milestone: milestone) }
let(:issue2) { create(:issue, author: user, assignee: user, project: project2) }
let(:issue3) { create(:issue, author: user2, assignee: user2, project: project2) }
let!(:label_link) { create(:label_link, label: label, target: issue2) }
before do
project1.team << [user, :master]
......@@ -48,6 +50,24 @@
expect(issues).to eq([issue1])
end
it 'should filter by no milestone id' do
params = { scope: "all", milestone_title: Milestone::None.title, state: 'opened' }
issues = IssuesFinder.new(user, params).execute
expect(issues).to match_array([issue2, issue3])
end
it 'should filter by label name' do
params = { scope: "all", label_name: label.title, state: 'opened' }
issues = IssuesFinder.new(user, params).execute
expect(issues).to eq([issue2])
end
it 'should filter by no label name' do
params = { scope: "all", label_name: Label::None.title, state: 'opened' }
issues = IssuesFinder.new(user, params).execute
expect(issues).to match_array([issue1, issue3])
end
it 'should be empty for unauthorized user' do
params = { scope: "all", state: 'opened' }
issues = IssuesFinder.new(nil, params).execute
......
......@@ -14,6 +14,11 @@
expect(label).not_to receive(:project)
link_to_label(label)
end
it 'includes option for "No Label"' do
result = project_labels_options(project)
expect(result).to include('No Label')
end
end
context 'without @project set' do
......
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