Commit 50f90482152b5eb3b7a7e603d875f9f03e1a321f

Authored by Joenio Costa
2 parents 08976954 040b05e2

Merge branch 'master' into AI2993-display_content_plugin_content

Showing 125 changed files with 2581 additions and 366 deletions   Show diff stats
@@ -23,7 +23,7 @@ You need to install some packages Noosfero depends on. On Debian GNU/Linux or De @@ -23,7 +23,7 @@ You need to install some packages Noosfero depends on. On Debian GNU/Linux or De
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 libhpricot-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 libnokogiri-ruby 26 + tango-icon-theme
27 27
28 On other systems, they may or may not be available through your regular package management system. Below are the links to their homepages. 28 On other systems, they may or may not be available through your regular package management system. Below are the links to their homepages.
29 29
@@ -41,7 +41,6 @@ On other systems, they may or may not be available through your regular package @@ -41,7 +41,6 @@ On other systems, they may or may not be available through your regular package
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 43 * Hpricot: http://hpricot.com
44 -* Nokogiri: http://nokogiri.org/  
45 44
46 If you manage to install Noosfero successfully on other systems than Debian, 45 If you manage to install Noosfero successfully on other systems than Debian,
47 please feel free to contact the Noosfero development mailing with the 46 please feel free to contact the Noosfero development mailing with the
app/controllers/admin/environment_design_controller.rb
@@ -3,6 +3,8 @@ class EnvironmentDesignController < BoxOrganizerController @@ -3,6 +3,8 @@ class EnvironmentDesignController < BoxOrganizerController
3 protect 'edit_environment_design', :environment 3 protect 'edit_environment_design', :environment
4 4
5 def available_blocks 5 def available_blocks
  6 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  7 + # the Noosfero core soon, see ActionItem3045
6 @available_blocks ||= [ ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ] 8 @available_blocks ||= [ ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ]
7 @available_blocks += plugins.dispatch(:extra_blocks, :type => Environment) 9 @available_blocks += plugins.dispatch(:extra_blocks, :type => Environment)
8 end 10 end
app/controllers/admin/users_controller.rb
@@ -7,7 +7,7 @@ class UsersController < AdminController @@ -7,7 +7,7 @@ class UsersController < AdminController
7 include UsersHelper 7 include UsersHelper
8 8
9 def index 9 def index
10 - @filter = params[:filter] 10 + @filter = params[:filter] || 'all_users'
11 scope = environment.people.no_templates 11 scope = environment.people.no_templates
12 if @filter == 'admin_users' 12 if @filter == 'admin_users'
13 scope = scope.admins 13 scope = scope.admins
@@ -16,6 +16,7 @@ class UsersController < AdminController @@ -16,6 +16,7 @@ class UsersController < AdminController
16 elsif @filter == 'deactivated_users' 16 elsif @filter == 'deactivated_users'
17 scope = scope.deactivated 17 scope = scope.deactivated
18 end 18 end
  19 + scope = scope.order('name ASC')
19 @q = params[:q] 20 @q = params[:q]
20 @collection = find_by_contents(:people, scope, @q, {:per_page => per_page, :page => params[:npage]})[:results] 21 @collection = find_by_contents(:people, scope, @q, {:per_page => per_page, :page => params[:npage]})[:results]
21 end 22 end
@@ -44,6 +45,20 @@ class UsersController < AdminController @@ -44,6 +45,20 @@ class UsersController < AdminController
44 redirect_to :action => :index, :q => params[:q], :filter => params[:filter] 45 redirect_to :action => :index, :q => params[:q], :filter => params[:filter]
45 end 46 end
46 47
  48 +
  49 + def destroy_user
  50 + if request.post?
  51 + person = environment.people.find_by_id(params[:id])
  52 + if person && person.destroy
  53 + session[:notice] = _('The profile was deleted.')
  54 + else
  55 + session[:notice] = _('Could not remove profile')
  56 + end
  57 + end
  58 + redirect_to :action => :index, :q => params[:q], :filter => params[:filter]
  59 + end
  60 +
  61 +
47 def download 62 def download
48 respond_to do |format| 63 respond_to do |format|
49 format.html 64 format.html
app/controllers/application_controller.rb
@@ -21,6 +21,7 @@ class ApplicationController < ActionController::Base @@ -21,6 +21,7 @@ class ApplicationController < ActionController::Base
21 include ApplicationHelper 21 include ApplicationHelper
22 layout :get_layout 22 layout :get_layout
23 def get_layout 23 def get_layout
  24 + return nil if request.format == :js
24 theme_layout = theme_option(:layout) 25 theme_layout = theme_option(:layout)
25 if theme_layout 26 if theme_layout
26 theme_view_file('layouts/'+theme_layout) || theme_layout 27 theme_view_file('layouts/'+theme_layout) || theme_layout
app/controllers/box_organizer_controller.rb
@@ -70,7 +70,7 @@ class BoxOrganizerController < ApplicationController @@ -70,7 +70,7 @@ class BoxOrganizerController < ApplicationController
70 else 70 else
71 @center_block_types = (Box.acceptable_center_blocks & available_blocks) + plugins.dispatch(:extra_blocks, :type => boxes_holder.class, :position => 1) 71 @center_block_types = (Box.acceptable_center_blocks & available_blocks) + plugins.dispatch(:extra_blocks, :type => boxes_holder.class, :position => 1)
72 @side_block_types = (Box.acceptable_side_blocks & available_blocks) + plugins.dispatch(:extra_blocks, :type => boxes_holder.class, :position => [2,3]) 72 @side_block_types = (Box.acceptable_side_blocks & available_blocks) + plugins.dispatch(:extra_blocks, :type => boxes_holder.class, :position => [2,3])
73 - @boxes = boxes_holder.boxes 73 + @boxes = boxes_holder.boxes.with_position
74 render :action => 'add_block', :layout => false 74 render :action => 'add_block', :layout => false
75 end 75 end
76 end 76 end
app/controllers/my_profile/cms_controller.rb
@@ -221,11 +221,10 @@ class CmsController < MyProfileController @@ -221,11 +221,10 @@ class CmsController < MyProfileController
221 221
222 def update_categories 222 def update_categories
223 @object = params[:id] ? @profile.articles.find(params[:id]) : Article.new 223 @object = params[:id] ? @profile.articles.find(params[:id]) : Article.new
  224 + @categories = @toplevel_categories = environment.top_level_categories
224 if params[:category_id] 225 if params[:category_id]
225 @current_category = Category.find(params[:category_id]) 226 @current_category = Category.find(params[:category_id])
226 @categories = @current_category.children 227 @categories = @current_category.children
227 - else  
228 - @categories = environment.top_level_categories.select{|i| !i.children.empty?}  
229 end 228 end
230 render :partial => 'shared/select_categories', :locals => {:object_name => 'article', :multiple => true}, :layout => false 229 render :partial => 'shared/select_categories', :locals => {:object_name => 'article', :multiple => true}, :layout => false
231 end 230 end
app/controllers/my_profile/profile_editor_controller.rb
@@ -55,11 +55,10 @@ class ProfileEditorController < MyProfileController @@ -55,11 +55,10 @@ class ProfileEditorController < MyProfileController
55 55
56 def update_categories 56 def update_categories
57 @object = profile 57 @object = profile
  58 + @categories = @toplevel_categories = environment.top_level_categories
58 if params[:category_id] 59 if params[:category_id]
59 @current_category = Category.find(params[:category_id]) 60 @current_category = Category.find(params[:category_id])
60 @categories = @current_category.children 61 @categories = @current_category.children
61 - else  
62 - @categories = environment.top_level_categories.select{|i| !i.children.empty?}  
63 end 62 end
64 render :partial => 'shared/select_categories', :locals => {:object_name => 'profile_data', :multiple => true}, :layout => false 63 render :partial => 'shared/select_categories', :locals => {:object_name => 'profile_data', :multiple => true}, :layout => false
65 end 64 end
app/controllers/my_profile/profile_members_controller.rb
@@ -2,7 +2,7 @@ class ProfileMembersController < MyProfileController @@ -2,7 +2,7 @@ class ProfileMembersController < MyProfileController
2 protect 'manage_memberships', :profile 2 protect 'manage_memberships', :profile
3 3
4 def index 4 def index
5 - @members = profile.members 5 + @members = profile.members_by_name
6 @member_role = environment.roles.find_by_name('member') 6 @member_role = environment.roles.find_by_name('member')
7 end 7 end
8 8
app/controllers/public/profile_controller.rb
@@ -67,7 +67,7 @@ class ProfileController < PublicController @@ -67,7 +67,7 @@ class ProfileController < PublicController
67 67
68 def members 68 def members
69 if is_cache_expired?(profile.members_cache_key(params)) 69 if is_cache_expired?(profile.members_cache_key(params))
70 - @members = profile.members.includes(relations_to_include).paginate(:per_page => members_per_page, :page => params[:npage]) 70 + @members = profile.members_by_name.includes(relations_to_include).paginate(:per_page => members_per_page, :page => params[:npage])
71 end 71 end
72 end 72 end
73 73
@@ -304,14 +304,6 @@ class ProfileController < PublicController @@ -304,14 +304,6 @@ class ProfileController < PublicController
304 end 304 end
305 end 305 end
306 306
307 - def profile_info  
308 - begin  
309 - @block = profile.blocks.find(params[:block_id])  
310 - rescue  
311 - render :text => _('Profile information could not be loaded')  
312 - end  
313 - end  
314 -  
315 def report_abuse 307 def report_abuse
316 @abuse_report = AbuseReport.new 308 @abuse_report = AbuseReport.new
317 render :layout => false 309 render :layout => false
app/controllers/themes_controller.rb
@@ -12,7 +12,7 @@ class ThemesController < ApplicationController @@ -12,7 +12,7 @@ class ThemesController < ApplicationController
12 12
13 def index 13 def index
14 @environment = environment 14 @environment = environment
15 - @themes = environment.themes + Theme.approved_themes(target) 15 + @themes = (environment.themes + Theme.approved_themes(target)).sort_by { |t| t.name }
16 16
17 @current_theme = target.theme 17 @current_theme = target.theme
18 18
app/helpers/application_helper.rb
@@ -608,49 +608,18 @@ module ApplicationHelper @@ -608,49 +608,18 @@ module ApplicationHelper
608 end 608 end
609 609
610 attr_reader :environment 610 attr_reader :environment
  611 +
611 def select_categories(object_name, title=nil, title_size=4) 612 def select_categories(object_name, title=nil, title_size=4)
612 return nil if environment.enabled?(:disable_categories) 613 return nil if environment.enabled?(:disable_categories)
613 if title.nil? 614 if title.nil?
614 title = _('Categories') 615 title = _('Categories')
615 end 616 end
616 617
617 - object = instance_variable_get("@#{object_name}")  
618 -  
619 - result = content_tag 'h'+title_size.to_s(), title  
620 - result << javascript_tag( 'function open_close_cat( link ) {  
621 - var div = link.parentNode.getElementsByTagName("div")[0];  
622 - var end = function(){  
623 - if ( div.style.display == "none" ) {  
624 - this.link.className="button icon-button icon-down"  
625 - } else {  
626 - this.link.className="button icon-button icon-up-red"  
627 - }  
628 - }  
629 - Effect.toggle( div, "slide", { link:link, div:div, afterFinish:end } )  
630 - }')  
631 - environment.top_level_categories.select{|i| !i.children.empty?}.each do |toplevel|  
632 - next unless object.accept_category?(toplevel)  
633 - # FIXME  
634 - ([toplevel] + toplevel.children_for_menu).each do |cat|  
635 - if cat.top_level?  
636 - result << '<div class="categorie_box">'.html_safe  
637 - result << icon_button( :down, _('open'), '#', :onclick => 'open_close_cat(this); return false' )  
638 - result << content_tag('h5', toplevel.name)  
639 - result << '<div style="display:none"><ul class="categories">'.html_safe  
640 - else  
641 - checkbox_id = "#{object_name}_#{cat.full_name.downcase.gsub(/\s+|\//, '_')}"  
642 - result << content_tag('li', labelled_check_box(  
643 - cat.full_name_without_leading(1, " &rarr; "),  
644 - "#{object_name}[category_ids][]", cat.id,  
645 - object.category_ids.include?(cat.id), :id => checkbox_id,  
646 - :onchange => 'this.parentNode.className=(this.checked?"cat_checked":"")' ),  
647 - :class => ( object.category_ids.include?(cat.id) ? 'cat_checked' : '' ) ) + "\n"  
648 - end  
649 - end  
650 - result << '</ul></div></div>'.html_safe  
651 - end 618 + @object = instance_variable_get("@#{object_name}")
  619 + @categories = environment.top_level_categories
652 620
653 - content_tag('div', result) 621 + @current_categories = environment.top_level_categories.select{|i| !i.children.empty?}
  622 + render :partial => 'shared/select_categories_top', :locals => {:object_name => object_name, :title => title, :title_size => title_size, :multiple => true, :categories_selected => @object.categories }, :layout => false
654 end 623 end
655 624
656 def theme_option(opt = nil) 625 def theme_option(opt = nil)
@@ -1382,16 +1351,16 @@ module ApplicationHelper @@ -1382,16 +1351,16 @@ module ApplicationHelper
1382 end 1351 end
1383 1352
1384 def convert_macro(html, source) 1353 def convert_macro(html, source)
1385 - doc = Nokogiri::HTML(html) 1354 + doc = Hpricot(html)
1386 #TODO This way is more efficient but do not support macro inside of 1355 #TODO This way is more efficient but do not support macro inside of
1387 # macro. You must parse them from the inside-out in order to enable 1356 # macro. You must parse them from the inside-out in order to enable
1388 # that. 1357 # that.
1389 - doc.css('.macro').each do |macro| 1358 + doc.search('.macro').each do |macro|
1390 macro_name = macro['data-macro'] 1359 macro_name = macro['data-macro']
1391 result = @plugins.parse_macro(macro_name, macro, source) 1360 result = @plugins.parse_macro(macro_name, macro, source)
1392 - macro.content = result.kind_of?(Proc) ? self.instance_eval(&result) : result 1361 + macro.inner_html = result.kind_of?(Proc) ? self.instance_eval(&result) : result
1393 end 1362 end
1394 - CGI.unescapeHTML(doc.xpath('//body/*').to_s) 1363 + doc.html
1395 end 1364 end
1396 1365
1397 def default_folder_for_image_upload(profile) 1366 def default_folder_for_image_upload(profile)
app/helpers/boxes_helper.rb
@@ -39,7 +39,7 @@ module BoxesHelper @@ -39,7 +39,7 @@ module BoxesHelper
39 end 39 end
40 40
41 def display_boxes(holder, main_content) 41 def display_boxes(holder, main_content)
42 - boxes = holder.boxes.first(holder.boxes_limit) 42 + boxes = holder.boxes.with_position.first(holder.boxes_limit)
43 content = boxes.reverse.map { |item| display_box(item, main_content) }.join("\n") 43 content = boxes.reverse.map { |item| display_box(item, main_content) }.join("\n")
44 content = main_content if (content.blank?) 44 content = main_content if (content.blank?)
45 45
app/helpers/categories_helper.rb
@@ -48,4 +48,12 @@ module CategoriesHelper @@ -48,4 +48,12 @@ module CategoriesHelper
48 labelled_form_field(_('Type of category'), select_tag('type', options_for_select(TYPES, value))) 48 labelled_form_field(_('Type of category'), select_tag('type', options_for_select(TYPES, value)))
49 end 49 end
50 50
  51 + #FIXME make this test
  52 + def selected_category_link(cat)
  53 + content_tag('div', button_to_function_without_text(:remove, _('Remove'), nil) {|page| page["selected-category-#{cat.id}"].remove} +
  54 + link_to_function(cat.full_name(' &rarr; '), nil, :id => "remove-selected-category-#{cat.id}-button", :class => 'select-subcategory-link') {|page| page["selected-category-#{cat.id}"].remove},
  55 + :class => 'selected-category'
  56 + )
  57 + end
  58 +
51 end 59 end
app/models/box.rb
@@ -5,6 +5,8 @@ class Box &lt; ActiveRecord::Base @@ -5,6 +5,8 @@ class Box &lt; ActiveRecord::Base
5 5
6 include Noosfero::Plugin::HotSpot 6 include Noosfero::Plugin::HotSpot
7 7
  8 + named_scope :with_position, :conditions => ['boxes.position > 0']
  9 +
8 def environment 10 def environment
9 owner ? (owner.kind_of?(Environment) ? owner : owner.environment) : nil 11 owner ? (owner.kind_of?(Environment) ? owner : owner.environment) : nil
10 end 12 end
@@ -24,6 +26,8 @@ class Box &lt; ActiveRecord::Base @@ -24,6 +26,8 @@ class Box &lt; ActiveRecord::Base
24 CategoriesBlock, 26 CategoriesBlock,
25 CommunitiesBlock, 27 CommunitiesBlock,
26 EnterprisesBlock, 28 EnterprisesBlock,
  29 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  30 + # the Noosfero core soon, see ActionItem3045
27 EnvironmentStatisticsBlock, 31 EnvironmentStatisticsBlock,
28 FansBlock, 32 FansBlock,
29 FavoriteEnterprisesBlock, 33 FavoriteEnterprisesBlock,
@@ -50,6 +54,8 @@ class Box &lt; ActiveRecord::Base @@ -50,6 +54,8 @@ class Box &lt; ActiveRecord::Base
50 CommunitiesBlock, 54 CommunitiesBlock,
51 DisabledEnterpriseMessageBlock, 55 DisabledEnterpriseMessageBlock,
52 EnterprisesBlock, 56 EnterprisesBlock,
  57 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  58 + # the Noosfero core soon, see ActionItem3045
53 EnvironmentStatisticsBlock, 59 EnvironmentStatisticsBlock,
54 FansBlock, 60 FansBlock,
55 FavoriteEnterprisesBlock, 61 FavoriteEnterprisesBlock,
app/models/environment.rb
@@ -161,6 +161,8 @@ class Environment &lt; ActiveRecord::Base @@ -161,6 +161,8 @@ class Environment &lt; ActiveRecord::Base
161 161
162 # "left" area 162 # "left" area
163 env.boxes[1].blocks << LoginBlock.new 163 env.boxes[1].blocks << LoginBlock.new
  164 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  165 + # the Noosfero core soon, see ActionItem3045
164 env.boxes[1].blocks << EnvironmentStatisticsBlock.new 166 env.boxes[1].blocks << EnvironmentStatisticsBlock.new
165 env.boxes[1].blocks << RecentDocumentsBlock.new 167 env.boxes[1].blocks << RecentDocumentsBlock.new
166 168
@@ -186,7 +188,7 @@ class Environment &lt; ActiveRecord::Base @@ -186,7 +188,7 @@ class Environment &lt; ActiveRecord::Base
186 has_many :product_categories, :conditions => { :type => 'ProductCategory'} 188 has_many :product_categories, :conditions => { :type => 'ProductCategory'}
187 has_many :regions 189 has_many :regions
188 190
189 - has_many :roles 191 + has_many :roles, :dependent => :destroy
190 192
191 has_many :qualifiers 193 has_many :qualifiers
192 has_many :certifiers 194 has_many :certifiers
app/models/environment_statistics_block.rb
  1 +# TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  2 +# the Noosfero core soon, see ActionItem3045
  3 +
1 class EnvironmentStatisticsBlock < Block 4 class EnvironmentStatisticsBlock < Block
2 5
3 def self.description 6 def self.description
4 - _('Environment stastistics') 7 + _('Environment stastistics (DEPRECATED)')
5 end 8 end
6 9
7 def default_title 10 def default_title
app/models/link_list_block.rb
@@ -63,7 +63,7 @@ class LinkListBlock &lt; Block @@ -63,7 +63,7 @@ class LinkListBlock &lt; Block
63 def link_html(link) 63 def link_html(link)
64 klass = 'icon-' + link[:icon] if link[:icon] 64 klass = 'icon-' + link[:icon] if link[:icon]
65 sanitize_link( 65 sanitize_link(
66 - link_to(link[:name], expand_address(link[:address]), :target => link[:target], :class => klass) 66 + link_to(link[:name], expand_address(link[:address]), :target => link[:target], :class => klass, :title => link[:title])
67 ) 67 )
68 end 68 end
69 69
app/models/profile.rb
@@ -88,6 +88,10 @@ class Profile &lt; ActiveRecord::Base @@ -88,6 +88,10 @@ class Profile &lt; ActiveRecord::Base
88 ScopeTool.union *scopes 88 ScopeTool.union *scopes
89 end 89 end
90 90
  91 + def members_by_name
  92 + members.order(:name)
  93 + end
  94 +
91 def members_count 95 def members_count
92 members.count 96 members.count
93 end 97 end
app/sweepers/profile_sweeper.rb
@@ -8,6 +8,8 @@ class ProfileSweeper # &lt; ActiveRecord::Observer @@ -8,6 +8,8 @@ class ProfileSweeper # &lt; ActiveRecord::Observer
8 end 8 end
9 9
10 def after_create(profile) 10 def after_create(profile)
  11 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  12 + # the Noosfero core soon, see ActionItem3045
11 expire_statistics_block_cache(profile) 13 expire_statistics_block_cache(profile)
12 end 14 end
13 15
@@ -29,6 +31,8 @@ protected @@ -29,6 +31,8 @@ protected
29 expire_blogs(profile) if profile.organization? 31 expire_blogs(profile) if profile.organization?
30 end 32 end
31 33
  34 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  35 + # the Noosfero core soon, see ActionItem3045
32 def expire_statistics_block_cache(profile) 36 def expire_statistics_block_cache(profile)
33 blocks = profile.environment.blocks.select { |b| b.kind_of?(EnvironmentStatisticsBlock) } 37 blocks = profile.environment.blocks.select { |b| b.kind_of?(EnvironmentStatisticsBlock) }
34 BlockSweeper.expire_blocks(blocks) 38 BlockSweeper.expire_blocks(blocks)
app/views/blocks/location.html.erb
@@ -3,7 +3,6 @@ @@ -3,7 +3,6 @@
3 <div class='the-localization-map'> 3 <div class='the-localization-map'>
4 <img src="https://maps.google.com/maps/api/staticmap?center=<%=profile.lat%>,<%=profile.lng%>&zoom=<%=block.zoom%>&size=190x250&maptype=<%=block.map_type%>&markers=<%=profile.lat%>,<%=profile.lng%>&sensor=false"/> 4 <img src="https://maps.google.com/maps/api/staticmap?center=<%=profile.lat%>,<%=profile.lng%>&zoom=<%=block.zoom%>&size=190x250&maptype=<%=block.map_type%>&markers=<%=profile.lat%>,<%=profile.lng%>&sensor=false"/>
5 </div> 5 </div>
6 -</div>  
7 <% else %> 6 <% else %>
8 <i><%= _('This profile has no geographical position registered.') %></i> 7 <i><%= _('This profile has no geographical position registered.') %></i>
9 <% end %> 8 <% end %>
app/views/blocks/profile_image.rhtml
@@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
16 16
17 <% if !user.nil? and user.has_permission?('edit_profile', profile) %> 17 <% if !user.nil? and user.has_permission?('edit_profile', profile) %>
18 <div class='admin-link'> 18 <div class='admin-link'>
19 - <%= link_to _('Control panel'), :controller => 'profile_editor' %> 19 + <%= link_to _('Control panel'), block.owner.admin_url %>
20 </div> 20 </div>
21 <% end %> 21 <% end %>
22 22
app/views/blocks/profile_info.rhtml
@@ -21,7 +21,7 @@ @@ -21,7 +21,7 @@
21 <li><%= link_to(_('Products/Services'), :controller => 'catalog', :profile => block.owner.identifier) %></li> 21 <li><%= link_to(_('Products/Services'), :controller => 'catalog', :profile => block.owner.identifier) %></li>
22 <% end %> 22 <% end %>
23 <% if !user.nil? and user.has_permission?('edit_profile', profile) %> 23 <% if !user.nil? and user.has_permission?('edit_profile', profile) %>
24 - <li><%= link_to _('Control panel'), :controller => 'profile_editor' %></li> 24 + <li><%= link_to _('Control panel'), block.owner.admin_url %></li>
25 <% end %> 25 <% end %>
26 <% if profile.person? %> 26 <% if profile.person? %>
27 <li><%= _('Since %{year}/%{month}') % { :year => block.owner.created_at.year, :month => block.owner.created_at.month } %></li> 27 <li><%= _('Since %{year}/%{month}') % { :year => block.owner.created_at.year, :month => block.owner.created_at.month } %></li>
@@ -40,7 +40,7 @@ @@ -40,7 +40,7 @@
40 <% end %> 40 <% end %>
41 41
42 <div class="profile-info-options"> 42 <div class="profile-info-options">
43 - <%= render :file => view_for_profile_actions(@block.owner.class) %> 43 + <%= render :file => view_for_profile_actions(block.owner.class) %>
44 </div> 44 </div>
45 45
46 </div><!-- end class="vcard" --> 46 </div><!-- end class="vcard" -->
app/views/box_organizer/_link_list_block.rhtml
1 <strong><%= _('Links') %></strong> 1 <strong><%= _('Links') %></strong>
2 -<div id='edit-link-list-block' style='width:450px'> 2 +<div id='edit-link-list-block'>
3 <table id='links' class='noborder'> 3 <table id='links' class='noborder'>
4 - <tr><th><%= _('Icon') %></th><th><%= _('Name') %></th><th><%= _('Address') %></th><th><%= _('Target') %></th></tr> 4 + <tr>
  5 + <th><%= _('Icon') %></th>
  6 + <th><%= _('Name') %></th>
  7 + <th><%= _('Address') %></th>
  8 + <th><%= _('Title') %></th>
  9 + <th><%= _('Target') %></th>
  10 + </tr>
