[ARVADOS] created: eaa436ddd4aadf4fad387ea6115e35c885828ce0
git at public.curoverse.com
git at public.curoverse.com
Tue Jan 28 21:16:22 EST 2014
at eaa436ddd4aadf4fad387ea6115e35c885828ce0 (commit)
commit eaa436ddd4aadf4fad387ea6115e35c885828ce0
Author: Tom Clegg <tom at curoverse.com>
Date: Tue Jan 28 18:15:43 2014 -0800
Show condensed data about pipeline instances side by side on "compare"
page.
refs #1978
diff --git a/apps/workbench/app/assets/stylesheets/application.css b/apps/workbench/app/assets/stylesheets/application.css
index 9c67653..d2993be 100644
--- a/apps/workbench/app/assets/stylesheets/application.css
+++ b/apps/workbench/app/assets/stylesheets/application.css
@@ -75,3 +75,6 @@ form input.search-mini {
form.small-form-margin {
margin-bottom: 2px;
}
+.nowrap {
+ white-space: nowrap;
+}
diff --git a/apps/workbench/app/controllers/pipeline_instances_controller.rb b/apps/workbench/app/controllers/pipeline_instances_controller.rb
index f3932bf..99a4ddd 100644
--- a/apps/workbench/app/controllers/pipeline_instances_controller.rb
+++ b/apps/workbench/app/controllers/pipeline_instances_controller.rb
@@ -1,12 +1,75 @@
class PipelineInstancesController < ApplicationController
skip_before_filter :find_object_by_uuid, only: :compare
before_filter :find_objects_by_uuid, only: :compare
+ include PipelineInstancesHelper
def compare
+ @rows = [] # each is {name: S, components: [...]}
+
+ # Build a table: x=pipeline y=component
+ @objects.each_with_index do |pi, pi_index|
+ pipeline_jobs(pi).each do |component|
+ # Find a cell with the same name as this component but no
+ # entry for this pipeline
+ target_row = nil
+ @rows.each_with_index do |row, row_index|
+ if row[:name] == component[:name] and !row[:components][pi_index]
+ target_row = row
+ end
+ end
+ if !target_row
+ target_row = {name: component[:name], components: []}
+ @rows << target_row
+ end
+ target_row[:components][pi_index] = component
+ end
+ end
+
+ @rows.each do |row|
+ # Build a "normal" pseudo-component for this row by picking the
+ # most common value for each attribute. If all values are
+ # equally common, there is no "normal".
+ normal = {} # attr => most common value
+ highscore = {} # attr => how common "normal" is
+ score = {} # attr => { value => how common }
+ row[:components].each do |pj|
+ pj.each do |k,v|
+ vstr = for_comparison v
+ score[k] ||= {}
+ score[k][vstr] = (score[k][vstr.to_s] || 0) + 1
+ highscore[k] ||= 0
+ if score[k][vstr] == highscore[k]
+ # tie for first place = no "normal"
+ normal.delete k
+ elsif score[k][vstr] == highscore[k] + 1
+ # more pipelines have v than anything else
+ highscore[k] = score[k][vstr]
+ normal[k] = vstr
+ end
+ end
+ end
+
+ # Add a hash in component[:is_normal]: { attr => is_the_value_normal? }
+ row[:components].each do |pj|
+ pj[:is_normal] = {}
+ pj.each do |k,v|
+ pj[:is_normal][k] = (normal.has_key?(k) && normal[k] == for_comparison(v))
+ end
+ end
+ end
end
protected
+ def for_comparison v
+ if v.is_a? Hash or v.is_a? Array
+ v.to_json
+ else
+ v.to_s
+ end
+ end
+
def find_objects_by_uuid
- @objects = model_class.where(uuid: params[:uuid])
+ @objects = model_class.where(uuid: params[:uuid].split('/'))
end
+
end
diff --git a/apps/workbench/app/helpers/application_helper.rb b/apps/workbench/app/helpers/application_helper.rb
index 5500938..fe7012a 100644
--- a/apps/workbench/app/helpers/application_helper.rb
+++ b/apps/workbench/app/helpers/application_helper.rb
@@ -69,6 +69,7 @@ module ApplicationHelper
link_name = "#{resource_class.to_s}: #{link_name}"
end
end
+ style_opts[:class] = (style_opts[:class] || '') + ' nowrap'
link_to link_name, { controller: resource_class.to_s.underscore.pluralize, action: 'show', id: link_uuid }, style_opts
else
attrvalue
diff --git a/apps/workbench/app/helpers/pipeline_instances_helper.rb b/apps/workbench/app/helpers/pipeline_instances_helper.rb
index c792db8..f314c65 100644
--- a/apps/workbench/app/helpers/pipeline_instances_helper.rb
+++ b/apps/workbench/app/helpers/pipeline_instances_helper.rb
@@ -1,18 +1,36 @@
module PipelineInstancesHelper
- def pipeline_jobs
- if @object.components[:steps].is_a? Array
- pipeline_jobs_oldschool
- elsif @object.components.is_a? Hash
- pipeline_jobs_newschool
+ def pipeline_jobs object=nil
+ object ||= @object
+ if object.components[:steps].is_a? Array
+ pipeline_jobs_oldschool object
+ elsif object.components.is_a? Hash
+ pipeline_jobs_newschool object
end
end
+ def render_pipeline_jobs
+ pipeline_jobs.collect do |pj|
+ render_pipeline_job pj
+ end
+ end
+
+ def render_pipeline_job pj
+ if pj[:percent_done]
+ pj[:progress_bar] = raw("<div class=\"progress\" style=\"width:100px\"><div class=\"bar bar-success\" style=\"width:#{pj[:percent_done]}%\"></div><div class=\"bar\" style=\"width:#{pj[:percent_running]}%\"></div></div>")
+ elsif pj[:progress]
+ raw("<div class=\"progress\" style=\"width:100px\"><div class=\"bar\" style=\"width:#{pj[:progress]*100}%\"></div></div>")
+ end
+ pj[:output_link] = link_to_if_arvados_object pj[:output]
+ pj[:job_link] = link_to_if_arvados_object pj[:job][:uuid]
+ pj
+ end
+
protected
- def pipeline_jobs_newschool
+ def pipeline_jobs_newschool object
ret = []
i = -1
- @object.components.each do |cname, c|
+ object.components.each do |cname, c|
i += 1
pj = {index: i, name: cname}
pj[:job] = c[:job].is_a?(Hash) ? c[:job] : {}
@@ -58,20 +76,18 @@ module PipelineInstancesHelper
end
end
pj[:job_id] = pj[:job][:uuid]
- pj[:job_link] = link_to_if_arvados_object pj[:job][:uuid]
+ pj[:script] = pj[:job][:script]
pj[:script_version] = pj[:job][:script_version]
pj[:output] = pj[:job][:output]
pj[:finished_at] = (Time.parse(pj[:job][:finished_at]) rescue nil)
- pj[:progress_bar] = raw("<div class=\"progress\" style=\"width:100px\"><div class=\"bar bar-success\" style=\"width:#{pj[:percent_done]}%\"></div><div class=\"bar\" style=\"width:#{pj[:percent_running]}%\"></div></div>")
- pj[:output_link] = link_to_if_arvados_object pj[:output]
ret << pj
end
ret
end
- def pipeline_jobs_oldschool
+ def pipeline_jobs_oldschool object
ret = []
- @object.components[:steps].each_with_index do |step, i|
+ object.components[:steps].each_with_index do |step, i|
pj = {index: i, name: step[:name]}
if step[:complete] and step[:complete] != 0
if step[:output_data_locator]
@@ -112,8 +128,6 @@ module PipelineInstancesHelper
pj[:script_version] = (step[:warehousejob][:revision] rescue nil)
pj[:output] = step[:output_data_locator]
pj[:finished_at] = (Time.parse(step[:warehousejob][:finishtime]) rescue nil)
- pj[:progress_bar] = raw("<div class=\"progress\" style=\"width:100px\"><div class=\"bar\" style=\"width:#{pj[:progress]*100}%\"></div></div>")
- pj[:output_link] = link_to_if_arvados_object pj[:output]
ret << pj
end
ret
diff --git a/apps/workbench/app/views/application/_arvados_object_attr.html.erb b/apps/workbench/app/views/application/_arvados_object_attr.html.erb
index ec2ac36..d7e126e 100644
--- a/apps/workbench/app/views/application/_arvados_object_attr.html.erb
+++ b/apps/workbench/app/views/application/_arvados_object_attr.html.erb
@@ -1,8 +1,9 @@
+<% object ||= @object %>
<% if attrvalue.is_a? Hash then attrvalue.each do |infokey, infocontent| %>
<tr class="info">
<td><%= attr %>[<%= infokey %>]</td>
<td>
- <%= render partial: 'application/arvados_attr_value', locals: { obj: @object, attr: nil, attrvalue: infocontent } %>
+ <%= render partial: 'application/arvados_attr_value', locals: { obj: object, attr: nil, attrvalue: infocontent } %>
</td>
</tr>
<% end %>
@@ -10,7 +11,7 @@
<tr class="<%= 'info' if %w(uuid owner_uuid created_at modified_at modified_by_user_uuid modified_by_client_uuid updated_at).index(attr.to_s).nil? %>">
<td><%= attr %></td>
<td>
- <%= render partial: 'application/arvados_attr_value', locals: { obj: @object, attr: attr, attrvalue: attrvalue } %>
+ <%= render partial: 'application/arvados_attr_value', locals: { obj: object, attr: attr, attrvalue: attrvalue } %>
</td>
</tr>
<% end %>
diff --git a/apps/workbench/app/views/pipeline_instances/compare.html.erb b/apps/workbench/app/views/pipeline_instances/compare.html.erb
index f75f32a..7f90064 100644
--- a/apps/workbench/app/views/pipeline_instances/compare.html.erb
+++ b/apps/workbench/app/views/pipeline_instances/compare.html.erb
@@ -1,44 +1,78 @@
-<table class="table table-condensed table-hover topalign">
- <thead>
- </thead>
- <tbody>
- <tr>
- <% @objects.each do |object| %>
- <td>
+<% content_for :css do %>
+.notnormal {
+ background: #ffffaa;
+}
+.headrow div {
+ padding-top: .5em;
+ padding-bottom: .5em;
+}
+.headrow:first-child {
+ border-bottom: 1px solid black;
+}
+<% end %>
- <table class="table table-condensed table-hover topalign">
- <thead>
- </thead>
- <tbody>
- <% object.attributes_for_display.each do |attr, attrvalue| %>
- <% if attr == 'components' and attrvalue.is_a? Hash %>
+<ul class="breadcrumb">
+ <li><%= link_to 'Pipeline instances', pipeline_instances_path %> <span class="divider">/</span></li>
+ <li class="active">Compare</li>
+</ul>
- <tr class="info"><td><%= attr %></td><td>
- <table class="table">
- <% pipeline_jobs.each do |pj| %>
- <tr><% %w(index name result job_link script script_version progress_detail progress_bar output_link).each do |key| %>
- <td>
- <% if key == 'script_version' %>
- <%= pj[key.to_sym][0..6] rescue '' %>
- <% else %>
- <%= pj[key.to_sym] %>
- <% end %>
- </td>
- <% end %>
- </tr>
- <% end %>
- </table>
- </td></tr>
+<% pi_span = [(10.0/(@objects.count)).floor,1].max %>
+<div>
+<% [['Instance', :uuid], ['Template', :pipeline_template_uuid]].each do |label, attr| %>
+<div class="row headrow">
+ <div class="span2">
+ <%# label %>
+ </div>
+ <% @objects.each do |object| %>
+ <div class="span<%= pi_span %>">
+ <%= render partial: 'application/arvados_attr_value', locals: { obj: object, attr: attr, attrvalue: object.send(attr.to_sym) } %>
+ </div>
+ <% end %>
+</div>
+<% end %>
+</div>
- <% else %>
- <%= render partial: 'application/arvados_object_attr', locals: { attr: attr, attrvalue: attrvalue } %>
- <% end %>
- <% end %>
- </tbody>
- </table>
+<% @rows.each do |row| %>
+<div class="row">
+ <div class="span2">
+ <%= row[:name] %>
+ </div>
+ <% @objects.each_with_index do |_, x| %>
+ <div class="span<%= pi_span %>">
+ <div class="row">
- </td>
- <% end %>
- </tr>
- </tbody>
-</table>
+ <% if row[:components][x] %>
+ <% pj = render_pipeline_job row[:components][x] %>
+
+ <div class="span3">
+ <%= link_to_if_arvados_object pj[:job_id], {friendly_name: true, with_class_name: true}, {class: 'deemphasize'} %>
+ </div>
+
+ <% %w(script script_version script_parameters output).each do |key| %>
+ <div class="span3">
+ <% unless key=='output' and pj[:result] != 'complete' %>
+ <% val = pj[key.to_sym] || pj[:job].andand[key.to_sym] %>
+ <% link_name = case
+ when key == 'script_version' && val.match(/^[0-9a-f]{7,}$/)
+ val = val[0..7] # TODO: leave val alone, make link_to handle git commits
+ when key == 'output'
+ val.sub! /\+K.*$/, ''
+ val[0..12]
+ when key == 'script_parameters'
+ val = val.keys.sort.join(', ')
+ end
+ %>
+ <span class="deemphasize"><%= key %>:</span> <span class="<%= 'notnormal' if !pj[:is_normal][key.to_sym] %>"><%= link_to_if_arvados_object val, {friendly_name: true, link_text: link_name} %></span>
+ <% end %>
+ </div>
+ <% end %>
+ <% else %>
+ None
+ <% end %>
+ </div>
+ </div>
+ <% end %>
+</div>
+<div class="row" style="padding: .5em">
+</div>
+<% end %>
diff --git a/apps/workbench/app/views/pipeline_instances/show.html.erb b/apps/workbench/app/views/pipeline_instances/show.html.erb
index 74c090d..a36412e 100644
--- a/apps/workbench/app/views/pipeline_instances/show.html.erb
+++ b/apps/workbench/app/views/pipeline_instances/show.html.erb
@@ -7,7 +7,7 @@
<tr class="info"><td><%= attr %></td><td>
<table class="table">
- <% pipeline_jobs.each do |pj| %>
+ <% render_pipeline_jobs.each do |pj| %>
<tr><% %w(index name result job_link script script_version progress_detail progress_bar output_link).each do |key| %>
<td>
<% if key == 'script_version' %>
diff --git a/apps/workbench/config/routes.rb b/apps/workbench/config/routes.rb
index a035535..c9bf19b 100644
--- a/apps/workbench/config/routes.rb
+++ b/apps/workbench/config/routes.rb
@@ -26,9 +26,8 @@ ArvadosWorkbench::Application.routes.draw do
resources :groups
resources :specimens
resources :pipeline_templates
- resources :pipeline_instances do
- get 'compare/*uuid' => 'pipeline_instances#compare'
- end
+ resources :pipeline_instances
+ get '/pipeline_instances/compare/*uuid' => 'pipeline_instances#compare'
resources :links
match '/collections/graph' => 'collections#graph'
resources :collections
commit 043f54270bb129da9f5f07c2c975c6e89edd4a22
Author: Tom Clegg <tom at curoverse.com>
Date: Tue Jan 28 07:57:47 2014 -0800
Add pipeline_instances/compare page
diff --git a/apps/workbench/app/controllers/pipeline_instances_controller.rb b/apps/workbench/app/controllers/pipeline_instances_controller.rb
index afb9949..f3932bf 100644
--- a/apps/workbench/app/controllers/pipeline_instances_controller.rb
+++ b/apps/workbench/app/controllers/pipeline_instances_controller.rb
@@ -1,2 +1,12 @@
class PipelineInstancesController < ApplicationController
+ skip_before_filter :find_object_by_uuid, only: :compare
+ before_filter :find_objects_by_uuid, only: :compare
+
+ def compare
+ end
+
+ protected
+ def find_objects_by_uuid
+ @objects = model_class.where(uuid: params[:uuid])
+ end
end
diff --git a/apps/workbench/app/views/pipeline_instances/compare.html.erb b/apps/workbench/app/views/pipeline_instances/compare.html.erb
new file mode 100644
index 0000000..f75f32a
--- /dev/null
+++ b/apps/workbench/app/views/pipeline_instances/compare.html.erb
@@ -0,0 +1,44 @@
+<table class="table table-condensed table-hover topalign">
+ <thead>
+ </thead>
+ <tbody>
+ <tr>
+ <% @objects.each do |object| %>
+ <td>
+
+ <table class="table table-condensed table-hover topalign">
+ <thead>
+ </thead>
+ <tbody>
+ <% object.attributes_for_display.each do |attr, attrvalue| %>
+ <% if attr == 'components' and attrvalue.is_a? Hash %>
+
+ <tr class="info"><td><%= attr %></td><td>
+ <table class="table">
+ <% pipeline_jobs.each do |pj| %>
+ <tr><% %w(index name result job_link script script_version progress_detail progress_bar output_link).each do |key| %>
+ <td>
+ <% if key == 'script_version' %>
+ <%= pj[key.to_sym][0..6] rescue '' %>
+ <% else %>
+ <%= pj[key.to_sym] %>
+ <% end %>
+ </td>
+ <% end %>
+ </tr>
+ <% end %>
+ </table>
+ </td></tr>
+
+ <% else %>
+ <%= render partial: 'application/arvados_object_attr', locals: { attr: attr, attrvalue: attrvalue } %>
+ <% end %>
+ <% end %>
+ </tbody>
+ </table>
+
+ </td>
+ <% end %>
+ </tr>
+ </tbody>
+</table>
diff --git a/apps/workbench/config/routes.rb b/apps/workbench/config/routes.rb
index f2480c6..a035535 100644
--- a/apps/workbench/config/routes.rb
+++ b/apps/workbench/config/routes.rb
@@ -26,7 +26,9 @@ ArvadosWorkbench::Application.routes.draw do
resources :groups
resources :specimens
resources :pipeline_templates
- resources :pipeline_instances
+ resources :pipeline_instances do
+ get 'compare/*uuid' => 'pipeline_instances#compare'
+ end
resources :links
match '/collections/graph' => 'collections#graph'
resources :collections
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list