Pipeline parameter editing supports selection box for choosing from workbench persist...
authorPeter Amstutz <peter.amstutz@curoverse.com>
Wed, 26 Feb 2014 16:58:38 +0000 (11:58 -0500)
committerPeter Amstutz <peter.amstutz@curoverse.com>
Wed, 26 Feb 2014 16:58:38 +0000 (11:58 -0500)
Also changed layout of selection dropdown and added "clear selections" button.

apps/workbench/app/assets/javascripts/application.js
apps/workbench/app/assets/javascripts/selection.js
apps/workbench/app/assets/stylesheets/application.css.scss
apps/workbench/app/controllers/application_controller.rb
apps/workbench/app/helpers/application_helper.rb
apps/workbench/app/helpers/collections_helper.rb
apps/workbench/app/helpers/provenance_helper.rb
apps/workbench/app/models/pipeline_instance.rb
apps/workbench/app/views/layouts/application.html.erb
apps/workbench/app/views/pipeline_instances/_show_components.html.erb

index bcedc4b7b5286995760982c969a2480b2190fe1d..e7884b95165173bdce213624172957085e05c737 100644 (file)
@@ -21,7 +21,7 @@
 //= require bootstrap3-editable/bootstrap-editable
 //= require_tree .
 
-(function($){
+jQuery(function($){
     $.ajaxSetup({
         headers: {
             'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
         fixer.duplicateTheadTr();
         fixer.fixThead();
     });
-})(jQuery);
+});
index 5d0900aa768972f48728c486e19f6e98d9ac037a..29c52d6e42e8b13d570e375d8acac010006b2e07 100644 (file)
@@ -3,27 +3,31 @@
 
 /** Javascript for local persistent selection. */
 
+get_selection_list = null;
+
 (function($){
-    var get_storage = function() {
-        if (!sessionStorage.persistentSelection) {
-            sessionStorage.persistentSelection = JSON.stringify([]);
+    var storage = localStorage; // sessionStorage
+
+    get_selection_list = function() {
+        if (!storage.persistentSelection) {
+            storage.persistentSelection = JSON.stringify([]);
         }
-        return JSON.parse(sessionStorage.persistentSelection);
+        return JSON.parse(storage.persistentSelection);
     }
 
     var put_storage = function(lst) {
-        sessionStorage.persistentSelection = JSON.stringify(lst);
+        storage.persistentSelection = JSON.stringify(lst);
     }
 
     var add_selection = function(uuid, name, href, type) {
-        var lst = get_storage();
+        var lst = get_selection_list();
         lst.push({"uuid": uuid, "name": name, "href": href, "type": type});
         put_storage(lst);
         update_count();
     };
 
     var remove_selection = function(uuid) {
-        var lst = get_storage();
+        var lst = get_selection_list();
         for (var i = 0; i < lst.length; i++) {
             if (lst[i].uuid == uuid) {
                 lst.splice(i, 1);
     };
 
     var remove_selection_click = function(e) {
-        remove_selection($(this).attr('name'));
+        //remove_selection($(this).attr('name'));
+        remove_selection($(this).val());
     };
 
+    var clear_selections = function() {
+        put_storage([]);
+        update_count();
+    }
+
     var update_count = function(e) {
-        var lst = get_storage();
+        var lst = get_selection_list();
         $("#persistent-selection-count").text(lst.length);
 
-        $('#persistent-selection-list > li > table').empty();
         if (lst.length > 0) {
+            $('#persistent-selection-list').html('<li><a href="#" class="btn pull-right" id="clear_selections_button">Clear selections</a></li>'
+                                                 +'<li class="notification"><table style="width: 100%"></table></li>');
             for (var i = 0; i < lst.length; i++) {
                 $('#persistent-selection-list > li > table').append("<tr>"
-                                                       + "<td style=\"vertical-align: top\">"
-                                                       + "<span style=\"padding-right: 1em\">" + lst[i].type + "</span>"
+                                                       + "<td>"
+                                                       + "<form>"
+                                                       + "<input class='remove-selection' type='checkbox' value='" + lst[i].uuid + "' checked='true'></input>"
+                                                       + "</form>"
                                                        + "</td>"
 
                                                        + "<td>"
-                                                       + "<span><a href=\"" + lst[i].href + "\">" + lst[i].name + "</a></span>"
+                                                       + "<span style='padding-left: 1em'><a href=\"" + lst[i].href + "\">" + lst[i].name + "</a></span>"
                                                        + "</td>"
 
-                                                       + "<td>"
-                                                       + "<a href=\"#\" class=\"remove-selection\" name=\"" + lst[i].uuid + "\">" 
-                                                       + "<span class=\"glyphicon glyphicon-trash pull-right\"></span>"
-                                                       + "</a></span>"
+                                                       + "<td style=\"vertical-align: top\">"
+                                                       + "<span style=\"padding-right: 1em\">" + lst[i].type + "</span>"
                                                        + "</td>"
+
                                                        + "</tr>");
             }
         } else {
-            $('#persistent-selection-list > li > table').html("<tr><td>No selections.</td></tr>");
+            $('#persistent-selection-list').html("<li class='notification empty'>No selections.</li>");
         }
 
         var checkboxes = $('.persistent-selection:checkbox');
@@ -79,6 +91,7 @@
         }
         
         $('.remove-selection').on('click', remove_selection_click);
+        $('#clear_selections_button').on('click', clear_selections);
     };
 
     $(document).
index 2bbff9b8e33f559897baeadd2af9067c4e2c935b..be54dd01ba1adacd5e02185c25f68fcfccc6d8ab 100644 (file)
@@ -189,15 +189,6 @@ table.table-fixed-header-row tbody {
     width: 500px;
 }
 
-#persistent-selection-list li {
-    margin-left: 1em;
-    padding: 3px 20px;
-    font-weight: normal;
-    line-height: 1.42857;
-    color: rgb(51, 51, 51);
-    
-}
-
 #persistent-selection-list li table tr {
-  border-bottom: 1px solid rgb(221, 221, 221);
+  border-top: 1px solid rgb(221, 221, 221);
 }
index 2817735fe83845b02d3ff6d9bdde68a502345b29..412f86ce07a6b874d05b7d5d796bb84a9017bf09 100644 (file)
@@ -24,6 +24,7 @@ class ApplicationController < ActionController::Base
 
   def unprocessable(message=nil)
     @errors ||= []
+
     @errors << message if message
     render_error status: 422
   end
index 48b6bb404d96a5286b5bab8c32684290293349c7..b6690427f1bd4eefaf69af634624f2b89d096799 100644 (file)
@@ -3,6 +3,10 @@ module ApplicationHelper
     controller.current_user
   end
 
+  def self.match_uuid(uuid)
+    /^([0-9a-z]{5})-([0-9a-z]{5})-([0-9a-z]{15})$/.match(uuid.to_s)
+  end
+
   def current_api_host
     Rails.configuration.arvados_v1_base.gsub /https?:\/\/|\/arvados\/v1/,''
   end
@@ -100,4 +104,61 @@ module ApplicationHelper
       :class => "editable"
     }.merge(htmloptions)
   end
+
+  def render_editable_subattribute(object, attr, subattr, template, htmloptions={})
+    attrvalue = object.send(attr)
+    subattr.each do |k|
+      attrvalue = attrvalue[k]
+    end
+
+    datatype = nil
+    if template
+      if template.is_a? Hash
+        if template[:output_of]
+          return "Output of \"#{template[:output_of]}\""
+        elsif template[:datatype]
+          datatype = template[:datatype]
+        end
+      elsif attrvalue == nil
+        attrvalue = template
+      end
+    end
+
+    return attrvalue if !object.attribute_editable? attr
+
+    if not datatype
+      dataclass = ArvadosBase.resource_class_for_uuid(attrvalue)
+      if dataclass
+        datatype = 'select'
+      else
+        if /^\d+$/.match(attrvalue) 
+          datatype = 'number'
+        elsif
+          datatype = 'text'
+        end
+      end
+    end
+
+    subattr.insert(0, attr)
+    id = "#{object.uuid}-#{subattr.join('-')}"
+
+    lt = link_to attrvalue, '#', {
+      "data-emptytext" => "none",
+      "data-placement" => "bottom",
+      "data-type" => datatype,
+      "data-url" => url_for(action: "update", id: object.uuid, controller: object.class.to_s.pluralize.underscore),
+      "data-title" => "Update #{subattr[-1].to_s.titleize}",
+      "data-name" => subattr.to_json,
+      "data-pk" => "{id: \"#{object.uuid}\", key: \"#{object.class.to_s.underscore}\"}",
+      :class => "editable",
+      :id => id
+    }.merge(htmloptions)
+
+    lt += raw(%{
+<script>
+  $('##{id}').editable({source: select_#{dataclass}_source});
+</script>})
+
+    lt 
+  end
 end
index b2eee48ea695bdec16988c2d1d9126ed66ba75e8..df0ba22eac92f411ed58a268ccfd5b6a4cb2af8d 100644 (file)
@@ -4,4 +4,8 @@ module CollectionsHelper
       {source: x.tail_uuid, target: x.head_uuid, type: x.name}
     end
   end
+
+  def self.match(uuid)
+    /^([a-f0-9]{32}(\+[0-9]+)?)(\+.*)?$/.match(uuid.to_s)
+  end
 end
index 6d6ae5516c838ebdfe0556948ee980e8f6782c2b..8278d37f3ec022525bdfc42b0f2103bdf080e078 100644 (file)
@@ -9,7 +9,7 @@ module ProvenanceHelper
     end
 
     def self.collection_uuid(uuid)
-      m = /^([a-f0-9]{32}(\+[0-9]+)?)(\+.*)?$/.match(uuid.to_s)
+      m = CollectionsHelper.match(uuid)
       if m
         #if m[2]
         return m[1]
index da6116e91626ad2590ec042e6256c92c7455aa22..14eb89ab2bba61a03bc1477d2e1fe7d5f54a2065 100644 (file)
@@ -18,7 +18,7 @@ class PipelineInstance < ArvadosBase
   end
 
   def attribute_editable?(attr)
-    attr == 'name'
+    attr.to_sym == :name || (attr.to_sym == :components and self.active == nil)
   end
 
   def attributes_for_display
index 1d6a46828a06ca93bd90f5a2ded2557968ec547b..2128515860a5946a9e8b8b273ea5262cc9cc283b 100644 (file)
         </li>
         -->
 
-        <li class="dropdown">
+        <li class="dropdown notification-menu">
           <a href="#" class="dropdown-toggle" data-toggle="dropdown">
             <span class="glyphicon glyphicon-paperclip"></span>
             <span class="badge" id="persistent-selection-count"></span>
             <span class="caret"></span>
           </a>
           <ul class="dropdown-menu" role="menu" id="persistent-selection-list">
-            <li><table style="width:100%"></table></li>
           </ul>
         </li>
 
index 1785f6ac0b77929a6452ec94d71cb620459a9968..395ef77369cd2d48809392da023f80014504b90a 100644 (file)
@@ -23,6 +23,19 @@ table.pipeline-components-table td {
 
 <% end %>
 
+<% content_for :js do %>
+  function select_Collection_source() {
+    var ret = [];
+    var lst = get_selection_list();
+    for (var i = 0; i < lst.length; i++) {
+      if (lst[i].type == 'Collection') {
+        ret.push({text: lst[i].name, value: lst[i].uuid})
+      }
+    }
+    return ret;
+  };
+<% end %>
+
 <% if @object.active != nil %>
 <table class="table pipeline-components-table">
   <colgroup>
@@ -113,7 +126,8 @@ setInterval(function(){$('a.refresh').click()}, 30000);
     </tr>
   </thead>
   <tbody>
-  <% @object.components.each do |k, v| %>
+    <% template = PipelineTemplate.find(@object.pipeline_template_uuid) %>
+    <% template.components.each do |k, v| %>
 
     <% sp = v[:script_parameters].collect do |k, v| [k, v] end %>
 
@@ -129,7 +143,7 @@ setInterval(function(){$('a.refresh').click()}, 30000);
       </td>
 
       <td>
-        <%= sp[0][1] %>
+        <%= render_editable_subattribute @object, :components, [k, :script_parameters, sp[0][0].to_sym], sp[0][1] %>
       </td>
       </tr>
 
@@ -139,8 +153,8 @@ setInterval(function(){$('a.refresh').click()}, 30000);
       <td style="border-top: none"></td>
 
       <% sp[1..-1].each do |p| %>
-        <td style="border-top: none"><%= p[0] %></td>
-        <td style="border-top: none"><%= p[1] %></td>
+        <td><%= p[0] %></td>
+        <td><%= p[1] %></td>
       <% end %>
     </tr>
   <% end %>