From f4d3639a0d01c0e552f54fa3caf56efb98295b0d Mon Sep 17 00:00:00 2001
From: Robert Speicher <robert@gitlab.com>
Date: Fri, 16 Oct 2015 21:29:47 +0000
Subject: [PATCH] Merge branch 'filter-label' into 'master'

Allow dashboard and group issues/MRs to be filtered by label

See merge request !1591
---
 CHANGELOG                                   |  1 +
 app/helpers/labels_helper.rb                | 18 ++++++++++----
 app/models/group_label.rb                   |  9 +++++++
 app/models/group_milestone.rb               | 12 ++--------
 app/services/labels/group_service.rb        | 26 +++++++++++++++++++++
 app/views/shared/issuable/_filter.html.haml |  9 ++++---
 spec/helpers/labels_helper_spec.rb          |  5 ----
 7 files changed, 55 insertions(+), 25 deletions(-)
 create mode 100644 app/models/group_label.rb
 create mode 100644 app/services/labels/group_service.rb

diff --git a/CHANGELOG b/CHANGELOG
index 57768d6b3eb..a1161a7a527 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -59,6 +59,7 @@ v 8.1.0 (unreleased)
   - Fix position of hamburger in header for smaller screens (Han Loong Liauw)
   - Fix bug where Emojis in Markdown would truncate remaining text (Sakata Sinji)
   - Persist filters when sorting on admin user page (Jerry Lukins)
+  - Allow dashboard and group issues/MRs to be filtered by label
   - Add spellcheck=false to certain input fields
   - Invalidate stored service password if the endpoint URL is changed
   - Project names are not fully shown if group name is too big, even on group page view
diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb
index 66b18eea699..ee04ace35d0 100644
--- a/app/helpers/labels_helper.rb
+++ b/app/helpers/labels_helper.rb
@@ -92,11 +92,19 @@ module LabelsHelper
     end
   end
 
-  def project_labels_options(project)
-    labels = project.labels.to_a
-    labels.unshift(Label::None)
-    labels.unshift(Label::Any)
-    options_from_collection_for_select(labels, 'name', 'title', params[:label_name])
+  def projects_labels_options
+    labels =
+      if @project
+        @project.labels
+      else
+        Label.where(project_id: @projects)
+      end
+
+    grouped_labels = Labels::GroupService.new(labels).execute
+    grouped_labels.unshift(Label::None)
+    grouped_labels.unshift(Label::Any)
+
+    options_from_collection_for_select(grouped_labels, 'name', 'title', params[:label_name])
   end
 
   # Required for Gitlab::Markdown::LabelReferenceFilter
diff --git a/app/models/group_label.rb b/app/models/group_label.rb
new file mode 100644
index 00000000000..0fc39cb8771
--- /dev/null
+++ b/app/models/group_label.rb
@@ -0,0 +1,9 @@
+class GroupLabel
+  attr_accessor :title, :labels
+  alias_attribute :name, :title
+
+  def initialize(title, labels)
+    @title = title
+    @labels = labels
+  end
+end
diff --git a/app/models/group_milestone.rb b/app/models/group_milestone.rb
index 1dd2be68ebf..91844da62e2 100644
--- a/app/models/group_milestone.rb
+++ b/app/models/group_milestone.rb
@@ -1,5 +1,5 @@
 class GroupMilestone
-
+  attr_accessor :title, :milestones
   alias_attribute :name, :title
 
   def initialize(title, milestones)
@@ -7,18 +7,10 @@ class GroupMilestone
     @milestones = milestones
   end
 
-  def title
-    @title
-  end
-
   def safe_title
     @title.parameterize
   end
-
-  def milestones
-    @milestones
-  end
-
+  
   def projects
     milestones.map { |milestone| milestone.project }
   end
diff --git a/app/services/labels/group_service.rb b/app/services/labels/group_service.rb
new file mode 100644
index 00000000000..b26cee24d56
--- /dev/null
+++ b/app/services/labels/group_service.rb
@@ -0,0 +1,26 @@
+module Labels
+  class GroupService < ::BaseService
+    def initialize(project_labels)
+      @project_labels = project_labels.group_by(&:title)
+    end
+
+    def execute
+      build(@project_labels)
+    end
+
+    def label(title)
+      if title
+        group_label = @project_labels[title].group_by(&:title)
+        build(group_label).first
+      else
+        nil
+      end
+    end
+
+    private
+
+    def build(label)
+      label.map { |title, labels| GroupLabel.new(title, labels) }
+    end
+  end
+end
diff --git a/app/views/shared/issuable/_filter.html.haml b/app/views/shared/issuable/_filter.html.haml
index 8f16773077e..0e4e9c0987a 100644
--- a/app/views/shared/issuable/_filter.html.haml
+++ b/app/views/shared/issuable/_filter.html.haml
@@ -42,11 +42,10 @@
             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', include_blank: true,
-              data: {placeholder: 'Label'})
+        .filter-item.inline.labels-filter
+          = select_tag('label_name', projects_labels_options,
+            class: 'select2 trigger-submit', include_blank: true,
+            data: {placeholder: 'Label'})
 
         .pull-right
           = render 'shared/sort_dropdown'
diff --git a/spec/helpers/labels_helper_spec.rb b/spec/helpers/labels_helper_spec.rb
index fb70a36dc02..0c8d06b7059 100644
--- a/spec/helpers/labels_helper_spec.rb
+++ b/spec/helpers/labels_helper_spec.rb
@@ -14,11 +14,6 @@ describe LabelsHelper do
         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
-- 
GitLab