5 <% for link in @block.links do %> 11 <% for link in @block.links do %>
6 - <tr>  
7 - <td>  
8 - <%= icon_selector(link['icon']) %>  
9 - </td>  
10 - <td><%= text_field_tag 'block[links][][name]', link[:name], :class => 'link-name', :maxlength => 20 %></td>  
11 - <td class='cel-address'><%= text_field_tag 'block[links][][address]', link[:address], :class => 'link-address' %></td>  
12 - <td>  
13 - <%= select_tag('block[links][][target]', options_for_select(LinkListBlock::TARGET_OPTIONS, link[:target])) %>  
14 - </td>  
15 - </tr> 12 + <tr>
  13 + <td><%= icon_selector(link['icon']) %></td>
  14 + <td><%= text_field_tag 'block[links][][name]', link[:name], :class => 'link-name', :maxlength => 20 %></td>
  15 + <td class='cel-address'><%= text_field_tag 'block[links][][address]', link[:address], :class => 'link-address' %></td>
  16 + <td><%= text_field_tag 'block[links][][title]', link[:title], :class => 'link-title' %></td>
  17 + <td><%= select_tag('block[links][][target]', options_for_select(LinkListBlock::TARGET_OPTIONS, link[:target])) %></td>
  18 + </tr>
16 <% end %> 19 <% end %>
17 </table> 20 </table>
18 </div> 21 </div>
@@ -22,8 +25,8 @@ @@ -22,8 +25,8 @@
22 content_tag('td', icon_selector('ok')) + 25 content_tag('td', icon_selector('ok')) +
23 content_tag('td', text_field_tag('block[links][][name]', '', :maxlength => 20)) + 26 content_tag('td', text_field_tag('block[links][][name]', '', :maxlength => 20)) +
24 content_tag('td', text_field_tag('block[links][][address]', nil, :class => 'link-address'), :class => 'cel-address') + 27 content_tag('td', text_field_tag('block[links][][address]', nil, :class => 'link-address'), :class => 'cel-address') +
25 - content_tag('td', select_tag('block[links][][target]',  
26 -options_for_select(LinkListBlock::TARGET_OPTIONS, '_self'))) 28 + content_tag('td', text_field_tag('block[links][][title]', '', :class => 'link-title')) +
  29 + content_tag('td', select_tag('block[links][][target]', options_for_select(LinkListBlock::TARGET_OPTIONS, '_self')))
27 ) + 30 ) +
28 javascript_tag("$('edit-link-list-block').scrollTop = $('edit-link-list-block').scrollHeight") 31 javascript_tag("$('edit-link-list-block').scrollTop = $('edit-link-list-block').scrollHeight")
29 end %> 32 end %>
app/views/content_viewer/view_page.rhtml
@@ -40,14 +40,6 @@ @@ -40,14 +40,6 @@
40 </div> 40 </div>
41 <% end %> 41 <% end %>
42 42
43 -<% if !@page.tags.empty? %>  
44 - <div id="article-tags">  
45 - <%= _("This article's tags:") %>  
46 - <%= @page.tags.map { |t| link_to(t, :controller => 'profile', :profile => @profile.identifier, :action => 'tags', :id => t.name ) }.join("\n") %>  
47 - </div>  
48 -<% end %>  
49 -  
50 -  
51 <%= render :partial => 'shared/disabled_enterprise' %> 43 <%= render :partial => 'shared/disabled_enterprise' %>
52 44
53 <% if NOOSFERO_CONF['addthis_enabled'] %> 45 <% if NOOSFERO_CONF['addthis_enabled'] %>
@@ -83,6 +75,13 @@ @@ -83,6 +75,13 @@
83 </div> 75 </div>
84 <% end %> 76 <% end %>
85 77
  78 +<% if !@page.tags.empty? %>
  79 + <div id="article-tags">
  80 + <%= _("This article's tags:") %>
  81 + <%= @page.tags.map { |t| link_to(t, :controller => 'profile', :profile => @profile.identifier, :action => 'tags', :id => t.name ) }.join("\n") %>
  82 + </div>
  83 +<% end %>
  84 +
86 <%= display_source_info(@page) %> 85 <%= display_source_info(@page) %>
87 86
88 <div class="comments" id="comments_list"> 87 <div class="comments" id="comments_list">
app/views/features/_manage_community_fields.rhtml
1 -<h2><%= __('Manage community fields') %></h2>  
2 -  
3 <% labelled_form_for(:environment, @environment, :url => {:action => 'manage_community_fields'}) do |f| %> 1 <% labelled_form_for(:environment, @environment, :url => {:action => 'manage_community_fields'}) do |f| %>
4 2
5 <table id='community_fields_conf'> 3 <table id='community_fields_conf'>
@@ -9,21 +7,37 @@ @@ -9,21 +7,37 @@
9 <th><%= _('Required') %></th> 7 <th><%= _('Required') %></th>
10 <th><%= _('Display on creation?') %></th> 8 <th><%= _('Display on creation?') %></th>
11 </tr> 9 </tr>
  10 +
  11 + <tr class='manage-fields-batch-actions'>
  12 + <td>
  13 + <%= _("Check/Uncheck All")%>
  14 + </td>
  15 + <td>
  16 + <input type="checkbox" id="community_active" />
  17 + </td>
  18 + <td>
  19 + <input type="checkbox" id="community_required" />
  20 + </td>
  21 + <td>
  22 + <input type="checkbox" id="community_signup" />
  23 + </td>
  24 + </tr>
  25 +
12 <% @community_fields.each do |field| %> 26 <% @community_fields.each do |field| %>
13 <tr> 27 <tr>
14 <td><label for="community_fields[<%= field %>][active]"><%= _(field.humanize) %></label></td> 28 <td><label for="community_fields[<%= field %>][active]"><%= _(field.humanize) %></label></td>
15 29
16 <td> 30 <td>
17 <%= hidden_field_tag "community_fields[#{field}][active]", false %> 31 <%= hidden_field_tag "community_fields[#{field}][active]", false %>
18 - <%= check_box_tag "community_fields[#{field}][active]", true, environment.custom_community_field(field, 'active'), :onclick => "$('community_fields[#{field}][required]').disabled=$('community_fields[#{field}][signup]').disabled=!this.checked;" %> 32 + <%= check_box_tag "community_fields[#{field}][active]", true, environment.custom_community_field(field, 'active'), :onclick => "active_action(this, 'community_fields[#{field}][required]', 'community_fields[#{field}][signup]')" %>
19 </td> 33 </td>
20 <td> 34 <td>
21 <%= hidden_field_tag "community_fields[#{field}][required]", false %> 35 <%= hidden_field_tag "community_fields[#{field}][required]", false %>
22 - <%= check_box_tag "community_fields[#{field}][required]", true, environment.custom_community_field(field, 'required'), :onclick => "if(this.checked) $('community_fields[#{field}][signup]').checked = true;" %> 36 + <%= check_box_tag "community_fields[#{field}][required]", true, environment.custom_community_field(field, 'required'), :onclick => "required_action('community_fields[#{field}][active]','community_fields[#{field}][required]', 'community_fields[#{field}][signup]')" %>
23 </td> 37 </td>
24 <td> 38 <td>
25 <%= hidden_field_tag "community_fields[#{field}][signup]", false %> 39 <%= hidden_field_tag "community_fields[#{field}][signup]", false %>
26 - <%= check_box_tag "community_fields[#{field}][signup]", true, environment.custom_community_field(field, 'signup'), :onclick => "if(!this.checked) $('community_fields[#{field}][required]').checked = false;" %> 40 + <%= check_box_tag "community_fields[#{field}][signup]", true, environment.custom_community_field(field, 'signup'), :onclick => "signup_action('community_fields[#{field}][active]','community_fields[#{field}][required]', 'community_fields[#{field}][signup]')" %>
27 </td> 41 </td>
28 42
29 </tr> 43 </tr>
@@ -31,18 +45,18 @@ @@ -31,18 +45,18 @@
31 </table> 45 </table>
32 46
33 <script type='text/javascript'> 47 <script type='text/javascript'>
34 - var trs = $$('#community_fields_conf tr'); 48 + var trs = jQuery('#community_fields_conf tr');
35 var tr, td2; 49 var tr, td2;
36 - for ( var i=0; tr=trs[i]; i++ ) { 50 + for ( var i=2; tr=trs[i]; i++ ) {
37 if ( td2 = tr.getElementsByTagName('td')[1] ) { 51 if ( td2 = tr.getElementsByTagName('td')[1] ) {
38 - td2.getElementsByTagName('input')[0].onclick(); 52 + td2.getElementsByTagName('input')[1].onclick();
39 } 53 }
40 } 54 }
41 </script> 55 </script>
42 56
43 <div> 57 <div>
44 <% button_bar do %> 58 <% button_bar do %>
45 - <%= submit_button('save', _('Save changes')) %> 59 + <%= submit_button('save', _('Save changes'), :id=>"save_community_fields") %>
46 <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %> 60 <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %>
47 <% end %> 61 <% end %>
48 </div> 62 </div>
app/views/features/_manage_enterprise_fields.rhtml
1 -<h2><%= __('Manage enterprise fields') %></h2>  
2 -  
3 <% labelled_form_for(:environment, @environment, :url => {:action => 'manage_enterprise_fields'}) do |f| %> 1 <% labelled_form_for(:environment, @environment, :url => {:action => 'manage_enterprise_fields'}) do |f| %>
4 2
5 <table id='enterprise_fields_conf'> 3 <table id='enterprise_fields_conf'>
@@ -9,21 +7,37 @@ @@ -9,21 +7,37 @@
9 <th><%= _('Required') %></th> 7 <th><%= _('Required') %></th>
10 <th><%= _('Display on registration?') %></th> 8 <th><%= _('Display on registration?') %></th>
11 </tr> 9 </tr>
  10 +
  11 + <tr class='manage-fields-batch-actions'>
  12 + <td>
  13 + <%= _("Check/Uncheck All")%>
  14 + </td>
  15 + <td>
  16 + <input type="checkbox" id="enterprise_active" />
  17 + </td>
  18 + <td>
  19 + <input type="checkbox" id="enterprise_required" />
  20 + </td>
  21 + <td>
  22 + <input type="checkbox" id="enterprise_signup" />
  23 + </td>
  24 + </tr>
  25 +
12 <% @enterprise_fields.each do |field| %> 26 <% @enterprise_fields.each do |field| %>
13 <tr> 27 <tr>
14 28
15 <td><label for="enterprise_fields[<%= field %>][active]"><%= _(field.humanize) %></label></td> 29 <td><label for="enterprise_fields[<%= field %>][active]"><%= _(field.humanize) %></label></td>
16 <td> 30 <td>
17 <%= hidden_field_tag "enterprise_fields[#{field}][active]", false %> 31 <%= hidden_field_tag "enterprise_fields[#{field}][active]", false %>
18 - <%= check_box_tag "enterprise_fields[#{field}][active]", true, environment.custom_enterprise_field(field, 'active'), :onclick => "$('enterprise_fields[#{field}][required]').disabled=$('enterprise_fields[#{field}][signup]').disabled=!this.checked;" %> 32 + <%= check_box_tag "enterprise_fields[#{field}][active]", true, environment.custom_enterprise_field(field, 'active'), :onclick => "active_action(this, 'enterprise_fields[#{field}][required]', 'enterprise_fields[#{field}][signup]')" %>
19 </td> 33 </td>
20 <td> 34 <td>
21 <%= hidden_field_tag "enterprise_fields[#{field}][required]", false %> 35 <%= hidden_field_tag "enterprise_fields[#{field}][required]", false %>
22 - <%= check_box_tag "enterprise_fields[#{field}][required]", true, environment.custom_enterprise_field(field, 'required'), :onclick => "if(this.checked) $('enterprise_fields[#{field}][signup]').checked = true;" %> 36 + <%= check_box_tag "enterprise_fields[#{field}][required]", true, environment.custom_enterprise_field(field, 'required'), :onclick => "required_action('enterprise_fields[#{field}][active]','enterprise_fields[#{field}][required]', 'enterprise_fields[#{field}][signup]')" %>
23 </td> 37 </td>
24 <td> 38 <td>
25 <%= hidden_field_tag "enterprise_fields[#{field}][signup]", false %> 39 <%= hidden_field_tag "enterprise_fields[#{field}][signup]", false %>
26 - <%= check_box_tag "enterprise_fields[#{field}][signup]", true, environment.custom_enterprise_field(field, 'signup'), :onclick => "if(!this.checked) $('enterprise_fields[#{field}][required]').checked = false;" %> 40 + <%= check_box_tag "enterprise_fields[#{field}][signup]", true, environment.custom_enterprise_field(field, 'signup'), :onclick => "signup_action('enterprise_fields[#{field}][active]','enterprise_fields[#{field}][required]', 'enterprise_fields[#{field}][signup]')" %>
27 </td> 41 </td>
28 42
29 </tr> 43 </tr>
@@ -31,18 +45,18 @@ @@ -31,18 +45,18 @@
31 </table> 45 </table>
32 46
33 <script type='text/javascript'> 47 <script type='text/javascript'>
34 - var trs = $$('#enterprise_fields_conf tr'); 48 + var trs = jQuery('#enterprise_fields_conf tr');
35 var tr, td2; 49 var tr, td2;
36 - for ( var i=0; tr=trs[i]; i++ ) { 50 + for ( var i=2; tr=trs[i]; i++ ) {
37 if ( td2 = tr.getElementsByTagName('td')[1] ) { 51 if ( td2 = tr.getElementsByTagName('td')[1] ) {
38 - td2.getElementsByTagName('input')[0].onclick(); 52 + td2.getElementsByTagName('input')[1].onclick();
39 } 53 }
40 } 54 }
41 </script> 55 </script>
42 56
43 <div> 57 <div>
44 <% button_bar do %> 58 <% button_bar do %>
45 - <%= submit_button('save', _('Save changes')) %> 59 + <%= submit_button('save', _('Save changes'), :id=>"save_enterprise_fields") %>
46 <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %> 60 <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %>
47 <% end %> 61 <% end %>
48 </div> 62 </div>
app/views/features/_manage_person_fields.rhtml
1 -<h2><%= _('Manage person fields') %></h2>  
2 -  
3 <% labelled_form_for(:environment, @environment, :url => {:action => 'manage_person_fields'}) do |f| %> 1 <% labelled_form_for(:environment, @environment, :url => {:action => 'manage_person_fields'}) do |f| %>
4 2
5 <table id='person_fields_conf'> 3 <table id='person_fields_conf'>
@@ -9,31 +7,48 @@ @@ -9,31 +7,48 @@
9 <th><%= _('Required') %></th> 7 <th><%= _('Required') %></th>
10 <th><%= _('Display on signup?') %></th> 8 <th><%= _('Display on signup?') %></th>
11 </tr> 9 </tr>
  10 +
  11 + <tr class='manage-fields-batch-actions'>
  12 + <td>
  13 + <%= _("Check/Uncheck All")%>
  14 + </td>
  15 + <td>
  16 + <input type="checkbox" id="person_active" />
  17 + </td>
  18 + <td>
  19 + <input type="checkbox" id="person_required" />
  20 + </td>
  21 + <td>
  22 + <input type="checkbox" id="person_signup" />
  23 + </td>
  24 + </tr>
  25 +
12 <% @person_fields.each do |field| %> 26 <% @person_fields.each do |field| %>
13 <tr> 27 <tr>
14 <td><label for="person_fields[<%= field %>][active]"><%= _(field.humanize) %></label></td> 28 <td><label for="person_fields[<%= field %>][active]"><%= _(field.humanize) %></label></td>
15 <td> 29 <td>
16 <%= hidden_field_tag "person_fields[#{field}][active]", false %> 30 <%= hidden_field_tag "person_fields[#{field}][active]", false %>
17 - <%= check_box_tag "person_fields[#{field}][active]", true, environment.custom_person_field(field, 'active'), :onclick => "$('person_fields[#{field}][required]').disabled=$('person_fields[#{field}][signup]').disabled=!this.checked;" %> 31 + <%= check_box_tag "person_fields[#{field}][active]", true, environment.custom_person_field(field, 'active'), :onclick => "active_action(this, 'person_fields[#{field}][required]', 'person_fields[#{field}][signup]')" %>
18 </td> 32 </td>
19 <td> 33 <td>
20 <%= hidden_field_tag "person_fields[#{field}][required]", false %> 34 <%= hidden_field_tag "person_fields[#{field}][required]", false %>
21 - <%= check_box_tag "person_fields[#{field}][required]", true, environment.custom_person_field(field, 'required'), :onclick => "if(this.checked) $('person_fields[#{field}][signup]').checked = true;" %> 35 + <%= check_box_tag "person_fields[#{field}][required]", true, environment.custom_person_field(field, 'required'), :onclick => "required_action('person_fields[#{field}][active]','person_fields[#{field}][required]', 'person_fields[#{field}][signup]')" %>
22 </td> 36 </td>
23 <td> 37 <td>
24 <%= hidden_field_tag "person_fields[#{field}][signup]", false %> 38 <%= hidden_field_tag "person_fields[#{field}][signup]", false %>
25 - <%= check_box_tag "person_fields[#{field}][signup]", true, environment.custom_person_field(field, 'signup'), :onclick => "if(!this.checked) $('person_fields[#{field}][required]').checked = false;" %> 39 + <%= check_box_tag "person_fields[#{field}][signup]", true, environment.custom_person_field(field, 'signup'), :onclick => "signup_action('person_fields[#{field}][active]','person_fields[#{field}][required]', 'person_fields[#{field}][signup]')" %>
26 </td> 40 </td>
27 </tr> 41 </tr>
28 <% end %> 42 <% end %>
29 </table> 43 </table>
30 44
31 <script type='text/javascript'>// <!-- 45 <script type='text/javascript'>// <!--
32 - var trs = $$('#person_fields_conf tr'); 46 + var trs = jQuery('#person_fields_conf tr');
  47 +
33 var tr, td2; 48 var tr, td2;
34 - for ( var i=0; tr=trs[i]; i++ ) { 49 + for ( var i=2; tr=trs[i]; i++ ) {
35 if ( td2 = tr.getElementsByTagName('td')[1] ) { 50 if ( td2 = tr.getElementsByTagName('td')[1] ) {
36 - td2.getElementsByTagName('input')[0].onclick(); 51 + td2.getElementsByTagName('input')[1].onclick();
37 } 52 }
38 } 53 }
39 // --> 54 // -->
@@ -41,7 +56,7 @@ @@ -41,7 +56,7 @@
41 56
42 <div> 57 <div>
43 <% button_bar do %> 58 <% button_bar do %>
44 - <%= submit_button('save', _('Save changes')) %> 59 + <%= submit_button('save', _('Save changes'), :id=>"save_person_fields") %>
45 <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %> 60 <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %>
46 <% end %> 61 <% end %>
47 </div> 62 </div>
app/views/features/manage_fields.rhtml
1 -<%= render :partial => 'manage_person_fields' %> 1 +<h1><%= _('Manage fields displayed for profiles') %></h1>
2 2
3 -<% if !environment.enabled?('disable_asset_enterprises') %>  
4 - <%= render :partial => 'manage_enterprise_fields' %> 3 +<% tabs = [] %>
  4 +<% tabs << {:title => _("Person's fields"), :id => 'person-fields',
  5 + :content => (render :partial => 'manage_person_fields')} %>
  6 +<% tabs << {:title => _("Community's fields"), :id => 'community-fields',
  7 + :content => (render :partial => 'manage_community_fields')} %>
  8 +<% unless environment.enabled?('disable_asset_enterprises') %>
  9 + <% tabs << {:title => _("Enterprise's fields"), :id => 'enterprise-fields',
  10 + :content => (render :partial => 'manage_enterprise_fields')} %>
5 <% end %> 11 <% end %>
6 12
7 -<%= render :partial => 'manage_community_fields' %> 13 +<%= render_tabs(tabs) %>
  14 +
  15 +<%= javascript_include_tag "manage-fields.js" %>
app/views/profile_members/_members_list.rhtml
1 -<% collection = @collection == :profile_admins ? profile.admins : profile.members %> 1 +<% collection = @collection == :profile_admins ? profile.admins : profile.members_by_name %>
2 <% title = @title ? @title : _('Current members') %> 2 <% title = @title ? @title : _('Current members') %>
3 <% remove_action = @remove_action ? @remove_action : {:action => 'unassociate'} %> 3 <% remove_action = @remove_action ? @remove_action : {:action => 'unassociate'} %>
4 4
app/views/shared/_select_categories.rhtml
1 -<div id="category-ajax-selector"> 1 +<% extend CategoriesHelper %>
  2 +
2 <% if !@current_category.nil? %> 3 <% if !@current_category.nil? %>
3 - <h3 class="box-title"><%= _('Current category:') %></h3>  
4 <%= hidden_field_tag "#{object_name}[#{object_name}_category_id]", @current_category.id unless multiple %> 4 <%= hidden_field_tag "#{object_name}[#{object_name}_category_id]", @current_category.id unless multiple %>
  5 + <%= hidden_field_tag "#{object_name}[category_ids][]", @current_category.id if multiple %>
  6 + <%= button_to_remote_without_text(:back, _('Back'),
  7 + { :update => "select-categories",
  8 + :url => { :action => 'update_categories', :id => @object },
  9 + :loaded => visual_effect(:highlight, "select-categories")
  10 + },
  11 + :id => 'cancel-category-button') %>
5 <% 12 <%
6 categories = [@current_category] 13 categories = [@current_category]
7 categories.push(@current_category) while @current_category = @current_category.parent 14 categories.push(@current_category) while @current_category = @current_category.parent
8 %> 15 %>
9 <%= categories.compact.reverse.map{|i| 16 <%= categories.compact.reverse.map{|i|
10 - link_to_remote(i.name, 17 + link_to_remote(i.name,
11 :update => "select-categories", 18 :update => "select-categories",
12 :url => { :action => 'update_categories', :category_id => i.id, :id => @object }, 19 :url => { :action => 'update_categories', :category_id => i.id, :id => @object },
13 :loaded => visual_effect(:highlight, "select-categories"), 20 :loaded => visual_effect(:highlight, "select-categories"),
14 :class => 'select-current-category-link')}.join(' &rarr; ') 21 :class => 'select-current-category-link')}.join(' &rarr; ')
15 %> 22 %>
16 - <strong>  
17 - <%= button_to_function_without_text(:save, _('Save'), nil, :id => 'save-category-button') do |page|  
18 - page.insert_html :bottom, 'selected-categories', content_tag('li', categories.first.full_name + 23 + <%= button_to_function_without_text(:add, _('Add'), nil, :id => 'save-category-button') do |page|
  24 + page.insert_html :bottom, 'selected-categories', content_tag('div',
19 hidden_field_tag("#{object_name}[category_ids][]", categories.first.id) + 25 hidden_field_tag("#{object_name}[category_ids][]", categories.first.id) +
20 - button_to_function_without_text(:cancel, _('Remove'), nil, :id => "remove-selected-category-#{categories.first.id}-button") {|page| page["selected-category-#{categories.first.id}"].remove}, :id => "selected-category-#{categories.first.id}") 26 + selected_category_link(categories.first), :id => "selected-category-#{categories.first.id}")
  27 + page.replace_html 'select-categories', :partial => 'shared/select_subcategories',
  28 + :locals => {:object_name => object_name, :categories => @toplevel_categories}
21 end if multiple %> 29 end if multiple %>
22 - <%= button_to_remote_without_text(:cancel, _('Cancel'),  
23 - { :update => "select-categories",  
24 - :url => { :action => 'update_categories', :id => @object },  
25 - :loaded => visual_effect(:highlight, "select-categories")  
26 - },  
27 - :id => 'cancel-category-button') %>  
28 - </strong>  
29 -<% else %>  
30 - <h3 class="box-title"><%= _('Select a category:') %></h3>  
31 <% end %> 30 <% end %>
32 31
33 -<% if !@categories.empty? %>  
34 - <h3><%= _('Categories:') %></h3>  
35 - <% @categories.select{|i| !@object.respond_to?(:accept_category?) || @object.accept_category?(i)}.each do |category| %>  
36 - <%= link_to_remote category.name,  
37 - { :update => "select-categories",  
38 - :url => { :action => "update_categories", :category_id => category.id, :id => @object},  
39 - :loaded => visual_effect(:highlight, "select-categories")  
40 - },  
41 - :class => 'select-subcategory-link',  
42 - :id => "select-category-#{category.id}-link"  
43 - %>  
44 - <% end %> &nbsp;  
45 -<% end %> 32 +<div class="toplevel-categories">
  33 + <%= render :partial => 'shared/select_subcategories', :locals => {:object_name => object_name, :categories => @categories} %>
