Commit 0531c6a234fa8cf1abc7ad890d8e24d572d61d98

Authored by Leandro Santos
1 parent 02798bcc

merging with master

Showing 355 changed files with 38615 additions and 5958 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 355 files displayed.

@@ -3,8 +3,6 @@ gem 'rails', '~> 3.2.21' @@ -3,8 +3,6 @@ gem 'rails', '~> 3.2.21'
3 gem 'minitest', '~> 3.2.0' 3 gem 'minitest', '~> 3.2.0'
4 gem 'fast_gettext', '~> 0.6.8' 4 gem 'fast_gettext', '~> 0.6.8'
5 gem 'acts-as-taggable-on', '~> 3.0.2' 5 gem 'acts-as-taggable-on', '~> 3.0.2'
6 -gem 'prototype-rails', '~> 3.2.1'  
7 -gem 'prototype_legacy_helper', '0.0.0', :path => 'vendor/prototype_legacy_helper'  
8 gem 'rails_autolink', '~> 1.1.5' 6 gem 'rails_autolink', '~> 1.1.5'
9 gem 'pg', '~> 0.13.2' 7 gem 'pg', '~> 0.13.2'
10 gem 'rmagick', '~> 2.13.1' 8 gem 'rmagick', '~> 2.13.1'
@@ -13,8 +11,7 @@ gem 'will_paginate', '~> 3.0.3' @@ -13,8 +11,7 @@ gem 'will_paginate', '~> 3.0.3'
13 gem 'ruby-feedparser', '~> 0.7' 11 gem 'ruby-feedparser', '~> 0.7'
14 gem 'daemons', '~> 1.1.5' 12 gem 'daemons', '~> 1.1.5'
15 gem 'thin', '~> 1.3.1' 13 gem 'thin', '~> 1.3.1'
16 -gem 'hpricot', '~> 0.8.6'  
17 -gem 'nokogiri', '~> 1.6.0' 14 +gem 'nokogiri', '~> 1.5.5'
18 gem 'rake', :require => false 15 gem 'rake', :require => false
19 gem 'grape', '~> 0.2.1' 16 gem 'grape', '~> 0.2.1'
20 gem 'rest-client', '~> 1.6.7' 17 gem 'rest-client', '~> 1.6.7'
@@ -24,8 +21,7 @@ gem 'locale', '~> 2.0.5' @@ -24,8 +21,7 @@ gem 'locale', '~> 2.0.5'
24 21
25 gem 'whenever', :require => false 22 gem 'whenever', :require => false
26 23
27 -# FIXME list here all actual dependencies (i.e. the ones in debian/control),  
28 -# with their GEM names (not the Debian package names) 24 +gem 'eita-jrails', path: 'vendor/plugins/eita-jrails'
29 25
30 group :production do 26 group :production do
31 gem 'dalli', '~> 2.7.0' 27 gem 'dalli', '~> 2.7.0'
@@ -45,6 +41,9 @@ group :cucumber do @@ -45,6 +41,9 @@ group :cucumber do
45 gem 'selenium-webdriver', '~> 2.39.0' 41 gem 'selenium-webdriver', '~> 2.39.0'
46 end 42 end
47 43
  44 +# Requires custom dependencies
  45 +eval(File.read('config/Gemfile'), binding) rescue nil
  46 +
48 # include gemfiles from enabled plugins 47 # include gemfiles from enabled plugins
49 # plugins in baseplugins/ are not included on purpose. They should not have any 48 # plugins in baseplugins/ are not included on purpose. They should not have any
50 # dependencies. 49 # dependencies.
@@ -21,7 +21,7 @@ Noosfero is written in Ruby with the "[Rails framework](http://www.rubyonrails.o @@ -21,7 +21,7 @@ Noosfero is written in Ruby with the "[Rails framework](http://www.rubyonrails.o
21 You need to install some packages Noosfero depends on. On Debian GNU/Linux or Debian-based systems, all of these packages are available through the Debian archive. You can install them with the following command: 21 You need to install some packages Noosfero depends on. On Debian GNU/Linux or Debian-based systems, all of these packages are available through the Debian archive. You can install them with the following command:
22 22
23 # apt-get install ruby rake po4a libgettext-ruby-util libgettext-ruby1.8 \ 23 # apt-get install ruby rake po4a libgettext-ruby-util libgettext-ruby1.8 \
24 - libsqlite3-ruby rcov librmagick-ruby libredcloth-ruby libhpricot-ruby \ 24 + libsqlite3-ruby rcov librmagick-ruby libredcloth-ruby \
25 libwill-paginate-ruby iso-codes libfeedparser-ruby libdaemons-ruby thin \ 25 libwill-paginate-ruby iso-codes libfeedparser-ruby libdaemons-ruby thin \
26 tango-icon-theme 26 tango-icon-theme
27 27
@@ -40,7 +40,6 @@ On other systems, they may or may not be available through your regular package @@ -40,7 +40,6 @@ On other systems, they may or may not be available through your regular package
40 * Daemons - http://daemons.rubyforge.org 40 * Daemons - http://daemons.rubyforge.org
41 * Thin: http://code.macournoyer.com/thin 41 * Thin: http://code.macournoyer.com/thin
42 * tango-icon-theme: http://tango.freedesktop.org/Tango_Icon_Library 42 * tango-icon-theme: http://tango.freedesktop.org/Tango_Icon_Library
43 -* Hpricot: http://hpricot.com  
44 43
45 If you manage to install Noosfero successfully on other systems than Debian, 44 If you manage to install Noosfero successfully on other systems than Debian,
46 please feel free to contact the Noosfero development mailing with the 45 please feel free to contact the Noosfero development mailing with the
INSTALL.multitenancy.md
@@ -26,7 +26,7 @@ The file config/database.yml must follow a structure in order to achieve multite @@ -26,7 +26,7 @@ The file config/database.yml must follow a structure in order to achieve multite
26 26
27 Each "hosted" environment must have an entry like this: 27 Each "hosted" environment must have an entry like this:
28 28
29 - env1_production: 29 + env1_production: &DEFAULT
30 adapter: postgresql 30 adapter: postgresql
31 encoding: unicode 31 encoding: unicode
32 database: noosfero 32 database: noosfero
@@ -61,7 +61,7 @@ The "hosted" environments define, besides the `schema_search_path`, a list of do @@ -61,7 +61,7 @@ The "hosted" environments define, besides the `schema_search_path`, a list of do
61 You must also tell the application which is the default environment. 61 You must also tell the application which is the default environment.
62 62
63 production: 63 production:
64 - env1_production 64 + <<: *DEFAULT
65 65
66 On the example above there are only three hosted environments, but it can be more than three. The schemas `env2` and `env3` must already exist in the same database of the hosting environment. As postgres user, you can create them typing: 66 On the example above there are only three hosted environments, but it can be more than three. The schemas `env2` and `env3` must already exist in the same database of the hosting environment. As postgres user, you can create them typing:
67 67
SECURITY.md 0 → 100644
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +# Noosfero security
  2 +
  3 +## Reporting security issues in Noosfero
  4 +
  5 +Security vulnerabilities should be reported via an email to
  6 +noosfero-security@listas.softwarelivre.org, which ia a private mailing list.
  7 +Reported problems will be published after fixes are available.
  8 +
  9 +The members of the mailing list are people who provide Noosfero (Noosfero
  10 +committers, mainly).
app/controllers/admin/admin_panel_controller.rb
@@ -87,6 +87,6 @@ class AdminPanelController &lt; AdminController @@ -87,6 +87,6 @@ class AdminPanelController &lt; AdminController
87 scope = scope.order('name ASC') 87 scope = scope.order('name ASC')
88 88
89 @q = params[:q] 89 @q = params[:q]
90 - @collection = find_by_contents(:organizations, scope, @q, {:per_page => 10, :page => params[:npage]})[:results] 90 + @collection = find_by_contents(:organizations, environment, scope, @q, {:per_page => 10, :page => params[:npage]})[:results]
91 end 91 end
92 end 92 end
app/controllers/application_controller.rb
@@ -33,6 +33,7 @@ class ApplicationController &lt; ActionController::Base @@ -33,6 +33,7 @@ class ApplicationController &lt; ActionController::Base
33 unless environment.access_control_allow_methods.blank? 33 unless environment.access_control_allow_methods.blank?
34 response.headers["Access-Control-Allow-Methods"] = environment.access_control_allow_methods 34 response.headers["Access-Control-Allow-Methods"] = environment.access_control_allow_methods
35 end 35 end
  36 + response.headers["Access-Control-Allow-Credentials"] = 'true'
36 elsif environment.restrict_to_access_control_origins 37 elsif environment.restrict_to_access_control_origins
37 render_access_denied _('Origin not in allowed.') 38 render_access_denied _('Origin not in allowed.')
38 end 39 end
@@ -64,15 +65,7 @@ class ApplicationController &lt; ActionController::Base @@ -64,15 +65,7 @@ class ApplicationController &lt; ActionController::Base
64 helper :document 65 helper :document
65 helper :language 66 helper :language
66 67
67 - def self.no_design_blocks  
68 - @no_design_blocks = true  
69 - end  
70 - def self.uses_design_blocks?  
71 - !@no_design_blocks  
72 - end  
73 - def uses_design_blocks?  
74 - !@no_design_blocks && self.class.uses_design_blocks?  
75 - end 68 + include DesignHelper
76 69
77 # Be sure to include AuthenticationSystem in Application Controller instead 70 # Be sure to include AuthenticationSystem in Application Controller instead
78 include AuthenticatedSystem 71 include AuthenticatedSystem
app/controllers/public/chat_controller.rb
@@ -6,6 +6,7 @@ class ChatController &lt; PublicController @@ -6,6 +6,7 @@ class ChatController &lt; PublicController
6 def start_session 6 def start_session
7 login = user.jid 7 login = user.jid
8 password = current_user.crypted_password 8 password = current_user.crypted_password
  9 + session[:chat] ||= {:rooms => []}
9 begin 10 begin
10 jid, sid, rid = RubyBOSH.initialize_session(login, password, "http://#{environment.default_hostname}/http-bind", 11 jid, sid, rid = RubyBOSH.initialize_session(login, password, "http://#{environment.default_hostname}/http-bind",
11 :wait => 30, :hold => 1, :window => 5) 12 :wait => 30, :hold => 1, :window => 5)
@@ -16,6 +17,31 @@ class ChatController &lt; PublicController @@ -16,6 +17,31 @@ class ChatController &lt; PublicController
16 end 17 end
17 end 18 end
18 19
  20 + def toggle
  21 + session[:chat][:status] = session[:chat][:status] == 'opened' ? 'closed' : 'opened'
  22 + render :nothing => true
  23 + end
  24 +
  25 + def tab
  26 + session[:chat][:tab_id] = params[:tab_id]
  27 + render :nothing => true
  28 + end
  29 +
  30 + def join
  31 + session[:chat][:rooms] << params[:room_id]
  32 + session[:chat][:rooms].uniq!
  33 + render :nothing => true
  34 + end
  35 +
  36 + def leave
  37 + session[:chat][:rooms].delete(params[:room_id])
  38 + render :nothing => true
  39 + end
  40 +
  41 + def my_session
  42 + render :text => session[:chat].to_json, :layout => false
  43 + end
  44 +
19 def avatar 45 def avatar
20 profile = environment.profiles.find_by_identifier(params[:id]) 46 profile = environment.profiles.find_by_identifier(params[:id])
21 filename, mimetype = profile_icon(profile, :minor, true) 47 filename, mimetype = profile_icon(profile, :minor, true)
@@ -51,18 +77,28 @@ class ChatController &lt; PublicController @@ -51,18 +77,28 @@ class ChatController &lt; PublicController
51 messages = ChatMessage.where('(to_id=:other and from_id=:me) or (to_id=:me and from_id=:other)', {:me => user.id, :other => other.id}) 77 messages = ChatMessage.where('(to_id=:other and from_id=:me) or (to_id=:me and from_id=:other)', {:me => user.id, :other => other.id})
52 end 78 end
53 79
54 - messages = messages.order('created_at DESC').includes(:to, :from).limit(20) 80 + messages = messages.order('created_at DESC').includes(:to, :from).offset(params[:offset]).limit(20)
55 messages_json = messages.map do |message| 81 messages_json = messages.map do |message|
56 { 82 {
57 :body => message.body, 83 :body => message.body,
58 - :to => {:id => message.to.identifier, :name => message.to.name, :type => message.to.type},  
59 - :from => {:id => message.from.identifier, :name => message.from.name, :type => message.from.type}, 84 + :to => {:id => message.to.identifier, :name => message.to.name},
  85 + :from => {:id => message.from.identifier, :name => message.from.name},
60 :created_at => message.created_at 86 :created_at => message.created_at
61 } 87 }
62 end 88 end
63 render :json => messages_json.reverse 89 render :json => messages_json.reverse
64 end 90 end
65 91
  92 + def recent_conversations
  93 + conversations_order = ActiveRecord::Base.connection.execute("select profiles.identifier from profiles inner join (select distinct r.id as id, MAX(r.created_at) as created_at from (select from_id, to_id, created_at, (case when from_id=#{user.id} then to_id else from_id end) as id from chat_messages where from_id=#{user.id} or to_id=#{user.id}) as r group by id order by created_at desc, id) as t on profiles.id=t.id order by t.created_at desc").entries.map {|e| e['identifier']}
  94 + render :json => {:order => conversations_order.reverse, :domain => environment.default_hostname.gsub('.','-')}.to_json
  95 + end
  96 +
  97 + #TODO Ideally this is done through roster table on ejabberd.
  98 + def roster_groups
  99 + render :text => user.memberships.map {|m| {:jid => m.jid, :name => m.name}}.to_json
  100 + end
  101 +
66 protected 102 protected
67 103
68 def check_environment_feature 104 def check_environment_feature
app/controllers/public/contact_controller.rb
1 class ContactController < PublicController 1 class ContactController < PublicController
2 2
3 needs_profile 3 needs_profile
  4 + before_filter :allow_access_to_page
4 5
5 def new 6 def new
6 @contact = build_contact 7 @contact = build_contact
app/controllers/public/events_controller.rb
1 class EventsController < PublicController 1 class EventsController < PublicController
2 2
3 needs_profile 3 needs_profile
  4 + before_filter :allow_access_to_page
4 5
5 def events 6 def events
6 @events = [] 7 @events = []
app/controllers/public/home_controller.rb
@@ -2,13 +2,13 @@ class HomeController &lt; PublicController @@ -2,13 +2,13 @@ class HomeController &lt; PublicController
2 2
3 def index 3 def index
4 @has_news = false 4 @has_news = false
5 - if environment.enabled?('use_portal_community') && environment.portal_community 5 + if environment.portal_enabled
6 @has_news = true 6 @has_news = true
7 @news_cache_key = environment.portal_news_cache_key(FastGettext.locale) 7 @news_cache_key = environment.portal_news_cache_key(FastGettext.locale)
8 if !read_fragment(@news_cache_key) 8 if !read_fragment(@news_cache_key)
9 portal_community = environment.portal_community 9 portal_community = environment.portal_community
10 - @highlighted_news = portal_community.news(2, true)  
11 - @portal_news = portal_community.news(7, true) - @highlighted_news 10 + @highlighted_news = portal_community.news(environment.highlighted_news_amount, true)
  11 + @portal_news = portal_community.news(environment.portal_news_amount, true).offset(environment.highlighted_news_amount)
12 @area_news = environment.portal_folders 12 @area_news = environment.portal_folders
13 end 13 end
14 end 14 end
app/controllers/public/profile_controller.rb
@@ -16,13 +16,7 @@ class ProfileController &lt; PublicController @@ -16,13 +16,7 @@ class ProfileController &lt; PublicController
16 @activities = @profile.activities.paginate(:per_page => 15, :page => params[:page]) 16 @activities = @profile.activities.paginate(:per_page => 15, :page => params[:page])
17 end 17 end
18 @tags = profile.article_tags 18 @tags = profile.article_tags
19 - unless profile.display_info_to?(user)  
20 - if profile.visible?  
21 - private_profile  
22 - else  
23 - invisible_profile  
24 - end  
25 - end 19 + allow_access_to_page
26 end 20 end
27 21
28 def tags 22 def tags
@@ -399,17 +393,6 @@ class ProfileController &lt; PublicController @@ -399,17 +393,6 @@ class ProfileController &lt; PublicController
399 end 393 end
400 end 394 end
401 395
402 - def private_profile  
403 - private_profile_partial_parameters  
404 - render :action => 'index', :status => 403  
405 - end  
406 -  
407 - def invisible_profile  
408 - unless profile.is_template?  
409 - render_access_denied(_("This profile is inaccessible. You don't have the permission to view the content here."), _("Oops ... you cannot go ahead here"))  
410 - end  
411 - end  
412 -  
413 def per_page 396 def per_page
414 Noosfero::Constants::PROFILE_PER_PAGE 397 Noosfero::Constants::PROFILE_PER_PAGE
415 end 398 end
app/controllers/public_controller.rb
1 class PublicController < ApplicationController 1 class PublicController < ApplicationController
  2 + protected
  3 +
  4 + def allow_access_to_page
  5 + unless profile.display_info_to?(user)
  6 + if profile.visible?
  7 + private_profile
  8 + else
  9 + invisible_profile
  10 + end
  11 + end
  12 + end
  13 +
  14 + def private_profile
  15 + private_profile_partial_parameters
  16 + render :template => 'shared/access_denied.html.erb', :status => 403
  17 + end
  18 +
  19 + def invisible_profile
  20 + unless profile.is_template?
  21 + render_access_denied(_("This profile is inaccessible. You don't have the permission to view the content here."), _("Oops ... you cannot go ahead here"))
  22 + end
  23 + end
2 end 24 end
app/helpers/application_helper.rb
@@ -8,11 +8,7 @@ module ApplicationHelper @@ -8,11 +8,7 @@ module ApplicationHelper
8 8
9 include PermissionNameHelper 9 include PermissionNameHelper
10 10
11 - include LightboxHelper  
12 -  
13 - include ThickboxHelper  
14 -  
15 - include ColorboxHelper 11 + include ModalHelper
16 12
17 include BoxesHelper 13 include BoxesHelper
18 14
@@ -46,6 +42,8 @@ module ApplicationHelper @@ -46,6 +42,8 @@ module ApplicationHelper
46 42
47 include CatalogHelper 43 include CatalogHelper
48 44
  45 + include PluginsHelper
  46 +
49 def locale 47 def locale
50 (@page && !@page.language.blank?) ? @page.language : FastGettext.locale 48 (@page && !@page.language.blank?) ? @page.language : FastGettext.locale
51 end 49 end
@@ -649,8 +647,8 @@ module ApplicationHelper @@ -649,8 +647,8 @@ module ApplicationHelper
649 ' onfocus="if(this.value==\''+s+'\'){this.value=\'\'} this.form.className=\'focus-in\'"'+ 647 ' onfocus="if(this.value==\''+s+'\'){this.value=\'\'} this.form.className=\'focus-in\'"'+
650 ' onblur="if(/^\s*$/.test(this.value)){this.value=\''+s+'\'} this.form.className=\'focus-out\'">'+ 648 ' onblur="if(/^\s*$/.test(this.value)){this.value=\''+s+'\'} this.form.className=\'focus-out\'">'+
651 '</form>' 649 '</form>'
652 - else #opt == 'lightbox_link' is default  
653 - lightbox_link_to '<span class="icon-menu-search"></span>'+ _('Search'), { 650 + else
  651 + modal_link_to '<span class="icon-menu-search"></span>'+ _('Search'), {
654 :controller => 'search', 652 :controller => 'search',
655 :action => 'popup', 653 :action => 'popup',
656 :category_path => (@category ? @category.explode_path : nil)}, 654 :category_path => (@category ? @category.explode_path : nil)},
@@ -1048,7 +1046,7 @@ module ApplicationHelper @@ -1048,7 +1046,7 @@ module ApplicationHelper
1048 {s_('contents|Most commented') => {:href => url_for({:controller => 'search', :action => 'contents', :filter => 'more_comments'})}} 1046 {s_('contents|Most commented') => {:href => url_for({:controller => 'search', :action => 'contents', :filter => 'more_comments'})}}
1049 ] 1047 ]
1050 if logged_in? 1048 if logged_in?
1051 - links.push(_('New content') => colorbox_options({:href => url_for({:controller => 'cms', :action => 'new', :profile => current_user.login, :cms => true})})) 1049 + links.push(_('New content') => modal_options({:href => url_for({:controller => 'cms', :action => 'new', :profile => current_user.login, :cms => true})}))
1052 end 1050 end
1053 1051
1054 link_to(content_tag(:span, _('Contents'), :class => 'icon-menu-articles'), {:controller => "search", :action => 'contents', :category_path => nil}, :id => 'submenu-contents') + 1052 link_to(content_tag(:span, _('Contents'), :class => 'icon-menu-articles'), {:controller => "search", :action => 'contents', :category_path => nil}, :id => 'submenu-contents') +
@@ -1408,16 +1406,16 @@ module ApplicationHelper @@ -1408,16 +1406,16 @@ module ApplicationHelper
1408 end 1406 end
1409 1407
1410 def convert_macro(html, source) 1408 def convert_macro(html, source)
1411 - doc = Hpricot(html) 1409 + doc = Nokogiri::HTML.fragment html
1412 #TODO This way is more efficient but do not support macro inside of 1410 #TODO This way is more efficient but do not support macro inside of
1413 # macro. You must parse them from the inside-out in order to enable 1411 # macro. You must parse them from the inside-out in order to enable
1414 # that. 1412 # that.
1415 - doc.search('.macro').each do |macro| 1413 + doc.css('.macro').each do |macro|
1416 macro_name = macro['data-macro'] 1414 macro_name = macro['data-macro']
1417 result = @plugins.parse_macro(macro_name, macro, source) 1415 result = @plugins.parse_macro(macro_name, macro, source)
1418 macro.inner_html = result.kind_of?(Proc) ? self.instance_exec(&result) : result 1416 macro.inner_html = result.kind_of?(Proc) ? self.instance_exec(&result) : result
1419 end 1417 end
1420 - doc.html 1418 + doc.to_html
1421 end 1419 end
1422 1420
1423 def default_folder_for_image_upload(profile) 1421 def default_folder_for_image_upload(profile)
app/helpers/article_helper.rb
1 module ArticleHelper 1 module ArticleHelper
2 2
3 - include PrototypeHelper  
4 include TokenHelper 3 include TokenHelper
5 4
6 def article_reported_version(article) 5 def article_reported_version(article)
@@ -35,7 +34,7 @@ module ArticleHelper @@ -35,7 +34,7 @@ module ArticleHelper
35 'div', 34 'div',
36 check_box(:article, :notify_comments) + 35 check_box(:article, :notify_comments) +
37 content_tag('label', _('I want to receive a notification of each comment written by e-mail'), :for => 'article_notify_comments') + 36 content_tag('label', _('I want to receive a notification of each comment written by e-mail'), :for => 'article_notify_comments') +
38 - observe_field(:article_accept_comments, :function => "$('article_notify_comments').disabled = ! $('article_accept_comments').checked;$('article_moderate_comments').disabled = ! $('article_accept_comments').checked") 37 + observe_field(:article_accept_comments, :function => "jQuery('#article_notify_comments')[0].disabled = ! jQuery('#article_accept_comments')[0].checked;jQuery('#article_moderate_comments')[0].disabled = ! jQuery('#article_accept_comments')[0].checked")
39 ) + 38 ) +
40 39
41 content_tag( 40 content_tag(
app/helpers/boxes_helper.rb
@@ -38,8 +38,12 @@ module BoxesHelper @@ -38,8 +38,12 @@ module BoxesHelper
38 end 38 end
39 end 39 end
40 40
  41 + def boxes_limit holder
  42 + controller.send(:custom_design)[:boxes_limit] || holder.boxes_limit(controller.send(:custom_design)[:layout_template])
  43 + end
  44 +
41 def display_boxes(holder, main_content) 45 def display_boxes(holder, main_content)
42 - boxes = holder.boxes.with_position.first(holder.boxes_limit) 46 + boxes = holder.boxes.with_position.first(boxes_limit(holder))
43 content = boxes.reverse.map { |item| display_box(item, main_content) }.join("\n") 47 content = boxes.reverse.map { |item| display_box(item, main_content) }.join("\n")
44 content = main_content if (content.blank?) 48 content = main_content if (content.blank?)
45 49
@@ -65,11 +69,13 @@ module BoxesHelper @@ -65,11 +69,13 @@ module BoxesHelper
65 end 69 end
66 70
67 def display_box_content(box, main_content) 71 def display_box_content(box, main_content)
68 - context = { :article => @page, :request_path => request.path, :locale => locale, :params => request.params, :user => user }  
69 - box_decorator.select_blocks(box.blocks.includes(:box), context).map { |item| display_block(item, main_content) }.join("\n") + box_decorator.block_target(box) 72 + context = { :article => @page, :request_path => request.path, :locale => locale, :params => request.params, :user => user, :controller => controller }
  73 + box_decorator.select_blocks(box, box.blocks.includes(:box), context).map do |item|
  74 + display_block item, main_content
  75 + end.join("\n") + box_decorator.block_target(box)
70 end 76 end
71 77
72 - def select_blocks(arr, context) 78 + def select_blocks box, arr, context
73 arr 79 arr
74 end 80 end
75 81
@@ -150,8 +156,22 @@ module BoxesHelper @@ -150,8 +156,22 @@ module BoxesHelper
150 def self.block_edit_buttons(block) 156 def self.block_edit_buttons(block)
151 '' 157 ''
152 end 158 end
153 - def self.select_blocks(arr, context)  
154 - arr.select { |block| block.visible?(context) } 159 + def self.select_blocks box, arr, context
  160 + arr = arr.select{ |block| block.visible? context }
  161 +
  162 + custom_design = context[:controller].send(:custom_design)
  163 + inserts = [custom_design[:insert]].flatten.compact
  164 + inserts.each do |insert_opts|
  165 + next unless box.position == insert_opts[:box]
  166 + position, block = insert_opts[:position], insert_opts[:block]
  167 + block = block.new box: box if block.is_a? Class
  168 +
  169 + if not insert_opts[:uniq] or not box.blocks.map(&:class).include? block.klass
  170 + arr = arr.insert position, block
  171 + end
  172 + end
  173 +
  174 + arr
155 end 175 end
156 end 176 end
157 177
@@ -211,7 +231,7 @@ module BoxesHelper @@ -211,7 +231,7 @@ module BoxesHelper
211 end 231 end
212 232
213 if block.editable? 233 if block.editable?
214 - buttons << colorbox_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id }) 234 + buttons << modal_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id })
215 end 235 end
216 236
217 if !block.main? 237 if !block.main?
@@ -221,7 +241,7 @@ module BoxesHelper @@ -221,7 +241,7 @@ module BoxesHelper
221 end 241 end
222 242
223 if block.respond_to?(:help) 243 if block.respond_to?(:help)
224 - buttons << thickbox_inline_popup_icon(:help, _('Help on this block'), {}, "help-on-box-#{block.id}") << content_tag('div', content_tag('h2', _('Help')) + content_tag('div', block.help, :style => 'margin-bottom: 1em;') + thickbox_close_button(_('Close')), :style => 'display: none;', :id => "help-on-box-#{block.id}") 244 + buttons << modal_inline_icon(:help, _('Help on this block'), {}, "#help-on-box-#{block.id}") << content_tag('div', content_tag('h2', _('Help')) + content_tag('div', block.help, :style => 'margin-bottom: 1em;') + modal_close_button(_('Close')), :style => 'display: none;', :id => "help-on-box-#{block.id}")
225 end 245 end
226 246
227 if block.embedable? 247 if block.embedable?
app/helpers/chat_helper.rb
@@ -6,8 +6,9 @@ module ChatHelper @@ -6,8 +6,9 @@ module ChatHelper
6 ['icon-menu-busy', _('Busy'), 'chat-busy'], 6 ['icon-menu-busy', _('Busy'), 'chat-busy'],
7 ['icon-menu-offline', _('Sign out of chat'), 'chat-disconnect'], 7 ['icon-menu-offline', _('Sign out of chat'), 'chat-disconnect'],
8 ] 8 ]
  9 + avatar = profile_image(user, :portrait, :class => 'avatar')
