From 5c000b40ffefa47822c164eb03730eac4befa7aa Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Jan 20 2017 10:09:08 +0000
Subject: [PATCH 1/6] Add buttons for "All milestone tags", or "All active milestone tags"


---

diff --git a/pagure/templates/roadmap.html b/pagure/templates/roadmap.html
index e78587c..668d69e 100644
--- a/pagure/templates/roadmap.html
+++ b/pagure/templates/roadmap.html
@@ -42,7 +42,7 @@
 
 <section id="flags">
   <span class="btn-group btn-group-sm issues-tagbar" role="group">
-  <span class="oi m-l-2 btn btn-nopad" data-glyph="briefcase" title="Status"></span>
+  <span class="oi m-l-2 btn btn-nopad" title="Status"></span>
     <a class="btn {%
       if status|lower in ['open', 'true'] %}btn-primary{%
       else %}btn-secondary{%
@@ -51,6 +51,7 @@
         username=username,
         namespace=repo.namespace,
         milestone=requested_stones,
+        all_ms_tags=all_ms_tags,
         tag=tags) }}" title="Filter issues by status">Open</a>
     <a class="btn {%
       if status|lower in ['closed', 'false'] %}btn-primary{%
@@ -61,6 +62,7 @@
         namespace=repo.namespace,
         tag=tags,
         milestone=requested_stones,
+        all_ms_tags=all_ms_tags,
         status='Closed') }}" title="Filter issues by status">Closed</a>
     <a class="btn {%
       if status|lower in ['all', 'none'] %}btn-primary{%
@@ -71,34 +73,61 @@
         namespace=repo.namespace,
         tag=tags,
         milestone=requested_stones,
+        all_ms_tags=all_ms_tags,
         status='all') }}" title="Filter issues by status">All</a>
   </span>
+  <span class="btn-group btn-group-sm issues-tagbar" role="group">
+  <span class="oi m-l-2 btn btn-nopad" title="Status"></span>
+    <a class="btn {%
+      if all_ms_tags is none %}btn-primary{%
+      else %}btn-secondary{%
+      endif %} btn-sm" href="{{ url_for('view_roadmap',
+        repo=repo.name,
+        username=username,
+        namespace=repo.namespace,
+        tag=tags,
+        status=status) }}" title="Only display active milestone tags">Active Milestones</a>
+    <a class="btn {%
+      if all_ms_tags is not none %}btn-primary{%
+      else %}btn-secondary{%
+      endif %} btn-sm" href="{{ url_for('view_roadmap',
+        repo=repo.name,
+        username=username,
+        namespace=repo.namespace,
+        tag=tags,
+        all_ms_tags=true,
+        status=status) }}" title="Display all milestone tags">All Milestones</a>
+  </span>
   <span class="btn-group btn-group-sm issues-tagbar" role="group" aria-label="Basic example">
   <span class="oi m-l-2 btn btn-nopad" data-glyph="target" title="Milestones"></span>
     {% for stone in milestones %}
-      {% if stone in requested_stones %}
-        <a class="btn btn-secondary btn-sm {% if stone in requested_stones %}active{% endif %}"
-          href="{{ url_for(
-            'view_roadmap',
-            repo=repo.name,
-            username=username,
-            namespace=repo.namespace,
-            tag=tags,
-            status=status) }}"
-            title="Filter issues by milestone">
-          {{ stone }}</a>
-      {% else %}
-        <a class="btn btn-secondary btn-sm {% if stone in requested_stones%}active{% endif %}"
-          href="{{ url_for(
-            'view_roadmap',
-            repo=repo.name,
-            username=username,
-            namespace=repo.namespace,
-            milestone=stone,
-            tag=tags,
-            status=status) }}"
-            title="Filter issues by milestone">
-          {{ stone }}</a>
+      {% if (all_ms_tags is none and (stone in issues or stone in requested_stones)) or all_ms_tags is not none %}
+        {% if stone in requested_stones %}
+          <a class="btn btn-secondary btn-sm {% if stone in requested_stones and all_ms_tags %}active{% endif %}"
+           href="{{ url_for(
+              'view_roadmap',
+              repo=repo.name,
+              username=username,
+              namespace=repo.namespace,
+              tag=tags,
+              all_ms_tags=all_ms_tags,
+              status=status) }}"
+              title="Filter issues by milestone">
+            {{ stone }}</a>
+        {% else %}
+          <a class="btn btn-secondary btn-sm"
+            href="{{ url_for(
+              'view_roadmap',
+              repo=repo.name,
+              username=username,
+              namespace=repo.namespace,
+              milestone=stone,
+              tag=tags,
+              all_ms_tags=all_ms_tags,
+              status=status) }}"
+              title="Filter issues by milestone">
+            {{ stone }}</a>
+        {% endif %}
       {% endif %}
     {% endfor %}
   </span>
