Commit 11dfb86bf56dd6ce8784ab13682b46a96f9efc2f

Authored by Rodrigo Souto
2 parents d442dac2 ec0f8b0e

Merge branch 'master' of gitlab.com:noosfero/noosfero

Showing 174 changed files with 2162 additions and 2196 deletions   Show diff stats
@@ -11,7 +11,6 @@ gem 'will_paginate', '~> 3.0.3' @@ -11,7 +11,6 @@ gem 'will_paginate', '~> 3.0.3'
11 gem 'ruby-feedparser', '~> 0.7' 11 gem 'ruby-feedparser', '~> 0.7'
12 gem 'daemons', '~> 1.1.5' 12 gem 'daemons', '~> 1.1.5'
13 gem 'thin', '~> 1.3.1' 13 gem 'thin', '~> 1.3.1'
14 -gem 'hpricot', '~> 0.8.6'  
15 gem 'nokogiri', '~> 1.5.5' 14 gem 'nokogiri', '~> 1.5.5'
16 gem 'rake', :require => false 15 gem 'rake', :require => false
17 gem 'rest-client', '~> 1.6.7' 16 gem 'rest-client', '~> 1.6.7'
@@ -41,9 +40,12 @@ group :cucumber do @@ -41,9 +40,12 @@ group :cucumber do
41 gem 'selenium-webdriver', '~> 2.39.0' 40 gem 'selenium-webdriver', '~> 2.39.0'
42 end 41 end
43 42
  43 +# Requires custom dependencies
  44 +eval(File.read('config/Gemfile'), binding) rescue nil
  45 +
44 # include gemfiles from enabled plugins 46 # include gemfiles from enabled plugins
45 # plugins in baseplugins/ are not included on purpose. They should not have any 47 # plugins in baseplugins/ are not included on purpose. They should not have any
46 # dependencies. 48 # dependencies.
47 Dir.glob('config/plugins/*/Gemfile').each do |gemfile| 49 Dir.glob('config/plugins/*/Gemfile').each do |gemfile|
48 eval File.read(gemfile) 50 eval File.read(gemfile)
49 -end 51 -end
  52 +end
50 \ No newline at end of file 53 \ No newline at end of file
@@ -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
app/controllers/application_controller.rb
@@ -28,6 +28,7 @@ class ApplicationController &lt; ActionController::Base @@ -28,6 +28,7 @@ class ApplicationController &lt; ActionController::Base
28 unless environment.access_control_allow_methods.blank? 28 unless environment.access_control_allow_methods.blank?
29 response.headers["Access-Control-Allow-Methods"] = environment.access_control_allow_methods 29 response.headers["Access-Control-Allow-Methods"] = environment.access_control_allow_methods
30 end 30 end
  31 + response.headers["Access-Control-Allow-Credentials"] = 'true'
31 elsif environment.restrict_to_access_control_origins 32 elsif environment.restrict_to_access_control_origins
32 render_access_denied _('Origin not in allowed.') 33 render_access_denied _('Origin not in allowed.')
33 end 34 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
@@ -651,8 +647,8 @@ module ApplicationHelper @@ -651,8 +647,8 @@ module ApplicationHelper
651 ' 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\'"'+
652 ' 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\'">'+
653 '</form>' 649 '</form>'
654 - else #opt == 'lightbox_link' is default  
655 - lightbox_link_to '<span class="icon-menu-search"></span>'+ _('Search'), { 650 + else
  651 + modal_link_to '<span class="icon-menu-search"></span>'+ _('Search'), {
656 :controller => 'search', 652 :controller => 'search',
657 :action => 'popup', 653 :action => 'popup',
658 :category_path => (@category ? @category.explode_path : nil)}, 654 :category_path => (@category ? @category.explode_path : nil)},
@@ -1050,7 +1046,7 @@ module ApplicationHelper @@ -1050,7 +1046,7 @@ module ApplicationHelper
1050 {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'})}}
1051 ] 1047 ]
1052 if logged_in? 1048 if logged_in?
1053 - 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})}))
1054 end 1050 end
1055 1051
1056 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') +
@@ -1398,16 +1394,16 @@ module ApplicationHelper @@ -1398,16 +1394,16 @@ module ApplicationHelper
1398 end 1394 end
1399 1395
1400 def convert_macro(html, source) 1396 def convert_macro(html, source)
1401 - doc = Hpricot(html) 1397 + doc = Nokogiri::HTML.fragment html
1402 #TODO This way is more efficient but do not support macro inside of 1398 #TODO This way is more efficient but do not support macro inside of
1403 # macro. You must parse them from the inside-out in order to enable 1399 # macro. You must parse them from the inside-out in order to enable
1404 # that. 1400 # that.
1405 - doc.search('.macro').each do |macro| 1401 + doc.css('.macro').each do |macro|
1406 macro_name = macro['data-macro'] 1402 macro_name = macro['data-macro']
1407 result = @plugins.parse_macro(macro_name, macro, source) 1403 result = @plugins.parse_macro(macro_name, macro, source)
1408 macro.inner_html = result.kind_of?(Proc) ? self.instance_exec(&result) : result 1404 macro.inner_html = result.kind_of?(Proc) ? self.instance_exec(&result) : result
1409 end 1405 end
1410 - doc.html 1406 + doc.to_html
1411 end 1407 end
1412 1408
1413 def default_folder_for_image_upload(profile) 1409 def default_folder_for_image_upload(profile)
app/helpers/boxes_helper.rb
@@ -231,7 +231,7 @@ module BoxesHelper @@ -231,7 +231,7 @@ module BoxesHelper
231 end 231 end
232 232
233 if block.editable? 233 if block.editable?
234 - buttons << colorbox_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id }) 234 + buttons << modal_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id })
235 end 235 end
236 236
237 if !block.main? 237 if !block.main?
@@ -241,7 +241,7 @@ module BoxesHelper @@ -241,7 +241,7 @@ module BoxesHelper
241 end 241 end
242 242
243 if block.respond_to?(:help) 243 if block.respond_to?(:help)
244 - 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}")
245 end 245 end
246 246
247 if block.embedable? 247 if block.embedable?
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/layout_helper.rb
@@ -45,8 +45,6 @@ module LayoutHelper @@ -45,8 +45,6 @@ module LayoutHelper
45 standard_stylesheets = [ 45 standard_stylesheets = [
46 'application', 46 'application',
47 'search', 47 'search',
48 - 'thickbox',  
49 - 'lightbox',  
50 'colorbox', 48 'colorbox',
51 'selectordie', 49 'selectordie',
52 'inputosaurus', 50 'inputosaurus',
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/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/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
@@ -707,7 +706,7 @@ class Article &lt; ActiveRecord::Base @@ -707,7 +706,7 @@ class Article &lt; ActiveRecord::Base
707 end 706 end
708 707
709 def first_paragraph 708 def first_paragraph
710 - paragraphs = Hpricot(to_html).search('p') 709 + paragraphs = Nokogiri::HTML.fragment(to_html).css('p')
711 paragraphs.empty? ? '' : paragraphs.first.to_html 710 paragraphs.empty? ? '' : paragraphs.first.to_html
712 end 711 end
713 712
@@ -729,8 +728,8 @@ class Article &lt; ActiveRecord::Base @@ -729,8 +728,8 @@ class Article &lt; ActiveRecord::Base
729 728
730 def body_images_paths 729 def body_images_paths
731 require 'uri' 730 require 'uri'
732 - Hpricot(self.body.to_s).search('img[@src]').collect do |i|  
733 - (self.profile && self.profile.environment) ? URI.join(self.profile.environment.top_url, URI.escape(i.attributes['src'])).to_s : i.attributes['src'] 731 + Nokogiri::HTML.fragment(self.body.to_s).css('img[src]').collect do |i|
  732 + (self.profile && self.profile.environment) ? URI.join(self.profile.environment.top_url, URI.escape(i['src'])).to_s : i['src']
734 end 733 end
735 end 734 end
736 735
@@ -767,8 +766,8 @@ class Article &lt; ActiveRecord::Base @@ -767,8 +766,8 @@ class Article &lt; ActiveRecord::Base
767 end 766 end
768 767
769 def first_image 768 def first_image
770 - img = Hpricot(self.lead.to_s).search('img[@src]').first || Hpricot(self.body.to_s).search('img').first  
771 - img.nil? ? '' : img.attributes['src'] 769 + img = Nokogiri::HTML.fragment(self.lead.to_s).css('img[src]').first || Nokogiri::HTML.fragment(self.body.to_s).search('img').first
  770 + img.nil? ? '' : img['src']
772 end 771 end
773 772
774 delegate :lat, :lng, :region, :region_id, :environment, :environment_id, :to => :profile, :allow_nil => true 773 delegate :lat, :lng, :region, :region_id, :environment, :environment_id, :to => :profile, :allow_nil => true
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
@@ -273,6 +273,7 @@ class Environment &lt; ActiveRecord::Base @@ -273,6 +273,7 @@ class Environment &lt; ActiveRecord::Base
273 settings_items :help_message_to_add_enterprise, :type => String, :default => '' 273 settings_items :help_message_to_add_enterprise, :type => String, :default => ''
274 settings_items :tip_message_enterprise_activation_question, :type => String, :default => '' 274 settings_items :tip_message_enterprise_activation_question, :type => String, :default => ''
275 275
  276 + settings_items :currency_iso_unit, :type => String, :default => 'USD'
276 settings_items :currency_unit, :type => String, :default => '$' 277 settings_items :currency_unit, :type => String, :default => '$'
277 settings_items :currency_separator, :type => String, :default => '.' 278 settings_items :currency_separator, :type => String, :default => '.'
278 settings_items :currency_delimiter, :type => String, :default => ',' 279 settings_items :currency_delimiter, :type => String, :default => ','
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/person_notifier.rb
@@ -22,12 +22,17 @@ class PersonNotifier @@ -22,12 +22,17 @@ class PersonNotifier
22 schedule_next_notification_mail 22 schedule_next_notification_mail
23 end 23 end
24 24
  25 + def notify_from
  26 + @person.last_notification || DateTime.now - @person.notification_time.hours
  27 + end
  28 +
25 def notify 29 def notify
26 if @person.notification_time && @person.notification_time > 0 30 if @person.notification_time && @person.notification_time > 0
27 - from = @person.last_notification || DateTime.now - @person.notification_time.hours  
28 - notifications = @person.tracked_notifications.find(:all, :conditions => ["created_at > ?", from]) 31 + notifications = @person.tracked_notifications.find(:all, :conditions => ["created_at > ?", notify_from])
  32 + tasks = Task.to(@person).without_spam.pending.where("created_at > ?", notify_from).order_by('created_at', 'asc')
  33 +
29 Noosfero.with_locale @person.environment.default_language do 34 Noosfero.with_locale @person.environment.default_language do
30 - Mailer::content_summary(@person, notifications).deliver unless notifications.empty? 35 + Mailer::content_summary(@person, notifications, tasks).deliver unless notifications.empty? && tasks.empty?
31 end 36 end
32 @person.settings[:last_notification] = DateTime.now 37 @person.settings[:last_notification] = DateTime.now
33 @person.save! 38 @person.save!
@@ -59,8 +64,12 @@ class PersonNotifier @@ -59,8 +64,12 @@ class PersonNotifier
59 end 64 end
60 65
61 def failure(job) 66 def failure(job)
62 - person = Person.find(person_id)  
63 - person.notifier.dispatch_notification_mail 67 + begin
  68 + person = Person.find(person_id)
  69 + person.notifier.dispatch_notification_mail
  70 + rescue
  71 + Rails.logger.error "PersonNotifier::NotifyJob: Cannot recover from failure"
  72 + end
64 end 73 end
65 74
66 end 75 end
@@ -73,18 +82,24 @@ class PersonNotifier @@ -73,18 +82,24 @@ class PersonNotifier
73 {:theme => nil} 82 {:theme => nil}
74 end 83 end
75 84
76 - def content_summary(person, notifications) 85 + def content_summary(person, notifications, tasks)
  86 + if person.environment
  87 + ActionMailer::Base.asset_host = person.environment.top_url
  88 + ActionMailer::Base.default_url_options[:host] = person.environment.default_hostname
  89 + end
  90 +
77 @current_theme = 'default' 91 @current_theme = 'default'
78 @profile = person 92 @profile = person
79 @recipient = @profile.nickname || @profile.name 93 @recipient = @profile.nickname || @profile.name
80 @notifications = notifications 94 @notifications = notifications
  95 + @tasks = tasks
81 @environment = @profile.environment.name 96 @environment = @profile.environment.name
82 @url = @profile.environment.top_url 97 @url = @profile.environment.top_url
83 mail( 98 mail(
84 content_type: "text/html", 99 content_type: "text/html",
85 from: "#{@profile.environment.name} <#{@profile.environment.noreply_email}>", 100 from: "#{@profile.environment.name} <#{@profile.environment.noreply_email}>",
86 to: @profile.email, 101 to: @profile.email,
87 - subject: _("[%s] Network Activity") % [@profile.environment.name] 102 + subject: _("[%s] Notifications") % [@profile.environment.name]
88 ) 103 )
89 end 104 end
90 end 105 end
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'
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
@@ -54,7 +54,7 @@ class User &lt; ActiveRecord::Base @@ -54,7 +54,7 @@ class User &lt; ActiveRecord::Base
54 54
55 user.person = p 55 user.person = p
56 end 56 end
57 - if user.environment.enabled?('skip_new_user_email_confirmation') 57 + if user.environment.enabled?('skip_new_user_email_confirmation')
58 if user.environment.enabled?('admin_must_approve_new_users') 58 if user.environment.enabled?('admin_must_approve_new_users')
59 create_moderate_task 59 create_moderate_task
60 else 60 else
@@ -102,6 +102,7 @@ class User &lt; ActiveRecord::Base @@ -102,6 +102,7 @@ class User &lt; ActiveRecord::Base
102 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?})
103 validates_uniqueness_of :login, :email, :case_sensitive => false, :scope => :environment_id 103 validates_uniqueness_of :login, :email, :case_sensitive => false, :scope => :environment_id
104 before_save :encrypt_password 104 before_save :encrypt_password
  105 + before_save :normalize_email, if: proc{ |u| u.email.present? }
105 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?})
106 107
107 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
@@ -114,6 +115,10 @@ class User &lt; ActiveRecord::Base @@ -114,6 +115,10 @@ class User &lt; ActiveRecord::Base
114 u && u.authenticated?(password) ? u : nil 115 u && u.authenticated?(password) ? u : nil
115 end 116 end
116 117
  118 + def register_login
  119 + self.update_attribute :last_login_at, Time.now
  120 + end
  121 +
117 # Activates the user in the database. 122 # Activates the user in the database.
118 def activate 123 def activate
119 return false unless self.person 124 return false unless self.person
@@ -332,6 +337,11 @@ class User &lt; ActiveRecord::Base @@ -332,6 +337,11 @@ class User &lt; ActiveRecord::Base
332 end 337 end
333 338
334 protected 339 protected
  340 +
  341 + def normalize_email
  342 + self.email = self.email.squish.downcase
  343 + end
  344 +
335 # before filter 345 # before filter
336 def encrypt_password 346 def encrypt_password
337 return if password.blank? 347 return if password.blank?
@@ -359,6 +369,6 @@ class User &lt; ActiveRecord::Base @@ -359,6 +369,6 @@ class User &lt; ActiveRecord::Base
359 369
360 def delay_activation_check 370 def delay_activation_check
361 return if person.is_template? 371 return if person.is_template?
362 - Delayed::Job.enqueue(UserActivationJob.new(self.id), {:priority => 0, :run_at => 72.hours.from_now}) 372 + Delayed::Job.enqueue(UserActivationJob.new(self.id), {:priority => 0, :run_at => (NOOSFERO_CONF['hours_until_user_activation_check'] || 72).hours.from_now})
363 end 373 end
364 end 374 end
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/_signup_form.html.erb
@@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
16 <input type="hidden" id="signup_time_key" name="signup_time_key" /> 16 <input type="hidden" id="signup_time_key" name="signup_time_key" />
17 <script type="text/javascript"> 17 <script type="text/javascript">
18 jQuery.ajax({ 18 jQuery.ajax({
19 - type: "POST", 19 + type: "GET",
20 url: "<%= url_for :controller=>'account', :action=>'signup_time' %>", 20 url: "<%= url_for :controller=>'account', :action=>'signup_time' %>",
21 dataType: 'json', 21 dataType: 'json',
22 success: function(data) { 22 success: function(data) {
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/box_organizer/add_block.html.erb
@@ -42,7 +42,7 @@ @@ -42,7 +42,7 @@
42 42
43 <% button_bar do %> 43 <% button_bar do %>
44 <%= submit_button(:add, _("Add")) %> 44 <%= submit_button(:add, _("Add")) %>
45 - <%= colorbox_close_button(_('Close')) %> 45 + <%= modal_close_button(_('Close')) %>
46 <% end %> 46 <% end %>
47 47
48 <% end %> 48 <% end %>
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/index.html.erb
1 <h1><%= _('Editing sideboxes')%></h1> 1 <h1><%= _('Editing sideboxes')%></h1>
2 2
3 <% button_bar :class=>'design-menu' do %> 3 <% button_bar :class=>'design-menu' do %>
4 - <%= colorbox_button('add', _('Add a block'), { :action => 'add_block' }) %> 4 + <%= modal_button('add', _('Add a block'), { :action => 'add_block' }) %>
5 <%= button(:back, _('Back to control panel'), :controller => (profile.nil? ? 'admin_panel': 'profile_editor')) %> 5 <%= button(:back, _('Back to control panel'), :controller => (profile.nil? ? 'admin_panel': 'profile_editor')) %>
6 <% end %> 6 <% end %>
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
@@ -28,14 +28,14 @@ @@ -28,14 +28,14 @@
28 <%= expirable_button @page, :locale, content, url %> 28 <%= expirable_button @page, :locale, content, url %>
29 <% end %> 29 <% end %>
30 30
31 - <%= 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) %> 31 + <%= 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) %>
32 <% end %> 32 <% end %>
33 33
34 <% if @page.accept_uploads? && @page.allow_create?(user) %> 34 <% if @page.accept_uploads? && @page.allow_create?(user) %>
35 <%= 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)%> 35 <%= 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 <% end %> 36 <% end %>
37 37
38 - <% if !@page.allow_create?(user) && profile.community? && (@page.blog? || @page.parent && @page.parent.blog?) && !remove_content_button(:suggest, @page) %> 38 + <% if !@page.allow_create?(user) && profile.organization? && (@page.blog? || @page.parent && @page.parent.blog?) && !remove_content_button(:suggest, @page) %>
39 <% content = content_tag( 'span', _('Suggest an article') ) %> 39 <% content = content_tag( 'span', _('Suggest an article') ) %>
40 <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'suggest_an_article'}) %> 40 <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'suggest_an_article'}) %>
41 <% options = {:id => 'suggest-article-link'} %> 41 <% 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/layouts/_javascript.html.erb
1 <%= javascript_include_tag 'jquery-2.1.1.min', 'jquery-migrate-1.2.1', 'jrails', 'rails.js', 1 <%= javascript_include_tag 'jquery-2.1.1.min', 'jquery-migrate-1.2.1', 'jrails', 'rails.js',
2 -'jquery.cycle.all.min.js', 'thickbox.js', 'lightbox', 'colorbox',  
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 -'add-and-join', 'report-abuse', 'catalog', 'manage-products', 'autogrow', 'select-or-die/_src/selectordie',  
6 -'jquery-timepicker-addon/dist/jquery-ui-timepicker-addon', 'application.js', 'inputosaurus.js', :cache => 'cache/application' %> 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' %>
7 10
8 <% language = FastGettext.locale %> 11 <% language = FastGettext.locale %>
9 <% %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
@@ -18,7 +18,7 @@ @@ -18,7 +18,7 @@
18 <%= yield :head %> 18 <%= yield :head %>
19 <%= 19 <%=
20 @plugins.dispatch(:head_ending).map do |content| 20 @plugins.dispatch(:head_ending).map do |content|
21 - 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
22 end.join("\n") 22 end.join("\n")
23 %> 23 %>
24 24
@@ -32,7 +32,7 @@ @@ -32,7 +32,7 @@
32 32
33 <%= 33 <%=
34 @plugins.dispatch(:body_beginning).map do |content| 34 @plugins.dispatch(:body_beginning).map do |content|
35 - 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
36 end.join("\n") 36 end.join("\n")
37 %> 37 %>
38 38
app/views/person_notifier/mailer/_comment.html.erb
@@ -19,7 +19,7 @@ @@ -19,7 +19,7 @@
19 <span style="font-size: 12px;"><%= comment.title %></span><br/> 19 <span style="font-size: 12px;"><%= comment.title %></span><br/>
20 <% end %> 20 <% end %>
21 <span style="font-size: 10px;"><%= txt2html comment.body %></span><br/> 21 <span style="font-size: 10px;"><%= txt2html comment.body %></span><br/>
22 - <span style="font-size: 8px; color: #444444"><%= time_ago_as_sentence(comment.created_at) %></span> 22 + <span style="font-size: 8px; color: #929292"><%= time_ago_as_sentence(comment.created_at) %></span>
23 <br style="clear: both;" /> 23 <br style="clear: both;" />
24 24
25 <% unless comment.replies.blank? %> 25 <% unless comment.replies.blank? %>
app/views/person_notifier/mailer/_create_article.html.erb
1 -<table>  
2 <tr> 1 <tr>
3 - <td> 2 + <td style="width: 11%">
4 <%= link_to(profile_image(activity.user, :minor), activity.user.url) %> 3 <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
5 </td> 4 </td>
6 <td> 5 <td>
7 - <p style="width:550px"> 6 + <p>
8 <span style="font-size: 14px;"><%= link_to activity.user.short_name(20), activity.user.url %></span> 7 <span style="font-size: 14px;"><%= link_to activity.user.short_name(20), activity.user.url %></span>
9 <span style="font-size: 14px;"><%= _("has published on community %s") % link_to(activity.target.profile.short_name(20), activity.target.profile.url, :style => "color: #333; font-weight: bold; text-decoration: none;") if activity.target.profile.is_a?(Community) %></span> 8 <span style="font-size: 14px;"><%= _("has published on community %s") % link_to(activity.target.profile.short_name(20), activity.target.profile.url, :style => "color: #333; font-weight: bold; text-decoration: none;") if activity.target.profile.is_a?(Community) %></span>
10 - <span style="font-size: 10px; color: #444444; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span> 9 + <span style="font-size: 10px; color: #929292; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span>
11 </p> 10 </p>
12 <p> 11 <p>
13 <span style="font-size: 14px;"><%= link_to(activity.params['name'], activity.params['url'], :style => "color: #333; font-weight: bold; text-decoration: none;") %></span> 12 <span style="font-size: 14px;"><%= link_to(activity.params['name'], activity.params['url'], :style => "color: #333; font-weight: bold; text-decoration: none;") %></span>
@@ -24,4 +23,3 @@ @@ -24,4 +23,3 @@
24 <%= render :partial => 'profile_comments', :locals => { :activity => activity } %> 23 <%= render :partial => 'profile_comments', :locals => { :activity => activity } %>
25 </td> 24 </td>
26 </tr> 25 </tr>
27 -</table>  
app/views/person_notifier/mailer/_default_activity.html.erb
1 -<table>  
2 <tr> 1 <tr>
3 - <td> 2 + <td style="width: 11%">
4 <%= link_to(profile_image(activity.user, :minor), activity.user.url) %> 3 <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
5 </td> 4 </td>
6 <td> 5 <td>
7 - <p style="width:550px"> 6 + <p>
8 <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span> 7 <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span>
9 - <span style="font-size: 10px; color: #444444; float: right;"><%= time_ago_as_sentence(activity.created_at) %></span> 8 + <span style="font-size: 10px; color: #929292; float: right;"><%= time_ago_as_sentence(activity.created_at) %></span>
10 </p> 9 </p>
11 </td> 10 </td>
12 </tr> 11 </tr>
@@ -16,4 +15,3 @@ @@ -16,4 +15,3 @@
16 <%= render :partial => 'profile_comments', :locals => { :activity => activity } %> 15 <%= render :partial => 'profile_comments', :locals => { :activity => activity } %>
17 </td> 16 </td>
18 </tr> 17 </tr>
19 -</table>  
app/views/person_notifier/mailer/_task.html.erb 0 → 100644
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +<div style="border-bottom:1px solid #e2e2e2;padding:15px 0;width:600px">
  2 + <table style="width:100%;">
  3 + <tr>
  4 + <td style="width: 11%">
  5 + <%= profile_image(task.requestor, :minor) %>
  6 + </td>
  7 + <td>
  8 + <div>
  9 + <strong><%= link_to task.title, url_for(:controller => 'tasks', :profile => @profile.identifier, :action => 'index', :only_path => false) %></strong>
  10 + </div>
  11 + <div style="font-size: 14px">
  12 + <span style="font-size: 14px">
  13 + <%= task_information(task) %>
  14 + </span>
  15 + <span style="font-size: 10px; color: #929292; float: right;"><%= time_ago_as_sentence(task.created_at) %></span>
  16 + </div>
  17 + </td>
  18 + </tr>
  19 + </table>
  20 +</div>
app/views/person_notifier/mailer/_upload_image.html.erb
1 -<table>  
2 <tr> 1 <tr>
3 - <td> 2 + <td style="width: 11%">
4 <%= link_to(profile_image(activity.user, :minor), activity.user.url) %> 3 <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
5 </td> 4 </td>
6 <td> 5 <td>
7 - <p style="width:550px"> 6 + <p>
8 <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span> 7 <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span>
9 - <span style="font-size: 10px; color: #444444; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span> 8 + <span style="font-size: 10px; color: #929292; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span>
10 </p> 9 </p>
11 </td> 10 </td>
12 </tr> 11 </tr>
13 -</table>  
14 <div title='<%= activity.target.class.short_description %>' class='profile-activity-icon icon-new icon-newgallery'></div> 12 <div title='<%= activity.target.class.short_description %>' class='profile-activity-icon icon-new icon-newgallery'></div>
15 <br/> 13 <br/>
app/views/person_notifier/mailer/content_summary.html.erb
1 -<h3><%= _("%s's network activity") % @profile.name %></h3>  
2 -<br/>  
3 -<div>  
4 -<% @notifications.each do |activity| %>  
5 - <div style="border-left:none;border-right:none;border-top:1px solid #ccc;border-bottom:none;padding:10px;width:600px">  
6 - <%= render :partial => activity.verb, :locals => { :activity => activity } rescue "cannot render notification for #{activity.verb}" %>  
7 - </div>  
8 -<% end %>  
9 -</div> 1 +<div style="background-color: #EEEEEE">
  2 + <table style="width: 100%;"><tbody><tr><td align="center">
  3 + <div style="display: table; background-color: white; margin: 26px 0;">
  4 + <div style="padding: 25px 20px 20px 20px;text-align: left;">
  5 + <%= link_to @url, :style => "text-decoration: none;" do %>
  6 + <span style="font-weight:bold;font-size: 28px;margin: 0;color: white;background-color: #AAAAAA;padding: 5px;"><%= @environment %></span>
  7 + <% end %>
  8 + <span style="font-weight:bold;color: #333;font-size:19px;margin-left: 8px;"><%= _("%s's Notifications") % @profile.name %></h3>
  9 + </div>
  10 + <div style="margin: 0 20px 20px 20px;border-top:1px solid #e2e2e2;">
  11 + <% if @tasks.present? %>
  12 + <div style="border-top: 1px solid #e2e2e2;">
  13 + <div style="border-bottom: 1px solid #CBCBCB;padding-top: 15px;font-weight: bold;text-align: right;color: #7c7c7c;float: right;min-width: 140px;">
  14 + <%= _('Tasks') %>
  15 + </div>
  16 + <%= render :partial => 'task', :collection => @tasks %>
  17 + </div>
  18 + <% end %>
  19 +
  20 + <% if @notifications.present? %>
  21 + <div style="border-top: 1px solid #e2e2e2;">
  22 + <div style="border-bottom: 1px solid #CBCBCB;padding-top: 15px;font-weight: bold;text-align: right;color: #7c7c7c;float: right;min-width: 140px;">
  23 + <%= _('Network Activity') %>
  24 + </div>
  25 + <% @notifications.each do |activity| %>
  26 + <div style="border-bottom:1px solid #e2e2e2;padding:15px 0;width:600px">
  27 + <table style="width:100%;">
  28 + <%= render :partial => activity.verb, :locals => { :activity => activity } rescue "cannot render notification for #{activity.verb}" %>
  29 + </table>
  30 + </div>
  31 + <% end %>
  32 + </div>
  33 + <% end %>
10 34
11 -<div style="color:#444444;font-size:11px;">  
12 -<p><%= _("Greetings,") %></p>  
13 -<br/>  
14 -<p>--</p>  
15 -<p><%= _('%s team.') % @environment %></p>  
16 -<p><%= url_for @url %></p> 35 + <div style="color:#444444;font-size:11px;margin-bottom: 20px;">
  36 + <p style="margin:0"><%= _("Greetings,") %></p>
  37 + <p style="margin:0"><%= _('%s team.') % @environment %></p>
  38 + <p style="margin:0"><%= link_to @url, url_for(@url) %></p>
  39 + </div>
  40 + </div>
  41 + </td></tr></tbody></table>
17 </div> 42 </div>
18 -<br/>  
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_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/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 %>
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/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/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
@@ -733,6 +733,7 @@ ActiveRecord::Schema.define(:version =&gt; 20150122165042) do @@ -733,6 +733,7 @@ ActiveRecord::Schema.define(:version =&gt; 20150122165042) do
733 t.string "activation_code", :limit => 40 733 t.string "activation_code", :limit => 40
734 t.datetime "activated_at" 734 t.datetime "activated_at"
735 t.string "return_to" 735 t.string "return_to"
  736 + t.datetime "last_login_at"
736 end 737 end
737 738
738 create_table "validation_infos", :force => true do |t| 739 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,
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/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
lib/noosfero/plugin/macro.rb
@@ -35,7 +35,7 @@ class Noosfero::Plugin::Macro @@ -35,7 +35,7 @@ class Noosfero::Plugin::Macro
35 def attributes(macro) 35 def attributes(macro)
36 macro.attributes.to_hash. 36 macro.attributes.to_hash.
37 select {|key, value| key[0..10] == 'data-macro-'}. 37 select {|key, value| key[0..10] == 'data-macro-'}.
38 - inject({}){|result, a| result.merge({a[0][11..-1] => a[1]})}. 38 + inject({}){|result, a| result.merge({a[0][11..-1] => a[1].to_s})}.
39 with_indifferent_access 39 with_indifferent_access
40 end 40 end
41 41
lib/noosfero/plugin/routes.rb
1 plugins_root = Rails.env.test? ? 'plugins' : '{baseplugins,config/plugins}' 1 plugins_root = Rails.env.test? ? 'plugins' : '{baseplugins,config/plugins}'
  2 +prefixes_by_folder = {public: 'plugin',
  3 + profile: 'profile/:profile/plugin',
  4 + myprofile: 'myprofile/:profile/plugin',
  5 + admin: 'admin/plugin'}
2 6
3 Dir.glob(Rails.root.join(plugins_root, '*', 'controllers')) do |controllers_dir| 7 Dir.glob(Rails.root.join(plugins_root, '*', 'controllers')) do |controllers_dir|
4 - prefixes_by_folder = {'public' => 'plugin',  
5 - 'profile' => 'profile/:profile/plugin',  
6 - 'myprofile' => 'myprofile/:profile/plugin',  
7 - 'admin' => 'admin/plugin'} 8 + plugin_name = File.basename(File.dirname(controllers_dir))
8 9
9 controllers_by_folder = prefixes_by_folder.keys.inject({}) do |hash, folder| 10 controllers_by_folder = prefixes_by_folder.keys.inject({}) do |hash, folder|
10 - hash.merge!({folder => Dir.glob(File.join(controllers_dir, folder, '*')).map {|full_names| File.basename(full_names).gsub(/_controller.rb$/,'')}}) 11 + path = "#{controllers_dir}/#{folder}/"
  12 + hash[folder] = Dir.glob("#{path}{*.rb,#{plugin_name}_plugin/*.rb}").map do |filename|
  13 + filename.gsub(path, '').gsub(/_controller.rb$/, '')
  14 + end
  15 + hash
