Commit 645f9328979e3efa711c1f06d0a9d6ef364719df

Authored by Joenio Costa
2 parents 225bf66e 12a28da7

Merge branch 'master' into AI2694-network_activity_email

Showing 134 changed files with 2941 additions and 355 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 134 files displayed.

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)
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/helpers/comment_helper.rb
@@ -22,6 +22,12 @@ module CommentHelper @@ -22,6 +22,12 @@ module CommentHelper
22 title 22 title
23 end 23 end
24 24
  25 + def comment_extra_contents(comment)
  26 + @plugins.dispatch(:comment_extra_contents, comment).collect do |extra_content|
  27 + extra_content.kind_of?(Proc) ? self.instance_eval(&extra_content) : extra_content
  28 + end.join('\n')
  29 + end
  30 +
25 def comment_actions(comment) 31 def comment_actions(comment)
26 url = url_for(:profile => profile.identifier, :controller => :comment, :action => :check_actions, :id => comment.id) 32 url = url_for(:profile => profile.identifier, :controller => :comment, :action => :check_actions, :id => comment.id)
27 links = links_for_comment_actions(comment) 33 links = links_for_comment_actions(comment)
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,8 +75,17 @@ @@ -83,8 +75,17 @@
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
  87 +<%= @plugins.dispatch(:article_extra_contents, @page).collect { |content| instance_eval(&content) }.join("") %>
  88 +
88 <div class="comments" id="comments_list"> 89 <div class="comments" id="comments_list">
89 90
90 <% if @page.accept_comments? || @comments_count > 0 %> 91 <% if @page.accept_comments? || @comments_count > 0 %>
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 %>
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
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.rb
@@ -349,6 +349,12 @@ class Noosfero::Plugin @@ -349,6 +349,12 @@ class Noosfero::Plugin
349 [] 349 []
350 end 350 end
351 351
  352 + # -> Adds adicional content to article
  353 + # returns = lambda block that creates html code
  354 + def article_extra_contents(article)
  355 + nil
  356 + end
  357 +
352 # -> Adds fields to the signup form 358 # -> Adds fields to the signup form
353 # returns = lambda block that creates html code 359 # returns = lambda block that creates html code
354 def signup_extra_contents 360 def signup_extra_contents
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/display_content/lib/display_content_block.rb
@@ -61,9 +61,12 @@ class DisplayContentBlock &lt; Block @@ -61,9 +61,12 @@ class DisplayContentBlock &lt; Block
61 61
62 VALID_CONTENT = ['RawHTMLArticle', 'TextArticle', 'TextileArticle', 'TinyMceArticle', 'Folder', 'Blog', 'Forum'] 62 VALID_CONTENT = ['RawHTMLArticle', 'TextArticle', 'TextileArticle', 'TinyMceArticle', 'Folder', 'Blog', 'Forum']
63 63
  64 + include Noosfero::Plugin::HotSpot
  65 +
64 def articles_of_parent(parent = nil) 66 def articles_of_parent(parent = nil)
65 return [] if self.holder.nil? 67 return [] if self.holder.nil?
66 - holder.articles.find(:all, :conditions => {:type => VALID_CONTENT, :parent_id => (parent.nil? ? nil : parent)}) 68 + types = VALID_CONTENT + plugins.dispatch(:content_types).map(&:name)
  69 + holder.articles.find(:all, :conditions => {:type => types, :parent_id => (parent.nil? ? nil : parent)})
67 end 70 end
68 71
69 include ActionController::UrlWriter 72 include ActionController::UrlWriter
plugins/display_content/test/unit/display_content_block_test.rb
@@ -238,6 +238,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase @@ -238,6 +238,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase
238 block.nodes= [a1.id, a2.id, a3.id] 238 block.nodes= [a1.id, a2.id, a3.id]
239 box = mock() 239 box = mock()
240 box.stubs(:owner).returns(profile) 240 box.stubs(:owner).returns(profile)
  241 + box.stubs(:environment).returns(Environment.default)
241 block.stubs(:box).returns(box) 242 block.stubs(:box).returns(box)
242 assert_equal [], [a1, a2] - block.articles_of_parent 243 assert_equal [], [a1, a2] - block.articles_of_parent
243 assert_equal [], block.articles_of_parent - [a1, a2] 244 assert_equal [], block.articles_of_parent - [a1, a2]
@@ -253,6 +254,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase @@ -253,6 +254,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase
253 block = DisplayContentBlock.new 254 block = DisplayContentBlock.new
254 box = mock() 255 box = mock()
255 box.stubs(:owner).returns(profile) 256 box.stubs(:owner).returns(profile)
  257 + box.stubs(:environment).returns(Environment.default)
256 block.stubs(:box).returns(box) 258 block.stubs(:box).returns(box)
257 assert_equal [], [a3] - block.articles_of_parent(a2) 259 assert_equal [], [a3] - block.articles_of_parent(a2)
258 assert_equal [], block.articles_of_parent(a2) - [a3] 260 assert_equal [], block.articles_of_parent(a2) - [a3]
@@ -270,6 +272,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase @@ -270,6 +272,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase
270 box = mock() 272 box = mock()
271 block.stubs(:box).returns(box) 273 block.stubs(:box).returns(box)
272 box.stubs(:owner).returns(environment) 274 box.stubs(:owner).returns(environment)
  275 + box.stubs(:environment).returns(Environment.default)
273 environment.stubs(:portal_community).returns(profile) 276 environment.stubs(:portal_community).returns(profile)
274 277
275 assert_equal [], [a1, a2] - block.articles_of_parent 278 assert_equal [], [a1, a2] - block.articles_of_parent
@@ -288,6 +291,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase @@ -288,6 +291,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase
288 box = mock() 291 box = mock()
289 block.stubs(:box).returns(box) 292 block.stubs(:box).returns(box)
290 box.stubs(:owner).returns(environment) 293 box.stubs(:owner).returns(environment)
  294 + box.stubs(:environment).returns(Environment.default)
291 environment.stubs(:portal_community).returns(profile) 295 environment.stubs(:portal_community).returns(profile)
292 296
293 assert_equal [], [a3] - block.articles_of_parent(a2) 297 assert_equal [], [a3] - block.articles_of_parent(a2)
@@ -301,6 +305,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase @@ -301,6 +305,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase
301 box = mock() 305 box = mock()
302 block.stubs(:box).returns(box) 306 block.stubs(:box).returns(box)
303 box.stubs(:owner).returns(environment) 307 box.stubs(:owner).returns(environment)
  308 + box.stubs(:environment).returns(Environment.default)
304 309
305 assert_equal [], block.articles_of_parent() 310 assert_equal [], block.articles_of_parent()
306 end 311 end
@@ -316,6 +321,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase @@ -316,6 +321,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase
316 block = DisplayContentBlock.new 321 block = DisplayContentBlock.new
317 box = mock() 322 box = mock()
318 box.stubs(:owner).returns(profile) 323 box.stubs(:owner).returns(profile)
  324 + box.stubs(:environment).returns(Environment.default)
319 block.stubs(:box).returns(box) 325 block.stubs(:box).returns(box)
320 assert_equal [], [a2] - block.articles_of_parent 326 assert_equal [], [a2] - block.articles_of_parent
321 assert_equal [], block.articles_of_parent - [a2] 327 assert_equal [], block.articles_of_parent - [a2]
@@ -334,6 +340,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase @@ -334,6 +340,7 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase
334 block = DisplayContentBlock.new 340 block = DisplayContentBlock.new
335 box = mock() 341 box = mock()
336 box.stubs(:owner).returns(profile) 342 box.stubs(:owner).returns(profile)
  343 + box.stubs(:environment).returns(Environment.default)
337 block.stubs(:box).returns(box) 344 block.stubs(:box).returns(box)
338 assert_equal [a1], block.articles_of_parent 345 assert_equal [a1], block.articles_of_parent
339 end 346 end
@@ -526,4 +533,28 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase @@ -526,4 +533,28 @@ class DisplayContentBlockTest &lt; ActiveSupport::TestCase
526 assert_equivalent [f1.id, a1.id, a2.id, a3.id], block.nodes 533 assert_equivalent [f1.id, a1.id, a2.id, a3.id], block.nodes
527 end 534 end
528 535
  536 + should "test should return plugins articles in articles of parent method" do
  537 + class PluginArticle < Article; end
  538 +
  539 + class Plugin1 < Noosfero::Plugin
  540 + def content_types
  541 + [PluginArticle]
  542 + end
  543 + end
  544 +
  545 + profile = create_user('testuser').person
  546 + Article.delete_all
  547 + a1 = fast_create(PluginArticle, :name => 'test article 1', :profile_id => profile.id)
  548 +
  549 + env = fast_create(Environment)
  550 + env.enable_plugin(Plugin1)
  551 +
  552 + block = DisplayContentBlock.new
  553 + box = mock()
  554 + box.stubs(:owner).returns(profile)
  555 + box.stubs(:environment).returns(env)
  556 + block.stubs(:box).returns(box)
  557 + assert_equal [a1], block.articles_of_parent
  558 + end
  559 +