46 </div> 34 </div>
app/views/shared/_select_categories_top.rhtml 0 → 100644
@@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
  1 +<% categories_selected ||= nil %>
  2 +<% title ||= nil %>
  3 +
  4 +<% extend CategoriesHelper %>
  5 +
  6 +<%= content_tag "h#{title_size}", title, :class => "box-title" %>
  7 +
  8 +<%= hidden_field_tag "#{object_name}[category_ids][]", nil %>
  9 +
  10 +<div id="category-ajax-selector">
  11 +<% unless categories_selected.nil? %>
  12 +<div id="selected-categories">
  13 + <div class="label"><%= _('Selected categories:') %></div>
  14 + <% categories_selected.each do |cat| %>
  15 + <div id="selected-category-<%= cat.id %>">
  16 + <%= hidden_field_tag("#{object_name}[category_ids][]", cat.id) %>
  17 + <%= selected_category_link(cat) %>
  18 + </div>
  19 + <% end %>
  20 +</div>
  21 +<% end %>
  22 +<div id="select-categories">
  23 + <%= render :partial => 'shared/select_categories', :locals => {:object_name => object_name, :multiple => true, :categories_selected => categories_selected }, :layout => false %>
  24 +</div>
  25 +
  26 +</div>
app/views/shared/_select_subcategories.rhtml 0 → 100644
@@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
  1 +<% if !categories.nil? && !categories.empty? && !@object.nil? %>
  2 + <hr>
  3 + <div class="category-helper-label"><%= _('Click to select a category') %></div>
  4 +
  5 + <% categories.select{|i| @object.accept_category?(i)}.each do |category| %>
  6 +
  7 + <%= link_to_remote category.name,
  8 + { :update => "select-categories",
  9 + :url => { :action => "update_categories", :category_id => category.id, :id => @object},
  10 + :loaded => visual_effect(:highlight, "select-categories")
  11 + },
  12 + :class => 'select-subcategory-link',
  13 + :id => "select-category-#{category.id}-link"
  14 + %>
  15 + <% end %>
  16 +<% end %>
app/views/users/_users_list.rhtml
@@ -19,16 +19,17 @@ @@ -19,16 +19,17 @@
19 <td class='actions'> 19 <td class='actions'>
20 <div class="members-buttons-cell"> 20 <div class="members-buttons-cell">
21 <% if p.is_admin? %> 21 <% if p.is_admin? %>
22 - <%= button_without_text :'reset-admin-role', _('Reset admin role'), :action => 'reset_admin_role', :id => p, :q => @q, :filter => @filter %> 22 + <%= button_without_text :'reset-admin-role', _('Reset admin role'), {:action => 'reset_admin_role', :id => p, :q => @q}, :filter => @filter, :confirm => _("Do you want to reset this user as administrator?") %>
23 <% else %> 23 <% else %>
24 - <%= button_without_text :'set-admin-role', _('Set admin role'), :action => 'set_admin_role', :id => p, :q => @q, :filter => @filter %> 24 + <%= button_without_text :'set-admin-role', _('Set admin role'), {:action => 'set_admin_role', :id => p, :q => @q}, :filter => @filter, :confirm => _("Do you want to set this user as administrator?") %>
25 <% end %> 25 <% end %>
26 <% if !p.user.activated? %> 26 <% if !p.user.activated? %>
27 - <%= button_without_text :'activate-user', _('Activate user'), :action => 'activate', :id => p, :q => @q, :filter => @filter %> 27 + <%= button_without_text :'activate-user', _('Activate user'), {:action => 'activate', :id => p, :q => @q}, :filter => @filter, :confirm => _("Do you want to activate this user?") %>
28 <% else %> 28 <% else %>
29 - <%= button_without_text :'deactivate-user', _('Deactivate user'), :action => 'deactivate', :id => p, :q => @q, :filter => @filter %> 29 + <%= button_without_text :'deactivate-user', _('Deactivate user'), {:action => 'deactivate', :id => p, :q => @q}, :filter => @filter, :confirm => _("Do you want to deactivate this user?") %>
30 <% end %> 30 <% end %>
31 - </div> 31 + <%= button_without_text :'delete', _('Remove'), {:action => :destroy_user, :id => p, :q => @q}, :method => :post, :filter => @filter, :confirm => _("Do you want to remove this user?") %>
  32 + </div>
32 </td> 33 </td>
33 </tr> 34 </tr>
34 <% end %> 35 <% end %>
config/initializers/dependencies.rb
@@ -8,4 +8,3 @@ require &#39;route_if&#39; @@ -8,4 +8,3 @@ require &#39;route_if&#39;
8 8
9 # third-party libraries 9 # third-party libraries
10 require 'will_paginate' 10 require 'will_paginate'
11 -require 'nokogiri'  
debian/changelog
  1 +noosfero (0.46.1) unstable; urgency=low
  2 +
  3 + * Bugfixes release
  4 +
  5 + -- Daniela Soares Feitosa <daniela@colivre.coop.br> Fri, 07 Mar 2014 10:33:11 +0000
  6 +
1 noosfero (0.46.0) unstable; urgency=low 7 noosfero (0.46.0) unstable; urgency=low
2 8
3 * New features release 9 * New features release
debian/control
@@ -41,7 +41,6 @@ Depends: @@ -41,7 +41,6 @@ Depends:
41 thin, 41 thin,
42 tango-icon-theme, 42 tango-icon-theme,
43 libhpricot-ruby, 43 libhpricot-ruby,
44 - libnokogiri-ruby,  
45 memcached, 44 memcached,
46 debconf, 45 debconf,
47 dbconfig-common, 46 dbconfig-common,
features/manage_fields.feature 0 → 100644
@@ -0,0 +1,76 @@ @@ -0,0 +1,76 @@
  1 +Feature: check all manage fields
  2 + As an administrator
  3 + I want to check and uncheck all person, enterprise and community's fields
  4 +
  5 + Background:
  6 + Given the following users
  7 + | login | name |
  8 + | mariasilva | Maria Silva |
  9 + And the following enterprises
  10 + | identifier | owner | name | contact_email | contact_phone | enabled |
  11 + | paper-street | mariasilva | Paper Street | marial.silva@workerbees.org | (288) 555-0153 | true |
  12 + And the following community
  13 + | identifier | name |
  14 + | mycommunity | My Community |
  15 + And I am logged in as admin
  16 + And I go to /admin/features/manage_fields
  17 +
  18 + @selenium
  19 + Scenario: check all active person fields
  20 + Given I follow "Person's fields"
  21 + And I check "person_active"
  22 + And I press "save_person_fields"
  23 + When I go to admin_user's control panel
  24 + And I follow "Edit Profile"
  25 + Then I should see "Custom area of study"
  26 +
  27 + @selenium
  28 + Scenario: check all active enterprise fields
  29 + Given I follow "Enterprise's fields"
  30 + And I check "enterprise_active"
  31 + And I press "save_enterprise_fields"
  32 + When I go to paper-street's control panel
  33 + And I follow "Enterprise Info and settings"
  34 + Then I should see "Historic and current context"
  35 +
  36 + @selenium
  37 + Scenario: check all active community fields
  38 + Given I follow "Community's fields"
  39 + And I check "community_active"
  40 + And I press "save_community_fields"
  41 + When I go to mycommunity's control panel
  42 + And I follow "Community Info and settings"
  43 + Then I should see "Economic activity"
  44 +
  45 + @selenium
  46 + Scenario: uncheck Check/Uncheck All active person field
  47 + Given I follow "Person's fields"
  48 + And I check "person_active"
  49 + And I press "save_person_fields"
  50 + And I uncheck "person_active"
  51 + And I press "save_person_fields"
  52 + And I follow "Control panel"
  53 + When I follow "Edit Profile"
  54 + Then I should not see "Custom area of study"
  55 +
  56 + @selenium
  57 + Scenario: uncheck Check/Uncheck All active community field
  58 + Given I follow "Community's fields"
  59 + And I check "community_active"
  60 + And I press "save_community_fields"
  61 + And I uncheck "community_active"
  62 + And I press "save_community_fields"
  63 + When I go to mycommunity's control panel
  64 + And I follow "Community Info and settings"
  65 + Then I should not see "Economic activity"
  66 +
  67 + @selenium
  68 + Scenario: uncheck Check/Uncheck All active enterprise field
  69 + Given I follow "Enterprise's fields"
  70 + And I check "enterprise_active"
  71 + And I press "save_enterprise_fields"
  72 + And I uncheck "enterprise_active"
  73 + And I press "save_enterprise_fields"
  74 + When I go to paper-street's control panel
  75 + And I follow "Enterprise Info and settings"
  76 + Then I should not see "Historic and current context"
features/manage_users.feature 0 → 100644
@@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
  1 +Feature: manage users
  2 + As an environment administrator
  3 + I want to manage users
  4 + In order to remove, activate, deactivate users, and set admin roles.
  5 +
  6 +Background:
  7 + Given the following users
  8 + | login | name |
  9 + | joaosilva | Joao Silva |
  10 + | paulosantos | Paulo Santos |
  11 + Given I am logged in as admin
  12 + Given I go to /admin/users
  13 +
  14 + @selenium
  15 + Scenario: deactive user
  16 + When I follow "Deactivate user" within "tr[title='Joao Silva']"
  17 + And I confirm the "Do you want to deactivate this user?" dialog
  18 + Then I should see "Activate user" within "tr[title='Joao Silva']"
  19 +
  20 + @selenium
  21 + Scenario: activate user
  22 + Given I follow "Deactivate user" within "tr[title='Paulo Santos']"
  23 + Given I confirm the "Do you want to deactivate this user?" dialog
  24 + When I follow "Activate user" within "tr[title='Paulo Santos']"
  25 + And I confirm the "Do you want to activate this user?" dialog
  26 + Then I should see "Deactivate user" within "tr[title='Paulo Santos']"
  27 +
  28 + @selenium
  29 + Scenario: remove user
  30 + When I follow "Remove" within "tr[title='Joao Silva']"
  31 + And I confirm the "Do you want to remove this user?" dialog
  32 + And I go to /admin/users
  33 + Then I should not see "Joao Silva"
  34 +
  35 + @selenium
  36 + Scenario: admin user
  37 + When I follow "Set admin role" within "tr[title='Joao Silva']"
  38 + And I confirm the "Do you want to set this user as administrator?" dialog
  39 + Then I should see "Reset admin role" within "tr[title='Joao Silva']"
  40 +
  41 + @selenium
  42 + Scenario: unadmin user
  43 + Given I follow "Set admin role" within "tr[title='Paulo Santos']"
  44 + And I confirm the "Do you want to set this user as administrator?" dialog
  45 + When I follow "Reset admin role" within "tr[title='Paulo Santos']"
  46 + And I confirm the "Do you want to reset this user as administrator?" dialog
  47 + Then I should see "Set admin role" within "tr[title='Paulo Santos']"
lib/noosfero.rb
@@ -3,7 +3,7 @@ require &#39;fast_gettext&#39; @@ -3,7 +3,7 @@ require &#39;fast_gettext&#39;
3 3
4 module Noosfero 4 module Noosfero
5 PROJECT = 'noosfero' 5 PROJECT = 'noosfero'
6 - VERSION = '0.46.0' 6 + VERSION = '0.46.1'
7 7
8 def self.pattern_for_controllers_in_directory(dir) 8 def self.pattern_for_controllers_in_directory(dir)
9 disjunction = controllers_in_directory(dir).join('|') 9 disjunction = controllers_in_directory(dir).join('|')
lib/noosfero/core_ext.rb
1 require 'noosfero/core_ext/string' 1 require 'noosfero/core_ext/string'
2 require 'noosfero/core_ext/integer' 2 require 'noosfero/core_ext/integer'
  3 +require 'noosfero/core_ext/array'
3 require 'noosfero/core_ext/object' 4 require 'noosfero/core_ext/object'
4 require 'noosfero/core_ext/active_record' 5 require 'noosfero/core_ext/active_record'
lib/noosfero/core_ext/array.rb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +class Array
  2 +
  3 + def uniq_by
  4 + hash, array = {}, []
  5 + each { |i| hash[yield(i)] ||= (array << i) }
  6 + array
  7 + end
  8 +
  9 +end
lib/noosfero/plugin/macro.rb
@@ -33,9 +33,9 @@ class Noosfero::Plugin::Macro @@ -33,9 +33,9 @@ class Noosfero::Plugin::Macro
33 end 33 end
34 34
35 def attributes(macro) 35 def attributes(macro)
36 - macro.attributes. 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].value})}. 38 + inject({}){|result, a| result.merge({a[0][11..-1] => a[1]})}.
39 with_indifferent_access 39 with_indifferent_access
40 end 40 end
41 41
lib/noosfero/plugin/routes.rb
@@ -15,12 +15,16 @@ Dir.glob(File.join(Rails.root, plugins_root, &#39;*&#39;, &#39;controllers&#39;)) do |controller @@ -15,12 +15,16 @@ Dir.glob(File.join(Rails.root, plugins_root, &#39;*&#39;, &#39;controllers&#39;)) do |controller
15 controllers_by_folder.each do |folder, controllers| 15 controllers_by_folder.each do |folder, controllers|
16 controllers.each do |controller| 16 controllers.each do |controller|
17 controller_name = controller.gsub("#{plugin_name}_plugin_",'') 17 controller_name = controller.gsub("#{plugin_name}_plugin_",'')
18 - map.connect "#{prefixes_by_folder[folder]}/#{plugin_name}/#{controller_name}/:action/:id", :controller => controller 18 + if %w[profile myprofile].include?(folder)
  19 + map.connect "#{prefixes_by_folder[folder]}/#{plugin_name}/#{controller_name}/:action/:id", :controller => controller, :profile => /#{Noosfero.identifier_format}/
  20 + else
  21 + map.connect "#{prefixes_by_folder[folder]}/#{plugin_name}/#{controller_name}/:action/:id", :controller => controller
  22 + end
19 end 23 end
20 end 24 end
21 25
22 map.connect 'plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin' 26 map.connect 'plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin'
23 - map.connect 'profile/:profile/plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_profile'  
24 - map.connect 'myprofile/:profile/plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_myprofile' 27 + map.connect 'profile/:profile/plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_profile', :profile => /#{Noosfero.identifier_format}/
  28 + map.connect 'myprofile/:profile/plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_myprofile', :profile => /#{Noosfero.identifier_format}/
25 map.connect 'admin/plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_admin' 29 map.connect 'admin/plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_admin'
26 end 30 end
plugins/comment_classification/README.md 0 → 100644
@@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
  1 +README - Comment Classification Plugin
  2 +======================================
  3 +
  4 +This plugin creates the structure for classifying the comments. The
  5 +initial idea of this plugin is to support the management of public
  6 +consulting, but it can be used in different contexts.
  7 +For now, two kind of classification will be available:
  8 +
  9 + * Label: when creating a comment, the user identify the kind of it by
  10 +choosing the label of the comment. Example: "Suggestion",
  11 +"Disagreement"...
  12 + * Status: users with permission can include a Status for a comment.
  13 +Example: "Merged", "Unmerged"
  14 +
  15 +Dependency
  16 +==========
  17 +
  18 +This plugin was developed to help public consulting and needs the
  19 +CommentGroupPlugin enabled to be used.
plugins/comment_classification/controllers/admin/comment_classification_plugin_labels_controller.rb 0 → 100644
@@ -0,0 +1,55 @@ @@ -0,0 +1,55 @@
  1 +class CommentClassificationPluginLabelsController < AdminController
  2 + append_view_path File.join(File.dirname(__FILE__) + '/../../views')
  3 +
  4 + def index
  5 +# @labels = @environment.labels
  6 + @labels = CommentClassificationPlugin::Label.all
  7 + end
  8 +
  9 + def create
  10 + @label = CommentClassificationPlugin::Label.new(params[:label])
  11 + @colors = CommentClassificationPlugin::Label::COLORS
  12 + if request.post?
  13 + begin
  14 + @label.owner = environment
  15 + @label.save!
  16 + session[:notice] = _('Label created')
  17 + redirect_to :action => 'index'
  18 + rescue
  19 + session[:notice] = _('Label could not be created')
  20 + end
  21 + end
  22 + end
  23 +
  24 + def edit
  25 +# @labels = @environment.labels.find(params[:id])
  26 + @label = CommentClassificationPlugin::Label.find(params[:id])
  27 + @colors = CommentClassificationPlugin::Label::COLORS
  28 + if request.post?
  29 + begin
  30 + @label.update_attributes!(params[:label])
  31 + session[:notice] = _('Label updated')
  32 + redirect_to :action => :index
  33 + rescue
  34 + session[:notice] = _('Failed to edit label')
  35 + end
  36 + end
  37 + end
  38 +
  39 + def remove
  40 +# @label = environment.labels.find(params[:label])
  41 + @label = CommentClassificationPlugin::Label.find(params[:id])
  42 + if request.post?
  43 + begin
  44 + @label.destroy
  45 + session[:notice] = _('Label removed')
  46 + rescue
  47 + session[:notice] = _('Label could not be removed')
  48 + end
  49 + else
  50 + session[:notice] = _('Label could not be removed')
  51 + end
  52 + redirect_to :action => 'index'
  53 + end
  54 +
  55 +end
plugins/comment_classification/controllers/admin/comment_classification_plugin_status_controller.rb 0 → 100644
@@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
  1 +class CommentClassificationPluginStatusController < AdminController
  2 + append_view_path File.join(File.dirname(__FILE__) + '/../../views')
  3 +
  4 + def index
  5 +# @labels = @environment.labels
  6 + @status = CommentClassificationPlugin::Status.all
  7 + end
  8 +
  9 + def create
  10 + @status = CommentClassificationPlugin::Status.new(params[:status])
  11 + if request.post?
  12 + begin
  13 + @status.owner = environment
  14 + @status.save!
  15 + session[:notice] = _('Status created')
  16 + redirect_to :action => 'index'
  17 + rescue
  18 + session[:notice] = _('Status could not be created')
  19 + end
  20 + end
  21 + end
  22 +
  23 + def edit
  24 +# @labels = @environment.labels.find(params[:id])
  25 + @status = CommentClassificationPlugin::Status.find(params[:id])
  26 + if request.post?
  27 + begin
  28 + @status.update_attributes!(params[:status])
  29 + session[:notice] = _('Status updated')
  30 + redirect_to :action => :index
  31 + rescue
  32 + session[:notice] = _('Failed to edit status')
  33 + end
  34 + end
  35 + end
  36 +
  37 + def remove
  38 +# @label = environment.labels.find(params[:label])
  39 + @status = CommentClassificationPlugin::Status.find(params[:id])
  40 + if request.post?
  41 + begin
  42 + @status.destroy
  43 + session[:notice] = _('Status removed')
  44 + rescue
  45 + session[:notice] = _('Status could not be removed')
  46 + end
  47 + else
  48 + session[:notice] = _('Status could not be removed')
  49 + end
  50 + redirect_to :action => 'index'
  51 + end
  52 +
  53 +end
plugins/comment_classification/controllers/comment_classification_plugin_admin_controller.rb 0 → 100644
@@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
  1 +class CommentClassificationPluginAdminController < AdminController
  2 + append_view_path File.join(File.dirname(__FILE__) + '/../views')
  3 +
  4 + def index
  5 + end
  6 +
  7 +end
plugins/comment_classification/controllers/comment_classification_plugin_myprofile_controller.rb 0 → 100644
@@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
  1 +class CommentClassificationPluginMyprofileController < MyProfileController
  2 + append_view_path File.join(File.dirname(__FILE__) + '/../views')
  3 +
  4 + before_filter :organizations_only
  5 + protect 'moderate_comments', :profile
  6 +
  7 + def index
  8 + @comments = Comment.all
  9 + end
  10 +
  11 + def add_status
  12 + @comment = Comment.find(params[:id])
  13 + @statuses = CommentClassificationPlugin::Status.enabled
  14 + @status = CommentClassificationPlugin::CommentStatusUser.new(:profile => user, :comment => @comment)
  15 + if request.post? && params[:status]
  16 + @status.update_attributes(params[:status])
  17 + @status.save
  18 + end
  19 + end
  20 +
  21 + private
  22 +
  23 + def organizations_only
  24 + render_not_found if !profile.organization?
  25 + end
  26 +end
plugins/comment_classification/db/migrate/20130822043033_create_comments_labels.rb 0 → 100644
@@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
  1 +class CreateCommentsLabels < ActiveRecord::Migration
  2 + def self.up
  3 + create_table :comment_classification_plugin_labels do |t|
  4 + t.string :name
  5 + t.string :color
  6 + t.boolean :enabled, :default => true
  7 + t.references :owner, :polymorphic => true
  8 +
  9 + t.timestamps
  10 + end
  11 + end
  12 +
  13 + def self.down
  14 + drop_table :comment_classification_plugin_labels
  15 + end
  16 +end
plugins/comment_classification/db/migrate/20130822075623_create_comment_label_user.rb 0 → 100644
@@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
  1 +class CreateCommentLabelUser < ActiveRecord::Migration
  2 + def self.up
  3 + create_table :comment_classification_plugin_comment_label_user do |t|
  4 + t.references :profile
  5 + t.references :comment
  6 + t.references :label
  7 +
  8 + t.timestamps
  9 + end
  10 +
  11 + end
  12 +
  13 + def self.down
  14 + drop_table :comment_classification_plugin_comment_label_user
  15 + end
  16 +end
plugins/comment_classification/db/migrate/20130829130226_create_comment_status.rb 0 → 100644
@@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
  1 +class CreateCommentStatus < ActiveRecord::Migration
  2 + def self.up
  3 + create_table :comment_classification_plugin_statuses do |t|
  4 + t.string :name
  5 + t.boolean :enabled, :default => true
  6 + t.boolean :enable_reason, :default => true
  7 + t.references :owner, :polymorphic => true
  8 + t.timestamps
  9 + end
  10 +
  11 + end
  12 +
  13 + def self.down
  14 + drop_table :comment_classification_plugin_statuses
  15 + end
  16 +end
plugins/comment_classification/db/migrate/20130829144037_create_comment_status_user.rb 0 → 100644
@@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
  1 +class CreateCommentStatusUser < ActiveRecord::Migration
  2 + def self.up
  3 + create_table :comment_classification_plugin_comment_status_user do |t|
  4 + t.references :profile
  5 + t.references :comment
  6 + t.references :status
  7 + t.text :reason
  8 +
  9 + t.timestamps
  10 + end
  11 + end
  12 +
  13 + def self.down
  14 + drop_table :comment_classification_plugin_comment_status_user
  15 + end
  16 +end
plugins/comment_classification/features/labels.feature 0 → 100644
@@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
  1 +Feature:
  2 + As a user
  3 + I want to add label for comments
  4 +
  5 +Background:
  6 + Given the following users
  7 + | login | name |
  8 + | joaosilva | Joao Silva |
  9 + | mariasilva | Maria Silva |
  10 + And the following communities
  11 + | identifier | name |
  12 + | sample-community | Sample Community |
  13 + And the following articles
  14 + | owner | name | body |
  15 + | sample-community | Article to comment | First post |
  16 + And CommentClassificationPlugin is enabled
  17 + And "Maria Silva" is a member of "Sample Community"
  18 + And "Joao Silva" is admin of "Sample Community"
  19 + And I am logged in as "joaosilva"
  20 +
  21 + @selenium
  22 + Scenario: dont display labels if admin did not configure status
  23 + Given I am on article "Article to comment"
  24 + And I follow "Post a comment"
  25 + Then I should not see "Label" within "#page-comment-form"
  26 +
  27 + Scenario: admin configure labels
  28 + Given I am logged in as "admin_user"
  29 + And I am on the environment control panel
  30 + And I follow "Plugins"
  31 + And I follow "Configuration"
  32 + And I follow "Manage Labels"
  33 + Then I should see "no label registered yet" within "#comment-classification-labels"
  34 + When I follow "Add a new label"
  35 + And I fill in "Name" with "Question"
  36 + And I check "Enable this label"
  37 + And I press "Save"
  38 + Then I should see "Question" within "#comment-classification-labels"
  39 +
  40 + @selenium
  41 + Scenario: save label for comment
  42 + Given the following labels
  43 + | owner | name | enabled |
  44 + | environment | Addition | true |
  45 + And I go to article "Article to comment"
  46 + And I follow "Post a comment"
  47 + And I fill in "Enter your comment" with "Hey ho, let's go!"
  48 + Then I select "Addition" from "comment_label_id"
  49 + And I press "Post comment"
  50 + Then I should see "Addition" within ".comment-details"
  51 +
  52 + @selenium
  53 + Scenario: users without permission should not edit the labels
  54 + Given the following labels
  55 + | owner | name | enabled |
  56 + | environment | Addition | true |
  57 + And I go to article "Article to comment"
  58 + And I follow "Post a comment"
  59 + Then I should see "Label" within "#page-comment-form"
  60 + And I should see "Addition" within "#comment_label_id"
  61 + When I am not logged in
  62 + And I am on article "Article to comment"
  63 + And I follow "Post a comment"
  64 + Then I should not see "Label" within "#page-comment-form"
plugins/comment_classification/features/status.feature 0 → 100644
@@ -0,0 +1,67 @@ @@ -0,0 +1,67 @@
  1 +Feature:
  2 + As a user
  3 + I want to add status for comments
  4 +
  5 +Background:
  6 + Given the following users
  7 + | login | name |
  8 + | joaosilva | Joao Silva |
  9 + | mariasilva | Maria Silva |
  10 + And the following communities
  11 + | identifier | name |
  12 + | sample-community | Sample Community |
  13 + And the following articles
  14 + | owner | name | body |
  15 + | sample-community | Article to comment | First post |
  16 + And the following comments
  17 + | article | author | body |
  18 + | Article to comment | mariasilva | great post! |
  19 + And CommentClassificationPlugin is enabled
  20 + And "Maria Silva" is a member of "Sample Community"
  21 + And "Joao Silva" is admin of "Sample Community"
  22 + And I am logged in as "joaosilva"
  23 +
  24 + Scenario: dont display to add status if not an organization
  25 + Given the following articles
  26 + | owner | name | body |
  27 + | joaosilva | Article on a person profile | First post |
  28 + And the following comments
  29 + | article | author | body |
  30 + | Article on a person profile | mariasilva | great post! |
  31 + Given I am on article "Article on a person profile"
  32 + Then I should see "great post!" within ".comment-details"
  33 + And I should not see "Status" within ".comment-details"
  34 +
  35 + Scenario: dont display to add status if admin did not configure status
  36 + Given I am on article "Article to comment"
  37 + Then I should see "great post!" within ".comment-details"
  38 + And I should not see "Status" within ".comment-details"
  39 +
  40 + Scenario: admin configure status
  41 + Given I am logged in as "admin_user"
  42 + And I am on the environment control panel
  43 + And I follow "Plugins"
  44 + And I follow "Configuration"
  45 + And I follow "Manage Status"
  46 + Then I should see "no status registered yet" within "#comment-classification-status"
  47 + When I follow "Add a new status"
  48 + And I fill in "Name" with "Merged"
  49 + And I check "Enable this status"
  50 + And I press "Save"
  51 + Then I should see "Merged" within "#comment-classification-status"
  52 +
  53 + Scenario: save status for comment
  54 + Given the following status
  55 + | owner | name | enabled |
  56 + | environment | Merged | true |
  57 + And I go to article "Article to comment"
  58 + And I follow "Status"
  59 + Then I select "Merged" from "status_status_id"
  60 + And I press "Save"
  61 + Then I should see "added the status Merged" within "#comment-classification-status-list"
  62 +
  63 + Scenario: dont display to add status if user not allowed
  64 + Given I am logged in as "mariasilva"
  65 + When I go to article "Article to comment"
  66 + Then I should see "great post!" within ".comment-details"
  67 + And I should not see "Status" within ".comment-details"
plugins/comment_classification/features/step_definitions/plugin_steps.rb 0 → 100644
@@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
  1 +Given /^CommentClassificationPlugin is enabled$/ do
  2 + Given %{I am logged in as admin}
  3 + And %{I am on the environment control panel}
  4 + And %{I follow "Plugins"}
  5 + And %{I check "Comment Classification"}
  6 + And %{I press "Save changes"}
  7 + Environment.default.enabled_plugins.should include("CommentClassificationPlugin")
  8 +end
  9 +
  10 +Given /^the following labels$/ do |table|
  11 + table.hashes.map{|item| item.dup}.each do |item|
  12 + owner_type = item.delete('owner')
  13 + owner = owner_type == 'environment' ? Environment.default : Profile[owner_type]
  14 + CommentClassificationPlugin::Label.create!(item)
  15 + end
  16 +end
  17 +
  18 +Given /^the following status$/ do |table|
  19 + table.hashes.map{|item| item.dup}.each do |item|
  20 + owner_type = item.delete('owner')
  21 + owner = owner_type == 'environment' ? Environment.default : Profile[owner_type]
  22 + CommentClassificationPlugin::Status.create!(item)
  23 + end
  24 +end
plugins/comment_classification/lib/comment_classification_plugin.rb 0 → 100644
@@ -0,0 +1,57 @@ @@ -0,0 +1,57 @@
  1 +require 'ext/environment'
  2 +require 'ext/comment'
  3 +
  4 +class CommentClassificationPlugin < Noosfero::Plugin
  5 +
  6 + def self.plugin_name
  7 + "Comment Classification"
  8 + end
  9 +
  10 + def self.plugin_description
  11 + _("A plugin that allow classification of comments.")
  12 + end
  13 +
  14 +#TODO Each organization can add its own status and labels
  15 +# def control_panel_buttons
  16 +# if context.profile.organization?
  17 +# { :title => _('Manage comment classification'), :icon => 'comment_classification', :url => {:controller => 'comment_classification_plugin_myprofile'} }
  18 +# end
  19 +# end
  20 +
  21 + def comment_form_extra_contents(args)
  22 + comment = args[:comment]
  23 + lambda {
  24 + render :file => 'comment/comments_labels_select.rhtml', :locals => {:comment => comment }
  25 + }
  26 + end
  27 +
  28 + def comment_extra_contents(args)
  29 + comment = args[:comment]
  30 + lambda {
  31 + render :file => 'comment/comment_extra.rhtml', :locals => {:comment => comment}
  32 + }
  33 + end
  34 +
  35 + def process_extra_comment_params(args)
  36 + comment = Comment.find args[0]
  37 + label_id = args[1][:comment_label_id]
  38 + if label_id.blank?
  39 + if !CommentClassificationPlugin::CommentLabelUser.find_by_comment_id(comment.id).nil?
  40 + CommentClassificationPlugin::CommentLabelUser.find_by_comment_id(comment.id).destroy
  41 + end
  42 + else
  43 + label = CommentClassificationPlugin::Label.find label_id
  44 + relation = CommentClassificationPlugin::CommentLabelUser.new(:profile => comment.author, :comment => comment, :label => label )
  45 + relation.save
  46 + end
  47 + end
  48 +
  49 + def js_files
  50 + 'comment_classification.js'
  51 + end
  52 +
  53 + def stylesheet?
  54 + true
  55 + end
  56 +
  57 +end
plugins/comment_classification/lib/comment_classification_plugin/comment_label_user.rb 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +class CommentClassificationPlugin::CommentLabelUser < Noosfero::Plugin::ActiveRecord
  2 + set_table_name :comment_classification_plugin_comment_label_user
  3 +
  4 + belongs_to :profile
  5 + belongs_to :comment
  6 + belongs_to :label, :class_name => 'CommentClassificationPlugin::Label'
  7 +
  8 + validates_presence_of :profile
  9 + validates_presence_of :comment
  10 + validates_presence_of :label
  11 +end
plugins/comment_classification/lib/comment_classification_plugin/comment_status_user.rb 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +class CommentClassificationPlugin::CommentStatusUser < Noosfero::Plugin::ActiveRecord
  2 + set_table_name :comment_classification_plugin_comment_status_user
  3 +
  4 + belongs_to :profile
  5 + belongs_to :comment
  6 + belongs_to :status, :class_name => 'CommentClassificationPlugin::Status'
  7 +
  8 + validates_presence_of :profile
  9 + validates_presence_of :comment
  10 + validates_presence_of :status
  11 +end
plugins/comment_classification/lib/comment_classification_plugin/label.rb 0 → 100644
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +class CommentClassificationPlugin::Label < Noosfero::Plugin::ActiveRecord
  2 +
  3 + belongs_to :owner, :polymorphic => true
  4 +
  5 + validates_presence_of :name
  6 +
  7 + named_scope :enabled, :conditions => { :enabled => true }
  8 +
  9 + COLORS = ['red', 'green', 'yellow', 'gray', 'blue']
  10 +end
plugins/comment_classification/lib/comment_classification_plugin/status.rb 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +class CommentClassificationPlugin::Status < Noosfero::Plugin::ActiveRecord
  2 +
  3 + belongs_to :owner, :polymorphic => true
  4 +
  5 + validates_presence_of :name
  6 +
  7 + named_scope :enabled, :conditions => { :enabled => true }
  8 +end
plugins/comment_classification/lib/ext/comment.rb 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +require_dependency 'comment'
  2 +require 'comment_classification_plugin.rb'
  3 +require 'comment_classification_plugin/label.rb'
  4 +
  5 +class Comment
  6 +
  7 + has_one :comment_classification_plugin_comment_label_user, :class_name => 'CommentClassificationPlugin::CommentLabelUser'
  8 + has_one :label, :through => :comment_classification_plugin_comment_label_user, :foreign_key => 'label_id'
  9 +
  10 + has_many :comment_classification_plugin_comment_status_users, :class_name => 'CommentClassificationPlugin::CommentStatusUser'
  11 + has_many :statuses, :through => :comment_classification_plugin_comment_status_users, :foreign_key => 'status_id'
  12 +
  13 +end
plugins/comment_classification/lib/ext/environment.rb 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +require_dependency 'environment'
  2 +
  3 +class Environment
  4 +
  5 + has_many :labels, :as => :owner, :class_name => 'CommentClassificationPlugin::Label'
  6 +
  7 +end
  8 +
plugins/comment_classification/public/images/comment-classification.png 0 → 100644

4.15 KB

plugins/comment_classification/public/style.css 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +.controller-profile_editor .control-panel a.control-panel-comment_classification {
  2 + background-image: url(images/comment-classification.png);
  3 +}
  4 +
  5 +#content .comment-classification-options .label-name {
  6 + font-style: italic;
  7 +}
  8 +
  9 +#content .comment-classification-options a.button {
  10 + background-color: transparent;
  11 + border: none;
  12 +}
