def getLatestTask(self, req, username=None): """ Returns a structure representing the info about the latest task. """ if username: mgr = WorkLogManager(self.env, self.config, username) else: mgr = WorkLogManager(self.env, self.config, req.authname) return mgr.get_latest_task()
def get_navigation_items(self, req): match = re.match(r'/ticket/([0-9]+)$', req.path_info) if match: add_stylesheet(req, "worklog/worklogplugin.css") ticket = int(match.group(1)) mgr = WorkLogManager(self.env, self.config, req.authname) task_js = '' if req.authname != 'anonymous': task = mgr.get_active_task() if task: task_js = self.get_task_js(req, ticket, task) who, since = mgr.who_is_working_on(ticket) ticket_js = '' if who: # If who == req.authname then we will have some text from above. if who != req.authname: ticket_js = self.get_ticket_js(who, since) else: ticket_js = self.get_ticket_js_noone() button_js = '' if req.authname != 'anonymous': if mgr.can_work_on(ticket): # Display a "Work on Link" button. button_js = self.get_button_js(req, ticket) elif task and task['ticket'] == ticket: # We are currently working on this, so display the stop button... button_js = self.get_button_js(req, ticket, True) yield 'mainnav', 'ticket-worklog-addon', self.get_javascript( task_js, ticket_js, button_js)
def getActiveTask(self, req, username=None): """ Returns a structure representing the info about the active task (identical to getLatestTask but does not return anything if the work has stopped). """ if username: mgr = WorkLogManager(self.env, self.config, username) else: mgr = WorkLogManager(self.env, self.config, req.authname) return mgr.get_active_task()
def get_navigation_items(self, req): match = re.match(r'/ticket/([0-9]+)$', req.path_info) if match: add_stylesheet(req, "worklog/worklogplugin.css") ticket = int(match.group(1)) mgr = WorkLogManager(self.env, self.config, req.authname) task_js = '' if req.authname != 'anonymous': task = mgr.get_active_task() if task: task_js = self.get_task_js(req, ticket, task) who,since = mgr.who_is_working_on(ticket) ticket_js = '' if who: # If who == req.authname then we will have some text from above. if who != req.authname: ticket_js = self.get_ticket_js(who, since) else: ticket_js = self.get_ticket_js_noone() button_js = '' if req.authname != 'anonymous': if mgr.can_work_on(ticket): # Display a "Work on Link" button. button_js = self.get_button_js(req, ticket) elif task and task['ticket'] == ticket: # We are currently working on this, so display the stop button... button_js = self.get_button_js(req, ticket, True) yield 'mainnav', 'ticket-worklog-addon', self.get_javascript(task_js, ticket_js, button_js)
class WorkLogTicketObserver(Component): implements(ITicketChangeListener) def __init__(self): self.mgr = WorkLogManager(self.env) def ticket_created(self, ticket): """Called when a ticket is created.""" pass def ticket_changed(self, ticket, comment, author, old_values): """Called when a ticket is modified. `old_values` is a dictionary containing the previous values of the fields that have changed. """ syllabus_id = ticket.syllabus_id if self.mgr.autostop.syllabus(syllabus_id) \ and 'closed' == ticket['status'] \ and 'closed' != old_values.get('status'): who, since = self.mgr.who_is_working_on(ticket.id) if who: self.mgr.stop_work(who, ticket.pid) def ticket_deleted(self, ticket): """Called when a ticket is deleted.""" pass
def filter_stream(self, req, method, filename, stream, data): match = re.match(r'/ticket/([0-9]+)$', req.path_info) if match and req.perm.has_permission('WORK_LOG'): ticket = int(match.group(1)) add_stylesheet(req, "worklog/worklogplugin.css") add_script(req, 'worklog/jqModal.js') add_stylesheet(req, 'worklog/jqModal.css') add_script(req, 'worklog/ui.datepicker.js') add_stylesheet(req, 'worklog/ui.datepicker.css') add_script(req, 'worklog/jquery.mousewheel.pack.js') add_script(req, 'worklog/jquery.timeentry.pack.js') add_script(req, 'worklog/tracWorklog.js') mgr = WorkLogManager(self.env, self.config, req.authname) task_markup = '' if req.authname != 'anonymous': task = mgr.get_active_task() if task: task_markup = self.get_task_markup(req, ticket, task) who, since = mgr.who_is_working_on(ticket) ticket_markup = '' if who: # If who == req.authname then we will have some text from above. if who != req.authname: ticket_markup = self.get_ticket_markup(who, since) else: ticket_markup = self.get_ticket_markup_noone() button_markup = '' if req.authname != 'anonymous': if mgr.can_work_on(ticket): # Display a "Work on Link" button. button_markup = self.get_button_markup(req, ticket) elif task and task['ticket'] == ticket: # We are currently working on this, so display the stop button... button_markup = self.get_button_markup(req, ticket, True) # User's current task information html = XML(''' <fieldset class="workloginfo"> <legend>Work Log</legend> %s <ul> %s %s </ul> </fieldset> ''' % (button_markup, task_markup, ticket_markup)) stream |= Transformer('.//div[@id="ticket"]').before(html) return stream
def filter_stream(self, req, method, filename, stream, data): match = re.match(r'/ticket/([0-9]+)$', req.path_info) if match and req.perm.has_permission('WORK_LOG'): ticket = int(match.group(1)) add_stylesheet(req, "worklog/worklogplugin.css") add_script(req, 'worklog/jqModal.js') add_stylesheet(req, 'worklog/jqModal.css') add_script(req, 'worklog/ui.datepicker.js') add_stylesheet(req, 'worklog/ui.datepicker.css') add_script(req, 'worklog/jquery.mousewheel.pack.js') add_script(req, 'worklog/jquery.timeentry.pack.js') add_script(req, 'worklog/tracWorklog.js') mgr = WorkLogManager(self.env, self.config, req.authname) task_markup = '' if req.authname != 'anonymous': task = mgr.get_active_task() if task: task_markup = self.get_task_markup(req, ticket, task) who,since = mgr.who_is_working_on(ticket) ticket_markup = '' if who: # If who == req.authname then we will have some text from above. if who != req.authname: ticket_markup = self.get_ticket_markup(who, since) else: ticket_markup = self.get_ticket_markup_noone() button_markup = '' if req.authname != 'anonymous': if mgr.can_work_on(ticket): # Display a "Work on Link" button. button_markup = self.get_button_markup(req, ticket) elif task and task['ticket'] == ticket: # We are currently working on this, so display the stop button... button_markup = self.get_button_markup(req, ticket, True) # User's current task information html = XML(''' <fieldset class="workloginfo"> <legend>Work Log</legend> %s <ul> %s %s </ul> </fieldset> ''' % (button_markup, task_markup, ticket_markup)) stream |= Transformer('.//div[@id="ticket"]').before(html) return stream
def ticket_changed(self, ticket, comment, author, old_values): """Called when a ticket is modified. `old_values` is a dictionary containing the previous values of the fields that have changed. """ if self.config.getbool('worklog', 'autostop') \ and 'closed' == ticket['status'] \ and old_values.has_key('status') \ and 'closed' != old_values['status']: mgr = WorkLogManager(self.env, self.config) who,since = mgr.who_is_working_on(ticket.id) if who: mgr = WorkLogManager(self.env, self.config, who) mgr.stop_work()
def ticket_changed(self, ticket, comment, author, old_values): """Called when a ticket is modified. `old_values` is a dictionary containing the previous values of the fields that have changed. """ if ( self.config.getbool("worklog", "autostop") and "closed" == ticket["status"] and old_values.has_key("status") and "closed" != old_values["status"] ): mgr = WorkLogManager(self.env, self.config) who, since = mgr.who_is_working_on(ticket.id) if who: mgr = WorkLogManager(self.env, self.config, who) mgr.stop_work()
class WorlLogRPC(Component): """ Interface to the [http://trac-hacks.org/wiki/WorkLogPlugin Work Log Plugin] """ implements(IXMLRPCHandler) def __init__(self): self.mgr = WorkLogManager(self.env) def xmlrpc_namespace(self): return 'worklog' def xmlrpc_methods(self): yield ('WIKI_VIEW', ((int,),), self.getRPCVersionSupported) yield ('WIKI_VIEW', ((str, int),), self.startWork) yield ('WIKI_VIEW', ((str, int), (str, int, str), (str, int, str, int),), self.stopWork) yield ('WIKI_VIEW', ((dict, int), (dict, int, str),), self.getLatestTask) yield ('WIKI_VIEW', ((dict, int), (dict, int, str),), self.getActiveTask) yield ('WIKI_VIEW', ((str, int,),), self.whoIsWorkingOn) yield ('WIKI_VIEW', ((str, int,),), self.whoLastWorkedOn) def getRPCVersionSupported(self, req): """ Returns 1 with this version of the Work Log XMLRPC API. """ return 1 def startWork(self, req, ticket): """ Start work on a ticket. Returns the string 'OK' on success or an explanation on error (requires authentication)""" res, err = self.mgr.start_work(req.authname, ticket) if res: return 'OK' else: return err def stopWork(self, req, pid, comment=None, stoptime=None): """ Stops work. Returns the string 'OK' on success or an explanation on error (requires authentication, stoptime is seconds since epoch) """ res, err = self.mgr.stop_work(req.authname, pid, stoptime, comment) if res: return 'OK' else: return err def getLatestTask(self, req, pid, username=None): """ Returns a structure representing the info about the latest task. """ if not username: username = req.authname return self.mgr.get_latest_task(username, pid) def getActiveTask(self, req, pid, username=None): """ Returns a structure representing the info about the active task (identical to getLatestTask but does not return anything if the work has stopped). """ if not username: username = req.authname return self.mgr.get_active_task(username, pid) def whoIsWorkingOn(self, req, ticket): """ Returns the username of the person currently working on the given ticket """ who, since = self.mgr.who_is_working_on(ticket) return who def whoLastWorkedOn(self, req, ticket): """ Returns the username of the person last worked on the given ticket """ return self.mgr.who_last_worked_on(ticket)
def ticket_changed(self, ticket, comment, author, old_values): """Called when a ticket is modified. `old_values` is a dictionary containing the previous values of the fields that have changed. """ if self.config.getbool('worklog', 'autostop') \ and 'closed' == ticket['status'] \ and old_values.has_key('status') \ and 'closed' != old_values['status']: mgr = WorkLogManager(self.env, self.config) who, since = mgr.who_is_working_on(ticket.id) if who: mgr = WorkLogManager(self.env, self.config, who) mgr.stop_work()
class WorkLogTicketAddon(Component): implements(ITemplateStreamFilter) def __init__(self): self.mgr = WorkLogManager(self.env) self.pm = ProjectManagement(self.env) def get_task_markup(self, req, ticket, task): if not task: return '' ticket_text = 'ticket #' + str(task['ticket']) if task['ticket'] == ticket: ticket_text = 'this ticket' timedelta = pretty_timedelta(task['starttime'], None); return '<li>%s</li>' % wiki_to_oneliner('You have been working on %s for %s' % (ticket_text, timedelta), self.env, req=req) def get_ticket_markup(self, who, since): timedelta = pretty_timedelta(since, None); return '<li>%s has been working on this ticket for %s</li>' % (who, timedelta) def get_ticket_markup_noone(self): return '<li>Nobody is working on this ticket</li>' def get_button_markup(self, req, ticket, stop=False): if stop: action = 'stop' label = 'Stop Work' else: action = 'start' label = 'Start Work' return ''' <form id="worklogTicketForm" method="post" action="%s" class="inlinebuttons" onsubmit="return tracWorklog.%s();"> <input type="hidden" name="source_url" value="%s" /> <input type="hidden" name="ticket" value="%s" /> <input type="submit" name="%swork" value="%s" /> </form> <div id="worklogPopup" class="jqmWindow"> <div style="text-align: right;"> <span style="text-decoration: underline; color: blue; cursor: pointer;" class="jqmClose">close</span> </div> <form method="post" action="%s" class="inlinebuttons"> <input type="hidden" name="source_url" value="%s" /> <input type="hidden" name="ticket" value="%s" /> <input id="worklogStoptime" type="hidden" name="stoptime" value="" /> <fieldset> <legend>Stop work</legend> <div class="field"> <fieldset class="iefix"> <label for="worklogComment">Optional: Leave a comment about the work you have done...</label> <p><textarea id="worklogComment" name="comment" class="wikitext" rows="6" cols="60"></textarea></p> </fieldset> </div> <div class="field"> <label>Override end time</label> <div align="center"> <div style="width: 185px;"> <div id="worklogStopDate"></div> <br clear="all" /> <div style="text-align: right;"> @ <input id="worklogStopTime" type="text" size="6" /> </div> </div> </div> </div> <div style="text-align: right;"><input id="worklogSubmit" type="submit" name="%swork" value="%s" /></div> </fieldset> </form> </div> ''' % (req.href.worklog(), action, req.href.ticket(ticket), ticket, action, label, req.href.worklog(), req.href.ticket(ticket), ticket, action, label) # ITemplateStreamFilter def filter_stream(self, req, method, filename, stream, data): match = re.match(r'/ticket/([0-9]+)$', req.path_info) if match and req.perm.has_permission('WORK_LOG') and 'ticket' in data: ticket = data['ticket'] self.pm.check_component_enabled(self, pid=ticket.pid) tkt_id = ticket.id add_stylesheet(req, "worklog/worklogplugin.css") add_script(req, 'worklog/jqModal.js') add_stylesheet(req, 'worklog/jqModal.css') add_stylesheet(req, 'common/css/jquery-ui/jquery.ui.core.css') add_stylesheet(req, 'common/css/jquery-ui/jquery.ui.datepicker.css') add_stylesheet(req, 'common/css/jquery-ui/jquery.ui.theme.css') add_script(req, 'common/js/jquery.ui.core.js') add_script(req, 'common/js/jquery.ui.widget.js') add_script(req, 'common/js/jquery.ui.datepicker.js') add_script(req, 'worklog/jquery.mousewheel.pack.js') add_script(req, 'worklog/jquery.timeentry.pack.js') add_script(req, 'worklog/tracWorklog.js') username = req.authname task_markup = '' if username != 'anonymous': task = self.mgr.get_active_task(username, ticket.pid) if task: task_markup = self.get_task_markup(req, tkt_id, task) who, since = self.mgr.who_is_working_on(tkt_id) ticket_markup = '' if who: if who != username: ticket_markup = self.get_ticket_markup(who, since) else: ticket_markup = self.get_ticket_markup_noone() button_markup = '' if username != 'anonymous': can, _ = self.mgr.can_work_on(username, ticket) if can: # Display a "Work on Link" button. button_markup = self.get_button_markup(req, tkt_id) elif task and task['ticket'] == tkt_id: # We are currently working on this, so display the stop button... button_markup = self.get_button_markup(req, tkt_id, True) # User's current task information html = XML(''' <fieldset class="workloginfo"> <legend>Work Log</legend> %s <ul> %s %s </ul> </fieldset> ''' % (button_markup, task_markup, ticket_markup)) stream |= Transformer('.//div[@id="ticket"]').before(html) return stream
def process_request(self, req): req.perm.require('WORK_VIEW') messages = [] def addMessage(s): messages.extend([s]); # General protection (not strictly needed if Trac behaves itself) if not re.search('/worklog', req.path_info): return None add_stylesheet(req, "worklog/worklogplugin.css") # Specific pages: match = re.search('/worklog/users/(.*)', req.path_info) if match: mgr = WorkLogManager(self.env, self.config, match.group(1)) if req.args.has_key('format') and req.args['format'] == 'csv': self.worklog_csv(req, mgr.get_work_log('user')) return None data = {"worklog": mgr.get_work_log('user'), "ticket_href": req.href.ticket(), "usermanual_href":req.href.wiki(user_manual_wiki_title), "usermanual_title":user_manual_title } return 'worklog_user.html', data, None match = re.search('/worklog/stop/([0-9]+)', req.path_info) if match: ticket = match.group(1) data = {'worklog_href': req.href.worklog(), 'ticket_href': req.href.ticket(ticket), 'ticket': ticket, 'action': 'stop', 'label': 'Stop Work'} xhr = req.get_header('X-Requested-With') == 'XMLHttpRequest' if xhr: data['xhr'] = True return 'worklog_stop.html', data, None mgr = WorkLogManager(self.env, self.config, req.authname) if req.args.has_key('format') and req.args['format'] == 'csv': self.worklog_csv(req, mgr.get_work_log()) return None # Not any specific page, so process POST actions here. if req.method == 'POST': if req.args.has_key('startwork') and req.args.has_key('ticket'): if not mgr.start_work(req.args['ticket']): addMessage(mgr.get_explanation()) else: addMessage('You are now working on ticket #%s.' % (req.args['ticket'],)) req.redirect(req.args['source_url']) return None elif req.args.has_key('stopwork'): stoptime = None if req.args.has_key('stoptime') and req.args['stoptime']: stoptime = int(req.args['stoptime']) comment = '' if req.args.has_key('comment'): comment = req.args['comment'] if not mgr.stop_work(stoptime, comment): addMessage(mgr.get_explanation()) else: addMessage('You have stopped working.') req.redirect(req.args['source_url']) return None # no POST, so they're just wanting a list of the worklog entries data = {"messages": messages, "worklog": mgr.get_work_log('summary'), "worklog_href": req.href.worklog(), "ticket_href": req.href.ticket(), "usermanual_href": req.href.wiki(user_manual_wiki_title), "usermanual_title": user_manual_title } return 'worklog.html', data, None
def startWork(self, req, ticket): """ Start work on a ticket. Returns the string 'OK' on success or an explanation on error (requires authentication)""" mgr = WorkLogManager(self.env, self.config, req.authname) if mgr.start_work(ticket): return 'OK' return mgr.get_explanation()
def whoLastWorkedOn(self, req, ticket): """ Returns the username of the person last worked on the given ticket """ mgr = WorkLogManager(self.env, self.config, req.authname) return mgr.who_last_worked_on(ticket)
def whoIsWorkingOn(self, req, ticket): """ Returns the username of the person currently working on the given ticket """ mgr = WorkLogManager(self.env, self.config, req.authname) (who, when) = mgr.who_is_working_on(ticket) return who
def stopWork(self, req, comment='', stoptime=None): """ Stops work. Returns the string 'OK' on success or an explanation on error (requires authentication, stoptime is seconds since epoch) """ mgr = WorkLogManager(self.env, self.config, req.authname) if mgr.stop_work(stoptime, comment): return 'OK' return mgr.get_explanation()
def __init__(self): self.mgr = WorkLogManager(self.env)
def __init__(self): self.mgr = WorkLogManager(self.env) self.pm = ProjectManagement(self.env)
def process_request(self, req): req.perm.require('WORK_VIEW') messages = [] def addMessage(s): messages.extend([s]) # General protection (not strictly needed if Trac behaves itself) if not re.search('/worklog', req.path_info): return None add_stylesheet(req, "worklog/worklogplugin.css") # Specific pages: match = re.search('/worklog/users/(.*)', req.path_info) if match: mgr = WorkLogManager(self.env, self.config, match.group(1)) if req.args.has_key('format') and req.args['format'] == 'csv': self.worklog_csv(req, mgr.get_work_log('user')) return None data = { "worklog": mgr.get_work_log('user'), "ticket_href": req.href.ticket(), "usermanual_href": req.href.wiki(user_manual_wiki_title), "usermanual_title": user_manual_title } return 'worklog_user.html', data, None match = re.search('/worklog/stop/([0-9]+)', req.path_info) if match: ticket = match.group(1) data = { 'worklog_href': req.href.worklog(), 'ticket_href': req.href.ticket(ticket), 'ticket': ticket, 'action': 'stop', 'label': 'Stop Work' } xhr = req.get_header('X-Requested-With') == 'XMLHttpRequest' if xhr: data['xhr'] = True return 'worklog_stop.html', data, None mgr = WorkLogManager(self.env, self.config, req.authname) if req.args.has_key('format') and req.args['format'] == 'csv': self.worklog_csv(req, mgr.get_work_log()) return None # Not any specific page, so process POST actions here. if req.method == 'POST': if req.args.has_key('startwork') and req.args.has_key('ticket'): if not mgr.start_work(req.args['ticket']): addMessage(mgr.get_explanation()) else: addMessage('You are now working on ticket #%s.' % (req.args['ticket'], )) req.redirect(req.args['source_url']) return None elif req.args.has_key('stopwork'): stoptime = None if req.args.has_key('stoptime') and req.args['stoptime']: stoptime = int(req.args['stoptime']) comment = '' if req.args.has_key('comment'): comment = req.args['comment'] if not mgr.stop_work(stoptime, comment): addMessage(mgr.get_explanation()) else: addMessage('You have stopped working.') req.redirect(req.args['source_url']) return None # no POST, so they're just wanting a list of the worklog entries data = { "messages": messages, "worklog": mgr.get_work_log('summary'), "worklog_href": req.href.worklog(), "ticket_href": req.href.ticket(), "usermanual_href": req.href.wiki(user_manual_wiki_title), "usermanual_title": user_manual_title } return 'worklog.html', data, None
def process_request(self, req): messages = [] def addMessage(s): messages.extend([s]); # General protection (not strictly needed if Trac behaves itself) if not re.search('/worklog', req.path_info): return None # Specific pages: match = re.search('/worklog/users/(.*)', req.path_info) if match: mgr = WorkLogManager(self.env, self.config, match.group(1)) if req.args.has_key('format') and req.args['format'] == 'csv': self.worklog_csv(req, mgr.get_work_log('user')) return None req.hdf["worklog"] = {"worklog": mgr.get_work_log('user'), "ticket_href": req.href.ticket(), "usermanual_href":req.href.wiki(user_manual_wiki_title), "usermanual_title":user_manual_title } add_stylesheet(req, "worklog/worklogplugin.css") return 'worklog_user.cs', None mgr = WorkLogManager(self.env, self.config, req.authname) if req.args.has_key('format') and req.args['format'] == 'csv': self.worklog_csv(req, mgr.get_work_log()) return None # Not any specific page, so process POST actions here. if req.method == 'POST': if req.args.has_key('startwork') and req.args.has_key('ticket'): if not mgr.start_work(req.args['ticket']): addMessage(mgr.get_explanation()) else: addMessage('You are now working on ticket #%s.' % (req.args['ticket'],)) req.redirect(req.args['source_url']) return None elif req.args.has_key('stopwork'): stoptime = None if req.args.has_key('stoptime'): stoptime = int(req.args['stoptime']) comment = '' if req.args.has_key('comment'): comment = str(req.args['comment']) if not mgr.stop_work(stoptime, comment): addMessage(mgr.get_explanation()) else: addMessage('You have stopped working.') req.redirect(req.args['source_url']) return None # no POST, so they're just wanting a list of the worklog entries req.hdf["worklog"] = {"messages": messages, "worklog": mgr.get_work_log('summary'), "href": req.href.worklog(), "ticket_href": req.href.ticket(), "usermanual_href": req.href.wiki(user_manual_wiki_title), "usermanual_title": user_manual_title } add_stylesheet(req, "worklog/worklogplugin.css") return 'worklog.cs', None