Edgewall Software

Ticket #919: category.1048.patch

File category.1048.patch, 13.9 kB (added by cboos@…, 4 years ago)

patch that implements the proposed feature

  • htdocs/css/ticket.css

    === htdocs/css/ticket.css
    ==================================================================
     
    2121#ticket th { color: #996; font-weight: normal; text-align: left } 
    2222#ticket hr { color: #dd9; border-color: #dd9; border-width: 1px 0 0; height: 1px; margin: .5em 0 0 } 
    2323 
     24#ticket .category { font-size: 200% }  
     25 
    2426#attachments { border: 1px outset #996; padding: 1em } 
    2527#attachments .attachments { list-style: square; margin-left: 2em; padding: 0 } 
    2628 
  • scripts/trac-admin

    === scripts/trac-admin
    ==================================================================
     
    706706                self._do_wiki_import(filename, page, cursor) 
    707707 
    708708 
     709    ## (Ticket) Category 
     710    _help_category = [('category list', 'Show possible ticket categories'), 
     711                       ('category add <value>', 'Add a category value option'), 
     712                       ('category change <value> <newvalue>', 
     713                        'Change a category value'), 
     714                       ('category remove <value>', 'Remove category value')] 
     715 
     716    def complete_category (self, text, line, begidx, endidx): 
     717        if begidx == 16: 
     718            comp = self.get_enum_list ('category') 
     719        elif begidx < 15: 
     720            comp = ['list','add','change','remove'] 
     721        return self.word_complete(text, comp) 
     722 
     723    def do_category(self, line): 
     724        self._do_enum('category', line) 
     725 
    709726    ## (Ticket) Priority 
    710727    _help_priority = [('priority list', 'Show possible ticket priorities'), 
    711728                       ('priority add <value>', 'Add a priority value option'), 
  • templates/newticket.cs

    === templates/newticket.cs
    ==================================================================
     
    99 
    1010<div id="content" class="ticket"> 
    1111 
    12 <h3>Create New Ticket:</h3> 
    1312<form id="newticket" action="<?cs var:cgi_location ?>#preview" method="post"> 
     13 <h3>Create New Ticket of <label for="category">category:</label><?cs 
     14  call:hdf_select(enums.category, "category", newticket.category) ?> 
     15 </h3> 
    1416 <div class="field"> 
    1517  <label for="reporter">Your email or username:</label><br /> 
    1618  <input type="text" id="reporter" name="reporter" size="40" value="<?cs 
  • templates/query.cs

    === templates/query.cs
    ==================================================================
     
    22<?cs include:"header.cs" ?> 
    33<?cs include:"macros.cs" ?> 
    44 
    5 <div id="ctxtnav" class="nav"><?cs if:query.edit_href ?> 
    6  <ul> 
    7   <li class="last"><a href="<?cs var:query.edit_href ?>">Refine Query</a></li> 
     5<div id="ctxtnav" class="nav"> 
     6 <ul><?cs  
     7  if:query.edit_href ?> 
     8   <li class="last"><a href="<?cs var:query.edit_href ?>">Refine Query</a></li><?cs  
     9  /if ?><?cs  
     10  if:query.clear_href ?> 
     11   <li class="last"><a href="<?cs var:query.clear_href ?>">Clear Query</a></li><?cs  
     12  /if ?> 
    813 </ul> 
    9 <?cs /if ?></div> 
     14</div> 
    1015 
    1116<div id="content" class="query"> 
    1217 <h1><?cs var:title ?></h1> 
     
    2025  <?cs if:query.desc ?><input type="hidden" name="desc" value="1" /><?cs /if ?> 
    2126  <legend>Ticket Properties</legend> 
    2227  <div> 
     28   <label for="category" accesskey="t">Category:</label> 
     29   <?cs call:hdf_select_multiple(query.options.category, 'category', 4) ?> 
     30  </div> 
     31  <div> 
    2332   <label for="component" accesskey="c">Component:</label> 
    2433   <?cs call:hdf_select_multiple(query.options.component, 'component', 4) ?> 
    2534  </div> 
     
    112121 /if ?> matched this query.</p> 
    113122 <table id="tktlist" class="listing"> 
    114123  <thead><tr><?cs each:header = query.headers ?><?cs 
    115    if:name(header) == 0 ?><th class="ticket<?cs 
     124   if:header.name == 'id' ?><th class="ticket<?cs 
    116125    if:header.order ?> <?cs var:header.order ?><?cs /if ?>"> 
    117126    <a href="<?cs var:header.href ?>" title="Sort by ID (<?cs 
    118127      if:header.order == 'asc' ?>descending<?cs 
     
    131140     if:name(result) % 2 ?>odd<?cs else ?>even<?cs /if ?> <?cs 
    132141     var:result.priority ?>"> 
    133142    <?cs each:header = query.headers ?><?cs 
    134      if:name(header) == 0 ?> 
    135       <td class="ticket"><a href="<?cs var:result.href ?>" title="View ticket"><?cs 
     143     if:header.name == 'id' ?> 
     144      <td class="ticket"><a href="<?cs var:result.href ?>" title="View ticket">#<?cs 
    136145        var:result.id ?></a></td><?cs 
    137146     else ?> 
    138147      <td><?cs if:header.name == 'summary' ?> 
  • templates/ticket.cs

    === templates/ticket.cs
    ==================================================================
     
    3232 
    3333<div id="ticket"> 
    3434 <div class="date"><?cs var:ticket.opened ?></div> 
    35  <h1>Ticket #<?cs var:ticket.id ?> <?cs 
     35 <h1><?cs var:ticket.category ?> Ticket #<?cs var:ticket.id ?> <?cs 
    3636 if:ticket.status == 'closed' ?>(Closed: <?cs var:ticket.resolution ?>)<?cs 
    3737 elif:ticket.status != 'new' ?>(<?cs var:ticket.status ?>)<?cs 
    3838 /if ?></h1> 
     
    166166     var:ticket.summary ?>" /><?cs 
    167167   if $trac.acl.TICKET_ADMIN ?> 
    168168    <br /> 
     169    <label for="category">Category:</label><?cs 
     170    call:hdf_select(enums.category, "category", ticket.category) ?> 
     171    <br /> 
    169172    <label for="description">Description:</label> 
    170173    <div style="float: left"> 
    171174     <textarea id="description" name="description" rows="10" cols="68"><?cs 
  • trac/Query.py

    === trac/Query.py
    ==================================================================
     
    5959            results.append({ 
    6060                'id': id, 
    6161                'href': self.env.href.ticket(id), 
     62                'category': row['category'], 
    6263                'summary': util.escape(row['summary'] or '(no summary)'), 
    6364                'status': row['status'] or '', 
    6465                'component': row['component'] or '', 
     
    7879        if self.args.has_key('search'): 
    7980            self.req.redirect(self.env.href.query(constraints, order, desc, 
    8081                                                  action='view')) 
     82        if self.args.has_key('clear'): 
     83            self.req.redirect(self.env.href.query()) 
    8184 
    8285        action = self.args.get('action') 
    8386        if not action and not constraints: 
     
    9194 
    9295    def _render_editor(self, constraints, order, desc): 
    9396        self.req.hdf.setValue('title', 'Custom Query') 
     97        self.req.hdf.setValue('query.clear_href', self.env.href.query(action='edit')) 
    9498        util.add_to_hdf(constraints, self.req.hdf, 'query.constraints') 
    9599        self.req.hdf.setValue('query.order', order) 
    96100        if desc: self.req.hdf.setValue('query.desc', '1') 
     
    112116                del constraints[field] 
    113117 
    114118        cursor = self.db.cursor() 
     119        add_options('category', constraints, 'query.options.', cursor, 
     120                    "SELECT name FROM enum WHERE type='category' ORDER BY value") 
    115121        add_options('status', constraints, 'query.options.', cursor, 
    116122                    "SELECT name FROM enum WHERE type='status' ORDER BY value") 
    117123        add_options('resolution', constraints, 'query.options.', cursor, 
     
    146152 
    147153        # FIXME: the user should be able to configure which columns should 
    148154        # be displayed 
    149         headers = [ 'id', 'summary', 'status', 'component', 'owner' ] 
     155        headers = [ 'category', 'id', 'summary', 'status', 'component', 'owner' ] 
    150156        cols = headers 
    151157        if not 'priority' in cols: 
    152158            cols.append('priority') 
     
    176182                      "(id=%s.ticket AND %s.name='%s')" 
    177183                      % (k, k, k, k)) 
    178184 
    179         for col in [c for c in ['status', 'resolution', 'priority', 'severity'] 
     185        for col in [c for c in ['category', 'status', 'resolution', 'priority', 'severity'] 
    180186                    if c in cols]: 
    181187            sql.append(" INNER JOIN (SELECT name AS %s_name, value AS %s_value " \ 
    182188                                   "FROM enum WHERE type='%s')" \ 
     
    194200        if clauses: 
    195201            sql.append(" WHERE " + " AND ".join(clauses)) 
    196202 
    197         if order in ['status', 'resolution', 'priority', 'severity']: 
     203        if order in ['category', 'status', 'resolution', 'priority', 'severity']: 
    198204            sql.append(" ORDER BY %s_value" % order) 
    199205        else: 
    200206            sql.append(" ORDER BY " + order) 
  • trac/Ticket.py

    === trac/Ticket.py
    ==================================================================
     
    3737class Ticket(UserDict): 
    3838    std_fields = ['time', 'component', 'severity', 'priority', 'milestone', 
    3939                  'reporter', 'owner', 'cc', 'url', 'version', 'status', 'resolution', 
    40                   'keywords', 'summary', 'description'] 
     40                  'keywords', 'summary', 'description', 'category'] 
    4141 
    4242    def __init__(self, *args): 
    4343        UserDict.__init__(self) 
     
    303303                          self.env.get_config('ticket', 'default_component')) 
    304304        ticket.setdefault('milestone', 
    305305                          self.env.get_config('ticket', 'default_milestone')) 
     306        ticket.setdefault('category', 
     307                          self.env.get_config('ticket', 'default_category')) 
    306308        ticket.setdefault('priority', 
    307309                          self.env.get_config('ticket', 'default_priority')) 
    308310        ticket.setdefault('severity', 
     
    393395        util.hdf_add_if_missing(self.req.hdf, 'ticket.components', ticket['component']) 
    394396        util.hdf_add_if_missing(self.req.hdf, 'ticket.milestones', ticket['milestone']) 
    395397        util.hdf_add_if_missing(self.req.hdf, 'ticket.versions', ticket['version']) 
     398        util.hdf_add_if_missing(self.req.hdf, 'enums.category', ticket['category']) 
    396399        util.hdf_add_if_missing(self.req.hdf, 'enums.priority', ticket['priority']) 
    397400        util.hdf_add_if_missing(self.req.hdf, 'enums.severity', ticket['severity']) 
    398401        util.hdf_add_if_missing(self.req.hdf, 'enums.resolution', 'fixed') 
  • trac/core.py

    === trac/core.py
    ==================================================================
     
    199199    pass 
    200200 
    201201def populate_hdf(hdf, env, db, req): 
     202    sql_to_hdf(db, "SELECT name FROM enum WHERE type='category' " 
     203               "ORDER BY value", hdf, 'enums.category') 
    202204    sql_to_hdf(db, "SELECT name FROM enum WHERE type='priority' " 
    203205               "ORDER BY value", hdf, 'enums.priority') 
    204206    sql_to_hdf(db, "SELECT name FROM enum WHERE type='severity' " 
  • trac/db_default.py

    === trac/db_default.py
    ==================================================================
     
    2121 
    2222 
    2323# Database version identifier. Used for automatic upgrades. 
    24 db_version = 7 
     24db_version = 8 
    2525 
    2626def __mkreports(reps): 
    2727    """Utility function used to create report data in same syntax as the 
  • trac/Timeline.py

    === trac/Timeline.py
    ==================================================================
     
    5656        q = [] 
    5757        if changeset: 
    5858            q.append("SELECT time, rev AS idata, '' AS tdata, 1 AS type, " 
    59                      " message, author " 
     59                     " message, author, '' AS category " 
    6060                     "FROM revision WHERE time>=%s AND time<=%s" % 
    6161                     (start, stop)) 
    6262        if tickets: 
    6363            q.append("SELECT time, id AS idata, '' AS tdata, 2 AS type, " 
    64                      "summary AS message, reporter AS author " 
     64                     " summary AS message, reporter AS author, category " 
    6565                     "FROM ticket WHERE time>=%s AND time<=%s" % 
    6666                     (start, stop)) 
    67             q.append("SELECT time, ticket AS idata, '' AS tdata, 4 AS type, " 
    68                      "'' AS message, author " 
    69                      "FROM ticket_change WHERE field='status' " 
    70                      "AND newvalue='reopened' AND time>=%s AND time<=%s" % 
     67            q.append("SELECT t1.time, t1.ticket AS idata, '' AS tdata, 4 AS type, " 
     68                     " '' AS message, t1.author, t0.category AS category " 
     69                     "FROM ticket_change t1 " 
     70                     " LEFT JOIN ticket t0 ON t0.id = t1.ticket " 
     71                     "WHERE t1.field='status' " 
     72                     "AND t1.newvalue='reopened' AND t1.time>=%s AND t1.time<=%s" % 
    7173                     (start, stop)) 
    7274            q.append("SELECT t1.time AS time, t1.ticket AS idata," 
    7375                     "       t2.newvalue AS tdata, 3 AS type," 
    74                      "       t3.newvalue AS message, t1.author AS author" 
     76                     "       t3.newvalue AS message, t1.author AS author, t0.category AS category" 
    7577                     " FROM ticket_change t1" 
     78                     "   LEFT JOIN ticket t0 ON t0.id = t1.ticket" 
    7679                     "   INNER JOIN ticket_change t2 ON t1.ticket = t2.ticket" 
    7780                     "     AND t1.time = t2.time" 
    7881                     "   LEFT OUTER JOIN ticket_change t3 ON t1.time = t3.time" 
     
    8285                     "   AND t1.time >= %s AND t1.time <= %s" % (start,stop)) 
    8386        if wiki: 
    8487            q.append("SELECT time, -1 AS idata, name AS tdata, 5 AS type, " 
    85                      "comment AS message, author " 
     88                     "comment AS message, author, '' AS category " 
    8689                        "FROM wiki WHERE time>=%s AND time<=%s" % 
    8790                     (start, stop)) 
    8891        if milestone: 
    8992            q.append("SELECT time, -1 AS idata, '' AS tdata, 6 AS type, " 
    90                      "name AS message, '' AS author "  
     93                     "name AS message, '' AS author, '' AS category "  
    9194                     "FROM milestone WHERE time>=%s AND time<=%s" % 
    9295                     (start, stop)) 
    9396 
     
    113116                    'tdata': row['tdata'], 
    114117                    'type': int(row['type']), 
    115118                    'message': row['message'] or '', 
     119                    'category': row['category'], 
    116120                    'author': util.escape(row['author'] or 'anonymous') 
    117121                    } 
    118122