@@ -106,22 +135,24 @@
   <span class="oi m-l-2 btn btn-nopad" data-glyph="tag" title="Tags"></span>
     {% for tag in tag_list %}
       {% if tag in tags %}
-        <a class="btn btn-secondary btn-sm {% if tag in tags%}active{% endif %}"
+        <a class="btn btn-secondary btn-sm {% if tag in tags %}active{% endif %}"
           href="{{ url_for('view_roadmap',
               repo=repo.name,
               username=username,
               namespace=repo.namespace,
               milestone=requested_stones,
+              all_ms_tags=all_ms_tags,
               status=status) }}"
               title="Filter issues by tag">
       {% else %}
-        <a class="btn btn-secondary btn-sm {% if tag in tags%}active{%endif%}"
+        <a class="btn btn-secondary btn-sm {% if tag in tags %}active{% endif %}"
           href="{{ url_for('view_roadmap',
               repo=repo.name,
               username=username,
               namespace=repo.namespace,
               status=status,
               tag=tag,
+              all_ms_tags=all_ms_tags,
               milestone=requested_stones) }}"
               title="Filter issues by tag">
       {% endif %}
diff --git a/pagure/ui/issues.py b/pagure/ui/issues.py
index ac56587..74f440c 100644
--- a/pagure/ui/issues.py
+++ b/pagure/ui/issues.py
@@ -713,6 +713,7 @@ def view_roadmap(repo, username=None, namespace=None):
     status = flask.request.args.get('status', 'Open')
     milestones = flask.request.args.getlist('milestone', None)
     tags = flask.request.args.getlist('tag', None)
+    all_ms_tags = flask.request.args.get('all_ms_tags', None)
 
     repo = flask.g.repo
 
@@ -736,7 +737,7 @@ def view_roadmap(repo, username=None, namespace=None):
         milestones=milestones or all_milestones,
         tags=tags,
         private=private,
-        status=status if status.lower()!= 'all' else None,
+        status=status if status.lower() != 'all' else None,
     )
 
     # Change from a list of issues to a dict of milestone/issues
@@ -778,6 +779,7 @@ def view_roadmap(repo, username=None, namespace=None):
         username=username,
         tag_list=tag_list,
         status=status,
+        all_ms_tags=all_ms_tags,
         milestones=all_milestones,
         requested_stones=milestones,
         issues=milestone_issues,

From aae88fcd048b51e0495bab9e48cb73fc6e008585 Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Jan 20 2017 10:09:08 +0000
Subject: [PATCH 2/6] Improve how the milestone tags are dispalyed when filtering is applied


---

diff --git a/pagure/templates/roadmap.html b/pagure/templates/roadmap.html
index 668d69e..a634cb1 100644
--- a/pagure/templates/roadmap.html
+++ b/pagure/templates/roadmap.html
@@ -101,9 +101,9 @@
   <span class="btn-group btn-group-sm issues-tagbar" role="group" aria-label="Basic example">
   <span class="oi m-l-2 btn btn-nopad" data-glyph="target" title="Milestones"></span>
     {% for stone in milestones %}
-      {% if (all_ms_tags is none and (stone in issues or stone in requested_stones)) or all_ms_tags is not none %}
+      {% if (all_ms_tags is none and (stone in active_milestones or stone in requested_stones)) or all_ms_tags is not none %}
         {% if stone in requested_stones %}
