keithsalisbury-subtrac 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.rdoc +7 -0
- data/Rakefile +56 -0
- data/VERSION.yml +4 -0
- data/bin/subtrac +40 -0
- data/lib/subtrac.rb +245 -0
- data/lib/subtrac/common/clients/index.wsgi +89 -0
- data/lib/subtrac/common/favicon.ico +0 -0
- data/lib/subtrac/common/images/trac/banner_bg.jpg +0 -0
- data/lib/subtrac/common/images/trac/bar_bg.gif +0 -0
- data/lib/subtrac/common/images/trac/footer_back.png +0 -0
- data/lib/subtrac/common/images/trac/main_bg.gif +0 -0
- data/lib/subtrac/common/images/trac/saint_logo_small.png +0 -0
- data/lib/subtrac/common/static/404.html +14 -0
- data/lib/subtrac/common/styles/trac.css +222 -0
- data/lib/subtrac/common/trac.ini +178 -0
- data/lib/subtrac/config/config.yml +54 -0
- data/lib/subtrac/passwords +1 -0
- data/lib/subtrac/shared/trac.ini +178 -0
- data/lib/subtrac/templates/location.erb +16 -0
- data/lib/subtrac/templates/projects/blank/svn/branches/README +0 -0
- data/lib/subtrac/templates/projects/blank/svn/tags/README +0 -0
- data/lib/subtrac/templates/projects/blank/svn/trunk/README +0 -0
- data/lib/subtrac/templates/projects/blank/trac/wiki/WikiStart +57 -0
- data/lib/subtrac/templates/projects/new/svn/trunk/trac/wiki/WikiStart +46 -0
- data/lib/subtrac/templates/projects/new/trac/wiki/WikiStart +23 -0
- data/lib/subtrac/templates/projects/trac_theme/svn/trunk/index/index.html +22 -0
- data/lib/subtrac/templates/projects/trac_theme/svn/trunk/templates/layout.html +56 -0
- data/lib/subtrac/templates/projects/trac_theme/svn/trunk/templates/site.html +27 -0
- data/lib/subtrac/templates/projects/trac_theme/svn/trunk/templates/theme.html +86 -0
- data/lib/subtrac/templates/projects/trac_theme/trac/wiki/WikiStart +4 -0
- data/lib/subtrac/templates/trac.erb +25 -0
- data/lib/subtrac/templates/vhost.erb +35 -0
- data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/advancedworkflow/__init__.py +0 -0
- data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/advancedworkflow/controller.py +419 -0
- data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/setup.cfg +3 -0
- data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/setup.py +20 -0
- data/lib/subtrac/trac-plugins/clientsplugin/clients/__init__.py +0 -0
- data/lib/subtrac/trac-plugins/clientsplugin/clients/action.py +28 -0
- data/lib/subtrac/trac-plugins/clientsplugin/clients/action_email.py +168 -0
- data/lib/subtrac/trac-plugins/clientsplugin/clients/action_zendesk_forum.py +137 -0
- data/lib/subtrac/trac-plugins/clientsplugin/clients/admin.py +91 -0
- data/lib/subtrac/trac-plugins/clientsplugin/clients/api.py +199 -0
- data/lib/subtrac/trac-plugins/clientsplugin/clients/client.py +105 -0
- data/lib/subtrac/trac-plugins/clientsplugin/clients/events.py +287 -0
- data/lib/subtrac/trac-plugins/clientsplugin/clients/eventsadmin.py +71 -0
- data/lib/subtrac/trac-plugins/clientsplugin/clients/htdocs/clients.css +4 -0
- data/lib/subtrac/trac-plugins/clientsplugin/clients/model.py +135 -0
- data/lib/subtrac/trac-plugins/clientsplugin/clients/processor.py +70 -0
- data/lib/subtrac/trac-plugins/clientsplugin/clients/reportmanager.py +142 -0
- data/lib/subtrac/trac-plugins/clientsplugin/clients/reports.py +231 -0
- data/lib/subtrac/trac-plugins/clientsplugin/clients/summary.py +27 -0
- data/lib/subtrac/trac-plugins/clientsplugin/clients/summary_milestone.py +152 -0
- data/lib/subtrac/trac-plugins/clientsplugin/clients/summary_ticketchanges.py +160 -0
- data/lib/subtrac/trac-plugins/clientsplugin/clients/templates/admin_client_events.html +124 -0
- data/lib/subtrac/trac-plugins/clientsplugin/clients/templates/admin_clients.html +134 -0
- data/lib/subtrac/trac-plugins/clientsplugin/cron/changes.xslt +132 -0
- data/lib/subtrac/trac-plugins/clientsplugin/cron/run-client-event +97 -0
- data/lib/subtrac/trac-plugins/clientsplugin/cron/summary.xslt +161 -0
- data/lib/subtrac/trac-plugins/clientsplugin/setup.py +43 -0
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/__init__.py +4 -0
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/burndownchart.py +273 -0
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/hoursinplaceeditor.py +44 -0
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/hoursremaining.py +36 -0
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery-1.2.3.min.js +32 -0
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery.jeditable.js +409 -0
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery.jeditable.mini.js +30 -0
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/templates/edithours.html +53 -0
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/burndownchart.py +181 -0
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/hoursremaining.py +66 -0
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/workloadchart.py +47 -0
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/utils.py +93 -0
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/workloadchart.py +86 -0
- data/lib/subtrac/trac-plugins/estimationtoolsplugin/setup.py +20 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/SumRollups.js +23 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/adw_tracdb.py +128 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/git-post-receive +40 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/trac-post-commit.py +285 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/trac_billing.py +173 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/utils/__init__.py +0 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/utils/mail.py +164 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/setup.py +69 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/__init__.py +1 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/api.py +292 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/blackmagic.py +172 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/dbhelper.py +178 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/billingplugin.css +25 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/field_disabler.js +6 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/formatDate.js +356 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/tip_centerwindow.js +100 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/tip_followscroll.js +84 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/wz_tooltip.js +1149 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/linkifyer.js +119 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/query.js +73 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/ticket.js +165 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/query_webui.py +28 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reportmanager.py +221 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reports.py +675 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reports_filter.py +150 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/statuses.py +25 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/tande_filters.py +131 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/templates/billing.cs +84 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/templates/billing.html +104 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_daemon.py +194 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_policy.py +62 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_webui.py +28 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/usermanual.py +127 -0
- data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/webui.py +129 -0
- data/lib/subtrac/trac-plugins/worklogplugin/setup.py +29 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/__init__.py +1 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/api.py +187 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jqModal.css +40 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jqModal.js +67 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jquery.mousewheel.pack.js +12 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jquery.timeentry.pack.js +7 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/tracWorklog.js +40 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/ui.datepicker.css +208 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/ui.datepicker.js +1439 -0
- 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 +80 -0
- 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 +336 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/reports.py +598 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog.html +45 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_stop.html +70 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_user.html +40 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_webadminui.html +59 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/ticket_daemon.py +33 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/ticket_filter.py +153 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/timeline_hook.py +96 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/usermanual.py +29 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/util.py +31 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/webadminui.py +47 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/webui.py +174 -0
- data/lib/subtrac/trac-plugins/worklogplugin/worklog/xmlrpc.py +73 -0
- data/lib/subtrac/version.rb +4 -0
- metadata +191 -0
data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/blackmagic.py
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
from trac.core import Component, implements, TracError
|
2
|
+
from trac.config import Option, IntOption, ListOption, BoolOption
|
3
|
+
from trac.web.chrome import ITemplateProvider, add_stylesheet, add_script
|
4
|
+
from pkg_resources import resource_filename
|
5
|
+
from trac.web.api import ITemplateStreamFilter
|
6
|
+
from genshi.builder import tag
|
7
|
+
from genshi.core import Markup, Stream
|
8
|
+
from genshi.filters.transform import Transformer
|
9
|
+
import re, cPickle
|
10
|
+
from trac.perm import IPermissionRequestor
|
11
|
+
|
12
|
+
#@staticmethod
|
13
|
+
def disable_field(stream, field):
|
14
|
+
def helper(field_stream):
|
15
|
+
s = Stream(field_stream)
|
16
|
+
value = s.select('@value').render()
|
17
|
+
name = s.select('@name').render()
|
18
|
+
for kind,data,pos in tag.span(value, id=("field-%s"%field)).generate():
|
19
|
+
yield kind,data,pos
|
20
|
+
for kind,data,pos in tag.input(value=value, name=name, type="hidden").generate():
|
21
|
+
yield kind,data,pos
|
22
|
+
|
23
|
+
return stream | Transformer(
|
24
|
+
'//input[@id="field-%s"]' % field
|
25
|
+
).filter(helper)
|
26
|
+
|
27
|
+
|
28
|
+
def remove_header(stream, field):
|
29
|
+
""" Removes the display from the ticket properties """
|
30
|
+
stream = stream | \
|
31
|
+
Transformer('//th[@id="h_%s"]' % field).replace(tag.th(id="h_%s" % field))
|
32
|
+
stream = stream | \
|
33
|
+
Transformer('//td[@headers="h_%s"]' % field).replace(tag.th(id="h_%s" % field))
|
34
|
+
return stream
|
35
|
+
|
36
|
+
def remove_changelog(stream, field):
|
37
|
+
""" Removes entries from the visible changelog"""
|
38
|
+
def helper(field_stream):
|
39
|
+
s = Stream(field_stream)
|
40
|
+
f = s.select('//strong/text()').render()
|
41
|
+
if field != f: #if we are the field just skip it
|
42
|
+
#identity stream filter
|
43
|
+
for kind, data, pos in s:
|
44
|
+
yield kind, data, pos
|
45
|
+
stream = stream | Transformer('//ul[@class="changes"]/li').filter(helper)
|
46
|
+
return stream
|
47
|
+
|
48
|
+
|
49
|
+
def hide_field(stream , field):
|
50
|
+
""" Replaces a field from the form area with an input type=hidden"""
|
51
|
+
def helper (field_stream):
|
52
|
+
type = Stream(field_stream).select('@type').render()
|
53
|
+
if type == 'checkbox':
|
54
|
+
if Stream(field_stream).select('@checked').render() == "checked":
|
55
|
+
value = 1
|
56
|
+
else:
|
57
|
+
value = 0
|
58
|
+
else:
|
59
|
+
value = Stream(field_stream).select('@value').render()
|
60
|
+
name = Stream(field_stream).select('@name').render()
|
61
|
+
for kind,data,pos in tag.input( value=value,
|
62
|
+
type="hidden", name=name).generate():
|
63
|
+
yield kind,data,pos
|
64
|
+
stream = stream | Transformer('//label[@for="field-%s"]' % field).replace(" ")
|
65
|
+
stream = stream | Transformer('//input[@id="field-%s"]' % field).filter(helper)
|
66
|
+
|
67
|
+
return remove_changelog(remove_header(stream , field), field)
|
68
|
+
|
69
|
+
def remove_field(stream , field):
|
70
|
+
""" Removes a field from the form area"""
|
71
|
+
stream = stream | Transformer('//label[@for="field-%s"]' % field).replace(" ")
|
72
|
+
stream = stream | Transformer('//input[@id="field-%s"]' % field).replace(" ")
|
73
|
+
return remove_changelog(remove_header(stream , field), field)
|
74
|
+
|
75
|
+
def istrue(v, otherwise=None):
|
76
|
+
if v.lower() in ('yes', 'true', '1', 'on'):
|
77
|
+
return True
|
78
|
+
else:
|
79
|
+
if otherwise is None:
|
80
|
+
return False
|
81
|
+
else:
|
82
|
+
return otherwise
|
83
|
+
|
84
|
+
csection = 'field settings'
|
85
|
+
|
86
|
+
class TicketTweaks(Component):
|
87
|
+
implements(ITemplateStreamFilter, ITemplateProvider)
|
88
|
+
## ITemplateStreamFilter
|
89
|
+
|
90
|
+
def filter_stream(self, req, method, filename, stream, data):
|
91
|
+
self.log.debug('IN BlackMagic')
|
92
|
+
if not filename == "ticket.html":
|
93
|
+
self.log.debug('Not a ticket returning')
|
94
|
+
return stream
|
95
|
+
fields = self.config.getlist(csection, 'fields', [])
|
96
|
+
self.log.debug('read enchants = %r' % fields)
|
97
|
+
for field in fields:
|
98
|
+
self.log.debug('starting : %s' % field)
|
99
|
+
disabled = False
|
100
|
+
hidden = False
|
101
|
+
hide_summary = False
|
102
|
+
remove = False
|
103
|
+
perms = self.config.getlist(csection, '%s.permission' % field, [])
|
104
|
+
self.log.debug('read permission config: %s has %s' % (field, perms))
|
105
|
+
for (perm, denial) in [s.split(":") for s in perms] :
|
106
|
+
perm = perm.upper()
|
107
|
+
self.log.debug('testing permission: %s:%s should act= %s' %
|
108
|
+
(field, perm, (not req.perm.has_permission(perm) or perm == "ALWAYS")))
|
109
|
+
if (not req.perm.has_permission(perm) or perm == "ALWAYS"):
|
110
|
+
if denial:
|
111
|
+
denial = denial.lower()
|
112
|
+
if denial == "disable":
|
113
|
+
disabled = True
|
114
|
+
elif denial == "hide":
|
115
|
+
hidden = True
|
116
|
+
elif denial == "remove":
|
117
|
+
remove = True
|
118
|
+
else:
|
119
|
+
disabled = True
|
120
|
+
else:
|
121
|
+
disabled = True
|
122
|
+
|
123
|
+
if disabled or istrue(self.config.get(csection, '%s.disable' % field, False)):
|
124
|
+
self.log.debug('disabling: %s' % field)
|
125
|
+
stream = disable_field(stream, field)
|
126
|
+
|
127
|
+
if self.config.get(csection, '%s.label' % field, None):
|
128
|
+
self.log.debug('labeling: %s' % field)
|
129
|
+
stream = stream | Transformer('//label[@for="field-%s"]' % field).replace(
|
130
|
+
self.config.get(csection, '%s.label' % field)
|
131
|
+
)
|
132
|
+
|
133
|
+
if self.config.get(csection, '%s.notice' % field, None):
|
134
|
+
self.log.debug('noticing: %s' % field)
|
135
|
+
stream = stream | Transformer('//*[@id="field-%s"]' % field).after(
|
136
|
+
tag.br() + tag.small()(
|
137
|
+
tag.em()(
|
138
|
+
Markup(self.config.get(csection, '%s.notice' % field))
|
139
|
+
)
|
140
|
+
)
|
141
|
+
)
|
142
|
+
|
143
|
+
tip = self.config.get(csection, '%s.tip' % field, None)
|
144
|
+
if tip:
|
145
|
+
self.log.debug('tipping: %s' % field)
|
146
|
+
stream = stream | Transformer('//div[@id="banner"]').before(
|
147
|
+
tag.script(type="text/javascript",
|
148
|
+
src=req.href.chrome("blackmagic", "js", "wz_tooltip.js"))()
|
149
|
+
)
|
150
|
+
|
151
|
+
stream = stream | Transformer('//*[@id="field-%s"]' % field).attr(
|
152
|
+
"onmouseover", "Tip('%s')" % tip.replace(r"'", r"\'")
|
153
|
+
)
|
154
|
+
|
155
|
+
if remove or istrue(self.config.get(csection, '%s.remove' % field, None)):
|
156
|
+
self.log.debug('removing: %s' % field)
|
157
|
+
stream = remove_field(stream, field)
|
158
|
+
|
159
|
+
if hidden or istrue(self.config.get(csection, '%s.hide' % field, None)):
|
160
|
+
self.log.debug('hiding: %s' % field)
|
161
|
+
stream = hide_field(stream, field)
|
162
|
+
|
163
|
+
return stream
|
164
|
+
|
165
|
+
## ITemplateProvider
|
166
|
+
|
167
|
+
def get_htdocs_dirs(self):
|
168
|
+
from pkg_resources import resource_filename
|
169
|
+
return [('blackmagic', resource_filename(__name__, 'htdocs'))]
|
170
|
+
|
171
|
+
def get_templates_dirs(self):
|
172
|
+
return []
|
@@ -0,0 +1,178 @@
|
|
1
|
+
|
2
|
+
def get_all(com, sql, *params):
|
3
|
+
"""Executes the query and returns the (description, data)"""
|
4
|
+
db = com.env.get_db_cnx()
|
5
|
+
cur = db.cursor()
|
6
|
+
desc = None
|
7
|
+
data = None
|
8
|
+
try:
|
9
|
+
cur.execute(sql, params)
|
10
|
+
data = list(cur.fetchall())
|
11
|
+
desc = cur.description
|
12
|
+
db.commit();
|
13
|
+
except Exception, e:
|
14
|
+
com.log.error('There was a problem executing sql:%s \n \
|
15
|
+
with parameters:%s\nException:%s'%(sql, params, e));
|
16
|
+
db.rollback();
|
17
|
+
try:
|
18
|
+
db.close()
|
19
|
+
except:
|
20
|
+
pass
|
21
|
+
|
22
|
+
return (desc, data)
|
23
|
+
|
24
|
+
def execute_non_query(com, sql, *params):
|
25
|
+
"""Executes the query on the given project"""
|
26
|
+
db = com.env.get_db_cnx()
|
27
|
+
cur = db.cursor()
|
28
|
+
try:
|
29
|
+
cur.execute(sql, params)
|
30
|
+
db.commit()
|
31
|
+
except Exception, e:
|
32
|
+
com.log.error('There was a problem executing sql:%s \n \
|
33
|
+
with parameters:%s\nException:%s'%(sql, params, e));
|
34
|
+
db.rollback();
|
35
|
+
try:
|
36
|
+
db.close()
|
37
|
+
except:
|
38
|
+
pass
|
39
|
+
|
40
|
+
def get_first_row(com, sql,*params):
|
41
|
+
""" Returns the first row of the query results as a tuple of values (or None)"""
|
42
|
+
db = com.env.get_db_cnx()
|
43
|
+
cur = db.cursor()
|
44
|
+
data = None;
|
45
|
+
try:
|
46
|
+
cur.execute(sql, params)
|
47
|
+
data = cur.fetchone();
|
48
|
+
db.commit();
|
49
|
+
except Exception, e:
|
50
|
+
com.log.error('There was a problem executing sql:%s \n \
|
51
|
+
with parameters:%s\nException:%s'%(sql, params, e));
|
52
|
+
db.rollback()
|
53
|
+
try:
|
54
|
+
db.close()
|
55
|
+
except:
|
56
|
+
pass
|
57
|
+
return data;
|
58
|
+
|
59
|
+
def get_scalar(com, sql, col=0, *params):
|
60
|
+
""" Gets a single value (in the specified column) from the result set of the query"""
|
61
|
+
data = get_first_row(com, sql, *params);
|
62
|
+
if data:
|
63
|
+
return data[col]
|
64
|
+
else:
|
65
|
+
return None;
|
66
|
+
|
67
|
+
def execute_in_trans(com, *args):
|
68
|
+
db = com.env.get_db_cnx()
|
69
|
+
cur = db.cursor()
|
70
|
+
result = True
|
71
|
+
try:
|
72
|
+
for sql, params in args:
|
73
|
+
cur.execute(sql, params)
|
74
|
+
db.commit()
|
75
|
+
except Exception, e:
|
76
|
+
com.log.error('There was a problem executing sql:%s \n \
|
77
|
+
with parameters:%s\nException:%s'%(sql, params, e));
|
78
|
+
db.rollback();
|
79
|
+
result = e
|
80
|
+
try:
|
81
|
+
db.close()
|
82
|
+
except:
|
83
|
+
pass
|
84
|
+
return result
|
85
|
+
|
86
|
+
def db_table_exists(com, table):
|
87
|
+
db = com.env.get_db_cnx()
|
88
|
+
sql = "SELECT * FROM %s LIMIT 1" % table;
|
89
|
+
cur = db.cursor()
|
90
|
+
has_table = True;
|
91
|
+
try:
|
92
|
+
cur.execute(sql)
|
93
|
+
db.commit()
|
94
|
+
except Exception, e:
|
95
|
+
has_table = False
|
96
|
+
db.rollback()
|
97
|
+
|
98
|
+
try:
|
99
|
+
db.close()
|
100
|
+
except:
|
101
|
+
pass
|
102
|
+
return has_table
|
103
|
+
|
104
|
+
def get_column_as_list(com, sql, col=0, *params):
|
105
|
+
data = get_all(com, sql, *params)[1] or ()
|
106
|
+
return [valueList[col] for valueList in data]
|
107
|
+
|
108
|
+
def get_system_value(com, key):
|
109
|
+
return get_scalar(com, "SELECT value FROM system WHERE name=%s", 0, key)
|
110
|
+
|
111
|
+
def set_system_value(com, key, value):
|
112
|
+
if get_system_value(com, key):
|
113
|
+
execute_non_query(com, "UPDATE system SET value=%s WHERE name=%s", value, key)
|
114
|
+
else:
|
115
|
+
execute_non_query(com, "INSERT INTO system (value, name) VALUES (%s, %s)",
|
116
|
+
value, key)
|
117
|
+
|
118
|
+
|
119
|
+
def get_result_set(com, sql, *params):
|
120
|
+
"""Executes the query and returns a Result Set"""
|
121
|
+
tpl = get_all(com, sql, *params);
|
122
|
+
if tpl and tpl[0] and tpl[1]:
|
123
|
+
return ResultSet(tpl)
|
124
|
+
else:
|
125
|
+
return None
|
126
|
+
|
127
|
+
|
128
|
+
class ResultSet:
|
129
|
+
""" the result of calling getResultSet """
|
130
|
+
def __init__ (self, (columnDescription, rows)):
|
131
|
+
self.columnDescription, self.rows = columnDescription, rows
|
132
|
+
self.columnMap = self.get_column_map()
|
133
|
+
|
134
|
+
def get_column_map ( self ):
|
135
|
+
"""This function will take the result set from getAll and will
|
136
|
+
return a hash of the column names to their index """
|
137
|
+
h = {}
|
138
|
+
i = 0
|
139
|
+
if self.columnDescription:
|
140
|
+
for col in self.columnDescription:
|
141
|
+
h[ col[0] ] = i
|
142
|
+
i+=1
|
143
|
+
return h;
|
144
|
+
|
145
|
+
def value(self, col, row ):
|
146
|
+
""" given a row(list or idx) and a column( name or idx ), retrieve the appropriate value"""
|
147
|
+
tcol = type(col)
|
148
|
+
trow = type(row)
|
149
|
+
if tcol == str:
|
150
|
+
if(trow == list or trow == tuple):
|
151
|
+
return row[self.columnMap[col]]
|
152
|
+
elif(trow == int):
|
153
|
+
return self.rows[row][self.columnMap[col]]
|
154
|
+
else:
|
155
|
+
print ("rs.value Type Failed col:%s row:%s" % (type(col), type(row)))
|
156
|
+
elif tcol == int:
|
157
|
+
if(trow == list or trow == tuple):
|
158
|
+
return row[col]
|
159
|
+
elif(trow == int):
|
160
|
+
return self.rows[row][col]
|
161
|
+
else:
|
162
|
+
print ("rs.value Type Failed col:%s row:%s" % (type(col), type(row)))
|
163
|
+
else:
|
164
|
+
print ("rs.value Type Failed col:%s row:%s" % (type(col), type(row)))
|
165
|
+
|
166
|
+
def json_out(self):
|
167
|
+
json = "[%s]" % ',\r\n'. join(
|
168
|
+
[("{%s}" % ','.join(
|
169
|
+
["'%s':'%s'" %
|
170
|
+
(key, str(self.value(val, row)).
|
171
|
+
replace("'","\\'").
|
172
|
+
replace('"','\\"').
|
173
|
+
replace('\r','\\r').
|
174
|
+
replace('\n','\\n'))
|
175
|
+
for (key, val) in self.columnMap.items()]))
|
176
|
+
for row in self.rows])
|
177
|
+
#mylog.debug('serializing to json : %s'% json)
|
178
|
+
return json
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#messages{
|
2
|
+
}
|
3
|
+
.message{
|
4
|
+
font-weight:bold;
|
5
|
+
color:#283;
|
6
|
+
}
|
7
|
+
.minorsection{
|
8
|
+
padding:5px;
|
9
|
+
border:1px solid #eee;
|
10
|
+
}
|
11
|
+
.minorsectionleft{
|
12
|
+
padding:5px;
|
13
|
+
border-width:1px 0px 1px 1px;
|
14
|
+
border-style: solid;
|
15
|
+
border-color: #eee;
|
16
|
+
}
|
17
|
+
.minorsectionright{
|
18
|
+
padding:5px;
|
19
|
+
border-width:1px 1px 1px 0px;
|
20
|
+
border-style: solid;
|
21
|
+
border-color: #eee;
|
22
|
+
}
|
23
|
+
label,.label{
|
24
|
+
font-weight:bold;
|
25
|
+
}
|
@@ -0,0 +1,356 @@
|
|
1
|
+
// formatDate :
|
2
|
+
// a PHP date like function, for formatting date strings
|
3
|
+
// authored by Svend Tofte <www.svendtofte.com>
|
4
|
+
// the code is in the public domain
|
5
|
+
//
|
6
|
+
// see http://www.svendtofte.com/code/date_format/
|
7
|
+
// and http://www.php.net/date
|
8
|
+
//
|
9
|
+
// thanks to
|
10
|
+
// - Daniel Berlin <mail@daniel-berlin.de>,
|
11
|
+
// major overhaul and improvements
|
12
|
+
// - Matt Bannon,
|
13
|
+
// correcting some stupid bugs in my days-in-the-months list!
|
14
|
+
//
|
15
|
+
// input : format string
|
16
|
+
// time : epoch time (seconds, and optional)
|
17
|
+
//
|
18
|
+
// if time is not passed, formatting is based on
|
19
|
+
// the current "this" date object's set time.
|
20
|
+
//
|
21
|
+
// supported switches are
|
22
|
+
// a, A, B, c, d, D, F, g, G, h, H, i, I (uppercase i), j, l (lowecase L),
|
23
|
+
// L, m, M, n, N, O, P, r, s, S, t, U, w, W, y, Y, z, Z
|
24
|
+
//
|
25
|
+
// unsupported (as compared to date in PHP 5.1.3)
|
26
|
+
// T, e, o
|
27
|
+
|
28
|
+
Date.prototype.formatDate = function (input,time) {
|
29
|
+
|
30
|
+
var daysLong = ["Sunday", "Monday", "Tuesday", "Wednesday",
|
31
|
+
"Thursday", "Friday", "Saturday"];
|
32
|
+
var daysShort = ["Sun", "Mon", "Tue", "Wed",
|
33
|
+
"Thu", "Fri", "Sat"];
|
34
|
+
var monthsShort = ["Jan", "Feb", "Mar", "Apr",
|
35
|
+
"May", "Jun", "Jul", "Aug", "Sep",
|
36
|
+
"Oct", "Nov", "Dec"];
|
37
|
+
var monthsLong = ["January", "February", "March", "April",
|
38
|
+
"May", "June", "July", "August", "September",
|
39
|
+
"October", "November", "December"];
|
40
|
+
|
41
|
+
var switches = { // switches object
|
42
|
+
|
43
|
+
a : function () {
|
44
|
+
// Lowercase Ante meridiem and Post meridiem
|
45
|
+
return date.getHours() > 11? "pm" : "am";
|
46
|
+
},
|
47
|
+
|
48
|
+
A : function () {
|
49
|
+
// Uppercase Ante meridiem and Post meridiem
|
50
|
+
return (this.a().toUpperCase ());
|
51
|
+
},
|
52
|
+
|
53
|
+
B : function (){
|
54
|
+
// Swatch internet time. code simply grabbed from ppk,
|
55
|
+
// since I was feeling lazy:
|
56
|
+
// http://www.xs4all.nl/~ppk/js/beat.html
|
57
|
+
var off = (date.getTimezoneOffset() + 60)*60;
|
58
|
+
var theSeconds = (date.getHours() * 3600) +
|
59
|
+
(date.getMinutes() * 60) +
|
60
|
+
date.getSeconds() + off;
|
61
|
+
var beat = Math.floor(theSeconds/86.4);
|
62
|
+
if (beat > 1000) beat -= 1000;
|
63
|
+
if (beat < 0) beat += 1000;
|
64
|
+
if ((String(beat)).length == 1) beat = "00"+beat;
|
65
|
+
if ((String(beat)).length == 2) beat = "0"+beat;
|
66
|
+
return beat;
|
67
|
+
},
|
68
|
+
|
69
|
+
c : function () {
|
70
|
+
// ISO 8601 date (e.g.: "2004-02-12T15:19:21+00:00"), as per
|
71
|
+
// http://www.cl.cam.ac.uk/~mgk25/iso-time.html
|
72
|
+
return (this.Y() + "-" + this.m() + "-" + this.d() + "T" +
|
73
|
+
this.h() + ":" + this.i() + ":" + this.s() + this.P());
|
74
|
+
},
|
75
|
+
|
76
|
+
d : function () {
|
77
|
+
// Day of the month, 2 digits with leading zeros
|
78
|
+
var j = String(this.j());
|
79
|
+
return (j.length == 1 ? "0"+j : j);
|
80
|
+
},
|
81
|
+
|
82
|
+
D : function () {
|
83
|
+
// A textual representation of a day, three letters
|
84
|
+
return daysShort[date.getDay()];
|
85
|
+
},
|
86
|
+
|
87
|
+
F : function () {
|
88
|
+
// A full textual representation of a month
|
89
|
+
return monthsLong[date.getMonth()];
|
90
|
+
},
|
91
|
+
|
92
|
+
g : function () {
|
93
|
+
// 12-hour format of an hour without leading zeros
|
94
|
+
return date.getHours() > 12? date.getHours()-12 : date.getHours();
|
95
|
+
},
|
96
|
+
|
97
|
+
G : function () {
|
98
|
+
// 24-hour format of an hour without leading zeros
|
99
|
+
return date.getHours();
|
100
|
+
},
|
101
|
+
|
102
|
+
h : function () {
|
103
|
+
// 12-hour format of an hour with leading zeros
|
104
|
+
var g = String(this.g());
|
105
|
+
return (g.length == 1 ? "0"+g : g);
|
106
|
+
},
|
107
|
+
|
108
|
+
H : function () {
|
109
|
+
// 24-hour format of an hour with leading zeros
|
110
|
+
var G = String(this.G());
|
111
|
+
return (G.length == 1 ? "0"+G : G);
|
112
|
+
},
|
113
|
+
|
114
|
+
i : function () {
|
115
|
+
// Minutes with leading zeros
|
116
|
+
var min = String (date.getMinutes ());
|
117
|
+
return (min.length == 1 ? "0" + min : min);
|
118
|
+
},
|
119
|
+
|
120
|
+
I : function () {
|
121
|
+
// Whether or not the date is in daylight saving time (DST)
|
122
|
+
// note that this has no bearing in actual DST mechanics,
|
123
|
+
// and is just a pure guess. buyer beware.
|
124
|
+
var noDST = new Date ("January 1 " + this.Y() + " 00:00:00");
|
125
|
+
return (noDST.getTimezoneOffset () ==
|
126
|
+
date.getTimezoneOffset () ? 0 : 1);
|
127
|
+
},
|
128
|
+
|
129
|
+
j : function () {
|
130
|
+
// Day of the month without leading zeros
|
131
|
+
return date.getDate();
|
132
|
+
},
|
133
|
+
|
134
|
+
l : function () {
|
135
|
+
// A full textual representation of the day of the week
|
136
|
+
return daysLong[date.getDay()];
|
137
|
+
},
|
138
|
+
|
139
|
+
L : function () {
|
140
|
+
// leap year or not. 1 if leap year, 0 if not.
|
141
|
+
// the logic should match iso's 8601 standard.
|
142
|
+
// http://www.uic.edu/depts/accc/software/isodates/leapyear.html
|
143
|
+
var Y = this.Y();
|
144
|
+
if (
|
145
|
+
(Y % 4 == 0 && Y % 100 != 0) ||
|
146
|
+
(Y % 4 == 0 && Y % 100 == 0 && Y % 400 == 0)
|
147
|
+
) {
|
148
|
+
return 1;
|
149
|
+
} else {
|
150
|
+
return 0;
|
151
|
+
}
|
152
|
+
},
|
153
|
+
|
154
|
+
m : function () {
|
155
|
+
// Numeric representation of a month, with leading zeros
|
156
|
+
var n = String(this.n());
|
157
|
+
return (n.length == 1 ? "0"+n : n);
|
158
|
+
},
|
159
|
+
|
160
|
+
M : function () {
|
161
|
+
// A short textual representation of a month, three letters
|
162
|
+
return monthsShort[date.getMonth()];
|
163
|
+
},
|
164
|
+
|
165
|
+
n : function () {
|
166
|
+
// Numeric representation of a month, without leading zeros
|
167
|
+
return date.getMonth()+1;
|
168
|
+
},
|
169
|
+
|
170
|
+
N : function () {
|
171
|
+
// ISO-8601 numeric representation of the day of the week
|
172
|
+
var w = this.w();
|
173
|
+
return (w == 0 ? 7 : w);
|
174
|
+
},
|
175
|
+
|
176
|
+
O : function () {
|
177
|
+
// Difference to Greenwich time (GMT) in hours
|
178
|
+
var os = Math.abs(date.getTimezoneOffset());
|
179
|
+
var h = String(Math.floor(os/60));
|
180
|
+
var m = String(os%60);
|
181
|
+
h.length == 1? h = "0"+h:1;
|
182
|
+
m.length == 1? m = "0"+m:1;
|
183
|
+
return date.getTimezoneOffset() < 0 ? "+"+h+m : "-"+h+m;
|
184
|
+
},
|
185
|
+
|
186
|
+
P : function () {
|
187
|
+
// Difference to GMT, with colon between hours and minutes
|
188
|
+
var O = this.O();
|
189
|
+
return (O.substr(0, 3) + ":" + O.substr(3, 2));
|
190
|
+
},
|
191
|
+
|
192
|
+
r : function () {
|
193
|
+
// RFC 822 formatted date
|
194
|
+
var r; // result
|
195
|
+
// Thu , 21 Dec 2000
|
196
|
+
r = this.D() + ", " + this.d() + " " + this.M() + " " + this.Y() +
|
197
|
+
// 16 : 01 : 07 0200
|
198
|
+
" " + this.H() + ":" + this.i() + ":" + this.s() + " " + this.O();
|
199
|
+
return r;
|
200
|
+
},
|
201
|
+
|
202
|
+
s : function () {
|
203
|
+
// Seconds, with leading zeros
|
204
|
+
var sec = String (date.getSeconds ());
|
205
|
+
return (sec.length == 1 ? "0" + sec : sec);
|
206
|
+
},
|
207
|
+
|
208
|
+
S : function () {
|
209
|
+
// English ordinal suffix for the day of the month, 2 characters
|
210
|
+
switch (date.getDate ()) {
|
211
|
+
case 1: return ("st");
|
212
|
+
case 2: return ("nd");
|
213
|
+
case 3: return ("rd");
|
214
|
+
case 21: return ("st");
|
215
|
+
case 22: return ("nd");
|
216
|
+
case 23: return ("rd");
|
217
|
+
case 31: return ("st");
|
218
|
+
default: return ("th");
|
219
|
+
}
|
220
|
+
},
|
221
|
+
|
222
|
+
t : function () {
|
223
|
+
// thanks to Matt Bannon for some much needed code-fixes here!
|
224
|
+
var daysinmonths = [null,31,28,31,30,31,30,31,31,30,31,30,31];
|
225
|
+
if (this.L()==1 && this.n()==2) return 29; // ~leap day
|
226
|
+
return daysinmonths[this.n()];
|
227
|
+
},
|
228
|
+
|
229
|
+
U : function () {
|
230
|
+
// Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)
|
231
|
+
return Math.round(date.getTime()/1000);
|
232
|
+
},
|
233
|
+
|
234
|
+
w : function () {
|
235
|
+
// Numeric representation of the day of the week
|
236
|
+
return date.getDay();
|
237
|
+
},
|
238
|
+
|
239
|
+
W : function () {
|
240
|
+
// Weeknumber, as per ISO specification:
|
241
|
+
// http://www.cl.cam.ac.uk/~mgk25/iso-time.html
|
242
|
+
|
243
|
+
var DoW = this.N ();
|
244
|
+
var DoY = this.z ();
|
245
|
+
|
246
|
+
// If the day is 3 days before New Year's Eve and is Thursday or earlier,
|
247
|
+
// it's week 1 of next year.
|
248
|
+
var daysToNY = 364 + this.L () - DoY;
|
249
|
+
if (daysToNY <= 2 && DoW <= (3 - daysToNY)) {
|
250
|
+
return 1;
|
251
|
+
}
|
252
|
+
|
253
|
+
// If the day is within 3 days after New Year's Eve and is Friday or later,
|
254
|
+
// it belongs to the old year.
|
255
|
+
if (DoY <= 2 && DoW >= 5) {
|
256
|
+
return new Date (this.Y () - 1, 11, 31).formatDate ("W");
|
257
|
+
}
|
258
|
+
|
259
|
+
var nyDoW = new Date (this.Y (), 0, 1).getDay ();
|
260
|
+
nyDoW = nyDoW != 0 ? nyDoW - 1 : 6;
|
261
|
+
|
262
|
+
if (nyDoW <= 3) { // First day of the year is a Thursday or earlier
|
263
|
+
return (1 + Math.floor ((DoY + nyDoW) / 7));
|
264
|
+
} else { // First day of the year is a Friday or later
|
265
|
+
return (1 + Math.floor ((DoY - (7 - nyDoW)) / 7));
|
266
|
+
}
|
267
|
+
},
|
268
|
+
|
269
|
+
y : function () {
|
270
|
+
// A two-digit representation of a year
|
271
|
+
var y = String(this.Y());
|
272
|
+
return y.substring(y.length-2,y.length);
|
273
|
+
},
|
274
|
+
|
275
|
+
Y : function () {
|
276
|
+
// A full numeric representation of a year, 4 digits
|
277
|
+
|
278
|
+
// we first check, if getFullYear is supported. if it
|
279
|
+
// is, we just use that. ppks code is nice, but wont
|
280
|
+
// work with dates outside 1900-2038, or something like that
|
281
|
+
if (date.getFullYear) {
|
282
|
+
var newDate = new Date("January 1 2001 00:00:00 +0000");
|
283
|
+
var x = newDate .getFullYear();
|
284
|
+
if (x == 2001) {
|
285
|
+
// i trust the method now
|
286
|
+
return date.getFullYear();
|
287
|
+
}
|
288
|
+
}
|
289
|
+
// else, do this:
|
290
|
+
// codes thanks to ppk:
|
291
|
+
// http://www.xs4all.nl/~ppk/js/introdate.html
|
292
|
+
var x = date.getYear();
|
293
|
+
var y = x % 100;
|
294
|
+
y += (y < 38) ? 2000 : 1900;
|
295
|
+
return y;
|
296
|
+
},
|
297
|
+
|
298
|
+
|
299
|
+
z : function () {
|
300
|
+
// The day of the year, zero indexed! 0 through 366
|
301
|
+
var t = new Date("January 1 " + this.Y() + " 00:00:00");
|
302
|
+
var diff = date.getTime() - t.getTime();
|
303
|
+
return Math.floor(diff/1000/60/60/24);
|
304
|
+
},
|
305
|
+
|
306
|
+
Z : function () {
|
307
|
+
// Timezone offset in seconds
|
308
|
+
return (date.getTimezoneOffset () * -60);
|
309
|
+
}
|
310
|
+
|
311
|
+
}
|
312
|
+
|
313
|
+
function getSwitch(str) {
|
314
|
+
if (switches[str] != undefined) {
|
315
|
+
return switches[str]();
|
316
|
+
} else {
|
317
|
+
return str;
|
318
|
+
}
|
319
|
+
}
|
320
|
+
|
321
|
+
var date;
|
322
|
+
if (time) {
|
323
|
+
var date = new Date (time);
|
324
|
+
} else {
|
325
|
+
var date = this;
|
326
|
+
}
|
327
|
+
|
328
|
+
var formatString = input.split("");
|
329
|
+
var i = 0;
|
330
|
+
while (i < formatString.length) {
|
331
|
+
if (formatString[i] == "\\") {
|
332
|
+
// this is our way of allowing users to escape stuff
|
333
|
+
formatString.splice(i,1);
|
334
|
+
} else {
|
335
|
+
formatString[i] = getSwitch(formatString[i]);
|
336
|
+
}
|
337
|
+
i++;
|
338
|
+
}
|
339
|
+
|
340
|
+
return formatString.join("");
|
341
|
+
}
|
342
|
+
|
343
|
+
|
344
|
+
// Some (not all) predefined format strings from PHP 5.1.1, which
|
345
|
+
// offer standard date representations.
|
346
|
+
// See: http://www.php.net/manual/en/ref.datetime.php#datetime.constants
|
347
|
+
//
|
348
|
+
|
349
|
+
// Atom "2005-08-15T15:52:01+00:00"
|
350
|
+
Date.DATE_ATOM = "Y-m-d\\TH:i:sP";
|
351
|
+
// ISO-8601 "2005-08-15T15:52:01+0000"
|
352
|
+
Date.DATE_ISO8601 = "Y-m-d\\TH:i:sO";
|
353
|
+
// RFC 2822 "Mon, 15 Aug 2005 15:52:01 +0000"
|
354
|
+
Date.DATE_RFC2822 = "D, d M Y H:i:s O";
|
355
|
+
// W3C "2005-08-15T15:52:01+00:00"
|
356
|
+
Date.DATE_W3C = "Y-m-d\\TH:i:sP";
|