Edgewall Software

Ticket #7026: query_column_reorder2_6737.diff

File query_column_reorder2_6737.diff, 14.4 kB (added by ebray <hyugaricdeau@…>, 6 months ago)

Simplified patch without modifying url query strings.

  • trac/ticket/web_ui.py

     
    7272    default_priority = Option('ticket', 'default_priority', 'major', 
    7373        """Default priority for newly created tickets.""") 
    7474 
     75    default_resolution = Option('ticket', 'default_resolution', 'fixed', 
     76        """Default resolution when closing tickets.""") 
     77 
    7578    default_milestone = Option('ticket', 'default_milestone', '', 
    7679        """Default milestone for newly created tickets.""") 
    7780 
  • trac/ticket/default_workflow.py

     
    263263                             resolutions[0]) 
    264264            else: 
    265265                id = action + '_resolve_resolution' 
     266<<<<<<< .mine 
     267                default = self.config.get('ticket', 'default_resolution') 
     268                selected_option = req.args.get(id, default) 
     269======= 
    266270                selected_option = req.args.get(id, 
    267271                        self.config.get('ticket', 'default_resolution')) 
     272>>>>>>> .r6363 
    268273                control.append(tag(['as ', tag.select( 
    269274                    [tag.option(x, selected=(x == selected_option or None)) 
    270275                     for x in resolutions], 
  • trac/ticket/model.py

     
    6262    def _init_defaults(self, db=None): 
    6363        for field in self.fields: 
    6464            default = None 
     65<<<<<<< .mine 
     66            field_name = field['name'] 
     67            if not field.get('custom'): 
     68======= 
    6569            if field['name'] in ['resolution', 'status']: 
    6670                # Ignore for new - only change through workflow 
    6771                pass 
    6872            elif not field.get('custom'): 
    69                 default = self.env.config.get('ticket', 
    70                                               'default_' + field['name']) 
     73>>>>>>> .r6363 
     74                if field_name != 'resolution': 
     75                    default = self.env.config.get('ticket', 
     76                                                  'default_' + field_name) 
    7177            else: 
    7278                default = field.get('value') 
    7379                options = field.get('options') 
     
    7783                    except (ValueError, IndexError): 
    7884                        self.env.log.warning('Invalid default value "%s" ' 
    7985                                             'for custom field "%s"' 
    80                                              % (default, field['name'])) 
     86                                             % (default, field_name)) 
    8187            if default: 
    82                 self.values.setdefault(field['name'], default) 
     88                self.values.setdefault(field_name, default) 
    8389 
    8490    def _fetch_ticket(self, tkt_id, db=None): 
    8591        db = self._get_db(db) 
  • trac/ticket/query.py

     
    4141                            INavigationContributor, Chrome 
    4242from trac.wiki.api import IWikiSyntaxProvider, parse_args 
    4343from trac.wiki.macros import WikiMacroBase # TODO: should be moved in .api 
    44 from trac.config import Option  
     44from trac.config import Option 
    4545 
    4646class QuerySyntaxError(Exception): 
    4747    """Exception raised when a ticket query cannot be parsed from a string.""" 
     
    9494        for filter_ in filters: 
    9595            filter_ = filter_.split('=') 
    9696            if len(filter_) != 2: 
    97                 raise QuerySyntaxError('Query filter requires field and '  
     97                raise QuerySyntaxError('Query filter requires field and ' 
    9898                                       'constraints separated by a "="') 
    9999            field,values = filter_ 
    100100            if not field: 
     
    254254        # shorter in the common case where we just want the default columns. 
    255255        if cols == self.get_default_columns(): 
    256256            cols = None 
     257                                for idx, col in enumerate(cols))) 
    257258        return href.query(report=id, 
    258259                          order=order, desc=desc and 1 or None, 
    259260                          group=self.group or None, 
     
    637638                      rows, 
    638639                      req.args.get('limit')) 
    639640 
     641        if cols: 
     642            for idx, col in enumerate(cols): 
     643                if 'up_' + col in req.args: 
     644                    query.cols[idx] = cols[idx-1] 
     645                    query.cols[idx-1] = col 
     646                    req.redirect(query.get_href(req.href)) 
     647                elif 'down_' + col in req.args: 
     648                    query.cols[idx] = cols[idx+1] 
     649                    query.cols[idx+1] = col 
     650                    req.redirect(query.get_href(req.href)) 
     651 
    640652        if 'update' in req.args: 
    641653            # Reset session vars 
    642654            for var in ('query_constraints', 'query_time', 'query_tickets'): 
     
    779791        data.setdefault('description', None) 
    780792        data['title'] = title 
    781793 
    782         data['all_columns'] = query.get_all_columns() 
     794        all_columns = query.get_all_columns() 
     795        all_columns.sort(key=lambda x: (not x in query.cols, 
     796                                        x in query.cols and  
     797                                        query_cols.index(x))) 
    783798        # Don't allow the user to remove the id column         
    784         data['all_columns'].remove('id') 
     799        all_columns.remove('id') 
     800        data['all_columns'] = all_columns 
    785801        data['all_textareas'] = query.get_all_textareas() 
    786802 
    787803        add_stylesheet(req, 'common/css/report.css') 
  • trac/ticket/templates/query.html

     
    136136        <fieldset id="columns"> 
    137137          <legend>Columns</legend> 
    138138          <div> 
    139             <py:for each="column in all_columns"> 
    140               <label> 
    141                 <input type="checkbox" name="col" value="$column" 
    142                        checked="${any([(value == column) for value in col]) 
    143                                   and 'checked' or None}" /> 
    144                 ${labels.get(column, column or 'none')} 
    145               </label> 
    146             </py:for> 
     139            <table> 
     140              <tbody> 
     141                <tr py:for="idx, column in enumerate(all_columns)"> 
     142                  <td> 
     143                    <input type="checkbox" name="col" value="$column" 
     144                           checked="${any([(value == column) for value in col]) 
     145                                      and 'selected' or None}" /> 
     146                  </td> 
     147                  <td>${labels.get(column, column or 'none')}</td> 
     148                  <td> 
     149                    <input type="submit" name="up_${column}" value="Up" 
     150                           disabled="${not idx or None}" />&nbsp; 
     151                    <input type="submit" name="down_${column}" value="Down" 
     152                           disabled="${idx == len(all_columns)-1 or None}" /> 
     153                  </td> 
     154                </tr> 
     155              </tbody> 
     156            </table> 
    147157          </div> 
    148158        </fieldset> 
    149159 
  • trac/htdocs/js/query.js

     
    273273      } 
    274274      select.selectedIndex = 0; 
    275275    } 
     276 
     277    $("input[@name^='up_']").click(function() { 
     278      var row = $(this).parents('tr'); 
     279      if (row.prev().length) { 
     280        var prev = row.prev(); 
     281        if (!row.next().length) { 
     282          prev.find("input[@name^='down_']").attr("disabled", true); 
     283        } 
     284        prev.find("input[@name^='up_']").attr("disabled", false); 
     285        row.insertBefore(row.prev()); 
     286        if (!row.prev().length) { 
     287          $(this).attr("disabled", true); 
     288        } 
     289        row.find("input[@name^='down_']").attr("disabled", false); 
     290      } 
     291      return false; 
     292    }); 
     293    $("input[@name^='down_']").click(function() { 
     294      var row = $(this).parents('tr'); 
     295      if (row.next().length) { 
     296        var next = row.next(); 
     297        if (!row.prev().length) { 
     298          next.find("input[@name^='up_']").attr("disabled", true); 
     299        } 
     300        next.find("input[@name^='down_']").attr("disabled", false); 
     301        row.insertAfter(row.next()); 
     302        if (!row.next().length) { 
     303          $(this).attr("disabled", true); 
     304        } 
     305        row.find("input[@name^='up_']").attr("disabled", false); 
     306      } 
     307      return false; 
     308    }); 
    276309  } 
    277  
    278 })(jQuery); 
    279  No newline at end of file 
     310})(jQuery); 
  • trac/htdocs/js/expand_dir.js

     
    11// Enable expanding/folding folders in TracBrowser 
    22 
     3<<<<<<< .mine 
     4var FOLDERID_COUNTER = 0; 
     5var SUBFOLDER_INDENT = 20; 
     6 
     7// enableExpandDir adds the capability to folder rows to be expanded and folded 
     8// It also teach the rows about their ancestors. It expects: 
     9//  - `parent_tr`, the logical parent row (`null` if there's no ancestor) 
     10//  - a `rows` jQuery object matching the newly created entry rows 
     11//  - `qargs`, additional parameters to send to the server when expanding 
     12 
     13function enableExpandDir(parent_tr, rows, qargs) { 
     14  // the ancestors folder ids are present in the parent_tr class attribute 
     15  var ancestor_folderids = []; 
     16  if (parent_tr) 
     17    ancestor_folderids = $.grep(parent_tr.attr("class").split(" "),  
     18                                function(c) { return c.match(/^f\d+$/)}); 
     19  var space = ($.browser.msie && $.browser.version == "6.0" ? "&nbsp;" : 
     20                                                              "&#x200b;"); 
     21  rows.each(function () { 
     22    var a = $(this).find("a.dir"); 
     23 
     24    if (a.length) { // then the entry is a folder 
     25      // create new folder id 
     26      var folderid = "f" + FOLDERID_COUNTER++; 
     27      this.id = folderid; 
     28      $(this).addClass(folderid); 
     29 
     30      // add the expander icon 
     31      a.wrap('<div></div>'); 
     32<<<<<<< .mine 
     33      var expander = a.before('<span class="expander">' + space + 
     34                              '</span>').prev(); 
     35======= 
     36      var expander = a.before('<span class="expander">&nbsp;</span>').prev(); 
     37>>>>>>> .r6391 
     38      expander.attr("title", "Expand sub-directory in place") 
     39        .click(function() { toggleDir($(this), qargs); }); 
     40    } 
     41 
     42    // tie that row to ancestor folders 
     43======= 
    344(function($){ 
    445  var FOLDERID_COUNTER = 0; 
    546  var SUBFOLDER_INDENT = 20; 
     
    1354  window.enableExpandDir = function(parent_tr, rows, qargs) { 
    1455    // the ancestors folder ids are present in the parent_tr class attribute 
    1556    var ancestor_folderids = []; 
     57>>>>>>> .r6737 
    1658    if (parent_tr) 
    1759      ancestor_folderids = $.grep(parent_tr.attr("class").split(" "),  
    1860                                  function(c) { return c.match(/^f\d+$/)}); 
  • trac/htdocs/css/report.css

     
    4141#filters td.filter label { padding-right: 1em } 
    4242#filters td.actions { text-align: right; white-space: nowrap } 
    4343 
     44#columns div { 
     45 height: 15em; 
     46 overflow: -moz-scrollbars-vertical; 
     47 overflow-x: hidden; 
     48 overflow-y: scroll; 
     49} 
     50 
    4451#columns div label {  
    4552 display: block; 
    4653 float: left; 
  • trac/wiki/web_ui.py

     
    4343from trac.wiki.formatter import format_to_oneliner 
    4444from trac.wiki.model import WikiPage 
    4545 
    46 class InvalidWikiPage(TracError): 
    47     """Exception raised when a Wiki page fails validation.""" 
    48  
    49  
    5046class WikiModule(Component): 
    5147 
    5248    implements(IContentConverter, INavigationContributor, IPermissionRequestor, 
     
    131127                    if a in req.args: 
    132128                        action = a 
    133129                        break 
    134                 if action == 'edit' and not has_collision: 
     130                valid = self._validate(context) 
     131                if action == 'edit' and not has_collision and valid: 
    135132                    self._do_save(req, versioned_page) 
    136133                else: 
    137134                    return self._render_editor(req, page, action, has_collision) 
     
    167164 
    168165    # Internal methods 
    169166 
     167<<<<<<< .mine 
     168    def _validate(self, context): 
     169        req = context.req 
     170        page = context.resource 
     171         
     172        valid = True 
     173        # Give the manipulators a pass at post-processing the page 
     174        for manipulator in self.page_manipulators: 
     175            for field, message in manipulator.validate_wiki_page(req, page): 
     176                valid = False 
     177                if field: 
     178                    req.warning(_("The Wiki page field '%(field)s' is " 
     179                                  "invalid: %(message)s", 
     180                                  field=field, message=message)) 
     181                else: 
     182                    req.warning(_("Invalid Wiki page: %(message)s", 
     183                                  message=message)) 
     184        return valid 
     185 
     186    def _page_data(self, context, action=''): 
     187        page_name = context.name() 
     188        title = context.summary() 
     189======= 
    170190    def _page_data(self, req, page, action=''): 
    171191        title = get_resource_summary(self.env, page.resource) 
     192>>>>>>> .r6363 
    172193        if action: 
    173194            title += ' (%s)' % action 
    174195        return {'page': page, 'action': action, 'title': title} 
     
    240261            # WIKI_ADMIN 
    241262            page.readonly = int('readonly' in req.args) 
    242263 
    243         # Give the manipulators a pass at post-processing the page 
    244         for manipulator in self.page_manipulators: 
    245             for field, message in manipulator.validate_wiki_page(req, page): 
    246                 if field: 
    247                     raise InvalidWikiPage(_("The Wiki page field '%(field)s' " 
    248                                             "is invalid: %(message)s", 
    249                                             field=field, message=message)) 
    250                 else: 
    251                     raise InvalidWikiPage(_("Invalid Wiki page: %(message)s", 
    252                                             message=message)) 
    253  
    254264        try: 
    255265            page.save(get_reporter_id(req, 'author'), 
    256266                            req.args.get('comment'),