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
RevLine 
[2538]1from pkg_resources import resource_filename
[1119]2import re
3import time
4import datetime
5import dbhelper
[3784]6from usermanual import *
[1119]7from trac.core import *
8from trac.web import IRequestHandler
[4258]9from trac.perm import IPermissionRequestor
[1119]10from trac.util import Markup
11from trac.web.chrome import add_stylesheet, add_script, \
12     INavigationContributor, ITemplateProvider
13from trac.web.href import Href
[2390]14from reportmanager import CustomReportManager
[2774]15from statuses import get_statuses
[8131]16import datetime
17import trac.util.datefmt
[8260]18import reports
[1119]19
[11383]20def strptime(date_string, format):
21    return datetime.datetime(*(time.strptime(date_string, format)[0:6]))
[8131]22
[2774]23#get_statuses = api.get_statuses
[10625]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',
[11040]29    '%Y-%m-%d',
[10625]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',
[11040]35    '%Y/%m/%d',
[10625]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',
[11040]41    '%Y.%m.%d',
[10625]42    ]
[11040]43def parsetime(val, tzinfo=trac.util.datefmt.to_datetime(None).tzinfo):
[10625]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)
[11383]50        try: return strptime(val, f).replace(tzinfo=tzinfo)
[10625]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)
[1119]53
[10625]54
[1119]55class TimingEstimationAndBillingPage(Component):
[4255]56    implements(IPermissionRequestor, INavigationContributor, IRequestHandler, ITemplateProvider)
[1119]57
58    def __init__(self):
59        pass
60
[4255]61    # IPermissionRequestor methods
62    def get_permission_actions(self): 
[4260]63        return ["TIME_VIEW", "TIME_RECORD", ("TIME_ADMIN", ["TIME_RECORD", "TIME_VIEW"])] 
[4255]64
[8131]65    def set_bill_date(self, username="Timing and Estimation Plugin",  when=None):
66        now = trac.util.datefmt.to_datetime(None)#get now
[10625]67        if isinstance(when, str) or isinstance(when, unicode):
68            when = parsetime(when, now.tzinfo)
69        if not when: when = now
[8131]70
[10625]71        strwhen = "%#04d-%#02d-%#02d %#02d:%#02d:%#02d" % \
[8131]72                (when.year, when.month, when.day, when.hour,when.minute, when.second)
[10625]73
[1119]74        sql = """
75        INSERT INTO bill_date (time, set_when, str_value)
[1365]76        VALUES (%s, %s, %s)
[1119]77        """
[8141]78        dbhelper.execute_non_query(self.env, sql, trac.util.datefmt.to_timestamp(when),
[8131]79                                   trac.util.datefmt.to_timestamp(now), strwhen)
[2774]80
81
[1119]82    # INavigationContributor methods
83    def get_active_navigation_item(self, req):
[9866]84        val = re.search('/billing$', req.path_info)
[4782]85        if val and val.start() == 0:
[9866]86            return "billing"
[1119]87        else:
88            return ""
89
90    def get_navigation_items(self, req):
[9866]91        url = req.href.billing()
[4255]92        if req.perm.has_permission("TIME_VIEW"):
[9866]93            yield 'mainnav', "billing", \
[4258]94                Markup('<a href="%s">%s</a>' % \
95                           (url , "Time Reports"))
[1119]96
97    # IRequestHandler methods
[2298]98    def set_request_billing_dates(self, data):
[1119]99        billing_dates = []
100        billing_time_sql = """
[1369]101        SELECT DISTINCT time as value, str_value as text
[1119]102        FROM bill_date
[7840]103        ORDER BY time DESC
[1119]104        """
[8141]105        rs = dbhelper.get_result_set(self.env, billing_time_sql)
[3119]106        if rs:
107            for (value, text) in rs.rows:
[8131]108                billing_info = {'text':text , 'value':value*1000*1000}
109                billing_dates.extend([billing_info]) 
[1369]110        #self.log.debug("bill-dates: %s"%billing_dates)
[2298]111        data['billing_info']["billdates"] = billing_dates
[1119]112
113    def match_request(self, req):
[9866]114        val = re.search('/billing$', req.path_info)
[4782]115        return val and val.start() == 0
[1119]116
117    def process_request(self, req):
118        messages = []
[4258]119        req.perm.require("TIME_VIEW")
[1119]120        def addMessage(s):
121            messages.extend([s]);
122
123        if req.method == 'POST':
[10625]124            req.perm.require("TIME_ADMIN")
[4260]125            if req.args.has_key('setbillingtime'):
[10625]126                self.set_bill_date(req.authname, req.args.get('newbilltime'))
[4260]127                addMessage("All tickets last bill date updated")
[2390]128
129        mgr = CustomReportManager(self.env, self.log)
130        data = {};
[4255]131        data["is_time_admin"] = req.perm.has_permission("TIME_ADMIN")
[8166]132        data["statuses"] = get_statuses(self.env)
[2774]133        data["reports"] = mgr.get_reports_by_group(CustomReportManager.TimingAndEstimationKey);
[8260]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]
[2390]143        #self.log.debug("DEBUG got %s, %s" % (data["reports"], type(data["reports"])));
144        data["billing_info"] = {"messages":         messages,
[9866]145                                "href":             req.href.billing(),
[2390]146                                "report_base_href": req.href.report(),
147                                "usermanual_href":  req.href.wiki(user_manual_wiki_title),
148                                "usermanual_title": user_manual_title }
149
[2298]150        self.set_request_billing_dates(data)
151
[9866]152        add_stylesheet(req, "billing/billingplugin.css")
153        add_script(req, "billing/date.js")
154        add_script(req, "billing/linkifyer.js")
[2298]155        return 'billing.html', data, None
[3784]156
157
[1119]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        """
[9866]163        return [('billing', resource_filename(__name__, 'htdocs'))]
[1119]164
165    def get_templates_dirs(self):
166        """Return the absolute path of the directory containing the provided
[2538]167        genshi templates.
[1119]168        """
[2298]169        rtn = [resource_filename(__name__, 'templates')]
170        return rtn
[3784]171
Note: See TracBrowser for help on using the repository browser.