Version 29 (modified by ChrisNelson, 3 years ago) (diff)

PM configuration moved to TracPM section of trac.ini

Trac jsGantt plugin


A plugin which allows Trac ticket data to be displayed in a jsGantt chart in a wiki page. Tasks and milestones are links to the corresponding ticket or milestone.

Configurable field names allow integration with other plugins such as MasterTicketsPlugin (for dependencies), SubticketsPlugin (for parent/child relationships) and TimingAndEstimationPlugin (for estimated and total hours).


[[TracJSGanttChart(sample=1)]] displays the sample project from [[TracJSGanttChart(milestone=Test)]] displays all the tickets in the Test milestone.

jsGantt sample tasks in a wiki page


The chart display can be controlled with a number of macro arguments:

Argument Version Description Default
caption Caption to place to right of tasks: None, Caption, Resource, Duration, %Complete Resource
comp Show (1) percent complete column, or do not (0). 1
colorBy Field to use to color tasks. Useful fields are priority, owner and milestone but any field can be used. priority
dur Show (1) duration colunn, or do not (0). 1
dateDisplay Format to display dates: mm/dd/yyyy, dd/mm/yyyy, or yyyy-mm-dd mm/dd/yyyy
endDate Show (1) end date column, or do not (0). 1
expandClosedTickets0.9Show (1) children of closed tickets in the task hierarchy or collapse the subtree (0). 1
format Initial display format, one of those listed in formats day
formatsFormats to show for Gantt chart. A pipe-separated list of minute, hour, day, week, month, and quarter. day|week|month|quarter
goal 0.9 Ticket(s) to show predecessors of. When using something like MasterTicketsPlugin to maintain ticket dependencies, you may create a Gantt showing a ticket and all of its predecessors with goal=<ticket#>. The macro uses the configured succ field to find all predecessor tasks and build an id= argument for Trac's native query handler.

Multiple goals may be provided like goal=1|12|32.

When used in a ticket description or comment, goal=self will display the current ticket's predecessors.
hoursPerDay Hours worked per day 8.0
lwidth Width (in pixels) of left table (The one contains task names, etc. on the left of the Gantt chart.) None
omitMilestones0.8Show milestones for displayed tickets (0) or only those specified by milestone= (1). 0
openLevel How many levels of task hierarchy to show open. 1 = only top level task. 999
res Show (1) resource column, or do not (0). 1
root Ticket(s) to show descendants of. When using something like Subtickets plugin to maintain a tree of tickets and subtickets, you may create a Gantt showing a ticket and all of its descendants with root=<ticket#>. The macro uses the configured parent field to find all descendant tasks and build an id= argument for Trac's native query handler.

Multiple roots may be provided like root=1|12|32.

When used in a ticket description or comment, root=self will display the current ticket's descendants.
sample Display (1) sample tasks in Gantt, or do not (0) 0
schedule Schedule algorithm: as-last-as-possible (alap) or as-soon-as-possible (asap) alap
showdep Show (1) dependencies in Gantt, or do not (0). 1
startDate Show (1) start date column, or do not (0). 1
userMap0.8Map (1) user IDs to full names, or do not (0). 1

Site-wide defaults for macro arguments may be set in trac.ini. option.<opt> overrides the built-in default for <opt> from the table above.

All other macro arguments are treated as TracQuery specification (e.g., milestone=MS1|MS2) to control which tickets are displayed.


  1. Install globally with:
      sudo easy_install
  2. Enable the plugin by updating TracIni file (..../trac.ini) as follows:
      tracjsgantt.* = enabled
  3. Configure the project management support for the plugin in its own configuration section, placed into 'trac.ini' file as follows:
      # To work with Timing and Estimation for percent complete
      ## Ticket field to use as the data source for estimated work (default: None)
      fields.estimate = estimatedhours
      ## Ticket field to use as the data source for completed work (default: None)
      fields.worked = totalhours
      # Each unit in estimate is 1/8 of a day
      days_per_estimate = 0.125
      # To work with Master Tickets for dependencies
      ## Ticket field to use as the data source for predecessor list
      fields.pred = blockedby
      ## Ticket field to use as the data source for successor list
      fields.succ = blocking
      # To work with Subtickets for parent/child relationships
      ## Ticket field to use as the data source for the parent parent_format', '%s', Format of ticket IDs in parent field (default: None).
      fields.parent = parents
      # To work with ChildTickets plugin
      # parent_format = #%s
      # Custom fields for start and due dates
      ## Ticket field to use as the data source for start date (default: None)
      fields.start = userstart
      ## Ticket field to use as the data source for finish date (default: None)
      fields.finish = userfinish
      # Format for ''start'' and ''finish'' date strings (default: '%Y-%m-%d')
      date_format = %Y-%m-%d
      # Ticket type for milestone-like tickets (default: 'milestone')
      milestone_type = milestone
      # Ticket field to use as the data source for the percent complete column (default: None).
      # fields.percent =
      # Hours represented by each unit of estimated work (default: 1).
      # hours_per_estimate = 1
      # Default work for an unestimated task, same units as estimate  (default: 4.0).
      # default_estimate = 4.0
      # How much work may be remaining when a task goes over estimate, same units as estimate (default: 0.0)..
      # estimate_pad = 0.0
  4. Restart web server on command line:
        $ sudo /etc/init.d/apache2 restart

Configuration details