11 end 16 end
12 17
13 - plugin_name = File.basename(File.dirname(controllers_dir))  
14 -  
15 controllers_by_folder.each do |folder, controllers| 18 controllers_by_folder.each do |folder, controllers|
16 controllers.each do |controller| 19 controllers.each do |controller|
17 controller_name = controller.gsub("#{plugin_name}_plugin_",'') 20 controller_name = controller.gsub("#{plugin_name}_plugin_",'')
lib/noosfero/plugin/spammable.rb
1 -Rails.configuration.to_prepare do 1 +ActionDispatch::Reloader.to_prepare do
2 Spammable.module_eval do 2 Spammable.module_eval do
3 def marked_as_spam 3 def marked_as_spam
4 plugins.dispatch(:marked_as_spam, self) 4 plugins.dispatch(:marked_as_spam, self)
lib/tasks/multitenancy.rake
1 namespace :multitenancy do 1 namespace :multitenancy do
2 2
3 - task :create do 3 + task :create => :environment do
4 db_envs = ActiveRecord::Base.configurations.keys.select{ |k| k.match(/_development$|_production$|_test$/) } 4 db_envs = ActiveRecord::Base.configurations.keys.select{ |k| k.match(/_development$|_production$|_test$/) }
5 cd Rails.root.join('config', 'environments'), :verbose => true 5 cd Rails.root.join('config', 'environments'), :verbose => true
6 - file_envs = Dir.glob "{*_development.rb,*_prodution.rb,*_test.rb}" 6 + file_envs = Dir.glob "{*_development.rb,*_production.rb,*_test.rb}"
7 (db_envs.map{ |e| e + '.rb' } - file_envs).each { |env| ln_s env.split('_').last, env } 7 (db_envs.map{ |e| e + '.rb' } - file_envs).each { |env| ln_s env.split('_').last, env }
8 end 8 end
9 9
10 - task :remove do 10 + task :remove => :environment do
11 db_envs = ActiveRecord::Base.configurations.keys.select{ |k| k.match(/_development$|_production$|_test$/) } 11 db_envs = ActiveRecord::Base.configurations.keys.select{ |k| k.match(/_development$|_production$|_test$/) }
12 cd Rails.root.join('config', 'environments'), :verbose => true 12 cd Rails.root.join('config', 'environments'), :verbose => true
13 - file_envs = Dir.glob "{*_development.rb,*_prodution.rb,*_test.rb}" 13 + file_envs = Dir.glob "{*_development.rb,*_production.rb,*_test.rb}"
14 (file_envs - db_envs.map{ |e| e + '.rb' }).each { |env| safe_unlink env } 14 (file_envs - db_envs.map{ |e| e + '.rb' }).each { |env| safe_unlink env }
15 end 15 end
16 16
lib/tasks/plugins_tests.rake
@@ -106,7 +106,7 @@ def run_test(name, files) @@ -106,7 +106,7 @@ def run_test(name, files)
106 files = Array(files) 106 files = Array(files)
107 plugin = filename2plugin(files.first) 107 plugin = filename2plugin(files.first)
108 if name == :cucumber || name == :selenium 108 if name == :cucumber || name == :selenium
109 - run_cucumber task2_profile(name, plugin), files 109 + run_cucumber task2profile(name, plugin), files
110 else 110 else
111 run_testrb files 111 run_testrb files
112 end 112 end
@@ -134,7 +134,11 @@ end @@ -134,7 +134,11 @@ end
134 134
135 def run_tests(name, plugins, run=:all) 135 def run_tests(name, plugins, run=:all)
136 plugins = Array(plugins) 136 plugins = Array(plugins)
137 - glob = "plugins/{#{plugins.join(',')}}/test/#{task2folder(name)}/**/*.#{task2ext(name)}" 137 + if name == :cucumber || name == :selenium
  138 + glob = "plugins/{#{plugins.join(',')}}/#{task2folder(name)}/**/*.#{task2ext(name)}"
  139 + else
  140 + glob = "plugins/{#{plugins.join(',')}}/test/#{task2folder(name)}/**/*.#{task2ext(name)}"
  141 + end
138 files = Dir.glob(glob) 142 files = Dir.glob(glob)
139 if files.empty? 143 if files.empty?
140 puts "I: no tests to run #{name}" 144 puts "I: no tests to run #{name}"
plugins/bsc/public/jquery.ui.spinner
@@ -1 +0,0 @@ @@ -1 +0,0 @@
1 -Subproject commit bd879003043b4a93b78cbd4a582b6e0650900bcb  
plugins/comment_classification/features/step_definitions/plugin_steps.rb
1 Given /^CommentClassificationPlugin is enabled$/ do 1 Given /^CommentClassificationPlugin is enabled$/ do
2 - step %{I am logged in as admin}  
3 - step %{I am on the environment control panel}  
4 - step %{I follow "Plugins"}  
5 - step %{I check "Comment Classification"}  
6 - step %{I press "Save changes"} 2 + steps %Q{
  3 + Given I am logged in as admin
  4 + Given I am on the environment control panel
  5 + Given I follow "Plugins"
  6 + Given I check "Comment Classification"
  7 + Given I press "Save changes"
  8 + }
  9 +
7 Environment.default.enabled_plugins.should include("CommentClassificationPlugin") 10 Environment.default.enabled_plugins.should include("CommentClassificationPlugin")
8 end 11 end
9 12
plugins/comment_classification/lib/ext/comment.rb
1 require_dependency 'comment' 1 require_dependency 'comment'
2 -require 'comment_classification_plugin.rb'  
3 -require 'comment_classification_plugin/label.rb'  
4 2
5 class Comment 3 class Comment
6 4
plugins/comment_group/lib/ext/article.rb
@@ -9,7 +9,7 @@ class Article @@ -9,7 +9,7 @@ class Article
9 def not_empty_group_comments_removed 9 def not_empty_group_comments_removed
10 if body && body_changed? 10 if body && body_changed?
11 groups_with_comments = Comment.find(:all, :select => 'distinct group_id', :conditions => {:source_id => self.id}).map(&:group_id).compact 11 groups_with_comments = Comment.find(:all, :select => 'distinct group_id', :conditions => {:source_id => self.id}).map(&:group_id).compact
12 - groups = Hpricot(body.to_s).search('.macro').collect{|element| element['data-macro-group_id'].to_i} 12 + groups = Nokogiri::HTML.fragment(body.to_s).css('.macro').collect{|element| element['data-macro-group_id'].to_i}
13 errors[:base] << (N_('Not empty group comment cannot be removed')) unless (groups_with_comments-groups).empty? 13 errors[:base] << (N_('Not empty group comment cannot be removed')) unless (groups_with_comments-groups).empty?
14 end 14 end
15 end 15 end
plugins/community_track/lib/community_track_plugin/track.rb
@@ -59,7 +59,7 @@ class CommunityTrackPlugin::Track &lt; Folder @@ -59,7 +59,7 @@ class CommunityTrackPlugin::Track &lt; Folder
59 59
60 def first_paragraph 60 def first_paragraph
61 return '' if body.blank? 61 return '' if body.blank?
62 - paragraphs = Hpricot(body).search('p') 62 + paragraphs = Nokogiri::HTML.fragment(body).css('p')
63 paragraphs.empty? ? '' : paragraphs.first.to_html 63 paragraphs.empty? ? '' : paragraphs.first.to_html
64 end 64 end
65 65
plugins/custom_forms/public/style.css
@@ -25,7 +25,7 @@ @@ -25,7 +25,7 @@
25 .edit-information { 25 .edit-information {
26 display: none; 26 display: none;
27 } 27 }
28 -#colorbox .edit-information { 28 +.modal .edit-information {
29 display: block; 29 display: block;
30 } 30 }
31 31
plugins/custom_forms/views/custom_forms_plugin_myprofile/_edit_select.html.erb
@@ -26,7 +26,7 @@ @@ -26,7 +26,7 @@
26 <%= labelled_radio_button 'Multiple Select', "fields[#{counter}][kind]", 'multiple_select', field.multiple && field.list %><br /> 26 <%= labelled_radio_button 'Multiple Select', "fields[#{counter}][kind]", 'multiple_select', field.multiple && field.list %><br />
27 27
28 <% button_bar do %> 28 <% button_bar do %>
29 - <%= button :ok, c_('Ok'), '#', :class => 'colorbox-ok-button', :div_id => elem_id %> 29 + <%= button :ok, _('Ok'), '#', :div_id => elem_id %>
30 <% end %> 30 <% end %>
31 </div> 31 </div>
32 32
plugins/oauth_client/Gemfile 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +gem 'omniauth', '~> 1.2.2'
  2 +gem 'omniauth-facebook', '~> 2.0.0'
  3 +gem "omniauth-google-oauth2", '~> 0.2.6'
plugins/oauth_client/README.md 0 → 100644
@@ -0,0 +1,72 @@ @@ -0,0 +1,72 @@
  1 +README - Oauth Client Plugin
  2 +================================
  3 +
  4 +OauthClient is a plugin which allow users to login/signup to noosfero with some oauth providers (for now, google, facebook and noosfero itself).
  5 +
  6 +Install
  7 +=======
  8 +
  9 +Enable Plugin
  10 +-------------
  11 +
  12 +cd <your_noosfero_dir>
  13 +./script/noosfero-plugins enable oauth_client
  14 +
  15 +Active Plugin
  16 +-------------
  17 +
  18 +As a Noosfero administrator user, go to administrator panel:
  19 +
  20 +- Click on "Enable/disable plugins" option
  21 +- Click on "Oauth Client Plugin" check-box
  22 +
  23 +Provider Settings
  24 +=================
  25 +
  26 +Goggle
  27 +------
  28 +
  29 +[Create Google+ application](https://developers.google.com/+/web/signin/javascript-flow)
  30 +
  31 +Facebook
  32 +--------
  33 +
  34 +[Create Facebook application](https://developers.facebook.com/docs/facebook-login/v2.1)
  35 +
  36 +Varnish Settings
  37 +================
  38 +If varnish has been used in your stack, you've to bypass the cache for signup page and prevent cookies to be removed when calling the oauth_client plugin callback. E.g.:
  39 +
  40 +```
  41 +if (req.url !~ "^/account/*" && req.url !~ "^/plugin/oauth_provider/*" && req.url !~ "^/plugin/oauth_client/*" && req.http.cookie !~ "_noosfero_.*") {
  42 + unset req.http.cookie;
  43 + return(lookup);
  44 +}
  45 +```
  46 +
  47 +Using Oauth Provider Plugin
  48 +===========================
  49 +The oauth_provider plugin may be used as a provider in the same noosfero installation that hosts your oauth_client plugin (this is usefull in a multi environment setup).
  50 +
  51 +However, you've to use a distinct set of thin processes to handle the authorization requests (to avoid deadlock).
  52 +
  53 +Apache settings example:
  54 +```
  55 +RewriteRule ^/oauth_provider/oauth/(authorize|token).*$ balancer://noosfero-oauth-provider%{REQUEST_URI} [P,QSA,L]
  56 +```
  57 +
  58 +
  59 +Development
  60 +===========
  61 +
  62 +Running OauthClient tests
  63 +--------------------
  64 +
  65 +$ rake test:noosfero_plugins:oauth_client
  66 +
  67 +License
  68 +=======
  69 +
  70 +Copyright (c) The Author developers.
  71 +
  72 +See Noosfero license.
plugins/oauth_client/controllers/oauth_client_plugin_admin_controller.rb 0 → 100644
@@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
  1 +class OauthClientPluginAdminController < AdminController
  2 +
  3 + def index
  4 + end
  5 +
  6 + def new
  7 + @provider = environment.oauth_providers.new
  8 + render :file => 'oauth_client_plugin_admin/edit'
  9 + end
  10 +
  11 + def remove
  12 + environment.oauth_providers.find(params[:id]).destroy
  13 + redirect_to :action => 'index'
  14 + end
  15 +
  16 + def edit
  17 + @provider = params[:id] ? environment.oauth_providers.find(params[:id]) : environment.oauth_providers.new
  18 + if request.post?
  19 + if @provider.update_attributes(params['oauth_client_plugin_provider'])
  20 + session[:notice] = _('Saved!')
  21 + else
  22 + session[:notice] = _('Error!')
  23 + end
  24 + end
  25 + end
  26 +
  27 +end
plugins/oauth_client/controllers/public/oauth_client_plugin_public_controller.rb 0 → 100644
@@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
  1 +class OauthClientPluginPublicController < PublicController
  2 +
  3 + skip_before_filter :login_required
  4 +
  5 + def callback
  6 + auth = request.env["omniauth.auth"]
  7 + user = environment.users.find_by_email(auth.info.email)
  8 + user ? login(user) : signup(auth)
  9 + end
  10 +
  11 + def failure
  12 + session[:notice] = _('Failed to login')
  13 + redirect_to root_url
  14 + end
  15 +
  16 + def destroy
  17 + session[:user] = nil
  18 + redirect_to root_url
  19 + end
  20 +
  21 + protected
  22 +
  23 + def login(user)
  24 + provider = OauthClientPlugin::Provider.find(session[:provider_id])
  25 + user_provider = user.oauth_user_providers.find_by_provider_id(provider.id)
  26 + unless user_provider
  27 + user_provider = user.oauth_user_providers.create(:user => user, :provider => provider, :enabled => true)
  28 + end
  29 + if user_provider.enabled? && provider.enabled?
  30 + session[:user] = user.id
  31 + else
  32 + session[:notice] = _("Can't login with #{provider.name}")
  33 + end
  34 +
  35 + redirect_to :controller => :account, :action => :login
  36 + end
  37 +
  38 + def signup(auth)
  39 + login = auth.info.email.split('@').first
  40 + session[:oauth_data] = auth
  41 + name = auth.info.name
  42 + name ||= auth.extra && auth.extra.raw_info ? auth.extra.raw_info.name : ''
  43 + redirect_to :controller => :account, :action => :signup, :user => {:login => login, :email => auth.info.email}, :profile_data => {:name => name}
  44 + end
  45 +
  46 +end
plugins/oauth_client/db/migrate/20141010135314_create_oauth_client_plugin_provider.rb 0 → 100644
@@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
  1 +class CreateOauthClientPluginProvider < ActiveRecord::Migration
  2 +
  3 + def self.up
  4 + create_table :oauth_client_plugin_providers do |t|
  5 + t.integer :environment_id
  6 + t.string :strategy
  7 + t.string :name
  8 + t.text :options
  9 + t.boolean :enabled
  10 + t.integer :image_id
  11 +
  12 + t.timestamps
  13 + end
  14 + end
  15 +
  16 + def self.down
  17 + drop_table :oauth_client_plugin_providers
  18 + end
  19 +end
plugins/oauth_client/db/migrate/20141014162710_create_oauth_client_user_providers.rb 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +class CreateOauthClientUserProviders < ActiveRecord::Migration
  2 + def self.up
  3 + create_table :oauth_client_plugin_user_providers do |t|
  4 + t.references :user
  5 + t.references :provider
  6 + t.boolean :enabled
  7 + t.timestamps
  8 + end
  9 + end
  10 +
  11 + def self.down
  12 + drop_table :oauth_client_plugin_user_providers
  13 + end
  14 +end
plugins/oauth_client/lib/ext/environment.rb 0 → 100644
@@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
  1 +require_dependency 'environment'
  2 +
  3 +class Environment
  4 +
  5 + has_many :oauth_providers, :class_name => 'OauthClientPlugin::Provider'
  6 +
  7 +end
plugins/oauth_client/lib/ext/user.rb 0 → 100644
@@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
  1 +require_dependency 'user'
  2 +
  3 +class User
  4 +
  5 + has_many :oauth_user_providers, :class_name => 'OauthClientPlugin::UserProvider'
  6 + has_many :oauth_providers, :through => :oauth_user_providers, :source => :provider
  7 +
  8 + def password_required_with_oauth?
  9 + password_required_without_oauth? && oauth_providers.empty?
  10 + end
  11 +
  12 + alias_method_chain :password_required?, :oauth
  13 +
  14 + after_create :activate_oauth_user
  15 +
  16 + def activate_oauth_user
  17 + unless oauth_providers.empty?
  18 + activate
  19 + oauth_providers.each do |provider|
  20 + OauthClientPlugin::UserProvider.create!(:user => self, :provider => provider, :enabled => true)
  21 + end
  22 + end
  23 + end
  24 +
  25 + def make_activation_code_with_oauth
  26 + oauth_providers.blank? ? make_activation_code_without_oauth : nil
  27 + end
  28 +
  29 + alias_method_chain :make_activation_code, :oauth
  30 +
  31 +end
plugins/oauth_client/lib/oauth_client_plugin.rb 0 → 100644
@@ -0,0 +1,95 @@ @@ -0,0 +1,95 @@
  1 +require 'omniauth/strategies/noosfero_oauth2'
  2 +
  3 +class OauthClientPlugin < Noosfero::Plugin
  4 +
  5 + def self.plugin_name
  6 + "Oauth Client Plugin"
  7 + end
  8 +
  9 + def self.plugin_description
  10 + _("Login with Oauth.")
  11 + end
  12 +
  13 + def login_extra_contents
  14 + plugin = self
  15 + proc do
  16 + render :partial => 'auth/oauth_login', :locals => {:providers => environment.oauth_providers.enabled}
  17 + end
  18 + end
  19 +
  20 + def signup_extra_contents
  21 + plugin = self
  22 +
  23 + proc do
  24 + if plugin.context.session[:oauth_data].present?
  25 + render :partial => 'account/oauth_signup'
  26 + else
  27 + ''
  28 + end
  29 + end
  30 + end
  31 +
  32 + PROVIDERS = {
  33 + :facebook => {
  34 + :name => 'Facebook'
  35 + },
  36 + :google_oauth2 => {
  37 + :name => 'Google'
  38 + },
  39 + :noosfero_oauth2 => {
  40 + :name => 'Noosfero'
  41 + }
  42 + }
  43 +
  44 + def stylesheet?
  45 + true
  46 + end
  47 +
  48 + OmniAuth.config.on_failure = OauthClientPluginPublicController.action(:failure)
  49 +
  50 + Rails.application.config.middleware.use OmniAuth::Builder do
  51 + PROVIDERS.each do |provider, options|
  52 + setup = lambda { |env|
  53 + request = Rack::Request.new(env)
  54 + strategy = env['omniauth.strategy']
  55 +
  56 + Noosfero::MultiTenancy.setup!(request.host)
  57 + domain = Domain.find_by_name(request.host)
  58 + environment = domain.environment rescue Environment.default
  59 +
  60 + provider_id = request.params['id']
  61 + provider_id ||= request.session['omniauth.params']['id'] if request.session['omniauth.params']
  62 + provider = environment.oauth_providers.find(provider_id)
  63 + strategy.options.merge!(provider.options.symbolize_keys)
  64 +
  65 + request.session[:provider_id] = provider_id
  66 + }
  67 +
  68 + provider provider, :setup => setup,
  69 + :path_prefix => '/plugin/oauth_client',
  70 + :callback_path => "/plugin/oauth_client/public/callback/#{provider}",
  71 + :client_options => { :connection_opts => { :proxy => ENV["OAUTH_HTTP_PROXY"] } }
  72 + end
  73 +
  74 + unless Rails.env.production?
  75 + provider :developer, :path_prefix => "/plugin/oauth_client", :callback_path => "/plugin/oauth_client/public/callback/developer"
  76 + end
  77 + end
  78 +
  79 + def account_controller_filters
  80 + {
  81 + :type => 'before_filter', :method_name => 'signup',
  82 + :block => proc {
  83 + auth = session[:oauth_data]
  84 +
  85 + if auth.present? && params[:user].present?
  86 + params[:user][:oauth_providers] = [OauthClientPlugin::Provider.find(session[:provider_id])]
  87 + if request.post? && auth.info.email != params[:user][:email]
  88 + raise "Wrong email for oauth signup"
  89 + end
  90 + end
  91 + }
  92 + }
  93 + end
  94 +
  95 +end
plugins/oauth_client/lib/oauth_client_plugin/provider.rb 0 → 100644
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +class OauthClientPlugin::Provider < Noosfero::Plugin::ActiveRecord
  2 +
  3 + belongs_to :environment
  4 +
  5 + validates_presence_of :name, :strategy
  6 +
  7 + acts_as_having_image
  8 + acts_as_having_settings :field => :options
  9 +
  10 + settings_items :client_id, :type => :string
  11 + settings_items :client_secret, :type => :string
  12 + settings_items :client_options, :type => Hash
  13 +
  14 + attr_accessible :name, :environment, :strategy, :client_id, :client_secret, :enabled, :client_options, :image_builder
  15 +
  16 + scope :enabled, :conditions => {:enabled => true}
  17 +
  18 + acts_as_having_image
  19 +
  20 +end
plugins/oauth_client/lib/oauth_client_plugin/user_provider.rb 0 → 100644
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +class OauthClientPlugin::UserProvider < Noosfero::Plugin::ActiveRecord
  2 +
  3 + belongs_to :user, :class_name => 'User'
  4 + belongs_to :provider, :class_name => 'OauthClientPlugin::Provider'
  5 +
  6 + set_table_name :oauth_client_plugin_user_providers
  7 +
  8 + attr_accessible :user, :provider, :enabled
  9 +
  10 +end
plugins/oauth_client/lib/omniauth/strategies/noosfero_oauth2.rb 0 → 100644
@@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
  1 +require 'omniauth/strategies/oauth2'
  2 +
  3 +module OmniAuth
  4 + module Strategies
  5 + class NoosferoOauth2 < OmniAuth::Strategies::OAuth2
  6 + option :name, :noosfero_oauth2
  7 + option :client_options, {
  8 + :authorize_url => '/oauth_provider/oauth/authorize',
  9 + :token_url => '/oauth_provider/oauth/token'
  10 + }
  11 +
  12 + uid { raw_info["id"] }
  13 +
  14 + info do
  15 + {
  16 + :email => raw_info["email"]
  17 + }
  18 + end
  19 +
  20 + def raw_info
  21 + #FIXME access the noosfero api (coming soon)
  22 + @raw_info ||= access_token.get('/plugin/oauth_provider/public/me').parsed
  23 + end
  24 + end
  25 + end
  26 +end
plugins/oauth_client/public/style.css 0 → 100644
@@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
  1 +.oauth-login .provider a {
  2 + min-width: 20px;
  3 + min-height: 20px;
  4 + background-size: 20px;
  5 + display: inline-block;
  6 + text-decoration: none;
  7 + background-repeat: no-repeat;
  8 + line-height: 20px;
  9 +}
  10 +.oauth-login .provider a img {
  11 + max-width: 40px;
  12 +}
  13 +.oauth-login .provider a:hover {
  14 + opacity: 0.7;
  15 +}
  16 +.oauth-login .provider .developer {
  17 + display: none;
  18 +}
plugins/oauth_client/test/functional/oauth_client_plugin_public_controller_test.rb 0 → 100644
@@ -0,0 +1,80 @@ @@ -0,0 +1,80 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class OauthClientPluginPublicControllerTest < ActionController::TestCase
  4 +
  5 + def setup
  6 + @auth = mock
  7 + @auth.stubs(:info).returns(mock)
  8 + request.env["omniauth.auth"] = @auth
  9 + @environment = Environment.default
  10 + @provider = OauthClientPlugin::Provider.create!(:name => 'provider', :strategy => 'provider', :enabled => true)
  11 + end
  12 + attr_reader :auth, :environment, :provider
  13 +
  14 + should 'redirect to signup when user is not found' do
  15 + auth.info.stubs(:email).returns("xyz123@noosfero.org")
  16 + auth.info.stubs(:name).returns('xyz123')
  17 + session[:provider_id] = provider.id
  18 +
  19 + get :callback
  20 + assert_match /.*\/account\/signup/, @response.redirect_url
  21 + end
  22 +
  23 + should 'redirect to login when user is found' do
  24 + user = fast_create(User, :environment_id => environment.id)
  25 + auth.info.stubs(:email).returns(user.email)
  26 + auth.info.stubs(:name).returns(user.name)
  27 + session[:provider_id] = provider.id
  28 +
  29 + get :callback
  30 + assert_redirected_to :controller => :account, :action => :login
  31 + assert_equal user.id, session[:user]
  32 + end
  33 +
  34 + should 'do not login when the provider is disabled' do
  35 + user = fast_create(User, :environment_id => environment.id)
  36 + auth.info.stubs(:email).returns(user.email)
  37 + auth.info.stubs(:name).returns(user.name)
  38 + session[:provider_id] = provider.id
  39 + provider.update_attribute(:enabled, false)
  40 +
  41 + get :callback
  42 + assert_redirected_to :controller => :account, :action => :login
  43 + assert_equal nil, session[:user]
  44 + end
  45 +
  46 + should 'do not login when the provider is disabled for a user' do
  47 + user = fast_create(User, :environment_id => environment.id)
  48 + auth.info.stubs(:email).returns(user.email)
  49 + auth.info.stubs(:name).returns(user.name)
  50 + session[:provider_id] = provider.id
  51 + user.oauth_user_providers.create(:user => user, :provider => provider, :enabled => false)
  52 +
  53 + get :callback
  54 + assert_redirected_to :controller => :account, :action => :login
  55 + assert_equal nil, session[:user]
  56 + end
  57 +
  58 + should 'save provider when an user login with it' do
  59 + user = fast_create(User, :environment_id => environment.id)
  60 + auth.info.stubs(:email).returns(user.email)
  61 + auth.info.stubs(:name).returns(user.name)
  62 + session[:provider_id] = provider.id
  63 +
  64 + get :callback
  65 + assert_equal [provider], user.oauth_providers
  66 + end
  67 +
  68 + should 'do not duplicate relations between an user and a provider when the same provider was used again in a login' do
  69 + user = fast_create(User, :environment_id => environment.id)
  70 + auth.info.stubs(:email).returns(user.email)
  71 + auth.info.stubs(:name).returns(user.name)
  72 + session[:provider_id] = provider.id
  73 +
  74 + get :callback
  75 + assert_no_difference 'user.oauth_user_providers.count' do
  76 + 3.times { get :callback }
  77 + end
  78 + end
  79 +
  80 +end
plugins/oauth_client/test/test_helper.rb 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +require File.dirname(__FILE__) + '/../../../test/test_helper'
plugins/oauth_client/test/unit/environment_test.rb 0 → 100644
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class UserTest < ActiveSupport::TestCase
  4 +
  5 + should 'be able to add oauth providers in a environment' do
  6 + env = fast_create(Environment)
  7 + env.oauth_providers << OauthClientPlugin::Provider.new(:name => 'test', :strategy => 'test')
  8 + end
  9 +
  10 +end
plugins/oauth_client/test/unit/oauth_client_plugin_test.rb 0 → 100644
@@ -0,0 +1,86 @@ @@ -0,0 +1,86 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class OauthClientPluginTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @plugin = OauthClientPlugin.new(self)
  7 + @params = {}
  8 + @plugin.stubs(:context).returns(self)
  9 + @environment = Environment.default
  10 + @session = {}
  11 + @request = mock
  12 + @provider = OauthClientPlugin::Provider.create!(:name => 'name', :strategy => 'strategy')
  13 + end
  14 +
  15 + attr_reader :params, :plugin, :environment, :session, :request, :provider
  16 +
  17 + should 'has extra contents for login' do
  18 + assert plugin.login_extra_contents
  19 + end
  20 +
  21 + should 'has no signup extra contents if no provider was enabled' do
  22 + assert_equal '', instance_eval(&plugin.signup_extra_contents)
  23 + end
  24 +
  25 + should 'has signup extra contents if oauth_data exists in session' do
  26 + session[:oauth_data] = {:oauth => 'test'}
  27 + expects(:render).with(:partial => 'account/oauth_signup').once
  28 + instance_eval(&plugin.signup_extra_contents)
  29 + end
  30 +
  31 + should 'define before filter for account controller' do
  32 + assert plugin.account_controller_filters
  33 + end
  34 +
  35 + should 'raise error if oauth email was changed' do
  36 + request.expects(:post?).returns(true)
  37 +
  38 + oauth_data = mock
  39 + info = mock
  40 + oauth_data.stubs(:info).returns(info)
  41 + oauth_data.stubs(:uid).returns('uid')
  42 + oauth_data.stubs(:provider).returns('provider')
  43 + info.stubs(:email).returns('test@example.com')
  44 + session[:oauth_data] = oauth_data
  45 + session[:provider_id] = provider.id
  46 +
  47 + params[:user] = {:email => 'test2@example.com'}
  48 + assert_raises RuntimeError do
  49 + instance_eval(&plugin.account_controller_filters[:block])
  50 + end
  51 + end
  52 +
  53 + should 'do not raise error if oauth email was not changed' do
  54 + request.expects(:post?).returns(true)
  55 +
  56 + oauth_data = mock
  57 + info = mock
  58 + oauth_data.stubs(:info).returns(info)
  59 + oauth_data.stubs(:uid).returns('uid')
  60 + oauth_data.stubs(:provider).returns('provider')
  61 + info.stubs(:email).returns('test@example.com')
  62 + session[:oauth_data] = oauth_data
  63 + session[:provider_id] = provider.id
  64 +
  65 + params[:user] = {:email => 'test@example.com'}
  66 + instance_eval(&plugin.account_controller_filters[:block])
  67 + end
  68 +
  69 + should 'do not raise error if oauth session is not set' do
  70 + instance_eval(&plugin.account_controller_filters[:block])
  71 + end
  72 +
  73 + should 'do not raise error if it is not a post' do
  74 + request.expects(:post?).returns(false)
  75 + params[:user] = {:email => 'test2@example.com'}
  76 +
  77 + oauth_data = mock
  78 + oauth_data.stubs(:uid).returns('uid')
  79 + oauth_data.stubs(:provider).returns('provider')
  80 + session[:provider_id] = provider.id
  81 +
  82 + session[:oauth_data] = oauth_data
  83 + instance_eval(&plugin.account_controller_filters[:block])
  84 + end
  85 +
  86 +end
plugins/oauth_client/test/unit/user_test.rb 0 → 100644
@@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class UserTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @provider = OauthClientPlugin::Provider.create!(:name => 'name', :strategy => 'strategy')
  7 + end
  8 + attr_reader :provider
  9 +
  10 + should 'password is not required if there is a oauth provider' do
  11 + User.create!(:email => 'testoauth@example.com', :login => 'testoauth', :oauth_providers => [provider])
  12 + end
  13 +
  14 + should 'password is required if there is a oauth provider' do
  15 + user = User.new(:email => 'testoauth@example.com', :login => 'testoauth')
  16 + user.save
  17 + assert user.errors[:password].present?
  18 + end
  19 +
  20 + should 'activate user when created with oauth' do
  21 + user = User.create!(:email => 'testoauth@example.com', :login => 'testoauth', :oauth_providers => [provider])
  22 + assert user.activated?
  23 + end
  24 +
  25 + should 'not activate user when created without oauth' do
  26 + user = fast_create(User)
  27 + assert !user.activated?
  28 + end
  29 +
  30 + should 'not make activation code when created with oauth' do
  31 + user = User.create!(:email => 'testoauth@example.com', :login => 'testoauth', :oauth_providers => [provider])
  32 + assert !user.activation_code
  33 + end
  34 +
  35 + should 'make activation code when created without oauth' do
  36 + user = User.create!(:email => 'testoauth@example.com', :login => 'testoauth', :password => 'test', :password_confirmation => 'test')
  37 + assert user.activation_code
  38 + end
  39 +
  40 +end
plugins/oauth_client/views/account/_oauth_signup.html.erb 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +<%= hidden_field_tag 'return_to', '/' %>
  2 +
  3 +<style>
  4 + #signup-password, #signup-password-confirmation, #signup-email {
  5 + display: none;
  6 + }
  7 +</style>
  8 +
  9 +<div id='signup-email-readonly'>
  10 + <%= labelled_form_field(_('Email'), text_field(:user, :email, :class => "disabled", :readonly => true)) %>
  11 +</div>
plugins/oauth_client/views/auth/_oauth_login.html.erb 0 → 100644
@@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
  1 +<div class="oauth-login">
  2 + <% unless providers.empty? %>
  3 + <%= _('Login with:') %>
  4 + <% end %>
  5 + <% providers.each do |provider| %>
  6 + <span class="provider">
  7 + <%= link_to provider.image ? image_tag(provider.image.public_filename) : provider.name, "/plugin/oauth_client/#{provider.strategy}?id=#{provider.id}", :class => provider.strategy, :title => provider.name %>
  8 + </span>
  9 + <% end %>
  10 +
  11 + <span class="provider">
  12 + <% unless Rails.env.production? %>
  13 + <%= link_to _('Developer Login'), "/plugin/oauth_client/developer", :class => 'developer' %>
  14 + <% end %>
  15 + </span>
  16 +</div>
plugins/oauth_client/views/oauth_client_plugin_admin/_noosfero_oauth2.html.erb 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +<%= f.fields_for :client_options, OpenStruct.new(provider.options[:client_options]) do |c| %>
  2 + <div class="client-url">
  3 + <%= labelled_form_field _('Client Url'), c.text_field(:site) %>
  4 + </div>
  5 +<% end %>
plugins/oauth_client/views/oauth_client_plugin_admin/edit.html.erb 0 → 100644
@@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
  1 +<h1><%= _('Oauth Client Settings') %></h1>
  2 +<h3><%= _('Edit Provider') %></h3>
  3 +
  4 +<%= form_for @provider, :url => {:action => 'edit'}, :method => 'post' do |f| %>
  5 +
  6 + <div class="enabled">
  7 + <%= labelled_form_field f.check_box(:enabled) + _('Enabled'), '' %>
  8 + </div>
  9 +
  10 + <div class="name">
  11 + <%= labelled_form_field _('Name'), f.text_field(:name) %>
  12 + </div>
  13 +
  14 + <div class="strategy">
  15 + <%= labelled_form_field _('Strategy'), f.select(:strategy, OauthClientPlugin::PROVIDERS) %>
  16 + </div>
  17 +
  18 + <div class="client-id">
  19 + <%= labelled_form_field _('Client Id'), f.text_field(:client_id) %>
  20 + </div>
  21 +
  22 + <div class="client-secret">
  23 + <%= labelled_form_field _('Client Secret'), f.text_field(:client_secret) %>
  24 + </div>
  25 +
  26 + <% if File.exists?(File.join(File.dirname(__FILE__), "_#{@provider.strategy}.html.erb")) %>
  27 + <%= render :partial => "#{@provider.strategy}", :locals => {:f => f, :provider => @provider} %>
  28 + <% end %>
  29 +
  30 + <div class="image-icon">
  31 + <%= f.fields_for :image_builder, @provider.image do |i| %>
  32 + <%= file_field_or_thumbnail(_('Image:'), @provider.image, i) %><%= _("Max size: %s (.jpg, .gif, .png)")% Image.max_size.to_humanreadable %>
  33 + <% end %>
  34 + </div>
  35 +
  36 + <% button_bar do %>
  37 + <%= submit_button(:save, _('Save'), :cancel => {:action => 'index'}) %>
  38 + <% end %>
  39 +<% end %>
plugins/oauth_client/views/oauth_client_plugin_admin/index.html.erb 0 → 100644
@@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
  1 +<h1><%= _('Oauth Client Settings') %></h1>
  2 +<h3><%= _('Providers') %></h3>
  3 +<%= button :add, _('New'), {:action => 'new'} %>
  4 +<table>
  5 + <tr>
  6 + <th><%= _('Name') %></th>
  7 + <th><%= _('Strategy') %></th>
  8 + <th><%= _('Actions') %></th>
  9 + </tr>
  10 +
  11 + <% environment.oauth_providers.each do |provider| %>
  12 + <tr>
  13 + <td><%= provider.name %></td>
  14 + <td><%= provider.strategy %></td>
  15 + <td>
  16 + <%= link_to _('Edit'), {:action => 'edit', :id => provider.id} %>
  17 + <%= link_to _('Remove'), {:action => 'remove', :id => provider.id} %>
  18 + </td>
  19 + </tr>
  20 + <% end %>
  21 +</table>
  22 +<div class="actions">
  23 + <%= button(:back, _('Go back'), {:controller => 'plugins', :action => 'index'}) %>
  24 +</div>
plugins/oauth_provider/Gemfile 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +gem 'doorkeeper', '~> 1.4.0'
plugins/oauth_provider/README.md 0 → 100644
@@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
  1 +README - Oauth Provider Plugin
  2 +================================
  3 +
  4 +OauthProvider is a plugin which allow noosfero to be used as an oauth provider
  5 +
  6 +Install
  7 +=======
  8 +
  9 +Enable Plugin
  10 +-------------
  11 +
  12 +cd <your_noosfero_dir>
  13 +./script/noosfero-plugins enable oauth_provider
  14 +
  15 +Active Plugin
  16 +-------------
  17 +
  18 +As a Noosfero administrator user, go to administrator panel:
  19 +
  20 +- Click on "Enable/disable plugins" option
  21 +- Click on "Oauth Provider Plugin" check-box
  22 +
  23 +Varnish Settings
  24 +================
  25 +If varnish has been used in your stack, you've to prevent cookies to be removed when calling authorization actions for oauth_provider. E.g.:
  26 +
  27 +```
  28 +if (req.url !~ "^/plugin/oauth_provider/*" && req.http.cookie !~ "_noosfero_.*") {
  29 + unset req.http.cookie;
  30 + return(lookup);
  31 +}
  32 +```
  33 +
  34 +Development
  35 +===========
  36 +
  37 +Running OauthProvider tests
  38 +--------------------
  39 +
  40 +$ rake test:noosfero_plugins:oauth_provider
  41 +
  42 +License
  43 +=======
  44 +
  45 +Copyright (c) The Author developers.
  46 +
  47 +See Noosfero license.
plugins/oauth_provider/controllers/doorkeeper/application_controller.rb 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +module Doorkeeper
  2 + class ApplicationController < ApplicationController
  3 +
  4 + include Helpers::Controller
  5 + helper 'doorkeeper/form_errors'
  6 +
  7 + end
  8 +end
plugins/oauth_provider/controllers/oauth_provider_applications_controller.rb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +class OauthProviderApplicationsController < Doorkeeper::ApplicationsController
  2 +
  3 + no_design_blocks
  4 + layout :get_layout
  5 +
  6 + def show
  7 + end
  8 +
  9 +end
plugins/oauth_provider/controllers/oauth_provider_authorizations_controller.rb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +class OauthProviderAuthorizationsController < Doorkeeper::AuthorizationsController
  2 +
  3 + no_design_blocks
  4 + layout :get_layout
  5 +
  6 + def index
  7 + end
  8 +
  9 +end
plugins/oauth_provider/controllers/oauth_provider_authorized_applications_controller.rb 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +class OauthProviderAuthorizedApplicationsController < Doorkeeper::AuthorizedApplicationsController
  2 +
  3 + no_design_blocks
  4 + layout :get_layout
  5 +
  6 +end
plugins/oauth_provider/controllers/oauth_provider_plugin_admin_controller.rb 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +class OauthProviderPluginAdminController < AdminController
  2 +
  3 + def index
  4 + end
  5 +
  6 +end
plugins/oauth_provider/controllers/public/oauth_provider_plugin_public_controller.rb 0 → 100644
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +class OauthProviderPluginPublicController < PublicController
  2 +
  3 + doorkeeper_for :me
  4 +
  5 + def me
  6 + user = environment.users.find(doorkeeper_token.resource_owner_id) if doorkeeper_token
  7 + render :json => {:id =>user.login, :email => user.email}.to_json
  8 + end
  9 +
  10 +end
plugins/oauth_provider/db/migrate/20140829153047_create_doorkeeper_tables.rb 0 → 100644
@@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
  1 +class CreateDoorkeeperTables < ActiveRecord::Migration
  2 + def change
  3 + create_table :oauth_applications do |t|
  4 + t.string :name, null: false
  5 + t.string :uid, null: false
  6 + t.string :secret, null: false
  7 + t.text :redirect_uri, null: false
  8 + t.timestamps
  9 + end
  10 +
  11 + add_index :oauth_applications, :uid, unique: true
  12 +
  13 + create_table :oauth_access_grants do |t|
  14 + t.integer :resource_owner_id, null: false
  15 + t.integer :application_id, null: false
  16 + t.string :token, null: false
  17 + t.integer :expires_in, null: false
  18 + t.text :redirect_uri, null: false
  19 + t.datetime :created_at, null: false
  20 + t.datetime :revoked_at
  21 + t.string :scopes
  22 + end
  23 +
  24 + add_index :oauth_access_grants, :token, unique: true
  25 +
  26 + create_table :oauth_access_tokens do |t|
  27 + t.integer :resource_owner_id
  28 + t.integer :application_id
  29 + t.string :token, null: false
  30 + t.string :refresh_token
  31 + t.integer :expires_in
  32 + t.datetime :revoked_at
  33 + t.datetime :created_at, null: false
  34 + t.string :scopes
  35 + end
  36 +
  37 + add_index :oauth_access_tokens, :token, unique: true
  38 + add_index :oauth_access_tokens, :resource_owner_id
  39 + add_index :oauth_access_tokens, :refresh_token, unique: true
  40 + end
  41 +end
plugins/oauth_provider/lib/oauth_provider_plugin.rb 0 → 100644
@@ -0,0 +1,55 @@ @@ -0,0 +1,55 @@
  1 +class OauthProviderPlugin < Noosfero::Plugin
  2 +
  3 + def self.plugin_name
  4 + "Oauth Provider Plugin"
  5 + end
  6 +
  7 + def self.plugin_description
  8 + _("Oauth Provider.")
  9 + end
  10 +
  11 + def stylesheet?
  12 + true
  13 + end
  14 +
  15 + Doorkeeper.configure do
  16 + orm :active_record
  17 +
  18 + resource_owner_authenticator do
  19 + domain = Domain.find_by_name(request.host)
  20 + environment = domain ? domain.environment : Environment.default
  21 + environment.users.find_by_id(session[:user]) || redirect_to('/account/login')
  22 + end
  23 +
  24 + admin_authenticator do
  25 + domain = Domain.find_by_name(request.host)
  26 + environment = domain ? domain.environment : Environment.default
  27 + user = environment.users.find_by_id(session[:user])
  28 + unless user && user.person.is_admin?(environment)
  29 + redirect_to('/account/login')
  30 + end
  31 + user
  32 + end
  33 +
  34 + default_scopes :public
  35 + end
  36 +
  37 + Rails.configuration.to_prepare do
  38 + Rails.application.routes.prepend do
  39 + scope 'oauth_provider' do
  40 + use_doorkeeper do
  41 + controllers ({
  42 + :applications => 'oauth_provider_applications',
  43 + :authorized_applications => 'oauth_provider_authorized_applications',
  44 + :authorizations => 'oauth_provider_authorizations'
  45 + })
  46 + end
  47 + end
  48 + end
  49 + end
  50 +
  51 + SCOPE_TRANSLATION = {
  52 + 'public' => _('Access your public data')
  53 + }
  54 +
  55 +end
plugins/oauth_provider/public/style.css 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +.oauth-provider-authorize .actions form {
  2 + display: inline-block;
  3 +}
  4 +.oauth-provider-authorize .h4 {
  5 + font-size: 14px;
  6 + color: rgb(36, 36, 36)
  7 +}
  8 +.oauth-provider-authorize #oauth-permissions {
  9 + color: rgb(92, 92, 92);
  10 +}
  11 +.oauth-provider .actions {
  12 + margin-top: 10px;
  13 +}