plugins/comment_classification/views/comment/comment_extra.rhtml 0 → 100644
@@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
  1 +<div class='comment-classification-options'>
  2 +
  3 + <% unless comment.label.nil? %>
  4 + <p class='label-name' style='color:<%= comment.label.color %>'>
  5 + <%= comment.label.name %>
  6 + </p>
  7 + <% end %>
  8 +
  9 + <% statuses = CommentClassificationPlugin::Status.enabled %>
  10 + <% if profile.organization? && user && user.has_permission?(:moderate_comments, profile) && !statuses.empty? %>
  11 + <div class='comment-classification-status'>
  12 + <%= link_to(_('Status'), :profile => profile.identifier, :controller => :comment_classification_plugin_myprofile, :action => :add_status, :id => comment.id)
  13 + %>
  14 + </div>
  15 + <% end %>
  16 +
  17 +</div>
plugins/comment_classification/views/comment/comments_labels_select.rhtml 0 → 100644
@@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
  1 +<% labels = CommentClassificationPlugin::Label.enabled %>
  2 +<% if logged_in? && user.has_permission?(:moderate_comments, profile) && !labels.empty? %>
  3 + <%= labelled_form_field(_('Label'), select_tag('comment_label_id', options_for_select( [[_('[Select ...]'), nil]] + labels.map{|l|[l.name,l.id]}, @comment.label.nil? ? '' : @comment.label.id))) %>
  4 +<% end %>
plugins/comment_classification/views/comment_classification_plugin_admin/index.rhtml 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +<h1><%= _('Comments classification options')%></h1>
  2 +
  3 +<ul>
  4 + <li><%= link_to _('Manage Labels'), :controller => 'comment_classification_plugin_labels' %></li>
  5 + <li><%= link_to _('Manage Status'), :controller => 'comment_classification_plugin_status' %></li>
  6 +</ul>
plugins/comment_classification/views/comment_classification_plugin_labels/_form.rhtml 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +<%= error_messages_for :label %>
  2 +
  3 +<% form_for :label, @label do |f| %>
  4 + <%= required_fields_message %>
  5 +
  6 + <%= required labelled_form_field(_('Name'), f.text_field(:name)) %>
  7 + <%= labelled_form_field(_('Color'), f.select(:color, @colors.map{|s|[s.capitalize,s]})) %>
  8 + <%= labelled_form_field(f.check_box(:enabled) + _('Enable this label?'),'') %>
  9 +
  10 + <% button_bar do %>
  11 + <%= submit_button('save', _('Save'), :cancel => {:action => 'index'} ) %>
  12 + <% end %>
  13 +<% end %>
plugins/comment_classification/views/comment_classification_plugin_labels/create.rhtml 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +<h2> <%= _("Add a new label") %> </h2>
  2 +
  3 +<%= render :partial => 'form' %>
plugins/comment_classification/views/comment_classification_plugin_labels/edit.rhtml 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +<h2> <%= _("Editing label %s") % @label.name %> </h2>
  2 +
  3 +<%= render :partial => 'form' %>
plugins/comment_classification/views/comment_classification_plugin_labels/index.rhtml 0 → 100644
@@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
  1 +<h1><%= _("Manage comments labels") %></h1>
  2 +
  3 +<div id='comment-classification-labels'>
  4 + <% if @labels.empty? %>
  5 + <%= _('(no label registered yet)') %>
  6 + <% else %>
  7 + <table>
  8 + <tr>
  9 + <th><%= _('Label') %></th>
  10 + <th><%= _('Color') %></th>
  11 + <th><%= _('Enabled') %></th>
  12 + <th><%= _('Actions') %></th>
  13 + </tr>
  14 + <% @labels.each do |label| %>
  15 + <tr>
  16 + <td><%= label.name %></td>
  17 + <td><%= label.color %></td>
  18 + <td><%= label.enabled %></td>
  19 + <td>
  20 + <%= button_without_text :edit, _('Edit'), {:action => 'edit', :id => label} %>
  21 + <%= button_without_text :delete, _('Remove'), {:action => 'destroy', :id => label}, :confirm => _('Are you sure you want to remove this label?') %>
  22 + </td>
  23 + </tr>
  24 + <% end %>
  25 + </table>
  26 + <% end %>
  27 +
  28 + <% button_bar do %>
  29 + <%= button(:add, _('Add a new label'), :action => 'create')%>
  30 + <%= button :back, _('Back to admin panel'), :controller => 'admin_panel' %>
  31 + <% end %>
  32 +</div>
plugins/comment_classification/views/comment_classification_plugin_myprofile/_status_form.html.erb 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +<%= error_messages_for :status %>
  2 +
  3 +<% form_for :status, @status do |f| %>
  4 + <%= required_fields_message %>
  5 +
  6 + <%= labelled_form_field(_('Status'), f.select(:status_id, @statuses.map{|s|[s.name,s.id]})) %>
  7 + <%= labelled_form_field(_('Reason:'), f.text_area(:reason, :rows => 5)) %>
  8 +
  9 + <% button_bar do %>
  10 + <%= submit_button('save', _('Save') ) %>
  11 + <% end %>
  12 +<% end %>
plugins/comment_classification/views/comment_classification_plugin_myprofile/add_status.html.erb 0 → 100644
@@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
  1 +<h1><%= _('Status for comment') %></h1>
  2 +
  3 +<div id='comment-classification-status-list'>
  4 + <% unless @comment.title.blank? %>
  5 + <div class='comment-title'><%= _("Title: %s") % @comment.title %></div>
  6 + <% end %>
  7 +
  8 + <b><%= _('Body:') %></b>
  9 + <p><%= @comment.body %></p>
  10 +
  11 + <h2> <%= _("History") %> </h2>
  12 +
  13 + <ul>
  14 + <% @comment.comment_classification_plugin_comment_status_users.each do |relation| %>
  15 + <li>
  16 + <%= _("<i>%{user}</i> added the status <i>%{status_name}</i> at <i>%{created_at}</i>.") % { :user => relation.profile.name, :status_name => relation.status.name, :created_at => time_ago_as_sentence(relation.created_at)} %>
  17 + <% unless relation.reason.blank? %>
  18 + <p><%= _("<i>Reason:</i> %s") % relation.reason %></p>
  19 + <% end %>
  20 + </li>
  21 + <% end %>
  22 + </ul>
  23 +
  24 + <h2> <%= _("Add a new status") %> </h2>
  25 +
  26 + <%= render :partial => 'status_form' %>
  27 +</div>
plugins/comment_classification/views/comment_classification_plugin_myprofile/index.html.erb 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +<h1><%= _('Manage comment classification') %></h1>
  2 +
  3 +List all classifications
plugins/comment_classification/views/comment_classification_plugin_status/_form.rhtml 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +<%= error_messages_for :status %>
  2 +
  3 +<% form_for :status, @status do |f| %>
  4 + <%= required_fields_message %>
  5 +
  6 + <%= required labelled_form_field(_('Name'), f.text_field(:name)) %>
  7 + <%= labelled_form_field(f.check_box(:enabled) + _('Enable this status?'),'') %>
  8 + <%#= labelled_form_field(f.check_box(:enable_reason) + _('This status allows reason?'),'') %>
  9 +
  10 + <% button_bar do %>
  11 + <%= submit_button('save', _('Save'), :cancel => {:action => 'index'} ) %>
  12 + <% end %>
  13 +<% end %>
plugins/comment_classification/views/comment_classification_plugin_status/create.rhtml 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +<h2> <%= _("Add a new status") %> </h2>
  2 +
  3 +<%= render :partial => 'form' %>
plugins/comment_classification/views/comment_classification_plugin_status/edit.rhtml 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +<h2> <%= _("Editing status %s") % @status.name %> </h2>
  2 +
  3 +<%= render :partial => 'form' %>
plugins/comment_classification/views/comment_classification_plugin_status/index.rhtml 0 → 100644
@@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
  1 +<h1> <%= _("Manage comments status") %></h1>
  2 +
  3 +<div id='comment-classification-status'>
  4 + <% if @status.empty? %>
  5 + <%= _('(no status registered yet)') %>
  6 + <% else %>
  7 + <table>
  8 + <tr>
  9 + <th><%= _('Status') %></th>
  10 + <th><%= _('Enabled') %></th>
  11 + <th><%= _('Reason enabled?') %></th>
  12 + <th><%= _('Actions') %></th>
  13 + </tr>
  14 + <% @status.each do |st| %>
  15 + <tr>
  16 + <td><%= st.name %></td>
  17 + <td><%= st.enabled %></td>
  18 + <td><%= st.enable_reason %></td>
  19 + <td>
  20 + <%= button_without_text :edit, _('Edit'), {:action => 'edit', :id => st} %>
  21 + <%= button_without_text :delete, _('Remove'), {:action => 'destroy', :id => st}, :confirm => _('Are you sure you want to remove this status?') %>
  22 + </td>
  23 + </tr>
  24 + <% end %>
  25 + </table>
  26 + <% end %>
  27 +
  28 + <% button_bar do %>
  29 + <%= button(:add, _('Add a new status'), :action => 'create')%>
  30 + <%= button :back, _('Back to admin panel'), :controller => 'admin_panel' %>
  31 + <% end %>
  32 +</div>
plugins/container_block/lib/container_block_plugin.rb
@@ -16,4 +16,8 @@ class ContainerBlockPlugin &lt; Noosfero::Plugin @@ -16,4 +16,8 @@ class ContainerBlockPlugin &lt; Noosfero::Plugin
16 true 16 true
17 end 17 end
18 18
  19 + def js_files
  20 + 'container_block.js'
  21 + end
  22 +
19 end 23 end
plugins/container_block/lib/container_block_plugin/container_block.rb
@@ -7,6 +7,16 @@ class ContainerBlockPlugin::ContainerBlock &lt; Block @@ -7,6 +7,16 @@ class ContainerBlockPlugin::ContainerBlock &lt; Block
7 settings_items :container_box_id, :type => Integer, :default => nil 7 settings_items :container_box_id, :type => Integer, :default => nil
8 settings_items :children_settings, :type => Hash, :default => {} 8 settings_items :children_settings, :type => Hash, :default => {}
9 9
  10 + validate :no_cyclical_reference, :if => 'container_box_id.present?'
  11 +
  12 + def no_cyclical_reference
  13 + errors.add(:box_id, _('cyclical reference is not allowed.')) if box_id == container_box_id
  14 + end
  15 +
  16 + before_save do |b|
  17 + raise "cyclical reference is not allowed" if b.box_id == b.container_box_id && !b.container_box_id.blank?
  18 + end
  19 +
10 def self.description 20 def self.description
11 _('Container') 21 _('Container')
12 end 22 end
@@ -15,6 +25,10 @@ class ContainerBlockPlugin::ContainerBlock &lt; Block @@ -15,6 +25,10 @@ class ContainerBlockPlugin::ContainerBlock &lt; Block
15 _('This block acts as a container for another blocks') 25 _('This block acts as a container for another blocks')
16 end 26 end
17 27
  28 + def cacheable?
  29 + false
  30 + end
  31 +
18 def layout_template 32 def layout_template
19 nil 33 nil
20 end 34 end
@@ -24,8 +38,9 @@ class ContainerBlockPlugin::ContainerBlock &lt; Block @@ -24,8 +38,9 @@ class ContainerBlockPlugin::ContainerBlock &lt; Block
24 end 38 end
25 39
26 def create_box 40 def create_box
27 - box = Box.create!(:owner => owner)  
28 - settings[:container_box_id] = box.id 41 + container_box = Box.create!(:owner => owner)
  42 + container_box.update_attribute(:position, nil)
  43 + settings[:container_box_id] = container_box.id
29 save! 44 save!
30 end 45 end
31 46
plugins/container_block/public/container_block.js 0 → 100644
@@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
  1 +function enableMoveContainerChildren(container, box) {
  2 + var div = jQuery('#box-'+box+' > .block-outer > .block');
  3 + if(!div.is('.ui-resizable')) {
  4 + div.resizable({
  5 + handles: 'e, w',
  6 + containment: '#block-'+container+' .block-inner-2',
  7 + resize: function( event, ui ) {
  8 + ui.element.height('auto');
  9 + }
  10 + });
  11 + }
  12 +}
  13 +
  14 +function disableMoveContainerChildren(container, box) {
  15 + var div = jQuery('#box-'+box+' > .block-outer > .block');
  16 + if(div.is('.ui-resizable')) {
  17 + div.resizable('destroy');
  18 + }
  19 +}
  20 +
  21 +function containerChildrenWidth(container, box) {
  22 + widths = "";
  23 + jQuery('#box-'+box+' > .block-outer > .block').each(function(i) {
  24 + childId = jQuery(this).attr('id').match(/block-(\d+)/)[1];
  25 + widths+=childId+","+jQuery(this).width()+"|";
  26 + });
  27 + return "widths="+widths;
  28 +}
plugins/container_block/public/style.css
  1 +#box-organizer .container-block-plugin_container-block > .block-inner-1 > .block-inner-2 > .button-bar {
  2 + height: 22px;
  3 + padding-bottom: 0px;
  4 + width: auto;
  5 +}
  6 +
1 #content .boxes .container-block-plugin_container-block .container_block_child, .container-block-plugin_container-block .block-outer { 7 #content .boxes .container-block-plugin_container-block .container_block_child, .container-block-plugin_container-block .block-outer {
2 display: inline-block; 8 display: inline-block;
3 vertical-align: top; 9 vertical-align: top;
@@ -17,14 +23,10 @@ @@ -17,14 +23,10 @@
17 background-image: url(/designs/icons/default/Tango/16x16/actions/go-previous.png); 23 background-image: url(/designs/icons/default/Tango/16x16/actions/go-previous.png);
18 } 24 }
19 25
20 -#content .boxes .container-block-plugin_container-block .block {  
21 - outline-offset: -2px;  
22 -}  
23 -  
24 #content .boxes .container-block-plugin_container-block .block .ui-resizable-handle { 26 #content .boxes .container-block-plugin_container-block .block .ui-resizable-handle {
25 width: 10px; 27 width: 10px;
26 height: 28px; 28 height: 28px;
27 - z-index: 0; 29 + z-index: 1000;
28 } 30 }
29 31
30 #content .boxes .container-block-plugin_container-block .block .ui-resizable-e { 32 #content .boxes .container-block-plugin_container-block .block .ui-resizable-e {
@@ -37,6 +39,21 @@ @@ -37,6 +39,21 @@
37 background-image: url(/plugins/container_block/images/handle_w.png); 39 background-image: url(/plugins/container_block/images/handle_w.png);
38 } 40 }
39 41
40 -.container-block-plugin_container-block .button-bar .icon-resize { 42 +.container-block-plugin_container-block .container-block-button-bar .icon-resize {
41 background-image: url(/designs/icons/default/Tango/16x16/actions/view-fullscreen.png); 43 background-image: url(/designs/icons/default/Tango/16x16/actions/view-fullscreen.png);
42 } 44 }
  45 +
  46 +#box-organizer .block .container-block-button-bar {
  47 + right: 0px;
  48 + bottom: 0px;
  49 + height: auto;
  50 +}
  51 +
  52 +#box-organizer .container-block-plugin_container-block:hover .block {
  53 + outline: 1px dashed black;
  54 + outline-offset: -1px;
  55 +}
  56 +
  57 +.container-block-plugin_container-block .block-target {
  58 + background: #afd;
  59 +}
