17119: bugfix: when "count: none" is specified, the group/contents
[arvados.git] / apps / workbench / app / controllers / trash_items_controller.rb
1 # Copyright (C) The Arvados Authors. All rights reserved.
2 #
3 # SPDX-License-Identifier: AGPL-3.0
4
5 class TrashItemsController < ApplicationController
6   def model_class
7     Collection
8   end
9
10   def index_pane_list
11     %w(Trashed_collections Trashed_projects)
12   end
13
14   def find_objects_for_index
15     # If it's not the index rows partial display, just return
16     # The /index request will again be invoked to display the
17     # partial at which time, we will be using the objects found.
18     return if !params[:partial]
19
20     trashed_items
21
22     if @objects.any?
23       @objects = @objects.sort_by { |obj| obj.modified_at }.reverse
24       @next_page_filters = next_page_filters('<=')
25       @next_page_href = url_for(partial: params[:partial],
26                                 filters: @next_page_filters.to_json)
27     else
28       @next_page_href = nil
29     end
30   end
31
32   def next_page_href with_params={}
33     @next_page_href
34   end
35
36   def next_page_filters nextpage_operator
37     next_page_filters = @filters.reject do |attr, op, val|
38       (attr == 'modified_at' and op == nextpage_operator) or
39       (attr == 'uuid' and op == 'not in')
40     end
41
42     if @objects.any?
43       last_trash_at = @objects.last.modified_at
44
45       last_uuids = []
46       @objects.each do |obj|
47         last_uuids << obj.uuid if obj.trash_at.eql?(last_trash_at)
48       end
49
50       next_page_filters += [['modified_at', nextpage_operator, last_trash_at]]
51       next_page_filters += [['uuid', 'not in', last_uuids]]
52     end
53
54     next_page_filters
55   end
56
57   def trashed_items
58     if params[:partial] == "trashed_collection_rows"
59       query_on = Collection
60     elsif params[:partial] == "trashed_project_rows"
61       query_on = Group
62     end
63
64     last_mod_at = nil
65     last_uuids = []
66
67     # API server index doesn't return manifest_text by default, but our
68     # callers want it unless otherwise specified.
69     #@select ||= query_on.columns.map(&:name) - %w(id updated_at)
70     limit = if params[:limit] then params[:limit].to_i else 100 end
71     offset = if params[:offset] then params[:offset].to_i else 0 end
72
73     @objects = []
74     while !@objects.any?
75       base_search = query_on
76
77       if !last_mod_at.nil?
78         base_search = base_search.filter([["modified_at", "<=", last_mod_at], ["uuid", "not in", last_uuids]])
79       end
80
81       base_search = base_search.include_trash(true).limit(limit).with_count("none").offset(offset)
82
83       if params[:filters].andand.length.andand > 0
84         tags = Link.filter(params[:filters]).with_count("none")
85         tagged = []
86         if tags.results.length > 0
87           tagged = query_on.include_trash(true).where(uuid: tags.collect(&:head_uuid))
88         end
89         @objects = (tagged | base_search.filter(params[:filters])).uniq(&:uuid)
90       else
91         @objects = base_search.where(is_trashed: true)
92       end
93
94       if @objects.any?
95         owner_uuids = @objects.collect(&:owner_uuid).uniq
96         @owners = {}
97         @not_trashed = {}
98         [Group, User].each do |owner_class|
99           owner_class.filter([["uuid", "in", owner_uuids]]).with_count("none")
100             .include_trash(true).fetch_multiple_pages(false)
101             .each do |owner|
102             @owners[owner.uuid] = owner
103           end
104         end
105         Group.filter([["uuid", "in", owner_uuids]]).with_count("none").select([:uuid]).each do |grp|
106           @not_trashed[grp.uuid] = true
107         end
108       else
109         return
110       end
111
112       last_mod_at = @objects.last.modified_at
113       last_uuids = []
114       @objects.each do |obj|
115         last_uuids << obj.uuid if obj.modified_at.eql?(last_mod_at)
116       end
117
118       @objects = @objects.select {|item| item.is_trashed || @not_trashed[item.owner_uuid].nil? }
119     end
120   end
121
122   def untrash_items
123     @untrashed_uuids = []
124
125     updates = {trash_at: nil}
126
127     if params[:selection].is_a? Array
128       klass = resource_class_for_uuid(params[:selection][0])
129     else
130       klass = resource_class_for_uuid(params[:selection])
131     end
132
133     first = nil
134     klass.include_trash(1).where(uuid: params[:selection]).each do |c|
135       first = c
136       c.untrash
137       @untrashed_uuids << c.uuid
138     end
139
140     respond_to do |format|
141       format.js
142       format.html do
143         redirect_to first
144       end
145     end
146   end
147 end