plugins/oauth_provider/views/doorkeeper/applications/_delete_form.html.erb 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +<%- submit_btn_css ||= 'btn btn-link' %>
  2 +<%= form_tag [:oauth, application] do %>
  3 + <input type="hidden" name="_method" value="delete">
  4 + <%= submit_tag 'Destroy', onclick: "return confirm('Are you sure?')", class: submit_btn_css %>
  5 +<% end %>
plugins/oauth_provider/views/doorkeeper/applications/_form.html.erb 0 → 100644
@@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
  1 +<%= form_for [:oauth, application], html: {class: 'form-horizontal', role: 'form'} do |f| %>
  2 + <% if application.errors.any? %>
  3 + <div class="alert alert-danger" data-alert>
  4 + <p><%= _('Whoops! Check your form for possible errors') %></p>
  5 + </div>
  6 + <% end %>
  7 +
  8 + <%= content_tag :div, class: "form-group#{' has-error' if application.errors[:name].present?}" do %>
  9 + <%= f.label :name, class: 'col-sm-2 control-label', for: 'application_name' %>
  10 + <div class="col-sm-10">
  11 + <%= f.text_field :name, class: 'form-control' %>
  12 + <%= doorkeeper_errors_for application, :name %>
  13 + </div>
  14 + <% end %>
  15 +
  16 + <%= content_tag :div, class: "form-group#{' has-error' if application.errors[:redirect_uri].present?}" do %>
  17 + <%= f.label :redirect_uri, class: 'col-sm-2 control-label', for: 'application_redirect_uri' %>
  18 + <div class="col-sm-10">
  19 + <%= f.text_area :redirect_uri, class: 'form-control' %>
  20 + <%= doorkeeper_errors_for application, :redirect_uri %>
  21 + <span class="help-block">
  22 + <%= _('Use one line per URI') %>
  23 + </span>
  24 + <% if Doorkeeper.configuration.native_redirect_uri %>
  25 + <span class="help-block">
  26 + Use <code><%= Doorkeeper.configuration.native_redirect_uri %></code> for local tests
  27 + </span>
  28 + <% end %>
  29 + </div>
  30 + <% end %>
  31 +
  32 + <div class="form-group">
  33 + <div class="col-sm-offset-2 col-sm-10">
  34 + <%= f.submit _('Submit'), class: "btn btn-primary" %>
  35 + <%= link_to _("Cancel"), oauth_applications_path, :class => "btn btn-default" %>
  36 + </div>
  37 + </div>
  38 +<% end %>
  39 +
plugins/oauth_provider/views/doorkeeper/applications/edit.html.erb 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +<div class="page-header">
  2 + <h1><%= _('Edit application') %></h1>
  3 +</div>
  4 +
  5 +<%= render 'form', application: @application %>
plugins/oauth_provider/views/doorkeeper/applications/index.html.erb 0 → 100644
@@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
  1 +<div class="oauth-provider">
  2 +<div class="page-header">
  3 + <h3><%= link_to _('Oauh Provider'), '/admin/plugin/oauth_provider' %></h3>
  4 +</div>
  5 +
  6 +<p><%= link_to _('New Application'), new_oauth_application_path, class: 'btn btn-success' %></p>
  7 +
  8 +<table class="table table-striped">
  9 + <thead>
  10 + <tr>
  11 + <th><%= _('Name') %></th>
  12 + <th><%= _('Callback URL') %></th>
  13 + <th></th>
  14 + <th></th>
  15 + </tr>
  16 + </thead>
  17 + <tbody>
  18 + <% @applications.each do |application| %>
  19 + <tr id="application_<%= application.id %>">
  20 + <td><%= link_to application.name, [:oauth, application] %></td>
  21 + <td><%= application.redirect_uri %></td>
  22 + <td><%= link_to _('Edit'), edit_oauth_application_path(application), class: 'btn btn-link' %></td>
  23 + <td><%= render 'delete_form', application: application %></td>
  24 + </tr>
  25 + <% end %>
  26 + </tbody>
  27 +</table>
  28 +<div class="actions">
  29 + <%= button(:back, _('Go back'), {:controller => 'oauth_provider_plugin_admin', :action => 'index'}) %>
  30 +</div>
  31 +</div>
plugins/oauth_provider/views/doorkeeper/applications/new.html.erb 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +<div class="page-header">
  2 + <h1>New application</h1>
  3 +</div>
  4 +
  5 +<%= render 'form', application: @application %>
plugins/oauth_provider/views/doorkeeper/applications/show.html.erb 0 → 100644
@@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
  1 +<div class="page-header">
  2 + <h1><%= _('Application: %s' % @application.name) %></h1>
  3 +</div>
  4 +
  5 +<div class="row">
  6 + <div class="col-md-8">
  7 + <h4><%= _('Application Id:') %></h4>
  8 +
  9 + <p><code id="application_id"><%= @application.uid %></code></p>
  10 +
  11 + <h4><%= _('Secret:') %></h4>
  12 +
  13 + <p><code id="secret"><%= @application.secret %></code></p>
  14 +
  15 + <h4><%= _('Callback urls:') %></h4>
  16 +
  17 + <table>
  18 + <% @application.redirect_uri.split.each do |uri| %>
  19 + <tr>
  20 + <td>
  21 + <code><%= uri %></code>
  22 + </td>
  23 + <td>
  24 + </td>
  25 + </tr>
  26 + <% end %>
  27 + </table>
  28 + </div>
  29 +
  30 + <div class="col-md-4">
  31 + <h3><%= _('Actions') %></h3>
  32 +
  33 + <p>
  34 + <%= link_to _('Edit'), edit_oauth_application_path(@application), class: 'btn btn-primary' %>
  35 + <%= link_to _("Cancel"), oauth_applications_path, :class => "btn btn-default" %>
  36 + </p>
  37 +
  38 + <p><%= render 'delete_form', application: @application, submit_btn_css: 'btn btn-danger' %></p>
  39 + </div>
  40 +</div>
plugins/oauth_provider/views/doorkeeper/authorizations/error.html.erb 0 → 100644
@@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
  1 +<div class="page-header">
  2 + <h1>An error has occurred</h1>
  3 +</div>
  4 +
  5 +<main role="main">
  6 + <pre><%= @pre_auth.error_response.body[:error_description] %></pre>
  7 +</main>
plugins/oauth_provider/views/doorkeeper/authorizations/new.html.erb 0 → 100644
@@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
  1 +<div class="oauth-provider-authorize">
  2 +
  3 +<header class="page-header" role="banner">
  4 + <h1><%= _('Authorize required') %></h1>
  5 +</header>
  6 +
  7 +<main role="main">
  8 + <p class="h4">
  9 + <%= _('Authorize %s to use your account?' % "<strong class=\"text-info\">#{@pre_auth.client.name}</strong>") %>
  10 + </p>
  11 +
  12 + <% if @pre_auth.scopes %>
  13 + <div id="oauth-permissions">
  14 + <p><%= _('This application will be able to:') %></p>
  15 +
  16 + <ul class="text-info">
  17 + <% @pre_auth.scopes.each do |scope| %>
  18 + <li><%= OauthProviderPlugin::SCOPE_TRANSLATION[scope] %></li>
  19 + <% end %>
  20 + </ul>
  21 + </div>
  22 + <% end %>
  23 +
  24 + <div class="actions">
  25 + <%= form_tag oauth_authorization_path, method: :post do %>
  26 + <%= hidden_field_tag :client_id, @pre_auth.client.uid %>
  27 + <%= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri %>
  28 + <%= hidden_field_tag :state, @pre_auth.state %>
  29 + <%= hidden_field_tag :response_type, @pre_auth.response_type %>
  30 + <%= hidden_field_tag :scope, @pre_auth.scope %>
  31 + <%= submit_button :ok, _("Authorize") %>
  32 + <% end %>
  33 + <%= form_tag oauth_authorization_path, method: :delete do %>
  34 + <%= hidden_field_tag :client_id, @pre_auth.client.uid %>
  35 + <%= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri %>
  36 + <%= hidden_field_tag :state, @pre_auth.state %>
  37 + <%= hidden_field_tag :response_type, @pre_auth.response_type %>
  38 + <%= hidden_field_tag :scope, @pre_auth.scope %>
  39 + <%= submit_button :cancel, _("Deny") %>
  40 + <% end %>
  41 + </div>
  42 +</main>
  43 +</div>
plugins/oauth_provider/views/doorkeeper/authorizations/show.html.erb 0 → 100644
@@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
  1 +<header class="page-header">
  2 + <h1>Authorization code:</h1>
  3 +</header>
  4 +
  5 +<main role="main">
  6 + <code id="authorization_code"><%= params[:code] %></code>
  7 +</main>
plugins/oauth_provider/views/doorkeeper/authorized_applications/_delete_form.html.erb 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +<%- submit_btn_css ||= 'btn btn-link' %>
  2 +<%= form_tag oauth_authorized_application_path(application) do %>
  3 + <input type="hidden" name="_method" value="delete">
  4 + <%= submit_tag 'Revoke', onclick: "return confirm('Are you sure?')", class: submit_btn_css %>
  5 +<% end %>
plugins/oauth_provider/views/doorkeeper/authorized_applications/index.html.erb 0 → 100644
@@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
  1 +<div class="oauth-provider">
  2 +<header class="page-header">
  3 + <h1>Your authorized applications</h1>
  4 +</header>
  5 +
  6 +<main role="main">
  7 + <table class="table table-striped">
  8 + <thead>
  9 + <tr>
  10 + <th>Application</th>
  11 + <th>Created At</th>
  12 + <th></th>
  13 + <th></th>
  14 + </tr>
  15 + </thead>
  16 + <tbody>
  17 + <% @applications.each do |application| %>
  18 + <tr>
  19 + <td><%= application.name %></td>
  20 + <td><%= application.created_at.strftime('%Y-%m-%d %H:%M:%S') %></td>
  21 + <td><%= render 'delete_form', application: application %></td>
  22 + </tr>
  23 + <% end %>
  24 + </tbody>
  25 + </table>
  26 +</main>
  27 +
  28 +<div class="actions">
  29 + <%= button(:back, _('Go back'), :back) %>
  30 +</div>
  31 +</div>
plugins/oauth_provider/views/oauth_provider_plugin_admin/index.html.erb 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +<div class="oauth-provider">
  2 +<h3><%= _('Oauh Provider') %></h3>
  3 +
  4 + <div class="applications">
  5 + <%= link_to _('Applications'), oauth_applications_path %>
  6 + </div>
  7 + <div class="authorized-applications">
  8 + <%= link_to _('Authorized Applications'), oauth_authorized_applications_path %>
  9 + </div>
  10 +
  11 + <div class="actions">
  12 + <%= button(:back, _('Go back'), {:controller => 'plugins', :action => 'index'}) %>
  13 + </div>
  14 +</div>
plugins/relevant_content/lib/relevant_content_plugin/relevant_content_block.rb
@@ -4,7 +4,7 @@ class RelevantContentPlugin::RelevantContentBlock &lt; Block @@ -4,7 +4,7 @@ class RelevantContentPlugin::RelevantContentBlock &lt; Block
4 end 4 end
5 5
6 def default_title 6 def default_title
7 - _('Relevant content') 7 + _('Relevant content')
8 end 8 end
9 9
10 def help 10 def help
@@ -53,7 +53,7 @@ class RelevantContentPlugin::RelevantContentBlock &lt; Block @@ -53,7 +53,7 @@ class RelevantContentPlugin::RelevantContentBlock &lt; Block
53 env = owner.environment 53 env = owner.environment
54 end 54 end
55 55
56 - if env.plugin_enabled?(VotePlugin) 56 + if env.plugin_enabled?('VotePlugin')
57 if self.show_most_liked 57 if self.show_most_liked
58 docs = Article.more_positive_votes(owner, self.limit) 58 docs = Article.more_positive_votes(owner, self.limit)
59 if !docs.blank? 59 if !docs.blank?
plugins/relevant_content/test/unit/article.rb
@@ -20,10 +20,10 @@ class RelevantContentBlockTest &lt; ActiveSupport::TestCase @@ -20,10 +20,10 @@ class RelevantContentBlockTest &lt; ActiveSupport::TestCase
20 20
21 def enable_vote_plugin 21 def enable_vote_plugin
22 enabled = false 22 enabled = false
23 - environment=Environment.default 23 + environment = Environment.default
24 if Noosfero::Plugin.all.include?('VotePlugin') 24 if Noosfero::Plugin.all.include?('VotePlugin')
25 - if not environment.enabled_plugins.include?(:vote)  
26 - environment.enable_plugin(Vote) 25 + if not environment.enabled_plugins.include?('VotePlugin')
  26 + environment.enable_plugin(VotePlugin)
27 environment.save! 27 environment.save!
28 end 28 end
29 enabled = true 29 enabled = true
@@ -145,4 +145,4 @@ class RelevantContentBlockTest &lt; ActiveSupport::TestCase @@ -145,4 +145,4 @@ class RelevantContentBlockTest &lt; ActiveSupport::TestCase
145 assert_equal '23 votes for 29 votes against', articles.first.name 145 assert_equal '23 votes for 29 votes against', articles.first.name
146 assert_equal '2 votes against', articles.last.name 146 assert_equal '2 votes against', articles.last.name
147 end 147 end
148 -end  
149 \ No newline at end of file 148 \ No newline at end of file
  149 +end
plugins/relevant_content/test/unit/relevant_content_block_test.rb
@@ -44,4 +44,19 @@ class RelevantContentBlockTest &lt; ActiveSupport::TestCase @@ -44,4 +44,19 @@ class RelevantContentBlockTest &lt; ActiveSupport::TestCase
44 assert_equal RelevantContentPlugin::RelevantContentBlock.expire_on, {:environment=>[:article], :profile=>[:article]} 44 assert_equal RelevantContentPlugin::RelevantContentBlock.expire_on, {:environment=>[:article], :profile=>[:article]}
45 end 45 end
46 46
  47 + should 'not crash if vote plugin is not found' do
  48 + box = fast_create(Box, :owner_id => @profile.id, :owner_type => 'Profile')
  49 + block = RelevantContentPlugin::RelevantContentBlock.new(:box => box)
  50 +
  51 + Environment.any_instance.stubs(:enabled_plugins).returns(['RelevantContent'])
  52 + # When the plugin is disabled from noosfero instance, its constant name is
  53 + # undefined. To test this case, I have to manually undefine the constant
  54 + # if necessary.
  55 + Object.send(:remove_const, VotePlugin.to_s) if defined? VotePlugin
  56 +
  57 + assert_nothing_raised do
  58 + block.content
  59 + end
  60 + end
  61 +
47 end 62 end
plugins/shopping_cart/public/cart.js
@@ -290,14 +290,11 @@ function Cart(config) { @@ -290,14 +290,11 @@ function Cart(config) {
290 log.error('Send request - HTTP '+status, errorThrown); 290 log.error('Send request - HTTP '+status, errorThrown);
291 }, 291 },
292 complete: function() { 292 complete: function() {
293 - $.colorbox.close(); 293 + noosfero.modal.close();
294 } 294 }
295 }); 295 });
296 } 296 }
297 297
298 - Cart.colorbox_close = function() {  
299 - $.colorbox.close();  
300 - }  
301 298
302 $(window).bind('beforeunload', function(){ 299 $(window).bind('beforeunload', function(){
303 log('Page unload.'); 300 log('Page unload.');
plugins/shopping_cart/views/cart.html.erb
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 <a href="cart:clean" onclick="Cart.clean(this); return false" class="cart-clean"><%=_('Clean basket')%></a> 5 <a href="cart:clean" onclick="Cart.clean(this); return false" class="cart-clean"><%=_('Clean basket')%></a>
6 <ul class="cart-items"></ul> 6 <ul class="cart-items"></ul>
7 <div class="cart-total"><%=_('Total:')%> <b></b></div> 7 <div class="cart-total"><%=_('Total:')%> <b></b></div>
8 - <a href="/plugin/shopping_cart/buy" class="cart-buy colorbox"><%=_('Shopping checkout')%></a> 8 + <a href="/plugin/shopping_cart/buy" class="cart-buy modal"><%=_('Shopping checkout')%></a>
9 </div> 9 </div>
10 <a href="#" onclick="Cart.toggle(this); return false" class="cart-toggle"> 10 <a href="#" onclick="Cart.toggle(this); return false" class="cart-toggle">
11 <span class="str-show"><%=_('Show basket')%></span> 11 <span class="str-show"><%=_('Show basket')%></span>
plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb
@@ -24,7 +24,7 @@ @@ -24,7 +24,7 @@
24 <% end %> 24 <% end %>
25 <% delivery_option = @settings.delivery_options.first && @settings.delivery_options.first.first %> 25 <% delivery_option = @settings.delivery_options.first && @settings.delivery_options.first.first %>
26 <%= items_table(@cart[:items], @profile, delivery_option) %> 26 <%= items_table(@cart[:items], @profile, delivery_option) %>
27 - <%= link_to '', '#', :onclick => "Cart.colorbox_close(this);", :class => 'cart-box-close icon-cancel' %> 27 + <%= link_to_function '', "noosfero.modal.close();", :class => 'cart-box-close icon-cancel' %>
28 </div> 28 </div>
29 29
30 <%= javascript_include_tag '../plugins/shopping_cart/buy' %> 30 <%= javascript_include_tag '../plugins/shopping_cart/buy' %>
plugins/shopping_cart/views/shopping_cart_plugin_profile/buy.html.erb
@@ -17,7 +17,7 @@ @@ -17,7 +17,7 @@
17 </div> 17 </div>
18 <% end %> 18 <% end %>
19 <%= items_table(session[:cart][:items], profile) %> 19 <%= items_table(session[:cart][:items], profile) %>
20 - <%= link_to '', '#', :onclick => "Cart.colorbox_close(this);", :class => 'cart-box-close icon-cancel' %> 20 + <%= link_to_function '', "noosfero.modal.close();", :class => 'cart-box-close icon-cancel' %>
21 </div> 21 </div>
22 22
23 <script type="text/javascript"> 23 <script type="text/javascript">
plugins/statistics/test/functional/statistics_plugin_home_controller_test.rb 100644 → 100755
@@ -84,6 +84,9 @@ class HomeControllerTest &lt; ActionController::TestCase @@ -84,6 +84,9 @@ class HomeControllerTest &lt; ActionController::TestCase
84 end 84 end
85 85
86 should 'not display products class in statistics-block-data block' do 86 should 'not display products class in statistics-block-data block' do
  87 + @block.product_counter = true
  88 + @environment.disable('products_for_enterprises')
  89 + @block.save!
87 get :index 90 get :index
88 91
89 assert_no_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'products'} } 92 assert_no_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'products'} }
plugins/stoa/public/javascripts/signup_complement.js
@@ -55,9 +55,10 @@ $(&quot;#usp_id_field&quot;).observe_field(1, function(){ @@ -55,9 +55,10 @@ $(&quot;#usp_id_field&quot;).observe_field(1, function(){
55 }); 55 });
56 56
57 function displayValidationUspIdError(error){ 57 function displayValidationUspIdError(error){
58 - jQuery.colorbox({html: '<h2>'+error.message+'</h2>'+error.backtrace.join("<br />"), 58 + noosfero.modal.html('<h2>'+error.message+'</h2>'+error.backtrace.join("<br />"), {
59 height: "80%", 59 height: "80%",
60 - width: "70%" }); 60 + width: "70%"
  61 + });
61 } 62 }
62 63
63 jQuery('#usp_id_field').focus(function() { jQuery('#usp-id-balloon').fadeIn('slow'); }); 64 jQuery('#usp_id_field').focus(function() { jQuery('#usp-id-balloon').fadeIn('slow'); });
plugins/tolerance_time/lib/tolerance_time_plugin.rb
@@ -28,8 +28,7 @@ class ToleranceTimePlugin &lt; Noosfero::Plugin @@ -28,8 +28,7 @@ class ToleranceTimePlugin &lt; Noosfero::Plugin
28 end 28 end
29 29
30 def cms_controller_filters 30 def cms_controller_filters
31 - p = Proc.new { |context| return if !context.environment.plugin_enabled?(ToleranceTimePlugin) }  
32 - block = lambda do 31 + block = proc do
33 content = Article.find(params[:id]) 32 content = Article.find(params[:id])
34 if ToleranceTimePlugin.expired?(content) 33 if ToleranceTimePlugin.expired?(content)
35 session[:notice] = _("This content can't be edited anymore because it expired the tolerance time") 34 session[:notice] = _("This content can't be edited anymore because it expired the tolerance time")
@@ -43,8 +42,7 @@ class ToleranceTimePlugin &lt; Noosfero::Plugin @@ -43,8 +42,7 @@ class ToleranceTimePlugin &lt; Noosfero::Plugin
43 end 42 end
44 43
45 def content_viewer_controller_filters 44 def content_viewer_controller_filters
46 - p = Proc.new { |context| return if !context.environment.plugin_enabled?(ToleranceTimePlugin) }  
47 - block = lambda do 45 + block = proc do
48 content = Comment.find(params[:id]) 46 content = Comment.find(params[:id])
49 if ToleranceTimePlugin.expired?(content) 47 if ToleranceTimePlugin.expired?(content)
50 session[:notice] = _("This content can't be edited anymore because it expired the tolerance time") 48 session[:notice] = _("This content can't be edited anymore because it expired the tolerance time")
public/designs/templates/topleft/config.yml 0 → 100644
@@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
  1 +name: "Top and Left Bar"
  2 +title: "Style 2 columns and a box at top of content"
  3 +description: "A theme with 2 columns and a box at the top of the content"
  4 +number_of_boxes: 3
public/designs/templates/topleft/stylesheets/style.css 0 → 100644
@@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
  1 +#boxes {
  2 + display: table;
  3 + width: 100%;
  4 +}
  5 +
  6 +.box-1 {
  7 + margin: 0 0 0 240px;
  8 +}
  9 +
  10 +.box-1 .blocks {
  11 + width: 100%;
  12 + float: left;
  13 +}
  14 +
  15 +.box-2 {
  16 + position: relative;
  17 + float: left;
  18 + width: 190px;
  19 +}
  20 +
  21 +.box-3 {
  22 + position: relative;
  23 + display: table-footer-group;
  24 + width: 100%;
  25 +}
  26 +
  27 +#profile-activity ul,
  28 +#profile-network ul,
  29 +#profile-wall ul {
  30 + width: 460px;
  31 +}
  32 +#profile-activity ul.comment-replies,
  33 +#profile-network ul.comment-replies,
  34 +#profile-wall ul.comment-replies {
  35 + width: auto;
  36 +}
  37 +
public/designs/templates/topleft/thumbnail.png 0 → 100644

3.87 KB

