You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bloodhound.apache.org by gj...@apache.org on 2012/06/01 14:44:33 UTC

svn commit: r1345132 - in /incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets: templates/widget_cloud.html ticket.py

Author: gjm
Date: Fri Jun  1 12:44:33 2012
New Revision: 1345132

URL: http://svn.apache.org/viewvc?rev=1345132&view=rev
Log:
dashbard: support for TracQuery language in TicketFieldCloudWidget - towards #93 (from olemis)

Modified:
    incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/templates/widget_cloud.html
    incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/ticket.py

Modified: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/templates/widget_cloud.html
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/templates/widget_cloud.html?rev=1345132&r1=1345131&r2=1345132&view=diff
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/templates/widget_cloud.html (original)
+++ incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/templates/widget_cloud.html Fri Jun  1 12:44:33 2012
@@ -8,11 +8,22 @@
   <p style="font-size: medium; line-height: 150%;">
     <py:for each="item in items"
         py:with="_max = bounds.max + 1; _min = bounds.min" >
-      <a href="${item_link(item)}" 
-          style="font-size: ${int(28 - (13 / (_max - _min)) * (_max - item[1] - 1) )}px">
-        ${item[0]} <py:if test="verbose">(${item[1]})</py:if>
-      </a>
-      &nbsp;&nbsp;
+      <py:if test="item[1] > 0">
+        <a href="${item_link(item)}" 
+            style="font-size: ${int(28 - (13 / (_max - _min)) * (_max - item[1] - 1) )}px">
+          <py:choose test="item[0]">
+            <py:when test="None">
+              <span class="label">empty</span>
+            </py:when>
+            <py:when test="''">
+              <span class="label">empty</span>
+            </py:when>
+            <py:otherwise>${item[0]}</py:otherwise>
+          </py:choose>
+          <py:if test="verbose">(${item[1]})</py:if>
+        </a>
+        &nbsp;&nbsp;
+      </py:if>
     </py:for>
   </p>
 </div>

