TracGanttCalendarプラグイン をカスタマイズ(Trac 0.10)
会社で運用しているTracのバージョンはいまだに 0.10 です。
この記事も、Trac 0.10とTracGanttCalendarプラグインの0.10 brancheについてのものです。
- TracGanttCalendarプラグイン
- インストール方法
- 詳しい説明は以下
- ソースをShibuya.tracのSVNからチェックアウトします
svn checkout http://svn.sourceforge.jp/svnroot/shibuya-trac/plugins/ganttcalendarplugin/branches/0.10
ガントチャートが出ると、便利です!
超有用なこのプラグインですが、次のような不満があったりします。。
- チケットの並び順が...
- チケット番号順でもない(?)です。できれば開始日で並べ替えると、前後関係が把握しやすくて吉ですよね
- 画面レイアウトの関係で、チケットの概要の文字数が多いと、省略されてしまい、一覧性に乏しい
- プリントできない(消える)
これらの不満を解消すべく、カスタマイズしてみました。
カスタマイズのポイント
カスタマイズ内容
Index: ganttcalendar/ticketgantt.py =================================================================== --- ganttcalendar/ticketgantt.py (リビジョン 429) +++ ganttcalendar/ticketgantt.py (作業コピー) @@ -52,7 +52,7 @@ show_closed_ticket = req.args.get('show_closed_ticket') sorted_field = req.args.get('sorted_field') if sorted_field == None: - sorted_field = 'component' + sorted_field = 'milestone' if baseday != None: r = re.match(r'^(\d+)/(\d+)/(\d+)$', baseday) @@ -112,22 +112,26 @@ tickets=[] for id, type, summary, owner, description, status, due_assign, due_close, complete, item in cursor: due_assign_date = None + due_assign_date_short = None #assign date without year due_close_date = None + due_close_date_short = None #close date without year try: t = time.strptime(due_assign,"%Y/%m/%d") due_assign_date = date(t[0],t[1],t[2]) + due_assign_date_short = date(t[0],t[1],t[2]).strftime('%m/%d') except ValueError, TypeError: continue try: t = time.strptime(due_close,"%Y/%m/%d") due_close_date = date(t[0],t[1],t[2]) + due_close_date_short = date(t[0],t[1],t[2]).strftime('%m/%d') except ValueError, TypeError: continue if item == None or item == "": item = "*" if complete != None and len(complete)>1 and complete[len(complete)-1]=='%': complete = complete[0:len(complete)-1] - ticket = {'id':id, 'type':type, 'summary':summary, 'owner':owner, 'description': description, 'status':status, 'due_assign':due_assign_date, 'due_close':due_close_date, 'complete': complete, sorted_field: item} + ticket = {'id':id, 'type':type, 'summary':summary, 'owner':owner, 'description': description, 'status':status, 'due_assign':due_assign_date, 'due_close':due_close_date, 'complete': complete, sorted_field: item, 'due_assign_short':due_assign_date_short, 'due_close_short':due_close_date_short} self.log.debug(ticket) tickets.append(ticket) @@ -233,6 +237,8 @@ 'url':url, 'short_summary':t['summary'][0:10], 'assign':assign, 'todow':todow, 'latew':latew, 'complete':complete }) + # add for sort by assign date. + ts.sort(cmp=lambda x, y: cmp(x['assign'], y['assign'])) req.hdf['gan'] = { 'weekdays':[u"月", u"火", u"水", u"木", u"金", u"土", u"日"], Index: ganttcalendar/templates/gantt.cs =================================================================== --- ganttcalendar/templates/gantt.cs (リビジョン 429) +++ ganttcalendar/templates/gantt.cs (作業コピー) @@ -119,7 +119,7 @@ } </style> -<form> +<form class="printableform"> <table class="list"> <tr> <td> @@ -324,7 +324,18 @@ <?cs if:t.complete > 0 && t.assign != -1 ?> <div style="top: <?cs var:offset * ti + 60 ?>px; left: <?cs var:t.assign * dw ?>px; width: <?cs var:t.complete ?>px;" class="ticket ticket_done"></div> <?cs /if ?> - + <!-- add for showing ticket title on gantt bar --> + <div class="ticket" style="position:absolute; height:8px; top: <?cs var:offset * ti + 48 ?>px; left: <?cs if:t.assign * dw < 0 ?>3<?cs else ?><?cs var:t.assign * dw ?><?cs /if ?>px; width: 100%; font-size:10px; color:black"> + <span class="tip"> + <pre><span class="type"><?cs var:t.ticket['type'] ?></span>#<?cs var:t.ticket['id'] ?>: <?cs var:t.ticket['summary'] ?></pre> + <strong>担当者</strong>: <?cs var:t.ticket['owner'] ?><br /> + <strong>開始日</strong>: <?cs var:t.ticket['due_assign'] ?><br /> + <strong>終了日</strong>: <?cs var:t.ticket['due_close'] ?><br /> + <strong>達成率</strong>: <?cs var:t.ticket['complete'] ?>%<br /> + <strong>詳細</strong>: <pre><?cs var:t.ticket['description'] ?></pre> + </span> + <a href="<?cs var:t.url ?>" target="_blank">#<?cs var:t.ticket['id'] ?>:<?cs var:t.ticket['summary'] ?> (<?cs var:t.ticket['due_assign_short'] ?> - <?cs var:t.ticket['due_close_short'] ?>)</a> + </div> <?cs set:offset = offset + 1 ?> </span>
パッチをソースに適用しつつ、次のような感じでやります
cd <チェックアウト先の0.10ディレクトリ> patch -p0 < gantt.patch python setup.py bdist_egg cp -f dist/TracGanttCalendarPlugin-0.0.1-py2.4.egg /usr/share/trac/plugins/ service httpd restart
Windows環境(Trac Lighting)なら、
http://cetus.sakura.ne.jp/softlab/toolbox1/index.html#difpat
とかのpatchツールを使うといいかもしれません。
また、
C:\TracLight\python\share\trac\plugins
あたりに、出来上がったeggファイルをコピーすればよいです。
ついでに
レポート用のSQLです。
マイルストーン別に 開始日か終了日が設定されていないチケットをリストアップします
SELECT p.value AS __color__, milestone AS __group__, id AS ticket, summary, status, assigned.value AS 開始日, closed.value AS 終了日, t.type AS type, (CASE status WHEN 'assigned' THEN owner||' *' ELSE owner END) AS owner, time AS created FROM ticket t LEFT JOIN enum p ON p.name = t.priority AND p.type = 'priority' LEFT JOIN (select ticket, name, value from ticket_custom where name = 'due_assign' ) assigned ON t.id = assigned.ticket LEFT JOIN (select ticket, name, value from ticket_custom where name = 'due_close' ) closed ON t.id = closed.ticket WHERE (assigned.value IS NULL) OR (assigned.value = '') OR (closed.value IS NULL) OR (closed.value = '') ORDER BY (milestone IS NULL),milestone, t.id