Advertisement
brauliobo

g dc f135f26

Jun 20th, 2015
363
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 130.86 KB | None | 0 0
  1. diff --cc Gemfile
  2. index 9777628,ac78c37..fbf08e5
  3. --- a/Gemfile
  4. +++ b/Gemfile
  5. @@@ -61,12 -29,10 +61,12 @@@ group :production d
  6.   end
  7.  
  8.   group :test do
  9.  +  gem 'spring'
  10.  +  gem 'spring-commands-testunit'
  11. +   gem 'rspec',                  '~> 2.14.0'
  12. +   gem 'rspec-rails',            '~> 2.14.1'
  13. +   gem 'mocha',                  '~> 1.1.0', :require => false
  14.     gem 'test-unit' if RUBY_VERSION >= '2.2.0'
  15. -   gem 'rspec',                  '~> 2.10.0'
  16. -   gem 'rspec-rails',            '~> 2.10.1'
  17. -   gem 'mocha',                  '~> 1.1.0', require: false
  18.   end
  19.  
  20.   group :cucumber do
  21. diff --cc app/controllers/application_controller.rb
  22. index adc9d9b,8e90268..1e63ee3
  23. --- a/app/controllers/application_controller.rb
  24. +++ b/app/controllers/application_controller.rb
  25. @@@ -9,7 -9,7 +9,8 @@@ class ApplicationController < ActionCon
  26.     before_filter :allow_cross_domain_access
  27.     before_filter :login_required, :if => :private_environment?
  28.     before_filter :verify_members_whitelist, :if => [:private_environment?, :user]
  29. +   before_filter :redirect_to_current_user
  30.  +  around_filter :set_time_zone
  31.  
  32.     def verify_members_whitelist
  33.       render_access_denied unless user.is_admin? || environment.in_whitelist?(user)
  34. @@@ -196,23 -179,8 +197,24 @@@
  35.  
  36.     include SearchTermHelper
  37.  
  38.  +  private
  39.  +
  40.  +  def autocomplete asset, scope, query, paginate_options={:page => 1}, options={:field => 'name'}
  41.  +    plugins.dispatch_first(:autocomplete, asset, scope, query, paginate_options, options) ||
  42.  +    fallback_autocomplete(asset, scope, query, paginate_options, options)
  43.  +  end
  44.  +
  45.  +  def fallback_autocomplete asset, scope, query, paginate_options, options
  46.  +    field = options[:field]
  47.  +    query = query.downcase
  48.  +    scope.where([
  49.  +      "LOWER(#{field}) ILIKE ? OR #{field}) ILIKE ?", "#{query}%", "% #{query}%"
  50.  +    ])
  51.  +    {:results => scope.paginate(paginate_options)}
  52.  +  end
  53.  +
  54.     def find_by_contents(asset, context, scope, query, paginate_options={:page => 1}, options={})
  55. +     scope = scope.with_templates(options[:template_id]) unless options[:template_id].blank?
  56.       search = plugins.dispatch_first(:find_by_contents, asset, scope, query, paginate_options, options)
  57.       register_search_term(query, scope.count, search[:results].count, context, asset)
  58.       search
  59. diff --cc app/helpers/application_helper.rb
  60. index d72a340,27c63f4..6601a4d
  61. --- a/app/helpers/application_helper.rb
  62. +++ b/app/helpers/application_helper.rb
  63. @@@ -693,6 -707,24 +710,24 @@@ module ApplicationHelpe
  64.       javascript_include_tag script if script
  65.     end
  66.  
  67. +   def template_path
  68. +     if profile.nil?
  69. +       "/designs/templates/#{environment.layout_template}"
  70. +     else
  71. +       "/designs/templates/#{profile.layout_template}"
  72. +     end
  73. +   end
  74. +
  75. +   def template_javascript_src
  76. +     script = File.join template_path, '/javascripts/template.js'
  77. +     script if File.exists? File.join(Rails.root, 'public', script)
  78. +   end
  79. +
  80.  -  def templete_javascript_ng
  81. ++  def template_javascript_ng
  82. +     script = template_javascript_src
  83. +     javascript_include_tag script if script
  84. +   end
  85. +
  86.     def file_field_or_thumbnail(label, image, i)
  87.       display_form_field label, (
  88.         render :partial => (image && image.valid? ? 'shared/show_thumbnail' : 'shared/change_image'),
  89. diff --cc app/helpers/layout_helper.rb
  90. index bf61b41,1139aba..a5d859a
  91. --- a/app/helpers/layout_helper.rb
  92. +++ b/app/helpers/layout_helper.rb
  93. @@@ -29,7 -28,7 +29,7 @@@ module LayoutHelpe
  94.     end
  95.  
  96.     def noosfero_javascript
  97. -     plugins_javascripts = @plugins.map { |plugin| [plugin.js_files].flatten.map { |js| plugin.class.public_path(js, true) } }.flatten
  98.  -    plugins_javascripts = @plugins.flat_map{ |plugin| Array.wrap(plugin.js_files).map{ |js| plugin.class.public_path(js, true) } }.flatten
  99. ++    plugins_javascripts = @plugins.flat_map{ |plugin| Array.wrap(plugin.js_files).map{ |js| plugin.class.public_path(js, true) } }
  100.  
  101.       output = ''
  102.       output += render 'layouts/javascript'
  103. @@@ -39,7 -38,8 +39,8 @@@
  104.       output += theme_javascript_ng.to_s
  105.       output += javascript_tag 'render_all_jquery_ui_widgets()'
  106.  
  107. -     output += javascript_tag 'render_all_jquery_ui_widgets()'
  108.  -    output += templete_javascript_ng.to_s
  109. ++    output += template_javascript_ng.to_s
  110. +
  111.       output
  112.     end
  113.  
  114. diff --cc app/helpers/plugins_helper.rb
  115. index c9a53f6,4b3074a..089042d
  116. --- a/app/helpers/plugins_helper.rb
  117. +++ b/app/helpers/plugins_helper.rb
  118. @@@ -8,43 -6,11 +8,46 @@@ module PluginsHelpe
  119.       end
  120.     end
  121.  
  122. -   def plugins_article_toolbar_actions
  123. -     @plugins.dispatch(:article_toolbar_actions, @page).collect { |content| instance_exec(&content) }.join ""
  124. -   end
  125. -
  126.  +  def plugins_catalog_search_extras_begin
  127.  +    @plugins.dispatch(:catalog_search_extras_begin).map do |content|
  128.  +      instance_exec(&content)
  129.  +    end.join
  130.  +  end
  131.  +
  132.  +  def plugins_catalog_search_extras_end
  133.  +    @plugins.dispatch(:catalog_search_extras_end).map do |content|
  134.  +      instance_exec(&content)
  135.  +    end.join
  136.  +  end
  137.  +
  138.  +  def plugins_catalog_autocomplete_item_extras product
  139.  +    @plugins.dispatch(:catalog_autocomplete_item_extras, product).map do |content|
  140.  +      instance_exec(&content)
  141.  +    end.join
  142.  +  end
  143.  +
  144.  +  def plugins_search_order asset
  145.  +    @plugins.dispatch_first :search_order, asset
  146.  +  end
  147.  +
  148.  +  def plugins_search_pre_contents
  149.  +    @plugins.dispatch(:search_pre_contents).map do |content|
  150.  +      instance_exec(&content)
  151.  +    end.join
  152.  +  end
  153. -  
  154. ++
  155.  +  def plugins_search_post_contents
  156.  +    @plugins.dispatch(:search_post_contents).map do |content|
  157.  +      instance_exec(&content)
  158.  +    end.join
  159.  +  end
  160.  +
  161. +   def plugins_toolbar_actions_for_article(article)
  162. +     toolbar_actions = Array.wrap(@plugins.dispatch(:article_extra_toolbar_buttons, article))
  163. +     toolbar_actions.each do |action|
  164. +       [:title, :url, :icon].each { |param| raise "No #{param} was passed as parameter for #{action}" unless action.has_key?(param) }
  165. +     end
  166. +   end
  167. +
  168.   end
  169.  +
  170. diff --cc app/models/article.rb
  171. index d619e5f,6899eac..4a92b23
  172. --- a/app/models/article.rb
  173. +++ b/app/models/article.rb
  174. @@@ -5,11 -5,10 +5,11 @@@ class Article < ActiveRecord::Bas
  175.                     :allow_members_to_edit, :translation_of_id, :language,
  176.                     :license_id, :parent_id, :display_posts_in_current_language,
  177.                     :category_ids, :posts_per_page, :moderate_comments,
  178. -                   :accept_comments, :feed, :published, :source,
  179. +                   :accept_comments, :feed, :published, :source, :source_name,
  180.                     :highlighted, :notify_comments, :display_hits, :slug,
  181.                     :external_feed_builder, :display_versions, :external_link,
  182.  -                  :image_builder, :show_to_followers
  183.  +                  :image_builder, :show_to_followers, :published_at,
  184.  +                  :author, :created_by, :last_changed_by
  185.  
  186.     acts_as_having_image
  187.  
  188. @@@ -729,8 -724,9 +740,9 @@@
  189.       paragraphs.empty? ? '' : paragraphs.first.to_html
  190.     end
  191.  
  192. -   def lead
  193. -     abstract.blank? ? automatic_abstract : abstract.html_safe
  194. +   def lead(length = nil)
  195.  -    content = abstract.blank? ? first_paragraph.html_safe : abstract.html_safe
  196. ++    content = abstract.blank? ? automatic_abstract.html_safe : abstract.html_safe
  197. +     length.present? ? content.truncate(length) : content
  198.     end
  199.  
  200.     def short_lead
  201. @@@ -785,7 -781,9 +797,10 @@@
  202.     end
  203.  
  204.     def first_image
  205. -     img = Nokogiri::HTML.fragment(self.abstract.to_s).css('img[src]').first || Nokogiri::HTML.fragment(self.body.to_s).search('img').first
  206. +     img = ( image.present? && { 'src' => image.public_filename } ) ||
  207.  -          Nokogiri::HTML.fragment(self.lead.to_s).css('img[src]').first ||
  208. ++          # automatic_abstract conflict, this leads to infinite loop
  209. ++          #Nokogiri::HTML.fragment(self.lead.to_s).css('img[src]').first ||
  210. +           Nokogiri::HTML.fragment(self.body.to_s).search('img').first
  211.       img.nil? ? '' : img['src']
  212.     end
  213.  
  214. diff --cc app/models/profile.rb
  215. index 14f5953,7c5a0e9..9ed7136
  216. --- a/app/models/profile.rb
  217. +++ b/app/models/profile.rb
  218. @@@ -318,11 -333,13 +337,13 @@@ class Profile < ActiveRecord::Bas
  219.     end
  220.  
  221.     validates_presence_of :identifier, :name
  222. -   validates_format_of :identifier, :with => IDENTIFIER_FORMAT, :if => lambda { |profile| !profile.identifier.blank? }
  223. -   validates_exclusion_of :identifier, :in => RESERVED_IDENTIFIERS
  224. -   validates_uniqueness_of :identifier, :scope => :environment_id
  225.  -  validates_length_of :nickname, :maximum => 16, :allow_nil => true
  226.  +  validates_length_of :nickname, :maximum => 40, :allow_nil => true
  227.     validate :valid_template
  228. +   validate :valid_identifier
  229. +
  230. +   def valid_identifier
  231. +     errors.add(:identifier, _('is not available.')) unless Profile.is_available?(identifier, environment, id)
  232. +   end
  233.  
  234.     def valid_template
  235.       if template_id.present? && template && !template.is_template
  236. diff --cc app/views/blocks/profile_info_actions/_join_leave_community.html.erb
  237. index 1ecd22e,787a8eb..949d9fa
  238. --- a/app/views/blocks/profile_info_actions/_join_leave_community.html.erb
  239. +++ b/app/views/blocks/profile_info_actions/_join_leave_community.html.erb
  240. @@@ -1,21 -1,27 +1,21 @@@
  241. - <div class='join-leave-button'>
  242. + <div class='join-leave-button require-login-popup'>
  243.  -  <% if logged_in? %>
  244.  -    <% if profile.members.include?(user) %>
  245.  +  <% if logged_in? and not profile.already_request_membership? user %>
  246.  +    <% if user.in? profile.members %>
  247.         <%= button(:delete, content_tag('span', _('Leave community')), profile.leave_url,
  248.  -        :class => 'leave-community',
  249.  -        :title => _("Leave community"),
  250.  -        :style => 'position: relative;') %>
  251.  -      <%= button(:add, content_tag('span', _('Join')), profile.join_url,
  252.  -        :class => 'join-community',
  253.  -        :title => _("Join community"),
  254.  -        :style => 'position: relative; display: none;') %>
  255.  +        class: 'leave-community',
  256.  +        title: _("Leave community"),
  257.  +        style: 'position: relative;') %>
  258.  +      <%= button(:add, content_tag('span', _('Join this community')), profile.join_url,
  259.  +        class: 'join-community',
  260.  +        title: _("Join community"),
  261.  +        style: 'position: relative; display: none;') %>
  262.       <% else %>
  263.  -      <% unless profile.already_request_membership?(user) %>
  264.  -        <%= button(:delete, content_tag('span', _('Leave community')), profile.leave_url,
  265.  -          :class => 'leave-community',
  266.  -          :title => _("Leave community"),
  267.  -          :style => 'position: relative; display: none;') %>
  268.  -        <%= button(:add, content_tag('span', _('Join')), profile.join_url,
  269.  -          :class => 'join-community',
  270.  -          :title => _("Join community"),
  271.  -          :style => 'position: relative;') %>
  272.  -      <% end %>
  273.  +      <%= button :add, _('Join this community'), profile.join_not_logged_url, title: _('Join this community'), class: 'join-community' %>
  274.       <% end %>
  275.  -  <% else %>
  276.  -      <%= button(:add, _('Join'), profile.join_not_logged_url, :title => _('Join this community')) %>
  277.     <% end %>
  278.   </div>
  279.  +
  280.  +<%= javascript_tag do %>
  281.  +  noosfero.add_and_join.locales.leaveConfirmation = <%= (_("Please confirm to leave the community '%{name}'") % {name: profile.name}).to_json %>
  282.  +<% end %>
  283.  +
  284. diff --cc app/views/box_organizer/edit.html.erb
  285. index f9b9619,031946b..f866ba9
  286. --- a/app/views/box_organizer/edit.html.erb
  287. +++ b/app/views/box_organizer/edit.html.erb
  288. @@@ -3,14 -3,8 +3,8 @@@
  289.  
  290.     <%= form_tag(:action => 'save', :id => @block.id) do %>
  291.  
  292.  -    <%= labelled_form_field(_('Custom title for this block: '), text_field(:block, :title, :maxlength => 20)) %>
  293.  +    <%= labelled_form_field(_('Custom title for this block: '), text_field(:block, :title, :maxlength => 25)) %>
  294.  
  295. -     <% if environment.admins.include?(user) %>
  296. -       <div class="fixed_block">
  297. -         <%= labelled_check_box(_("Fixed"), "block[fixed]", value = "1", checked = @block.fixed) %>
  298. -       </div>
  299. -     <% end %>
  300. -
  301.       <%= render :partial => partial_for_class(@block.class) %>
  302.  
  303.       <div class="display">
  304. diff --cc app/views/cms/_forum.html.erb
  305. index 20f8495,621d78e..cd1430e
  306. --- a/app/views/cms/_forum.html.erb
  307. +++ b/app/views/cms/_forum.html.erb
  308. @@@ -2,9 -2,11 +2,11 @@@
  309.  
  310.   <h1><%= _('My Forum') %></h1>
  311.  
  312. + <%= required_fields_message %>
  313. +
  314.   <%= render :file => 'shared/tiny_mce' %>
  315.  
  316.  -<%= required f.text_field(:name, :size => '64', :maxlength => 150, :onchange => "updateUrlField(this, 'article_slug')") %>
  317.  +<%= required f.text_field(:name, :size => '64', :maxlength => 150, :onchange => "updateUrlField(this, '#article_slug')") %>
  318.  
  319.   <%= render :partial => 'general_fields' %>
  320.  
  321. diff --cc app/views/cms/suggest_an_article.html.erb
  322. index 507a6e3,885db31..156ad4a
  323. --- a/app/views/cms/suggest_an_article.html.erb
  324. +++ b/app/views/cms/suggest_an_article.html.erb
  325. @@@ -20,7 -21,7 +21,7 @@@
  326.  
  327.     <%= hidden_field_tag('back_to', @back_to) %>
  328.  
  329. -   <%= render 'shared/captcha' %>
  330.  -  <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) unless logged_in? %>
  331. ++  <%= render 'shared/captcha' unless logged_in? %>
  332.  
  333.     <% button_bar do %>
  334.       <%= submit_button :save, _('Save') %>
  335. diff --cc app/views/content_viewer/_article_toolbar.html.erb
  336. index dd2b438,2dbc1ee..a3aa490
  337. --- a/app/views/content_viewer/_article_toolbar.html.erb
  338. +++ b/app/views/content_viewer/_article_toolbar.html.erb
  339. @@@ -55,9 -62,9 +62,9 @@@
  340.       <% if @page.blog? and !@page.image.nil? %>
  341.         <div class="blog-cover"><%= image_tag(@page.image.public_filename())%></div>
  342.       <% end %>
  343.  -    <%= link_to(image_tag('/images/icons-mime/rss-feed.png'), @page.feed.url, :class => 'blog-feed-link') if @page.has_posts? && @page.feed %>
  344.  +    <%= button_without_text('feed', _('RSS feed'), @page.feed.url, :class => 'blog-feed-link') if @page.has_posts? && @page.feed %>
  345.       <%= @plugins.dispatch(:article_header_extra_contents, @page).collect { |content| instance_exec(&content) }.join("") %>
  346. -     <%= article_title(@page, :no_link => true) %>
  347. +     <%= render :partial => 'article_title', :locals => {:no_link => true} %>
  348.       <%= article_translations(@page) %>
  349.     </div>
  350.   </div>
  351. diff --cc app/views/search/_search_content.html.erb
  352. index d993ffe,c226a98..1332651
  353. --- a/app/views/search/_search_content.html.erb
  354. +++ b/app/views/search/_search_content.html.erb
  355. @@@ -1,15 -1,10 +1,19 @@@
  356.   <div id='search-content'>
  357. +   <div class='total'>
  358. +     <%= _('Total of %s results ') % @searches[@asset][:results].total_entries.inspect %>
  359. +   </div>
  360. +
  361.  -<%= display_results(@searches, @asset) %>
  362.  -<% if params[:display] != 'map' %>
  363.  -  <%= pagination_links @searches[@asset][:results] %>
  364.  -<% end %>
  365.  +  <%= plugins_search_pre_contents %>
  366.  +
  367.  +  <% if @asset == :products %>
  368.  +    <% @show_supplier = true %>
  369.  +    <%= render 'search_products_content' %>
  370.  +  <% else %>
  371.  +    <%= display_results(@searches, @asset) %>
  372.  +    <% if params[:display] != 'map' %>
  373.  +      <%= pagination_links @searches[@asset][:results] %>
  374.  +    <% end %>
  375.  +  <% end %>
  376.  +
  377.  +  <%= plugins_search_post_contents %>
  378.   </div>
  379. diff --cc app/views/search/_search_form.html.erb
  380. index 3e7dfa1,6ca673f..e1c9c31
  381. --- a/app/views/search/_search_form.html.erb
  382. +++ b/app/views/search/_search_form.html.erb
  383. @@@ -3,18 -3,20 +3,23 @@@
  384.     <%= form_tag( { :controller => 'search', :action => @asset ? @asset : 'index', :asset => nil, :category_path => ( @category ? @category.path : nil ) },
  385.                    :method => 'get', :class => 'search_form' ) do %>
  386.       <div id='search-header'>
  387.  +      <h1><%= _('Searches') %></h1>
  388.         <%= assets_menu(@asset) %>
  389.         <%= filters(@asset) %>
  390. +       <div class="clear"></div>
  391. +     </div>
  392. +
  393. +     <div id='search-subheader'>
  394. +       <%= assets_submenu(@asset) %>
  395.       </div>
  396.  -    <div class="search-field">
  397.  -      <span class="formfield">
  398.  -        <%= search_input_with_suggestions('query', @asset, @query, {:id => 'search-input', :size => 50, :placeholder => hint}) %>
  399.  -      </span>
  400.  
  401.  -      <%= submit_button(:search, _('Search')) %>
  402.  +    <div id='search-box' class="search-field form-group">
  403.  +      <div class="formfield input-group">
  404.  +        <%= search_input_with_suggestions('query', @asset, @query, {:id => 'search-input', :size => 50, :placeholder => hint}) %>
  405.  +        <span class="input-group-btn">
  406.  +          <%= submit_button :search, _('Search'), size: 'default' %>
  407.  +        </span>
  408.  +      </div>
  409.       </div>
  410.  
  411.       <%= render :partial => 'search_form_extra_fields' %>
  412. diff --cc app/views/shared/_captcha.html.erb
  413. index 98bfdf1,0000000..2aea0de
  414. mode 100644,000000..100644
  415. --- a/app/views/shared/_captcha.html.erb
  416. +++ b/app/views/shared/_captcha.html.erb
  417. @@@ -1,4 -1,0 +1,4 @@@
  418. - <%= recaptcha_tags :ajax => true, :display => {:theme => 'clean'} %>
  419. ++<%= recaptcha_tags ajax: true, display: {theme: 'clean'} %>
  420.  +
  421.  +<%= hidden_captcha_field %>
  422.  +
  423. diff --cc config/environments/production.rb
  424. index ce2af54,058171f..58e6675
  425. --- a/config/environments/production.rb
  426. +++ b/config/environments/production.rb
  427. @@@ -8,9 -8,9 +8,6 @@@ Noosfero::Application.configure d
  428.     # Full error reports are disabled and caching is turned on
  429.     # config.action_controller.perform_caching = true
  430.  
  431. --  # Enable Rails's static asset server (Apache or nginx should do this)
  432. --  config.serve_static_assets = true
  433. --
  434.     # Compress JavaScripts and CSS
  435.     config.assets.compress = true
  436.  
  437. @@@ -23,10 -23,6 +20,11 @@@
  438.       File.basename file
  439.     end.compact
  440.  
  441.  +  # fallback to assets pipeline if a precompiled asset is missed
  442. -   config.assets.digest = true
  443. ++  config.serve_static_assets = true
  444. ++  config.assets.compile = true
  445.  +  config.assets.cache_store = :assets_live_compile_store
  446.  +
  447.     # Defaults to nil and saved in location specified by config.assets.prefix
  448.     # config.assets.manifest = YOUR_PATH
  449.  
  450. diff --cc config/routes.rb
  451. index 82c5563,76ca289..522c063
  452. --- a/config/routes.rb
  453. +++ b/config/routes.rb
  454. @@@ -59,48 -55,38 +59,48 @@@ Noosfero::Application.routes.draw d
  455.     # search
  456.     match 'search(/:action(/*category_path))', :controller => 'search'
  457.  
  458.  +  ######################################################
  459.  +  # plugin routes
  460.  +  # need to come first as 'plugin' will become the :profile parameter when custom domains are used
  461.  +  ######################################################
  462.  +  plugins_routes = File.join(File.dirname(__FILE__) + '/../lib/noosfero/plugin/routes.rb')
  463.  +  eval(IO.read(plugins_routes), binding, plugins_routes)
  464.  +
  465.     # events
  466. -   match 'profile(/:profile)/events_by_day', :controller => 'events', :action => 'events_by_day', :profile => /#{Noosfero.identifier_format}/
  467. -   match 'profile(/:profile)/events_by_month', :controller => 'events', :action => 'events_by_month', :profile => /#{Noosfero.identifier_format}/
  468. -   match 'profile(/:profile)/events/:year/:month/:day', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :day => /\d*/, :profile => /#{Noosfero.identifier_format}/
  469. -   match 'profile(/:profile)/events/:year/:month', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :profile => /#{Noosfero.identifier_format}/
  470. -   match 'profile(/:profile)/events', :controller => 'events', :action => 'events', :profile => /#{Noosfero.identifier_format}/
  471.  -  match 'profile/:profile/events_by_day', :controller => 'events', :action => 'events_by_day', :profile => /#{Noosfero.identifier_format_in_url}/
  472.  -  match 'profile/:profile/events_by_month', :controller => 'events', :action => 'events_by_month', :profile => /#{Noosfero.identifier_format_in_url}/
  473.  -  match 'profile/:profile/events/:year/:month/:day', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :day => /\d*/, :profile => /#{Noosfero.identifier_format_in_url}/
  474.  -  match 'profile/:profile/events/:year/:month', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :profile => /#{Noosfero.identifier_format_in_url}/
  475.  -  match 'profile/:profile/events', :controller => 'events', :action => 'events', :profile => /#{Noosfero.identifier_format_in_url}/
  476. ++  match 'profile(/:profile)/events_by_day', :controller => 'events', :action => 'events_by_day', :profile => /#{Noosfero.identifier_format_in_url}/
  477. ++  match 'profile(/:profile)/events_by_month', :controller => 'events', :action => 'events_by_month', :profile => /#{Noosfero.identifier_format_in_url}/
  478. ++  match 'profile(/:profile)/events/:year/:month/:day', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :day => /\d*/, :profile => /#{Noosfero.identifier_format_in_url}/
  479. ++  match 'profile(/:profile)/events/:year/:month', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :profile => /#{Noosfero.identifier_format_in_url}/
  480. ++  match 'profile(/:profile)/events', :controller => 'events', :action => 'events', :profile => /#{Noosfero.identifier_format_in_url}/
  481.  
  482.     # catalog
  483. -   match 'profile(/:profile)/catalog(/:action(/:id))', :controller => :catalog, :profile => /#{Noosfero.identifier_format}/, :as => :catalog
  484.  -  match 'catalog/:profile', :controller => 'catalog', :action => 'index', :profile => /#{Noosfero.identifier_format_in_url}/, :as => :catalog
  485. ++  match 'profile(/:profile)/catalog(/:action(/:id))', :controller => :catalog, :profile => /#{Noosfero.identifier_format_in_url}/, :as => :catalog
  486.  +  # DEPRECATED
  487. -   match 'catalog(/:profile)', :controller => :catalog, :action => :index, :profile => /#{Noosfero.identifier_format}/, :as => :catalog
  488. ++  match 'catalog(/:profile)', :controller => :catalog, :action => :index, :profile => /#{Noosfero.identifier_format_in_url}/, :as => :catalog
  489.  
  490.     # invite
  491. -   match 'profile(/:profile)/invite/friends', :controller => 'invite', :action => 'invite_friends', :profile => /#{Noosfero.identifier_format}/
  492. -   match 'profile(/:profile)/invite/:action', :controller => 'invite', :profile => /#{Noosfero.identifier_format}/
  493.  -  match 'profile/:profile/invite/friends', :controller => 'invite', :action => 'invite_friends', :profile => /#{Noosfero.identifier_format_in_url}/
  494.  -  match 'profile/:profile/invite/:action', :controller => 'invite', :profile => /#{Noosfero.identifier_format_in_url}/
  495. ++  match 'profile(/:profile)/invite/friends', :controller => 'invite', :action => 'invite_friends', :profile => /#{Noosfero.identifier_format_in_url}/
  496. ++  match 'profile(/:profile)/invite/:action', :controller => 'invite', :profile => /#{Noosfero.identifier_format_in_url}/
  497.  
  498.     # feeds per tag
  499. -   match 'profile(/:profile)/tags/:id/feed', :controller => 'profile', :action =>'tag_feed', :id => /.+/, :profile => /#{Noosfero.identifier_format}/, :as => :tag_feed
  500.  -  match 'profile/:profile/tags/:id/feed', :controller => 'profile', :action =>'tag_feed', :id => /.+/, :profile => /#{Noosfero.identifier_format_in_url}/, :as => :tag_feed
  501. ++  match 'profile(/:profile)/tags/:id/feed', :controller => 'profile', :action =>'tag_feed', :id => /.+/, :profile => /#{Noosfero.identifier_format_in_url}/, :as => :tag_feed
  502.  
  503.     # profile tags
  504. -   match 'profile(/:profile)/tags/:id', :controller => 'profile', :action => 'content_tagged', :id => /.+/, :profile => /#{Noosfero.identifier_format}/
  505. -   match 'profile(/:profile)/tags(/:id)', :controller => 'profile', :action => 'tags', :profile => /#{Noosfero.identifier_format}/
  506.  -  match 'profile/:profile/tags/:id', :controller => 'profile', :action => 'content_tagged', :id => /.+/, :profile => /#{Noosfero.identifier_format_in_url}/
  507.  -  match 'profile/:profile/tags(/:id)', :controller => 'profile', :action => 'tags', :profile => /#{Noosfero.identifier_format_in_url}/
  508. ++  match 'profile(/:profile)/tags/:id', :controller => 'profile', :action => 'content_tagged', :id => /.+/, :profile => /#{Noosfero.identifier_format_in_url}/
  509. ++  match 'profile(/:profile)/tags(/:id)', :controller => 'profile', :action => 'tags', :profile => /#{Noosfero.identifier_format_in_url}/
  510.  
  511.     # profile search
  512. -   match 'profile(/:profile)/search', :controller => 'profile_search', :action => 'index', :profile => /#{Noosfero.identifier_format}/
  513.  -  match 'profile/:profile/search', :controller => 'profile_search', :action => 'index', :profile => /#{Noosfero.identifier_format_in_url}/
  514. ++  match 'profile(/:profile)/search', :controller => 'profile_search', :action => 'index', :profile => /#{Noosfero.identifier_format_in_url}/
  515.  
  516.     # comments
  517. -   match 'profile(/:profile)/comment/:action/:id', :controller => 'comment', :profile => /#{Noosfero.identifier_format}/
  518.  -  match 'profile/:profile/comment/:action/:id', :controller => 'comment', :profile => /#{Noosfero.identifier_format_in_url}/
  519. ++  match 'profile(/:profile)/comment/:action/:id', :controller => 'comment', :profile => /#{Noosfero.identifier_format_in_url}/
  520.  
  521.     # public profile information
  522. -   match 'profile/:profile(/:action(/:id))', :controller => 'profile', :action => 'index', :id => /[^\/]*/, :profile => /#{Noosfero.identifier_format}/, :as => :profile
  523. -   match 'profile/(/:action(/:id))', :controller => 'profile', :action => 'index', :id => /[^\/]*/, :profile => /#{Noosfero.identifier_format}/, :as => :profile
  524. +   match 'profile/:profile(/:action(/:id))', :controller => 'profile', :action => 'index', :id => /[^\/]*/, :profile => /#{Noosfero.identifier_format_in_url}/, :as => :profile
  525. ++  match 'profile/(/:action(/:id))', :controller => 'profile', :action => 'index', :id => /[^\/]*/, :profile => /#{Noosfero.identifier_format_in_url}/, :as => :profile
  526.  
  527.     # contact
  528. -   match 'contact(/:profile)/:action(/:id)', :controller => 'contact', :action => 'index', :id => /.*/, :profile => /#{Noosfero.identifier_format}/
  529.  -  match 'contact/:profile/:action(/:id)', :controller => 'contact', :action => 'index', :id => /.*/, :profile => /#{Noosfero.identifier_format_in_url}/
  530. ++  match 'contact(/:profile)/:action(/:id)', :controller => 'contact', :action => 'index', :id => /.*/, :profile => /#{Noosfero.identifier_format_in_url}/
  531.  
  532.     # map balloon
  533.     match 'map_balloon/:action/:id', :controller => 'map_balloon', :id => /.*/
  534. @@@ -112,8 -98,9 +112,8 @@@
  535.     ## Controllers that are profile-specific (for profile admins )
  536.     ######################################################
  537.     # profile customization - "My profile"
  538. -   match 'myprofile(/:profile)/:controller(/:action(/:id))', :controller => Noosfero.pattern_for_controllers_in_directory('my_profile'), :profile => /#{Noosfero.identifier_format}/, :as => :myprofile
  539. -   match 'myprofile(/:profile)', :controller => 'profile_editor', :action => 'index', :profile => /#{Noosfero.identifier_format}/
  540.  -  match 'myprofile/:profile', :controller => 'profile_editor', :action => 'index', :profile => /#{Noosfero.identifier_format_in_url}/
  541.  -  match 'myprofile/:profile/:controller(/:action(/:id))', :controller => Noosfero.pattern_for_controllers_in_directory('my_profile'), :profile => /#{Noosfero.identifier_format_in_url}/, :as => :myprofile
  542.  -
  543. ++  match 'myprofile(/:profile)/:controller(/:action(/:id))', :controller => Noosfero.pattern_for_controllers_in_directory('my_profile'), :profile => /#{Noosfero.identifier_format_in_url}/, :as => :myprofile
  544. ++  match 'myprofile(/:profile)', :controller => 'profile_editor', :action => 'index', :profile => /#{Noosfero.identifier_format_in_url}/
  545.  
  546.     ######################################################
  547.     ## Controllers that are used by environment admin
  548. diff --cc db/migrate/20140820173129_create_chat_messages.rb
  549. index 0000000,6193098..33623d6
  550. mode 000000,100644..100644
  551. --- a/db/migrate/20140820173129_create_chat_messages.rb
  552. +++ b/db/migrate/20140820173129_create_chat_messages.rb
  553. @@@ -1,0 -1,15 +1,18 @@@
  554. + class CreateChatMessages < ActiveRecord::Migration
  555. +   def up
  556. +     create_table :chat_messages do |t|
  557. +       t.integer :to_id
  558. +       t.integer :from_id
  559. +       t.string :body
  560. +
  561. +       t.timestamps
  562. +     end
  563. ++    add_index :chat_messages, :from_id
  564. ++    add_index :chat_messages, :to_id
  565. ++    add_index :chat_messages, :created_at
  566. +   end
  567. +
  568. +   def down
  569. +     drop_table :chat_messages
  570. +   end
  571. + end
  572. diff --cc db/schema.rb
  573. index 403fd6d,b2e1c73..e0ade14
  574. --- a/db/schema.rb
  575. +++ b/db/schema.rb
  576. @@@ -199,37 -203,7 +202,43 @@@ ActiveRecord::Schema.define(:version =
  577.       t.integer "position"
  578.     end
  579.  
  580.  -  add_index "boxes", ["owner_id", "owner_type"], :name => "index_boxes_on_owner_type_and_owner_id"
  581.  +  add_index "boxes", ["owner_type", "owner_id"], :name => "index_boxes_on_owner_type_and_owner_id"
  582.  +
  583. ++  create_table "br_nivel2", :id => false, :force => true do |t|
  584. ++    t.string "cidade"
  585. ++    t.float  "lat"
  586. ++    t.float  "lng"
  587. ++  end
  588. ++
  589.  +  create_table "bsc_plugin_contracts", :force => true do |t|
  590.  +    t.string   "client_name"
  591.  +    t.integer  "client_type"
  592.  +    t.integer  "business_type"
  593.  +    t.string   "state"
  594.  +    t.string   "city"
  595.  +    t.integer  "status",              :default => 0
  596.  +    t.integer  "number_of_producers", :default => 0
  597.  +    t.datetime "supply_start"
  598.  +    t.datetime "supply_end"
  599.  +    t.text     "annotations"
  600.  +    t.integer  "bsc_id"
  601.  +    t.datetime "created_at"
  602.  +    t.datetime "updated_at"
  603.  +  end
  604.  +
  605.  +  create_table "bsc_plugin_contracts_enterprises", :id => false, :force => true do |t|
  606.  +    t.integer "contract_id"
  607.  +    t.integer "enterprise_id"
  608.  +  end
  609.  +
  610.  +  create_table "bsc_plugin_sales", :force => true do |t|
  611.  +    t.integer  "product_id",  :null => false
  612.  +    t.integer  "contract_id", :null => false
  613.  +    t.integer  "quantity",    :null => false
  614.  +    t.decimal  "price"
  615.  +    t.datetime "created_at"
  616.  +    t.datetime "updated_at"
  617.  +  end
  618.  
  619.     create_table "categories", :force => true do |t|
  620.       t.string  "name"
  621. @@@ -274,50 -245,17 +283,54 @@@
  622.     end
  623.  
  624.     create_table "chat_messages", :force => true do |t|
  625. -     t.integer  "to_id"
  626.  -    t.integer  "from_id",    :null => false
  627.  -    t.integer  "to_id",      :null => false
  628.  +    t.integer  "from_id"
  629. -     t.string   "body"
  630. ++    t.integer  "to_id"
  631. +     t.text     "body"
  632.       t.datetime "created_at", :null => false
  633.       t.datetime "updated_at", :null => false
  634.     end
  635.  
  636. +   add_index "chat_messages", ["created_at"], :name => "index_chat_messages_on_created_at"
  637. +   add_index "chat_messages", ["from_id"], :name => "index_chat_messages_on_from_id"
  638. +   add_index "chat_messages", ["to_id"], :name => "index_chat_messages_on_to_id"
  639. +
  640.  +  create_table "comment_classification_plugin_comment_label_user", :force => true do |t|
  641.  +    t.integer  "profile_id"
  642.  +    t.integer  "comment_id"
  643.  +    t.integer  "label_id"
  644.  +    t.datetime "created_at"
  645.  +    t.datetime "updated_at"
  646.  +  end
  647.  +
  648.  +  create_table "comment_classification_plugin_comment_status_user", :force => true do |t|
  649.  +    t.integer  "profile_id"
  650.  +    t.integer  "comment_id"
  651.  +    t.integer  "status_id"
  652.  +    t.text     "reason"
  653.  +    t.datetime "created_at"
  654.  +    t.datetime "updated_at"
  655.  +  end
  656.  +
  657.  +  create_table "comment_classification_plugin_labels", :force => true do |t|
  658.  +    t.string   "name"
  659.  +    t.string   "color"
  660.  +    t.boolean  "enabled",    :default => true
  661.  +    t.integer  "owner_id"
  662.  +    t.string   "owner_type"
  663.  +    t.datetime "created_at"
  664.  +    t.datetime "updated_at"
  665.  +  end
  666.  +
  667.  +  create_table "comment_classification_plugin_statuses", :force => true do |t|
  668.  +    t.string   "name"
  669.  +    t.boolean  "enabled",       :default => true
  670.  +    t.boolean  "enable_reason", :default => true
  671.  +    t.integer  "owner_id"
  672.  +    t.string   "owner_type"
  673.  +    t.datetime "created_at"
  674.  +    t.datetime "updated_at"
  675.  +  end
  676.  +
  677.     create_table "comments", :force => true do |t|
  678.       t.string   "title"
  679.       t.text     "body"
  680. @@@ -332,7 -270,7 +345,8 @@@
  681.       t.string   "source_type"
  682.       t.string   "user_agent"
  683.       t.string   "referrer"
  684.  +    t.integer  "group_id"
  685. +     t.text     "settings"
  686.     end
  687.  
  688.     add_index "comments", ["source_id", "spam"], :name => "index_comments_on_source_id_and_spam"
  689. @@@ -468,14 -324,14 +482,15 @@@
  690.       t.text     "terms_of_use_acceptance_text"
  691.       t.datetime "created_at"
  692.       t.datetime "updated_at"
  693.  +    t.text     "send_email_plugin_allow_to"
  694. -     t.integer  "reports_lower_bound",          :default => 0,                   :null => false
  695. +     t.integer  "reports_lower_bound",          :default => 0,                      :null => false
  696.  -    t.string   "redirection_after_login",      :default => "keep_on_same_page"
  697.  -    t.text     "signup_welcome_text"
  698.       t.string   "languages"
  699.       t.string   "default_language"
  700.  +    t.string   "redirection_after_login",      :default => "keep_on_same_page"
  701.  +    t.text     "signup_welcome_text"
  702.       t.string   "noreply_email"
  703.       t.string   "redirection_after_signup",     :default => "keep_on_same_page"
  704. +     t.string   "date_format",                  :default => "month_name_with_year"
  705.     end
  706.  
  707.     create_table "external_feeds", :force => true do |t|
  708. @@@ -937,25 -529,23 +953,26 @@@
  709.       t.date     "birth_date"
  710.       t.integer  "preferred_domain_id"
  711.       t.datetime "updated_at"
  712.  -    t.boolean  "visible",                               :default => true
  713.  +    t.boolean  "visible",                 :default => true
  714.       t.integer  "image_id"
  715.  -    t.boolean  "validated",                             :default => true
  716.  +    t.integer  "bsc_id"
  717.  +    t.string   "company_name"
  718.  +    t.boolean  "validated",               :default => true
  719.       t.string   "cnpj"
  720.       t.string   "national_region_code"
  721.  -    t.boolean  "is_template",                           :default => false
  722.  +    t.boolean  "is_template",             :default => false
  723.       t.integer  "template_id"
  724.       t.string   "redirection_after_login"
  725.  -    t.integer  "friends_count",                         :default => 0,     :null => false
  726.  -    t.integer  "members_count",                         :default => 0,     :null => false
  727.  -    t.integer  "activities_count",                      :default => 0,     :null => false
  728.  +    t.integer  "friends_count",           :default => 0,     :null => false
  729.  +    t.integer  "members_count",           :default => 0,     :null => false
  730.  +    t.integer  "activities_count",        :default => 0,     :null => false
  731.       t.string   "personal_website"
  732.       t.string   "jabber_id"
  733.  +    t.string   "usp_id"
  734.       t.integer  "welcome_page_id"
  735.  -    t.boolean  "allow_members_to_invite",               :default => true
  736.  -    t.boolean  "invite_friends_only",                   :default => false
  737.  -    t.boolean  "secret",                                :default => false
  738.  +    t.boolean  "allow_members_to_invite", :default => true
  739.  +    t.boolean  "invite_friends_only",     :default => false
  740. ++    t.boolean  "secret",                  :default => false
  741.     end
  742.  
  743.     add_index "profiles", ["activities_count"], :name => "index_profiles_on_activities_count"
  744. @@@ -1010,15 -596,13 +1027,16 @@@
  745.       t.boolean "is_global"
  746.     end
  747.  
  748.  +  add_index "role_assignments", ["accessor_id", "accessor_type"], :name => "index_role_assignments_on_accessor_id_and_accessor_type"
  749.  +  add_index "role_assignments", ["resource_id", "resource_type"], :name => "index_role_assignments_on_resource_id_and_resource_type"
  750.  +
  751.     create_table "roles", :force => true do |t|
  752.       t.string  "name"
  753.  +    t.text    "permissions"
  754.       t.string  "key"
  755.       t.boolean "system",         :default => false
  756.  -    t.text    "permissions"
  757.       t.integer "environment_id"
  758. +     t.integer "profile_id"
  759.     end
  760.  
  761.     create_table "scraps", :force => true do |t|
  762. @@@ -1183,8 -691,9 +1201,10 @@@
  763.       t.datetime "created_at"
  764.       t.string   "target_type"
  765.       t.integer  "image_id"
  766.  +    t.integer  "bsc_id"
  767. -     t.boolean  "spam",                       :default => false
  768. +     t.boolean  "spam",                         :default => false
  769. +     t.integer  "responsible_id"
  770. +     t.integer  "closed_by_id"
  771.     end
  772.  
  773.     add_index "tasks", ["requestor_id"], :name => "index_tasks_on_requestor_id"
  774. diff --cc lib/noosfero.rb
  775. index 0fbe10b,b1ae492..23f3036
  776. --- a/lib/noosfero.rb
  777. +++ b/lib/noosfero.rb
  778. @@@ -54,9 -54,15 +54,15 @@@ module Noosfer
  779.     end
  780.  
  781.     def self.identifier_format
  782.  -    '[a-z0-9][a-z0-9~.]*([_\-][a-z0-9~.]+)*'
  783.  +    '[a-z0-9][a-z0-9~.]*([_\-][a-z0-9~.|:*]+)*'
  784.     end
  785.  
  786. +   # All valid identifiers, plus ~ meaning "the current user". See
  787. +   # ApplicationController#redirect_to_current_user
  788. +   def self.identifier_format_in_url
  789. +     "(#{identifier_format}|~)"
  790. +   end
  791. +
  792.     def self.default_hostname
  793.       Environment.table_exists? && Environment.default ? Environment.default.default_hostname : 'localhost'
  794.     end
  795. diff --cc lib/noosfero/plugin.rb
  796. index f410b71,4d33221..e810252
  797. --- a/lib/noosfero/plugin.rb
  798. +++ b/lib/noosfero/plugin.rb
  799. @@@ -10,6 -9,10 +10,10 @@@ class Noosfero::Plugi
  800.       self.context = context
  801.     end
  802.  
  803. +   def environment
  804.  -    context.environment if self.context
  805. ++    context.send :environment if self.context
  806. +   end
  807. +
  808.     class << self
  809.  
  810.       include Noosfero::Plugin::ParentMethods
  811. diff --cc lib/noosfero/plugin/hot_spot/definitions.rb
  812. index 81feb72,0000000..f20961a
  813. mode 100644,000000..100644
  814. --- a/lib/noosfero/plugin/hot_spot/definitions.rb
  815. +++ b/lib/noosfero/plugin/hot_spot/definitions.rb
  816. @@@ -1,529 -1,0 +1,549 @@@
  817.  +
  818.  +module Noosfero
  819.  +  class Plugin
  820.  +    module HotSpot
  821.  +      module Definitions
  822.  +
  823.  +        # -> Adds buttons to the control panel
  824.  +        # returns        = { :title => title, :icon => icon, :url => url }
  825.  +        #   title        = name that will be displayed.
  826.  +        #   icon         = css class name (for customized icons include them in a css file).
  827.  +        #   url          = url or route to which the button will redirect.
  828.  +        #   html_options = aditional html options.
  829.  +        def control_panel_buttons
  830.  +          nil
  831.  +        end
  832.  +
  833.  +        # -> Customize profile block design and behavior
  834.  +        # (overwrites profile_image_link function)
  835.  +        # returns = lambda block that creates html code.
  836.  +        def profile_image_link(profile, size, tag, extra_info)
  837.  +          nil
  838.  +        end
  839.  +
  840.  +        # -> Adds tabs to the profile
  841.  +        # returns   = { :title => title, :id => id, :content => content, :start => start }
  842.  +        #   title   = name that will be displayed.
  843.  +        #   id      = div id.
  844.  +        #   content = lambda block that creates html code.
  845.  +        #   start   = boolean that specifies if the tab must come before noosfero tabs (optional).
  846.  +        def profile_tabs
  847.  +          nil
  848.  +        end
  849.  +
  850.  +        # -> Adds new block types in profile
  851.  +        # returs = class implements Block
  852.  +        def profile_blocks(profile)
  853.  +          nil
  854.  +        end
  855.  +
  856.  +        # -> Adds plugin-specific content types to CMS
  857.  +        # returns  = [ContentClass1, ContentClass2, ...]
  858.  +        def content_types
  859.  +          nil
  860.  +        end
  861.  +
  862.  +        # -> Adds tabs to the products
  863.  +        # returns   = { :title => title, :id => id, :content => content }
  864.  +        #   title   = name that will be displayed.
  865.  +        #   id      = div id.
  866.  +        #   content = lambda block that creates html code.
  867.  +        def product_tabs product
  868.  +          nil
  869.  +        end
  870.  +
  871.  +        # -> Adds content to calalog item
  872.  +        # returns = lambda block that creates html code
  873.  +        def catalog_item_extras(item)
  874.  +          nil
  875.  +        end
  876.  +
  877.  +        # -> Allows to add content to the beginning of the catalog top bar
  878.  +        # returns = lambda block that creates array of html codes
  879.  +        def catalog_search_extras_begin
  880.  +          nil
  881.  +        end
  882.  +
  883.  +        # -> Allows to add content to the endof the catalog top bar
  884.  +        # returns = lambda block that creates array of html codes
  885.  +        def catalog_search_extras_end
  886.  +          nil
  887.  +        end
  888.  +
  889.  +        # -> Adds content to add to each autocompleted item on search
  890.  +        # returns = lambda block that creates html code
  891.  +        def catalog_autocomplete_item_extras product
  892.  +          nil
  893.  +        end
  894.  +
  895. ++        # -> Filters the types of organizations that are shown on manage organizations
  896. ++        # returns a scope filtered by the specified type
  897. ++        def filter_manage_organization_scope type
  898. ++          nil
  899. ++        end
  900. ++
  901. ++        # -> Add new options for manage organization filters
  902. ++        # returns an array of new options
  903. ++        # i.e [[_('Type'), 'type'], [_('Type2'), 'type2']]
  904. ++        def organization_types_filter_options
  905. ++          nil
  906. ++        end
  907. ++
  908.  +        # -> Adds content to profile editor info and settings
  909.  +        # returns = lambda block that creates html code or raw rhtml/html.erb
  910.  +        def profile_editor_extras
  911.  +          nil
  912.  +        end
  913.  +
  914.  +        # -> Adds content to catalog list item
  915.  +        # returns = lambda block that creates html code
  916.  +        def catalog_list_item_extras(item)
  917.  +          nil
  918.  +        end
  919.  +
  920.  +        # -> Adds content to products info
  921.  +        # returns = lambda block that creates html code
  922.  +        def product_info_extras(product)
  923.  +          nil
  924.  +        end
  925.  +
  926.  +        # -> Adds content to products on asset list
  927.  +        # returns = lambda block that creates html code
  928.  +        def asset_product_extras(product)
  929.  +          nil
  930.  +        end
  931.  +
  932.  +        # -> Adds a property to the product on asset products
  933.  +        # returns = {:name => name, :content => content}
  934.  +        #   name = Name of the property
  935.  +        #   content = lambda block that creates an html
  936.  +        def asset_product_properties(product)
  937.  +          nil
  938.  +        end
  939.  +
  940.  +        # -> Adds content to the beginning of the page
  941.  +        # returns = lambda block that creates html code or raw rhtml/html.erb
  942.  +        def body_beginning
  943.  +          nil
  944.  +        end
  945.  +
  946.  +        # -> Adds content to the ending of the page
  947.  +        # returns = lambda block that creates html code or raw rhtml/html.erb
  948.  +        def body_ending
  949.  +          nil
  950.  +        end
  951.  +
  952.  +        # -> Adds content to the ending of the page head
  953.  +        # returns = lambda block that creates html code or raw rhtml/html.erb
  954.  +        def head_ending
  955.  +          nil
  956.  +        end
  957.  +
  958.  +        # -> Adds plugins' javascript files to application
  959.  +        # returns = ['example1.js', 'javascripts/example2.js', 'example3.js']
  960.  +        def js_files
  961.  +          []
  962.  +        end
  963.  +
  964.  +        # -> Adds stuff in user data hash
  965.  +        # returns = { :some_data => some_value, :another_data => another_value }
  966.  +        def user_data_extras
  967.  +          {}
  968.  +        end
  969.  +
  970.  +        # -> Parse and possibly make changes of content (article, block, etc) during HTML rendering
  971.  +        # returns = content as string after parser and changes
  972.  +        def parse_content(html, source)
  973.  +          [html, source]
  974.  +        end
  975.  +
  976.  +        # -> Adds links to the admin panel
  977.  +        # returns = {:title => title, :url => url}
  978.  +        #   title = name that will be displayed in the link
  979.  +        #   url   = url or route to which the link will redirect to.
  980.  +        def admin_panel_links
  981.  +          nil
  982.  +        end
  983.  +
  984.  +        # -> Adds buttons to manage members page
  985.  +        # returns = { :title => title, :icon => icon, :url => url }
  986.  +        #   title = name that will be displayed.
  987.  +        #   icon  = css class name (for customized icons include them in a css file).
  988.  +        #   url   = url or route to which the button will redirect.
  989.  +        def manage_members_extra_buttons
  990.  +          nil
  991.  +        end
  992.  +
  993.  +        # This method will be called just before a comment is saved to the database.
  994.  +        #
  995.  +        # It can modify the comment in several ways. In special, a plugin can call
  996.  +        # reject! on the comment and that will cause the comment to not be saved.
  997.  +        #
  998.  +        # example:
  999.  +        #
  1000.  +        #   def filter_comment(comment)
  1001.  +        #     if user_not_logged_in
  1002.  +        #       comment.reject!
  1003.  +        #     end
  1004.  +        #   end
  1005.  +        #
  1006.  +        def filter_comment(comment)
  1007.  +        end
  1008.  +
  1009.  +        # Define custom logic to filter loaded comments.
  1010.  +        #
  1011.  +        # Example:
  1012.  +        #
  1013.  +        #   def unavailable_comments(scope)
  1014.  +        #     scope.without_spams
  1015.  +        #   end
  1016.  +        #
  1017.  +        def unavailable_comments(scope)
  1018.  +          scope
  1019.  +        end
  1020.  +
  1021.  +        # -> Allows plugins to check weather object is a spam
  1022.  +        def check_for_spam(object)
  1023.  +        end
  1024.  +
  1025.  +        # -> Allows plugins to know when an object is marked as a spam
  1026.  +        def marked_as_spam(object)
  1027.  +        end
  1028.  +
  1029.  +        # -> Allows plugins to know when an object is marked as a ham
  1030.  +        def marked_as_ham(object)
  1031.  +        end
  1032.  +
  1033.  +        # Adds extra actions for comments
  1034.  +        # returns = list of hashes or lambda block that creates a list of hashes
  1035.  +        # example:
  1036.  +        #
  1037.  +        #   def comment_actions(comment)
  1038.  +        #     [{:link => link_to_function(...)}]
  1039.  +        #   end
  1040.  +        #
  1041.  +        def comment_actions(comment)
  1042.  +          nil
  1043.  +        end
  1044.  +
  1045.  +        # This method is called when the user click on comment actions menu.
  1046.  +        # returns = list or lambda block that return ids of enabled menu items for comments
  1047.  +        # example:
  1048.  +        #
  1049.  +        #   def check_comment_actions(comment)
  1050.  +        #     ['#action1', '#action2']
  1051.  +        #   end
  1052.  +        #
  1053.  +        def check_comment_actions(comment)
  1054.  +          []
  1055.  +        end
  1056.  +
  1057. -         # -> Adds aditional actions to article
  1058. -         # returns = lambda block that creates html code
  1059. -         def article_toolbar_actions article
  1060. -           nil
  1061. ++        # -> Adds aditional action buttons to article
  1062. ++        # returns = { :title => title, :icon => icon, :url => url, :html_options => {} }
  1063. ++        #   title         = name that will be displayed.
  1064. ++        #   icon          = css class name (for customized icons include them in a css file).
  1065. ++        #   url           = url or route to which the button will redirect.
  1066. ++        #   html_options  = Html options for customization
  1067. ++        #
  1068. ++        # Multiple values could be passed as parameter.
  1069. ++        # returns = [{:title => title, :icon => icon}, {:title => title, :icon => icon}]
  1070. ++        def article_extra_toolbar_buttons(article)
  1071. ++          []
  1072.  +        end
  1073.  +
  1074.  +        # -> Adds aditional content to article
  1075.  +        # returns = lambda block that creates html code
  1076.  +        def article_extra_contents(article)
  1077.  +          nil
  1078.  +        end
  1079.  +
  1080.  +        # -> Adds adicional fields to a view
  1081.  +        # returns = proc block that creates html code
  1082.  +        def upload_files_extra_fields(article)
  1083.  +          nil
  1084.  +        end
  1085.  +
  1086.  +        # -> Adds fields to the signup form
  1087.  +        # returns = proc that creates html code
  1088.  +        def signup_extra_contents
  1089.  +          nil
  1090.  +        end
  1091.  +
  1092.  +        # -> Adds adicional content to profile info
  1093.  +        # returns = lambda block that creates html code
  1094.  +        def profile_info_extra_contents
  1095.  +          nil
  1096.  +        end
  1097.  +
  1098.  +        # -> Removes the invite friend button from the friends controller
  1099.  +        # returns = boolean
  1100.  +        def remove_invite_friends_button
  1101.  +          nil
  1102.  +        end
  1103.  +
  1104.  +        # -> Extends organization list of members
  1105.  +        # returns = An instance of ActiveRecord::NamedScope::Scope retrieved through
  1106.  +        # Person.members_of method.
  1107.  +        def organization_members(organization)
  1108.  +          nil
  1109.  +        end
  1110.  +
  1111.  +        # -> Extends person memberships list
  1112.  +        # returns = An instance of ActiveRecord::NamedScope::Scope retrived through
  1113.  +        # Person.memberships_of method.
  1114.  +        def person_memberships(person)
  1115.  +          nil
  1116.  +        end
  1117.  +
  1118.  +        # -> Extends person permission access
  1119.  +        # returns = boolean
  1120.  +        def has_permission?(person, permission, target)
  1121.  +          nil
  1122.  +        end
  1123.  +
  1124.  +        # -> Adds hidden_fields to the new community view
  1125.  +        # returns = {key => value}
  1126.  +        def new_community_hidden_fields
  1127.  +          nil
  1128.  +        end
  1129.  +
  1130.  +        # -> Adds hidden_fields to the enterprise registration view
  1131.  +        # returns = {key => value}
  1132.  +        def enterprise_registration_hidden_fields
  1133.  +          nil
  1134.  +        end
  1135.  +
  1136.  +        # -> Add an alternative authentication method.
  1137.  +        # Your plugin have to make the access control and return the logged user.
  1138.  +        # returns = User
  1139.  +        def alternative_authentication
  1140.  +          nil
  1141.  +        end
  1142.  +
  1143.  +        # -> Adds adicional link to make the user authentication
  1144.  +        # returns = lambda block that creates html code
  1145.  +        def alternative_authentication_link
  1146.  +          nil
  1147.  +        end
  1148.  +
  1149.  +        # -> Allow or not user registration
  1150.  +        # returns = boolean
  1151.  +        def allow_user_registration
  1152.  +          true
  1153.  +        end
  1154.  +
  1155.  +        # -> Allow or not password recovery by users
  1156.  +        # returns = boolean
  1157.  +        def allow_password_recovery
  1158.  +          true
  1159.  +        end
  1160.  +
  1161.  +        # -> Adds fields to the login form
  1162.  +        # returns = proc that creates html code
  1163.  +        def login_extra_contents
  1164.  +          nil
  1165.  +        end
  1166.  +
  1167.  +        # -> Adds adicional content to comment form
  1168.  +        # returns = lambda block that creates html code
  1169.  +        def comment_form_extra_contents(args)
  1170.  +          nil
  1171.  +        end
  1172.  +
  1173.  +        # -> Adds adicional content to article header
  1174.  +        # returns = lambda block that creates html code
  1175.  +        def article_header_extra_contents(article)
  1176.  +          nil
  1177.  +        end
  1178.  +
  1179.  +        # -> Adds adittional content to comment visualization
  1180.  +        # returns = lambda block that creates html code
  1181.  +        def comment_extra_contents(args)
  1182.  +          nil
  1183.  +        end
  1184.  +
  1185.  +        # This method is called when the user clicks to send a comment.
  1186.  +        # A plugin can add new content to comment form and this method can process the params sent to avoid creating field on core tables.
  1187.  +        # returns = params after processed by plugins
  1188.  +        # example:
  1189.  +        #
  1190.  +        #   def process_extra_comment_params(params)
  1191.  +        #     params.delete(:extra_field)
  1192.  +        #   end
  1193.  +        #
  1194.  +        def process_extra_comment_params(params)
  1195.  +          params
  1196.  +        end
  1197.  +
  1198.  +        # -> Auto complete search
  1199.  +        # returns = {:results => [a, b, c, ...], ...}
  1200.  +        # P.S.: The plugin might add other informations on the return hash for its
  1201.  +        # own use in specific views
  1202.  +        def autocomplete asset, scope, query, paginate_options={:page => 1}, options={:field => 'name'}
  1203.  +        end
  1204.  +
  1205.  +        # -> Specify order options for the search engine
  1206.  +        # returns = { select_options: [['Name', 'key'], ['Name2', 'key2']] }
  1207.  +        def search_order asset
  1208.  +          nil
  1209.  +        end
  1210.  +
  1211.  +        # -> Add column before search results
  1212.  +        # returns = lambda block that creates html code
  1213.  +        def search_pre_contents
  1214.  +          nil
  1215.  +        end
  1216.  +
  1217.  +        # -> Add content after search results
  1218.  +        # returns = lambda block that creates html code
  1219.  +        def search_post_contents
  1220.  +          nil
  1221.  +        end
  1222.  +
  1223.  +        # -> Finds objects by their contents
  1224.  +        # returns = {:results => [a, b, c, ...], ...}
  1225.  +        # P.S.: The plugin might add other informations on the return hash for its
  1226.  +        # own use in specific views
  1227.  +        def find_by_contents(asset, scope, query, paginate_options={}, options={})
  1228.  +          scope = scope.like_search(query, options) unless query.blank?
  1229.  +          scope = scope.send(options[:filter]) unless options[:filter].blank?
  1230.  +          {:results => scope.paginate(paginate_options)}
  1231.  +        end
  1232.  +
  1233.  +        # -> Suggests terms based on asset and query
  1234.  +        # returns = [a, b, c, ...]
  1235.  +        def find_suggestions(query, context, asset, options={:limit => 5})
  1236.  +          context.search_terms.
  1237.  +            where(:asset => asset).
  1238.  +            where("search_terms.term like ?", "%#{query}%").
  1239.  +            where('search_terms.score > 0').
  1240.  +            order('search_terms.score DESC').
  1241.  +            limit(options[:limit]).map(&:term)
  1242.  +        end
  1243.  +
  1244.  +        # -> Adds aditional fields for change_password
  1245.  +        # returns = [{:field => 'field1', :name => 'field 1 name', :model => 'person'}, {...}]
  1246.  +        def change_password_fields
  1247.  +          nil
  1248.  +        end
  1249.  +
  1250.  +        # -> Perform extra transactions related to profile in profile editor
  1251.  +        # returns = true in success or raise and exception if it could not update the data
  1252.  +        def profile_editor_transaction_extras
  1253.  +          nil
  1254.  +        end
  1255.  +
  1256.  +        # -> Return a list of hashs with the needed information to create optional fields
  1257.  +        # returns = a list of hashs as {:name => "string", :label => "string", :object_name => :key, :method => :key}
  1258.  +        def extra_optional_fields
  1259.  +          []
  1260.  +        end
  1261.  +
  1262.  +        # -> Adds css class to <html> tag
  1263.  +        # returns = ['class1', 'class2']
  1264.  +        def html_tag_classes
  1265.  +          nil
  1266.  +        end
  1267.  +
  1268.  +        # -> Adds additional blocks to profiles and environments.
  1269.  +        # Your plugin must implements a class method called 'extra_blocks'
  1270.  +        # that returns a hash with the following syntax.
  1271.  +        #    {
  1272.  +        #      'block_name' =>
  1273.  +        #        {
  1274.  +        #          :type => 'for which holder the block will be available',
  1275.  +        #          :position => 'where the block could be displayed'
  1276.  +        #        }
  1277.  +        #    }
  1278.  +        #
  1279.  +        # Where:
  1280.  +        #
  1281.  +        #   - block_name: Name of the new block added to the blocks list
  1282.  +        #   - type: Might have some of the values
  1283.  +        #      - 'environment' or Environment: If the block is available only for Environment models
  1284.  +        #      - 'community' or Community: If the block is available only for Community models
  1285.  +        #      - 'enterprise' or Enterprise: If the block is available only for Enterprise models
  1286.  +        #      - 'person' or Person: If the block is available only for Person models
  1287.  +        #      - nil: If no type parameter is passed the block will be available for all types
  1288.  +        #   - position: Is the layout position of the block. It should be:
  1289.  +        #      - '1' or 1: Area 1 of layout
  1290.  +        #      - '2' or 2: Area 2 of layout
  1291.  +        #      - '3' or 3: Area 3 of layout
  1292.  +        #      - nil: If no position parameter is passed the block will be available for all positions
  1293.  +        #
  1294.  +        #      OBS: Area 1 is where stay the main content of layout. Areas 2 and 3 are the sides of layout.
  1295.  +        #
  1296.  +        # examples:
  1297.  +        #
  1298.  +        #   def extra_blocks(params)
  1299.  +        #     {
  1300.  +        #       #Display 'CustomBlock1' only for 'Person' on position '1'
  1301.  +        #       CustomBlock1 => {:type => 'person', :position => '1' },
  1302.  +        #
  1303.  +        #       #Display 'CustomBlock2' only for 'Community' on position '2'
  1304.  +        #       CustomBlock2 => {:type => Community, :position => '2' },
  1305.  +        #
  1306.  +        #       #Display 'CustomBlock3' only for 'Enterprise' on position '3'
  1307.  +        #       CustomBlock3 => {:type => 'enterprise', :position => 3 },
  1308.  +        #
  1309.  +        #       #Display 'CustomBlock2' for 'Environment' and 'Person' on positions '1' and '3'
  1310.  +        #       CustomBlock4 => {:type => ['environment', Person], :position => ['1','3'] },
  1311.  +        #
  1312.  +        #       #Display 'CustomBlock5' for all types and all positions
  1313.  +        #       CustomBlock5 => {},
  1314.  +        #     }
  1315.  +        #   end
  1316.  +        #
  1317.  +        #   OBS: The default value is a empty hash.
  1318.  +        def extra_blocks
  1319.  +          {}
  1320.  +        end
  1321.  +
  1322.  +        def method_missing(method, *args, &block)
  1323.  +          # This is a generic hotspot for all controllers on Noosfero.
  1324.  +          # If any plugin wants to define filters to run on any controller, the name of
  1325.  +          # the hotspot must be in the following form: <underscored_controller_name>_filters.
  1326.  +          # Example: for ProfileController the hotspot is profile_controller_filters
  1327.  +          #
  1328.  +          # -> Adds a filter to a controller
  1329.  +          # returns = { :type => type,
  1330.  +          #             :method_name => method_name,
  1331.  +          #             :options => {:opt1 => opt1, :opt2 => opt2},
  1332.  +          #             :block => Proc or lambda block}
  1333.  +          #   type = 'before_filter' or 'after_filter'
  1334.  +          #   method_name = The name of the filter
  1335.  +          #   option = Filter options, like :only or :except
  1336.  +          #   block = Block that the filter will call
  1337.  +          if method.to_s =~ /^(.+)_controller_filters$/
  1338.  +            []
  1339.  +            # -> Removes the action button from the content
  1340.  +            # returns = boolean
  1341.  +          elsif method.to_s =~ /^content_remove_(#{content_actions.join('|')})$/
  1342.  +            nil
  1343.  +            # -> Expire the action button from the content
  1344.  +            # returns = string with reason of expiration
  1345.  +          elsif method.to_s =~ /^content_expire_(#{content_actions.join('|')})$/
  1346.  +            nil
  1347.  +          elsif self.context.respond_to? method, true
  1348.  +            self.context.send method, *args, &block
  1349.  +          else
  1350.  +            super
  1351.  +          end
  1352.  +        end
  1353.  +
  1354.  +        def respond_to_missing? method, include_private=true
  1355.  +          self.context.respond_to? method, include_private or super
  1356.  +        end
  1357.  +
  1358.  +        private
  1359.  +
  1360.  +        def content_actions
  1361.  +          #FIXME 'new' and 'upload' only works for content_remove. It should work for
  1362.  +          #content_expire too.
  1363.  +          %w[edit delete spread locale suggest home new upload undo]
  1364.  +        end
  1365.  +
  1366.  +      end
  1367.  +    end
  1368.  +  end
  1369.  +end
  1370. diff --cc plugins/bsc/lib/bsc_plugin.rb
  1371. index 17eca13,17eca13..367298a
  1372. --- a/plugins/bsc/lib/bsc_plugin.rb
  1373. +++ b/plugins/bsc/lib/bsc_plugin.rb
  1374. @@@ -43,7 -43,7 +43,7 @@@ class BscPlugin < Noosfero::Plugi
  1375.     end
  1376.  
  1377.     def profile_controller_filters
  1378. --    if profile
  1379. ++    if profile
  1380.         special_enterprise = profile.enterprise? && !profile.validated && profile.bsc
  1381.         is_member_of_any_bsc = is_member_of_any_bsc?(context.user)
  1382.         block = lambda {
  1383. @@@ -72,7 -72,7 +72,7 @@@
  1384.  
  1385.     def profile_editor_controller_filters
  1386.       if context.user
  1387. --      is_not_admin = !context.environment.admins.include?(context.user)
  1388. ++      is_not_admin = !environment.admins.include?(context.user)
  1389.         [{  :type => 'before_filter',
  1390.             :method_name => 'bsc_destroy_access',
  1391.             :options => {:only => :destroy_profile},
  1392. @@@ -124,7 -124,7 +124,7 @@@
  1393.     end
  1394.  
  1395.     def profile
  1396. --    context.environment.profiles.find_by_identifier(context.params[:profile])
  1397. ++    environment.profiles.find_by_identifier(context.params[:profile])
  1398.     end
  1399.  
  1400.   end
  1401. diff --cc plugins/classify_members/lib/classify_members_plugin.rb
  1402. index 6745b17,6745b17..a071545
  1403. --- a/plugins/classify_members/lib/classify_members_plugin.rb
  1404. +++ b/plugins/classify_members/lib/classify_members_plugin.rb
  1405. @@@ -46,7 -46,7 +46,7 @@@ class ClassifyMembersPlugin < Noosfero:
  1406.  
  1407.     def settings
  1408.       @settings ||= Noosfero::Plugin::Settings.new(
  1409. --      context.environment, ClassifyMembersPlugin
  1410. ++      environment, ClassifyMembersPlugin
  1411.       )
  1412.     end
  1413.  
  1414. diff --cc plugins/event/po/pt/event.po
  1415. index acf8575,c0a79f9..83839f3
  1416. --- a/plugins/event/po/pt/event.po
  1417. +++ b/plugins/event/po/pt/event.po
  1418. @@@ -5,9 -5,9 +5,9 @@@
  1419.   #
  1420.   msgid ""
  1421.   msgstr ""
  1422. - "Project-Id-Version: 1.1~rc4\n"
  1423. - "POT-Creation-Date: 2015-04-20 19:44-0300\n"
  1424. - "PO-Revision-Date: 2015-04-24 08:50-0300\n"
  1425. + "Project-Id-Version: 1.1-166-gaf47713\n"
  1426. + "POT-Creation-Date: 2015-06-01 17:26-0300\n"
  1427.  -"PO-Revision-Date: 2015-01-30 00:18-0000\n"
  1428. ++"PO-Revision-Date: 2015-06-20 20:08-0300\n"
  1429.   "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
  1430.   "Language-Team: LANGUAGE <LL@li.org>\n"
  1431.   "Language: \n"
  1432. @@@ -92,16 -98,10 +98,10 @@@ msgstr "Limite de dias para mostrar
  1433.   msgid "Only show events in this interval of days."
  1434.   msgstr "Mostar somente os eventos nesse intervalo de dias"
  1435.  
  1436. - #: plugins/event/views/event_plugin/event_block_item.html.erb:6
  1437. - msgid "Duration: 1 day"
  1438. - msgid_plural "Duration: %s days"
  1439. - msgstr[0] "Duração: 1 dia"
  1440. - msgstr[1] "Duração: %s dias"
  1441. -
  1442.  -#~ msgid "Started one day ago."
  1443.  -#~ msgid_plural "Started %d days ago."
  1444.  -#~ msgstr[0] "Iniciou a Um dia atrás."
  1445.  -#~ msgstr[1] "Iniciou a %d dias atrás."
  1446.  +msgid "Started one day ago."
  1447.  +msgid_plural "Started %d days ago."
  1448.  +msgstr[0] "Iniciou ontem."
  1449.  +msgstr[1] "Iniciou há %d dias atrás."
  1450.  
  1451.   #~ msgid "I happens today."
  1452.   #~ msgstr "Acontece hoje."
  1453. diff --cc plugins/google_cse/lib/google_cse_plugin.rb
  1454. index bc91aed,bc91aed..5956caf
  1455. --- a/plugins/google_cse/lib/google_cse_plugin.rb
  1456. +++ b/plugins/google_cse/lib/google_cse_plugin.rb
  1457. @@@ -9,7 -9,7 +9,7 @@@ class GoogleCsePlugin < Noosfero::Plugi
  1458.     end
  1459.  
  1460.     def google_id
  1461. --    context.environment.settings[:google_cse_id]
  1462. ++    environment.settings[:google_cse_id]
  1463.     end
  1464.  
  1465.     def self.results_url_path
  1466. diff --cc plugins/google_cse/views/search-box.html.erb
  1467. index 7e776ea,0000000..a56db3b
  1468. mode 100644,000000..100644
  1469. --- a/plugins/google_cse/views/search-box.html.erb
  1470. +++ b/plugins/google_cse/views/search-box.html.erb
  1471. @@@ -1,10 -1,0 +1,10 @@@
  1472.  +<script type="text/javascript">
  1473.  +  jQuery(function($) {
  1474.  +    $('<%= locals[:selector] %>')
  1475.  +      .attr({'class': "cse-search-box", 'action': "<%= GoogleCsePlugin.results_url_path %>"})
  1476. -       .append('<input type="hidden" name="cx" value="<%= locals[:plugin].google_id %>" /><input type="hidden" name="cof" value="FORID:10" /><input type="hidden" name="ie" value="UTF-8" /><input type="hidden" name="siteurl" value="<%= context.environment.default_hostname %>">')
  1477. ++      .append('<input type="hidden" name="cx" value="<%= locals[:plugin].google_id %>" /><input type="hidden" name="cof" value="FORID:10" /><input type="hidden" name="ie" value="UTF-8" /><input type="hidden" name="siteurl" value="<%= environment.default_hostname %>">')
  1478.  +      .children("input[name='query']")
  1479.  +        .attr('name', 'q')
  1480.  +        .attr('id', 'q');
  1481.  +  });
  1482.  +</script>
  1483. diff --cc plugins/ldap/lib/ldap_plugin.rb
  1484. index 4653e65,9dade30..dfdc39d
  1485. --- a/plugins/ldap/lib/ldap_plugin.rb
  1486. +++ b/plugins/ldap/lib/ldap_plugin.rb
  1487. @@@ -21,7 -42,7 +42,7 @@@ class LdapPlugin < Noosfero::Plugi
  1488.     def alternative_authentication
  1489.       login = context.params[:user][:login]
  1490.       password = context.params[:user][:password]
  1491. --    ldap = LdapAuthentication.new(context.environment.ldap_plugin_attributes)
  1492. ++    ldap = LdapAuthentication.new(environment.ldap_plugin_attributes)
  1493.  
  1494.       user = User.find_or_initialize_by_login(login)
  1495.  
  1496. @@@ -43,9 -64,14 +64,14 @@@
  1497.           user.activated_at = Time.now.utc
  1498.           user.activation_code = nil
  1499.  
  1500. --        ldap = LdapAuthentication.new(context.environment.ldap_plugin_attributes)
  1501. ++        ldap = LdapAuthentication.new(environment.ldap_plugin_attributes)
  1502.           begin
  1503. -           user = nil unless user.save
  1504. +           if user.save
  1505. +             user.activate
  1506. +             plugins.dispatch(:ldap_plugin_update_user, user, attrs)
  1507. +           else
  1508. +             user = nil
  1509. +           end
  1510.           rescue
  1511.             #User not saved
  1512.           end
  1513. diff --cc plugins/metadata/lib/ext/product.rb
  1514. index b1e18f2,11a7e69..a6ff72e
  1515. --- a/plugins/metadata/lib/ext/product.rb
  1516. +++ b/plugins/metadata/lib/ext/product.rb
  1517. @@@ -3,22 -3,14 +3,22 @@@ require_dependency 'product
  1518.   class Product
  1519.  
  1520.     metadata_spec namespace: :og, tags: {
  1521.  -    type: MetadataPlugin.og_types[:product] || :product,
  1522.  -    url: proc{ |p, plugin| plugin.og_url_for p.url },
  1523.  +    type: proc{ |p, plugin| plugin.context.params[:og_type] || MetadataPlugin.og_types[:product] || :product },
  1524.  +    url: proc do |p, plugin|
  1525.  +      url = p.url.merge! profile: p.profile.identifier, og_type: plugin.context.params[:og_type]
  1526.  +      plugin.og_url_for url
  1527.  +    end,
  1528.       gr_hascurrencyvalue: proc{ |p, plugin| p.price.to_f },
  1529.       gr_hascurrency: proc{ |p, plugin| p.environment.currency_unit },
  1530. -     title: proc{ |p, plugin| "#{p.name} - #{p.profile.name}" },
  1531. +     title: proc{ |p, plugin| "#{p.name} - #{p.profile.name}" if p },
  1532.       description: proc{ |p, plugin| ActionView::Base.full_sanitizer.sanitize p.description },
  1533.  
  1534.  -    image: proc{ |p, plugin| "#{p.environment.top_url}#{p.image.public_filename}" if p.image },
  1535.  +    image: proc do |p, plugin|
  1536.  +      img = "#{p.environment.top_url}#{p.image.public_filename}" if p.image
  1537.  +      img = "#{p.environment.top_url}#{p.profile.image.public_filename}" if img.blank? and p.profile.image
  1538.  +      img ||= MetadataPlugin.config[:open_graph][:environment_logo] rescue nil if img.blank?
  1539.  +      img
  1540.  +    end,
  1541.       'image:type' => proc{ |p, plugin| p.image.content_type if p.image },
  1542.       'image:height' => proc{ |p, plugin| p.image.height if p.image },
  1543.       'image:width' => proc{ |p, plugin| p.image.width if p.image },
  1544. diff --cc plugins/open_graph/lib/open_graph_plugin/stories.rb
  1545. index 1cb90a9,0000000..a5956ff
  1546. mode 100644,000000..100644
  1547. --- a/plugins/open_graph/lib/open_graph_plugin/stories.rb
  1548. +++ b/plugins/open_graph/lib/open_graph_plugin/stories.rb
  1549. @@@ -1,298 -1,0 +1,303 @@@
  1550.  +
  1551.  +class OpenGraphPlugin::Stories
  1552.  +
  1553.  +  class_attribute :publishers
  1554.  +  self.publishers = []
  1555.  +
  1556.  +  def self.register_publisher publisher
  1557.  +    self.publishers << publisher
  1558.  +  end
  1559.  +
  1560.  +  def self.publish record, stories
  1561.  +    actor = User.current.person rescue nil
  1562.  +    return unless actor
  1563.  +
  1564.  +    self.publishers.each do |publisher|
  1565.  +      publisher = publisher.delay unless Rails.env.development? or Rails.env.test?
  1566.  +      publisher.publish_stories record, actor, stories
  1567.  +    end
  1568.  +  end
  1569.  +
  1570.  +  Definitions = {
  1571.  +    # needed a patch on UploadedFile: def notifiable?; true; end
  1572.  +    add_a_document: {
  1573.  +      action_tracker_verb: :create_article,
  1574.  +      track_config: 'OpenGraphPlugin::ActivityTrackConfig',
  1575.  +      action: :add,
  1576.  +      object_type: :uploaded_file,
  1577.  +      models: :UploadedFile,
  1578.  +      on: :create,
  1579.  +      criteria: proc do |article, actor|
  1580.  +        article.is_a? UploadedFile
  1581.  +      end,
  1582.  +      publish_if: proc do |uploaded_file, actor|
  1583.  +        # done in add_an_image
  1584.  +        next false if uploaded_file.image?
  1585.  +        uploaded_file.published?
  1586.  +      end,
  1587.  +      object_data_url: proc do |uploaded_file, actor|
  1588.  +        uploaded_file.url.merge view: true
  1589.  +      end,
  1590.  +    },
  1591.  +    add_an_image: {
  1592.  +      # :upload_image verb can't be used as it uses the parent Gallery as target
  1593.  +      # hooked via open_graph_attach_stories
  1594.  +      action_tracker_verb: nil,
  1595.  +      track_config: 'OpenGraphPlugin::ActivityTrackConfig',
  1596.  +      action: :add,
  1597.  +      object_type: :gallery_image,
  1598.  +      models: :UploadedFile,
  1599.  +      on: :create,
  1600.  +      criteria: proc do |article, actor|
  1601.  +        article.is_a? UploadedFile
  1602.  +      end,
  1603.  +      publish_if: proc do |uploaded_file, actor|
  1604.  +        uploaded_file.image? and uploaded_file.parent.is_a? Gallery
  1605.  +      end,
  1606.  +      object_data_url: proc do |uploaded_file, actor|
  1607.  +        uploaded_file.url.merge view: true
  1608.  +      end,
  1609.  +    },
  1610.  +    create_an_article: {
  1611.  +      action_tracker_verb: :create_article,
  1612.  +      track_config: 'OpenGraphPlugin::ActivityTrackConfig',
  1613.  +      action: :create,
  1614.  +      object_type: :blog_post,
  1615.  +      models: :Article,
  1616.  +      on: :create,
  1617.  +      criteria: proc do |article, actor|
  1618.  +        article.parent.is_a? Blog
  1619.  +      end,
  1620.  +      publish_if: proc do |article, actor|
  1621.  +        article.published?
  1622.  +      end,
  1623.  +    },
  1624.  +    create_an_event: {
  1625.  +      action_tracker_verb: :create_article,
  1626.  +      track_config: 'OpenGraphPlugin::ActivityTrackConfig',
  1627.  +      action: :create,
  1628.  +      object_type: :event,
  1629.  +      models: :Event,
  1630.  +      on: :create,
  1631.  +      criteria: proc do |article, actor|
  1632.  +        article.is_a? Event
  1633.  +      end,
  1634.  +      publish_if: proc do |event, actor|
  1635.  +        event.published?
  1636.  +      end,
  1637.  +    },
  1638.  +    start_a_discussion: {
  1639.  +      action_tracker_verb: :create_article,
  1640.  +      track_config: 'OpenGraphPlugin::ActivityTrackConfig',
  1641.  +      action: :start,
  1642.  +      object_type: :forum,
  1643.  +      models: :Article,
  1644.  +      on: :create,
  1645.  +      criteria: proc do |article, actor|
  1646.  +        article.parent.is_a? Forum
  1647.  +      end,
  1648.  +      publish_if: proc do |article, actor|
  1649.  +        article.published?
  1650.  +      end,
  1651.  +      object_data_url: proc do |article, actor|
  1652.  +        article.url.merge og_type: "#{MetadataPlugin::og_types[:forum]}"
  1653.  +      end,
  1654.  +    },
  1655.  +
  1656.  +    # these a published as passive to give focus to the enterprise
  1657.  +=begin
  1658.  +    add_a_sse_product: {
  1659.  +      action_tracker_verb: :create_product,
  1660.  +      track_config: 'OpenGraphPlugin::ActivityTrackConfig',
  1661.  +      action: :announce_new,
  1662.  +      models: :Product,
  1663.  +      on: :create,
  1664.  +      object_type: :product,
  1665.  +      publish_if: proc do |product, actor|
  1666.  +        product.profile.public?
  1667.  +      end,
  1668.  +    },
  1669.  +    update_a_sse_product: {
  1670.  +      action_tracker_verb: :update_product,
  1671.  +      track_config: 'OpenGraphPlugin::ActivityTrackConfig',
  1672.  +      action: :announce_update,
  1673.  +      object_type: :product,
  1674.  +      models: :Product,
  1675.  +      on: :update,
  1676.  +      publish_if: proc do |product, actor|
  1677.  +        product.profile.public?
  1678.  +      end,
  1679.  +    },
  1680.  +=end
  1681.  +
  1682.  +    favorite_a_sse_initiative: {
  1683.  +      action_tracker_verb: :favorite_enterprise,
  1684.  +      track_config: 'OpenGraphPlugin::ActivityTrackConfig',
  1685.  +      action: :favorite,
  1686.  +      object_type: :favorite_enterprise,
  1687.  +      models: :FavoriteEnterprisePerson,
  1688.  +      on: :create,
  1689.  +      object_actor: proc do |favorite_enterprise_person|
  1690.  +        favorite_enterprise_person.person
  1691.  +      end,
  1692.  +      object_profile: proc do |favorite_enterprise_person|
  1693.  +        favorite_enterprise_person.enterprise
  1694.  +      end,
  1695.  +      object_data_url: proc do |favorite_enterprise_person, actor|
  1696.  +        self.og_profile_url favorite_enterprise_person.enterprise
  1697.  +      end,
  1698.  +    },
  1699.  +
  1700.  +=begin
  1701.  +    comment_a_discussion: {
  1702.  +      action_tracker_verb: nil,
  1703.  +      action: :comment,
  1704.  +      object_type: :forum,
  1705.  +      models: :Comment,
  1706.  +      on: :create,
  1707.  +      criteria: proc do |comment, actor|
  1708.  +        source, parent = comment.source, comment.source.parent
  1709.  +        source.is_a? Article and parent.is_a? Forum
  1710.  +      end,
  1711.  +      publish_if: proc do |comment, actor|
  1712.  +        comment.source.parent.published?
  1713.  +      end,
  1714.  +    },
  1715.  +    comment_an_article: {
  1716.  +      action_tracker_verb: nil,
  1717.  +      action: :comment,
  1718.  +      object_type: :blog_post,
  1719.  +      models: :Comment,
  1720.  +      on: :create,
  1721.  +      criteria: proc do |comment, actor|
  1722.  +        source, parent = comment.source, comment.source.parent
  1723.  +        source.is_a? Article and parent.is_a? Blog
  1724.  +      end,
  1725.  +      publish_if: proc do |comment, actor|
  1726.  +        comment.source.parent.published?
  1727.  +      end,
  1728.  +    },
  1729.  +=end
  1730.  +
  1731.  +    make_friendship_with: {
  1732.  +      action_tracker_verb: :new_friendship,
  1733.  +      track_config: 'OpenGraphPlugin::ActivityTrackConfig',
  1734.  +      action: :make_friendship,
  1735.  +      object_type: :friend,
  1736.  +      models: :Friendship,
  1737.  +      on: :create,
  1738.  +      custom_actor: proc do |friendship|
  1739.  +        friendship.person
  1740.  +      end,
  1741.  +      object_actor: proc do |friendship|
  1742.  +        friendship.person
  1743.  +      end,
  1744.  +      object_profile: proc do |friendship|
  1745.  +        friendship.friend
  1746.  +      end,
  1747.  +      object_data_url: proc do |friendship, actor|
  1748.  +        self.og_profile_url friendship.friend
  1749.  +      end,
  1750.  +    },
  1751.  +
  1752.  +    # PASSIVE STORIES
  1753.  +    announce_news_from_a_sse_initiative: {
  1754.  +      action_tracker_verb: :create_article,
  1755.  +      track_config: 'OpenGraphPlugin::EnterpriseTrackConfig',
  1756.  +      action: :announce_news,
  1757.  +      object_type: :enterprise,
  1758.  +      passive: true,
  1759.  +      models: :Article,
  1760.  +      on: :create,
  1761.  +      criteria: proc do |article, actor|
  1762.  +        article.profile.enterprise?
  1763.  +      end,
  1764.  +      publish_if: proc do |article, actor|
  1765.  +        article.published?
  1766.  +      end,
  1767.  +    },
  1768. ++    # this does not work with the current interface as the product
  1769. ++    # is created empty and then have a lot of updates
  1770. ++=begin
  1771.  +    announce_a_new_sse_product: {
  1772.  +      action_tracker_verb: :create_product,
  1773.  +      track_config: 'OpenGraphPlugin::EnterpriseTrackConfig',
  1774.  +      action: :announce_new,
  1775.  +      object_type: :product,
  1776.  +      passive: true,
  1777.  +      models: :Product,
  1778.  +      on: :create,
  1779.  +      criteria: proc do |product, actor|
  1780.  +        product.profile.enterprise?
  1781.  +      end,
  1782.  +    },
  1783. ++=end
  1784.  +    announce_an_update_of_sse_product: {
  1785.  +      action_tracker_verb: :update_product,
  1786.  +      track_config: 'OpenGraphPlugin::EnterpriseTrackConfig',
  1787.  +      action: :announce_update,
  1788.  +      object_type: :product,
  1789.  +      passive: true,
  1790.  +      models: :Product,
  1791.  +      on: :update,
  1792.  +      criteria: proc do |product, actor|
  1793. -         product.profile.enterprise?
  1794. ++        # only post from enterprises and products with images
  1795. ++        product.profile.enterprise? and product.image.present?
  1796.  +      end,
  1797.  +    },
  1798.  +
  1799.  +    announce_news_from_a_community: {
  1800.  +      action_tracker_verb: :create_article,
  1801.  +      track_config: 'OpenGraphPlugin::CommunityTrackConfig',
  1802.  +      action: :announce_news,
  1803.  +      object_type: :community,
  1804.  +      passive: true,
  1805.  +      models: :Article,
  1806.  +      on: :create,
  1807.  +      criteria: proc do |article, actor|
  1808.  +        article.profile.community?
  1809.  +      end,
  1810.  +      publish_if: proc do |article, actor|
  1811.  +        article.published?
  1812.  +      end,
  1813.  +    },
  1814.  +
  1815.  +  }
  1816.  +
  1817.  +  ValidObjectList = Definitions.map{ |story, data| data[:object_type] }.uniq
  1818.  +  ValidActionList = Definitions.map{ |story, data| data[:action] }.uniq
  1819.  +
  1820.  +  # TODO make this verification work
  1821.  +  #raise "Each active story must use a unique object_type for configuration to work" if ValidObjectList.size < Definitions.size
  1822.  +
  1823.  +  DefaultActions = ValidActionList.inject({}){ |h, a| h[a] = a; h }
  1824.  +  DefaultObjects = ValidObjectList.inject({}){ |h, o| h[o] = o; h }
  1825.  +
  1826.  +  TrackerStories = {}; Definitions.each do |story, data|
  1827.  +    Array(data[:action_tracker_verb]).each do |verb|
  1828.  +      next unless verb
  1829.  +      TrackerStories[verb] ||= []
  1830.  +      TrackerStories[verb] << story
  1831.  +    end
  1832.  +  end
  1833.  +
  1834.  +  TrackConfigStories = {}; Definitions.each do |story, data|
  1835.  +    Array(data[:track_config]).each do |track_config|
  1836.  +      next unless track_config
  1837.  +      TrackConfigStories[track_config] ||= []
  1838.  +      TrackConfigStories[track_config] << [story, data]
  1839.  +    end
  1840.  +  end
  1841.  +
  1842.  +  ModelStories = {}; Definitions.each do |story, data|
  1843.  +    Array(data[:models]).each do |model|
  1844.  +      ModelStories[model] ||= {}
  1845.  +      Array(data[:on]).each do |on|
  1846.  +        ModelStories[model][on] ||= []
  1847.  +        ModelStories[model][on] << story
  1848.  +      end
  1849.  +    end
  1850.  +  end
  1851.  +
  1852.  +end
  1853.  +
  1854. diff --cc plugins/piwik/lib/piwik_plugin.rb
  1855. index a7c3500,a7c3500..f0e162f
  1856. --- a/plugins/piwik/lib/piwik_plugin.rb
  1857. +++ b/plugins/piwik/lib/piwik_plugin.rb
  1858. @@@ -14,8 -14,8 +14,8 @@@ class PiwikPlugin < Noosfero::Plugi
  1859.     end
  1860.  
  1861.     def body_ending
  1862. --    domain = context.environment.piwik_domain
  1863. --    site_id = context.environment.piwik_site_id
  1864. ++    domain = environment.piwik_domain
  1865. ++    site_id = environment.piwik_site_id
  1866.       unless domain.blank? || site_id.blank?
  1867.         expanded_template('tracking-code.rhtml',{:domain => domain, :site_id => site_id})
  1868.       end
  1869. diff --cc plugins/require_auth_to_comment/lib/require_auth_to_comment_plugin.rb
  1870. index 68d9443,8d8dbc3..0c37177
  1871. --- a/plugins/require_auth_to_comment/lib/require_auth_to_comment_plugin.rb
  1872. +++ b/plugins/require_auth_to_comment/lib/require_auth_to_comment_plugin.rb
  1873. @@@ -23,7 -21,16 +23,16 @@@ class RequireAuthToCommentPlugin < Noos
  1874.     end
  1875.  
  1876.     def stylesheet?
  1877. -     true
  1878. +     !display_login_popup?
  1879. +   end
  1880. +
  1881. +   def display_login_popup?
  1882.  -    settings = Noosfero::Plugin::Settings.new(context.environment, self.class)
  1883. ++    settings = Noosfero::Plugin::Settings.new(environment, self.class)
  1884. +     settings.require_type == 'display_login_popup'
  1885. +   end
  1886. +
  1887. +   def self.require_type_default_setting
  1888. +     'hide_button'
  1889.     end
  1890.  
  1891.     def js_files
  1892. diff --cc plugins/shopping_cart/po/pt/shopping_cart.po
  1893. index fd98eeb,109b9e7..b67eea7
  1894. --- a/plugins/shopping_cart/po/pt/shopping_cart.po
  1895. +++ b/plugins/shopping_cart/po/pt/shopping_cart.po
  1896. @@@ -11,12 -11,12 +11,12 @@@
  1897.   #
  1898.   msgid ""
  1899.   msgstr ""
  1900. - "Project-Id-Version: 1.0-690-gcb6e853\n"
  1901. - "POT-Creation-Date: 2015-03-05 12:09-0300\n"
  1902. - "PO-Revision-Date: 2015-06-12 11:29-0300\n"
  1903. + "Project-Id-Version: 1.1-166-gaf47713\n"
  1904. + "POT-Creation-Date: 2015-06-01 17:26-0300\n"
  1905.  -"PO-Revision-Date: 2015-02-23 11:36+0200\n"
  1906. ++"PO-Revision-Date: 2015-06-20 20:13-0300\n"
  1907.   "Last-Translator: Michal Čihař <michal@cihar.com>\n"
  1908. - "Language-Team: Portuguese <https://hosted.weblate.org/projects/noosfero"
  1909. - "/plugin-shopping-cart/pt/>\n"
  1910. + "Language-Team: Portuguese <https://hosted.weblate.org/projects/noosfero/"
  1911. + "plugin-shopping-cart/pt/>\n"
  1912.   "Language: pt\n"
  1913.   "MIME-Version: 1.0\n"
  1914.   "Content-Type: text/plain; charset=UTF-8\n"
  1915. diff --cc plugins/sniffer/po/pt/sniffer.po
  1916. index d1ade72,ef50cfc..25047bf
  1917. --- a/plugins/sniffer/po/pt/sniffer.po
  1918. +++ b/plugins/sniffer/po/pt/sniffer.po
  1919. @@@ -3,12 -3,12 +3,11 @@@
  1920.   # This file is distributed under the same license as the PACKAGE package.
  1921.   # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
  1922.   #
  1923. --#, fuzzy
  1924.   msgid ""
  1925.   msgstr ""
  1926. - "Project-Id-Version: 1.1~rc1-4309-g8df8054\n"
  1927. - "POT-Creation-Date: 2015-05-07 12:03-0300\n"
  1928. - "PO-Revision-Date: 2015-05-07 11:11-0300\n"
  1929. + "Project-Id-Version: 1.1-166-gaf47713\n"
  1930. + "POT-Creation-Date: 2015-06-01 17:26-0300\n"
  1931.  -"PO-Revision-Date: 2015-05-07 11:11-0300\n"
  1932. ++"PO-Revision-Date: 2015-06-20 20:19-0300\n"
  1933.   "Last-Translator: daniel tygel <dtygel@eita.org.br>\n"
  1934.   "Language-Team: pt_BR <dtygel@eita.org.br>\n"
  1935.   "Language: \n"
  1936. @@@ -120,8 -88,8 +87,8 @@@ msgid "
  1937.   "interests from our list."
  1938.   msgstr ""
  1939.   "Selecione aqui as categorias de produtos e serviços que você tem interesse "
  1940. - "em comprar. Com isso, empreendimentos saberão suas necessidades e poderão te fazer ofertas."
  1941. - "Digite e escolha quais são seus interesses."
  1942. + "em comprar. Com isso, empreendimentos saberão suas necessidades e poderão te "
  1943.  -"fazer ofertas.Digite e escolha quais são seus interesses."
  1944. ++"fazer ofertas. Digite e escolha quais são seus interesses."
  1945.  
  1946.   #: plugins/sniffer/views/sniffer_plugin_myprofile/edit.html.erb:12
  1947.   msgid "Type in a keyword"
  1948. @@@ -131,18 -99,59 +98,60 @@@ msgstr "Escreva uma palavra chave
  1949.   msgid "Save"
  1950.   msgstr "Salvar"
  1951.  
  1952. - #: plugins/sniffer/views/blocks/sniffer_plugin/interests_block.html.erb:12
  1953. - msgid "Edit %{inputs} and %{interests}"
  1954. - msgstr "Editar %{inputs} e %{interests}"
  1955. + #: plugins/sniffer/views/sniffer_plugin_myprofile/edit.html.erb:18
  1956. + #: plugins/sniffer/views/sniffer_plugin_myprofile/search.html.erb:27
  1957. + msgid "Back to control panel"
  1958. + msgstr "Voltar ao painel de controle"
  1959.  
  1960. - #: plugins/sniffer/views/blocks/sniffer_plugin/interests_block.html.erb:13
  1961. - msgid "products' inputs"
  1962. - msgstr "Insumos de produtos"
  1963. + #: plugins/sniffer/views/sniffer_plugin_myprofile/search.html.erb:11
  1964. + msgid "Up to %s km from you. %s result(s) found."
  1965. + msgstr ""
  1966.  
  1967. - #: plugins/sniffer/views/blocks/sniffer_plugin/interests_block.html.erb:14
  1968. - msgid "declared interests"
  1969. - msgstr "interesses declarados"
  1970. + #: plugins/sniffer/views/sniffer_plugin_myprofile/search.html.erb:22
  1971. + msgid "Legend"
  1972. + msgstr "Legenda"
  1973. +
  1974. + #: plugins/sniffer/views/sniffer_plugin_myprofile/search.html.erb:23
  1975. + msgid "your enterprise"
  1976. + msgstr "seu empreendimento"
  1977. +
  1978. + #: plugins/sniffer/views/sniffer_plugin_myprofile/search.html.erb:24
  1979. + msgid "suppliers"
  1980. + msgstr "fornecedores"
  1981. +
  1982. + #: plugins/sniffer/views/sniffer_plugin_myprofile/search.html.erb:25
  1983. + msgid "consumers"
  1984. + msgstr "consumidores"
  1985. +
  1986. + #: plugins/sniffer/views/sniffer_plugin_myprofile/search.html.erb:26
  1987. + msgid "both"
  1988. + msgstr "ambos"
  1989. +
  1990. + #: plugins/sniffer/views/sniffer_plugin_myprofile/_product_search_box.html.erb:9
  1991. + msgid "Suppliers"
  1992. + msgstr "Fornecedores"
  1993. +
  1994. + #: plugins/sniffer/views/sniffer_plugin_myprofile/_product_search_box.html.erb:14
  1995. + msgid "Consumers"
  1996. + msgstr "Consumidores"
  1997. +
  1998. + #: plugins/sniffer/views/sniffer_plugin_myprofile/_product_search_box.html.erb:19
  1999. + msgid "Both"
  2000. + msgstr ""
  2001. +
  2002. + #: plugins/sniffer/views/sniffer_plugin_myprofile/_product_search_box.html.erb:25
  2003. + msgid "look for products..."
  2004. + msgstr "buscar por produtos..."
  2005. +
  2006. + #: plugins/sniffer/views/sniffer_plugin_myprofile/_product_search_box.html.erb:54
  2007. + msgid "Maximum distance:"
  2008. + msgstr "Distância máxima:"
  2009. +
  2010. + #: plugins/sniffer/views/sniffer_plugin_myprofile/map_balloon.html.erb:12
  2011. + msgid "Can supply"
  2012. + msgstr "Fornece"
  2013. +
  2014. + #: plugins/sniffer/views/sniffer_plugin_myprofile/map_balloon.html.erb:22
  2015. + msgid "May consum"
  2016. + msgstr "Consome"
  2017.  +
  2018. - #: plugins/sniffer/views/blocks/sniffer_plugin/interests_block.html.erb:23
  2019. - msgid "%{interest} from %{profile}"
  2020. - msgstr "%{interest} de %{profile}"
  2021. diff --cc plugins/solr/lib/solr_plugin/base.rb
  2022. index cbb17ff,0000000..6ac50de
  2023. mode 100644,000000..100644
  2024. --- a/plugins/solr/lib/solr_plugin/base.rb
  2025. +++ b/plugins/solr/lib/solr_plugin/base.rb
  2026. @@@ -1,197 -1,0 +1,199 @@@
  2027.  +# FIXME: module not being loaded
  2028.  +require 'solr_plugin'
  2029.  +
  2030.  +class SolrPlugin::Base < Noosfero::Plugin
  2031.  +
  2032.  +  def stylesheet?
  2033.  +    true
  2034.  +  end
  2035.  +
  2036.  +  def js_files
  2037.  +    ['solr'].map{ |j| "javascripts/#{j}" }
  2038.  +  end
  2039.  +
  2040.  +  def catalog_find_by_contents asset, scope, query, paginate_options={}, options={}
  2041.  +      klass = Product
  2042.  +
  2043.  +      # Search for products -> considers the query and the filters:
  2044.  +    params[:facet] = {}
  2045.  +    params[:facet][:solr_plugin_f_category] = params[:category] if params[:category].present?
  2046.  +    params[:facet][:solr_plugin_f_qualifier] = params[:qualifier] if params[:qualifier].present?
  2047.  +    solr_options = build_solr_options asset, klass, scope, nil
  2048.  +    solr_options[:all_facets] = false
  2049.  +
  2050.  +    order = params[:order]
  2051.  +    order = if order.blank? then :relevance else order.to_sym end
  2052.  +    if sort = SortOptions[:catalog][order] rescue nil
  2053.  +      solr_options.merge! (if query.blank? and sort[:empty_solr_opts] then sort[:empty_solr_opts] else sort[:solr_opts] end)
  2054.  +    end
  2055.  +    result = scope.find_by_contents query, paginate_options, solr_options
  2056.  +
  2057.  +    # Preparing the filters -> they must always contain all filters for the specific query:
  2058.  +    solr_options = build_solr_options asset, klass, scope, nil, ignore_filters: true
  2059.  +    solr_options[:all_facets] = false
  2060.  +    query = "" if result[:results].total_entries == 0
  2061.  +    result_facets = scope.find_by_contents query, paginate_options, solr_options
  2062.  +    facets = result_facets[:facets]['facet_fields'] || {}
  2063.  +
  2064.  +    result[:categories] = facets['solr_plugin_f_category_facet'].to_a.map{ |name,count| ["#{name} (#{count})", name] }
  2065.  +    result[:categories].sort!{ |a,b| a[0] <=> b[0] }
  2066.  +    result[:qualifiers] = facets['solr_plugin_f_qualifier_facet'].to_a
  2067.  +    result[:qualifiers] = Product.solr_plugin_f_qualifier_proc nil, result[:qualifiers]
  2068.  +    result[:qualifiers].map!{ |id, name, count| ["#{name} (#{count})", id] }
  2069.  +    result[:qualifiers].sort!{ |a,b| a[0] <=> b[0] }
  2070.  +
  2071.  +    result
  2072.  +  end
  2073.  +
  2074.  +  def find_by_contents asset, scope, query, paginate_options={}, options={}
  2075.  +      # The query in the catalog top bar is too specific and therefore must be treated differently
  2076.  +    return catalog_find_by_contents asset, scope, query, paginate_options, options if asset == :catalog
  2077.  +
  2078.  +    category = options.delete :category
  2079.  +    filter = options.delete(:filter).to_s.to_sym
  2080.  +      klass = asset_class asset
  2081.  +
  2082.  +      solr_options = build_solr_options asset, klass, scope, category
  2083.  +    solr_options.merge! sort_options asset, klass, filter
  2084.  +    solr_options.merge! options
  2085. ++    # We don't yet use the option to filter by template
  2086. ++    solr_options.delete :template_id
  2087.  +
  2088.  +    scope.find_by_contents query, paginate_options, solr_options
  2089.  +  rescue Exception => e
  2090.  +    # solr seaches depends on a constant translation of named scopes SQL's into solr filtered fields
  2091.  +    # so while we can't keep up it core changes, report the error and use default like search
  2092.  +    if Rails.env.production?
  2093.  +      ExceptionNotifier.notify_exception e,
  2094.  +        env: context.request.env, data: {message: "Solr search failed"}
  2095.  +      super
  2096.  +    else
  2097.  +      raise
  2098.  +    end
  2099.  +  end
  2100.  +
  2101.  +  def autocomplete asset, scope, query, paginate_options={}, options={}
  2102.  +    solr_options = {}
  2103.  +    solr_options.merge! paginate_options
  2104.  +
  2105.  +    case asset
  2106.  +    when :catalog
  2107.  +      klass = Product
  2108.  +      solr_options[:query_fields] = %w[solr_plugin_ac_name^100 solr_plugin_ac_category^90 solr_plugin_ac_supplier^80]
  2109.  +      solr_options[:highlight] = {fields: 'name'}
  2110.  +      solr_options[:filter_queries] = scopes_to_solr_options scope, klass, options
  2111.  +    end
  2112.  +    solr_options[:default_field] = 'ngramText'
  2113.  +
  2114.  +    result = {results: scope.find_by_solr(query, solr_options).results}
  2115.  +    result
  2116.  +  end
  2117.  +
  2118.  +  def search_order asset
  2119.  +    case asset
  2120.  +    when :catalog
  2121.  +      {
  2122.  +        select_options: SortOptions[:catalog].map do |key, options|
  2123.  +          option = options[:option]
  2124.  +          [_(option[0]), option[1]]
  2125.  +        end,
  2126.  +      }
  2127.  +    end
  2128.  +  end
  2129.  +
  2130.  +  def search_pre_contents
  2131.  +    lambda do
  2132.  +      render 'solr_plugin/search/search_pre_contents'
  2133.  +    end
  2134.  +  end
  2135.  +
  2136.  +  def search_post_contents
  2137.  +    lambda do
  2138.  +      render 'solr_plugin/search/search_post_contents'
  2139.  +    end
  2140.  +  end
  2141.  +
  2142.  +  protected
  2143.  +
  2144.  +  include SolrPlugin::SearchHelper
  2145.  +
  2146.  +  def build_solr_options asset, klass, scope, category, options = {}
  2147.  +    solr_options = {}
  2148.  +
  2149.  +    selected_facets = if options[:ignore_filters] then {} else params[:facet] end
  2150.  +    if klass.respond_to? :facets
  2151.  +      solr_options.merge! klass.facets_find_options selected_facets
  2152.  +      solr_options[:all_facets] = true
  2153.  +    end
  2154.  +
  2155.  +    solr_options[:filter_queries] ||= []
  2156.  +    solr_options[:filter_queries] += solr_filters_queries asset, environment
  2157.  +    solr_options[:filter_queries] << klass.facet_category_query.call(category) if category
  2158.  +    solr_options[:filter_queries] += scopes_to_solr_options scope, klass, options
  2159.  +
  2160.  +    solr_options[:boost_functions] ||= []
  2161.  +    params[:order_by] = nil if params[:order_by] == 'none'
  2162.  +    if params[:order_by]
  2163.  +      order = SortOptions[asset][params[:order_by].to_sym]
  2164.  +      raise "Unknown order by" if order.nil?
  2165.  +      order[:solr_opts].each do |opt, value|
  2166.  +        solr_options[opt] = value.is_a?(Proc) ? instance_eval(&value) : value
  2167.  +      end
  2168.  +    end
  2169.  +
  2170.  +    solr_options
  2171.  +  end
  2172.  +
  2173.  +  def scopes_to_solr_options scope, klass = nil, options = {}
  2174.  +    filter_queries = []
  2175.  +    klass ||= scope.base_class
  2176.  +    solr_fields = klass.configuration[:solr_fields].keys rescue []
  2177.  +    scopes_applied = scope.scopes_applied.dup rescue [] #rescue association and class direct filtering
  2178.  +
  2179.  +    scope.scope_attributes.each do |attr, value|
  2180.  +      next if attr == 'type'
  2181.  +      raise "Non-indexed attribute '#{attr}' speficied in scope_attributes" unless solr_fields.include? attr.to_sym
  2182.  +
  2183.  +      # if the filter is present here, then prefer it
  2184.  +      scopes_applied.reject!{ |name| name == attr.to_sym }
  2185.  +
  2186.  +      filter_queries << "#{attr}:#{value}"
  2187.  +    end
  2188.  +
  2189.  +    scopes_applied.each do |name|
  2190.  +      #next if name.to_s == options[:filter].to_s
  2191.  +
  2192.  +      has_value = name === Hash
  2193.  +      if has_value
  2194.  +        name, args = name.keys.first, name.values.first
  2195.  +        value = args.first
  2196.  +      end
  2197.  +
  2198.  +      related_field = nil
  2199.  +      related_field = name if solr_fields.include? name
  2200.  +      related_field = "solr_plugin_#{name}" if solr_fields.include? :"solr_plugin_#{name}"
  2201.  +
  2202.  +      if has_value
  2203.  +        if related_field
  2204.  +          filter_queries << "#{related_field}:#{value}"
  2205.  +        else
  2206.  +          filter_queries << klass.send("solr_filter_#{name}", *args)
  2207.  +        end
  2208.  +      else
  2209.  +        raise "Undeclared solr field for scope #{name}" if related_field.nil?
  2210.  +        if related_field
  2211.  +          filter_queries << "#{related_field}:true"
  2212.  +        end
  2213.  +      end
  2214.  +    end
  2215.  +
  2216.  +    filter_queries
  2217.  +  end
  2218.  +
  2219.  +  def sort_options asset, klass, filter
  2220.  +    options = SolrPlugin::SearchHelper::SortOptions[asset]
  2221.  +    options[filter][:solr_opts] || {} rescue {}
  2222.  +  end
  2223.  +
  2224.  +end
  2225.  +
  2226. diff --cc plugins/solr/po/pt/solr.po
  2227. index 98768b5,688adc2..551143a
  2228. --- a/plugins/solr/po/pt/solr.po
  2229. +++ b/plugins/solr/po/pt/solr.po
  2230. @@@ -11,12 -11,12 +11,12 @@@
  2231.   #
  2232.   msgid ""
  2233.   msgstr ""
  2234. - "Project-Id-Version: 1.0-690-gcb6e853\n"
  2235. - "POT-Creation-Date: 2015-03-05 12:10-0300\n"
  2236. - "PO-Revision-Date: 2015-06-13 09:54-0300\n"
  2237. + "Project-Id-Version: 1.1-166-gaf47713\n"
  2238. + "POT-Creation-Date: 2015-06-01 17:26-0300\n"
  2239.  -"PO-Revision-Date: 2015-02-23 11:36+0200\n"
  2240. ++"PO-Revision-Date: 2015-06-20 20:21-0300\n"
  2241.   "Last-Translator: Michal Čihař <michal@cihar.com>\n"
  2242. - "Language-Team: Portuguese <https://hosted.weblate.org/projects/noosfero"
  2243. - "/plugin-solr/pt/>\n"
  2244. + "Language-Team: Portuguese <https://hosted.weblate.org/projects/noosfero/"
  2245. + "plugin-solr/pt/>\n"
  2246.   "Language: pt\n"
  2247.   "MIME-Version: 1.0\n"
  2248.   "Content-Type: text/plain; charset=UTF-8\n"
  2249. @@@ -102,15 -98,15 +102,15 @@@ msgstr "Mais próximo de mim
  2250.   msgid "Sort results by "
  2251.   msgstr "Ordenar resultados por "
  2252.  
  2253.  -#: plugins/solr/lib/solr_plugin/search_helper.rb:136
  2254.  -msgid "%s products offers found"
  2255.  -msgstr "%s ofertas de produtos encontrados"
  2256.  +#: plugins/solr/lib/solr_plugin/search_helper.rb:135
  2257.  +msgid "%s products and/or services found"
  2258.  +msgstr "%s produtos e/ou serviços encontrados"
  2259.  
  2260.  -#: plugins/solr/lib/solr_plugin/search_helper.rb:137
  2261.  -msgid "%s articles found"
  2262.  -msgstr "%s artigos encontrados"
  2263.  +#: plugins/solr/lib/solr_plugin/search_helper.rb:136
  2264.  +msgid "%s contents found"
  2265.  +msgstr "%s conteúdos encontrados"
  2266.  
  2267. - #: plugins/solr/lib/solr_plugin/search_helper.rb:137
  2268. + #: plugins/solr/lib/solr_plugin/search_helper.rb:138
  2269.   msgid "%s events found"
  2270.   msgstr "%s eventos encontrados"
  2271.  
  2272. diff --cc plugins/solr/views/solr_plugin/search/_search_pre_contents.html.erb
  2273. index c089fdc,0000000..2bf15b1
  2274. mode 100644,000000..100644
  2275. --- a/plugins/solr/views/solr_plugin/search/_search_pre_contents.html.erb
  2276. +++ b/plugins/solr/views/solr_plugin/search/_search_pre_contents.html.erb
  2277. @@@ -1,26 -1,0 +1,17 @@@
  2278.  +<div class="row">
  2279.  +  <div class="col-lg-12 col-md-12 col-sm-12 text-left form-control-static">
  2280.  +
  2281. -     <div class="search-results-header-information">
  2282. -       <% if @searches[@asset][:results].total_entries > 0 %>
  2283. -         <%= label_total_found @asset, @searches[@asset][:results].total_entries %>
  2284. -         <% if params[:display] != 'map' %>
  2285. -           <span class="current-page"><%= _("Showing page %s of %s") % [@searches[@asset][:results].current_page, @searches[@asset][:results].total_pages] %></span>
  2286. -         <% end %>
  2287. -       <% end %>
  2288. -     </div>
  2289. -
  2290.  +    <%= facets_unselect_menu @asset %>
  2291.  +    <div class="row hidden-md hidden-lg">
  2292.  +      <div class="col-lg-12 col-md-12 col-sm-12">
  2293.  +        <a href="#solr-left-menu" class="fa fa-angle-right btn btn-default" role="button" ><%= _('Show filters') %></a>
  2294.  +      </div>
  2295.  +    </div>
  2296.  +
  2297.  +  </div>
  2298.  +</div>
  2299.  +
  2300.  +<div class="row">
  2301.  +  <%= render 'solr_plugin/search/facets_column' %>
  2302.  +  <div class="col-lg-9 col-md-8 col-sm-12 col-xs-12">
  2303.  +
  2304. diff --cc public/designs/icons/tango/style.css
  2305. index 3fe60fa,1fe4e21..f56d008
  2306. --- a/public/designs/icons/tango/style.css
  2307. +++ b/public/designs/icons/tango/style.css
  2308. @@@ -118,9 -114,108 +118,111 @@@
  2309.   .icon-set-admin-role          { background-image: url(mod/16x16/apps/user.png) }
  2310.   .icon-reset-admin-role        { background-image: url(../../../images/icons-app/person-icon.png) }
  2311.   .icon-clock                   { background-image: url(Tango/16x16/actions/appointment.png) }
  2312.  +.icon-feed,
  2313.  +.icon-newrss-feed,
  2314.  +.icon-rss-feed                { background-image: url(../../../images/icons-mime/rss-feed-16.png) }
  2315. + .icon-fullscreen              { background-image: url(Tango/16x16/actions/view-fullscreen.png) }
  2316. +
  2317. + /******************BIG ICONS************************/
  2318. + .bigicon-embed     { background-image: url(Tango/scalable/apps/utilities-terminal.svg) }
  2319. + .bigicon-edit      { background-image: url(Tango/scalable/apps/text-editor.svg) }
  2320. + .bigicon-undo      { background-image: url(Tango/scalable/actions/edit-undo.svg) }
  2321. + .bigicon-home      { background-image: url(Tango/scalable/actions/go-home.svg) }
  2322. + .bigicon-home-not  { background-image: url(mod/scalable/actions/go-home-not.svg) }
  2323. + .bigicon-new,
  2324. + .bigicon-suggest   { background-image: url(Tango/scalable/actions/filenew.svg) }
  2325. + .bigicon-close     { background-image: url(Tango/scalable/actions/gtk-cancel.svg) }
  2326. + .bigicon-newfolder { background-image: url(Tango/scalable/actions/folder-new.svg) }
  2327. + .bigicon-folder    { background-image: url(Tango/scalable/places/folder.svg) }
  2328. + .bigicon-parent-folder { background-image: url(Tango/scalable/places/folder_home.svg) }
  2329. + .bigicon-newblog   { background-image: url(mod/scalable/apps/text-editor.svg) }
  2330. + .bigicon-blog      { background-image: url(mod/scalable/apps/text-editor.svg) }
  2331. + .bigicon-save      { background-image: url(Tango/scalable/actions/filesave.svg) }
  2332. + .bigicon-send      { background-image: url(Tango/scalable/actions/stock_mail-forward.svg) }
  2333. + .bigicon-cancel    { background-image: url(Tango/scalable/actions/gtk-cancel.svg) }
  2334. + .bigicon-person    { background-image: url(Tango/scalable/apps/system-config-users.svg) }
  2335. + .bigicon-product   { background-image: url(Tango/scalable/mimetypes/package.svg) }
  2336. + .bigicon-delete    { background-image: url(Tango/scalable/places/user-trash.svg) }
  2337. + .bigicon-back      { background-image: url(Tango/scalable/actions/back.svg) }
  2338. + .bigicon-next      { background-image: url(Tango/scalable/actions/go-next.svg) }
  2339. + .bigicon-add       { background-image: url(Tango/scalable/actions/add.svg) }
  2340. + .bigicon-remove    { background-image: url(Tango/scalable/actions/gtk-remove.svg) }
  2341. + .bigicon-more      { background-image: url(Tango/scalable/actions/add.svg) }
  2342. + .bigicon-up        { background-image: url(Tango/scalable/actions/go-up.svg) }
  2343. + .bigicon-down      { background-image: url(Tango/scalable/actions/go-down.svg) }
  2344. + .bigicon-left      { background-image: url(Tango/scalable/actions/go-previous.svg) }
  2345. + .bigicon-right     { background-image: url(Tango/scalable/actions/go-next.svg) }
  2346. + .bigicon-up-disabled    { background-image: url(Tango/scalable/actions/go-up.svg); opacity: 0.25; filter:alpha(opacity=25); }
  2347. + .bigicon-down-disabled  { background-image: url(Tango/scalable/actions/go-down.svg); opacity: 0.25; filter:alpha(opacity=25); }
  2348. + .bigicon-left-disabled  { background-image: url(Tango/scalable/actions/go-previous.svg); opacity: 0.25; filter:alpha(opacity=25); }
  2349. + .bigicon-right-disabled { background-image: url(Tango/scalable/actions/go-next.svg); opacity: 0.25; filter:alpha(opacity=25); }
  2350. + .bigicon-up-red    { background-image: url(mod/scalable/actions/go-up-red.svg) }
  2351. + .bigicon-forward   { background-image: url(Tango/scalable/actions/go-next.svg) }
  2352. + .bigicon-search    { background-image: url(Tango/scalable/actions/search.svg) }
  2353. + .bigicon-ok        { background-image: url(Tango/scalable/actions/media-playback-start.svg) }
  2354. + .bigicon-login     { background-image: url(mod/scalable/actions/log-in.svg) }
  2355. + .bigicon-help      { background-image: url(Tango/scalable/apps/gnome-help.svg) }
  2356. + .bigicon-help32on  { background-image: url(Tango/scalable/apps/gnome-help.svg) }
  2357. + .bigicon-help32off { background-image: url(mod/scalable/apps/gnome-help-red.svg) }
  2358. + .bigicon-spread    { background-image: url(mod/scalable/actions/spread.svg) }
  2359. + .bigicon-todo            { background-image: url(Tango/scalable/actions/stock_paste.svg) }
  2360. + .bigicon-eyes            { background-image: url(Tango/scalable/actions/find.svg) }
  2361. + .bigicon-menu-home       { background-image: url(Tango/scalable/actions/go-home.svg) }
  2362. + .bigicon-menu-product    { background-image: url(Tango/scalable/mimetypes/package.svg) }
  2363. + .bigicon-menu-enterprise { background-image: url(Tango/scalable/actions/go-home.svg) }
  2364. + .bigicon-menu-community  { background-image: url(Tango/scalable/apps/system-config-users.svg) }
  2365. + .bigicon-menu-ctrl-panel { background-image: url(Tango/scalable/categories/preferences-desktop.svg) }
  2366. + .bigicon-menu-admin      { background-image: url(Tango/scalable/categories/preferences-system.svg) }
  2367. + .bigicon-menu-my-groups  { background-image: url(Tango/scalable/apps/system-config-users.svg) }
  2368. + .bigicon-menu-login      { background-image: url(mod/scalable/actions/log-in.svg) }
  2369. + .bigicon-menu-logout     { background-image: url(mod/scalable/actions/log-out.svg) }
  2370. + .bigicon-menu-search     { background-image: url(Tango/scalable/actions/search.svg) }
  2371. + .bigicon-menu-events     { background-image: url(Tango/scalable/mimetypes/stock_calendar.svg) }
  2372. + .bigicon-event           { background-image: url(Tango/scalable/mimetypes/stock_calendar.svg) }
  2373. + .bigicon-newevent        { background-image: url(Tango/scalable/mimetypes/stock_calendar.svg) }
  2374. + .bigicon-menu-articles   { background-image: url(Tango/scalable/apps/text-editor.svg) }
  2375. + .bigicon-menu-people     { background-image: url(mod/scalable/apps/user.svg) }
  2376. + .bigicon-menu-mail       { background-image: url(Tango/scalable/apps/email.svg) }
  2377. + .bigicon-upload-file     { background-image: url(Tango/scalable/actions/filesave.svg) }
  2378. + .bigicon-newupload-file  { background-image: url(Tango/scalable/actions/filesave.svg) }
  2379. + .bigicon-slideshow       { background-image: url(Tango/scalable/mimetypes/x-office-presentation.svg) }
  2380. + .bigicon-photos          { background-image: url(Tango/scalable/devices/camera-photo.svg) }
  2381. + .bigicon-vertical-toggle { background-image: url(Tango/scalable/actions/mail-send-receive.svg) }
  2382. + .bigicon-text-html       { background-image: url(Tango/scalable/mimetypes/text-html.svg) }
  2383. + .bigicon-text-plain      { background-image: url(Tango/scalable/mimetypes/text-x-generic.svg) }
  2384. + .bigicon-image-svg-xml   { background-image: url(Tango/scalable/mimetypes/image-x-generic.svg) }
  2385. + .bigicon-application-octet-stream { background-image: url(Tango/scalable/mimetypes/binary.svg) }
  2386. + .bigicon-application-x-gzip       { background-image: url(Tango/scalable/mimetypes/gnome-mime-application-x-gzip.svg) }
  2387. + .bigicon-application-postscript   { background-image: url(Tango/scalable/mimetypes/gnome-mime-application-postscript.svg) }
  2388. + .bigicon-application-pdf          { background-image: url(Tango/scalable/mimetypes/gnome-mime-application-pdf.svg) }
  2389. + .bigicon-application-ogg          { background-image: url(Tango/scalable/mimetypes/gnome-mime-application-ogg.svg) }
  2390. + .bigicon-video, .icon-video-mpeg  { background-image: url(Tango/scalable/mimetypes/video-x-generic.svg) }
  2391. + .bigicon-application-vnd-oasis-opendocument-text         { background-image: url(Tango/scalable/mimetypes/gnome-mime-application-vnd.oasis.opendocument.text.svg) }
  2392. + .bigicon-application-vnd-oasis-opendocument-spreadsheet  { background-image: url(Tango/scalable/mimetypes/gnome-mime-application-vnd.oasis.opendocument.spreadsheet.svg) }
  2393. + .bigicon-application-vnd-oasis-opendocument-presentation { background-image: url(Tango/scalable/mimetypes/gnome-mime-application-vnd.oasis.opendocument.presentation.svg) }
  2394. + .bigicon-welcome-page   { background-image: url(mod/scalable/mimetypes/welcome-page.svg) }
  2395. + .bigicon-blocks         { background-image: url(mod/scalable/mimetypes/blocks.svg) }
  2396. + .bigicon-header-footer  { background-image: url(mod/scalable/mimetypes/header-footer.svg) }
  2397. + .bigicon-appearance     { background-image: url(Tango/scalable/apps/preferences-desktop-wallpaper.svg) }
  2398. + .bigicon-media-pause  { background-image: url(Tango/scalable/actions/media-playback-pause.svg) }
  2399. + .bigicon-media-play   { background-image: url(Tango/scalable/actions/media-playback-start.svg) }
  2400. + .bigicon-media-prev   { background-image: url(Tango/scalable/actions/media-skip-backward.svg) }
  2401. + .bigicon-media-next   { background-image: url(Tango/scalable/actions/media-skip-forward.svg) }
  2402. + .bigicon-lock         { background-image: url(Tango/scalable/actions/lock.svg) }
  2403. + .bigicon-chat         { background-image: url(Tango/scalable/apps/internet-group-chat.svg); background-repeat: no-repeat }
  2404. + .bigicon-reply        { background-image: url(Tango/scalable/actions/mail-reply-sender.svg) }
  2405. + .bigicon-newforum     { background-image: url(Tango/scalable/apps/internet-group-chat.svg) }
  2406. + .bigicon-forum        { background-image: url(Tango/scalable/apps/system-users.svg) }
  2407. + .bigicon-gallery      { background-image: url(Tango/scalable/mimetypes/image-x-generic.svg) }
  2408. + .bigicon-newgallery   { background-image: url(Tango/scalable/mimetypes/image-x-generic.svg) }
  2409. + .bigicon-locale       { background-image: url(Tango/scalable/apps/preferences-desktop-locale.svg) }
  2410. + .bigicon-user-removed { background-image: url(Tango/scalable/actions/gtk-cancel.svg) }
  2411. + .bigicon-user-unknown { background-image: url(Tango/scalable/status/dialog-error.svg) }
  2412. + .bigicon-alert        { background-image: url(Tango/scalable/status/dialog-warning.svg) }
  2413. + .bigicon-clone        { background-image: url(Tango/scalable/actions/edit-copy.svg) }
  2414. + .bigicon-activate-user           { background-image: url(Tango/scalable/emblems/emblem-system.svg) }
  2415. + .bigicon-deactivate-user         { background-image: url(Tango/scalable/emblems/emblem-unreadable.svg) }
  2416. + .bigicon-clock                   { background-image: url(Tango/scalable/actions/appointment.svg) }
  2417.  
  2418.   /******************LARGE ICONS********************/
  2419.   .image-gallery-item .folder  { background-image: url(mod/96x96/places/folder.png) }
  2420. diff --cc public/designs/themes/base/style.css
  2421. index 12d8530,59a3a2e..68d5665
  2422. --- a/public/designs/themes/base/style.css
  2423. +++ b/public/designs/themes/base/style.css
  2424. @@@ -2742,20 -1061,14 +2734,23 @@@ hr.pre-posts, hr.sep-posts
  2425.     text-decoration: none;
  2426.   }
  2427.  
  2428.  +#content .automatic-abstract-thumb,
  2429.  +#content #boxes .box-1 .article-block img.automatic-abstract-thumb,
  2430.  +#content #article .article-body img.automatic-abstract-thumb {
  2431.  +  float:left;
  2432.  +  max-width:100px;
  2433.  +  max-height:100px;
  2434.  +  margin: 5px 5px 5px 0;
  2435.  +}
  2436.  +
  2437. - #content .main-block .created-at {
  2438. + #content .main-block .publishing-info {
  2439.     text-align: left;
  2440.     color: #AAA;
  2441. +   font-size: 11px;
  2442. +   /*padding-top: 20px;*/
  2443. +   margin-bottom:15px;
  2444.   }
  2445. - #content .main-block .created-at a {
  2446. + #content .main-block .publishing-info a {
  2447.     color: #AAA;
  2448.     text-decoration: none;
  2449.   }
  2450. @@@ -3105,357 -1418,115 +3100,469 @@@ table#recaptcha_table tr:hover td
  2451.     color:#333;
  2452.   }
  2453.  
  2454.  +/* Provisory: hide the yellow activation box in the person control panel: */
  2455.  +#activation_enterprise {
  2456.  +  display: none;
  2457.  +}
  2458.  +/* sign-up form */
  2459.  +
  2460.  +
  2461.  +#signup-form {
  2462.  +    color: #4A4A4A;
  2463.  +    display: inline-block;
  2464.  +}
  2465.  +
  2466.  +#signup-form small {
  2467.  +    display: none;
  2468.  +}
  2469.  +
  2470.  +#signup-form #signup-form-header {
  2471.  +    -moz-border-radius: 8px;
  2472.  +    border-radius: 8px;
  2473.  +    -webkit-border-radius: 8px;
  2474.  +    margin: 60px auto 5px;
  2475.  +    position: relative;
  2476.  +}
  2477.  +
  2478.  +#signup-form input.invalid_input {
  2479.  +    border: 1px solid #7f0000;
  2480.  +    background: #FFF;
  2481.  +    box-shadow: 0 0 7px red;
  2482.  +}
  2483.  +
  2484.  +#signup-form input.valid_input {
  2485.  +    border: 1px solid #005000;
  2486.  +    background: #FFF;
  2487.  +}
  2488.  +
  2489.  +#signup-form select,
  2490.  +#signup-form textarea,
  2491.  +#signup-form input {
  2492.  +    padding: 7px 7% 10px 3%;
  2493.  +    height: 20px;
  2494.  +    width: 90%;
  2495.  +    color: #6d786e;
  2496.  +    font-size: 18px;
  2497.  +}
  2498.  +
  2499.  +#signup-form #profile_data_login {
  2500.  +    margin: 3px 0px 0px 5px;
  2501.  +}
  2502.  +
  2503.  +#signup-form .filled-in,
  2504.  +#signup-form .invalid,
  2505.  +#signup-form input.validated,
  2506.  +#signup-form .checking {
  2507.  +    border-width: 1px;
  2508.  +    border-style: solid;
  2509.  +    background-color: #fff;
  2510.  +    background-position: right center;
  2511.  +    background-repeat: no-repeat;
  2512.  +    padding: 7px 7% 8px 3%;
  2513.  +    color: #4A4A4A;
  2514.  +    box-shadow: 0 0 7px green;
  2515.  +}
  2516.  +
  2517.  +#signup-form input.checking {
  2518.  +    box-shadow: none;
  2519.  +}
  2520.  +
  2521.  +#signup-form select {
  2522.  +    height: auto;
  2523.  +    padding-right: 3px;
  2524.  +    width: 365px;
  2525.  +}
  2526.  +
  2527.  +#signup-form .select-birth-date select {
  2528.  +    width: 93px;
  2529.  +    margin-right: 2px;
  2530.  +    margin-left: 0;
  2531.  +}
  2532.  +
  2533.  +.webkit #signup-form select {
  2534.  +    background: #fff;
  2535.  +}
  2536.  +
  2537.  +#signup-form textarea {
  2538.  +    background: #fff;
  2539.  +    height: 100px;
  2540.  +    padding-right: 3px;
  2541.  +    width: 365px;
  2542.  +}
  2543.  +
  2544.  +#signup-form input[type=file] {
  2545.  +    font-size: 12px;
  2546.  +}
  2547.  +
  2548.  +#signup-form input[type=radio] {
  2549.  +    height: auto;
  2550.  +    margin: 0px 5px 0px 3px;
  2551.  +    width: auto;
  2552.  +}
  2553.  +
  2554.  +#signup-form .fieldgroup {
  2555.  +    margin: 5px 10px;
  2556.  +}
  2557.  +
  2558.  +#signup-form #template-options li label {
  2559.  +    font-size: 18px;
  2560.  +}
  2561.  +
  2562.  +#signup-form #template-options li a {
  2563.  +    color: #555753
  2564.  +}
  2565.  +
  2566.  +#signup-form label[for=profile_data_sex_female],
  2567.  +#signup-form label[for=profile_data_sex_male] {
  2568.  +    color: #6d786e;
  2569.  +    font-size: 20px;
  2570.  +    display: inline;
  2571.  +    margin-left: 8px;
  2572.  +}
  2573.  +
  2574.  +#signup-form label[for=profile_data_country],
  2575.  +#signup-form label[for=profile_data_preferred_domain_id],
  2576.  +#signup-form label[for=profile_data_birth_date_2i],
  2577.  +#signup-form label[for=profile_data_birth_date_3i],
  2578.  +#signup-form label[for=profile_data_schooling],
  2579.  +#signup-form label[for=profile_data_formation],
  2580.  +#signup-form label[for=profile_data_area_of_study],
  2581.  +#signup-form label[for=profile_data_image_builder_uploaded_data] {
  2582.  +    display: block;
  2583.  +}
  2584.  +
  2585.  +#signup-form .invalid {
  2586.  +    border-color: #7f0000;
  2587.  +    background-image: url(/images/passwords_nomatch.png);
  2588.  +    box-shadow: 0 0 7px red;
  2589.  +}
  2590.  +
  2591.  +#signup-form span.invalid {
  2592.  +    border: none;
  2593.  +    padding: 0px;
  2594.  +    background: transparent;
  2595.  +    color: #7f0000;
  2596.  +    box-shadow: none;
  2597.  +}
  2598.  +
  2599.  +#signup-form .checking {
  2600.  +    border-color: #4A4A4A;
  2601.  +    background-image: url(/images/login_checking.png);
  2602.  +}
  2603.  +
  2604.  +#signup-form span.checking {
  2605.  +    border: none;
  2606.  +    padding: 0px;
  2607.  +    background: transparent;
  2608.  +    color: #4A4A4A;
  2609.  +    box-shadow: none;
  2610.  +}
  2611.  +
  2612.  +#signup-form .validated {
  2613.  +    border-color: #005000;
  2614.  +    background-image: url(/images/passwords_match.png);
  2615.  +}
  2616.  +
  2617.  +#signup-form span.validated {
  2618.  +    background: transparent;
  2619.  +    color: #005000;
  2620.  +}
  2621.  +/* ==> public/stylesheets/controller_account.css <== */
  2622.  +.controller-account #profile-data .type-text input, .controller-account #profile-data .type-password input, .controller-account #profile-data .type-select select {
  2623.  +    width: 220px
  2624.  +}
  2625.  +.controller-account #profile-data .type-select select.select-schooling {
  2626.  +    width: 108px;
  2627.  +}
  2628.  +.controller-account #profile-data .select-birth-date select#profile_data_birth_date_3i {
  2629.  +    width: 47px;
  2630.  +}
  2631.  +.controller-account .button.disabled {
  2632.  +    opacity: 0.5;
  2633.  +}
  2634.  +.controller-account #content .icon-forward.disabled {
  2635.  +    background-image: url('/designs/icons/default/go-right-disabled-HC.gif');
  2636.  +}
  2637.  +.controller-account .no-boxes {
  2638.  +    margin-left: 200px;
  2639.  +    margin-right: 200px;
  2640.  +}
  2641.  +
  2642.  +.controller-content_viewer .no-boxes, .controller-profile .no-boxes {
  2643.  +    margin: 0px 200px;
  2644.  +}
  2645.  +
  2646.  +
  2647.  +#signup-domain {
  2648.  +    float: left;
  2649.  +    display: inline-block;
  2650.  +    vertical-align: middle;
  2651.  +    background: #EEE;
  2652.  +    border: 1px solid #CFCFCF;
  2653.  +    line-height: 36px;
  2654.  +    padding: 0px 7px;
  2655.  +    color: #4A4A4A;
  2656.  +    font-size: 20px;
  2657.  +    text-transform: lowercase;
  2658.  +    min-width: 190px;
  2659.  +}
  2660.  +
  2661.  +#signup-form #signup-form-header #user_login {
  2662.  +    margin: 0;
  2663.  +    padding-right: 30px;
  2664.  +    width: 150px;
  2665.  +}
  2666.  +
  2667.  +#signup-login-field {
  2668.  +    float: left;
  2669.  +}
  2670.  +
  2671.  +#signup-form #signup-login {
  2672.  +    display: inline-block;
  2673.  +}
  2674.  +
  2675.  +#signup-form #signup-password,
  2676.  +#signup-form #signup-password-confirmation,
  2677.  +#signup-form #signup-email,
  2678.  +#signup-form #signup-name,
  2679.  +#signup-form #signup-login {
  2680.  +    position: relative;
  2681.  +}
  2682.  +
  2683.  +#signup-form small#signup-balloon,
  2684.  +#signup-form small#password-balloon,
  2685.  +#signup-form small#password-confirmation-balloon,
  2686.  +#signup-form small#email-balloon,
  2687.  +#signup-form small#name-balloon {
  2688.  +    display: none;
  2689.  +    width: 142px;
  2690.  +    height: 69px;
  2691.  +    color: #FFFFFF;
  2692.  +    font-weight: bold;
  2693.  +    font-size: 11px;
  2694.  +    padding: 5px 10px 45px 10px;
  2695.  +    margin: 0;
  2696.  +    line-height: 1.5em;
  2697.  +    background: transparent url(/images/gray-balloon.png) bottom center no-repeat;
  2698.  +    position: absolute;
  2699.  +    z-index: 2;
  2700.  +    right: -150px;
  2701.  +}
  2702.  +
  2703.  +#signup-form small#signup-balloon {
  2704.  +    top: -110px;
  2705.  +}
  2706.  +
  2707.  +#signup-form small#password-balloon,
  2708.  +#signup-form small#password-confirmation-balloon,
  2709.  +#signup-form small#email-balloon,
  2710.  +#signup-form small#name-balloon {
  2711.  +    top: -80px;
  2712.  +}
  2713.  +
  2714.  +#signup-form .required-field label,
  2715.  +#signup-form .formlabel {
  2716.  +    color: #4A4A4A;
  2717.  +    font-size: 20px;
  2718.  +    font-weight: normal;
  2719.  +    text-align: left;
  2720.  +}
  2721.  +
  2722.  +#signup-form .required-field label::after {
  2723.  +    content: '';
  2724.  +}
  2725.  +
  2726.  +.tooltip {
  2727.  +    padding: 8px;
  2728.  +    border: 1px solid #FF8000;
  2729.  +    background-color: #FFFF66;
  2730.  +    z-index: 100;
  2731.  +    -moz-border-radius: 3px;
  2732.  +    -webkit-border-radius: 3px;
  2733.  +}
  2734.  +
  2735.  +
  2736.  +/* Text editors sidebar */
  2737.  +
  2738.  +.controller-cms div.with_media_panel {
  2739.  +    float: left;
  2740.  +    width: 500px;
  2741.  +}
  2742.  +div.with_media_panel .formfield input {
  2743.  +    width: 100%;
  2744.  +}
  2745.  +div.with_media_panel .formfield input[type="checkbox"] {
  2746.  +    width: auto;
  2747.  +}
  2748.  +
  2749.  +
  2750.  +.text-editor-sidebar {
  2751.  +    position: absolute;
  2752.  +    width: 380px;
  2753.  +    right: 20px;
  2754.  +    top: 70px;
  2755.  +}
  2756.  +
  2757.  +#product-name h2 {
  2758.  +    display: inline;
  2759.  +}
  2760.  +#product_name {
  2761.  +    width: 60%;
  2762.  +}
  2763.  +
  2764.  +.image-gallery ul {
  2765.  +    width: 486px;
  2766.  +}
  2767.  +
  2768.  +.image-gallery-item {
  2769.  +    margin: 10px;
  2770.  +    float: left;
  2771.  +}
  2772.  +
  2773.  +.controller-profile_editor .control-panel a {
  2774.  +    width: 140px;
  2775.  +}
  2776.  +
  2777.  +
  2778.  +.categories_container {
  2779.  +  min-width: 100px;
  2780.  +}
  2781.  +
  2782.  +
  2783.  +#product-list .product-image-link {
  2784.  +  width: 200px;
  2785.  +}
  2786.  +
  2787.  +#product-list .product-big {
  2788.  +  width: 200px;
  2789.  +}
  2790.  +
  2791.  +#product-list .expand-box {
  2792.  +  width: 202px;
  2793.  +}
  2794.  +
  2795.  +#content .common-profile-list-block li, #content .comment-actions li {
  2796.  +  margin: 0px !important;
  2797.  +}
  2798.  +
  2799.  +#catalog-search-input {
  2800.  +  width: 150px;
  2801.  +  color: #555;
  2802.  +  height: 28px;
  2803.  +  padding: 0px 0px 0px 10px;
  2804.  +}
  2805.  +
  2806.  +/*PROVISORY!*/
  2807.  +#product-owner { display:none; }
  2808. + /************************* Article Page *****************************/
  2809. +
  2810. + #article-header .preview {
  2811. +   font-size: 15px;
  2812. + }
  2813. +
  2814. + .article-body-img {
  2815. +   float: left;
  2816. +   margin-right: 20px;
  2817. +   margin-top: 5px;
  2818. + }
  2819. +
  2820. + #content #article .article-body .article-body-img img {
  2821. +   height: auto;
  2822. +   width: auto;
  2823. +   min-height: 120px;
  2824. +   max-height: 180px;
  2825. +   max-width: 250px;
  2826. +   background-position: center center;
  2827. +   background-repeat: no-repeat;
  2828. + }
  2829. +
  2830. + #content #article .article-body .article-body-img p {
  2831. +   margin-bottom: 10px;
  2832. +   font-size: 10px;
  2833. +   min-height: 20px;
  2834. + }
  2835. + /* Noosfero Events */
  2836. +
  2837. + .event-card {
  2838. +   float: left;
  2839. +   padding-top: 25px;
  2840. +   width: 494px;
  2841. +   height: 116px;
  2842. +   background-repeat: no-repeat;
  2843. +   margin-bottom: 30px;
  2844. + }
  2845. +
  2846. + .event-image {
  2847. +   position: relative;
  2848. +   float: left;
  2849. +   padding-right: 22px;
  2850. +   max-width: 130px;
  2851. +   height: 130px;
  2852. + }
  2853. +
  2854. + #content #article .article-body img{
  2855. +   max-height: 100%;
  2856. + }
  2857. +
  2858. + .about-event {
  2859. +   position: relative;
  2860. +   float: left;
  2861. +   height: 160px;
  2862. +   width: 300px;
  2863. +   max-width: 300px;
  2864. + }
  2865. +
  2866. + .about-event > span {
  2867. +   display: block;
  2868. +   max-width: inherit;
  2869. +   margin-left: 20px;
  2870. +   padding-left: 21px;
  2871. +   line-height: 13px;
  2872. +   margin-right: 11px;
  2873. + }
  2874. +
  2875. + .about-event .event-date {
  2876. +   margin-top: 3px;
  2877. + }
  2878. +
  2879. + .about-event .event-address {
  2880. +   margin-top: 19px;
  2881. + }
  2882. +
  2883. + .about-event .event-address span {
  2884. +   display: block;
  2885. +   margin-left: 0px;
  2886. +   margin-top: 4.4px;
  2887. +   line-height: 14px;
  2888. + }
  2889. +
  2890. + .event-date {
  2891. +   background: url('/images/calendar_date_select/calendar-icon.png') no-repeat left center;
  2892. +   padding: 5px;
  2893. + }
  2894. +
  2895. + .event-link {
  2896. +   background: url('/images/globe-icon.png') no-repeat left center;
  2897. +   margin-top: 18px;
  2898. + }
  2899. +
  2900. + .event-link a {
  2901. + }
  2902. +
  2903. + .event-address {
  2904. +   background: url('/images/icone_pin.png') no-repeat left top;
  2905. + }
  2906. +
  2907. + .event-body {
  2908. +   float: left;
  2909. + }
  2910. +
  2911. + .event-body .event-lead {
  2912. +   font-size: 15px;
  2913. + }
  2914. +
  2915. + .event-body .event-content p {
  2916. +   margin-top: 20px;
  2917. +   width: 494px;
  2918. +   padding-left: 2px;
  2919. + }
  2920. diff --cc public/javascripts/application.js
  2921. index 09ca7da,33615ea..f27cbdd
  2922. --- a/public/javascripts/application.js
  2923. +++ b/public/javascripts/application.js
  2924. @@@ -2,11 -2,10 +2,11 @@@
  2925.   // This file is automatically included by javascript_include_tag :defaults
  2926.   /*
  2927.   * third party libraries
  2928.  +*= require lodash.js
  2929.   *= require jquery-2.1.1.min.js
  2930.   *= require jquery-migrate-1.2.1.js
  2931. - *= require jquery.colorbox-min.js
  2932.   *= require jquery.cycle.all.min.js
  2933. + *= require jquery.colorbox-min.js
  2934.   *= require jquery-ui-1.10.4/js/jquery-ui-1.10.4.min.js
  2935.   *= require jquery.scrollTo.js
  2936.   *= require jquery.form.js
  2937. @@@ -14,14 -13,10 +14,12 @@@
  2938.   *= require jquery.cookie.js
  2939.   *= require jquery.ba-bbq.min.js
  2940.   *= require jquery.tokeninput.js
  2941. - *= require jquery.typewatch.js
  2942. - *= require jquery.textchange.js
  2943. ++* select-or-die/_src/selectordie
  2944.   *= require jquery-timepicker-addon/dist/jquery-ui-timepicker-addon.js
  2945.   *= require inputosaurus.js
  2946.   *= require reflection.js
  2947. - *= require select-or-die/_src/selectordie
  2948.   *= require rails.js
  2949.  +*= require rails-extended.js
  2950.   *= require jrails.js
  2951.   * noosfero libraries
  2952.   *= require_self
  2953. @@@ -32,15 -25,11 +30,16 @@@
  2954.   *= require add-and-join.js
  2955.   *= require report-abuse.js
  2956.   *= require manage-products.js
  2957.  -*= require catalog.js
  2958.   *= require autogrow.js
  2959.  +*= require pagination.js
  2960.  +*= require loading-overlay.js
  2961. + *= require require_login.js
  2962.   */
  2963.  
  2964.  +_.templateSettings = {
  2965.  +  interpolate: /\{\{(.+?)\}\}/g,
  2966.  +};
  2967.  +
  2968.   // scope for noosfero stuff
  2969.   noosfero = {
  2970.   };
  2971. diff --cc public/javascripts/chat.js
  2972. index 0e38491,fc787df..f589037
  2973. --- a/public/javascripts/chat.js
  2974. +++ b/public/javascripts/chat.js
  2975. @@@ -184,11 -184,6 +184,12 @@@ jQuery(function($)
  2976.         $('#buddy-list #user-status img.avatar').replaceWith(getMyAvatar());
  2977.         $.get('/chat/update_presence_status', { status: {chat_status: presence, last_chat_status: presence} });
  2978.       },
  2979.  +    change_status: function(status_element, callback) {
  2980.  +      $('#chat-connect, #chat-disconnect, #chat-busy').removeClass('active')
  2981. ++      $('#chat .simplemenu-submenu').hide();
  2982.  +      status_element.addClass('active')
  2983.  +      callback()
  2984.  +    },
  2985.  
  2986.       send_availability_status: function(presence) {
  2987.         log('send availability status ' + presence);
  2988. diff --cc public/stylesheets/application.css
  2989. index be187f9,5c668ee..1342600
  2990. --- a/public/stylesheets/application.css
  2991. +++ b/public/stylesheets/application.css
  2992. @@@ -9,12 -10,10 +10,12 @@@
  2993.    *= require token-input-facet
  2994.    * noosfero libraries
  2995.    *= require_self
  2996.  + *= require pagination
  2997.    *= require iepngfix/iepngfix
  2998.  + *= require loading-overlay
  2999.    * views specifics
  3000. -  *= require search
  3001.    *= require chat
  3002. +  *= require search
  3003.    */
  3004.  
  3005.   /* browser fixes */
  3006. diff --cc public/stylesheets/chat.scss
  3007. index 931d5c5,0000000..6577c67
  3008. mode 100644,000000..100644
  3009. --- a/public/stylesheets/chat.scss
  3010. +++ b/public/stylesheets/chat.scss
  3011. @@@ -1,652 -1,0 +1,654 @@@
  3012.  +#chat {
  3013.  +  width: 0;
  3014.  +  position: fixed;
  3015.  +  right: 0;
  3016.  +  top: 100px;
  3017.  +  bottom: 0;
  3018.  +  z-index: 10;
  3019.  +  background-color: #FFF;
  3020.  +  box-shadow: -3px 0px 5px #888;
  3021.  +  transition: width 0.3s ease-in;
  3022. ++  z-index: 200;
  3023.  +}
  3024.  +
  3025.  +#chat.opened {
  3026.  +  width: 350px;
  3027.  +  transition: width 0.3s ease-in;
  3028.  +}
  3029.  +@media (max-width: 367px){
  3030.  +  body.responsive #chat.opened {
  3031.  +    width: 300px;
  3032.  +  }
  3033.  +}
  3034.  +
  3035.  +#chat-window {
  3036.  +  height: 100%;
  3037.  +  position: relative;
  3038.  +}
  3039.  +
  3040.  +#chat #buddy-list {
  3041.  +  background-color: #f9f9f9;
  3042.  +  top: 0;
  3043.  +  right: -5px;
  3044.  +  width: 0;
  3045.  +  bottom: 100px;
  3046.  +  position: absolute;
  3047.  +  border-left: 1px solid #DCE4E7;
  3048.  +  border-bottom: 1px solid #DCE4E7;
  3049.  +  z-index: 2;
  3050.  +  transition: width 0.3s ease-in;
  3051.  +}
  3052.  +
  3053.  +#chat.opened #buddy-list {
  3054.  +  width: 70px;
  3055.  +  transition: width 0.3s ease-in;
  3056.  +}
  3057.  +/*
  3058.  +#chat #buddy-list:hover {
  3059.  +  right: 0;
  3060.  +  width: 190px;
  3061.  +  transition: width 0.3s ease-in;
  3062.  +}
  3063.  +*/
  3064.  +
  3065.  +#buddy-list .buddies {
  3066.  +  position: absolute;
  3067.  +  bottom: 0;
  3068.  +  top: 25px;
  3069.  +  right: 6px;
  3070.  +  left: 7px;
  3071.  +  bottom: 7px;
  3072.  +  overflow: hidden;
  3073.  +  white-space: nowrap;
  3074.  +  transition: all 0.3s ease-in;
  3075.  +}
  3076.  +
  3077.  +/*
  3078.  +#buddy-list:hover .buddies {
  3079.  +  top: 57px;
  3080.  +  left: 15px;
  3081.  +  right: 0;
  3082.  +  transition: all 0.3s ease-in;
  3083.  +}
  3084.  +*/
  3085.  +
  3086.  +#buddy-list .buddies ul {
  3087.  +  list-style-type: none;
  3088.  +  padding: 0;
  3089.  +  margin: 0;
  3090.  +}
  3091.  +#buddy-list .buddies a:hover {
  3092.  +  background-color: #eeeeec;
  3093.  +}
  3094.  +
  3095.  +.occupant-list li a:hover {
  3096.  +  background-color: black;
  3097.  +}
  3098.  +
  3099.  +.occupant-list .icon-menu-chat-11 {
  3100.  +  background-image: none;
  3101.  +}
  3102.  +
  3103.  +#buddy-list .buddies li a, .occupant-list li a {
  3104.  +  background-position: 0% 50%;
  3105.  +  display: block;
  3106.  +  padding-left: 17px;
  3107.  +  text-decoration: none;
  3108.  +  height: 35px;
  3109.  +  overflow: hidden;
  3110.  +  margin-top: 5px;
  3111.  +}
  3112.  +#buddy-list .buddies li a .name, .occupant-list li a .name {
  3113.  +  vertical-align: middle;
  3114.  +  margin-left: 5px;
  3115.  +  position: relative;
  3116.  +  display: inline-block;
  3117.  +  max-width: 128px;
  3118.  +  overflow: hidden;
  3119.  +}
  3120.  +.occupant-list li a .name {
  3121.  +  color: white;
  3122.  +}
  3123.  +
  3124.  +#buddy-list .buddies li a img, .occupant-list li a img, #chat .avatar {
  3125.  +  border-radius: 5px;
  3126.  +  width: 24px;
  3127.  +  max-height: 25px;
  3128.  +  vertical-align: middle;
  3129.  +}
  3130.  +#chat #buddy-list .toolbar {
  3131.  +  height: 45px;
  3132.  +  width: 100%;
  3133.  +  background-color: #bbbeb7;
  3134.  +  display: table;
  3135.  +}
  3136.  +#buddy-list .toolbar .dialog-error {
  3137.  +  position: absolute;
  3138.  +  top: 30px;
  3139.  +  left: 10px;
  3140.  +  padding: 5px;
  3141.  +  width: 170px;
  3142.  +  -moz-border-radius: 5px;
  3143.  +  -webkit-border-radius: 5px;
  3144.  +  background: white;
  3145.  +  border: 1px solid #888;
  3146. ++  z-index: 10;
  3147.  +}
  3148.  +#buddy-list .toolbar .dialog-error p {
  3149.  +  margin: 0 0 5px 0;
  3150.  +}
  3151.  +
  3152.  +#buddy-list .body{
  3153.  +  position: absolute;
  3154.  +  bottom: 0;
  3155.  +  right: 0;
  3156.  +  left: 0;
  3157.  +  top: 20px;
  3158.  +  padding: 15px;
  3159.  +  transition: top 0.3s ease-in;
  3160.  +}
  3161.  +
  3162.  +/*
  3163.  +#buddy-list:hover .body{
  3164.  +  top: 45px;
  3165.  +  transition: top 0.3s ease-in;
  3166.  +}
  3167.  +*/
  3168.  +
  3169.  +#buddy-list .search{
  3170.  +  width: 142px;
  3171.  +  padding: 0;
  3172.  +  height: 0;
  3173.  +  color: #000;
  3174.  +  background-color: #dee1da;
  3175.  +  border: 0;
  3176.  +  transition: all 0.2s ease-in;
  3177.  +}
  3178.  +
  3179.  +/*
  3180.  +#buddy-list:hover .search{
  3181.  +  transition: all 0.3s ease-in 0.3;
  3182.  +  height: 16px;
  3183.  +  padding: 9px;
  3184.  +}
  3185.  +*/
  3186.  +
  3187.  +.conversation .input-div {
  3188.  +  position: absolute;
  3189.  +  right: 0;
  3190.  +  left: 0;
  3191.  +  bottom: 33px;
  3192.  +  height: 80px;
  3193.  +  padding-left: 7px;
  3194.  +}
  3195.  +.msie7 .conversation .input-div {
  3196.  +  padding-left: 5px;
  3197.  +  margin-right: 10px;
  3198.  +}
  3199.  +.conversation .input-div .icon-chat {
  3200.  +  width: 16px;
  3201.  +  height: 16px;
  3202.  +  position: relative;
  3203.  +  bottom: -23px;
  3204.  +  left: 5px;
  3205.  +}
  3206.  +.msie7 .conversation .input-div .icon-chat {
  3207.  +  left: 20px;
  3208.  +}
  3209.  +.conversation textarea {
  3210.  +  height: 100%;
  3211.  +  width: 98%;
  3212.  +  overflow: auto;
  3213.  +  padding-left: 25px;
  3214.  +  padding-top: 3px;
  3215.  +}
  3216.  +#conversations .history {
  3217.  +  overflow: hidden;
  3218.  +  position: absolute;
  3219.  +  right: 66px;
  3220.  +  left: 0;
  3221.  +  top: 45px;
  3222.  +  bottom: 100px;
  3223.  +}
  3224.  +
  3225.  +#conversations .history.room {
  3226.  +  bottom: 132px;
  3227.  +}
  3228.  +
  3229.  +#chat-label.opened #unread-messages,
  3230.  +#unread-messages:empty {
  3231.  +  display: none;
  3232.  +}
  3233.  +
  3234.  +#unread-messages {
  3235.  +  padding: 3px 5px;
  3236.  +  background-color: #F57900;
  3237.  +  border-radius: 5px;
  3238.  +  margin-top: -10px;
  3239.  +  margin-left: -30px;
  3240.  +  position: absolute;
  3241.  +  z-index: 1;
  3242.  +}
  3243.  +
  3244.  +#chat .unread-messages {
  3245.  +  height: 32px;
  3246.  +  line-height: 32px;
  3247.  +  width: 32px;
  3248.  +  background-color: black;
  3249.  +  border-radius: 5px;
  3250.  +  color: white;
  3251.  +  font-size: 22px;
  3252.  +  text-align: center;
  3253.  +  vertical-align: middle;
  3254.  +}
  3255.  +
  3256.  +#chat-window .history .message {
  3257.  +  padding: 10px 8px 10px 6px;
  3258.  +  clear: both;
  3259.  +}
  3260.  +
  3261.  +#chat-window .history .message.self .time {
  3262.  +  color: #888a85;
  3263.  +}
  3264.  +
  3265.  +#chat-window .history .message .time {
  3266.  +  float: right;
  3267.  +  color: white;
  3268.  +  font-style: italic;
  3269.  +  font-size: 10px;
  3270.  +  border-bottom: 1px solid #d3d7cf;
  3271.  +  width: 100%;
  3272.  +  text-align: right;
  3273.  +  margin-bottom: 5px;
  3274.  +}
  3275.  +#chat-window .history .message h5, #chat-window .history .message p {
  3276.  +  margin: 0;
  3277.  +}
  3278.  +#chat-window .history .message p {
  3279.  +  margin-left: 40px;
  3280.  +  word-wrap: break-word;
  3281.  +}
  3282.  +
  3283.  +#chat-window .history .message.self p {
  3284.  +  margin-left: 1px;
  3285.  +  margin-right: 40px;
  3286.  +}
  3287.  +
  3288.  +#chat-window .history .message .content {
  3289.  +  background-color: #bbbeb7;
  3290.  +  color: white;;
  3291.  +  padding: 8px;
  3292.  +  border-radius: 5px;
  3293.  +  display: inline-block;
  3294.  +  width: 100%;
  3295.  +  font-size: 15px;
  3296.  +}
  3297.  +#chat-window .history .message .content a {
  3298.  +  color: rgb(108, 226, 255);
  3299.  +  text-decoration: none;
  3300.  +}
  3301.  +#chat-window .history .message.self .content {
  3302.  +  background-color: #f9f9f9;
  3303.  +  color: #888a85;
  3304.  +}
  3305.  +
  3306.  +#chat-window .history .message .avatar {
  3307.  +  max-height: 42px;
  3308.  +  max-width: 32px;
  3309.  +  margin: auto;
  3310.  +  display: block;
  3311.  +}
  3312.  +#chat-window .history .notice {
  3313.  +  font-size: 10px;
  3314.  +  font-style: italic;
  3315.  +  color: gray;
  3316.  +  text-align: center;
  3317.  +  display: block;
  3318.  +}
  3319.  +
  3320.  +#chat .user-status a:hover {
  3321.  +  color: #FFF;
  3322.  +  background-color: #999;
  3323.  +  transition: 0.2s;
  3324.  +}
  3325.  +
  3326.  +.conversation div.occupants {
  3327.  +  bottom: 118px;
  3328.  +  background-color: #2e3436;
  3329.  +}
  3330.  +
  3331.  +div.occupants ul.occupant-list {
  3332.  +  padding: 0;
  3333.  +  margin: 0;
  3334.  +  max-height: 162px;
  3335.  +  overflow: hidden;
  3336.  +  position: relative;
  3337.  +  display: none;
  3338.  +  border-top: 1px solid rgb(37, 37, 37);
  3339.  +}
  3340.  +div.occupants ul.occupant-list {
  3341.  +  text-align: left;
  3342.  +}
  3343.  +
  3344.  +div.occupants > a {
  3345.  +  color: rgb(168, 168, 168);
  3346.  +  text-align: center;
  3347.  +  width: 100%;
  3348.  +  display: inline-block;
  3349.  +  text-decoration: none;
  3350.  +  background-image: url(/images/down-arrow.png);
  3351.  +  background-position: 158px center;
  3352.  +  background-repeat: no-repeat;
  3353.  +  font-size: 10px;
  3354.  +  font-weight: bold;
  3355.  +}
  3356.  +div.occupants > a.up {
  3357.  +  background-image: url(/images/top-arrow.png);
  3358.  +}
  3359.  +
  3360.  +#chat-window .comment-balloon-content {
  3361.  +  min-height: 50px;
  3362.  +  padding: 5px 0 5px 25px;
  3363.  +  position: relative;
  3364.  +}
  3365.  +#chat-window .comment-wrapper-1 {
  3366.  +  margin-left: 0;
  3367.  +}
  3368.  +
  3369.  +#chat .title-bar {
  3370.  +  height: 34px;
  3371.  +  background: #ccc url(/images/icons-app/chat-22x22.png) 3px 5px no-repeat;
  3372.  +  width: 250px;
  3373.  +  background-color: #303030;
  3374.  +  border-bottom: 1px solid #383838;
  3375.  +}
  3376.  +#chat .title-bar a {
  3377.  +  text-decoration: none;
  3378.  +}
  3379.  +
  3380.  +#conversations {
  3381.  +  height: 100%;
  3382.  +}
  3383.  +
  3384.  +#conversations .conversation {
  3385.  +  height: 100%;
  3386.  +  position: relative;
  3387.  +}
  3388.  +
  3389.  +#chat-window #conversations .conversation-header {
  3390.  +  position: absolute;
  3391.  +  right: 0;
  3392.  +  left: 0;
  3393.  +  background-color: #2e3436;
  3394.  +  color: white;
  3395.  +  width: 100%;
  3396.  +  height: 32px;
  3397.  +  font-size: 16px;
  3398.  +  text-align: left;
  3399.  +  padding-left: 15px;
  3400.  +  z-index: 20;
  3401.  +}
  3402.  +
  3403.  +#user-status .avatar {
  3404.  +  margin-left: 4px;
  3405.  +}
  3406.  +
  3407.  +.title-bar .title {
  3408.  +  margin: 0;
  3409.  +  font-size: 12px;
  3410.  +  padding-left: 30px;
  3411.  +  line-height: 32px;
  3412.  +  color: rgb(82, 212, 253);
  3413.  +  float: left;
  3414.  +}
  3415.  +#chat #chat-templates {
  3416.  +  display: none;
  3417.  +}
  3418.  +.conversation .header {
  3419.  +  position: absolute;
  3420.  +  top: 0;
  3421.  +  right: 0;
  3422.  +  width: 100%;
  3423.  +  height: 40px;
  3424.  +  background-color: rgb(39, 39, 39);
  3425.  +}
  3426.  +.conversation .header .other-name {
  3427.  + color: rgb(238, 238, 238);
  3428.  +}
  3429.  +#chat .back {
  3430.  +  float: right;
  3431.  +  margin: 6px;
  3432.  +  padding: 7px;
  3433.  +  background-color: rgb(98, 98, 98);
  3434.  +  border-radius: 6px;
  3435.  +  text-decoration: none;
  3436.  +  font-weight: bold;
  3437.  +  color: white;
  3438.  +}
  3439.  +#chat #chat-window .other-name, #chat #chat-window .history .self-name, #chat #chat-window .history h5, #chat .toolbar #user-status span.other-name {
  3440.  +  color: white;
  3441.  +  overflow: hidden;
  3442.  +  max-width: 140px;
  3443.  +  line-height: 28px;
  3444.  +}
  3445.  +#chat .toolbar #user-status span, #chat #conversations .header .chat-target span {
  3446.  +  max-width: 140px;
  3447.  +  font-weight: 900;
  3448.  +  color: white;
  3449.  +  display: inline-block
  3450.  +}
  3451.  +#chat .toolbar #user-status span.user-status {
  3452.  +  max-width: 200px;
  3453.  +}
  3454.  +#chat #chat-window .history h5 {
  3455.  +  text-align: center;
  3456.  +  word-wrap: break-word;
  3457.  +  font-size: 9px;
  3458.  +  max-height: 20px;
  3459.  +}
  3460.  +.webkit .simplemenu-submenu.opened {
  3461.  +  top: 18px;
  3462.  +}
  3463.  +#chat .simplemenu-submenu {
  3464.  +  background: #585858;
  3465.  +  border: 1px solid #6B6B6B;
  3466.  +  top: 42px;
  3467.  +  left: auto;
  3468.  +  right: 0;
  3469.  +}
  3470.  +
  3471.  +#chat .simplemenu-item:hover {
  3472.  +  background: none;
  3473.  +}
  3474.  +
  3475.  +#buddy-list #user-status {
  3476.  +  display: table-cell;
  3477.  +  vertical-align: middle;
  3478.  +  padding: 0;
  3479.  +  white-space: nowrap;
  3480.  +  transition: padding 0.3s ease-in;
  3481.  +}
  3482.  +
  3483.  +#chat .user-status a {
  3484.  +  color: rgb(224, 224, 224);
  3485.  +}
  3486.  +
  3487.  +.user-status {
  3488.  +  vertical-align: middle;
  3489.  +}
  3490.  +
  3491.  +.user-status span {
  3492.  +  position: relative;
  3493.  +}
  3494.  +.user-status span, .user-status .ui-icon {
  3495.  +  margin-left: 10px;
  3496.  +}
  3497.  +
  3498.  +.user-status .simplemenu-trigger {
  3499.  +  display: block;
  3500.  +  height: 42px;
  3501.  +  line-height: 40px;
  3502.  +  width: 161px;
  3503.  +  padding-left: 21px;
  3504.  +  background-position: 5px 11px;
  3505.  +  margin: 0px;
  3506.  +}
  3507.  +
  3508.  +.user-status .simplemenu-trigger .ui-icon-triangle-1-s {
  3509.  +  top: 20px;
  3510.  +  right: 0px;
  3511.  +}
  3512.  +
  3513.  +.user-status .simplemenu-item a {
  3514.  +  display: block;
  3515.  +  height: 20px;
  3516.  +  padding-left: 20px;
  3517.  +  line-height: 19px;
  3518.  +  background-position: 2px 1px;
  3519.  +}
  3520.  +
  3521.  +.conversation .author {
  3522.  +  width: 32px;
  3523.  +  display: inline-block;
  3524.  +  vertical-align: top;
  3525.  +  float: left;
  3526.  +}
  3527.  +.conversation .self .author {
  3528.  +  float: right;
  3529.  +}
  3530.  +
  3531.  +#chat .header {
  3532.  +  border: 0;
  3533.  +  height: 50px;
  3534.  +  line-height: 50px;
  3535.  +  text-align: center;
  3536.  +  color: #FFF;
  3537.  +  font-size: 19px;
  3538.  +  background-image: linear-gradient(to left, #E3E3E3 25%, #BABDB6 100%, #FFFFFF 100%);
  3539.  +  xbackground-color: #BABDB6;
  3540.  +}
  3541.  +
  3542.  +#chat-label {
  3543.  +  right: 0;
  3544.  +  width: 0;
  3545.  +  height: 0;
  3546.  +  background-color: #888A85;
  3547.  +  position: fixed;
  3548.  +  top: 150px;
  3549.  +  cursor: pointer;
  3550.  +  text-align: center;
  3551.  +  z-index: 11;
  3552.  +  transition: background-color 0.2s linear, right 0.3s ease-in;
  3553.  +}
  3554.  +
  3555.  +#chat-label.opened {
  3556.  +  width: 20px;
  3557.  +  height: 90px;
  3558.  +  right: 350px;
  3559.  +  background-color: #888A85;
  3560.  +  border-radius: 10px 0px 0 10px;
  3561.  +  font-size: 14px;
  3562.  +  transition: background-color 0.2s linear, right 0.3s ease-in;
  3563.  +}
  3564.  +@media (max-width: 367px){
  3565.  +  body.responsive #chat-label.opened {
  3566.  +    right: 300px;
  3567.  +  }
  3568.  +}
  3569.  +
  3570.  +#chat-label.opened:hover {
  3571.  +  background-color: #2E3436;
  3572.  +  transition: background-color 0.2s linear, right 0.3s ease-in;
  3573.  +}
  3574.  +
  3575.  +#chat-label span {
  3576.  +  color: white;
  3577.  +}
  3578.  +
  3579.  +#chat-label span.title {
  3580.  +  font-size: 16px;
  3581.  +  position: absolute;
  3582.  +  background-color: #888A85;
  3583.  +  border-radius: 10px 10px 0 0;
  3584.  +  transform: rotate(-90deg);
  3585.  +  top: 35px;
  3586.  +  right: -34px;
  3587.  +  width: 80px;
  3588.  +  padding: 2px 5px;
  3589.  +  text-shadow: 1px -1px 0 #666;
  3590.  +  transition: background-color 0.2s linear, right 0.3s ease-in;
  3591.  +}
  3592.  +
  3593.  +#chat-label:hover span.title {
  3594.  +  background-color: #2E3436;
  3595.  +  transition: background-color 0.2s linear, right 0.3s ease-in;
  3596.  +}
  3597.  +
  3598.  +#chat-label span.right-arrow {
  3599.  +  font-size: 18pxpx;
  3600.  +  line-height: 87px;
  3601.  +}
  3602.  +
  3603.  +#chat-label .title {
  3604.  +  display: inline;
  3605.  +}
  3606.  +
  3607.  +#chat-label.opened .title {
  3608.  +  display: none;
  3609.  +}
  3610.  +
  3611.  +#chat-label .right-arrow {
  3612.  +  display: none;
  3613.  +}
  3614.  +
  3615.  +#chat-label.opened .right-arrow {
  3616.  +  display: inline;
  3617.  +}
  3618.  +
  3619.  +#chat-label div {
  3620.  +  width: 64px;
  3621.  +  height: 64px;
  3622.  +  display: none;
  3623.  +}
  3624.  +
  3625.  +#chat-label.opened div {
  3626.  +  display: inline-block;
  3627.  +}
  3628.  +
  3629.  +.conversation .room-action {
  3630.  +  position: absolute;
  3631.  +  bottom: 100px;
  3632.  +  left: 7px;
  3633.  +  right: 79px;
  3634.  +  text-align: center;
  3635.  +  cursor: pointer;
  3636.  +  z-index: 1;
  3637.  +  color: white;
  3638.  +  border-radius: 3px;
  3639.  +  font-size: 14px;
  3640.  +}
  3641.  +
  3642.  +.conversation .join {
  3643.  + background-color: #4E9A06;
  3644.  +}
  3645.  +
  3646.  +.conversation .leave {
  3647.  + background-color: #A40000;
  3648.  +}
  3649.  +
  3650.  +body.responsive.chat-opened #wrap-1 {
  3651.  +  width:100%;
  3652.  +  padding-right:355px;
  3653.  +  transition: width 0.3s ease-in;
  3654.  +}
  3655.  +body.responsive.chat-opened #wrap-1 {
  3656.  +  background-color: transparent !important;
  3657.  +}
  3658.  +body.responsive.chat-opened #wrap-1 > #content {
  3659.  +  background-color: #fff;
  3660.  +}
  3661.  +@media (max-width: 767px){
  3662.  +  body.responsive.chat-opened #wrap-1{
  3663.  +      padding-right:0;
  3664.  +  }
  3665.  +}
  3666. diff --cc test/functional/content_viewer_controller_test.rb
  3667. index 214c506,3006e97..647e958
  3668. --- a/test/functional/content_viewer_controller_test.rb
  3669. +++ b/test/functional/content_viewer_controller_test.rb
  3670. @@@ -784,10 -789,24 +797,24 @@@ class ContentViewerControllerTest < Act
  3671.  
  3672.       get :view_page, :profile => profile.identifier, :page => blog.path
  3673.  
  3674.  -    assert_tag :tag => 'div', :attributes => { :class => 'short-post'}, :content => /Content to be displayed./
  3675.  -    assert_no_tag :tag => 'div', :attributes => { :class => 'short-post'}, :content => /Anything/
  3676.  +    assert_tag :tag => 'img', :attributes => { :class => 'automatic-abstract-thumb', :src => 'http://this_is_an_url/this_is_an_image.png', :style => nil}
  3677.  +    assert_tag :tag => 'div', :attributes => { :class => 'short-post'}, :content => /The first paragraph of the article\. The second paragraph The third which is a really biiiiiiig paragraph jds ksajdhf ksdfkjhsdh fakdshf askdjhfsd lfhsdlkfa dslkfah dskjahsd faksdhfk sdfkas fkjshfk sdhjf sdkjf sdkj fkdsjhfal ksdjhflaksjdhdsghfg sjhfgsdjhf sdjhgf asdjf sadj fadjhs gfas dkjgf asdjhf asdjh fjkdsg fjsdgf asdjf sadjlgf jsçlkdsjhfdsa lksajsalj aldja lkja slkdjal aj dasldkjas lkjsdj kj \.\.\./
  3678.     end
  3679.  
  3680. +   should 'show only first paragraph with picture of posts if visualization_format is short+pic' do
  3681. +     login_as(profile.identifier)
  3682. +
  3683. +     blog = Blog.create!(:name => 'A blog test', :profile => profile, :visualization_format => 'short+pic')
  3684. +
  3685. +     blog.posts << TinyMceArticle.create!(:name => 'first post', :parent => blog, :profile => profile, :body => '<p>Content to be displayed.</p> <img src="pic.jpg">')
  3686. +
  3687. +     get :view_page, :profile => profile.identifier, :page => blog.path
  3688. +
  3689. +     assert_select '.blog-post .post-pic' do |el|
  3690. +       assert_match /background-image:url\(pic.jpg\)/, el.to_s
  3691. +     end
  3692. +   end
  3693. +
  3694.     should 'display link to edit blog for allowed' do
  3695.       blog = fast_create(Blog, :profile_id => profile.id, :path => 'blog')
  3696.       login_as(profile.identifier)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement