[ARVADOS] created: 1.1.0-64-g6561762

Git user git at public.curoverse.com
Thu Oct 19 16:47:37 EDT 2017


        at  656176226eeb75d24c17de792cc090e4862c46f5 (commit)


commit 656176226eeb75d24c17de792cc090e4862c46f5
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Oct 9 16:41:05 2017 -0400

    12125: Can search within trashed projects.
    
    Don't show items within trashed projects in the complete list, but do make it
    possible to search for them.
    
    Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz at veritasgenetics.com>

diff --git a/apps/workbench/app/assets/stylesheets/application.css.scss b/apps/workbench/app/assets/stylesheets/application.css.scss
index 31f06e9..32d8025 100644
--- a/apps/workbench/app/assets/stylesheets/application.css.scss
+++ b/apps/workbench/app/assets/stylesheets/application.css.scss
@@ -203,6 +203,10 @@ li.notification {
     padding: 10px;
 }
 
+td.trash-project-msg {
+    white-space: normal;
+}
+
 // See HeaderRowFixer in application.js
 table.table-fixed-header-row {
     width: 100%;
diff --git a/apps/workbench/app/controllers/trash_items_controller.rb b/apps/workbench/app/controllers/trash_items_controller.rb
index 797ccc3..7d6e143 100644
--- a/apps/workbench/app/controllers/trash_items_controller.rb
+++ b/apps/workbench/app/controllers/trash_items_controller.rb
@@ -66,31 +66,33 @@ class TrashItemsController < ApplicationController
 
     # API server index doesn't return manifest_text by default, but our
     # callers want it unless otherwise specified.
-    @select ||= query_on.columns.map(&:name) - %w(id updated_at)
+    #@select ||= query_on.columns.map(&:name) - %w(id updated_at)
     limit = if params[:limit] then params[:limit].to_i else 100 end
     offset = if params[:offset] then params[:offset].to_i else 0 end
 
     @objects = []
     while !@objects.any?
-      base_search = query_on.select(@select).include_trash(true)
-      base_search = base_search.filter(params[:filters]) if params[:filters]
+      base_search = query_on
 
       if !last_mod_at.nil?
         base_search = base_search.filter([["modified_at", "<=", last_mod_at], ["uuid", "not in", last_uuids]])
       end
 
-      if params[:search].andand.length.andand > 0
-        tags = Link.where(any: ['contains', params[:search]])
-        base_search = base_search.limit(limit).offset(offset)
-        @objects = (base_search.where(uuid: tags.collect(&:head_uuid)) |
-                    base_search.where(any: ['contains', params[:search]])).
-                   uniq { |c| c.uuid }
+      base_search = base_search.include_trash(true).limit(limit).offset(offset)
+
+      if params[:filters].andand.length.andand > 0
+        tags = Link.filter(params[:filters])
+        tagged = []
+        if tags.results.length > 0
+          tagged = query_on.include_trash(true).where(uuid: tags.collect(&:head_uuid))
+        end
+        @objects = (tagged | base_search.filter(params[:filters])).uniq(&:uuid)
       else
-        @objects = base_search.limit(limit).offset(offset)
+        @objects = base_search.where(is_trashed: true)
       end
 
       if @objects.any?
-        owner_uuids = @objects.collect {|item| item.owner_uuid}.uniq
+        owner_uuids = @objects.collect(&:owner_uuid).uniq
         @owners = {}
         @not_trashed = {}
         Group.filter([["uuid", "in", owner_uuids]]).include_trash(true).each do |grp|
@@ -98,12 +100,9 @@ class TrashItemsController < ApplicationController
         end
         User.filter([["uuid", "in", owner_uuids]]).include_trash(true).each do |grp|
           @owners[grp.uuid] = grp
-        end
-
-        Group.filter([["uuid", "in", owner_uuids]]).select([:uuid]).each do |grp|
           @not_trashed[grp.uuid] = true
         end
-        User.filter([["uuid", "in", owner_uuids]]).select([:uuid]).each do |grp|
+        Group.filter([["uuid", "in", owner_uuids]]).select([:uuid]).each do |grp|
           @not_trashed[grp.uuid] = true
         end
       else
diff --git a/apps/workbench/app/views/application/404.html.erb b/apps/workbench/app/views/application/404.html.erb
index ee72ccd..2d9b5cf 100644
--- a/apps/workbench/app/views/application/404.html.erb
+++ b/apps/workbench/app/views/application/404.html.erb
@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0 %>
 
 <%
    if (controller.andand.action_name == 'show') and params[:uuid]
-     check_trash = controller.model_class.include_trash(true).where(uuid: params[:uuid], is_trashed: true)
+     check_trash = controller.model_class.include_trash(true).where(uuid: params[:uuid])
      class_name = controller.model_class.to_s.underscore
      class_name_h = class_name.humanize(capitalize: false)
      req_item = safe_join([class_name_h, " with UUID ",
@@ -21,18 +21,27 @@ SPDX-License-Identifier: AGPL-3.0 %>
 
     <p>The <%= req_item %> is in the trash.
 
-    <% object = check_trash.first %>
-    <% if object.editable? %>
-      <% msg = "Untrash '" + if !object.name.blank? then object.name else object.uuid end + "'?" %>
-      <%= link_to({action: 'untrash_items', selection: [object.uuid], controller: :trash_items}, remote: true, method: :post,
+      <% object = check_trash.first %>
+
+      <% if object.is_trashed
+         untrash_object = object
+         else
+       end %>
+
+        <% if untrash_object.editable? %>
+          <% msg = "Untrash '" + if !untrash_object.name.blank? then untrash_object.name else untrash_object.uuid end + "'?" %>
+          <%= link_to({action: 'untrash_items', selection: [untrash_object.uuid], controller: :trash_items}, remote: true, method: :post,
         title: "Untrash", style: 'cursor: pointer;') do %>
 
-      <% end %>
+          <% end %>
 
-      <%= form_tag url_for({action: 'untrash_items', controller: :trash_items}), {method: :post} %>
-      <%= hidden_field_tag :selection, [object.uuid] %>
-      <button type="submit">Click here to untrash this item <i class="fa fa-fw fa-recycle"></i></button>
-    <% end %>
+          <%= form_tag url_for({action: 'untrash_items', controller: :trash_items}), {method: :post} %>
+          <%= hidden_field_tag :selection, [untrash_object.uuid] %>
+          <button type="submit">Click here to untrash this item <i class="fa fa-fw fa-recycle"></i></button>
+        <% end %>
+      <% else %>
+        <% %>
+      <% end %>
     </p>
 
   <% else %>
diff --git a/apps/workbench/app/views/trash_items/_show_trash_rows.html.erb b/apps/workbench/app/views/trash_items/_show_trash_rows.html.erb
new file mode 100644
index 0000000..ee61e45
--- /dev/null
+++ b/apps/workbench/app/views/trash_items/_show_trash_rows.html.erb
@@ -0,0 +1,49 @@
+<%# Copyright (C) The Arvados Authors. All rights reserved.
+
+SPDX-License-Identifier: AGPL-3.0 %>
+
+<% @objects.each do |obj| %>
+  <tr data-object-uuid="<%= obj.uuid %>" data-kind="<%= obj.kind %>" >
+    <td>
+      <% if obj.editable? %>
+        <%= check_box_tag 'uuids[]', obj.uuid, false, :class => 'persistent-selection', style: 'cursor: pointer;' %>
+      <% end %>
+    </td>
+    <td>
+      <%= if !obj.name.blank? then obj.name else obj.uuid end %>
+    </td>
+    <% if obj.is_trashed %>
+      <td>
+        <%= link_to_if_arvados_object @owners[obj.owner_uuid], friendly_name: true %>
+      </td>
+
+      <td>
+        <% if obj.trash_at %>
+          <%= render_localized_date(obj.trash_at)  %>
+        <% end %>
+        <br />
+        <% if obj.delete_at %>
+          <%= render_localized_date(obj.delete_at) %>
+        <% end %>
+      </td>
+    <% else %>
+      <td colspan="2" class="trash-project-msg">
+        <%= link_to_if_arvados_object @owners[obj.owner_uuid], friendly_name: true %>
+        <br>
+        This item is contained within a trashed project.  You must untrash the parent project to recover it.
+      </td>
+    <% end %>
+    <td>
+      <%= obj.uuid %>
+      <% if defined? obj.portable_data_hash %>
+        <br /><%= obj.portable_data_hash %>
+      <% end %>
+    </td>
+    <td>
+      <% if obj.is_trashed %>
+        <%= render partial: 'untrash_item', locals: {object:obj} %>
+      <% end %>
+    </td>
+  </tr>
+
+<% end %>
diff --git a/apps/workbench/app/views/trash_items/_show_trashed_collection_rows.html.erb b/apps/workbench/app/views/trash_items/_show_trashed_collection_rows.html.erb
deleted file mode 100644
index 443c7d4..0000000
--- a/apps/workbench/app/views/trash_items/_show_trashed_collection_rows.html.erb
+++ /dev/null
@@ -1,50 +0,0 @@
-<%# Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: AGPL-3.0 %>
-
-<% @objects.each do |obj| %>
-    <tr data-object-uuid="<%= obj.uuid %>" data-kind="<%= obj.kind %>" >
-      <td>
-        <% if obj.editable? %>
-          <%= check_box_tag 'uuids[]', obj.uuid, false, :class => 'persistent-selection', style: 'cursor: pointer;' %>
-        <% end %>
-      </td>
-      <td>
-        <%= if !obj.name.blank? then obj.name else obj.uuid end %>
-      </td>
-      <td>
-        <% if obj.trash_at %>
-          <%= render_localized_date(obj.trash_at)  %>
-        <% end %>
-        <br />
-        <% if obj.delete_at %>
-          <%= render_localized_date(obj.delete_at) %>
-        <% end %>
-      </td>
-      <td>
-        <%= link_to_if_arvados_object @owners[obj.owner_uuid], friendly_name: true %>
-        <% if @not_trashed[obj.owner_uuid].nil? %>
-          (trashed)
-        <% end %>
-      </td>
-      <td>
-        <%= obj.uuid %><br /><%= obj.portable_data_hash %>
-      </td>
-      <td>
-        <% for i in (0..[2, obj.files.length-1].min) %>
-          <% file = obj.files[i] %>
-          <% file_path = "#{file[0]}/#{file[1]}" %>
-          <%= file_path %><br />
-        <% end %>
-        <% if obj.files.length > 3 %>
-          <%= "(#{obj.files.length-3} more files)" %>
-        <% end %>
-      </td>
-      <td>
-        <% if @not_trashed[obj.owner_uuid].nil? %>
-        <% else %>
-          <%= render partial: 'untrash_item', locals: {object:obj} %>
-        <% end %>
-      </td>
-    </tr>
-<% end %>
diff --git a/apps/workbench/app/views/trash_items/_show_trashed_collection_rows.html.erb b/apps/workbench/app/views/trash_items/_show_trashed_collection_rows.html.erb
new file mode 120000
index 0000000..6841b57
--- /dev/null
+++ b/apps/workbench/app/views/trash_items/_show_trashed_collection_rows.html.erb
@@ -0,0 +1 @@
+_show_trash_rows.html.erb
\ No newline at end of file
diff --git a/apps/workbench/app/views/trash_items/_show_trashed_collections.html.erb b/apps/workbench/app/views/trash_items/_show_trashed_collections.html.erb
index 0cb941c..a2ef087 100644
--- a/apps/workbench/app/views/trash_items/_show_trashed_collections.html.erb
+++ b/apps/workbench/app/views/trash_items/_show_trashed_collections.html.erb
@@ -29,12 +29,11 @@ SPDX-License-Identifier: AGPL-3.0 %>
   <div>
     <table id="trash-index" class="topalign table table-condensed table-fixedlayout">
       <colgroup>
-        <col width="2%" />
-        <col width="20%" />
-        <col width="13%" />
-        <col width="15%" />
-        <col width="20%" />
+        <col width="5%" />
+        <col width="16%" />
         <col width="25%" />
+        <col width="20%" />
+        <col width="29%" />
         <col width="5%" />
       </colgroup>
 
@@ -42,10 +41,9 @@ SPDX-License-Identifier: AGPL-3.0 %>
         <tr class="contain-align-left">
           <th></th>
           <th>Name</th>
-          <th>Date trashed /<br />to be deleted</th>
           <th>Parent project</th>
+          <th>Date trashed /<br />to be deleted</th>
           <th>UUID /<br />Content address (PDH)</th>
-          <th>Contents</th>
           <th></th>
         </tr>
       </thead>
diff --git a/apps/workbench/app/views/trash_items/_show_trashed_project_rows.html.erb b/apps/workbench/app/views/trash_items/_show_trashed_project_rows.html.erb
deleted file mode 100644
index ef3a478..0000000
--- a/apps/workbench/app/views/trash_items/_show_trashed_project_rows.html.erb
+++ /dev/null
@@ -1,34 +0,0 @@
-<%# Copyright (C) The Arvados Authors. All rights reserved.
-
-SPDX-License-Identifier: AGPL-3.0 %>
-
-<% @objects.each do |obj| %>
-  <tr data-object-uuid="<%= obj.uuid %>" data-kind="<%= obj.kind %>" >
-      <td>
-        <% if obj.editable? %>
-          <%= check_box_tag 'uuids[]', obj.uuid, false, :class => 'persistent-selection', style: 'cursor: pointer;' %>
-        <% end %>
-      </td>
-      <td>
-        <%= if !obj.name.blank? then obj.name else obj.uuid end %>
-      </td>
-      <td>
-        <% if obj.trash_at %>
-          <%= render_localized_date(obj.trash_at)  %>
-        <% end %>
-        <br />
-        <% if obj.delete_at %>
-          <%= render_localized_date(obj.delete_at) %>
-        <% end %>
-      </td>
-      <td>
-        <%= link_to_if_arvados_object obj.owner_uuid, friendly_name: true %>
-      </td>
-      <td>
-        <%= obj.uuid %>
-      </td>
-      <td>
-        <%= render partial: 'untrash_item', locals: {object:obj} %>
-      </td>
-    </tr>
-<% end %>
diff --git a/apps/workbench/app/views/trash_items/_show_trashed_project_rows.html.erb b/apps/workbench/app/views/trash_items/_show_trashed_project_rows.html.erb
new file mode 120000
index 0000000..6841b57
--- /dev/null
+++ b/apps/workbench/app/views/trash_items/_show_trashed_project_rows.html.erb
@@ -0,0 +1 @@
+_show_trash_rows.html.erb
\ No newline at end of file
diff --git a/apps/workbench/app/views/trash_items/_show_trashed_projects.html.erb b/apps/workbench/app/views/trash_items/_show_trashed_projects.html.erb
index 2882814..ced1990 100644
--- a/apps/workbench/app/views/trash_items/_show_trashed_projects.html.erb
+++ b/apps/workbench/app/views/trash_items/_show_trashed_projects.html.erb
@@ -29,20 +29,20 @@ SPDX-License-Identifier: AGPL-3.0 %>
   <div>
     <table id="trash-index" class="topalign table table-condensed table-fixedlayout">
       <colgroup>
-        <col width="10%" />
-        <col width="21%" />
-        <col width="21%" />
-        <col width="21%" />
-        <col width="21%" />
-        <col width="6%" />
+        <col width="5%" />
+        <col width="16%" />
+        <col width="25%" />
+        <col width="20%" />
+        <col width="29%" />
+        <col width="5%" />
       </colgroup>
 
       <thead>
         <tr class="contain-align-left">
           <th></th>
           <th>Name</th>
-          <th>Date trashed /<br />to be deleted</th>
           <th>Parent project</th>
+          <th>Date trashed /<br />to be deleted</th>
           <th>UUID</th>
           <th></th>
         </tr>
diff --git a/services/api/lib/trashable.rb b/services/api/lib/trashable.rb
index 38ebaf7..9687962 100644
--- a/services/api/lib/trashable.rb
+++ b/services/api/lib/trashable.rb
@@ -120,7 +120,7 @@ module TrashableController
         @object.save!
       end
     else
-      raise InvalidStateTransitionError
+      raise ArvadosModel::InvalidStateTransitionError.new("Item is not trashed, cannot untrash")
     end
     show
   end

commit 98aa37e898eca8021206b838b45cbe66bfa9e4e3
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Fri Oct 6 19:04:43 2017 -0400

    12125: Displaying only trashed collections sort of works.
    
    Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz at veritasgenetics.com>

diff --git a/apps/workbench/app/controllers/trash_items_controller.rb b/apps/workbench/app/controllers/trash_items_controller.rb
index 4aac884..797ccc3 100644
--- a/apps/workbench/app/controllers/trash_items_controller.rb
+++ b/apps/workbench/app/controllers/trash_items_controller.rb
@@ -20,7 +20,7 @@ class TrashItemsController < ApplicationController
     trashed_items
 
     if @objects.any?
-      @objects = @objects.sort_by { |obj| obj.trash_at }.reverse
+      @objects = @objects.sort_by { |obj| obj.modified_at }.reverse
       @next_page_filters = next_page_filters('<=')
       @next_page_href = url_for(partial: params[:partial],
                                 filters: @next_page_filters.to_json)
@@ -35,19 +35,19 @@ class TrashItemsController < ApplicationController
 
   def next_page_filters nextpage_operator
     next_page_filters = @filters.reject do |attr, op, val|
-      (attr == 'trash_at' and op == nextpage_operator) or
+      (attr == 'modified_at' and op == nextpage_operator) or
       (attr == 'uuid' and op == 'not in')
     end
 
     if @objects.any?
-      last_trash_at = @objects.last.trash_at
+      last_trash_at = @objects.last.modified_at
 
       last_uuids = []
       @objects.each do |obj|
         last_uuids << obj.uuid if obj.trash_at.eql?(last_trash_at)
       end
 
-      next_page_filters += [['trash_at', nextpage_operator, last_trash_at]]
+      next_page_filters += [['modified_at', nextpage_operator, last_trash_at]]
       next_page_filters += [['uuid', 'not in', last_uuids]]
     end
 
@@ -61,23 +61,62 @@ class TrashItemsController < ApplicationController
       query_on = Group
     end
 
+    last_mod_at = nil
+    last_uuids = []
+
     # API server index doesn't return manifest_text by default, but our
     # callers want it unless otherwise specified.
     @select ||= query_on.columns.map(&:name) - %w(id updated_at)
     limit = if params[:limit] then params[:limit].to_i else 100 end
     offset = if params[:offset] then params[:offset].to_i else 0 end
 
-    base_search = query_on.select(@select).include_trash(true).where(is_trashed: true)
-    base_search = base_search.filter(params[:filters]) if params[:filters]
+    @objects = []
+    while !@objects.any?
+      base_search = query_on.select(@select).include_trash(true)
+      base_search = base_search.filter(params[:filters]) if params[:filters]
 
-    if params[:search].andand.length.andand > 0
-      tags = Link.where(any: ['contains', params[:search]])
-      base_search = base_search.limit(limit).offset(offset)
-      @objects = (base_search.where(uuid: tags.collect(&:head_uuid)) |
-                  base_search.where(any: ['contains', params[:search]])).
-                  uniq { |c| c.uuid }
-    else
-      @objects = base_search.limit(limit).offset(offset)
+      if !last_mod_at.nil?
+        base_search = base_search.filter([["modified_at", "<=", last_mod_at], ["uuid", "not in", last_uuids]])
+      end
+
+      if params[:search].andand.length.andand > 0
+        tags = Link.where(any: ['contains', params[:search]])
+        base_search = base_search.limit(limit).offset(offset)
+        @objects = (base_search.where(uuid: tags.collect(&:head_uuid)) |
+                    base_search.where(any: ['contains', params[:search]])).
+                   uniq { |c| c.uuid }
+      else
+        @objects = base_search.limit(limit).offset(offset)
+      end
+
+      if @objects.any?
+        owner_uuids = @objects.collect {|item| item.owner_uuid}.uniq
+        @owners = {}
+        @not_trashed = {}
+        Group.filter([["uuid", "in", owner_uuids]]).include_trash(true).each do |grp|
+          @owners[grp.uuid] = grp
+        end
+        User.filter([["uuid", "in", owner_uuids]]).include_trash(true).each do |grp|
+          @owners[grp.uuid] = grp
+        end
+
+        Group.filter([["uuid", "in", owner_uuids]]).select([:uuid]).each do |grp|
+          @not_trashed[grp.uuid] = true
+        end
+        User.filter([["uuid", "in", owner_uuids]]).select([:uuid]).each do |grp|
+          @not_trashed[grp.uuid] = true
+        end
+      else
+        return
+      end
+
+      last_mod_at = @objects.last.modified_at
+      last_uuids = []
+      @objects.each do |obj|
+        last_uuids << obj.uuid if obj.modified_at.eql?(last_mod_at)
+      end
+
+      @objects = @objects.select {|item| item.is_trashed || @not_trashed[item.owner_uuid].nil? }
     end
   end
 
diff --git a/apps/workbench/app/views/trash_items/_show_trashed_collection_rows.html.erb b/apps/workbench/app/views/trash_items/_show_trashed_collection_rows.html.erb
index a7e53e2..443c7d4 100644
--- a/apps/workbench/app/views/trash_items/_show_trashed_collection_rows.html.erb
+++ b/apps/workbench/app/views/trash_items/_show_trashed_collection_rows.html.erb
@@ -22,7 +22,10 @@ SPDX-License-Identifier: AGPL-3.0 %>
         <% end %>
       </td>
       <td>
-        <%= link_to_if_arvados_object obj.owner_uuid, friendly_name: true %>
+        <%= link_to_if_arvados_object @owners[obj.owner_uuid], friendly_name: true %>
+        <% if @not_trashed[obj.owner_uuid].nil? %>
+          (trashed)
+        <% end %>
       </td>
       <td>
         <%= obj.uuid %><br /><%= obj.portable_data_hash %>
@@ -38,7 +41,10 @@ SPDX-License-Identifier: AGPL-3.0 %>
         <% end %>
       </td>
       <td>
-        <%= render partial: 'untrash_item', locals: {object:obj} %>
+        <% if @not_trashed[obj.owner_uuid].nil? %>
+        <% else %>
+          <%= render partial: 'untrash_item', locals: {object:obj} %>
+        <% end %>
       </td>
     </tr>
 <% end %>

commit d80d6de97c0e54249bdbd1f7c92014ef6855448c
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Wed Oct 4 08:23:00 2017 -0400

    12125: Expand test case.
    
    Tests trashing project and checking that it shows up on the trash page.  Tests
    UI using both trash/recycle buttons and using selections.
    
    Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz at veritasgenetics.com>

diff --git a/apps/workbench/test/integration/trash_test.rb b/apps/workbench/test/integration/trash_test.rb
index 3e7d897..d01f636 100644
--- a/apps/workbench/test/integration/trash_test.rb
+++ b/apps/workbench/test/integration/trash_test.rb
@@ -55,32 +55,79 @@ class TrashTest < ActionDispatch::IntegrationTest
     assert_no_text expired2['uuid']
   end
 
-  test "trashed projects" do
-    deleted = api_fixture('groups')['trashed_project']
-
-    # verify that the un-trashed item are missing in /groups page
-    visit page_with_token('active', "/groups")
-    assert_no_text deleted['uuid']
-
-    # visit trash page
-    visit page_with_token('active', "/trash")
-    click_on "Trashed projects"
-
-    assert_text deleted['name']
-    assert_text deleted['uuid']
-
-    # Un-trash item using the recycle button
-    within('tr', text: deleted['name']) do
-      first('.fa-recycle').click
+  ["button","selection"].each do |method|
+    test "trashed projects using #{method}" do
+      deleted = api_fixture('groups')['trashed_project']
+      aproject = api_fixture('groups')['aproject']
+
+      # verify that the un-trashed item are missing in /groups page
+      visit page_with_token('active', "/projects/zzzzz-tpzed-xurymjxw79nv3jz")
+      click_on "Subprojects"
+      assert_no_text deleted['name']
+
+      # visit trash page
+      visit page_with_token('active', "/trash")
+      click_on "Trashed projects"
+
+      assert_text deleted['name']
+      assert_text deleted['uuid']
+      assert_no_text aproject['name']
+      assert_no_text aproject['uuid']
+
+      # Un-trash item
+      if method == "button"
+        within('tr', text: deleted['name']) do
+          first('.fa-recycle').click
+        end
+      else
+        within('tr', text: deleted['name']) do
+          first('input').click
+        end
+        click_button 'Selection...'
+        within('.selection-action-container') do
+          click_link 'Un-trash selected items'
+        end
+      end
+
+      wait_for_ajax
+
+      assert_no_text deleted['name']
+      visit current_path
+      assert_no_text deleted['name']
+
+      # check that the un-trashed item are now shown on parent project page
+      visit page_with_token('active', "/projects/zzzzz-tpzed-xurymjxw79nv3jz")
+      click_on "Subprojects"
+      assert_text deleted['name']
+      assert_text aproject['name']
+
+      # Trash another item
+      if method == "button"
+        within('tr', text: aproject['name']) do
+          first('.fa-trash-o').click
+        end
+      else
+        within('tr', text: aproject['name']) do
+          first('input').click
+        end
+        click_button 'Selection'
+        within('.selection-action-container') do
+          click_link 'Remove selected'
+        end
+      end
+
+      wait_for_ajax
+      assert_no_text aproject['name']
+      visit current_path
+      assert_no_text aproject['name']
+
+      # visit trash page
+      visit page_with_token('active', "/trash")
+      click_on "Trashed projects"
+
+      assert_text aproject['name']
+      assert_text aproject['uuid']
     end
-
-    wait_for_ajax
-
-    assert_no_text deleted['uuid']
-
-    # verify that the un-trashed item are now shown in /groups page
-    visit page_with_token('active', "/groups")
-    assert_text deleted['uuid']
   end
 
   test "trash page with search" do

commit e951503aca74be84ea501d4316e38a662210b247
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Tue Oct 3 21:05:54 2017 -0400

    12125: Adding test
    
    Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz at veritasgenetics.com>

diff --git a/apps/workbench/test/controllers/projects_controller_test.rb b/apps/workbench/test/controllers/projects_controller_test.rb
index f45f178..bdf983f 100644
--- a/apps/workbench/test/controllers/projects_controller_test.rb
+++ b/apps/workbench/test/controllers/projects_controller_test.rb
@@ -146,7 +146,6 @@ class ProjectsControllerTest < ActionController::TestCase
   # An object which does not offer an expired_at field but has a xx_owner_uuid_name_unique constraint
   # will be renamed when removed and another object with the same name exists in user's home project.
   [
-    ['groups', 'subproject_in_asubproject_with_same_name_as_one_in_active_user_home'],
     ['pipeline_templates', 'template_in_asubproject_with_same_name_as_one_in_active_user_home'],
   ].each do |dm, fixture|
     test "removing #{dm} from a subproject results in renaming it when there is another such object with same name in home project" do
diff --git a/apps/workbench/test/integration/trash_test.rb b/apps/workbench/test/integration/trash_test.rb
index 5c6987e..3e7d897 100644
--- a/apps/workbench/test/integration/trash_test.rb
+++ b/apps/workbench/test/integration/trash_test.rb
@@ -55,6 +55,34 @@ class TrashTest < ActionDispatch::IntegrationTest
     assert_no_text expired2['uuid']
   end
 
+  test "trashed projects" do
+    deleted = api_fixture('groups')['trashed_project']
+
+    # verify that the un-trashed item are missing in /groups page
+    visit page_with_token('active', "/groups")
+    assert_no_text deleted['uuid']
+
+    # visit trash page
+    visit page_with_token('active', "/trash")
+    click_on "Trashed projects"
+
+    assert_text deleted['name']
+    assert_text deleted['uuid']
+
+    # Un-trash item using the recycle button
+    within('tr', text: deleted['name']) do
+      first('.fa-recycle').click
+    end
+
+    wait_for_ajax
+
+    assert_no_text deleted['uuid']
+
+    # verify that the un-trashed item are now shown in /groups page
+    visit page_with_token('active', "/groups")
+    assert_text deleted['uuid']
+  end
+
   test "trash page with search" do
     deleted = api_fixture('collections')['deleted_on_next_sweep']
     expired = api_fixture('collections')['unique_expired_collection']

commit c62d9a299247f31ef1baff27b9726010c963e3f1
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Tue Oct 3 13:17:00 2017 -0400

    12125: Adjust table layout
    
    Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz at veritasgenetics.com>
    
    Reviewed-by: Peter Amstutz <peter.amstutz at curoverse.com>

diff --git a/apps/workbench/app/views/trash_items/_show_trashed_collections.html.erb b/apps/workbench/app/views/trash_items/_show_trashed_collections.html.erb
index aaa2936..0cb941c 100644
--- a/apps/workbench/app/views/trash_items/_show_trashed_collections.html.erb
+++ b/apps/workbench/app/views/trash_items/_show_trashed_collections.html.erb
@@ -43,7 +43,7 @@ SPDX-License-Identifier: AGPL-3.0 %>
           <th></th>
           <th>Name</th>
           <th>Date trashed /<br />to be deleted</th>
-          <th>Owner</th>
+          <th>Parent project</th>
           <th>UUID /<br />Content address (PDH)</th>
           <th>Contents</th>
           <th></th>
diff --git a/apps/workbench/app/views/trash_items/_show_trashed_project_rows.html.erb b/apps/workbench/app/views/trash_items/_show_trashed_project_rows.html.erb
index 1937bcf..ef3a478 100644
--- a/apps/workbench/app/views/trash_items/_show_trashed_project_rows.html.erb
+++ b/apps/workbench/app/views/trash_items/_show_trashed_project_rows.html.erb
@@ -3,7 +3,7 @@
 SPDX-License-Identifier: AGPL-3.0 %>
 
 <% @objects.each do |obj| %>
-    <tr data-object-uuid="<%= obj.uuid %>" data-kind="<%= obj.kind %>" >
+  <tr data-object-uuid="<%= obj.uuid %>" data-kind="<%= obj.kind %>" >
       <td>
         <% if obj.editable? %>
           <%= check_box_tag 'uuids[]', obj.uuid, false, :class => 'persistent-selection', style: 'cursor: pointer;' %>
@@ -11,16 +11,21 @@ SPDX-License-Identifier: AGPL-3.0 %>
       </td>
       <td>
         <%= if !obj.name.blank? then obj.name else obj.uuid end %>
+      </td>
       <td>
-        <%= render_localized_date(obj.trash_at) if obj.trash_at %>
-      <td>
-        <%= render_localized_date(obj.delete_at) if obj.delete_at %>
+        <% if obj.trash_at %>
+          <%= render_localized_date(obj.trash_at)  %>
+        <% end %>
+        <br />
+        <% if obj.delete_at %>
+          <%= render_localized_date(obj.delete_at) %>
+        <% end %>
       </td>
       <td>
         <%= link_to_if_arvados_object obj.owner_uuid, friendly_name: true %>
       </td>
       <td>
-
+        <%= obj.uuid %>
       </td>
       <td>
         <%= render partial: 'untrash_item', locals: {object:obj} %>
diff --git a/apps/workbench/app/views/trash_items/_show_trashed_projects.html.erb b/apps/workbench/app/views/trash_items/_show_trashed_projects.html.erb
index ef782d6..2882814 100644
--- a/apps/workbench/app/views/trash_items/_show_trashed_projects.html.erb
+++ b/apps/workbench/app/views/trash_items/_show_trashed_projects.html.erb
@@ -29,23 +29,21 @@ SPDX-License-Identifier: AGPL-3.0 %>
   <div>
     <table id="trash-index" class="topalign table table-condensed table-fixedlayout">
       <colgroup>
-        <col width="5%" />
-        <col width="20%" />
-        <col width="15%" />
-        <col width="15%" />
         <col width="10%" />
-        <col width="30%" />
-        <col width="5%" />
+        <col width="21%" />
+        <col width="21%" />
+        <col width="21%" />
+        <col width="21%" />
+        <col width="6%" />
       </colgroup>
 
       <thead>
         <tr class="contain-align-left">
           <th></th>
           <th>Name</th>
-          <th>Trashed at</th>
-          <th title="After this time, no longer available to be recovered from Trash">Permanently<br/>Deleted At</th>
-          <th>Owner</th>
-          <th></th>
+          <th>Date trashed /<br />to be deleted</th>
+          <th>Parent project</th>
+          <th>UUID</th>
           <th></th>
         </tr>
       </thead>

commit ae0781e5decb54f1c18f1dc12961b18d03043337
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Tue Oct 3 10:06:24 2017 -0400

    12125: Missing file
    
    Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz at veritasgenetics.com>

diff --git a/apps/workbench/app/views/trash_items/_show_trashed_project_rows.html.erb b/apps/workbench/app/views/trash_items/_show_trashed_project_rows.html.erb
new file mode 100644
index 0000000..1937bcf
--- /dev/null
+++ b/apps/workbench/app/views/trash_items/_show_trashed_project_rows.html.erb
@@ -0,0 +1,29 @@
+<%# Copyright (C) The Arvados Authors. All rights reserved.
+
+SPDX-License-Identifier: AGPL-3.0 %>
+
+<% @objects.each do |obj| %>
+    <tr data-object-uuid="<%= obj.uuid %>" data-kind="<%= obj.kind %>" >
+      <td>
+        <% if obj.editable? %>
+          <%= check_box_tag 'uuids[]', obj.uuid, false, :class => 'persistent-selection', style: 'cursor: pointer;' %>
+        <% end %>
+      </td>
+      <td>
+        <%= if !obj.name.blank? then obj.name else obj.uuid end %>
+      <td>
+        <%= render_localized_date(obj.trash_at) if obj.trash_at %>
+      <td>
+        <%= render_localized_date(obj.delete_at) if obj.delete_at %>
+      </td>
+      <td>
+        <%= link_to_if_arvados_object obj.owner_uuid, friendly_name: true %>
+      </td>
+      <td>
+
+      </td>
+      <td>
+        <%= render partial: 'untrash_item', locals: {object:obj} %>
+      </td>
+    </tr>
+<% end %>

commit 9d223ac56644eb23cdc39c5044f4fb12cf29b685
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Sep 18 09:55:07 2017 -0400

    12125: Restore "move trashed items to home" behavior for now.
    
    Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz at veritasgenetics.com>

diff --git a/apps/workbench/app/controllers/projects_controller.rb b/apps/workbench/app/controllers/projects_controller.rb
index a2ed89b..4a7563a 100644
--- a/apps/workbench/app/controllers/projects_controller.rb
+++ b/apps/workbench/app/controllers/projects_controller.rb
@@ -134,8 +134,31 @@ class ProjectsController < ApplicationController
     @removed_uuids = []
     links = []
     params[:item_uuids].collect { |uuid| ArvadosBase.find uuid }.each do |item|
-      item.destroy
-      @removed_uuids << item.uuid
+      if item.class == Collection or item.class == Group
+        # Use delete API on collections and projects/groups
+        item.destroy
+        @removed_uuids << item.uuid
+      elsif item.owner_uuid == @object.uuid
+        # Object is owned by this project. Remove it from the project by
+        # changing owner to the current user.
+        begin
+          item.update_attributes owner_uuid: current_user.uuid
+          @removed_uuids << item.uuid
+        rescue ArvadosApiClient::ApiErrorResponseException => e
+          if e.message.include? '_owner_uuid_'
+            rename_to = item.name + ' removed from ' +
+                        (@object.name ? @object.name : @object.uuid) +
+                        ' at ' + Time.now.to_s
+            updates = {}
+            updates[:name] = rename_to
+            updates[:owner_uuid] = current_user.uuid
+            item.update_attributes updates
+            @removed_uuids << item.uuid
+          else
+            raise
+          end
+        end
+      end
     end
   end
 

commit 14fccf0ed91ebb0a0dbf1bff47edfb156538f42f
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Fri Sep 15 08:33:22 2017 -0400

    12125: Fix 404 page when not showing a specific object.
    
    Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz at veritasgenetics.com>

diff --git a/apps/workbench/app/views/application/404.html.erb b/apps/workbench/app/views/application/404.html.erb
index 31462ef..ee72ccd 100644
--- a/apps/workbench/app/views/application/404.html.erb
+++ b/apps/workbench/app/views/application/404.html.erb
@@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0 %>
    end
 %>
 
-  <% if check_trash.any? %>
+  <% if check_trash.andand.any? %>
     <h2>Trashed</h2>
 
     <p>The <%= req_item %> is in the trash.

commit 9adcefaec1be61e847d0e463f609e035995bb51f
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Thu Sep 14 22:11:22 2017 -0400

    12125: Workbench 404 page checks if item is in the trash.
    
    Provides a convenient button to untrash it.
    
    Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz at veritasgenetics.com>

diff --git a/apps/workbench/app/controllers/trash_items_controller.rb b/apps/workbench/app/controllers/trash_items_controller.rb
index 27cbb32..4aac884 100644
--- a/apps/workbench/app/controllers/trash_items_controller.rb
+++ b/apps/workbench/app/controllers/trash_items_controller.rb
@@ -86,15 +86,24 @@ class TrashItemsController < ApplicationController
 
     updates = {trash_at: nil}
 
-    klass = resource_class_for_uuid(params[:selection][0])
+    if params[:selection].is_a? Array
+      klass = resource_class_for_uuid(params[:selection][0])
+    else
+      klass = resource_class_for_uuid(params[:selection])
+    end
 
+    first = nil
     klass.include_trash(1).where(uuid: params[:selection]).each do |c|
+      first = c
       c.untrash
       @untrashed_uuids << c.uuid
     end
 
     respond_to do |format|
       format.js
+      format.html do
+        redirect_to first
+      end
     end
   end
 end
diff --git a/apps/workbench/app/views/application/404.html.erb b/apps/workbench/app/views/application/404.html.erb
index e02d0b3..31462ef 100644
--- a/apps/workbench/app/views/application/404.html.erb
+++ b/apps/workbench/app/views/application/404.html.erb
@@ -4,10 +4,11 @@ SPDX-License-Identifier: AGPL-3.0 %>
 
 <%
    if (controller.andand.action_name == 'show') and params[:uuid]
+     check_trash = controller.model_class.include_trash(true).where(uuid: params[:uuid], is_trashed: true)
      class_name = controller.model_class.to_s.underscore
      class_name_h = class_name.humanize(capitalize: false)
      req_item = safe_join([class_name_h, " with UUID ",
-                           raw("<code>"), params[:uuid], raw("</code>")], "")
+                             raw("<code>"), params[:uuid], raw("</code>")], "")
      req_item_plain_text = safe_join([class_name_h, " with UUID ", params[:uuid]])
    else
      req_item = "page you requested"
@@ -15,6 +16,27 @@ SPDX-License-Identifier: AGPL-3.0 %>
    end
 %>
 
+  <% if check_trash.any? %>
+    <h2>Trashed</h2>
+
+    <p>The <%= req_item %> is in the trash.
+
+    <% object = check_trash.first %>
+    <% if object.editable? %>
+      <% msg = "Untrash '" + if !object.name.blank? then object.name else object.uuid end + "'?" %>
+      <%= link_to({action: 'untrash_items', selection: [object.uuid], controller: :trash_items}, remote: true, method: :post,
+        title: "Untrash", style: 'cursor: pointer;') do %>
+
+      <% end %>
+
+      <%= form_tag url_for({action: 'untrash_items', controller: :trash_items}), {method: :post} %>
+      <%= hidden_field_tag :selection, [object.uuid] %>
+      <button type="submit">Click here to untrash this item <i class="fa fa-fw fa-recycle"></i></button>
+    <% end %>
+    </p>
+
+  <% else %>
+
 <h2>Not Found</h2>
 
 <p>The <%= req_item %> was not found.</p>
@@ -39,5 +61,7 @@ SPDX-License-Identifier: AGPL-3.0 %>
 
 <% end %>
 
+<% end %>
+
 <% error_message = "The #{req_item_plain_text} was not found." %>
 <%= render :partial => "report_error", :locals => {error_message: error_message, error_type: '404'} %>

commit b74478a602b3cc5fcc18c2beb2962f98d1225ac4
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Thu Sep 14 21:35:40 2017 -0400

    12125: Can browse trashed projects & untrash them.
    
    Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz at veritasgenetics.com>

diff --git a/apps/workbench/app/controllers/projects_controller.rb b/apps/workbench/app/controllers/projects_controller.rb
index c010123..a2ed89b 100644
--- a/apps/workbench/app/controllers/projects_controller.rb
+++ b/apps/workbench/app/controllers/projects_controller.rb
@@ -134,50 +134,8 @@ class ProjectsController < ApplicationController
     @removed_uuids = []
     links = []
     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
-        # project. 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.class == Collection
-        # Use delete API on collections
-        item.destroy
-        @removed_uuids << item.uuid
-      elsif item.owner_uuid == @object.uuid
-        # Object is owned by this project. Remove it from the project by
-        # changing owner to the current user.
-        begin
-          item.update_attributes owner_uuid: current_user.uuid
-          @removed_uuids << item.uuid
-        rescue ArvadosApiClient::ApiErrorResponseException => e
-          if e.message.include? '_owner_uuid_'
-            rename_to = item.name + ' removed from ' +
-                        (@object.name ? @object.name : @object.uuid) +
-                        ' at ' + Time.now.to_s
-            updates = {}
-            updates[:name] = rename_to
-            updates[:owner_uuid] = current_user.uuid
-            item.update_attributes updates
-            @removed_uuids << item.uuid
-          else
-            raise
-          end
-        end
-      end
+      item.destroy
+      @removed_uuids << item.uuid
     end
   end
 
@@ -337,7 +295,7 @@ class ProjectsController < ApplicationController
   def public  # Yes 'public' is the name of the action for public projects
     return render_not_found if not Rails.configuration.anonymous_user_token or not Rails.configuration.enable_public_projects_page
     @objects = using_specific_api_token Rails.configuration.anonymous_user_token do
-      Group.where(group_class: 'project').order("updated_at DESC")
+      Group.where(group_class: 'project').order("modified_at DESC")
     end
   end
 end
diff --git a/apps/workbench/app/controllers/trash_items_controller.rb b/apps/workbench/app/controllers/trash_items_controller.rb
index b957798..27cbb32 100644
--- a/apps/workbench/app/controllers/trash_items_controller.rb
+++ b/apps/workbench/app/controllers/trash_items_controller.rb
@@ -22,7 +22,7 @@ class TrashItemsController < ApplicationController
     if @objects.any?
       @objects = @objects.sort_by { |obj| obj.trash_at }.reverse
       @next_page_filters = next_page_filters('<=')
-      @next_page_href = url_for(partial: :trash_rows,
+      @next_page_href = url_for(partial: params[:partial],
                                 filters: @next_page_filters.to_json)
     else
       @next_page_href = nil
@@ -55,13 +55,19 @@ class TrashItemsController < ApplicationController
   end
 
   def trashed_items
+    if params[:partial] == "trashed_collection_rows"
+      query_on = Collection
+    elsif params[:partial] == "trashed_project_rows"
+      query_on = Group
+    end
+
     # API server index doesn't return manifest_text by default, but our
     # callers want it unless otherwise specified.
-    @select ||= Collection.columns.map(&:name)
+    @select ||= query_on.columns.map(&:name) - %w(id updated_at)
     limit = if params[:limit] then params[:limit].to_i else 100 end
     offset = if params[:offset] then params[:offset].to_i else 0 end
 
-    base_search = Collection.select(@select).include_trash(true).where(is_trashed: true)
+    base_search = query_on.select(@select).include_trash(true).where(is_trashed: true)
     base_search = base_search.filter(params[:filters]) if params[:filters]
 
     if params[:search].andand.length.andand > 0
@@ -80,7 +86,9 @@ class TrashItemsController < ApplicationController
 
     updates = {trash_at: nil}
 
-    Collection.include_trash(1).where(uuid: params[:selection]).each do |c|
+    klass = resource_class_for_uuid(params[:selection][0])
+
+    klass.include_trash(1).where(uuid: params[:selection]).each do |c|
       c.untrash
       @untrashed_uuids << c.uuid
     end
diff --git a/apps/workbench/app/models/group.rb b/apps/workbench/app/models/group.rb
index 523e5e9..08b13bf 100644
--- a/apps/workbench/app/models/group.rb
+++ b/apps/workbench/app/models/group.rb
@@ -40,4 +40,8 @@ class Group < ArvadosBase
   def self.creatable?
     false
   end
+
+  def untrash
+    arvados_api_client.api(self.class, "/#{self.uuid}/untrash", {"ensure_unique_name" => true})
+  end
 end
diff --git a/apps/workbench/app/views/trash_items/_show_trash_rows.html.erb b/apps/workbench/app/views/trash_items/_show_trashed_collection_rows.html.erb
similarity index 100%
rename from apps/workbench/app/views/trash_items/_show_trash_rows.html.erb
rename to apps/workbench/app/views/trash_items/_show_trashed_collection_rows.html.erb
diff --git a/apps/workbench/app/views/trash_items/_show_trashed_collections.html.erb b/apps/workbench/app/views/trash_items/_show_trashed_collections.html.erb
index c534e52..aaa2936 100644
--- a/apps/workbench/app/views/trash_items/_show_trashed_collections.html.erb
+++ b/apps/workbench/app/views/trash_items/_show_trashed_collections.html.erb
@@ -22,7 +22,7 @@ SPDX-License-Identifier: AGPL-3.0 %>
   <div class="col-md-4 pull-right">
     <input type="text" class="form-control filterable-control recent-trash-items"
            placeholder="Search trash"
-           data-filterable-target="#recent-trash-items"
+           data-filterable-target="#recent-collection-trash-items"
            value="<%= params[:search] %>" />
   </div>
 
@@ -50,8 +50,8 @@ SPDX-License-Identifier: AGPL-3.0 %>
         </tr>
       </thead>
 
-      <tbody data-infinite-scroller="#recent-trash-items" id="recent-trash-items"
-        data-infinite-content-href="<%= url_for partial: :trash_rows %>" >
+      <tbody data-infinite-scroller="#recent-collection-trash-items" id="recent-collection-trash-items"
+        data-infinite-content-href="<%= url_for partial: :trashed_collection_rows %>" >
       </tbody>
     </table>
   </div>
diff --git a/apps/workbench/app/views/trash_items/_show_trashed_projects.html.erb b/apps/workbench/app/views/trash_items/_show_trashed_projects.html.erb
index a78b02f..ef782d6 100644
--- a/apps/workbench/app/views/trash_items/_show_trashed_projects.html.erb
+++ b/apps/workbench/app/views/trash_items/_show_trashed_projects.html.erb
@@ -22,7 +22,7 @@ SPDX-License-Identifier: AGPL-3.0 %>
   <div class="col-md-4 pull-right">
     <input type="text" class="form-control filterable-control recent-trash-items"
            placeholder="Search trash"
-           data-filterable-target="#recent-trash-items"
+           data-filterable-target="#recent-project-trash-items"
            value="<%= params[:search] %>" />
   </div>
 
@@ -45,13 +45,13 @@ SPDX-License-Identifier: AGPL-3.0 %>
           <th>Trashed at</th>
           <th title="After this time, no longer available to be recovered from Trash">Permanently<br/>Deleted At</th>
           <th>Owner</th>
-          <th>Contents</th>
+          <th></th>
           <th></th>
         </tr>
       </thead>
 
-      <tbody data-infinite-scroller="#recent-trash-items" id="recent-trash-items"
-        data-infinite-content-href="<%= url_for partial: :trash_rows %>" >
+      <tbody data-infinite-scroller="#recent-project-trash-items" id="recent-project-trash-items"
+        data-infinite-content-href="<%= url_for partial: :trashed_project_rows %>" >
       </tbody>
     </table>
   </div>

commit 9a4c456560f0b78660c2bfc9a7aa4030de74c741
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Thu Sep 14 20:36:24 2017 -0400

    12125: Initial work, separate collection and project trash tabs.
    
    Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz at veritasgenetics.com>

diff --git a/apps/workbench/app/controllers/trash_items_controller.rb b/apps/workbench/app/controllers/trash_items_controller.rb
index 3604e78..b957798 100644
--- a/apps/workbench/app/controllers/trash_items_controller.rb
+++ b/apps/workbench/app/controllers/trash_items_controller.rb
@@ -8,7 +8,7 @@ class TrashItemsController < ApplicationController
   end
 
   def index_pane_list
-    %w(Recent_trash)
+    %w(Trashed_collections Trashed_projects)
   end
 
   def find_objects_for_index
diff --git a/apps/workbench/app/views/trash_items/_show_recent_trash.html.erb b/apps/workbench/app/views/trash_items/_show_trashed_collections.html.erb
similarity index 100%
copy from apps/workbench/app/views/trash_items/_show_recent_trash.html.erb
copy to apps/workbench/app/views/trash_items/_show_trashed_collections.html.erb
diff --git a/apps/workbench/app/views/trash_items/_show_recent_trash.html.erb b/apps/workbench/app/views/trash_items/_show_trashed_projects.html.erb
similarity index 87%
rename from apps/workbench/app/views/trash_items/_show_recent_trash.html.erb
rename to apps/workbench/app/views/trash_items/_show_trashed_projects.html.erb
index c534e52..a78b02f 100644
--- a/apps/workbench/app/views/trash_items/_show_recent_trash.html.erb
+++ b/apps/workbench/app/views/trash_items/_show_trashed_projects.html.erb
@@ -29,12 +29,12 @@ SPDX-License-Identifier: AGPL-3.0 %>
   <div>
     <table id="trash-index" class="topalign table table-condensed table-fixedlayout">
       <colgroup>
-        <col width="2%" />
+        <col width="5%" />
         <col width="20%" />
-        <col width="13%" />
         <col width="15%" />
-        <col width="20%" />
-        <col width="25%" />
+        <col width="15%" />
+        <col width="10%" />
+        <col width="30%" />
         <col width="5%" />
       </colgroup>
 
@@ -42,9 +42,9 @@ SPDX-License-Identifier: AGPL-3.0 %>
         <tr class="contain-align-left">
           <th></th>
           <th>Name</th>
-          <th>Date trashed /<br />to be deleted</th>
+          <th>Trashed at</th>
+          <th title="After this time, no longer available to be recovered from Trash">Permanently<br/>Deleted At</th>
           <th>Owner</th>
-          <th>UUID /<br />Content address (PDH)</th>
           <th>Contents</th>
           <th></th>
         </tr>

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


hooks/post-receive
-- 




More information about the arvados-commits mailing list