def get_work_log(self, mode='all'): db = self.env.get_db_cnx() cursor = db.cursor() if mode == 'user': cursor.execute('SELECT wl.user, s.value, wl.starttime, wl.endtime, wl.ticket, t.summary, t.status, wl.comment ' 'FROM work_log wl ' 'INNER JOIN ticket t ON wl.ticket=t.id ' 'LEFT JOIN session_attribute s ON wl.user=s.sid AND s.name=\'name\' ' 'WHERE wl.user=%s ' 'ORDER BY wl.lastchange DESC', (self.authname,)) elif mode == 'summary': cursor.execute('SELECT wl.user, s.value, wl.starttime, wl.endtime, wl.ticket, t.summary, t.status, wl.comment ' 'FROM (SELECT user,MAX(lastchange) lastchange FROM work_log GROUP BY user) wlt ' 'INNER JOIN work_log wl ON wlt.user=wl.user AND wlt.lastchange=wl.lastchange ' 'INNER JOIN ticket t ON wl.ticket=t.id ' 'LEFT JOIN session_attribute s ON wl.user=s.sid AND s.name=\'name\' ' 'ORDER BY wl.lastchange DESC, wl.user') else: cursor.execute('SELECT wl.user, s.value, wl.starttime, wl.endtime, wl.ticket, t.summary, t.status, wl.comment ' 'FROM work_log wl ' 'INNER JOIN ticket t ON wl.ticket=t.id ' 'LEFT JOIN session_attribute s ON wl.user=s.sid AND s.name=\'name\' ' 'ORDER BY wl.lastchange DESC, wl.user') rv = [] for user,name,starttime,endtime,ticket,summary,status,comment in cursor: starttime = float(starttime) endtime = float(endtime) started = datetime.fromtimestamp(starttime) dispname = user if name: dispname = '%s (%s)' % (name, user) if not endtime == 0: finished = datetime.fromtimestamp(endtime) delta = 'Worked for %s (between %s %s and %s %s)' % \ (pretty_timedelta(started, finished), format_date(starttime), format_time(starttime), format_date(endtime), format_time(endtime)) else: delta = 'Started %s ago (%s %s)' % \ (pretty_timedelta(started), format_date(starttime), format_time(starttime)) rv.append({'user': user, 'name': name, 'dispname': dispname, 'starttime': int(starttime), 'endtime': int(endtime), 'delta': delta, 'ticket': ticket, 'summary': summary, 'status': status, 'comment': comment}) return rv
def get_timeline_events(self, req, start, stop, filters): # Worklog changes show_starts = 'workstart' in filters show_stops = 'workstop' in filters if show_starts or show_stops: add_stylesheet(req, "worklog/worklogplugin.css") ts_start = to_timestamp(start) ts_stop = to_timestamp(stop) ticket_realm = Resource('ticket') db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute("""SELECT wl.worker,wl.ticket,wl.time,wl.starttime,wl.comment,wl.kind,t.summary,t.status,t.resolution,t.type FROM ( SELECT worker, ticket, starttime AS time, starttime, comment, 'start' AS kind FROM work_log UNION SELECT worker, ticket, endtime AS time, starttime, comment, 'stop' AS kind FROM work_log ) AS wl INNER JOIN ticket t ON t.id = wl.ticket AND wl.time>=%s AND wl.time<=%s ORDER BY wl.time""" % (ts_start, ts_stop)) previous_update = None for worker,tid,ts,ts_start,comment,kind,summary,status,resolution,type in cursor: ticket = ticket_realm(id=tid) time = datetime.fromtimestamp(ts, utc) started = None if kind == 'start': if not show_starts: continue yield ('workstart', time, worker, (ticket,summary,status,resolution,type, started, "")) else: if not show_stops: continue started = datetime.fromtimestamp(ts_start, utc) if comment: comment = "(Time spent: %s)[[BR]]%s" % (pretty_timedelta(started, time), comment) else: comment = '(Time spent: %s)' % pretty_timedelta(started, time) yield ('workstop', time, worker, (ticket,summary,status,resolution,type, started, comment))
def get_ticket_js(self, who, since): timedelta = pretty_timedelta(datetime.fromtimestamp(since), None); script = """ li_tctk = document.createElement('li'); ul.appendChild(li_tctk); li_tctk.appendChild(document.createTextNode('""" + who + """ has been working on this ticket for """ + timedelta + """'));""" return script;
def get_ticket_js(self, who, since): timedelta = pretty_timedelta(datetime.fromtimestamp(since), None) script = """ li_tctk = document.createElement('li'); ul.appendChild(li_tctk); li_tctk.appendChild(document.createTextNode('""" + who + """ has been working on this ticket for """ + timedelta + """'));""" return script
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(datetime.fromtimestamp(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_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(datetime.fromtimestamp(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_task_js(self, req, ticket, task): script = """ li_task = document.createElement('li'); ul.appendChild(li_task); li_task.appendChild(document.createTextNode('You have been working on '));""" if task: if ticket == task['ticket']: script += """ li_task.appendChild(document.createTextNode('this ticket'));""" else: script += """ li_task.appendChild(document.createTextNode('ticket ')); var a = document.createElement('a'); a.setAttribute('href', '""" + req.href.ticket(task['ticket']) + """'); a.setAttribute('title', '""" + task['summary'].replace("'", "\\'") + """'); a.appendChild(document.createTextNode('#""" + str(task['ticket']) + """')); li_task.appendChild(a);""" timedelta = pretty_timedelta(datetime.fromtimestamp(task['starttime']), None); script += """ li_task.appendChild(document.createTextNode(' for """ + timedelta + """'));""" return script;
def get_task_js(self, req, ticket, task): script = """ li_task = document.createElement('li'); ul.appendChild(li_task); li_task.appendChild(document.createTextNode('You have been working on '));""" if task: if ticket == task['ticket']: script += """ li_task.appendChild(document.createTextNode('this ticket'));""" else: script += """ li_task.appendChild(document.createTextNode('ticket ')); var a = document.createElement('a'); a.setAttribute('href', '""" + req.href.ticket(task['ticket']) + """'); a.setAttribute('title', '""" + task['summary'].replace("'", "\\'") + """'); a.appendChild(document.createTextNode('#""" + str(task['ticket']) + """')); li_task.appendChild(a);""" timedelta = pretty_timedelta( datetime.fromtimestamp(task['starttime']), None) script += """ li_task.appendChild(document.createTextNode(' for """ + timedelta + """'));""" return script
def stop_work(self, stoptime=None, comment=''): active = self.get_active_task() if not active: self.explanation = 'You cannot stop working as you appear to be a complete slacker already!' return False if stoptime: if stoptime <= active['starttime']: self.explanation = 'You cannot set your stop time to that value as it is before the start time!' return False elif stoptime >= self.now: self.explanation = 'You cannot set your stop time to that value as it is in the future!' return False else: stoptime = self.now - 1 stoptime = float(stoptime) db = self.env.get_db_cnx(); cursor = db.cursor() cursor.execute('UPDATE work_log ' 'SET endtime=%s, lastchange=%s, comment=%s ' 'WHERE user=%s AND lastchange=%s AND endtime=0', (stoptime, stoptime, comment, self.authname, active['lastchange'])) db.commit() message = '' # Leave a comment if the user has configured this or if they have entered # a work log comment. if self.config.getbool('worklog', 'comment') or comment: started = datetime.fromtimestamp(active['starttime']) finished = datetime.fromtimestamp(stoptime) message = '%s worked on this ticket for %s between %s %s and %s %s.' % \ (self.authname, pretty_timedelta(started, finished), \ format_date(active['starttime']), format_time(active['starttime']), \ format_date(stoptime), format_time(stoptime)) if comment: message += "\n[[BR]]\n" + comment if self.config.getbool('worklog', 'timingandestimation') and \ self.config.get('ticket-custom', 'hours'): if not message: message = 'Hours recorded automatically by the worklog plugin.' round_delta = float(self.config.getint('worklog', 'roundup') or 1) # Get the delta in minutes delta = float(int(stoptime) - int(active['starttime'])) / float(60) # Round up if needed delta = int(round((delta / round_delta) + float(0.5))) * int(round_delta) db = self.env.get_db_cnx() tckt = Ticket(self.env, active['ticket'], db) # This hideous hack is here because I don't yet know how to do variable-DP rounding in python - sorry! # It's meant to round to 2 DP, so please replace it if you know how. Many thanks, MK. tckt['hours'] = str(float(int(100 * float(delta) / 60) / 100.0)) self.save_ticket(tckt, db, message) message = '' if message: db = self.env.get_db_cnx() tckt = Ticket(self.env, active['ticket'], db) self.save_ticket(tckt, db, message) return True
def get_ticket_markup(self, who, since): timedelta = pretty_timedelta(datetime.fromtimestamp(since), None) return '<li>%s has been working on this ticket for %s</li>' % ( who, timedelta)
def get_ticket_markup(self, who, since): timedelta = pretty_timedelta(datetime.fromtimestamp(since), None); return '<li>%s has been working on this ticket for %s</li>' % (who, timedelta)
def get_work_log(self, mode='all'): db = self.env.get_db_cnx() cursor = db.cursor() if mode == 'user': cursor.execute( 'SELECT wl.worker, s.value, wl.starttime, wl.endtime, wl.ticket, t.summary, t.status, wl.comment ' 'FROM work_log wl ' 'INNER JOIN ticket t ON wl.ticket=t.id ' 'LEFT JOIN session_attribute s ON wl.worker=s.sid AND s.name=\'name\' ' 'WHERE wl.worker=%s ' 'ORDER BY wl.lastchange DESC', (self.authname, )) elif mode == 'summary': cursor.execute( 'SELECT wl.worker, s.value, wl.starttime, wl.endtime, wl.ticket, t.summary, t.status, wl.comment ' 'FROM (SELECT worker,MAX(lastchange) AS lastchange FROM work_log GROUP BY worker) wlt ' 'INNER JOIN work_log wl ON wlt.worker=wl.worker AND wlt.lastchange=wl.lastchange ' 'INNER JOIN ticket t ON wl.ticket=t.id ' 'LEFT JOIN session_attribute s ON wl.worker=s.sid AND s.name=\'name\' ' 'ORDER BY wl.lastchange DESC, wl.worker') else: cursor.execute( 'SELECT wl.worker, s.value, wl.starttime, wl.endtime, wl.ticket, t.summary, t.status, wl.comment ' 'FROM work_log wl ' 'INNER JOIN ticket t ON wl.ticket=t.id ' 'LEFT JOIN session_attribute s ON wl.worker=s.sid AND s.name=\'name\' ' 'ORDER BY wl.lastchange DESC, wl.worker') rv = [] for user, name, starttime, endtime, ticket, summary, status, comment in cursor: starttime = float(starttime) endtime = float(endtime) started = datetime.fromtimestamp(starttime) dispname = user if name: dispname = '%s (%s)' % (name, user) if not endtime == 0: finished = datetime.fromtimestamp(endtime) delta = 'Worked for %s (between %s %s and %s %s)' % \ (pretty_timedelta(started, finished), format_date(starttime), format_time(starttime), format_date(endtime), format_time(endtime)) else: delta = 'Started %s ago (%s %s)' % \ (pretty_timedelta(started), format_date(starttime), format_time(starttime)) rv.append({ 'user': user, 'name': name, 'dispname': dispname, 'starttime': int(starttime), 'endtime': int(endtime), 'delta': delta, 'ticket': ticket, 'summary': summary, 'status': status, 'comment': comment }) return rv
def stop_work(self, stoptime=None, comment=''): active = self.get_active_task() if not active: self.explanation = 'You cannot stop working as you appear to be a complete slacker already!' return False if stoptime: if stoptime <= active['starttime']: self.explanation = 'You cannot set your stop time to that value as it is before the start time!' return False elif stoptime >= self.now: self.explanation = 'You cannot set your stop time to that value as it is in the future!' return False else: stoptime = self.now - 1 stoptime = float(stoptime) db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( 'UPDATE work_log ' 'SET endtime=%s, lastchange=%s, comment=%s ' 'WHERE worker=%s AND lastchange=%s AND endtime=0', (stoptime, stoptime, comment, self.authname, active['lastchange'])) db.commit() plugtne = self.config.getbool( 'worklog', 'timingandestimation') and self.config.get( 'ticket-custom', 'hours') plughrs = self.config.getbool('worklog', 'trachoursplugin') and self.config.get( 'ticket-custom', 'totalhours') message = '' hours = '0.0' # Leave a comment if the user has configured this or if they have entered # a work log comment. if plugtne or plughrs: round_delta = float(self.config.getint('worklog', 'roundup') or 1) # Get the delta in minutes delta = float(int(stoptime) - int(active['starttime'])) / float(60) # Round up if needed delta = int( round((delta / round_delta) + float(0.5))) * int(round_delta) # This hideous hack is here because I don't yet know how to do variable-DP rounding in python - sorry! # It's meant to round to 2 DP, so please replace it if you know how. Many thanks, MK. hours = str(float(int(100 * float(delta) / 60) / 100.0)) if plughrs: message = 'Hours recorded automatically by the worklog plugin. %s hours' % hours elif self.config.getbool('worklog', 'comment') or comment: started = datetime.fromtimestamp(active['starttime']) finished = datetime.fromtimestamp(stoptime) message = '%s worked on this ticket for %s between %s %s and %s %s.' % \ (self.authname, pretty_timedelta(started, finished), \ format_date(active['starttime']), format_time(active['starttime']), \ format_date(stoptime), format_time(stoptime)) if comment: message += "\n[[BR]]\n" + comment if plugtne or plughrs: if not message: message = 'Hours recorded automatically by the worklog plugin.' tckt = Ticket(self.env, active['ticket']) if plugtne: tckt['hours'] = hours self.save_ticket(tckt, message) message = '' if message: tckt = Ticket(self.env, active['ticket']) self.save_ticket(tckt, message) return True