[#5479] Allow user control of automatic tool grouping threshold
Signed-off-by: Cory Johns <johnsca@geek.net>
diff --git a/Allura/allura/ext/admin/admin_main.py b/Allura/allura/ext/admin/admin_main.py
index 2ba4a56..c0ce5ed 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -203,6 +203,18 @@
@expose()
@require_post()
+ def configure_tool_grouping(self, grouping_threshold='1', **kw):
+ try:
+ grouping_threshold = int(grouping_threshold)
+ if grouping_threshold < 1:
+ raise ValueError('Invalid threshold')
+ c.project.set_tool_data('allura', grouping_threshold=grouping_threshold)
+ except ValueError as e:
+ flash('Invalid threshold', 'error')
+ redirect('tools')
+
+ @expose()
+ @require_post()
def update_labels(self, labels=None, **kw):
require_access(c.project, 'admin')
c.project.labels = labels.split(',')
diff --git a/Allura/allura/ext/admin/templates/project_tools.html b/Allura/allura/ext/admin/templates/project_tools.html
index 30f72b6..5c62cde 100644
--- a/Allura/allura/ext/admin/templates/project_tools.html
+++ b/Allura/allura/ext/admin/templates/project_tools.html
@@ -115,6 +115,14 @@
{{c.admin_modal.display(content='<h1 id="popup_title"></h1><div id="popup_contents"></div>')}}
{{c.mount_delete.display(content='<h1>Confirm Delete</h1>')}}
<div><!--dummy-->
+
+<h3 style="clear:left">Grouping</h3>
+<form method="POST" action="configure_tool_grouping" id="configure_grouping_form">
+ <label>Threshold for grouping tools by type:
+ <input name="grouping_threshold" value="{{c.project.get_tool_data('allura', 'grouping_threshold', 1)}}"/>
+ </label>
+ <br/><input type="submit" value="Change"/>
+</form>
{% endblock %}
{% block extra_js %}
@@ -132,5 +140,12 @@
.pad .fourcol .fleft {
min-height: 200px;
}
+
+#configure_grouping_form {
+ padding-left: 10px;
+}
+#configure_grouping_form input[name=grouping_threshold] {
+ width: 1.5em;
+}
</style>
{% endblock %}
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index e8263e7..84f346d 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -443,26 +443,25 @@
grouped_nav = OrderedDict()
# count how many tools of each type we have
counts = Counter([e.tool_name.lower() for e in sitemap if e.tool_name])
+ grouping_threshold = self.get_tool_data('allura', 'grouping_threshold', 1)
for e in sitemap:
# if it's not a tool, add to navbar and continue
if not e.tool_name:
grouped_nav[id(e)] = e
continue
tool_name = e.tool_name.lower()
- # tool of a type we don't have in the navbar yet
- if tool_name not in grouped_nav:
- # there's more than one tool of this type
- if counts.get(tool_name, 1) > 1:
+ if counts.get(tool_name, 1) <= grouping_threshold:
+ # don't need grouping, so just add it by label
+ grouped_nav[e.label] = e
+ else:
+ # tool of a type we don't have in the navbar yet
+ if tool_name not in grouped_nav:
# change label to be the tool name (type)
e.label = tool_name.capitalize()
- # add tool url to list of urls that will match this nav entry
- e.matching_urls.append(e.url)
# change url to point to tool list page
e.url = self.url() + '_list/' + tool_name
- grouped_nav[tool_name] = e
- else:
- # already have a tool of this type in the nav; add this tool's
- # url to the list of urls that match this nav entry
+ grouped_nav[tool_name] = e
+ # add tool url to list of urls that will match this nav entry
grouped_nav[tool_name].matching_urls.append(e.url)
return grouped_nav.values()
diff --git a/Allura/allura/tests/functional/test_admin.py b/Allura/allura/tests/functional/test_admin.py
index 9c0be46..ad933ab 100644
--- a/Allura/allura/tests/functional/test_admin.py
+++ b/Allura/allura/tests/functional/test_admin.py
@@ -175,6 +175,19 @@
# that we don't know about
assert len(set(expected_tools) - set(tool_strings)) == 0, tool_strings
+ def test_grouping_threshold(self):
+ r = self.app.get('/admin/tools')
+ grouping_threshold = r.html.find('input',{'name':'grouping_threshold'})
+ assert_equals(grouping_threshold['value'], '1')
+ r = self.app.post('/admin/configure_tool_grouping', params={
+ 'grouping_threshold': '2',
+ }).follow()
+ grouping_threshold = r.html.find('input',{'name':'grouping_threshold'})
+ assert_equals(grouping_threshold['value'], '2')
+ r = self.app.get('/admin/tools')
+ grouping_threshold = r.html.find('input',{'name':'grouping_threshold'})
+ assert_equals(grouping_threshold['value'], '2')
+
def test_project_icon(self):
file_name = 'neo-icon-set-454545-256x350.png'
file_path = os.path.join(allura.__path__[0],'nf','allura','images',file_name)
diff --git a/Allura/allura/tests/unit/test_project.py b/Allura/allura/tests/unit/test_project.py
index b59d04f..f33c592 100644
--- a/Allura/allura/tests/unit/test_project.py
+++ b/Allura/allura/tests/unit/test_project.py
@@ -28,3 +28,28 @@
actual = [(e.label, e.url, len(e.matching_urls))
for e in p.grouped_navbar_entries()]
self.assertEqual(expected, actual)
+
+ def test_grouped_navbar_threshold(self):
+ p = M.Project()
+ sitemap_entries = [
+ SitemapEntry('bugs', url='bugs url', tool_name='Tickets'),
+ SitemapEntry('wiki', url='wiki url', tool_name='Wiki'),
+ SitemapEntry('discuss', url='discuss url', tool_name='Discussion'),
+ SitemapEntry('subproject', url='subproject url'),
+ SitemapEntry('features', url='features url', tool_name='Tickets'),
+ SitemapEntry('help', url='help url', tool_name='Discussion'),
+ SitemapEntry('support reqs', url='support url', tool_name='Tickets'),
+ ]
+ p.url = Mock(return_value='proj_url/')
+ p.sitemap = Mock(return_value=sitemap_entries)
+ p.tool_data['allura'] = {'grouping_threshold': 2}
+ expected = [
+ ('Tickets', 'proj_url/_list/tickets', 3),
+ ('wiki', 'wiki url', 0),
+ ('discuss', 'discuss url', 0),
+ ('subproject', 'subproject url', 0),
+ ('help', 'help url', 0),
+ ]
+ actual = [(e.label, e.url, len(e.matching_urls))
+ for e in p.grouped_navbar_entries()]
+ self.assertEqual(expected, actual)