Edgewall Software

Ticket #7026: query_column_reorder3-r7181.diff

File query_column_reorder3-r7181.diff, 9.4 kB (added by ebray <hyugaricdeau@…>, 3 months ago)

An updated version of this patch with a somewhat improved implementation. The UI for adding and removing columns is now more similar to the UI for adding/removing filters.

  • trac/ticket/query.py

     
    787787                      req.args.get('page'),  
    788788                      req.args.get('max')) 
    789789 
     790        if cols: 
     791            for idx, col in enumerate(cols): 
     792                if 'up_' + col in req.args: 
     793                    query.cols[idx] = cols[idx-1] 
     794                    query.cols[idx-1] = col 
     795                    req.redirect(query.get_href(req.href)) 
     796                elif 'down_' + col in req.args: 
     797                    query.cols[idx] = cols[idx+1] 
     798                    query.cols[idx+1] = col 
     799                    req.redirect(query.get_href(req.href)) 
     800                elif 'rm_column_' + col in req.args: 
     801                    query.cols.remove(col) 
     802                    req.redirect(query.get_href(req.href)) 
     803 
    790804        if 'update' in req.args: 
    791805            # Reset session vars 
    792806            for var in ('query_constraints', 'query_time', 'query_tickets'): 
     
    883897                constraint.setdefault('values', []).append('') 
    884898                # FIXME: '' not always correct (e.g. checkboxes) 
    885899 
     900        # For clients without JavaScript, we add a new column here if 
     901        # requested 
     902        cols = data['col'] 
     903        if 'add_column' in req.args: 
     904            column = req.args.get('new_column') 
     905            if column: 
     906                cols.append(column) 
     907 
    886908        req.session['query_href'] = query.get_href(context.href) 
    887909        req.session['query_time'] = to_timestamp(orig_time) 
    888910        req.session['query_tickets'] = ' '.join([str(t['id']) 
     
    912934        data.setdefault('description', None) 
    913935        data['title'] = title 
    914936 
    915         data['all_columns'] = query.get_all_columns() 
     937        all_columns = query.get_all_columns() 
     938        all_columns.sort(key=lambda x: data['labels'].get(x, x)) 
    916939        # Don't allow the user to remove the id column         
    917         data['all_columns'].remove('id') 
     940        all_columns.remove('id') 
     941        data['all_columns'] = all_columns 
    918942        data['all_textareas'] = query.get_all_textareas() 
    919943 
    920944        add_stylesheet(req, 'common/css/report.css') 
  • trac/ticket/templates/query.html

     
    132132        <fieldset id="columns"> 
    133133          <legend>Columns</legend> 
    134134          <div> 
    135             <py:for each="column in all_columns"> 
    136               <label> 
    137                 <input type="checkbox" name="col" value="$column" 
    138                        checked="${any([(value == column) for value in col]) 
    139                                   and 'checked' or None}" /> 
     135             <table> 
     136               <tbody> 
     137                 <tr py:for="idx, column in enumerate(col[1:])"> 
     138                   <td>${labels.get(column, column or 'none')}</td> 
     139                   <td class="up_down"> 
     140                     <input type="hidden" name="col" value="${column}" /> 
     141                     <input type="submit" name="up_${column}" value="&#8593;" 
     142                            disabled="${not idx or None}" />&nbsp; 
     143                     <input type="submit" name="down_${column}" value="&#8595;" 
     144                            disabled="${idx == len(col)-2 or None}" /> 
     145                   </td> 
     146                   <td class="actions"><input type="submit" name="rm_column_${column}" value="-" /></td> 
     147                 </tr> 
     148               </tbody> 
     149               <tbody> 
     150                 <tr class="actions"> 
     151                   <td class="actions" colspan="3" style="text-align: right"> 
     152                     <label for="new_column">Add column</label>&nbsp; 
     153                     <select name="new_column" id="new_column"> 
     154                       <option></option> 
     155                       <option py:for="column in all_columns" 
     156                               py:if="column not in col" 
     157                               value="${column}"> 
    140158                ${labels.get(column, column or 'none')} 
    141               </label> 
    142             </py:for> 
     159                       </option> 
     160                     </select> 
     161                     <input type="submit" name="add_column" value="+" /> 
     162                   </td> 
     163                 </tr> 
     164               </tbody> 
     165             </table> 
    143166          </div> 
    144167        </fieldset> 
    145168 
  • trac/htdocs/js/query.js

     
    273273      } 
    274274      select.selectedIndex = 0; 
    275275    } 
     276 
     277    // Functionality for adding/removing/redordering columns.  This is a little 
     278    // disjointed as it's written using jQuery, unlike the above code for dealing 
     279    // with filters, which was written prior to the use of jQuery in Trac. 
     280   
     281    // Inserts row after insertionPoint (which is another row) 
     282    function insertColumnRow(row, insertionPoint) { 
     283      if (!insertionPoint.next().length) { 
     284        row.find("input[@name^='down_']").attr("disabled", true); 
     285      } 
     286      row.find("input[@name^='up_']").attr("disabled", false); 
     287       
     288      if (!insertionPoint.length){ 
     289        $("#columns table").append(row); 
     290      } 
     291      else{ 
     292        row.insertAfter(insertionPoint); 
     293      } 
     294      insertionPoint.find("input[@name^='down_']").attr("disabled", false); 
     295      if (!insertionPoint.prev().length) { 
     296        insertionPoint.find("input[@name^='up_']").attr("disabled", true); 
     297      } 
     298    } 
     299   
     300    function removeColumnRow() { 
     301      var row = $(this).parents("tr"); 
     302   
     303      //Disable the Up or Down buttons. 
     304      if (!row.next().length) { 
     305         row.prev().find("input[@name^='down_']").attr("disabled", true); 
     306      } 
     307      if (!row.prev().length) { 
     308         row.next().find("input[@name^='up_']").attr("disabled", true); 
     309      } 
     310      var column_val = row.find("input[@name^='col']").val(); 
     311      var column_label = row.children().eq(0).text(); 
     312      var select = $("#new_column"); 
     313      var option = $("<option value='" + column_val + "'>" + column_label + 
     314                     "</option>"); 
     315      //Add item to the appropriate place in the drop-down list. 
     316      var found = false; 
     317      select.children().each(function() { 
     318        if ($.trim($(this).text().toLowerCase()) > $.trim(column_label.toLowerCase())) { 
     319          $(this).before(option); 
     320          found = true; 
     321          return false; 
    276322  } 
     323      }); 
     324      if (!found) select.append(option); 
     325      select[0].selectedIndex = 0; 
    277326 
     327      //Remove selected row. 
     328      row.remove(); 
     329   
     330      return false; 
     331    } 
     332   
     333    function moveColumnUp() { 
     334      var row = $(this).parents("tr"); 
     335      insertColumnRow(row.prev(), row); 
     336      return false; 
     337    } 
     338   
     339    function moveColumnDown() { 
     340      var row = $(this).parents('tr'); 
     341      insertColumnRow(row, row.next()); 
     342      return false; 
     343    } 
     344   
     345    $("input[@name^='up_']").click(moveColumnUp); 
     346    $("input[@name^='down_']").click(moveColumnDown); 
     347    $("input[@name^='rm_column_']").click(removeColumnRow); 
     348   
     349    // Make the drop-down menu for adding a column a client-side trigger 
     350    $("input[@name='add_column']").remove(); 
     351    $("#new_column").change(function() { 
     352      if (this.selectedIndex < 1) return; 
     353      var option = $(this).children().eq(this.selectedIndex); 
     354      $(this).children().eq(this.selectedIndex).remove(); 
     355   
     356      this.selectedIndex = 0; 
     357   
     358      // The newlines in here are because of FireFox laying things out slightly 
     359      // differently depending on whitespace -_- 
     360      var row = $("<tr><td>" + option.text() +"</td><td class='up_down'>" + 
     361                  "<input type='hidden' name='col' " + 
     362                         "value='" + option.val() +"' />" + 
     363                  "<input type='submit' name='up_" + option.val() + "' " + 
     364                         "value=&#8593; />&nbsp;\n" + 
     365                  "<input type='submit' name='down_" + option.val() + "' " + 
     366                         "value=&#8595; /></td><td class='actions'>\n" + 
     367                  "<input type='submit' name='rm_column_" + option.val() + "' " + 
     368                         "value='-' />\n</td></tr>"); 
     369      row.find("input[@name^='up_']").click(moveColumnUp); 
     370      row.find("input[@name^='down_']").click(moveColumnDown); 
     371      row.find("input[@name^='rm_column_']").click(removeColumnRow); 
     372      var rows = $("#columns table > tbody").eq(0).children(); 
     373      insertColumnRow(row, rows.eq(rows.length - 1)); 
     374    }); 
     375  } 
    278376})(jQuery); 
     377 No newline at end of file 
  • 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 label {  
    45  display: block; 
    46  float: left; 
    47  padding: 0pt 1em .5em 0pt; 
     44#columns table { width: 100% } 
     45#columns tr { height: 2em } 
     46#columns th, #columns td { 
     47 padding: 0 .2em; 
     48 vertical-align: middle; 
     49 white-space: nowrap; 
    4850} 
     51#columns th { font-size: 11px; text-align: right } 
     52#columns td label { font-size: 11px } 
     53#columns td.up_down { width: 100% } 
     54#columns td.actions { text-align: right } 
    4955 
    5056/* Styles for the report list and the report results table 
    5157   (extends the styles for "table.listing") */