9043: Complete support for editing basic parameter types.
authorPeter Amstutz <peter.amstutz@curoverse.com>
Mon, 22 Aug 2016 20:21:59 +0000 (16:21 -0400)
committerPeter Amstutz <peter.amstutz@curoverse.com>
Thu, 25 Aug 2016 15:58:10 +0000 (11:58 -0400)
Supported parameter types: boolean, string, int, long, float, double, enum,
File, Directory.  May be specified required or optional.

Not supported: arrays, unions (other than with "null"), records.

apps/workbench/app/controllers/container_requests_controller.rb
apps/workbench/app/helpers/application_helper.rb
apps/workbench/app/views/container_requests/_show_inputs.html.erb

index ff6105f61b5811d995abf7e962b02cceb08defd8..34f892a8362b597aed4189442b3dc177ee9bd421 100644 (file)
@@ -23,22 +23,32 @@ class ContainerRequestsController < ApplicationController
 
   def update
     @updates ||= params[@object.class.to_s.underscore.singularize.to_sym]
-    input_obj = @updates[:mounts][:"/var/lib/cwl/cwl.input.json"][:content]
-    workflow = @object.mounts[:"/var/lib/cwl/workflow.json"][:content]
-    workflow[:inputs].each do |input_schema|
-      if input_obj.include? input_schema[:id]
-        required, primary_type, param_id = cwl_input_info(input_schema)
-        if primary_type == "boolean"
-          input_obj[param_id] = input_obj[param_id] == "true"
-        elsif ["int", "long"].include? primary_type
-          input_obj[param_id] = input_obj[param_id].to_i
-        elsif ["float", "double"].include? primary_type
-          input_obj[param_id] = input_obj[param_id].to_f
-        elsif ["File", "Directory"].include? primary_type
-          input_obj[param_id] = {"class" => "File", "location" => "keep:" + input_obj[param_id]}
+    input_obj = @updates[:mounts].andand[:"/var/lib/cwl/cwl.input.json"].andand[:content]
+    if input_obj
+      workflow = @object.mounts[:"/var/lib/cwl/workflow.json"][:content]
+      workflow[:inputs].each do |input_schema|
+        if input_obj.include? input_schema[:id]
+          required, primary_type, param_id = cwl_input_info(input_schema)
+          if input_obj[param_id] == ""
+            input_obj[param_id] = nil
+          elsif primary_type == "boolean"
+            input_obj[param_id] = input_obj[param_id] == "true"
+          elsif ["int", "long"].include? primary_type
+            input_obj[param_id] = input_obj[param_id].to_i
+          elsif ["float", "double"].include? primary_type
+            input_obj[param_id] = input_obj[param_id].to_f
+          elsif ["File", "Directory"].include? primary_type
+            input_obj[param_id].match /^([0-9a-z]{5}-([0-9a-z]{5})-[0-9a-z]{15})(\/.*)?$/ do |re|
+              c = display_value = Collection.find(re[1])
+              input_obj[param_id] = {"class" => primary_type,
+                                     "location" => "keep:#{c.portable_data_hash}#{re[3]}",
+                                     "arv:collection" => input_obj[param_id]}
+            end
+          end
         end
       end
     end
+    params[:merge] = true
     super
   end
 
index a82c795aec753e3cd2bfcaa50d0db5279ba427bd..27c7504ebbe04a4105907a28b7d4f1cedaca5781 100644 (file)
@@ -424,6 +424,8 @@ module ApplicationHelper
       primary_type = input_schema[:type].select { |n| n != "null" }[0]
     elsif input_schema[:type].is_a? String
       primary_type = input_schema[:type]
+    elsif input_schema[:type].is_a? Hash
+      primary_type = input_schema[:type]
     end
     param_id = input_schema[:id]
     return required, primary_type, param_id
@@ -453,14 +455,25 @@ module ApplicationHelper
     required, primary_type, param_id = cwl_input_info(input_schema)
 
     dn, attrvalue = cwl_input_value(object, input_schema, set_attr_path + [param_id])
-    attrvalue ||= ""
+    attrvalue = if attrvalue.nil? then "" else attrvalue end
 
     id = "#{object.uuid}-#{param_id}"
 
+    opt_empty_selection = if required then [] else [{value: "", text: ""}] end
+
     if ["Directory", "File"].include? primary_type
       chooser_title = "Choose a #{primary_type == 'Directory' ? 'dataset' : 'file'}:"
       selection_param = object.class.to_s.underscore + dn
