[ARVADOS] updated: 29487f418ff010e6ed536bc0a4d52997c1d0cd4f

git at public.curoverse.com git at public.curoverse.com
Tue Jun 3 04:18:05 EDT 2014


Summary of changes:
 .../javascripts/{folders.js => filterable.js}      |  22 +--
 .../app/assets/javascripts/infinite_scroll.js      |   9 +-
 .../app/assets/javascripts/pipeline_instances.js   |  17 ++
 apps/workbench/app/assets/javascripts/selection.js |  44 ++++-
 .../app/assets/stylesheets/select_modal.css.scss   |   4 +-
 .../app/controllers/application_controller.rb      |  18 ++
 .../app/controllers/folders_controller.rb          |  55 +++---
 .../controllers/pipeline_instances_controller.rb   |   9 +
 apps/workbench/app/helpers/application_helper.rb   |   7 +-
 apps/workbench/app/models/arvados_base.rb          |   5 +-
 .../app/views/application/_choose.html.erb         |  17 +-
 .../app/views/application/_content.html.erb        |   2 +-
 .../app/views/collections/_choose_rows.html.erb    |   6 +-
 apps/workbench/app/views/folders/_choose.html.erb  |   2 +-
 .../folders/_index_jobs_and_pipelines.html.erb     |   4 +-
 .../app/views/folders/_show_contents.html.erb      |  72 +++++---
 .../app/views/folders/_show_contents_rows.html.erb |   4 +-
 .../app/views/folders/_show_permissions.html.erb   |   2 +-
 apps/workbench/app/views/folders/index.html.erb    |   2 +-
 .../{remove_item.js.erb => remove_items.js.erb}    |   0
 .../app/views/layouts/application.html.erb         |   6 +-
 .../pipeline_instances/_show_components.html.erb   | 202 +++++++++++----------
 .../views/pipeline_instances/_show_inputs.html.erb |  10 +-
 .../views/pipeline_instances/_show_recent.html.erb |  19 --
 .../views/pipeline_templates/_choose_rows.html.erb |   6 +-
 apps/workbench/app/views/users/_home.html.erb      |   2 +-
 apps/workbench/config/routes.rb                    |   2 +
 apps/workbench/test/integration/users_test.rb      |  10 +-
 .../test/integration/virtual_machines_test.rb      |   2 +-
 29 files changed, 341 insertions(+), 219 deletions(-)
 rename apps/workbench/app/assets/javascripts/{folders.js => filterable.js} (61%)
 rename apps/workbench/app/views/folders/{remove_item.js.erb => remove_items.js.erb} (100%)

       via  29487f418ff010e6ed536bc0a4d52997c1d0cd4f (commit)
       via  77225263b324d4a75f5f3fae1fd01d244dc4afa1 (commit)
       via  1f0868d558a44c6e3ca14240b92848cacd58a866 (commit)
       via  747efcd9371118c2db9c265c13ce399fc4b6c96b (commit)
       via  be778bdec0bb03b08699c6ee1343a0e791f5dfbf (commit)
      from  153642799375c2983363b48a40b05abb173750e6 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit 29487f418ff010e6ed536bc0a4d52997c1d0cd4f
Author: Tom Clegg <tom at curoverse.com>
Date:   Tue Jun 3 04:17:32 2014 -0400

    2872: Add selection checkboxes to folder view. Compare pipeline instances and remove multiple items.

diff --git a/apps/workbench/app/assets/javascripts/pipeline_instances.js b/apps/workbench/app/assets/javascripts/pipeline_instances.js
index d23ced7..614f45f 100644
--- a/apps/workbench/app/assets/javascripts/pipeline_instances.js
+++ b/apps/workbench/app/assets/javascripts/pipeline_instances.js
@@ -72,3 +72,20 @@ $(document).on('arv-log-event', '.arv-log-event-handler-append-logs', function(e
       $(this).append(parsedData.summary + "<br/>");
     }
 });