Modified: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/ticket.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/ticket.py?rev=1345132&r1=1345131&r2=1345132&view=diff
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/ticket.py (original)
+++ incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/ticket.py Fri Jun  1 12:44:33 2012
@@ -25,11 +25,13 @@ Widgets displaying ticket data.
 """
 
 from itertools import imap, islice
+from urllib import urlencode
 
 from genshi.builder import tag
 from genshi.core import Markup
 from trac.core import implements, TracError
 from trac.ticket.api import TicketSystem
+from trac.ticket.query import Query
 from trac.ticket.roadmap import apply_ticket_permissions, get_ticket_stats, \
                             ITicketGroupStatsProvider, RoadmapModule
 from trac.util.translation import _
@@ -53,8 +55,11 @@ class TicketFieldCloudWidget(WidgetBase)
         """
         return {
                 'field' : {
-                        'desc' : """Target ticket field""",
-                        'required' : True,
+                        'desc' : """Target ticket field. """
+                                """Required if no group in `query`.""",
+                    },
+                'query' : {
+                        'desc' : """TracQuery used to filter target tickets.""",
                     },
                 'title' : {
                         'desc' : """Widget title""",
@@ -80,79 +85,107 @@ class TicketFieldCloudWidget(WidgetBase)
         """Count ocurrences of values assigned to given ticket field.
         """
         req = context.req
-        params = ('field', 'verbose', 'threshold', 'max', 'title')
-        fieldnm, verbose, threshold, maxitems, title = \
+        params = ('field', 'query', 'verbose', 'threshold', 'max', 'title')
+        fieldnm, query, verbose, threshold, maxitems, title = \
                 self.bind_params(name, options, *params)
-        tsys = self.env[TicketSystem]
-        if tsys is None:
-            raise TracError(_('Error loading ticket system (disabled?)'))
-        for field in tsys.get_ticket_fields():
-            if field['name'] == fieldnm:
-                break
-        else:
-            field_maps = {'type': {'admin_url': 'type',
-                                   'title': 'Types',
-                                   },
-                          'status': {'admin_url': 'status',
-                                     'title': 'Statuses',
-                                     },
-                          'priority': {'admin_url': 'priority',
-                                       'title': 'Priorities',
-                                       },
-                          'milestone': {'admin_url': 'milestones',
-                                        'title': 'Milestones',
-                                        },
-                          'component': {'admin_url': 'components',
-                                        'title': 'Components',
-                                        },
-                          'version': {'admin_url': 'versions',
-                                      'title': 'Versions',
-                                      },
-                          'severity': {'admin_url': 'severity',
-                                       'title': 'Severities',
+        if query is None :
+            if fieldnm is None:
+                raise InvalidWidgetArgument('field', 'Missing ticket field')
+            tsys = self.env[TicketSystem]
+            if tsys is None:
+                raise TracError(_('Error loading ticket system (disabled?)'))
+            for field in tsys.get_ticket_fields():
+                if field['name'] == fieldnm:
+                    break
+            else:
+                field_maps = {'type': {'admin_url': 'type',
+                                       'title': 'Types',
                                        },
-                          'resolution': {'admin_url': 'resolution',
-                                         'title': 'Resolutions',
+                              'status': {'admin_url': 'status',
+                                         'title': 'Statuses',
                                          },
-                          }
-            if fieldnm in field_maps.keys():
-                if 'TICKET_ADMIN' in req.perm:
-                    hint = _('You can add one or more '
-                             '<a href="%(url)s">here</a>',
-                            url=req.href.admin('ticket', 
-                                        field_maps[fieldnm]['admin_url']))
+                              'priority': {'admin_url': 'priority',
+                                           'title': 'Priorities',
+                                           },
+                              'milestone': {'admin_url': 'milestones',
+                                            'title': 'Milestones',
+                                            },
+                              'component': {'admin_url': 'components',
+                                            'title': 'Components',
+                                            },
+                              'version': {'admin_url': 'versions',
+                                          'title': 'Versions',
+                                          },
+                              'severity': {'admin_url': 'severity',
+                                           'title': 'Severities',
+                                           },
+                              'resolution': {'admin_url': 'resolution',
+                                             'title': 'Resolutions',
+                                             },
+                              }
+                if fieldnm in field_maps.keys():
+                    if 'TICKET_ADMIN' in req.perm:
+                        hint = _('You can add one or more '
+                                 '<a href="%(url)s">here</a>',
+                                url=req.href.admin('ticket', 
+                                            field_maps[fieldnm]['admin_url']))
+                    else:
+                        hint = _('Contact your administrator for further details')
+                    return 'widget_alert.html', \
+                            {
+                                'title' : Markup(_('%(field)s',
+                                            field=field_maps[fieldnm]['title'])),
+                                'data' : dict(msgtype='info',
+                                    msglabel="Note",
+                                    msgbody=Markup(_('''There is no value defined
+                                        for ticket field <em>%(field)s</em>. 
+                                        %(hint)s''', field=fieldnm, hint=hint) )
+                                    )
+                            }, context
                 else:
-                    hint = _('Contact your administrator for further details')
-                return 'widget_alert.html', \
-                        {
-                            'title' : Markup(_('%(field)s',
-                                        field=field_maps[fieldnm]['title'])),
-                            'data' : dict(msgtype='info',
-                                msglabel="Note",
-                                msgbody=Markup(_('''There is no value defined
-                                    for ticket field <em>%(field)s</em>. 
-                                    %(hint)s''', field=fieldnm, hint=hint) )
-                                )
-                        }, context
+                    raise InvalidWidgetArgument('field', 
+                            'Unknown ticket field %s' % (fieldnm,))
+            if field.get('custom'):
+                sql = "SELECT value, count(value) FROM ticket_custom " \
+                        "WHERE name='%(name)s' GROUP BY value"
             else:
-                raise InvalidWidgetArgument('field', 
-                        'Unknown ticket field %s' % (fieldnm,))
-        if field.get('custom'):
-            sql = "SELECT value, count(value) FROM ticket_custom " \
-                    "WHERE name='%(name)s' GROUP BY value"
+                sql = "SELECT %(name)s, count(%(name)s) FROM ticket " \
+                        "GROUP BY %(name)s"
+            sql = sql % field
+            # TODO : Implement threshold and max
+            db = self.env.get_db_cnx()
+            try :
+                cursor = db.cursor()
+                cursor.execute(sql)
+                items = cursor.fetchall()
+            finally:
+                cursor.close()
+
+            QUERY_COLS = ['id', 'summary', 'owner', 'type', 'status', 'priority']
+            item_link= lambda item: req.href.query(col=QUERY_COLS + [fieldnm], 
+                                                    **{fieldnm:item[0]})
         else:
-            sql = "SELECT %(name)s, count(%(name)s) FROM ticket " \
-                    "GROUP BY %(name)s"
-        sql = sql % field
-        # TODO : Implement threshold and max
-        db = self.env.get_db_cnx()
-        cursor = db.cursor()
-        cursor.execute(sql)
-        items = cursor.fetchall()
-
-        QUERY_COLS = ['id', 'summary', 'owner', 'type', 'status', 'priority']
-        item_link= lambda item: req.href.query(col=QUERY_COLS + [fieldnm], 
-                                                **{fieldnm:item[0]})
+            query = Query.from_string(self.env, query, group=fieldnm)
+            if query.group is None:
+                raise InvalidWidgetArgument('field', 
+                        'Invalid ticket field for ticket groups')
+            fieldnm = query.group
+            sql, v = query.get_sql() 
+            sql = 'SELECT %(name)s , count(%(name)s) ' \
+                    'FROM (%(sql)s) GROUP BY %(name)s' % \
+                    { 'name' : fieldnm, 'sql' : sql }
+            db = self.env.get_db_cnx()
+            try :
+                cursor = db.cursor()
+                cursor.execute(sql, v)
+                items = cursor.fetchall()
+            finally:
+                cursor.close()
+
+            query_href = query.get_href(req.href)
+            item_link= lambda item: query_href + \
+                    '&' + urlencode([(fieldnm, item[0])])
+
         return 'widget_cloud.html', \
                 {
                     'title' : title,