diff options
author | Tim Laszlo <tim.laszlo@gmail.com> | 2012-06-01 17:05:58 -0500 |
---|---|---|
committer | Tim Laszlo <tim.laszlo@gmail.com> | 2012-06-01 17:06:16 -0500 |
commit | b7977ff7b228802ffd2b82bfd446b6afc6e8a091 (patch) | |
tree | b17b989f74b611c8d0eda29791e283ccf208fe1f /src | |
parent | 82388019f6d271e954c07260ed3a4578cc0c47e4 (diff) | |
download | bcfg2-b7977ff7b228802ffd2b82bfd446b6afc6e8a091.tar.gz bcfg2-b7977ff7b228802ffd2b82bfd446b6afc6e8a091.tar.bz2 bcfg2-b7977ff7b228802ffd2b82bfd446b6afc6e8a091.zip |
bcfg2-web: D=Make detailed client list sortable
Diffstat (limited to 'src')
3 files changed, 135 insertions, 9 deletions
diff --git a/src/lib/Bcfg2/Server/Reports/reports/templates/clients/detailed-list.html b/src/lib/Bcfg2/Server/Reports/reports/templates/clients/detailed-list.html index 84ac71d92..005c8b998 100644 --- a/src/lib/Bcfg2/Server/Reports/reports/templates/clients/detailed-list.html +++ b/src/lib/Bcfg2/Server/Reports/reports/templates/clients/detailed-list.html @@ -10,14 +10,14 @@ {% filter_navigator %} <table cellpadding="3"> <tr id='table_list_header' class='listview'> - <td class='left_column'>Node</td> - <td class='right_column' style='width:75px'>State</td> - <td class='right_column_narrow'>Good</td> - <td class='right_column_narrow'>Bad</td> - <td class='right_column_narrow'>Modified</td> - <td class='right_column_narrow'>Extra</td> - <td class='right_column'>Last Run</td> - <td class='right_column_wide'>Server</td> + <td class='left_column'>{% sort_link 'client' 'Node' %}</td> + <td class='right_column' style='width:75px'>{% sort_link 'state' 'State' %}</td> + <td class='right_column_narrow'>{% sort_link '-good' 'Good' %}</td> + <td class='right_column_narrow'>{% sort_link '-bad' 'Bad' %}</td> + <td class='right_column_narrow'>{% sort_link '-modified' 'Modified' %}</td> + <td class='right_column_narrow'>{% sort_link '-extra' 'Extra' %}</td> + <td class='right_column'>{% sort_link 'timestamp' 'Last Run' %}</td> + <td class='right_column_wide'>{% sort_link 'server' 'Server' %}</td> </tr> {% for entry in entry_list %} <tr class='{% cycle listview,listview_alt %}'> diff --git a/src/lib/Bcfg2/Server/Reports/reports/templatetags/bcfg2_tags.py b/src/lib/Bcfg2/Server/Reports/reports/templatetags/bcfg2_tags.py index ac63cda3e..d65833c48 100644 --- a/src/lib/Bcfg2/Server/Reports/reports/templatetags/bcfg2_tags.py +++ b/src/lib/Bcfg2/Server/Reports/reports/templatetags/bcfg2_tags.py @@ -1,9 +1,14 @@ import sys +from copy import copy from django import template +from django.conf import settings from django.core.urlresolvers import resolve, reverse, \ Resolver404, NoReverseMatch +from django.template.loader import get_template, \ + get_template_from_string,TemplateDoesNotExist from django.utils.encoding import smart_unicode, smart_str +from django.utils.safestring import mark_safe from datetime import datetime, timedelta from Bcfg2.Server.Reports.utils import filter_list @@ -311,3 +316,98 @@ def determine_client_state(entry): else: thisdirty = "very-dirty-lineitem" return thisdirty + + +@register.tag(name='qs') +def do_qs(parser, token): + """ + qs tag + + accepts a name value pair and inserts or replaces it in the query string + """ + try: + tag, name, value = token.split_contents() + except ValueError: + raise TemplateSyntaxError, "%r tag requires exactly two arguments" \ + % token.contents.split()[0] + return QsNode(name, value) + +class QsNode(template.Node): + def __init__(self, name, value): + self.name = template.Variable(name) + self.value = template.Variable(value) + + def render(self, context): + try: + name = self.name.resolve(context) + value = self.value.resolve(context) + request = context['request'] + qs = copy(request.GET) + qs[name] = value + return "?%s" % qs.urlencode() + except template.VariableDoesNotExist: + return '' + except KeyError: + if settings.TEMPLATE_DEBUG: + raise Exception, "'qs' tag requires context['request']" + return '' + except: + return '' + + +@register.tag +def sort_link(parser, token): + ''' + Create a sort anchor tag. Reverse it if active. + + {% sort_link sort_key text %} + ''' + try: + tag, sort_key, text = token.split_contents() + except ValueError: + raise TemplateSyntaxError("%r tag requires at least four arguments" \ + % token.split_contents()[0]) + + return SortLinkNode(sort_key, text) + +class SortLinkNode(template.Node): + __TMPL__ = "{% load bcfg2_tags %}<a href='{% qs 'sort' key %}'>{{ text }}</a>" + + def __init__(self, sort_key, text): + self.sort_key = template.Variable(sort_key) + self.text = template.Variable(text) + + def render(self, context): + try: + try: + sort = context['request'].GET['sort'] + except KeyError: + #fall back on this + sort = context.get('sort', '') + sort_key = self.sort_key.resolve(context) + text = self.text.resolve(context) + + # add arrows + try: + sort_base = sort_key.lstrip('-') + if sort[0] == '-' and sort[1:] == sort_base: + text = text + '▼' + sort_key = sort_base + elif sort_base == sort: + text = text + '▲' + sort_key = '-' + sort_base + except IndexError: + pass + + context.push() + context['key'] = sort_key + context['text'] = mark_safe(text) + output = get_template_from_string(self.__TMPL__).render(context) + context.pop() + return output + except: + if settings.DEBUG: + raise + raise + return '' + diff --git a/src/lib/Bcfg2/Server/Reports/reports/views.py b/src/lib/Bcfg2/Server/Reports/reports/views.py index ccd71a60e..fd6f5443a 100644 --- a/src/lib/Bcfg2/Server/Reports/reports/views.py +++ b/src/lib/Bcfg2/Server/Reports/reports/views.py @@ -18,6 +18,9 @@ from django.db import connection from Bcfg2.Server.Reports.reports.models import * +__SORT_FIELDS__ = ( 'client', 'state', 'good', 'bad', 'modified', 'extra', \ + 'timestamp', 'server' ) + class PaginationError(Exception): """This error is raised when pagination cannot be completed.""" pass @@ -177,8 +180,29 @@ def client_detailed_list(request, timestamp=None, **kwargs): """ + try: + sort = request.GET['sort'] + if sort[0] == '-': + sort_key = sort[1:] + else: + sort_key = sort + if not sort_key in __SORT_FIELDS__: + raise ValueError + + if sort_key == "client": + kwargs['orderby'] = "%s__name" % sort + elif sort_key == "good": + kwargs['orderby'] = "%scount" % sort + elif sort_key in ["bad", "modified", "extra"]: + kwargs['orderby'] = "%s_entries" % sort + else: + kwargs['orderby'] = sort + kwargs['sort'] = sort + except (ValueError, KeyError): + kwargs['orderby'] = "client__name" + kwargs['sort'] = "client" + kwargs['interaction_base'] = Interaction.objects.interaction_per_client(timestamp).select_related() - kwargs['orderby'] = "client__name" kwargs['page_limit'] = 0 return render_history_view(request, 'clients/detailed-list.html', **kwargs) @@ -349,6 +373,8 @@ def render_history_view(request, template='clients/history.html', **kwargs): if 'orderby' in kwargs and kwargs['orderby']: iquery = iquery.order_by(kwargs['orderby']) + if 'sort' in kwargs: + context['sort'] = kwargs['sort'] if 'state' in kwargs and kwargs['state']: iquery = iquery.filter(state__exact=kwargs['state']) |