Merge branch 'master' into 3618-column-ordering
authorPhil Hodgson <bitbucket@philhodgson.net>
Fri, 24 Oct 2014 12:06:45 +0000 (14:06 +0200)
committerPhil Hodgson <bitbucket@philhodgson.net>
Fri, 24 Oct 2014 12:06:45 +0000 (14:06 +0200)
1  2 
apps/workbench/app/assets/javascripts/infinite_scroll.js
apps/workbench/app/assets/stylesheets/application.css.scss

index 1f947e1c14c8232a13a022dd791d472859d0de3b,5de778688efd2d808652ac146e8e5ae17bdd9230..2ca45484baaa974b842c74bb3c35b5f926d17f31
@@@ -41,45 -41,26 +41,26 @@@ function maybe_load_more_content(event
          $container.append(spinner);
          $container.attr('data-infinite-serial', serial);
  
-         // Combine infiniteContentParams from multiple sources. This
-         // mechanism allows each of several components to set and
-         // update its own set of filters, without having to worry
-         // about stomping on some other component's filters.
-         //
-         // For example, filterable.js writes filters in
-         // infiniteContentParamsFilterable ("search for text foo")
-         // without worrying about clobbering the filters set up by the
-         // tab pane ("only show jobs and pipelines in this tab").
-         params = {};
-         $.each($container.data(), function(datakey, datavalue) {
-             // Note: We attach these data to DOM elements using
-             // <element data-foo-bar="baz">. We store/retrieve them
-             // using $('element').data('foo-bar'), although
-             // .data('fooBar') would also work. The "all data" hash
-             // returned by $('element').data(), however, always has
-             // keys like 'fooBar'. In other words, where we have a
-             // choice, we stick with the 'foo-bar' style to be
-             // consistent with HTML. Here, our only option is
-             // 'fooBar'.
-             if (/^infiniteContentParams/.exec(datakey)) {
-                 if (datavalue instanceof Object) {
-                     $.each(datavalue, function(hkey, hvalue) {
-                         if (hvalue instanceof Array) {
-                             params[hkey] = (params[hkey] || []).concat(hvalue);
-                         } else if (hvalue instanceof Object) {
-                             $.extend(params[hkey], hvalue);
-                         } else {
-                             params[hkey] = hvalue;
-                         }
-                     });
+         if (src == $container.attr('data-infinite-content-href0')) {
+             // If we're loading the first page, collect filters from
+             // various sources.
+             params = mergeInfiniteContentParams($container);
+             $.each(params, function(k,v) {
+                 if (v instanceof Object) {
+                     params[k] = JSON.stringify(v);
                  }
-             }
-         });
-         $.each(params, function(k,v) {
-             if (v instanceof Object) {
-                 params[k] = JSON.stringify(v);
-             }
-         });
+             });
+         } else {
+             // If we're loading page >1, ignore other filtering
+             // mechanisms and just use the "next page" URI from the
+             // previous page's response. Aside from avoiding race
+             // conditions (where page 2 could have different filters
+             // than page 1), this allows the server to use filters in
+             // the "next page" URI to achieve paging. (To apply any
+             // new filters effectively, we need to load page 1 again
+             // anyway.)
+             params = {};
+         }
  
          $.ajax(src,
                 {dataType: 'json',
@@@ -127,6 -108,45 +108,45 @@@ function ping_all_scrollers() 
      $('.infinite-scroller').add(window).trigger('scroll');
  }
  
+ function mergeInfiniteContentParams($container) {
+     var params = {};
+     // Combine infiniteContentParams from multiple sources. This
+     // mechanism allows each of several components to set and
+     // update its own set of filters, without having to worry
+     // about stomping on some other component's filters.
+     //
+     // For example, filterable.js writes filters in
+     // infiniteContentParamsFilterable ("search for text foo")
+     // without worrying about clobbering the filters set up by the
+     // tab pane ("only show jobs and pipelines in this tab").
+     $.each($container.data(), function(datakey, datavalue) {
+         // Note: We attach these data to DOM elements using
+         // <element data-foo-bar="baz">. We store/retrieve them
+         // using $('element').data('foo-bar'), although
+         // .data('fooBar') would also work. The "all data" hash
+         // returned by $('element').data(), however, always has
+         // keys like 'fooBar'. In other words, where we have a
+         // choice, we stick with the 'foo-bar' style to be
+         // consistent with HTML. Here, our only option is
+         // 'fooBar'.
+         if (/^infiniteContentParams/.exec(datakey)) {
+             if (datavalue instanceof Object) {
+                 $.each(datavalue, function(hkey, hvalue) {
+                     if (hvalue instanceof Array) {
+                         params[hkey] = (params[hkey] || []).
+                             concat(hvalue);
+                     } else if (hvalue instanceof Object) {
+                         $.extend(params[hkey], hvalue);
+                     } else {
+                         params[hkey] = hvalue;
+                     }
+                 });
+             }
+         }
+     });
+     return params;
+ }
  $(document).
      on('click', 'div.infinite-retry button', function() {
          var $retry_div = $(this).closest('.infinite-retry');
                  on('scroll resize', { container: this }, maybe_load_more_content).
                  trigger('scroll');
          });
 +    }).
 +    on('click', 'th[data-sort-order]', function() {
 +        var direction = $(this).data('sort-order-direction');
 +        // reverse the current direction, or do ascending if none
 +        if( typeof(direction) == 'undefined' || direction == 'desc' ) {
 +            direction = 'asc';
 +        } else {
 +            direction = 'desc';
 +        }
 +        $(this).data('sort-order-direction', direction);
 +        // change the ordering parameter and refresh the data display with the new order
 +        var $target = $(this).closest('table').find('[data-infinite-content-params-attr]');
 +        var params_attr = 'infinite-content-params-' + $target.data('infinite-content-params-attr');
 +        var params = $target.data(params_attr) || {};
 +        params.order = $(this).data('sort-order').split(",").join( ' ' + direction + ', ' ) + ' ' + direction;
 +        $target.data(params_attr, params);
 +        $target.trigger('refresh-content');
 +    }).
 +    on('ready arv:pane:loaded refresh-content', function() {
 +        $('th[data-sort-order]').each(function() {
 +            $(this).find('i').remove();
 +            var direction = $(this).data('sort-order-direction');
 +            if( typeof(direction) != 'undefined' ) {
 +                $(this).append('<i class="fa fa-sort-' + direction + '"/>');
 +            } else {
 +                $(this).append('<i class="fa fa-sort"/>');
 +            }
 +        });
      });
index 77fe7126c05e0ea9b64c368d226dad63e36462f0,fc7e462b88c5a4c6a797b05a26530c54506207c4..7007d8c348657c11dc08b19d8c051db360b603d5
@@@ -150,10 -150,6 +150,10 @@@ nav.navbar-fixed-top .navbar-nav.navbar
      color: #800;
  }
  
 +th[data-sort-order] {
 +    cursor: pointer;
 +}
 +
  .inline-progress-container div.progress {
      margin-bottom: 0;
  }
@@@ -261,7 -257,9 +261,9 @@@ span.editable-textile 
    min-width: 1em;
    padding: 0px 2px 0px 0px;
  }
+ .task-summary-status {
+   font-size: 80%;
+ }
  #page-wrapper > div > h2 {
    margin-top: 0px;
  }