public/designs/templates/topleft/thumbnail.svg 0 → 100644
@@ -0,0 +1,239 @@ @@ -0,0 +1,239 @@
  1 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
  3 +
  4 +<svg
  5 + xmlns:dc="http://purl.org/dc/elements/1.1/"
  6 + xmlns:cc="http://creativecommons.org/ns#"
  7 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  8 + xmlns:svg="http://www.w3.org/2000/svg"
  9 + xmlns="http://www.w3.org/2000/svg"
  10 + xmlns:xlink="http://www.w3.org/1999/xlink"
  11 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
  12 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
  13 + width="64px"
  14 + height="64px"
  15 + id="svg2383"
  16 + sodipodi:version="0.32"
  17 + inkscape:version="0.48.4 r9939"
  18 + sodipodi:docname="thumbnail.svg"
  19 + inkscape:output_extension="org.inkscape.output.svg.inkscape"
  20 + inkscape:export-filename="thumbnail.png"
  21 + inkscape:export-xdpi="90"
  22 + inkscape:export-ydpi="90"
  23 + version="1.1">
  24 + <defs
  25 + id="defs2385">
  26 + <linearGradient
  27 + id="linearGradient3263">
  28 + <stop
  29 + id="stop3265"
  30 + offset="0"
  31 + style="stop-color:#204a87;stop-opacity:1" />
  32 + <stop
  33 + id="stop3267"
  34 + offset="1"
  35 + style="stop-color:#729fcf;stop-opacity:1" />
  36 + </linearGradient>
  37 + <linearGradient
  38 + id="linearGradient3257"
  39 + inkscape:collect="always">
  40 + <stop
  41 + id="stop3259"
  42 + offset="0"
  43 + style="stop-color:#204a87;stop-opacity:1" />
  44 + <stop
  45 + id="stop3261"
  46 + offset="1"
  47 + style="stop-color:#729fcf;stop-opacity:1" />
  48 + </linearGradient>
  49 + <linearGradient
  50 + inkscape:collect="always"
  51 + id="linearGradient3245">
  52 + <stop
  53 + style="stop-color:#204a87;stop-opacity:1"
  54 + offset="0"
  55 + id="stop3247" />
  56 + <stop
  57 + style="stop-color:#729fcf;stop-opacity:1"
  58 + offset="1"
  59 + id="stop3249" />
  60 + </linearGradient>
  61 + <inkscape:perspective
  62 + sodipodi:type="inkscape:persp3d"
  63 + inkscape:vp_x="0 : 32 : 1"
  64 + inkscape:vp_y="0 : 1000 : 0"
  65 + inkscape:vp_z="64 : 32 : 1"
  66 + inkscape:persp3d-origin="32 : 21.333333 : 1"
  67 + id="perspective2391" />
  68 + <filter
  69 + inkscape:collect="always"
  70 + id="filter3241">
  71 + <feGaussianBlur
  72 + inkscape:collect="always"
  73 + stdDeviation="0.9075"
  74 + id="feGaussianBlur3243" />
  75 + </filter>
  76 + <linearGradient
  77 + inkscape:collect="always"
  78 + xlink:href="#linearGradient3245"
  79 + id="linearGradient3251"
  80 + x1="11.5"
  81 + y1="60.5"
  82 + x2="3.5"
  83 + y2="3.5"
  84 + gradientUnits="userSpaceOnUse"
  85 + gradientTransform="matrix(1.0025263,0,0,0.76423683,0.2157619,0.85033188)" />
  86 + <linearGradient
  87 + inkscape:collect="always"
  88 + xlink:href="#linearGradient3263"
  89 + id="linearGradient3253"
  90 + x1="42.5"
  91 + y1="60.5"
  92 + x2="19.5"
  93 + y2="3.5"
  94 + gradientUnits="userSpaceOnUse"
  95 + gradientTransform="matrix(1.4160224,0,0,0.76166072,-5.6247232,0.93276759)" />
  96 + <linearGradient
  97 + inkscape:collect="always"
  98 + xlink:href="#linearGradient3257"
  99 + id="linearGradient3255"
  100 + x1="60.5"
  101 + y1="60.5"
  102 + x2="51.5"
  103 + y2="3.5"
  104 + gradientUnits="userSpaceOnUse"
  105 + gradientTransform="translate(0.32391508,-62.512846)" />
  106 + </defs>
  107 + <sodipodi:namedview
  108 + id="base"
  109 + pagecolor="#ffffff"
  110 + bordercolor="#666666"
  111 + borderopacity="1.0"
  112 + inkscape:pageopacity="0.0"
  113 + inkscape:pageshadow="2"
  114 + inkscape:zoom="3.5852524"
  115 + inkscape:cx="21.387308"
  116 + inkscape:cy="33.791467"
  117 + inkscape:current-layer="layer1"
  118 + showgrid="true"
  119 + inkscape:document-units="px"
  120 + inkscape:grid-bbox="true"
  121 + inkscape:window-width="1364"
  122 + inkscape:window-height="714"
  123 + inkscape:window-x="0"
  124 + inkscape:window-y="27"
  125 + objecttolerance="10"
  126 + gridtolerance="10"
  127 + guidetolerance="10"
  128 + inkscape:window-maximized="0">
  129 + <inkscape:grid
  130 + type="xygrid"
  131 + id="grid2382"
  132 + visible="true"
  133 + enabled="true"
  134 + originx="0.5px"
  135 + originy="0.5px"
  136 + empcolor="#0000ff"
  137 + empopacity="0.1254902"
  138 + dotted="true" />
  139 + </sodipodi:namedview>
  140 + <metadata
  141 + id="metadata2388">
  142 + <rdf:RDF>
  143 + <cc:Work
  144 + rdf:about="">
  145 + <dc:format>image/svg+xml</dc:format>
  146 + <dc:type
  147 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
  148 + <dc:title></dc:title>
  149 + </cc:Work>
  150 + </rdf:RDF>
  151 + </metadata>
  152 + <g
  153 + id="layer1"
  154 + inkscape:label="Layer 1"
  155 + inkscape:groupmode="layer">
  156 + <rect
  157 + rx="2"
  158 + ry="2"
  159 + y="2.5"
  160 + x="50.5"
  161 + height="59"
  162 + width="12"
  163 + id="rect3186"
  164 + style="opacity:0.4;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter3241);enable-background:accumulate"
  165 + transform="matrix(0,1,-1,0,64.512846,0.32391508)" />
  166 + <rect
  167 + style="fill:url(#linearGradient3255);fill-opacity:1;fill-rule:nonzero;stroke:#204a87;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
  168 + id="rect3154"
  169 + width="12"
  170 + height="59"
  171 + x="49.823914"
  172 + y="-61.012848"
  173 + ry="2"
  174 + transform="matrix(0,1,-1,0,0,0)" />
  175 + <rect
  176 + style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
  177 + id="rect3164"
  178 + width="10"
  179 + height="57"
  180 + x="50.823914"
  181 + y="-60.012848"
  182 + ry="1"
  183 + transform="matrix(0,1,-1,0,0,0)" />
  184 + <rect
  185 + rx="2"
  186 + ry="2"
  187 + style="opacity:0.4;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter3241);enable-background:accumulate"
  188 + id="rect3184"
  189 + width="11"
  190 + height="59"
  191 + x="2.5"
  192 + y="2.5"
  193 + transform="matrix(1.0025263,0,0,0.76423683,0.2157619,0.85033188)" />
  194 + <rect
  195 + rx="2"
  196 + ry="2"
  197 + style="opacity:0.4;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter3241);enable-background:accumulate"
  198 + id="rect3188"
  199 + width="31"
  200 + height="59"
  201 + x="16.5"
  202 + y="2.5"
  203 + transform="matrix(1.4160224,0,0,0.76166071,-5.6247232,0.93276758)" />
  204 + <rect
  205 + y="1.9966872"
  206 + x="1.7195514"
  207 + height="45.089973"
  208 + width="11.02779"
  209 + id="rect2395"
  210 + style="fill:url(#linearGradient3251);fill-opacity:1;fill-rule:nonzero;stroke:#204a87;stroke-width:0.87531;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
  211 + ry="1.5284736" />
  212 + <rect
  213 + y="2.0752587"
  214 + x="16.323626"
  215 + height="44.937984"
  216 + width="43.896694"
  217 + id="rect3156"
  218 + style="fill:url(#linearGradient3253);fill-opacity:1;fill-rule:nonzero;stroke:#204a87;stroke-width:1.03852236;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
  219 + ry="1.5233214" />
  220 + <rect
  221 + ry="0.76423681"
  222 + style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:0.87531;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
  223 + id="rect3158"
  224 + width="9.0227375"
  225 + height="43.561501"
  226 + x="2.7220778"
  227 + y="2.7609239" />
  228 + <rect
  229 + y="2.8369193"
  230 + x="17.739647"
  231 + height="43.414661"
  232 + width="41.064651"
  233 + id="rect3162"
  234 + style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1.03852236;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
  235 + ry="0.7616607"
  236 + inkscape:export-xdpi="90"
  237 + inkscape:export-ydpi="90" />
  238 + </g>
  239 +</svg>
public/images/colorbox/controls.png

1.22 KB | W: | H:

