def get_query(self, constraints=None, args=None): req = self.req if not args: args = req.args if not constraints: # If no constraints are given in the URL, use the default ones. if req.authname and req.authname != 'anonymous': qstring = self.default_query user = req.authname else: email = req.session.get('email') name = req.session.get('name') qstring = self.default_anonymous_query user = email or name or None query = Query.from_string(self.env, qstring) args = {'order': query.order, 'col': query.cols, 'max': 0} constraints = query.constraints # Substitute $USER, or ensure no field constraints that depend # on $USER are used if we have no username. for clause in constraints: for field, vals in clause.items(): for (i, val) in enumerate(vals): if user: vals[i] = val.replace('$USER', user) elif val.endswith('$USER'): del clause[field] break query = Query(self.env, args.get('report'), constraints, self._get_cols(), args.get('order'), args.get('desc')) self._set_no_paginator(query) return query
def _sticky_from_report(self, req, data): ids = [] for value_for_group, row_group in data['row_groups']: ids.extend([int(row['id']) for row in row_group if row['resource'] and row['resource'].realm == 'ticket' and 'TICKET_VIEW' in req.perm(row['resource'])]) cols = ['id', 'summary', 'type'] for col in self._fields: if col not in cols: cols.append(col) if hasattr(self.env, 'get_read_db'): db = self.env.get_read_db() else: db = self.env.get_db_cnx() start = 0 count = 100 tickets = [] while start < len(ids): constraints = [{ 'id': [str(id) for id in ids[start:start + count]], }] query = Query(self.env, constraints=constraints, cols=cols, max=0) tickets.extend(query.execute(req, db)) start += count tickets_dict = dict((int(ticket['id']), ticket) for ticket in tickets) tickets = [tickets_dict[id] for id in ids if id in tickets_dict] return self._sticky(req, tickets)
def test_all_ordered_by_priority_desc(self): query = Query(self.env, desc=1) # priority is default order sql = query.get_sql() self.assertEqual(sql, """SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.milestone AS milestone,t.time AS time,t.changetime AS changetime,priority.value AS priority_value FROM ticket AS t LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority) ORDER BY COALESCE(t.priority,'')='' DESC,priority.value DESC,t.id""") tickets = query.execute()
def test_all_ordered_by_id_verbose(self): query = Query(self.env, order='id', verbose=1) sql = query.get_sql() self.assertEqual(sql, """SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.milestone AS milestone,t.reporter AS reporter,t.description AS description,t.time AS time,t.changetime AS changetime,priority.value AS priority_value FROM ticket AS t LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority) ORDER BY COALESCE(t.id,0)=0,t.id""") tickets = query.execute()
def test_grouped_by_priority(self): query = Query(self.env, group='priority') sql = query.get_sql() self.assertEqual(sql, """SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.milestone AS milestone,t.component AS component,t.priority AS priority,t.time AS time,t.changetime AS changetime,priority.value AS priority_value FROM ticket AS t LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority) ORDER BY COALESCE(t.priority,'')='',priority.value,t.id""") tickets = query.execute()
def test_all_ordered_by_id_desc(self): query = Query(self.env, order='id', desc=1) sql, args = query.get_sql() self.assertEqualSQL(sql, """SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.product AS product,t.time AS time,t.changetime AS changetime,priority.value AS priority_value FROM ticket AS t LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority) ORDER BY COALESCE(t.id,0)=0 DESC,t.id DESC""") self.assertEqual([], args) tickets = query.execute(self.req)
def test_all_ordered_by_version_desc(self): query = Query(self.env, order='version', desc=1) sql = query.get_sql() self.assertEqual(sql, """SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.version AS version,t.time AS time,t.changetime AS changetime,priority.value AS priority_value FROM ticket AS t LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority) LEFT OUTER JOIN version ON (version.name=version) ORDER BY COALESCE(t.version,'')='' DESC,COALESCE(version.time,0)=0 DESC,version.time DESC,t.version DESC,t.id""") tickets = query.execute()
def test_all_grouped_by_milestone_desc(self): query = Query(self.env, order='id', group='milestone', groupdesc=1) sql = query.get_sql() self.assertEqual(sql, """SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.component AS component,t.milestone AS milestone,t.time AS time,t.changetime AS changetime,priority.value AS priority_value FROM ticket AS t LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority) LEFT OUTER JOIN milestone ON (milestone.name=milestone) ORDER BY COALESCE(t.milestone,'')='' DESC,COALESCE(milestone.due,0)=0 DESC,milestone.due DESC,t.milestone DESC,COALESCE(t.id,0)=0,t.id""") tickets = query.execute()
def test_all_ordered_by_id(self): query = Query(self.env, order='id') sql, args = query.get_sql() self.assertEqual( sql, """SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.milestone AS milestone,t.time AS time,t.changetime AS changetime,priority.value AS priority_value FROM ticket AS t LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority) ORDER BY COALESCE(t.id,0)=0,t.id""") self.assertEqual([], args) tickets = query.execute(Mock(href=self.env.href))
def test_grouped_by_priority(self): query = Query(self.env, group='priority') sql, args = query.get_sql() self.assertEqualSQL(sql, """SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.product AS product,t.milestone AS milestone,t.priority AS priority,t.time AS time,t.changetime AS changetime,priority.value AS priority_value FROM ticket AS t LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority) ORDER BY COALESCE(priority.value,'')='',%(cast_priority)s,t.id""" % { 'cast_priority': self.env.get_read_db().cast('priority.value', 'int')}) self.assertEqual([], args) tickets = query.execute(self.req)
def test_grouped_by_custom_field(self): self.env.config.set('ticket-custom', 'foo', 'text') query = Query(self.env, group='foo', order='id') sql = query.get_sql() self.assertEqual(sql, """SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.milestone AS milestone,t.time AS time,t.changetime AS changetime,priority.value AS priority_value,foo.value AS foo FROM ticket AS t LEFT OUTER JOIN ticket_custom AS foo ON (id=foo.ticket AND foo.name='foo') LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority) ORDER BY COALESCE(foo.value,'')='',foo.value,COALESCE(t.id,0)=0,t.id""") tickets = query.execute()
def test_all_ordered_by_priority_desc(self): query = Query(self.env, desc=1) # priority is default order sql, args = query.get_sql() self.assertEqualSQL( sql, """SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.milestone AS milestone,t.time AS time,t.changetime AS changetime,priority.value AS priority_value FROM ticket AS t LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority) ORDER BY COALESCE(priority.value,'')='' DESC,%(cast_priority)s DESC,t.id""" % { 'cast_priority': self.env.get_db_cnx().cast('priority.value', 'int') }) self.assertEqual([], args) tickets = query.execute(self.req)
def test_grouped_by_custom_field(self): self.env.config.set('ticket-custom', 'foo', 'text') query = Query(self.env, group='foo', order='id') sql, args = query.get_sql() foo = self.env.get_read_db().quote('foo') self.assertEqualSQL(sql, """SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.product AS product,t.time AS time,t.changetime AS changetime,priority.value AS priority_value,%s.value AS %s FROM ticket AS t LEFT OUTER JOIN ticket_custom AS %s ON (id=%s.ticket AND %s.name='foo') LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority) ORDER BY COALESCE(%s.value,'')='',%s.value,COALESCE(t.id,0)=0,t.id""" % ((foo,) * 7)) self.assertEqual([], args) tickets = query.execute(self.req)
def test_grouped_by_custom_field(self): self.env.config.set('ticket-custom', 'foo', 'text') query = Query(self.env, group='foo', order='id') sql, args = query.get_sql() foo = self.env.get_read_db().quote('foo') self.assertEqualSQL(sql, """SELECT t.id AS id,t.summary AS summary,t.owner AS owner,t.type AS type,t.status AS status,t.priority AS priority,t.milestone AS milestone,t.time AS time,t.changetime AS changetime,priority.value AS priority_value,c.%s AS %s FROM ticket AS t LEFT JOIN (SELECT id AS ticket, (SELECT c.value FROM ticket_custom c WHERE c.ticket=t.id AND c.name='foo') AS %s FROM ticket t) AS c ON (c.ticket=t.id) LEFT OUTER JOIN enum AS priority ON (priority.type='priority' AND priority.name=priority) ORDER BY COALESCE(c.%s,'')='',c.%s,COALESCE(t.id,0)=0,t.id""" % ((foo,) * 5)) self.assertEqual([], args) tickets = query.execute(self.req)
def _create_query_object(env, query, required_columns=None): """Create a query object from a query string. If query is None, the default Query is returned :param required_columns: Columns that must be included in the query. """ if query is None: return Query(env, cols=required_columns) query_object = Query.from_string(env, query) # Add the required_columns for column in required_columns or []: if column not in query_object.cols: query_object.cols.append(column) return query_object
def process_request(self, req): constraints = QueryModule(self.env)._get_constraints(req) if not constraints and not req.args.has_key('order'): # avoid displaying all tickets when the query module is invoked # with no parameters. Instead show only open tickets, possibly # associated with the user constraints = {'status': ('new', 'assigned', 'reopened')} if req.authname and req.authname != 'anonymous': constraints['owner'] = (req.authname,) else: email = req.session.get('email') name = req.session.get('name') if email or name: constraints['cc'] = ('~%s' % email or name,) query = Query(self.env, constraints, req.args.get('order'), req.args.has_key('desc'), req.args.get('group'), req.args.has_key('groupdesc'), req.args.has_key('verbose')) format = req.args.get('format') self.send_converted(req, 'trac.ticket.Query', query, format, 'query')
def process_request(self, req): req.perm.assert_permission('TICKET_VIEW') constraints = self._get_constraints(req) if not constraints and not 'order' in req.args: # If no constraints are given in the URL, use the default ones. if req.authname and req.authname != 'anonymous': qstring = self.default_query user = req.authname else: email = req.session.get('email') name = req.session.get('name') qstring = self.default_anonymous_query user = email or name or None if user: qstring = qstring.replace('$USER', user) self.log.debug('TasklistPlugin: Using default query: %s', qstring) constraints = Query.from_string(self.env, qstring).constraints # Ensure no field constraints that depend on $USER are used # if we have no username. for field, vals in constraints.items(): for val in vals: if val.endswith('$USER'): del constraints[field] cols = req.args.get('col') if not cols: cols = self.default_cols cols.append(self.field_name) if isinstance(cols, basestring): cols = [cols] form_cols = copy.copy(cols) # Since we don't show 'id' or the tasklist_field as an option # to the user, we need to re-insert it here. if cols and 'id' not in cols: cols.insert(0, 'id') if cols and self.field_name not in cols: cols.insert(0, self.field_name) rows = req.args.get('row', []) if isinstance(rows, basestring): rows = [rows] q = Query(self.env, constraints=constraints, cols=cols) query = Query(self.env, req.args.get('report'), constraints, cols, req.args.get('order'), 'desc' in req.args, req.args.get('group'), 'groupdesc' in req.args, 'verbose' in req.args, rows, req.args.get('limit')) if 'update' in req.args: # Reset session vars for var in ('query_constraints', 'query_time', 'query_tickets'): if var in req.session: del req.session[var] req.redirect(q.get_href(req.href).replace('/query', '/tasklist')) if 'add' in req.args: req.perm.require('TICKET_CREATE') t = Ticket(self.env) if req.method == 'POST' and 'field_owner' in req.args and \ 'TICKET_MODIFY' not in req.perm: del req.args['field_owner'] self._populate(req, t) reporter_id = req.args.get('field_reporter') or \ get_reporter_id(req, 'author') t.values['reporter'] = reporter_id valid = None valid = self._validate_ticket(req, t) if valid: t.insert() # Notify try: tn = TicketNotifyEmail(self.env) tn.notify(t, newticket=True) except Exception, e: self.log.exception( "Failure sending notification on creation of " "ticket #%s: %s" % (t.id, e)) req.redirect(q.get_href(req.href).replace('/query', '/tasklist'))
def process_request(self, req): realm = req.args['realm'] id_ = req.args['id'] if not which(self.dot_path): raise TracError( _("Path to dot executable is invalid: %(path)s", path=self.dot_path)) # Urls to generate the depgraph for a ticket is /depgraph/ticketnum # Urls to generate the depgraph for a milestone is # /depgraph/milestone/milestone_name # List of tickets to generate the depgraph. if realm == 'milestone': # We need to query the list of tickets in the milestone query = Query(self.env, constraints={'milestone': [id_]}, max=0) tkt_ids = [fields['id'] for fields in query.execute(req)] else: tid = as_int(id_, None) if tid is None: raise TracError( tag_("%(id)s is not a valid ticket id.", id=html.tt(id_))) tkt_ids = [tid] # The summary argument defines whether we place the ticket id or # its summary in the node's label label_summary = 0 if 'summary' in req.args: label_summary = int(req.args.get('summary')) g = self._build_graph(req, tkt_ids, label_summary=label_summary) if req.path_info.endswith('/depgraph.png') or 'format' in req.args: format_ = req.args.get('format') if format_ == 'text': # In case g.__str__ returns unicode, convert it in ascii req.send( to_unicode(g).encode('ascii', 'replace'), 'text/plain') elif format_ == 'debug': import pprint req.send( pprint.pformat( [TicketLinks(self.env, tkt_id) for tkt_id in tkt_ids]), 'text/plain') elif format_ is not None: if format_ in self.acceptable_formats: req.send(g.render(self.dot_path, format_), 'text/plain') else: raise TracError( _("The %(format)s format is not allowed.", format=format_)) if self.use_gs: ps = g.render(self.dot_path, 'ps2') gs = subprocess.Popen([ self.gs_path, '-q', '-dTextAlphaBits=4', '-dGraphicsAlphaBits=4', '-sDEVICE=png16m', '-sOutputFile=%stdout%', '-' ], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) img, err = gs.communicate(ps) if err: self.log.debug('MasterTickets: Error from gs: %s', err) else: img = g.render(self.dot_path) req.send(img, 'image/png') else: data = {} # Add a context link to enable/disable labels in nodes. if label_summary: add_ctxtnav(req, 'Without labels', req.href(req.path_info, summary=0)) else: add_ctxtnav(req, 'With labels', req.href(req.path_info, summary=1)) if realm == 'milestone': add_ctxtnav(req, 'Back to Milestone: %s' % id_, req.href.milestone(id_)) data['milestone'] = id_ else: data['ticket'] = id_ add_ctxtnav(req, 'Back to Ticket #%s' % id_, req.href.ticket(id_)) data['graph'] = g data['graph_render'] = functools.partial(g.render, self.dot_path) data['use_gs'] = self.use_gs return 'depgraph.html', data, None
def process_request(self, req): req.perm.assert_permission('TICKET_VIEW') constraints = self._get_constraints(req) if not constraints and not req.args.has_key('order'): # avoid displaying all tickets when the query module is invoked # with no parameters. Instead show only open tickets, possibly # associated with the user constraints = {'status': ('new', 'assigned', 'reopened')} if req.authname and req.authname != 'anonymous': constraints['owner'] = (req.authname,) else: email = req.session.get('email') name = req.session.get('name') if email or name: constraints['cc'] = ('~%s' % email or name,) query = Query(self.env, constraints, req.args.get('order'), req.args.has_key('desc'), req.args.get('group'), req.args.has_key('groupdesc'), req.args.has_key('verbose')) if req.args.has_key('update'): # Reset session vars for var in ('query_constraints', 'query_time', 'query_tickets'): if req.session.has_key(var): del req.session[var] req.redirect(query.get_href()) add_link(req, 'alternate', query.get_href('rss'), 'RSS Feed', 'application/rss+xml', 'rss') add_link(req, 'alternate', query.get_href('csv'), 'Comma-delimited Text', 'text/plain') add_link(req, 'alternate', query.get_href('tab'), 'Tab-delimited Text', 'text/plain') constraints = {} for k, v in query.constraints.items(): constraint = {'values': [], 'mode': ''} for val in v: neg = val.startswith('!') if neg: val = val[1:] mode = '' if val[:1] in ('~', '^', '$'): mode, val = val[:1], val[1:] constraint['mode'] = (neg and '!' or '') + mode constraint['values'].append(val) constraints[k] = constraint req.hdf['query.constraints'] = constraints format = req.args.get('format') if format == 'rss': self.display_rss(req, query) return 'query_rss.cs', 'application/rss+xml' elif format == 'csv': self.display_csv(req, query) elif format == 'tab': self.display_csv(req, query, '\t') else: self.display_html(req, query) return 'query.cs', None
def _process_export(self, req): fields = [{'name': 'id', 'label': 'id'}] fields.extend(TicketSystem(self.env).get_ticket_fields()) fieldsFormat = self._get_fields_format(fields) fieldsExport = self._get_fields_export(fields) fieldsWeight = self._get_fields_weight(fields) comment_changeset = req.args.get('export.changeset') and req.args.get( 'export.changeset') == 'True' fields = [c for c in fields if fieldsExport[c['name']]] fieldnames = [c['name'] for c in fields] fields.sort( lambda a, b: fieldsWeight[a['name']] - fieldsWeight[b['name']]) # ticket #8805 : unavailable for python 2.4 or 2.5 #content = BytesIO() content = cStringIO.StringIO() headerStyle = xlwt.easyxf( 'font: bold on; pattern: pattern solid, fore-colour grey25; borders: top thin, bottom thin, left thin, right thin' ) wb = xlwt.Workbook() sheetName = ('Tickets - %s' % self.config.get('project', 'name', '')) try: ws = wb.add_sheet(sheetName) except: # Project name incompatible with sheet name constraints. sheetName = 'Tickets' ws = wb.add_sheet(sheetName) colIndex = {} c = 0 for f in fields: ws.write(0, c, unicode(f['label']), headerStyle) colIndex[f['name']] = c c += 1 if comment_changeset: ws.write(0, c, unicode('Comments in change log'), headerStyle) constraints = {} if req.args.get('filter.type') and len(req.args['filter.type']) > 0: if type(req.args['filter.type']) == list: constraints['type'] = req.args['filter.type'] else: constraints['type'] = [req.args['filter.type']] if req.args.get('filter.version') and len( req.args['filter.version']) > 0: if type(req.args['filter.version']) == list: constraints['version'] = req.args['filter.version'] else: constraints['version'] = [req.args['filter.version']] if req.args.get('filter.milestone') and len( req.args['filter.milestone']) > 0: if type(req.args['filter.milestone']) == list: constraints['milestone'] = req.args['filter.milestone'] else: constraints['milestone'] = [req.args['filter.milestone']] if req.args.get('filter.component') and len( req.args['filter.component']) > 0: if type(req.args['filter.component']) == list: constraints['component'] = req.args['filter.component'] else: constraints['component'] = [req.args['filter.component']] if req.args.get('filter.status') and len( req.args['filter.status']) > 0: if type(req.args['filter.status']) == list: constraints['status'] = req.args['filter.status'] else: constraints['status'] = [req.args['filter.status']] if req.args.get('filter.priority') and len( req.args['filter.priority']) > 0: if type(req.args['filter.priority']) == list: constraints['priority'] = req.args['filter.priority'] else: constraints['priority'] = [req.args['filter.priority']] if req.args.get('filter.severity') and len( req.args['filter.severity']) > 0: if type(req.args['filter.severity']) == list: constraints['severity'] = req.args['filter.severity'] else: constraints['severity'] = [req.args['filter.severity']] if req.args.get('filter.resolution') and len( req.args['filter.resolution']) > 0: if type(req.args['filter.resolution']) == list: constraints['resolution'] = req.args['filter.resolution'] else: constraints['resolution'] = [req.args['filter.resolution']] query = Query(self.env, cols=fieldnames, order='id', max=sys.maxint, constraints=constraints) results = query.execute(req) r = 0 cols = query.get_columns() for result in results: r += 1 for col in cols: value = result[col] format = self.formats[fieldsFormat[col]] value = format.convert(value) style = format.get_style(value) ws.write(r, colIndex[col], value, style) if comment_changeset: format = self.formats['longtext'] value = format.convert( self._get_changelog_comments(result['id'])) style = format.get_style(value) ws.write(r, len(cols), value, style) if req.args.get('export.statistics') and req.args.get( 'export.statistics') == 'True': wb = self._add_statistics_sheet(req, sheetName, wb, fields, colIndex, constraints) wb.save(content) return (content.getvalue(), 'application/excel')
def process_request(self, req): path_info = req.path_info[10:] if not path_info: raise TracError('No ticket specified') #list of tickets to generate the depgraph for tkt_ids = [] milestone = None split_path = path_info.split('/', 2) #Urls to generate the depgraph for a ticket is /depgraph/ticketnum #Urls to generate the depgraph for a milestone is /depgraph/milestone/milestone_name if split_path[0] == 'milestone': #we need to query the list of tickets in the milestone milestone = split_path[1] query = Query(self.env, constraints={'milestone': [milestone]}, max=0) tkt_ids = [fields['id'] for fields in query.execute()] else: #the list is a single ticket tkt_ids = [int(split_path[0])] #the summary argument defines whether we place the ticket id or #it's summary in the node's label label_summary = 0 if 'summary' in req.args: label_summary = int(req.args.get('summary')) g = self._build_graph(req, tkt_ids, label_summary=label_summary) if path_info.endswith('/depgraph.png') or 'format' in req.args: format = req.args.get('format') if format == 'text': #in case g.__str__ returns unicode, we need to convert it in ascii req.send( to_unicode(g).encode('ascii', 'replace'), 'text/plain') elif format == 'debug': import pprint req.send( pprint.pformat( [TicketLinks(self.env, tkt_id) for tkt_id in tkt_ids]), 'text/plain') elif format is not None: req.send(g.render(self.dot_path, format), 'text/plain') if self.use_gs: ps = g.render(self.dot_path, 'ps2') gs = subprocess.Popen([ self.gs_path, '-q', '-dTextAlphaBits=4', '-dGraphicsAlphaBits=4', '-sDEVICE=png16m', '-sOutputFile=%stdout%', '-' ], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) img, err = gs.communicate(ps) if err: self.log.debug('MasterTickets: Error from gs: %s', err) else: img = g.render(self.dot_path) req.send(img, 'image/png') else: data = {} #add a context link to enable/disable labels in nodes if label_summary: add_ctxtnav(req, 'Without labels', req.href(req.path_info, summary=0)) else: add_ctxtnav(req, 'With labels', req.href(req.path_info, summary=1)) if milestone is None: tkt = Ticket(self.env, tkt_ids[0]) data['tkt'] = tkt add_ctxtnav(req, 'Back to Ticket #%s' % tkt.id, req.href.ticket(tkt.id)) else: add_ctxtnav(req, 'Back to Milestone %s' % milestone, req.href.milestone(milestone)) data['milestone'] = milestone data['graph'] = g data['graph_render'] = partial(g.render, self.dot_path) data['use_gs'] = self.use_gs return 'depgraph.html', data, None
def process_timeline(self, req): """/hours view""" if 'update' in req.args: # Reset session vars for var in ('query_constraints', 'query_time', 'query_tickets'): if var in req.session: del req.session[var] if self.process_query(req): """the user has clicked on the 'Save Query' button; redirect them""" return ### lifted from trac.ticket.query.QueryModule.process_request req.perm.assert_permission('TICKET_VIEW') constraints = self._get_constraints(req) if not constraints and not 'order' in req.args: # If no constraints are given in the URL, use the default ones. if req.authname and req.authname != 'anonymous': qstring = 'status!=bogus' user = req.authname else: email = req.session.get('email') name = req.session.get('name') qstring = 'status!=bogus' user = email or name or None if user: qstring = qstring.replace('$USER', user) self.log.debug('QueryModule: Using default query: %s', str(qstring)) constraints = Query.from_string(self.env, qstring).constraints # Ensure no field constraints that depend on $USER are used # if we have no username. for constraint_set in constraints: for field, vals in constraint_set.items(): for val in vals: if val.endswith('$USER'): del constraint_set[field] cols = req.args.get('col') if isinstance(cols, basestring): cols = [cols] if not cols: cols = ['id', 'summary'] + self.get_default_columns() # Since we don't show 'id' as an option to the user, # we need to re-insert it here. if cols and 'id' not in cols: cols.insert(0, 'id') rows = req.args.get('row', []) if isinstance(rows, basestring): rows = [rows] format = req.args.get('format') max = 0 # unlimited number of tickets # compute estimated hours even if not selected for columns rm_est_hours = False if not 'estimatedhours' in cols: cols.append('estimatedhours') rm_est_hours = True query = Query(self.env, req.args.get('report'), constraints, cols, req.args.get('order'), 'desc' in req.args, req.args.get('group'), 'groupdesc' in req.args, 'verbose' in req.args, rows, req.args.get('page'), max) if rm_est_hours: # if not in the columns, remove estimatedhours cols.pop() return self.display_html(req, query)