plugins/container_block/test/functional/container_block_home_controller_test.rb
@@ -31,6 +31,13 @@ class HomeControllerTest &lt; ActionController::TestCase @@ -31,6 +31,13 @@ class HomeControllerTest &lt; ActionController::TestCase
31 assert_tag :div, :attributes => { :class => 'block container-block-plugin_container-block' } 31 assert_tag :div, :attributes => { :class => 'block container-block-plugin_container-block' }
32 end 32 end
33 33
  34 + should 'display block title' do
  35 + @block.title = "Block Title"
  36 + @block.save!
  37 + get :index
  38 + assert_tag :div, :attributes => { :class => 'block container-block-plugin_container-block' }, :descendant => {:tag => 'h3', :attributes => { :class => "block-title"}, :content => @block.title }
  39 + end
  40 +
34 should 'display container children' do 41 should 'display container children' do
35 c1 = RawHTMLBlock.create!(:box => @block.container_box, :html => 'child1 content') 42 c1 = RawHTMLBlock.create!(:box => @block.container_box, :html => 'child1 content')
36 c2 = RawHTMLBlock.create!(:box => @block.container_box, :html => 'child2 content') 43 c2 = RawHTMLBlock.create!(:box => @block.container_box, :html => 'child2 content')
plugins/container_block/test/unit/block_test.rb
@@ -1,31 +0,0 @@ @@ -1,31 +0,0 @@
1 -require 'test_helper'  
2 -  
3 -class BlockTest < ActiveSupport::TestCase  
4 -  
5 - def setup  
6 - @environment = fast_create(Environment)  
7 - @box = Box.create!(:owner => @environment)  
8 - @container = ContainerBlockPlugin::ContainerBlock.create!(:box => @box)  
9 - end  
10 -  
11 - should 'return environment box if block owner is not a ContainerBlock' do  
12 - block = Block.create!(:box => @box)  
13 - assert_equal @box, block.box  
14 - end  
15 -  
16 - should 'return container box if block owner is a ContainerBlock' do  
17 - block = Block.create!(:box => @container.container_box)  
18 - assert_equal @container.container_box, block.box  
19 - end  
20 -  
21 - should 'return block owner if block onwer is not a ContainerBlock' do  
22 - block = Block.create!(:box => @box)  
23 - assert_equal @environment, block.owner  
24 - end  
25 -  
26 - should 'return environment as owner if block onwer is a ContainerBlock' do  
27 - block = Block.create!(:box => @container.container_box)  
28 - assert_equal @environment, block.owner  
29 - end  
30 -  
31 -end  
plugins/container_block/test/unit/container_block_plugin/container_block_test.rb
@@ -20,6 +20,11 @@ class ContainerBlockPlugin::ContainerBlockTest &lt; ActiveSupport::TestCase @@ -20,6 +20,11 @@ class ContainerBlockPlugin::ContainerBlockTest &lt; ActiveSupport::TestCase
20 assert @block.container_box_id 20 assert @block.container_box_id
21 end 21 end
22 22
  23 + should 'created box should have nil as position' do
  24 + @block.save!
  25 + assert_equal nil, @block.container_box.position
  26 + end
  27 +
23 should 'return created box' do 28 should 'return created box' do
24 @block.save! 29 @block.save!
25 assert @block.container_box 30 assert @block.container_box
@@ -89,4 +94,27 @@ class ContainerBlockPlugin::ContainerBlockTest &lt; ActiveSupport::TestCase @@ -89,4 +94,27 @@ class ContainerBlockPlugin::ContainerBlockTest &lt; ActiveSupport::TestCase
89 end 94 end
90 end 95 end
91 96
  97 + should 'not mess up with boxes positions when destroyed' do
  98 + env = fast_create(Environment)
  99 + box1 = fast_create(Box, :owner_id => env.id, :owner_type => 'Environment', :position => 1)
  100 + box2 = fast_create(Box, :owner_id => env.id, :owner_type => 'Environment', :position => 2)
  101 + box3 = fast_create(Box, :owner_id => env.id, :owner_type => 'Environment', :position => 3)
  102 + block = ContainerBlockPlugin::ContainerBlock.create!(:box => box1)
  103 + block.destroy
  104 + assert_equal [1, 2, 3], [box1.reload.position, box2.reload.position, box3.reload.position]
  105 + end
  106 +
  107 + should 'be able to change box' do
  108 + @block.save!
  109 + @block.box = Box.new(:owner => Environment.default)
  110 + @block.save!
  111 + end
  112 +
  113 + should 'not able to change box to be the same as container_box' do
  114 + @block.save!
  115 + @block.box = @block.container_box
  116 + @block.save
  117 + assert @block.errors.invalid?(:box_id)
  118 + end
  119 +
92 end 120 end
plugins/container_block/test/unit/environment_test.rb
@@ -1,32 +0,0 @@ @@ -1,32 +0,0 @@
1 -require 'test_helper'  
2 -  
3 -class EnvironmentTest < ActiveSupport::TestCase  
4 -  
5 - def setup  
6 - @environment = fast_create(Environment)  
7 -  
8 - @box = Box.create!(:owner => @environment)  
9 - @block = Block.create!(:box => @box)  
10 -  
11 - @container = ContainerBlockPlugin::ContainerBlock.create!(:box => @box)  
12 - end  
13 -  
14 - should 'return blocks as usual' do  
15 - assert_equal [@block, @container], @environment.blocks  
16 - end  
17 -  
18 - should 'return blocks with container children' do  
19 - child = Block.create!(:box => @container.container_box)  
20 - assert_equal [@block, @container, child], @environment.blocks  
21 - end  
22 -  
23 - should 'return block with id at find method' do  
24 - assert_equal @block, @environment.blocks.find(@block.id)  
25 - end  
26 -  
27 - should 'return child block with id at find method' do  
28 - child = Block.create!(:box => @container.container_box)  
29 - assert_equal child, @environment.blocks.find(child.id)  
30 - end  
31 -  
32 -end  
plugins/container_block/test/unit/profile_test.rb
@@ -1,32 +0,0 @@ @@ -1,32 +0,0 @@
1 -require 'test_helper'  
2 -  
3 -class ProfileTest < ActiveSupport::TestCase  
4 -  
5 - def setup  
6 - @profile = fast_create(Profile)  
7 -  
8 - @box = Box.create!(:owner => @profile)  
9 - @block = Block.create!(:box => @box)  
10 -  
11 - @container = ContainerBlockPlugin::ContainerBlock.create!(:box => @box)  
12 - end  
13 -  
14 - should 'return blocks as usual' do  
15 - assert_equal [@block, @container], @profile.blocks  
16 - end  
17 -  
18 - should 'return blocks with container children' do  
19 - child = Block.create!(:box => @container.container_box)  
20 - assert_equal [@block, @container, child], @profile.blocks  
21 - end  
22 -  
23 - should 'return block with id at find method' do  
24 - assert_equal @block, @profile.blocks.find(@block.id)  
25 - end  
26 -  
27 - should 'return child block with id at find method' do  
28 - child = Block.create!(:box => @container.container_box)  
29 - assert_equal child, @profile.blocks.find(child.id)  
30 - end  
31 -  
32 -end  
plugins/container_block/views/blocks/container.rhtml
1 <% edit_mode = @controller.send(:boxes_editor?) && @controller.send(:uses_design_blocks?) %> 1 <% edit_mode = @controller.send(:boxes_editor?) && @controller.send(:uses_design_blocks?) %>
2 <% box_decorator = edit_mode ? self : BoxesHelper::DontMoveBlocks %> 2 <% box_decorator = edit_mode ? self : BoxesHelper::DontMoveBlocks %>
3 3
  4 +<%= block_title(block.title) %>
4 5
5 <div class="box" id="box-<%= block.container_box.id %>"> 6 <div class="box" id="box-<%= block.container_box.id %>">
6 <%= display_box_content(block.container_box, nil) %> 7 <%= display_box_content(block.container_box, nil) %>
@@ -15,8 +16,18 @@ @@ -15,8 +16,18 @@
15 </style> 16 </style>
16 17
17 <% if edit_mode %> 18 <% if edit_mode %>
18 - <div class="button-bar">  
19 - <a href="#" onclick="toggleMoveContainerChildren(<%= block.id %>, <%= block.container_box.id %>); return false;" class="button icon-resize" title=<%= _('Resize blocks').to_json %>></a> 19 +
  20 + <script>
  21 + jQuery("#block-<%= block.id %>").hover(
  22 + function() {
  23 + enableMoveContainerChildren(<%= block.id %>, <%= block.container_box.id %>);
  24 + }, function() {
  25 + disableMoveContainerChildren(<%= block.id %>, <%= block.container_box.id %>);
  26 + }
  27 + );
  28 + </script>
  29 +
  30 + <div class="container-block-button-bar button-bar">
20 <%= link_to_remote '', :url => { :controller => @controller.boxes_holder.kind_of?(Environment) ? 'container_block_plugin_admin' : 'container_block_plugin_myprofile', :action => 'saveWidths', :id => block.id }, 31 <%= link_to_remote '', :url => { :controller => @controller.boxes_holder.kind_of?(Environment) ? 'container_block_plugin_admin' : 'container_block_plugin_myprofile', :action => 'saveWidths', :id => block.id },
21 :with => "containerChildrenWidth(#{block.id}, #{block.container_box.id})", 32 :with => "containerChildrenWidth(#{block.id}, #{block.container_box.id})",
22 :html => {:class => "button icon-save container_block_save", :id => "container_block_save_#{block.id}", :title => _('Save') }, 33 :html => {:class => "button icon-save container_block_save", :id => "container_block_save_#{block.id}", :title => _('Save') },
@@ -24,37 +35,4 @@ @@ -24,37 +35,4 @@
24 :loaded => "close_loading();", 35 :loaded => "close_loading();",
25 :complete => "display_notice(request.responseText);"%> 36 :complete => "display_notice(request.responseText);"%>
26 </div> 37 </div>
27 -  
28 - <script>  
29 - function toggleMoveContainerChildren(container, box) {  
30 - var div = jQuery('#box-'+box+' > .block-outer > .block');  
31 - var targetDiv = jQuery('#box-'+box+' .block-outer .block-target');  
32 - if(div.is('.ui-resizable')) {  
33 - targetDiv.show();  
34 - div.find("a").die("click");  
35 - div.resizable('destroy');  
36 - } else {  
37 - targetDiv.hide();  
38 - div.find("a").live("click", function(e) {  
39 - e.preventDefault();  
40 - });  
41 - div.resizable({  
42 - handles: 'e, w',  
43 - containment: '#block-'+container+' .block-inner-2',  
44 - resize: function( event, ui ) {  
45 - ui.element.height('auto');  
46 - }  
47 - });  
48 - }  
49 - }  
50 -  
51 - function containerChildrenWidth(container, box) {  
52 - widths = "";  
53 - jQuery('#box-'+box+' > .block-outer > .block').each(function(i) {  
54 - childId = jQuery(this).attr('id').match(/block-(\d+)/)[1];  
55 - widths+=childId+","+jQuery(this).width()+"|";  
56 - });  
57 - return "widths="+widths;  
58 - }  
59 - </script>  
60 <% end %> 38 <% end %>
plugins/context_content/views/blocks/_more.rhtml
1 <% if contents.total_pages > 1 %> 1 <% if contents.total_pages > 1 %>
2 - <%= link_to_remote(nil, :url => {:id => block.id, :controller => 'context_content_plugin_profile', :action => 'view_content', :page => contents.previous_page, :article_id => article_id }, :html => {:class => "button icon-button icon-left #{contents.previous_page ? '':'disabled'}".strip}, :condition => "#{!contents.previous_page.nil?}", :success => "jQuery('#context_content_#{block.id}').effect('slide', {direction: 'left'});" )%>  
3 - <%= link_to_remote(nil, :url => {:id => block.id, :controller => 'context_content_plugin_profile', :action => 'view_content', :page => contents.next_page, :article_id => article_id }, :html => {:class => "button icon-button icon-right #{contents.next_page ? '':'disabled'}".strip}, :condition => "#{!contents.next_page.nil?}", :success => "jQuery('#context_content_#{block.id}').effect('slide', {direction: 'right'});" )%> 2 + <%= link_to_remote(nil, :url => {:profile => block.owner.identifier, :id => block.id, :controller => 'context_content_plugin_profile', :action => 'view_content', :page => contents.previous_page, :article_id => article_id }, :html => {:class => "button icon-button icon-left #{contents.previous_page ? '':'disabled'}".strip}, :condition => "#{!contents.previous_page.nil?}", :success => "jQuery('#context_content_#{block.id}').effect('slide', {direction: 'left'});" )%>
  3 + <%= link_to_remote(nil, :url => {:profile => block.owner.identifier, :id => block.id, :controller => 'context_content_plugin_profile', :action => 'view_content', :page => contents.next_page, :article_id => article_id }, :html => {:class => "button icon-button icon-right #{contents.next_page ? '':'disabled'}".strip}, :condition => "#{!contents.next_page.nil?}", :success => "jQuery('#context_content_#{block.id}').effect('slide', {direction: 'right'});" )%>
4 <% end %> 4 <% end %>
plugins/require_auth_to_comment/public/hide_comment_form.js
1 (function($) { 1 (function($) {
2 $(window).bind('userDataLoaded', function(event, data) { 2 $(window).bind('userDataLoaded', function(event, data) {
3 - if (data.login || $('meta[name=profile.allow_unauthenticated_comments]').length > 0) { 3 + if (data.login || $('meta[name="profile.allow_unauthenticated_comments"]').length > 0) {
4 $('.post-comment-button').livequery(function() { 4 $('.post-comment-button').livequery(function() {
5 $(this).show(); 5 $(this).show();
6 }); 6 });
@@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
8 $(this).show(); 8 $(this).show();
9 }); 9 });
10 $('.comment-footer').livequery(function() { 10 $('.comment-footer').livequery(function() {
11 - $(this).show(); 11 + $(this).show();
12 }); 12 });
13 } 13 }
14 }); 14 });
plugins/shopping_cart/views/shopping_cart_plugin_myprofile/edit.html.erb
@@ -33,8 +33,8 @@ @@ -33,8 +33,8 @@
33 </tr> 33 </tr>
34 </table> 34 </table>
35 35
36 - <%= labelled_form_field(_('Free delivery price:'), f.text_field(:free_delivery_price)) %>  
37 - <%= content_tag('small', _('Empty stands for no free delivery price.')) %> 36 + <%= labelled_form_field(_("Order's minimum price for free delivery:"), f.text_field(:free_delivery_price)) %>
  37 + <%= content_tag('small', _('Empty stands for no minimum price for free delivery.')) %>
38 </fieldset> 38 </fieldset>
39 <br style='clear: both'/> 39 <br style='clear: both'/>
40 <br style='clear: both'/> 40 <br style='clear: both'/>
plugins/statistics/README 0 → 100644
@@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
  1 +README - Statistics (Statistics Plugin)
  2 +================================
  3 +
  4 +Statistics is a plugin to allow the user adds a block where you could see statistics of it's context.
  5 +
  6 +The Statistics block will be available for all layout columns of communities, peole, enterprises and environments.
  7 +
  8 +INSTALL
  9 +=======
  10 +
  11 +Enable Plugin
  12 +-------------
  13 +
  14 +Also, you need to enable Statistics Plugin at you Noosfero:
  15 +
  16 +cd <your_noosfero_dir>
  17 +./script/noosfero-plugins enable statistics
  18 +
  19 +Active Plugin
  20 +-------------
  21 +
  22 +As a Noosfero administrator user, go to administrator panel:
  23 +
  24 +- Click on "Enable/disable plugins" option
  25 +- Click on "Statistics Plugin" check-box
  26 +
  27 +Running Statistics tests
  28 +--------------------
  29 +
  30 +$ rake test:noosfero_plugins:statistics
  31 +
  32 +
  33 +Get Involved
  34 +============
  35 +
  36 +If you found any bug and/or want to collaborate, please send an e-mail to eduardo.edington@gmail.com
  37 +
  38 +LICENSE
  39 +=======
  40 +
  41 +Copyright (c) The Author developers.
  42 +
  43 +See Noosfero license.
  44 +
  45 +
  46 +AUTHORS
  47 +=======
  48 +
  49 + Eduardo Tourinho Edington (eduardo.edington at gmail.com)
  50 +
  51 +ACKNOWLEDGMENTS
  52 +===============
  53 +
  54 +The author has been supported by Serpro
plugins/statistics/lib/statistics_block.rb 0 → 100644
@@ -0,0 +1,146 @@ @@ -0,0 +1,146 @@
  1 +class StatisticsBlock < Block
  2 +
  3 + settings_items :community_counter, :default => false
  4 + settings_items :user_counter, :default => true
  5 + settings_items :enterprise_counter, :default => false
  6 + settings_items :category_counter, :default => false
  7 + settings_items :tag_counter, :default => true
  8 + settings_items :comment_counter, :default => true
  9 + settings_items :hit_counter, :default => false
  10 + settings_items :templates_ids_counter, Hash, :default => {}
  11 +
  12 + USER_COUNTERS = [:community_counter, :user_counter, :enterprise_counter, :tag_counter, :comment_counter, :hit_counter]
  13 + COMMUNITY_COUNTERS = [:user_counter, :tag_counter, :comment_counter, :hit_counter]
  14 + ENTERPRISE_COUNTERS = [:user_counter, :tag_counter, :comment_counter, :hit_counter]
  15 +
  16 + def self.description
  17 + _('Statistics')
  18 + end
  19 +
  20 + def default_title
  21 + _('Statistics for %s') % owner.name
  22 + end
  23 +
  24 + def is_visible? counter
  25 + value = self.send(counter)
  26 + value == '1' || value == true
  27 + end
  28 +
  29 + def is_counter_available? counter
  30 + if owner.kind_of?(Environment)
  31 + true
  32 + elsif owner.kind_of?(Person)
  33 + USER_COUNTERS.include?(counter)
  34 + elsif owner.kind_of?(Community)
  35 + COMMUNITY_COUNTERS.include?(counter)
  36 + elsif owner.kind_of?(Enterprise)
  37 + ENTERPRISE_COUNTERS.include?(counter)
  38 + end
  39 +
  40 + end
  41 +
  42 + def help
  43 + _('This block presents some statistics about your context.')
  44 + end
  45 +
  46 + def timeout
  47 + 60.minutes
  48 + end
  49 +
  50 + def environment
  51 + if owner.kind_of?(Environment)
  52 + owner
  53 + elsif owner.kind_of?(Profile)
  54 + owner.environment
  55 + else
  56 + nil
  57 + end
  58 + end
  59 +
  60 + def templates
  61 + Community.templates(environment)
  62 + end
  63 +
  64 + def is_template_counter_active? template_id
  65 + self.templates_ids_counter[template_id.to_s].to_s == 'true'
  66 + end
  67 +
  68 + def template_counter_count(template_id)
  69 + owner.communities.visible.count(:conditions => {:template_id => template_id})
  70 + end
  71 +
  72 + def users
  73 + if owner.kind_of?(Environment)
  74 + owner.people.visible.count
  75 + elsif owner.kind_of?(Organization)
  76 + owner.members.visible.count
  77 + elsif owner.kind_of?(Person)
  78 + owner.friends.visible.count
  79 + else
  80 + 0
  81 + end
  82 + end
  83 +
  84 + def enterprises
  85 + if owner.kind_of?(Environment) || owner.kind_of?(Person)
  86 + owner.enterprises.visible.count
  87 + else
  88 + 0
  89 + end
  90 + end
  91 +
  92 + def communities
  93 + if owner.kind_of?(Environment) || owner.kind_of?(Person)
  94 + owner.communities.visible.count
  95 + else
  96 + 0
  97 + end
  98 + end
  99 +
  100 + def categories
  101 + if owner.kind_of?(Environment) then
  102 + owner.categories.count
  103 + else
  104 + 0
  105 + end
  106 + end
  107 +
  108 + def tags
  109 + if owner.kind_of?(Environment) then
  110 + owner.tag_counts.count
  111 + elsif owner.kind_of?(Profile) then
  112 + owner.article_tags.count
  113 + else
  114 + 0
  115 + end
  116 + end
  117 +
  118 + def comments
  119 + if owner.kind_of?(Environment) then
  120 + owner.profiles.joins(:articles).sum(:comments_count).to_i
  121 + elsif owner.kind_of?(Profile) then
  122 + owner.articles.sum(:comments_count)
  123 + else
  124 + 0
  125 + end
  126 + end
  127 +
  128 + def hits
  129 + if owner.kind_of?(Environment) then
  130 + owner.profiles.joins(:articles).sum(:hits).to_i
  131 + elsif owner.kind_of?(Profile) then
  132 + owner.articles.sum(:hits)
  133 + else
  134 + 0
  135 + end
  136 + end
  137 +
  138 + def content(args={})
  139 + block = self
  140 +
  141 + lambda do
  142 + render :file => 'statistics_block', :locals => { :block => block }
  143 + end
  144 + end
  145 +
  146 +end
plugins/statistics/lib/statistics_plugin.rb 0 → 100644
@@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
  1 +require_dependency File.dirname(__FILE__) + '/statistics_block'
  2 +
  3 +class StatisticsPlugin < Noosfero::Plugin
  4 +
  5 + def self.plugin_name
  6 + "Statistics Plugin"
  7 + end
  8 +
  9 + def self.plugin_description
  10 + _("A plugin that adds a block where you can see statistics of it's context.")
  11 + end
  12 +
  13 + def self.extra_blocks
  14 + {
  15 + StatisticsBlock => {}
  16 + }
  17 + end
  18 +
  19 +end
plugins/statistics/test/functional/statistics_plugin_environment_design_controller_test.rb 0 → 100644
@@ -0,0 +1,161 @@ @@ -0,0 +1,161 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +# Re-raise errors caught by the controller.
  4 +class EnvironmentDesignController; def rescue_action(e) raise e end; end
  5 +
  6 +class EnvironmentDesignControllerTest < ActionController::TestCase
  7 +
  8 + def setup
  9 + @controller = EnvironmentDesignController.new
  10 + @request = ActionController::TestRequest.new
  11 + @response = ActionController::TestResponse.new
  12 +
  13 + Environment.delete_all
  14 +
  15 + @environment = Environment.create(:name => 'testenv', :is_default => true)
  16 + @environment.enabled_plugins = ['StatisticsPlugin']
  17 + @environment.save!
  18 +
  19 + user = create_user('testinguser')
  20 + @environment.add_admin(user.person)
  21 +
  22 + StatisticsBlock.delete_all
  23 + @box1 = Box.create!(:owner => @environment)
  24 + @environment.boxes = [@box1]
  25 +
  26 + @block = StatisticsBlock.new
  27 + @block.box = @box1
  28 + @block.save!
  29 +
  30 + login_as(user.login)
  31 + end
  32 +
  33 + attr_accessor :block
  34 +
  35 + should 'be able to edit StatisticsBlock' do
  36 + get :edit, :id => @block.id
  37 + assert_tag :tag => 'input', :attributes => { :id => 'block_title' }
  38 + end
  39 +
  40 + should 'be able to save StatisticsBlock' do
  41 + get :edit, :id => @block.id
  42 + post :save, :id => @block.id, :block => {:title => 'Statistics' }
  43 + @block.reload
  44 + assert_equal 'Statistics', @block.title
  45 + end
  46 +
  47 + should 'be able to uncheck core counters' do
  48 + @block.user_counter = true
  49 + @block.community_counter = true
  50 + @block.enterprise_counter = true
  51 + @block.category_counter = true
  52 + @block.tag_counter = true
  53 + @block.comment_counter = true
  54 + @block.hit_counter = true
  55 + @block.save!
  56 + get :edit, :id => @block.id
  57 + post :save, :id => @block.id, :block => {:user_counter => '0', :community_counter => '0', :enterprise_counter => '0',
  58 + :category_counter => '0', :tag_counter => '0', :comment_counter => '0', :hit_counter => '0' }
  59 + @block.reload
  60 + any_checked = @block.is_visible?('user_counter') ||
  61 + @block.is_visible?('community_counter') ||
  62 + @block.is_visible?('enterprise_counter') ||
  63 + @block.is_visible?('category_counter') ||
  64 + @block.is_visible?('tag_counter') ||
  65 + @block.is_visible?('comment_counter') ||
  66 + @block.is_visible?('hit_counter')
  67 + assert_equal false, any_checked
  68 +
  69 + end
  70 +
  71 + should 'be able to check core counters' do
  72 + @block.user_counter = false
  73 + @block.community_counter = false
  74 + @block.enterprise_counter = false
  75 + @block.category_counter = false
  76 + @block.tag_counter = false
  77 + @block.comment_counter = false
  78 + @block.hit_counter = false
  79 + @block.save!
  80 + get :edit, :id => @block.id
  81 + post :save, :id => @block.id, :block => {:user_counter => '1', :community_counter => '1', :enterprise_counter => '1',
  82 + :category_counter => '1', :tag_counter => '1', :comment_counter => '1', :hit_counter => '1' }
  83 + @block.reload
  84 + all_checked = @block.is_visible?('user_counter') &&
  85 + @block.is_visible?('community_counter') &&
  86 + @block.is_visible?('enterprise_counter') &&
  87 + @block.is_visible?('category_counter') &&
  88 + @block.is_visible?('tag_counter') &&
  89 + @block.is_visible?('comment_counter') &&
  90 + @block.is_visible?('hit_counter')
  91 + assert all_checked
  92 +
  93 + end
  94 +
  95 + should 'be able to check template counters' do
  96 + template = fast_create(Community, :name => 'Councils', :is_template => true, :environment_id => @environment.id)
  97 + @block.templates_ids_counter = {template.id.to_s => 'false'}
  98 + @block.save!
  99 + get :edit, :id => @block.id
  100 + post :save, :id => @block.id, :block => {:templates_ids_counter => {template.id.to_s => 'true'}}
  101 + @block.reload
  102 +
  103 + assert @block.is_template_counter_active?(template.id)
  104 + end
  105 +
  106 + should 'be able to uncheck template counters' do
  107 + template = fast_create(Community, :name => 'Councils', :is_template => true, :environment_id => @environment.id)
  108 + @block.templates_ids_counter = {template.id.to_s => 'true'}
  109 + @block.save!
  110 + get :edit, :id => @block.id
  111 + post :save, :id => @block.id, :block => {:templates_ids_counter => {template.id.to_s => 'false'}}
  112 + @block.reload
  113 +
  114 + assert_equal false, @block.is_template_counter_active?(template.id)
  115 + end
  116 +
  117 + should 'input user counter be checked by default' do
  118 + get :edit, :id => @block.id
  119 +
  120 + assert_tag :input, :attributes => {:id => 'block_user_counter', :checked => 'checked'}
  121 + end
  122 +
  123 + should 'not input community counter be checked by default' do
  124 + get :edit, :id => @block.id
  125 +
  126 + assert_tag :input, :attributes => {:id => 'block_community_counter'}
  127 + assert_no_tag :input, :attributes => {:id => 'block_community_counter', :checked => 'checked'}
  128 + end
  129 +
  130 + should 'not input enterprise counter be checked by default' do
  131 + get :edit, :id => @block.id
  132 +
  133 + assert_tag :input, :attributes => {:id => 'block_enterprise_counter'}
  134 + assert_no_tag :input, :attributes => {:id => 'block_enterprise_counter', :checked => 'checked'}
  135 + end
  136 +
  137 + should 'not input category counter be checked by default' do
  138 + get :edit, :id => @block.id
  139 +
  140 + assert_tag :input, :attributes => {:id => 'block_category_counter'}
  141 + assert_no_tag :input, :attributes => {:id => 'block_category_counter', :checked => 'checked'}
  142 + end
  143 +
  144 + should 'input tag counter be checked by default' do
  145 + get :edit, :id => @block.id
  146 +
  147 + assert_tag :input, :attributes => {:id => 'block_tag_counter', :checked => 'checked'}
  148 + end
  149 +
  150 + should 'input comment counter be checked by default' do
  151 + get :edit, :id => @block.id
  152 +
  153 + assert_tag :input, :attributes => {:id => 'block_comment_counter', :checked => 'checked'}
  154 + end
  155 +
  156 + should 'input hit counter not be checked by default' do
  157 + get :edit, :id => @block.id
  158 +
  159 + assert_no_tag :input, :attributes => {:id => 'block_hit_counter', :checked => 'checked'}
  160 + end
  161 +end