529 end 560 end
plugins/mark_comment_as_read/controllers/mark_comment_as_read_plugin_profile_controller.rb 0 → 100644
@@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
  1 +class MarkCommentAsReadPluginProfileController < ProfileController
  2 +
  3 + append_view_path File.join(File.dirname(__FILE__) + '/../views')
  4 +
  5 + def mark_as_read
  6 + comment = Comment.find(params[:id])
  7 + comment.mark_as_read(user)
  8 + render :text => {'ok' => true}.to_json, :content_type => 'application/json'
  9 + end
  10 +
  11 + def mark_as_not_read
  12 + comment = Comment.find(params[:id])
  13 + comment.mark_as_not_read(user)
  14 + render :text => {'ok' => true}.to_json, :content_type => 'application/json'
  15 + end
  16 +
  17 +end
plugins/mark_comment_as_read/db/migrate/20130509184338_create_mark_comment_as_read_plugin.rb 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +class CreateMarkCommentAsReadPlugin < ActiveRecord::Migration
  2 + def self.up
  3 + create_table :mark_comment_as_read_plugin do |t|
  4 + t.integer :comment_id
  5 + t.integer :person_id
  6 + end
  7 + add_index :mark_comment_as_read_plugin, [:comment_id, :person_id], :unique => true
  8 + end
  9 +
  10 + def self.down
  11 + drop_table :mark_comment_as_read_plugin
  12 + end
  13 +end
plugins/mark_comment_as_read/lib/mark_comment_as_read_plugin.rb 0 → 100644
@@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
  1 +require_dependency 'mark_comment_as_read_plugin/ext/comment'
  2 +
  3 +class MarkCommentAsReadPlugin < Noosfero::Plugin
  4 +
  5 + def self.plugin_name
  6 + "MarkCommentAsReadPlugin"
  7 + end
  8 +
  9 + def self.plugin_description
  10 + _("Provide a button to mark a comment as read.")
  11 + end
  12 +
  13 + def js_files
  14 + 'mark_comment_as_read.js'
  15 + end
  16 +
  17 + def stylesheet?
  18 + true
  19 + end
  20 +
  21 + def comment_actions(comment)
  22 + lambda do
  23 + [{:link => link_to_function(_('Mark as not read'), 'toggle_comment_read(this, %s, false);' % url_for(:controller => 'mark_comment_as_read_plugin_profile', :profile => profile.identifier, :action => 'mark_as_not_read', :id => comment.id).to_json, :class => 'comment-footer comment-footer-link comment-footer-hide comment-action-extra', :style => 'display: none', :id => "comment-action-mark-as-not-read-#{comment.id}")},
  24 + {:link => link_to_function(_('Mark as read'), 'toggle_comment_read(this, %s, true);' % url_for(:controller => 'mark_comment_as_read_plugin_profile', :profile => profile.identifier, :action => 'mark_as_read', :id => comment.id).to_json, :class => 'comment-footer comment-footer-link comment-footer-hide comment-action-extra', :style => 'display: none', :id => "comment-action-mark-as-read-#{comment.id}")}] if user
  25 + end
  26 + end
  27 +
  28 + def check_comment_actions(comment)
  29 + lambda do
  30 + if user
  31 + comment.marked_as_read?(user) ? "#comment-action-mark-as-not-read-#{comment.id}" : "#comment-action-mark-as-read-#{comment.id}"
  32 + end
  33 + end
  34 + end
  35 +
  36 + def article_extra_contents(article)
  37 + lambda do
  38 + if user
  39 + ids = article.comments.marked_as_read(user).collect { |comment| comment.id}
  40 + "<script type=\"text/javascript\">mark_comments_as_read(#{ids.to_json});</script>" if !ids.empty?
  41 + end
  42 + end
  43 + end
  44 +
  45 +end
plugins/mark_comment_as_read/lib/mark_comment_as_read_plugin/ext/comment.rb 0 → 100644
@@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
  1 +require_dependency 'comment'
  2 +
  3 +class Comment
  4 +
  5 + has_many :read_comments, :class_name => 'MarkCommentAsReadPlugin::ReadComments'
  6 + has_many :people, :through => :read_comments
  7 +
  8 + def mark_as_read(person)
  9 + people << person
  10 + end
  11 +
  12 + def mark_as_not_read(person)
  13 + people.delete(person)
  14 + end
  15 +
  16 + def marked_as_read?(person)
  17 + person && people.find(:first, :conditions => {:id => person.id})
  18 + end
  19 +
  20 + def self.marked_as_read(person)
  21 + find(:all, :joins => [:read_comments], :conditions => {:author_id => person.id})
  22 + end
  23 +
  24 +end
