Implement package difference filtering
This is done as client-side JS which makes the page nice and fast. Minor versions can be excluded, as can packages in [multilib]. In addition, architecture filtering is in place so you can limit the subset of shown packages to those in any, both, one or the other. Signed-off-by: Dan McGee <dan@archlinux.org>
This commit is contained in:
parent
f498ceca1d
commit
9df541f95f
@ -175,7 +175,6 @@ table.results th.headerSortUp { background-color: #e4eeff; background-image: url
|
||||
table.results .flagged { color: red; }
|
||||
|
||||
/* pkglist: layout */
|
||||
div#pkglist-search { margin-bottom: 1.5em; }
|
||||
div#pkglist-about { margin-top: 1.5em; }
|
||||
|
||||
/* pkglist: results navigation */
|
||||
@ -184,11 +183,11 @@ div#pkglist-about { margin-top: 1.5em; }
|
||||
.pkglist-nav .prev { margin-right: 1em; }
|
||||
.pkglist-nav .next { margin-right: 1em; }
|
||||
|
||||
/* pkglist: search fields */
|
||||
#pkglist-search h3 { font-size: 1em; margin-top:0; }
|
||||
#pkglist-search div { float: left; margin-right: 1.65em; font-size: 0.85em; }
|
||||
#pkglist-search legend { display: none; }
|
||||
#pkglist-search label { width: auto; display: block; font-weight: normal; }
|
||||
/* search fields and other filter selections */
|
||||
.filter-criteria h3 { font-size: 1em; margin-top:0; }
|
||||
.filter-criteria div { float: left; margin-right: 1.65em; font-size: 0.85em; }
|
||||
.filter-criteria legend { display: none; }
|
||||
.filter-criteria label { width: auto; display: block; font-weight: normal; }
|
||||
|
||||
/* pkgdetails: details links that float on the right */
|
||||
#pkgdetails #detailslinks { float: right; }
|
||||
|
@ -44,6 +44,32 @@ def get_group_info():
|
||||
groups.extend(val.itervalues())
|
||||
return sorted(groups, key=itemgetter('name', 'arch'))
|
||||
|
||||
class Difference(object):
|
||||
def __init__(self, pkgname, repo, pkg_a, pkg_b):
|
||||
self.pkgname = pkgname
|
||||
self.repo = repo
|
||||
self.pkg_a = pkg_a
|
||||
self.pkg_b = pkg_b
|
||||
|
||||
def classes(self):
|
||||
'''A list of CSS classes that should be applied to this row in any
|
||||
generated HTML. Useful for sorting, filtering, etc. Contains whether
|
||||
this difference is in both architectures or the sole architecture it
|
||||
belongs to, as well as the repo name.'''
|
||||
css_classes = [self.repo.name.lower()]
|
||||
if self.pkg_a and self.pkg_b:
|
||||
css_classes.append('both')
|
||||
elif self.pkg_a:
|
||||
css_classes.append(self.pkg_a.arch.name)
|
||||
elif self.pkg_b:
|
||||
css_classes.append(self.pkg_b.arch.name)
|
||||
return ' '.join(css_classes)
|
||||
|
||||
def __cmp__(self, other):
|
||||
if isinstance(other, Difference):
|
||||
return cmp(self.__dict__, other.__dict__)
|
||||
return False
|
||||
|
||||
@cache_function(300)
|
||||
def get_differences_info(arch_a, arch_b):
|
||||
# This is a monster. Join packages against itself, looking for packages in
|
||||
@ -87,17 +113,17 @@ def get_differences_info(arch_a, arch_b):
|
||||
# We want arch_a to always appear first
|
||||
# pkg_a should never be None
|
||||
if pkg_a.arch == arch_a:
|
||||
item = (pkg_a.pkgname, pkg_a.repo, pkg_a, pkg_b)
|
||||
item = Difference(pkg_a.pkgname, pkg_a.repo, pkg_a, pkg_b)
|
||||
else:
|
||||
# pkg_b can be None in this case, so be careful
|
||||
name = pkg_a.pkgname if pkg_a else pkg_b.pkgname
|
||||
repo = pkg_a.repo if pkg_a else pkg_b.repo
|
||||
item = (name, repo, pkg_b, pkg_a)
|
||||
item = Difference(name, repo, pkg_b, pkg_a)
|
||||
if item not in differences:
|
||||
differences.append(item)
|
||||
|
||||
# now sort our list by repository, package name
|
||||
differences.sort(key=lambda a: (a[1].name, a[0]))
|
||||
differences.sort(key=lambda a: (a.repo.name, a.pkgname))
|
||||
return differences
|
||||
|
||||
# vim: set ts=4 sw=4 et:
|
||||
|
@ -51,6 +51,8 @@
|
||||
'django.template.loaders.app_directories.load_template_source',
|
||||
)
|
||||
|
||||
# This bug is a real bummer:
|
||||
# http://code.djangoproject.com/ticket/14105
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'main.middleware.UpdateCacheMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
|
@ -4,8 +4,30 @@
|
||||
|
||||
{% block content %}
|
||||
{% if differences %}
|
||||
<div class="box">
|
||||
<div id="differences-filter" class="box filter-criteria">
|
||||
<h2>Package Differences by Architecture</h2>
|
||||
<h3>Filter Differences View</h3>
|
||||
<form id="diff_filter" method="post" action=".">
|
||||
<fieldset>
|
||||
<legend>Select filter criteria</legend>
|
||||
<div><label for="id_archonly" title="Limit packages to selected architecture">Architecture Limitation</label>
|
||||
<select name="archonly" id="id_archonly">
|
||||
<option value="all">Show All</option>
|
||||
<option value="both">Only In Both</option>
|
||||
<option value="{{ arch_a.name }}">In {{ arch_a.name }} Only</option>
|
||||
<option value="{{ arch_b.name }}">In {{ arch_b.name }} Only</option>
|
||||
</select>
|
||||
</div>
|
||||
<div><label for="id_multilib" title="Show multilib packages"><tt>[multilib]</tt> Visible</label>
|
||||
<input type="checkbox" checked="checked" name="multilib" id="id_multilib" value="multilib"/></div>
|
||||
<div><label for="id_minor" title="Show minor version mismatches">Minor Version Mismatches</label>
|
||||
<input type="checkbox" checked="checked" name="minor" id="id_minor" value="minor"/></div>
|
||||
<div ><label> </label><input title="Reset search criteria" type="button" id="criteria_reset" value="Reset"/></div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<table class="results">
|
||||
<thead>
|
||||
<tr>
|
||||
@ -16,19 +38,19 @@ <h2>Package Differences by Architecture</h2>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for name, repo, pkg1, pkg2 in differences %}
|
||||
<tr class="{% cycle 'odd' 'even' %}">
|
||||
<td>{{ name }}</td>
|
||||
<td>{{ repo.name }}</td>
|
||||
{% if pkg1 %}
|
||||
<td><a href="{{ pkg1.get_absolute_url }}"
|
||||
title="View package details for {{ pkg1.pkgname }}">
|
||||
<span{% if pkg1.flag_date %} class="flagged"{% endif %}>{{ pkg1.pkgver }}-{{ pkg1.pkgrel }}</span></a></td>
|
||||
{% for diff in differences %}
|
||||
<tr class="{% cycle 'odd' 'even' %} {{ diff.classes }}">
|
||||
<td>{{ diff.pkgname }}</td>
|
||||
<td>{{ diff.repo.name }}</td>
|
||||
{% if diff.pkg_a %}
|
||||
<td><a href="{{ diff.pkg_a.get_absolute_url }}"
|
||||
title="View package details for {{ diff.pkg_a.pkgname }}">
|
||||
<span{% if diff.pkg_a.flag_date %} class="flagged"{% endif %}>{{ diff.pkg_a.pkgver }}-{{ diff.pkg_a.pkgrel }}</span></a></td>
|
||||
{% else %}<td>-</td>{% endif %}
|
||||
{% if pkg2 %}
|
||||
<td><a href="{{ pkg2.get_absolute_url }}"
|
||||
title="View package details for {{ pkg2.pkgname }}">
|
||||
<span{% if pkg2.flag_date %} class="flagged"{% endif %}>{{ pkg2.pkgver }}-{{ pkg2.pkgrel }}</span></a></td>
|
||||
{% if diff.pkg_b %}
|
||||
<td><a href="{{ diff.pkg_b.get_absolute_url }}"
|
||||
title="View package details for {{ diff.pkg_b.pkgname }}">
|
||||
<span{% if diff.pkg_b.flag_date %} class="flagged"{% endif %}>{{ diff.pkg_b.pkgver }}-{{ diff.pkg_b.pkgrel }}</span></a></td>
|
||||
{% else %}<td>-</td>{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@ -38,8 +60,53 @@ <h2>Package Differences by Architecture</h2>
|
||||
{% load cdn %}{% jquery %}
|
||||
<script type="text/javascript" src="/media/jquery.tablesorter.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
filter_packages = function() {
|
||||
// start with all rows, and then remove ones we shouldn't show
|
||||
var rows = $(".results tbody tr");
|
||||
if(!$('#id_multilib').is(':checked')) {
|
||||
rows = rows.not(".multilib");
|
||||
}
|
||||
var arch = $("#id_archonly").val();
|
||||
if(arch !== "all") {
|
||||
rows = rows.filter("." + arch);
|
||||
}
|
||||
if(!$('#id_minor').is(':checked')) {
|
||||
// this check is done last because it is the most expensive
|
||||
rows = rows.filter(function(index) {
|
||||
// all this just to get the split version out of the table cell
|
||||
var pat = /(.*)-(.+)/;
|
||||
var ver_a = $('td:eq(2) a', this).text().match(pat);
|
||||
var ver_b = $('td:eq(3) a', this).text().match(pat);
|
||||
// did we match at all?
|
||||
if(!ver_a || !ver_b) return true;
|
||||
// first check pkgver
|
||||
if(ver_a[1] !== ver_b[1]) return true;
|
||||
// pkgver matched, so see if rounded pkgrel matches
|
||||
if(Math.floor(parseFloat(ver_a[1])) == Math.floor(parseFloat(ver_b[1]))) return false;
|
||||
// pkgrel didn't match, so keep the row
|
||||
return true;
|
||||
});
|
||||
}
|
||||
// hide all rows, then show the set we care about
|
||||
$('.results tbody tr').hide();
|
||||
rows.show();
|
||||
// make sure we update the odd/even styling from sorting
|
||||
$('.results').trigger("applyWidgets");
|
||||
};
|
||||
filter_reset = function() {
|
||||
console.log("reset firing");
|
||||
$('#id_archonly').val("all");
|
||||
$('#id_multilib').attr("checked", "checked");
|
||||
$('#id_minor').attr("checked", "checked");
|
||||
filter_packages();
|
||||
};
|
||||
$(document).ready(function() {
|
||||
$(".results").tablesorter({widgets: ['zebra'], sortList: [[1,0], [0,0]]});
|
||||
$('.results').tablesorter({widgets: ['zebra'], sortList: [[1,0], [0,0]]});
|
||||
$('#diff_filter select').change(filter_packages);
|
||||
$('#diff_filter input').change(filter_packages);
|
||||
$('#criteria_reset').click(filter_reset);
|
||||
// fire function on page load to ensure the current form selections take effect
|
||||
filter_packages();
|
||||
});
|
||||
</script>
|
||||
{% endif %}
|
||||
|
Loading…
Reference in New Issue
Block a user