Edgewall Software

Ticket #10178: 10178-multi-column-order-r10691.patch

File 10178-multi-column-order-r10691.patch, 7.0 KB (added by Remy Blank, 6 years ago)

Fixed and simplified.

  • trac/ticket/query.py

    diff --git a/trac/ticket/query.py b/trac/ticket/query.py
    a b class Query(object):  
    7474            constraints = [constraints]
    7575        self.constraints = constraints
    7676        synonyms = TicketSystem(self.env).get_field_synonyms()
    77         self.order = synonyms.get(order, order)     # 0.11 compatibility
    78         self.desc = desc
     77        if not isinstance(order, list):
     78            order = [order] if order is not None else []
     79        order = [synonyms.get(o, o) for o in order] # 0.11 compatibility
     80        if not isinstance(desc, list):
     81            desc = [desc] if desc is not None else []
     82        if len(order) > len(desc):
     83            desc += [0] * (len(order) - len(desc))
    7984        self.group = group
    8085        self.groupdesc = groupdesc
    8186        self.format = format
    class Query(object):  
    125130        self.cols = [c for c in cols or [] if c in field_names or
    126131                     c == 'id']
    127132        self.rows = [c for c in rows if c in field_names]
    128         if self.order != 'id' and self.order not in field_names:
    129             self.order = 'priority'
     133        order_desc = [(o, d) for o, d in zip(order, desc)
     134                      if o in field_names or o == 'id']
     135        if not order_desc:
     136            order_desc = [('priority', desc[0] if desc else 0)]
     137        self.order = [o for o, d in order_desc]
     138        self.desc = [d for o, d in order_desc]
    130139
    131140        if self.group not in field_names:
    132141            self.group = None
    class Query(object):  
    142151   
    143152    @classmethod
    144153    def from_string(cls, env, string, **kw):
    145         kw_strs = ['order', 'group', 'page', 'max', 'format']
    146         kw_arys = ['rows']
    147         kw_bools = ['desc', 'groupdesc', 'verbose']
     154        kw_strs = ['group', 'page', 'max', 'format']
     155        kw_bools = ['groupdesc', 'verbose']
     156        kw_arys_str = ['order', 'rows']
     157        kw_arys_bool = ['desc']
    148158        kw_synonyms = {'row': 'rows'}
    149159        # i18n TODO - keys will be unicode
    150160        synonyms = TicketSystem(env).get_field_synonyms()
    class Query(object):  
    181191                                for val in cls._item_splitter.split(values)]
    182192            if field in kw_strs:
    183193                kw[as_str(field)] = processed_values[0]
    184             elif field in kw_arys:
     194            elif field in kw_arys_str:
    185195                kw.setdefault(as_str(field), []).extend(processed_values)
     196            elif field in kw_arys_bool:
     197                kw.setdefault(as_str(field), []).extend(
     198                    as_bool(v) for v in processed_values)
    186199            elif field in kw_bools:
    187200                kw[as_str(field)] = as_bool(processed_values[0])
    188201            elif field == 'col':
    class Query(object):  
    258271
    259272        # Only display the first seven columns by default
    260273        cols = cols[:7]
    261         # Make sure the column we order by is visible, if it isn't also
    262         # the column we group by
    263         if not self.order in cols and not self.order == self.group:
    264             cols[-1] = self.order
     274        # Make sure the columns we order by are visible, if they don't also
     275        # overlap the column we group by
     276        if set(self.order) - set(cols) - set([self.group]):
     277            del cols[-1]
     278            for col in self.order:
     279                if col not in cols and col != self.group:
     280                    cols.append(col)
    265281        return cols
    266282
    267283    def count(self, req=None, db=None, cached_ids=None, authname=None,
    class Query(object):  
    372388            id = self.id
    373389        if desc is None:
    374390            desc = self.desc
     391        elif not isinstance(desc, list):
     392            desc = [desc]
    375393        if order is None:
    376394            order = self.order
    377395        if max is None:
    class Query(object):  
    399417       
    400418        return href.query(constraints,
    401419                          report=id,
    402                           order=order, desc=1 if desc else None,
     420                          order=order, desc=[d or None for d in desc],
    403421                          group=self.group or None,
    404422                          groupdesc=1 if self.groupdesc else None,
    405423                          col=cols,
    class Query(object):  
    439457            add_cols(self.group)
    440458        if self.rows:
    441459            add_cols('reporter', *self.rows)
    442         add_cols('status', 'priority', 'time', 'changetime', self.order)
     460        add_cols('status', 'priority', 'time', 'changetime', *self.order)
    443461        cols.extend([c for c in self.constraint_cols if not c in cols])
    444462
    445463        custom_fields = [f['name'] for f in self.fields if f.get('custom')]
    class Query(object):  
    460478
    461479        # Join with the enum table for proper sorting
    462480        for col in [c for c in enum_columns
    463                     if c == self.order or c == self.group or c == 'priority']:
     481                    if c in self.order or c == self.group or c == 'priority']:
    464482            sql.append("\n  LEFT OUTER JOIN enum AS %s ON "
    465483                       "(%s.type='%s' AND %s.name=%s)"
    466484                       % (col, col, col, col, col))
    467485
    468486        # Join with the version/milestone tables for proper sorting
    469487        for col in [c for c in ['milestone', 'version']
    470                     if c == self.order or c == self.group]:
     488                    if c in self.order or c == self.group]:
    471489            sql.append("\n  LEFT OUTER JOIN %s ON (%s.name=%s)"
    472490                       % (col, col, col))
    473491
    class Query(object):  
    618636                           (','.join([str(id) for id in cached_ids])))
    619637           
    620638        sql.append("\nORDER BY ")
    621         order_cols = [(self.order, self.desc)]
    622         if self.group and self.group != self.order:
     639        order_cols = [(col, dsc) for col, dsc in zip(self.order, self.desc)]
     640        if self.group and self.group not in self.order:
    623641            order_cols.insert(0, (self.group, self.groupdesc))
    624642
    625         for name, desc in order_cols:
     643        for i, (name, desc) in enumerate(order_cols):
    626644            if name in enum_columns:
    627645                col = name + '.value'
    628646            elif name in custom_fields:
    class Query(object):  
    650668                           % (desc, desc, col, desc))
    651669            else:
    652670                sql.append("%s%s" % (col, desc))
    653             if name == self.group and not name == self.order:
     671            if i < len(order_cols) - 1:
    654672                sql.append(",")
    655         if self.order != 'id':
     673        if 'id' not in self.order:
    656674            sql.append(",t.id") 
    657675
    658676        if errors:
    class Query(object):  
    713731            'name': col, 'label': labels.get(col, _('Ticket')),
    714732            'wikify': col in wikify,
    715733            'href': self.get_href(context.href, order=col,
    716                                   desc=(col == self.order and not self.desc))
     734                                  desc=(col in self.order and
     735                                        not self.desc[self.order.index(col)]))
    717736        } for col in cols]
    718737
    719738        fields = {'id': {'type': 'id', 'label': _("Ticket")}}