+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: AGPL-3.0
+
module ApplicationHelper
def current_user
controller.current_user
end
def render_markup(markup)
- raw RedCloth.new(markup.to_s).to_html(:refs_arvados, :textile) if markup
+ allowed_tags = Rails::Html::Sanitizer.white_list_sanitizer.allowed_tags + %w(table tbody th tr td col colgroup caption thead tfoot)
+ sanitize(raw(RedCloth.new(markup.to_s).to_html(:refs_arvados, :textile)), tags: allowed_tags) if markup
end
def human_readable_bytes_html(n)
end
return h(n)
- #raw = n.to_s
- #cooked = ''
- #while raw.length > 3
- # cooked = ',' + raw[-3..-1] + cooked
- # raw = raw[0..-4]
- #end
- #cooked = raw + cooked
end
def resource_class_for_uuid(attrvalue, opts={})
else
begin
if resource_class.name == 'Collection'
- link_name = collections_for_object(link_uuid).andand.first.andand.friendly_link_name
+ if CollectionsHelper.match(link_uuid)
+ link_name = collection_for_pdh(link_uuid).andand.first.andand.portable_data_hash
+ else
+ link_name = collections_for_object(link_uuid).andand.first.andand.friendly_link_name
+ end
else
link_name = object_for_dataclass(resource_class, link_uuid).andand.friendly_link_name
end
"data-placement" => "bottom",
"data-type" => input_type,
"data-title" => "Edit #{attr.to_s.gsub '_', ' '}",
- "data-name" => attr,
+ "data-name" => htmloptions['selection_name'] || attr,
"data-object-uuid" => object.uuid,
"data-toggle" => "manual",
- "data-value" => attrvalue,
+ "data-value" => htmloptions['data-value'] || attrvalue,
"id" => span_id,
:class => "editable #{is_textile?( object, attr ) ? 'editable-textile' : ''}"
}.merge(htmloptions).merge(ajax_options)
lt
end
+ def get_cwl_main(workflow)
+ if workflow[:"$graph"].nil?
+ return workflow
+ else
+ workflow[:"$graph"].each do |tool|
+ if tool[:id] == "#main"
+ return tool
+ end
+ end
+ end
+ end
+
+ def get_cwl_inputs(workflow)
+ get_cwl_main(workflow)[:inputs]
+ end
+
+
+ def cwl_shortname(id)
+ if id[0] == "#"
+ id = id[1..-1]
+ end
+ return id.split("/")[-1]
+ end
+
def cwl_input_info(input_schema)
required = !(input_schema[:type].include? "null")
if input_schema[:type].is_a? Array
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]
+ param_id = cwl_shortname(input_schema[:id])
return required, primary_type, param_id
end
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]
+ re = CollectionsHelper.match_uuid_with_optional_filepath(display_value)
+ if re
+ if re[4]
+ display_value = "#{Collection.find(re[1]).name} / #{re[4][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,
end
end
elsif "boolean" == primary_type
+ return link_to attrvalue.to_s, '#', {
+ "data-emptytext" => "none",
+ "data-placement" => "bottom",
+ "data-type" => "select",
+ "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 #{cwl_shortname(input_schema[:id])}",
+ "data-name" => dn,
+ "data-pk" => "{id: \"#{object.uuid}\", key: \"#{object.class.to_s.underscore}\"}",
+ "data-value" => attrvalue.to_s,
+ # "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? Hash and primary_type[:type] == "enum"
return link_to attrvalue, '#', {
"data-emptytext" => "none",
"data-placement" => "bottom",
"data-type" => "select",
- "data-source" => "[{value: true, text: \"true\"}, {value: false, text: \"false\"}]",
+ "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-title" => "Set value for #{cwl_shortname(input_schema[:id])}",
"data-name" => dn,
"data-pk" => "{id: \"#{object.uuid}\", key: \"#{object.class.to_s.underscore}\"}",
"data-value" => attrvalue,
:class => "editable #{'required' if required} form-control",
:id => id
}.merge(htmloptions)
- elsif "enum" == primary_type
-
- else
- if ["float", "double", "int", "long"].include? primary_type
+ elsif primary_type.is_a? String
+ if ["int", "long"].include? primary_type
datatype = "number"
else
datatype = "text"
"data-placement" => "bottom",
"data-type" => datatype,
"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-title" => "Set value for #{cwl_shortname(input_schema[:id])}",
"data-name" => dn,
"data-pk" => "{id: \"#{object.uuid}\", key: \"#{object.class.to_s.underscore}\"}",
"data-value" => attrvalue,
"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
RESOURCE_CLASS_ICONS = {
"Collection" => "fa-archive",
+ "ContainerRequest" => "fa-gears",
"Group" => "fa-users",
"Human" => "fa-male", # FIXME: Use a more inclusive icon.
"Job" => "fa-gears",
"Trait" => "fa-clipboard",
"User" => "fa-user",
"VirtualMachine" => "fa-terminal",
+ "Workflow" => "fa-gears",
}
DEFAULT_ICON_CLASS = "fa-cube"
render_runtime duration, use_words, round_to_min
end
+ # Keep locators are expected to be of the form \"...<pdh/file_path>\"
+ JSON_KEEP_LOCATOR_REGEXP = /([0-9a-f]{32}\+\d+[^'"]*?)(?=['"]|\z|$)/
+ def keep_locator_in_json str
+ # Return a list of all matches
+ str.scan(JSON_KEEP_LOCATOR_REGEXP).flatten
+ end
+
private
def is_textile?( object, attr )
is_textile = object.textile_attributes.andand.include?(attr)