Schneimi’s Dev Weblog


Trac SubticketsPlugin with progress bar and report

Posted in Trac by schneimi on February 2, 2013
Tags: , , ,

I came across the problem, that I needed a sub-ticket plugin for Trac v1.0. I found the SubTicketPlugin for TRAC on trac-hacks.org but also the ChildTicketsPlugin, that comes along with a very neat progress meter for parent tickets, but unfortunately is not yet available for Trac v1.0.

Because I wanted it so much, I searched for a way of having such a progress meter with the SubTicketPlugin. Then finally I found a way of building a site template for Trac, where the progress meter is displayed conditionally. It’s not that easy to understand and also uses some inline python code to cover all conditions, but it should work without further explanation. Just place the site.html in the /templates folder of your trac project.

ticket_view


/templates/site.html

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:xi="http://www.w3.org/2001/XInclude"
      xmlns:py="http://genshi.edgewall.org/"
      py:strip="">
<div py:match="div[@class='description']" py:attrs="select('@*')">
  ${select('*')}
  <?python
    subticketCount = 0
    if 'ticket' in vars() and ticket.id != None:
      from trac.env import open_environment
      env = open_environment('D:\Development\TRAC\myapp')
      with env.db_query as db:
          cursor = db.cursor()
          cursor.execute(''.join(["SELECT count(*) FROM subtickets WHERE parent=", str(ticket.id)]))
          for row in cursor:
            subticketCount=row[0]
  ?>
  <py:if test="subticketCount > 0">
    <h3>Progress </h3>
    ${wiki_to_html(context, ''.join(["[[TicketQuery(format=progress,parents=", str(ticket.id), ')]]']))}
  </py:if>
</div>
</html>

I also developed a custom report, showing the tickets and their sub-tickets.

ticket_query

SELECT p.value AS __color__,
       id AS ticket,
       (SELECT GROUP_CONCAT(summary) FROM ticket WHERE id = parent) AS __group__,
       summary,
       component, version, milestone,
       t.type AS type,
       owner, status,
       CONCAT(ROUND(100 / (SELECT COUNT(*) FROM subtickets WHERE parent=t.id) * (SELECT COUNT(*) FROM subtickets INNER JOIN ticket ON (child=ticket.id ) WHERE parent=t.id AND status='closed')), "%") AS progress,
       CASE WHEN (SELECT COUNT(*) FROM subtickets WHERE parent=t.id) > 0 THEN 'border-bottom:solid 3px #DDD;border-top: solid 3px #DDD;background-color: #DDD' ELSE 'text-indent: 10px' END AS __style__,
       time AS created,
       changetime AS _changetime,
       description AS _description,
       reporter AS _reporter
  FROM subtickets s
  LEFT JOIN ticket AS t ON (parent =  t.id)
  LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority'
  WHERE status <> 'closed'
  GROUP BY ticket
UNION
  SELECT  p.value AS __color__,
       id AS ticket,
       (SELECT GROUP_CONCAT(summary) FROM ticket WHERE id = parent) AS __group__,
       summary,
       component, version, milestone,
       t.type AS type,
       owner, status,
       CONCAT(ROUND(100 / (SELECT COUNT(*) FROM subtickets WHERE parent=t.id) * (SELECT COUNT(*) FROM subtickets INNER JOIN ticket ON (child=ticket.id ) WHERE parent=t.id AND status='closed')), "%") AS progress,
       CASE WHEN (SELECT COUNT(*) FROM subtickets WHERE parent=t.id) > 0 THEN 'border-bottom:solid 3px #DDD;border-top:solid 3px #DDD;background-color: #DDD' ELSE 'text-indent: 10px' END AS __style__,
       time AS created,
       changetime AS _changetime,
       description AS _description,
       reporter AS _reporter
  FROM subtickets s
  LEFT JOIN ticket AS t ON (child = id)
  LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority'
  WHERE status <> 'closed'
  GROUP BY ticket
ORDER BY __group__ DESC

Advertisements