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
@@ -1,105 +0,0 @@
|
|
1
|
-
from trac.core import *
|
2
|
-
from trac.web.chrome import add_stylesheet, ITemplateProvider
|
3
|
-
from trac.web.api import IRequestFilter, ITemplateStreamFilter
|
4
|
-
from trac.ticket.api import ITicketManipulator
|
5
|
-
from trac.ticket.model import Ticket
|
6
|
-
from trac.util.html import html, Markup
|
7
|
-
|
8
|
-
from genshi.core import Markup
|
9
|
-
from genshi.builder import tag
|
10
|
-
from genshi.filters.transform import Transformer
|
11
|
-
|
12
|
-
from clients import model
|
13
|
-
from StringIO import StringIO
|
14
|
-
|
15
|
-
class ClientModule(Component):
|
16
|
-
"""Allows for tickets to be assigned to particular clients."""
|
17
|
-
|
18
|
-
implements(IRequestFilter, ITemplateStreamFilter, ITemplateProvider)
|
19
|
-
|
20
|
-
# IRequestFilter methods
|
21
|
-
def pre_process_request(self, req, handler):
|
22
|
-
# Add Stylesheet here, so that the ticket page gets it too :)
|
23
|
-
add_stylesheet(req, "clients/clients.css")
|
24
|
-
return handler
|
25
|
-
|
26
|
-
def post_process_request(self, req, template, data, content_type):
|
27
|
-
# Some ticket views do not actually load the data in this way
|
28
|
-
# e.g. action=history or action=diff
|
29
|
-
if not data or not data.has_key('fields'):
|
30
|
-
return template, data, content_type
|
31
|
-
|
32
|
-
newticket = req.path_info.startswith('/newticket')
|
33
|
-
if req.path_info.startswith('/ticket/') or newticket:
|
34
|
-
for field in data['fields']:
|
35
|
-
if 'client' == field['name']:
|
36
|
-
field['type'] = 'select'
|
37
|
-
field['options'] = []
|
38
|
-
for client in model.Client.select(self.env):
|
39
|
-
field['options'].append(client.name)
|
40
|
-
if newticket:
|
41
|
-
default_client = self.config.get('ticket', 'default_client')
|
42
|
-
if default_client:
|
43
|
-
data['ticket']['client'] = default_client
|
44
|
-
break;
|
45
|
-
elif req.path_info.startswith('/query'):
|
46
|
-
if data['fields'].has_key('client'):
|
47
|
-
data['fields']['client']['type'] = 'select'
|
48
|
-
data['fields']['client']['options'] = []
|
49
|
-
for client in model.Client.select(self.env):
|
50
|
-
data['fields']['client']['options'].append(client.name)
|
51
|
-
return template, data, content_type
|
52
|
-
|
53
|
-
# ITemplateStreamFilter methods
|
54
|
-
def filter_stream(self, req, method, filename, stream, data):
|
55
|
-
newticket = req.path_info.startswith('/newticket')
|
56
|
-
if req.path_info.startswith('/ticket/') or newticket:
|
57
|
-
setdefaultrate = ''
|
58
|
-
if newticket:
|
59
|
-
setdefaultrate = "$('#field-client').trigger('change');"
|
60
|
-
|
61
|
-
script = StringIO()
|
62
|
-
script.write("""
|
63
|
-
$(document).ready(function() {
|
64
|
-
$('#field-client').change(function() {
|
65
|
-
""");
|
66
|
-
script.write('var clientrates = new Array();')
|
67
|
-
for client in model.Client.select(self.env):
|
68
|
-
script.write('clientrates["%s"] = %s;' % (client.name, client.default_rate or '""'))
|
69
|
-
script.write("""
|
70
|
-
try { $('#field-clientrate').attr('value', clientrates[this.options[this.selectedIndex].value]); }
|
71
|
-
catch (er) { }
|
72
|
-
});
|
73
|
-
%s
|
74
|
-
});""" % setdefaultrate);
|
75
|
-
stream |= Transformer('.//head').append(tag.script(script.getvalue(), type_='text/javascript'))
|
76
|
-
return stream
|
77
|
-
|
78
|
-
# ITemplateProvider
|
79
|
-
def get_htdocs_dirs(self):
|
80
|
-
"""Return the absolute path of a directory containing additional
|
81
|
-
static resources (such as images, style sheets, etc).
|
82
|
-
"""
|
83
|
-
from pkg_resources import resource_filename
|
84
|
-
return [('clients', resource_filename(__name__, 'htdocs'))]
|
85
|
-
|
86
|
-
def get_templates_dirs(self):
|
87
|
-
"""Return the absolute path of the directory containing the provided
|
88
|
-
ClearSilver templates.
|
89
|
-
"""
|
90
|
-
from pkg_resources import resource_filename
|
91
|
-
return [resource_filename(__name__, 'templates')]
|
92
|
-
|
93
|
-
# ITicketManipulator methods
|
94
|
-
def prepare_ticket(self, req, ticket, fields, actions):
|
95
|
-
pass
|
96
|
-
|
97
|
-
def validate_ticket(self, req, ticket):
|
98
|
-
# Todo validate client is valid
|
99
|
-
pass
|
100
|
-
#if req.args.get('action') == 'resolve':
|
101
|
-
# links = TicketLinks(self.env, ticket)
|
102
|
-
# for i in links.blocked_by:
|
103
|
-
# if Ticket(self.env, i)['status'] != 'closed':
|
104
|
-
# yield None, 'Ticket #%s is blocking this ticket'%i
|
105
|
-
|
@@ -1,287 +0,0 @@
|
|
1
|
-
import md5
|
2
|
-
import sys
|
3
|
-
import time
|
4
|
-
|
5
|
-
from trac.core import *
|
6
|
-
|
7
|
-
from clients.summary import IClientSummaryProvider
|
8
|
-
from clients.action import IClientActionProvider
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
__all__ = ['ClientEvent']
|
13
|
-
|
14
|
-
def simplify_whitespace(name):
|
15
|
-
"""Strip spaces and remove duplicate spaces within names"""
|
16
|
-
return ' '.join(name.split())
|
17
|
-
|
18
|
-
class ClientEventsSystem(Component):
|
19
|
-
summaries = ExtensionPoint(IClientSummaryProvider)
|
20
|
-
actions = ExtensionPoint(IClientActionProvider)
|
21
|
-
|
22
|
-
def get_summaries(self):
|
23
|
-
for summary in self.summaries:
|
24
|
-
yield summary.get_name()
|
25
|
-
|
26
|
-
def get_summary(self, name):
|
27
|
-
for summary in self.summaries:
|
28
|
-
if name == summary.get_name():
|
29
|
-
return summary
|
30
|
-
return None
|
31
|
-
|
32
|
-
def get_actions(self):
|
33
|
-
for action in self.actions:
|
34
|
-
yield action.get_name()
|
35
|
-
|
36
|
-
def get_action(self, name):
|
37
|
-
for action in self.actions:
|
38
|
-
if name == action.get_name():
|
39
|
-
return action
|
40
|
-
return None
|
41
|
-
|
42
|
-
class ClientEvent(object):
|
43
|
-
|
44
|
-
def __init__(self, env, name=None, client=None, db=None):
|
45
|
-
self.env = env
|
46
|
-
if name:
|
47
|
-
name = simplify_whitespace(name)
|
48
|
-
if name:
|
49
|
-
if not db:
|
50
|
-
db = self.env.get_db_cnx()
|
51
|
-
cursor = db.cursor()
|
52
|
-
cursor.execute("SELECT summary, action, lastrun "
|
53
|
-
"FROM client_events "
|
54
|
-
"WHERE name=%s", (name,))
|
55
|
-
row = cursor.fetchone()
|
56
|
-
if not row:
|
57
|
-
raise TracError('Client Event %s does not exist.' % name)
|
58
|
-
self.md5 = md5.new(name).hexdigest()
|
59
|
-
self.name = self._old_name = name
|
60
|
-
self.summary = row[0] or ''
|
61
|
-
self.action = row[1] or ''
|
62
|
-
self.lastrun = row[2] or 0
|
63
|
-
self._load_options(client, db)
|
64
|
-
else:
|
65
|
-
self.name = self._old_name = None
|
66
|
-
self.summary = ''
|
67
|
-
self.action = ''
|
68
|
-
self.lastrun = 0
|
69
|
-
|
70
|
-
|
71
|
-
exists = property(fget=lambda self: self._old_name is not None)
|
72
|
-
|
73
|
-
|
74
|
-
def delete(self, db=None):
|
75
|
-
assert self.exists, 'Cannot deleting non-existent client event'
|
76
|
-
if not db:
|
77
|
-
db = self.env.get_db_cnx()
|
78
|
-
handle_ta = True
|
79
|
-
else:
|
80
|
-
handle_ta = False
|
81
|
-
|
82
|
-
cursor = db.cursor()
|
83
|
-
self.env.log.info('Deleting client event %s' % self.name)
|
84
|
-
cursor.execute("DELETE FROM client_events WHERE name=%s", (self.name,))
|
85
|
-
|
86
|
-
self.name = self._old_name = None
|
87
|
-
|
88
|
-
if handle_ta:
|
89
|
-
db.commit()
|
90
|
-
|
91
|
-
def insert(self, db=None):
|
92
|
-
assert not self.exists, 'Cannot insert existing client event'
|
93
|
-
system = ClientEventsSystem(self.env);
|
94
|
-
assert system.get_summary(self.summary) is not None , 'Invalid summary'
|
95
|
-
assert system.get_action(self.action) is not None, 'Invalid action'
|
96
|
-
self.name = simplify_whitespace(self.name)
|
97
|
-
assert self.name, 'Cannot create client event with no name'
|
98
|
-
if not db:
|
99
|
-
db = self.env.get_db_cnx()
|
100
|
-
handle_ta = True
|
101
|
-
else:
|
102
|
-
handle_ta = False
|
103
|
-
|
104
|
-
# Todo: verify client_event with that name does not currently exist...
|
105
|
-
cursor = db.cursor()
|
106
|
-
self.env.log.debug("Creating new client event '%s'" % self.name)
|
107
|
-
cursor.execute("INSERT INTO client_events (name,summary,action,lastrun) "
|
108
|
-
"VALUES (%s,%s,%s,%s)",
|
109
|
-
(self.name, self.summary, self.action, int(time.time())))
|
110
|
-
|
111
|
-
if handle_ta:
|
112
|
-
db.commit()
|
113
|
-
|
114
|
-
def _load_client_options(self, client, opttype, db):
|
115
|
-
assert self.exists, 'Cannot update non-existent client event'
|
116
|
-
assert opttype in ('summary', 'action'), 'Invalid options type'
|
117
|
-
system = ClientEventsSystem(self.env);
|
118
|
-
if 'summary' == opttype:
|
119
|
-
thing = system.get_summary(self.summary)
|
120
|
-
assert thing is not None , 'Invalid summary'
|
121
|
-
self.summary_description = thing.get_description()
|
122
|
-
else:
|
123
|
-
thing = system.get_action(self.action)
|
124
|
-
assert thing is not None, 'Invalid action'
|
125
|
-
self.action_description = thing.get_description()
|
126
|
-
|
127
|
-
options = {}
|
128
|
-
table = 'client_event_' + opttype + '_options'
|
129
|
-
cursor = db.cursor()
|
130
|
-
cursor.execute("SELECT name, value "
|
131
|
-
"FROM " + table + " "
|
132
|
-
"WHERE client_event=%s AND client=%s",
|
133
|
-
(self._old_name, client or ''))
|
134
|
-
for name, value in cursor:
|
135
|
-
options[name] = value
|
136
|
-
rv = {}
|
137
|
-
for option in thing.options(client):
|
138
|
-
option['md5'] = md5.new(option['name']).hexdigest()
|
139
|
-
if options.has_key(option['name']):
|
140
|
-
option['value'] = options[option['name']]
|
141
|
-
else:
|
142
|
-
option['value'] = ''
|
143
|
-
rv[option['name']] = option
|
144
|
-
return rv
|
145
|
-
|
146
|
-
|
147
|
-
def _load_options(self, client, db):
|
148
|
-
self.summary_options = self._load_client_options(None, 'summary', db)
|
149
|
-
self.action_options = self._load_client_options(None, 'action', db)
|
150
|
-
if client:
|
151
|
-
self.summary_client_options = self._load_client_options(client, 'summary', db)
|
152
|
-
self.action_client_options = self._load_client_options(client, 'action', db)
|
153
|
-
|
154
|
-
|
155
|
-
def _update_client_options(self, client, opttype, options, db=None):
|
156
|
-
assert self.exists, 'Cannot update non-existent client event'
|
157
|
-
assert opttype in ('summary', 'action'), 'Invalid options type'
|
158
|
-
system = ClientEventsSystem(self.env);
|
159
|
-
if 'summary' == opttype:
|
160
|
-
thing = system.get_summary(self.summary)
|
161
|
-
assert thing is not None , 'Invalid summary'
|
162
|
-
else:
|
163
|
-
thing = system.get_action(self.action)
|
164
|
-
assert thing is not None, 'Invalid action'
|
165
|
-
|
166
|
-
if not db:
|
167
|
-
db = self.env.get_db_cnx()
|
168
|
-
handle_ta = True
|
169
|
-
else:
|
170
|
-
handle_ta = False
|
171
|
-
|
172
|
-
table = 'client_event_' + opttype + '_options'
|
173
|
-
cursor = db.cursor()
|
174
|
-
self.env.log.info('Updating client event "%s"' % self._old_name)
|
175
|
-
cursor.execute("DELETE FROM " + table + " "
|
176
|
-
"WHERE client_event=%s AND client=%s",
|
177
|
-
(self._old_name, client or ''))
|
178
|
-
|
179
|
-
valid_options = []
|
180
|
-
for option in thing.options(client):
|
181
|
-
valid_options.append(option['name'])
|
182
|
-
for option in options.values():
|
183
|
-
if option['name'] in valid_options:
|
184
|
-
cursor.execute("INSERT INTO " + table + " (client_event, client, name, value) "
|
185
|
-
"VALUES (%s, %s, %s, %s)",
|
186
|
-
(self._old_name, client or '', option['name'], option['value']))
|
187
|
-
|
188
|
-
if handle_ta:
|
189
|
-
db.commit()
|
190
|
-
|
191
|
-
|
192
|
-
def update_options(self, client=None, db=None):
|
193
|
-
assert self.exists, 'Cannot update non-existent client event'
|
194
|
-
if not db:
|
195
|
-
db = self.env.get_db_cnx()
|
196
|
-
handle_ta = True
|
197
|
-
else:
|
198
|
-
handle_ta = False
|
199
|
-
|
200
|
-
if client:
|
201
|
-
self._update_client_options(client, 'summary', self.summary_client_options, db)
|
202
|
-
self._update_client_options(client, 'action', self.action_client_options, db)
|
203
|
-
else:
|
204
|
-
self._update_client_options(None, 'summary', self.summary_options, db)
|
205
|
-
self._update_client_options(None, 'action', self.action_options, db)
|
206
|
-
|
207
|
-
if handle_ta:
|
208
|
-
db.commit()
|
209
|
-
|
210
|
-
|
211
|
-
def update(self, db=None):
|
212
|
-
assert self.exists, 'Cannot update non-existent client event'
|
213
|
-
self.name = simplify_whitespace(self.name)
|
214
|
-
assert self.name, 'Cannot update client event with no name'
|
215
|
-
if not db:
|
216
|
-
db = self.env.get_db_cnx()
|
217
|
-
handle_ta = True
|
218
|
-
else:
|
219
|
-
handle_ta = False
|
220
|
-
|
221
|
-
cursor = db.cursor()
|
222
|
-
self.env.log.info('Updating client event "%s"' % self._old_name)
|
223
|
-
cursor.execute("UPDATE client_events SET lastrun=%s "
|
224
|
-
"WHERE name=%s",
|
225
|
-
(int(self.lastrun), self._old_name))
|
226
|
-
|
227
|
-
if handle_ta:
|
228
|
-
db.commit()
|
229
|
-
|
230
|
-
def trigger(self, req, client, fromdate, todate, db=None):
|
231
|
-
assert self.exists, 'Cannot trigger a client event that does not exits'
|
232
|
-
system = ClientEventsSystem(self.env);
|
233
|
-
summary = system.get_summary(self.summary)
|
234
|
-
assert summary is not None , 'Invalid summary'
|
235
|
-
action = system.get_action(self.action)
|
236
|
-
assert action is not None, 'Invalid action'
|
237
|
-
|
238
|
-
if not summary.init(self, client):
|
239
|
-
self.env.log.info("Could not init summary")
|
240
|
-
return False
|
241
|
-
if not action.init(self, client):
|
242
|
-
self.env.log.info("Could not init action")
|
243
|
-
return False
|
244
|
-
|
245
|
-
self.env.log.debug("Performing action")
|
246
|
-
return action.perform(req, summary.get_summary(req, fromdate, todate))
|
247
|
-
|
248
|
-
|
249
|
-
def select(cls, env, client=None, db=None):
|
250
|
-
if not db:
|
251
|
-
db = env.get_db_cnx()
|
252
|
-
cursor = db.cursor()
|
253
|
-
cursor.execute("SELECT name, summary, action, lastrun "
|
254
|
-
"FROM client_events "
|
255
|
-
"ORDER BY name")
|
256
|
-
for name, summary, action, lastrun in cursor:
|
257
|
-
clev = cls(env)
|
258
|
-
clev.md5 = md5.new(name).hexdigest()
|
259
|
-
clev.name = clev._old_name = name
|
260
|
-
clev.summary = summary or ''
|
261
|
-
clev.action = action or ''
|
262
|
-
clev.lastrun = lastrun or 0
|
263
|
-
clev._load_options(client, db)
|
264
|
-
yield clev
|
265
|
-
select = classmethod(select)
|
266
|
-
|
267
|
-
def triggerall(cls, env, req, event, db=None):
|
268
|
-
if not db:
|
269
|
-
db = env.get_db_cnx()
|
270
|
-
|
271
|
-
try:
|
272
|
-
ev = cls(env, event, None, db)
|
273
|
-
except:
|
274
|
-
env.log.error("Could not run the event %s" % (event,))
|
275
|
-
return
|
276
|
-
#ev.lastrun = 1
|
277
|
-
now = int(time.time())
|
278
|
-
|
279
|
-
cursor = db.cursor()
|
280
|
-
cursor.execute("SELECT name FROM client ORDER BY name")
|
281
|
-
for client, in cursor:
|
282
|
-
env.log.info("Running event for client: %s" % (client, ))
|
283
|
-
clev = cls(env, event, client)
|
284
|
-
clev.trigger(req, client, ev.lastrun, now)
|
285
|
-
ev.lastrun = now
|
286
|
-
ev.update()
|
287
|
-
triggerall = classmethod(triggerall)
|
@@ -1,71 +0,0 @@
|
|
1
|
-
from trac.core import *
|
2
|
-
from trac.perm import PermissionSystem
|
3
|
-
#from trac.ticket.model import AbstractEnum
|
4
|
-
#from trac.ticket.admin import AbstractEnumAdminPage
|
5
|
-
from trac.ticket.admin import TicketAdminPanel
|
6
|
-
|
7
|
-
|
8
|
-
from clients.events import ClientEvent, ClientEventsSystem
|
9
|
-
|
10
|
-
from trac.util.datefmt import utc, parse_date, get_date_format_hint, \
|
11
|
-
get_datetime_format_hint
|
12
|
-
from trac.web.chrome import add_link, add_script
|
13
|
-
|
14
|
-
|
15
|
-
class ClientEventsAdminPanel(TicketAdminPanel):
|
16
|
-
|
17
|
-
_type = 'clientevents'
|
18
|
-
_label = ('Client Events', 'Client Events')
|
19
|
-
|
20
|
-
# TicketAdminPanel methods
|
21
|
-
def _render_admin_panel(self, req, cat, page, event):
|
22
|
-
# Detail view?
|
23
|
-
if event:
|
24
|
-
clev = ClientEvent(self.env, event)
|
25
|
-
if req.method == 'POST':
|
26
|
-
if req.args.get('save'):
|
27
|
-
# Client Events are not saved... just deleted or viewed...
|
28
|
-
for option in clev.summary_options:
|
29
|
-
arg = 'summary-option-%s' % clev.summary_options[option]['md5']
|
30
|
-
clev.summary_options[option]['value'] = req.args.get(arg)
|
31
|
-
for option in clev.action_options:
|
32
|
-
arg = 'action-option-%s' % clev.action_options[option]['md5']
|
33
|
-
clev.action_options[option]['value'] = req.args.get(arg)
|
34
|
-
clev.update_options()
|
35
|
-
req.redirect(req.href.admin(cat, page))
|
36
|
-
elif req.args.get('cancel'):
|
37
|
-
req.redirect(req.href.admin(cat, page))
|
38
|
-
|
39
|
-
add_script(req, 'common/js/wikitoolbar.js')
|
40
|
-
data = {'view': 'detail', 'event': clev}
|
41
|
-
|
42
|
-
else:
|
43
|
-
if req.method == 'POST':
|
44
|
-
# Add Client
|
45
|
-
if req.args.get('add') and req.args.get('name'):
|
46
|
-
clev = ClientEvent(self.env)
|
47
|
-
clev.name = req.args.get('name')
|
48
|
-
clev.summary = req.args.get('summary')
|
49
|
-
clev.action = req.args.get('action')
|
50
|
-
clev.insert()
|
51
|
-
req.redirect(req.href.admin(cat, page))
|
52
|
-
|
53
|
-
# Remove clients
|
54
|
-
elif req.args.get('remove') and req.args.get('sel'):
|
55
|
-
sel = req.args.get('sel')
|
56
|
-
sel = isinstance(sel, list) and sel or [sel]
|
57
|
-
if not sel:
|
58
|
-
raise TracError('No client event selected')
|
59
|
-
db = self.env.get_db_cnx()
|
60
|
-
for name in sel:
|
61
|
-
clev = ClientEvent(self.env, name, db=db)
|
62
|
-
clev.delete(db=db)
|
63
|
-
db.commit()
|
64
|
-
req.redirect(req.href.admin(cat, page))
|
65
|
-
|
66
|
-
data = {'view': 'list',
|
67
|
-
'events': ClientEvent.select(self.env),
|
68
|
-
'summaries': ClientEventsSystem(self.env).get_summaries(),
|
69
|
-
'actions': ClientEventsSystem(self.env).get_actions()}
|
70
|
-
|
71
|
-
return 'admin_client_events.html', data
|