plugins/statistics/test/functional/statistics_plugin_home_controller_test.rb 0 → 100644
@@ -0,0 +1,147 @@ @@ -0,0 +1,147 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +# Re-raise errors caught by the controller.
  4 +class HomeController; def rescue_action(e) raise e end; end
  5 +
  6 +class HomeControllerTest < ActionController::TestCase
  7 +
  8 + def setup
  9 + @controller = HomeController.new
  10 + @request = ActionController::TestRequest.new
  11 + @response = ActionController::TestResponse.new
  12 +
  13 + Environment.delete_all
  14 +
  15 + @environment = Environment.create(:name => 'testenv', :is_default => true)
  16 + @environment.enabled_plugins = ['StatisticsPlugin']
  17 + @environment.save!
  18 +
  19 + user = create_user('testinguser')
  20 + @environment.add_admin(user.person)
  21 +
  22 + StatisticsBlock.delete_all
  23 + @box1 = Box.create!(:owner => @environment)
  24 + @environment.boxes = [@box1]
  25 +
  26 + @block = StatisticsBlock.new
  27 + @block.box = @box1
  28 + @block.save!
  29 +
  30 + login_as(user.login)
  31 + end
  32 +
  33 + attr_accessor :block
  34 +
  35 + should 'display statistics-block-data class in environment block edition' do
  36 + get :index
  37 +
  38 + assert_tag :div, :attributes => {:class => 'statistics-block-data'}
  39 + end
  40 +
  41 + should 'display users class in statistics-block-data block' do
  42 + get :index
  43 +
  44 + assert_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'users'} }
  45 + end
  46 +
  47 + should 'not display users class in statistics-block-data block' do
  48 + @block.user_counter = false
  49 + @block.save!
  50 + get :index
  51 +
  52 + assert_no_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'users'} }
  53 + end
  54 +
  55 + should 'display communities class in statistics-block-data block' do
  56 + @block.community_counter = true
  57 + @block.save!
  58 + get :index
  59 +
  60 + assert_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'communities'} }
  61 + end
  62 +
  63 + should 'not display communities class in statistics-block-data block' do
  64 + get :index
  65 +
  66 + assert_no_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'communities'} }
  67 + end
  68 +
  69 + should 'display enterprises class in statistics-block-data block' do
  70 + @block.enterprise_counter = true
  71 + @block.save!
  72 + get :index
  73 +
  74 + assert_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'enterprises'} }
  75 + end
  76 +
  77 + should 'not display enterprises class in statistics-block-data block' do
  78 + get :index
  79 +
  80 + assert_no_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'enterprises'} }
  81 + end
  82 +
  83 + should 'display categories class in statistics-block-data block' do
  84 + @block.category_counter = true
  85 + @block.save!
  86 + get :index
  87 +
  88 + assert_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'categories'} }
  89 + end
  90 +
  91 + should 'not display categories class in statistics-block-data block' do
  92 + get :index
  93 +
  94 + assert_no_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'categories'} }
  95 + end
  96 +
  97 + should 'display tags class in statistics-block-data block' do
  98 + get :index
  99 +
  100 + assert_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'tags'} }
  101 + end
  102 +
  103 + should 'not display tags class in statistics-block-data block' do
  104 + @block.tag_counter = false
  105 + @block.save!
  106 + get :index
  107 +
  108 + assert_no_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'tags'} }
  109 + end
  110 +
  111 + should 'display comments class in statistics-block-data block' do
  112 + get :index
  113 +
  114 + assert_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'comments'} }
  115 + end
  116 +
  117 + should 'not display comments class in statistics-block-data block' do
  118 + @block.comment_counter = false
  119 + @block.save!
  120 + get :index
  121 +
  122 + assert_no_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'comments'} }
  123 + end
  124 +
  125 + should 'display hits class in statistics-block-data block' do
  126 + @block.hit_counter = true
  127 + @block.save!
  128 + get :index
  129 +
  130 + assert_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'hits'} }
  131 + end
  132 +
  133 + should 'not display hits class in statistics-block-data block' do
  134 + get :index
  135 +
  136 + assert_no_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'hits'} }
  137 + end
  138 +
  139 + should 'display template name in class in statistics-block-data block' do
  140 + template = fast_create(Community, :name => 'Councils', :is_template => true, :environment_id => @environment.id)
  141 + @block.templates_ids_counter = {template.id.to_s => 'true'}
  142 + @block.save!
  143 + get :index
  144 +
  145 + assert_tag :tag => 'div', :attributes => {:class => 'statistics-block-data'}, :descendant => { :tag => 'li', :attributes => {:class => 'councils'} }
  146 + end
  147 +end
plugins/statistics/test/functional/statistics_plugin_profile_design_controller_test.rb 0 → 100644
@@ -0,0 +1,85 @@ @@ -0,0 +1,85 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +# Re-raise errors caught by the controller.
  4 +class ProfileDesignController; def rescue_action(e) raise e end; end
  5 +
  6 +class ProfileDesignControllerTest < ActionController::TestCase
  7 +
  8 + def setup
  9 + @controller = ProfileDesignController.new
  10 + @request = ActionController::TestRequest.new
  11 + @response = ActionController::TestResponse.new
  12 +
  13 + Environment.delete_all
  14 +
  15 + @environment = Environment.create(:name => 'testenv', :is_default => true)
  16 + @environment.enabled_plugins = ['StatisticsPlugin']
  17 + @environment.save!
  18 +
  19 + user = create_user('testinguser')
  20 + @person = user.person
  21 + @environment.add_admin(@person)
  22 +
  23 + StatisticsBlock.delete_all
  24 + @box1 = Box.create!(:owner => @person)
  25 + @environment.boxes = [@box1]
  26 +
  27 + @block = StatisticsBlock.new
  28 + @block.box = @box1
  29 + @block.save!
  30 +
  31 + login_as(user.login)
  32 + end
  33 +
  34 + attr_accessor :block
  35 +
  36 + should 'be able to edit StatisticsBlock' do
  37 + get :edit, :id => @block.id, :profile => @person.identifier
  38 + assert_tag :tag => 'input', :attributes => { :id => 'block_title' }
  39 + end
  40 +
  41 + should 'be able to save StatisticsBlock' do
  42 + get :edit, :id => @block.id, :profile => @person.identifier
  43 + post :save, :id => @block.id, :block => {:title => 'Statistics' }, :profile => @person.identifier
  44 + @block.reload
  45 + assert_equal 'Statistics', @block.title
  46 + end
  47 +
  48 + should 'be able to uncheck core counters' do
  49 + @block.user_counter = true
  50 + @block.tag_counter = true
  51 + @block.comment_counter = true
  52 + @block.hit_counter = true
  53 + @block.save!
  54 + get :edit, :id => @block.id, :profile => @person.identifier
  55 + post :save, :id => @block.id, :block => {:user_counter => '0', :tag_counter => '0', :comment_counter => '0', :hit_counter => '0' }, :profile => @person.identifier
  56 + @block.reload
  57 + any_checked = @block.is_visible?('user_counter') ||
  58 + @block.is_visible?('tag_counter') ||
  59 + @block.is_visible?('comment_counter') ||
  60 + @block.is_visible?('hit_counter')
  61 + assert_equal false, any_checked
  62 + end
  63 +
  64 + should 'be able to check core counters' do
  65 + @block.user_counter = false
  66 + @block.community_counter = false
  67 + @block.enterprise_counter = false
  68 + @block.category_counter = false
  69 + @block.tag_counter = false
  70 + @block.comment_counter = false
  71 + @block.hit_counter = false
  72 + @block.save!
  73 + get :edit, :id => @block.id, :profile => @person.identifier
  74 + post :save, :id => @block.id, :block => {:user_counter => '1',
  75 + :tag_counter => '1', :comment_counter => '1', :hit_counter => '1' }, :profile => @person.identifier
  76 + @block.reload
  77 + all_checked = @block.is_visible?('user_counter') &&
  78 + @block.is_visible?('tag_counter') &&
  79 + @block.is_visible?('comment_counter') &&
  80 + @block.is_visible?('hit_counter')
  81 + assert all_checked
  82 +
  83 + end
  84 +
  85 +end
plugins/statistics/test/test_helper.rb 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +require File.dirname(__FILE__) + '/../../../test/test_helper'
plugins/statistics/test/unit/statistics_block_test.rb 0 → 100644
@@ -0,0 +1,336 @@ @@ -0,0 +1,336 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +class StatisticsBlockTest < ActiveSupport::TestCase
  3 +
  4 + ['user_counter', 'tag_counter', 'comment_counter'].map do |counter|
  5 + should "#{counter} be true by default" do
  6 + b = StatisticsBlock.new
  7 + assert b.is_visible?(counter)
  8 + end
  9 + end
  10 +
  11 + ['community_counter', 'enterprise_counter', 'category_counter', 'hit_counter'].map do |counter|
  12 + should "#{counter} be false by default" do
  13 + b = StatisticsBlock.new
  14 + assert !b.is_visible?(counter)
  15 + end
  16 + end
  17 +
  18 + should 'inherit from Block' do
  19 + assert_kind_of Block, StatisticsBlock.new
  20 + end
  21 +
  22 + should 'provide a default title' do
  23 + block = StatisticsBlock.new
  24 +
  25 + owner = mock
  26 + owner.expects(:name).returns('my environment')
  27 + block.expects(:owner).returns(owner)
  28 + assert_equal 'Statistics for my environment', block.title
  29 + end
  30 +
  31 + should 'describe itself' do
  32 + assert_not_equal StatisticsBlock.description, Block.description
  33 + end
  34 +
  35 + should 'is_visible? return true if setting is true' do
  36 + b = StatisticsBlock.new
  37 + b.community_counter = true
  38 + assert b.is_visible?('community_counter')
  39 + end
  40 +
  41 + should 'is_visible? return false if setting is false' do
  42 + b = StatisticsBlock.new
  43 + b.community_counter = false
  44 + assert !b.is_visible?('community_counter')
  45 + end
  46 +
  47 + should 'templates return the Community templates of the Environment' do
  48 + b = StatisticsBlock.new
  49 + e = fast_create(Environment)
  50 +
  51 + t1 = fast_create(Community, :is_template => true, :environment_id => e.id)
  52 + t2 = fast_create(Community, :is_template => true, :environment_id => e.id)
  53 + fast_create(Community, :is_template => false)
  54 +
  55 + b.expects(:owner).at_least_once.returns(e)
  56 +
  57 + t = b.templates
  58 + assert_equal [], [t1,t2] - t
  59 + assert_equal [], t - [t1,t2]
  60 + end
  61 +
  62 + should 'users return the amount of users of the Environment' do
  63 + b = StatisticsBlock.new
  64 + e = fast_create(Environment)
  65 +
  66 + fast_create(Person, :environment_id => e.id)
  67 + fast_create(Person, :environment_id => e.id)
  68 + fast_create(Person, :visible => false, :environment_id => e.id)
  69 +
  70 + b.expects(:owner).at_least_once.returns(e)
  71 +
  72 + assert_equal 2, b.users
  73 + end
  74 +
  75 + should 'users return the amount of members of the community' do
  76 + b = StatisticsBlock.new
  77 +
  78 + c1 = fast_create(Community)
  79 + c1.add_member(fast_create(Person))
  80 + c1.add_member(fast_create(Person))
  81 + c1.add_member(fast_create(Person))
  82 + c1.add_member(fast_create(Person, :visible => false))
  83 + c1.add_member(fast_create(Person, :visible => false))
  84 +
  85 + b.expects(:owner).at_least_once.returns(c1)
  86 + assert_equal 3, b.users
  87 + end
  88 +
  89 + should 'users return the amount of friends of the person' do
  90 + b = StatisticsBlock.new
  91 +
  92 + p1 = fast_create(Person)
  93 + p1.add_friend(fast_create(Person))
  94 + p1.add_friend(fast_create(Person))
  95 + p1.add_friend(fast_create(Person))
  96 + p1.add_friend(fast_create(Person, :visible => false))
  97 + p1.add_friend(fast_create(Person, :visible => false))
  98 +
  99 + b.expects(:owner).at_least_once.returns(p1)
  100 + assert_equal 3, b.users
  101 + end
  102 +
  103 + should 'communities return the amount of communities of the Environment' do
  104 + b = StatisticsBlock.new
  105 + e = fast_create(Environment)
  106 +
  107 + fast_create(Community, :environment_id => e.id)
  108 + fast_create(Community, :environment_id => e.id)
  109 + fast_create(Community, :visible => false, :environment_id => e.id)
  110 +
  111 + b.expects(:owner).at_least_once.returns(e)
  112 +
  113 + assert_equal 2, b.communities
  114 + end
  115 +
  116 + should 'enterprises return the amount of enterprises of the Environment' do
  117 + b = StatisticsBlock.new
  118 + e = fast_create(Environment)
  119 +
  120 + fast_create(Enterprise, :environment_id => e.id)
  121 + fast_create(Enterprise, :environment_id => e.id)
  122 + fast_create(Enterprise, :visible => false, :environment_id => e.id)
  123 +
  124 + b.expects(:owner).at_least_once.returns(e)
  125 +
  126 + assert_equal 2, b.enterprises
  127 + end
  128 +
  129 + should 'categories return the amount of categories of the Environment' do
  130 + b = StatisticsBlock.new
  131 + e = fast_create(Environment)
  132 +
  133 + fast_create(Category, :environment_id => e.id)
  134 + fast_create(Category, :environment_id => e.id)
  135 +
  136 + b.expects(:owner).at_least_once.returns(e)
  137 +
  138 + assert_equal 2, b.categories
  139 + end
  140 +
  141 + should 'tags return the amount of tags of the Environment' do
  142 + b = StatisticsBlock.new
  143 + e = fast_create(Environment)
  144 +
  145 + p1 = fast_create(Person, :environment_id => e.id)
  146 + a1 = fast_create(Article, :profile_id => p1.id)
  147 + t1 = fast_create(Tag, :name => 'T1')
  148 + t2 = fast_create(Tag, :name => 'T2')
  149 + a1.tags << t1
  150 + a1.tags << t2
  151 + a2 = fast_create(Article, :profile_id => p1.id)
  152 + t3 = fast_create(Tag, :name => 'T3')
  153 + t4 = fast_create(Tag, :name => 'T4')
  154 + a2.tags << t3
  155 + a2.tags << t4
  156 +
  157 + b.expects(:owner).at_least_once.returns(e)
  158 +
  159 + assert_equal 4, b.tags
  160 + end
  161 +
  162 + should 'tags return the amount of tags of the community' do
  163 + b = StatisticsBlock.new
  164 + e = fast_create(Environment)
  165 +
  166 + c1 = fast_create(Community, :environment_id => e.id)
  167 + a1 = fast_create(Article, :profile_id => c1.id)
  168 + t1 = fast_create(Tag, :name => 'T1')
  169 + t2 = fast_create(Tag, :name => 'T2')
  170 + a1.tags << t1
  171 + a1.tags << t2
  172 + a2 = fast_create(Article, :profile_id => c1.id)
  173 + t3 = fast_create(Tag, :name => 'T3')
  174 + t4 = fast_create(Tag, :name => 'T4')
  175 + a2.tags << t3
  176 + a2.tags << t4
  177 +
  178 + b.expects(:owner).at_least_once.returns(c1)
  179 +
  180 + assert_equal 4, b.tags
  181 + end
  182 +
  183 + should 'tags return the amount of tags of the profile (person)' do
  184 + b = StatisticsBlock.new
  185 + e = fast_create(Environment)
  186 +
  187 + p1 = fast_create(Person, :environment_id => e.id)
  188 + a1 = fast_create(Article, :profile_id => p1.id)
  189 + t1 = fast_create(Tag, :name => 'T1')
  190 + t2 = fast_create(Tag, :name => 'T2')
  191 + a1.tags << t1
  192 + a1.tags << t2
  193 + a2 = fast_create(Article, :profile_id => p1.id)
  194 + t3 = fast_create(Tag, :name => 'T3')
  195 + t4 = fast_create(Tag, :name => 'T4')
  196 + a2.tags << t3
  197 + a2.tags << t4
  198 +
  199 + b.expects(:owner).at_least_once.returns(p1)
  200 +
  201 + assert_equal 4, b.tags
  202 + end
  203 +
  204 + should 'comments return the amount of comments of the Environment' do
  205 + b = StatisticsBlock.new
  206 + e = fast_create(Environment)
  207 +
  208 + p1 = fast_create(Person, :environment_id => e.id)
  209 + a1 = fast_create(Article, :profile_id => p1.id)
  210 +
  211 + Comment.create!(:source => a1, :body => 'C1', :author_id => 1)
  212 + Comment.create!(:source => a1, :body => 'C2', :author_id => 1)
  213 +
  214 + a2 = fast_create(Article, :profile_id => p1.id)
  215 + Comment.create!(:source => a2, :body => 'C3', :author_id => 1)
  216 + Comment.create!(:source => a2, :body => 'C4', :author_id => 1)
  217 +
  218 + b.expects(:owner).at_least_once.returns(e)
  219 +
  220 + assert_equal 4, b.comments
  221 + end
  222 +
  223 + should 'comments return the amount of comments of the community' do
  224 + b = StatisticsBlock.new
  225 + e = Environment.default
  226 +
  227 + c1 = fast_create(Community, :environment_id => e.id)
  228 + a1 = fast_create(Article, :profile_id => c1.id)
  229 + Comment.create!(:source => a1, :body => 'C1', :author_id => 1)
  230 + Comment.create!(:source => a1, :body => 'C2', :author_id => 1)
  231 +
  232 + a2 = fast_create(Article, :profile_id => c1.id)
  233 + Comment.create!(:source => a2, :body => 'C3', :author_id => 1)
  234 + Comment.create!(:source => a2, :body => 'C4', :author_id => 1)
  235 +
  236 + b.expects(:owner).at_least_once.returns(c1)
  237 +
  238 + assert_equal 4, b.comments
  239 + end
  240 +
  241 + should 'comments return the amount of comments of the profile (person)' do
  242 + b = StatisticsBlock.new
  243 + e = fast_create(Environment)
  244 +
  245 + p1 = fast_create(Person, :environment_id => e.id)
  246 + a1 = fast_create(Article, :profile_id => p1.id)
  247 + Comment.create!(:source => a1, :body => 'C1', :author_id => 1)
  248 + Comment.create!(:source => a1, :body => 'C2', :author_id => 1)
  249 +
  250 + a2 = fast_create(Article, :profile_id => p1.id)
  251 + Comment.create!(:source => a1, :body => 'C3', :author_id => 1)
  252 + Comment.create!(:source => a1, :body => 'C4', :author_id => 1)
  253 +
  254 + b.expects(:owner).at_least_once.returns(p1)
  255 +
  256 + assert_equal 4, b.comments
  257 + end
  258 +
  259 + should 'hits return the amount of hits of the Environment' do
  260 + b = StatisticsBlock.new
  261 + e = fast_create(Environment)
  262 +
  263 + p1 = fast_create(Person, :environment_id => e.id)
  264 + a1 = fast_create(Article, :profile_id => p1.id, :hits => 2)
  265 + a2 = fast_create(Article, :profile_id => p1.id, :hits => 5)
  266 +
  267 + b.expects(:owner).at_least_once.returns(e)
  268 +
  269 + assert_equal 7, b.hits
  270 + end
  271 +
  272 + should 'hits return the amount of hits of the community' do
  273 + b = StatisticsBlock.new
  274 + e = fast_create(Environment)
  275 +
  276 + c1 = fast_create(Community, :environment_id => e.id)
  277 + a1 = fast_create(Article, :profile_id => c1.id, :hits => 2)
  278 + a2 = fast_create(Article, :profile_id => c1.id, :hits => 5)
  279 +
  280 + b.expects(:owner).at_least_once.returns(c1)
  281 +
  282 + assert_equal 7, b.hits
  283 + end
  284 +
  285 + should 'hits return the amount of hits of the profile (person)' do
  286 + b = StatisticsBlock.new
  287 + e = fast_create(Environment)
  288 +
  289 + p1 = fast_create(Person, :environment_id => e.id)
  290 + a1 = fast_create(Article, :profile_id => p1.id, :hits => 2)
  291 + a2 = fast_create(Article, :profile_id => p1.id, :hits => 5)
  292 +
  293 + b.expects(:owner).at_least_once.returns(p1)
  294 +
  295 + assert_equal 7, b.hits
  296 + end
  297 +
  298 + should 'is_counter_available? return true for all counters if owner is environment' do
  299 + b = StatisticsBlock.new
  300 + e = fast_create(Environment)
  301 +
  302 + b.expects(:owner).at_least_once.returns(e)
  303 +
  304 + assert b.is_counter_available?(:user_counter)
  305 + end
  306 +
  307 + should 'is_template_counter_active? return true if setting is true' do
  308 + b = StatisticsBlock.new
  309 + b.templates_ids_counter = {'1' => 'true'}
  310 + assert b.is_template_counter_active?(1)
  311 + end
  312 +
  313 + should 'is_template_counter_active? return false if setting is false' do
  314 + b = StatisticsBlock.new
  315 + b.templates_ids_counter = {'1' => 'false'}
  316 + assert !b.is_template_counter_active?(1)
  317 + end
  318 +
  319 + should 'template_counter_count return the amount of communities of the Environment using a template' do
  320 + b = StatisticsBlock.new
  321 + e = fast_create(Environment)
  322 +
  323 + t1 = fast_create(Community, :is_template => true, :environment_id => e.id)
  324 + t2 = fast_create(Community, :is_template => true, :environment_id => e.id)
  325 + fast_create(Community, :is_template => false, :environment_id => e.id, :template_id => t1.id, :visible => true)
  326 + fast_create(Community, :is_template => false, :environment_id => e.id, :template_id => t1.id, :visible => true)
  327 + fast_create(Community, :is_template => false, :environment_id => e.id, :template_id => t1.id, :visible => false)
  328 +
  329 + fast_create(Community, :is_template => false, :environment_id => e.id, :template_id => t2.id, :visible => true)
  330 + fast_create(Community, :is_template => false, :environment_id => e.id, :template_id => t2.id, :visible => false)
  331 +
  332 + b.expects(:owner).at_least_once.returns(e)
  333 +
  334 + assert_equal 2, b.template_counter_count(t1.id)
  335 + end
  336 +end
