11739: preload containers and children of all container_requests in dashboard display.
[arvados.git] / apps / workbench / app / views / projects / _show_dashboard.html.erb
1 <%
2   recent_procs = recent_processes(12)
3
4   # preload container_uuids of any container requests
5   recent_crs = recent_procs.map {|p| p if p.is_a?(ContainerRequest)}.compact.uniq
6   recent_cr_containers = recent_crs.map {|cr| cr.container_uuid}.compact.uniq
7   preload_objects_for_dataclass(Container, recent_cr_containers) if recent_cr_containers.andand.any?
8
9   # fetch children of all the active crs in one call, if there are any
10   active_crs = recent_crs.each {|cr| cr if (cr.priority > 0 and cr.state != 'Final' and cr.container_uuid)}
11   active_cr_uuids = active_crs.map(&:uuid)
12   active_cr_containers = active_crs.map {|cr| cr.container_uuid}.compact.uniq
13   cr_children = {}
14   if active_cr_containers.any?
15     active_cr_containers.each { |c| cr_children[c] = []}
16     cols = ContainerRequest.columns.map(&:name) - %w(id updated_at mounts)
17     reqs = ContainerRequest.select(cols).where(requesting_container_uuid: active_cr_containers).results
18     reqs.each {|cr| cr_children[cr.requesting_container_uuid] << cr} if reqs
19   end
20
21   wus = {}
22   outputs = []
23   recent_procs.each do |p|
24     if p.uuid.in?(active_cr_uuids)
25       wu = p.work_unit(nil, child_objects=cr_children[p.container_uuid])
26     else
27       wu = p.work_unit
28     end
29
30     wus[p] = wu
31     outputs << wu.outputs
32   end
33   outputs = outputs.flatten.uniq
34
35   collection_pdhs = outputs.select {|x| !(m = CollectionsHelper.match(x)).nil?}.uniq.compact
36   collection_uuids = outputs - collection_pdhs
37
38   if Rails.configuration.show_recent_collections_on_dashboard
39     recent_cs = recent_collections(8)
40     collection_uuids = collection_uuids + recent_cs[:collections].collect {|c| c.uuid}
41     collection_uuids.flatten.uniq
42   end
43
44   preload_collections_for_objects collection_uuids if collection_uuids.any?
45   preload_for_pdhs collection_pdhs if collection_pdhs.any?
46   preload_links_for_objects(collection_pdhs + collection_uuids)
47 %>
48
49 <%
50   recent_procs_panel_width = 6
51   if !PipelineInstance.api_exists?(:index)
52     recent_procs_title = 'Recent processes'
53     run_proc_title = 'Choose a workflow to run:'
54     show_node_status = false
55     # Recent processes panel should take the entire width when is the only one
56     # being rendered.
57     if !Rails.configuration.show_recent_collections_on_dashboard
58       recent_procs_panel_width = 12
59     end
60   else
61     recent_procs_title = 'Recent pipelines and processes'
62     run_proc_title = 'Choose a pipeline or workflow to run:'
63     show_node_status = true
64   end
65 %>
66
67   <div class="row">
68     <div class="col-md-<%= recent_procs_panel_width %>">
69       <div class="panel panel-default" style="min-height: 10.5em">
70         <div class="panel-heading">
71           <span class="panel-title"><%=recent_procs_title%></span>
72           <% if current_user.andand.is_active %>
73             <span class="pull-right recent-processes-actions">
74               <span>
75                 <%= link_to(
76                 choose_work_unit_templates_path(
77                   title: run_proc_title,
78                   action_name: 'Next: choose inputs <i class="fa fa-fw fa-arrow-circle-right"></i>',
79                   action_href: work_units_path,
80                   action_method: 'post',
81                   action_data: {'selection_param' => 'work_unit[template_uuid]', 'work_unit[owner_uuid]' => current_user.uuid, 'success' => 'redirect-to-created-object'}.to_json),
82                 { class: "btn btn-primary btn-xs", remote: true }) do %>
83                   <i class="fa fa-fw fa-gear"></i> Run a process...
84                 <% end %>
85               </span>
86               <span>
87                   <%= link_to all_processes_path, class: 'btn btn-default btn-xs' do %>
88                     All processes <i class="fa fa-fw fa-arrow-circle-right"></i>
89                   <% end %>
90               </span>
91             </span>
92           <% end %>
93         </div>
94
95         <div class="panel-body recent-processes">
96           <% if recent_procs.empty? %>
97             No recent pipelines or processes.
98           <% else %>
99           <% wus.each do |p, wu| %>
100             <% if wu.is_finished? %>
101             <div class="dashboard-panel-info-row row-<%=wu.uuid%>">
102               <div class="row">
103                 <div class="col-md-6 text-overflow-ellipsis">
104                   <%= link_to_if_arvados_object p, {friendly_name: true} %>
105                 </div>
106                 <div class="col-md-2">
107                   <span class="label label-<%=wu.state_bootstrap_class%>"><%=wu.state_label%></span>
108                 </div>
109                 <div class="col-md-4">
110                   <%= render_localized_date(wu.finished_at || wu.modified_at, "noseconds") %>
111                 </div>
112               </div>
113               <div class="row">
114                 <div class="col-md-12">
115                   <% if wu.started_at and wu.finished_at %>
116                     <% wu_time = wu.finished_at - wu.started_at %>
117                     Active for <%= render_runtime(wu_time, false) %>
118                   <% end %>
119
120                   <%= render partial: 'work_units/show_output', locals: {wu: wu, align: 'pull-right', include_icon: true} %>
121                 </div>
122               </div>
123
124             </div>
125             <% else %>
126             <div class="dashboard-panel-info-row row-<%=wu.uuid%>">
127               <div class="row">
128                 <div class="col-md-6">
129                   <%= link_to_if_arvados_object p, {friendly_name: true} %>
130                 </div>
131                 <% if wu.is_running? %>
132                 <div class="col-md-6">
133                   <div class="progress" style="margin-bottom: 0px">
134                     <% wu.progress %>
135                   </div>
136                 </div>
137                 <% else %>
138                 <div class="col-md-2">
139                   <span class="label label-<%=wu.state_bootstrap_class%>"><%=wu.state_label%></span>
140                 </div>
141                 <% end %>
142               </div>
143
144               <%
145                 children = wu.children
146                 running = children.select { |c| c.state_label == "Running" }
147                 queued = children.select { |c| c.state_label == "Queued" }
148               %>
149
150               <div class="clearfix">
151                 Started at <%= render_localized_date(wu.started_at || wu.created_at, "noseconds") %>.
152                 <% wu_time = Time.now - (wu.started_at || wu.created_at) %>
153                 Active for <%= render_runtime(wu_time, false) %>.
154
155                 <div class="pull-right">
156                   <% running.each do |r| %>
157                     <span class="label label-<%= r.state_bootstrap_class %>"> <%= r.label || r.state_label || 'Not ready' %> </span>
158                   <% end %>
159                   <% queued.each do |q| %>
160                     <span class="label label-<%= q.state_bootstrap_class %>"> <%= q.label || r.state_label || 'Not ready' %> </span>
161                   <% end %>
162                 </div>
163               </div>
164             </div>
165             <% end %>
166           <% end %>
167           <% end %>
168         </div>
169       </div>
170     </div>
171
172     <div class="col-md-6">
173       <% if show_node_status %>
174       <% nodes = Node.filter([["last_ping_at", ">", Time.now - 3600]]).results %>
175       <div class="panel panel-default" style="min-height: 10.5em">
176         <div class="panel-heading"><span class="panel-title">Compute node status</span>
177           <span class="pull-right compute-node-actions">
178             <% if current_user.andand.is_admin %>
179               <span>
180                 <%= link_to nodes_path, class: 'btn btn-default btn-xs' do %>
181                   All nodes <i class="fa fa-fw fa-arrow-circle-right"></i>
182                 <% end %>
183               </span>
184             <% end %>
185           </span>
186         </div>
187         <div class="panel-body compute-node-summary-pane">
188           <div>
189             <%= render partial: 'compute_node_summary', locals: {nodes: nodes} %>
190             <% active_nodes = [] %>
191             <% nodes.sort_by { |n| n.hostname || "" }.each do |n| %>
192               <% if n.crunch_worker_state.in? ["busy", "idle"] %>
193                 <% active_nodes << n %>
194               <% end %>
195             <% end %>
196             <% if active_nodes.any? %>
197               <div style="text-align: center">
198                 <a data-toggle="collapse" href="#compute_node_status">Details <span class="caret"></span></a>
199               </div>
200             <% end %>
201           </div>
202           <div id="compute_node_status" class="collapse">
203             <%= render partial: 'compute_node_status', locals: {nodes: active_nodes} %>
204           </div>
205         </div>
206       </div>
207       <% end %>
208       <% if Rails.configuration.show_recent_collections_on_dashboard %>
209       <div class="panel panel-default">
210         <div class="panel-heading"><span class="panel-title">Recent collections</span>
211           <span class="pull-right">
212             <%= link_to collections_path, class: 'btn btn-default btn-xs' do %>
213               All collections <i class="fa fa-fw fa-arrow-circle-right"></i>
214             <% end %>
215           </span>
216         </div>
217         <div class="panel-body">
218           <% recent_cs[:collections].each do |p| %>
219             <div class="dashboard-panel-info-row">
220               <div>
221                 <% if recent_cs[:owners][p[:owner_uuid]].is_a?(Group) %>
222                 <i class="fa fa-fw fa-folder-o"></i><%= link_to_if_arvados_object recent_cs[:owners][p[:owner_uuid]], friendly_name: true %>/
223                 <% end %>
224                 <span class="pull-right"><%= render_localized_date(p[:modified_at], "noseconds") %></span>
225               </div>
226               <div class="text-overflow-ellipsis" style="margin-left: 1em; width: 100%"><%= link_to_if_arvados_object p, {friendly_name: true, no_tags: true} %>
227               </div>
228             </div>
229           <% end %>
230         </div>
231       </div>
232       <% end %>
233     </div>
234   </div>