source: trunk/trac-hacks/progressmetermacro/progressmeter/macro.py @ 448

Revision 448, 3.7 KB checked in by dgynn, 5 years ago (diff)

updating non-modified trac-hacks to  th:changeset:4267

Line 
1# -*- coding: utf-8 -*-
2"""
3Progress meter macro plugin for Trac.
4"""
5
6from genshi.builder import tag
7
8from trac.core import *
9from trac.wiki.api import IWikiMacroProvider, parse_args
10from trac.web.chrome import add_stylesheet, ITemplateProvider
11from trac.wiki.macros import WikiMacroBase
12from trac.ticket.query import Query
13
14
15__all__ = ['ProgressMeterMacro']
16
17class ProgressMeterMacro(WikiMacroBase):
18    """
19    ProgressMeter (wiki macro) plugin
20    Usage and installation instructions can be found at:
21        http://trac-hacks.org/wiki/ProgressMeterMacro
22    """
23    implements(IWikiMacroProvider, ITemplateProvider)
24
25    # IWikiMacroProvider methods
26    def expand_macro(self, formatter, name, content):
27        # Stripping content -- allows using spaces within arguments --
28        # and checking whether there is not argument 'status'
29        content = ','.join([x.strip() for x in content.split(',') if not x.strip().startswith('status')])
30
31        # Parsing arguments (copied from ticket/query.py from standard trac distribution)
32        # suggested by dhellman
33        req = formatter.req
34        query_string = ''
35        argv, kwargs = parse_args(content, strict=False)
36        if len(argv) > 0 and not 'ticket_value' in kwargs: # 0.10 compatibility hack
37            kwargs['ticket_value'] = argv[0]
38
39        ticket_value = kwargs.pop('ticket_value', 'list').strip().lower()
40        query_string = '&'.join(['%s=%s' % item for item in kwargs.iteritems()])
41        cnt = {}
42        qs_add = {'total': '', 'closed': '&status=closed', 'active': '&status=!closed'}
43        for key in ('closed', 'total'):
44            query = Query.from_string(self.env, query_string + qs_add[key])
45            tickets = query.execute(req)
46            cnt[key] = (tickets and len(tickets) or 0)
47
48        # calculate the number of active tickets
49        cnt['active'] = cnt['total'] - cnt['closed']
50
51        # Getting percent of active/closed tickets
52        percents = {'closed': float(cnt['closed']) / float(cnt['total'])}
53        percents['active'] = 1 - percents['closed']
54
55        add_stylesheet(formatter.req, 'progressmeter/css/progressmeter.css')
56
57        main_div = tag.div(class_='milestone')
58
59        # Add title above progress bar
60        argv and main_div.children.append(tag.h2(argv))
61
62        # Add progress bar
63        table = tag.table(class_='progress')(tag.tr())
64
65        for key in reversed(percents.keys()):
66            # reversing because we want the closed tickets to be processed firstly
67            percents[key] = unicode(int(percents[key] * 100)) + u'%'
68            table.children[0](tag.td(style='width: '+percents[key], class_=key)
69              (tag.a(title="%i of %i tickets %s" % (cnt[key], cnt['total'], key.title()),
70              href="%s?%s" % (formatter.href.query(),query_string + qs_add[key]))))
71        main_div.children.append(table)
72
73        # Add percentage displaied to the right of the progress bar
74        percent_para = tag.p(class_='percent')(percents['closed'])
75        main_div.children.append(percent_para)
76
77        # Add ticket count below progress bar
78        ticket_count = tag.dl()
79
80        for key in qs_add.keys():
81            ticket_count.children.append(tag.dt()("%s tickets:" % key.title()))
82            ticket_count.children.append(tag.dd()(tag.a(str(cnt[key]),
83              href="%s?%s" % (formatter.href.query(), query_string + qs_add[key]))))
84        main_div.children.append(ticket_count)
85
86        return main_div
87
88
89    # ITemplateProvider methods
90    def get_htdocs_dirs(self):
91        """ Makes the 'htdocs' folder available for Trac. """
92        from pkg_resources import resource_filename
93        return [('progressmeter', resource_filename('progressmeter', 'htdocs'))]
94
95    def get_templates_dirs(self):
96        return []  # must return an iterable
97
Note: See TracBrowser for help on using the repository browser.