plugins/statistics/test/unit/statistics_plugin_test.rb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class StatisticsPluginTest < ActiveSupport::TestCase
  4 +
  5 + should "return StatisticsBlock in extra_mlocks class method" do
  6 + assert StatisticsPlugin.extra_blocks.keys.include?(StatisticsBlock)
  7 + end
  8 +
  9 +end
plugins/statistics/views/box_organizer/_statistics_block.rhtml 0 → 100644
@@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
  1 +<%= labelled_form_field check_box(:block, :user_counter) + _('Show user counter'), '' %>
  2 +
  3 +<% if @block.is_counter_available?(:community_counter) %>
  4 +<%= labelled_form_field check_box(:block, :community_counter) + _('Show community counter'), '' %>
  5 +<% end %>
  6 +
  7 +<% if @block.is_counter_available?(:enterprise_counter) %>
  8 +<%= labelled_form_field check_box(:block, :enterprise_counter) + _('Show enterprise counter'), '' %>
  9 +<% end %>
  10 +
  11 +<% if @block.is_counter_available?(:category_counter) %>
  12 +<%= labelled_form_field check_box(:block, :category_counter) + _('Show category counter'), '' %>
  13 +<% end %>
  14 +
  15 +<% if @block.is_counter_available?(:tag_counter) %>
  16 +<%= labelled_form_field check_box(:block, :tag_counter) + _('Show tag counter'), '' %>
  17 +<% end %>
  18 +
  19 +<% if @block.is_counter_available?(:comment_counter) %>
  20 +<%= labelled_form_field check_box(:block, :comment_counter) + _('Show comment counter'), '' %>
  21 +<% end %>
  22 +
  23 +<% if @block.is_counter_available?(:hit_counter) %>
  24 +<%= labelled_form_field check_box(:block, :hit_counter) + _('Show hit counter'), '' %>
  25 +<% end %>
  26 +
  27 +<% if @block.is_counter_available?(:templates_ids_counter) %>
  28 +<% @block.templates.map do |item|%>
  29 + <%= hidden_field_tag("block[templates_ids_counter][#{item.id}]", false)%>
  30 + <%= labelled_form_field check_box_tag("block[templates_ids_counter][#{item.id}]", true, @block.is_template_counter_active?(item.id)) + _("Show counter for communities with template %s" % item.name), '' %>
  31 +<% end %>
  32 +<% end %>
plugins/statistics/views/environment_design 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +box_organizer
0 \ No newline at end of file 2 \ No newline at end of file
plugins/statistics/views/profile_design 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +box_organizer
0 \ No newline at end of file 2 \ No newline at end of file
plugins/statistics/views/statistics_block.rhtml 0 → 100644
@@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
  1 +<h3 class="block-title">
  2 + <span><%=block.title%></span>
  3 +</h3>
  4 +<div class="statistics-block-data">
  5 + <ul>
  6 + <% if block.is_visible?('user_counter') %>
  7 + <li class="users"><span class="amount"><%= block.users%> </span><span class="label"><%= _('users')%></span></li>
  8 + <% end %>
  9 + <% if block.is_visible?('enterprise_counter') && !block.environment.enabled?('disable_asset_enterprises') %>
  10 + <li class="enterprises"><span class="amount"><%= block.enterprises%> </span><span class="label"><%= _('enterprises')%></span></li>
  11 + <% end %>
  12 + <% if block.is_visible?('community_counter') %>
  13 + <li class="communities"><span class="amount"><%= block.communities%> </span><span class="label"><%= _('communities')%></span></li>
  14 + <% end %>
  15 + <% if block.is_visible?('category_counter') %>
  16 + <li class="categories"><span class="amount"><%= block.categories%> </span><span class="label"><%= _('categories')%></span></li>
  17 + <% end %>
  18 + <% if block.is_visible?('tag_counter') %>
  19 + <li class="tags"><span class="amount"><%= block.tags%> </span><span class="label"><%= _('tags')%></span></li>
  20 + <% end %>
  21 + <% if block.is_visible?('comment_counter') %>
  22 + <li class="comments"><span class="amount"><%= block.comments%> </span><span class="label"><%= _('comments')%></span></li>
  23 + <% end %>
  24 + <% if block.is_visible?('hit_counter') %>
  25 + <li class="hits"><span class="amount"><%= block.hits%> </span><span class="label"><%= _('hits')%></span></li>
  26 + <% end %>
  27 +
  28 + <% if block.owner.kind_of?(Environment) then %>
  29 + <% block.templates.each do |item| %>
  30 + <% if block.is_template_counter_active? item.id %>
  31 + <li class="<%= item.name.to_slug%>"><span class="amount"><%= block.template_counter_count(item.id)%> </span><span class="label"><%= item.name%></span></li>
  32 + <% end %>
  33 + <% end %>
  34 + <% end %>
  35 + </ul>
  36 +</div>
public/javascripts/manage-fields.js 0 → 100644
@@ -0,0 +1,83 @@ @@ -0,0 +1,83 @@
  1 +function update_active(name_active, name_required, name_signup) {
  2 + var required = jQuery("input[name='" + name_required + "']")[1]
  3 + var signup = jQuery("input[name='" + name_signup + "']")[1]
  4 + var active = jQuery("input[name='" + name_active + "']")[1]
  5 +
  6 + if(required.checked || signup.checked)
  7 + active.checked = true
  8 +}
  9 +
  10 +function active_action(obj_active, name_required, name_signup) {
  11 + var required = jQuery("input[name='" + name_required + "']")[0]
  12 + var signup = jQuery("input[name='" + name_signup + "']")[0]
  13 +
  14 + required.disabled = signup.disabled = !obj_active.checked
  15 +}
  16 +
  17 +function required_action(name_active, name_required, name_signup) {
  18 + var obj_required = jQuery("input[name='" + name_required + "']")[1]
  19 +
  20 + if(obj_required.checked) {
  21 + jQuery("input[name='" + name_signup + "']")[0].checked = true
  22 + jQuery("input[name='" + name_signup + "']")[1].checked = true
  23 + }
  24 +
  25 + update_active(name_active, name_required, name_signup)
  26 +}
  27 +
  28 +function signup_action(name_active, name_required, name_signup) {
  29 + var obj_signup = jQuery("input[name='" + name_signup + "']")[1]
  30 +
  31 + if(!obj_signup.checked) {
  32 + jQuery("input[name='" + name_required + "']")[0].checked = false
  33 + jQuery("input[name='" + name_required + "']")[1].checked = false
  34 + }
  35 +
  36 + update_active(name_active, name_required, name_signup)
  37 +}
  38 +
  39 +
  40 +jQuery(document).ready(function(){
  41 + function check_fields(check, table_id, start) {
  42 + var checkboxes = jQuery("#" + table_id + " tbody tr td input[type='checkbox']")
  43 + for (var i = start; i < checkboxes.length; i+=3) {
  44 + checkboxes[i].checked = check
  45 + }
  46 + }
  47 +
  48 + function verify_checked(fields_id){
  49 + var checkboxes = jQuery("#" + fields_id + "_fields_conf tbody tr td input[type='checkbox']")
  50 + for (var i = 2; i >= 0; i--) {
  51 + var allchecked = true
  52 + for (var j = i+3; j < checkboxes.length; j+=3) {
  53 + if(!checkboxes[j].checked) {
  54 + allchecked = false
  55 + break
  56 + }
  57 + }
  58 +
  59 + var checkbox = jQuery(checkboxes[i+3]).attr("id").split("_")
  60 + jQuery("#" + checkbox.first() + "_" + checkbox.last()).attr("checked", allchecked)
  61 + }
  62 + }
  63 +
  64 + function check_all(fields_id) {
  65 + jQuery("#" + fields_id + "_active").click(function (){check_fields(this.checked, fields_id + "_fields_conf", 0)})
  66 + jQuery("#" + fields_id + "_required").click(function (){check_fields(this.checked, fields_id + "_fields_conf", 1)})
  67 + jQuery("#" + fields_id +"_signup").click(function (){check_fields(this.checked, fields_id + "_fields_conf", 2)})
  68 + verify_checked(fields_id)
  69 + }
  70 +
  71 + check_all("person")
  72 + check_all("enterprise")
  73 + check_all("community")
  74 +
  75 + jQuery("input[type='checkbox']").click(function (){
  76 + var checkbox = jQuery(this).attr("id").split("_")
  77 + verify_checked(checkbox.first())
  78 +
  79 + if(this.checked == false) {
  80 + jQuery("#" + checkbox.first() + "_" + checkbox.last()).attr("checked", false)
  81 + }
  82 + })
  83 +})
public/stylesheets/application.css
  1 +/* browser fixes */
  2 +
  3 +img:-moz-broken {
  4 + -moz-force-broken-image-icon:1;
  5 +}
  6 +
  7 +/* general styles */
  8 +
1 body { 9 body {
2 padding: 0px; 10 padding: 0px;
3 margin: 0px; 11 margin: 0px;
@@ -346,21 +354,32 @@ div.pending-tasks { @@ -346,21 +354,32 @@ div.pending-tasks {
346 margin-bottom: 1px; 354 margin-bottom: 1px;
347 } 355 }
348 /* * * category ajax selector * * */ 356 /* * * category ajax selector * * */
349 - 357 +#category-ajax-selector .category-helper-label {
  358 + font-size: 16px;
  359 + color: rgb(158, 158, 158);
  360 + padding: 5px 0px;
  361 +}
350 #category-ajax-selector { 362 #category-ajax-selector {
351 border: 1px solid #AAA; 363 border: 1px solid #AAA;
352 - background: #EEE;  
353 - padding: 15px 0px 15px 20px;  
354 - margin: 30px 0px 0px 0px; 364 + padding: 3px 10px 10px 10px;
  365 + margin: 0px 0px 0px 0px;
355 position: relative; 366 position: relative;
356 - font-size: 18px; 367 + font-size: 10px;
  368 + background-color: #fcfcf9;
357 } 369 }
358 #category-ajax-selector a { 370 #category-ajax-selector a {
359 - font-size: 14px; 371 + font-size: 12px;
360 } 372 }
361 -#category-ajax-selector h3 {  
362 - margin: 10px 0px;  
363 - font-size: 14px; 373 +#selected-categories {
  374 + padding-bottom: 5px;
  375 +}
  376 +#selected-categories .label {
  377 + font-size: 16px;
  378 + margin-bottom: 10px;
  379 + margin-top: 5px;
  380 +}
  381 +.selected-category {
  382 + padding: 2px 0;
364 } 383 }
365 #category-ajax-selector .box-title { 384 #category-ajax-selector .box-title {
366 position: absolute; 385 position: absolute;
@@ -376,25 +395,32 @@ div.pending-tasks { @@ -376,25 +395,32 @@ div.pending-tasks {
376 .msie6 #category-ajax-selector .box-title { 395 .msie6 #category-ajax-selector .box-title {
377 top: -29px; 396 top: -29px;
378 } 397 }
379 -#category-ajax-selector .select-subcategory-link { 398 +#category-ajax-selector .select-subcategory-link,
  399 +.select-subcategory-link {
380 border: 1px solid #BBB; 400 border: 1px solid #BBB;
381 padding: 1px 3px; 401 padding: 1px 3px;
382 margin: 0px 1px; 402 margin: 0px 1px;
383 text-decoration: none; 403 text-decoration: none;
384 white-space: nowrap; 404 white-space: nowrap;
385 - font-size: 11px; 405 + font-size: 12px;
  406 + line-height: 20px;
  407 + border-radius: 3px;
  408 +}
  409 +#category-ajax-selector .selected-category .select-subcategory-link {
  410 + border: 0;
386 } 411 }
387 -#category-ajax-selector .select-subcategory-link:hover { 412 +#category-ajax-selector .select-subcategory-link:hover,
  413 +.select-subcategory-link:hover {
388 background-color: black; 414 background-color: black;
389 } 415 }
390 #category-ajax-selector .button { 416 #category-ajax-selector .button {
391 - display: block;  
392 - position: absolute;  
393 top: 4px; 417 top: 4px;
394 right: 2px; 418 right: 2px;
395 } 419 }
396 -#category-ajax-selector .icon-save {  
397 - right: 25px; 420 +#category-ajax-selector hr {
  421 + border: 0;
  422 + border-bottom: 1px solid #EEE;
  423 + margin-top: 15px;
398 } 424 }
399 #profile-header, #profile-footer { 425 #profile-header, #profile-footer {
400 clear: both; 426 clear: both;
@@ -1727,8 +1753,8 @@ a.button.disabled, input.disabled { @@ -1727,8 +1753,8 @@ a.button.disabled, input.disabled {
1727 display: none; 1753 display: none;
1728 } 1754 }
1729 1755
1730 -#box-organizer .block:focus .button-bar,  
1731 -#box-organizer .block:hover .button-bar { 1756 +#box-organizer .block-outer:focus .button-bar,
  1757 +#box-organizer .block-outer:hover .button-bar {
1732 display: block; 1758 display: block;
1733 } 1759 }
1734 1760
@@ -1834,8 +1860,13 @@ a.button.disabled, input.disabled { @@ -1834,8 +1860,13 @@ a.button.disabled, input.disabled {
1834 } 1860 }
1835 /* ==> blocks/link-list-block.css <<= */ 1861 /* ==> blocks/link-list-block.css <<= */
1836 1862
  1863 +#edit-link-list-block {
  1864 + width: 820px;
  1865 +}
  1866 +
1837 #edit-link-list-block table { 1867 #edit-link-list-block table {
1838 - width: 100%; 1868 + width: auto;
  1869 + margin-bottom: 10px;
1839 } 1870 }
1840 #edit-link-list-block table .cel-address { 1871 #edit-link-list-block table .cel-address {
1841 width: 220px; 1872 width: 220px;
@@ -4183,6 +4214,11 @@ h1#agenda-title { @@ -4183,6 +4214,11 @@ h1#agenda-title {
4183 display: block; 4214 display: block;
4184 float: left; 4215 float: left;
4185 } 4216 }
  4217 +
  4218 +.actions .members-buttons-cell {
  4219 + width : 100px
  4220 +}
  4221 +
4186 .controller-profile_members .msie6 .button-bar a { 4222 .controller-profile_members .msie6 .button-bar a {
4187 position: relative; 4223 position: relative;
4188 } 4224 }
@@ -6475,3 +6511,15 @@ ul.article-versions li { @@ -6475,3 +6511,15 @@ ul.article-versions li {
6475 font-size: 13px; 6511 font-size: 13px;
6476 padding: 3px 0px; 6512 padding: 3px 0px;
6477 } 6513 }
  6514 +
  6515 +/* * * Admin manage fields * * */
  6516 +
  6517 +.controller-features .manage-fields-batch-actions,
  6518 +.controller-features .manage-fields-batch-actions:hover {
  6519 + border-bottom:solid 2px #000;
  6520 + background-color: #EEE;
  6521 +}
  6522 +
  6523 +.controller-features .manage-fields-batch-actions td {
  6524 + font-style: italic;
  6525 +}
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 libnokogiri-ruby libmocha-ruby imagemagick po4a xvfb libxml2-dev libxslt-dev postgresql openjdk-6-jre 8 +run sudo apt-get -y install libtidy-ruby libhpricot-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/application_controller_test.rb
@@ -233,7 +233,7 @@ class ApplicationControllerTest &lt; ActionController::TestCase @@ -233,7 +233,7 @@ class ApplicationControllerTest &lt; ActionController::TestCase
233 get :index 233 get :index
234 234
235 assert_tag :tag => 'div', :attributes => { :id => 'theme-test-panel' }, :descendant => { 235 assert_tag :tag => 'div', :attributes => { :id => 'theme-test-panel' }, :descendant => {
236 - :tag => 'a', :attributes => { :href => '/myprofile/testinguser/themes/edit/my-test-theme'} 236 + :tag => 'a', :attributes => { :href => '/myprofile/testinguser/profile_themes/edit/my-test-theme'}
237 } 237 }
238 #{ :tag => 'a', :attributes => { :href => '/myprofile/testinguser/themes/stop_test/my-test-theme'} } 238 #{ :tag => 'a', :attributes => { :href => '/myprofile/testinguser/themes/stop_test/my-test-theme'} }
239 end 239 end
test/functional/cms_controller_test.rb
@@ -451,24 +451,23 @@ class CmsControllerTest &lt; ActionController::TestCase @@ -451,24 +451,23 @@ class CmsControllerTest &lt; ActionController::TestCase
451 assert_tag :tag => 'h3', :content => /max size #{UploadedFile.max_size.to_humanreadable}/ 451 assert_tag :tag => 'h3', :content => /max size #{UploadedFile.max_size.to_humanreadable}/
452 end 452 end
453 453
454 - should 'display link for selecting categories' do  
455 - # FIXME  
456 - assert true  
457 - #env = Environment.default  
458 - #top = env.categories.build(:display_in_menu => true, :name => 'Top-Level category'); top.save!  
459 - #c1 = env.categories.build(:display_in_menu => true, :name => "Test category 1", :parent_id => top.id); c1.save!  
460 - #c2 = env.categories.build(:display_in_menu => true, :name => "Test category 2", :parent_id => top.id); c2.save!  
461 - #c3 = env.categories.build(:display_in_menu => true, :name => "Test Category 3", :parent_id => top.id); c3.save!  
462 -  
463 - #article = Article.new(:name => 'test')  
464 - #article.profile = profile  
465 - #article.save!  
466 -  
467 - #get :edit, :profile => profile.identifier, :id => article.id  
468 -  
469 - #[c1,c2,c3].each do |item|  
470 - # assert_tag :tag => 'a', :attributes => { :id => "select-category-#{item.id}-link" }  
471 - #end 454 + should 'display link for selecting top categories' do
  455 + env = Environment.default
  456 + top = env.categories.build(:display_in_menu => true, :name => 'Top-Level category'); top.save!
  457 + top2 = env.categories.build(:display_in_menu => true, :name => 'Top-Level category 2'); top2.save!
  458 + c1 = env.categories.build(:display_in_menu => true, :name => "Test category 1", :parent_id => top.id); c1.save!
  459 + c2 = env.categories.build(:display_in_menu => true, :name => "Test category 2", :parent_id => top.id); c2.save!
  460 + c3 = env.categories.build(:display_in_menu => true, :name => "Test Category 3", :parent_id => top.id); c3.save!
  461 +
  462 + article = Article.new(:name => 'test')
  463 + article.profile = profile
  464 + article.save!
  465 +
  466 + get :edit, :profile => profile.identifier, :id => article.id
  467 +
  468 + [top, top2].each do |item|
  469 + assert_tag :tag => 'a', :attributes => { :id => "select-category-#{item.id}-link" }
  470 + end
472 end 471 end
473 472
474 should 'be able to associate articles with categories' do 473 should 'be able to associate articles with categories' do
test/functional/environment_design_controller_test.rb
@@ -6,6 +6,8 @@ class EnvironmentDesignController; def rescue_action(e) raise e end; end @@ -6,6 +6,8 @@ class EnvironmentDesignController; def rescue_action(e) raise e end; end
6 6
7 class EnvironmentDesignControllerTest < ActionController::TestCase 7 class EnvironmentDesignControllerTest < ActionController::TestCase
8 8
  9 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  10 + # the Noosfero core soon, see ActionItem3045
9 ALL_BLOCKS = [ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ] 11 ALL_BLOCKS = [ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ]
10 12
11 def setup 13 def setup
@@ -83,6 +85,8 @@ class EnvironmentDesignControllerTest &lt; ActionController::TestCase @@ -83,6 +85,8 @@ class EnvironmentDesignControllerTest &lt; ActionController::TestCase
83 assert_tag :tag => 'p', :attributes => { :id => 'no_portal_community' } 85 assert_tag :tag => 'p', :attributes => { :id => 'no_portal_community' }
84 end 86 end
85 87
  88 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  89 + # the Noosfero core soon, see ActionItem3045