-          <a class="btn btn-secondary btn-sm {% if stone in requested_stones and all_ms_tags %}active{% endif %}"
+          <a class="btn btn-secondary btn-sm active"
            href="{{ url_for(
               'view_roadmap',
               repo=repo.name,
@@ -111,6 +111,7 @@
               namespace=repo.namespace,
               tag=tags,
               all_ms_tags=all_ms_tags,
+              active_milestones=active_milestones,
               status=status) }}"
               title="Filter issues by milestone">
             {{ stone }}</a>
@@ -124,6 +125,7 @@
               milestone=stone,
               tag=tags,
               all_ms_tags=all_ms_tags,
+              active_milestones=active_milestones,
               status=status) }}"
               title="Filter issues by milestone">
             {{ stone }}</a>
@@ -142,6 +144,7 @@
               namespace=repo.namespace,
               milestone=requested_stones,
               all_ms_tags=all_ms_tags,
+              active_milestones=active_milestones,
               status=status) }}"
               title="Filter issues by tag">
       {% else %}
@@ -153,6 +156,7 @@
               status=status,
               tag=tag,
               all_ms_tags=all_ms_tags,
+              active_milestones=active_milestones,
               milestone=requested_stones) }}"
               title="Filter issues by tag">
       {% endif %}
diff --git a/pagure/ui/issues.py b/pagure/ui/issues.py
index 74f440c..c43ea82 100644
--- a/pagure/ui/issues.py
+++ b/pagure/ui/issues.py
@@ -714,6 +714,7 @@ def view_roadmap(repo, username=None, namespace=None):
     milestones = flask.request.args.getlist('milestone', None)
     tags = flask.request.args.getlist('tag', None)
     all_ms_tags = flask.request.args.get('all_ms_tags', None)
+    active_milestones = flask.request.args.getlist('active_milestones', None)
 
     repo = flask.g.repo
 
@@ -772,6 +773,20 @@ def view_roadmap(repo, username=None, namespace=None):
         cnt = len(all_milestones)
         all_milestones.insert(cnt, all_milestones.pop(index))
 
+    if len(active_milestones) == 0 and all_ms_tags is None:
+        # We don't have any requested active milestones, so grab a fresh list.
+        # Get all the active tickets regardless what tags/milestones were
+        # requested.
+        active_issues = pagure.lib.search_issues(
+            SESSION,
+            repo,
+            milestones=all_milestones,
+            private=private,
+            status=status if status.lower() != 'all' else None,
+        )
+        for issue in active_issues:
+            active_milestones.append(issue.milestone)
+
     return flask.render_template(
         'roadmap.html',
         select='issues',
@@ -781,6 +796,7 @@ def view_roadmap(repo, username=None, namespace=None):
         status=status,
         all_ms_tags=all_ms_tags,
         milestones=all_milestones,
+        active_milestones=active_milestones,
         requested_stones=milestones,
         issues=milestone_issues,
         tags=tags,

From 0e99a171a04c0fb919b3979319bf92d0aa94beac Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: Jan 20 2017 10:20:03 +0000
Subject: [PATCH 3/6] Rework a little the active milestone/all milestone filtering


So we want either only the active milestones, or all of them, so this
is a simple boolean, if we want only the active milestones then we
retrieve the list of all the active milestones (ie: having at least one
ticket open) and consider only this list.
Otherwise, we get the list of all the milestones and consider this list.

---

diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py
index b3e33c3..6a292fc 100644
--- a/pagure/lib/__init__.py
+++ b/pagure/lib/__init__.py
@@ -3656,3 +3656,20 @@ def get_custom_key(session, project, keyname):
     )
 
     return query.first()
+
+
+def get_active_milestones(session, project):
+    ''' Returns the list of all the active milestones for a given project.
+    '''
+
+    query = session.query(
+        model.Issue.milestone
+    ).filter(
+        model.Issue.project_id == project.id
+    ).filter(
+        model.Issue.status == 'Open'
+    ).filter(
+        model.Issue.milestone.isnot(None)
+    )
+
+    return sorted([item[0] for item in query.distinct()])
diff --git a/pagure/templates/roadmap.html b/pagure/templates/roadmap.html
index a634cb1..dca552d 100644
--- a/pagure/templates/roadmap.html
+++ b/pagure/templates/roadmap.html
@@ -101,35 +101,31 @@
   <span class="btn-group btn-group-sm issues-tagbar" role="group" aria-label="Basic example">
   <span class="oi m-l-2 btn btn-nopad" data-glyph="target" title="Milestones"></span>
     {% for stone in milestones %}
