SysMO-DB/seek

View on GitHub
app/helpers/application_helper.rb

Summary

Maintainability
F
4 days
Test Coverage
# Methods added to this helper will be available to all templates in the application.
#require_dependency File.join(Gem.loaded_specs['my_annotations'].full_gem_path,'lib','app','helpers','application_helper')
require 'savage_beast/application_helper'
require 'app_version'

module ApplicationHelper  
  include SavageBeast::ApplicationHelper
  include FancyMultiselectHelper
  include TavernaPlayer::RunsHelper
  include Recaptcha::ClientHelper


  def is_front_page?
    current_page?(main_app.root_url)
  end

  def seek_stylesheet_tags main='application'
    css = (Seek::Config.css_prepended || "").split(",")
    css << main
    css = css | (Seek::Config.css_appended || "").split(",")
    css.empty? ? "" : stylesheet_link_tag(*css)
  end

  def seek_javascript_tags main='application'
    js = (Seek::Config.javascript_prepended || "").split(",")
    js << main
    js = js | (Seek::Config.javascript_appended || "").split(",")
    js.empty? ? "" : javascript_include_tag(*js)
  end

  def date_as_string date,show_time_of_day=false,year_only_1st_jan=false
    #for publications, if it is the first of jan, then it can be assumed it is just the year (unlikely have a publication on New Years Day)
    if (year_only_1st_jan && !date.blank? && date.month==1 && date.day==1)
      str=date.year.to_s
    else
      date = Time.parse(date.to_s) unless date.is_a?(Time) || date.blank?
      if date.blank?
        str="<span class='none_text'>No date defined</span>"
      else
        str = date.localtime.strftime("#{date.day.ordinalize} %b %Y")
        str = date.localtime.strftime("#{str} at %H:%M") if show_time_of_day
      end
    end

    str.html_safe
  end

  def show_title title
    render :partial=>"general/item_title", :locals=>{:title=>title}
  end

  def version_text
    "(v.#{SEEK::Application::APP_VERSION.to_s})"
  end

  def authorized_list all_items, attribute, sort=true, max_length=75, count_hidden_items=false
    items = all_items.select &:can_view?
    if Seek::Config.is_virtualliver
      title_only_items = (all_items - items).select &:title_is_public?
    else
      title_only_items = []
    end

    if count_hidden_items
      original_size = all_items.size
      hidden_items = []
      hidden_items |= (all_items - items - title_only_items)
    else
      hidden_items = []
    end

    html = "<b>#{(items.size > 1 ? attribute.pluralize : attribute)}:</b> "
    if items.empty? && title_only_items.empty? && hidden_items.empty?
      html << "<span class='none_text'>No #{attribute}</span>"
    else
      items = items.sort_by { |i| get_object_title(i) } if sort
      title_only_items = title_only_items.sort_by { |i| get_object_title(i) } if sort

      list = items.collect { |i| link_to truncate(i.title, :length => max_length), show_resource_path(i), :title => get_object_title(i) }
      list = list + title_only_items.collect { |i| h(truncate(i.title, :length => max_length)) }
      html << list.join(', ')
      if count_hidden_items && !hidden_items.empty?
        text = items.size > 0 ? " and " : ""
        text << "#{hidden_items.size} hidden #{hidden_items.size > 1 ? 'items' : 'item'}"
        html << hidden_items_html(hidden_items, text)
      end

    end
    html.html_safe
  end

  def hidden_items_html hidden_items, text='hidden item'
    html = "<span class='none_text'>#{text}</span>"
    contributor_links = hidden_item_contributor_links hidden_items
    if !contributor_links.empty?
      html << "<span class='none_text'> - Please contact: #{contributor_links.join(', ')}</span>"
    end
    html.html_safe
  end

  def hidden_item_contributor_links hidden_items
    contributor_links = []
    hidden_items = hidden_items.select { |hi| !hi.contributing_user.try(:person).nil? }
    hidden_items.sort! { |a, b| a.contributing_user.person.name <=> b.contributing_user.person.name }
    hidden_items.each do |hi|
      contributor_person = hi.contributing_user.person
      if current_user.try(:person) && hi.can_see_hidden_item?(current_user.person) && contributor_person.can_view?
        contributor_name = contributor_person.name
        contributor_link = "<a href='#{person_path(contributor_person)}'>#{h(contributor_name)}</a>"
        contributor_links << contributor_link if contributor_link && !contributor_links.include?(contributor_link)
      end
    end
    contributor_links
  end

  def tabbar
    Seek::Config.is_virtualliver ? render(:partial=>"general/tabnav_dropdown") : render(:partial=>"general/menutabs")
  end

  #joins the list with seperator and the last item with an 'and'
  def join_with_and list, seperator=", "
    return list.first if list.count==1
    result = ""
    list.each do |item|
      result << item
      unless item==list.last
        if item==list[-2]
          result << " and "
        else
          result << seperator
        end
      end
    end
    result
  end

  def tab_definition(options={})
    options[:gap_before] ||= false
    options[:title] ||= options[:controllers].first.capitalize
    options[:path] ||= eval "#{options[:controllers].first}_path"

    attributes = (options[:controllers].include?(controller.controller_name.to_s) ? ' id="selected_tabnav"' : '')
    attributes += " class='tab_gap_before'" if options[:gap_before]

    link=link_to options[:title], options[:path]
    "<li #{attributes}>#{link}</li>".html_safe
  end

  #Classifies each result item into a hash with the class name as the key.
  #
  #This is to enable the resources to be displayed in the asset tabbed listing by class, or defined by .tab. Items not originating within SEEK are identified by is_external
  def classify_for_tabs result_collection
    results={}

    result_collection.each do |res|
      tab = res.respond_to?(:tab) ? res.tab : res.class.name
      results[tab] = {:items => [], :hidden_count => 0, :is_external=>(res.respond_to?(:is_external_search_result?) && res.is_external_search_result?)} unless results[tab]
      results[tab][:items] << res
    end

    return results
  end

  def new_creatable_javascript
    script="<script type='text/javascript'>\n"
    script << "function newAsset() {\n"
    script << "selected_model=$('new_resource_type').value;\n"
    Seek::Util.user_creatable_types.each do |c|
      name=c.name.underscore
      path = eval "new_#{name}_path"
      data_file_with_sample_path = eval "new_data_file_path(:page_title=>'#{t("data_file")} with Sample Parsing',:is_with_sample=>true)"
      if c==Seek::Util.user_creatable_types.first
        script << "if "
      else
        script << "else if(selected_model == 'data_file_with_sample'){
          \n location.href = '#{data_file_with_sample_path}';\n
        } \n"
        script << "else if "
      end
      script << "(selected_model == '#{name}') {\n location.href = '#{path}';\n }\n"

    end
    script << "}\n"
    script << "</script>"
    script.html_safe
  end

  #selection of assets for new asset gadget
  def new_creatable_selection_list
    creatable_options = Seek::Util.user_creatable_types.collect { |c| [c.name.underscore.humanize, c.name.underscore] }
    creatable_options << ["#{t('data_file')} with sample", "data_file_with_sample"] if Seek::Config.sample_parser_enabled
    creatable_options
  end

  def is_nil_or_empty? thing
    thing.nil? or thing.empty?
  end
  
  def empty_list_li_text list
    return "<li><div class='none_text'> None specified</div></li>".html_safe if is_nil_or_empty?(list)
  end  

  def model_title_or_not_specified model
    text=model.nil? ? nil : model.title
    text_or_not_specified text,:capitalize=>true    
  end
  
  def text_or_not_specified text, options = {}
    text=text.to_s if text.kind_of?(Numeric)
    if text.nil? or text.chomp.empty?
      not_specified_text||=options[:none_text]
      not_specified_text||="No description specified" if options[:description]==true
      not_specified_text||="Not specified"
      res = "<span class='none_text'>#{not_specified_text}</span>"
    else      
      text.capitalize! if options[:capitalize]            
      res = text.html_safe
      res = white_list(res)
      res = truncate_without_splitting_words(res, options[:length])  if options[:length]
      res = auto_link(res, :all, :rel => 'nofollow') if options[:auto_link]==true  
      res = simple_format(res).html_safe if options[:description]==true || options[:address]==true
      
      res=mail_to(res) if options[:email]==true
      res=link_to(res,res,:popup=>true) if options[:external_link]==true
      res=res+"&nbsp;"+flag_icon(text) if options[:flag]==true
      res = "&nbsp;" + flag_icon(text) + link_to(res,country_path(res)) if options[:link_as_country]==true 
    end
    res.html_safe
  end

  def tooltip_title_attrib(text, delay=200)
    return "header=[] body=[#{text}] cssheader=[boxoverTooltipHeader] cssbody=[boxoverTooltipBody] delay=[#{delay}]"
  end
      
  # text in "caption" will be used to display the item next to the image_tag_for_key;
  # if "caption" is nil, item.name will be used by default
  def list_item_with_icon(icon_type, item, caption, truncate_to, custom_tooltip=nil, size=nil)
    list_item = "<li>"
    if icon_type.downcase == "flag"
      list_item += flag_icon(item.country)
    elsif icon_type == "data_file" || icon_type == "sop"
      list_item += file_type_icon(item)
    else
      list_item += image_tag_for_key(icon_type.downcase, nil, icon_type.camelize, nil, "", false, size)
    end
    item_caption = " " + (caption.blank? ? item.title : caption)
    list_item += link_to truncate(item_caption, :length=>truncate_to), url_for(item), :title => tooltip_title_attrib(custom_tooltip.blank? ? item_caption : custom_tooltip)
    list_item += "</li>"
    
    return list_item.html_safe
  end
  
  
  def contributor(contributor, avatar=false, size=100, you_text=false)
    return jerm_harvester_name unless contributor
    
    if contributor.class.name == "User"
      # this string will output " (you) " for current user next to the display name, when invoked with 'you_text == true'
      you_string = (you_text && logged_in? && user.id == current_user.id) ? "<small style='vertical-align: middle; color: #666666; margin-left: 0.5em;'>(you)</small>" : ""
      contributor_person = contributor.person
      contributor_name = h(contributor_person.name)
      contributor_url = person_path(contributor_person.id)
      contributor_name_link = link_to(contributor_name, contributor_url)
      
      if avatar
        result = avatar(contributor_person, size, false, contributor_url, contributor_name, false)
        result += "<p style='margin: 0; text-align: center;'>#{contributor_name_link}#{you_string}</p>"
        return result.html_safe
      else
        return (contributor_name_link + you_string).html_safe
      end
    else
      return nil
    end
  end
  
  # this helper is to be extended to include many more types of objects that can belong to the
  # user - for example, SOPs and others
  def mine?(thing)
    return false if thing.nil?
    return false unless logged_in?
    
    c_id = current_user.id.to_i
    
    case thing.class.name
    when "Person"
      return (current_user.person.id == thing.id)
    else
      return false
    end
  end
  
  def fast_auto_complete_field(field_id, options={})
    div_id = "#{field_id}_auto_complete"
    url = options.delete(:url) or raise "url required"
    options = options.merge(:tokens => ',', :frequency => 0.01 )
    script = javascript_tag <<-end
    new Ajax.Request('#{url}', {
      method: 'get',
      onSuccess: function(transport) {
        new Autocompleter.Local('#{field_id}', '#{div_id}', eval(transport.responseText), #{options.to_json});
      }
    });
    end
    content_tag 'div', script, :class => 'auto_complete', :id => div_id
  end

  def link_to_draggable(link_name, url, link_options = {}, drag_options = {})
    if !link_options[:id]
      return ":id mandatory"
    end
    
    can_click_var = "can_click_for_#{link_options[:id]}"
    html = javascript_tag("var #{can_click_var} = true;");
    html << link_to(
      link_name,
      url,
      :id => link_options[:id],
      :class => link_options[:class] || "",
      :title => link_options[:title] || "",
      :onclick => "if (!#{can_click_var}) {#{can_click_var}=true;return(false);} else {return true;}",
      :onMouseUp => "setTimeout('#{can_click_var} = true;', 200);")
      html << draggable_element(link_options[:id],
      :revert => drag_options[:revert] || true,
      :ghosting => drag_options[:ghosting] || false,
      :change => "function(element){#{can_click_var} = false;}")
    return html.html_safe
  end

  def page_title controller_name, action_name
    name=PAGE_TITLES[controller_name]
    name ||=""
    name += " (Development)" if Rails.env=="development"
    return "#{Seek::Config.application_title} "+name
  end

  # http://www.igvita.com/blog/2006/09/10/faster-pagination-in-rails/
  def windowed_pagination_links(pagingEnum, options)
    link_to_current_page = options[:link_to_current_page]
    always_show_anchors = options[:always_show_anchors]
    padding = options[:window_size]

    current_page = pagingEnum.page
    html = ''

    #Calculate the window start and end pages
    padding = padding < 0 ? 0 : padding
    first = pagingEnum.page_exists?(current_page  - padding) ? current_page - padding : 1
    last = pagingEnum.page_exists?(current_page + padding) ? current_page + padding : pagingEnum.last_page

    # Print start page if anchors are enabled
    html << yield(1) if always_show_anchors and not first == 1

    # Print window pages
    first.upto(last) do |page|
      (current_page == page && !link_to_current_page) ? html << page : html << yield(page)
    end

    # Print end page if anchors are enabled
    html << yield(pagingEnum.last_page) if always_show_anchors and not last == pagingEnum.last_page
    html.html_safe
  end

  def favourite_group_popup_link_action_new resource_type=nil
    return link_to_remote_redbox("Create new #{t('favourite_group')}",
      { :url => main_app.new_favourite_group_url,
        :failure => "alert('Sorry, an error has occurred.'); RedBox.close();",
        :with => "'resource_type=' + '#{resource_type}'" },
      { #:style => options[:style],
        :id => "create_new_f_group_redbox",
        :onclick => "javascript: currentFavouriteGroupSettings = {};" }#,
      #:alt => "Click to create a new favourite group (opens popup window)",#options[:tooltip_text],
      #:title => tooltip_title_attrib("Opens a popup window, where you can create a new favourite<br/>group, add people to it and set individual access rights.") }  #options[:tooltip_text]
    )
  end
  
  def favourite_group_popup_link_action_edit resource_type=nil
    return link_to_remote_redbox("Edit selected #{t('favourite_group')}",
      { :url => main_app.edit_favourite_group_url,
        :failure => "alert('Sorry, an error has occurred.'); RedBox.close();",
        :with => "'resource_type=' + '#{resource_type}' + '&id=' + selectedFavouriteGroup()" },
      { #:style => options[:style],
        :id => "edit_existing_f_group_redbox",
        :onclick => "javascript: currentFavouriteGroupSettings = {};" } #,
      #:alt => "Click to create a new favourite group (opens popup window)",#options[:tooltip_text],
      #:title => tooltip_title_attrib("Opens a popup window, where you can create a new favourite<br/>group, add people to it and set individual access rights.") }  #options[:tooltip_text]
    )
  end
  
  def workgroup_member_review_popup_link resource_type=nil
    return link_to_remote_redbox("<b>Review members, set individual<br/>permissions and add afterwards</b>".html_safe,
      { :url => main_app.review_work_group_url("type", "id", "access_type"),
        :failure => "alert('Sorry, an error has occurred.'); RedBox.close();",
        :with => "'resource_type=' + '#{resource_type}'" },
      { #:style => options[:style],
        :id => "review_work_group_redbox" } #,
      #:alt => "Click to create a new favourite group (opens popup window)",#options[:tooltip_text],
      #:title => tooltip_title_attrib("Opens a popup window, where you can create a new favourite<br/>group, add people to it and set individual access rights.") }  #options[:tooltip_text]
    )
  end
  
  # the parameter must be the *standard* name of the whitelist or blacklist (depending on the link that needs to be produced)
  # (standard names are defined in FavouriteGroup model)
  def whitelist_blacklist_edit_popup_link(f_group_name)
    return link_to_remote_redbox("edit", 
      { :url => edit_favourite_group_url,
        :failure => "alert('Sorry, an error has occurred.'); RedBox.close();" },
      { #:style => options[:style],
        :id => "#{f_group_name}_edit_redbox",
        :onclick => "javascript: currentFavouriteGroupSettings = {};" } #,
      #:alt => "Click to create a new favourite group (opens popup window)",#options[:tooltip_text],
      #:title => tooltip_title_attrib("Opens a popup window, where you can create a new favourite<br/>group, add people to it and set individual access rights.") }  #options[:tooltip_text]
    )
  end

  def preview_permission_popup_link resource
    resource_name = resource.class.name.underscore
    resource_id = resource.id
    url = preview_permissions_policies_path
    is_new_file = resource.new_record?
    contributor_id = resource.contributing_user.try(:id)
    return link_to_remote_redbox("preview permission",
      { :url => url ,
        :failure => "alert('Sorry, an error has occurred.'); RedBox.close();",
        :with => "'sharing_scope=' + selectedSharingScope() + '&access_type=' + selectedAccessType(selectedSharingScope())
        + '&project_ids=' + getProjectIds('#{resource_name}') + '&project_access_type=' + $F('sharing_your_proj_access_type')
        + '&contributor_types=' + $F('sharing_permissions_contributor_types') + '&contributor_values=' + $F('sharing_permissions_values')
        + '&creators=' + encodeURIComponent(getCreators()) + '&contributor_id=' + '#{contributor_id}' + '&resource_name=' + '#{resource_name}' + '&resource_id=' + '#{resource_id}' + '&is_new_file=' + '#{is_new_file}'"},
      { :id => 'preview_permission',
        :style => 'display:none'
      }
    )
  end
  #Return whether or not to hide contact details from this user
  #Current decided by Seek::Config.hide_details_enabled in config.rb
  #Defaults to false
  def hide_contact_details?
    #hide for non-login and non-project-member
    if !logged_in? or !current_user.person.member?
      return true
    else
      Seek::Config.hide_details_enabled
    end
  end

  # Finn's truncate method. Doesn't split up words, tries to get as close to length as possible
  def truncate_without_splitting_words(text, length=50)
    truncated_result = ""
    remaining_length = length
    stop = false
    truncated = false
    #lines
    text.split("\n").each do |l|
      #words
      l.split(" ").each do |w|
        #If we're going to go over the length, and we've not already
        if (remaining_length - w.length) <= 0 && !stop
          truncated = true
          stop = true
          #Decide if adding or leaving out the last word puts us closer to the desired length
          if (remaining_length-w.length).abs < remaining_length.abs
            truncated_result += (w + " ")
          end
        elsif !stop
          truncated_result += (w + " ")
          remaining_length -= (w.length + 1)
        end
      end
      truncated_result += "\n"
    end    
    #Need some kind of whitespace before elipses or auto-link breaks
    html = truncated_result.strip + (truncated ? "\n..." : "")
    html.html_safe
  end    
  
  def get_object_title(item)
    return h(item.title)
  end

  def can_manage_announcements?
    return admin_logged_in?
  end

  def show_or_hide_block visible=true
    html = "display:" + (visible ? 'block' : 'none')
    html.html_safe
  end

  def toggle_appear_javascript block_id
    "Effect.toggle('#{block_id}','slide',{duration:0.5})".html_safe
  end

  def count_actions(object, actions=nil)
    count = 0
    if actions.nil?
      count = ActivityLog.count(:conditions => {:activity_loggable_type => object.class.name, :activity_loggable_id => object.id})
    else
      count = ActivityLog.no_spider.count(:conditions => {:action => actions, :activity_loggable_type => object.class.name, :activity_loggable_id => object.id})
    end
    count
  end

  def set_parameters_for_sharing_form object=nil
    object ||= eval "@#{controller_name.singularize}"
    policy = nil
    policy_type = ""

    # obtain a policy to use
    if object
      if object.instance_of? Project
        if object.default_policy
          policy = object.default_policy
          policy_type ="project"
        else
          policy = Policy.default
          policy_type = "system"
        end
      elsif (policy = object.policy)
        # object exists and has a policy associated with it - normal case
        policy_type = "asset"
      end
    end

    unless policy
      policy = Policy.default
      policy_type = "system"
    end

    # set the parameters
    # ..from policy
    @policy = policy
    @policy_type = policy_type
    @sharing_mode = policy.sharing_scope
    @access_mode = policy.access_type
    @use_custom_sharing = !policy.permissions.empty?
    @use_whitelist = (policy.use_whitelist == true || policy.use_whitelist == 1)
    @use_blacklist = (policy.use_blacklist == true || policy.use_blacklist == 1)

    # ..other
    @resource_type = text_for_resource object
    @favourite_groups = current_user.favourite_groups
    @resource = object

    @all_people_as_json = Person.get_all_as_json

    @enable_black_white_listing = @resource.nil? || (@resource.respond_to?(:contributor) and !@resource.contributor.nil?)
  end

  def folding_box id, title, options = nil
    render :partial => 'assets/folding_box', :locals =>
        {:fold_id => id,
         :fold_title => title,
         :contents => options[:contents],
         :hidden => options[:hidden]}
  end

  def resource_tab_item_name resource_type,pluralize=true
    resource_type = resource_type.singularize
    if resource_type == "Speciman"
      result = t('biosamples.sample_parent_term')
    elsif resource_type == "Assay"
      result = t('assays.assay')
    else
      translated_resource_type = translate_resource_type(resource_type)
      result = translated_resource_type.include?("translation missing") ? resource_type : translated_resource_type
    end
    pluralize ? result.pluralize : result
  end

  def internationalized_resource_name resource_type,pluralize=true
    resource_type = resource_type.singularize
    if resource_type == "Speciman"
      result = t('biosamples.sample_parent_term')
    elsif resource_type == "Assay"
      result = t('assays.assay')
    elsif resource_type == "TavernaPlayer::Run"
      result = "Run"
    else
      translated_resource_type = translate_resource_type(resource_type)
      result = translated_resource_type.include?("translation missing") ? resource_type : translated_resource_type
    end
    pluralize ? result.pluralize : result
  end

  def translate_resource_type resource_type
    t("#{resource_type.underscore}")
  end

  def add_return_to_search
    referer = request.headers["Referer"].try(:normalize_trailing_slash)
    search_path = main_app.search_url.normalize_trailing_slash
    root_path = main_app.root_url.normalize_trailing_slash
    request_uri = request.fullpath.try(:normalize_trailing_slash)
    if !request_uri.include?(root_path)
      request_uri = root_path.chop + request_uri
    end

    if referer == search_path && referer != request_uri && request_uri != root_path
      javascript_tag "
        if (window.history.length > 1){
          var a = document.createElement('a');
          a.onclick = function(){ window.history.back(); };
          a.onmouseover = function(){ this.style.cursor='pointer'; }
          a.appendChild(document.createTextNode('Return to search'));
          a.style.textDecoration='underline';
          document.getElementById('return_to_search').appendChild(a);
        }
      "
      #link_to_function 'Return to search', "window.history.back();"
    end
  end

  def no_deletion_explanation_message(clz)
    no_deletion_explanation_messages[clz] || "You are unable to delete this #{clz.name}. It might be published"
  end

  def no_deletion_explanation_messages
    {Assay=>"You cannot delete this #{I18n.t('assays.assay')}. It might be published or it has items associated with it.",
     Study=>"You cannot delete this #{I18n.t('study')}. It might be published or it has #{I18n.t('assays.assay').pluralize} associated with it.",
     Investigation=>"You cannot delete this #{I18n.t('investigation')}. It might be published or it has #{I18n.t('study').pluralize} associated with it." ,
     Strain=>"You cannot delete this Strain. It might be published or it has #{I18n.t('biosamples.sample_parent_term').pluralize}/Samples associated with it or you are not authorized.",
     Specimen=>"You cannot delete this #{I18n.t 'biosamples.sample_parent_term'}. It might be published or it has Samples associated with it or you are not authorized.",
     Sample=>"You cannot delete this Sample. It might be published or it has #{I18n.t('assays.assay').pluralize} associated with it or you are not authorized.",
     Project=>"You cannot delete this #{I18n.t 'project'}. It might has people associated with it.",
     Institution=>"You cannot delete this Institution. It might has people associated with it."
    }
  end


  
  def unable_to_delete_text model_item
    no_deletion_explanation_message(model_item.class).html_safe
  end

  #
  # Converts the given HASH array like 'params' to a flat
  # HASH array that's compatible with url_for and link_to
  # From http://www.gamecreatures.com/blog/2007/08/21/rails-url_for-and-params-missery/
  #
  def flatten_param_hash( params )
    found = true

    while found
      found = false
      new_hash = {}

      params.each do |key,value|
        if value.is_a?( Hash )
          found = true
          value.each do |key2,value2|
            new_hash[ key.to_s + '[' + key2.to_s + ']' ] = value2
          end
        else
          new_hash[ key.to_s ] = value
        end
      end
      params = new_hash
    end
    params
  end

  #returns a new instance of the string describing a resource type, or nil if it is not applicable
  def instance_of_resource_type resource_type
    resource = nil
    begin
      resource_class = resource_type.classify.constantize unless resource_type.nil?
      resource = resource_class.send(:new) if !resource_class.nil? && resource_class.respond_to?(:new)
    rescue NameError=>e
      logger.error("Unable to find constant for resource type #{resource_type}")
    end
    resource
  end

  def klass_from_controller controller_name
    controller_name.singularize.camelize.constantize
  end

  def describe_visibility(model)
    text = '<strong>Visibility:</strong> '

    if model.policy.sharing_scope == 0
      css_class = 'private'
      text << "Private "
      text << "with some exceptions " unless model.policy.permissions.empty?
      text << image('lock', :style => 'vertical-align: middle')
    elsif model.policy.sharing_scope == 2 && model.policy.access_type == 0
      css_class = 'group'
      text << "Only visible to members of "
      text << model.policy.permissions.select {|p| p.contributor_type == 'Project'}.map {|p| p.contributor.title}.to_sentence
    else
      css_class = 'public'
      text << "Public #{image('world', :style => 'vertical-align: middle')}"
    end

    "<span class='visibility #{css_class}'>#{text}</span>".html_safe
  end

  private  
  PAGE_TITLES={"home"=>"Home", "projects"=>I18n.t('project').pluralize,"institutions"=>"Institutions", "people"=>"People", "sessions"=>"Login","users"=>"Signup","search"=>"Search",
               "assays"=>I18n.t('assays.assay').pluralize.capitalize,"sops"=>I18n.t('sop').pluralize,"models"=>I18n.t('model').pluralize,"data_files"=>I18n.t('data_file').pluralize,
               "publications"=>"Publications","investigations"=>I18n.t('investigation').pluralize,"studies"=>I18n.t('study').pluralize,
               "specimens"=>I18n.t('biosamples.sample_parent_term').pluralize,"samples"=>"Samples","strains"=>"Strains","organisms"=>"Organisms","biosamples"=>"Biosamples",
               "presentations"=>I18n.t('presentation').pluralize,"programmes"=>I18n.t('programme').pluralize,"events"=>I18n.t('event').pluralize,"help_documents"=>"Help"}
end

class ApplicationFormBuilder< ActionView::Helpers::FormBuilder
  def fancy_multiselect association, options = {}
    @template.fancy_multiselect object, association, options
  end

  def subform_delete_link(link_text='remove', link_options = {}, hidden_field_options = {})
    hidden_field(:_destroy, hidden_field_options) + @template.link_to_function(link_text, "$(this).previous().value = '1';$(this).up().hide();", link_options)
  end
end

ActionView::Base.default_form_builder = ApplicationFormBuilder