86 should 'be able to edit EnvironmentStatisticsBlock' do 90 should 'be able to edit EnvironmentStatisticsBlock' do
87 login_as(create_admin_user(Environment.default)) 91 login_as(create_admin_user(Environment.default))
88 b = EnvironmentStatisticsBlock.create! 92 b = EnvironmentStatisticsBlock.create!
test/functional/profile_controller_test.rb
@@ -176,7 +176,7 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -176,7 +176,7 @@ class ProfileControllerTest &lt; ActionController::TestCase
176 should 'not show Leave This Community button for non-registered users' do 176 should 'not show Leave This Community button for non-registered users' do
177 community = Community.create!(:name => 'my test community') 177 community = Community.create!(:name => 'my test community')
178 community.boxes.first.blocks << block = ProfileInfoBlock.create! 178 community.boxes.first.blocks << block = ProfileInfoBlock.create!
179 - get :profile_info, :profile => community.identifier, :block_id => block.id 179 + get :index, :profile => community.identifier
180 assert_no_match /\/profile\/#{@profile.identifier}\/leave/, @response.body 180 assert_no_match /\/profile\/#{@profile.identifier}\/leave/, @response.body
181 end 181 end
182 182
@@ -206,7 +206,7 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -206,7 +206,7 @@ class ProfileControllerTest &lt; ActionController::TestCase
206 friend = create_user_full('friendtestuser').person 206 friend = create_user_full('friendtestuser').person
207 friend.user.activate 207 friend.user.activate
208 friend.boxes.first.blocks << block = ProfileInfoBlock.create! 208 friend.boxes.first.blocks << block = ProfileInfoBlock.create!
209 - get :profile_info, :profile => friend.identifier, :block_id => block.id 209 + get :index, :profile => friend.identifier
210 assert_match /Add friend/, @response.body 210 assert_match /Add friend/, @response.body
211 end 211 end
212 212
@@ -215,7 +215,7 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -215,7 +215,7 @@ class ProfileControllerTest &lt; ActionController::TestCase
215 friend = create_user_full('friendtestuser').person 215 friend = create_user_full('friendtestuser').person
216 friend.boxes.first.blocks << block = ProfileInfoBlock.create! 216 friend.boxes.first.blocks << block = ProfileInfoBlock.create!
217 AddFriend.create!(:person => @profile, :friend => friend) 217 AddFriend.create!(:person => @profile, :friend => friend)
218 - get :profile_info, :profile => friend.identifier, :block_id => block.id 218 + get :index, :profile => friend.identifier
219 assert_no_match /Add friend/, @response.body 219 assert_no_match /Add friend/, @response.body
220 end 220 end
221 221
@@ -226,7 +226,7 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -226,7 +226,7 @@ class ProfileControllerTest &lt; ActionController::TestCase
226 @profile.add_friend(friend) 226 @profile.add_friend(friend)
227 @profile.friends.reload 227 @profile.friends.reload
228 assert @profile.is_a_friend?(friend) 228 assert @profile.is_a_friend?(friend)
229 - get :profile_info, :profile => friend.identifier, :block_id => block.id 229 + get :index, :profile => friend.identifier
230 assert_no_match /Add friend/, @response.body 230 assert_no_match /Add friend/, @response.body
231 end 231 end
232 232
@@ -301,13 +301,13 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -301,13 +301,13 @@ class ProfileControllerTest &lt; ActionController::TestCase
301 should 'display contact us for enterprises' do 301 should 'display contact us for enterprises' do
302 ent = Enterprise.create!(:name => 'my test enterprise', :identifier => 'my-test-enterprise') 302 ent = Enterprise.create!(:name => 'my test enterprise', :identifier => 'my-test-enterprise')
303 ent.boxes.first.blocks << block = ProfileInfoBlock.create! 303 ent.boxes.first.blocks << block = ProfileInfoBlock.create!
304 - get :profile_info, :profile => 'my-test-enterprise', :block_id => block.id 304 + get :index, :profile => 'my-test-enterprise'
305 assert_match /\/contact\/my-test-enterprise\/new/, @response.body 305 assert_match /\/contact\/my-test-enterprise\/new/, @response.body
306 end 306 end
307 307
308 should 'not display contact us for non-enterprises' do 308 should 'not display contact us for non-enterprises' do
309 @profile.boxes.first.blocks << block = ProfileInfoBlock.create! 309 @profile.boxes.first.blocks << block = ProfileInfoBlock.create!
310 - get :profile_info, :profile => @profile.identifier, :block_id => block.id 310 + get :index, :profile => @profile.identifier
311 assert_no_match /\/contact\/#{@profile.identifier}\/new/, @response.body 311 assert_no_match /\/contact\/#{@profile.identifier}\/new/, @response.body
312 end 312 end
313 313
@@ -315,7 +315,7 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -315,7 +315,7 @@ class ProfileControllerTest &lt; ActionController::TestCase
315 ent = Enterprise.create! :name => 'my test enterprise', :identifier => 'my-test-enterprise' 315 ent = Enterprise.create! :name => 'my test enterprise', :identifier => 'my-test-enterprise'
316 ent.boxes.first.blocks << block = ProfileInfoBlock.create! 316 ent.boxes.first.blocks << block = ProfileInfoBlock.create!
317 ent.update_attribute(:enable_contact_us, false) 317 ent.update_attribute(:enable_contact_us, false)
318 - get :profile_info, :profile => 'my-test-enterprise', :block_id => block.id 318 + get :index, :profile => 'my-test-enterprise'
319 assert_no_match /\/contact\/my-test-enterprise\/new/, @response.body 319 assert_no_match /\/contact\/my-test-enterprise\/new/, @response.body
320 end 320 end
321 321
@@ -328,7 +328,7 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -328,7 +328,7 @@ class ProfileControllerTest &lt; ActionController::TestCase
328 env.disable('disable_contact_person') 328 env.disable('disable_contact_person')
329 env.save! 329 env.save!
330 login_as(@profile.identifier) 330 login_as(@profile.identifier)
331 - get :profile_info, :profile => friend.identifier, :block_id => block.id 331 + get :index, :profile => friend.identifier
332 assert_match /\/contact\/#{friend.identifier}\/new/, @response.body 332 assert_match /\/contact\/#{friend.identifier}\/new/, @response.body
333 end 333 end
334 334
@@ -336,7 +336,7 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -336,7 +336,7 @@ class ProfileControllerTest &lt; ActionController::TestCase
336 nofriend = create_user_full('no_friend').person 336 nofriend = create_user_full('no_friend').person
337 nofriend.boxes.first.blocks << block = ProfileInfoBlock.create! 337 nofriend.boxes.first.blocks << block = ProfileInfoBlock.create!
338 login_as(@profile.identifier) 338 login_as(@profile.identifier)
339 - get :profile_info, :profile => nofriend.identifier, :block_id => block.id 339 + get :index, :profile => nofriend.identifier
340 assert_no_match /\/contact\/#{nofriend.identifier}\/new/, @response.body 340 assert_no_match /\/contact\/#{nofriend.identifier}\/new/, @response.body
341 end 341 end
342 342
@@ -349,7 +349,7 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -349,7 +349,7 @@ class ProfileControllerTest &lt; ActionController::TestCase
349 env.save! 349 env.save!
350 @profile.add_friend(friend) 350 @profile.add_friend(friend)
351 login_as(@profile.identifier) 351 login_as(@profile.identifier)
352 - get :profile_info, :profile => friend.identifier, :block_id => block.id 352 + get :index, :profile => friend.identifier
353 assert_match /\/contact\/#{friend.identifier}\/new/, @response.body 353 assert_match /\/contact\/#{friend.identifier}\/new/, @response.body
354 end 354 end
355 355
@@ -361,7 +361,7 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -361,7 +361,7 @@ class ProfileControllerTest &lt; ActionController::TestCase
361 env.save! 361 env.save!
362 @profile.add_friend(friend) 362 @profile.add_friend(friend)
363 login_as(@profile.identifier) 363 login_as(@profile.identifier)
364 - get :profile_info, :profile => friend.identifier, :block_id => block.id 364 + get :index, :profile => friend.identifier
365 assert_no_match /\/contact\/#{friend.identifier}\/new/, @response.body 365 assert_no_match /\/contact\/#{friend.identifier}\/new/, @response.body
366 end 366 end
367 367
@@ -373,7 +373,7 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -373,7 +373,7 @@ class ProfileControllerTest &lt; ActionController::TestCase
373 env.save! 373 env.save!
374 community.add_member(@profile) 374 community.add_member(@profile)
375 login_as(@profile.identifier) 375 login_as(@profile.identifier)
376 - get :profile_info, :profile => community.identifier, :block_id => block.id 376 + get :index, :profile => community.identifier
377 assert_match /\/contact\/#{community.identifier}\/new/, @response.body 377 assert_match /\/contact\/#{community.identifier}\/new/, @response.body
378 end 378 end
379 379
@@ -385,7 +385,7 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -385,7 +385,7 @@ class ProfileControllerTest &lt; ActionController::TestCase
385 env.save! 385 env.save!
386 community.add_member(@profile) 386 community.add_member(@profile)
387 login_as(@profile.identifier) 387 login_as(@profile.identifier)
388 - get :profile_info, :profile => community.identifier, :block_id => block.id 388 + get :index, :profile => community.identifier
389 assert_no_match /\/contact\/#{community.identifier}\/new/, @response.body 389 assert_no_match /\/contact\/#{community.identifier}\/new/, @response.body
390 end 390 end
391 391
test/functional/profile_editor_controller_test.rb
@@ -73,7 +73,8 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase @@ -73,7 +73,8 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase
73 get :edit, :profile => profile.identifier 73 get :edit, :profile => profile.identifier
74 assert_response :success 74 assert_response :success
75 assert_template 'edit' 75 assert_template 'edit'
76 - assert_tag :tag => 'input', :attributes => {:name => 'profile_data[category_ids][]', :value => cat2.id} 76 + assert_tag :tag => 'input', :attributes => {:name => 'profile_data[category_ids][]'}
  77 + assert_tag :tag => 'a', :attributes => { :class => 'select-subcategory-link', :id => "select-category-#{cat1.id}-link" }
77 end 78 end
78 79
79 should 'save categorization of profile' do 80 should 'save categorization of profile' do
@@ -236,7 +237,7 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase @@ -236,7 +237,7 @@ class ProfileEditorControllerTest &lt; ActionController::TestCase
236 cat2 = Environment.default.categories.create!(:display_in_menu => true, :name => 'sub category', :parent => cat1) 237 cat2 = Environment.default.categories.create!(:display_in_menu => true, :name => 'sub category', :parent => cat1)
237 person = create_user('testuser').person 238 person = create_user('testuser').person
238 get :edit, :profile => 'testuser' 239 get :edit, :profile => 'testuser'
239 - assert_tag :tag => 'input', :attributes => { :type => 'checkbox', :name => 'profile_data[category_ids][]', :value => cat2.id} 240 + assert_tag :tag => 'a', :attributes => { :class => 'select-subcategory-link', :id => "select-category-#{cat1.id}-link" }
240 end 241 end
241 242
242 should 'render edit template' do 243 should 'render edit template' do
test/functional/profile_themes_controller_test.rb
@@ -310,4 +310,23 @@ class ProfileThemesControllerTest &lt; ActionController::TestCase @@ -310,4 +310,23 @@ class ProfileThemesControllerTest &lt; ActionController::TestCase
310 assert_no_tag :content => "Select theme" 310 assert_no_tag :content => "Select theme"
311 end 311 end
312 312
  313 + should 'not duplicate themes that are included by the user and by the environment' do
  314 + t1 = Theme.create('theme1')
  315 + t2 = Theme.create('theme2')
  316 + Environment.any_instance.stubs('themes').returns([t1,t2])
  317 + Theme.stubs(:approved_themes).returns([t2])
  318 +
  319 + get :index, :profile => "testinguser"
  320 + assert_equivalent [t1, t2], assigns(:themes)
  321 + end
  322 +
  323 + should 'sort themes by name' do
  324 + t1 = Theme.create('bill-theme')
  325 + t2 = Theme.create('ana-theme')
  326 + Theme.stubs(:approved_themes).returns([t1,t2])
  327 +
  328 + get :index, :profile => "testinguser"
  329 + assert_equal [t2, t1], assigns(:themes)
  330 + end
  331 +
313 end 332 end
test/functional/users_controller_test.rb
@@ -107,6 +107,21 @@ class UsersControllerTest &lt; ActionController::TestCase @@ -107,6 +107,21 @@ class UsersControllerTest &lt; ActionController::TestCase
107 assert_equal false, u.activated? 107 assert_equal false, u.activated?
108 end 108 end
109 109
  110 + should 'order users by name' do
  111 + create_user('jeremy')
  112 + create_user('bill')
  113 + create_user('ana')
  114 + create_user('creed')
  115 + get :index
  116 +
  117 + assert_order ['ana', 'bill', 'creed', 'jeremy'], assigns(:collection).map(&:name)
  118 + end
  119 +
  120 + should 'set filter to all_users by default' do
  121 + get :index
  122 + assert_equal 'all_users', assigns(:filter)
  123 + end
  124 +
110 should 'response as XML to export users' do 125 should 'response as XML to export users' do
111 get :download, :format => 'xml' 126 get :download, :format => 'xml'
112 assert_equal 'text/xml', @response.content_type 127 assert_equal 'text/xml', @response.content_type
@@ -118,4 +133,20 @@ class UsersControllerTest &lt; ActionController::TestCase @@ -118,4 +133,20 @@ class UsersControllerTest &lt; ActionController::TestCase
118 assert_equal 'name;email', @response.body.split("\n")[0] 133 assert_equal 'name;email', @response.body.split("\n")[0]
119 end 134 end
120 135
  136 + should 'be able to remove a person' do
  137 + person = fast_create(Person, :environment_id => environment.id)
  138 + assert_difference Person, :count, -1 do
  139 + post :destroy_user, :id => person.id
  140 + end
  141 + end
  142 +
  143 + should 'not crash if user does not exist' do
  144 + person = fast_create(Person)
  145 +
  146 + assert_no_difference Person, :count do
  147 + post :destroy_user, :id => 99999
  148 + end
  149 + assert_redirected_to :action => 'index'
  150 + end
  151 +
121 end 152 end
test/test_helper.rb
@@ -177,6 +177,19 @@ class ActiveSupport::TestCase @@ -177,6 +177,19 @@ class ActiveSupport::TestCase
177 assert !tag, "expected no tag #{options.inspect}, but tag found in #{text.inspect}" 177 assert !tag, "expected no tag #{options.inspect}, but tag found in #{text.inspect}"
178 end 178 end
179 179
  180 + def assert_order(reference, original)
  181 + original.each do |value|
  182 + if reference.include?(value)
  183 + if reference.first == value
  184 + reference.shift
  185 + else
  186 + assert false, "'#{value}' was found before it should be on: #{original.inspect}"
  187 + end
  188 + end
  189 + end
  190 + assert reference.blank?, "The following elements are not in the collection: #{reference.inspect}"
  191 + end
  192 +
180 # For models that render views (blocks, articles, ...) 193 # For models that render views (blocks, articles, ...)
181 def render(*args) 194 def render(*args)
182 view_paths = @explicit_view_paths || ActionController::Base.view_paths 195 view_paths = @explicit_view_paths || ActionController::Base.view_paths
test/unit/array_core_ext_test.rb 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +# tests for Array core extension. See lib/noosfero/core_ext/array.rb
  4 +class StringCoreExtTest < ActiveSupport::TestCase
  5 +
  6 + should 'allow uniq by a block' do
  7 + array = [0,1,2,3,4,5,6]
  8 + assert_equal [0,1], array.uniq_by {|number| number%2 }
  9 + end
  10 +
  11 +end
test/unit/box_test.rb
@@ -33,6 +33,8 @@ class BoxTest &lt; ActiveSupport::TestCase @@ -33,6 +33,8 @@ class BoxTest &lt; ActiveSupport::TestCase
33 assert blocks.include?('categories-block') 33 assert blocks.include?('categories-block')
34 assert blocks.include?('communities-block') 34 assert blocks.include?('communities-block')
35 assert blocks.include?('enterprises-block') 35 assert blocks.include?('enterprises-block')
  36 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  37 + # the Noosfero core soon, see ActionItem3045
36 assert blocks.include?('environment-statistics-block') 38 assert blocks.include?('environment-statistics-block')
37 assert blocks.include?('fans-block') 39 assert blocks.include?('fans-block')
38 assert blocks.include?('favorite-enterprises-block') 40 assert blocks.include?('favorite-enterprises-block')
@@ -65,6 +67,8 @@ class BoxTest &lt; ActiveSupport::TestCase @@ -65,6 +67,8 @@ class BoxTest &lt; ActiveSupport::TestCase
65 assert blocks.include?('communities-block') 67 assert blocks.include?('communities-block')
66 assert blocks.include?('disabled-enterprise-message-block') 68 assert blocks.include?('disabled-enterprise-message-block')
67 assert blocks.include?('enterprises-block') 69 assert blocks.include?('enterprises-block')
  70 + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  71 + # the Noosfero core soon, see ActionItem3045
68 assert blocks.include?('environment-statistics-block') 72 assert blocks.include?('environment-statistics-block')
69 assert blocks.include?('fans-block') 73 assert blocks.include?('fans-block')
70 assert blocks.include?('favorite-enterprises-block') 74 assert blocks.include?('favorite-enterprises-block')
@@ -140,4 +144,11 @@ class BoxTest &lt; ActiveSupport::TestCase @@ -140,4 +144,11 @@ class BoxTest &lt; ActiveSupport::TestCase
140 assert !blocks.include?('box-test_plugin-block') 144 assert !blocks.include?('box-test_plugin-block')
141 end 145 end
142 146
  147 + should 'list only boxes with a postion greater than zero' do
  148 + profile = fast_create(Profile)
  149 + box = fast_create(Box, :owner_id => profile.id, :owner_type => 'Profile', :position => 0)
  150 + box2 = fast_create(Box, :owner_id => profile.id, :owner_type => 'Profile', :position => 1)
  151 + assert_equal [box2], profile.boxes.with_position
  152 + end
  153 +
143 end 154 end
test/unit/boxes_helper_test.rb
@@ -13,7 +13,8 @@ class BoxesHelperTest &lt; ActiveSupport::TestCase @@ -13,7 +13,8 @@ class BoxesHelperTest &lt; ActiveSupport::TestCase
13 13
14 should 'include profile-specific header' do 14 should 'include profile-specific header' do
15 holder = mock 15 holder = mock
16 - holder.stubs(:boxes).returns([]) 16 + holder.stubs(:boxes).returns(boxes = [])
  17 + boxes.stubs(:with_position).returns([])
17 holder.stubs(:boxes_limit).returns(0) 18 holder.stubs(:boxes_limit).returns(0)
18 holder.stubs(:custom_header_expanded).returns('my custom header') 19 holder.stubs(:custom_header_expanded).returns('my custom header')
19 @controller.stubs(:boxes_holder).returns(holder) 20 @controller.stubs(:boxes_holder).returns(holder)
@@ -23,7 +24,8 @@ class BoxesHelperTest &lt; ActiveSupport::TestCase @@ -23,7 +24,8 @@ class BoxesHelperTest &lt; ActiveSupport::TestCase
23 24
24 should 'include profile-specific footer' do 25 should 'include profile-specific footer' do
25 holder = mock 26 holder = mock
26 - holder.stubs(:boxes).returns([]) 27 + holder.stubs(:boxes).returns(boxes = [])
  28 + boxes.stubs(:with_position).returns([])
27 holder.stubs(:boxes_limit).returns(0) 29 holder.stubs(:boxes_limit).returns(0)
28 holder.stubs(:custom_footer_expanded).returns('my custom footer') 30 holder.stubs(:custom_footer_expanded).returns('my custom footer')
29 @controller.stubs(:boxes_holder).returns(holder) 31 @controller.stubs(:boxes_holder).returns(holder)
test/unit/comment_test.rb
@@ -285,6 +285,37 @@ class CommentTest &lt; ActiveSupport::TestCase @@ -285,6 +285,37 @@ class CommentTest &lt; ActiveSupport::TestCase
285 assert_equal [c1,c3], c.reload.children 285 assert_equal [c1,c3], c.reload.children
286 end 286 end
287 287
  288 + should "return activities comments as a thread" do
  289 + person = fast_create(Person)
  290 + a = TextileArticle.create!(:profile => person, :name => 'My article', :body => 'Article body')
  291 + c0 = Comment.create!(:source => a, :body => 'My comment', :author => person)
  292 + c1 = Comment.create!(:reply_of_id => c0.id, :source => a, :body => 'bla', :author => person)
  293 + c2 = Comment.create!(:reply_of_id => c1.id, :source => a, :body => 'bla', :author => person)
  294 + c3 = Comment.create!(:reply_of_id => c0.id, :source => a, :body => 'bla', :author => person)
  295 + c4 = Comment.create!(:source => a, :body => 'My comment', :author => person)
  296 + result = a.activity.comments
  297 + assert_equal c0, result[0]
  298 + assert_equal [c1, c3], result[0].replies
  299 + assert_equal [c2], result[0].replies[0].replies
  300 + assert_equal c4, result[1]
  301 + assert result[1].replies.empty?
  302 + end
  303 +
  304 + should "return activities comments when some comment on thread is spam and not display its replies" do
  305 + person = fast_create(Person)
  306 + a = TextileArticle.create!(:profile => person, :name => 'My article', :body => 'Article body')
  307 + c0 = Comment.create(:source => a, :body => 'Root comment', :author => person)
  308 + c1 = Comment.create(:reply_of_id => c0.id, :source => a, :body => 'c1', :author => person)
  309 + c2 = Comment.create(:source => a, :body => 'c2', :author => person)
  310 + spam = Comment.create(:spam => true, :reply_of_id => c2.id, :source => a, :body => 'spam', :author => person)
  311 + spam_reply = Comment.create(:reply_of_id => spam.id, :source => a, :body => 'spam reply', :author => person)
  312 + result = a.activity.comments
  313 + assert_equal c0, result[0]
  314 + assert_equal [c1], result[0].replies.without_spam
  315 + assert_equal c2, result[1]
  316 + assert_equal [], result[1].replies.without_spam
  317 + end
  318 +
288 should 'provide author url for authenticated user' do 319 should 'provide author url for authenticated user' do
289 author = Person.new 320 author = Person.new
290 author.expects(:url).returns('http://blabla.net/author') 321 author.expects(:url).returns('http://blabla.net/author')
@@ -389,6 +420,7 @@ class CommentTest &lt; ActiveSupport::TestCase @@ -389,6 +420,7 @@ class CommentTest &lt; ActiveSupport::TestCase
389 end 420 end
390 421
391 should 'be able to select non-spam comments' do 422 should 'be able to select non-spam comments' do
  423 + Comment.destroy_all
392 c1 = fast_create(Comment) 424 c1 = fast_create(Comment)
393 c2 = fast_create(Comment, :spam => false) 425 c2 = fast_create(Comment, :spam => false)
394 c3 = fast_create(Comment, :spam => true) 426 c3 = fast_create(Comment, :spam => true)
@@ -660,6 +692,7 @@ class CommentTest &lt; ActiveSupport::TestCase @@ -660,6 +692,7 @@ class CommentTest &lt; ActiveSupport::TestCase
660 end 692 end
661 693
662 should 'be able to select non-reply comments' do 694 should 'be able to select non-reply comments' do
  695 + Comment.destroy_all
663 c1 = fast_create(Comment) 696 c1 = fast_create(Comment)
664 c2 = fast_create(Comment, :reply_of_id => c1.id) 697 c2 = fast_create(Comment, :reply_of_id => c1.id)
665 c3 = fast_create(Comment, :reply_of_id => c2.id) 698 c3 = fast_create(Comment, :reply_of_id => c2.id)
test/unit/environment_statistics_block_test.rb
  1 +# TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from
  2 +# the Noosfero core soon, see ActionItem3045
  3 +
1 require File.dirname(__FILE__) + '/../test_helper' 4 require File.dirname(__FILE__) + '/../test_helper'
2 5
3 class EnvironmentStatisticsBlockTest < ActiveSupport::TestCase 6 class EnvironmentStatisticsBlockTest < ActiveSupport::TestCase
@@ -36,7 +39,7 @@ class EnvironmentStatisticsBlockTest &lt; ActiveSupport::TestCase @@ -36,7 +39,7 @@ class EnvironmentStatisticsBlockTest &lt; ActiveSupport::TestCase
36 assert_match(/2 users/, content) 39 assert_match(/2 users/, content)
37 assert_match(/One community/, content) 40 assert_match(/One community/, content)
38 end 41 end
39 - 42 +
40 should 'generate statistics including private profiles' do 43 should 'generate statistics including private profiles' do
41 env = create(Environment) 44 env = create(Environment)
42 user1 = create_user('testuser1', :environment_id => env.id) 45 user1 = create_user('testuser1', :environment_id => env.id)
test/unit/environment_test.rb
@@ -783,6 +783,18 @@ class EnvironmentTest &lt; ActiveSupport::TestCase @@ -783,6 +783,18 @@ class EnvironmentTest &lt; ActiveSupport::TestCase
783 assert role2.valid? 783 assert role2.valid?
784 end 784 end
785 785
  786 + should 'destroy roles when its environment is destroyed' do
  787 + e1 = fast_create(Environment)
  788 + role1 = Role.create!(:name => 'test_role', :environment => e1, :key => 'a_member')
  789 + e2 = fast_create(Environment)
  790 + role2 = Role.create!(:name => 'test_role', :environment => e2, :key => 'a_member')
  791 +
  792 + e2.destroy
  793 +
  794 + assert_nothing_raised {Role.find(role1.id)}
  795 + assert_raise(ActiveRecord::RecordNotFound) {Role.find(role2.id)}
  796 + end
  797 +
786 should 'have a help_message_to_add_enterprise attribute' do 798 should 'have a help_message_to_add_enterprise attribute' do
787 env = Environment.new 799 env = Environment.new
788 800
test/unit/link_list_block_test.rb
@@ -86,4 +86,9 @@ class LinkListBlockTest &lt; ActiveSupport::TestCase @@ -86,4 +86,9 @@ class LinkListBlockTest &lt; ActiveSupport::TestCase
86 assert_equivalent LinkListBlock::TARGET_OPTIONS.map {|t|t[1]}, ['_self', '_blank', '_new'] 86 assert_equivalent LinkListBlock::TARGET_OPTIONS.map {|t|t[1]}, ['_self', '_blank', '_new']
87 end 87 end
88 88
  89 + should 'link with title' do
  90 + l = LinkListBlock.new
  91 + assert_match /title="mytitle"/, l.link_html({:name => 'mylink', :address => '/myaddress', :title => 'mytitle'})
  92 + end
  93 +
89 end 94 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 = Nokogiri::HTML(MACRO).css('.macro').first 18 + @macro_element = Hpricot(MACRO).search('.macro').first
19 end 19 end
20 20
21 attr_reader :macro, :macro_element 21 attr_reader :macro, :macro_element
test/unit/profile_test.rb
@@ -1461,7 +1461,7 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -1461,7 +1461,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
1461 should 'list events by month' do 1461 should 'list events by month' do
1462 profile = fast_create(Profile) 1462 profile = fast_create(Profile)
1463 1463
1464 - today = Date.today 1464 + today = Date.new(2014, 03, 2)
1465 yesterday_event = Event.new(:name => 'Joao Birthday', :start_date => today - 1.day) 1465 yesterday_event = Event.new(:name => 'Joao Birthday', :start_date => today - 1.day)
1466 today_event = Event.new(:name => 'Ze Birthday', :start_date => today) 1466 today_event = Event.new(:name => 'Ze Birthday', :start_date => today)
1467 tomorrow_event = Event.new(:name => 'Mane Birthday', :start_date => today + 1.day) 1467 tomorrow_event = Event.new(:name => 'Mane Birthday', :start_date => today + 1.day)
@@ -1692,6 +1692,28 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -1692,6 +1692,28 @@ class ProfileTest &lt; ActiveSupport::TestCase
1692 assert_equal 1, community.members_count 1692 assert_equal 1, community.members_count
1693 end 1693 end
1694 1694
  1695 + should 'order members by name alphabetically considering special characters' do
  1696 + community = fast_create(Community)
  1697 +
  1698 + community.add_member(create_user('José').person)
  1699 + community.add_member(create_user('João').person)
  1700 + community.add_member(create_user('Mariana').person)
  1701 + members = community.members_by_name
  1702 +
  1703 + assert_equal ["João", "José", "Mariana"], members.map(&:name)
  1704 + end
  1705 +
  1706 + should 'order members by name alphabetically considering upper and lower cases' do
  1707 + community = fast_create(Community)
  1708 +
  1709 + community.add_member(create_user('mariana').person)
  1710 + community.add_member(create_user('João').person)
  1711 + community.add_member(create_user('guest').person)
  1712 + members = community.members_by_name
  1713 +
  1714 + assert_equal ["guest", "João", "mariana"], members.map(&:name)
  1715 + end
  1716 +
1695 should 'know if url is the profile homepage' do 1717 should 'know if url is the profile homepage' do
1696 profile = fast_create(Profile) 1718 profile = fast_create(Profile)
1697 1719
vendor/plugins/action_tracker_has_comments/init.rb
@@ -11,5 +11,6 @@ Rails.configuration.to_prepare do @@ -11,5 +11,6 @@ Rails.configuration.to_prepare do
11 type, id = (self.target_type == 'Article' ? ['Article', self.target_id] : [self.class.to_s, self.id]) 11 type, id = (self.target_type == 'Article' ? ['Article', self.target_id] : [self.class.to_s, self.id])
12 "source_type = '#{type}' AND source_id = '#{id}' AND spam IS NOT TRUE AND reply_of_id IS NULL" 12 "source_type = '#{type}' AND source_id = '#{id}' AND spam IS NOT TRUE AND reply_of_id IS NULL"
13 end 13 end
  14 +
14 end 15 end
15 end 16 end