plugins/mark_comment_as_read/lib/mark_comment_as_read_plugin/read_comments.rb 0 → 100644
@@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
  1 +class MarkCommentAsReadPlugin::ReadComments < Noosfero::Plugin::ActiveRecord
  2 + set_table_name 'mark_comment_as_read_plugin'
  3 + belongs_to :comment
  4 + belongs_to :person
  5 +
  6 + validates_presence_of :comment, :person
  7 +end
plugins/mark_comment_as_read/public/mark_comment_as_read.js 0 → 100644
@@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
  1 +function mark_comments_as_read(comments) {
  2 + jQuery(document).ready(function($) {
  3 + for(var i=0; i<comments.length; i++) {
  4 + $comment = jQuery('#comment-'+comments[i]);
  5 + $comment.find('.comment-content').first().addClass('comment-mark-read');
  6 + }
  7 + });
  8 +}
  9 +
  10 +function toggle_comment_read(button, url, mark) {
  11 + var $ = jQuery;
  12 + var $button = $(button);
  13 + $button.addClass('comment-button-loading');
  14 + $.post(url, function(data) {
  15 + if (data.ok) {
  16 + var $comment = $button.closest('.article-comment');
  17 + var $content = $comment.find('.comment-content').first();
  18 + if(mark)
  19 + $content.addClass('comment-mark-read');
  20 + else
  21 + $content.removeClass('comment-mark-read');
  22 + $button.hide();
  23 + $button.removeClass('comment-button-loading');
  24 + return;
  25 + }
  26 + });
  27 +}
  28 +
plugins/mark_comment_as_read/public/style.css 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +.article-comments-list .comment-mark-read .comment-text, .article-comments-list .comment-mark-read h4, .article-comments-list .comment-mark-read .comment-picture {
  2 + opacity: 0.2;
  3 +}
