[ARVADOS] updated: 55315b668b8fa04572a44fd7db6598478f54130a
Git user
git at public.curoverse.com
Mon Jun 5 18:58:17 EDT 2017
Summary of changes:
apps/workbench/app/assets/images/trash-icon.png | Bin 0 -> 18381 bytes
.../app/assets/javascripts/selection.js.erb | 4 +
.../app/controllers/trash_items_controller.rb | 67 ++++++++++++++++
apps/workbench/app/models/arvados_base.rb | 4 +
apps/workbench/app/models/arvados_resource_list.rb | 6 ++
apps/workbench/app/models/collection.rb | 3 +
.../app/views/application/_breadcrumbs.html.erb | 7 ++
.../trash_items/_create_new_object_button.html.erb | 1 +
.../app/views/trash_items/_show_recent.html.erb | 54 +++++++++++++
.../views/trash_items/_show_trash_rows.html.erb | 32 ++++++++
.../app/views/trash_items/_untrash_item.html.erb | 7 ++
.../workbench/app/views/trash_items/index.html.erb | 1 +
.../untrash_items.js.erb} | 3 +-
.../views/work_units/_show_all_processes.html.erb | 2 +-
apps/workbench/config/routes.rb | 5 ++
apps/workbench/test/integration/trash_test.rb | 87 +++++++++++++++++++++
.../arvados/v1/collections_controller.rb | 13 ++-
services/api/config/routes.rb | 1 +
services/api/test/fixtures/collections.yml | 2 +-
.../arvados/v1/collections_controller_test.rb | 18 +++++
20 files changed, 311 insertions(+), 6 deletions(-)
create mode 100644 apps/workbench/app/assets/images/trash-icon.png
create mode 100644 apps/workbench/app/controllers/trash_items_controller.rb
create mode 100644 apps/workbench/app/views/trash_items/_create_new_object_button.html.erb
create mode 100644 apps/workbench/app/views/trash_items/_show_recent.html.erb
create mode 100644 apps/workbench/app/views/trash_items/_show_trash_rows.html.erb
create mode 100644 apps/workbench/app/views/trash_items/_untrash_item.html.erb
create mode 100644 apps/workbench/app/views/trash_items/index.html.erb
copy apps/workbench/app/views/{projects/remove_items.js.erb => trash_items/untrash_items.js.erb} (58%)
create mode 100644 apps/workbench/test/integration/trash_test.rb
via 55315b668b8fa04572a44fd7db6598478f54130a (commit)
via 0a6adabd77bf483186a29a7cffef38866a5ee8e0 (commit)
via 0560a5812377315a92c8a4e9b41a68677832ea65 (commit)
via 695a100d4bd3bf4f5534c7e489c118c2917bf35a (commit)
from dcd20d41fde4216345a20ddfa950b40de74b85b5 (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 55315b668b8fa04572a44fd7db6598478f54130a
Merge: dcd20d4 0a6adab
Author: radhika <radhika at curoverse.com>
Date: Mon Jun 5 18:58:03 2017 -0400
closes #9587
Merge branch '9587-trash-page'
commit 0a6adabd77bf483186a29a7cffef38866a5ee8e0
Author: radhika <radhika at curoverse.com>
Date: Fri Jun 2 17:31:04 2017 -0400
9587: sort order issue
diff --git a/apps/workbench/app/controllers/trash_items_controller.rb b/apps/workbench/app/controllers/trash_items_controller.rb
index bbc0b26..31581bb 100644
--- a/apps/workbench/app/controllers/trash_items_controller.rb
+++ b/apps/workbench/app/controllers/trash_items_controller.rb
@@ -3,6 +3,10 @@ class TrashItemsController < ApplicationController
Collection
end
+ def show_pane_list
+ %w(Recent)
+ end
+
def find_objects_for_index
# If it's not the index rows partial display, just return
# The /index request will again be invoked to display the
@@ -12,6 +16,7 @@ class TrashItemsController < ApplicationController
trashed_items
if @objects.any?
+ @objects = @objects.sort_by { |obj| obj.created_at }.reverse
@next_page_filters = next_page_filters('<=')
@next_page_href = url_for(partial: :trash_rows,
filters: @next_page_filters.to_json)
diff --git a/apps/workbench/app/views/trash_items/_create_new_object_button.html.erb b/apps/workbench/app/views/trash_items/_create_new_object_button.html.erb
new file mode 100644
index 0000000..2ba9e1a
--- /dev/null
+++ b/apps/workbench/app/views/trash_items/_create_new_object_button.html.erb
@@ -0,0 +1 @@
+<%# There is no such thing %>
diff --git a/apps/workbench/app/views/trash_items/_show_trash_items.html.erb b/apps/workbench/app/views/trash_items/_show_recent.html.erb
similarity index 95%
rename from apps/workbench/app/views/trash_items/_show_trash_items.html.erb
rename to apps/workbench/app/views/trash_items/_show_recent.html.erb
index 153d7d0..6776e7a 100644
--- a/apps/workbench/app/views/trash_items/_show_trash_items.html.erb
+++ b/apps/workbench/app/views/trash_items/_show_recent.html.erb
@@ -27,10 +27,10 @@
<colgroup>
<col width="5%" />
<col width="20%" />
+ <col width="15%" />
+ <col width="15%" />
<col width="10%" />
- <col width="10%" />
- <col width="10%" />
- <col width="40%" />
+ <col width="30%" />
<col width="5%" />
</colgroup>
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
index d617d8d..8db21ed 100644
--- a/apps/workbench/app/views/trash_items/_show_trash_rows.html.erb
+++ b/apps/workbench/app/views/trash_items/_show_trash_rows.html.erb
@@ -1,4 +1,4 @@
-<% @objects.sort_by { |obj| obj.created_at }.reverse.each do |obj| %>
+<% @objects.each do |obj| %>
<tr data-object-uuid="<%= obj.uuid %>" data-kind="<%= obj.kind %>" >
<td>
<% if obj.editable? %>
@@ -8,9 +8,9 @@
<td>
<%= if !obj.name.blank? then obj.name else obj.uuid end %>
<td>
- <%= obj.created_at.to_s if obj.created_at %>
+ <%= render_localized_date(obj.created_at) if obj.created_at %>
<td>
- <%= obj.trash_at.to_s if obj.trash_at %>
+ <%= render_localized_date(obj.trash_at) if obj.trash_at %>
</td>
<td>
<%= link_to_if_arvados_object obj.owner_uuid, friendly_name: true %>
@@ -22,7 +22,7 @@
<%= file_path %><br />
<% end %>
<% if obj.files.length > 3 %>
- ⋮
+ <%= "(#{obj.files.length-3} more files)" %>
<% end %>
</td>
<td>
diff --git a/apps/workbench/app/views/trash_items/_untrash_item.html.erb b/apps/workbench/app/views/trash_items/_untrash_item.html.erb
index 2ba9dc9..8732531 100644
--- a/apps/workbench/app/views/trash_items/_untrash_item.html.erb
+++ b/apps/workbench/app/views/trash_items/_untrash_item.html.erb
@@ -1,7 +1,7 @@
<% if object.editable? %>
- <% msg = "Un-trash '" + if !object.name.blank? then object.name else object.uuid end + "'?" %>
+ <% msg = "Untrash '" + if !object.name.blank? then object.name else object.uuid end + "'?" %>
<%= link_to({action: 'untrash_items', selection: [object.uuid]}, remote: true, method: :post,
- data: {confirm: msg}) do %>
+ title: "Untrash", data: {confirm: msg}) do %>
<i class="fa fa-fw fa-recycle"></i>
<% end %>
<% end %>
diff --git a/apps/workbench/app/views/trash_items/index.html.erb b/apps/workbench/app/views/trash_items/index.html.erb
index bd55a3f..5f5bc83 100644
--- a/apps/workbench/app/views/trash_items/index.html.erb
+++ b/apps/workbench/app/views/trash_items/index.html.erb
@@ -1 +1 @@
-<%= render partial: 'show_trash_items' %>
+<%= render file: 'application/index.html.erb', locals: local_assigns %>
diff --git a/services/api/test/functional/arvados/v1/collections_controller_test.rb b/services/api/test/functional/arvados/v1/collections_controller_test.rb
index a31ad8a..7618985 100644
--- a/services/api/test/functional/arvados/v1/collections_controller_test.rb
+++ b/services/api/test/functional/arvados/v1/collections_controller_test.rb
@@ -1024,4 +1024,22 @@ EOS
assert_operator c.delete_at, :>=, time_before_trashing + Rails.configuration.default_trash_lifetime
end
end
+
+ test 'untrash a trashed collection' do
+ authorize_with :active
+ post :untrash, {
+ id: collections(:expired_collection).uuid,
+ }
+ assert_response 200
+ assert_equal false, json_response['is_trashed']
+ assert_nil json_response['trash_at']
+ end
+
+ test 'untrash error on not trashed collection' do
+ authorize_with :active
+ post :untrash, {
+ id: collections(:collection_owned_by_active).uuid,
+ }
+ assert_response 422
+ end
end
commit 0560a5812377315a92c8a4e9b41a68677832ea65
Author: radhika <radhika at curoverse.com>
Date: Wed May 31 15:03:53 2017 -0400
9587: expose untrash api
diff --git a/apps/workbench/app/assets/images/trash-icon.png b/apps/workbench/app/assets/images/trash-icon.png
new file mode 100644
index 0000000..5c26c24
Binary files /dev/null and b/apps/workbench/app/assets/images/trash-icon.png differ
diff --git a/apps/workbench/app/controllers/trash_items_controller.rb b/apps/workbench/app/controllers/trash_items_controller.rb
index 5190474..bbc0b26 100644
--- a/apps/workbench/app/controllers/trash_items_controller.rb
+++ b/apps/workbench/app/controllers/trash_items_controller.rb
@@ -15,7 +15,6 @@ class TrashItemsController < ApplicationController
@next_page_filters = next_page_filters('<=')
@next_page_href = url_for(partial: :trash_rows,
filters: @next_page_filters.to_json)
- preload_links_for_objects(@objects.to_a)
else
@next_page_href = nil
end
@@ -37,39 +36,13 @@ class TrashItemsController < ApplicationController
if params[:search].andand.length.andand > 0
tags = Link.where(any: ['contains', params[:search]])
- @objects = (base_search.limit(limit).offset(offset).where(uuid: tags.collect(&:head_uuid)) |
- base_search.where(any: ['contains', params[:search]])).
- uniq { |c| c.uuid }
+ 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
-
- @links = Link.where(head_uuid: @objects.collect(&:uuid))
- @collection_info = {}
- @objects.each do |c|
- @collection_info[c.uuid] = {
- tag_links: [],
- wanted: false,
- wanted_by_me: false,
- provenance: [],
- links: []
- }
- end
- @links.each do |link|
- @collection_info[link.head_uuid] ||= {}
- info = @collection_info[link.head_uuid]
- case link.link_class
- when 'tag'
- info[:tag_links] << link
- when 'resources'
- info[:wanted] = true
- info[:wanted_by_me] ||= link.tail_uuid == current_user.uuid
- when 'provenance'
- info[:provenance] << link.name
- end
- info[:links] << link
- end
- @request_url = request.url
end
def untrash_items
@@ -77,9 +50,9 @@ class TrashItemsController < ApplicationController
updates = {trash_at: nil}
- params[:selection].collect { |uuid| ArvadosBase.find uuid }.each do |item|
- item.update_attributes updates
- @untrashed_uuids << item.uuid
+ Collection.include_trash(1).where(uuid: params[:selection]).each do |c|
+ c.untrash
+ @untrashed_uuids << c.uuid
end
respond_to do |format|
diff --git a/apps/workbench/app/models/collection.rb b/apps/workbench/app/models/collection.rb
index ea81ad8..305ea01 100644
--- a/apps/workbench/app/models/collection.rb
+++ b/apps/workbench/app/models/collection.rb
@@ -98,4 +98,7 @@ class Collection < ArvadosBase
[ 'description' ]
end
+ def untrash
+ arvados_api_client.api(self.class, "/#{self.uuid}/untrash", {})
+ end
end
diff --git a/apps/workbench/app/views/application/_breadcrumbs.html.erb b/apps/workbench/app/views/application/_breadcrumbs.html.erb
index 489dbf3..2db43ed 100644
--- a/apps/workbench/app/views/application/_breadcrumbs.html.erb
+++ b/apps/workbench/app/views/application/_breadcrumbs.html.erb
@@ -69,7 +69,7 @@
<ul class="nav navbar-nav navbar-right">
<li>
<a href="/trash">
- <i class="fa fa-lg fa-fw fa-trash-o"></i>
+ <%= image_tag("trash-icon.png", size: "19x19" ) %> Trash
</a>
</li>
</ul>
diff --git a/apps/workbench/app/views/trash_items/_show_trash_items.html.erb b/apps/workbench/app/views/trash_items/_show_trash_items.html.erb
index dc615fc..153d7d0 100644
--- a/apps/workbench/app/views/trash_items/_show_trash_items.html.erb
+++ b/apps/workbench/app/views/trash_items/_show_trash_items.html.erb
@@ -1,5 +1,5 @@
-<div class="container selection-action-container">
- <div class="col-md-6 pull-left">
+<div class="container selection-action-container" style="width: 100%">
+ <div class="col-md-2 pull-left">
<div class="btn-group btn-group-sm">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">Selection... <span class="caret"></span></button>
<ul class="dropdown-menu" role="menu">
@@ -15,7 +15,7 @@
</ul>
</div>
</div>
- <div class="col-md-6 pull-right">
+ <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"
@@ -26,11 +26,11 @@
<table id="trash-index" class="topalign table table-condensed table-fixedlayout">
<colgroup>
<col width="5%" />
- <col width="15%" />
+ <col width="20%" />
<col width="10%" />
<col width="10%" />
- <col width="30%" />
- <col width="25%" />
+ <col width="10%" />
+ <col width="40%" />
<col width="5%" />
</colgroup>
@@ -40,8 +40,8 @@
<th>Name</th>
<th>Created at</th>
<th>Trashed at</th>
+ <th>Owner</th>
<th>Contents</th>
- <th>Tags</th>
<th></th>
</tr>
</thead>
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
index 73b89dd..d617d8d 100644
--- a/apps/workbench/app/views/trash_items/_show_trash_rows.html.erb
+++ b/apps/workbench/app/views/trash_items/_show_trash_rows.html.erb
@@ -1,38 +1,31 @@
<% @objects.sort_by { |obj| obj.created_at }.reverse.each do |obj| %>
<tr data-object-uuid="<%= obj.uuid %>" data-kind="<%= obj.kind %>" >
<td>
- <%= check_box_tag 'uuids[]', obj.uuid, false, :class => 'persistent-selection' %>
+ <% if obj.editable? %>
+ <%= check_box_tag 'uuids[]', obj.uuid, false, :class => 'persistent-selection' %>
+ <% end %>
</td>
<td>
- <%= link_to_if_arvados_object obj, friendly_name: true %>
+ <%= if !obj.name.blank? then obj.name else obj.uuid end %>
<td>
<%= obj.created_at.to_s if obj.created_at %>
<td>
<%= obj.trash_at.to_s if obj.trash_at %>
</td>
<td>
- <% i = 0 %>
- <% while i < 3 and i < obj.files.length %>
+ <%= link_to_if_arvados_object obj.owner_uuid, friendly_name: true %>
+ </td>
+ <td>
+ <% for i in (0..[2, obj.files.length-1].min) %>
<% file = obj.files[i] %>
<% file_path = "#{file[0]}/#{file[1]}" %>
- <%= link_to file[1], {controller: 'collections', action: 'show_file', uuid: obj.uuid, file: file_path, size: file[2], disposition: 'inline'}, {title: 'View in browser'} %><br />
- <% i += 1 %>
+ <%= file_path %><br />
<% end %>
- <% if i < obj.files.length %>
+ <% if obj.files.length > 3 %>
⋮
<% end %>
</td>
<td>
- <span class="tag-container">
- <% if @collection_info[obj.uuid] %>
- <% @collection_info[obj.uuid][:tag_links].each do |tag_link| %>
- <span class="label label-info" data-tag-link-uuid="<%= tag_link.uuid %>"><%= tag_link.name %>
- </span>
- <% end %>
- <% end %>
- </span>
- </td>
- <td>
<%= render partial: 'untrash_item', locals: {object:obj} %>
</td>
</tr>
diff --git a/apps/workbench/app/views/trash_items/_untrash_item.html.erb b/apps/workbench/app/views/trash_items/_untrash_item.html.erb
index a40a4be..2ba9dc9 100644
--- a/apps/workbench/app/views/trash_items/_untrash_item.html.erb
+++ b/apps/workbench/app/views/trash_items/_untrash_item.html.erb
@@ -1,5 +1,7 @@
<% if object.editable? %>
- <%= link_to({action: 'untrash_items', selection: [object.uuid]}, remote: true, method: :post, data: {confirm: "Un-trash #{object.class_for_display.downcase} '#{object.friendly_link_name}'?"}) do %>
+ <% msg = "Un-trash '" + if !object.name.blank? then object.name else object.uuid end + "'?" %>
+ <%= link_to({action: 'untrash_items', selection: [object.uuid]}, remote: true, method: :post,
+ data: {confirm: msg}) do %>
<i class="fa fa-fw fa-recycle"></i>
<% end %>
<% end %>
diff --git a/apps/workbench/app/views/work_units/_show_all_processes.html.erb b/apps/workbench/app/views/work_units/_show_all_processes.html.erb
index ea17843..0fc1ef6 100644
--- a/apps/workbench/app/views/work_units/_show_all_processes.html.erb
+++ b/apps/workbench/app/views/work_units/_show_all_processes.html.erb
@@ -1,4 +1,4 @@
-<div class="container">
+<div class="container" style="width: 100%">
<div class="row">
<div class="pull-right">
<input type="text" class="form-control filterable-control recent-all-processes-filterable-control"
diff --git a/apps/workbench/test/integration/trash_test.rb b/apps/workbench/test/integration/trash_test.rb
new file mode 100644
index 0000000..6cac1be
--- /dev/null
+++ b/apps/workbench/test/integration/trash_test.rb
@@ -0,0 +1,87 @@
+require 'integration_helper'
+
+class TrashTest < ActionDispatch::IntegrationTest
+ setup do
+ need_javascript
+ end
+
+ test "trash page" do
+ deleted = api_fixture('collections')['deleted_on_next_sweep']
+ expired1 = api_fixture('collections')['unique_expired_collection']
+ expired2 = api_fixture('collections')['unique_expired_collection2']
+
+ # visit trash page
+ visit page_with_token('active', "/trash")
+
+ assert_text deleted['name']
+ assert_text expired1['name']
+ assert_text expired2['name']
+ assert_no_text 'foo_file'
+
+ # Un-trash one item using selection dropdown
+ 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
+
+ wait_for_ajax
+
+ assert_text expired1['name'] # this should still be there
+ assert_no_text deleted['name'] # this should no longer be here
+
+ # expired2 is not editable by me; checkbox and recycle button shouldn't be offered
+ within('tr', text: expired2['name']) do
+ assert_nil first('input')
+ assert_nil first('.fa-recycle')
+ end
+
+ # Un-trash another item using the recycle button
+ within('tr', text: expired1['name']) do
+ first('.fa-recycle').click
+ accept_alert
+ end
+
+ wait_for_ajax
+
+ assert_text expired2['name']
+ assert_no_text expired1['name']
+
+ # verify that the two un-trashed items are now shown in /collections page
+ visit page_with_token('active', "/collections")
+ assert_text deleted['uuid']
+ assert_text expired1['uuid']
+ assert_no_text expired2['uuid']
+ end
+
+ test "trash page with search" do
+ deleted = api_fixture('collections')['deleted_on_next_sweep']
+ expired = api_fixture('collections')['unique_expired_collection2']
+
+ visit page_with_token('active', "/trash")
+
+ assert_text deleted['name']
+ assert_text expired['name']
+
+ page.find_field('Search trash').set 'expired'
+
+ assert_text expired['name']
+ assert_no_text deleted['name']
+
+ click_button 'Selection...'
+ within('.selection-action-container') do
+ assert_selector 'li.disabled', text: 'Un-trash selected items'
+ end
+
+ first('input').click
+
+ click_button 'Selection...'
+ within('.selection-action-container') do
+ assert_selector 'li', text: 'Un-trash selected items'
+ assert_selector 'li.disabled', text: 'Un-trash selected items'
+ end
+ end
+end
diff --git a/services/api/app/controllers/arvados/v1/collections_controller.rb b/services/api/app/controllers/arvados/v1/collections_controller.rb
index 8ba7925..73a7e09 100644
--- a/services/api/app/controllers/arvados/v1/collections_controller.rb
+++ b/services/api/app/controllers/arvados/v1/collections_controller.rb
@@ -12,7 +12,7 @@ class Arvados::V1::CollectionsController < ApplicationController
end
def find_objects_for_index
- if params[:include_trash] || ['destroy', 'trash'].include?(action_name)
+ if params[:include_trash] || ['destroy', 'trash', 'untrash'].include?(action_name)
@objects = Collection.readable_by(*@read_users).unscoped
end
super
@@ -63,6 +63,15 @@ class Arvados::V1::CollectionsController < ApplicationController
show
end
+ def untrash
+ if @object.is_trashed
+ @object.update_attributes!(trash_at: nil)
+ else
+ raise InvalidStateTransitionError
+ end
+ show
+ end
+
def find_collections(visited, sp, &b)
case sp
when ArvadosModel
diff --git a/services/api/config/routes.rb b/services/api/config/routes.rb
index 77e5372..87c4d91 100644
--- a/services/api/config/routes.rb
+++ b/services/api/config/routes.rb
@@ -21,6 +21,7 @@ Server::Application.routes.draw do
get 'provenance', on: :member
get 'used_by', on: :member
post 'trash', on: :member
+ post 'untrash', on: :member
end
resources :groups do
get 'contents', on: :collection
diff --git a/services/api/test/fixtures/collections.yml b/services/api/test/fixtures/collections.yml
index f48fbf1..8aedbdc 100644
--- a/services/api/test/fixtures/collections.yml
+++ b/services/api/test/fixtures/collections.yml
@@ -297,7 +297,7 @@ unique_expired_collection:
trash_at: 2001-01-01T00:00:00Z
delete_at: 2038-01-01T00:00:00Z
manifest_text: ". 29d7797f1888013986899bc9083783fa+3 0:3:expired\n"
- name: unique_expired_collection
+ name: unique_expired_collection1
unique_expired_collection2:
uuid: zzzzz-4zz18-mto52zx1s7sn3jr
commit 695a100d4bd3bf4f5534c7e489c118c2917bf35a
Author: radhika <radhika at curoverse.com>
Date: Tue May 30 18:35:06 2017 -0400
9587: trash page
diff --git a/apps/workbench/app/assets/javascripts/selection.js.erb b/apps/workbench/app/assets/javascripts/selection.js.erb
index f60bef7..a8e2738 100644
--- a/apps/workbench/app/assets/javascripts/selection.js.erb
+++ b/apps/workbench/app/assets/javascripts/selection.js.erb
@@ -81,6 +81,10 @@ function enable_disable_selection_actions() {
toggleClass('disabled',
($checked.length < 0) ||
!($checked.length > 0 && collection_lock_classes && collection_lock_classes.indexOf("fa-unlock") !=-1));
+ $('[data-selection-action=untrash-selected-items]', $container).
+ closest('li').
+ toggleClass('disabled',
+ ($checked.length < 1));
}
$(document).
diff --git a/apps/workbench/app/controllers/trash_items_controller.rb b/apps/workbench/app/controllers/trash_items_controller.rb
new file mode 100644
index 0000000..5190474
--- /dev/null
+++ b/apps/workbench/app/controllers/trash_items_controller.rb
@@ -0,0 +1,89 @@
+class TrashItemsController < ApplicationController
+ def model_class
+ Collection
+ end
+
+ def find_objects_for_index
+ # If it's not the index rows partial display, just return
+ # The /index request will again be invoked to display the
+ # partial at which time, we will be using the objects found.
+ return if !params[:partial]
+
+ trashed_items
+
+ if @objects.any?
+ @next_page_filters = next_page_filters('<=')
+ @next_page_href = url_for(partial: :trash_rows,
+ filters: @next_page_filters.to_json)
+ preload_links_for_objects(@objects.to_a)
+ else
+ @next_page_href = nil
+ end
+ end
+
+ def next_page_href with_params={}
+ @next_page_href
+ end
+
+ def trashed_items
+ # API server index doesn't return manifest_text by default, but our
+ # callers want it unless otherwise specified.
+ @select ||= Collection.columns.map(&:name)
+ 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 = base_search.filter(params[:filters]) if params[:filters]
+
+ if params[:search].andand.length.andand > 0
+ tags = Link.where(any: ['contains', params[:search]])
+ @objects = (base_search.limit(limit).offset(offset).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
+
+ @links = Link.where(head_uuid: @objects.collect(&:uuid))
+ @collection_info = {}
+ @objects.each do |c|
+ @collection_info[c.uuid] = {
+ tag_links: [],
+ wanted: false,
+ wanted_by_me: false,
+ provenance: [],
+ links: []
+ }
+ end
+ @links.each do |link|
+ @collection_info[link.head_uuid] ||= {}
+ info = @collection_info[link.head_uuid]
+ case link.link_class
+ when 'tag'
+ info[:tag_links] << link
+ when 'resources'
+ info[:wanted] = true
+ info[:wanted_by_me] ||= link.tail_uuid == current_user.uuid
+ when 'provenance'
+ info[:provenance] << link.name
+ end
+ info[:links] << link
+ end
+ @request_url = request.url
+ end
+
+ def untrash_items
+ @untrashed_uuids = []
+
+ updates = {trash_at: nil}
+
+ params[:selection].collect { |uuid| ArvadosBase.find uuid }.each do |item|
+ item.update_attributes updates
+ @untrashed_uuids << item.uuid
+ end
+
+ respond_to do |format|
+ format.js
+ end
+ end
+end
diff --git a/apps/workbench/app/models/arvados_base.rb b/apps/workbench/app/models/arvados_base.rb
index 5d6a4c9..f06193c 100644
--- a/apps/workbench/app/models/arvados_base.rb
+++ b/apps/workbench/app/models/arvados_base.rb
@@ -152,6 +152,10 @@ class ArvadosBase < ActiveRecord::Base
ArvadosResourceList.new(self).distinct(*args)
end
+ def self.include_trash(*args)
+ ArvadosResourceList.new(self).include_trash(*args)
+ end
+
def self.eager(*args)
ArvadosResourceList.new(self).eager(*args)
end
diff --git a/apps/workbench/app/models/arvados_resource_list.rb b/apps/workbench/app/models/arvados_resource_list.rb
index 35dcde3..8ae48d8 100644
--- a/apps/workbench/app/models/arvados_resource_list.rb
+++ b/apps/workbench/app/models/arvados_resource_list.rb
@@ -21,6 +21,11 @@ class ArvadosResourceList
self
end
+ def include_trash(option=nil)
+ @include_trash = option
+ self
+ end
+
def limit(max_results)
if not max_results.nil? and not max_results.is_a? Integer
raise ArgumentError("argument to limit() must be an Integer or nil")
@@ -192,6 +197,7 @@ class ArvadosResourceList
api_params[:order] = @orderby_spec if @orderby_spec
api_params[:filters] = @filters if @filters
api_params[:distinct] = @distinct if @distinct
+ api_params[:include_trash] = @include_trash if @include_trash
if @fetch_multiple_pages
# Default limit to (effectively) api server's MAX_LIMIT
api_params[:limit] = 2**(0.size*8 - 1) - 1
diff --git a/apps/workbench/app/views/application/_breadcrumbs.html.erb b/apps/workbench/app/views/application/_breadcrumbs.html.erb
index 3ef2aec..489dbf3 100644
--- a/apps/workbench/app/views/application/_breadcrumbs.html.erb
+++ b/apps/workbench/app/views/application/_breadcrumbs.html.erb
@@ -66,4 +66,11 @@
<% end %>
<% end %>
</ul>
+ <ul class="nav navbar-nav navbar-right">
+ <li>
+ <a href="/trash">
+ <i class="fa fa-lg fa-fw fa-trash-o"></i>
+ </a>
+ </li>
+ </ul>
</nav>
diff --git a/apps/workbench/app/views/trash_items/_show_trash_items.html.erb b/apps/workbench/app/views/trash_items/_show_trash_items.html.erb
new file mode 100644
index 0000000..dc615fc
--- /dev/null
+++ b/apps/workbench/app/views/trash_items/_show_trash_items.html.erb
@@ -0,0 +1,54 @@
+<div class="container selection-action-container">
+ <div class="col-md-6 pull-left">
+ <div class="btn-group btn-group-sm">
+ <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">Selection... <span class="caret"></span></button>
+ <ul class="dropdown-menu" role="menu">
+ <li><%= link_to "Un-trash selected items", '#',
+ method: :post,
+ remote: true,
+ 'id' => 'untrash_selected_items',
+ 'data-href' => untrash_items_trash_items_path,
+ 'data-selection-param-name' => 'selection[]',
+ 'data-selection-action' => 'untrash-selected-items',
+ 'data-toggle' => 'dropdown'
+ %></li>
+ </ul>
+ </div>
+ </div>
+ <div class="col-md-6 pull-right">
+ <input type="text" class="form-control filterable-control recent-trash-items"
+ placeholder="Search trash"
+ data-filterable-target="#recent-trash-items"
+ value="<%= params[:search] %>" />
+ </div>
+
+ <div>
+ <table id="trash-index" class="topalign table table-condensed table-fixedlayout">
+ <colgroup>
+ <col width="5%" />
+ <col width="15%" />
+ <col width="10%" />
+ <col width="10%" />
+ <col width="30%" />
+ <col width="25%" />
+ <col width="5%" />
+ </colgroup>
+
+ <thead>
+ <tr class="contain-align-left">
+ <th></th>
+ <th>Name</th>
+ <th>Created at</th>
+ <th>Trashed at</th>
+ <th>Contents</th>
+ <th>Tags</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>
+ </table>
+ </div>
+</div>
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..73b89dd
--- /dev/null
+++ b/apps/workbench/app/views/trash_items/_show_trash_rows.html.erb
@@ -0,0 +1,39 @@
+<% @objects.sort_by { |obj| obj.created_at }.reverse.each do |obj| %>
+ <tr data-object-uuid="<%= obj.uuid %>" data-kind="<%= obj.kind %>" >
+ <td>
+ <%= check_box_tag 'uuids[]', obj.uuid, false, :class => 'persistent-selection' %>
+ </td>
+ <td>
+ <%= link_to_if_arvados_object obj, friendly_name: true %>
+ <td>
+ <%= obj.created_at.to_s if obj.created_at %>
+ <td>
+ <%= obj.trash_at.to_s if obj.trash_at %>
+ </td>
+ <td>
+ <% i = 0 %>
+ <% while i < 3 and i < obj.files.length %>
+ <% file = obj.files[i] %>
+ <% file_path = "#{file[0]}/#{file[1]}" %>
+ <%= link_to file[1], {controller: 'collections', action: 'show_file', uuid: obj.uuid, file: file_path, size: file[2], disposition: 'inline'}, {title: 'View in browser'} %><br />
+ <% i += 1 %>
+ <% end %>
+ <% if i < obj.files.length %>
+ ⋮
+ <% end %>
+ </td>
+ <td>
+ <span class="tag-container">
+ <% if @collection_info[obj.uuid] %>
+ <% @collection_info[obj.uuid][:tag_links].each do |tag_link| %>
+ <span class="label label-info" data-tag-link-uuid="<%= tag_link.uuid %>"><%= tag_link.name %>
+ </span>
+ <% end %>
+ <% end %>
+ </span>
+ </td>
+ <td>
+ <%= render partial: 'untrash_item', locals: {object:obj} %>
+ </td>
+ </tr>
+<% end %>
diff --git a/apps/workbench/app/views/trash_items/_untrash_item.html.erb b/apps/workbench/app/views/trash_items/_untrash_item.html.erb
new file mode 100644
index 0000000..a40a4be
--- /dev/null
+++ b/apps/workbench/app/views/trash_items/_untrash_item.html.erb
@@ -0,0 +1,5 @@
+<% if object.editable? %>
+ <%= link_to({action: 'untrash_items', selection: [object.uuid]}, remote: true, method: :post, data: {confirm: "Un-trash #{object.class_for_display.downcase} '#{object.friendly_link_name}'?"}) do %>
+ <i class="fa fa-fw fa-recycle"></i>
+ <% end %>
+<% end %>
diff --git a/apps/workbench/app/views/trash_items/index.html.erb b/apps/workbench/app/views/trash_items/index.html.erb
new file mode 100644
index 0000000..bd55a3f
--- /dev/null
+++ b/apps/workbench/app/views/trash_items/index.html.erb
@@ -0,0 +1 @@
+<%= render partial: 'show_trash_items' %>
diff --git a/apps/workbench/app/views/trash_items/untrash_items.js.erb b/apps/workbench/app/views/trash_items/untrash_items.js.erb
new file mode 100644
index 0000000..3d26658
--- /dev/null
+++ b/apps/workbench/app/views/trash_items/untrash_items.js.erb
@@ -0,0 +1,5 @@
+<% @untrashed_uuids.each do |uuid| %>
+ $('[data-object-uuid=<%= uuid %>]').hide('slow', function() {
+ $(this).remove();
+ });
+<% end %>
diff --git a/apps/workbench/config/routes.rb b/apps/workbench/config/routes.rb
index 0eef73f..badb471 100644
--- a/apps/workbench/config/routes.rb
+++ b/apps/workbench/config/routes.rb
@@ -108,6 +108,11 @@ ArvadosWorkbench::Application.routes.draw do
resources :workflows
+ get "trash" => 'trash_items#index', :as => :trash
+ resources :trash_items do
+ post 'untrash_items', on: :collection
+ end
+
post 'actions' => 'actions#post'
get 'actions' => 'actions#show'
get 'websockets' => 'websocket#index'
diff --git a/services/api/app/controllers/arvados/v1/collections_controller.rb b/services/api/app/controllers/arvados/v1/collections_controller.rb
index 939ca21..8ba7925 100644
--- a/services/api/app/controllers/arvados/v1/collections_controller.rb
+++ b/services/api/app/controllers/arvados/v1/collections_controller.rb
@@ -13,7 +13,7 @@ class Arvados::V1::CollectionsController < ApplicationController
def find_objects_for_index
if params[:include_trash] || ['destroy', 'trash'].include?(action_name)
- @objects = Collection.unscoped.readable_by(*@read_users)
+ @objects = Collection.readable_by(*@read_users).unscoped
end
super
end
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list