-      {% if (all_ms_tags is none and (stone in active_milestones or stone in requested_stones)) or all_ms_tags is not none %}
-        {% if stone in requested_stones %}
-          <a class="btn btn-secondary btn-sm active"
-           href="{{ url_for(
-              'view_roadmap',
-              repo=repo.name,
-              username=username,
-              namespace=repo.namespace,
-              tag=tags,
-              all_ms_tags=all_ms_tags,
-              active_milestones=active_milestones,
-              status=status) }}"
-              title="Filter issues by milestone">
-            {{ stone }}</a>
-        {% else %}
-          <a class="btn btn-secondary btn-sm"
-            href="{{ url_for(
-              'view_roadmap',
-              repo=repo.name,
-              username=username,
-              namespace=repo.namespace,
-              milestone=stone,
-              tag=tags,
-              all_ms_tags=all_ms_tags,
-              active_milestones=active_milestones,
-              status=status) }}"
-              title="Filter issues by milestone">
-            {{ stone }}</a>
-        {% endif %}
+      {% if stone in requested_stones %}
+        <a class="btn btn-secondary btn-sm active"
+         href="{{ url_for(
+            'view_roadmap',
+            repo=repo.name,
+            username=username,
+            namespace=repo.namespace,
+            tag=tags,
+            all_ms_tags=all_ms_tags,
+            status=status) }}"
+            title="Filter issues by milestone">
+          {{ stone }}</a>
+      {% else %}
+        <a class="btn btn-secondary btn-sm"
+          href="{{ url_for(
+            'view_roadmap',
+            repo=repo.name,
+            username=username,
+            namespace=repo.namespace,
+            milestone=stone,
+            tag=tags,
+            all_ms_tags=all_ms_tags,
+            status=status) }}"
+            title="Filter issues by milestone">
+          {{ stone }}</a>
       {% endif %}
     {% endfor %}
   </span>
@@ -144,7 +140,6 @@
               namespace=repo.namespace,
               milestone=requested_stones,
               all_ms_tags=all_ms_tags,
-              active_milestones=active_milestones,
               status=status) }}"
               title="Filter issues by tag">
       {% else %}
@@ -156,7 +151,6 @@
               status=status,
               tag=tag,
               all_ms_tags=all_ms_tags,
-              active_milestones=active_milestones,
               milestone=requested_stones) }}"
               title="Filter issues by tag">
       {% endif %}
diff --git a/pagure/ui/issues.py b/pagure/ui/issues.py
index c43ea82..c5e54fb 100644
--- a/pagure/ui/issues.py
+++ b/pagure/ui/issues.py
@@ -731,6 +731,7 @@ def view_roadmap(repo, username=None, namespace=None):
         private = None
 
     all_milestones = sorted(list(repo.milestones.keys()))