2.83 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
public/javascripts/application.js
@@ -1005,31 +1005,6 @@ log.error = function() { @@ -1005,31 +1005,6 @@ log.error = function() {
1005 window.log.apply(window, jQuery.merge(['error'], arguments)); 1005 window.log.apply(window, jQuery.merge(['error'], arguments));
1006 } 1006 }
1007 1007
1008 -jQuery(function($) {  
1009 - $('.colorbox').live('click', function() {  
1010 - $.colorbox({  
1011 - href: $(this).attr('href'),  
1012 - maxWidth: $(window).width()-50,  
1013 - height: $(window).height()-50,  
1014 - open: true,  
1015 - fixed: true,  
1016 - close: 'Cancel',  
1017 - onComplete: function(bt) {  
1018 - var opt = {}, maxH = $(window).height()-50;  
1019 - if ($('#cboxLoadedContent *:first').height() > maxH) opt.height = maxH;  
1020 - $.colorbox.resize(opt);  
1021 - }  
1022 - });  
1023 - return false;  
1024 - });  
1025 -  
1026 - $('.colorbox-close').live('click', function() {  
1027 - $.colorbox.close();  
1028 - return false;  
1029 - });  
1030 -  
1031 -});  
1032 -  
1033 function showHideTermsOfUse() { 1008 function showHideTermsOfUse() {
1034 if( jQuery("#article_has_terms_of_use").attr("checked") ) 1009 if( jQuery("#article_has_terms_of_use").attr("checked") )
1035 jQuery("#text_area_terms_of_use").show(); 1010 jQuery("#text_area_terms_of_use").show();
public/javascripts/article.js
@@ -88,7 +88,7 @@ jQuery(function($) { @@ -88,7 +88,7 @@ jQuery(function($) {
88 var $item = $(this).closest('.item'); 88 var $item = $(this).closest('.item');
89 var html_selector = $item.attr('data-item'); 89 var html_selector = $item.attr('data-item');
90 insert_item_in_text($item.find(html_selector)); 90 insert_item_in_text($item.find(html_selector));
91 - $.colorbox.close(); 91 + noosfero.modal.close();
92 return false; 92 return false;
93 }); 93 });
94 $('a.zoom').live('click', function() { 94 $('a.zoom').live('click', function() {
@@ -96,14 +96,13 @@ jQuery(function($) { @@ -96,14 +96,13 @@ jQuery(function($) {
96 var html_selector = $item.attr('data-item'); 96 var html_selector = $item.attr('data-item');
97 var name = $item.attr('title'); 97 var name = $item.attr('title');
98 var img = $item.find(html_selector).find('img').attr('src'); 98 var img = $item.find(html_selector).find('img').attr('src');
99 - $.colorbox({  
100 - html: zoom_dialog_html(name, img),  
101 - scrolling: false 99 + noosfero.modal.html(zoom_dialog_html(img), {
  100 + scrolling: false,
102 }); 101 });
103 return false; 102 return false;
104 }); 103 });
105 $('a.close').live('click', function() { 104 $('a.close').live('click', function() {
106 - $.colorbox.close(); 105 + noosfero.modal.close();
107 return false; 106 return false;
108 }) 107 })
109 108
public/javascripts/colorbox.js
@@ -1,814 +0,0 @@ @@ -1,814 +0,0 @@
1 -// ColorBox v1.3.16 - a full featured, light-weight, customizable lightbox based on jQuery 1.3+  
2 -// Copyright (c) 2011 Jack Moore - jack@colorpowered.com  
3 -// Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php  
4 -(function ($, document, window) {  
5 - var  
6 - // ColorBox Default Settings.  
7 - // See http://colorpowered.com/colorbox for details.  
8 - defaults = {  
9 - transition: "elastic",  
10 - speed: 300,  
11 - width: false,  
12 - initialWidth: "600",  
13 - innerWidth: false,  
14 - maxWidth: false,  
15 - height: false,  
16 - initialHeight: "450",  
17 - innerHeight: false,  
18 - maxHeight: false,  
19 - scalePhotos: true,  
20 - scrolling: true,  
21 - inline: false,  
22 - html: false,  
23 - iframe: false,  
24 - fastIframe: true,  
25 - photo: false,  
26 - href: false,  
27 - title: false,  
28 - rel: false,  
29 - opacity: 0.9,  
30 - preloading: true,  
31 - current: "image {current} of {total}",  
32 - previous: "previous",  
33 - next: "next",  
34 - close: "close",  
35 - open: false,  
36 - returnFocus: true,  
37 - loop: true,  
38 - slideshow: false,  
39 - slideshowAuto: true,  
40 - slideshowSpeed: 2500,  
41 - slideshowStart: "start slideshow",  
42 - slideshowStop: "stop slideshow",  
43 - onOpen: false,  
44 - onLoad: false,  
45 - onComplete: false,  
46 - onCleanup: false,  
47 - onClosed: false,  
48 - overlayClose: true,  
49 - escKey: true,  
50 - arrowKey: true  
51 - },  
52 -  
53 - // Abstracting the HTML and event identifiers for easy rebranding  
54 - colorbox = 'colorbox',  
55 - prefix = 'cbox',  
56 -  
57 - // Events  
58 - event_open = prefix + '_open',  
59 - event_load = prefix + '_load',  
60 - event_complete = prefix + '_complete',  
61 - event_cleanup = prefix + '_cleanup',  
62 - event_closed = prefix + '_closed',  
63 - event_purge = prefix + '_purge',  
64 -  
65 - // Special Handling for IE  
66 - isIE = $.browser.msie && !$.support.opacity, // feature detection alone gave a false positive on at least one phone browser and on some development versions of Chrome.  
67 - isIE6 = isIE && $.browser.version < 7,  
68 - event_ie6 = prefix + '_IE6',  
69 -  
70 - // Cached jQuery Object Variables  
71 - $overlay,  
72 - $box,  
73 - $wrap,  
74 - $content,  
75 - $topBorder,  
76 - $leftBorder,  
77 - $rightBorder,  
78 - $bottomBorder,  
79 - $related,  
80 - $window,  
81 - $loaded,  
82 - $loadingBay,  
83 - $loadingOverlay,  
84 - $title,  
85 - $current,  
86 - $slideshow,  
87 - $next,  
88 - $prev,  
89 - $close,  
90 - $groupControls,  
91 -  
92 - // Variables for cached values or use across multiple functions  
93 - settings = {},  
94 - interfaceHeight,  
95 - interfaceWidth,  
96 - loadedHeight,  
97 - loadedWidth,  
98 - element,  
99 - index,  
100 - photo,  
101 - open,  
102 - active,  
103 - closing = false,  
104 -  
105 - publicMethod,  
106 - boxElement = prefix + 'Element';  
107 -  
108 - // ****************  
109 - // HELPER FUNCTIONS  
110 - // ****************  
111 -  
112 - // jQuery object generator to reduce code size  
113 - function $div(id, cssText) {  
114 - var div = document.createElement('div');  
115 - if (id) {  
116 - div.id = prefix + id;  
117 - }  
118 - div.style.cssText = cssText || false;  
119 - return $(div);  
120 - }  
121 -  
122 - // Convert % values to pixels  
123 - function setSize(size, dimension) {  
124 - dimension = dimension === 'x' ? $window.width() : $window.height();  
125 - return (typeof size === 'string') ? Math.round((/%/.test(size) ? (dimension / 100) * parseInt(size, 10) : parseInt(size, 10))) : size;  
126 - }  
127 -  
128 - // Checks an href to see if it is a photo.  
129 - // There is a force photo option (photo: true) for hrefs that cannot be matched by this regex.  
130 - function isImage(url) {  
131 - return settings.photo || /\.(gif|png|jpg|jpeg|bmp)(?:\?([^#]*))?(?:#(\.*))?$/i.test(url);  
132 - }  
133 -  
134 - // Assigns function results to their respective settings. This allows functions to be used as values.  
135 - function process(settings) {  
136 - for (var i in settings) {  
137 - if ($.isFunction(settings[i]) && i.substring(0, 2) !== 'on') { // checks to make sure the function isn't one of the callbacks, they will be handled at the appropriate time.  
138 - settings[i] = settings[i].call(element);  
139 - }  
140 - }  
141 - settings.rel = settings.rel || element.rel || 'nofollow';  
142 - settings.href = $.trim(settings.href || $(element).attr('href'));  
143 - settings.title = settings.title || element.title;  
144 - }  
145 -  
146 - function trigger(event, callback) {  
147 - if (callback) {  
148 - callback.call(element);  
149 - }  
150 - $.event.trigger(event);  
151 - }  
152 -  
153 - // Slideshow functionality  
154 - function slideshow() {  
155 - var  
156 - timeOut,  
157 - className = prefix + "Slideshow_",  
158 - click = "click." + prefix,  
159 - start,  
160 - stop,  
161 - clear;  
162 -  
163 - if (settings.slideshow && $related[1]) {  
164 - start = function () {  
165 - $slideshow  
166 - .text(settings.slideshowStop)  
167 - .unbind(click)  
168 - .bind(event_complete, function () {  
169 - if (index < $related.length - 1 || settings.loop) {  
170 - timeOut = setTimeout(publicMethod.next, settings.slideshowSpeed);  
171 - }  
172 - })  
173 - .bind(event_load, function () {  
174 - clearTimeout(timeOut);  
175 - })  
176 - .one(click + ' ' + event_cleanup, stop);  
177 - $box.removeClass(className + "off").addClass(className + "on");  
178 - timeOut = setTimeout(publicMethod.next, settings.slideshowSpeed);  
179 - };  
180 -  
181 - stop = function () {  
182 - clearTimeout(timeOut);  
183 - $slideshow  
184 - .text(settings.slideshowStart)  
185 - .unbind([event_complete, event_load, event_cleanup, click].join(' '))  
186 - .one(click, start);  
187 - $box.removeClass(className + "on").addClass(className + "off");  
188 - };  
189 -  
190 - if (settings.slideshowAuto) {  
191 - start();  
192 - } else {  
193 - stop();  
194 - }  
195 - }  
196 - }  
197 -  
198 - function launch(elem) {  
199 - if (!closing) {  
200 -  
201 - element = elem;  
202 -  
203 - process($.extend(settings, $.data(element, colorbox)));  
204 -  
205 - $related = $(element);  
206 -  
207 - index = 0;  
208 -  
209 - if (settings.rel !== 'nofollow') {  
210 - $related = $('.' + boxElement).filter(function () {  
211 - var relRelated = $.data(this, colorbox).rel || this.rel;  
212 - return (relRelated === settings.rel);  
213 - });  
214 - index = $related.index(element);  
215 -  
216 - // Check direct calls to ColorBox.  
217 - if (index === -1) {  
218 - $related = $related.add(element);  
219 - index = $related.length - 1;  
220 - }  
221 - }  
222 -  
223 - if (!open) {  
224 - open = active = true; // Prevents the page-change action from queuing up if the visitor holds down the left or right keys.  
225 -  
226 - $box.show();  
227 -  
228 - if (settings.returnFocus) {  
229 - try {  
230 - element.blur();  
231 - $(element).one(event_closed, function () {  
232 - try {  
233 - this.focus();  
234 - } catch (e) {  
235 - // do nothing  
236 - }  
237 - });  
238 - } catch (e) {  
239 - // do nothing  
240 - }  
241 - }  
242 -  
243 - // +settings.opacity avoids a problem in IE when using non-zero-prefixed-string-values, like '.5'  
244 - $overlay.css({"opacity": +settings.opacity, "cursor": settings.overlayClose ? "pointer" : "auto"}).show();  
245 -  
246 - // Opens inital empty ColorBox prior to content being loaded.  
247 - settings.w = setSize(settings.initialWidth, 'x');  
248 - settings.h = setSize(settings.initialHeight, 'y');  
249 - publicMethod.position(0);  
250 -  
251 - if (isIE6) {  
252 - $window.bind('resize.' + event_ie6 + ' scroll.' + event_ie6, function () {  
253 - $overlay.css({width: $window.width(), height: $window.height(), top: $window.scrollTop(), left: $window.scrollLeft()});  
254 - }).trigger('resize.' + event_ie6);  
255 - }  
256 -  
257 - trigger(event_open, settings.onOpen);  
258 -  
259 - $groupControls.add($title).hide();  
260 -  
261 - $close.html(settings.close).show();  
262 - }  
263 -  
264 - publicMethod.load(true);  
265 - }  
266 - }  
267 -  
268 - // ****************  
269 - // PUBLIC FUNCTIONS  
270 - // Usage format: $.fn.colorbox.close();  
271 - // Usage from within an iframe: parent.$.fn.colorbox.close();  
272 - // ****************  
273 -  
274 - publicMethod = $.fn[colorbox] = $[colorbox] = function (options, callback) {  
275 - var $this = this, autoOpen;  
276 -  
277 - if (!$this[0] && $this.selector) { // if a selector was given and it didn't match any elements, go ahead and exit.  
278 - return $this;  
279 - }  
280 -  
281 - options = options || {};  
282 -  
283 - if (callback) {  
284 - options.onComplete = callback;  
285 - }  
286 -  
287 - if (!$this[0] || $this.selector === undefined) { // detects $.colorbox() and $.fn.colorbox()  
288 - $this = $('<a/>');  
289 - options.open = true; // assume an immediate open  
290 - }  
291 -  
292 - $this.each(function () {  
293 - $.data(this, colorbox, $.extend({}, $.data(this, colorbox) || defaults, options));  
294 - $(this).addClass(boxElement);  
295 - });  
296 -  
297 - autoOpen = options.open;  
298 -  
299 - if ($.isFunction(autoOpen)) {  
300 - autoOpen = autoOpen.call($this);  
301 - }  
302 -  
303 - if (autoOpen) {  
304 - launch($this[0]);  
305 - }  
306 -  
307 - return $this;  
308 - };  
309 -  
310 - // Initialize ColorBox: store common calculations, preload the interface graphics, append the html.  
311 - // This preps colorbox for a speedy open when clicked, and lightens the burdon on the browser by only  
312 - // having to run once, instead of each time colorbox is opened.  
313 - publicMethod.init = function () {  
314 - // Create & Append jQuery Objects  
315 - $window = $(window);  
316 - $box = $div().attr({id: colorbox, 'class': isIE ? prefix + (isIE6 ? 'IE6' : 'IE') : ''});  
317 - $overlay = $div("Overlay", isIE6 ? 'position:absolute' : '').hide();  
318 -  
319 - $wrap = $div("Wrapper");  
320 - $content = $div("Content").append(  
321 - $loaded = $div("LoadedContent", 'width:0; height:0; overflow:hidden'),  
322 - $loadingOverlay = $div("LoadingOverlay").add($div("LoadingGraphic")),  
323 - $title = $div("Title"),  
324 - $current = $div("Current"),  
325 - $next = $div("Next"),  
326 - $prev = $div("Previous"),  
327 - $slideshow = $div("Slideshow").bind(event_open, slideshow),  
328 - $close = $div("Close")  
329 - );  
330 - $wrap.append( // The 3x3 Grid that makes up ColorBox  
331 - $div().append(  
332 - $div("TopLeft"),  
333 - $topBorder = $div("TopCenter"),  
334 - $div("TopRight")  
335 - ),  
336 - $div(false, 'clear:left').append(  
337 - $leftBorder = $div("MiddleLeft"),  
338 - $content,  
339 - $rightBorder = $div("MiddleRight")  
340 - ),  
341 - $div(false, 'clear:left').append(  
342 - $div("BottomLeft"),  
343 - $bottomBorder = $div("BottomCenter"),  
344 - $div("BottomRight")  
345 - )  
346 - ).children().children().css({'float': 'left'});  
347 -  
348 - $loadingBay = $div(false, 'position:absolute; width:9999px; visibility:hidden; display:none');  
349 -  
350 - $('body').prepend($overlay, $box.append($wrap, $loadingBay));  
351 -  
352 - $content.children()  
353 - .hover(function () {  
354 - $(this).addClass('hover');  
355 - }, function () {  
356 - $(this).removeClass('hover');  
357 - }).addClass('hover');  
358 -  
359 - // Cache values needed for size calculations  
360 - interfaceHeight = $topBorder.height() + $bottomBorder.height() + $content.outerHeight(true) - $content.height();//Subtraction needed for IE6  
361 - interfaceWidth = $leftBorder.width() + $rightBorder.width() + $content.outerWidth(true) - $content.width();  
362 - loadedHeight = $loaded.outerHeight(true);  
363 - loadedWidth = $loaded.outerWidth(true);  
364 -  
365 - // Setting padding to remove the need to do size conversions during the animation step.  
366 - $box.css({"padding-bottom": interfaceHeight, "padding-right": interfaceWidth}).hide();  
367 -  
368 - // Setup button events.  
369 - $next.click(function () {  
370 - publicMethod.next();  
371 - });  
372 - $prev.click(function () {  
373 - publicMethod.prev();  
374 - });  
375 - $close.click(function () {  
376 - publicMethod.close();  
377 - });  
378 -  
379 - $groupControls = $next.add($prev).add($current).add($slideshow);  
380 -  
381 - // Adding the 'hover' class allowed the browser to load the hover-state  
382 - // background graphics. The class can now can be removed.  
383 - $content.children().removeClass('hover');  
384 -  
385 - $('.' + boxElement).live('click', function (e) {  
386 - // checks to see if it was a non-left mouse-click and for clicks modified with ctrl, shift, or alt.  
387 - if (!((e.button !== 0 && typeof e.button !== 'undefined') || e.ctrlKey || e.shiftKey || e.altKey)) {  
388 - e.preventDefault();  
389 - launch(this);  
390 - }  
391 - });  
392 -  
393 - $overlay.click(function () {  
394 - if (settings.overlayClose) {  
395 - publicMethod.close();  
396 - }  
397 - });  
398 -  
399 - // Set Navigation Key Bindings  
400 - $(document).bind('keydown.' + prefix, function (e) {  
401 - var key = e.keyCode;  
402 - if (open && settings.escKey && key === 27) {  
403 - e.preventDefault();  
404 - publicMethod.close();  
405 - }  
406 - if (open && settings.arrowKey && $related[1]) {  
407 - if (key === 37) {  
408 - e.preventDefault();  
409 - $prev.click();  
410 - } else if (key === 39) {  
411 - e.preventDefault();  
412 - $next.click();  
413 - }  
414 - }  
415 - });  
416 - };  
417 -  
418 - publicMethod.remove = function () {  
419 - $box.add($overlay).remove();  
420 - $('.' + boxElement).die('click').removeData(colorbox).removeClass(boxElement);  
421 - };  
422 -  
423 - publicMethod.position = function (speed, loadedCallback) {  
424 - var  
425 - animate_speed,  
426 - // keeps the top and left positions within the browser's viewport.  
427 - posTop = Math.max(document.documentElement.clientHeight - settings.h - loadedHeight - interfaceHeight, 0) / 2 + $window.scrollTop(),  
428 - posLeft = Math.max($window.width() - settings.w - loadedWidth - interfaceWidth, 0) / 2 + $window.scrollLeft();  
429 -  
430 - // setting the speed to 0 to reduce the delay between same-sized content.  
431 - animate_speed = ($box.width() === settings.w + loadedWidth && $box.height() === settings.h + loadedHeight) ? 0 : speed;  
432 -  
433 - // this gives the wrapper plenty of breathing room so it's floated contents can move around smoothly,  
434 - // but it has to be shrank down around the size of div#colorbox when it's done. If not,  
435 - // it can invoke an obscure IE bug when using iframes.  
436 - $wrap[0].style.width = $wrap[0].style.height = "9999px";  
437 -  
438 - function modalDimensions(that) {  
439 - // loading overlay height has to be explicitly set for IE6.  
440 - $topBorder[0].style.width = $bottomBorder[0].style.width = $content[0].style.width = that.style.width;  
441 - $loadingOverlay[0].style.height = $loadingOverlay[1].style.height = $content[0].style.height = $leftBorder[0].style.height = $rightBorder[0].style.height = that.style.height;  
442 - }  
443 -  
444 - $box.dequeue().animate({width: settings.w + loadedWidth, height: settings.h + loadedHeight, top: posTop, left: posLeft}, {  
445 - duration: animate_speed,  
446 - complete: function () {  
447 - modalDimensions(this);  
448 -  
449 - active = false;  
450 -  
451 - // shrink the wrapper down to exactly the size of colorbox to avoid a bug in IE's iframe implementation.  
452 - $wrap[0].style.width = (settings.w + loadedWidth + interfaceWidth) + "px";  
453 - $wrap[0].style.height = (settings.h + loadedHeight + interfaceHeight) + "px";  
454 -  
455 - if (loadedCallback) {  
456 - loadedCallback();  
457 - }  
458 - },  
459 - step: function () {  
460 - modalDimensions(this);  
461 - }  
462 - });  
463 - };  
464 -  
465 - publicMethod.resize = function (options) {  
466 - if (open) {  
467 - options = options || {};  
468 -  
469 - if (options.width) {  
470 - settings.w = setSize(options.width, 'x') - loadedWidth - interfaceWidth;  
471 - }  
472 - if (options.innerWidth) {  
473 - settings.w = setSize(options.innerWidth, 'x');  
474 - }  
475 - $loaded.css({width: settings.w});  
476 -  
477 - if (options.height) {  
478 - settings.h = setSize(options.height, 'y') - loadedHeight - interfaceHeight;  
479 - }  
480 - if (options.innerHeight) {  
481 - settings.h = setSize(options.innerHeight, 'y');  
482 - }  
483 - if (!options.innerHeight && !options.height) {  
484 - var $child = $loaded.wrapInner("<div style='overflow:auto'></div>").children(); // temporary wrapper to get an accurate estimate of just how high the total content should be.  
485 - settings.h = $child.height();  
486 - $child.replaceWith($child.children()); // ditch the temporary wrapper div used in height calculation  
487 - }  
488 - $loaded.css({height: settings.h});  
489 -  
490 - publicMethod.position(settings.transition === "none" ? 0 : settings.speed);  
491 - }  
492 - };  
493 -  
494 - publicMethod.prep = function (object) {  
495 - if (!open) {  
496 - return;  
497 - }  
498 -  
499 - var speed = settings.transition === "none" ? 0 : settings.speed;  
500 -  
501 - $window.unbind('resize.' + prefix);  
502 - $loaded.remove();  
503 - $loaded = $div('LoadedContent').html(object);  
504 -  
505 - function getWidth() {  
506 - settings.w = settings.w || $loaded.width();  
507 - settings.w = settings.mw && settings.mw < settings.w ? settings.mw : settings.w;  
508 - return settings.w;  
509 - }  
510 - function getHeight() {  
511 - settings.h = settings.h || $loaded.height();  
512 - settings.h = settings.mh && settings.mh < settings.h ? settings.mh : settings.h;  
513 - return settings.h;  
514 - }  
515 -  
516 - $loaded.hide()  
517 - .appendTo($loadingBay.show())// content has to be appended to the DOM for accurate size calculations.  
518 - .css({width: getWidth(), overflow: settings.scrolling ? 'auto' : 'hidden'})  
519 - .css({height: getHeight()})// sets the height independently from the width in case the new width influences the value of height.  
520 - .prependTo($content);  
521 -  
522 - $loadingBay.hide();  
523 -  
524 - // floating the IMG removes the bottom line-height and fixed a problem where IE miscalculates the width of the parent element as 100% of the document width.  
525 - //$(photo).css({'float': 'none', marginLeft: 'auto', marginRight: 'auto'});  
526 -  
527 - $(photo).css({'float': 'none'});  
528 -  
529 - // Hides SELECT elements in IE6 because they would otherwise sit on top of the overlay.  
530 - if (isIE6) {  
531 - $('select').not($box.find('select')).filter(function () {  
532 - return this.style.visibility !== 'hidden';  
533 - }).css({'visibility': 'hidden'}).one(event_cleanup, function () {  
534 - this.style.visibility = 'inherit';  
535 - });  
536 - }  
537 -  
538 - function setPosition(s) {  
539 - publicMethod.position(s, function () {  
540 - var prev, prevSrc, next, nextSrc, total = $related.length, iframe, complete;  
541 -  
542 - if (!open) {  
543 - return;  
544 - }  
545 -  
546 - complete = function () {  
547 - $loadingOverlay.hide();  
548 - trigger(event_complete, settings.onComplete);  
549 - };  
550 -  
551 - if (isIE) {  
552 - //This fadeIn helps the bicubic resampling to kick-in.  
553 - if (photo) {  
554 - $loaded.fadeIn(100);  
555 - }  
556 - }  
557 -  
558 - $title.html(settings.title).add($loaded).show();  
559 -  
560 - if (total > 1) { // handle grouping  
561 - if (typeof settings.current === "string") {  
562 - $current.html(settings.current.replace(/\{current\}/, index + 1).replace(/\{total\}/, total)).show();  
563 - }  
564 -  
565 - $next[(settings.loop || index < total - 1) ? "show" : "hide"]().html(settings.next);  
566 - $prev[(settings.loop || index) ? "show" : "hide"]().html(settings.previous);  
567 -  
568 - prev = index ? $related[index - 1] : $related[total - 1];  
569 - next = index < total - 1 ? $related[index + 1] : $related[0];  
570 -  
571 - if (settings.slideshow) {  
572 - $slideshow.show();  
573 - }  
574 -  
575 - // Preloads images within a rel group  
576 - if (settings.preloading) {  
577 - nextSrc = $.data(next, colorbox).href || next.href;  
578 - prevSrc = $.data(prev, colorbox).href || prev.href;  
579 -  
580 - nextSrc = $.isFunction(nextSrc) ? nextSrc.call(next) : nextSrc;  
581 - prevSrc = $.isFunction(prevSrc) ? prevSrc.call(prev) : prevSrc;  
582 -  
583 - if (isImage(nextSrc)) {  
584 - $('<img/>')[0].src = nextSrc;  
585 - }  
586 -  
587 - if (isImage(prevSrc)) {  
588 - $('<img/>')[0].src = prevSrc;  
589 - }  
590 - }  
591 - } else {  
592 - $groupControls.hide();  
593 - }  
594 -  
595 - if (settings.iframe) {  
596 - iframe = $('<iframe/>').addClass(prefix + 'Iframe')[0];  
597 -  
598 - if (settings.fastIframe) {  
599 - complete();  
600 - } else {  
601 - $(iframe).load(complete);  
602 - }  
603 - iframe.name = prefix + (+new Date());  
604 - iframe.src = settings.href;  
605 -  
606 - if (!settings.scrolling) {  
607 - iframe.scrolling = "no";  
608 - }  
609 -  
610 - if (isIE) {  
611 - iframe.frameBorder=0;  
612 - iframe.allowTransparency = "true";  
613 - }  
614 -  
615 - $(iframe).appendTo($loaded).one(event_purge, function () {  
616 - iframe.src = "//about:blank";  
617 - });  
618 - } else {  
619 - complete();  
620 - }  
621 -  
622 - if (settings.transition === 'fade') {  
623 - $box.fadeTo(speed, 1, function () {  
624 - $box[0].style.filter = "";  
625 - });  
626 - } else {  
627 - $box[0].style.filter = "";  
628 - }  
629 -  
630 - $window.bind('resize.' + prefix, function () {  
631 - publicMethod.position(0);  
632 - });  
633 - });  
634 - }  
635 -  
636 - if (settings.transition === 'fade') {  
637 - $box.fadeTo(speed, 0, function () {  
638 - setPosition(0);  
639 - });  
640 - } else {  
641 - setPosition(speed);  
642 - }  
643 - };  
644 -  
645 - publicMethod.load = function (launched) {  
646 - var href, setResize, prep = publicMethod.prep;  
647 -  
648 - active = true;  
649 -  
650 - photo = false;  
651 -  
652 - element = $related[index];  
653 -  
654 - if (!launched) {  
655 - process($.extend(settings, $.data(element, colorbox)));  
656 - }  
657 -  
658 - trigger(event_purge);  
659 -  
660 - trigger(event_load, settings.onLoad);  
661 -  
662 - settings.h = settings.height ?  
663 - setSize(settings.height, 'y') - loadedHeight - interfaceHeight :  
664 - settings.innerHeight && setSize(settings.innerHeight, 'y');  
665 -  
666 - settings.w = settings.width ?  
667 - setSize(settings.width, 'x') - loadedWidth - interfaceWidth :  
668 - settings.innerWidth && setSize(settings.innerWidth, 'x');  
669 -  
670 - // Sets the minimum dimensions for use in image scaling  
671 - settings.mw = settings.w;  
672 - settings.mh = settings.h;  
673 -  
674 - // Re-evaluate the minimum width and height based on maxWidth and maxHeight values.  
675 - // If the width or height exceed the maxWidth or maxHeight, use the maximum values instead.  
676 - if (settings.maxWidth) {  
677 - settings.mw = setSize(settings.maxWidth, 'x') - loadedWidth - interfaceWidth;  
678 - settings.mw = settings.w && settings.w < settings.mw ? settings.w : settings.mw;  
679 - }  
680 - if (settings.maxHeight) {  
681 - settings.mh = setSize(settings.maxHeight, 'y') - loadedHeight - interfaceHeight;  
682 - settings.mh = settings.h && settings.h < settings.mh ? settings.h : settings.mh;  
683 - }  
684 -  
685 - href = settings.href;  
686 -  
687 - $loadingOverlay.show();  
688 -  
689 - if (settings.inline) {  
690 - // Inserts an empty placeholder where inline content is being pulled from.  
691 - // An event is bound to put inline content back when ColorBox closes or loads new content.  
692 - $div().hide().insertBefore($(href)[0]).one(event_purge, function () {  
693 - $(this).replaceWith($loaded.children());  
694 - });  
695 - prep($(href));  
696 - } else if (settings.iframe) {  
697 - // IFrame element won't be added to the DOM until it is ready to be displayed,  
698 - // to avoid problems with DOM-ready JS that might be trying to run in that iframe.  
699 - prep(" ");  
700 - } else if (settings.html) {  
701 - prep(settings.html);  
702 - } else if (isImage(href)) {  
703 - $(photo = new Image())  
704 - .addClass(prefix + 'Photo')  
705 - .error(function () {  
706 - settings.title = false;  
707 - prep($div('Error').text('This image could not be loaded'));  
708 - })  
709 - .load(function () {  
710 - var percent;  
711 - photo.onload = null; //stops animated gifs from firing the onload repeatedly.  
712 -  
713 - if (settings.scalePhotos) {  
714 - setResize = function () {  
715 - photo.height -= photo.height * percent;  
716 - photo.width -= photo.width * percent;  
717 - };  
718 - if (settings.mw && photo.width > settings.mw) {  
719 - percent = (photo.width - settings.mw) / photo.width;  
720 - setResize();  
721 - }  
722 - if (settings.mh && photo.height > settings.mh) {  
723 - percent = (photo.height - settings.mh) / photo.height;  
724 - setResize();  
725 - }  
726 - }  
727 -  
728 - if (settings.h) {  
729 - photo.style.marginTop = Math.max(settings.h - photo.height, 0) / 2 + 'px';  
730 - }  
731 -  
732 - if ($related[1] && (index < $related.length - 1 || settings.loop)) {  
733 - photo.style.cursor = 'pointer';  
734 - photo.onclick = function () {  
735 - publicMethod.next();  
736 - };  
737 - }  
738 -  
739 - if (isIE) {  
740 - photo.style.msInterpolationMode = 'bicubic';  
741 - }  
742 -  
743 - setTimeout(function () { // A pause because Chrome will sometimes report a 0 by 0 size otherwise.  
744 - prep(photo);  
745 - }, 1);  
746 - });  
747 -  
748 - setTimeout(function () { // A pause because Opera 10.6+ will sometimes not run the onload function otherwise.  
749 - photo.src = href;  
750 - }, 1);  
751 - } else if (href) {  
752 - $loadingBay.load(href, function (data, status, xhr) {  
753 - prep(status === 'error' ? $div('Error').text('Request unsuccessful: ' + xhr.statusText) : $(this).contents());  
754 - });  
755 - }  
756 - };  
757 -  
758 - // Navigates to the next page/image in a set.  
759 - publicMethod.next = function () {  
760 - if (!active && $related[1] && (index < $related.length - 1 || settings.loop)) {  
761 - index = index < $related.length - 1 ? index + 1 : 0;  
762 - publicMethod.load();  
763 - }  
764 - };  
765 -  
766 - publicMethod.prev = function () {  
767 - if (!active && $related[1] && (index || settings.loop)) {  
768 - index = index ? index - 1 : $related.length - 1;  
769 - publicMethod.load();  
770 - }  
771 - };  
772 -  
773 - // Note: to use this within an iframe use the following format: parent.$.fn.colorbox.close();  
774 - publicMethod.close = function () {  
775 - if (open && !closing) {  
776 -  
777 - closing = true;  
778 -  
779 - open = false;  
780 -  
781 - trigger(event_cleanup, settings.onCleanup);  
782 -  
783 - $window.unbind('.' + prefix + ' .' + event_ie6);  
784 -  
785 - $overlay.fadeTo(200, 0);  
786 -  
787 - $box.stop().fadeTo(300, 0, function () {  
788 -  
789 - $box.add($overlay).css({'opacity': 1, cursor: 'auto'}).hide();  
790 -  
791 - trigger(event_purge);  
792 -  
793 - $loaded.remove();  
794 -  
795 - setTimeout(function () {  
796 - closing = false;  
797 - trigger(event_closed, settings.onClosed);  
798 - }, 1);  
799 - });  
800 - }  
801 - };  
802 -  
803 - // A method for fetching the current element ColorBox is referencing.  
804 - // returns a jQuery object.  
805 - publicMethod.element = function () {  
806 - return $(element);  
807 - };  
808 -  
809 - publicMethod.settings = defaults;  
810 -  
811 - // Initializes ColorBox when the DOM has loaded  
812 - $(publicMethod.init);  
813 -  
814 -}(jQuery, document, this));  
815 \ No newline at end of file 0 \ No newline at end of file
public/javascripts/comment_form.js
@@ -53,7 +53,7 @@ function save_comment(button) { @@ -53,7 +53,7 @@ function save_comment(button) {
53 //Comment of reply 53 //Comment of reply
54 $('#'+ data.render_target).replaceWith(data.html); 54 $('#'+ data.render_target).replaceWith(data.html);
55 $('#' + data.render_target).effect("highlight", {}, 3000); 55 $('#' + data.render_target).effect("highlight", {}, 3000);
56 - $.colorbox.close(); 56 + noosfero.modal.close();
57 increment_comment_count(comment_div); 57 increment_comment_count(comment_div);
58 } else { 58 } else {
59 //New comment of article 59 //New comment of article
@@ -64,7 +64,7 @@ function save_comment(button) { @@ -64,7 +64,7 @@ function save_comment(button) {
64 }); 64 });
65 65
66 page_comment_form.find('.errorExplanation').remove(); 66 page_comment_form.find('.errorExplanation').remove();
67 - $.colorbox.close(); 67 + noosfero.modal.close();
68 increment_comment_count(comment_div); 68 increment_comment_count(comment_div);
69 } 69 }
70 70
public/javascripts/jquery.colorbox-min.js 0 → 100644
@@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
  1 +/*!
  2 + Colorbox v1.4.36 - 2014-02-01
  3 + jQuery lightbox and modal window plugin
  4 + (c) 2014 Jack Moore - http://www.jacklmoore.com/colorbox
  5 + license: http://www.opensource.org/licenses/mit-license.php
  6 +*/
  7 +(function(e,t,i){function o(i,o,n){var r=t.createElement(i);return o&&(r.id=Z+o),n&&(r.style.cssText=n),e(r)}function n(){return i.innerHeight?i.innerHeight:e(i).height()}function r(e){var t=k.length,i=(z+e)%t;return 0>i?t+i:i}function h(e,t){return Math.round((/%/.test(e)?("x"===t?E.width():n())/100:1)*parseInt(e,10))}function l(e,t){return e.photo||e.photoRegex.test(t)}function s(e,t){return e.retinaUrl&&i.devicePixelRatio>1?t.replace(e.photoRegex,e.retinaSuffix):t}function a(e){"contains"in g[0]&&!g[0].contains(e.target)&&(e.stopPropagation(),g.focus())}function d(){var t,i=e.data(N,Y);null==i?(B=e.extend({},X),console&&console.log&&console.log("Error: cboxElement missing settings object")):B=e.extend({},i);for(t in B)e.isFunction(B[t])&&"on"!==t.slice(0,2)&&(B[t]=B[t].call(N));B.rel=B.rel||N.rel||e(N).data("rel")||"nofollow",B.href=B.href||e(N).attr("href"),B.title=B.title||N.title,"string"==typeof B.href&&(B.href=e.trim(B.href))}function c(i,o){e(t).trigger(i),lt.triggerHandler(i),e.isFunction(o)&&o.call(N)}function u(i){q||(N=i,d(),k=e(N),z=0,"nofollow"!==B.rel&&(k=e("."+et).filter(function(){var t,i=e.data(this,Y);return i&&(t=e(this).data("rel")||i.rel||this.rel),t===B.rel}),z=k.index(N),-1===z&&(k=k.add(N),z=k.length-1)),w.css({opacity:parseFloat(B.opacity),cursor:B.overlayClose?"pointer":"auto",visibility:"visible"}).show(),J&&g.add(w).removeClass(J),B.className&&g.add(w).addClass(B.className),J=B.className,B.closeButton?K.html(B.close).appendTo(y):K.appendTo("<div/>"),U||(U=$=!0,g.css({visibility:"hidden",display:"block"}),H=o(st,"LoadedContent","width:0; height:0; overflow:hidden"),y.css({width:"",height:""}).append(H),O=x.height()+C.height()+y.outerHeight(!0)-y.height(),_=b.width()+T.width()+y.outerWidth(!0)-y.width(),D=H.outerHeight(!0),A=H.outerWidth(!0),B.w=h(B.initialWidth,"x"),B.h=h(B.initialHeight,"y"),H.css({width:"",height:B.h}),Q.position(),c(tt,B.onOpen),P.add(L).hide(),g.focus(),B.trapFocus&&t.addEventListener&&(t.addEventListener("focus",a,!0),lt.one(rt,function(){t.removeEventListener("focus",a,!0)})),B.returnFocus&&lt.one(rt,function(){e(N).focus()})),m())}function f(){!g&&t.body&&(V=!1,E=e(i),g=o(st).attr({id:Y,"class":e.support.opacity===!1?Z+"IE":"",role:"dialog",tabindex:"-1"}).hide(),w=o(st,"Overlay").hide(),F=e([o(st,"LoadingOverlay")[0],o(st,"LoadingGraphic")[0]]),v=o(st,"Wrapper"),y=o(st,"Content").append(L=o(st,"Title"),S=o(st,"Current"),I=e('<button type="button"/>').attr({id:Z+"Previous"}),R=e('<button type="button"/>').attr({id:Z+"Next"}),M=o("button","Slideshow"),F),K=e('<button type="button"/>').attr({id:Z+"Close"}),v.append(o(st).append(o(st,"TopLeft"),x=o(st,"TopCenter"),o(st,"TopRight")),o(st,!1,"clear:left").append(b=o(st,"MiddleLeft"),y,T=o(st,"MiddleRight")),o(st,!1,"clear:left").append(o(st,"BottomLeft"),C=o(st,"BottomCenter"),o(st,"BottomRight"))).find("div div").css({"float":"left"}),W=o(st,!1,"position:absolute; width:9999px; visibility:hidden; display:none; max-width:none;"),P=R.add(I).add(S).add(M),e(t.body).append(w,g.append(v,W)))}function p(){function i(e){e.which>1||e.shiftKey||e.altKey||e.metaKey||e.ctrlKey||(e.preventDefault(),u(this))}return g?(V||(V=!0,R.click(function(){Q.next()}),I.click(function(){Q.prev()}),K.click(function(){Q.close()}),w.click(function(){B.overlayClose&&Q.close()}),e(t).bind("keydown."+Z,function(e){var t=e.keyCode;U&&B.escKey&&27===t&&(e.preventDefault(),Q.close()),U&&B.arrowKey&&k[1]&&!e.altKey&&(37===t?(e.preventDefault(),I.click()):39===t&&(e.preventDefault(),R.click()))}),e.isFunction(e.fn.on)?e(t).on("click."+Z,"."+et,i):e("."+et).live("click."+Z,i)),!0):!1}function m(){var n,r,a,u=Q.prep,f=++at;$=!0,j=!1,N=k[z],d(),c(ht),c(it,B.onLoad),B.h=B.height?h(B.height,"y")-D-O:B.innerHeight&&h(B.innerHeight,"y"),B.w=B.width?h(B.width,"x")-A-_:B.innerWidth&&h(B.innerWidth,"x"),B.mw=B.w,B.mh=B.h,B.maxWidth&&(B.mw=h(B.maxWidth,"x")-A-_,B.mw=B.w&&B.w<B.mw?B.w:B.mw),B.maxHeight&&(B.mh=h(B.maxHeight,"y")-D-O,B.mh=B.h&&B.h<B.mh?B.h:B.mh),n=B.href,G=setTimeout(function(){F.show()},100),B.inline?(a=o(st).hide().insertBefore(e(n)[0]),lt.one(ht,function(){a.replaceWith(H.children())}),u(e(n))):B.iframe?u(" "):B.html?u(B.html):l(B,n)?(n=s(B,n),j=t.createElement("img"),e(j).addClass(Z+"Photo").bind("error",function(){B.title=!1,u(o(st,"Error").html(B.imgError))}).one("load",function(){var t;f===at&&(e.each(["alt","longdesc","aria-describedby"],function(t,i){var o=e(N).attr(i)||e(N).attr("data-"+i);o&&j.setAttribute(i,o)}),B.retinaImage&&i.devicePixelRatio>1&&(j.height=j.height/i.devicePixelRatio,j.width=j.width/i.devicePixelRatio),B.scalePhotos&&(r=function(){j.height-=j.height*t,j.width-=j.width*t},B.mw&&j.width>B.mw&&(t=(j.width-B.mw)/j.width,r()),B.mh&&j.height>B.mh&&(t=(j.height-B.mh)/j.height,r())),B.h&&(j.style.marginTop=Math.max(B.mh-j.height,0)/2+"px"),k[1]&&(B.loop||k[z+1])&&(j.style.cursor="pointer",j.onclick=function(){Q.next()}),j.style.width=j.width+"px",j.style.height=j.height+"px",setTimeout(function(){u(j)},1))}),setTimeout(function(){j.src=n},1)):n&&W.load(n,B.data,function(t,i){f===at&&u("error"===i?o(st,"Error").html(B.xhrError):e(this).contents())})}var w,g,v,y,x,b,T,C,k,E,H,W,F,L,S,M,R,I,K,P,B,O,_,D,A,N,z,j,U,$,q,G,Q,J,V,X={html:!1,photo:!1,iframe:!1,inline:!1,transition:"elastic",speed:300,fadeOut:300,width:!1,initialWidth:"600",innerWidth:!1,maxWidth:!1,height:!1,initialHeight:"450",innerHeight:!1,maxHeight:!1,scalePhotos:!0,scrolling:!0,href:!1,title:!1,rel:!1,opacity:.9,preloading:!0,className:!1,overlayClose:!0,escKey:!0,arrowKey:!0,top:!1,bottom:!1,left:!1,right:!1,fixed:!1,data:void 0,closeButton:!0,fastIframe:!0,open:!1,reposition:!0,loop:!0,slideshow:!1,slideshowAuto:!0,slideshowSpeed:2500,slideshowStart:"start slideshow",slideshowStop:"stop slideshow",photoRegex:/\.(gif|png|jp(e|g|eg)|bmp|ico|webp)((#|\?).*)?$/i,retinaImage:!1,retinaUrl:!1,retinaSuffix:"@2x.$1",current:"image {current} of {total}",previous:"previous",next:"next",close:"close",xhrError:"This content failed to load.",imgError:"This image failed to load.",returnFocus:!0,trapFocus:!0,onOpen:!1,onLoad:!1,onComplete:!1,onCleanup:!1,onClosed:!1},Y="colorbox",Z="cbox",et=Z+"Element",tt=Z+"_open",it=Z+"_load",ot=Z+"_complete",nt=Z+"_cleanup",rt=Z+"_closed",ht=Z+"_purge",lt=e("<a/>"),st="div",at=0,dt={},ct=function(){function e(){clearTimeout(h)}function t(){(B.loop||k[z+1])&&(e(),h=setTimeout(Q.next,B.slideshowSpeed))}function i(){M.html(B.slideshowStop).unbind(s).one(s,o),lt.bind(ot,t).bind(it,e),g.removeClass(l+"off").addClass(l+"on")}function o(){e(),lt.unbind(ot,t).unbind(it,e),M.html(B.slideshowStart).unbind(s).one(s,function(){Q.next(),i()}),g.removeClass(l+"on").addClass(l+"off")}function n(){r=!1,M.hide(),e(),lt.unbind(ot,t).unbind(it,e),g.removeClass(l+"off "+l+"on")}var r,h,l=Z+"Slideshow_",s="click."+Z;return function(){r?B.slideshow||(lt.unbind(nt,n),n()):B.slideshow&&k[1]&&(r=!0,lt.one(nt,n),B.slideshowAuto?i():o(),M.show())}}();e.colorbox||(e(f),Q=e.fn[Y]=e[Y]=function(t,i){var o=this;if(t=t||{},f(),p()){if(e.isFunction(o))o=e("<a/>"),t.open=!0;else if(!o[0])return o;i&&(t.onComplete=i),o.each(function(){e.data(this,Y,e.extend({},e.data(this,Y)||X,t))}).addClass(et),(e.isFunction(t.open)&&t.open.call(o)||t.open)&&u(o[0])}return o},Q.position=function(t,i){function o(){x[0].style.width=C[0].style.width=y[0].style.width=parseInt(g[0].style.width,10)-_+"px",y[0].style.height=b[0].style.height=T[0].style.height=parseInt(g[0].style.height,10)-O+"px"}var r,l,s,a=0,d=0,c=g.offset();if(E.unbind("resize."+Z),g.css({top:-9e4,left:-9e4}),l=E.scrollTop(),s=E.scrollLeft(),B.fixed?(c.top-=l,c.left-=s,g.css({position:"fixed"})):(a=l,d=s,g.css({position:"absolute"})),d+=B.right!==!1?Math.max(E.width()-B.w-A-_-h(B.right,"x"),0):B.left!==!1?h(B.left,"x"):Math.round(Math.max(E.width()-B.w-A-_,0)/2),a+=B.bottom!==!1?Math.max(n()-B.h-D-O-h(B.bottom,"y"),0):B.top!==!1?h(B.top,"y"):Math.round(Math.max(n()-B.h-D-O,0)/2),g.css({top:c.top,left:c.left,visibility:"visible"}),v[0].style.width=v[0].style.height="9999px",r={width:B.w+A+_,height:B.h+D+O,top:a,left:d},t){var u=0;e.each(r,function(e){return r[e]!==dt[e]?(u=t,void 0):void 0}),t=u}dt=r,t||g.css(r),g.dequeue().animate(r,{duration:t||0,complete:function(){o(),$=!1,v[0].style.width=B.w+A+_+"px",v[0].style.height=B.h+D+O+"px",B.reposition&&setTimeout(function(){E.bind("resize."+Z,Q.position)},1),i&&i()},step:o})},Q.resize=function(e){var t;U&&(e=e||{},e.width&&(B.w=h(e.width,"x")-A-_),e.innerWidth&&(B.w=h(e.innerWidth,"x")),H.css({width:B.w}),e.height&&(B.h=h(e.height,"y")-D-O),e.innerHeight&&(B.h=h(e.innerHeight,"y")),e.innerHeight||e.height||(t=H.scrollTop(),H.css({height:"auto"}),B.h=H.height()),H.css({height:B.h}),t&&H.scrollTop(t),Q.position("none"===B.transition?0:B.speed))},Q.prep=function(i){function n(){return B.w=B.w||H.width(),B.w=B.mw&&B.mw<B.w?B.mw:B.w,B.w}function h(){return B.h=B.h||H.height(),B.h=B.mh&&B.mh<B.h?B.mh:B.h,B.h}if(U){var a,d="none"===B.transition?0:B.speed;H.empty().remove(),H=o(st,"LoadedContent").append(i),H.hide().appendTo(W.show()).css({width:n(),overflow:B.scrolling?"auto":"hidden"}).css({height:h()}).prependTo(y),W.hide(),e(j).css({"float":"none"}),a=function(){function i(){e.support.opacity===!1&&g[0].style.removeAttribute("filter")}var n,h,a=k.length,u="frameBorder",f="allowTransparency";U&&(h=function(){clearTimeout(G),F.hide(),c(ot,B.onComplete)},L.html(B.title).add(H).show(),a>1?("string"==typeof B.current&&S.html(B.current.replace("{current}",z+1).replace("{total}",a)).show(),R[B.loop||a-1>z?"show":"hide"]().html(B.next),I[B.loop||z?"show":"hide"]().html(B.previous),ct(),B.preloading&&e.each([r(-1),r(1)],function(){var i,o,n=k[this],r=e.data(n,Y);r&&r.href?(i=r.href,e.isFunction(i)&&(i=i.call(n))):i=e(n).attr("href"),i&&l(r,i)&&(i=s(r,i),o=t.createElement("img"),o.src=i)})):P.hide(),B.iframe?(n=o("iframe")[0],u in n&&(n[u]=0),f in n&&(n[f]="true"),B.scrolling||(n.scrolling="no"),e(n).attr({src:B.href,name:(new Date).getTime(),"class":Z+"Iframe",allowFullScreen:!0,webkitAllowFullScreen:!0,mozallowfullscreen:!0}).one("load",h).appendTo(H),lt.one(ht,function(){n.src="//about:blank"}),B.fastIframe&&e(n).trigger("load")):h(),"fade"===B.transition?g.fadeTo(d,1,i):i())},"fade"===B.transition?g.fadeTo(d,0,function(){Q.position(0,a)}):Q.position(d,a)}},Q.next=function(){!$&&k[1]&&(B.loop||k[z+1])&&(z=r(1),u(k[z]))},Q.prev=function(){!$&&k[1]&&(B.loop||z)&&(z=r(-1),u(k[z]))},Q.close=function(){U&&!q&&(q=!0,U=!1,c(nt,B.onCleanup),E.unbind("."+Z),w.fadeTo(B.fadeOut||0,0),g.stop().fadeTo(B.fadeOut||0,0,function(){g.add(w).css({opacity:1,cursor:"auto"}).hide(),c(ht),H.empty().remove(),setTimeout(function(){q=!1,c(rt,B.onClosed)},1)}))},Q.remove=function(){g&&(g.stop(),e.colorbox.close(),g.stop().remove(),w.remove(),q=!1,g=null,e("."+et).removeData(Y).removeClass(et),e(t).unbind("click."+Z))},Q.element=function(){return e(N)},Q.settings=X)})(jQuery,document,window);
0 \ No newline at end of file 8 \ No newline at end of file
public/javascripts/lightbox.js
@@ -1,232 +0,0 @@ @@ -1,232 +0,0 @@
1 -/*  
2 -Created By: Chris Campbell  
3 -Website: http://particletree.com  
4 -Date: 2/1/2006  
5 -  
6 -Inspired by the lightbox implementation found at http://www.huddletogether.com/projects/lightbox/  
7 -*/  
8 -  
9 -/*-------------------------------GLOBAL VARIABLES------------------------------------*/  
10 -  
11 -var detect = navigator.userAgent.toLowerCase();  
12 -var OS,browser,version,total,thestring;  
13 -  
14 -/*-----------------------------------------------------------------------------------------------*/  
15 -  
16 -//Browser detect script origionally created by Peter Paul Koch at http://www.quirksmode.org/  
17 -  
18 -function getBrowserInfo() {  
19 - if (checkIt('konqueror')) {  
20 - browser = "Konqueror";  
21 - OS = "Linux";  
22 - }  
23 - else if (checkIt('safari')) browser = "Safari"  
24 - else if (checkIt('omniweb')) browser = "OmniWeb"  
25 - else if (checkIt('opera')) browser = "Opera"  
26 - else if (checkIt('webtv')) browser = "WebTV";  
27 - else if (checkIt('icab')) browser = "iCab"  
28 - else if (checkIt('msie')) browser = "Internet Explorer"  
29 - else if (!checkIt('compatible')) {  
30 - browser = "Netscape Navigator"  
31 - version = detect.charAt(8);  
32 - }  
33 - else browser = "An unknown browser";  
34 -  
35 - if (!version) version = detect.charAt(place + thestring.length);  
36 -  
37 - if (!OS) {  
38 - if (checkIt('linux')) OS = "Linux";  
39 - else if (checkIt('x11')) OS = "Unix";  
40 - else if (checkIt('mac')) OS = "Mac"  
41 - else if (checkIt('win')) OS = "Windows"  
42 - else OS = "an unknown operating system";  
43 - }  
44 -}  
45 -  
46 -function checkIt(string) {  
47 - place = detect.indexOf(string) + 1;  
48 - thestring = string;  
49 - return place;  
50 -}  
51 -  
52 -/*-----------------------------------------------------------------------------------------------*/  
53 -  
54 -Event.observe(window, 'load', getBrowserInfo, false);  
55 -  
56 -var lightbox = Class.create();  
57 -  
58 -lightbox.prototype = {  
59 -  
60 - yPos : 0,  
61 - xPos : 0,  
62 -  
63 - initialize: function(ctrl) {  
64 - this.content = ctrl.href;  
65 - if (ctrl.id != '') {  
66 - this.lightbox_className = ctrl.id;  
67 - }  
68 - ctrl.onclick = function(){return false;};  
69 - ctrl.lightbox = this;  
70 - },  
71 -  
72 - // Turn everything on - mainly the IE fixes  
73 - activate: function(){  
74 - if (browser == 'Internet Explorer'){  
75 - this.getScroll();  
76 - this.prepareIE('100%', 'hidden');  
77 - this.setScroll(0,0);  
78 - this.hideSelects('hidden');  
79 - }  
80 - this.hideObjectsAndEmbeds('hidden');  
81 - this.displayLightbox("block");  
82 - },  
83 -  
84 - // Ie requires height to 100% and overflow hidden or else you can scroll down past the lightbox  
85 - prepareIE: function(height, overflow){  
86 - bod = document.getElementsByTagName('body')[0];  
87 - bod.style.height = height;  
88 - bod.style.overflow = overflow;  
89 -  
90 - htm = document.getElementsByTagName('html')[0];  
91 - htm.style.height = height;  
92 - htm.style.overflow = overflow;  
93 - },  
94 -  
95 - // In IE, select elements hover on top of the lightbox  
96 - hideSelects: function(visibility){  
97 - selects = document.getElementsByTagName('select');  
98 - for(i = 0; i < selects.length; i++) {  
99 - selects[i].style.visibility = visibility;  
100 - }  
101 - },  
102 -  
103 - // In FF, objects and embeds elements hover on top of the lightbox  
104 - hideObjectsAndEmbeds: function(visibility){  
105 - var f = function(collection) {  
106 - for(i = 0; i < collection.length; i++) {  
107 - if (collection[i].style) {  
108 - collection[i].style.visibility = visibility;  
109 - }  
110 - }  
111 - };  
112 - f(document.getElementsByTagName('object'));  
113 - f(document.getElementsByTagName('embed'));  
114 - },  
115 -  
116 - // Taken from lightbox implementation found at http://www.huddletogether.com/projects/lightbox/  
117 - getScroll: function(){  
118 - if (self.pageYOffset) {  
119 - this.yPos = self.pageYOffset;  
120 - } else if (document.documentElement && document.documentElement.scrollTop){  
121 - this.yPos = document.documentElement.scrollTop;  
122 - } else if (document.body) {  
123 - this.yPos = document.body.scrollTop;  
124 - }  
125 - },  
126 -  
127 - setScroll: function(x, y){  
128 - window.scrollTo(x, y);  
129 - },  
130 -  
131 - displayLightbox: function(display){  
132 - $('overlay').style.display = display;  
133 - $('lightbox').style.display = display;  
134 - if(display != 'none') this.loadInfo();  
135 - },  
136 -  
137 - // Begin Ajax request based off of the href of the clicked linked  
138 - loadInfo: function() {  
139 - var myAjax = new Ajax.Request(  
140 - this.content,  
141 - {method: 'post', parameters: "", onComplete: this.processInfo.bindAsEventListener(this)}  
142 - );  
143 -  
144 - },  
145 -  
146 - // Display Ajax response  
147 - processInfo: function(response){  
148 - info = "<div id='lbContent'><div id='lbBottomBG'><div id='lbTopBG'>" + response.responseText + "</div></div></div>";  
149 - new Insertion.Before($('lbLoadMessage'), info)  
150 - if (this.lightbox_className) {  
151 - $('lightbox').className = "done " + this.lightbox_className;  
152 - } else {  
153 - $('lightbox').className = "done";  
154 - }  
155 - this.actions();  
156 - },  
157 -  
158 - // Search through new links within the lightbox, and attach click event  
159 - actions: function(){  
160 - lbActions = document.getElementsByClassName('lbAction');  
161 -  
162 - for(i = 0; i < lbActions.length; i++) {  
163 - Event.observe(lbActions[i], 'click', this[lbActions[i].rel].bindAsEventListener(this), false);  
164 - lbActions[i].onclick = function(){return false;};  
165 - }  
166 -  
167 - },  
168 -  
169 - // Example of creating your own functionality once lightbox is initiated  
170 - insert: function(e){  
171 - link = Event.element(e).parentNode;  
172 - Element.remove($('lbContent'));  
173 -  
174 - var myAjax = new Ajax.Request(  
175 - link.href,  
176 - {method: 'post', parameters: "", onComplete: this.processInfo.bindAsEventListener(this)}  
177 - );  
178 -  
179 - },  
180 -  
181 - // Example of creating your own functionality once lightbox is initiated  
182 - deactivate: function(){  
183 - Element.remove($('lbContent'));  
184 -  
185 - if (browser == "Internet Explorer"){  
186 - this.setScroll(0,this.yPos);  
187 - this.prepareIE("auto", "auto");  
188 - this.hideSelects("visible");  
189 - }  
190 - this.hideObjectsAndEmbeds("visible");  
191 - this.displayLightbox("none");  
192 - }  
193 -}  
194 -  
195 -/*-----------------------------------------------------------------------------------------------*/  
196 -  
197 -jQuery('.lbOn').live('click', function(event) {  
198 - if (jQuery('#lbLoadMessage').length == 0)  
199 - addLightboxMarkup();  
200 - if (this.lightbox == undefined)  
201 - valid = new lightbox(this);  
202 - else {  
203 - removeLightboxMarkup();  
204 - addLightboxMarkup();  
205 - }  
206 -  
207 - this.lightbox.activate();  
208 -  
209 - event.preventDefault();  
210 - return false;  
211 -});  
212 -  
213 -// Add in markup necessary to make this work. Basically two divs:  
214 -// Overlay holds the shadow  
215 -// Lightbox is the centered square that the content is put into.  
216 -function addLightboxMarkup() {  
217 - bod = document.getElementsByTagName('body')[0];  
218 - overlay = document.createElement('div');  
219 - overlay.id = 'overlay';  
220 - lb = document.createElement('div');  
221 - lb.id = 'lightbox';  
222 - lb.className = 'loading';  
223 - lb.innerHTML = '<div id="lbLoadMessage">' +  
224 - '<img src="' + noosfero_root() + '/images/2loading.gif"/>' +  
225 - '</div>';  
226 - bod.appendChild(overlay);  
227 - bod.appendChild(lb);  
228 -}  
229 -function removeLightboxMarkup() {  
230 - Element.remove($('overlay'));  
231 - Element.remove($('lightbox'));  
232 -}  
public/javascripts/modal.js 0 → 100644
@@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
  1 +noosfero.modal = {
  2 +
  3 + watchClass: function() {
  4 + jQuery(function($) {
  5 + $(document).delegate('.modal-toggle', 'click', function() {
  6 + $.colorbox({
  7 + href: $(this).attr('href'),
  8 + maxWidth: $(window).width()-50,
  9 + height: $(window).height()-50,
  10 + open: true,
  11 + close: 'Cancel',
  12 + class: 'modal',
  13 + onComplete: function(bt) {
  14 + var opt = {}, maxH = $(window).height()-50;
  15 + if ($('#cboxLoadedContent *:first').height() > maxH) opt.height = maxH;
  16 + $.colorbox.resize(opt);
  17 + }
  18 + });
  19 + return false;
  20 + });
  21 +
  22 + $(document).delegate('.modal-close', 'click', function() {
  23 + $.colorbox.close();
  24 + return false;
  25 + });
  26 +
  27 + });
  28 + },
  29 +
  30 + inline: function(href, options) {
  31 + href = jQuery(href);
  32 + options = jQuery.extend({
  33 + inline: true, href: href,
  34 + onLoad: function(){ href.show(); },
  35 + onCleanup: function(){ href.hide(); },
  36 + }, options)
  37 +
  38 + jQuery.colorbox(options);
  39 +
  40 + return false;
  41 + },
  42 +
  43 + html: function(html, options) {
  44 + options = jQuery.extend({
  45 + html: html,
  46 + }, options);
  47 +
  48 + jQuery.colorbox(options);
  49 + },
  50 +
  51 + close: function() {
  52 + jQuery.colorbox.close();
  53 + },
  54 +
  55 +};
  56 +
  57 +noosfero.modal.watchClass();
  58 +
public/javascripts/report-abuse.js
1 jQuery(function($) { 1 jQuery(function($) {
2 $('.report-abuse-action').live('click', function() { 2 $('.report-abuse-action').live('click', function() {
3 if($(this).attr('href')){ 3 if($(this).attr('href')){
4 - $.fn.colorbox({  
5 - href: $(this).attr('href'), 4 + noosfero.modal.inline($(this).attr('href'), {
6 innerHeight: '300px', 5 innerHeight: '300px',
7 innerWidth: '445px' 6 innerWidth: '445px'
8 }); 7 });
public/javascripts/thickbox.js
@@ -1,319 +0,0 @@ @@ -1,319 +0,0 @@
1 -/*  
2 - * Thickbox 3.1 - One Box To Rule Them All.  
3 - * By Cody Lindley (http://www.codylindley.com)  
4 - * Copyright (c) 2007 cody lindley  
5 - * Licensed under the MIT License: http://www.opensource.org/licenses/mit-license.php  
6 -*/  
7 -  
8 -var tb_pathToImage = "/images/loading.gif";  
9 -  
10 -/*!!!!!!!!!!!!!!!!! edit below this line at your own risk !!!!!!!!!!!!!!!!!!!!!!!*/  
11 -  
12 -//on page load call tb_init  
13 -jQuery(document).ready(function(){  
14 - tb_init('a.thickbox, area.thickbox, input.thickbox');//pass where to apply thickbox  
15 - imgLoader = new Image();// preload image  
16 - imgLoader.src = noosfero_root() + tb_pathToImage;  
17 -});  
18 -  
19 -//add thickbox to href & area elements that have a class of .thickbox  
20 -function tb_init(domChunk){  
21 - jQuery(domChunk).click(function(){  
22 - var t = this.title || this.name || null;  
23 - var a = this.href || this.alt;  
24 - var g = this.rel || false;  
25 - tb_show(t,a,g);  
26 - this.blur();  
27 - return false;  
28 - });  
29 -}  
30 -  
31 -function tb_show(caption, url, imageGroup) {//function called when the user clicks on a thickbox link  
32 -  
33 - try {  
34 - if (typeof document.body.style.maxHeight === "undefined") {//if IE 6  
35 - jQuery("body","html").css({height: "100%", width: "100%"});  
36 - jQuery("html").css("overflow","hidden");  
37 - if (document.getElementById("TB_HideSelect") === null) {//iframe to hide select elements in ie6  
38 - jQuery("body").append("<iframe id='TB_HideSelect'></iframe><div id='TB_overlay'></div><div id='TB_window'></div>");  
39 - jQuery("#TB_overlay").click(tb_remove);  
40 - }  
41 - }else{//all others  
42 - if(document.getElementById("TB_overlay") === null){  
43 - jQuery("body").append("<div id='TB_overlay'></div><div id='TB_window'></div>");  
44 - jQuery("#TB_overlay").click(tb_remove);  
45 - }  
46 - }  
47 -  
48 - if(tb_detectMacXFF()){  
49 - jQuery("#TB_overlay").addClass("TB_overlayMacFFBGHack");//use png overlay so hide flash  
50 - }else{  
51 - jQuery("#TB_overlay").addClass("TB_overlayBG");//use background and opacity  
52 - }  
53 -  
54 - if(caption===null){caption="";}  
55 - jQuery("body").append("<div id='TB_load'><img src='"+imgLoader.src+"' /></div>");//add loader to the page  
56 - jQuery('#TB_load').show();//show loader  
57 -  
58 - var baseURL;  
59 - if(url.indexOf("?")!==-1){ //ff there is a query string involved  
60 - baseURL = url.substr(0, url.indexOf("?"));  
61 - }else{  
62 - baseURL = url;  
63 - }  
64 -  
65 - var urlString = /\.jpg$|\.jpeg$|\.png$|\.gif$|\.bmp$/;  
66 - var urlType = baseURL.toLowerCase().match(urlString);  
67 -  
68 - if(urlType == '.jpg' || urlType == '.jpeg' || urlType == '.png' || urlType == '.gif' || urlType == '.bmp'){//code to show images  
69 -  
70 - TB_PrevCaption = "";  
71 - TB_PrevURL = "";  
72 - TB_PrevHTML = "";  
73 - TB_NextCaption = "";  
74 - TB_NextURL = "";  
75 - TB_NextHTML = "";  
76 - TB_imageCount = "";  
77 - TB_FoundURL = false;  
78 - if(imageGroup){  
79 - TB_TempArray = jQuery("a[@rel="+imageGroup+"]").get();  
80 - for (TB_Counter = 0; ((TB_Counter < TB_TempArray.length) && (TB_NextHTML === "")); TB_Counter++) {  
81 - var urlTypeTemp = TB_TempArray[TB_Counter].href.toLowerCase().match(urlString);  
82 - if (!(TB_TempArray[TB_Counter].href == url)) {  
83 - if (TB_FoundURL) {  
84 - TB_NextCaption = TB_TempArray[TB_Counter].title;  
85 - TB_NextURL = TB_TempArray[TB_Counter].href;  
86 - TB_NextHTML = "<span id='TB_next'>&nbsp;&nbsp;<a href='#'>Next &gt;</a></span>";  
87 - } else {  
88 - TB_PrevCaption = TB_TempArray[TB_Counter].title;  
89 - TB_PrevURL = TB_TempArray[TB_Counter].href;  
90 - TB_PrevHTML = "<span id='TB_prev'>&nbsp;&nbsp;<a href='#'>&lt; Prev</a></span>";  
91 - }  
92 - } else {  
93 - TB_FoundURL = true;  
94 - TB_imageCount = "Image " + (TB_Counter + 1) +" of "+ (TB_TempArray.length);  
95 - }  
96 - }  
97 - }  
98 -  
99 - imgPreloader = new Image();  
100 - imgPreloader.onload = function(){  
101 - imgPreloader.onload = null;  
102 -  
103 - // Resizing large images - orginal by Christian Montoya edited by me.  
104 - var pagesize = tb_getPageSize();  
105 - var x = pagesize[0] - 150;  
106 - var y = pagesize[1] - 150;  
107 - var imageWidth = imgPreloader.width;  
108 - var imageHeight = imgPreloader.height;  
109 - if (imageWidth > x) {  
110 - imageHeight = imageHeight * (x / imageWidth);  
111 - imageWidth = x;  
112 - if (imageHeight > y) {  
113 - imageWidth = imageWidth * (y / imageHeight);  
114 - imageHeight = y;  
115 - }  
116 - } else if (imageHeight > y) {  
117 - imageWidth = imageWidth * (y / imageHeight);  
118 - imageHeight = y;  
119 - if (imageWidth > x) {  
120 - imageHeight = imageHeight * (x / imageWidth);  
121 - imageWidth = x;  
122 - }  
123 - }  
124 - // End Resizing  
125 -  
126 - TB_WIDTH = imageWidth + 30;  
127 - TB_HEIGHT = imageHeight + 60;  
128 - jQuery("#TB_window").append("<a href='' id='TB_ImageOff' title='Close'><img id='TB_Image' src='"+url+"' width='"+imageWidth+"' height='"+imageHeight+"' alt='"+caption+"'/></a>" + "<div id='TB_caption'>"+caption+"<div id='TB_secondLine'>" + TB_imageCount + TB_PrevHTML + TB_NextHTML + "</div></div><div id='TB_closeWindow'><a href='#' id='TB_closeWindowButton' title='Close'>close</a> or Esc Key</div>");  
129 -  
130 - jQuery("#TB_closeWindowButton").click(tb_remove);  
131 -  
132 - if (!(TB_PrevHTML === "")) {  
133 - function goPrev(){  
134 - if(jQuery(document).unbind("click",goPrev)){jQuery(document).unbind("click",goPrev);}  
135 - jQuery("#TB_window").remove();  
136 - jQuery("body").append("<div id='TB_window'></div>");  
137 - tb_show(TB_PrevCaption, TB_PrevURL, imageGroup);  
138 - return false;  
139 - }  
140 - jQuery("#TB_prev").click(goPrev);  
141 - }  
142 -  
143 - if (!(TB_NextHTML === "")) {  
144 - function goNext(){  
145 - jQuery("#TB_window").remove();  
146 - jQuery("body").append("<div id='TB_window'></div>");  
147 - tb_show(TB_NextCaption, TB_NextURL, imageGroup);  
148 - return false;  
149 - }  
150 - jQuery("#TB_next").click(goNext);  
151 -  
152 - }  
153 -  
154 - document.onkeydown = function(e){  
155 - if (e == null) { // ie  
156 - keycode = event.keyCode;  
157 - } else { // mozilla  
158 - keycode = e.which;  
159 - }  
160 - if(keycode == 27){ // close  
161 - tb_remove();  
162 - } else if(keycode == 190){ // display previous image  
163 - if(!(TB_NextHTML == "")){  
164 - document.onkeydown = "";  
165 - goNext();  
166 - }  
167 - } else if(keycode == 188){ // display next image  
168 - if(!(TB_PrevHTML == "")){  
169 - document.onkeydown = "";  
170 - goPrev();  
171 - }  
172 - }  
173 - };  
174 -  
175 - tb_position();  
176 - jQuery("#TB_load").remove();  
177 - jQuery("#TB_ImageOff").click(tb_remove);  
178 - jQuery("#TB_window").css({display:"block"}); //for safari using css instead of show  
179 - };  
180 -  
181 - imgPreloader.src = url;  
182 - }else{//code to show html  
183 -  
184 - var queryString = url.replace(/^[^\?]+\??/,'');  
185 - var params = tb_parseQuery( queryString );  
186 -  
187 - TB_WIDTH = (params['width']*1) + 30 || 630; //defaults to 630 if no paramaters were added to URL  
188 - TB_HEIGHT = (params['height']*1) + 40 || 440; //defaults to 440 if no paramaters were added to URL  
189 - ajaxContentW = TB_WIDTH - 30;  
190 - ajaxContentH = TB_HEIGHT - 45;  
191 -  
192 - if(url.indexOf('TB_iframe') != -1){// either iframe or ajax window  
193 - urlNoQuery = url.split('TB_');  
194 - jQuery("#TB_iframeContent").remove();  
195 - if(params['modal'] != "true"){//iframe no modal  
196 - jQuery("#TB_window").append("<div id='TB_title'><div id='TB_ajaxWindowTitle'>"+caption+"</div><div id='TB_closeAjaxWindow'><a href='#' id='TB_closeWindowButton' title='Close'>close</a> or Esc Key</div></div><iframe frameborder='0' hspace='0' src='"+urlNoQuery[0]+"' id='TB_iframeContent' name='TB_iframeContent"+Math.round(Math.random()*1000)+"' onload='tb_showIframe()' style='width:"+(ajaxContentW + 29)+"px;height:"+(ajaxContentH + 17)+"px;' > </iframe>");  
197 - }else{//iframe modal  
198 - jQuery("#TB_overlay").unbind();  
199 - jQuery("#TB_window").append("<iframe frameborder='0' hspace='0' src='"+urlNoQuery[0]+"' id='TB_iframeContent' name='TB_iframeContent"+Math.round(Math.random()*1000)+"' onload='tb_showIframe()' style='width:"+(ajaxContentW + 29)+"px;height:"+(ajaxContentH + 17)+"px;'> </iframe>");  
200 - }  
201 - }else{// not an iframe, ajax  
202 - if(jQuery("#TB_window").css("display") != "block"){  
203 - if(params['modal'] != "true"){//ajax no modal  
204 - jQuery("#TB_window").append("<div id='TB_title'><div id='TB_ajaxWindowTitle'>"+caption+"</div><div id='TB_closeAjaxWindow'><a href='#' id='TB_closeWindowButton'>close</a> or Esc Key</div></div><div id='TB_ajaxContent' style='width:"+ajaxContentW+"px;height:"+ajaxContentH+"px'></div>");  
205 - }else{//ajax modal  
206 - jQuery("#TB_overlay").unbind();  
207 - jQuery("#TB_window").append("<div id='TB_ajaxContent' class='TB_modal' style='width:"+ajaxContentW+"px;height:"+ajaxContentH+"px;'></div>");  
208 - }  
209 - }else{//this means the window is already up, we are just loading new content via ajax  
210 - jQuery("#TB_ajaxContent")[0].style.width = ajaxContentW +"px";  
211 - jQuery("#TB_ajaxContent")[0].style.height = ajaxContentH +"px";  
212 - jQuery("#TB_ajaxContent")[0].scrollTop = 0;  
213 - jQuery("#TB_ajaxWindowTitle").html(caption);  
214 - }  
215 - }  
216 -  
217 - jQuery("#TB_closeWindowButton").click(tb_remove);  
218 -  
219 - if(url.indexOf('TB_inline') != -1){  
220 - jQuery("#TB_ajaxContent").append(jQuery('#' + params['inlineId']).children());  
221 - jQuery("#TB_window").unload(function () {  
222 - jQuery('#' + params['inlineId']).append( jQuery("#TB_ajaxContent").children() ); // move elements back when you're finished  
223 - });  
224 - tb_position();  
225 - jQuery("#TB_load").remove();  
226 - jQuery("#TB_window").css({display:"block"});  
227 - }else if(url.indexOf('TB_iframe') != -1){  
228 - tb_position();  
229 - if(jQuery.browser.safari){//safari needs help because it will not fire iframe onload  
230 - jQuery("#TB_load").remove();  
231 - jQuery("#TB_window").css({display:"block"});  
232 - }  
233 - }else{  
234 - jQuery("#TB_ajaxContent").load(url += "&random=" + (new Date().getTime()),function(){//to do a post change this load method  
235 - tb_position();  
236 - jQuery("#TB_load").remove();  
237 - tb_init("#TB_ajaxContent a.thickbox");  
238 - jQuery("#TB_window").css({display:"block"});  
239 - });  
240 - }  
241 -  
242 - }  
243 -  
244 - if(!params['modal']){  
245 - document.onkeyup = function(e){  
246 - if (e == null) { // ie  
247 - keycode = event.keyCode;  
248 - } else { // mozilla  
249 - keycode = e.which;  
250 - }  
251 - if(keycode == 27){ // close  
252 - tb_remove();  
253 - }  
254 - };  
255 - }  
256 -  
257 - } catch(e) {  
258 - //nothing here  
259 - }  
260 -}  
261 -  
262 -//helper functions below  
263 -function tb_showIframe(){  
264 - jQuery("#TB_load").remove();  
265 - jQuery("#TB_window").css({display:"block"});  
266 -}  
267 -  
268 -function tb_remove() {  
269 - jQuery("#TB_imageOff").unbind("click");  
270 - jQuery("#TB_closeWindowButton").unbind("click");  
271 - jQuery("#TB_window").fadeOut("fast",function(){jQuery('#TB_window,#TB_overlay,#TB_HideSelect').trigger("unload").unbind().remove();});  
272 - jQuery("#TB_load").remove();  
273 - if (typeof document.body.style.maxHeight == "undefined") {//if IE 6  
274 - jQuery("body","html").css({height: "auto", width: "auto"});  
275 - jQuery("html").css("overflow","");  
276 - }  
277 - document.onkeydown = "";  
278 - document.onkeyup = "";  
279 - return false;  
280 -}  
281 -  
282 -function tb_position() {  
283 -jQuery("#TB_window").css({marginLeft: '-' + parseInt((TB_WIDTH / 2),10) + 'px', width: TB_WIDTH + 'px'});  
284 - if ( !(jQuery.browser.msie && jQuery.browser.version < 7)) { // take away IE6  
285 - jQuery("#TB_window").css({marginTop: '-' + parseInt((TB_HEIGHT / 2),10) + 'px'});  
286 - }  
287 -}  
288 -  
289 -function tb_parseQuery ( query ) {  
290 - var Params = {};  
291 - if ( ! query ) {return Params;}// return empty object  
292 - var Pairs = query.split(/[;&]/);  
293 - for ( var i = 0; i < Pairs.length; i++ ) {  
294 - var KeyVal = Pairs[i].split('=');  
295 - if ( ! KeyVal || KeyVal.length != 2 ) {continue;}  
296 - var key = unescape( KeyVal[0] );  
297 - var val = unescape( KeyVal[1] );  
298 - val = val.replace(/\+/g, ' ');  
299 - Params[key] = val;  
300 - }  
301 - return Params;  
302 -}  
303 -  
304 -function tb_getPageSize(){  
305 - var de = document.documentElement;  
306 - var w = window.innerWidth || self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth;  
307 - var h = window.innerHeight || self.innerHeight || (de&&de.clientHeight) || document.body.clientHeight;  
308 - arrayPageSize = [w,h];  
309 - return arrayPageSize;  
310 -}  
311 -  
312 -function tb_detectMacXFF() {  
313 - var userAgent = navigator.userAgent.toLowerCase();  
314 - if (userAgent.indexOf('mac') != -1 && userAgent.indexOf('firefox')!=-1) {  
315 - return true;  
316 - }  
317 -}  
318 -  
319 -  
public/stylesheets/application.css
@@ -1901,17 +1901,6 @@ a.button.disabled, input.disabled { @@ -1901,17 +1901,6 @@ a.button.disabled, input.disabled {
1901 * Block options editor floating window * 1901 * Block options editor floating window *
1902 ****************************************/ 1902 ****************************************/
1903 1903
1904 -/* FIXME This changes broke colorboxes all over the place.  
1905 - * Therefore I'm canceling them until they are properly treateda. */  
1906 -#cboxLoadedContent {  
1907 - background: #FFF;  
1908 -/* box-shadow: 0 0 15px #888 inset;  
1909 - border-radius: 5px;  
1910 - border: 1px solid #777;  
1911 - border-left: none;  
1912 - border-right: none; */  
1913 -}  
1914 -  
1915 .block-config-options { 1904 .block-config-options {
1916 padding: 0px 10px 0px 30px; 1905 padding: 0px 10px 0px 30px;
1917 } 1906 }
public/stylesheets/colorbox.css
1 /* 1 /*
2 - ColorBox Core Style: 2 + Colorbox Core Style:
3 The following CSS is consistent between example themes and should not be altered. 3 The following CSS is consistent between example themes and should not be altered.
4 */ 4 */
5 #colorbox, #cboxOverlay, #cboxWrapper{position:absolute; top:0; left:0; z-index:9999; overflow:hidden;} 5 #colorbox, #cboxOverlay, #cboxWrapper{position:absolute; top:0; left:0; z-index:9999; overflow:hidden;}
  6 +#cboxWrapper {max-width:none;}
6 #cboxOverlay{position:fixed; width:100%; height:100%;} 7 #cboxOverlay{position:fixed; width:100%; height:100%;}
7 #cboxMiddleLeft, #cboxBottomLeft{clear:left;} 8 #cboxMiddleLeft, #cboxBottomLeft{clear:left;}
8 #cboxContent{position:relative;} 9 #cboxContent{position:relative;}
9 -#cboxLoadedContent{overflow:auto;} 10 +#cboxLoadedContent{overflow:auto; -webkit-overflow-scrolling: touch;}
10 #cboxTitle{margin:0;} 11 #cboxTitle{margin:0;}
11 -#cboxLoadingOverlay, #cboxLoadingGraphic{position:absolute; top:0; left:0; width:100%;} 12 +#cboxLoadingOverlay, #cboxLoadingGraphic{position:absolute; top:0; left:0; width:100%; height:100%;}
12 #cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{cursor:pointer;} 13 #cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{cursor:pointer;}
13 -.cboxPhoto{float:left; margin:auto; border:0; display:block;} 14 +.cboxPhoto{float:left; margin:auto; border:0; display:block; max-width:none; -ms-interpolation-mode:bicubic;}
14 .cboxIframe{width:100%; height:100%; display:block; border:0;} 15 .cboxIframe{width:100%; height:100%; display:block; border:0;}
  16 +#colorbox, #cboxContent, #cboxLoadedContent{box-sizing:content-box; -moz-box-sizing:content-box; -webkit-box-sizing:content-box;}
15 17
16 -/* 18 +/*
17 User Style: 19 User Style:
18 - Change the following styles to modify the appearance of ColorBox. They are 20 + Change the following styles to modify the appearance of Colorbox. They are
19 ordered & tabbed in a way that represents the nesting of the generated HTML. 21 ordered & tabbed in a way that represents the nesting of the generated HTML.
20 */ 22 */
21 #cboxOverlay{background:url(../images/colorbox/overlay.png) repeat 0 0;} 23 #cboxOverlay{background:url(../images/colorbox/overlay.png) repeat 0 0;}
22 -#colorbox{}  
23 - #cboxTopLeft{width:21px; height:21px; background:url(../images/colorbox/controls.png) no-repeat -100px 0;}  
24 - #cboxTopRight{width:21px; height:21px; background:url(../images/colorbox/controls.png) no-repeat -129px 0;}  
25 - #cboxBottomLeft{width:21px; height:21px; background:url(../images/colorbox/controls.png) no-repeat -100px -29px;}  
26 - #cboxBottomRight{width:21px; height:21px; background:url(../images/colorbox/controls.png) no-repeat -129px -29px;} 24 +#colorbox{outline:0;}
  25 + #cboxTopLeft{width:21px; height:21px; background:url(../images/colorbox/controls.png) no-repeat -101px 0;}
  26 + #cboxTopRight{width:21px; height:21px; background:url(../images/colorbox/controls.png) no-repeat -130px 0;}
  27 + #cboxBottomLeft{width:21px; height:21px; background:url(../images/colorbox/controls.png) no-repeat -101px -29px;}
  28 + #cboxBottomRight{width:21px; height:21px; background:url(../images/colorbox/controls.png) no-repeat -130px -29px;}
27 #cboxMiddleLeft{width:21px; background:url(../images/colorbox/controls.png) left top repeat-y;} 29 #cboxMiddleLeft{width:21px; background:url(../images/colorbox/controls.png) left top repeat-y;}
28 #cboxMiddleRight{width:21px; background:url(../images/colorbox/controls.png) right top repeat-y;} 30 #cboxMiddleRight{width:21px; background:url(../images/colorbox/controls.png) right top repeat-y;}
29 #cboxTopCenter{height:21px; background:url(../images/colorbox/border.png) 0 0 repeat-x;} 31 #cboxTopCenter{height:21px; background:url(../images/colorbox/border.png) 0 0 repeat-x;}
30 #cboxBottomCenter{height:21px; background:url(../images/colorbox/border.png) 0 -29px repeat-x;} 32 #cboxBottomCenter{height:21px; background:url(../images/colorbox/border.png) 0 -29px repeat-x;}
31 #cboxContent{background:#fff; overflow:hidden;} 33 #cboxContent{background:#fff; overflow:hidden;}
  34 + .cboxIframe{background:#fff;}
32 #cboxError{padding:50px; border:1px solid #ccc;} 35 #cboxError{padding:50px; border:1px solid #ccc;}
33 #cboxLoadedContent{margin-bottom:28px;} 36 #cboxLoadedContent{margin-bottom:28px;}
34 #cboxTitle{position:absolute; bottom:4px; left:0; text-align:center; width:100%; color:#949494;} 37 #cboxTitle{position:absolute; bottom:4px; left:0; text-align:center; width:100%; color:#949494;}
35 #cboxCurrent{position:absolute; bottom:4px; left:58px; color:#949494;} 38 #cboxCurrent{position:absolute; bottom:4px; left:58px; color:#949494;}
  39 + #cboxLoadingOverlay{background:url(../images/colorbox/loading_background.png) no-repeat center center;}
  40 + #cboxLoadingGraphic{background:url(../images/colorbox/loading.gif) no-repeat center center;}
  41 +
  42 + /* these elements are buttons, and may need to have additional styles reset to avoid unwanted base styles */
  43 + #cboxPrevious, #cboxNext, #cboxSlideshow, #cboxClose {border:0; padding:0; margin:0; overflow:visible; width:auto; background:none; }
  44 +
  45 + /* avoid outlines on :active (mouseclick), but preserve outlines on :focus (tabbed navigating) */
  46 + #cboxPrevious:active, #cboxNext:active, #cboxSlideshow:active, #cboxClose:active {outline:0;}
  47 +
36 #cboxSlideshow{position:absolute; bottom:4px; right:30px; color:#0092ef;} 48 #cboxSlideshow{position:absolute; bottom:4px; right:30px; color:#0092ef;}
37 #cboxPrevious{position:absolute; bottom:0; left:0; background:url(../images/colorbox/controls.png) no-repeat -75px 0; width:25px; height:25px; text-indent:-9999px;} 49 #cboxPrevious{position:absolute; bottom:0; left:0; background:url(../images/colorbox/controls.png) no-repeat -75px 0; width:25px; height:25px; text-indent:-9999px;}
38 - #cboxPrevious.hover{background-position:-75px -25px;} 50 + #cboxPrevious:hover{background-position:-75px -25px;}
39 #cboxNext{position:absolute; bottom:0; left:27px; background:url(../images/colorbox/controls.png) no-repeat -50px 0; width:25px; height:25px; text-indent:-9999px;} 51 #cboxNext{position:absolute; bottom:0; left:27px; background:url(../images/colorbox/controls.png) no-repeat -50px 0; width:25px; height:25px; text-indent:-9999px;}
40 - #cboxNext.hover{background-position:-50px -25px;}  
41 - #cboxLoadingOverlay{background:url(../images/colorbox/loading_background.png) no-repeat center center;}  
42 - #cboxLoadingGraphic{background:url(../images/colorbox/loading.gif) no-repeat center center;} 52 + #cboxNext:hover{background-position:-50px -25px;}
43 #cboxClose{position:absolute; bottom:0; right:0; background:url(../images/colorbox/controls.png) no-repeat -25px 0; width:25px; height:25px; text-indent:-9999px;} 53 #cboxClose{position:absolute; bottom:0; right:0; background:url(../images/colorbox/controls.png) no-repeat -25px 0; width:25px; height:25px; text-indent:-9999px;}
44 - #cboxClose.hover{background-position:-25px -25px;} 54 + #cboxClose:hover{background-position:-25px -25px;}
45 55
46 /* 56 /*
47 - The following fixes a problem where IE7+ replaces a PNG's alpha transparency with a black fill  
48 - when an alpha filter (opacity change) is set on the element or ancestor element. 57 + The following fixes a problem where IE7 and IE8 replace a PNG's alpha transparency with a black fill
  58 + when an alpha filter (opacity change) is set on the element or ancestor element. This style is not applied to or needed in IE9.
  59 + See: http://jacklmoore.com/notes/ie-transparency-problems/
49 */ 60 */
50 .cboxIE #cboxTopLeft, 61 .cboxIE #cboxTopLeft,
51 .cboxIE #cboxTopCenter, 62 .cboxIE #cboxTopCenter,
@@ -57,26 +68,3 @@ @@ -57,26 +68,3 @@
57 .cboxIE #cboxMiddleRight { 68 .cboxIE #cboxMiddleRight {
58 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#00FFFFFF,endColorstr=#00FFFFFF); 69 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#00FFFFFF,endColorstr=#00FFFFFF);
59 } 70 }
60 -  
61 -/*  
62 - The following provides PNG transparency support for IE6  
63 -*/  
64 -.cboxIE6 #cboxTopLeft{background:url(../images/colorbox/ie6/borderTopLeft.png);}  
65 -.cboxIE6 #cboxTopCenter{background:url(../images/colorbox/ie6/borderTopCenter.png);}  
66 -.cboxIE6 #cboxTopRight{background:url(../images/colorbox/ie6/borderTopRight.png);}  
67 -.cboxIE6 #cboxBottomLeft{background:url(../images/colorbox/ie6/borderBottomLeft.png);}  
68 -.cboxIE6 #cboxBottomCenter{background:url(../images/colorbox/ie6/borderBottomCenter.png);}  
69 -.cboxIE6 #cboxBottomRight{background:url(../images/colorbox/ie6/borderBottomRight.png);}  
70 -.cboxIE6 #cboxMiddleLeft{background:url(../images/colorbox/ie6/borderMiddleLeft.png);}  
71 -.cboxIE6 #cboxMiddleRight{background:url(../images/colorbox/ie6/borderMiddleRight.png);}  
72 -  
73 -.cboxIE6 #cboxTopLeft,  
74 -.cboxIE6 #cboxTopCenter,  
75 -.cboxIE6 #cboxTopRight,  
76 -.cboxIE6 #cboxBottomLeft,  
77 -.cboxIE6 #cboxBottomCenter,  
78 -.cboxIE6 #cboxBottomRight,  
79 -.cboxIE6 #cboxMiddleLeft,  
80 -.cboxIE6 #cboxMiddleRight {  
81 - _behavior: expression(this.src = this.src ? this.src : this.currentStyle.backgroundImage.split('"')[1], this.style.background = "none", this.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src=" + this.src + ", sizingMethod='scale')");  
82 -}  
public/stylesheets/lightbox.css
@@ -1,63 +0,0 @@ @@ -1,63 +0,0 @@
1 -/* - - - - - - - - - - - - - - - - - - - - -  
2 -  
3 -Title : Lightbox CSS  
4 -Author : Kevin Hale  
5 -URL : http://particletree.com/features/lightbox-gone-wild/  
6 -  
7 -Created : January 13, 2006  
8 -Modified : February 1, 2006  
9 -  
10 -- - - - - - - - - - - - - - - - - - - - - */  
11 -  
12 -#lightbox {  
13 - display: none;  
14 - position: absolute;  
15 - top: 150px;  
16 - left: 50%;  
17 - z-index: 300;  
18 - width: 500px;  
19 - margin-left: -265px;  
20 - border: 1px solid #000;  
21 - text-align: left;  
22 - padding: 1em;  
23 - background: #FFF;  
24 -}  
25 -  
26 -#overlay{  
27 - display:none;  
28 - position:absolute;  
29 - top:0;  
30 - left:0;  
31 - width:100%;  
32 - height:100%;  
33 - z-index:200;  
34 - background-color:#000;  
35 - -moz-opacity: 0.75;  
36 - opacity:.75;  
37 - filter: alpha(opacity=75);  
38 -}  
39 -#overlay[id]{  
40 - position:fixed;  
41 -}  
42 -  
43 -#lightbox.done #lbLoadMessage{  
44 - display:none;  
45 -}  
46 -#lightbox.done #lbContent{  
47 - display:block;  
48 -}  
49 -#lightbox.loading #lbContent{  
50 - display:none;  
51 -}  
52 -#lightbox.loading #lbLoadMessage{  
53 - display:block;  
54 -}  
55 -  
56 -#lightbox.done img{  
57 - width:100%;  
58 - height:100%;  
59 -}  
60 -  
61 -#lightbox select {  
62 - max-width: 100%;  
63 -}  
public/stylesheets/thickbox.css
@@ -1,163 +0,0 @@ @@ -1,163 +0,0 @@
1 -/* ----------------------------------------------------------------------------------------------------------------*/  
2 -/* ---------->>> global settings needed for thickbox <<<-----------------------------------------------------------*/  
3 -/* ----------------------------------------------------------------------------------------------------------------*/  
4 -/**{padding: 0; margin: 0;}*/  
5 -  
6 -/* ----------------------------------------------------------------------------------------------------------------*/  
7 -/* ---------->>> thickbox specific link and font settings <<<------------------------------------------------------*/  
8 -/* ----------------------------------------------------------------------------------------------------------------*/  
9 -#TB_window {  
10 - font: 12px Arial, Helvetica, sans-serif;  
11 - color: #333333;  
12 -}  
13 -  
14 -#TB_secondLine {  
15 - font: 10px Arial, Helvetica, sans-serif;  
16 - color:#666666;  
17 -}  
18 -  
19 -#TB_window a:link {color: #666666;}  
20 -#TB_window a:visited {color: #666666;}  
21 -#TB_window a:hover {color: #000;}  
22 -#TB_window a:active {color: #666666;}  
23 -#TB_window a:focus{color: #666666;}  
24 -  
25 -/* ----------------------------------------------------------------------------------------------------------------*/  
26 -/* ---------->>> thickbox settings <<<-----------------------------------------------------------------------------*/  
27 -/* ----------------------------------------------------------------------------------------------------------------*/  
28 -#TB_overlay {  
29 - position: fixed;  
30 - z-index:200;  
31 - top: 0px;  
32 - left: 0px;  
33 - height:100%;  
34 - width:100%;  
35 -}  
36 -  
37 -.TB_overlayMacFFBGHack {background: url(macFFBgHack.png) repeat;}  
38 -.TB_overlayBG {  
39 - background-color:#000;  
40 - filter:alpha(opacity=75);  
41 - -moz-opacity: 0.75;  
42 - opacity: 0.75;  
43 -}  
44 -  
45 -* html #TB_overlay { /* ie6 hack */  
46 - position: absolute;  
47 - height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px');  
48 -}  
49 -  
50 -#TB_window {  
51 - position: fixed;  
52 - background: white;  
53 - z-index: 202;  
54 - color:#000000;  
55 - display:none;  
56 - border: 1px solid #000;  
57 - text-align:left;  
58 - top:50%;  
59 - left:50%;  
60 -}  
61 -  
62 -* html #TB_window { /* ie6 hack */  
63 -position: absolute;  
64 -margin-top: expression(0 - parseInt(this.offsetHeight / 2) + (TBWindowMargin = document.documentElement && document.documentElement.scrollTop || document.body.scrollTop) + 'px');  
65 -}  
66 -  
67 -#TB_window img#TB_Image {  
68 - display:block;  
69 - margin: 15px 0 0 15px;  
70 - border-right: 1px solid #ccc;  
71 - border-bottom: 1px solid #ccc;  
72 - border-top: 1px solid #666;  
73 - border-left: 1px solid #666;  
74 -}  
75 -  
76 -#TB_caption{  
77 - height:25px;  
78 - padding:7px 30px 10px 25px;  
79 - float:left;  
80 -}  
81 -  
82 -#TB_closeWindow{  
83 - height:25px;  
84 - padding:11px 25px 10px 0;  
85 - float:right;  
86 -}  
87 -  
88 -#TB_closeAjaxWindow{  
89 - padding:7px 10px 5px 0;  
90 - margin-bottom:1px;  
91 - text-align:right;  
92 - float:right;  
93 -}  
94 -  
95 -#TB_ajaxWindowTitle{  
96 - float:left;  
97 - padding:7px 0 5px 10px;  
98 - margin-bottom:1px;  
99 -}  
100 -  
101 -#TB_title{  
102 - background-color:#e8e8e8;  
103 - height:27px;  
104 -}  
105 -  
106 -#TB_ajaxContent{  
107 - clear:both;  
108 - padding:2px 15px 15px 15px;  
109 - overflow:auto;  
110 - text-align:left;  
111 - line-height:1.4em;  
112 -}  
113 -  
114 -#TB_ajaxContent.TB_modal{  
115 - padding:15px;  
116 -}  
117 -  
118 -#TB_ajaxContent p{  
119 - padding:5px 0px 5px 0px;  
120 -}  
121 -  
122 -#TB_load{  
123 - position: fixed;  
124 - display:none;  
125 - height:13px;  
126 - width:208px;  
127 - z-index:203;  
128 - top: 50%;  
129 - left: 50%;  
130 - margin: -6px 0 0 -104px; /* -height/2 0 0 -width/2 */  
131 -}  
132 -  
133 -* html #TB_load { /* ie6 hack */  
134 -position: absolute;  
135 -margin-top: expression(0 - parseInt(this.offsetHeight / 2) + (TBWindowMargin = document.documentElement && document.documentElement.scrollTop || document.body.scrollTop) + 'px');  
136 -}  
137 -  
138 -#TB_HideSelect{  
139 - z-index:199;  
140 - position:fixed;  
141 - top: 0;  
142 - left: 0;  
143 - background-color:#fff;  
144 - border:none;  
145 - filter:alpha(opacity=0);  
146 - -moz-opacity: 0;  
147 - opacity: 0;  
148 - height:100%;  
149 - width:100%;  
150 -}  
151 -  
152 -* html #TB_HideSelect { /* ie6 hack */  
153 - position: absolute;  
154 - height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px');  
155 -}  
156 -  
157 -#TB_iframeContent{  
158 - clear:both;  
159 - border:none;  
160 - margin-bottom:-1px;  
161 - margin-top:1px;  
162 - _margin-bottom:1px;  
163 -}  
script/gitlab-ci 0 → 100755
@@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
  1 +#!/usr/bin/env ruby
  2 +
  3 +# These just forward the signals to the whole process group and
  4 +# then immediately exit.
  5 +pgid = Process.getpgid Process.pid
  6 +Signal.trap(:TERM) { Process.kill(:TERM, -pgid); exit }
  7 +Signal.trap(:INT) { Process.kill(:INT, -pgid); exit }
  8 +
  9 +def run command, options = {}
  10 + command = "#{command} 2>&1 > /dev/null" if options[:output] == false
  11 + #command = "time #{command}" unless options[:runtime] == false
  12 + puts "== #{command}"
  13 + system command
  14 +end
  15 +
  16 +@id = (0...10).map{ ('a'..'z').to_a[rand(26)] }.join
  17 +@db = "gitlab-ci-#{@id}"
  18 +
  19 +def config
  20 + require 'yaml'
  21 + db_config = {
  22 + 'adapter' => 'postgresql', 'encoding' => 'unicode',
  23 + 'database' => @db, 'username' => ENV['USER'],
  24 + }
  25 + File.write 'config/database.yml', YAML.dump('test' => db_config, 'development' => db_config)
  26 +end
  27 +
  28 +def prepare
  29 + run("createdb #{@db}") and
  30 + run('mkdir -p tmp/pids log') and
  31 + run('bundle check || bundle install') and
  32 + run('rake db:schema:load', output: false) and
  33 + run('script/noosfero-plugins disableall') and
  34 + run('rake db:migrate')
  35 +end
  36 +
  37 +def test
  38 + %w[
  39 + test:units
  40 + test:functionals
  41 + test:integration
  42 + cucumber
  43 + test:noosfero_plugins
  44 + ].each do |task|
  45 + run "rake #{task}"
  46 + end
  47 +end
  48 +
  49 +def cleanup
  50 + run "dropdb #{@db}"
  51 +end
  52 +
  53 +ret = config and prepare and test
  54 +cleanup
  55 +
  56 +exit (if ret == true then 0 else 1 end)
