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.
- data/VERSION.yml +1 -1
- data/bin/subtrac +2 -0
- data/lib/subtrac.rb +85 -50
- data/lib/subtrac/config/config.yml +22 -19
- data/lib/subtrac/templates/location.erb +2 -2
- data/lib/subtrac/templates/projects/blank/trac/wiki/WikiStart +1 -1
- data/lib/subtrac/templates/trac.erb +1 -1
- data/lib/subtrac/templates/vhost.erb +6 -6
- metadata +1 -105
- data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/advancedworkflow/__init__.py +0 -0
- data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/advancedworkflow/controller.py +0 -419
- data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/setup.cfg +0 -3
- data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/setup.py +0 -20
- data/lib/subtrac/trac-plugins/clientsplugin/clients/__init__.py +0 -0
- data/lib/subtrac/trac-plugins/clientsplugin/clients/action.py +0 -28
- data/lib/subtrac/trac-plugins/clientsplugin/clients/action_email.py +0 -168
- data/lib/subtrac/trac-plugins/clientsplugin/clients/action_zendesk_forum.py +0 -137
- data/lib/subtrac/trac-plugins/clientsplugin/clients/admin.py +0 -91
- data/lib/subtrac/trac-plugins/clientsplugin/clients/api.py +0 -199
- data/lib/subtrac/trac-plugins/clientsplugin/clients/client.py +0 -105
- data/lib/subtrac/trac-plugins/clientsplugin/clients/events.py +0 -287
- data/lib/subtrac/trac-plugins/clientsplugin/clients/eventsadmin.py +0 -71
- data/lib/subtrac/trac-plugins/clientsplugin/clients/htdocs/clients.css +0 -4
- data/lib/subtrac/trac-plugins/clientsplugin/clients/model.py +0 -135
- data/lib/subtrac/trac-plugins/clientsplugin/clients/processor.py +0 -70
- data/lib/subtrac/trac-plugins/clientsplugin/clients/reportmanager.py +0 -142
- data/lib/subtrac/trac-plugins/clientsplugin/clients/reports.py +0 -231
- data/lib/subtrac/trac-plugins/clientsplugin/clients/summary.py +0 -27
- data/lib/subtrac/trac-plugins/clientsplugin/clients/summary_milestone.py +0 -152
- data/lib/subtrac/trac-plugins/clientsplugin/clients/summary_ticketchanges.py +0 -160
- data/lib/subtrac/trac-plugins/clientsplugin/clients/templates/admin_client_events.html +0 -124
- data/lib/subtrac/trac-plugins/clientsplugin/clients/templates/admin_clients.html +0 -134
- data/lib/subtrac/trac-plugins/clientsplugin/cron/changes.xslt +0 -132
- data/lib/subtrac/trac-plugins/clientsplugin/cron/run-client-event +0 -97
- data/lib/subtrac/trac-plugins/clientsplugin/cron/summary.xslt +0 -161
- data/lib/subtrac/trac-plugins/clientsplugin/setup.py +0 -43
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/__init__.py +0 -4
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/burndownchart.py +0 -273
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/hoursinplaceeditor.py +0 -44
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/hoursremaining.py +0 -36
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery-1.2.3.min.js +0 -32
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery.jeditable.js +0 -409
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery.jeditable.mini.js +0 -30
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/templates/edithours.html +0 -53
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/burndownchart.py +0 -181
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/hoursremaining.py +0 -66
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/workloadchart.py +0 -47
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/utils.py +0 -93
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/workloadchart.py +0 -86
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/setup.py +0 -20
- data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/SumRollups.js +0 -23
- data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/adw_tracdb.py +0 -128
- data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/git-post-receive +0 -40
- data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/trac-post-commit.py +0 -285
- data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/trac_billing.py +0 -173
- data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/utils/__init__.py +0 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/utils/mail.py +0 -164
- data/lib/subtrac/trac-plugins/timingandestimationplugin/setup.py +0 -69
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/__init__.py +0 -1
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/api.py +0 -292
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/blackmagic.py +0 -172
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/dbhelper.py +0 -178
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/billingplugin.css +0 -25
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/field_disabler.js +0 -6
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/formatDate.js +0 -356
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/tip_centerwindow.js +0 -100
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/tip_followscroll.js +0 -84
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/wz_tooltip.js +0 -1149
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/linkifyer.js +0 -119
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/query.js +0 -73
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/ticket.js +0 -165
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/query_webui.py +0 -28
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reportmanager.py +0 -221
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reports.py +0 -675
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reports_filter.py +0 -150
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/statuses.py +0 -25
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/tande_filters.py +0 -131
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/templates/billing.cs +0 -84
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/templates/billing.html +0 -104
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_daemon.py +0 -194
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_policy.py +0 -62
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_webui.py +0 -28
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/usermanual.py +0 -127
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/webui.py +0 -129
- data/lib/subtrac/trac-plugins/worklogplugin/setup.py +0 -29
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/__init__.py +0 -1
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/api.py +0 -187
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jqModal.css +0 -40
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jqModal.js +0 -67
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jquery.mousewheel.pack.js +0 -12
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jquery.timeentry.pack.js +0 -7
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/tracWorklog.js +0 -40
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/ui.datepicker.css +0 -208
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/ui.datepicker.js +0 -1439
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/work.png +0 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/work.xcf +0 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/worklogplugin.css +0 -80
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/workstart.png +0 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/workstop.png +0 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/manager.py +0 -336
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/reports.py +0 -598
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog.html +0 -45
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_stop.html +0 -70
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_user.html +0 -40
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_webadminui.html +0 -59
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/ticket_daemon.py +0 -33
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/ticket_filter.py +0 -153
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/timeline_hook.py +0 -96
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/usermanual.py +0 -29
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/util.py +0 -31
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/webadminui.py +0 -47
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/webui.py +0 -174
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/xmlrpc.py +0 -73
data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reports_filter.py
DELETED
@@ -1,150 +0,0 @@
|
|
1
|
-
from trac.web.api import ITemplateStreamFilter
|
2
|
-
from trac.core import *
|
3
|
-
from genshi.core import *
|
4
|
-
from genshi.builder import tag
|
5
|
-
from sets import Set as set
|
6
|
-
from genshi.filters.transform import Transformer
|
7
|
-
import re
|
8
|
-
|
9
|
-
from trac.ticket.report import ReportModule
|
10
|
-
from trac.util.datefmt import format_datetime, format_time
|
11
|
-
import csv
|
12
|
-
from trac.web.api import RequestDone
|
13
|
-
|
14
|
-
billing_report_regex = re.compile("\{(?P<reportid>\d*)\}")
|
15
|
-
def report_id_from_text(text):
|
16
|
-
m = billing_report_regex.match(text)
|
17
|
-
if m:
|
18
|
-
return int(m.groupdict()["reportid"])
|
19
|
-
|
20
|
-
def get_billing_reports(comp):
|
21
|
-
cur = comp.env.get_db_cnx().cursor()
|
22
|
-
try:
|
23
|
-
cur.execute("SELECT id FROM custom_report")
|
24
|
-
return set([x[0] for x in cur.fetchall()])
|
25
|
-
except Exception, e:
|
26
|
-
# if we can't get the billing reports (e.g. the
|
27
|
-
# TimingAndEstimationPlugin isn't installed), silently continue
|
28
|
-
# without hiding anything.
|
29
|
-
return set()
|
30
|
-
|
31
|
-
class RowFilter(object):
|
32
|
-
"""A genshi filter that operates on table rows, completely hiding any that
|
33
|
-
are in the billing_reports table."""
|
34
|
-
|
35
|
-
def __init__(self, comp):
|
36
|
-
self.component = comp
|
37
|
-
self.billing_reports = get_billing_reports(comp)
|
38
|
-
self.component.log.debug('self.billing_reports= %r' % self.billing_reports)
|
39
|
-
|
40
|
-
def __call__(self, row_stream):
|
41
|
-
events = list(row_stream)
|
42
|
-
report_url = Stream(events) \
|
43
|
-
.select('td[@class="report"]/a/@href').render()
|
44
|
-
id = int(report_url.split('/')[-1])
|
45
|
-
|
46
|
-
if not id in self.billing_reports:
|
47
|
-
for kind,data,pos in Stream(events):
|
48
|
-
yield kind,data,pos
|
49
|
-
|
50
|
-
class ReportsFilter(Component):
|
51
|
-
"""Remove all billing reports from the reports list."""
|
52
|
-
implements(ITemplateStreamFilter)
|
53
|
-
|
54
|
-
def filter_stream(self, req, method, filename, stream, data):
|
55
|
-
if not filename == 'report_view.html':
|
56
|
-
return stream
|
57
|
-
self.log.debug("Applying Reports Filter to remove T&E reports")
|
58
|
-
return stream | Transformer(
|
59
|
-
'//table[@class="listing reports"]/tbody/tr'
|
60
|
-
).filter(RowFilter(self))
|
61
|
-
|
62
|
-
class ReportScreenFilter(Component):
|
63
|
-
"""Hides TandE reports even when you just go to the url"""
|
64
|
-
implements(ITemplateStreamFilter)
|
65
|
-
def __init__(self):
|
66
|
-
self.billing_reports = get_billing_reports(self)
|
67
|
-
self.log.debug('ReportScreenFilter: self.billing_reports= %r' % self.billing_reports)
|
68
|
-
|
69
|
-
def filter_stream(self, req, method, filename, stream, data):
|
70
|
-
if not filename == 'report_view.html':
|
71
|
-
return stream
|
72
|
-
reportid = [None]
|
73
|
-
|
74
|
-
def idhelper(strm):
|
75
|
-
header = strm[0][1]
|
76
|
-
if not reportid[0]:
|
77
|
-
self.log.debug("ReportScreenFilter: helper: %s %s %s"%(strm,header,report_id_from_text(header)))
|
78
|
-
reportid[0] = report_id_from_text(header)
|
79
|
-
for kind, data, pos in strm:
|
80
|
-
yield kind, data, pos
|
81
|
-
|
82
|
-
def permhelper(strm):
|
83
|
-
id = reportid[0]
|
84
|
-
self.log.debug("ReportScreenFilter: id:%s, in bill: %s has perm:%s" % (id, id in self.billing_reports, req.perm.has_permission("TIME_VIEW")))
|
85
|
-
if id and id in self.billing_reports and not req.perm.has_permission("TIME_VIEW"):
|
86
|
-
self.log.debug("ReportScreenFilter: No time view, prevent render")
|
87
|
-
msg = "YOU MUST HAVE TIME_VIEW PERMSSIONS TO VIEW THIS REPORT"
|
88
|
-
for kind, data, pos in tag.span(msg).generate():
|
89
|
-
yield kind, data, pos
|
90
|
-
else:
|
91
|
-
for kind, data, pos in strm:
|
92
|
-
yield kind, data, pos
|
93
|
-
|
94
|
-
self.log.debug("ReportScreenFilter: About to prevent rendering of billing reports without permissions")
|
95
|
-
stream = stream | Transformer('//div[@id="content"]/h1/text()').filter(idhelper)
|
96
|
-
stream = stream | Transformer('//div[@id="content"]').filter(permhelper)
|
97
|
-
return stream
|
98
|
-
|
99
|
-
## ENFORCE PERMISSIONS ON report exports
|
100
|
-
|
101
|
-
billing_report_fname_regex = re.compile("report_(?P<reportid>\d*)")
|
102
|
-
def report_id_from_filename(text):
|
103
|
-
if text:
|
104
|
-
m = billing_report_fname_regex.match(text)
|
105
|
-
if m:
|
106
|
-
return int(m.groupdict()["reportid"])
|
107
|
-
return -1;
|
108
|
-
|
109
|
-
|
110
|
-
def _send_csv(self, req, cols, rows, sep=',', mimetype='text/plain',
|
111
|
-
filename=None):
|
112
|
-
req.send_response(200)
|
113
|
-
req.send_header('Content-Type', mimetype + ';charset=utf-8')
|
114
|
-
if filename:
|
115
|
-
req.send_header('Content-Disposition', 'filename=' + filename)
|
116
|
-
req.end_headers()
|
117
|
-
|
118
|
-
id = report_id_from_filename(filename)
|
119
|
-
reports = get_billing_reports(self)
|
120
|
-
if id in reports and not req.perm.has_permission("TIME_VIEW"):
|
121
|
-
raise RequestDone
|
122
|
-
|
123
|
-
def iso_time(t):
|
124
|
-
return format_time(t, 'iso8601')
|
125
|
-
|
126
|
-
def iso_datetime(dt):
|
127
|
-
return format_datetime(dt, 'iso8601')
|
128
|
-
|
129
|
-
col_conversions = {
|
130
|
-
'time': iso_time,
|
131
|
-
'datetime': iso_datetime,
|
132
|
-
'changetime': iso_datetime,
|
133
|
-
'date': iso_datetime,
|
134
|
-
'created': iso_datetime,
|
135
|
-
'modified': iso_datetime,
|
136
|
-
}
|
137
|
-
|
138
|
-
converters = [col_conversions.get(c.strip('_'), unicode) for c in cols]
|
139
|
-
|
140
|
-
writer = csv.writer(req, delimiter=sep)
|
141
|
-
writer.writerow([unicode(c).encode('utf-8') for c in cols])
|
142
|
-
for row in rows:
|
143
|
-
row = list(row)
|
144
|
-
for i in xrange(len(row)):
|
145
|
-
row[i] = converters[i](row[i]).encode('utf-8')
|
146
|
-
writer.writerow(row)
|
147
|
-
|
148
|
-
raise RequestDone
|
149
|
-
|
150
|
-
ReportModule._send_csv = _send_csv
|
data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/statuses.py
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
import dbhelper
|
2
|
-
from trac.ticket.default_workflow import get_workflow_config
|
3
|
-
from sets import Set
|
4
|
-
|
5
|
-
def status_variables(statuses):
|
6
|
-
return ', '.join(['$'+i.upper().replace("_","").replace(" ","") for i in list(statuses)])
|
7
|
-
|
8
|
-
def get_statuses(com):
|
9
|
-
config = com.config
|
10
|
-
stats = get_statuses_from_workflow(config)
|
11
|
-
status_sql = """
|
12
|
-
SELECT DISTINCT status FROM ticket WHERE status <> '' ;
|
13
|
-
"""
|
14
|
-
stats |= Set(dbhelper.get_column_as_list(com, status_sql))
|
15
|
-
stats.difference_update(['', None])
|
16
|
-
return stats
|
17
|
-
|
18
|
-
def get_statuses_from_workflow(config):
|
19
|
-
wf = get_workflow_config(config)
|
20
|
-
x = Set()
|
21
|
-
for key, value in wf.items():
|
22
|
-
x.add(value['newstate'])
|
23
|
-
x |= Set(value['oldstates'])
|
24
|
-
x.difference_update([u'*'])
|
25
|
-
return x
|
data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/tande_filters.py
DELETED
@@ -1,131 +0,0 @@
|
|
1
|
-
from trac.web.api import ITemplateStreamFilter
|
2
|
-
from trac.perm import IPermissionRequestor
|
3
|
-
from trac.core import *
|
4
|
-
from genshi.core import *
|
5
|
-
from genshi.builder import tag
|
6
|
-
from sets import Set as set
|
7
|
-
from genshi.filters.transform import Transformer
|
8
|
-
from blackmagic import *
|
9
|
-
from trac.ticket.query import QueryModule
|
10
|
-
|
11
|
-
from StringIO import StringIO
|
12
|
-
import csv
|
13
|
-
from trac.mimeview.api import Context
|
14
|
-
from trac.resource import Resource
|
15
|
-
|
16
|
-
## MONKEY PATCH THE QUERY MODULE CSV EXPORT FN TO ENFORCE PERMISSIONS
|
17
|
-
def new_csv_export(self, req, query, sep=',', mimetype='text/plain'):
|
18
|
-
self.log.debug("T&E plugin has overridden QueryModule.csv_export so to enforce field permissions")
|
19
|
-
|
20
|
-
## find the columns that should be hidden
|
21
|
-
hidden_fields = []
|
22
|
-
fields = self.config.getlist(csection, 'fields', [])
|
23
|
-
self.log.debug('QueryModule.csv_export: found : %s' % fields)
|
24
|
-
for field in fields:
|
25
|
-
perms = self.config.getlist(csection, '%s.permission' % field, [])
|
26
|
-
#self.log.debug('QueryModule.csv_export: read permission config: %s has %s' % (field, perms))
|
27
|
-
for (perm, denial) in [s.split(":") for s in perms] :
|
28
|
-
perm = perm.upper()
|
29
|
-
#self.log.debug('QueryModule.csv_export: testing permission: %s:%s should act= %s' %
|
30
|
-
# (field, perm, (not req.perm.has_permission(perm) or perm == "ALWAYS")))
|
31
|
-
if (not req.perm.has_permission(perm) or perm == "ALWAYS") and denial.lower() in ["remove","hide"]:
|
32
|
-
hidden_fields.append(field)
|
33
|
-
## END find the columns that should be hidden
|
34
|
-
|
35
|
-
content = StringIO()
|
36
|
-
cols = query.get_columns()
|
37
|
-
writer = csv.writer(content, delimiter=sep)
|
38
|
-
writer = csv.writer(content, delimiter=sep, quoting=csv.QUOTE_MINIMAL)
|
39
|
-
writer.writerow([unicode(c).encode('utf-8') for c in cols if c not in hidden_fields])
|
40
|
-
|
41
|
-
context = Context.from_request(req)
|
42
|
-
results = query.execute(req, self.env.get_db_cnx())
|
43
|
-
self.log.debug('QueryModule.csv_export: hidding columns %s' % hidden_fields)
|
44
|
-
for result in results:
|
45
|
-
ticket = Resource('ticket', result['id'])
|
46
|
-
if 'TICKET_VIEW' in req.perm(ticket):
|
47
|
-
values = []
|
48
|
-
for col in cols:
|
49
|
-
if col not in hidden_fields:
|
50
|
-
value = result[col]
|
51
|
-
if col in ('cc', 'reporter'):
|
52
|
-
value = Chrome(self.env).format_emails(context(ticket),
|
53
|
-
value)
|
54
|
-
values.append(unicode(value).encode('utf-8'))
|
55
|
-
writer.writerow(values)
|
56
|
-
return (content.getvalue(), '%s;charset=utf-8' % mimetype)
|
57
|
-
|
58
|
-
QueryModule.export_csv = new_csv_export
|
59
|
-
|
60
|
-
class TicketFormatFilter(Component):
|
61
|
-
"""Filtering the streams to alter the base format of the ticket"""
|
62
|
-
implements(ITemplateStreamFilter)
|
63
|
-
|
64
|
-
def filter_stream(self, req, method, filename, stream, data):
|
65
|
-
self.log.debug("TicketFormatFilter executing")
|
66
|
-
if not filename == 'ticket.html':
|
67
|
-
self.log.debug("TicketFormatFilter not the correct template")
|
68
|
-
return stream
|
69
|
-
|
70
|
-
self.log.debug("TicketFormatFilter disabling totalhours and removing header hours")
|
71
|
-
stream = disable_field(stream, "totalhours")
|
72
|
-
stream = remove_header(stream, "hours")
|
73
|
-
return stream
|
74
|
-
|
75
|
-
|
76
|
-
class QueryColumnPermissionFilter(Component):
|
77
|
-
""" Filtering the stream to remove """
|
78
|
-
implements(ITemplateStreamFilter)
|
79
|
-
|
80
|
-
## ITemplateStreamFilter
|
81
|
-
|
82
|
-
def filter_stream(self, req, method, filename, stream, data):
|
83
|
-
if not filename == "query.html":
|
84
|
-
self.log.debug('Not a query returning')
|
85
|
-
return stream
|
86
|
-
|
87
|
-
def make_col_helper(field):
|
88
|
-
def column_helper (column_stream):
|
89
|
-
s = Stream(column_stream)
|
90
|
-
val = s.select('//input/@value').render()
|
91
|
-
if val.lower() != field.lower(): #if we are the field just skip it
|
92
|
-
#identity stream filter
|
93
|
-
for kind, data, pos in s:
|
94
|
-
yield kind, data, pos
|
95
|
-
return column_helper
|
96
|
-
|
97
|
-
fields = self.config.getlist(csection, 'fields', [])
|
98
|
-
for field in fields:
|
99
|
-
self.log.debug('found : %s' % field)
|
100
|
-
perms = self.config.getlist(csection, '%s.permission' % field, [])
|
101
|
-
self.log.debug('read permission config: %s has %s' % (field, perms))
|
102
|
-
for (perm, denial) in [s.split(":") for s in perms] :
|
103
|
-
perm = perm.upper()
|
104
|
-
self.log.debug('testing permission: %s:%s should act= %s' %
|
105
|
-
(field, perm, (not req.perm.has_permission(perm) or perm == "ALWAYS")))
|
106
|
-
if (not req.perm.has_permission(perm) or perm == "ALWAYS") and denial.lower() in ["remove","hide"]:
|
107
|
-
# remove from the list of addable
|
108
|
-
stream = stream | Transformer(
|
109
|
-
'//select[@id="add_filter"]/option[@value="%s"]' % field
|
110
|
-
).replace(" ")
|
111
|
-
|
112
|
-
# remove from the list of columns
|
113
|
-
stream = stream | Transformer(
|
114
|
-
'//fieldset[@id="columns"]/div/label'
|
115
|
-
).filter(make_col_helper(field))
|
116
|
-
|
117
|
-
#remove from the results table
|
118
|
-
stream = stream | Transformer(
|
119
|
-
'//th[@class="%s"]' % field
|
120
|
-
).replace(" ")
|
121
|
-
stream = stream | Transformer(
|
122
|
-
'//td[@class="%s"]' % field
|
123
|
-
).replace(" ")
|
124
|
-
|
125
|
-
# remove from the filters
|
126
|
-
stream = stream | Transformer(
|
127
|
-
'//tr[@class="%s"]' % field
|
128
|
-
).replace(" ")
|
129
|
-
|
130
|
-
|
131
|
-
return stream
|
@@ -1,84 +0,0 @@
|
|
1
|
-
<?cs include "header.cs"?>
|
2
|
-
<?cs include "macros.cs"?>
|
3
|
-
|
4
|
-
<form method="post" action="<?cs var:billing_info.href ?>" >
|
5
|
-
<div id="content" class="billing">
|
6
|
-
<a href="<?cs var:billing_info.usermanual_href ?>" ><?cs var:billing_info.usermanual_title ?></a>
|
7
|
-
<div id="messages" >
|
8
|
-
<?cs each:item = billing_info.messages ?>
|
9
|
-
<div class="message" ><?cs var:item ?></div>
|
10
|
-
<?cs /each ?>
|
11
|
-
</div>
|
12
|
-
|
13
|
-
<table border="0" cellspacing="0" cellpadding="0" class="minorsection">
|
14
|
-
<tr>
|
15
|
-
<td colspan="2" >
|
16
|
-
<div class="minorsection">
|
17
|
-
<div class="label" >Billing Status:</div>
|
18
|
-
<label for="billable">Billable: </label>
|
19
|
-
<input id="billable" name="billable" type="checkbox" checked="true" />
|
20
|
-
|
21
|
-
|
|
22
|
-
<label for="unbillable">Not Billable: </label>
|
23
|
-
<input id="unbillable" name="unbillable" type="checkbox" />
|
24
|
-
</div>
|
25
|
-
<div class="minorsection">
|
26
|
-
<div class="label" >Status:</div>
|
27
|
-
<label for="new">New: </label>
|
28
|
-
<input id="new" name="new" type="checkbox" checked="true" />
|
29
|
-
|
|
30
|
-
<label for="assigned">Assigned: </label>
|
31
|
-
<input id="assigned" name="assigned" type="checkbox" checked="true" />
|
32
|
-
|
|
33
|
-
<label for="reopened">Reopened: </label>
|
34
|
-
<input id="reopened" name="reopened" type="checkbox" checked="true" />
|
35
|
-
|
|
36
|
-
<label for="closed">Closed: </label>
|
37
|
-
<input id="closed" name="closed" type="checkbox" checked="true" />
|
38
|
-
</div>
|
39
|
-
|
40
|
-
</td>
|
41
|
-
</tr><tr class="minorsection">
|
42
|
-
<td class="minorsectionleft" valign="top"><label for="startdate" >Start Date:</label></td>
|
43
|
-
<td class="minorsectionright"><input id="startdate" name="startdate" type="text" /> or:<br />
|
44
|
-
<label for="startbilling" >Choose an old billing date:</label><br />
|
45
|
-
<select id="startbilling" name="startbilling" >
|
46
|
-
<option value="" ></option>
|
47
|
-
<?cs each:item = billing_info.billdates ?>
|
48
|
-
<option value="<?cs var:item.value ?>" ><?cs var:item.text ?></option>
|
49
|
-
<?cs /each ?>
|
50
|
-
</select>
|
51
|
-
</td>
|
52
|
-
</tr><tr class="minorsection">
|
53
|
-
<td class="minorsectionleft" valign="top"><label for="enddate" >End Date:</label>
|
54
|
-
</td>
|
55
|
-
<td class="minorsectionright">
|
56
|
-
<input id="enddate" name="enddate" type="text" /> or:<br />
|
57
|
-
<label for="endbilling" >Choose an old billing date:</label><br />
|
58
|
-
<select id="endbilling" name="endbilling" >
|
59
|
-
<option value="" ></option>
|
60
|
-
<?cs each:item = billing_info.billdates ?>
|
61
|
-
<option value="<?cs var:item.value ?>" ><?cs var:item.text ?></option>
|
62
|
-
<?cs /each ?>
|
63
|
-
</select>
|
64
|
-
</td>
|
65
|
-
</tr>
|
66
|
-
</table>
|
67
|
-
<ul id="reportlinks">
|
68
|
-
<?cs each:report_group = billing_info.reports ?>
|
69
|
-
<li><?cs var:report_group.title ?>
|
70
|
-
<ul>
|
71
|
-
<?cs each:report = report_group.reports ?>
|
72
|
-
<li><a href="" onmouseover="linkify(this, '<?cs var:billing_info.report_base_href ?>/<?cs var:report.id ?>')" >
|
73
|
-
<?cs var:report.title ?>
|
74
|
-
</a></li>
|
75
|
-
<?cs /each ?>
|
76
|
-
</ul>
|
77
|
-
</li>
|
78
|
-
<?cs /each ?>
|
79
|
-
</ul>
|
80
|
-
<input type="submit" name="setbillingtime" value="Set Billing Time" onclick="return confirm('Are you sure that you want to create a billed date?')" />
|
81
|
-
|
82
|
-
</div>
|
83
|
-
</form>
|
84
|
-
<?cs include "footer.cs"?>
|
@@ -1,104 +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:py="http://genshi.edgewall.org/"
|
6
|
-
xmlns:xi="http://www.w3.org/2001/XInclude">
|
7
|
-
<xi:include href="layout.html" />
|
8
|
-
<xi:include href="macros.html" />
|
9
|
-
|
10
|
-
<head>
|
11
|
-
<title>Time Tracking Management for Trac.11</title>
|
12
|
-
<script type="text/javascript" src="${chrome.htdocs_location}js/wikitoolbar.js"></script>
|
13
|
-
<script type="text/javascript" py:choose="">
|
14
|
-
$(document).ready(function() {
|
15
|
-
$("div.description").find("h1,h2,h3,h4,h5,h6").addAnchor("Link to this section");
|
16
|
-
});
|
17
|
-
</script>
|
18
|
-
</head>
|
19
|
-
|
20
|
-
<body>
|
21
|
-
<form method="post" action="${billing_info.href}" >
|
22
|
-
<div id="content" class="billing">
|
23
|
-
<a href="$billing_info.usermanual_href" >$billing_info.usermanual_title</a>
|
24
|
-
<div id="messages" >
|
25
|
-
<py:for each="item in billing_info.messages" >
|
26
|
-
<div class="message" >$item</div>
|
27
|
-
</py:for>
|
28
|
-
</div>
|
29
|
-
|
30
|
-
<table border="0" cellspacing="0" cellpadding="0" class="minorsection">
|
31
|
-
<tr>
|
32
|
-
<td colspan="2" >
|
33
|
-
<div class="minorsection">
|
34
|
-
<div class="label" >Billing Status:</div>
|
35
|
-
<label for="billable">Billable: </label>
|
36
|
-
<input id="billable" name="billable" type="checkbox" checked="true" />
|
37
|
-
|
38
|
-
|
|
39
|
-
<label for="unbillable">Not Billable: </label>
|
40
|
-
<input id="unbillable" name="unbillable" type="checkbox" />
|
41
|
-
</div>
|
42
|
-
|
43
|
-
<div class="minorsection">
|
44
|
-
<div class="label" >Status:</div>
|
45
|
-
<py:for each="status in statuses" >
|
46
|
-
<label for="$status">${status.capitalize()}: </label>
|
47
|
-
<input id="$status" name="$status" type="checkbox" checked="true" />
|
48
|
-
</py:for>
|
49
|
-
<script>
|
50
|
-
<py:for each="status in statuses" >
|
51
|
-
addBillingField("$status", "checkbox", true);
|
52
|
-
</py:for>
|
53
|
-
</script>
|
54
|
-
</div>
|
55
|
-
|
56
|
-
</td>
|
57
|
-
</tr><tr class="minorsection">
|
58
|
-
<td class="minorsectionleft" valign="top"><label for="startdate" >Start Date:</label></td>
|
59
|
-
<td class="minorsectionright"><input id="startdate" name="startdate" type="text" /> or:<br />
|
60
|
-
<label for="startbilling" >Choose an old billing date:</label><br />
|
61
|
-
<select id="startbilling" name="startbilling" >
|
62
|
-
<option value="" ></option>
|
63
|
-
<py:for each="item in billing_info.billdates" >
|
64
|
-
<option value="$item.value" >$item.text</option>
|
65
|
-
</py:for>
|
66
|
-
</select>
|
67
|
-
</td>
|
68
|
-
</tr><tr class="minorsection">
|
69
|
-
<td class="minorsectionleft" valign="top"><label for="enddate" >End Date:</label>
|
70
|
-
</td>
|
71
|
-
<td class="minorsectionright">
|
72
|
-
<input id="enddate" name="enddate" type="text" /> or:<br />
|
73
|
-
<label for="endbilling" >Choose an old billing date:</label><br />
|
74
|
-
<select id="endbilling" name="endbilling" >
|
75
|
-
<option value="" ></option>
|
76
|
-
<py:for each="item in billing_info.billdates" >
|
77
|
-
<option value="$item.value" >$item.text</option>
|
78
|
-
</py:for>
|
79
|
-
</select>
|
80
|
-
</td>
|
81
|
-
</tr>
|
82
|
-
</table>
|
83
|
-
<ul id="reportlinks">
|
84
|
-
<py:for each="key in reports" >
|
85
|
-
<li>${reports[key]["title"]}
|
86
|
-
<ul>
|
87
|
-
<py:for each="report in reports[key]['reports']">
|
88
|
-
<li><a href="" onmouseover="linkify(this, '$billing_info.report_base_href/$report.id')" >
|
89
|
-
$report.title
|
90
|
-
</a></li>
|
91
|
-
</py:for>
|
92
|
-
</ul>
|
93
|
-
</li>
|
94
|
-
</py:for>
|
95
|
-
|
96
|
-
</ul>
|
97
|
-
<input
|
98
|
-
py:if="is_time_admin"
|
99
|
-
type="submit" name="setbillingtime" value="Set Billing Time" onclick="return confirm('Are you sure that you want to create a billed date?')" />
|
100
|
-
|
101
|
-
</div>
|
102
|
-
</form>
|
103
|
-
</body>
|
104
|
-
</html>
|