9 content_tag('span', 10 content_tag('span',
10 - link_to(content_tag('span', user.name) + ui_icon('ui-icon-triangle-1-s'), 11 + link_to(avatar + content_tag('span', user.name) + ui_icon('ui-icon-triangle-1-s'),
11 '#', 12 '#',
12 :onclick => 'toggleMenu(this); return false', 13 :onclick => 'toggleMenu(this); return false',
13 :class => icon_class + ' simplemenu-trigger' 14 :class => icon_class + ' simplemenu-trigger'
app/helpers/colorbox_helper.rb
@@ -1,25 +0,0 @@ @@ -1,25 +0,0 @@
1 -module ColorboxHelper  
2 -  
3 - def colorbox_close_button(text, options = {})  
4 - button(:close, text, '#', colorbox_options(options, :close))  
5 - end  
6 -  
7 - def colorbox_button(type, label, url, options = {})  
8 - button(type, label, url, colorbox_options(options))  
9 - end  
10 -  
11 - def colorbox_icon_button(type, label, url, options = {})  
12 - icon_button(type, label, url, colorbox_options(options))  
13 - end  
14 -  
15 - # options must be an HTML options hash as passed to link_to etc.  
16 - #  
17 - # returns a new hash with colorbox class added. Keeps existing classes.  
18 - def colorbox_options(options, type=nil)  
19 - the_class = 'colorbox'  
20 - the_class += "-#{type.to_s}" unless type.nil?  
21 - the_class << " #{options[:class]}" if options.has_key?(:class)  
22 - options.merge(:class => the_class)  
23 - end  
24 -  
25 -end  
app/helpers/comment_helper.rb
@@ -65,7 +65,7 @@ module CommentHelper @@ -65,7 +65,7 @@ module CommentHelper
65 65
66 def link_for_edit(comment) 66 def link_for_edit(comment)
67 if comment.can_be_updated_by?(user) 67 if comment.can_be_updated_by?(user)
68 - {:link => expirable_comment_link(comment, :edit, _('Edit'), url_for(:profile => profile.identifier, :controller => :comment, :action => :edit, :id => comment.id),:class => 'colorbox')} 68 + {:link => expirable_comment_link(comment, :edit, _('Edit'), url_for(:profile => profile.identifier, :controller => :comment, :action => :edit, :id => comment.id),:class => 'modal')}
69 end 69 end
70 end 70 end
71 71
app/helpers/dates_helper.rb
@@ -2,24 +2,14 @@ require &#39;noosfero/i18n&#39; @@ -2,24 +2,14 @@ require &#39;noosfero/i18n&#39;
2 2
3 module DatesHelper 3 module DatesHelper
4 4
5 - # FIXME Date#strftime should translate this for us !!!!  
6 - MONTHS = [  
7 - N_('January'),  
8 - N_('February'),  
9 - N_('March'),  
10 - N_('April'),  
11 - N_('May'),  
12 - N_('June'),  
13 - N_('July'),  
14 - N_('August'),  
15 - N_('September'),  
16 - N_('October'),  
17 - N_('November'),  
18 - N_('December')  
19 - ]  
20 -  
21 - def month_name(n)  
22 - _(MONTHS[n-1]) 5 + MONTHS = I18n.t('date.month_names')
  6 +
  7 + def month_name(n, abbreviated = false)
  8 + if abbreviated
  9 + I18n.t('date.abbr_month_names')[n]
  10 + else
  11 + MONTHS[n]
  12 + end
23 end 13 end
24 14
25 # formats a date for displaying. 15 # formats a date for displaying.
@@ -91,15 +81,7 @@ module DatesHelper @@ -91,15 +81,7 @@ module DatesHelper
91 _(date.strftime("%a")) 81 _(date.strftime("%a"))
92 else 82 else
93 # FIXME Date#strftime should translate this for us !!!! 83 # FIXME Date#strftime should translate this for us !!!!
94 - _([  
95 - N_('Sunday'),  
96 - N_('Monday'),  
97 - N_('Tuesday'),  
98 - N_('Wednesday'),  
99 - N_('Thursday'),  
100 - N_('Friday'),  
101 - N_('Saturday'),  
102 - ][date.wday]) 84 + I18n.t('date.day_names')[date.wday]
103 end 85 end
104 end 86 end
105 87
@@ -111,7 +93,7 @@ module DatesHelper @@ -111,7 +93,7 @@ module DatesHelper
111 date = date << 1 93 date = date << 1
112 end 94 end
113 if opts[:only_month] 95 if opts[:only_month]
114 - _('%{month}') % {:month => month_name(date.month.to_i) } 96 + _('%{month}') % { :month => month_name(date.month.to_i) }
115 else 97 else
116 _('%{month} %{year}') % { :year => date.year, :month => month_name(date.month.to_i) } 98 _('%{month} %{year}') % { :year => date.year, :month => month_name(date.month.to_i) }
117 end 99 end
@@ -156,7 +138,7 @@ module DatesHelper @@ -156,7 +138,7 @@ module DatesHelper
156 else 138 else
157 order = [:day, :month, :year] 139 order = [:day, :month, :year]
158 end 140 end
159 - date_select(object, method, html_options.merge(options.merge(:include_blank => true, :order => order, :use_month_names => MONTHS.map {|item| gettext(item)}))) 141 + date_select(object, method, html_options.merge(options.merge(:include_blank => true, :order => order, :use_month_names => MONTHS)))
160 end 142 end
161 143
162 end 144 end
app/helpers/design_helper.rb 0 → 100644
@@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
  1 +module DesignHelper
  2 +
  3 + extend ActiveSupport::Concern
  4 +
  5 + included do
  6 + extend ClassMethods
  7 + include InstanceMethods
  8 + before_filter :load_custom_design if self.respond_to? :before_filter
  9 + end
  10 +
  11 + module ClassMethods
  12 +
  13 + def no_design_blocks
  14 + @no_design_blocks = true
  15 + end
  16 +
  17 + def use_custom_design options = {}
  18 + @custom_design = options
  19 + end
  20 +
  21 + def custom_design
  22 + @custom_design ||= {}
  23 + end
  24 +
  25 + def uses_design_blocks?
  26 + !@no_design_blocks
  27 + end
  28 +
  29 + end
  30 +
  31 + module InstanceMethods
  32 +
  33 + protected
  34 +
  35 + def uses_design_blocks?
  36 + !@no_design_blocks && self.class.uses_design_blocks?
  37 + end
  38 +
  39 + def load_custom_design
  40 + # see also: LayoutHelper#body_classes
  41 + @layout_template = self.class.custom_design[:layout_template]
  42 + end
  43 +
  44 + def custom_design
  45 + @custom_design || self.class.custom_design
  46 + end
  47 +
  48 + end
  49 +
  50 +end
app/helpers/lightbox_helper.rb
@@ -1,36 +0,0 @@ @@ -1,36 +0,0 @@
1 -module LightboxHelper  
2 -  
3 - def lightbox_link_to(text, url, options = {})  
4 - link_to(text, url, lightbox_options(options))  
5 - end  
6 -  
7 - def lightbox_close_button(text, options = {})  
8 - button(:close, text, '#', lightbox_options(options, 'lbAction').merge(:rel => 'deactivate'))  
9 - end  
10 -  
11 - def lightbox_button(type, label, url, options = {})  
12 - button(type, label, url, lightbox_options(options))  
13 - end  
14 -  
15 - def lightbox_icon_button(type, label, url, options = {})  
16 - icon_button(type, label, url, lightbox_options(options))  
17 - end  
18 -  
19 - # options must be an HTML options hash as passed to link_to etc.  
20 - #  
21 - # returns a new hash with lightbox class added. Keeps existing classes.  
22 - def lightbox_options(options, lightbox_type = 'lbOn')  
23 - the_class = lightbox_type  
24 - the_class << " #{options[:class]}" if options.has_key?(:class)  
25 - options.merge(:class => the_class)  
26 - end  
27 -  
28 - def lightbox?  
29 - request.xhr?  
30 - end  
31 -  
32 - def lightbox_remote_button(type, label, url, options = {})  
33 - button(type, label, url, lightbox_options(options, 'remote-lbOn'))  
34 - end  
35 -  
36 -end  
app/helpers/manage_products_helper.rb
@@ -137,7 +137,7 @@ module ManageProductsHelper @@ -137,7 +137,7 @@ module ManageProductsHelper
137 ui_button_to_remote(label, 137 ui_button_to_remote(label,
138 {:update => "product-#{field}", 138 {:update => "product-#{field}",
139 :url => { :controller => 'manage_products', :action => "edit", :id => product.id, :field => field }, 139 :url => { :controller => 'manage_products', :action => "edit", :id => product.id, :field => field },
140 - :complete => "$('edit-product-button-ui-#{field}').hide()", 140 + :complete => "jQuery('#edit-product-button-ui-#{field}').hide()",
141 :method => :get, 141 :method => :get,
142 :loading => "loading_for_button('##{id}')"}, 142 :loading => "loading_for_button('##{id}')"},
143 options) 143 options)
app/helpers/modal_helper.rb 0 → 100644
@@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
  1 +module ModalHelper
  2 +
  3 + def modal_inline_link_to title, url, selector, options = {}
  4 + link_to title, url, modal_options(options.merge(:inline => selector))
  5 + end
  6 +
  7 + def modal_inline_icon type, title, url, selector, options = {}
  8 + icon_button type, title, url, modal_options(options.merge(:inline => selector))
  9 + end
  10 +
  11 + def modal_link_to title, url, options = {}
  12 + link_to title, url, modal_options(options)
  13 + end
  14 +
  15 + def modal_close_link text, options = {}
  16 + link_to text, '#', modal_options(options, :close)
  17 + end
  18 +
  19 + def modal_close_button(text, options = {})
  20 + button :close, text, '#', modal_options(options, :close).merge(:rel => 'deactivate')
  21 + end
  22 +
  23 + def modal_button(type, label, url, options = {})
  24 + button type, label, url, modal_options(options)
  25 + end
  26 +
  27 + def modal_icon_button(type, label, url, options = {})
  28 + icon_button type, label, url, modal_options(options)
  29 + end
  30 +
  31 + # options must be an HTML options hash as passed to link_to etc.
  32 + #
  33 + # returns a new hash with modal class added. Keeps existing classes.
  34 + def modal_options(options, type=nil)
  35 + inline_selector = options.delete :inline
  36 + options[:onclick] = "return noosfero.modal.inline('#{inline_selector}')" if inline_selector
  37 +
  38 + classes = if inline_selector then '' else 'modal-toggle' end
  39 + classes += " modal-#{type.to_s}" if type.present?
  40 + classes << " #{options[:class]}" if options.has_key? :class
  41 + options.merge!(:class => classes)
  42 +
  43 + options
  44 + end
  45 +
  46 +end
app/helpers/plugins_helper.rb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +module PluginsHelper
  2 +
  3 + def plugins_product_tabs
  4 + @plugins.dispatch(:product_tabs, @product).map do |tab|
  5 + {:title => tab[:title], :id => tab[:id], :content => instance_eval(&tab[:content])}
  6 + end
  7 + end
  8 +
  9 +end
app/helpers/thickbox_helper.rb
@@ -1,11 +0,0 @@ @@ -1,11 +0,0 @@
1 -module ThickboxHelper  
2 - def thickbox_inline_popup_link(title, url, id, options = {})  
3 - link_to(title, url_for(url) + "#TB_inline?height=300&width=500&inlineId=#{id}&modal=true", {:class => 'thickbox'}.merge(options))  
4 - end  
5 - def thickbox_inline_popup_icon(type, title, url, id, options = {})  
6 - icon_button(type, title, url_for(url) + "#TB_inline?height=300&width=500&inlineId=#{id}&modal=true", {:class => "thickbox"}.merge(options))  
7 - end  
8 - def thickbox_close_button(title)  
9 - button_to_function(:close, title, 'tb_remove();')  
10 - end  
11 -end  
app/models/article.rb
1 -require 'hpricot'  
2 1
3 class Article < ActiveRecord::Base 2 class Article < ActiveRecord::Base
4 3
@@ -400,6 +399,10 @@ class Article &lt; ActiveRecord::Base @@ -400,6 +399,10 @@ class Article &lt; ActiveRecord::Base
400 {} 399 {}
401 end 400 end
402 401
  402 + def alternate_languages
  403 + self.translations.map(&:language)
  404 + end
  405 +
403 scope :native_translations, :conditions => { :translation_of_id => nil } 406 scope :native_translations, :conditions => { :translation_of_id => nil }
404 407
405 def translatable? 408 def translatable?
@@ -713,7 +716,7 @@ class Article &lt; ActiveRecord::Base @@ -713,7 +716,7 @@ class Article &lt; ActiveRecord::Base
713 end 716 end
714 717
715 def first_paragraph 718 def first_paragraph
716 - paragraphs = Hpricot(to_html).search('p') 719 + paragraphs = Nokogiri::HTML.fragment(to_html).css('p')
717 paragraphs.empty? ? '' : paragraphs.first.to_html 720 paragraphs.empty? ? '' : paragraphs.first.to_html
718 end 721 end
719 722
@@ -735,8 +738,8 @@ class Article &lt; ActiveRecord::Base @@ -735,8 +738,8 @@ class Article &lt; ActiveRecord::Base
735 738
736 def body_images_paths 739 def body_images_paths
737 require 'uri' 740 require 'uri'
738 - Hpricot(self.body.to_s).search('img[@src]').collect do |i|  
739 - (self.profile && self.profile.environment) ? URI.join(self.profile.environment.top_url, URI.escape(i.attributes['src'])).to_s : i.attributes['src'] 741 + Nokogiri::HTML.fragment(self.body.to_s).css('img[src]').collect do |i|
  742 + (self.profile && self.profile.environment) ? URI.join(self.profile.environment.top_url, URI.escape(i['src'])).to_s : i['src']
740 end 743 end
741 end 744 end
742 745
@@ -773,11 +776,11 @@ class Article &lt; ActiveRecord::Base @@ -773,11 +776,11 @@ class Article &lt; ActiveRecord::Base
773 end 776 end
774 777
775 def first_image 778 def first_image
776 - img = Hpricot(self.lead.to_s).search('img[@src]').first || Hpricot(self.body.to_s).search('img').first  
777 - img.nil? ? '' : img.attributes['src'] 779 + img = Nokogiri::HTML.fragment(self.lead.to_s).css('img[src]').first || Nokogiri::HTML.fragment(self.body.to_s).search('img').first
  780 + img.nil? ? '' : img['src']
778 end 781 end
779 782
780 - delegate :region, :region_id, :environment, :environment_id, :to => :profile, :allow_nil => true 783 + delegate :lat, :lng, :region, :region_id, :environment, :environment_id, :to => :profile, :allow_nil => true
781 784
782 def has_macro? 785 def has_macro?
783 true 786 true
app/models/blog_archives_block.rb
@@ -36,8 +36,7 @@ class BlogArchivesBlock &lt; Block @@ -36,8 +36,7 @@ class BlogArchivesBlock &lt; Block
36 results << content_tag('li', content_tag('strong', "#{year} (#{count})")) 36 results << content_tag('li', content_tag('strong', "#{year} (#{count})"))
37 results << "<ul class='#{year}-archive'>" 37 results << "<ul class='#{year}-archive'>"
38 posts.except(:order).count(:all, :conditions => ['EXTRACT(YEAR FROM published_at)=?', year], :group => 'EXTRACT(MONTH FROM published_at)').sort_by {|month, count| -month.to_i}.each do |month, count| 38 posts.except(:order).count(:all, :conditions => ['EXTRACT(YEAR FROM published_at)=?', year], :group => 'EXTRACT(MONTH FROM published_at)').sort_by {|month, count| -month.to_i}.each do |month, count|
39 - month_name = gettext(MONTHS[month.to_i - 1])  
40 - results << content_tag('li', link_to("#{month_name} (#{count})", owner_blog.url.merge(:year => year, :month => month))) 39 + results << content_tag('li', link_to("#{month_name(month.to_i)} (#{count})", owner_blog.url.merge(:year => year, :month => month)))
41 end 40 end
42 results << "</ul>" 41 results << "</ul>"
43 end 42 end
app/models/box.rb
@@ -14,8 +14,8 @@ class Box &lt; ActiveRecord::Base @@ -14,8 +14,8 @@ class Box &lt; ActiveRecord::Base
14 end 14 end
15 15
16 def acceptable_blocks 16 def acceptable_blocks
17 - blocks_classes = central? ? Box.acceptable_center_blocks + plugins.dispatch(:extra_blocks, :type => owner.class, :position => 1) : Box.acceptable_side_blocks + plugins.dispatch(:extra_blocks, :type => owner.class, :position => [2, 3])  
18 - to_css_class_name(blocks_classes) 17 + blocks_classes = if central? then Box.acceptable_center_blocks + plugins.dispatch(:extra_blocks, :type => owner.class, :position => 1) else Box.acceptable_side_blocks + plugins.dispatch(:extra_blocks, :type => owner.class, :position => [2, 3]) end
  18 + to_css_selector blocks_classes
19 end 19 end
20 20
21 def central? 21 def central?
@@ -74,8 +74,8 @@ class Box &lt; ActiveRecord::Base @@ -74,8 +74,8 @@ class Box &lt; ActiveRecord::Base
74 74
75 private 75 private
76 76
77 - def to_css_class_name(blocks_classes)  
78 - blocks_classes.map{ |block_class| block_class.name.to_css_class } 77 + def to_css_selector(blocks_classes)
  78 + blocks_classes.map{ |block_class| ".#{block_class.name.to_css_class}" }.join(',')
79 end 79 end
80 80
81 end 81 end
app/models/enterprise.rb
@@ -19,7 +19,8 @@ class Enterprise &lt; Organization @@ -19,7 +19,8 @@ class Enterprise &lt; Organization
19 has_many :inputs, :through => :products 19 has_many :inputs, :through => :products
20 has_many :production_costs, :as => :owner 20 has_many :production_costs, :as => :owner
21 21
22 - has_and_belongs_to_many :fans, :class_name => 'Person', :join_table => 'favorite_enteprises_people' 22 + has_many :favorite_enterprise_people
  23 + has_many :fans, through: :favorite_enterprise_people, source: :person
23 24
24 def product_categories 25 def product_categories
25 ProductCategory.by_enterprise(self) 26 ProductCategory.by_enterprise(self)
app/models/environment.rb
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 # domains. 3 # domains.
4 class Environment < ActiveRecord::Base 4 class Environment < ActiveRecord::Base
5 5
6 - attr_accessible :name, :is_default, :signup_welcome_text_subject, :signup_welcome_text_body, :terms_of_use, :message_for_disabled_enterprise, :news_amount_by_folder, :default_language, :languages, :description, :organization_approval_method, :enabled_plugins, :enabled_features, :disabled_blocks, :redirection_after_login, :redirection_after_signup, :contact_email, :theme, :reports_lower_bound, :noreply_email, :signup_welcome_screen_body, :members_whitelist_enabled, :members_whitelist 6 + attr_accessible :name, :is_default, :signup_welcome_text_subject, :signup_welcome_text_body, :terms_of_use, :message_for_disabled_enterprise, :news_amount_by_folder, :default_language, :languages, :description, :organization_approval_method, :enabled_plugins, :enabled_features, :redirection_after_login, :redirection_after_signup, :contact_email, :theme, :reports_lower_bound, :noreply_email, :signup_welcome_screen_body, :members_whitelist_enabled, :members_whitelist, :highlighted_news_amount, :portal_news_amount
7 7
8 has_many :users 8 has_many :users
9 9
@@ -268,9 +268,12 @@ class Environment &lt; ActiveRecord::Base @@ -268,9 +268,12 @@ class Environment &lt; ActiveRecord::Base
268 settings_items :description, :type => String, :default => '<div style="text-align: center"><a href="http://noosfero.org/"><img src="/images/noosfero-network.png" alt="Noosfero"/></a></div>' 268 settings_items :description, :type => String, :default => '<div style="text-align: center"><a href="http://noosfero.org/"><img src="/images/noosfero-network.png" alt="Noosfero"/></a></div>'
269 settings_items :local_docs, :type => Array, :default => [] 269 settings_items :local_docs, :type => Array, :default => []
270 settings_items :news_amount_by_folder, :type => Integer, :default => 4 270 settings_items :news_amount_by_folder, :type => Integer, :default => 4
  271 + settings_items :highlighted_news_amount, :type => Integer, :default => 2
  272 + settings_items :portal_news_amount, :type => Integer, :default => 5
271 settings_items :help_message_to_add_enterprise, :type => String, :default => '' 273 settings_items :help_message_to_add_enterprise, :type => String, :default => ''
272 settings_items :tip_message_enterprise_activation_question, :type => String, :default => '' 274 settings_items :tip_message_enterprise_activation_question, :type => String, :default => ''
273 275
  276 + settings_items :currency_iso_unit, :type => String, :default => 'USD'
274 settings_items :currency_unit, :type => String, :default => '$' 277 settings_items :currency_unit, :type => String, :default => '$'
275 settings_items :currency_separator, :type => String, :default => '.' 278 settings_items :currency_separator, :type => String, :default => '.'
276 settings_items :currency_delimiter, :type => String, :default => ',' 279 settings_items :currency_delimiter, :type => String, :default => ','
@@ -292,8 +295,6 @@ class Environment &lt; ActiveRecord::Base @@ -292,8 +295,6 @@ class Environment &lt; ActiveRecord::Base
292 295
293 settings_items :enabled_plugins, :type => Array, :default => Noosfero::Plugin.available_plugin_names 296 settings_items :enabled_plugins, :type => Array, :default => Noosfero::Plugin.available_plugin_names
294 297
295 - settings_items :disabled_blocks, :type => Array, :default => []  
296 -  
297 settings_items :search_hints, :type => Hash, :default => {} 298 settings_items :search_hints, :type => Hash, :default => {}
298 299
299 # Set to return http forbidden to host not on the allow origin list bellow 300 # Set to return http forbidden to host not on the allow origin list bellow
@@ -359,10 +360,6 @@ class Environment &lt; ActiveRecord::Base @@ -359,10 +360,6 @@ class Environment &lt; ActiveRecord::Base
359 enabled_plugins.include?(plugin.to_s) 360 enabled_plugins.include?(plugin.to_s)
360 end 361 end
361 362
362 - def block_disabled?(block)  
363 - disabled_blocks.include?(block.to_s)  
364 - end  
365 -  
366 # enables the features identified by <tt>features</tt>, which is expected to 363 # enables the features identified by <tt>features</tt>, which is expected to
367 # be an Enumarable object containing the identifiers of the desired features. 364 # be an Enumarable object containing the identifiers of the desired features.
368 # Passing <tt>nil</tt> is the same as passing an empty Array. 365 # Passing <tt>nil</tt> is the same as passing an empty Array.
app/models/event.rb
@@ -141,6 +141,10 @@ class Event &lt; Article @@ -141,6 +141,10 @@ class Event &lt; Article
141 result 141 result
142 end 142 end
143 143
  144 + def duration
  145 + ((self.end_date || self.start_date) - self.start_date).to_i
  146 + end
  147 +
144 def lead 148 def lead
145 content_tag('div', 149 content_tag('div',
146 show_period(start_date, end_date), 150 show_period(start_date, end_date),
app/models/external_feed.rb
@@ -14,9 +14,9 @@ class ExternalFeed &lt; ActiveRecord::Base @@ -14,9 +14,9 @@ class ExternalFeed &lt; ActiveRecord::Base
14 14
15 def add_item(title, link, date, content) 15 def add_item(title, link, date, content)
16 return if content.blank? 16 return if content.blank?
17 - doc = Hpricot(content)  
18 - doc.search('*').each do |p|  
19 - if p.instance_of? Hpricot::Elem 17 + doc = Nokogiri::HTML.fragment content
  18 + doc.css('*').each do |p|
  19 + if p.instance_of? Nokogiri::XML::Element
20 p.remove_attribute 'style' 20 p.remove_attribute 'style'
21 p.remove_attribute 'class' 21 p.remove_attribute 'class'
22 end 22 end
@@ -26,10 +26,10 @@ class ExternalFeed &lt; ActiveRecord::Base @@ -26,10 +26,10 @@ class ExternalFeed &lt; ActiveRecord::Base
26 article = TinyMceArticle.new 26 article = TinyMceArticle.new
27 article.name = title 27 article.name = title
28 article.profile = blog.profile 28 article.profile = blog.profile
29 - article.body = content  
30 - article.published_at = date  
31 - article.source = link  
32 - article.profile = blog.profile 29 + article.body = content
  30 + article.published_at = date
  31 + article.source = link
  32 + article.profile = blog.profile
33 article.parent = blog 33 article.parent = blog
34 article.author_name = self.feed_title 34 article.author_name = self.feed_title
35 unless blog.children.exists?(:slug => article.slug) 35 unless blog.children.exists?(:slug => article.slug)
app/models/favorite_enterprise_person.rb 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +class FavoriteEnterprisePerson < ActiveRecord::Base
  2 +
  3 + self.table_name = :favorite_enteprises_people
  4 +
  5 + belongs_to :enterprise
  6 + belongs_to :person
  7 +
  8 +end
app/models/forum.rb
@@ -54,7 +54,7 @@ class Forum &lt; Folder @@ -54,7 +54,7 @@ class Forum &lt; Folder
54 54
55 def first_paragraph 55 def first_paragraph
56 return '' if body.blank? 56 return '' if body.blank?
57 - paragraphs = Hpricot(body).search('p') 57 + paragraphs = Nokogiri::HTML.fragment(body).css('p')
58 paragraphs.empty? ? '' : paragraphs.first.to_html 58 paragraphs.empty? ? '' : paragraphs.first.to_html
59 end 59 end
60 60
app/models/input.rb
1 class Input < ActiveRecord::Base 1 class Input < ActiveRecord::Base
2 2
3 - attr_accessible :product, :product_category, :product_category_id, :amount_used, :unit_id, :price_per_unit, :relevant_to_price 3 + attr_accessible :product, :product_id, :product_category, :product_category_id,
  4 + :amount_used, :unit_id, :price_per_unit, :relevant_to_price, :is_from_solidarity_economy
4 5
5 belongs_to :product 6 belongs_to :product
6 belongs_to :product_category 7 belongs_to :product_category
app/models/product.rb
@@ -10,7 +10,8 @@ class Product &lt; ActiveRecord::Base @@ -10,7 +10,8 @@ class Product &lt; ActiveRecord::Base
10 :display => %w[full map] 10 :display => %w[full map]
11 } 11 }
12 12
13 - attr_accessible :name, :product_category, :highlighted, :price, :enterprise, :image_builder, :description, :available, :qualifiers, :unit_id, :discount, :inputs, :qualifiers_list 13 + attr_accessible :name, :product_category, :profile, :profile_id, :enterprise,
  14 + :highlighted, :price, :image_builder, :description, :available, :qualifiers, :unit_id, :discount, :inputs, :qualifiers_list
14 15
15 def self.default_search_display 16 def self.default_search_display
16 'full' 17 'full'
@@ -236,7 +237,7 @@ class Product &lt; ActiveRecord::Base @@ -236,7 +237,7 @@ class Product &lt; ActiveRecord::Base
236 237
237 def percentage_from_solidarity_economy 238 def percentage_from_solidarity_economy
238 se_i = t_i = 0 239 se_i = t_i = 0
239 - self.inputs(true).each{ |i| t_i += 1; se_i += 1 if i.is_from_solidarity_economy } 240 + self.inputs.each{ |i| t_i += 1; se_i += 1 if i.is_from_solidarity_economy }
240 t_i = 1 if t_i == 0 # avoid division by 0 241 t_i = 1 if t_i == 0 # avoid division by 0
241 p = case (se_i.to_f/t_i)*100 242 p = case (se_i.to_f/t_i)*100
242 when 0 then [0, ''] 243 when 0 then [0, '']
app/models/text_article.rb
1 require 'noosfero/translatable_content' 1 require 'noosfero/translatable_content'
2 2
3 -# a base class for all text article types. 3 +# a base class for all text article types.
4 class TextArticle < Article 4 class TextArticle < Article
5 5
6 xss_terminate :only => [ :name ], :on => 'validation' 6 xss_terminate :only => [ :name ], :on => 'validation'
@@ -26,10 +26,10 @@ class TextArticle &lt; Article @@ -26,10 +26,10 @@ class TextArticle &lt; Article
26 before_save :set_relative_path 26 before_save :set_relative_path
27 27
28 def set_relative_path 28 def set_relative_path
29 - parsed = Hpricot(self.body.to_s)  
30 - parsed.search('img[@src]').map { |i| change_element_path(i, 'src') }  
31 - parsed.search('a[@href]').map { |i| change_element_path(i, 'href') }  
32 - self.body = parsed.to_s 29 + parsed = Nokogiri::HTML.fragment(self.body.to_s)
  30 + parsed.css('img[src]').each { |i| change_element_path(i, 'src') }
  31 + parsed.css('a[href]').each { |i| change_element_path(i, 'href') }
  32 + self.body = parsed.to_html
33 end 33 end
34 34
35 def change_element_path(el, attribute) 35 def change_element_path(el, attribute)
app/models/user.rb
1 require 'digest/sha1' 1 require 'digest/sha1'
2 require 'user_activation_job' 2 require 'user_activation_job'
3 -require 'securerandom'  
4 3
5 # User models the system users, and is generated by the acts_as_authenticated 4 # User models the system users, and is generated by the acts_as_authenticated
6 # Rails generator. 5 # Rails generator.
@@ -55,7 +54,7 @@ class User &lt; ActiveRecord::Base @@ -55,7 +54,7 @@ class User &lt; ActiveRecord::Base
55 54
56 user.person = p 55 user.person = p
57 end 56 end
58 - if user.environment.enabled?('skip_new_user_email_confirmation') 57 + if user.environment.enabled?('skip_new_user_email_confirmation')
59 if user.environment.enabled?('admin_must_approve_new_users') 58 if user.environment.enabled?('admin_must_approve_new_users')
60 create_moderate_task 59 create_moderate_task
61 else 60 else
@@ -103,6 +102,7 @@ class User &lt; ActiveRecord::Base @@ -103,6 +102,7 @@ class User &lt; ActiveRecord::Base
103 validates_length_of :email, :within => 3..100, :if => (lambda {|user| !user.email.blank?}) 102 validates_length_of :email, :within => 3..100, :if => (lambda {|user| !user.email.blank?})
104 validates_uniqueness_of :login, :email, :case_sensitive => false, :scope => :environment_id 103 validates_uniqueness_of :login, :email, :case_sensitive => false, :scope => :environment_id
105 before_save :encrypt_password 104 before_save :encrypt_password
  105 + before_save :normalize_email, if: proc{ |u| u.email.present? }
106 validates_format_of :email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda {|user| !user.email.blank?}) 106 validates_format_of :email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda {|user| !user.email.blank?})
107 107
108 validates_inclusion_of :terms_accepted, :in => [ '1' ], :if => lambda { |u| ! u.terms_of_use.blank? }, :message => N_('{fn} must be checked in order to signup.').fix_i18n 108 validates_inclusion_of :terms_accepted, :in => [ '1' ], :if => lambda { |u| ! u.terms_of_use.blank? }, :message => N_('{fn} must be checked in order to signup.').fix_i18n
@@ -115,6 +115,10 @@ class User &lt; ActiveRecord::Base @@ -115,6 +115,10 @@ class User &lt; ActiveRecord::Base
115 u && u.authenticated?(password) ? u : nil 115 u && u.authenticated?(password) ? u : nil
116 end 116 end
117 117
  118 + def register_login
  119 + self.update_attribute :last_login_at, Time.now
  120 + end
  121 +
118 #FIXME make this test 122 #FIXME make this test
119 def generate_private_token! 123 def generate_private_token!
120 self.private_token = SecureRandom.hex 124 self.private_token = SecureRandom.hex
@@ -345,6 +349,11 @@ class User &lt; ActiveRecord::Base @@ -345,6 +349,11 @@ class User &lt; ActiveRecord::Base
345 end 349 end
346 350
347 protected 351 protected
  352 +
  353 + def normalize_email
  354 + self.email = self.email.squish.downcase
  355 + end
  356 +
348 # before filter 357 # before filter
349 def encrypt_password 358 def encrypt_password
350 return if password.blank? 359 return if password.blank?
app/views/account/_login_form.html.erb
1 <%= labelled_form_for :user, 1 <%= labelled_form_for :user,
2 :url => { :controller => 'account', :action => (params[:enterprise_code] ? 'activate_enterprise' : 'login') } do |f| %> 2 :url => { :controller => 'account', :action => (params[:enterprise_code] ? 'activate_enterprise' : 'login') } do |f| %>
3 3
4 -<%= f.text_field :login,  
5 - :id => ( lightbox? ? 'lightbox_' : '' ) + 'user_login',  
6 - :onchange => 'this.value = convToValidLogin( this.value )' %> 4 +<%= f.text_field :login, :id => 'user_login', :onchange => 'this.value = convToValidLogin( this.value )' %>
7 5
8 -<%= f.password_field :password,  
9 - :id => ( lightbox? ? 'lightbox_' : '' ) + 'user_password' %> 6 +<%= f.password_field :password, :id => 'user_password' %>
10 7
11 <% if params[:enterprise_code] %> 8 <% if params[:enterprise_code] %>
12 <%= hidden_field_tag :enterprise_code, params[:enterprise_code] %> 9 <%= hidden_field_tag :enterprise_code, params[:enterprise_code] %>
@@ -16,7 +13,7 @@ @@ -16,7 +13,7 @@
16 13
17 <% button_bar do %> 14 <% button_bar do %>
18 <%= submit_button( 'login', _('Log in') )%> 15 <%= submit_button( 'login', _('Log in') )%>
19 - <%= lightbox_close_button(_('Cancel')) if lightbox? %> 16 + <%= modal_close_button _('Cancel') if request.xhr? %>
20 <% end %> 17 <% end %>
21 18
22 <% end %> 19 <% end %>
app/views/account/activate_enterprise.html.erb
@@ -7,8 +7,8 @@ @@ -7,8 +7,8 @@
7 <p><%= _('Do you have a personal user account in the system?') %></p> 7 <p><%= _('Do you have a personal user account in the system?') %></p>
8 8
9 <div id="enterprise-activation-create-user-or-login-button"> 9 <div id="enterprise-activation-create-user-or-login-button">
10 - <%= button_to_function 'login', _('Yes'), "$('enterprise-activation-create-user-form').hide(); $('enterprise-activation-login-form').show()" %>  
11 - <%= button_to_function 'add', _('No'), "$('enterprise-activation-login-form').hide(); $('enterprise-activation-create-user-form').show()" %> 10 + <%= button_to_function 'login', _('Yes'), "jQuery('#enterprise-activation-create-user-form').hide(); jQuery('#enterprise-activation-login-form').show()" %>
  11 + <%= button_to_function 'add', _('No'), "jQuery('#enterprise-activation-login-form').hide(); jQuery('#enterprise-activation-create-user-form').show()" %>
12 </div> 12 </div>
13 13
14 <div id="enterprise-activation-create-user-form" style="display: none"> 14 <div id="enterprise-activation-create-user-form" style="display: none">
app/views/account/index_anonymous.html.erb
1 <h1><%= _('Identify yourself') %></h1> 1 <h1><%= _('Identify yourself') %></h1>
2 2
3 <p> 3 <p>
4 -<%= lightbox_link_to _('Login.'), { :controller => 'account', :action => 'login_popup' } %> 4 +<%= modal_link_to _('Login.'), { :controller => 'account', :action => 'login_popup' } %>
5 5
6 <%= _('You need to login to be able to use all the features in this environment.') %> 6 <%= _('You need to login to be able to use all the features in this environment.') %>
7 </p> 7 </p>
app/views/account/login.html.erb
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 <h2><%= _('Login') %></h2> 3 <h2><%= _('Login') %></h2>
4 4
5 <% @user ||= User.new %> 5 <% @user ||= User.new %>
6 -<% is_thickbox ||= false %> 6 +<% is_popin ||= false %>
7 7
8 <%= @message %> 8 <%= @message %>
9 9
@@ -17,8 +17,8 @@ @@ -17,8 +17,8 @@
17 17
18 <% button_bar do %> 18 <% button_bar do %>
19 <%= submit_button( 'login', _('Log in') )%> 19 <%= submit_button( 'login', _('Log in') )%>
20 - <% if is_thickbox %>  
21 - <%= thickbox_close_button(_('Cancel')) %> 20 + <% if is_popin %>
  21 + <%= modal_close_button(_('Cancel')) %>
22 <% end %> 22 <% end %>
23 <% end %> 23 <% end %>
24 24
app/views/account/logout_popup.html.erb
@@ -2,6 +2,6 @@ @@ -2,6 +2,6 @@
2 <p> 2 <p>
3 <% button_bar do %> 3 <% button_bar do %>
4 <%= button :ok, _('Yes'), { :controller => 'account', :action => 'logout' } %> 4 <%= button :ok, _('Yes'), { :controller => 'account', :action => 'logout' } %>
5 - <%= lightbox_close_button _('No, I want to stay.') %> 5 + <%= modal_close_button _('No, I want to stay.') %>
6 <% end %> 6 <% end %>
7 </p> 7 </p>
app/views/admin_panel/set_portal_community.html.erb
@@ -18,7 +18,7 @@ @@ -18,7 +18,7 @@
18 <%= button 'ok', _('Enable'), {:action => 'manage_portal_community', :activate => 1} %> 18 <%= button 'ok', _('Enable'), {:action => 'manage_portal_community', :activate => 1} %>
19 <% end %> 19 <% end %>
20 <%= button 'folder', _('Select Portal Folders'), {:action => 'set_portal_folders'} %> 20 <%= button 'folder', _('Select Portal Folders'), {:action => 'set_portal_folders'} %>
21 - <%= button 'edit', _('Define Amount by Folder'), {:action => 'set_portal_news_amount'} %> 21 + <%= button 'edit', _('Define news amount on portal'), {:action => 'set_portal_news_amount'} %>
22 <%= button 'delete', _('Remove'), { :action => 'unset_portal_community'} %> 22 <%= button 'delete', _('Remove'), { :action => 'unset_portal_community'} %>
23 <% end %> 23 <% end %>
24 <% end %> 24 <% end %>
app/views/admin_panel/set_portal_news_amount.html.erb
1 -<h1><%= _('News amount by folder') %></h1> 1 +<h1><%= _('News amount on portal') %></h1>
2 2
3 <%= labelled_form_for :environment do |f| %> 3 <%= labelled_form_for :environment do |f| %>
4 4
5 - <%= labelled_form_field _('Number of news'), select(:environment, :news_amount_by_folder, (1..10).to_a) %> 5 + <%= labelled_form_field _('Number of highlighted news'), select(:environment, :highlighted_news_amount, (0..10).to_a) %>
  6 + <%= labelled_form_field _('Number of portal news'), select(:environment, :portal_news_amount, (0..10).to_a) %>
  7 + <%= labelled_form_field _('Number of news by folder'), select(:environment, :news_amount_by_folder, (1..10).to_a) %>
6 8
7 <% button_bar do %> 9 <% button_bar do %>
8 <%= submit_button(:save, _('Save')) %> 10 <%= submit_button(:save, _('Save')) %>
app/views/box_organizer/edit.html.erb
@@ -27,7 +27,7 @@ @@ -27,7 +27,7 @@
27 27
28 <% button_bar do %> 28 <% button_bar do %>
29 <%= submit_button(:save, _('Save')) %> 29 <%= submit_button(:save, _('Save')) %>
30 - <%= colorbox_close_button(_('Cancel')) %> 30 + <%= modal_close_button(_('Cancel')) %>
31 <% end %> 31 <% end %>
32 32
33 <% end %> 33 <% end %>
app/views/box_organizer/move_block.rjs
@@ -6,3 +6,4 @@ page.replace_html(to, display_updated_box(@target_box)) @@ -6,3 +6,4 @@ page.replace_html(to, display_updated_box(@target_box))
6 6
7 page.visual_effect(:highlight, from) 7 page.visual_effect(:highlight, from)
8 page.visual_effect(:highlight, to) unless (from == to) 8 page.visual_effect(:highlight, to) unless (from == to)
  9 +
app/views/cms/_blog.html.erb
@@ -10,7 +10,8 @@ @@ -10,7 +10,8 @@
10 10
11 <script type="text/javascript"> 11 <script type="text/javascript">
12 function submit_button(index) { 12 function submit_button(index) {
13 - return $("article_slug").form.select("input.submit")[index]; 13 + var form = $($("#article_slug")[0].form)
  14 + return form.find("input[type=submit]")[index];
14 } 15 }
15 function warn_value_change() { 16 function warn_value_change() {
16 show_warning('article-formitem', "slug-change-confirmation"); 17 show_warning('article-formitem', "slug-change-confirmation");
@@ -23,7 +24,7 @@ @@ -23,7 +24,7 @@
23 hide_warning('slug-change-confirmation'); 24 hide_warning('slug-change-confirmation');
24 } 25 }
25 function no_change() { 26 function no_change() {
26 - $("article_slug").value = $("old_article_slug").value; 27 + jQuery("#article_slug").val(jQuery("#old_article_slug").val());
27 enable_button(submit_button(0)); 28 enable_button(submit_button(0));
28 enable_button(submit_button(1)); 29 enable_button(submit_button(1));
29 hide_warning('slug-change-confirmation'); 30 hide_warning('slug-change-confirmation');
@@ -78,7 +79,7 @@ @@ -78,7 +79,7 @@
78 <div id='fetch-external-feed'> 79 <div id='fetch-external-feed'>
79 <% enabled = @article.external_feed && @article.external_feed.enabled %> 80 <% enabled = @article.external_feed && @article.external_feed.enabled %>
80 <% only_once = @article.external_feed ? @article.external_feed.only_once : true %> 81 <% only_once = @article.external_feed ? @article.external_feed.only_once : true %>
81 - <%= labelled_check_box(_('Fetch posts from an external feed'), 'article[external_feed_builder][enabled]', 'true', enabled, {:onchange => "$('external-feed-options').toggle()"}) %> 82 + <%= labelled_check_box(_('Fetch posts from an external feed'), 'article[external_feed_builder][enabled]', 'true', enabled, {:onchange => "jQuery('#external-feed-options').toggle()"}) %>
82 <div id='external-feed-options' style="display: <%= enabled ? 'block' : 'none' %>"> 83 <div id='external-feed-options' style="display: <%= enabled ? 'block' : 'none' %>">
83 <%= efeed.hidden_field(:id) %> 84 <%= efeed.hidden_field(:id) %>
84 <%= labelled_form_field( _('Feed address'), efeed.text_field(:address) ) %> 85 <%= labelled_form_field( _('Feed address'), efeed.text_field(:address) ) %>
app/views/cms/_upload_file.html.erb
1 <p><%= file_field_tag('uploaded_files[]', :size => size) %></p> 1 <p><%= file_field_tag('uploaded_files[]', :size => size) %></p>
2 -<%= javascript_tag("$('uploaded_files').scrollTop = $('uploaded_files').scrollHeight") %> 2 +<%= javascript_tag("jQuery('#uploaded_files')[0].scrollTop = jQuery('#uploaded_files')[0].scrollHeight") %>
app/views/cms/edit.html.erb
@@ -28,7 +28,7 @@ @@ -28,7 +28,7 @@
28 <% end %> 28 <% end %>
29 29
30 <div style='float: right'> 30 <div style='float: right'>
31 - <%= lightbox_button :help, _('Why categorize?'), :action => 'why_categorize' %> 31 + <%= modal_button :help, _('Why categorize?'), :action => 'why_categorize' %>
32 </div> 32 </div>
33 33
34 <%= select_categories(:article, _('Categorize your article')) %> 34 <%= select_categories(:article, _('Categorize your article')) %>
app/views/cms/select_article_type.html.erb
@@ -15,6 +15,6 @@ @@ -15,6 +15,6 @@
15 </ul> 15 </ul>
16 <br style="clear:both" /> 16 <br style="clear:both" />
17 17
18 -<%= colorbox_close_button(_('Cancel')) %> 18 +<%= modal_close_button(_('Cancel')) %>
19 19
20 </div> 20 </div>
app/views/cms/view.html.erb
@@ -17,7 +17,7 @@ @@ -17,7 +17,7 @@
17 <% button_bar(:style => 'margin-bottom: 1em;') do %> 17 <% button_bar(:style => 'margin-bottom: 1em;') do %>
18 <% parent_id = ((@article && @article.allow_children?) ? @article : nil) %> 18 <% parent_id = ((@article && @article.allow_children?) ? @article : nil) %>
19 19
20 - <%= colorbox_button('new', _('New content'), :action => 'new', :parent_id => parent_id, :cms => true) %> 20 + <%= modal_button('new', _('New content'), :action => 'new', :parent_id => parent_id, :cms => true) %>
21 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor', :action => "index") %> 21 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor', :action => "index") %>
22 <% end %> 22 <% end %>
23 23
app/views/cms/why_categorize.html.erb
@@ -5,5 +5,5 @@ @@ -5,5 +5,5 @@
5 </p> 5 </p>
6 6
7 <% button_bar do %> 7 <% button_bar do %>
8 - <%= lightbox_close_button _('Close') %> 8 + <%= modal_close_button _('Close') %>
9 <% end %> 9 <% end %>
app/views/comment/_comment_form.html.erb
@@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
10 <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %> 10 <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %>
11 <% button_bar do %> 11 <% button_bar do %>
12 <%= button_to_function :add, _('Confirm'), "return false", :id => "confirm-captcha" %> 12 <%= button_to_function :add, _('Confirm'), "return false", :id => "confirm-captcha" %>
13 - <%= button_to_function :cancel, _('Cancel'), "jQuery.colorbox.close()" %> 13 + <%= button_to_function :cancel, _('Cancel'), "noosfero.modal.close()" %>
14 <% end %> 14 <% end %>
15 </div> 15 </div>
16 16
@@ -31,10 +31,10 @@ function check_captcha(button, confirm_action) { @@ -31,10 +31,10 @@ function check_captcha(button, confirm_action) {
31 return true; 31 return true;
32 <% else %> 32 <% else %>
33 jQuery('#recaptcha-container').show(); 33 jQuery('#recaptcha-container').show();
34 - jQuery.colorbox({ html: jQuery('#recaptcha-container').html(), maxWidth : '600px', maxHeight : '300px' }); 34 + noosfero.modal.inline('#recaptcha-container', {maxWidth :'600px', maxHeight : '300px' });
35 jQuery('#confirm-captcha').unbind('click'); 35 jQuery('#confirm-captcha').unbind('click');
36 jQuery('#confirm-captcha').bind('click', function() { 36 jQuery('#confirm-captcha').bind('click', function() {
37 - jQuery.colorbox.close(); 37 + noosfero.modal.close();
38 button.form.recaptcha_response_field.value = jQuery('#recaptcha_response_field').val(); 38 button.form.recaptcha_response_field.value = jQuery('#recaptcha_response_field').val();
39 button.form.recaptcha_challenge_field.value = jQuery('#recaptcha_challenge_field').val(); 39 button.form.recaptcha_challenge_field.value = jQuery('#recaptcha_challenge_field').val();
40 button.form.confirm.value = 'true'; 40 button.form.confirm.value = 'true';
@@ -88,7 +88,7 @@ function check_captcha(button, confirm_action) { @@ -88,7 +88,7 @@ function check_captcha(button, confirm_action) {
88 <% if !edition_mode %> 88 <% if !edition_mode %>
89 <%= button :cancel, _('Cancel'), '', :id => 'cancel-comment' %> 89 <%= button :cancel, _('Cancel'), '', :id => 'cancel-comment' %>
90 <% else %> 90 <% else %>
91 - <%= button :cancel, _('Cancel'), '#', :onclick => "jQuery.colorbox.close();" %> 91 + <%= button :cancel, _('Cancel'), '#', :onclick => "noosfero.modal.close();" %>
92 <% end %> 92 <% end %>
93 <% end %> 93 <% end %>
94 <% end %> 94 <% end %>
app/views/content_viewer/_article_toolbar.html.erb
@@ -29,14 +29,14 @@ @@ -29,14 +29,14 @@
29 <%= expirable_button @page, :locale, content, url %> 29 <%= expirable_button @page, :locale, content, url %>
30 <% end %> 30 <% end %>
31 31
32 - <%= colorbox_button(:new, label_for_new_article(@page), profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)))) unless remove_content_button(:new, @page) %> 32 + <%= modal_button(:new, label_for_new_article(@page), profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)))) unless remove_content_button(:new, @page) %>
33 <% end %> 33 <% end %>
34 34
35 <% if @page.accept_uploads? && @page.allow_create?(user) %> 35 <% if @page.accept_uploads? && @page.allow_create?(user) %>
36 <%= button('upload-file', _('Upload files'), profile.admin_url.merge(:controller => 'cms', :action => 'upload_files', :parent_id => (@page.folder? ? @page : @page.parent))) unless remove_content_button(:upload, @page)%> 36 <%= button('upload-file', _('Upload files'), profile.admin_url.merge(:controller => 'cms', :action => 'upload_files', :parent_id => (@page.folder? ? @page : @page.parent))) unless remove_content_button(:upload, @page)%>
37 <% end %> 37 <% end %>
38 38
39 - <% if !@page.allow_create?(user) && profile.community? && (@page.blog? || @page.parent && @page.parent.blog?) && !remove_content_button(:suggest, @page) %> 39 + <% if !@page.allow_create?(user) && profile.organization? && (@page.blog? || @page.parent && @page.parent.blog?) && !remove_content_button(:suggest, @page) %>
40 <% content = content_tag( 'span', _('Suggest an article') ) %> 40 <% content = content_tag( 'span', _('Suggest an article') ) %>
41 <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'suggest_an_article'}) %> 41 <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'suggest_an_article'}) %>
42 <% options = {:id => 'suggest-article-link'} %> 42 <% options = {:id => 'suggest-article-link'} %>
app/views/content_viewer/_comment_form.html.erb
@@ -7,10 +7,10 @@ function submit_comment_form(button) { @@ -7,10 +7,10 @@ function submit_comment_form(button) {
7 return true; 7 return true;
8 <% else %> 8 <% else %>
9 jQuery('#recaptcha-container').show(); 9 jQuery('#recaptcha-container').show();
10 - jQuery.colorbox({ inline : true, href : '#recaptcha-container', maxWidth : '600px', maxHeight : '300px' }); 10 + noosfero.modal.inline('#recaptcha-container', {maxWidth :'600px', maxHeight : '300px' });
11 jQuery('#confirm-captcha').unbind('click'); 11 jQuery('#confirm-captcha').unbind('click');
12 jQuery('#confirm-captcha').bind('click', function() { 12 jQuery('#confirm-captcha').bind('click', function() {
13 - jQuery.colorbox.close(); 13 + noosfero.modal.close();
14 button.form.recaptcha_response_field.value = jQuery('#recaptcha_response_field').val(); 14 button.form.recaptcha_response_field.value = jQuery('#recaptcha_response_field').val();
15 button.form.recaptcha_challenge_field.value = jQuery('#recaptcha_challenge_field').val(); 15 button.form.recaptcha_challenge_field.value = jQuery('#recaptcha_challenge_field').val();
16 button.form.confirm.value = 'true'; 16 button.form.confirm.value = 'true';
@@ -38,7 +38,7 @@ function submit_comment_form(button) { @@ -38,7 +38,7 @@ function submit_comment_form(button) {
38 <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %> 38 <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %>
39 <% button_bar do %> 39 <% button_bar do %>
40 <%= button_to_function :add, _('Confirm'), "return false", :id => "confirm-captcha" %> 40 <%= button_to_function :add, _('Confirm'), "return false", :id => "confirm-captcha" %>
41 - <%= button_to_function :cancel, _('Cancel'), "jQuery.colorbox.close()" %> 41 + <%= button_to_function :cancel, _('Cancel'), "noosfero.modal.close()" %>
42 <% end %> 42 <% end %>
43 </div> 43 </div>
44 44
app/views/events/_month.html.erb
@@ -13,8 +13,8 @@ @@ -13,8 +13,8 @@
13 date.day, 13 date.day,
14 :url => {:action => 'events_by_day', :year => date.year, :month => date.month, :day => date.day, :category_id => @category_id}, 14 :url => {:action => 'events_by_day', :year => date.year, :month => date.month, :day => date.day, :category_id => @category_id},
15 :update => 'events-of-the-day', 15 :update => 'events-of-the-day',
16 - :loading => "$('events-of-the-day').addClassName('loading')",  
17 - :complete => "$('events-of-the-day').removeClassName('loading')" 16 + :loading => "jQuery('#events-of-the-day').addClass('loading')",
  17 + :complete => "jQuery('#events-of-the-day').removeClass('loading')"
18 ) : 18 ) :
19 date.day 19 date.day
20 %> 20 %>
app/views/invite/_select_address_book.html.erb
@@ -12,16 +12,16 @@ @@ -12,16 +12,16 @@
12 12
13 <script type="text/javascript"> 13 <script type="text/javascript">
14 function hide_invite_friend_login_password() { 14 function hide_invite_friend_login_password() {
15 - $('invite-friends-login-password').hide(); 15 + jQuery('#invite-friends-login-password').hide();
16 } 16 }
17 function show_invite_friend_login_password(option) { 17 function show_invite_friend_login_password(option) {
18 if (option == 'hotmail') { 18 if (option == 'hotmail') {
19 - $('hotmail_username_tip').show(); 19 + jQuery('#hotmail_username_tip').show();
20 } else { 20 } else {
21 - $('hotmail_username_tip').hide(); 21 + jQuery('#hotmail_username_tip').hide();
22 } 22 }
23 - $('invite-friends-login-password').show();  
24 - $('login').focus(); 23 + jQuery('#invite-friends-login-password').show();
  24 + jQuery('#login').focus();
25 } 25 }
26 </script> 26 </script>
27 <div id='invite-friends-login-password' <%= "style='display: none;'" if (@import_from == 'manual') %>> 27 <div id='invite-friends-login-password' <%= "style='display: none;'" if (@import_from == 'manual') %>>
app/views/invite/select_friends.html.erb
@@ -24,8 +24,8 @@ @@ -24,8 +24,8 @@
24 </div> 24 </div>
25 <% if @import_from != 'manual' %> 25 <% if @import_from != 'manual' %>
26 <div> 26 <div>
27 - <%= link_to_function _('Check all'), "$$('input.contact_to_invite').each(function(checkbox) { checkbox.checked = true; });" %>  
28 - <%= link_to_function _('Uncheck all'), "$$('input.contact_to_invite').each(function(checkbox) { checkbox.checked = false; });" %> 27 + <%= link_to_function _('Check all'), "jQuery('input.contact_to_invite').each(function(index,checkbox) { checkbox.checked = true; });" %>
  28 + <%= link_to_function _('Uncheck all'), "jQuery('input.contact_to_invite').each(function(index,checkbox) { checkbox.checked = false; });" %>
29 <div id='contacts-list'></div> 29 <div id='contacts-list'></div>
30 </div> 30 </div>
31 <% end -%> 31 <% end -%>
app/views/layouts/_javascript.html.erb
1 -<%= javascript_include_tag 'prototype.js', 'effects.js', 'dragdrop.js', 'controls.js',  
2 -'jquery-2.1.1.min', 'jquery-migrate-1.2.1',  
3 -'jquery.noconflict.js', 'jquery.cycle.all.min.js', 'thickbox.js', 'lightbox', 'colorbox',  
4 -'jquery-ui-1.10.4/js/jquery-ui-1.10.4.min', 'jquery.scrollTo', 'jquery.form.js', 'jquery-validation/jquery.validate',  
5 -'jquery.cookie', 'jquery.ba-bbq.min.js', 'reflection', 'jquery.tokeninput', 'jquery.typewatch', 'jquery.textchange',  
6 -'add-and-join', 'report-abuse', 'catalog', 'manage-products', 'autogrow', 'select-or-die/_src/selectordie',  
7 -'jquery-timepicker-addon/dist/jquery-ui-timepicker-addon', 'application.js', 'rails.js', 'inputosaurus.js', :cache => 'cache/application' %> 1 +<%= javascript_include_tag 'jquery-2.1.1.min', 'jquery-migrate-1.2.1', 'jrails', 'rails.js',
  2 + 'jquery.cycle.all.min.js', 'jquery.colorbox-min.js',
  3 + 'jquery-ui-1.10.4/js/jquery-ui-1.10.4.min', 'jquery.scrollTo', 'jquery.form.js', 'jquery-validation/jquery.validate',
  4 + 'jquery.cookie', 'jquery.ba-bbq.min.js', 'reflection', 'jquery.tokeninput', 'jquery.typewatch', 'jquery.textchange',
  5 + 'jquery-timepicker-addon/dist/jquery-ui-timepicker-addon', 'inputosaurus.js', 'select-or-die/_src/selectordie',
  6 + # noosfero libraries
  7 + 'application.js', 'modal.js',
  8 + 'add-and-join', 'report-abuse', 'catalog', 'manage-products', 'autogrow',
  9 + :cache => 'cache/application' %>
8 10
9 <% language = FastGettext.locale %> 11 <% language = FastGettext.locale %>
10 <% %w{messages methods}.each do |type| %> 12 <% %w{messages methods}.each do |type| %>
app/views/layouts/_user.html.erb
@@ -7,11 +7,11 @@ @@ -7,11 +7,11 @@
7 </span> 7 </span>
8 <% else %> 8 <% else %>
9 <span class='not-logged-in'> 9 <span class='not-logged-in'>
10 - <%= _("<span class='login'>%s</span>") % thickbox_inline_popup_link('<i class="icon-menu-login"></i><strong>' + _('Login') + '</strong>', login_url, 'inlineLoginBox', :id => 'link_login') %> 10 + <%= _("<span class='login'>%s</span>") % modal_inline_link_to('<i class="icon-menu-login"></i><strong>' + _('Login') + '</strong>', login_url, '#inlineLoginBox', :id => 'link_login') %>
11 <%= @plugins.dispatch(:alternative_authentication_link).collect { |content| instance_exec(&content) }.join("") %> 11 <%= @plugins.dispatch(:alternative_authentication_link).collect { |content| instance_exec(&content) }.join("") %>
12 12
13 <div id='inlineLoginBox' style='display: none;'> 13 <div id='inlineLoginBox' style='display: none;'>
14 - <%= render :file => 'account/login', :locals => { :is_thickbox => true } %> 14 + <%= render :file => 'account/login', :locals => { :is_popin => true } %>
15 </div> 15 </div>
16 16
17 <% unless @plugins.dispatch(:allow_user_registration).include?(false) %> 17 <% unless @plugins.dispatch(:allow_user_registration).include?(false) %>
app/views/layouts/application-ng.html.erb
@@ -7,11 +7,6 @@ @@ -7,11 +7,6 @@
7 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> 7 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
8 <meta name="description" content="<%= @environment.name %>" /> 8 <meta name="description" content="<%= @environment.name %>" />
9 9
10 - <!-- Twitter Card -->  
11 - <meta name="twitter:card" value="summary">  
12 - <meta name="twitter:title" content="<%= h page_title %>">  
13 - <meta name="twitter:description" content="<%= meta_description_tag(@page) %>">  
14 -  
15 <!-- site root --> 10 <!-- site root -->
16 <meta property="noosfero:root" content="<%= Noosfero.root %>"/> 11 <meta property="noosfero:root" content="<%= Noosfero.root %>"/>
17 12
@@ -23,7 +18,7 @@ @@ -23,7 +18,7 @@
23 <%= yield :head %> 18 <%= yield :head %>
24 <%= 19 <%=
25 @plugins.dispatch(:head_ending).map do |content| 20 @plugins.dispatch(:head_ending).map do |content|
26 - if content.respond_to?(:call) then instance_exec(&content).html_safe else content.html_safe end 21 + if content.respond_to?(:call) then instance_exec(&content).to_s.html_safe else content.to_s.html_safe end
27 end.join("\n") 22 end.join("\n")
28 %> 23 %>
29 24
@@ -37,7 +32,7 @@ @@ -37,7 +32,7 @@
37 32
38 <%= 33 <%=
39 @plugins.dispatch(:body_beginning).map do |content| 34 @plugins.dispatch(:body_beginning).map do |content|
40 - if content.respond_to?(:call) then instance_exec(&content).html_safe else content.html_safe end 35 + if content.respond_to?(:call) then instance_exec(&content).to_s.html_safe else content.to_s.html_safe end
41 end.join("\n") 36 end.join("\n")
42 %> 37 %>
43 38
app/views/manage_products/_categories_for_selection.html.erb
1 <%= select_for_categories(categories, level) %> 1 <%= select_for_categories(categories, level) %>
2 2
3 <%= javascript_tag do %> 3 <%= javascript_tag do %>
4 - jQuery('#categories_container_wrapper').scrollTo('100%', 1000)  
5 - $('selected_category_id').value = <%= @category && @category.id %>  
6 - $('hierarchy_navigation').update('<%= escape_javascript(hierarchy_category_navigation(@category, :make_links => true)) %>')  
7 - toggleDisabled(<%= @category && @category.accept_products? ? 'true' : 'false' %>, $('save_and_continue')) 4 + jQuery(document).ready(function() {
  5 + jQuery('#categories_container_wrapper').scrollTo('100%', 1000)
  6 + jQuery('#selected_category_id').val(<%= @category.id rescue nil %>)
  7 + jQuery('#hierarchy_navigation').html(<%= hierarchy_category_navigation(@category, :make_links => true).to_json %>)
  8 + toggleDisabled(<%= (!!(@category && @category.accept_products?)).to_json %>, jQuery('#save_and_continue'))
  9 + });
8 <% end %> 10 <% end %>
app/views/manage_products/_display_name.html.erb
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 <%= edit_product_link_to_remote(@product, 'name', _('Edit name and unit'), :title => _('Click here to edit the name of your product and the unit')) %> 3 <%= edit_product_link_to_remote(@product, 'name', _('Edit name and unit'), :title => _('Click here to edit the name of your product and the unit')) %>
4 </div> 4 </div>
5 <%= javascript_tag do %> 5 <%= javascript_tag do %>
6 - $$('#display-product-category .hierarchy-category')[0].update('<%= 6 + jQuery('#display-product-category .hierarchy-category').first().html('<%=
7 escape_javascript(hierarchy_category_navigation( 7 escape_javascript(hierarchy_category_navigation(
8 @product.product_category, 8 @product.product_category,
9 :make_links => false, 9 :make_links => false,
app/views/manage_products/new.html.erb
@@ -26,5 +26,5 @@ @@ -26,5 +26,5 @@
26 <% end %> 26 <% end %>
27 27
28 <%= javascript_tag do %> 28 <%= javascript_tag do %>
29 - toggleDisabled(<%= @category && @category.accept_products? ? 'true' : 'false' %>, $('save_and_continue')) 29 + toggleDisabled(<%= @category && @category.accept_products? ? 'true' : 'false' %>, jQuery('#save_and_continue')[0])
30 <% end %> 30 <% end %>
app/views/manage_products/show.html.erb
@@ -24,6 +24,8 @@ @@ -24,6 +24,8 @@
24 <br style='clear: both'/> 24 <br style='clear: both'/>
25 25
26 <% unless !@allowed_user && (@product.description.blank? && @product.inputs.empty? && !@product.price_described? ) %> 26 <% unless !@allowed_user && (@product.description.blank? && @product.inputs.empty? && !@product.price_described? ) %>
  27 + <% plugins_tabs = plugins_product_tabs %>
  28 +
27 <div class='ui-tabs' id='product-<%= @product.id %>-tabs'> 29 <div class='ui-tabs' id='product-<%= @product.id %>-tabs'>
28 <ul> 30 <ul>
29 <% if !@product.description.blank? || @allowed_user %> 31 <% if !@product.description.blank? || @allowed_user %>
@@ -35,19 +37,32 @@ @@ -35,19 +37,32 @@
35 <% if @product.price_described? || @allowed_user %> 37 <% if @product.price_described? || @allowed_user %>
36 <li class='tab'><a href='#product-price-details'><%= _('Price composition') %></a></li> 38 <li class='tab'><a href='#product-price-details'><%= _('Price composition') %></a></li>
37 <% end %> 39 <% end %>
  40 +
  41 + <% plugins_tabs.each do |tab| %>
  42 + <li class='tab'><a href='#<%=tab[:id]%>'><%= tab[:title] %></a></li>
  43 + <% end %>
  44 +
38 </ul> 45 </ul>
  46 +
39 <div id='product-description'> 47 <div id='product-description'>
40 <%= render :partial => 'manage_products/display_description' %> 48 <%= render :partial => 'manage_products/display_description' %>
41 </div> 49 </div>
  50 +
42 <div id='product-inputs'> 51 <div id='product-inputs'>
43 <%= render :partial => 'manage_products/display_inputs' %> 52 <%= render :partial => 'manage_products/display_inputs' %>
44 </div> 53 </div>
  54 +
45 <% if @product.price_described? || @allowed_user %> 55 <% if @product.price_described? || @allowed_user %>
46 <div id='product-price-details'> 56 <div id='product-price-details'>
47 <%= render :partial => 'manage_products/display_price_details' %> 57 <%= render :partial => 'manage_products/display_price_details' %>
48 <%= render :partial => 'manage_products/price_details_button' %> 58 <%= render :partial => 'manage_products/price_details_button' %>
49 </div> 59 </div>
50 <% end %> 60 <% end %>
  61 +
  62 + <% plugins_tabs.each do |tab| %>
  63 + <div id='<%=tab[:id]%>'><%= raw tab[:content] %></div>
  64 + <% end %>
  65 +
51 </div> 66 </div>
52 <% end %> 67 <% end %>
53 68
app/views/maps/_google_map.js.erb
@@ -9,7 +9,7 @@ var mapZoom = 15; @@ -9,7 +9,7 @@ var mapZoom = 15;
9 var delay_autocomplete = 500; 9 var delay_autocomplete = 500;
10 10
11 function pointToAddress(latlng) { 11 function pointToAddress(latlng) {
12 - $('location-fields').addClassName("loading"); 12 + jQuery('#location-fields').addClass("loading");
13 13
14 if (latlng == null) 14 if (latlng == null)
15 return; 15 return;
@@ -22,11 +22,11 @@ function pointToAddress(latlng) { @@ -22,11 +22,11 @@ function pointToAddress(latlng) {
22 22
23 var place = results[0]; 23 var place = results[0];
24 24
25 - $('location-fields').removeClassName("loading"); 25 + jQuery('#location-fields').removeClass("loading");
26 26
27 var position = marker.getPosition(); 27 var position = marker.getPosition();
28 - $('profile_data_lat').value = position.lat();  
29 - $('profile_data_lng').value = position.lng(); 28 + jQuery('#profile_data_lat').val(position.lat());
  29 + jQuery('#profile_data_lng').val(position.lng());
30 30
31 form = jQuery('#location-form')[0]; 31 form = jQuery('#location-form')[0];
32 form.lat = marker.getPosition().lat(); 32 form.lat = marker.getPosition().lat();
@@ -85,26 +85,26 @@ function pointToAddress(latlng) { @@ -85,26 +85,26 @@ function pointToAddress(latlng) {
85 } 85 }
86 86
87 if (country_code) 87 if (country_code)
88 - $('profile_data_country').value = country_code; 88 + jQuery('#profile_data_country').val(country_code);
89 if (state) 89 if (state)
90 - $('profile_data_state').value = state; 90 + jQuery('#profile_data_state').val(state);
91 if (city) 91 if (city)
92 - $('profile_data_city').value = city; 92 + jQuery('#profile_data_city').val(city);
93 if (zip_code) 93 if (zip_code)
94 - $('profile_data_zip_code').value = zip_code; 94 + jQuery('#profile_data_zip_code').val(zip_code);
95 if (address) 95 if (address)
96 - $('profile_data_address').value = address; 96 + jQuery('#profile_data_address').val(address);
97 97
98 map.setCenter(marker.getPosition()); 98 map.setCenter(marker.getPosition());
99 }); 99 });
100 } 100 }
101 101
102 function addressToPoint() { 102 function addressToPoint() {
103 - $('location-fields').addClassName("loading"); 103 + jQuery('#location-fields').addClass("loading");
104 104
105 - var country_option = $('profile_data_country').value;  
106 - var address = $('profile_data_address').value + ", " + $('profile_data_zip_code').value + ", "  
107 - + $('profile_data_city').value+ ", " + $('profile_data_state').value + ", " + country_option; 105 + var country_option = jQuery('#profile_data_country').val();
  106 + var address = jQuery('#profile_data_address').val() + ", " + jQuery('#profile_data_zip_code').val() + ", "
  107 + + jQuery('#profile_data_city').val() + ", " + jQuery('#profile_data_state').val() + ", " + country_option;
108 108
109 if (geocoder) { 109 if (geocoder) {
110 geocoder.geocode({ 'address': address}, function(results, status) { 110 geocoder.geocode({ 'address': address}, function(results, status) {
@@ -113,12 +113,12 @@ function addressToPoint() { @@ -113,12 +113,12 @@ function addressToPoint() {
113 marker.setPosition(results[0].geometry.location); 113 marker.setPosition(results[0].geometry.location);
114 pointToAddress(marker.getPosition()); 114 pointToAddress(marker.getPosition());
115 115
116 - $('profile_data_lat').value = results[0].geometry.location.lat();  
117 - $('profile_data_lng').value = results[0].geometry.location.lng();  
118 - $('location-fields').removeClassName("loading"); 116 + jQuery('#profile_data_lat').val(results[0].geometry.location.lat());
  117 + jQuery('#profile_data_lng').val(results[0].geometry.location.lng());
  118 + jQuery('#location-fields').removeClass("loading");
119 enable_save(); 119 enable_save();
120 } else { 120 } else {
121 - $('location-fields').removeClassName("loading"); 121 + jQuery('#location-fields').removeClass("loading");
122 alert('<%=_("Address not found, reason:")%>' + statusErrorMessage(status)); 122 alert('<%=_("Address not found, reason:")%>' + statusErrorMessage(status));
123 } 123 }
124 }); 124 });
@@ -175,7 +175,6 @@ function initializeMap() { @@ -175,7 +175,6 @@ function initializeMap() {
175 175
176 } 176 }
177 177
178 -jQuery.noConflict();  
179 jQuery(document).ready(function () { 178 jQuery(document).ready(function () {
180 179
181 initializeMap(); 180 initializeMap();
@@ -198,7 +197,7 @@ jQuery(document).ready(function () { @@ -198,7 +197,7 @@ jQuery(document).ready(function () {
198 source: "../maps/search_city", 197 source: "../maps/search_city",
199 minLength: 3, 198 minLength: 3,
200 delay: delay_autocomplete, 199 delay: delay_autocomplete,
201 - select: function( event, ui ) { $('profile_data_state').value =( ui.item ? ui.item.category : this.value ); } 200 + select: function( event, ui ) { jQuery('#profile_data_state').val( ui.item ? ui.item.category : this.value ); }
202 }); 201 });
203 202
204 jQuery("#profile_data_state").autocomplete({ 203 jQuery("#profile_data_state").autocomplete({
app/views/profile/_profile_scrap.html.erb
@@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
9 <div class='profile-wall-actions'> 9 <div class='profile-wall-actions'>
10 <% if logged_in? && current_person.follows?(scrap.sender) %> 10 <% if logged_in? && current_person.follows?(scrap.sender) %>
11 <span class='profile-activity-send-reply'> 11 <span class='profile-activity-send-reply'>
12 - <%= link_to_function s_('profile|Comment'), "hide_and_show(['#profile-wall-message-response-#{scrap.id}'],['#profile-wall-reply-#{scrap.id}', '#profile-wall-reply-form-#{scrap.id}']);$('reply_content_#{scrap.id}').value='';$('reply_content_#{scrap.id}').focus();return false", :class => "profile-send-reply" %> 12 + <%= link_to_function s_('profile|Comment'), "hide_and_show(['#profile-wall-message-response-#{scrap.id}'],['#profile-wall-reply-#{scrap.id}', '#profile-wall-reply-form-#{scrap.id}']);jQuery('#reply_content_#{scrap.id}').val('');jQuery('#reply_content_#{scrap.id}').focus();return false", :class => "profile-send-reply" %>
13 </span> 13 </span>
14 <% end %> 14 <% end %>
15 <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_scrap, :scrap_id => scrap.id, :view => params[:view]), _('Are you sure you want to remove this scrap and all its replies?')]) if logged_in? && user.can_control_scrap?(scrap) %> 15 <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_scrap, :scrap_id => scrap.id, :view => params[:view]), _('Are you sure you want to remove this scrap and all its replies?')]) if logged_in? && user.can_control_scrap?(scrap) %>
app/views/profile/_profile_scraps.html.erb
@@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
9 <div class='profile-wall-actions'> 9 <div class='profile-wall-actions'>
10 <% if logged_in? && current_person.follows?(scrap.sender) %> 10 <% if logged_in? && current_person.follows?(scrap.sender) %>
11 <span class='profile-activity-send-reply'> 11 <span class='profile-activity-send-reply'>
12 - <%= link_to_function s_('profile|Comment'), "hide_and_show(['#profile-wall-message-response-#{scrap.id}'],['#profile-wall-reply-#{scrap.id}', '#profile-wall-reply-form-#{scrap.id}']);$('reply_content_#{scrap.id}').value='';$('reply_content_#{scrap.id}').focus();return false", :class => "profile-send-reply" %> 12 + <%= link_to_function s_('profile|Comment'), "hide_and_show(['#profile-wall-message-response-#{scrap.id}'],['#profile-wall-reply-#{scrap.id}', '#profile-wall-reply-form-#{scrap.id}']);jQuery('#reply_content_#{scrap.id}').val('');jQuery('#reply_content_#{scrap.id}').focus();return false", :class => "profile-send-reply" %>
13 </span> 13 </span>
14 <% end %> 14 <% end %>
15 <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_scrap, :scrap_id => scrap.id, :view => params[:view]), _('Are you sure you want to remove this scrap and all its replies?')]) if logged_in? && user.can_control_scrap?(scrap) %> 15 <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_scrap, :scrap_id => scrap.id, :view => params[:view]), _('Are you sure you want to remove this scrap and all its replies?')]) if logged_in? && user.can_control_scrap?(scrap) %>
app/views/profile/_profile_wall.html.erb
1 <h3><%= _("%s's wall") % @profile.name %></h3> 1 <h3><%= _("%s's wall") % @profile.name %></h3>
2 <div id='leave_scrap'> 2 <div id='leave_scrap'>
3 <%= flash[:error] %> 3 <%= flash[:error] %>
4 - <%= form_remote_tag :url => {:controller => 'profile', :action => 'leave_scrap', :tab_action => 'wall' }, :update => 'profile_activities', :success => "$('leave_scrap_content').value=''", :complete => "jQuery('#leave_scrap_form').removeClass('loading').find('*').attr('disabled', false)", :loading => "jQuery('#leave_scrap_form').addClass('loading').find('*').attr('disabled', true)", :html => {:id => 'leave_scrap_form' } do %> 4 + <%= form_remote_tag :url => {:controller => 'profile', :action => 'leave_scrap', :tab_action => 'wall' }, :update => 'profile_activities', :success => "jQuery('#leave_scrap_content').val('')", :complete => "jQuery('#leave_scrap_form').removeClass('loading').find('*').attr('disabled', false)", :loading => "jQuery('#leave_scrap_form').addClass('loading').find('*').attr('disabled', true)", :html => {:id => 'leave_scrap_form' } do %>
5 <%= limited_text_area :scrap, :content, 420, 'leave_scrap_content', :cols => 50, :rows => 2, :class => 'autogrow' %> 5 <%= limited_text_area :scrap, :content, 420, 'leave_scrap_content', :cols => 50, :rows => 2, :class => 'autogrow' %>
6 <%= submit_button :new, _('Share') %> 6 <%= submit_button :new, _('Share') %>
7 <% end %> 7 <% end %>
app/views/profile/join.html.erb
@@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
9 <%= hidden_field_tag(:confirmation, 1) %> 9 <%= hidden_field_tag(:confirmation, 1) %>
10 <%= submit_button(:ok, _("Yes, I want to join.") % profile.name) %> 10 <%= submit_button(:ok, _("Yes, I want to join.") % profile.name) %>
11 <% if logged_in? && request.xhr? %> 11 <% if logged_in? && request.xhr? %>
12 - <%= lightbox_close_button(_("No, I don't want")) %> 12 + <%= modal_close_button _("No, I don't want") %>
13 <% else %> 13 <% else %>
14 <%= button(:cancel, _("No, I don't want."), profile.url) %> 14 <%= button(:cancel, _("No, I don't want."), profile.url) %>
15 <% end %> 15 <% end %>
app/views/profile/leave.html.erb
@@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
9 <%= hidden_field_tag(:back_to, @back_to) %> 9 <%= hidden_field_tag(:back_to, @back_to) %>
10 <%= submit_button(:ok, _("Yes, I want to leave.") % profile.name) %> 10 <%= submit_button(:ok, _("Yes, I want to leave.") % profile.name) %>
11 <% if logged_in? && request.xhr? %> 11 <% if logged_in? && request.xhr? %>
12 - <%= lightbox_close_button(_("No, I don't want")) %> 12 + <%= modal_close_button _("No, I don't want") %>
13 <% else %> 13 <% else %>
14 <%= button(:cancel, _("No, I don't want."), profile.url) %> 14 <%= button(:cancel, _("No, I don't want."), profile.url) %>
15 <% end %> 15 <% end %>
app/views/profile/report_abuse.html.erb
@@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
9 <% end %> 9 <% end %>
10 10
11 <%= submit_button(:send, _('Report profile'), :style => 'float: left; cursor: pointer;', :id => 'report-abuse-submit-button', :onclick => "jQuery('#form-submit-loading').show()") %> 11 <%= submit_button(:send, _('Report profile'), :style => 'float: left; cursor: pointer;', :id => 'report-abuse-submit-button', :onclick => "jQuery('#form-submit-loading').show()") %>
12 - <%= button(:cancel, _('Cancel'), {}, :style => 'float: left; padding-top: 0px; padding-bottom: 0px;', :onclick => 'jQuery.colorbox.close(); return false;')%> 12 + <%= button(:cancel, _('Cancel'), {}, :style => 'float: left; padding-top: 0px; padding-bottom: 0px;', :onclick => 'noosfero.modal.close(); return false;')%>
13 <div id="form-submit-loading" class="small-loading" style="width: 16px; height: 16px; margin-top: 3px; float: left; display: none;"></div> 13 <div id="form-submit-loading" class="small-loading" style="width: 16px; height: 16px; margin-top: 3px; float: left; display: none;"></div>
14 <% end %> 14 <% end %>
15 15
@@ -30,7 +30,7 @@ @@ -30,7 +30,7 @@
30 success: function(data, status, ajax){ 30 success: function(data, status, ajax){
31 if ( !data.ok ) display_notice(data.error.message); 31 if ( !data.ok ) display_notice(data.error.message);
32 else { 32 else {
33 - $.colorbox.close(); 33 + noosfero.modal.close();
34 display_notice(data.message); 34 display_notice(data.message);
35 window.location.reload(); 35 window.location.reload();
36 } 36 }
app/views/profile_editor/_organization.html.erb
@@ -19,7 +19,7 @@ @@ -19,7 +19,7 @@
19 <% if @environment.enabled?('enable_organization_url_change') %> 19 <% if @environment.enabled?('enable_organization_url_change') %>
20 <script type="text/javascript"> 20 <script type="text/javascript">
21 function submit_button() { 21 function submit_button() {
22 - return $("profile-data").select("input.submit")[0]; 22 + return jQuery("#profile-data").find("input.submit")[0];
23 } 23 }
24 function warn_value_change() { 24 function warn_value_change() {
25 show_warning('profile-identifier-formitem', "identifier-change-confirmation"); 25 show_warning('profile-identifier-formitem', "identifier-change-confirmation");
@@ -30,7 +30,7 @@ @@ -30,7 +30,7 @@
30 hide_warning('identifier-change-confirmation'); 30 hide_warning('identifier-change-confirmation');
31 } 31 }
32 function no_change() { 32 function no_change() {
33 - $("profile_data_identifier").value = $("old_profile_identifier").value; 33 + jQuery("#profile_data_identifier").val(jQuery("#old_profile_identifier").val());
34 enable_button(submit_button()); 34 enable_button(submit_button());
35 hide_warning('identifier-change-confirmation'); 35 hide_warning('identifier-change-confirmation');
36 } 36 }
app/views/profile_members/_add_admins.html.erb
1 <h2><%= _('Add admins to %s') % profile.name %></h2> 1 <h2><%= _('Add admins to %s') % profile.name %></h2>
2 2
3 -<%= form_remote_tag :url => {:action => 'find_users', :profile => profile.identifier, :scope => 'new_admins'}, :update => 'users-list', :loading => '$("users-list").addClassName("loading")', :complete => '$("users-list").removeClassName("loading")' do %> 3 +<%= form_remote_tag :url => {:action => 'find_users', :profile => profile.identifier, :scope => 'new_admins'}, :update => 'users-list', :loading => 'jQuery("#users-list").addClass("loading")', :complete => 'jQuery("#users-list").removeClass("loading")' do %>
4 <%= text_field_tag('query', '', :autocomplete => 'off') %> 4 <%= text_field_tag('query', '', :autocomplete => 'off') %>
5 <%= submit_tag(_('Search')) %> 5 <%= submit_tag(_('Search')) %>
6 <% end %> 6 <% end %>
7 7
8 -<%= observe_field('query', :url => {:action => 'find_users', :profile => profile.identifier, :scope => 'new_admins'}, :update => 'users-list', :frequency => 1, :with => 'query', :condition => '$("query").value.length > 2', :loading => '$("users-list").addClassName("loading")', :complete => '$("users-list").removeClassName("loading")') %>  
9 -<%= observe_field('query', :frequency => 1, :condition => '$("query").value.length <= 2', :function => '$("users-list").update($("empty-query").innerHTML)') %> 8 +<%= observe_field('query', :url => {:action => 'find_users', :profile => profile.identifier, :scope => 'new_admins'}, :update => 'users-list', :frequency => 1, :with => 'query', :condition => 'jQuery("#query").val().length > 2', :loading => 'jQuery("#users-list").addClass("loading")', :complete => 'jQuery("#users-list").removeClass("loading")') %>
  9 +<%= observe_field('query', :frequency => 1, :condition => 'jQuery("#query").val().length <= 2', :function => 'jQuery("#users-list").html(jQuery("#empty-query").html())') %>
10 10
11 <div id="users-list"> 11 <div id="users-list">
12 <%= render :partial => 'find_users' %> 12 <%= render :partial => 'find_users' %>
@@ -21,10 +21,10 @@ @@ -21,10 +21,10 @@
21 </div> 21 </div>
22 <%= drop_receiving_element('members-list', 22 <%= drop_receiving_element('members-list',
23 :url => {:action => 'add_admin', :profile => profile.identifier, :leaving_admin => @person}, 23 :url => {:action => 'add_admin', :profile => profile.identifier, :leaving_admin => @person},
24 - :before => '$("tr-" + element.id).hide()',  
25 - :loading => '$("members-list").addClassName("loading")', 24 + :before => 'jQuery("#tr-" + element.id).hide()',
  25 + :loading => 'jQuery("#members-list").addClass("loading")',
26 :update => 'members-list', 26 :update => 'members-list',
27 - :success => '$("tr-" + element.id).hide(); $(element.id).show();',  
28 - :complete => '$("members-list").removeClassName("loading")') %> 27 + :success => 'jQuery("#tr-" + element.id).hide(); jQuery("#"+element.id).show();',
  28 + :complete => 'jQuery("#members-list").removeClass("loading")') %>
29 29
30 <br style="clear:both" /> 30 <br style="clear:both" />
app/views/profile_members/_members_list.html.erb
@@ -17,9 +17,9 @@ @@ -17,9 +17,9 @@
17 <%= button_without_text :edit, _('Edit'), :action => 'change_role', :id => m %> 17 <%= button_without_text :edit, _('Edit'), :action => 'change_role', :id => m %>
18 <%= button_to_remote_without_text(:remove, _('Remove'), 18 <%= button_to_remote_without_text(:remove, _('Remove'),
19 :update => 'members-list', 19 :update => 'members-list',
20 - :loading => "$('members-list').addClassName('loading')",  
21 - :success => "$('tr-#{m.identifier}').show()",  
22 - :complete => "$('members-list').removeClassName('loading')", 20 + :loading => "jQuery('#members-list').addClass('loading')",
  21 + :success => "jQuery('#tr-#{m.identifier}').show()",
  22 + :complete => "jQuery('#members-list').removeClass('loading')",
23 :url => { :id => m }.merge(remove_action)) if m != user %> 23 :url => { :id => m }.merge(remove_action)) if m != user %>
24 </div> 24 </div>
25 </td> 25 </td>
app/views/profile_themes/add_css.html.erb
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 5
6 <% button_bar do %> 6 <% button_bar do %>
7 <%= submit_button(:add, _('Add')) %> 7 <%= submit_button(:add, _('Add')) %>
8 - <%= lightbox_close_button(_('Cancel')) %> 8 + <%= modal_close_button _('Cancel') %>
9 <% end %> 9 <% end %>
10 10
11 <% end %> 11 <% end %>
app/views/profile_themes/edit.html.erb
@@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
16 <% end %> 16 <% end %>
17 </ul> 17 </ul>
18 <% button_bar do %> 18 <% button_bar do %>
19 - <%= lightbox_button(:add, _('New CSS'), :action => 'add_css', :id => @theme.id) %> 19 + <%= modal_button :add, _('New CSS'), :action => 'add_css', :id => @theme.id %>
20 <% end %> 20 <% end %>
21 </div> 21 </div>
22 22
@@ -25,10 +25,10 @@ @@ -25,10 +25,10 @@
25 <ul> 25 <ul>
26 <% for image in @image_files %> 26 <% for image in @image_files %>
27 <li><%= image_tag("/user_themes/#{@theme.id}/images/#{image}") %></li> 27 <li><%= image_tag("/user_themes/#{@theme.id}/images/#{image}") %></li>
28 - <% end %> 28 + <% end %>
29 </ul> 29 </ul>
30 <% button_bar do %> 30 <% button_bar do %>
31 - <%= lightbox_button(:add, _('Add image'), :action => 'add_image', :id => @theme.id) %> 31 + <%= modal_button :add, _('Add image'), :action => 'add_image', :id => @theme.id %>
32 <% end %> 32 <% end %>
33 </div> 33 </div>
34 34
app/views/profile_themes/index.html.erb
@@ -42,7 +42,7 @@ @@ -42,7 +42,7 @@
42 42
43 <% button_bar do %> 43 <% button_bar do %>
44 <% if environment.enabled?('user_themes') %> 44 <% if environment.enabled?('user_themes') %>
45 - <%= lightbox_button(:add, _('New theme ...'), :action => 'new') %> 45 + <%= modal_button :add, _('New theme ...'), :action => 'new' %>
46 <% end %> 46 <% end %>
47 <%= button(:back, _('Back'), :controller => 'profile_editor', :action => 'index') %> 47 <%= button(:back, _('Back'), :controller => 'profile_editor', :action => 'index') %>
48 <% end %> 48 <% end %>
app/views/shared/logged_in/xmpp_chat.html.erb
@@ -12,33 +12,27 @@ @@ -12,33 +12,27 @@
12 var $presence = '<%= current_user.last_chat_status %>'; 12 var $presence = '<%= current_user.last_chat_status %>';
13 </script> 13 </script>
14 14
  15 +
  16 + <div id="chat-label">
  17 + <span class="right-arrow">&#9654;</span>
  18 + <span class="title"><%= _('Chat') %></span>
  19 + </div>
  20 +
15 <div id='chat'> 21 <div id='chat'>
16 <div id='buddy-list'> 22 <div id='buddy-list'>
17 <div class='toolbar'> 23 <div class='toolbar'>
18 <div id='user-status'> 24 <div id='user-status'>
19 - <%= profile_image(user, :portrait, :class => 'avatar') %>  
20 <%= user_status_menu('icon-menu-offline', _('Offline')) %> 25 <%= user_status_menu('icon-menu-offline', _('Offline')) %>
21 </div> 26 </div>
22 - <a href="#" class="back"><%= _('Close') %></a>  
23 <div class='dialog-error' style='display: none'></div> 27 <div class='dialog-error' style='display: none'></div>
24 </div> 28 </div>
25 29
26 - <div id="friends">  
27 - <div class="status-group">  
28 - <div class='title-bar'><a href="#"><h1 class='title'><%= _("Online") %>&nbsp;(<span id='friends-online'>0</span>)</h1></a></div>  
29 - <ul class='buddy-list online'></ul>  
30 - </div>  
31 -  
32 - <div class="status-group">  
33 - <div class='title-bar'><a href="#"><h1 class='title'><%= _("Offline") %>&nbsp;(<span id='friends-offline'>0</span>)</h1></a></div>  
34 - <ul class='buddy-list offline'></ul>  
35 - </div>  
36 - </div> 30 + <div class='body'>
  31 + <%= text_field_tag(:query, '', :placeholder => _('Search...'), :class => 'search') %>
37 32
38 - <div id="rooms">  
39 - <div class="status-group">  
40 - <div class='title-bar'><a href="#"><h1 class='title'><%= _("Groups") %>&nbsp;(<span id='groups-online'>0</span>)</h1></a></div>  
41 - <ul class="buddy-list room-list"></ul> 33 + <div class='buddies'>
  34 + <ul class='online'></ul>
  35 + <ul class='offline'></ul>
42 </div> 36 </div>
43 </div> 37 </div>
44 </div> 38 </div>
@@ -47,37 +41,37 @@ @@ -47,37 +41,37 @@
47 <div id='conversations'></div> 41 <div id='conversations'></div>
48 </div> 42 </div>
49 43
50 - <div id="chat-templates"> 44 + <div id="chat-templates" style="display: none;">
51 45
52 - <div class="conversation-template">  
53 - <div class='conversation' style="display: none;">  
54 - <div class="header">  
55 - <span class="chat-target">  
56 - <img class="avatar">  
57 - <span class="other-name"></span>  
58 - </span>  
59 - <a href="#" class="back"><%= _('Back') %></a>  
60 - </div>  
61 - <div class='history'></div>  
62 - <div class='input-div'>  
63 - <div class='icon-chat'></div>  
64 - <textarea class='input'></textarea>  
65 - </div> 46 + <div class="conversation">
  47 + <div class="conversation-header">
  48 + <span class="chat-target">
  49 + <img class="avatar">
  50 + <span class="other-name"></span>
  51 + </span>
  52 + </div>
  53 + <div class='history'></div>
  54 + <div class='input-div'>
  55 + <div class='icon-chat'></div>
  56 + <textarea class='input'></textarea>
66 </div> 57 </div>
67 </div> 58 </div>
68 59
  60 + <a class='join room-action'><%= _('Join room') %></a>
  61 + <a class='leave room-action' style="display: none"><%= _('Leave room') %></a>
  62 +
69 <div class="buddy-item"> 63 <div class="buddy-item">
70 <li class='%{presence_status}'> 64 <li class='%{presence_status}'>
71 <a id='%{jid_id}' class='icon-menu-%{presence_status}-11' href='#'> 65 <a id='%{jid_id}' class='icon-menu-%{presence_status}-11' href='#'>
  66 + <span class="unread-messages"></span>
72 %{avatar} 67 %{avatar}
73 <span class="name">%{name}</span> 68 <span class="name">%{name}</span>
74 - <span class="unread-messages icon-chat"></span>  
75 </a> 69 </a>
76 </li> 70 </li>
77 </div> 71 </div>
78 72
79 <div class="occupant-list-template"> 73 <div class="occupant-list-template">
80 - <div class="occupants"> 74 + <div class="occupants room-action">
81 <a href="#" class="up"><%= _('Online') %>&nbsp;(<span class="occupants-online">0</span>)</a> 75 <a href="#" class="up"><%= _('Online') %>&nbsp;(<span class="occupants-online">0</span>)</a>
82 <ul class='occupant-list'></ul> 76 <ul class='occupant-list'></ul>
83 </div> 77 </div>
@@ -86,20 +80,20 @@ @@ -86,20 +80,20 @@
86 <div class="occupant-item"> 80 <div class="occupant-item">
87 <li class='%{presence_status}'> 81 <li class='%{presence_status}'>
88 <a data-id='%{jid_id}' class='icon-menu-%{presence_status}-11' href='#'> 82 <a data-id='%{jid_id}' class='icon-menu-%{presence_status}-11' href='#'>
  83 + <span class="unread-messages"></span>
89 %{avatar} 84 %{avatar}
90 - <span class="name">%{name}</span> 85 + <span class="name">%{name}<span>
91 </a> 86 </a>
92 </li> 87 </li>
93 </div> 88 </div>
94 89
95 <div class="message"> 90 <div class="message">
96 <div data-who="%{who}" class="message %{who}"> 91 <div data-who="%{who}" class="message %{who}">
97 - <div class="author">  
98 - %{avatar}  
99 - <h5 class="%{who}-name">%{name}</h5>  
100 - </div>  
101 <div class="content"> 92 <div class="content">
102 <span class="time" title="%{time}"></span> 93 <span class="time" title="%{time}"></span>
  94 + <div class="author">
  95 + %{avatar}
  96 + </div>
103 <p>%{message}</p> 97 <p>%{message}</p>
104 </div> 98 </div>
105 </div> 99 </div>
@@ -111,3 +105,7 @@ @@ -111,3 +105,7 @@
111 105
112 </div> 106 </div>
113 </div> 107 </div>
  108 + <a href='#' id='chat-online-users-title' onclick='return false;'>
  109 + <div class='header'><i class='icon-chat'></i><span><%= _("Friends in chat (<span class='amount_of_friends'>%{amount}</span>)") %></span></div>
  110 + </a>
  111 +</div>
app/views/shared/profile_actions/xmpp_chat.html.erb
@@ -1,5 +0,0 @@ @@ -1,5 +0,0 @@
1 -<% if profile.members.include?(user) %>  
2 - <li>  
3 - <%= button_to_function(:chat, _('Enter chat room'), "open_chat_window(this, '##{profile.full_jid}')") %>  
4 - </li>  
5 -<% end %>  
app/views/shared/user_menu.html.erb
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 </li> 20 </li>
21 21
22 <li> 22 <li>
23 - <%= lightbox_link_to('<span class="icon-new"></span>' + _('New article'), '/myprofile/{login}/cms/new') %> 23 + <%= modal_link_to '<span class="icon-new"></span>' + _('New article'), '/myprofile/{login}/cms/new' %>
24 </li> 24 </li>
25 25
26 <li id='manage-enterprises-link-template' style='display: none'><a href='/myprofile/{identifier}'><span class="icon-menu-enterprise"></span><%= _('Manage %s') % '{name}' %></a></li> 26 <li id='manage-enterprises-link-template' style='display: none'><a href='/myprofile/{identifier}'><span class="icon-menu-enterprise"></span><%= _('Manage %s') % '{name}' %></a></li>
@@ -58,9 +58,9 @@ @@ -58,9 +58,9 @@
58 <% if theme_option( :menu_login ) == 'full_form' %> 58 <% if theme_option( :menu_login ) == 'full_form' %>
59 <%= render :file => 'account/login_block' %> 59 <%= render :file => 'account/login_block' %>
60 <% else %> 60 <% else %>
61 - <%= thickbox_inline_popup_link('<span class="icon-menu-login"></span>'+ _('Login'), login_url, 'inlineLoginBox', :id => 'link_login') %> 61 + <%= modal_inline_link_to('<span class="icon-menu-login"></span>'+ _('Login'), login_url, '#inlineLoginBox', :id => 'link_login') %>
62 <div id='inlineLoginBox' style='display: none;'> 62 <div id='inlineLoginBox' style='display: none;'>
63 - <%= render :file => 'account/login', :locals => { :is_thickbox => true } %> 63 + <%= render :file => 'account/login', :locals => { :is_popin => true } %>
64 </div> 64 </div>
65 <% end %> 65 <% end %>
66 <% end %> 66 <% end %>
app/views/shared/usermenu/xmpp_chat.html.erb
@@ -1 +0,0 @@ @@ -1 +0,0 @@
1 -<%= link_to('<i class="icon-chat"></i><span class="unread-messages"></span>&nbsp;<strong>' + _('Open chat') +'</strong>', '#', :id => 'openchat', :onclick => 'open_chat_window(this)') %>  
config/application.rb
1 require File.expand_path('../boot', __FILE__) 1 require File.expand_path('../boot', __FILE__)
2 2
3 require 'rails/all' 3 require 'rails/all'
  4 +require 'active_support/dependencies'
4 5
5 # FIXME this silences the warnings about Rails 2.3-style plugins under 6 # FIXME this silences the warnings about Rails 2.3-style plugins under
6 # vendor/plugins, which are deprecated. Hiding those warnings makes it easier 7 # vendor/plugins, which are deprecated. Hiding those warnings makes it easier
config/database.yml.multitenancy
1 # Refer to INSTALL.multitenancy for more information on Multitenancy support 1 # Refer to INSTALL.multitenancy for more information on Multitenancy support
2 -env1_production: 2 +env1_production: &DEFAULT
3 adapter: postgresql 3 adapter: postgresql
4 encoding: unicode 4 encoding: unicode
5 database: noosfero 5 database: noosfero
@@ -30,4 +30,4 @@ env3_production: @@ -30,4 +30,4 @@ env3_production:
30 - env3.net 30 - env3.net
31 31
32 production: 32 production:
33 - env1_production 33 + <<: *DEFAULT
config/noosfero.yml.dist
@@ -9,6 +9,7 @@ development: @@ -9,6 +9,7 @@ development:
9 googlemaps_initial_zoom: 4 9 googlemaps_initial_zoom: 4
10 exception_recipients: [admin@example.com] 10 exception_recipients: [admin@example.com]
11 max_upload_size: 5MB 11 max_upload_size: 5MB
  12 + hours_until_user_activation_check: 72
12 13
13 test: 14 test:
14 15
config/schedule.rb
@@ -25,6 +25,6 @@ every 1.day do @@ -25,6 +25,6 @@ every 1.day do
25 runner "SearchTerm.calculate_scores" 25 runner "SearchTerm.calculate_scores"
26 end 26 end
27 27
28 -every 90.days do 28 +every 30.days do
29 runner "ProfileSuggestion.generate_all_profile_suggestions" 29 runner "ProfileSuggestion.generate_all_profile_suggestions"
30 end 30 end
db/migrate/20120820120000_index_parent_id_from_all_tables.rb 0 → 100644
@@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
  1 +class IndexParentIdFromAllTables < ActiveRecord::Migration
  2 + def self.up
  3 + add_index :article_versions, :parent_id
  4 + add_index :categories, :parent_id
  5 + add_index :images, :parent_id
  6 + add_index :tags, :parent_id
  7 + add_index :thumbnails, :parent_id
  8 + end
  9 +
  10 + def self.down
  11 + remove_index :article_versions, :parent_id
  12 + remove_index :categories, :parent_id
  13 + remove_index :images, :parent_id
  14 + remove_index :tags, :parent_id
  15 + remove_index :thumbnails, :parent_id
  16 + end
  17 +end
db/migrate/20120820142056_add_ancestry_to_categories.rb 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +class AddAncestryToCategories < ActiveRecord::Migration
  2 + def self.up
  3 + add_column :categories, :ancestry, :text
  4 +
  5 + Category.build_ancestry
  6 + end
  7 +
  8 + def self.down
  9 + remove_column :categories, :ancestry
  10 + end
  11 +end
db/migrate/20140519113821_add_last_login_at_to_user.rb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +class AddLastLoginAtToUser < ActiveRecord::Migration
  2 + def self.up
  3 + add_column :users, :last_login_at, :datetime
  4 + end
  5 +
  6 + def self.down
  7 + remove_column :users, :last_login_at
  8 + end
  9 +end
db/migrate/20140709212646_add_spam_comments_counter_cache_to_articles.rb
@@ -3,7 +3,7 @@ class AddSpamCommentsCounterCacheToArticles &lt; ActiveRecord::Migration @@ -3,7 +3,7 @@ class AddSpamCommentsCounterCacheToArticles &lt; ActiveRecord::Migration
3 add_column :articles, :spam_comments_count, :integer, :default => 0 3 add_column :articles, :spam_comments_count, :integer, :default => 0
4 add_column :article_versions, :spam_comments_count, :integer, :default => 0 4 add_column :article_versions, :spam_comments_count, :integer, :default => 0
5 5
6 - execute("SELECT comments.source_id as source_id, count(comments.id) as comments_count FROM comments LEFT OUTER JOIN articles ON articles.id = source_id WHERE comments.source_type = 'Article' AND comments.spam = 't' GROUP BY comments.source_id;").each do |data| 6 + execute("SELECT comments.source_id as source_id, count(comments.id) as comments_count FROM comments LEFT OUTER JOIN articles ON articles.id = source_id WHERE comments.source_type = 'Article' AND comments.spam = true GROUP BY comments.source_id;").each do |data|
7 execute("UPDATE articles SET spam_comments_count = '#{data['comments_count']}' WHERE id = #{data['source_id']}") 7 execute("UPDATE articles SET spam_comments_count = '#{data['comments_count']}' WHERE id = #{data['source_id']}")
8 end 8 end
9 end 9 end
db/migrate/20150112233715_normalize_users_email.rb 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +class NormalizeUsersEmail < ActiveRecord::Migration
  2 + def up
  3 + User.find_each do |u|
  4 + u.update_column :email, u.send(:normalize_email)
  5 + end
  6 + end
  7 +
  8 + def down
  9 + say "this migration can't be reverted"
  10 + end
  11 +end
@@ -101,6 +101,7 @@ ActiveRecord::Schema.define(:version =&gt; 20150122165042) do @@ -101,6 +101,7 @@ ActiveRecord::Schema.define(:version =&gt; 20150122165042) do
101 end 101 end
102 102
103 add_index "article_versions", ["article_id"], :name => "index_article_versions_on_article_id" 103 add_index "article_versions", ["article_id"], :name => "index_article_versions_on_article_id"
  104 + add_index "article_versions", ["parent_id"], :name => "index_article_versions_on_parent_id"
104 add_index "article_versions", ["path", "profile_id"], :name => "index_article_versions_on_path_and_profile_id" 105 add_index "article_versions", ["path", "profile_id"], :name => "index_article_versions_on_path_and_profile_id"
105 add_index "article_versions", ["path"], :name => "index_article_versions_on_path" 106 add_index "article_versions", ["path"], :name => "index_article_versions_on_path"
106 add_index "article_versions", ["published_at", "id"], :name => "index_article_versions_on_published_at_and_id" 107 add_index "article_versions", ["published_at", "id"], :name => "index_article_versions_on_published_at_and_id"
@@ -217,8 +218,11 @@ ActiveRecord::Schema.define(:version =&gt; 20150122165042) do @@ -217,8 +218,11 @@ ActiveRecord::Schema.define(:version =&gt; 20150122165042) do
217 t.string "acronym" 218 t.string "acronym"
218 t.string "abbreviation" 219 t.string "abbreviation"
219 t.string "display_color", :limit => 6 220 t.string "display_color", :limit => 6
  221 + t.text "ancestry"
220 end 222 end
221 223
  224 + add_index "categories", ["parent_id"], :name => "index_categories_on_parent_id"
  225 +
222 create_table "categories_profiles", :id => false, :force => true do |t| 226 create_table "categories_profiles", :id => false, :force => true do |t|
223 t.integer "profile_id" 227 t.integer "profile_id"
224 t.integer "category_id" 228 t.integer "category_id"
@@ -237,6 +241,14 @@ ActiveRecord::Schema.define(:version =&gt; 20150122165042) do @@ -237,6 +241,14 @@ ActiveRecord::Schema.define(:version =&gt; 20150122165042) do
237 t.datetime "updated_at" 241 t.datetime "updated_at"
238 end 242 end
239 243
  244 + create_table "chat_messages", :force => true do |t|
  245 + t.integer "to_id"
  246 + t.integer "from_id"
  247 + t.string "body"
  248 + t.datetime "created_at", :null => false
  249 + t.datetime "updated_at", :null => false
  250 + end
  251 +
240 create_table "comments", :force => true do |t| 252 create_table "comments", :force => true do |t|
241 t.string "title" 253 t.string "title"
242 t.text "body" 254 t.text "body"
@@ -251,6 +263,8 @@ ActiveRecord::Schema.define(:version =&gt; 20150122165042) do @@ -251,6 +263,8 @@ ActiveRecord::Schema.define(:version =&gt; 20150122165042) do
251 t.string "source_type" 263 t.string "source_type"
252 t.string "user_agent" 264 t.string "user_agent"
253 t.string "referrer" 265 t.string "referrer"
  266 + t.text "setting"
  267 + t.integer "paragraph_id"
254 end 268 end
255 269
256 add_index "comments", ["source_id", "spam"], :name => "index_comments_on_source_id_and_spam" 270 add_index "comments", ["source_id", "spam"], :name => "index_comments_on_source_id_and_spam"
@@ -357,6 +371,8 @@ ActiveRecord::Schema.define(:version =&gt; 20150122165042) do @@ -357,6 +371,8 @@ ActiveRecord::Schema.define(:version =&gt; 20150122165042) do
357 t.boolean "thumbnails_processed", :default => false 371 t.boolean "thumbnails_processed", :default => false
358 end 372 end
359 373
  374 + add_index "images", ["parent_id"], :name => "index_images_on_parent_id"
  375 +
360 create_table "inputs", :force => true do |t| 376 create_table "inputs", :force => true do |t|
361 t.integer "product_id", :null => false 377 t.integer "product_id", :null => false
362 t.integer "product_category_id", :null => false 378 t.integer "product_category_id", :null => false
@@ -650,6 +666,7 @@ ActiveRecord::Schema.define(:version =&gt; 20150122165042) do @@ -650,6 +666,7 @@ ActiveRecord::Schema.define(:version =&gt; 20150122165042) do
650 end 666 end
651 667
652 add_index "tags", ["name"], :name => "index_tags_on_name", :unique => true 668 add_index "tags", ["name"], :name => "index_tags_on_name", :unique => true
  669 + add_index "tags", ["parent_id"], :name => "index_tags_on_parent_id"
653 670
654 create_table "tasks", :force => true do |t| 671 create_table "tasks", :force => true do |t|
655 t.text "data" 672 t.text "data"
@@ -689,6 +706,8 @@ ActiveRecord::Schema.define(:version =&gt; 20150122165042) do @@ -689,6 +706,8 @@ ActiveRecord::Schema.define(:version =&gt; 20150122165042) do
689 t.string "thumbnail" 706 t.string "thumbnail"
690 end 707 end
691 708
  709 + add_index "thumbnails", ["parent_id"], :name => "index_thumbnails_on_parent_id"
  710 +
692 create_table "units", :force => true do |t| 711 create_table "units", :force => true do |t|
693 t.string "singular", :null => false 712 t.string "singular", :null => false
694 t.string "plural", :null => false 713 t.string "plural", :null => false
@@ -699,23 +718,26 @@ ActiveRecord::Schema.define(:version =&gt; 20150122165042) do @@ -699,23 +718,26 @@ ActiveRecord::Schema.define(:version =&gt; 20150122165042) do
699 create_table "users", :force => true do |t| 718 create_table "users", :force => true do |t|
700 t.string "login" 719 t.string "login"
701 t.string "email" 720 t.string "email"
702 - t.string "crypted_password", :limit => 40  
703 - t.string "salt", :limit => 40 721 + t.string "crypted_password", :limit => 40
  722 + t.string "salt", :limit => 40
704 t.datetime "created_at" 723 t.datetime "created_at"
705 t.datetime "updated_at" 724 t.datetime "updated_at"
706 t.string "remember_token" 725 t.string "remember_token"
707 t.datetime "remember_token_expires_at" 726 t.datetime "remember_token_expires_at"
708 t.text "terms_of_use" 727 t.text "terms_of_use"
709 - t.string "terms_accepted", :limit => 1 728 + t.string "terms_accepted", :limit => 1
710 t.integer "environment_id" 729 t.integer "environment_id"
711 t.string "password_type" 730 t.string "password_type"
712 - t.boolean "enable_email", :default => false  
713 - t.string "last_chat_status", :default => ""  
714 - t.string "chat_status", :default => "" 731 + t.boolean "enable_email", :default => false
  732 + t.string "last_chat_status", :default => ""
  733 + t.string "chat_status", :default => ""
715 t.datetime "chat_status_at" 734 t.datetime "chat_status_at"
716 - t.string "activation_code", :limit => 40 735 + t.string "activation_code", :limit => 40
717 t.datetime "activated_at" 736 t.datetime "activated_at"
718 t.string "return_to" 737 t.string "return_to"
  738 + t.datetime "last_login_at"
  739 + t.string "private_token"
  740 + t.datetime "private_token_generated_at"
719 end 741 end
720 742
721 create_table "validation_infos", :force => true do |t| 743 create_table "validation_infos", :force => true do |t|
debian/control
@@ -48,7 +48,6 @@ Depends: adduser, @@ -48,7 +48,6 @@ Depends: adduser,
48 ruby-feedparser, 48 ruby-feedparser,
49 ruby-feedparser (>= 0.7-3~), 49 ruby-feedparser (>= 0.7-3~),
50 ruby-gettext, 50 ruby-gettext,
51 - ruby-hpricot,  
52 ruby-memcache-client, 51 ruby-memcache-client,
53 ruby-minitest, 52 ruby-minitest,
54 ruby-nokogiri, 53 ruby-nokogiri,
features/events.feature
@@ -9,6 +9,7 @@ Feature: events @@ -9,6 +9,7 @@ Feature: events
9 And the following events 9 And the following events
10 | owner | name | start_date | 10 | owner | name | start_date |
11 | josesilva | Another Conference | 2009-10-24 | 11 | josesilva | Another Conference | 2009-10-24 |
  12 + | josesilva | Some Conference | 2009-10-22 |
12 13
13 Scenario: go to next month 14 Scenario: go to next month
14 Given I am on /profile/josesilva/events/2009/10 15 Given I am on /profile/josesilva/events/2009/10
@@ -114,9 +115,11 @@ Feature: events @@ -114,9 +115,11 @@ Feature: events
114 @selenium 115 @selenium
115 Scenario: show events when i follow a specific day 116 Scenario: show events when i follow a specific day
116 Given I am on /profile/josesilva/events/2009/10 117 Given I am on /profile/josesilva/events/2009/10
117 - And I should see "Another Conference" 118 + And I should see "Another Conference" within "#agenda"
  119 + And I should see "Some Conference" within "#agenda"
118 When I follow "24" 120 When I follow "24"
119 - Then I should see "Another Conference" 121 + Then I should see "Another Conference" within "#agenda"
  122 + And I should not see "Some Conference" within "#agenda"
120 123
121 @selenium 124 @selenium
122 Scenario: show events in a range when i follow a specific day 125 Scenario: show events in a range when i follow a specific day
lib/acts_as_filesystem.rb
1 module ActsAsFileSystem 1 module ActsAsFileSystem
2 2
3 - module ClassMethods 3 + module ActsMethods
4 4
5 # Declares the ActiveRecord model to acts like a filesystem: objects are 5 # Declares the ActiveRecord model to acts like a filesystem: objects are
6 # arranged in a tree (liks acts_as_tree), and . The underlying table must 6 # arranged in a tree (liks acts_as_tree), and . The underlying table must
@@ -14,66 +14,80 @@ module ActsAsFileSystem @@ -14,66 +14,80 @@ module ActsAsFileSystem
14 # the parent, a "/" and the slug of the object) 14 # the parent, a "/" and the slug of the object)
15 # * children_count - a cache of the number of children elements. 15 # * children_count - a cache of the number of children elements.
16 def acts_as_filesystem 16 def acts_as_filesystem
17 -  
18 - include ActsAsFileSystem::InstanceMethods  
19 -  
20 # a filesystem is a tree 17 # a filesystem is a tree
21 - acts_as_tree :order => 'name', :counter_cache => :children_count 18 + acts_as_tree :counter_cache => :children_count
22 19
23 - # calculate the right path  
24 - before_create do |record|  
25 - if record.path == record.slug && (! record.top_level?)  
26 - record.path = record.calculate_path  
27 - end  
28 - true 20 + extend ClassMethods
  21 + include InstanceMethods
  22 + if self.has_path?
  23 + after_update :update_children_path
  24 + before_create :set_path
  25 + include InstanceMethods::PathMethods
29 end 26 end
30 27
31 - # when renaming a category, all children categories must have their paths  
32 - # recalculated  
33 - after_update do |record|  
34 - if record.recalculate_path  
35 - record.children.each do |item|  
36 - item.path = item.calculate_path  
37 - item.recalculate_path = true  
38 - item.save!  
39 - end 28 + before_save :set_ancestry
  29 + end
  30 +
  31 + end
  32 +
  33 + module ClassMethods
  34 +
  35 + def build_ancestry(parent_id = nil, ancestry = '')
  36 + ActiveRecord::Base.transaction do
  37 + self.base_class.all(:conditions => {:parent_id => parent_id}).each do |node|
  38 + node.update_column :ancestry, ancestry
  39 +
  40 + build_ancestry node.id, (ancestry.empty? ? "#{node.formatted_ancestry_id}" :
  41 + "#{ancestry}#{node.ancestry_sep}#{node.formatted_ancestry_id}")
40 end 42 end
41 - record.recalculate_path = false  
42 - true  
43 end 43 end
44 44
  45 + #raise "Couldn't reach and set ancestry on every record" if self.base_class.count(:conditions => ['ancestry is null']) != 0
  46 + end
  47 +
  48 + def has_path?
  49 + (['name', 'slug', 'path'] - self.column_names).blank?
45 end 50 end
  51 +
46 end 52 end
47 53
48 module InstanceMethods 54 module InstanceMethods
49 - # used to know when to trigger batch renaming  
50 - attr_accessor :recalculate_path  
51 55
52 - # calculates the full name of a category by accessing the name of all its  
53 - # ancestors.  
54 - #  
55 - # If you have this category hierarchy:  
56 - # Category "A"  
57 - # Category "B"  
58 - # Category "C"  
59 - #  
60 - # Then Category "C" will have "A/B/C" as its full name.  
61 - def full_name(sep = '/')  
62 - self.hierarchy.map {|item| item.name || '?' }.join(sep) 56 + def ancestry_column
  57 + 'ancestry'
  58 + end
  59 + def ancestry_sep
  60 + '.'
  61 + end
  62 + def has_ancestry?
  63 + self.class.column_names.include? self.ancestry_column
  64 + end
  65 +
  66 + def formatted_ancestry_id
  67 + "%010d" % self.id if self.id
63 end 68 end
64 69
65 - # gets the name without leading parents. Usefull when dividing categories  
66 - # in top-level groups and full names must not include the top-level  
67 - # category which is already a emphasized label  
68 - def full_name_without_leading(count, sep = '/')  
69 - parts = self.full_name(sep).split(sep)  
70 - count.times { parts.shift }  
71 - parts.join(sep) 70 + def ancestry
  71 + self[ancestry_column]
  72 + end
  73 + def ancestor_ids
  74 + return nil if !has_ancestry? or ancestry.nil?
  75 + @ancestor_ids ||= ancestry.split(ancestry_sep).map{ |id| id.to_i }
  76 + end
  77 +
  78 + def ancestry=(value)
  79 + self[ancestry_column] = value
  80 + end
  81 + def set_ancestry
  82 + return unless self.has_ancestry?
  83 + if self.ancestry.nil? or (new_record? or parent_id_changed?) or recalculate_path
  84 + self.ancestry = self.hierarchy(true)[0...-1].map{ |p| p.formatted_ancestry_id }.join(ancestry_sep)
  85 + end
72 end 86 end
73 87
74 - # calculates the level of the category in the category hierarchy. Top-level  
75 - # categories have level 0; the children of the top-level categories have  
76 - # level 1; the children of categories with level 1 have level 2, and so on. 88 + # calculates the level of the record in the records hierarchy. Top-level
  89 + # records have level 0; the children of the top-level records have
  90 + # level 1; the children of records with level 1 have level 2, and so on.
77 # 91 #
78 # A level 0 92 # A level 0
79 # / \ 93 # / \
@@ -82,61 +96,36 @@ module ActsAsFileSystem @@ -82,61 +96,36 @@ module ActsAsFileSystem
82 # E F G H level 2 96 # E F G H level 2
83 # ... 97 # ...
84 def level 98 def level
85 - self.parent ? (self.parent.level + 1) : 0 99 + self.hierarchy.size - 1
86 end 100 end
87 101
88 - # Is this category a top-level category? 102 + # Is this record a top-level record?
89 def top_level? 103 def top_level?
90 self.parent.nil? 104 self.parent.nil?
91 end 105 end
92 106
93 - # Is this category a leaf in the hierarchy tree of categories? 107 + # Is this record a leaf in the hierarchy tree of records?
94 # 108 #
95 - # Being a leaf means that this category has no subcategories. 109 + # Being a leaf means that this record has no subrecord.
96 def leaf? 110 def leaf?
97 self.children.empty? 111 self.children.empty?
98 end 112 end
99 113
100 - def set_name(value)  
101 - if self.name != value  
102 - self.recalculate_path = true  
103 - end  
104 - self[:name] = value  
105 - end  
106 -  
107 - # sets the name of the category. Also sets #slug accordingly.  
108 - def name=(value)  
109 - self.set_name(value)  
110 - unless self.name.blank?  
111 - self.slug = self.name.to_slug  
112 - end  
113 - end  
114 -  
115 - # sets the slug of the category. Also sets the path with the new slug value.  
116 - def slug=(value)  
117 - self[:slug] = value  
118 - unless self.slug.blank?  
119 - self.path = self.calculate_path 114 + def top_ancestor
  115 + if has_ancestry? and !ancestry.nil?
  116 + self.class.base_class.find_by_id self.top_ancestor_id
  117 + else
  118 + self.hierarchy.first
120 end 119 end
121 end 120 end
122 -  
123 - # calculates the full path to this category using parent's path.  
124 - def calculate_path  
125 - if self.top_level?  
126 - self.slug 121 + def top_ancestor_id
  122 + if has_ancestry? and !ancestry.nil?
  123 + self.ancestor_ids.first
127 else 124 else
128 - self.parent.calculate_path + "/" + self.slug 125 + self.hierarchy.first.id
129 end 126 end
130 end 127 end
131 128
132 - def top_ancestor  
133 - self.top_level? ? self : self.parent.top_ancestor  
134 - end  
135 -  
136 - def explode_path  
137 - path.split(/\//)  
138 - end  
139 -  
140 # returns the full hierarchy from the top-level item to this one. For 129 # returns the full hierarchy from the top-level item to this one. For
141 # example, if item1 has a children item2 and item2 has a children item3, 130 # example, if item1 has a children item2 and item2 has a children item3,
142 # then item3's hierarchy would be [item1, item2, item3]. 131 # then item3's hierarchy would be [item1, item2, item3].
@@ -145,16 +134,21 @@ module ActsAsFileSystem @@ -145,16 +134,21 @@ module ActsAsFileSystem
145 # when the ActiveRecord object was modified in some way, or just after 134 # when the ActiveRecord object was modified in some way, or just after
146 # changing parent) 135 # changing parent)
147 def hierarchy(reload = false) 136 def hierarchy(reload = false)
148 - if reload  
149 - @hierarchy = nil  
150 - end 137 + @hierarchy = nil if reload or recalculate_path
151 138
152 - unless @hierarchy 139 + if @hierarchy.nil?
153 @hierarchy = [] 140 @hierarchy = []
154 - item = self  
155 - while item  
156 - @hierarchy.unshift(item)  
157 - item = item.parent 141 +
  142 + if !reload and !recalculate_path and ancestor_ids
  143 + objects = self.class.base_class.all(:conditions => {:id => ancestor_ids})
  144 + ancestor_ids.each{ |id| @hierarchy << objects.find{ |t| t.id == id } }
  145 + @hierarchy << self
  146 + else
  147 + item = self
  148 + while item
  149 + @hierarchy.unshift(item)
  150 + item = item.parent
  151 + end
158 end 152 end
159 end 153 end
160 154
@@ -181,8 +175,86 @@ module ActsAsFileSystem @@ -181,8 +175,86 @@ module ActsAsFileSystem
181 res 175 res
182 end 176 end
183 177
  178 + #####
  179 + # Path methods
  180 + # These methods are used when _path_, _name_ and _slug_ attributes exist
  181 + # and should be calculated based on the tree
  182 + #####
  183 + module PathMethods
  184 + # used to know when to trigger batch renaming
  185 + attr_accessor :recalculate_path
  186 +
  187 + # calculates the full path to this record using parent's path.
  188 + def calculate_path
  189 + self.hierarchy.map{ |obj| obj.slug }.join('/')
  190 + end
  191 + def set_path
  192 + if self.path == self.slug && !self.top_level?
  193 + self.path = self.calculate_path
  194 + end
  195 + end
  196 + def explode_path
  197 + path.split(/\//)
  198 + end
  199 +
  200 + def update_children_path
  201 + if self.recalculate_path
  202 + self.children.each do |child|
  203 + child.path = child.calculate_path
  204 + child.recalculate_path = true
  205 + child.save!
  206 + end
  207 + end
  208 + self.recalculate_path = false
  209 + end
  210 +
  211 + # calculates the full name of a record by accessing the name of all its
  212 + # ancestors.
  213 + #
  214 + # If you have this record hierarchy:
  215 + # Record "A"
  216 + # Record "B"
  217 + # Record "C"
  218 + #
  219 + # Then Record "C" will have "A/B/C" as its full name.
  220 + def full_name(sep = '/')
  221 + self.hierarchy.map {|item| item.name || '?' }.join(sep)
  222 + end
  223 +
  224 + # gets the name without leading parents. Useful when dividing records
  225 + # in top-level groups and full names must not include the top-level
  226 + # record which is already a emphasized label
  227 + def full_name_without_leading(count, sep = '/')
  228 + parts = self.full_name(sep).split(sep)
  229 + count.times { parts.shift }
  230 + parts.join(sep)
  231 + end
  232 +
  233 + def set_name(value)
  234 + if self.name != value
  235 + self.recalculate_path = true
  236 + end
  237 + self[:name] = value
  238 + end
  239 +
  240 + # sets the name of the record. Also sets #slug accordingly.
  241 + def name=(value)
  242 + self.set_name(value)
  243 + unless self.name.blank?
  244 + self.slug = self.name.to_slug
  245 + end
  246 + end
  247 +
  248 + # sets the slug of the record. Also sets the path with the new slug value.
  249 + def slug=(value)
  250 + self[:slug] = value
  251 + unless self.slug.blank?
  252 + self.path = self.calculate_path
  253 + end
  254 + end
  255 + end
184 end 256 end
185 end 257 end
186 258
187 -ActiveRecord::Base.extend ActsAsFileSystem::ClassMethods 259 +ActiveRecord::Base.extend ActsAsFileSystem::ActsMethods
188 260
lib/acts_as_having_boxes.rb
@@ -27,8 +27,9 @@ module ActsAsHavingBoxes @@ -27,8 +27,9 @@ module ActsAsHavingBoxes
27 end 27 end
28 28
29 # returns 3 unless the class table has a boxes_limit column. In that case 29 # returns 3 unless the class table has a boxes_limit column. In that case
30 - # return the value of the column.  
31 - def boxes_limit 30 + # return the value of the column.
  31 + def boxes_limit layout_template = nil
  32 + layout_template ||= self.layout_template
32 @boxes_limit ||= LayoutTemplate.find(layout_template).number_of_boxes || 3 33 @boxes_limit ||= LayoutTemplate.find(layout_template).number_of_boxes || 3
33 end 34 end
34 35
lib/authenticated_system.rb
@@ -5,22 +5,23 @@ module AuthenticatedSystem @@ -5,22 +5,23 @@ module AuthenticatedSystem
5 def logged_in? 5 def logged_in?
6 current_user != nil 6 current_user != nil
7 end 7 end
8 - 8 +
9 # Accesses the current user from the session. 9 # Accesses the current user from the session.
10 def current_user 10 def current_user
11 @current_user ||= (session[:user] && User.find_by_id(session[:user])) || nil 11 @current_user ||= (session[:user] && User.find_by_id(session[:user])) || nil
12 end 12 end
13 - 13 +
14 # Store the given user in the session. 14 # Store the given user in the session.
15 def current_user=(new_user) 15 def current_user=(new_user)
16 if new_user.nil? 16 if new_user.nil?
17 session.delete(:user) 17 session.delete(:user)
18 else 18 else
19 session[:user] = new_user.id 19 session[:user] = new_user.id
  20 + new_user.register_login
20 end 21 end
21 @current_user = new_user 22 @current_user = new_user
22 end 23 end
23 - 24 +
24 # Check if the user is authorized. 25 # Check if the user is authorized.
25 # 26 #
26 # Override this method in your controllers if you want to restrict access 27 # Override this method in your controllers if you want to restrict access
@@ -62,7 +63,7 @@ module AuthenticatedSystem @@ -62,7 +63,7 @@ module AuthenticatedSystem
62 access_denied 63 access_denied
63 end 64 end
64 end 65 end
65 - 66 +
66 # Redirect as appropriate when an access request fails. 67 # Redirect as appropriate when an access request fails.
67 # 68 #
68 # The default action is to redirect to the login screen. 69 # The default action is to redirect to the login screen.
@@ -88,15 +89,15 @@ module AuthenticatedSystem @@ -88,15 +89,15 @@ module AuthenticatedSystem
88 end 89 end
89 end 90 end
90 false 91 false
91 - end  
92 - 92 + end
  93 +
93 # Store the URI of the current request in the session. 94 # Store the URI of the current request in the session.
94 # 95 #
95 # We can return to this location by calling #redirect_back_or_default. 96 # We can return to this location by calling #redirect_back_or_default.
96 def store_location(location = request.url) 97 def store_location(location = request.url)
97 session[:return_to] = location 98 session[:return_to] = location
98 end 99 end
99 - 100 +
100 # Redirect to the URI stored by the most recent store_location call or 101 # Redirect to the URI stored by the most recent store_location call or
101 # to the passed default. 102 # to the passed default.
102 def redirect_back_or_default(default) 103 def redirect_back_or_default(default)
@@ -106,7 +107,7 @@ module AuthenticatedSystem @@ -106,7 +107,7 @@ module AuthenticatedSystem
106 redirect_to(default) 107 redirect_to(default)
107 end 108 end
108 end 109 end
109 - 110 +
110 # Inclusion hook to make #current_user and #logged_in? 111 # Inclusion hook to make #current_user and #logged_in?
111 # available as ActionView helper methods. 112 # available as ActionView helper methods.
112 def self.included(base) 113 def self.included(base)
@@ -132,6 +133,6 @@ module AuthenticatedSystem @@ -132,6 +133,6 @@ module AuthenticatedSystem
132 def get_auth_data 133 def get_auth_data
133 auth_key = @@http_auth_headers.detect { |h| request.env.has_key?(h) } 134 auth_key = @@http_auth_headers.detect { |h| request.env.has_key?(h) }
134 auth_data = request.env[auth_key].to_s.split unless auth_key.blank? 135 auth_data = request.env[auth_key].to_s.split unless auth_key.blank?
135 - return auth_data && auth_data[0] == 'Basic' ? Base64.decode64(auth_data[1]).split(':')[0..1] : [nil, nil] 136 + return auth_data && auth_data[0] == 'Basic' ? Base64.decode64(auth_data[1]).split(':')[0..1] : [nil, nil]
136 end 137 end
137 end 138 end
lib/noosfero/constants.rb
1 module Noosfero::Constants 1 module Noosfero::Constants
2 - EMAIL_FORMAT = /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i 2 + EMAIL_FORMAT = /\A([^@\s]+)@((?:[-_a-z0-9]+\.)+[a-z]{2,})\Z/i
3 INTEGER_FORMAT = /\A\d*\Z/i 3 INTEGER_FORMAT = /\A\d*\Z/i
4 PROFILE_PER_PAGE = 10 4 PROFILE_PER_PAGE = 10
5 end 5 end
lib/noosfero/plugin.rb
@@ -24,11 +24,17 @@ class Noosfero::Plugin @@ -24,11 +24,17 @@ class Noosfero::Plugin
24 24
25 def initialize! 25 def initialize!
26 return if !should_load 26 return if !should_load
27 - available_plugins.each do |plugin_dir| 27 +
  28 + klasses = available_plugins.map do |plugin_dir|
28 plugin_name = File.basename(plugin_dir) 29 plugin_name = File.basename(plugin_dir)
29 - plugin = load_plugin(plugin_name)  
30 - load_plugin_extensions(plugin_dir)  
31 - load_plugin_filters(plugin) 30 + load_plugin plugin_name
  31 + end
  32 + available_plugins.each do |plugin_dir|
  33 + load_plugin_extensions plugin_dir
  34 + end
  35 + # filters must be loaded after all extensions
  36 + klasses.each do |plugin|
  37 + load_plugin_filters plugin
32 end 38 end
33 end 39 end
34 40
@@ -88,7 +94,7 @@ class Noosfero::Plugin @@ -88,7 +94,7 @@ class Noosfero::Plugin
88 # This is a generic method that initialize any possible filter defined by a 94 # This is a generic method that initialize any possible filter defined by a
89 # plugin to a specific controller 95 # plugin to a specific controller
90 def load_plugin_filters(plugin) 96 def load_plugin_filters(plugin)
91 - Rails.configuration.to_prepare do 97 + ActionDispatch::Reloader.to_prepare do
92 filters = plugin.new.send 'application_controller_filters' rescue [] 98 filters = plugin.new.send 'application_controller_filters' rescue []
93 Noosfero::Plugin.add_controller_filters ApplicationController, plugin, filters 99 Noosfero::Plugin.add_controller_filters ApplicationController, plugin, filters
94 100
@@ -116,7 +122,7 @@ class Noosfero::Plugin @@ -116,7 +122,7 @@ class Noosfero::Plugin
116 end 122 end
117 123
118 def load_plugin_extensions(dir) 124 def load_plugin_extensions(dir)
119 - Rails.configuration.to_prepare do 125 + ActionDispatch::Reloader.to_prepare do
120 Dir[File.join(dir, 'lib', 'ext', '*.rb')].each {|file| require_dependency file } 126 Dir[File.join(dir, 'lib', 'ext', '*.rb')].each {|file| require_dependency file }
121 end 127 end
122 end 128 end
@@ -267,7 +273,16 @@ class Noosfero::Plugin @@ -267,7 +273,16 @@ class Noosfero::Plugin
267 nil 273 nil
268 end 274 end
269 275
270 - # -> Adds content to catalog item 276 + # -> Adds tabs to the products
  277 + # returns = { :title => title, :id => id, :content => content }
  278 + # title = name that will be displayed.
  279 + # id = div id.
  280 + # content = lambda block that creates html code.
  281 + def product_tabs product
  282 + nil
  283 + end
  284 +
  285 + # -> Adds content to calalog item
271 # returns = lambda block that creates html code 286 # returns = lambda block that creates html code
272 def catalog_item_extras(item) 287 def catalog_item_extras(item)
273 nil 288 nil
@@ -444,7 +459,7 @@ class Noosfero::Plugin @@ -444,7 +459,7 @@ class Noosfero::Plugin
444 def upload_files_extra_fields(article) 459 def upload_files_extra_fields(article)
445 nil 460 nil
446 end 461 end
447 - 462 +
448 # -> Adds fields to the signup form 463 # -> Adds fields to the signup form
449 # returns = proc that creates html code 464 # returns = proc that creates html code
450 def signup_extra_contents 465 def signup_extra_contents