script/install-dependencies/debian-squeeze.sh
@@ -5,7 +5,7 @@ run sudo apt-get -y install $runtime_dependencies @@ -5,7 +5,7 @@ run sudo apt-get -y install $runtime_dependencies
5 sudo apt-get -y install iceweasel || sudo apt-get -y install firefox 5 sudo apt-get -y install iceweasel || sudo apt-get -y install firefox
6 6
7 # needed for development 7 # needed for development
8 -run sudo apt-get -y install libtidy-ruby libhpricot-ruby libmocha-ruby imagemagick po4a xvfb libxml2-dev libxslt-dev postgresql openjdk-6-jre 8 +run sudo apt-get -y install libtidy-ruby libmocha-ruby imagemagick po4a xvfb libxml2-dev libxslt-dev postgresql openjdk-6-jre
9 gem which bundler >/dev/null 2>&1 || gem_install bundler 9 gem which bundler >/dev/null 2>&1 || gem_install bundler
10 setup_rubygems_path 10 setup_rubygems_path
11 run bundle install 11 run bundle install
test/functional/account_controller_test.rb
@@ -818,17 +818,17 @@ class AccountControllerTest &lt; ActionController::TestCase @@ -818,17 +818,17 @@ class AccountControllerTest &lt; ActionController::TestCase
818 end 818 end
819 819
820 should 'login with an alternative authentication defined by plugin' do 820 should 'login with an alternative authentication defined by plugin' do
  821 + user = create_user