TracJsGanttPlugin is intended to be flexible enough to get data from various plugins by configuring the field names for those plugins in trac.ini. It is known to work with TimingAndEstimationPlugin (for estimated and total hours), MasterTicketsPlugin (for FS dependencies), and SubticketsPlugin for parent/child relationships. Custom fields for start and finish date are also supported.

Tasks are colored based on ticket attributes. When colored by priority colors are consistent with the colors used in Trac reports. Other coloring choices (e.g., by milestone or owner) use arbitrary, unique colors.

All of the fields.* items name custom fields which may contain data for the Gantt.

When estimate and worked are both configured, the plugin attempts to display (100 * worked/estimate) as the percent complete. The example works with TimingAndEstimationPlugin. Alternatively, if percent is configured, the plugin attempts to display it as the percent complete (it should be a number from 0 to 100). If none of those are configured, all tasks will be marked as 0% complete.

When pred and succ are configured the plugin uses them to determine the task dependencies. The example works with MasterTicketsPlugin. If these fields are not configured, no dependencies are shown.

When parent is configured, it is the field which holds the parent ticket number. The example works with Subtickets. If this field is not configured, no parent/child relationship will be displayed. If it is configured, the Gantt can be collapsed by the user to show or hide subtasks. (parent_format determines the format of the content of the parent field. Use "%s" (default) for SubticketsPlugin, "#%s" for ChildTicketsPlugin.)

When start and finish are configured, the plugin uses them to set task start and finish dates. The date_format field is a Python strptime() format specifier which describes the contents of start and finish. If these fields are not configured, all tasks end today and have a 1-day duration.

When estimate and finish are both configured (and start is not configured or not on the ticket), the plugin attempts to determine the start of the task from finish and estimate as start = finish - estimate with consideration for weekends and hours per day.

The milestone_type may be used to have a custom ticket type show up as milestones on the chart. If this field is not specified, only Trac milestones are displayed as milestones.

Bugs/Feature Requests

Existing bugs and feature requests for TracJsGanttPlugin are here.

If you have any issues, create a new ticket.

Known issues

Planned enhancements

  1. Display a legend of task colors and their meaning (e.g., which milestone or owner they represent).
  2. Allow some tasks to be open or closed by default.
  3. Display critical path
  4. Display slack time

Source & Download

You can check out TracJsGanttPlugin from here using Subversion, or browse the source with Trac.

Download the zipped source from here.

Recent Changes

[14016] by rjollos on 2014-07-23 21:28:33
Added license text and file headers. Tidied up indentation. Refs #11871.
[13868] by ChrisNelson on 2014-04-24 16:38:38
Use executemany() when inserting multiple rows. Refs #11027.

Required for cross-db compatibility.

Light testing shows this still works for me in PostgreSQL so it
doesn't seem I broke anything. I need SQLite feedback, though.

[13853] by ChrisNelson on 2014-04-16 22:43:53
Remove comment that has been addressed. Refs #11489.
[13852] by ChrisNelson on 2014-04-16 22:41:44
Handle collapsing groups on multi-Gantt pages. Refs #11489.

Needed to add the chart ID to more DOM element IDs for uniqueness.

[13842] by ChrisNelson on 2014-04-09 13:55:57
Don't schedule closed tickets in background rescheduler. Refs #9648.

Also add some logging.

[13841] by ChrisNelson on 2014-04-09 13:55:54
Simplify interface to prune and repair routines. Refs #9648.
[13840] by ChrisNelson on 2014-04-09 13:55:51
Factor our graph repair. Refs #9648.
[13839] by ChrisNelson on 2014-04-09 13:55:48
Rewrite algorithm to identify tickets to reschedule. Refs #9648.

This is a shorter, cleaner algorithm:

  • Find what's active now
  • Find what was active
  • wasActive - isActive should be idled
  • isActive should be rescheduled
    • Save only if schedule changes

It also works. ;-) With the old algorithm if you has two goals scheduled
and interrupted the earlier one, the tasks for the second goal weren't
moved up. The code to find active and idled tickets was weak and
fragile and not worth fixing since it was also slow. In general, this
new approach handles a lot less data, defers getting ticket details as
long as possible, and gets them for many fewer tickets. In my
playground, I used to query 150 tickets (basically, everything in the
database) and now I query 4-5 tickets (the active set). I expect that
ratio to scale to production. Since querying for ticket details was the
longest part of rescheduling, this is much, much faster than the old

[13838] by ChrisNelson on 2014-04-09 13:55:45
Factor out schedule and schedule_change update. Refs #9648.

This makes the code which finds affected tickets clearer, closer.

[13837] by ChrisNelson on 2014-04-09 13:55:42
Use numerical precedence levels for start/finish sources. Refs #9648.

Before a date was either explicit or not. Values in the database
(actual start/finish dates, previously scheduled values, and explicit
user-supplied values) were all explicit so a test for "better" between
an old schedule table value and a new actual value were not resolved.
Now each source of a date has a different precedence so we have enough
information to resolve a conflict.

The way dates were calculated, we should not have seen conflicts in
new values, only in the explicit ones. This change allows an actual
start to be higher precedence than a previously-scheduled finish.
However, there is still the potential conflict between items of the
same precedence.

  • Two actual values should never be wrong (we can't finish before we start)
  • Two scheduled values should never be wrong if we never save bad values
  • If two user-supplied values are wrong, it's data entry, not

algorithm. We could validate this away but we don't currently even
allow explicit start dates.


Author: ChrisNelson
Maintainer: ChrisNelson
Contributors: rjollos, bof, Matt Sable

Attachments (1)

Download all attachments as: .zip