+    active_milestones = pagure.lib.get_active_milestones(SESSION, repo)
 
     issues = pagure.lib.search_issues(
         SESSION,
@@ -773,19 +774,9 @@ def view_roadmap(repo, username=None, namespace=None):
         cnt = len(all_milestones)
         all_milestones.insert(cnt, all_milestones.pop(index))
 
-    if len(active_milestones) == 0 and all_ms_tags is None:
-        # We don't have any requested active milestones, so grab a fresh list.
-        # Get all the active tickets regardless what tags/milestones were
-        # requested.
-        active_issues = pagure.lib.search_issues(
-            SESSION,
-            repo,
-            milestones=all_milestones,
-            private=private,
-            status=status if status.lower() != 'all' else None,
-        )
-        for issue in active_issues:
-            active_milestones.append(issue.milestone)
+    milestones_list = active_milestones
+    if all_ms_tags:
+        milestones_list = all_milestones
 
     return flask.render_template(
         'roadmap.html',
@@ -795,8 +786,7 @@ def view_roadmap(repo, username=None, namespace=None):
         tag_list=tag_list,
         status=status,
         all_ms_tags=all_ms_tags,
-        milestones=all_milestones,
-        active_milestones=active_milestones,
+        milestones=milestones_list,
         requested_stones=milestones,
         issues=milestone_issues,
         tags=tags,

From a44f850e21fd97ec654604bd6d2fb1f0a70424ad Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: Jan 20 2017 13:20:01 +0000
Subject: [PATCH 4/6] Rename the variable all_ms_tags to all_stones


---

diff --git a/pagure/templates/roadmap.html b/pagure/templates/roadmap.html
index dca552d..abc5024 100644
--- a/pagure/templates/roadmap.html
+++ b/pagure/templates/roadmap.html
@@ -51,7 +51,7 @@
         username=username,
         namespace=repo.namespace,
         milestone=requested_stones,
-        all_ms_tags=all_ms_tags,
+        all_stones=all_stones,
         tag=tags) }}" title="Filter issues by status">Open</a>
     <a class="btn {%
       if status|lower in ['closed', 'false'] %}btn-primary{%
@@ -62,7 +62,7 @@
         namespace=repo.namespace,
         tag=tags,
         milestone=requested_stones,
-        all_ms_tags=all_ms_tags,
+        all_stones=all_stones,
         status='Closed') }}" title="Filter issues by status">Closed</a>
     <a class="btn {%
       if status|lower in ['all', 'none'] %}btn-primary{%
@@ -73,13 +73,13 @@
         namespace=repo.namespace,
         tag=tags,
         milestone=requested_stones,
-        all_ms_tags=all_ms_tags,
+        all_stones=all_stones,
         status='all') }}" title="Filter issues by status">All</a>
   </span>
   <span class="btn-group btn-group-sm issues-tagbar" role="group">
   <span class="oi m-l-2 btn btn-nopad" title="Status"></span>
     <a class="btn {%
-      if all_ms_tags is none %}btn-primary{%
+      if all_stones is none %}btn-primary{%
       else %}btn-secondary{%
       endif %} btn-sm" href="{{ url_for('view_roadmap',
         repo=repo.name,
@@ -88,14 +88,14 @@
         tag=tags,
         status=status) }}" title="Only display active milestone tags">Active Milestones</a>
     <a class="btn {%
-      if all_ms_tags is not none %}btn-primary{%
+      if all_stones is not none %}btn-primary{%
       else %}btn-secondary{%
       endif %} btn-sm" href="{{ url_for('view_roadmap',
         repo=repo.name,
         username=username,
         namespace=repo.namespace,
         tag=tags,
-        all_ms_tags=true,
+        all_stones=true,
         status=status) }}" title="Display all milestone tags">All Milestones</a>
   </span>
   <span class="btn-group btn-group-sm issues-tagbar" role="group" aria-label="Basic example">
@@ -109,7 +109,7 @@
             username=username,
             namespace=repo.namespace,
             tag=tags,
-            all_ms_tags=all_ms_tags,
+            all_stones=all_stones,
             status=status) }}"
             title="Filter issues by milestone">
           {{ stone }}</a>
@@ -122,7 +122,7 @@
             namespace=repo.namespace,
             milestone=stone,
             tag=tags,
-            all_ms_tags=all_ms_tags,
+            all_stones=all_stones,
             status=status) }}"
             title="Filter issues by milestone">
           {{ stone }}</a>
@@ -139,7 +139,7 @@
               username=username,
               namespace=repo.namespace,
               milestone=requested_stones,
-              all_ms_tags=all_ms_tags,
+              all_stones=all_stones,
               status=status) }}"
               title="Filter issues by tag">
       {% else %}
@@ -150,7 +150,7 @@
               namespace=repo.namespace,
               status=status,
               tag=tag,
-              all_ms_tags=all_ms_tags,
+              all_stones=all_stones,
               milestone=requested_stones) }}"
               title="Filter issues by tag">
       {% endif %}
