keithsalisbury-subtrac 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. data/VERSION.yml +1 -1
  2. data/bin/subtrac +2 -0
  3. data/lib/subtrac.rb +85 -50
  4. data/lib/subtrac/config/config.yml +22 -19
  5. data/lib/subtrac/templates/location.erb +2 -2
  6. data/lib/subtrac/templates/projects/blank/trac/wiki/WikiStart +1 -1
  7. data/lib/subtrac/templates/trac.erb +1 -1
  8. data/lib/subtrac/templates/vhost.erb +6 -6
  9. metadata +1 -105
  10. data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/advancedworkflow/__init__.py +0 -0
  11. data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/advancedworkflow/controller.py +0 -419
  12. data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/setup.cfg +0 -3
  13. data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/setup.py +0 -20
  14. data/lib/subtrac/trac-plugins/clientsplugin/clients/__init__.py +0 -0
  15. data/lib/subtrac/trac-plugins/clientsplugin/clients/action.py +0 -28
  16. data/lib/subtrac/trac-plugins/clientsplugin/clients/action_email.py +0 -168
  17. data/lib/subtrac/trac-plugins/clientsplugin/clients/action_zendesk_forum.py +0 -137
  18. data/lib/subtrac/trac-plugins/clientsplugin/clients/admin.py +0 -91
  19. data/lib/subtrac/trac-plugins/clientsplugin/clients/api.py +0 -199
  20. data/lib/subtrac/trac-plugins/clientsplugin/clients/client.py +0 -105
  21. data/lib/subtrac/trac-plugins/clientsplugin/clients/events.py +0 -287
  22. data/lib/subtrac/trac-plugins/clientsplugin/clients/eventsadmin.py +0 -71
  23. data/lib/subtrac/trac-plugins/clientsplugin/clients/htdocs/clients.css +0 -4
  24. data/lib/subtrac/trac-plugins/clientsplugin/clients/model.py +0 -135
  25. data/lib/subtrac/trac-plugins/clientsplugin/clients/processor.py +0 -70
  26. data/lib/subtrac/trac-plugins/clientsplugin/clients/reportmanager.py +0 -142
  27. data/lib/subtrac/trac-plugins/clientsplugin/clients/reports.py +0 -231
  28. data/lib/subtrac/trac-plugins/clientsplugin/clients/summary.py +0 -27
  29. data/lib/subtrac/trac-plugins/clientsplugin/clients/summary_milestone.py +0 -152
  30. data/lib/subtrac/trac-plugins/clientsplugin/clients/summary_ticketchanges.py +0 -160
  31. data/lib/subtrac/trac-plugins/clientsplugin/clients/templates/admin_client_events.html +0 -124
  32. data/lib/subtrac/trac-plugins/clientsplugin/clients/templates/admin_clients.html +0 -134
  33. data/lib/subtrac/trac-plugins/clientsplugin/cron/changes.xslt +0 -132
  34. data/lib/subtrac/trac-plugins/clientsplugin/cron/run-client-event +0 -97
  35. data/lib/subtrac/trac-plugins/clientsplugin/cron/summary.xslt +0 -161
  36. data/lib/subtrac/trac-plugins/clientsplugin/setup.py +0 -43
  37. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/__init__.py +0 -4
  38. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/burndownchart.py +0 -273
  39. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/hoursinplaceeditor.py +0 -44
  40. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/hoursremaining.py +0 -36
  41. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery-1.2.3.min.js +0 -32
  42. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery.jeditable.js +0 -409
  43. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery.jeditable.mini.js +0 -30
  44. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/templates/edithours.html +0 -53
  45. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/burndownchart.py +0 -181
  46. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/hoursremaining.py +0 -66
  47. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/workloadchart.py +0 -47
  48. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/utils.py +0 -93
  49. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/workloadchart.py +0 -86
  50. data/lib/subtrac/trac-plugins/estimationtoolsplugin/setup.py +0 -20
  51. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/SumRollups.js +0 -23
  52. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/adw_tracdb.py +0 -128
  53. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/git-post-receive +0 -40
  54. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/trac-post-commit.py +0 -285
  55. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/trac_billing.py +0 -173
  56. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/utils/__init__.py +0 -0
  57. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/utils/mail.py +0 -164
  58. data/lib/subtrac/trac-plugins/timingandestimationplugin/setup.py +0 -69
  59. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/__init__.py +0 -1
  60. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/api.py +0 -292
  61. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/blackmagic.py +0 -172
  62. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/dbhelper.py +0 -178
  63. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/billingplugin.css +0 -25
  64. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/field_disabler.js +0 -6
  65. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/formatDate.js +0 -356
  66. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/tip_centerwindow.js +0 -100
  67. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/tip_followscroll.js +0 -84
  68. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/wz_tooltip.js +0 -1149
  69. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/linkifyer.js +0 -119
  70. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/query.js +0 -73
  71. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/ticket.js +0 -165
  72. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/query_webui.py +0 -28
  73. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reportmanager.py +0 -221
  74. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reports.py +0 -675
  75. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reports_filter.py +0 -150
  76. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/statuses.py +0 -25
  77. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/tande_filters.py +0 -131
  78. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/templates/billing.cs +0 -84
  79. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/templates/billing.html +0 -104
  80. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_daemon.py +0 -194
  81. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_policy.py +0 -62
  82. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_webui.py +0 -28
  83. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/usermanual.py +0 -127
  84. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/webui.py +0 -129
  85. data/lib/subtrac/trac-plugins/worklogplugin/setup.py +0 -29
  86. data/lib/subtrac/trac-plugins/worklogplugin/worklog/__init__.py +0 -1
  87. data/lib/subtrac/trac-plugins/worklogplugin/worklog/api.py +0 -187
  88. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jqModal.css +0 -40
  89. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jqModal.js +0 -67
  90. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jquery.mousewheel.pack.js +0 -12
  91. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jquery.timeentry.pack.js +0 -7
  92. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/tracWorklog.js +0 -40
  93. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/ui.datepicker.css +0 -208
  94. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/ui.datepicker.js +0 -1439
  95. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/work.png +0 -0
  96. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/work.xcf +0 -0
  97. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/worklogplugin.css +0 -80
  98. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/workstart.png +0 -0
  99. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/workstop.png +0 -0
  100. data/lib/subtrac/trac-plugins/worklogplugin/worklog/manager.py +0 -336
  101. data/lib/subtrac/trac-plugins/worklogplugin/worklog/reports.py +0 -598
  102. data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog.html +0 -45
  103. data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_stop.html +0 -70
  104. data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_user.html +0 -40
  105. data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_webadminui.html +0 -59
  106. data/lib/subtrac/trac-plugins/worklogplugin/worklog/ticket_daemon.py +0 -33
  107. data/lib/subtrac/trac-plugins/worklogplugin/worklog/ticket_filter.py +0 -153
  108. data/lib/subtrac/trac-plugins/worklogplugin/worklog/timeline_hook.py +0 -96
  109. data/lib/subtrac/trac-plugins/worklogplugin/worklog/usermanual.py +0 -29
  110. data/lib/subtrac/trac-plugins/worklogplugin/worklog/util.py +0 -31
  111. data/lib/subtrac/trac-plugins/worklogplugin/worklog/webadminui.py +0 -47
  112. data/lib/subtrac/trac-plugins/worklogplugin/worklog/webui.py +0 -174
  113. data/lib/subtrac/trac-plugins/worklogplugin/worklog/xmlrpc.py +0 -73