821 class Plugin1 < Noosfero::Plugin 822 class Plugin1 < Noosfero::Plugin
822 - def alternative_authentication  
823 - User.new(:login => 'testuser')  
824 - end  
825 end 823 end
  824 + Plugin1.send(:define_method, :alternative_authentication){ user }
  825 +
826 Noosfero::Plugin.stubs(:all).returns([Plugin1.name]) 826 Noosfero::Plugin.stubs(:all).returns([Plugin1.name])
827 Environment.default.enable_plugin(Plugin1.name) 827 Environment.default.enable_plugin(Plugin1.name)
828 828
829 post :login, :user => {:login => "testuser"} 829 post :login, :user => {:login => "testuser"}
830 830
831 - assert_equal 'testuser', assigns(:current_user).login 831 + assert_equal user.login, assigns(:current_user).login
832 assert_response :redirect 832 assert_response :redirect
833 end 833 end
834 834
test/functional/chat_controller_test.rb
@@ -6,18 +6,20 @@ class ChatControllerTest &lt; ActionController::TestCase @@ -6,18 +6,20 @@ class ChatControllerTest &lt; ActionController::TestCase
6 env = Environment.default 6 env = Environment.default
7 env.enable('xmpp_chat') 7 env.enable('xmpp_chat')
8 env.save! 8 env.save!
  9 + #TODO Maybe someday we should have a real testing ejabberd server
  10 + RubyBOSH.stubs(:initialize_session).returns(['fake-jid@example.org', 'fake-sid', 'fake-rid'])
9 @person = create_user('testuser').person 11 @person = create_user('testuser').person
10 end 12 end
11 13
12 should 'cant view chat when not logged in' do 14 should 'cant view chat when not logged in' do
13 - get :index 15 + get :start_session
14 assert_response 302 16 assert_response 302
15 end 17 end
16 18
17 should 'can view chat when logged in' do 19 should 'can view chat when logged in' do
18 login_as 'testuser' 20 login_as 'testuser'
19 21
20 - get :index 22 + get :start_session
21 assert_response :success 23 assert_response :success
22 end 24 end
23 25
@@ -39,29 +41,6 @@ class ChatControllerTest &lt; ActionController::TestCase @@ -39,29 +41,6 @@ class ChatControllerTest &lt; ActionController::TestCase
39 assert @response.body.index('PNG') 41 assert @response.body.index('PNG')
40 end 42 end
41 43
42 - should 'auto connect if last presence status is blank' do  
43 - login_as 'testuser'  
44 -  
45 - get :index  
46 - assert_template 'auto_connect_online'  
47 - end  
48 -  
49 - should 'auto connect if there last presence status was chat' do  
50 - create_user('testuser_online', :last_chat_status => 'chat')  
51 - login_as 'testuser_online'  
52 -  
53 - get :index  
54 - assert_template 'auto_connect_online'  
55 - end  
56 -  
57 - should 'auto connect busy if last presence status was dnd' do  
58 - create_user('testuser_busy', :last_chat_status => 'dnd')  
59 - login_as 'testuser_busy'  
60 -  
61 - get :index  
62 - assert_template 'auto_connect_busy'  
63 - end  
64 -  
65 begin 44 begin
66 require 'ruby_bosh' 45 require 'ruby_bosh'
67 should 'try to start xmpp session' do 46 should 'try to start xmpp session' do
@@ -87,7 +66,7 @@ class ChatControllerTest &lt; ActionController::TestCase @@ -87,7 +66,7 @@ class ChatControllerTest &lt; ActionController::TestCase
87 env.disable('xmpp_chat') 66 env.disable('xmpp_chat')
88 env.save! 67 env.save!
89 68
90 - get :index 69 + get :start_session
91 70
92 assert_response 404 71 assert_response 404
93 assert_template 'not_found' 72 assert_template 'not_found'
@@ -116,4 +95,67 @@ class ChatControllerTest &lt; ActionController::TestCase @@ -116,4 +95,67 @@ class ChatControllerTest &lt; ActionController::TestCase
116 assert_not_equal chat_status_at, @person.user.chat_status_at 95 assert_not_equal chat_status_at, @person.user.chat_status_at
117 end 96 end
118 97
  98 + should 'toggle chat status' do
  99 + login_as 'testuser'
  100 +
  101 + get :start_session
  102 + assert_nil session[:chat][:status]
  103 +
  104 + get :toggle
  105 + assert_equal 'opened', session[:chat][:status]
  106 +
  107 + get :toggle
  108 + assert_equal 'closed', session[:chat][:status]
  109 +
  110 + get :toggle
  111 + assert_equal 'opened', session[:chat][:status]
  112 + end
  113 +
  114 + should 'set tab' do
  115 + login_as 'testuser'
  116 + get :start_session
  117 +
  118 + post :tab, :tab_id => 'my_tab'
  119 + assert_equal 'my_tab', session[:chat][:tab_id]
  120 + end
  121 +
  122 + should 'join room' do
  123 + login_as 'testuser'
  124 + get :start_session
  125 +
  126 + post :join, :room_id => 'room1'
  127 + assert_equivalent ['room1'], session[:chat][:rooms]
  128 +
  129 + post :join, :room_id => 'room2'
  130 + assert_equivalent ['room1', 'room2'], session[:chat][:rooms]
  131 +
  132 + post :join, :room_id => 'room1'
  133 + assert_equivalent ['room1', 'room2'], session[:chat][:rooms]
  134 + end
  135 +
  136 + should 'leave room' do
  137 + login_as 'testuser'
  138 + get :start_session
  139 + session[:chat][:rooms] = ['room1', 'room2']
  140 +
  141 + post :leave, :room_id => 'room2'
  142 + assert_equivalent ['room1'], session[:chat][:rooms]
  143 +
  144 + post :leave, :room_id => 'room1'
  145 + assert_equivalent [], session[:chat][:rooms]
  146 +
  147 + post :leave, :room_id => 'room1'
  148 + assert_equivalent [], session[:chat][:rooms]
  149 + end
  150 +
  151 + should 'fetch chat session as json' do
  152 + login_as 'testuser'
  153 + get :start_session
  154 + my_chat = {:status => 'opened', :rooms => ['room1', 'room2'], :tab_id => 'room1'}
  155 + session[:chat] = my_chat
  156 +
  157 + get :my_session
  158 + assert_equal @response.body, my_chat.to_json
  159 + end
  160 +
119 end 161 end
test/functional/cms_controller_test.rb
@@ -638,7 +638,7 @@ class CmsControllerTest &lt; ActionController::TestCase @@ -638,7 +638,7 @@ class CmsControllerTest &lt; ActionController::TestCase
638 638
639 should 'display OK button on why_categorize popup' do 639 should 'display OK button on why_categorize popup' do
640 get :why_categorize, :profile => profile.identifier 640 get :why_categorize, :profile => profile.identifier
641 - assert_tag :tag => 'a', :attributes => { :rel => 'deactivate'} # lightbox close button 641 + assert_tag :tag => 'a', :attributes => { :rel => 'deactivate'} # modal close button
642 end 642 end
643 643
644 should 'display published option' do 644 should 'display published option' do
@@ -663,8 +663,8 @@ class CmsControllerTest &lt; ActionController::TestCase @@ -663,8 +663,8 @@ class CmsControllerTest &lt; ActionController::TestCase
663 should 'be able to add image with alignment' do 663 should 'be able to add image with alignment' do
664 post :new, :type => 'TinyMceArticle', :profile => profile.identifier, :article => { :name => 'image-alignment', :body => "the text of the article with image <img src='#' align='right'/> right align..." } 664 post :new, :type => 'TinyMceArticle', :profile => profile.identifier, :article => { :name => 'image-alignment', :body => "the text of the article with image <img src='#' align='right'/> right align..." }
665 saved = TinyMceArticle.find_by_name('image-alignment') 665 saved = TinyMceArticle.find_by_name('image-alignment')
666 - assert_match /<img.*src="#".*\/>/, saved.body  
667 - assert_match /<img.*align="right".*\/>/, saved.body 666 + assert_match /<img.*src="#".*>/, saved.body
  667 + assert_match /<img.*align="right".*>/, saved.body
668 end 668 end
669 669
670 should 'be able to add image with alignment when textile' do 670 should 'be able to add image with alignment when textile' do
test/functional/profile_editor_controller_test.rb
@@ -500,7 +500,7 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase @@ -500,7 +500,7 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase
500 xhr :get, :update_categories, :profile => profile.identifier, :category_id => top.id 500 xhr :get, :update_categories, :profile => profile.identifier, :category_id => top.id
501 assert_template 'shared/update_categories' 501 assert_template 'shared/update_categories'
502 assert_equal top, assigns(:current_category) 502 assert_equal top, assigns(:current_category)
503 - assert_equal [c1, c2], assigns(:categories) 503 + assert_equivalent [c1, c2], assigns(:categories)
504 end 504 end
505 505
506 should 'display manage my groups button for person' do 506 should 'display manage my groups button for person' do
test/test_helper.rb
@@ -3,7 +3,6 @@ ENV[&quot;RAILS_ENV&quot;] = &quot;test&quot; @@ -3,7 +3,6 @@ ENV[&quot;RAILS_ENV&quot;] = &quot;test&quot;
3 require File.expand_path(File.dirname(__FILE__) + "/../config/environment") 3 require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
4 require 'rails/test_help' 4 require 'rails/test_help'
5 require 'mocha' 5 require 'mocha'
6 -require 'hpricot'  
7 6
8 require 'noosfero/test' 7 require 'noosfero/test'
9 require 'authenticated_test_helper' 8 require 'authenticated_test_helper'
test/unit/application_helper_test.rb
@@ -261,7 +261,7 @@ class ApplicationHelperTest &lt; ActionView::TestCase @@ -261,7 +261,7 @@ class ApplicationHelperTest &lt; ActionView::TestCase
261 fast_create(Community, :is_template => true, :environment_id => environment.id) 261 fast_create(Community, :is_template => true, :environment_id => environment.id)
262 environment.community_default_template= community 262 environment.community_default_template= community
263 environment.save 263 environment.save
264 - 264 +
265 assert_tag_in_string template_options(:communities, 'community'), :tag => 'input', 265 assert_tag_in_string template_options(:communities, 'community'), :tag => 'input',
266 :attributes => { :name => "community[template_id]", :value => community.id, :checked => true } 266 :attributes => { :name => "community[template_id]", :value => community.id, :checked => true }
267 end 267 end
@@ -273,7 +273,7 @@ class ApplicationHelperTest &lt; ActionView::TestCase @@ -273,7 +273,7 @@ class ApplicationHelperTest &lt; ActionView::TestCase
273 fast_create(Person, :is_template => true, :environment_id => environment.id) 273 fast_create(Person, :is_template => true, :environment_id => environment.id)
274 environment.person_default_template= person 274 environment.person_default_template= person
275 environment.save 275 environment.save
276 - 276 +
277 assert_tag_in_string template_options(:people, 'profile_data'), :tag => 'input', 277 assert_tag_in_string template_options(:people, 'profile_data'), :tag => 'input',
278 :attributes => { :name => "profile_data[template_id]", :value => person.id, :checked => true } 278 :attributes => { :name => "profile_data[template_id]", :value => person.id, :checked => true }
279 end 279 end
@@ -287,7 +287,7 @@ class ApplicationHelperTest &lt; ActionView::TestCase @@ -287,7 +287,7 @@ class ApplicationHelperTest &lt; ActionView::TestCase
287 environment.enterprise_default_template= enterprise 287 environment.enterprise_default_template= enterprise
288 environment.save 288 environment.save
289 environment.reload 289 environment.reload
290 - 290 +
291 assert_tag_in_string template_options(:enterprises, 'create_enterprise'), :tag => 'input', 291 assert_tag_in_string template_options(:enterprises, 'create_enterprise'), :tag => 'input',
292 :attributes => { :name => "create_enterprise[template_id]", :value => enterprise.id, :checked => true } 292 :attributes => { :name => "create_enterprise[template_id]", :value => enterprise.id, :checked => true }
293 end 293 end
@@ -734,16 +734,16 @@ class ApplicationHelperTest &lt; ActionView::TestCase @@ -734,16 +734,16 @@ class ApplicationHelperTest &lt; ActionView::TestCase
734 <div class='macro nonEdit' data-macro='unexistent' data-macro-param='987'></div> 734 <div class='macro nonEdit' data-macro='unexistent' data-macro-param='987'></div>
735 " 735 "
736 parsed_html = convert_macro(html, mock()) 736 parsed_html = convert_macro(html, mock())
737 - parsed_divs = Hpricot(parsed_html).search('div')  
738 - expected_divs = Hpricot("  
739 - <div data-macro='#{macro1_name}' class='parsed-macro #{macro1_name}'>Test1</div>  
740 - <div data-macro='#{macro2_name}' class='parsed-macro #{macro2_name}'>Test2</div> 737 + parsed_divs = Nokogiri::HTML.fragment(parsed_html).css('div')
  738 + expected_divs = Nokogiri::HTML.fragment("
  739 + <div class='parsed-macro #{macro1_name}' data-macro='#{macro1_name}'>Test1</div>
  740 + <div class='parsed-macro #{macro2_name}' data-macro='#{macro2_name}'>Test2</div>
741 <div data-macro='unexistent' class='failed-macro unexistent'>Unsupported macro unexistent!</div> 741 <div data-macro='unexistent' class='failed-macro unexistent'>Unsupported macro unexistent!</div>
742 - ").search('div') 742 + ").css('div')
743 743
744 # comparing div attributes between parsed and expected html 744 # comparing div attributes between parsed and expected html
745 parsed_divs.each_with_index do |div, i| 745 parsed_divs.each_with_index do |div, i|
746 - assert_equal expected_divs[i].attributes.to_hash, div.attributes.to_hash 746 + assert_equal expected_divs[i].attributes.to_xml, div.attributes.to_xml
747 assert_equal expected_divs[i].inner_text, div.inner_text 747 assert_equal expected_divs[i].inner_text, div.inner_text
748 end 748 end
749 end 749 end
test/unit/colorbox_helper_test.rb
@@ -1,36 +0,0 @@ @@ -1,36 +0,0 @@
1 -require_relative "../test_helper"  
2 -  
3 -class ColorboxHelperTest < ActiveSupport::TestCase  
4 -  
5 - include ColorboxHelper  
6 -  
7 - should 'provide the needed files' do  
8 - assert File.exists?(Rails.root.join('public', 'stylesheets', 'colorbox.css')), 'colorbox.css expected to be in public/stylesheets, but not found'  
9 - assert File.exists?(Rails.root.join('public', 'javascripts', 'colorbox.js')), 'colorbox.js expected to be in public/javascripts, but not found'  
10 - end  
11 -  
12 - should 'provide link to close colorbox' do  
13 - expects(:button).with(:close, 'text', '#', has_entries({ :class => 'colorbox-close', :id => 'my-id' })).returns('[close-colorbox]')  
14 -  
15 - assert_equal '[close-colorbox]', colorbox_close_button('text', :id => 'my-id')  
16 - end  
17 -  
18 - should 'merge existing :class option in colorbox_close_button' do  
19 - expects(:button).with(:close, 'text', '#', has_entries({ :class => 'colorbox-close my-class', :id => 'my-id' })).returns('[close-colorbox]')  
20 -  
21 - assert_equal '[close-colorbox]', colorbox_close_button('text', :class => 'my-class', :id => 'my-id' )  
22 - end  
23 -  
24 - should 'provide colorbox_button' do  
25 - expects(:button).with('type', 'label', { :action => 'popup'}, has_entries({ :class => 'colorbox' })).returns('[button]')  
26 -  
27 - assert_equal '[button]', colorbox_button('type', 'label', { :action => 'popup'})  
28 - end  
29 -  
30 - should 'provide colorbox_icon_button' do  
31 - expects(:icon_button).with('type', 'label', { :action => 'popup'}, has_entries({ :class => 'colorbox' })).returns('[button]')  
32 -  
33 - assert_equal '[button]', colorbox_icon_button('type', 'label', { :action => 'popup'})  
34 - end  
35 -  
36 -end  
test/unit/comment_helper_test.rb
@@ -137,7 +137,7 @@ class CommentHelperTest &lt; ActiveSupport::TestCase @@ -137,7 +137,7 @@ class CommentHelperTest &lt; ActiveSupport::TestCase
137 plugin_action = {:link => 'plugin_action', :action_bar => true} 137 plugin_action = {:link => 'plugin_action', :action_bar => true}
138 @plugins.stubs(:dispatch).returns([plugin_action]) 138 @plugins.stubs(:dispatch).returns([plugin_action])
139 html = comment_actions(comment) 139 html = comment_actions(comment)
140 - assert_match /plugin_action/, Hpricot(html).search('.comments-action-bar').html 140 + assert_match /plugin_action/, Nokogiri::HTML.fragment(html).css('.comments-action-bar').to_html
141 end 141 end
142 142
143 def link_to_function(content, url, options = {}) 143 def link_to_function(content, url, options = {})
test/unit/external_feed_test.rb
@@ -18,7 +18,8 @@ class ExternalFeedTest &lt; ActiveSupport::TestCase @@ -18,7 +18,8 @@ class ExternalFeedTest &lt; ActiveSupport::TestCase
18 end 18 end
19 19
20 should 'not add same item twice' do 20 should 'not add same item twice' do
21 - e = create(:external_feed) 21 + blog = create_blog
  22 + e = create(:external_feed, blog: blog)
22 assert e.add_item('Article title', 'http://orig.link.invalid', Time.now, 'Content for external post') 23 assert e.add_item('Article title', 'http://orig.link.invalid', Time.now, 'Content for external post')
23 assert !e.add_item('Article title', 'http://orig.link.invalid', Time.now, 'Content for external post') 24 assert !e.add_item('Article title', 'http://orig.link.invalid', Time.now, 'Content for external post')
24 assert_equal 1, e.blog.posts.size 25 assert_equal 1, e.blog.posts.size
@@ -52,7 +53,8 @@ class ExternalFeedTest &lt; ActiveSupport::TestCase @@ -52,7 +53,8 @@ class ExternalFeedTest &lt; ActiveSupport::TestCase
52 53
53 should 'add items to blog as posts' do 54 should 'add items to blog as posts' do
54 handler = FeedHandler.new 55 handler = FeedHandler.new
55 - e = create(:external_feed) 56 + blog = create_blog
  57 + e = create(:external_feed, blog: blog)
56 handler.process(e) 58 handler.process(e)
57 assert_equal ["Last POST", "Second POST", "First POST"], e.blog.posts.map{|i| i.title} 59 assert_equal ["Last POST", "Second POST", "First POST"], e.blog.posts.map{|i| i.title}
58 end 60 end
@@ -164,7 +166,7 @@ class ExternalFeedTest &lt; ActiveSupport::TestCase @@ -164,7 +166,7 @@ class ExternalFeedTest &lt; ActiveSupport::TestCase
164 next if a.kind_of?(RssFeed) 166 next if a.kind_of?(RssFeed)
165 dd << a.body.to_s.strip.gsub(/\s+/, ' ') 167 dd << a.body.to_s.strip.gsub(/\s+/, ' ')
166 end 168 end
167 - assert_equal '<img src="noosfero.png" /><p>Html content 1.</p><p>Html content 2.</p>', dd.sort.join 169 + assert_equal '<img src="noosfero.png"><p>Html content 1.</p><p>Html content 2.</p>', dd.sort.join
168 end 170 end
169 171
170 should 'use feed title as author name' do 172 should 'use feed title as author name' do
test/unit/lightbox_helper_test.rb
@@ -1,65 +0,0 @@ @@ -1,65 +0,0 @@
1 -require_relative "../test_helper"  
2 -  
3 -class LightboxHelperTest < ActiveSupport::TestCase  
4 -  
5 - include LightboxHelper  
6 -  
7 - def setup  
8 - stubs(:_).with(anything).returns('TEXT')  
9 - end  
10 -  
11 - should 'provide the needed files' do  
12 - assert File.exists?(Rails.root.join('public', 'stylesheets', 'lightbox.css')), 'lightbox.css expected to be in public/stylesheets, but not found'  
13 - assert File.exists?(Rails.root.join('public', 'javascripts', 'lightbox.js')), 'lightbox.js expected to be in public/javascripts, but not found'  
14 - end  
15 -  
16 - should 'provide lightbox_link_to helper' do  
17 - expects(:link_to).with('text', { :action => 'view', :id => '1' }, has_entries({ :class => 'lbOn', :id => 'my-link' })).returns('[link]')  
18 - assert_equal '[link]', lightbox_link_to('text', { :action => 'view', :id => '1'}, { :id => 'my-link' })  
19 - end  
20 -  
21 - should 'merge existing :class option in lightbox_link_to' do  
22 - expects(:link_to).with('text', { :action => 'view', :id => '1' }, has_entries({ :class => 'lbOn my-button', :id => 'my-link' })).returns('[link]')  
23 - assert_equal '[link]', lightbox_link_to('text', { :action => 'view', :id => '1'}, { :class => 'my-button', :id => 'my-link' })  
24 -  
25 - end  
26 -  
27 - should 'provide link to close lightbox' do  
28 - expects(:button).with(:close, 'text', '#', has_entries({ :class => 'lbAction', :rel => 'deactivate', :id => 'my-id' })).returns('[close-lightbox]')  
29 -  
30 - assert_equal '[close-lightbox]', lightbox_close_button('text', :id => 'my-id')  
31 - end  
32 -  
33 - should 'merge existing :class option in lightbox_close_button' do  
34 - expects(:button).with(:close, 'text', '#', has_entries({ :class => 'lbAction my-class', :rel => 'deactivate', :id => 'my-id' })).returns('[close-lightbox]')  
35 -  
36 - assert_equal '[close-lightbox]', lightbox_close_button('text', :class => 'my-class', :id => 'my-id' )  
37 - end  
38 -  
39 - should 'provide lightbox_button' do  
40 - expects(:button).with('type', 'label', { :action => 'popup'}, has_entries({ :class => 'lbOn' })).returns('[button]')  
41 -  
42 - assert_equal '[button]', lightbox_button('type', 'label', { :action => 'popup'})  
43 - end  
44 -  
45 - should 'provide lightbox_icon_button' do  
46 - expects(:icon_button).with('type', 'label', { :action => 'popup'}, has_entries({ :class => 'lbOn' })).returns('[button]')  
47 -  
48 - assert_equal '[button]', lightbox_icon_button('type', 'label', { :action => 'popup'})  
49 - end  
50 -  
51 - should 'tell if rendering inside lightbox' do  
52 - request = mock  
53 - expects(:request).returns(request)  
54 - request.expects(:xhr?).returns(true)  
55 -  
56 - assert lightbox?  
57 - end  
58 -  
59 - should 'provide lightbox_remote_button' do  
60 - expects(:button).with('type', 'label', { :action => 'popup'}, has_entries({ :class => 'remote-lbOn' })).returns('[button]')  
61 -  
62 - assert_equal '[button]', lightbox_remote_button('type', 'label', { :action => 'popup'})  
63 - end  
64 -  
65 -end  
test/unit/macro_test.rb
@@ -15,7 +15,7 @@ class MacroTest &lt; ActiveSupport::TestCase @@ -15,7 +15,7 @@ class MacroTest &lt; ActiveSupport::TestCase
15 15
16 def setup 16 def setup
17 @macro = Plugin1::Macro.new 17 @macro = Plugin1::Macro.new
18 - @macro_element = Hpricot(MACRO).search('.macro').first 18 + @macro_element = Nokogiri::HTML.fragment(MACRO).css('.macro').first
19 end 19 end
20 20
21 attr_reader :macro, :macro_element 21 attr_reader :macro, :macro_element
test/unit/modal_helper_test.rb 0 → 100644
@@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
  1 +require_relative '../test_helper'
  2 +
  3 +class ModalHelperTest < ActiveSupport::TestCase
  4 +
  5 + include ModalHelper
  6 +
  7 + should 'provide the needed files' do
  8 + assert File.exists?(Rails.root.join('public', 'stylesheets', 'colorbox.css')), 'colorbox.css expected to be in public/stylesheets, but not found'
  9 + assert File.exists?(Rails.root.join('public', 'javascripts', 'jquery.colorbox-min.js')), 'jquery.colorbox-min.js expected to be in public/javascripts, but not found'
  10 + end
  11 +
  12 + should 'provide link to close modal' do
  13 + expects(:button).with(:close, 'text', '#', has_entries({ :class => 'modal-toggle modal-close', :id => 'my-id' })).returns('[close-modal]')
  14 +
  15 + assert_equal '[close-modal]', modal_close_button('text', :id => 'my-id')
  16 + end
  17 +
  18 + should 'merge existing :class option in modal_close_button' do
  19 + expects(:button).with(:close, 'text', '#', has_entries({ :class => 'modal-toggle modal-close my-class', :id => 'my-id' })).returns('[close-modal]')
  20 +
  21 + assert_equal '[close-modal]', modal_close_button('text', :class => 'my-class', :id => 'my-id' )
  22 + end
  23 +
  24 + should 'provide modal_button' do
  25 + expects(:button).with('type', 'label', { :action => 'popup'}, has_entries({ :class => 'modal-toggle' })).returns('[button]')
  26 +
  27 + assert_equal '[button]', modal_button('type', 'label', { :action => 'popup'})
  28 + end
  29 +
  30 + should 'provide modal_icon_button' do
  31 + expects(:icon_button).with('type', 'label', { :action => 'popup'}, has_entries({ :class => 'modal-toggle' })).returns('[button]')
  32 +
  33 + assert_equal '[button]', modal_icon_button('type', 'label', { :action => 'popup'})
  34 + end
  35 +
  36 +end
test/unit/person_notifier_test.rb
@@ -225,6 +225,35 @@ class PersonNotifierTest &lt; ActiveSupport::TestCase @@ -225,6 +225,35 @@ class PersonNotifierTest &lt; ActiveSupport::TestCase
225 assert !jobs.select {|j| !j.failed? && j.last_error.nil? }.empty? 225 assert !jobs.select {|j| !j.failed? && j.last_error.nil? }.empty?
226 end 226 end
227 227
  228 + should 'render image tags for both internal and external src' do
  229 + @community.add_member(@member)
  230 + process_delayed_job_queue
  231 + notify
  232 + sent = ActionMailer::Base.deliveries.last
  233 + assert_match /src="\/\/www.gravatar.com\/avatar.*"/, sent.body.to_s
  234 + assert_match /src="http:\/\/.*\/images\/icons-app\/community-icon.png.*"/, sent.body.to_s
  235 + end
  236 +
  237 + should 'do not raise errors in NotifyJob failure to avoid loop' do
  238 + Delayed::Worker.max_attempts = 1
  239 + Delayed::Job.enqueue(PersonNotifier::NotifyJob.new(@member.id))
  240 +
  241 + PersonNotifier.any_instance.stubs(:notify).raises('error')
  242 + PersonNotifier.any_instance.stubs(:dispatch_notification_mail).raises('error')
  243 +
  244 + process_delayed_job_queue
  245 + jobs = PersonNotifier::NotifyJob.find(@member.id)
  246 + assert jobs.select {|j| !j.failed? && j.last_error.nil? }.empty?
  247 + end
  248 +
  249 + should 'list tasks in notification mail' do
  250 + task = @member.tasks.create!
  251 + process_delayed_job_queue
  252 + notify
  253 + sent = ActionMailer::Base.deliveries.last
  254 + assert_match /href=".*\/myprofile\/member\/tasks"/, sent.body.to_s
  255 + end
  256 +
228 private 257 private
229 258
230 def notify 259 def notify
test/unit/product_test.rb
@@ -492,7 +492,7 @@ class ProductTest &lt; ActiveSupport::TestCase @@ -492,7 +492,7 @@ class ProductTest &lt; ActiveSupport::TestCase
492 :amount_used => 10, :price_per_unit => 10, :is_from_solidarity_economy => false) 492 :amount_used => 10, :price_per_unit => 10, :is_from_solidarity_economy => false)
493 assert_equal 25, prod.percentage_from_solidarity_economy.first 493 assert_equal 25, prod.percentage_from_solidarity_economy.first
494 494
495 - prod = fast_create(Product, :name => 'test product1', :product_category_id => @product_category.id, :enterprise_id => @profile.id) 495 + prod = fast_create(Product, :name => 'test product1', :product_category_id => @product_category.id, :profile_id => @profile.id)
496 prod.inputs.create!(:product_id => prod.id, :product_category_id => @product_category.id, 496 prod.inputs.create!(:product_id => prod.id, :product_category_id => @product_category.id,
497 :amount_used => 10, :price_per_unit => 10, :is_from_solidarity_economy => true) 497 :amount_used => 10, :price_per_unit => 10, :is_from_solidarity_economy => true)
498 prod.inputs.create!(:product_id => prod.id, :product_category_id => @product_category.id, 498 prod.inputs.create!(:product_id => prod.id, :product_category_id => @product_category.id,
@@ -503,7 +503,7 @@ class ProductTest &lt; ActiveSupport::TestCase @@ -503,7 +503,7 @@ class ProductTest &lt; ActiveSupport::TestCase
503 :amount_used => 10, :price_per_unit => 10, :is_from_solidarity_economy => false) 503 :amount_used => 10, :price_per_unit => 10, :is_from_solidarity_economy => false)
504 assert_equal 75, prod.percentage_from_solidarity_economy.first 504 assert_equal 75, prod.percentage_from_solidarity_economy.first
505 505
506 - prod = fast_create(Product, :name => 'test product', :product_category_id => @product_category.id, :enterprise_id => @profile.id) 506 + prod = fast_create(Product, :name => 'test product', :product_category_id => @product_category.id, :profile_id => @profile.id)
507 prod.inputs.create!(:product_id => prod.id, :product_category_id => @product_category.id, 507 prod.inputs.create!(:product_id => prod.id, :product_category_id => @product_category.id,
508 :amount_used => 10, :price_per_unit => 10, :is_from_solidarity_economy => true) 508 :amount_used => 10, :price_per_unit => 10, :is_from_solidarity_economy => true)
509 assert_equal 100, prod.percentage_from_solidarity_economy.first 509 assert_equal 100, prod.percentage_from_solidarity_economy.first
test/unit/text_article_test.rb
1 require_relative "../test_helper" 1 require_relative "../test_helper"
2 2
3 class TextArticleTest < ActiveSupport::TestCase 3 class TextArticleTest < ActiveSupport::TestCase
4 - 4 +
5 # mostly dummy test. Can be removed when (if) there are real tests for this 5 # mostly dummy test. Can be removed when (if) there are real tests for this
6 - # this class. 6 + # this class.
7 should 'inherit from Article' do 7 should 'inherit from Article' do
8 assert_kind_of Article, TextArticle.new 8 assert_kind_of Article, TextArticle.new
9 end 9 end
@@ -44,7 +44,7 @@ class TextArticleTest &lt; ActiveSupport::TestCase @@ -44,7 +44,7 @@ class TextArticleTest &lt; ActiveSupport::TestCase
44 env = Environment.default 44 env = Environment.default
45 article.body = "<img src=\"http://#{env.default_hostname}/test.png\" />" 45 article.body = "<img src=\"http://#{env.default_hostname}/test.png\" />"
46 article.save! 46 article.save!
47 - assert_equal "<img src=\"/test.png\" />", article.body 47 + assert_equal "<img src=\"/test.png\">", article.body
48 end 48 end
49 49
50 should 'change link to relative path' do 50 should 'change link to relative path' do
@@ -60,18 +60,18 @@ class TextArticleTest &lt; ActiveSupport::TestCase @@ -60,18 +60,18 @@ class TextArticleTest &lt; ActiveSupport::TestCase
60 person = create_user('testuser').person 60 person = create_user('testuser').person
61 article = TextArticle.new(:profile => person, :name => 'test') 61 article = TextArticle.new(:profile => person, :name => 'test')
62 env = Environment.default 62 env = Environment.default
63 - article.body = "<img src=\"https://#{env.default_hostname}/test.png\" />" 63 + article.body = "<img src=\"https://#{env.default_hostname}/test.png\">"
64 article.save! 64 article.save!
65 - assert_equal "<img src=\"/test.png\" />", article.body 65 + assert_equal "<img src=\"/test.png\">", article.body
66 end 66 end
67 67
68 should 'change image path to relative for domain with port' do 68 should 'change image path to relative for domain with port' do
69 person = create_user('testuser').person 69 person = create_user('testuser').person
70 article = TextArticle.new(:profile => person, :name => 'test') 70 article = TextArticle.new(:profile => person, :name => 'test')
71 env = Environment.default 71 env = Environment.default
72 - article.body = "<img src=\"http://#{env.default_hostname}:3000/test.png\" />" 72 + article.body = "<img src=\"http://#{env.default_hostname}:3000/test.png\">"
73 article.save! 73 article.save!
74 - assert_equal "<img src=\"/test.png\" />", article.body 74 + assert_equal "<img src=\"/test.png\">", article.body
75 end 75 end
76 76
77 should 'change image path to relative for domain with www' do 77 should 'change image path to relative for domain with www' do
@@ -80,16 +80,16 @@ class TextArticleTest &lt; ActiveSupport::TestCase @@ -80,16 +80,16 @@ class TextArticleTest &lt; ActiveSupport::TestCase
80 env = Environment.default 80 env = Environment.default
81 env.force_www = true 81 env.force_www = true
82 env.save! 82 env.save!
83 - article.body = "<img src=\"http://#{env.default_hostname}:3000/test.png\" />" 83 + article.body = "<img src=\"http://#{env.default_hostname}:3000/test.png\">"
84 article.save! 84 article.save!
85 - assert_equal "<img src=\"/test.png\" />", article.body 85 + assert_equal "<img src=\"/test.png\">", article.body
86 end 86 end
87 87
88 should 'not be translatable if there is no language available on environment' do 88 should 'not be translatable if there is no language available on environment' do
89 environment = fast_create(Environment) 89 environment = fast_create(Environment)
90 environment.languages = nil 90 environment.languages = nil
91 profile = fast_create(Person, :environment_id => environment.id) 91 profile = fast_create(Person, :environment_id => environment.id)
92 - 92 +
93 text = TextArticle.new(:profile => profile) 93 text = TextArticle.new(:profile => profile)
94 94
95 assert !text.translatable? 95 assert !text.translatable?
@@ -102,11 +102,10 @@ class TextArticleTest &lt; ActiveSupport::TestCase @@ -102,11 +102,10 @@ class TextArticleTest &lt; ActiveSupport::TestCase
102 text = fast_create(TextArticle, :profile_id => profile.id) 102 text = fast_create(TextArticle, :profile_id => profile.id)
103 103
104 assert !text.translatable? 104 assert !text.translatable?
105 -  
106 105
107 environment.languages = ['en','pt','fr'] 106 environment.languages = ['en','pt','fr']
108 environment.save 107 environment.save
109 - text.reload 108 + text.reload
110 assert text.translatable? 109 assert text.translatable?
111 end 110 end
112 111
test/unit/thickbox_helper_test.rb
@@ -1,25 +0,0 @@ @@ -1,25 +0,0 @@
1 -require_relative "../test_helper"  
2 -  
3 -class ThickboxHelperTest < ActiveSupport::TestCase  
4 - include ThickboxHelper  
5 -  
6 - def url_for(url)  
7 - url  
8 - end  
9 -  
10 - should 'create thickbox links correcly' do  
11 - expects(:link_to).with('Title', '/url#TB_inline?height=300&width=500&inlineId=inlineLoginBox&modal=true', :class => 'thickbox')  
12 - thickbox_inline_popup_link('Title', '/url', 'inlineLoginBox')  
13 - end  
14 -  
15 - should 'pass along extra options' do  
16 - expects(:link_to).with('Title', anything, :class => 'thickbox', :id => 'lalala', :title => 'lelele')  
17 - thickbox_inline_popup_link('Title', '/url', 'inlineLoginBox', :id => 'lalala', :title => 'lelele')  
18 - end  
19 -  
20 - should 'generate close button' do  
21 - expects(:button_to_function).with(:close, 'Title', 'tb_remove();').returns('[close-button]')  
22 - assert_equal '[close-button]', thickbox_close_button('Title')  
23 - end  
24 -  
25 -end  
test/unit/tiny_mce_article_test.rb
@@ -9,7 +9,7 @@ class TinyMceArticleTest &lt; ActiveSupport::TestCase @@ -9,7 +9,7 @@ class TinyMceArticleTest &lt; ActiveSupport::TestCase
9 end 9 end
10 attr_reader :profile 10 attr_reader :profile
11 11
12 - # this test can be removed when we get real tests for TinyMceArticle 12 + # this test can be removed when we get real tests for TinyMceArticle
13 should 'be an article' do 13 should 'be an article' do
14 assert_subclass TextArticle, TinyMceArticle 14 assert_subclass TextArticle, TinyMceArticle
15 end 15 end
@@ -44,11 +44,6 @@ class TinyMceArticleTest &lt; ActiveSupport::TestCase @@ -44,11 +44,6 @@ class TinyMceArticleTest &lt; ActiveSupport::TestCase
44 assert(article.body.is_utf8?, "%s expected to be valid UTF-8 content" % article.body.inspect) 44 assert(article.body.is_utf8?, "%s expected to be valid UTF-8 content" % article.body.inspect)
45 end 45 end
46 46
47 - should 'fix tinymce mess with itheora comments for IE from tiny mce article body' do  
48 - article = create(TinyMceArticle, :profile => profile, :name => 'article', :abstract => 'abstract', :body => "the <!--–-[if IE]--> just for ie... <!--[endif]-->")  
49 - assert_equal "the <!–-[if IE]> just for ie... <![endif]-–>", article.body.html_safe  
50 - end  
51 -  
52 should 'remove iframe if it is not from a trusted site' do 47 should 'remove iframe if it is not from a trusted site' do
53 article = create(TinyMceArticle, :profile => profile, :name => 'article', :abstract => 'abstract', :body => "<iframe src='http://anything/videos.ogg'></iframe>") 48 article = create(TinyMceArticle, :profile => profile, :name => 'article', :abstract => 'abstract', :body => "<iframe src='http://anything/videos.ogg'></iframe>")
54 assert_equal "", article.body 49 assert_equal "", article.body
@@ -94,12 +89,6 @@ class TinyMceArticleTest &lt; ActiveSupport::TestCase @@ -94,12 +89,6 @@ class TinyMceArticleTest &lt; ActiveSupport::TestCase
94 assert_equal '', article.body 89 assert_equal '', article.body
95 end 90 end
96 91
97 - #TinymMCE convert config={"key":(.*)} in config={&quotkey&quot:(.*)}  
98 - should 'not replace &quot with &amp;quot; when adding an Archive.org video' do  
99 - article = create(TinyMceArticle, :profile => profile, :name => 'article', :abstract => 'abstract', :body => "<embed flashvars='config={&quot;key&quot;:&quot;\#$b6eb72a0f2f1e29f3d4&quot;}'> </embed>")  
100 - assert_equal "<embed flashvars=\"config={&quot;key&quot;:&quot;\#$b6eb72a0f2f1e29f3d4&quot;}\"> </embed>", article.body  
101 - end  
102 -  
103 should 'not sanitize html comments' do 92 should 'not sanitize html comments' do
104 article = TinyMceArticle.new 93 article = TinyMceArticle.new
105 article.body = '<p><!-- <asdf> << aasdfa >>> --> <h1> Wellformed html code </h1>' 94 article.body = '<p><!-- <asdf> << aasdfa >>> --> <h1> Wellformed html code </h1>'
test/unit/user_activation_job_test.rb
1 require_relative "../test_helper" 1 require_relative "../test_helper"
2 2
3 -class NotifyActivityToProfilesJobTest < ActiveSupport::TestCase 3 +class UserActivationJobTest < ActiveSupport::TestCase
4 4
5 should 'create job on user creation' do 5 should 'create job on user creation' do
6 user = new_user :login => 'test1' 6 user = new_user :login => 'test1'
test/unit/user_test.rb
@@ -526,9 +526,19 @@ class UserTest &lt; ActiveSupport::TestCase @@ -526,9 +526,19 @@ class UserTest &lt; ActiveSupport::TestCase
526 assert user.activated? 526 assert user.activated?
527 end 527 end
528 528
529 - should 'delay activation check' do 529 + should 'delay activation check with default time' do
530 user = new_user 530 user = new_user
531 - assert_match /UserActivationJob/, Delayed::Job.last.handler 531 + job = Delayed::Job.last
  532 + assert_match /UserActivationJob/, job.handler
  533 + assert_equal 72, ((job.run_at - user.created_at)/1.hour).round
  534 + end
  535 +
  536 + should 'delay activation check with custom time' do
  537 + NOOSFERO_CONF.stubs(:[]).with('hours_until_user_activation_check').returns(240)
  538 + user = new_user
  539 + job = Delayed::Job.last
  540 + assert_match /UserActivationJob/, job.handler
  541 + assert_equal 240, ((job.run_at - user.created_at)/1.hour).round