diff --git a/pagure/ui/issues.py b/pagure/ui/issues.py
index c5e54fb..f4fba3f 100644
--- a/pagure/ui/issues.py
+++ b/pagure/ui/issues.py
@@ -713,7 +713,7 @@ def view_roadmap(repo, username=None, namespace=None):
     status = flask.request.args.get('status', 'Open')
     milestones = flask.request.args.getlist('milestone', None)
     tags = flask.request.args.getlist('tag', None)
-    all_ms_tags = flask.request.args.get('all_ms_tags', None)
+    all_stones = flask.request.args.get('all_stones')
     active_milestones = flask.request.args.getlist('active_milestones', None)
 
     repo = flask.g.repo
@@ -775,7 +775,7 @@ def view_roadmap(repo, username=None, namespace=None):
         all_milestones.insert(cnt, all_milestones.pop(index))
 
     milestones_list = active_milestones
-    if all_ms_tags:
+    if all_stones:
         milestones_list = all_milestones
 
     return flask.render_template(
@@ -785,7 +785,7 @@ def view_roadmap(repo, username=None, namespace=None):
         username=username,
         tag_list=tag_list,
         status=status,
-        all_ms_tags=all_ms_tags,
+        all_stones=all_stones,
         milestones=milestones_list,
         requested_stones=milestones,
         issues=milestone_issues,

From 8e22c805a1928fe14f2fcc06d95cc8ca27ca788a Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: Jan 20 2017 13:20:01 +0000
Subject: [PATCH 5/6] Fix toggling the All Milestones/Active Milestones buttons


---

diff --git a/pagure/templates/roadmap.html b/pagure/templates/roadmap.html
index abc5024..94eaac7 100644
--- a/pagure/templates/roadmap.html
+++ b/pagure/templates/roadmap.html
@@ -79,7 +79,7 @@
   <span class="btn-group btn-group-sm issues-tagbar" role="group">
   <span class="oi m-l-2 btn btn-nopad" title="Status"></span>
     <a class="btn {%
-      if all_stones is none %}btn-primary{%
+      if not all_stones %}btn-primary{%
       else %}btn-secondary{%
       endif %} btn-sm" href="{{ url_for('view_roadmap',
         repo=repo.name,
@@ -88,7 +88,7 @@
         tag=tags,
         status=status) }}" title="Only display active milestone tags">Active Milestones</a>
     <a class="btn {%
-      if all_stones is not none %}btn-primary{%
+      if all_stones %}btn-primary{%
       else %}btn-secondary{%
       endif %} btn-sm" href="{{ url_for('view_roadmap',
         repo=repo.name,

From 041a004227784e6835ba122b71f46c6a1e66d07c Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: Jan 20 2017 13:20:01 +0000
Subject: [PATCH 6/6] Fix the unit-tests


---

diff --git a/tests/test_pagure_flask_ui_roadmap.py b/tests/test_pagure_flask_ui_roadmap.py
index 31fdee0..64755e8 100644
--- a/tests/test_pagure_flask_ui_roadmap.py
+++ b/tests/test_pagure_flask_ui_roadmap.py
@@ -487,7 +487,7 @@ class PagureFlaskRoadmaptests(tests.Modeltests):
             output.data.count(u'<span class="label label-default">#'), 4)
 
         # test the roadmap view for all milestones
-        output = self.app.get('/test/roadmap?status=All')
+        output = self.app.get('/test/roadmap?all_stones=True&status=All')
         self.assertEqual(output.status_code, 200)
         self.assertIn(u'<th>v1.0', output.data)
         self.assertIn(u'<th>v2.0', output.data)
@@ -510,7 +510,8 @@ class PagureFlaskRoadmaptests(tests.Modeltests):
             output.data.count(u'<span class="label label-default">#'), 0)
 
         # test the roadmap view for a specific milestone - closed
-        output = self.app.get('/test/roadmap?milestone=v1.0&status=All')
+        output = self.app.get(
+            '/test/roadmap?milestone=v1.0&status=All&all_stones=True')
         self.assertEqual(output.status_code, 200)
         self.assertIn(u'<th>v1.0', output.data)
         self.assertEqual(

