# encoding: UTF-8
require 'redcloth'
# Methods added to this helper will be available to all templates in the
# application.
module ApplicationHelper
include PermissionNameHelper
include UrlHelper
include PartialsHelper
include ModalHelper
include BoxesHelper
include FormsHelper
include AssetsHelper
include BlockHelper
include DatesHelper
include FolderHelper
include ProfileEditorHelper
include DisplayHelper
include AccountHelper
include CommentHelper
include BlogHelper
include ContentViewerHelper
include LayoutHelper
include Noosfero::Gravatar
include TokenHelper
include PluginsHelper
include ButtonsHelper
include ProfileImageHelper
include ThemeLoaderHelper
include TaskHelper
include MembershipsHelper
def locale
(@page && !@page.language.blank?) ? @page.language : FastGettext.locale
end
# Displays context help. You can pass the content of the help message as the
# first parameter or using template code inside a block passed to this
# method. *Note*: the block is ignored if content is not
# nil
#
# The method returns the text generated, so you can also use it inside a
# <%= ... %>
#
# Follow some examples ...
#
# Passing the text as argument:
#
# <% help 'This your help message' %>
#
# Using a block:
#
# <% help do %>
# This is the help message to be displayed. It can contain any HTML you
# want: bold, italic. It can also contain calls
# to any Rails helper, like <%= link_to 'home', :controller => 'home' %>.
# <% end %>
#
# You can also pass an optional argument to force the use of textile in your
# help message:
#
# <% help nil, :textile do %>
# You can also use *textile*!
# <% end %>
#
# or, using the return of the method:
#
# <%= help 'this is your help message' %>
#
# Formally, the type argument can be :html (i.e. no
# conversion of the input) or :textile (converts the message, in
# textile, into HTML). It defaults to :html.
#
# TODO: implement correcly the 'Help' button click
def help(content = nil, link_name = nil, options = {}, &block)
link_name ||= _('Help')
@help_message_id ||= 1
help_id = "help_message_#{@help_message_id}"
if content.nil?
return '' if block.nil?
content = capture(&block)
end
options[:class] = '' if ! options[:class]
options[:class] += ' button icon-help' # with-text
# TODO: implement this button, and add style='display: none' to the help
# message DIV
button = link_to_function(content_tag('span', link_name), "Element.show('#{help_id}')", options )
close_button = content_tag("div", link_to_function(_("Close"), "Element.hide('#{help_id}')", :class => 'close_help_button'))
text = content_tag('div', button + content_tag('div', content_tag('div', content.html_safe) + close_button, :class => 'help_message', :id => help_id, :style => 'display: none;'), :class => 'help_box')
unless block.nil?
concat(text)
end
text
end
# TODO: do something more useful here
# TODO: test this helper
# TODO: add an icon?
# TODO: the command rake test:rcov didn't works because of this method. See what it's the problem
def environment_identification
content_tag('div', @environment.name, :id => 'environment_identification')
end
def link_to_cms(text, profile = nil, options = {})
profile ||= current_user.login
link_to text, myprofile_path(:controller => 'cms', :profile => profile), options
end
def link_to_profile(text, profile = nil, options = {})
profile ||= current_user.login
link_to text, profile_path(:profile => profile) , options
end
def link_to_homepage(text, profile, options = {})
link_to text, profile.url, options
end
def link_if_permitted(link, permission = nil, target = nil)
if permission.nil? || current_user.person.has_permission?(permission, target)
link
else
nil
end
end
def footer
# FIXME: add some information from the environment
[
content_tag('div', _('This is %s, version %s') % [ link_to(Noosfero::PROJECT, 'http://www.noosfero.com.br/'), Noosfero::VERSION]),
].join("\n")
end
# returns the current profile beign viewed.
#
# Make sure that you use this helper method only in contexts where there
# should be a current profile (i.e. while viewing some profile's pages, or the
# profile info, etc), because if there is no profile an exception is thrown.
def profile
controller.send(:profile)
end
def category_color
if @category.nil?
""
else
@category.top_ancestor.display_color
end
end
def text_editor(object, method, filter_type_method = nil, options = {})
text_area(object, method, { :rows => 10, :cols => 64 }.merge(options))
end
def hide(id)
"Element.hide(#{id.inspect});"
end
def show(id)
"Element.show(#{id.inspect});"
end
def toggle_panel(hide_label, show_label, id)
hide_button_id = id + "-hide"
show_button_id = id + "-show"
result = ""
result << button_to_function('open', show_label, show(id) + show(hide_button_id) + hide(show_button_id), :id => show_button_id, :class => 'show-button with-text', :style => 'display: none;' )
result < " "
result << button_to_function('close', hide_label, hide(id) + hide(hide_button_id) + show(show_button_id), :id => hide_button_id, :class => 'hide-button with-text')
result
end
def icon(icon_name, html_options = {})
the_class = "button #{icon_name}"
if html_options.has_key?(:class)
the_class << ' ' << html_options[:class]
end
content_tag('div', '', html_options.merge(:class => the_class))
end
def icon_button(type, text, url, html_options = {})
the_class = "button icon-button icon-#{type}"
if html_options.has_key?(:class)
the_class << ' ' << html_options[:class]
end
link_to(content_tag('span', text), url, html_options.merge(:class => the_class, :title => text))
end
def render_profile_actions klass
name = klass.to_s.underscore
begin
render "blocks/profile_info_actions/#{name}"
rescue ActionView::MissingTemplate
render_profile_actions klass.superclass
end
end
def user
controller.send(:user)
end
# DEPRECATED. Do not use this.
def stylesheet_import(*sources)
options = sources.last.is_a?(Hash) ? sources.pop : { }
themed_source = options.delete(:themed_source)
content_tag(
'style',
"\n" +
sources.flatten.map do |source|
filename = filename_for_stylesheet(source.to_s, themed_source)
if File.exists?(Rails.root.join('public', filename[1..-1]))
"@import url(#{filename});\n"
else
"/* Not included: url(#{filename}) */\n"
end
end.join(),
{ "type" => "text/css" }.merge(options)
)
end
# DEPRECATED. Do not use this.
def filename_for_stylesheet(name, in_theme)
result = ''
if in_theme
result << theme_path
end
name += '.css' if ( name[-4..-1] != '.css' )
if ( name[0..0] == '/' )
result << name
else
result << '/stylesheets/' << name
end
end
def theme_view_file(template, theme=nil)
# Since we cannot control what people are doing in external themes, we
# will keep looking for the deprecated .rhtml extension here.
addr = theme ? "designs/themes/#{theme}" : theme_path[1..-1]
file = Rails.root.join('public', addr, template + '.html.erb')
return file if File.exists?(file)
nil
end
def theme_include(template, options = {})
from_theme_include(nil, template, options)
end
def env_theme_include(template, options = {})
from_theme_include(environment.theme, template, options)
end
def from_theme_include(theme, template, options = {})
file = theme_view_file(template, theme)
if file
render options.merge(file: file, use_full_path: false)
else
nil
end
end
def theme_favicon
return '/designs/themes/' + current_theme + '/favicon.ico' if profile.nil? || profile.theme.nil?
if File.exists?(Rails.root.join('public', theme_path, 'favicon.ico'))
'/designs/themes/' + profile.theme + '/favicon.ico'
else
favicon = profile.articles.find_by path: 'favicon.ico'
if favicon
favicon.public_filename
else
'/designs/themes/' + environment.theme + '/favicon.ico'
end
end
end
def theme_site_title
@theme_site_title ||= theme_include 'site_title'
end
def theme_header
@theme_header ||= theme_include 'header'
end
def theme_footer
@theme_footer ||= theme_include 'footer'
end
def theme_extra_navigation
@theme_extra_navigation ||= theme_include 'navigation'
end
def global_header
@global_header ||= env_theme_include 'global_header'
end
def global_footer
@global_footer ||= env_theme_include 'global_footer'
end
def is_testing_theme
!controller.session[:user_theme].nil?
end
def theme_owner
Theme.find(current_theme).owner.identifier
end
def popover_menu(title,menu_title,links,html_options={})
html_options[:class] = "" unless html_options[:class]
html_options[:class] << " menu-submenu-trigger"
html_options[:onclick] = "toggleSubmenu(this, '#{menu_title}', #{CGI::escapeHTML(links.to_json)}); return false".html_safe
link_to(content_tag(:span, title), '#', html_options)
end
attr_reader :environment
def select_categories(object_name, title=nil, title_size=4)
return nil if environment.enabled?(:disable_categories)
if title.nil?
title = _('Categories')
end
@object = instance_variable_get("@#{object_name}")
@categories = environment.top_level_categories
@current_categories = environment.top_level_categories.select{|i| !i.children.empty?}
render :partial => 'shared/select_categories_top', :locals => {:object_name => object_name, :title => title, :title_size => title_size, :multiple => true, :categories_selected => @object.categories }, :layout => false
end
def theme_option(opt = nil)
conf = Rails.root.to_s() +
'/public' + theme_path +
'/theme.yml'
if File.exists?(conf)
opt ? YAML.load_file(conf)[opt.to_s()] : YAML.load_file(conf)
else
nil
end
end
def theme_opt_menu_search
opt = theme_option( :menu_search )
if opt == 'none'
""
elsif opt == 'simple_search'
s = _('Search...')
"
'
else
modal_link_to ''+ _('Search'), {
:controller => 'search',
:action => 'popup',
:category_path => (@category ? @category.explode_path : nil)},
:id => 'open_search'
end
end
def theme_javascript
option = theme_option(:js)
return if option.nil?
html = []
option.each do |file|
file = theme_path +
'/javascript/'+ file +'.js'
if File.exists? Rails.root.to_s() +'/public'+ file
html << javascript_src_tag( file, {} )
else
html << ''
end
end
html.join "\n"
end
def theme_javascript_src
script = File.join theme_path, 'theme.js'
script if File.exists? File.join(Rails.root, 'public', script)
end
def theme_javascript_ng
script = theme_javascript_src
javascript_include_tag script if script
end
def template_path
if profile.nil?
"/designs/templates/#{environment.layout_template}"
else
"/designs/templates/#{profile.layout_template}"
end
end
def template_javascript_src
script = File.join template_path, '/javascripts/template.js'
script if File.exists? File.join(Rails.root, 'public', script)
end
def templete_javascript_ng
script = template_javascript_src
javascript_include_tag script if script
end
def file_field_or_thumbnail(label, image, i, removable = true)
display_form_field label, (
render :partial => (image && image.valid? ? 'shared/show_thumbnail' : 'shared/change_image'),
:locals => { :i => i, :image => image, :removable => removable }
)
end
def rolename_for(profile, resource)
roles = profile.role_assignments.
where(:resource_id => resource.id).
sort_by{ |role_assignment| role_assignment.role_id }.
map(&:role)
names = []
roles.each do |role|
names << content_tag('span', role.name, :style => "color: #{role_color(role, resource.environment.id)}").html_safe
end
safe_join(names, ', ')
end
def role_color(role, env_id)
case role
when Profile::Roles.admin(env_id)
'blue'
when Profile::Roles.member(env_id)
'green'
when Profile::Roles.moderator(env_id)
'gray'
else
'black'
end
end
# Should be on the forms_helper file but when its there the translation of labels doesn't work
class NoosferoFormBuilder < ActionView::Helpers::FormBuilder
extend ActionView::Helpers::TagHelper
def self.output_field(text, field_html, field_id = nil)
# try to guess an id if none given
if field_id.nil?
field_html =~ /id=['"]([^'"]*)['"]/
field_id = $1
end
field_html =~ /type=['"]([^'"]*)['"]/
field_html =~ /<(\w*)/ unless $1
field_type = $1
field_class = 'formfield type-' + field_type if field_type
label_html = content_tag('label', gettext(text), :class => 'formlabel', :for => field_id)
control_html = content_tag('div', field_html, :class => field_class )
content_tag('div', label_html + control_html, :class => 'formfieldline' )
end
(field_helpers - %w(hidden_field)).each do |selector|
src = <<-END_SRC
def #{selector}(field, *args, &proc)
begin
object ||= @template.instance_variable_get("@"+object_name.to_s)
rescue
end
text = object.class.respond_to?(:human_attribute_name) && object.class.human_attribute_name(field.to_s) || field.to_s.humanize
NoosferoFormBuilder::output_field(text, super)
end
END_SRC
class_eval src, __FILE__, __LINE__
end
# Create a formatable radio collection
# Tha values parameter is a array of [value, label] arrays like this:
# [ ['en',_('English')], ['pt',_('Portuguese')], ['es',_('Spanish')] ]
# The option :size will set how many radios will be showed in each line
# Example: use :size => 3 as option if you want 3 radios by line
def radio_group( object_name, method, values, options = {} )
line_size = options[:size] || 0
line_item = 0
html = "\n"
values.each { |val, h_val|
id = object_name.to_s() +'_'+ method.to_s() +'_'+ val.to_s()
html += self.class.content_tag( 'span',
@template.radio_button( object_name, method, val,
:id => id, :object => @object ) +
self.class.content_tag( 'label', h_val, :for => id ),
:class => 'lineitem' + (line_item+=1).to_s() ) +"\n"
if line_item == line_size
line_item = 0
html += "
\n".html_safe
end
}
html = html.html_safe
html += "
\n".html_safe if line_size == 0 || ( values.size % line_size ) > 0
column = object.class.columns_hash[method.to_s] if object
text =
( column ?
column.human_name :
_(method.to_s.humanize)
)
label_html = self.class.content_tag 'label', text,
:class => 'formlabel'
control_html = self.class.content_tag 'div', html.html_safe,
:class => 'formfield type-radio '+
'fieldgroup linesize'+line_size.to_s()
self.class.content_tag 'div', label_html + control_html,
:class => 'formfieldline'
end
end
# create a form field structure (as if it were generated with
# labelled_form_for), but with a customized control and label.
#
# If +field_id+ is not given, the underlying implementation will try to guess
# it from +field_html+ using a regular expression. In this case, make sure
# that the first ocurrance of id=['"]([^'"]*)['"] in +field_html+ if the one
# you want (i.e. the correct id for the control )
def labelled_form_field(label, field_html, field_id = nil)
NoosferoFormBuilder::output_field(label, field_html, field_id)
end
alias_method :display_form_field, :labelled_form_field
def labelled_fields_for(name, object = nil, options = {}, &proc)
object ||= instance_variable_get("@#{name}")
fields_for(name, object, { :builder => NoosferoFormBuilder }.merge(options), &proc)
end
def labelled_form_for(name, options = {}, &proc)
form_for(name, { :builder => NoosferoFormBuilder }.merge(options), &proc)
end
def optional_field(profile, name, field_html = nil, only_required = false, &block)
result = ""
is_required = false
if profile.required_fields.include?(name)
is_required = true
else
return result if only_required
end
if block
field_html ||= ''.html_safe
field_html = [field_html, capture(&block)].safe_join
end
if controller.action_name == 'signup' || controller.action_name == 'new_community' || (controller.controller_name == "enterprise_registration" && controller.action_name == 'index') || (controller.controller_name == 'home' && controller.action_name == 'index' && user.nil?)
if profile.signup_fields.include?(name)
result = field_html
end
else
if profile.active_fields.include?(name)
result = content_tag :div, class: 'field-with-privacy-selector' do
[field_html, profile_field_privacy_selector(profile, name)].safe_join
end
end
end
if is_required
result = required(result)
end
result
end
def profile_field_privacy_selector(profile, name)
return '' unless profile.public?
content_tag('div', labelled_check_box(_('Public'), 'profile_data[fields_privacy]['+name+']', 'public', profile.public_fields.include?(name)), :class => 'field-privacy-selector')
end
def login_url
options = Noosfero.url_options.merge({ :controller => 'account', :action => 'login' })
url_for(options)
end
def base_url
profile ? profile.top_url(request.scheme) : environment.top_url(request.scheme)
end
alias :top_url :base_url
class View < ActionView::Base
def url_for *args
self.controller.url_for *args
end
end
def helper_for_article(article)
article_helper = View.new
article_helper.controller = controller
article_helper.extend ArticleHelper
article_helper.extend Rails.application.routes.url_helpers
begin
class_name = article.class.name + 'Helper'
klass = class_name.constantize
article_helper.extend klass
rescue
end
article_helper
end
def label_for_new_article(article)
article_helper = helper_for_article(!article.nil? && !article.parent.nil? ? article.parent : article)
article_helper.cms_label_for_new_children
end
def label_for_edit_article(article)
article_helper = helper_for_article(article)
article_helper.cms_label_for_edit
end
def label_for_clone_article(article)
translated_types = {
Folder => _('Folder'),
Blog => _('Blog'),
Event => _('Event'),
Forum => _('Forum')
}
translated_type = translated_types[article.class] || _('Article')
_('Clone %s') % translated_type
end
def add_rss_feed_to_head(title, url)
content_for :feeds do
tag(:link, :rel => 'alternate', :type => 'application/rss+xml', :title => title, :href => url_for(url))
end
end
def page_title
CGI.escapeHTML(
(@page ? @page.title + ' - ' : '') +
(@topic ? @topic.title + ' - ' : '') +
(@section ? @section.title + ' - ' : '') +
(@toc ? _('Online Manual') + ' - ' : '') +
(controller.controller_name == 'chat' ? _('Chat') + ' - ' : '') +
(profile ? profile.short_name : environment.name) +
(@category ? " - #{@category.full_name}" : '')
)
end
# DEPRECATED. Do not use this.
def import_controller_stylesheets(options = {})
stylesheet_import( "controller_"+ controller.controller_name(), options )
end
def link_to_email(email)
javascript_tag('var array = ' + email.split('@').to_json + '; document.write("" + array.join("@") + "")'.html_safe)
end
def stylesheet(*args)
content_for(:head) { stylesheet_link_tag(*args) }
end
# Please, use link_to by default!
# This method was created to work around to inexplicable
# chain of problems when display_short_format was called
# from Article model for an ArticleBlock.
def reference_to_article(text, article, anchor=nil)
if article.profile.domains.empty?
href = "#{Noosfero.root}/#{article.url[:profile]}/"
else
href = "http://#{article.profile.domains.first.name}#{Noosfero.root}/"
end
href += article.url[:page].join('/')
href += '#' + anchor if anchor
content_tag('a', text, :href => href)
end
def display_short_format(article, options={})
options[:comments_link] ||= true
options[:read_more_link] ||= true
lead_links = (options[:comments_link] ? link_to_comments(article) : '') + (options[:read_more_link] ? reference_to_article( _('Read more'), article) : '')
html = content_tag('div',
article.lead +
content_tag('div',
lead_links.html_safe,
:class => 'read-more'
),
:class => 'short-post'
)
html
end
def ui_icon(icon_class, extra_class = '')
"".html_safe
end
def ui_button(label, url, html_options = {})
link_to(label, url, html_options.merge(:class => 'ui_button fg-button'))
end
def ui_button_to_remote(label, options, html_options = {})
link_to_remote(label, options, html_options.merge(:class => 'ui_button fg-button'))
end
def jquery_theme
theme_option(:jquery_theme) || 'smoothness'
end
def ui_error(message)
content_tag('div', ui_icon('ui-icon-alert') + message, :class => 'alert fg-state-error ui-state-error')
end
def ui_highlight(message)
content_tag('div', ui_icon('ui-icon-info') + message, :class => 'alert fg-state-highlight ui-state-highlight')
end
def float_to_currency(value)
number_to_currency(value, :unit => environment.currency_unit, :separator => environment.currency_separator, :delimiter => environment.currency_delimiter, :format => "%u %n")
end
def collapsed_item_icon
"".html_safe
end
def expanded_item_icon
"".html_safe
end
def leaf_item_icon
"".html_safe
end
def display_category_menu(block, categories, root = true)
categories = categories.sort{|x,y| x.name <=> y.name}
return "" if categories.blank?
content_tag(:ul) do
categories.map do |category|
category_path = { :controller => 'search', :action => 'category_index', :category_path => category.explode_path }
if category.display_in_menu?
content_tag(:li) do
if !category.is_leaf_displayable_in_menu?
content_tag(:a, collapsed_item_icon, :href => "#", :id => "block_#{block.id}_category_#{category.id}", :class => "category-link-expand " + (root ? "category-root" : "category-no-root"), :onclick => "expandCategory(#{block.id}, #{category.id}); return false", :style => "display: none")
else
leaf_item_icon
end +
link_to(content_tag(:span, category.name, :class => "category-name"), category_path, :class => ("category-leaf" if category.is_leaf_displayable_in_menu?)) +
content_tag(:div, :id => "block_#{block.id}_category_content_#{category.id}", :class => 'child-category') do
display_category_menu(block, category.children, false)
end
end
else
""
end
end.join.html_safe
end +
content_tag(:p) +
(root ? javascript_tag("
jQuery('.child-category').hide();
jQuery('.category-link-expand').show();
var expanded_icon = \"#{ expanded_item_icon }\";
var collapsed_icon = \"#{ collapsed_item_icon }\";
var category_expanded = { 'block' : 0, 'category' : 0 };
") : '')
end
def search_contents_menu
host = environment.default_hostname
links = [
{s_('contents|More recent') => {href: url_for({host: host, controller: 'search', action: 'contents', filter: 'more_recent'})}},
{s_('contents|More viewed') => {href: url_for({host: host, controller: 'search', action: 'contents', filter: 'more_popular'})}},
{s_('contents|Most commented') => {href: url_for({host: host, controller: 'search', action: 'contents', filter: 'more_comments'})}}
]
if logged_in?
links.push(_('New content') => modal_options({:href => url_for({:controller => 'cms', :action => 'new', :profile => current_user.login, :cms => true})}))
end
link_to(content_tag(:span, _('Contents'), :class => 'icon-menu-articles'), {:controller => "search", :action => 'contents', :category_path => nil}, :id => 'submenu-contents') +
popover_menu(_('Contents menu'),'',links,:class => 'up', :id => 'submenu-contents-trigger')
end
alias :browse_contents_menu :search_contents_menu
def search_people_menu
host = environment.default_hostname
links = [
{s_('people|More recent') => {href: url_for({host: host, controller: 'search', action: 'people', filter: 'more_recent'})}},
{s_('people|More active') => {href: url_for({host: host, controller: 'search', action: 'people', filter: 'more_active'})}},
{s_('people|More popular') => {href: url_for({host: host, controller: 'search', action: 'people', filter: 'more_popular'})}}
]
if logged_in?
links.push(_('My friends') => {:href => url_for({:profile => current_user.login, :controller => 'friends'})})
links.push(_('Invite friends') => {:href => url_for({:profile => current_user.login, :controller => 'invite', :action => 'friends'})})
end
link_to(content_tag(:span, _('People'), :class => 'icon-menu-people'), {:controller => "search", :action => 'people', :category_path => ''}, :id => 'submenu-people') +
popover_menu(_('People menu'),'',links,:class => 'up', :id => 'submenu-people-trigger')
end
alias :browse_people_menu :search_people_menu
def search_communities_menu
host = environment.default_hostname
links = [
{s_('communities|More recent') => {href: url_for({host: host, controller: 'search', action: 'communities', filter: 'more_recent'})}},
{s_('communities|More active') => {href: url_for({host: host, controller: 'search', action: 'communities', filter: 'more_active'})}},
{s_('communities|More popular') => {href: url_for({host: host, controller: 'search', action: 'communities', filter: 'more_popular'})}}
]
if logged_in?
links.push(_('My communities') => {:href => url_for({:profile => current_user.login, :controller => 'memberships'})})
links.push(_('New community') => {:href => url_for({:profile => current_user.login, :controller => 'memberships', :action => 'new_community'})})
end
link_to(content_tag(:span, _('Communities'), :class => 'icon-menu-community'), {:controller => "search", :action => 'communities'}, :id => 'submenu-communities') +
popover_menu(_('Communities menu'),'',links,:class => 'up', :id => 'submenu-communities-trigger')
end
alias :browse_communities_menu :search_communities_menu
def pagination_links(collection, options={})
options = {:previous_label => content_tag(:span, '« '.html_safe, :class => 'previous-arrow') + _('Previous'), :next_label => _('Next') + content_tag(:span, ' »'.html_safe, :class => 'next-arrow'), :inner_window => 1, :outer_window => 0 }.merge(options)
will_paginate(collection, options)
end
def render_environment_features(folder)
result = ''
environment.enabled_features.keys.each do |feature|
file = Rails.root.join('app/views/shared', folder.to_s, "#{feature}.html.erb")
if File.exists?(file)
result << render(:file => file, :use_full_path => false)
end
end
result
end
def manage_link(list, kind, title)
if list.present?
link_to_all = nil
if list.count > 5
list = list.first(5)
link_to_all = link_to(content_tag('strong', _('See all')), :controller => 'memberships', :profile => user.identifier)
end
link = list.map do |element|
link_to(content_tag('strong', _('Manage %s').html_safe % element.short_name(25)), element.admin_url, :class => "icon-menu-"+element.class.identification.underscore, :title => _('Manage %s').html_safe % element.short_name)
end
if link_to_all
link << link_to_all
end
render :partial => "shared/manage_link", :locals => {:link => link, :kind => kind.to_s, :title => title}
end
end
def manage_enterprises
return '' unless user && user.environment.enabled?(:display_my_enterprises_on_user_menu)
manage_link(user.enterprises, :enterprises, _('My enterprises')).to_s
end
def manage_communities
return '' unless user && user.environment.enabled?(:display_my_communities_on_user_menu)
administered_communities = user.communities.more_popular.select {|c| c.admins.include? user}
manage_link(administered_communities, :communities, _('My communities')).to_s
end
def admin_link
admin_icon = '' + _('Administration') + ''
user.is_admin?(environment) ? link_to(admin_icon.html_safe, environment.admin_url, :title => _("Configure the environment"), :class => 'admin-link') : ''
end
def usermenu_logged_in
pending_tasks_count = ''
count = user ? Task.to(user).pending.count : -1
if count > 0
pending_tasks_count = link_to(count.to_s, user.tasks_url, :id => 'pending-tasks-count', :title => _("Manage your pending tasks"))
end
user_identifier = "#{user.identifier}"
welcome_link = link_to(user_identifier.html_safe, user.public_profile_url, :id => "homepage-link", :title => _('Go to your homepage'))
welcome_span = _("Welcome, %s") % welcome_link.html_safe
ctrl_panel_icon = ''
ctrl_panel_section = '' + ctrl_panel_icon + _('Control panel') + ''
ctrl_panel_link = link_to(ctrl_panel_section.html_safe, user.admin_url, :class => 'ctrl-panel', :title => _("Configure your personal account and content"))
logout_icon = '' + _('Logout') + ''
logout_link = link_to(logout_icon.html_safe, { :controller => 'account', :action => 'logout'} , :id => "logout", :title => _("Leave the system"))
join_result = safe_join(
[welcome_span.html_safe, render_environment_features(:usermenu).html_safe, admin_link.html_safe,
manage_enterprises, manage_communities, ctrl_panel_link.html_safe,
pending_tasks_count.html_safe, logout_link.html_safe], "")
join_result
end
def usermenu_notlogged_in
login_str = '' + _('Login') + ''
ret = _("%s") % modal_inline_link_to(login_str.html_safe, login_url, '#inlineLoginBox', :id => 'link_login')
return ret.html_safe
end
def usermenu_signup
signup_str = '' + _('Sign up') + ''
ret = _("or %s") % link_to(signup_str.html_safe, :controller => 'account', :action => 'signup')
return ret.html_safe
end
def limited_text_area(object_name, method, limit, text_area_id, options = {})
content_tag(:div, safe_join([
text_area(object_name, method, { :id => text_area_id, :onkeyup => "limited_text_area('#{text_area_id}', #{limit})" }.merge(options)),
content_tag(:p, content_tag(:span, limit) + ' ' + _(' characters left'), :id => text_area_id + '_left'),
content_tag(:p, _('Limit of characters reached'), :id => text_area_id + '_limit', :style => 'display: none')
]), :class => 'limited-text-area')
end
def expandable_text_area(object_name, method, text_area_id, options = {})
options[:class] = (options[:class] || '') + ' autogrow'
text_area(object_name, method, { :id => text_area_id }.merge(options))
end
def pluralize_without_count(count, singular, plural = nil)
count == 1 ? singular : (plural || singular.pluralize)
end
def unique_with_count(list, connector = 'for')
list.sort.inject(Hash.new(0)){|h,i| h[i] += 1; h }.collect{ |x, n| [n, connector, x].join(" ") }.sort
end
def comment_balloon(options = {}, &block)
wrapper = content_tag(:div, capture(&block), :class => 'comment-balloon-content')
(1..8).to_a.reverse.each { |i| wrapper = content_tag(:div, wrapper, :class => "comment-wrapper-#{i}") }
classes = options.delete(:class) || options.delete("class") || ''
concat(content_tag('div', wrapper + tag('br', :style => 'clear: both;'), { :class => 'comment-balloon ' + classes.to_s }.merge(options)))
end
def display_source_info(page)
if !page.source.blank?
source_url = link_to(page.source_name.blank? ? page.source : page.source_name, page.source)
elsif page.reference_article
source_url = link_to(page.reference_article.profile.name, page.reference_article.url)
end
content_tag(:div, _('Source: %s') % source_url, :id => 'article-source') unless source_url.nil?
end
def task_information(task, params = {})
values = {}
values.merge!(task.information[:variables]) if task.information[:variables]
values.merge!({:requestor => link_to(task.requestor.name, task.requestor.url)}) if task.requestor
if (task.target && task.target.respond_to?(:url))
values.merge!({:target => link_to(task.target.name, task.target.url)})
target_detail = _("in %s").html_safe % values[:target]
target_detail = '' if task.target.identifier == params[:profile]
values.merge!({:target_detail => target_detail})
end
values.merge!({:subject => content_tag('span', task.subject, :class=>'task_target')}) if task.subject
values.merge!({:linked_subject => link_to(content_tag('span', task.linked_subject[:text], :class => 'task_target'), task.linked_subject[:url])}) if task.linked_subject
(task.information[:message] % values).html_safe
end
def add_zoom_to_article_images
add_zoom_to_images if environment.enabled?(:show_zoom_button_on_article_images)
end
def add_zoom_to_images
stylesheet_link_tag('vendor/jquery.fancybox') +
javascript_include_tag('vendor/jquery.fancybox.pack') +
javascript_tag("apply_zoom_to_images(#{_('Zoom in').to_json})")
end
def render_dialog_error_messages(instance_name)
render :partial => 'shared/dialog_error_messages', :locals => { :object_name => instance_name }
end
def report_abuse(profile, type, content=nil)
return if !user || user == profile
url = { :controller => 'profile',
:action => 'report_abuse',
:profile => profile.identifier }
url.merge!({:content_type => content.class.name, :content_id => content.id}) if content
text = content_tag('span', _('Report abuse'))
klass = 'report-abuse-action'
already_reported_message = _('You already reported this profile.')
report_profile_message = _('Report this profile for abusive behaviour')
if type == :button
if user.already_reported?(profile)
button(:alert, text, url, :class => klass+' disabled', :disabled => true, :title => already_reported_message)
else
button(:alert, text, url, :class => klass, :title => report_profile_message)
end
elsif type == :link
if user.already_reported?(profile)
content_tag('a', text, :class => klass + ' disabled button with-text icon-alert', :title => already_reported_message)
else
link_to(text, url, :class => klass + ' button with-text icon-alert', :title => report_profile_message)
end
elsif type == :comment_link
(user.already_reported?(profile) ?
content_tag('a', text, :class => klass + ' disabled comment-footer comment-footer-link', :title => already_reported_message) :
link_to(text, url, :class => klass + ' comment-footer comment-footer-link', :title => report_profile_message)
) + content_tag('span', ' ', :class => 'comment-footer comment-footer-hide')
end
end
def cache_timeout(key, timeout, &block)
cache(key, { :expires_in => timeout, :skip_digest => true }, &block)
end
def is_cache_expired?(key)
!cache_store.fetch(ActiveSupport::Cache.expand_cache_key(key, :controller))
end
def render_tabs(tabs)
titles = tabs.inject(''.html_safe){ |result, tab| result << content_tag(:li, link_to(tab[:title], '#'+tab[:id]), :class => 'tab') }
contents = tabs.inject(''.html_safe){ |result, tab| result << content_tag(:div, tab[:content], :id => tab[:id]) }
content_tag(:div, content_tag(:ul, titles) + raw(contents), :class => 'ui-tabs')
end
def delete_article_message(article)
if article.folder?
_("Are you sure that you want to remove the folder \"%s\"? Note that all the items inside it will also be removed!") % article.name
else
_("Are you sure that you want to remove the item \"%s\"?") % article.name
end
end
def expirable_link_to(expired, content, url, options = {})
if expired
options[:class] = (options[:class] || '') + ' disabled'
content_tag('a', ' '.html_safe+content_tag('span', content), options)
else
if options[:modal]
options.delete(:modal)
modal_link_to content, url, options
else
link_to content, url, options
end
end
end
def content_remove_spread(content)
!content.public? || content.folder? || (profile == user && user.communities.blank? && !environment.portal_enabled)
end
def remove_content_button(action, content)
method_name = "content_remove_#{action.to_s}"
plugin_condition = @plugins.dispatch(method_name, content).include?(true)
begin
core_condition = self.send(method_name, content)
rescue NoMethodError
core_condition = false
end
core_condition || plugin_condition
end
def template_options(kind, field_name)
templates = environment.send(kind).templates
return '' if templates.count == 0
return hidden_field_tag("#{field_name}[template_id]", templates.first.id) if templates.count == 1
radios = templates.map do |template|
content_tag('li', labelled_radio_button(link_to(template.name, template.url, :target => '_blank'), "#{field_name}[template_id]", template.id, environment.is_default_template?(template)))
end.join("\n").html_safe
content_tag('div', content_tag('label', _('Profile organization'), :for => 'template-options', :class => 'formlabel') +
content_tag('p', _('Your profile will be created according to the selected template. Click on the options to view them.'), :style => 'margin: 5px 15px;padding: 0px 10px;') +
content_tag('ul', radios, :style => 'list-style: none; padding-left: 20px; margin-top: 0.5em;'),
:id => 'template-options',
:style => 'margin-top: 1em'
)
end
def expirable_content_reference(content, action, text, url, options = {})
reason = @plugins.dispatch("content_expire_#{action.to_s}", content).first
options[:title] = reason
expirable_link_to reason.present?, text, url, options
end
def expirable_button(content, action, text, url, options = {})
options[:class] = ["button with-text icon-#{action.to_s}", options[:class]].compact.join(' ')
expirable_content_reference content, action, text, url, options
end
def expirable_comment_link(content, action, text, url, options = {})
options[:class] = ["comment-footer comment-footer-link comment-footer-hide", options[:class]].compact.join(' ')
expirable_content_reference content, action, text, url, options
end
def error_messages_for(*args)
options = args.pop if args.last.is_a?(Hash)
errors = []
args.each do |name|
object = instance_variable_get("@#{name}")
object.errors.full_messages.each do |msg|
errors << msg
end if object
end
return '' if errors.empty?
content_tag(:div, :class => 'errorExplanation', :id => 'errorExplanation') do
content_tag(:h2, _('Errors while saving')) +
content_tag(:ul) do
safe_join(errors.map { |err| content_tag(:li, err.html_safe) })
end
end
end
def private_profile_partial_parameters
if profile.person?
@action = :add_friend
@message = _("The content here is available to %s's friends only.") % profile.short_name
else
@action = :join
@message = _('The contents in this profile is available to members only.')
end
@no_design_blocks = true
end
def convert_macro(html, source)
doc = Nokogiri::HTML.fragment html
#TODO This way is more efficient but do not support macro inside of
# macro. You must parse them from the inside-out in order to enable
# that.
doc.css('.macro').each do |macro|
macro_name = macro['data-macro']
result = @plugins.parse_macro(macro_name, macro, source)
macro.inner_html = result.kind_of?(Proc) ? self.instance_exec(&result) : result
end
doc.to_html
end
def default_folder_for_image_upload(profile)
default_folder = profile.folders.find_by type: 'Gallery'
default_folder = profile.folders.find_by type: 'Folder' if default_folder.nil?
default_folder
end
def content_id_to_str(content)
content.nil? ? '' : content.id.to_s
end
def display_article_versions(article, version = nil)
content_tag('ul', article.versions.map {|v| link_to("r#{v.version}", @page.url.merge(:version => v.version))})
end
def search_input_with_suggestions(name, asset, default, options = {})
text_field_tag name, default, options.merge({:class => 'search-input-with-suggestions', 'data-asset' => asset})
end
def profile_suggestion_profile_connections(suggestion)
profiles = suggestion.profile_connections.first(4).map do |profile|
link_to(profile_image(profile, :icon, :title => profile.name), profile.url, :class => 'profile-suggestion-connection-icon')
end
controller_target = suggestion.suggestion_type == 'Person' ? :friends : :memberships
profiles << link_to(" +#{suggestion.profile_connections.count - 4}".html_safe, :controller => controller_target, :action => :connections, :id => suggestion.suggestion_id) if suggestion.profile_connections.count > 4
if profiles.present?
content_tag(:div, profiles.safe_join , :class => 'profile-connections')
else
''
end
end
def profile_suggestion_tag_connections(suggestion)
tags = suggestion.tag_connections.first(4).map do |tag|
tag.name + ', '
end
last_tag = tags.pop
tags << last_tag.strip.chop if last_tag.present?
title = tags.join
controller_target = suggestion.suggestion_type == 'Person' ? :friends : :memberships
tags << ' ' + link_to('...', {:controller => controller_target, :action => :connections, :id => suggestion.suggestion_id}, :class => 'more-tag-connections', :title => _('See all connections')) if suggestion.tag_connections.count > 4
if tags.present?
content_tag(:div, tags.join, :class => 'tag-connections', :title => title)
else
''
end
end
def labelled_colorpicker_field(human_name, object_name, method, options = {})
options[:id] ||= 'text-field-' + FormsHelper.next_id_number
content_tag('label', human_name, :for => options[:id], :class => 'formlabel') +
colorpicker_field(object_name, method, options.merge(:class => 'colorpicker_field'))
end
def colorpicker_field(object_name, method, options = {})
text_field(object_name, method, options.merge(:class => 'colorpicker_field'))
end
def fullscreen_buttons(itemId)
content="
"
content+=content_tag('a', content_tag('span',_("Full screen")),
{ :id=>"fullscreen-btn",
:onClick=>"toggle_fullwidth('#{itemId}')",
:class=>"button with-text icon-fullscreen",
:href=>"#",
:title=>_("Go to full screen mode")
})
content+=content_tag('a', content_tag('span',_("Exit full screen")),
{ :style=>"display: none;",
:id=>"exit-fullscreen-btn",
:onClick=>"toggle_fullwidth('#{itemId}')",
:class=>"button with-text icon-fullscreen",
:href=>"#",
:title=>_("Exit full screen mode")
})
content.html_safe
end
def current_editor_is?(editor)
editor.blank? ? false : current_editor == editor
end
def current_editor(mode = '')
editor = @article.editor || Article::Editor::TINY_MCE unless @article.nil?
editor ||= (current_person.nil? || current_person.editor.nil?) ? Article::Editor::TINY_MCE : current_person.editor
editor += '_' + mode unless mode.blank?
editor
end
end