keithsalisbury-subtrac 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +7 -0
  3. data/Rakefile +56 -0
  4. data/VERSION.yml +4 -0
  5. data/bin/subtrac +40 -0
  6. data/lib/subtrac.rb +245 -0
  7. data/lib/subtrac/common/clients/index.wsgi +89 -0
  8. data/lib/subtrac/common/favicon.ico +0 -0
  9. data/lib/subtrac/common/images/trac/banner_bg.jpg +0 -0
  10. data/lib/subtrac/common/images/trac/bar_bg.gif +0 -0
  11. data/lib/subtrac/common/images/trac/footer_back.png +0 -0
  12. data/lib/subtrac/common/images/trac/main_bg.gif +0 -0
  13. data/lib/subtrac/common/images/trac/saint_logo_small.png +0 -0
  14. data/lib/subtrac/common/static/404.html +14 -0
  15. data/lib/subtrac/common/styles/trac.css +222 -0
  16. data/lib/subtrac/common/trac.ini +178 -0
  17. data/lib/subtrac/config/config.yml +54 -0
  18. data/lib/subtrac/passwords +1 -0
  19. data/lib/subtrac/shared/trac.ini +178 -0
  20. data/lib/subtrac/templates/location.erb +16 -0
  21. data/lib/subtrac/templates/projects/blank/svn/branches/README +0 -0
  22. data/lib/subtrac/templates/projects/blank/svn/tags/README +0 -0
  23. data/lib/subtrac/templates/projects/blank/svn/trunk/README +0 -0
  24. data/lib/subtrac/templates/projects/blank/trac/wiki/WikiStart +57 -0
  25. data/lib/subtrac/templates/projects/new/svn/trunk/trac/wiki/WikiStart +46 -0
  26. data/lib/subtrac/templates/projects/new/trac/wiki/WikiStart +23 -0
  27. data/lib/subtrac/templates/projects/trac_theme/svn/trunk/index/index.html +22 -0
  28. data/lib/subtrac/templates/projects/trac_theme/svn/trunk/templates/layout.html +56 -0
  29. data/lib/subtrac/templates/projects/trac_theme/svn/trunk/templates/site.html +27 -0
  30. data/lib/subtrac/templates/projects/trac_theme/svn/trunk/templates/theme.html +86 -0
  31. data/lib/subtrac/templates/projects/trac_theme/trac/wiki/WikiStart +4 -0
  32. data/lib/subtrac/templates/trac.erb +25 -0
  33. data/lib/subtrac/templates/vhost.erb +35 -0
  34. data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/advancedworkflow/__init__.py +0 -0
  35. data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/advancedworkflow/controller.py +419 -0
  36. data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/setup.cfg +3 -0
  37. data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/setup.py +20 -0
  38. data/lib/subtrac/trac-plugins/clientsplugin/clients/__init__.py +0 -0
  39. data/lib/subtrac/trac-plugins/clientsplugin/clients/action.py +28 -0
  40. data/lib/subtrac/trac-plugins/clientsplugin/clients/action_email.py +168 -0
  41. data/lib/subtrac/trac-plugins/clientsplugin/clients/action_zendesk_forum.py +137 -0
  42. data/lib/subtrac/trac-plugins/clientsplugin/clients/admin.py +91 -0
  43. data/lib/subtrac/trac-plugins/clientsplugin/clients/api.py +199 -0
  44. data/lib/subtrac/trac-plugins/clientsplugin/clients/client.py +105 -0
  45. data/lib/subtrac/trac-plugins/clientsplugin/clients/events.py +287 -0
  46. data/lib/subtrac/trac-plugins/clientsplugin/clients/eventsadmin.py +71 -0
  47. data/lib/subtrac/trac-plugins/clientsplugin/clients/htdocs/clients.css +4 -0
  48. data/lib/subtrac/trac-plugins/clientsplugin/clients/model.py +135 -0
  49. data/lib/subtrac/trac-plugins/clientsplugin/clients/processor.py +70 -0
  50. data/lib/subtrac/trac-plugins/clientsplugin/clients/reportmanager.py +142 -0
  51. data/lib/subtrac/trac-plugins/clientsplugin/clients/reports.py +231 -0
  52. data/lib/subtrac/trac-plugins/clientsplugin/clients/summary.py +27 -0
  53. data/lib/subtrac/trac-plugins/clientsplugin/clients/summary_milestone.py +152 -0
  54. data/lib/subtrac/trac-plugins/clientsplugin/clients/summary_ticketchanges.py +160 -0
  55. data/lib/subtrac/trac-plugins/clientsplugin/clients/templates/admin_client_events.html +124 -0
  56. data/lib/subtrac/trac-plugins/clientsplugin/clients/templates/admin_clients.html +134 -0
  57. data/lib/subtrac/trac-plugins/clientsplugin/cron/changes.xslt +132 -0
  58. data/lib/subtrac/trac-plugins/clientsplugin/cron/run-client-event +97 -0
  59. data/lib/subtrac/trac-plugins/clientsplugin/cron/summary.xslt +161 -0
  60. data/lib/subtrac/trac-plugins/clientsplugin/setup.py +43 -0
  61. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/__init__.py +4 -0
  62. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/burndownchart.py +273 -0
  63. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/hoursinplaceeditor.py +44 -0
  64. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/hoursremaining.py +36 -0
  65. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery-1.2.3.min.js +32 -0
  66. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery.jeditable.js +409 -0
  67. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery.jeditable.mini.js +30 -0
  68. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/templates/edithours.html +53 -0
  69. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/burndownchart.py +181 -0
  70. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/hoursremaining.py +66 -0
  71. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/workloadchart.py +47 -0
  72. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/utils.py +93 -0
  73. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/workloadchart.py +86 -0
  74. data/lib/subtrac/trac-plugins/estimationtoolsplugin/setup.py +20 -0
  75. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/SumRollups.js +23 -0
  76. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/adw_tracdb.py +128 -0
  77. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/git-post-receive +40 -0
  78. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/trac-post-commit.py +285 -0
  79. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/trac_billing.py +173 -0
  80. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/utils/__init__.py +0 -0
  81. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/utils/mail.py +164 -0
  82. data/lib/subtrac/trac-plugins/timingandestimationplugin/setup.py +69 -0
  83. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/__init__.py +1 -0
  84. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/api.py +292 -0
  85. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/blackmagic.py +172 -0
  86. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/dbhelper.py +178 -0
  87. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/billingplugin.css +25 -0
  88. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/field_disabler.js +6 -0
  89. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/formatDate.js +356 -0
  90. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/tip_centerwindow.js +100 -0
  91. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/tip_followscroll.js +84 -0
  92. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/wz_tooltip.js +1149 -0
  93. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/linkifyer.js +119 -0
  94. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/query.js +73 -0
  95. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/ticket.js +165 -0
  96. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/query_webui.py +28 -0
  97. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reportmanager.py +221 -0
  98. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reports.py +675 -0
  99. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reports_filter.py +150 -0
  100. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/statuses.py +25 -0
  101. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/tande_filters.py +131 -0
  102. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/templates/billing.cs +84 -0
  103. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/templates/billing.html +104 -0
  104. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_daemon.py +194 -0
  105. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_policy.py +62 -0
  106. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_webui.py +28 -0
  107. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/usermanual.py +127 -0
  108. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/webui.py +129 -0
  109. data/lib/subtrac/trac-plugins/worklogplugin/setup.py +29 -0
  110. data/lib/subtrac/trac-plugins/worklogplugin/worklog/__init__.py +1 -0
  111. data/lib/subtrac/trac-plugins/worklogplugin/worklog/api.py +187 -0
  112. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jqModal.css +40 -0
  113. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jqModal.js +67 -0
  114. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jquery.mousewheel.pack.js +12 -0
  115. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jquery.timeentry.pack.js +7 -0
  116. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/tracWorklog.js +40 -0
  117. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/ui.datepicker.css +208 -0
  118. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/ui.datepicker.js +1439 -0
  119. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/work.png +0 -0
  120. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/work.xcf +0 -0
  121. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/worklogplugin.css +80 -0
  122. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/workstart.png +0 -0
  123. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/workstop.png +0 -0
  124. data/lib/subtrac/trac-plugins/worklogplugin/worklog/manager.py +336 -0
  125. data/lib/subtrac/trac-plugins/worklogplugin/worklog/reports.py +598 -0
  126. data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog.html +45 -0
  127. data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_stop.html +70 -0
  128. data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_user.html +40 -0
  129. data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_webadminui.html +59 -0
  130. data/lib/subtrac/trac-plugins/worklogplugin/worklog/ticket_daemon.py +33 -0
  131. data/lib/subtrac/trac-plugins/worklogplugin/worklog/ticket_filter.py +153 -0
  132. data/lib/subtrac/trac-plugins/worklogplugin/worklog/timeline_hook.py +96 -0
  133. data/lib/subtrac/trac-plugins/worklogplugin/worklog/usermanual.py +29 -0
  134. data/lib/subtrac/trac-plugins/worklogplugin/worklog/util.py +31 -0
  135. data/lib/subtrac/trac-plugins/worklogplugin/worklog/webadminui.py +47 -0
  136. data/lib/subtrac/trac-plugins/worklogplugin/worklog/webui.py +174 -0
  137. data/lib/subtrac/trac-plugins/worklogplugin/worklog/xmlrpc.py +73 -0
  138. data/lib/subtrac/version.rb +4 -0
  139. metadata +191 -0
@@ -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,6 @@
1
+ (function(){
2
+ var x = document.getElementById('totalhours');
3
+ if(x){
4
+ x.disabled=true;
5
+ }
6
+ })()
@@ -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";