-      display_value = attrvalue
+      if attrvalue.is_a? Hash
+        display_value = attrvalue[:"arv:collection"] || attrvalue[:location]
+        display_value.match /^([0-9a-z]{5}-([0-9a-z]{5})-[0-9a-z]{15})(\/.*)?$/ do |re|
+          if re[3]
+            display_value = "#{Collection.find(re[1]).name} / #{re[3][1..-1]}"
+          else
+            display_value = Collection.find(re[1]).name
+          end
+        end
+      end
       modal_path = choose_collections_path \
       ({ title: chooser_title,
          filters: [['owner_uuid', '=', object.owner_uuid]].to_json,
@@ -494,7 +507,7 @@ module ApplicationHelper
                      "data-emptytext" => "none",
                      "data-placement" => "bottom",
                      "data-type" => "select",
-                     "data-source" => "[{value: true, text: \"true\"}, {value: false, text: \"false\"}]",
+                     "data-source" => (opt_empty_selection + [{value: "true", text: "true"}, {value: "false", text: "false"}]).to_json,
                      "data-url" => url_for(action: "update", id: object.uuid, controller: object.class.to_s.pluralize.underscore, merge: true),
                      "data-title" => "Set value for #{input_schema[:id]}",
                      "data-name" => dn,
@@ -505,9 +518,23 @@ module ApplicationHelper
                      :class => "editable #{'required' if required} form-control",
                      :id => id
                    }.merge(htmloptions)
-    elsif "enum" == primary_type
-
-    else
+    elsif primary_type.is_a? Hash and primary_type[:type] == "enum"
+      return link_to attrvalue, '#', {
+                     "data-emptytext" => "none",
+                     "data-placement" => "bottom",
+                     "data-type" => "select",
+                     "data-source" => (opt_empty_selection + primary_type[:symbols].map {|i| {:value => i, :text => i} }).to_json,
+                     "data-url" => url_for(action: "update", id: object.uuid, controller: object.class.to_s.pluralize.underscore, merge: true),
+                     "data-title" => "Set value for #{input_schema[:id]}",
+                     "data-name" => dn,
+                     "data-pk" => "{id: \"#{object.uuid}\", key: \"#{object.class.to_s.underscore}\"}",
+                     "data-value" => attrvalue,
+                     # "clear" button interferes with form-control's up/down arrows
+                     "data-clear" => false,
+                     :class => "editable #{'required' if required} form-control",
+                     :id => id
+                   }.merge(htmloptions)
+    elsif primary_type.is_a? String
       if ["float", "double", "int", "long"].include? primary_type
         datatype = "number"
       else
@@ -527,7 +554,9 @@ module ApplicationHelper
                      "data-clear" => false,
                      :class => "editable #{'required' if required} form-control",
                      :id => id
-                   }.merge(htmloptions)
+                     }.merge(htmloptions)
+    else
+      return "Unable to render editing control for parameter type #{primary_type}"
     end
   end
 
index 87b36c142ed403072c379355357d8f6df0900c6b..b365dc552905fc993654f85d605a33f4cca2a5f3 100644 (file)
 <% end %>
 
 <% if n_inputs == 0 %>
-  <p>This workflow does not need any further inputs specified. You can start it by clicking the "Run" button whenever you're ready. (It's not too late to change the settings, though.)</p>
+  <p><i>This workflow does not need any further inputs specified.  Click the "Run" button at the bottom of the page to start the workflow.</i></p>
 <% else %>
-  <%= render_unreadable_inputs_present %>
-
   <p><i>Provide <%= n_inputs > 1 ? 'values' : 'a value' %> for the following <%= n_inputs > 1 ? 'parameters' : 'parameter' %>, then click the "Run" button to start the workflow.</i></p>
-  <% if @object.editable? %>
-    <%= content_for :pi_input_form %>
-      <%= link_to(url_for('container_request[state]' => 'Committed'),
-          class: 'btn btn-primary run-pipeline-button',
-          method: :patch
-          ) do %>
-        Run <i class="fa fa-fw fa-play"></i>
-    <% end %>
-  <% end %>
+<% end %>
 
+<% if @object.editable? %>
+  <%= content_for :pi_input_form %>
+  <%= link_to(url_for('container_request[state]' => 'Committed'),
+        class: 'btn btn-primary run-pipeline-button',
+        method: :patch
+        ) do %>
+    Run <i class="fa fa-fw fa-play"></i>
+  <% end %>
 <% end %>
+
+<%= render_unreadable_inputs_present %>