532 end 542 end
533 543
534 should 'not create job to check activation to template users' do 544 should 'not create job to check activation to template users' do
vendor/cardmagic-contacts-f66219e6589ccaf3ab9e3574fdd41225d0dd5073/lib/contacts/aol.rb
@@ -8,20 +8,19 @@ class Hash @@ -8,20 +8,19 @@ class Hash
8 end 8 end
9 9
10 class Contacts 10 class Contacts
11 - require 'hpricot'  
12 class Aol < Base 11 class Aol < Base
13 URL = "http://www.aol.com/" 12 URL = "http://www.aol.com/"
14 LOGIN_URL = "https://my.screenname.aol.com/_cqr/login/login.psp" 13 LOGIN_URL = "https://my.screenname.aol.com/_cqr/login/login.psp"
15 LOGIN_REFERER_URL = "http://webmail.aol.com/" 14 LOGIN_REFERER_URL = "http://webmail.aol.com/"
16 LOGIN_REFERER_PATH = "sitedomain=sns.webmail.aol.com&lang=en&locale=us&authLev=0&uitype=mini&loginId=&redirType=js&xchk=false" 15 LOGIN_REFERER_PATH = "sitedomain=sns.webmail.aol.com&lang=en&locale=us&authLev=0&uitype=mini&loginId=&redirType=js&xchk=false"
17 AOL_NUM = "29970-343" # this seems to change each time they change the protocol 16 AOL_NUM = "29970-343" # this seems to change each time they change the protocol
18 - 17 +
19 CONTACT_LIST_URL = "http://webmail.aol.com/#{AOL_NUM}/aim-2/en-us/Lite/ContactList.aspx?folder=Inbox&showUserFolders=False" 18 CONTACT_LIST_URL = "http://webmail.aol.com/#{AOL_NUM}/aim-2/en-us/Lite/ContactList.aspx?folder=Inbox&showUserFolders=False"
20 CONTACT_LIST_CSV_URL = "http://webmail.aol.com/#{AOL_NUM}/aim-2/en-us/Lite/ABExport.aspx?command=all" 19 CONTACT_LIST_CSV_URL = "http://webmail.aol.com/#{AOL_NUM}/aim-2/en-us/Lite/ABExport.aspx?command=all"
21 PROTOCOL_ERROR = "AOL has changed its protocols, please upgrade this library first. If that does not work, dive into the code and submit a patch at http://github.com/cardmagic/contacts" 20 PROTOCOL_ERROR = "AOL has changed its protocols, please upgrade this library first. If that does not work, dive into the code and submit a patch at http://github.com/cardmagic/contacts"
22 - 21 +
23 def real_connect 22 def real_connect
24 - 23 +
25 postdata = { 24 postdata = {
26 "loginId" => login, 25 "loginId" => login,
27 "password" => password, 26 "password" => password,
@@ -62,15 +61,15 @@ class Contacts @@ -62,15 +61,15 @@ class Contacts
62 until forward.nil? 61 until forward.nil?
63 data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward] 62 data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
64 end 63 end
65 - 64 +
66 data, resp, cookies, forward, old_url = get("#{LOGIN_URL}?#{LOGIN_REFERER_PATH}", cookies) + [LOGIN_REFERER_URL] 65 data, resp, cookies, forward, old_url = get("#{LOGIN_URL}?#{LOGIN_REFERER_PATH}", cookies) + [LOGIN_REFERER_URL]
67 until forward.nil? 66 until forward.nil?
68 data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward] 67 data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
69 end 68 end
70 69
71 - doc = Hpricot(data)  
72 - (doc/:input).each do |input|  
73 - postdata["usrd"] = input.attributes["value"] if input.attributes["name"] == "usrd" 70 + doc = Nokogiri::HTML.fragment data
  71 + doc.css('input').each do |input|
  72 + postdata["usrd"] = input["value"] if input["name"] == "usrd"
74 end 73 end
75 # parse data for <input name="usrd" value="2726212" type="hidden"> and add it to the postdata 74 # parse data for <input name="usrd" value="2726212" type="hidden"> and add it to the postdata
76 75
@@ -78,13 +77,13 @@ class Contacts @@ -78,13 +77,13 @@ class Contacts
78 postdata["SNS_LDC"] = cookie_hash_from_string(cookies)["SNS_LDC"] 77 postdata["SNS_LDC"] = cookie_hash_from_string(cookies)["SNS_LDC"]
79 postdata["LTState"] = cookie_hash_from_string(cookies)["LTState"] 78 postdata["LTState"] = cookie_hash_from_string(cookies)["LTState"]
80 # raise data.inspect 79 # raise data.inspect
81 - 80 +
82 data, resp, cookies, forward, old_url = post(LOGIN_URL, postdata.to_query_string, cookies, LOGIN_REFERER_URL) + [LOGIN_REFERER_URL] 81 data, resp, cookies, forward, old_url = post(LOGIN_URL, postdata.to_query_string, cookies, LOGIN_REFERER_URL) + [LOGIN_REFERER_URL]
83 - 82 +
84 until forward.nil? 83 until forward.nil?
85 data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward] 84 data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
86 end 85 end
87 - 86 +
88 if data.index("Invalid Screen Name or Password.") 87 if data.index("Invalid Screen Name or Password.")
89 raise AuthenticationError, "Username and password do not match" 88 raise AuthenticationError, "Username and password do not match"
90 elsif data.index("Required field must not be blank") 89 elsif data.index("Required field must not be blank")
@@ -113,19 +112,19 @@ class Contacts @@ -113,19 +112,19 @@ class Contacts
113 until forward.nil? 112 until forward.nil?
114 data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward] 113 data, resp, cookies, forward, old_url = get(forward, cookies, old_url) + [forward]
115 end 114 end
116 - 115 +
117 if resp.code_type != Net::HTTPOK 116 if resp.code_type != Net::HTTPOK
118 raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR) 117 raise ConnectionError, self.class.const_get(:PROTOCOL_ERROR)
119 end 118 end
120 119
121 # parse data and grab <input name="user" value="8QzMPIAKs2" type="hidden"> 120 # parse data and grab <input name="user" value="8QzMPIAKs2" type="hidden">
122 - doc = Hpricot(data)  
123 - (doc/:input).each do |input|  
124 - postdata["user"] = input.attributes["value"] if input.attributes["name"] == "user" 121 + doc = Nokogiri::HTML.fragment data
  122 + doc.css('input').each do |input|
  123 + postdata["user"] = input["value"] if input["name"] == "user"
125 end 124 end
126 - 125 +
127 data, resp, cookies, forward, old_url = get(CONTACT_LIST_CSV_URL, @cookies, CONTACT_LIST_URL) + [CONTACT_LIST_URL] 126 data, resp, cookies, forward, old_url = get(CONTACT_LIST_CSV_URL, @cookies, CONTACT_LIST_URL) + [CONTACT_LIST_URL]
128 - 127 +
129 if forward.nil? 128 if forward.nil?
130 parse data 129 parse data
131 else 130 else
@@ -134,15 +133,15 @@ class Contacts @@ -134,15 +133,15 @@ class Contacts
134 end 133 end
135 end 134 end
136 private 135 private
137 - 136 +
138 def parse(data, options={}) 137 def parse(data, options={})
139 data = CSV.parse(data) 138 data = CSV.parse(data)
140 col_names = data.shift 139 col_names = data.shift
141 @contacts = data.map do |person| 140 @contacts = data.map do |person|
142 ["#{person[0]} #{person[1]}", person[4]] unless person[4].empty? 141 ["#{person[0]} #{person[1]}", person[4]] unless person[4].empty?
143 end.compact 142 end.compact
144 - end 143 + end
145 end 144 end
146 145
147 TYPES[:aol] = Aol 146 TYPES[:aol] = Aol
148 -end  
149 \ No newline at end of file 147 \ No newline at end of file
  148 +end
vendor/plugins/ruby_bosh/Rakefile
@@ -12,7 +12,7 @@ begin @@ -12,7 +12,7 @@ begin
12 12
13 s.add_dependency("builder") 13 s.add_dependency("builder")
14 s.add_dependency("rest-client") 14 s.add_dependency("rest-client")
15 - s.add_dependency("hpricot") 15 + s.add_dependency("nokogiri")
16 s.add_dependency("SystemTimer") 16 s.add_dependency("SystemTimer")
17 end 17 end
18 rescue LoadError 18 rescue LoadError
vendor/plugins/ruby_bosh/lib/ruby_bosh.rb
@@ -2,10 +2,10 @@ require &#39;rest_client&#39; @@ -2,10 +2,10 @@ require &#39;rest_client&#39;
2 require 'builder' 2 require 'builder'
3 require 'rexml/document' 3 require 'rexml/document'
4 require 'base64' 4 require 'base64'
5 -require 'hpricot' 5 +require 'nokogiri'
6 require 'timeout' 6 require 'timeout'
7 7
8 -class RubyBOSH 8 +class RubyBOSH
9 BOSH_XMLNS = 'http://jabber.org/protocol/httpbind' 9 BOSH_XMLNS = 'http://jabber.org/protocol/httpbind'
10 TLS_XMLNS = 'urn:ietf:params:xml:ns:xmpp-tls' 10 TLS_XMLNS = 'urn:ietf:params:xml:ns:xmpp-tls'
11 SASL_XMLNS = 'urn:ietf:params:xml:ns:xmpp-sasl' 11 SASL_XMLNS = 'urn:ietf:params:xml:ns:xmpp-sasl'
@@ -24,12 +24,12 @@ class RubyBOSH @@ -24,12 +24,12 @@ class RubyBOSH
24 end 24 end
25 25
26 attr_accessor :jid, :rid, :sid, :success 26 attr_accessor :jid, :rid, :sid, :success
27 - def initialize(jid, pw, service_url, opts={}) 27 + def initialize(jid, pw, service_url, opts={})
28 @service_url = service_url 28 @service_url = service_url
29 @jid, @pw = jid, pw 29 @jid, @pw = jid, pw
30 @host = jid.split("@").last 30 @host = jid.split("@").last
31 @success = false 31 @success = false
32 - @timeout = opts[:timeout] || 3 #seconds 32 + @timeout = opts[:timeout] || 3 #seconds
33 @headers = {"Content-Type" => "text/xml; charset=utf-8", 33 @headers = {"Content-Type" => "text/xml; charset=utf-8",
34 "Accept" => "text/xml"} 34 "Accept" => "text/xml"}
35 @wait = opts[:wait] || 5 35 @wait = opts[:wait] || 5
@@ -47,7 +47,7 @@ class RubyBOSH @@ -47,7 +47,7 @@ class RubyBOSH
47 47
48 def connect 48 def connect
49 initialize_bosh_session 49 initialize_bosh_session
50 - if send_auth_request 50 + if send_auth_request
51 send_restart_request 51 send_restart_request
52 request_resource_binding 52 request_resource_binding
53 @success = send_session_request 53 @success = send_session_request
@@ -55,12 +55,12 @@ class RubyBOSH @@ -55,12 +55,12 @@ class RubyBOSH
55 55
56 raise RubyBOSH::AuthFailed, "could not authenticate #{@jid}" unless success? 56 raise RubyBOSH::AuthFailed, "could not authenticate #{@jid}" unless success?
57 @rid += 1 #updates the rid for the next call from the browser 57 @rid += 1 #updates the rid for the next call from the browser
58 - 58 +
59 [@jid, @sid, @rid] 59 [@jid, @sid, @rid]
60 end 60 end
61 61
62 private 62 private
63 - def initialize_bosh_session 63 + def initialize_bosh_session
64 response = deliver(construct_body(:wait => @wait, :to => @host, 64 response = deliver(construct_body(:wait => @wait, :to => @host,
65 :hold => @hold, :window => @window, 65 :hold => @hold, :window => @window,
66 "xmpp:version" => '1.0')) 66 "xmpp:version" => '1.0'))
@@ -72,7 +72,7 @@ class RubyBOSH @@ -72,7 +72,7 @@ class RubyBOSH
72 72
73 builder = Builder::XmlMarkup.new 73 builder = Builder::XmlMarkup.new
74 parameters = {:rid => @rid, :xmlns => BOSH_XMLNS, 74 parameters = {:rid => @rid, :xmlns => BOSH_XMLNS,
75 - "xmpp:version" => "1.0", 75 + "xmpp:version" => "1.0",
76 "xmlns:xmpp" => "urn:xmpp:xbosh"}.merge(params) 76 "xmlns:xmpp" => "urn:xmpp:xbosh"}.merge(params)
77 77
78 if block_given? 78 if block_given?
@@ -82,10 +82,10 @@ class RubyBOSH @@ -82,10 +82,10 @@ class RubyBOSH
82 end 82 end
83 end 83 end
84 84
85 - def send_auth_request 85 + def send_auth_request
86 request = construct_body(:sid => @sid) do |body| 86 request = construct_body(:sid => @sid) do |body|
87 - auth_string = "#{@jid}\x00#{@jid.split("@").first.strip}\x00#{@pw}"  
88 - body.auth(Base64.encode64(auth_string).gsub(/\s/,''), 87 + auth_string = "#{@jid}\x00#{@jid.split("@").first.strip}\x00#{@pw}"
  88 + body.auth(Base64.encode64(auth_string).gsub(/\s/,''),
89 :xmlns => SASL_XMLNS, :mechanism => 'PLAIN') 89 :xmlns => SASL_XMLNS, :mechanism => 'PLAIN')
90 end 90 end
91 91
@@ -100,16 +100,16 @@ class RubyBOSH @@ -100,16 +100,16 @@ class RubyBOSH
100 100
101 def request_resource_binding 101 def request_resource_binding
102 request = construct_body(:sid => @sid) do |body| 102 request = construct_body(:sid => @sid) do |body|
103 - body.iq(:id => "bind_#{rand(100000)}", :type => "set", 103 + body.iq(:id => "bind_#{rand(100000)}", :type => "set",
104 :xmlns => "jabber:client") do |iq| 104 :xmlns => "jabber:client") do |iq|
105 iq.bind(:xmlns => BIND_XMLNS) do |bind| 105 iq.bind(:xmlns => BIND_XMLNS) do |bind|
106 bind.resource("bosh_#{rand(10000)}") 106 bind.resource("bosh_#{rand(10000)}")
107 end 107 end
108 end 108 end
109 end 109 end
110 - 110 +
111 response = deliver(request) 111 response = deliver(request)
112 - response.include?("<jid>") 112 + response.include?("<jid>")
113 end 113 end
114 114
115 def send_session_request 115 def send_session_request
@@ -117,16 +117,16 @@ class RubyBOSH @@ -117,16 +117,16 @@ class RubyBOSH
117 body.iq(:xmlns => CLIENT_XMLNS, :type => "set", 117 body.iq(:xmlns => CLIENT_XMLNS, :type => "set",
118 :id => "sess_#{rand(100000)}") do |iq| 118 :id => "sess_#{rand(100000)}") do |iq|
119 iq.session(:xmlns => SESSION_XMLNS) 119 iq.session(:xmlns => SESSION_XMLNS)
120 - end 120 + end
121 end 121 end
122 122
123 response = deliver(request) 123 response = deliver(request)
124 - response.include?("body") 124 + response.include?("body")
125 end 125 end
126 126
127 def parse(_response) 127 def parse(_response)
128 - doc = Hpricot(_response.to_s)  
129 - doc.search("//body").each do |body| 128 + doc = Nokogiri::HTML.fragment(_response.to_s)
  129 + doc.search("body").each do |body|
130 @sid = body.attributes["sid"].to_s 130 @sid = body.attributes["sid"].to_s
131 end 131 end
132 _response 132 _response
@@ -156,6 +156,6 @@ end @@ -156,6 +156,6 @@ end
156 156
157 157
158 if __FILE__ == $0 158 if __FILE__ == $0
159 - p RubyBOSH.initialize_session(ARGV[0], ARGV[1], 159 + p RubyBOSH.initialize_session(ARGV[0], ARGV[1],
160 "http://localhost:5280/http-bind") 160 "http://localhost:5280/http-bind")
161 end 161 end
vendor/plugins/ruby_bosh/ruby_bosh.gemspec
@@ -24,18 +24,15 @@ Gem::Specification.new do |s| @@ -24,18 +24,15 @@ Gem::Specification.new do |s|
24 if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then 24 if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
25 s.add_runtime_dependency(%q<builder>, [">= 0"]) 25 s.add_runtime_dependency(%q<builder>, [">= 0"])
26 s.add_runtime_dependency(%q<adamwiggins-rest-client>, [">= 0"]) 26 s.add_runtime_dependency(%q<adamwiggins-rest-client>, [">= 0"])
27 - s.add_runtime_dependency(%q<hpricot>, [">= 0"])  
28 s.add_runtime_dependency(%q<SystemTimer>, [">= 0"]) 27 s.add_runtime_dependency(%q<SystemTimer>, [">= 0"])
29 else 28 else
30 s.add_dependency(%q<builder>, [">= 0"]) 29 s.add_dependency(%q<builder>, [">= 0"])
31 s.add_dependency(%q<adamwiggins-rest-client>, [">= 0"]) 30 s.add_dependency(%q<adamwiggins-rest-client>, [">= 0"])
32 - s.add_dependency(%q<hpricot>, [">= 0"])  
33 s.add_dependency(%q<SystemTimer>, [">= 0"]) 31 s.add_dependency(%q<SystemTimer>, [">= 0"])
34 end 32 end
35 else 33 else
36 s.add_dependency(%q<builder>, [">= 0"]) 34 s.add_dependency(%q<builder>, [">= 0"])
37 s.add_dependency(%q<adamwiggins-rest-client>, [">= 0"]) 35 s.add_dependency(%q<adamwiggins-rest-client>, [">= 0"])
38 - s.add_dependency(%q<hpricot>, [">= 0"])  
39 s.add_dependency(%q<SystemTimer>, [">= 0"]) 36 s.add_dependency(%q<SystemTimer>, [">= 0"])
40 end 37 end
41 end 38 end