source: timingandestimationplugin/branches/trac1.0-Permissions/timingandestimationplugin/webui.py

Last change on this file was 14061, checked in by Russ Tyndall, 9 years ago

branched for trac1.0

File size: 6.3 KB
Line 
1from pkg_resources import resource_filename
2import re
3import time
4import datetime
5import dbhelper
6from usermanual import *
7from trac.core import *
8from trac.web import IRequestHandler
9from trac.perm import IPermissionRequestor
10from trac.util import Markup
11from trac.web.chrome import add_stylesheet, add_script, \
12     INavigationContributor, ITemplateProvider
13from trac.web.href import Href
14from reportmanager import CustomReportManager
15from statuses import get_statuses
16import datetime
17import trac.util.datefmt
18import reports
19
20def strptime(date_string, format):
21    return datetime.datetime(*(time.strptime(date_string, format)[0:6]))
22
23#get_statuses = api.get_statuses
24validTimeFormats=[
25    '%Y-%m-%d %H:%M:%S.%f', '%Y-%m-%d %I:%M:%S.%f %p',
26    '%Y-%m-%d %H:%M:%S', '%Y-%m-%d %I:%M:%S %p',
27    '%Y-%m-%d %H:%M', '%Y-%m-%d %I:%M %p',
28    '%Y-%m-%d %H', '%Y-%m-%d %I %p',
29    '%Y-%m-%d',
30   
31    '%Y/%m/%d %H:%M:%S.%f', '%Y/%m/%d %I:%M:%S.%f %p',
32    '%Y/%m/%d %H:%M:%S', '%Y/%m/%d %I:%M:%S %p',
33    '%Y/%m/%d %H:%M', '%Y/%m/%d %I:%M %p',
34    '%Y/%m/%d %H', '%Y/%m/%d %H %p',
35    '%Y/%m/%d',
36   
37    '%Y.%m.%d %H:%M:%S.%f', '%Y.%m.%d %I:%M:%S.%f %p',
38    '%Y.%m.%d %H:%M:%S', '%Y.%m.%d %I:%M:%S %p',
39    '%Y.%m.%d %H:%M', '%Y.%m.%d %I:%M %p',
40    '%Y.%m.%d %H', '%Y.%m.%d %I %p',
41    '%Y.%m.%d',
42    ]
43def parsetime(val, tzinfo=trac.util.datefmt.to_datetime(None).tzinfo):
44    if not val: return None
45    val = val.strip()
46    if not val: return None
47    it = None
48    for f in validTimeFormats:
49        #print f, datetime.datetime.strptime(val, f)
50        try: return strptime(val, f).replace(tzinfo=tzinfo)
51        except ValueError: pass
52    raise TracError('Unable to convert bill date %s to a time, please provide a date in yyyy-mm-dd hh:mm:ss format' % val)
53
54
55class TimingEstimationAndBillingPage(Component):
56    implements(IPermissionRequestor, INavigationContributor, IRequestHandler, ITemplateProvider)
57
58    def __init__(self):
59        pass
60
61    # IPermissionRequestor methods
62    def get_permission_actions(self): 
63        return ["TIME_VIEW", "TIME_RECORD", ("TIME_ADMIN", ["TIME_RECORD", "TIME_VIEW"])] 
64
65    def set_bill_date(self, username="Timing and Estimation Plugin",  when=None):
66        now = trac.util.datefmt.to_datetime(None)#get now
67        if isinstance(when, str) or isinstance(when, unicode):
68            when = parsetime(when, now.tzinfo)
69        if not when: when = now
70
71        strwhen = "%#04d-%#02d-%#02d %#02d:%#02d:%#02d" % \
72                (when.year, when.month, when.day, when.hour,when.minute, when.second)
73
74        sql = """
75        INSERT INTO bill_date (time, set_when, str_value)
76        VALUES (%s, %s, %s)
77        """
78        dbhelper.execute_non_query(self.env, sql, trac.util.datefmt.to_timestamp(when),
79                                   trac.util.datefmt.to_timestamp(now), strwhen)
80
81
82    # INavigationContributor methods
83    def get_active_navigation_item(self, req):
84        val = re.search('/billing$', req.path_info)
85        if val and val.start() == 0:
86            return "billing"
87        else:
88            return ""
89
90    def get_navigation_items(self, req):
91        url = req.href.billing()
92        if req.perm.has_permission("TIME_VIEW"):
93            yield 'mainnav', "billing", \
94                Markup('<a href="%s">%s</a>' % \
95                           (url , "Time Reports"))
96
97    # IRequestHandler methods
98    def set_request_billing_dates(self, data):
99        billing_dates = []
100        billing_time_sql = """
101        SELECT DISTINCT time as value, str_value as text
102        FROM bill_date
103        ORDER BY time DESC
104        """
105        rs = dbhelper.get_result_set(self.env, billing_time_sql)
106        if rs:
107            for (value, text) in rs.rows:
108                billing_info = {'text':text , 'value':value*1000*1000}
109                billing_dates.extend([billing_info]) 
110        #self.log.debug("bill-dates: %s"%billing_dates)
111        data['billing_info']["billdates"] = billing_dates
112
113    def match_request(self, req):
114        val = re.search('/billing$', req.path_info)
115        return val and val.start() == 0
116
117    def process_request(self, req):
118        messages = []
119        req.perm.require("TIME_VIEW")
120        def addMessage(s):
121            messages.extend([s]);
122
123        if req.method == 'POST':
124            req.perm.require("TIME_ADMIN")
125            if req.args.has_key('setbillingtime'):
126                self.set_bill_date(req.authname, req.args.get('newbilltime'))
127                addMessage("All tickets last bill date updated")
128
129        mgr = CustomReportManager(self.env, self.log)
130        data = {};
131        data["is_time_admin"] = req.perm.has_permission("TIME_ADMIN")
132        data["statuses"] = get_statuses(self.env)
133        data["reports"] = mgr.get_reports_by_group(CustomReportManager.TimingAndEstimationKey);
134        # Handle pulling in report_descriptions
135        # Could be added to custom report stuff, but that requires
136        # coordinating with too many people for me to care right now
137        report_descriptions = {}
138        for h in reports.all_reports:
139            report_descriptions[h["title"]] = h["description"]
140        for key in data["reports"]:
141            if report_descriptions.has_key(key):
142                data["reports"][key]["description"] = report_descriptions[key]
143        #self.log.debug("DEBUG got %s, %s" % (data["reports"], type(data["reports"])));
144        data["billing_info"] = {"messages":         messages,
145                                "href":             req.href.billing(),
146                                "report_base_href": req.href.report(),
147                                "usermanual_href":  req.href.wiki(user_manual_wiki_title),
148                                "usermanual_title": user_manual_title }
149
150        self.set_request_billing_dates(data)
151
152        add_stylesheet(req, "billing/billingplugin.css")
153        add_script(req, "billing/date.js")
154        add_script(req, "billing/linkifyer.js")
155        return 'billing.html', data, None
156
157
158    # ITemplateProvider
159    def get_htdocs_dirs(self):
160        """Return the absolute path of a directory containing additional
161        static resources (such as images, style sheets, etc).
162        """
163        return [('billing', resource_filename(__name__, 'htdocs'))]
164
165    def get_templates_dirs(self):
166        """Return the absolute path of the directory containing the provided
167        genshi templates.
168        """
169        rtn = [resource_filename(__name__, 'templates')]
170        return rtn
171
Note: See TracBrowser for help on using the repository browser.