From: Peter Amstutz Date: Fri, 28 Feb 2014 13:36:49 +0000 (-0500) Subject: Merge remote-tracking branch 'origin/master' into 2049-run-job-from-workbench X-Git-Tag: 1.1.0~2715^2~2 X-Git-Url: https://git.arvados.org/arvados.git/commitdiff_plain/f26cbf1c4d949d3e7c7b26ab27c5f4d48d8059ed?hp=45bbd49852b4fbd5a6d69122bd4c620c7c9e4674 Merge remote-tracking branch 'origin/master' into 2049-run-job-from-workbench --- diff --git a/apps/workbench/Gemfile b/apps/workbench/Gemfile index 66734ef3cd..6ae12f75db 100644 --- a/apps/workbench/Gemfile +++ b/apps/workbench/Gemfile @@ -43,7 +43,7 @@ gem 'less-rails' # gem 'capistrano' # To use debugger -# gem 'debugger' +#gem 'byebug' gem 'rvm-capistrano', :group => :test @@ -54,3 +54,4 @@ gem 'RedCloth' gem 'piwik_analytics' gem 'httpclient' gem 'themes_for_rails' +gem "deep_merge", :require => 'deep_merge/rails_compat' \ No newline at end of file diff --git a/apps/workbench/Gemfile.lock b/apps/workbench/Gemfile.lock index 7f4dc8e289..c7ffeb0057 100644 --- a/apps/workbench/Gemfile.lock +++ b/apps/workbench/Gemfile.lock @@ -51,6 +51,7 @@ GEM coffee-script-source (1.6.3) commonjs (0.2.7) daemon_controller (1.1.7) + deep_merge (1.0.1) erubis (2.7.0) execjs (2.0.2) highline (1.6.20) @@ -153,6 +154,7 @@ DEPENDENCIES bootstrap-sass (~> 3.1.0) bootstrap-x-editable-rails coffee-rails (~> 3.2.0) + deep_merge httpclient jquery-rails less diff --git a/apps/workbench/app/assets/javascripts/application.js b/apps/workbench/app/assets/javascripts/application.js index 3b697a6aa9..e7884b9516 100644 --- a/apps/workbench/app/assets/javascripts/application.js +++ b/apps/workbench/app/assets/javascripts/application.js @@ -41,6 +41,7 @@ jQuery(function($){ } targets.fadeToggle(200); }); + $(document). on('ajax:send', function(e, xhr) { $('.loading').fadeTo('fast', 1); @@ -139,4 +140,4 @@ jQuery(function($){ fixer.duplicateTheadTr(); fixer.fixThead(); }); -})(jQuery); +}); diff --git a/apps/workbench/app/assets/javascripts/editable.js b/apps/workbench/app/assets/javascripts/editable.js index 804eeb2d8f..a743586942 100644 --- a/apps/workbench/app/assets/javascripts/editable.js +++ b/apps/workbench/app/assets/javascripts/editable.js @@ -1,5 +1,6 @@ $.fn.editable.defaults.ajaxOptions = {type: 'put', dataType: 'json'}; $.fn.editable.defaults.send = 'always'; +//$.fn.editable.defaults.mode = 'inline'; $.fn.editable.defaults.params = function (params) { var a = {}; var key = params.pk.key; @@ -7,4 +8,4 @@ $.fn.editable.defaults.params = function (params) { a[key] = {}; a[key][params.name] = params.value; return a; -}; \ No newline at end of file +}; diff --git a/apps/workbench/app/assets/javascripts/pipeline_instances.js b/apps/workbench/app/assets/javascripts/pipeline_instances.js new file mode 100644 index 0000000000..ee14e3b781 --- /dev/null +++ b/apps/workbench/app/assets/javascripts/pipeline_instances.js @@ -0,0 +1,46 @@ + +(function() { + var run_pipeline_button_state = function() { + var a = $('a.editable.required.editable-empty'); + if (a.length > 0) { + $("#run-pipeline-button").addClass("disabled"); + } + else { + $("#run-pipeline-button").removeClass("disabled"); + } + } + + $.fn.editable.defaults.success = function (response, newValue) { + var tag = $(this); + if (tag.hasClass("required")) { + if (newValue && newValue.trim() != "") { + tag.removeClass("editable-empty"); + tag.parent().css("background-color", ""); + tag.parent().prev().css("background-color", ""); + } + else { + tag.addClass("editable-empty"); + tag.parent().css("background-color", "#ffdddd"); + tag.parent().prev().css("background-color", "#ffdddd"); + } + } + run_pipeline_button_state(); + } + + $(window).on('load', function() { + var a = $('a.editable.required'); + for (var i = 0; i < a.length; i++) { + var tag = $(a[i]); + if (tag.hasClass("editable-empty")) { + tag.parent().css("background-color", "#ffdddd"); + tag.parent().prev().css("background-color", "#ffdddd"); + } + else { + tag.parent().css("background-color", ""); + tag.parent().prev().css("background-color", ""); + } + } + run_pipeline_button_state(); + } ); + +})(); diff --git a/apps/workbench/app/assets/javascripts/pipeline_instances.js.coffee b/apps/workbench/app/assets/javascripts/pipeline_instances.js.coffee deleted file mode 100644 index 761567942f..0000000000 --- a/apps/workbench/app/assets/javascripts/pipeline_instances.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# Place all the behaviors and hooks related to the matching controller here. -# All this logic will automatically be available in application.js. -# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/apps/workbench/app/assets/javascripts/selection.js b/apps/workbench/app/assets/javascripts/selection.js new file mode 100644 index 0000000000..c8ec8100ac --- /dev/null +++ b/apps/workbench/app/assets/javascripts/selection.js @@ -0,0 +1,160 @@ +//= require jquery +//= require jquery_ujs + +/** Javascript for local persistent selection. */ + +get_selection_list = null; +form_selection_sources = {}; + +jQuery(function($){ + var storage = localStorage; // sessionStorage + + get_selection_list = function() { + if (!storage.persistentSelection) { + storage.persistentSelection = JSON.stringify([]); + } + return JSON.parse(storage.persistentSelection); + } + + var put_storage = function(lst) { + storage.persistentSelection = JSON.stringify(lst); + } + + var add_selection = function(uuid, name, href, type) { + 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_selection_list(); + for (var i = 0; i < lst.length; i++) { + if (lst[i].uuid == uuid) { + lst.splice(i, 1); + i--; + } + } + put_storage(lst); + update_count(); + }; + + var remove_selection_click = function(e) { + //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_selection_list(); + $("#persistent-selection-count").text(lst.length); + + if (lst.length > 0) { + $('#persistent-selection-list').html('
  • Clear selections
  • ' + +'
  • '); + for (var i = 0; i < lst.length; i++) { + $('#persistent-selection-list > li > table').append("" + + "" + + "
    " + + "" + + "
    " + + "" + + + "" + + "" + lst[i].name + "" + + "" + + + "" + + "" + lst[i].type + "" + + "" + + + ""); + } + } else { + $('#persistent-selection-list').html("
  • No selections.
  • "); + } + + var checkboxes = $('.persistent-selection:checkbox'); + for (i = 0; i < checkboxes.length; i++) { + for (var j = 0; j < lst.length; j++) { + if (lst[j].uuid == $(checkboxes[i]).val()) { + checkboxes[i].checked = true; + break; + } + } + if (j == lst.length) { + checkboxes[i].checked = false; + } + } + + $('.remove-selection').on('click', remove_selection_click); + $('#clear_selections_button').on('click', clear_selections); + }; + + $(document). + on('change', '.persistent-selection:checkbox', function(e) { + //console.log($(this)); + //console.log($(this).val()); + + var inc = 0; + if ($(this).is(":checked")) { + add_selection($(this).val(), $(this).attr('friendly_name'), $(this).attr('href'), $(this).attr('friendly_type')); + } + else { + remove_selection($(this).val()); + } + }); + + + $(window).on('load storage', update_count); +}); + +add_form_selection_sources = null; +select_form_sources = null; + +(function() { + var form_selection_sources = {}; + add_form_selection_sources = function (src) { + for (var i = 0; i < src.length; i++) { + var t = form_selection_sources[src[i].type]; + if (!t) { + t = form_selection_sources[src[i].type] = {}; + } + if (!t[src[i].uuid]) { + t[src[i].uuid] = src[i]; + } + } + }; + + select_form_sources = function(type) { + var ret = []; + + if (get_selection_list) { + var lst = get_selection_list(); + if (lst.length > 0) { + ret.push({text: "--- Selections ---", value: ""}); + + for (var i = 0; i < lst.length; i++) { + if (lst[i].type == type) { + ret.push({text: lst[i].name, value: lst[i].uuid}) + } + } + } + } + ret.push({text: "--- Recent ---", value: ""}); + + var t = form_selection_sources[type]; + for (var key in t) { + if (t.hasOwnProperty(key)) { + var obj = t[key]; + ret.push({text: obj.name, value: obj.uuid}) + } + } + return ret; + }; +})(); + diff --git a/apps/workbench/app/assets/javascripts/sizing.js b/apps/workbench/app/assets/javascripts/sizing.js index 388f727990..55d2301387 100644 --- a/apps/workbench/app/assets/javascripts/sizing.js +++ b/apps/workbench/app/assets/javascripts/sizing.js @@ -11,14 +11,14 @@ function graph_zoom(divId, svgId, scale) { } function smart_scroll_fixup(s) { - console.log(s); + //console.log(s); if (s != null && s.type == 'shown.bs.tab') { s = [s.target]; } else { s = $(".smart-scroll"); } - console.log(s); + //console.log(s); for (var i = 0; i < s.length; i++) { a = s[i]; var h = window.innerHeight - a.getBoundingClientRect().top - 20; diff --git a/apps/workbench/app/assets/stylesheets/application.css.scss b/apps/workbench/app/assets/stylesheets/application.css.scss index 2c361f9a5e..be54dd01ba 100644 --- a/apps/workbench/app/assets/stylesheets/application.css.scss +++ b/apps/workbench/app/assets/stylesheets/application.css.scss @@ -176,3 +176,19 @@ table.table-fixed-header-row tbody { position:relative; top:1.5em; } + +/* Setting the height needs to be fixed with javascript. */ +.dropdown-menu { + padding-right: 20px; + max-height: 440px; + width: 400px; + overflow-y: auto; +} + +#persistent-selection-list { + width: 500px; +} + +#persistent-selection-list li table tr { + border-top: 1px solid rgb(221, 221, 221); +} diff --git a/apps/workbench/app/controllers/application_controller.rb b/apps/workbench/app/controllers/application_controller.rb index e94428e92d..412f86ce07 100644 --- a/apps/workbench/app/controllers/application_controller.rb +++ b/apps/workbench/app/controllers/application_controller.rb @@ -24,6 +24,7 @@ class ApplicationController < ActionController::Base def unprocessable(message=nil) @errors ||= [] + @errors << message if message render_error status: 422 end @@ -109,6 +110,7 @@ class ApplicationController < ActionController::Base def create @object ||= model_class.new params[model_class.to_s.underscore.singularize] @object.save! + respond_to do |f| f.json { render json: @object } f.html { diff --git a/apps/workbench/app/controllers/pipeline_instances_controller.rb b/apps/workbench/app/controllers/pipeline_instances_controller.rb index 42cb2e9d44..12db3c3b64 100644 --- a/apps/workbench/app/controllers/pipeline_instances_controller.rb +++ b/apps/workbench/app/controllers/pipeline_instances_controller.rb @@ -45,6 +45,38 @@ class PipelineInstancesController < ApplicationController end def show + if @object.components.empty? and @object.pipeline_template_uuid + template = PipelineTemplate.find(@object.pipeline_template_uuid) + pipeline = {} + template.components.each do |component_name, component_props| + pipeline[component_name] = {} + component_props.each do |k, v| + if k == :script_parameters + pipeline[component_name][:script_parameters] = {} + v.each do |param_name, param_value| + if param_value.is_a? Hash + if param_value[:value] + pipeline[component_name][:script_parameters][param_name] = param_value[:value] + elsif param_value[:default] + pipeline[component_name][:script_parameters][param_name] = param_value[:default] + elsif param_value[:optional] and param_value.length == 1 + pipeline[component_name][:script_parameters][param_name] = "" + else + pipeline[component_name][:script_parameters][param_name] = param_value + end + else + pipeline[component_name][:script_parameters][param_name] = param_value + end + end + else + pipeline[component_name][k] = v + end + end + end + @object.components= pipeline + @object.save + end + @pipelines = [@object] if params[:compare] @@ -141,6 +173,15 @@ class PipelineInstancesController < ApplicationController %w(Compare Graph) end + def update + updates = params[@object.class.to_s.underscore.singularize.to_sym] + if updates["components"] + require 'deep_merge/rails_compat' + updates["components"] = updates["components"].deeper_merge(@object.components) + end + super + end + protected def for_comparison v if v.is_a? Hash or v.is_a? Array diff --git a/apps/workbench/app/helpers/application_helper.rb b/apps/workbench/app/helpers/application_helper.rb index cd8e5279dd..6de96e8995 100644 --- a/apps/workbench/app/helpers/application_helper.rb +++ b/apps/workbench/app/helpers/application_helper.rb @@ -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 @@ -67,7 +71,7 @@ module ApplicationHelper 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 + link_to link_name, { controller: resource_class.to_s.tableize, action: 'show', id: link_uuid }, style_opts else attrvalue end @@ -100,4 +104,113 @@ module ApplicationHelper :class => "editable" }.merge(htmloptions) end + + def render_editable_subattribute(object, attr, subattr, template, htmloptions={}) + attrvalue = object.send(attr) + subattr.each do |k| + if attrvalue and attrvalue.is_a? Hash + attrvalue = attrvalue[k] + else + break + end + end + + datatype = nil + required = true + if template + #puts "Template is #{template.class} #{template.is_a? Hash} #{template}" + if template.is_a? Hash + if template[:output_of] + return raw("#{template[:output_of]}") + end + if template[:dataclass] + dataclass = template[:dataclass] + end + if template[:optional] != nil + required = (template[:optional] != "true") + end + if template[:required] != nil + required = template[:required] + end + end + end + + return attrvalue if !object.attribute_editable? attr + + if not dataclass + rsc = template + if template.is_a? Hash + if template[:value] + rsc = template[:value] + elsif template[:default] + rsc = template[:default] + end + end + + dataclass = ArvadosBase.resource_class_for_uuid(rsc) + end + + if dataclass && dataclass.is_a?(Class) + datatype = 'select' + elsif dataclass == 'number' + datatype = 'number' + else + if template.is_a? Array + # ?!? + elsif template.is_a? String + if /^\d+$/.match(template) + datatype = 'number' + else + datatype = 'text' + end + end + end + + id = "#{object.uuid}-#{subattr.join('-')}" + dn = "[#{attr}]" + subattr.each do |a| + dn += "[#{a}]" + end + + if attrvalue.is_a? String + attrvalue = attrvalue.strip + end + + if dataclass and dataclass.is_a? Class + items = [] + items.append({name: attrvalue, uuid: attrvalue, type: dataclass.to_s}) + #dataclass.where(uuid: attrvalue).each do |item| + # items.append({name: item.uuid, uuid: item.uuid, type: dataclass.to_s}) + #end + dataclass.limit(10).each do |item| + items.append({name: item.uuid, uuid: item.uuid, type: dataclass.to_s}) + end + end + + 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" => dn, + "data-pk" => "{id: \"#{object.uuid}\", key: \"#{object.class.to_s.underscore}\"}", + "data-showbuttons" => "false", + "data-value" => attrvalue, + :class => "editable #{'required' if required}", + :id => id + }.merge(htmloptions) + + lt += raw('") + + lt + end end diff --git a/apps/workbench/app/helpers/collections_helper.rb b/apps/workbench/app/helpers/collections_helper.rb index b2eee48ea6..df0ba22eac 100644 --- a/apps/workbench/app/helpers/collections_helper.rb +++ b/apps/workbench/app/helpers/collections_helper.rb @@ -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 diff --git a/apps/workbench/app/helpers/pipeline_instances_helper.rb b/apps/workbench/app/helpers/pipeline_instances_helper.rb index 348004620e..3a923e1e00 100644 --- a/apps/workbench/app/helpers/pipeline_instances_helper.rb +++ b/apps/workbench/app/helpers/pipeline_instances_helper.rb @@ -43,9 +43,19 @@ module PipelineInstancesHelper def render_pipeline_job pj if pj[:percent_done] - pj[:progress_bar] = raw("
    ") + pj[:progress_bar] = raw < + + + +EOF elsif pj[:progress] - raw("
    ") + raw < + + + +EOF end pj[:output_link] = link_to_if_arvados_object pj[:output] pj[:job_link] = link_to_if_arvados_object pj[:job][:uuid] diff --git a/apps/workbench/app/helpers/provenance_helper.rb b/apps/workbench/app/helpers/provenance_helper.rb index 6d6ae5516c..8278d37f3e 100644 --- a/apps/workbench/app/helpers/provenance_helper.rb +++ b/apps/workbench/app/helpers/provenance_helper.rb @@ -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] diff --git a/apps/workbench/app/models/arvados_base.rb b/apps/workbench/app/models/arvados_base.rb index 72b76a5229..fbf7ee5e79 100644 --- a/apps/workbench/app/models/arvados_base.rb +++ b/apps/workbench/app/models/arvados_base.rb @@ -61,13 +61,16 @@ class ArvadosBase < ActiveRecord::Base attr_reader :kind @columns end + def self.column(name, sql_type = nil, default = nil, null = true) ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null) end + def self.attribute_info self.columns @attribute_info end + def self.find(uuid, opts={}) if uuid.class != String or uuid.length < 27 then raise 'argument to find() must be a uuid string. Acceptable formats: warehouse locator or string with format xxxxx-xxxxx-xxxxxxxxxxxxxxx' @@ -84,21 +87,27 @@ class ArvadosBase < ActiveRecord::Base end new.private_reload(hash) end + def self.order(*args) ArvadosResourceList.new(self).order(*args) end + def self.where(*args) ArvadosResourceList.new(self).where(*args) end + def self.limit(*args) ArvadosResourceList.new(self).limit(*args) end + def self.eager(*args) ArvadosResourceList.new(self).eager(*args) end + def self.all(*args) ArvadosResourceList.new(self).all(*args) end + def save obdata = {} self.class.columns.each do |col| @@ -128,8 +137,11 @@ class ArvadosBase < ActiveRecord::Base end end + @new_record = false + self end + def save! self.save or raise Exception.new("Save failed") end @@ -169,6 +181,7 @@ class ArvadosBase < ActiveRecord::Base @links = $arvados_api_client.api Link, '', { _method: 'GET', where: o, eager: true } @links = $arvados_api_client.unpack_api_response(@links) end + def all_links return @all_links if @all_links res = $arvados_api_client.api Link, '', { @@ -181,9 +194,11 @@ class ArvadosBase < ActiveRecord::Base } @all_links = $arvados_api_client.unpack_api_response(res) end + def reload private_reload(self.uuid) end + def private_reload(uuid_or_hash) raise "No such object" if !uuid_or_hash if uuid_or_hash.is_a? Hash @@ -206,8 +221,14 @@ class ArvadosBase < ActiveRecord::Base end end @all_links = nil + @new_record = false self end + + def to_param + uuid + end + def dup super.forget_uuid! end @@ -275,6 +296,10 @@ class ArvadosBase < ActiveRecord::Base (name if self.respond_to? :name) || uuid end + def selection_label + friendly_link_name + end + protected def forget_uuid! diff --git a/apps/workbench/app/models/collection.rb b/apps/workbench/app/models/collection.rb index bda5523d8c..e22a5f72f4 100644 --- a/apps/workbench/app/models/collection.rb +++ b/apps/workbench/app/models/collection.rb @@ -24,4 +24,23 @@ class Collection < ArvadosBase def used_by $arvados_api_client.api "collections/#{self.uuid}/", "used_by" end + + # def selection_label + # name = '' + # i = 0 + # if self.files.length > 3 + # m = 3 + # else + # m = self.files.length + # end + # while i < m + # name += "#{self.files[i][1]}" + # i += 1 + # name += ", " if i < m + # end + # if i < self.files.length + # name += "&ellip;" + # end + # name + # end end diff --git a/apps/workbench/app/models/pipeline_instance.rb b/apps/workbench/app/models/pipeline_instance.rb index da6116e916..ccb88351a7 100644 --- a/apps/workbench/app/models/pipeline_instance.rb +++ b/apps/workbench/app/models/pipeline_instance.rb @@ -16,9 +16,9 @@ class PipelineInstance < ArvadosBase end end end - + def attribute_editable?(attr) - attr == 'name' + attr.to_sym == :name || (attr.to_sym == :components and self.active == nil) end def attributes_for_display diff --git a/apps/workbench/app/views/application/_selection_checkbox.html.erb b/apps/workbench/app/views/application/_selection_checkbox.html.erb new file mode 100644 index 0000000000..4d47d892c5 --- /dev/null +++ b/apps/workbench/app/views/application/_selection_checkbox.html.erb @@ -0,0 +1,8 @@ +<%if object %> +<%= check_box_tag 'uuids[]', object.uuid, false, { + :class => 'persistent-selection', + :friendly_type => object.class.name, + :friendly_name => object.selection_label, + :href => "#{url_for controller: object.class.name.tableize, action: 'show', id: object.uuid }" +} %> +<% end %> diff --git a/apps/workbench/app/views/application/_show_recent.html.erb b/apps/workbench/app/views/application/_show_recent.html.erb index c58c628ee9..ef4a8d1f04 100644 --- a/apps/workbench/app/views/application/_show_recent.html.erb +++ b/apps/workbench/app/views/application/_show_recent.html.erb @@ -8,9 +8,12 @@ <% attr_blacklist = ' created_at modified_at modified_by_user_uuid modified_by_client_uuid updated_at' %> +<%= form_tag do |f| %> + + <% @objects.first.attributes_for_display.each do |attr, attrvalue| %> <% next if attr_blacklist.index(" "+attr) %> <% @objects.each do |object| %> + + <% object.attributes_for_display.each do |attr, attrvalue| %> <% next if attr_blacklist.index(" "+attr) %>
    @@ -26,6 +29,10 @@
    + <%= render :partial => "selection_checkbox", :locals => {:object => object} %> + @@ -55,3 +62,5 @@
    <% end %> + +<% end %> diff --git a/apps/workbench/app/views/collections/_index_tbody.html.erb b/apps/workbench/app/views/collections/_index_tbody.html.erb index eb9c93fbc3..96b73979eb 100644 --- a/apps/workbench/app/views/collections/_index_tbody.html.erb +++ b/apps/workbench/app/views/collections/_index_tbody.html.erb @@ -1,6 +1,9 @@ <% @collections.each do |c| %> + + <%= render :partial => "selection_checkbox", :locals => {:object => c} %> + <%= link_to_if_arvados_object c.uuid %> diff --git a/apps/workbench/app/views/collections/_show_files.html.erb b/apps/workbench/app/views/collections/_show_files.html.erb index 385af8a272..705ded388a 100644 --- a/apps/workbench/app/views/collections/_show_files.html.erb +++ b/apps/workbench/app/views/collections/_show_files.html.erb @@ -1,5 +1,6 @@ + @@ -7,6 +8,7 @@ + @@ -16,6 +18,16 @@ <% if @object then @object.files.sort_by{|f|[f[0],f[1]]}.each do |file| %> <% file_path = "#{file[0]}/#{file[1]}" %> + diff --git a/apps/workbench/app/views/collections/_show_recent.html.erb b/apps/workbench/app/views/collections/_show_recent.html.erb index 3cedb57e85..a3b93d84e6 100644 --- a/apps/workbench/app/views/collections/_show_recent.html.erb +++ b/apps/workbench/app/views/collections/_show_recent.html.erb @@ -15,8 +15,11 @@
    +<%= form_tag do |f| %> +
    path file size
    + <% fp2 = file_path[2..-1] if file_path[0..1] == './' %> + <% fp2 ||= file_path %> +<%= check_box_tag 'uuids[]', @object.uuid+file_path, false, { + :class => 'persistent-selection', + :friendly_type => "File", + :friendly_name => "#{@object.uuid}/#{fp2}", + :href => "#{url_for controller: 'collections', action: 'show', id: @object.uuid }/#{file_path}" + } %> + <%= file[0] %>
    + @@ -26,6 +29,7 @@ + @@ -38,6 +42,9 @@ <%= render partial: 'index_tbody' %>
    uuid contents owner
    + +<% end %> + <% content_for :footer_js do %> diff --git a/apps/workbench/app/views/layouts/application.html.erb b/apps/workbench/app/views/layouts/application.html.erb index 1dc6284c83..68f0e109bd 100644 --- a/apps/workbench/app/views/layouts/application.html.erb +++ b/apps/workbench/app/views/layouts/application.html.erb @@ -42,14 +42,6 @@ padding-top: 1.25em; } - /* Setting the height needs to be fixed with javascript. */ - .dropdown-menu { - padding-right: 20px; - max-height: 440px; - width: 400px; - overflow-y: auto; - } - @media (min-width: 768px) { .left-nav { position: fixed; @@ -93,7 +85,12 @@
  • -<%= link_to controller.breadcrumb_page_name, request.fullpath %> + <%= link_to controller.breadcrumb_page_name, request.fullpath %> +
  • +
  • + <%= form_tag do |f| %> + <%= render :partial => "selection_checkbox", :locals => {:object => @object} %> + <% end %>
  • <% end %> <% end %> @@ -118,18 +115,15 @@ --> - <% if current_user.is_active %>