@@ -1,45 +0,0 @@
1
- <!DOCTYPE html
2
- PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
4
- <html xmlns="http://www.w3.org/1999/xhtml"
5
- xmlns:xi="http://www.w3.org/2001/XInclude"
6
- xmlns:py="http://genshi.edgewall.org/">
7
- <xi:include href="layout.html" />
8
- <xi:include href="macros.html" />
9
- <head>
10
- <title>Work Log</title>
11
- </head>
12
-
13
- <body>
14
- <form method="post" action="${worklog_href}">
15
- <div id="content" class="worklog">
16
- <a id="worklogmanual" href="${usermanual_href}" >${usermanual_title}</a>
17
- <h2>Work Log Summary</h2>
18
- <div id="messages" >
19
- <div py:for="item in messages" class="message" >${item}</div>
20
- </div>
21
-
22
- <table border="0" cellspacing="0" cellpadding="0" id="worklog_report">
23
- <tr>
24
- <th>User</th>
25
- <th>Activity</th>
26
- <th>Time</th>
27
- <th>Comment</th>
28
- </tr>
29
- <tr py:for="log in worklog">
30
- <td><a href="${worklog_href}/users/${log.user}">${log.dispname}</a></td>
31
- <py:choose>
32
- <td py:when="log.endtime==0"><a class="${log.status} ticket" href="${ticket_href}/${log.ticket}">#${log.ticket}</a>: ${log.summary}</td>
33
- <td py:otherwise=""><em>Idle</em> <small>(Last worked on: <a class="${log.status} ticket" href="${ticket_href}/${log.ticket}">#${log.ticket}</a>: ${log.summary})</small></td>
34
- </py:choose>
35
- <td><span id="worklog_time_delta">${log.delta}</span></td>
36
- <td><span id="worklog_comment">${log.comment}</span></td>
37
- </tr>
38
- </table>
39
- </div>
40
- </form>
41
-
42
- <div id="altlinks"> <h3>Download in other formats:</h3><ul><li class="first last"><a href="?format=csv" class="csv">CSV</a></li></ul></div>
43
- </body>
44
-
45
- </html>
@@ -1,70 +0,0 @@
1
- <html xmlns="http://www.w3.org/1999/xhtml"
2
- xmlns:py="http://genshi.edgewall.org/"
3
- xmlns:xi="http://www.w3.org/2001/XInclude" py:strip="">
4
- <py:choose>
5
- <py:when test="xhr">
6
- <py:match path="head" once="true"><head>
7
- <title py:with="title = list(select('title/text()'))">
8
- <py:if test="title">${title} –</py:if>
9
- ${' – '.join(filter(None, [project.name, 'Trac']))}
10
- </title>
11
- <py:if test="chrome.links">
12
- <py:for each="rel, links in chrome.links.items()">
13
- <link rel="${rel}" py:for="link in links" py:attrs="link" />
14
- </py:for>
15
- </py:if>
16
- <py:if test="'SEARCH_VIEW' in perm" id="search">
17
- <link type="application/opensearchdescription+xml" rel="search"
18
- href="${href.search('opensearch')}" title="Search $project.name"/>
19
- </py:if>
20
- <script py:for="script in chrome.scripts"
21
- type="${script.type}" src="${script.href}"></script>
22
- ${Markup('&lt;!--[if lt IE 7]&gt;')}
23
- <script type="text/javascript" src="${chrome.htdocs_location}js/ie_pre7_hacks.js"></script>
24
- ${Markup('&lt;![endif]--&gt;')}
25
- ${select("*[local-name() != 'title']")}
26
- </head></py:match>
27
- </py:when>
28
- <py:otherwise>
29
- <xi:include href="layout.html" />
30
- </py:otherwise>
31
- </py:choose>
32
- <xi:include href="macros.html" />
33
- <head>
34
- <title>Work Log</title>
35
- </head>
36
- <body>
37
- <div>
38
- <div py:if="xhr" style="text-align: right;">
39
- <span style="text-decoration: underline; color: blue; cursor: pointer;" class="jqmClose">close</span>
40
- </div>
41
- <form method="post" action="${worklog_href}" class="inlinebuttons">
42
- <input type="hidden" name="source_url" value="${ticket_href}" />
43
- <input type="hidden" name="ticket" value="${ticket}" />
44
- <input id="worklogStoptime" type="hidden" name="stoptime" value="" />
45
- <fieldset>
46
- <legend>Stop work</legend>
47
- <div class="field">
48
- <fieldset class="iefix">
49
- <label for="worklogComment">Optional: Leave a comment about the work you have done...</label>
50
- <p><textarea id="worklogComment" name="comment" class="wikitext" rows="6" cols="60"></textarea></p>
51
- </fieldset>
52
- </div>
53
- <div class="field">
54
- <label>Override end time</label>
55
- <div align="center">
56
- <div style="width: 185px;">
57
- <div id="worklogStopDate"></div>
58
- <br clear="all" />
59
- <div style="text-align: right;">
60
- &nbsp;&nbsp;@&nbsp;<input id="worklogStopTime" type="text" size="6" />
61
- </div>
62
- </div>
63
- </div>
64
- </div>
65
- <div style="text-align: right;"><input id="worklogSubmit" type="submit" name="${action}work" value="${label}" /></div>
66
- </fieldset>
67
- </form>
68
- </div>
69
- </body>
70
- </html>
@@ -1,40 +0,0 @@
1
- <!DOCTYPE html
2
- PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
4
- <html xmlns="http://www.w3.org/1999/xhtml"
5
- xmlns:xi="http://www.w3.org/2001/XInclude"
6
- xmlns:py="http://genshi.edgewall.org/">
7
- <xi:include href="layout.html" />
8
- <xi:include href="macros.html" />
9
- <head>
10
- <title>Work Log</title>
11
- </head>
12
-
13
- <body>
14
- <form method="post" action="${worklog_href}">
15
- <div id="content" class="worklog">
16
- <a id="worklogmanual" href="${usermanual_href}" >${usermanual_title}</a>
17
- <h2>Work Log for ${worklog[0].dispname}</h2>
18
- <div id="messages" >
19
- <div py:for="item in messages" class="message" >${item}</div>
20
- </div>
21
-
22
- <table border="0" cellspacing="0" cellpadding="0" id="worklog_report">
23
- <tr>
24
- <th>Ticket</th>
25
- <th>Time</th>
26
- <th>Comment</th>
27
- </tr>
28
- <tr py:for="log in worklog">
29
- <td><a class="${log.status} ticket" href="${ticket_href}/${log.ticket}">#${log.ticket}</a>: ${log.summary}</td>
30
- <td><span id="worklog_time_delta">${log.delta}</span></td>
31
- <td><span id="worklog_comment">${log.comment}</span></td>
32
- </tr>
33
- </table>
34
- </div>
35
- </form>
36
-
37
- <div id="altlinks"> <h3>Download in other formats:</h3><ul><li class="first last"><a href="?format=csv" class="csv">CSV</a></li></ul></div>
38
- </body>
39
-
40
- </html>
@@ -1,59 +0,0 @@
1
- <!DOCTYPE html
2
- PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
4
- <html xmlns="http://www.w3.org/1999/xhtml"
5
- xmlns:xi="http://www.w3.org/2001/XInclude"
6
- xmlns:py="http://genshi.edgewall.org/">
7
- <xi:include href="admin.html" />
8
- <head>
9
- <title>Work Log Settings</title>
10
- </head>
11
-
12
- <body>
13
- <h2>Work Log Settings</h2>
14
-
15
- <py:choose test="view">
16
- <form py:when="'settings'" method="post">
17
- <fieldset>
18
- <legend>Options:</legend>
19
- <div class="field">
20
- <input type="checkbox" id="timingandestimation" name="timingandestimation" value="1" checked="${timingandestimation or None}" />
21
- <label for="timingandestimation">Record time via <a href="http://www.trac-hacks.org/wiki/TimingAndEstimationPlugin">Timing and Estimation Plugin</a>?</label>
22
- </div>
23
- <div class="field">
24
- <input type="checkbox" id="comment" name="comment" value="1" checked="${comment or None}" />
25
- <label for="comment">Automatically add a comment when you stop work on a ticket?</label><br />
26
- <small>Please note that if you leave a comment when you stop work, then a comment is always added to the ticket to ensure all information is present on the ticket.</small>
27
- </div>
28
- <div class="field">
29
- <input type="checkbox" id="autostop" name="autostop" value="1" checked="${autostop or None}" />
30
- <label for="autostop">Stop work automatically if ticket is closed?</label>
31
- </div>
32
- <div class="field">
33
- <input type="checkbox" id="autoreassignaccept" name="autoreassignaccept" value="1" checked="${autoreassignaccept or None}" />
34
- <label for="autoreassignaccept">Automatically reassign and accept (if necessary) when starting work?</label>
35
- </div>
36
- <div class="field">
37
- <input type="checkbox" id="autostopstart" name="autostopstart" value="1" checked="${autostopstart or None}" />
38
- <label for="autostopstart">Allow users to start working on a different ticket (i.e. automatically stop working on current ticket)?</label>
39
- </div>
40
- </fieldset>
41
- <br />
42
- <fieldset>
43
- <legend>Parameters:</legend>
44
- <div class="field">
45
- <label for="roundup">Round up to nearest minute</label>&nbsp;
46
- <input type="text" id="roundup" name="roundup" size="4" value="${roundup}" /><br />
47
- <small>This only applies when integrating with the
48
- <a href="http://www.trac-hacks.org/wiki/TimingAndEstimationPlugin">Timing and Estimation Plugin</a></small>
49
- </div>
50
- </fieldset>
51
-
52
- <div class="buttons">
53
- <input type="submit" name="update" value="Update Settings" />
54
- </div>
55
- </form>
56
- </py:choose>
57
- </body>
58
-
59
- </html>
@@ -1,33 +0,0 @@
1
- from trac.ticket import ITicketChangeListener, Ticket
2
- from trac.core import *
3
- from manager import WorkLogManager
4
-
5
- class WorkLogTicketObserver(Component):
6
- implements(ITicketChangeListener)
7
- def __init__(self):
8
- pass
9
-
10
- def ticket_created(self, ticket):
11
- """Called when a ticket is created."""
12
- pass
13
-
14
- def ticket_changed(self, ticket, comment, author, old_values):
15
- """Called when a ticket is modified.
16
-
17
- `old_values` is a dictionary containing the previous values of the
18
- fields that have changed.
19
- """
20
- if self.config.getbool('worklog', 'autostop') \
21
- and 'closed' == ticket['status'] \
22
- and old_values.has_key('status') \
23
- and 'closed' != old_values['status']:
24
- mgr = WorkLogManager(self.env, self.config)
25
- who,since = mgr.who_is_working_on(ticket.id)
26
- if who:
27
- mgr = WorkLogManager(self.env, self.config, who)
28
- mgr.stop_work()
29
-
30
- def ticket_deleted(self, ticket):
31
- """Called when a ticket is deleted."""
32
- pass
33
-
@@ -1,153 +0,0 @@
1
- import re
2
- from util import *
3
- from trac.core import *
4
- from trac.web.api import ITemplateStreamFilter
5
- from trac.web.chrome import add_stylesheet, add_script
6
- from trac.wiki import wiki_to_oneliner
7
-
8
- from manager import WorkLogManager
9
- from util import pretty_timedelta
10
-
11
- from genshi import XML
12
- from genshi.builder import tag
13
- from genshi.filters.transform import Transformer
14
-
15
- class WorkLogTicketAddon(Component):
16
- implements(ITemplateStreamFilter)
17
-
18
- def __init__(self):
19
- pass
20
-
21
- def get_task_markup(self, req, ticket, task):
22
- if not task:
23
- return ''
24
-
25
- ticket_text = 'ticket #' + str(task['ticket'])
26
- if task['ticket'] == ticket:
27
- ticket_text = 'this ticket'
28
- timedelta = pretty_timedelta(datetime.fromtimestamp(task['starttime']), None);
29
-
30
- return '<li>%s</li>' % wiki_to_oneliner('You have been working on %s for %s' % (ticket_text, timedelta), self.env, req=req)
31
-
32
-
33
- def get_ticket_markup(self, who, since):
34
- timedelta = pretty_timedelta(datetime.fromtimestamp(since), None);
35
- return '<li>%s has been working on this ticket for %s</li>' % (who, timedelta)
36
-
37
-
38
- def get_ticket_markup_noone(self):
39
- return '<li>Nobody is working on this ticket</li>'
40
-
41
-
42
- def get_button_markup(self, req, ticket, stop=False):
43
- if stop:
44
- action = 'stop'
45
- label = 'Stop Work'
46
- else:
47
- action = 'start'
48
- label = 'Start Work'
49
-
50
- return '''
51
- <form id="worklogTicketForm" method="post" action="%s" class="inlinebuttons" onsubmit="return tracWorklog.%s();">
52
- <input type="hidden" name="source_url" value="%s" />
53
- <input type="hidden" name="ticket" value="%s" />
54
- <input type="submit" name="%swork" value="%s" />
55
- </form>
56
- <div id="worklogPopup" class="jqmWindow">
57
- <div style="text-align: right;">
58
- <span style="text-decoration: underline; color: blue; cursor: pointer;" class="jqmClose">close</span>
59
- </div>
60
- <form method="post" action="%s" class="inlinebuttons">
61
- <input type="hidden" name="source_url" value="%s" />
62
- <input type="hidden" name="ticket" value="%s" />
63
- <input id="worklogStoptime" type="hidden" name="stoptime" value="" />
64
- <fieldset>
65
- <legend>Stop work</legend>
66
- <div class="field">
67
- <fieldset class="iefix">
68
- <label for="worklogComment">Optional: Leave a comment about the work you have done...</label>
69
- <p><textarea id="worklogComment" name="comment" class="wikitext" rows="6" cols="60"></textarea></p>
70
- </fieldset>
71
- </div>
72
- <div class="field">
73
- <label>Override end time</label>
74
- <div align="center">
75
- <div style="width: 185px;">
76
- <div id="worklogStopDate"></div>
77
- <br clear="all" />
78
- <div style="text-align: right;">
79
- &nbsp;&nbsp;@&nbsp;<input id="worklogStopTime" type="text" size="6" />
80
- </div>
81
- </div>
82
- </div>
83
- </div>
84
- <div style="text-align: right;"><input id="worklogSubmit" type="submit" name="%swork" value="%s" /></div>
85
- </fieldset>
86
- </form>
87
- </div>
88
- ''' % (req.href.worklog(), action,
89
- req.href.ticket(ticket),
90
- ticket,
91
- action, label,
92
- req.href.worklog(),
93
- req.href.ticket(ticket),
94
- ticket,
95
- action, label)
96
-
97
-
98
- # ITemplateStreamFilter methods
99
- def filter_stream(self, req, method, filename, stream, data):
100
- match = re.match(r'/ticket/([0-9]+)$', req.path_info)
101
- if match and req.perm.has_permission('WORK_LOG'):
102
- ticket = int(match.group(1))
103
- add_stylesheet(req, "worklog/worklogplugin.css")
104
-
105
- add_script(req, 'worklog/jqModal.js')
106
- add_stylesheet(req, 'worklog/jqModal.css')
107
-
108
- add_script(req, 'worklog/ui.datepicker.js')
109
- add_stylesheet(req, 'worklog/ui.datepicker.css')
110
-
111
- add_script(req, 'worklog/jquery.mousewheel.pack.js')
112
- add_script(req, 'worklog/jquery.timeentry.pack.js')
113
-
114
- add_script(req, 'worklog/tracWorklog.js')
115
-
116
- mgr = WorkLogManager(self.env, self.config, req.authname)
117
- task_markup = ''
118
- if req.authname != 'anonymous':
119
- task = mgr.get_active_task()
120
- if task:
121
- task_markup = self.get_task_markup(req, ticket, task)
122
-
123
- who,since = mgr.who_is_working_on(ticket)
124
- ticket_markup = ''
125
- if who:
126
- # If who == req.authname then we will have some text from above.
127
- if who != req.authname:
128
- ticket_markup = self.get_ticket_markup(who, since)
129
- else:
130
- ticket_markup = self.get_ticket_markup_noone()
131
-
132
- button_markup = ''
133
- if req.authname != 'anonymous':
134
- if mgr.can_work_on(ticket):
135
- # Display a "Work on Link" button.
136
- button_markup = self.get_button_markup(req, ticket)
137
- elif task and task['ticket'] == ticket:
138
- # We are currently working on this, so display the stop button...
139
- button_markup = self.get_button_markup(req, ticket, True)
140
-
141
- # User's current task information
142
- html = XML('''
143
- <fieldset class="workloginfo">
144
- <legend>Work Log</legend>
145
- %s
146
- <ul>
147
- %s
148
- %s
149
- </ul>
150
- </fieldset>
151
- ''' % (button_markup, task_markup, ticket_markup))
152
- stream |= Transformer('.//div[@id="ticket"]').before(html)
153
- return stream
@@ -1,96 +0,0 @@
1
- import re
2
- from genshi.builder import tag
3
- from util import *
4
- from trac.log import logger_factory
5
- from trac.core import *
6
- from trac.util.datefmt import to_timestamp, utc
7
- from trac.util.text import shorten_line
8
- from trac.ticket.api import TicketSystem
9
- from trac.timeline.api import ITimelineEventProvider
10
- from trac.wiki.formatter import format_to_oneliner
11
- from trac.resource import Resource, get_resource_url, \
12
- render_resource_link, get_resource_shortname, \
13
- get_resource_name
14
- from trac.web.chrome import add_stylesheet
15
-
16
- class WorkLogTimelineAddon(Component):
17
- implements(ITimelineEventProvider)
18
-
19
- # ITimelineEventProvider methods
20
-
21
- def get_timeline_filters(self, req):
22
- if req.perm.has_permission('WORK_VIEW'):
23
- yield ('workstart', 'Work started', True)
24
- yield ('workstop', 'Work stopped', True)
25
-
26
- def get_timeline_events(self, req, start, stop, filters):
27
- # Worklog changes
28
- show_starts = 'workstart' in filters
29
- show_stops = 'workstop' in filters
30
- if show_starts or show_stops:
31
- add_stylesheet(req, "worklog/worklogplugin.css")
32
-
33
- ts_start = to_timestamp(start)
34
- ts_stop = to_timestamp(stop)
35
-
36
- ticket_realm = Resource('ticket')
37
- db = self.env.get_db_cnx()
38
- cursor = db.cursor()
39
-
40
- cursor.execute("""SELECT wl.worker,wl.ticket,wl.time,wl.starttime,wl.comment,wl.kind,t.summary,t.status,t.resolution,t.type
41
- FROM (
42
-
43
- SELECT worker, ticket, starttime AS time, starttime, comment, 'start' AS kind
44
- FROM work_log
45
-
46
- UNION
47
-
48
- SELECT worker, ticket, endtime AS time, starttime, comment, 'stop' AS kind
49
- FROM work_log
50
-
51
- ) AS wl
52
- INNER JOIN ticket t ON t.id = wl.ticket
53
- AND wl.time>=%s AND wl.time<=%s
54
- ORDER BY wl.time"""
55
- % (ts_start, ts_stop))
56
- previous_update = None
57
- for worker,tid,ts,ts_start,comment,kind,summary,status,resolution,type in cursor:
58
- ticket = ticket_realm(id=tid)
59
- time = datetime.fromtimestamp(ts, utc)
60
- started = None
61
- if kind == 'start':
62
- if not show_starts:
63
- continue
64
- yield ('workstart', time, worker, (ticket,summary,status,resolution,type, started, ""))
65
- else:
66
- if not show_stops:
67
- continue
68
- started = datetime.fromtimestamp(ts_start, utc)
69
- if comment:
70
- comment = "(Time spent: %s)[[BR]]%s" % (pretty_timedelta(started, time), comment)
71
- else:
72
- comment = '(Time spent: %s)' % pretty_timedelta(started, time)
73
- yield ('workstop', time, worker, (ticket,summary,status,resolution,type, started, comment))
74
-
75
- def render_timeline_event(self, context, field, event):
76
- ticket,summary,status,resolution,type, started, comment = event[3]
77
- if field == 'url':
78
- return context.href.ticket(ticket.id)
79
- elif field == 'title':
80
- title = TicketSystem(self.env).format_summary(summary, status,
81
- resolution, type)
82
- return tag('Work ', started and 'stopped' or 'started',
83
- ' on Ticket ', tag.em('#', ticket.id, title=title),
84
- ' (', shorten_line(summary), ') ')
85
- elif field == 'description':
86
- if self.config['timeline'].getbool('abbreviated_messages'):
87
- comment = shorten_line(comment)
88
- markup = format_to_oneliner(self.env, context(resource=ticket),
89
- comment)
90
- #if wiki_page.version > 1:
91
- # diff_href = context.href.wiki(
92
- # wiki_page.id, version=wiki_page.version, action='diff')
93
- # markup = tag(markup, ' ', tag.a('(diff)', href=diff_href))
94
- return markup
95
-
96
-