plugins/mark_comment_as_read/test/functional/mark_comment_as_read_plugin_profile_controller_test.rb 0 → 100644
@@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
  1 +require File.dirname(__FILE__) + '/../../../../test/test_helper'
  2 +require File.dirname(__FILE__) + '/../../controllers/mark_comment_as_read_plugin_profile_controller'
  3 +
  4 +# Re-raise errors caught by the controller.
  5 +class MarkCommentAsReadPluginProfileController; def rescue_action(e) raise e end; end
  6 +
  7 +class MarkCommentAsReadPluginProfileControllerTest < ActionController::TestCase
  8 + def setup
  9 + @controller = MarkCommentAsReadPluginProfileController.new
  10 + @request = ActionController::TestRequest.new
  11 + @response = ActionController::TestResponse.new
  12 + @profile = create_user('profile').person
  13 + @article = TinyMceArticle.create!(:profile => @profile, :name => 'An article')
  14 + @comment = Comment.new(:source => @article, :author => @profile, :body => 'test')
  15 + @comment.save!
  16 + login_as(@profile.identifier)
  17 + environment = Environment.default
  18 + environment.enable_plugin(MarkCommentAsReadPlugin)
  19 + self.stubs(:user).returns(@profile)
  20 + end
  21 +
  22 + attr_reader :profile, :comment
  23 +
  24 + should 'mark comment as read' do
  25 + xhr :post, :mark_as_read, :profile => profile.identifier, :id => comment.id
  26 + assert_match /\{\"ok\":true\}/, @response.body
  27 + end
  28 +
  29 + should 'mark comment as not read' do
  30 + xhr :post, :mark_as_not_read, :profile => profile.identifier, :id => comment.id
  31 + assert_match /\{\"ok\":true\}/, @response.body
  32 + end
  33 +end
plugins/mark_comment_as_read/test/unit/mark_comment_as_read_plugin/comment_test.rb 0 → 100644
@@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
  1 +require File.dirname(__FILE__) + '/../../../../../test/test_helper'
  2 +
  3 +class MarkCommentAsReadPlugin::CommentTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @person = create_user('user').person
  7 + @article = TinyMceArticle.create!(:profile => @person, :name => 'An article')
  8 + @comment = Comment.create!(:title => 'title', :body => 'body', :author_id => @person.id, :source => @article)
  9 + end
  10 +
  11 + should 'mark comment as read' do
  12 + assert !@comment.marked_as_read?(@person)
  13 + @comment.mark_as_read(@person)
  14 + assert @comment.marked_as_read?(@person)
  15 + end
  16 +
  17 + should 'do not mark a comment as read again' do
  18 + @comment.mark_as_read(@person)
  19 + assert_raise ActiveRecord::StatementInvalid do
  20 + @comment.mark_as_read(@person)
  21 + end
  22 + end
  23 +
  24 + should 'mark comment as not read' do
  25 + @comment.mark_as_read(@person)
  26 + assert @comment.marked_as_read?(@person)
  27 + @comment.mark_as_not_read(@person)
  28 + assert !@comment.marked_as_read?(@person)
  29 + end
  30 +
  31 + should 'return comments marked as read for a user' do
  32 + person2 = create_user('user2').person
  33 + @comment.mark_as_read(@person)
  34 + assert_equal [], @article.comments.marked_as_read(@person) - [@comment]
  35 + assert_equal [], @article.comments.marked_as_read(person2)
  36 + end
  37 +
  38 +end
plugins/mark_comment_as_read/test/unit/mark_comment_as_read_test.rb 0 → 100644
@@ -0,0 +1,87 @@ @@ -0,0 +1,87 @@
  1 +require File.dirname(__FILE__) + '/../../../../test/test_helper'
  2 +
  3 +class MarkCommentAsReadPluginTest < ActiveSupport::TestCase
  4 +
  5 + include ActionView::Helpers::TagHelper
  6 + include NoosferoTestHelper
  7 +
  8 + def setup
  9 + @plugin = MarkCommentAsReadPlugin.new
  10 + @person = create_user('user').person
  11 + @article = TinyMceArticle.create!(:profile => @person, :name => 'An article')
  12 + @comment = Comment.create!(:source => @article, :author => @person, :body => 'test')
  13 + self.stubs(:user).returns(@person)
  14 + self.stubs(:profile).returns(@person)
  15 + end
  16 +
  17 + attr_reader :plugin, :comment
  18 +
  19 + should 'show link when person is logged in' do
  20 + action = @plugin.comment_actions(@comment)
  21 + link = self.instance_eval(&action)
  22 + assert link
  23 + end
  24 +
  25 + should 'do not show link when person is not logged in' do
  26 + self.stubs(:user).returns(nil)
  27 + action = @plugin.comment_actions(@comment)
  28 + link = self.instance_eval(&action)
  29 + assert !link
  30 + end
  31 +
  32 + should 'return actions when comment is not read' do
  33 + action = @plugin.comment_actions(@comment)
  34 + links = self.instance_eval(&action)
  35 + assert_equal 2, links.size
  36 + end
  37 +
  38 + should 'return actions when comment is read' do
  39 + @comment.mark_as_read(@person)
  40 + action = @plugin.comment_actions(@comment)
  41 + links = self.instance_eval(&action)
  42 + assert_equal 2, links.size
  43 + end
  44 +
  45 + should 'do not return any id when user is not logged in' do
  46 + self.stubs(:user).returns(nil)
  47 + action = @plugin.check_comment_actions(@comment)
  48 + id = self.instance_eval(&action)
  49 + assert !id
  50 + end
  51 +
  52 + should 'return id of mark as not read link when comment is read' do
  53 + @comment.mark_as_read(@person)
  54 + action = @plugin.check_comment_actions(@comment)
  55 + id = self.instance_eval(&action)
  56 + assert_equal "#comment-action-mark-as-not-read-#{@comment.id}", id
  57 + end
  58 +
  59 + should 'return id of mark as read link when comment is not read' do
  60 + action = @plugin.check_comment_actions(@comment)
  61 + id = self.instance_eval(&action)
  62 + assert_equal "#comment-action-mark-as-read-#{@comment.id}", id
  63 + end
  64 +
  65 + should 'return javascript to mark comment as read' do
  66 + @comment.mark_as_read(@person)
  67 + content = @plugin.article_extra_contents(@article)
  68 + assert self.instance_eval(&content)
  69 + end
  70 +
  71 + should 'do not return extra content if comment is not marked as read' do
  72 + content = @plugin.article_extra_contents(@article)
  73 + assert !self.instance_eval(&content)
  74 + end
  75 +
  76 + should 'do not return extra content if user is not logged in' do
  77 + @comment.mark_as_read(@person)
  78 + self.stubs(:user).returns(nil)
  79 + content = @plugin.article_extra_contents(@article)
  80 + assert !self.instance_eval(&content)
  81 + end
  82 +
  83 + def link_to_function(content, url, options = {})
  84 + link_to(content, url, options)
  85 + end
  86 +
  87 +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 });