+
+var showhide_compare = function() {
+    var form = $('form#compare')[0];
+    $('input[type=hidden][name="uuids[]"]', form).remove();
+    $('input[type=submit]', form).prop('disabled',true).show();
+    var checked_inputs = $('[data-object-uuid*=-d1hrv-] input[name="uuids[]"]:checked');
+    if (checked_inputs.length >= 2 && checked_inputs.length <= 3) {
+        checked_inputs.each(function(){
+            if(this.checked) {
+                $('input[type=submit]', form).prop('disabled',false).show();
+                $(form).append($('<input type="hidden" name="uuids[]"/>').val(this.value));
+            }
+        });
+    }
+};
+$('[data-object-uuid*=-d1hrv-] input[name="uuids[]"]').on('click', showhide_compare);
+showhide_compare();
diff --git a/apps/workbench/app/assets/javascripts/selection.js b/apps/workbench/app/assets/javascripts/selection.js
index 1e32c63..59f0fd1 100644
--- a/apps/workbench/app/assets/javascripts/selection.js
+++ b/apps/workbench/app/assets/javascripts/selection.js
@@ -100,13 +100,11 @@ jQuery(function($){
 
         $('.remove-selection').on('click', remove_selection_click);
         $('#clear_selections_button').on('click', clear_selections);
+        $(document).trigger('selections-updated', [lst]);
     };
 
     $(document).
         on('change', '.persistent-selection:checkbox', function(e) {
-            //console.log($(this));
-            //console.log($(this).val());
-
             var inc = 0;
             if ($(this).is(":checked")) {
                 add_selection($(this).val(), $(this).attr('friendly_name'), $(this).attr('href'), $(this).attr('friendly_type'));
@@ -116,7 +114,6 @@ jQuery(function($){
             }
         });
 
-
     $(window).on('load storage', update_count);
 
     $('#selection-form-content').on("click", function(e) {
@@ -178,3 +175,42 @@ select_form_sources = null;
         return ret;
     };
 })();
+
+function dispatch_selection_action() {
+    // Build a new "href" attribute for this link by starting with the
+    // "data-href" attribute and appending ?foo[]=bar&foo[]=baz (or
+    // &foo=... as appropriate) to reflect the current object
+    // selections.
+    var data = [];
+    var param_name = $(this).attr('data-selection-param-name');
+    var href = $(this).attr('data-href');
+    $('.persistent-selection:checkbox:checked').each(function() {
+        data.push({name: param_name, value: $(this).val()});
+    });
+    if (href.indexOf('?') >= 0)
+        href += '&';
+    else
+        href += '?';
+    href += $.param(data, true);
+    $(this).attr('href', href);
+    return true;
+}
+
+function enable_disable_selection_actions() {
+    var $checked = $('.persistent-selection:checkbox:checked');
+    $('[data-selection-action]').
+        closest('div.btn-group-sm').
+        find('*').
+        prop('disabled', ($checked.length == 0));
+    $('[data-selection-action=compare]').
+        closest('li').
+        toggleClass('disabled',
+                    ($checked.filter('[value*=-d1hrv-]').length < 2) ||
+                    ($checked.not('[value*=-d1hrv-]').length > 0));
+}
+
+$(document).
+    on('selections-updated ready ajax:complete', function() {
+        $('[data-selection-action]').click(dispatch_selection_action);
+        enable_disable_selection_actions();
+    });
diff --git a/apps/workbench/app/controllers/folders_controller.rb b/apps/workbench/app/controllers/folders_controller.rb
index 637ae36..000cbc9 100644
--- a/apps/workbench/app/controllers/folders_controller.rb
+++ b/apps/workbench/app/controllers/folders_controller.rb
@@ -12,32 +12,39 @@ class FoldersController < ApplicationController
   end
 
   def remove_item
+    params[:item_uuids] = [params[:item_uuid]]
+    remove_items
+    render template: 'folders/remove_items'
+  end
+
+  def remove_items
     @removed_uuids = []
     links = []
-    item = ArvadosBase.find params[:item_uuid]
-    if (item.class == Link and
-        item.link_class == 'name' and
-        item.tail_uuid = @object.uuid)
-      # Given uuid is a name link, linking an object to this
-      # folder. First follow the link to find the item we're removing,
-      # then delete the link.
-      links << item
-      item = ArvadosBase.find item.head_uuid
-    else
-      # Given uuid is an object. Delete all names.
-      links += Link.where(tail_uuid: @object.uuid,
-                          head_uuid: item.uuid,
-                          link_class: 'name')
-    end
-    links.each do |link|
-      @removed_uuids << link.uuid
-      link.destroy
-    end
-    if item.owner_uuid == @object.uuid
-      # Object is owned by this folder. Remove it from the folder by
-      # changing owner to the current user.
-      item.update_attributes owner_uuid: current_user.uuid
-      @removed_uuids << item.uuid
+    params[:item_uuids].collect { |uuid| ArvadosBase.find uuid }.each do |item|
+      if (item.class == Link and
+          item.link_class == 'name' and
+          item.tail_uuid == @object.uuid)
+        # Given uuid is a name link, linking an object to this
+        # folder. First follow the link to find the item we're removing,
+        # then delete the link.
+        links << item
+        item = ArvadosBase.find item.head_uuid
+      else
+        # Given uuid is an object. Delete all names.
+        links += Link.where(tail_uuid: @object.uuid,
+                            head_uuid: item.uuid,
+                            link_class: 'name')
+      end
+      links.each do |link|
+        @removed_uuids << link.uuid
+        link.destroy
+      end
+      if item.owner_uuid == @object.uuid
+        # Object is owned by this folder. Remove it from the folder by
+        # changing owner to the current user.
+        item.update_attributes owner_uuid: current_user.uuid
+        @removed_uuids << item.uuid
+      end
     end
   end
 
diff --git a/apps/workbench/app/helpers/application_helper.rb b/apps/workbench/app/helpers/application_helper.rb
index d9e97b9..5eed7f8 100644
--- a/apps/workbench/app/helpers/application_helper.rb
+++ b/apps/workbench/app/helpers/application_helper.rb
@@ -180,7 +180,7 @@ module ApplicationHelper
       :class => "editable"
     }.merge(htmloptions).merge(ajax_options)
     edit_button = raw('<a href="#" class="btn btn-xs btn-default btn-nodecorate" data-toggle="x-editable tooltip" data-toggle-selector="#' + span_id + '" data-placement="top" title="' + (htmloptions[:tiptitle] || 'edit') + '"><i class="fa fa-fw fa-pencil"></i></a>')
-    if htmloptions[:tipplacement] == :left
+    if htmloptions[:btnplacement] == :left
       edit_button + ' ' + span_tag
     else
       span_tag + ' ' + edit_button
diff --git a/apps/workbench/app/views/application/_choose.html.erb b/apps/workbench/app/views/application/_choose.html.erb
index 4708ac5..c42adac 100644
--- a/apps/workbench/app/views/application/_choose.html.erb
+++ b/apps/workbench/app/views/application/_choose.html.erb
@@ -6,7 +6,7 @@
         <h4 class="modal-title"><%= params[:title] || "Choose #{@objects.first.class_for_display}" %></h4>
       </div>
       <div class="modal-body">
-        <div class="container-fluid">
+        <div>
           <div class="row">
             <div class="col-sm-6">
             </div>
diff --git a/apps/workbench/app/views/application/_content.html.erb b/apps/workbench/app/views/application/_content.html.erb
index b41da15..0e3fa0b 100644
--- a/apps/workbench/app/views/application/_content.html.erb
+++ b/apps/workbench/app/views/application/_content.html.erb
@@ -36,7 +36,7 @@
 <div class="tab-content">
 <% panes.each_with_index do |(pane, content), i| %>
   <div id="<%= pane %>" class="tab-pane fade <%= 'in active' if i==0 %>">
-    <div id="<%= pane %>-scroll" class="smart-scroll" style="margin-top:0.5em;">
+    <div id="<%= pane %>-scroll" class="<%= 'smart-scroll' if pane.match(/graph/) %>" style="margin-top:0.5em;">
       <%= content %>
     </div>
   </div>
diff --git a/apps/workbench/app/views/collections/_choose_rows.html.erb b/apps/workbench/app/views/collections/_choose_rows.html.erb
index 88d71d2..d488743 100644
--- a/apps/workbench/app/views/collections/_choose_rows.html.erb
+++ b/apps/workbench/app/views/collections/_choose_rows.html.erb
@@ -4,7 +4,7 @@
       <i class="fa fa-fw fa-archive"></i>
       <%= name_link.name %>
     </div>
-    <div class="col-sm-11 col-sm-push-1 arv-description-in-table">
+    <div class="col-sm-11 col-sm-push-1" style="overflow-x: hidden">
       <%= render_controller_partial(
           'show_object_description_cell.html',
           controller_name: 'collections',
diff --git a/apps/workbench/app/views/folders/_choose.html.erb b/apps/workbench/app/views/folders/_choose.html.erb
index 7d57ca5..2262c07 100644
--- a/apps/workbench/app/views/folders/_choose.html.erb
+++ b/apps/workbench/app/views/folders/_choose.html.erb
@@ -8,7 +8,7 @@
       </div>
 
       <div class="modal-body">
-        <div class="container-fluid selectable-container" style="height: 15em; overflow-y: scroll">
+        <div class="selectable-container" style="height: 15em; overflow-y: scroll">
           <% [@my_folder_tree, @shared_folder_tree].each do |tree| %>
             <% tree.each do |foldernode| %>
               <% if foldernode[:object].is_a? String %>
diff --git a/apps/workbench/app/views/folders/_index_jobs_and_pipelines.html.erb b/apps/workbench/app/views/folders/_index_jobs_and_pipelines.html.erb
index fb637c6..4c066f9 100644
--- a/apps/workbench/app/views/folders/_index_jobs_and_pipelines.html.erb
+++ b/apps/workbench/app/views/folders/_index_jobs_and_pipelines.html.erb
@@ -1,4 +1,4 @@
-<div class="container-fluid">
+<div>
   <% any = false %>
   <% recent_jobs_and_pipelines[0..9].each do |object| %>
     <% any = true %>
@@ -6,7 +6,7 @@
       <div class="col-sm-4">
         <%= render :partial => "show_object_button", :locals => {object: object, size: 'xs'} %>
         <% if object.respond_to?(:name) %>
-          <%= render_editable_attribute object, 'name', nil %>
+          <%= render_editable_attribute object, 'name', nil, {tiptitle: 'rename', btnplacement: :left} %>
         <% else %>
           <%= object.class_for_display %> <%= object.uuid %>
         <% end %>
diff --git a/apps/workbench/app/views/folders/_show_contents.html.erb b/apps/workbench/app/views/folders/_show_contents.html.erb
index 68237f8..834d070 100644
--- a/apps/workbench/app/views/folders/_show_contents.html.erb
+++ b/apps/workbench/app/views/folders/_show_contents.html.erb
@@ -18,9 +18,30 @@
   <% end %>
 <% end %>
 
-<div class="container-fluid">
+<div class="selection-action-container">
   <div class="row">
-    <div class="col-md-4">
+    <div class="col-sm-5">
+      <div class="btn-group btn-group-sm">
+        <button type="button" class="btn btn-default">Selection...</button>
+        <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
+          <span class="caret"></span>
+          <span class="sr-only">Toggle Dropdown</span>
+        </button>
+        <ul class="dropdown-menu" role="menu">
+          <li><%= link_to "Compare selected", '#',
+                  'data-href' => compare_pipeline_instances_path,
+                  'data-selection-param-name' => 'uuids[]',
+                  'data-selection-action' => 'compare'
+            %></li>
+          <li><%= link_to "Remove selected", '#',
+                  'data-href' => url_for(action: :remove_items),
+                  'data-selection-param-name' => 'item_uuids[]',
+                  'data-selection-action' => 'remove',
+                  'data-remote' => true,
+                  'method' => 'delete'
+            %></li>
+        </ul>
+      </div>
       <% if @object.editable? %>
         <%= link_to(
               choose_collections_path(
@@ -45,10 +66,10 @@
         <% end %>
       <% end %>
     </div>
-    <div class="col-md-4">
+    <div class="col-sm-3">
       <form class="form-inline" role="form">
         Show:
-        <select class="form-control filterable-control" data-filterable-attribute="data-kind" data-filterable-target="table.arv-index.arv-folder-contents tbody">
+        <select class="form-control form-control-sm filterable-control" data-filterable-attribute="data-kind" data-filterable-target="table.arv-index.arv-folder-contents tbody">
           <option value="">Everything</option>
           <option value="arvados#collection">Data</option>
           <option value="arvados#pipelineInstance arvados#job">Compute jobs</option>
@@ -61,27 +82,28 @@
         </select>
       </form>
     </div>
-    <div class="col-md-4">
+    <div class="col-sm-4">
       <input type="text" class="form-control filterable-control" placeholder="Search folder contents" data-filterable-target="table.arv-index.arv-folder-contents tbody"/>
     </div>
   </div>
-</div>
 
-<table class="table table-condensed table-fixedlayout arv-index arv-folder-contents" style="overflow-x: hidden">
-  <colgroup>
-    <col width="40%" />
-    <col width="60%" />
-  </colgroup>
-  <tbody data-infinite-scroller="#Contents-scroll" data-infinite-content-href="<%= url_for(format: :json, partial: :contents_rows, offset: next_page_offset) if next_page_offset %>">
-    <%= render partial: 'show_contents_rows', locals: {folder: @object, objects_and_names: @objects_and_names} %>
-  </tbody>
-  <thead>
-    <tr>
-      <th>
-      </th>
-      <th>
-        description
-      </th>
-    </tr>
-  </thead>
-</table>
+  <table class="table table-condensed table-fixedlayout arv-index arv-folder-contents" style="overflow-x: hidden">
+    <colgroup>
+      <col width="40%" />
+      <col width="60%" />
+    </colgroup>
+    <tbody data-infinite-scroller="#Contents-scroll" data-infinite-content-href="<%= url_for(format: :json, partial: :contents_rows, offset: next_page_offset) if next_page_offset %>">
+      <%= render partial: 'show_contents_rows', locals: {folder: @object, objects_and_names: @objects_and_names} %>
+    </tbody>
+    <thead>
+      <tr>
+        <th>
+        </th>
+        <th>
+          description
+        </th>
+      </tr>
+    </thead>
+  </table>
+
+</div>
diff --git a/apps/workbench/app/views/folders/_show_contents_rows.html.erb b/apps/workbench/app/views/folders/_show_contents_rows.html.erb
index 6aa0a87..1cdd48f 100644
--- a/apps/workbench/app/views/folders/_show_contents_rows.html.erb
+++ b/apps/workbench/app/views/folders/_show_contents_rows.html.erb
@@ -5,6 +5,8 @@
       data-kind="<%= object.kind %>"
       >
     <td>
+      <%= render partial: 'selection_checkbox', locals: {object: object, friendly_name: (name_object.name rescue nil)} %>
+
       <% if folder.editable? %>
         <%= link_to({action: 'remove_item', id: folder.uuid, item_uuid: ((name_link && name_link.uuid) || object.uuid)}, method: :delete, remote: true, data: {confirm: "Remove #{object.class_for_display.downcase} #{name_object.name rescue object.uuid} from this folder?", toggle: 'tooltip', placement: 'top'}, class: 'btn btn-sm btn-default btn-nodecorate', title: 'remove') do %>
           <i class="fa fa-fw fa-ban"></i>
@@ -15,7 +17,7 @@
 
       <%= render :partial => "show_object_button", :locals => {object: object, size: 'sm'} %>
 
-      <%= render_editable_attribute name_object, 'name', nil, {tipplacement: :left, tiptitle: 'rename'} %>
+      <%= render_editable_attribute name_object, 'name', nil, {btnplacement: :left, tiptitle: 'rename'} %>
     </td>
     <td class="arv-description-in-table">
       <%= render_controller_partial(
diff --git a/apps/workbench/app/views/folders/_show_permissions.html.erb b/apps/workbench/app/views/folders/_show_permissions.html.erb
index 262cb3b..0eca228 100644
--- a/apps/workbench/app/views/folders/_show_permissions.html.erb
+++ b/apps/workbench/app/views/folders/_show_permissions.html.erb
@@ -1,4 +1,4 @@
-<div class="container-fluid">
+<div>
   <div class="row">
     <div class="col-md-6">
       <div class="panel panel-default">
diff --git a/apps/workbench/app/views/folders/index.html.erb b/apps/workbench/app/views/folders/index.html.erb
index 5197f84..ce5220b 100644
--- a/apps/workbench/app/views/folders/index.html.erb
+++ b/apps/workbench/app/views/folders/index.html.erb
@@ -3,7 +3,7 @@
 <li><a href="#">Home</a></li>
 <% end %>
 
-<div class="container-fluid">
+<div>
   <div class="row">
     <div class="col-sm-6">
       <% if my_folders.empty? %>
diff --git a/apps/workbench/app/views/folders/remove_item.js.erb b/apps/workbench/app/views/folders/remove_items.js.erb
similarity index 100%
rename from apps/workbench/app/views/folders/remove_item.js.erb
rename to apps/workbench/app/views/folders/remove_items.js.erb
diff --git a/apps/workbench/app/views/layouts/application.html.erb b/apps/workbench/app/views/layouts/application.html.erb
index 631595f..6359794 100644
--- a/apps/workbench/app/views/layouts/application.html.erb
+++ b/apps/workbench/app/views/layouts/application.html.erb
@@ -32,10 +32,6 @@
     height: 100%;
     }
 
-    body > div.container-fluid {
-    padding-top: 70px; /* 70px to make the container go all the way to the bottom of the navbar */
-    }
-
     @media (max-width: 979px) { body { padding-top: 0; } }
 
     .navbar .nav li.nav-separator > span.glyphicon.glyphicon-arrow-right {
@@ -51,7 +47,7 @@
   <link href="//netdna.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.css" rel="stylesheet">
 </head>
 <body>
-  <div id="wrapper">
+  <div id="wrapper" class="container-fluid">
     <nav class="navbar navbar-default navbar-fixed-top" role="navigation">
       <div class="navbar-header">
         <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
diff --git a/apps/workbench/app/views/pipeline_instances/_show_recent.html.erb b/apps/workbench/app/views/pipeline_instances/_show_recent.html.erb
index e9a01dc..86eab62 100644
--- a/apps/workbench/app/views/pipeline_instances/_show_recent.html.erb
+++ b/apps/workbench/app/views/pipeline_instances/_show_recent.html.erb
@@ -78,22 +78,3 @@
 <% end %>
 
 <%= render partial: "paging", locals: {results: @objects, object: @object} %>
-
-<% content_for :footer_js do %>
-var showhide_compare = function() {
-    var form = $('form#compare')[0];
-    $('input[type=hidden][name="uuids[]"]', form).remove();
-    $('input[type=submit]', form).prop('disabled',true).show();
-    var checked_inputs = $('input[name="uuids[]"]:checked');
-    if (checked_inputs.length >= 2 && checked_inputs.length <= 3) {
-        checked_inputs.each(function(){
-            if(this.checked) {
-                $('input[type=submit]', form).prop('disabled',false).show();
-                $(form).append($('<input type="hidden" name="uuids[]"/>').val(this.value));
-            }
-        });
-    }
-};
-$('form input[name="uuids[]"]').on('click', showhide_compare);
-showhide_compare();
-<% end %>
diff --git a/apps/workbench/app/views/users/_home.html.erb b/apps/workbench/app/views/users/_home.html.erb
index 5e8b3f8..0c5739c 100644
--- a/apps/workbench/app/views/users/_home.html.erb
+++ b/apps/workbench/app/views/users/_home.html.erb
@@ -27,7 +27,7 @@
       }
 <% end %>
 
-<div class="container-fluid" id="home-tables">
+<div id="home-tables">
 
     <%= render :partial => 'tables' %>
 
diff --git a/apps/workbench/config/routes.rb b/apps/workbench/config/routes.rb
index 971b0ce..95de0e0 100644
--- a/apps/workbench/config/routes.rb
+++ b/apps/workbench/config/routes.rb
@@ -57,6 +57,7 @@ ArvadosWorkbench::Application.routes.draw do
   get '/collections/:uuid/*file' => 'collections#show_file', :format => false
   resources :folders do
     match 'remove/:item_uuid', on: :member, via: :delete, action: :remove_item
+    match 'remove_items', on: :member, via: :delete, action: :remove_items
     get 'choose', on: :collection
   end
 

commit 77225263b324d4a75f5f3fae1fd01d244dc4afa1
Author: Tom Clegg <tom at curoverse.com>
Date:   Tue Jun 3 02:51:39 2014 -0400

    2872: Make infinite scroll work with regular window scrollbars too.

diff --git a/apps/workbench/app/assets/javascripts/filterable.js b/apps/workbench/app/assets/javascripts/filterable.js
index 8bb8085..76c5ac3 100644
--- a/apps/workbench/app/assets/javascripts/filterable.js
+++ b/apps/workbench/app/assets/javascripts/filterable.js
@@ -26,7 +26,7 @@ $(document).
             }
             return pass;
         }).show();
-        $('.infinite-scroller').trigger('scroll');
+        $('.infinite-scroller').add(window).trigger('scroll');
     }).on('change', 'select.filterable-control', function() {
         var val = $(this).val();
         var filterby = $(this).attr('data-filterable-attribute');
diff --git a/apps/workbench/app/assets/javascripts/infinite_scroll.js b/apps/workbench/app/assets/javascripts/infinite_scroll.js
index 48b8136..3e15c9d 100644
--- a/apps/workbench/app/assets/javascripts/infinite_scroll.js
+++ b/apps/workbench/app/assets/javascripts/infinite_scroll.js
@@ -2,9 +2,11 @@ function maybe_load_more_content() {
     var scroller = this;        // element with scroll bars
     var container;              // element that receives new content
     var src;                    // url for retrieving content
+    var scrollHeight;
+    scrollHeight = scroller.scrollHeight || $('body')[0].scrollHeight;
     if ($(scroller).scrollTop() + $(scroller).height()
         >
-        scroller.scrollHeight - 50) {
+        scrollHeight - 50) {
         container = $(this).data('infinite-container');
         src = $(container).attr('data-infinite-content-href');
         if (!src)
@@ -39,7 +41,10 @@ function maybe_load_more_content() {
 $(document).
     on('ready ajax:complete', function() {
         $('[data-infinite-scroller]').each(function() {
-            $($(this).attr('data-infinite-scroller')).
+            var $scroller = $($(this).attr('data-infinite-scroller'));
+            if (!$scroller.hasClass('smart-scroll'))
+                $scroller = $(window);
+            $scroller.
                 addClass('infinite-scroller').
                 data('infinite-container', this).
                 on('scroll', maybe_load_more_content);

commit 1f0868d558a44c6e3ca14240b92848cacd58a866
Author: Tom Clegg <tom at curoverse.com>
Date:   Tue Jun 3 02:12:43 2014 -0400

    2872: Add "clone and edit" button to pipeline instance page.

diff --git a/apps/workbench/app/controllers/application_controller.rb b/apps/workbench/app/controllers/application_controller.rb
index 4347b9b..1fcfc3a 100644
--- a/apps/workbench/app/controllers/application_controller.rb
+++ b/apps/workbench/app/controllers/application_controller.rb
@@ -191,6 +191,24 @@ class ApplicationController < ActionController::Base
     show
   end
 
+  # Clone the given object, merging any attribute values supplied as
+  # with a create action.
+  def copy
+    @new_resource_attrs ||= params[model_class.to_s.underscore.singularize]
+    @new_resource_attrs ||= {}
+    @object = @object.dup
+    @object.update_attributes @new_resource_attrs
+    if not @new_resource_attrs[:name] and @object.respond_to? :name
+      if @object.name and @object.name != ''
+        @object.name = "Copy of #{@object.name}"
+      else
+        @object.name = "Copy of unnamed #{@object.class_for_display.downcase}"
+      end
+    end
+    @object.save!
+    show
+  end
+
   def destroy
     if @object.destroy
       respond_to do |f|
diff --git a/apps/workbench/app/controllers/pipeline_instances_controller.rb b/apps/workbench/app/controllers/pipeline_instances_controller.rb
index 3bb18aa..4275410 100644
--- a/apps/workbench/app/controllers/pipeline_instances_controller.rb
+++ b/apps/workbench/app/controllers/pipeline_instances_controller.rb
@@ -3,6 +3,15 @@ class PipelineInstancesController < ApplicationController
   before_filter :find_objects_by_uuid, only: :compare
   include PipelineInstancesHelper
 
+  def copy
+    @object = @object.dup
+    @object.components.each do |cname, component|
+      component.delete :job
+    end
+    @object.state = 'New'
+    super
+  end
+
   def update
     @updates ||= params[@object.class.to_s.underscore.singularize.to_sym]
     if (components = @updates[:components])
diff --git a/apps/workbench/app/helpers/application_helper.rb b/apps/workbench/app/helpers/application_helper.rb
index dc97251..d9e97b9 100644
--- a/apps/workbench/app/helpers/application_helper.rb
+++ b/apps/workbench/app/helpers/application_helper.rb
@@ -179,7 +179,12 @@ module ApplicationHelper
       "id" => span_id,
       :class => "editable"
     }.merge(htmloptions).merge(ajax_options)
-    span_tag + raw(' <a href="#" class="btn btn-xs btn-default btn-nodecorate" data-toggle="x-editable tooltip" data-toggle-selector="#' + span_id + '" data-placement="top" title="edit"><i class="fa fa-fw fa-pencil"></i></a>')
+    edit_button = raw('<a href="#" class="btn btn-xs btn-default btn-nodecorate" data-toggle="x-editable tooltip" data-toggle-selector="#' + span_id + '" data-placement="top" title="' + (htmloptions[:tiptitle] || 'edit') + '"><i class="fa fa-fw fa-pencil"></i></a>')
+    if htmloptions[:tipplacement] == :left
+      edit_button + ' ' + span_tag
+    else
+      span_tag + ' ' + edit_button
+    end
   end
 
   def render_pipeline_component_attribute(object, attr, subattr, value_info, htmloptions={})
diff --git a/apps/workbench/app/models/arvados_base.rb b/apps/workbench/app/models/arvados_base.rb
index e8b4caf..590f628 100644
--- a/apps/workbench/app/models/arvados_base.rb
+++ b/apps/workbench/app/models/arvados_base.rb
@@ -273,8 +273,9 @@ class ArvadosBase < ActiveRecord::Base
     uuid
   end
 
-  def dup
-    super.forget_uuid!
+  def initialize_copy orig
+    super
+    forget_uuid!
   end
 
   def attributes_for_display
diff --git a/apps/workbench/app/views/folders/_show_contents_rows.html.erb b/apps/workbench/app/views/folders/_show_contents_rows.html.erb
index 54e7ff6..6aa0a87 100644
--- a/apps/workbench/app/views/folders/_show_contents_rows.html.erb
+++ b/apps/workbench/app/views/folders/_show_contents_rows.html.erb
@@ -15,7 +15,7 @@
 
       <%= render :partial => "show_object_button", :locals => {object: object, size: 'sm'} %>
 
-      <%= render_editable_attribute name_object, 'name', nil %>
+      <%= render_editable_attribute name_object, 'name', nil, {tipplacement: :left, tiptitle: 'rename'} %>
     </td>
     <td class="arv-description-in-table">
       <%= render_controller_partial(
diff --git a/apps/workbench/app/views/pipeline_instances/_show_components.html.erb b/apps/workbench/app/views/pipeline_instances/_show_components.html.erb
index 6d6a8b1..efd36d2 100644
--- a/apps/workbench/app/views/pipeline_instances/_show_components.html.erb
+++ b/apps/workbench/app/views/pipeline_instances/_show_components.html.erb
@@ -1,9 +1,4 @@
-<% content_for :css do %>
-
-<% end %>
-
 <% template = PipelineTemplate.find(@object.pipeline_template_uuid) rescue nil %>
-
 <%= content_for :content_top do %>
   <h2>
     <%= render_editable_attribute @object, 'name', nil %>
@@ -16,96 +11,112 @@
   <% end %>
 <% end %>
 
-<% pipeline_job_uuids = [] %>
+<% content_for :tab_line_buttons do %>
+  <%= link_to(copy_pipeline_instance_path('id' => @object.uuid, 'pipeline_instance[state]' => 'New'),
+      class: 'btn btn-primary',
+      #data: {toggle: :tooltip, placement: :top}, title: 'copy and modify',
+      method: :post,
+      ) do %>
+    Clone and edit <i class="fa fa-fw fa-copy"></i>
+  <% end %>
+<% end %>
 
-<% if !@object.state.in? ['New', 'Ready', 'Paused'] %>
-<table class="table pipeline-components-table">
-  <colgroup>
-    <col style="width: 15%" />
-    <col style="width: 20%" />
-    <col style="width: 12%" />
-    <col style="width: 12%" />
-    <col style="width: 45%" />
-  </colgroup>
-  <thead>
-    <tr>
-      <th>
-        component
-      </th><th>
-        script, version
-      </th><th>
-        job
-        <%# format:'js' here helps browsers avoid using the cached js
-        content in html context (e.g., duplicate tab -> see
-        javascript) %>
-        <%= link_to '(refresh)', {format: :js}, {class: 'refresh hide', remote: true, method: 'get'} %>
-      </th><th>
-      </th><th>
-        output
-      </th>
-    </tr>
-  </thead>
-  <tbody>
-    <% render_pipeline_jobs.each do |pj| %>
-      <% if pj[:job].andand[:uuid]
-           pipeline_job_uuids << pj[:job][:uuid]
-         end %>
-    <tr>
-      <td>
-        <%= pj[:name] %>
-      </td><td>
-        <%= pj[:script] %>
-        <br /><span class="deemphasize"><%= pj[:script_version] %></span>
-      </td><td>
-        <%= pj[:progress_bar] %>
-        <% if @object.state == 'Complete' || @object.state == 'Failed' %>
-          <% if pj[:job].andand[:uuid] %>
-            <span class="deemphasize">
-            <%= link_to("..."+pj[:job][:uuid].last(15), job_url(id: pj[:job][:uuid])) %>
-            </span>
+<% if !@object.state.in? ['New', 'Ready'] %>
 
-            <% current_job = Job.find(pj[:job][:uuid]) rescue nil %>
-            <% if current_job.andand[:log] %>
-              <% fixup = /([a-f0-9]{32}\+\d+)(\+?.*)/.match(current_job[:log])%>
-              <% Collection.limit(1).where(uuid: fixup[1]).each do |c| %>
-                <% c.files.each do |file| %>
-                  <br/><span class="deemphasize">
-                  <a href="<%= collection_path(current_job[:log]) %>/<%= file[1] %>?disposition=inline&size=<%= file[2] %>">log</a>
-                  </span>
+  <% if @object.state.in? ['RunningOnClient', 'RunningOnServer'] %>
+    <% content_for :tab_line_buttons do %>
+      <%= link_to(url_for('pipeline_instance[state]' => 'Paused'),
+          class: 'btn btn-primary run-pipeline-button',
+          method: :patch
+          ) do %>
+        Stop <i class="fa fa-fw fa-stop"></i>
+      <% end %>
+    <% end %>
+  <% end %>
+
+  <% pipeline_job_uuids = [] %>
+
+  <div class="pull-right">
+    Current state: <span class="badge badge-info"><%= @object.state.sub('OnServer', '') %></span> 
+  </div>
+
+  <table class="table pipeline-components-table">
+    <colgroup>
+      <col style="width: 15%" />
+      <col style="width: 20%" />
+      <col style="width: 12%" />
+      <col style="width: 12%" />
+      <col style="width: 45%" />
+    </colgroup>
+    <thead>
+      <tr>
+        <th>
+          component
+        </th><th>
+          script, version
+        </th><th>
+          job
+          <%# format:'js' here helps browsers avoid using the cached js
+          content in html context (e.g., duplicate tab -> see
+          javascript) %>
+          <%= link_to '(refresh)', {format: :js}, {class: 'refresh hide', remote: true, method: 'get'} %>
+        </th><th>
+        </th><th>
+          output
+        </th>
+      </tr>
+    </thead>
+    <tbody>
+      <% render_pipeline_jobs.each do |pj| %>
+        <% if pj[:job].andand[:uuid]
+             pipeline_job_uuids << pj[:job][:uuid]
+           end %>
+      <tr>
+        <td>
+          <%= pj[:name] %>
+        </td><td>
+          <%= pj[:script] %>
+          <br /><span class="deemphasize"><%= pj[:script_version] %></span>
+        </td><td>
+          <%= pj[:progress_bar] %>
+          <% if @object.state == 'Complete' || @object.state == 'Failed' %>
+            <% if pj[:job].andand[:uuid] %>
+              <span class="deemphasize">
+              <%= link_to("..."+pj[:job][:uuid].last(15), job_url(id: pj[:job][:uuid])) %>
+              </span>
+
+              <% current_job = Job.find(pj[:job][:uuid]) rescue nil %>
+              <% if current_job.andand[:log] %>
+                <% fixup = /([a-f0-9]{32}\+\d+)(\+?.*)/.match(current_job[:log])%>
+                <% Collection.limit(1).where(uuid: fixup[1]).each do |c| %>
+                  <% c.files.each do |file| %>
+                    <br/><span class="deemphasize">
+                    <a href="<%= collection_path(current_job[:log]) %>/<%= file[1] %>?disposition=inline&size=<%= file[2] %>">log</a>
+                    </span>
+                  <% end %>
                 <% end %>
               <% end %>
             <% end %>
           <% end %>
-        <% end %>
-      </td><td>
-        <%= render(partial: 'job_status_label',
-                               locals: { :j => pj[:job] }) %>
-      </td><td>
-        <%= link_to_if_arvados_object pj[:output], {:thumbnail => true} %>
-      </td>
-    </tr>
-    <% end %>
-  </tbody>
-  <tfoot>
-    <tr><td colspan="5"></td></tr>
-  </tfoot>
-</table>
-
-<% if @object.state == 'RunningOnServer' || @object.state == 'RunningOnClient' %>
-<% content_for :js do %>
-setInterval(function(){$('a.refresh').click()}, 15000);
-<% end %>
-
-<% content_for :tab_line_buttons do %>
-  <%= form_tag @object, :method => :put do |f| %>
+        </td><td>
+          <%= render(partial: 'job_status_label',
+                                 locals: { :j => pj[:job] }) %>
+        </td><td>
+          <%= link_to_if_arvados_object pj[:output], {:thumbnail => true} %>
+        </td>
+      </tr>
+      <% end %>
+    </tbody>
+    <tfoot>
+      <tr><td colspan="5"></td></tr>
+    </tfoot>
+  </table>
 
-    <%= hidden_field @object.class.to_s.underscore.singularize.to_sym, :state, :value => 'Paused' %>
+  <% if @object.state.in? %w(RunningOnServer RunningOnClient) %>
 
-    <%= button_tag({class: 'btn btn-primary pull-right run-pipeline-button'}) do %>
-      Stop <i class="fa fa-fw fa-stop"></i>
+    <% content_for :js do %>
+      setInterval(function(){$('a.refresh').click()}, 15000);
     <% end %>
-  <% end %>
-<% end %>
 
     <% if !pipeline_job_uuids.empty? %>
       <h4>Log messages from running jobs</h4>
@@ -117,21 +128,22 @@ setInterval(function(){$('a.refresh').click()}, 15000);
       </div>
       <div class="arv-log-event-listener arv-log-event-handler-append-logs" id="pipeline_event_log_div" data-object-uuids="<%=pipeline_job_uuids.join(" ")%>"/>
     <% end %>
+
   <% end %>
 
-<% else %>    <%# State new or ready or paused %>
-  <% if @object.state == 'New' %>
+<% else %>
+  <%# state is either New or Ready %>
+
+  <% if @object.state.in? %w(New Ready) %>
     <p><i>Here are all of the pipeline's components (jobs that will need to run in order to complete the pipeline). If you know what you're doing (or you're experimenting) you can modify these parameters before starting the pipeline. Usually, you only need to edit the settings presented on the "Inputs" tab above.</i></p>
   <% end %>
 
   <% content_for :tab_line_buttons do %>
-    <%= form_tag @object, :method => :put do |f| %>
-
-      <%= hidden_field @object.class.to_s.underscore.singularize.to_sym, :state, :value => 'RunningOnServer' %>
-
-      <%= button_tag({class: 'btn btn-primary pull-right run-pipeline-button'}) do %>
-        Run <i class="fa fa-fw fa-play"></i>
-      <% end %>
+    <%= link_to(url_for('pipeline_instance[state]' => 'RunningOnServer'),
+        class: 'btn btn-primary run-pipeline-button',
+        method: :patch
+        ) do %>
+      Run <i class="fa fa-fw fa-play"></i>
     <% end %>
   <% end %>
 
diff --git a/apps/workbench/app/views/pipeline_instances/_show_inputs.html.erb b/apps/workbench/app/views/pipeline_instances/_show_inputs.html.erb
index 556e9f8..5a86728 100644
--- a/apps/workbench/app/views/pipeline_instances/_show_inputs.html.erb
+++ b/apps/workbench/app/views/pipeline_instances/_show_inputs.html.erb
@@ -36,11 +36,11 @@
   <p><i>Provide <%= n_inputs > 1 ? 'values' : 'a value' %> for the following <%= n_inputs > 1 ? 'parameters' : 'parameter' %>, then click the "Run" button to start the pipeline.</i></p>
   <%= content_for :pi_input_form %>
 
-  <%= form_tag @object, :method => :put do |f| %>
-    <%= hidden_field @object.class.to_s.underscore.singularize.to_sym, :state, :value => 'RunningOnServer' %>
-    <%= button_tag({class: 'btn btn-primary run-pipeline-button'}) do %>
-      Run <i class="fa fa-fw fa-play"></i>
-    <% end %>
+  <%= link_to(url_for('pipeline_instance[state]' => 'RunningOnServer'),
+      class: 'btn btn-primary run-pipeline-button',
+      method: :patch
+      ) do %>
+    Run <i class="fa fa-fw fa-play"></i>
   <% end %>
 
 <% end %>
diff --git a/apps/workbench/app/views/pipeline_templates/_choose_rows.html.erb b/apps/workbench/app/views/pipeline_templates/_choose_rows.html.erb
index 2f51d5a..6ffd6ae 100644
--- a/apps/workbench/app/views/pipeline_templates/_choose_rows.html.erb
+++ b/apps/workbench/app/views/pipeline_templates/_choose_rows.html.erb
@@ -1,10 +1,10 @@
 <% @objects.each do |object| %>
   <div class="row filterable selectable <%= 'multiple' if multiple %>" data-object-uuid="<%= object.uuid %>">
-    <div class="col-md-6" style="overflow-x:hidden">
+    <div class="col-sm-12" style="overflow-x:hidden">
       <i class="fa fa-fw fa-gear"></i>
       <%= object.name %>
     </div>
-    <div class="col-md-6 arv-description-in-table">
+    <div class="col-sm-11 col-sm-push-1 arv-description-in-table">
       <%= object.description %>
     </div>
   </div>
diff --git a/apps/workbench/config/routes.rb b/apps/workbench/config/routes.rb
index 94e2a11..971b0ce 100644
--- a/apps/workbench/config/routes.rb
+++ b/apps/workbench/config/routes.rb
@@ -40,6 +40,7 @@ ArvadosWorkbench::Application.routes.draw do
   end
   resources :pipeline_instances do
     get 'compare', on: :collection
+    post 'copy', on: :member
   end
   resources :links
   get '/collections/graph' => 'collections#graph'

commit 747efcd9371118c2db9c265c13ce399fc4b6c96b
Author: Tom Clegg <tom at curoverse.com>
Date:   Tue Jun 3 01:00:39 2014 -0400

    2872: Add free text search in chooser.

diff --git a/apps/workbench/app/assets/javascripts/folders.js b/apps/workbench/app/assets/javascripts/filterable.js
similarity index 65%
rename from apps/workbench/app/assets/javascripts/folders.js
rename to apps/workbench/app/assets/javascripts/filterable.js
index 73dcfbb..8bb8085 100644
--- a/apps/workbench/app/assets/javascripts/folders.js
+++ b/apps/workbench/app/assets/javascripts/filterable.js
@@ -1,14 +1,14 @@
 $(document).
-    on('paste keyup change', 'input.search-folder-contents', function() {
+    on('paste keyup change', 'input[type=text].filterable-control', function() {
         var q = new RegExp($(this).val(), 'i');
-        $($(this).attr('data-search-target')).find('tbody').
+        $($(this).attr('data-filterable-target')).
+            addClass('filterable-container').
             data('q', q).
             trigger('refresh');
-    }).on('refresh', 'tbody', function() {
+    }).on('refresh', '.filterable-container', function() {
         var q = $(this).data('q');
         var filters = $(this).data('filters');
-        $('tr', this).hide();
-        $('tr', this).filter(function() {
+        $('.filterable', this).hide().filter(function() {
             var $row = $(this);
             var pass = true;
             if (q && !$row.text().match(q))
@@ -27,16 +27,16 @@ $(document).
             return pass;
         }).show();
         $('.infinite-scroller').trigger('scroll');
-    }).on('change', 'select[data-filter-rows-by]', function() {
+    }).on('change', 'select.filterable-control', function() {
         var val = $(this).val();
-        var filterby = $(this).attr('data-filter-rows-by');
-        var $target = $($(this).attr('data-filter-target'));
+        var filterby = $(this).attr('data-filterable-attribute');
+        var $target = $($(this).attr('data-filterable-target')).
+            addClass('filterable-container');
         var filters = $target.data('filters') || {};
         filters[filterby] = val;
         $target.
             data('filters', filters).
             trigger('refresh');
     }).on('ajax:complete', function() {
-        $('input.search-folder-contents').trigger('change');
-        $('select[data-filter-rows-by]').trigger('change');
+        $('.filterable-control').trigger('change');
     });
diff --git a/apps/workbench/app/assets/stylesheets/select_modal.css.scss b/apps/workbench/app/assets/stylesheets/select_modal.css.scss
index f97110a..5aab669 100644
--- a/apps/workbench/app/assets/stylesheets/select_modal.css.scss
+++ b/apps/workbench/app/assets/stylesheets/select_modal.css.scss
@@ -7,9 +7,9 @@
     background: #d9edf7;
 }
 .selectable.active,
-.selectable.active a,
+.selectable.active *,
 .selectable.active:hover,
-.selectable.active:hover a {
+.selectable.active:hover * {
     background: #428bca;
     color: #fff;
 }
diff --git a/apps/workbench/app/views/application/_choose.html.erb b/apps/workbench/app/views/application/_choose.html.erb
index 94ed8e6..4708ac5 100644
--- a/apps/workbench/app/views/application/_choose.html.erb
+++ b/apps/workbench/app/views/application/_choose.html.erb
@@ -1,14 +1,21 @@
-<div class="modal">
-  <div class="modal-dialog">
+<div class="modal arv-choose">
+  <div class="modal-dialog" style="width:80%">
     <div class="modal-content">
-
       <div class="modal-header">
         <button type="button" class="close" onClick="reset_form()" data-dismiss="modal" aria-hidden="true">×</button>
         <h4 class="modal-title"><%= params[:title] || "Choose #{@objects.first.class_for_display}" %></h4>
       </div>
-
       <div class="modal-body">
-        <div class="container-fluid arv-folder-list selectable-container" style="height: 15em; overflow-y: scroll" data-infinite-scroller="#choose-scroll" id="choose-scroll" data-infinite-content-href="<%= @next_page_href %>">
+        <div class="container-fluid">
+          <div class="row">
+            <div class="col-sm-6">
+            </div>
+            <div class="col-sm-6">
+              <input type="text" class="form-control filterable-control" placeholder="Search" data-filterable-target=".modal.arv-choose .selectable-container"/>
+            </div>
+          </div>
+        </div>
+        <div class="container-fluid arv-filterable-list selectable-container" style="height: 20em; overflow-y: scroll" data-infinite-scroller="#choose-scroll" id="choose-scroll" data-infinite-content-href="<%= @next_page_href %>">
           <%= render partial: 'choose_rows', locals: {multiple: multiple} %>
         </div>
       </div>
diff --git a/apps/workbench/app/views/collections/_choose_rows.html.erb b/apps/workbench/app/views/collections/_choose_rows.html.erb
index 55e6451..88d71d2 100644
--- a/apps/workbench/app/views/collections/_choose_rows.html.erb
+++ b/apps/workbench/app/views/collections/_choose_rows.html.erb
@@ -1,10 +1,10 @@
 <% @name_links.each do |name_link| %>
-  <div class="row selectable <%= 'multiple' if multiple %>" data-object-uuid="<%= name_link.uuid %>">
-    <div class="col-lg-12" style="overflow-x:hidden">
+  <div class="row filterable selectable <%= 'multiple' if multiple %>" data-object-uuid="<%= name_link.uuid %>">
+    <div class="col-sm-12" style="overflow-x:hidden">
       <i class="fa fa-fw fa-archive"></i>
       <%= name_link.name %>
     </div>
-    <div class="col-lg-12 arv-description-in-table">
+    <div class="col-sm-11 col-sm-push-1 arv-description-in-table">
       <%= render_controller_partial(
           'show_object_description_cell.html',
           controller_name: 'collections',
diff --git a/apps/workbench/app/views/folders/_show_contents.html.erb b/apps/workbench/app/views/folders/_show_contents.html.erb
index 450ba29..68237f8 100644
--- a/apps/workbench/app/views/folders/_show_contents.html.erb
+++ b/apps/workbench/app/views/folders/_show_contents.html.erb
@@ -48,7 +48,7 @@
     <div class="col-md-4">
       <form class="form-inline" role="form">
         Show:
-        <select class="form-control" data-filter-rows-by="data-kind" data-filter-target="table.arv-index.arv-folder-contents tbody">
+        <select class="form-control filterable-control" data-filterable-attribute="data-kind" data-filterable-target="table.arv-index.arv-folder-contents tbody">
           <option value="">Everything</option>
           <option value="arvados#collection">Data</option>
           <option value="arvados#pipelineInstance arvados#job">Compute jobs</option>
@@ -62,7 +62,7 @@
       </form>
     </div>
     <div class="col-md-4">
-      <input type="text" class="form-control search-folder-contents" placeholder="Search folder contents" data-search-target=".arv-index.arv-folder-contents"/>
+      <input type="text" class="form-control filterable-control" placeholder="Search folder contents" data-filterable-target="table.arv-index.arv-folder-contents tbody"/>
     </div>
   </div>
 </div>
diff --git a/apps/workbench/app/views/pipeline_templates/_choose_rows.html.erb b/apps/workbench/app/views/pipeline_templates/_choose_rows.html.erb
index 0e8c32f..2f51d5a 100644
--- a/apps/workbench/app/views/pipeline_templates/_choose_rows.html.erb
+++ b/apps/workbench/app/views/pipeline_templates/_choose_rows.html.erb
@@ -1,5 +1,5 @@
 <% @objects.each do |object| %>
-  <div class="row selectable <%= 'multiple' if multiple %>" data-object-uuid="<%= object.uuid %>">
+  <div class="row filterable selectable <%= 'multiple' if multiple %>" data-object-uuid="<%= object.uuid %>">
     <div class="col-md-6" style="overflow-x:hidden">
       <i class="fa fa-fw fa-gear"></i>
       <%= object.name %>

commit be778bdec0bb03b08699c6ee1343a0e791f5dfbf
Author: Tom Clegg <tom at curoverse.com>
Date:   Mon Jun 2 12:04:07 2014 -0400

    2872: Fix up tests

diff --git a/apps/workbench/test/integration/users_test.rb b/apps/workbench/test/integration/users_test.rb
index 7be12d7..b7bb49a 100644
--- a/apps/workbench/test/integration/users_test.rb
+++ b/apps/workbench/test/integration/users_test.rb
@@ -25,7 +25,7 @@ class UsersTest < ActionDispatch::IntegrationTest
     end
 
     find('tr', text: 'zzzzz-tpzed-xurymjxw79nv3jz').
-      find('a,button', text: 'Show').
+      find('a[data-original-title=show]').
       click
     assert page.has_text? 'Attributes'
     assert page.has_text? 'Metadata'
@@ -80,7 +80,7 @@ class UsersTest < ActionDispatch::IntegrationTest
 
     # go to the new user's page
     find('tr', text: new_user_uuid).
-      find('a,button', text: 'Show').
+      find('a[data-original-title=show]').
       click
 
     assert page.has_text? 'modified_by_user_uuid'
@@ -107,7 +107,7 @@ class UsersTest < ActionDispatch::IntegrationTest
 
     # click on active user
     find('tr', text: 'zzzzz-tpzed-xurymjxw79nv3jz').
-      find('a,button', text: 'Show').
+      find('a[data-original-title=show]').
       click
 
     # Setup user
@@ -167,7 +167,7 @@ class UsersTest < ActionDispatch::IntegrationTest
 
     # click on active user
     find('tr', text: 'zzzzz-tpzed-xurymjxw79nv3jz').
-      find('a,button', text: 'Show').
+      find('a[data-original-title=show]').
       click
 
     # Verify that is_active is set
@@ -193,6 +193,7 @@ class UsersTest < ActionDispatch::IntegrationTest
       assert_equal "false", text, "Expected user's is_active to be false after unsetup"
     end
 
+    click_link 'Advanced'
     click_link 'Metadata'
     assert !(page.has_text? '(Repository: test_repo)')
     assert !(page.has_text? '(Repository: second_test_repo)')
@@ -213,6 +214,7 @@ class UsersTest < ActionDispatch::IntegrationTest
 
     assert page.has_text? 'modified_by_client_uuid'
 
+    click_link 'Advanced'
     click_link 'Metadata'
     assert page.has_text? '(Repository: second_test_repo)'
     assert page.has_text? '(VirtualMachine: testvm.shell)'
diff --git a/apps/workbench/test/integration/virtual_machines_test.rb b/apps/workbench/test/integration/virtual_machines_test.rb
index 7a40d0d..121941e 100644
--- a/apps/workbench/test/integration/virtual_machines_test.rb
+++ b/apps/workbench/test/integration/virtual_machines_test.rb
@@ -9,7 +9,7 @@ class VirtualMachinesTest < ActionDispatch::IntegrationTest
     assert page.has_text? 'testvm.shell'
     click_on 'Add a new virtual machine'
     find('tr', text: 'hostname').
-      find('span', text: 'none').click
+      find('a[data-original-title=edit]').click
     assert page.has_text? 'Update hostname'
     fill_in 'editable-text', with: 'testname'
     click_button 'editable-submit'

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list