diff options
author | Dan McGee <dan@archlinux.org> | 2010-09-07 16:04:56 -0500 |
---|---|---|
committer | Dan McGee <dan@archlinux.org> | 2010-09-08 00:09:13 -0500 |
commit | 9df541f95f12d2fad5c9911008882b7ff35a9514 (patch) | |
tree | a41c05af3448e3ae49acd4d413fd9f51653e5e7f | |
parent | f498ceca1de3b3db0b96007b33eed620702acce9 (diff) |
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>
-rw-r--r-- | media/archweb.css | 11 | ||||
-rw-r--r-- | packages/utils.py | 32 | ||||
-rw-r--r-- | settings.py | 2 | ||||
-rw-r--r-- | templates/packages/differences.html | 95 |
4 files changed, 117 insertions, 23 deletions
diff --git a/media/archweb.css b/media/archweb.css index e5e5e6e0..f417e5ee 100644 --- a/media/archweb.css +++ b/media/archweb.css @@ -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; } diff --git a/packages/utils.py b/packages/utils.py index 204e5bf2..55b7acf9 100644 --- a/packages/utils.py +++ b/packages/utils.py @@ -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 @@ SELECT p.id, q.id # 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: diff --git a/settings.py b/settings.py index b1ad20ec..6e98adce 100644 --- a/settings.py +++ b/settings.py @@ -51,6 +51,8 @@ TEMPLATE_LOADERS = ( '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', diff --git a/templates/packages/differences.html b/templates/packages/differences.html index 1c3e97e3..4c3b43c6 100644 --- a/templates/packages/differences.html +++ b/templates/packages/differences.html @@ -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 @@ </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 @@ {% 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 %} |