Commit 645f9328979e3efa711c1f06d0a9d6ef364719df
Exists in
master
and in
29 other branches
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 | 3 | protect 'edit_environment_design', :environment |
| 4 | 4 | |
| 5 | 5 | def available_blocks |
| 6 | + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from | |
| 7 | + # the Noosfero core soon, see ActionItem3045 | |
| 6 | 8 | @available_blocks ||= [ ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ] |
| 7 | 9 | @available_blocks += plugins.dispatch(:extra_blocks, :type => Environment) |
| 8 | 10 | end | ... | ... |
app/controllers/admin/users_controller.rb
| ... | ... | @@ -7,7 +7,7 @@ class UsersController < AdminController |
| 7 | 7 | include UsersHelper |
| 8 | 8 | |
| 9 | 9 | def index |
| 10 | - @filter = params[:filter] | |
| 10 | + @filter = params[:filter] || 'all_users' | |
| 11 | 11 | scope = environment.people.no_templates |
| 12 | 12 | if @filter == 'admin_users' |
| 13 | 13 | scope = scope.admins |
| ... | ... | @@ -16,6 +16,7 @@ class UsersController < AdminController |
| 16 | 16 | elsif @filter == 'deactivated_users' |
| 17 | 17 | scope = scope.deactivated |
| 18 | 18 | end |
| 19 | + scope = scope.order('name ASC') | |
| 19 | 20 | @q = params[:q] |
| 20 | 21 | @collection = find_by_contents(:people, scope, @q, {:per_page => per_page, :page => params[:npage]})[:results] |
| 21 | 22 | end |
| ... | ... | @@ -44,6 +45,20 @@ class UsersController < AdminController |
| 44 | 45 | redirect_to :action => :index, :q => params[:q], :filter => params[:filter] |
| 45 | 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 | 62 | def download |
| 48 | 63 | respond_to do |format| |
| 49 | 64 | format.html | ... | ... |
app/controllers/application_controller.rb
| ... | ... | @@ -21,6 +21,7 @@ class ApplicationController < ActionController::Base |
| 21 | 21 | include ApplicationHelper |
| 22 | 22 | layout :get_layout |
| 23 | 23 | def get_layout |
| 24 | + return nil if request.format == :js | |
| 24 | 25 | theme_layout = theme_option(:layout) |
| 25 | 26 | if theme_layout |
| 26 | 27 | theme_view_file('layouts/'+theme_layout) || theme_layout | ... | ... |
app/controllers/box_organizer_controller.rb
| ... | ... | @@ -70,7 +70,7 @@ class BoxOrganizerController < ApplicationController |
| 70 | 70 | else |
| 71 | 71 | @center_block_types = (Box.acceptable_center_blocks & available_blocks) + plugins.dispatch(:extra_blocks, :type => boxes_holder.class, :position => 1) |
| 72 | 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 | 74 | render :action => 'add_block', :layout => false |
| 75 | 75 | end |
| 76 | 76 | end | ... | ... |
app/controllers/my_profile/cms_controller.rb
| ... | ... | @@ -221,11 +221,10 @@ class CmsController < MyProfileController |
| 221 | 221 | |
| 222 | 222 | def update_categories |
| 223 | 223 | @object = params[:id] ? @profile.articles.find(params[:id]) : Article.new |
| 224 | + @categories = @toplevel_categories = environment.top_level_categories | |
| 224 | 225 | if params[:category_id] |
| 225 | 226 | @current_category = Category.find(params[:category_id]) |
| 226 | 227 | @categories = @current_category.children |
| 227 | - else | |
| 228 | - @categories = environment.top_level_categories.select{|i| !i.children.empty?} | |
| 229 | 228 | end |
| 230 | 229 | render :partial => 'shared/select_categories', :locals => {:object_name => 'article', :multiple => true}, :layout => false |
| 231 | 230 | end | ... | ... |
app/controllers/my_profile/profile_editor_controller.rb
| ... | ... | @@ -55,11 +55,10 @@ class ProfileEditorController < MyProfileController |
| 55 | 55 | |
| 56 | 56 | def update_categories |
| 57 | 57 | @object = profile |
| 58 | + @categories = @toplevel_categories = environment.top_level_categories | |
| 58 | 59 | if params[:category_id] |
| 59 | 60 | @current_category = Category.find(params[:category_id]) |
| 60 | 61 | @categories = @current_category.children |
| 61 | - else | |
| 62 | - @categories = environment.top_level_categories.select{|i| !i.children.empty?} | |
| 63 | 62 | end |
| 64 | 63 | render :partial => 'shared/select_categories', :locals => {:object_name => 'profile_data', :multiple => true}, :layout => false |
| 65 | 64 | end | ... | ... |
app/controllers/my_profile/profile_members_controller.rb
app/controllers/public/profile_controller.rb
| ... | ... | @@ -67,7 +67,7 @@ class ProfileController < PublicController |
| 67 | 67 | |
| 68 | 68 | def members |
| 69 | 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 | 71 | end |
| 72 | 72 | end |
| 73 | 73 | |
| ... | ... | @@ -304,14 +304,6 @@ class ProfileController < PublicController |
| 304 | 304 | end |
| 305 | 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 | 307 | def report_abuse |
| 316 | 308 | @abuse_report = AbuseReport.new |
| 317 | 309 | render :layout => false | ... | ... |
app/controllers/themes_controller.rb
| ... | ... | @@ -12,7 +12,7 @@ class ThemesController < ApplicationController |
| 12 | 12 | |
| 13 | 13 | def index |
| 14 | 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 | 17 | @current_theme = target.theme |
| 18 | 18 | ... | ... |
app/helpers/application_helper.rb
| ... | ... | @@ -608,49 +608,18 @@ module ApplicationHelper |
| 608 | 608 | end |
| 609 | 609 | |
| 610 | 610 | attr_reader :environment |
| 611 | + | |
| 611 | 612 | def select_categories(object_name, title=nil, title_size=4) |
| 612 | 613 | return nil if environment.enabled?(:disable_categories) |
| 613 | 614 | if title.nil? |
| 614 | 615 | title = _('Categories') |
| 615 | 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, " → "), | |
| 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 | 623 | end |
| 655 | 624 | |
| 656 | 625 | def theme_option(opt = nil) | ... | ... |
app/helpers/boxes_helper.rb
| ... | ... | @@ -39,7 +39,7 @@ module BoxesHelper |
| 39 | 39 | end |
| 40 | 40 | |
| 41 | 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 | 43 | content = boxes.reverse.map { |item| display_box(item, main_content) }.join("\n") |
| 44 | 44 | content = main_content if (content.blank?) |
| 45 | 45 | ... | ... |
app/helpers/categories_helper.rb
| ... | ... | @@ -48,4 +48,12 @@ module CategoriesHelper |
| 48 | 48 | labelled_form_field(_('Type of category'), select_tag('type', options_for_select(TYPES, value))) |
| 49 | 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(' → '), 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 | 59 | end | ... | ... |
app/helpers/comment_helper.rb
| ... | ... | @@ -22,6 +22,12 @@ module CommentHelper |
| 22 | 22 | title |
| 23 | 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 | 31 | def comment_actions(comment) |
| 26 | 32 | url = url_for(:profile => profile.identifier, :controller => :comment, :action => :check_actions, :id => comment.id) |
| 27 | 33 | links = links_for_comment_actions(comment) | ... | ... |
app/models/box.rb
| ... | ... | @@ -5,6 +5,8 @@ class Box < ActiveRecord::Base |
| 5 | 5 | |
| 6 | 6 | include Noosfero::Plugin::HotSpot |
| 7 | 7 | |
| 8 | + named_scope :with_position, :conditions => ['boxes.position > 0'] | |
| 9 | + | |
| 8 | 10 | def environment |
| 9 | 11 | owner ? (owner.kind_of?(Environment) ? owner : owner.environment) : nil |
| 10 | 12 | end |
| ... | ... | @@ -24,6 +26,8 @@ class Box < ActiveRecord::Base |
| 24 | 26 | CategoriesBlock, |
| 25 | 27 | CommunitiesBlock, |
| 26 | 28 | EnterprisesBlock, |
| 29 | + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from | |
| 30 | + # the Noosfero core soon, see ActionItem3045 | |
| 27 | 31 | EnvironmentStatisticsBlock, |
| 28 | 32 | FansBlock, |
| 29 | 33 | FavoriteEnterprisesBlock, |
| ... | ... | @@ -50,6 +54,8 @@ class Box < ActiveRecord::Base |
| 50 | 54 | CommunitiesBlock, |
| 51 | 55 | DisabledEnterpriseMessageBlock, |
| 52 | 56 | EnterprisesBlock, |
| 57 | + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from | |
| 58 | + # the Noosfero core soon, see ActionItem3045 | |
| 53 | 59 | EnvironmentStatisticsBlock, |
| 54 | 60 | FansBlock, |
| 55 | 61 | FavoriteEnterprisesBlock, | ... | ... |
app/models/environment.rb
| ... | ... | @@ -161,6 +161,8 @@ class Environment < ActiveRecord::Base |
| 161 | 161 | |
| 162 | 162 | # "left" area |
| 163 | 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 | 166 | env.boxes[1].blocks << EnvironmentStatisticsBlock.new |
| 165 | 167 | env.boxes[1].blocks << RecentDocumentsBlock.new |
| 166 | 168 | |
| ... | ... | @@ -186,7 +188,7 @@ class Environment < ActiveRecord::Base |
| 186 | 188 | has_many :product_categories, :conditions => { :type => 'ProductCategory'} |
| 187 | 189 | has_many :regions |
| 188 | 190 | |
| 189 | - has_many :roles | |
| 191 | + has_many :roles, :dependent => :destroy | |
| 190 | 192 | |
| 191 | 193 | has_many :qualifiers |
| 192 | 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 | 4 | class EnvironmentStatisticsBlock < Block |
| 2 | 5 | |
| 3 | 6 | def self.description |
| 4 | - _('Environment stastistics') | |
| 7 | + _('Environment stastistics (DEPRECATED)') | |
| 5 | 8 | end |
| 6 | 9 | |
| 7 | 10 | def default_title | ... | ... |
app/models/link_list_block.rb
| ... | ... | @@ -63,7 +63,7 @@ class LinkListBlock < Block |
| 63 | 63 | def link_html(link) |
| 64 | 64 | klass = 'icon-' + link[:icon] if link[:icon] |
| 65 | 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 | 68 | end |
| 69 | 69 | ... | ... |
app/models/profile.rb
app/sweepers/profile_sweeper.rb
| ... | ... | @@ -8,6 +8,8 @@ class ProfileSweeper # < ActiveRecord::Observer |
| 8 | 8 | end |
| 9 | 9 | |
| 10 | 10 | def after_create(profile) |
| 11 | + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from | |
| 12 | + # the Noosfero core soon, see ActionItem3045 | |
| 11 | 13 | expire_statistics_block_cache(profile) |
| 12 | 14 | end |
| 13 | 15 | |
| ... | ... | @@ -29,6 +31,8 @@ protected |
| 29 | 31 | expire_blogs(profile) if profile.organization? |
| 30 | 32 | end |
| 31 | 33 | |
| 34 | + # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from | |
| 35 | + # the Noosfero core soon, see ActionItem3045 | |
| 32 | 36 | def expire_statistics_block_cache(profile) |
| 33 | 37 | blocks = profile.environment.blocks.select { |b| b.kind_of?(EnvironmentStatisticsBlock) } |
| 34 | 38 | BlockSweeper.expire_blocks(blocks) | ... | ... |
app/views/blocks/location.html.erb
| ... | ... | @@ -3,7 +3,6 @@ |
| 3 | 3 | <div class='the-localization-map'> |
| 4 | 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 | 5 | </div> |
| 6 | -</div> | |
| 7 | 6 | <% else %> |
| 8 | 7 | <i><%= _('This profile has no geographical position registered.') %></i> |
| 9 | 8 | <% end %> | ... | ... |
app/views/blocks/profile_image.rhtml
| ... | ... | @@ -16,7 +16,7 @@ |
| 16 | 16 | |
| 17 | 17 | <% if !user.nil? and user.has_permission?('edit_profile', profile) %> |
| 18 | 18 | <div class='admin-link'> |
| 19 | - <%= link_to _('Control panel'), :controller => 'profile_editor' %> | |
| 19 | + <%= link_to _('Control panel'), block.owner.admin_url %> | |
| 20 | 20 | </div> |
| 21 | 21 | <% end %> |
| 22 | 22 | ... | ... |
app/views/blocks/profile_info.rhtml
| ... | ... | @@ -21,7 +21,7 @@ |
| 21 | 21 | <li><%= link_to(_('Products/Services'), :controller => 'catalog', :profile => block.owner.identifier) %></li> |
| 22 | 22 | <% end %> |
| 23 | 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 | 25 | <% end %> |
| 26 | 26 | <% if profile.person? %> |
| 27 | 27 | <li><%= _('Since %{year}/%{month}') % { :year => block.owner.created_at.year, :month => block.owner.created_at.month } %></li> |
| ... | ... | @@ -40,7 +40,7 @@ |
| 40 | 40 | <% end %> |
| 41 | 41 | |
| 42 | 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 | 44 | </div> |
| 45 | 45 | |
| 46 | 46 | </div><!-- end class="vcard" --> | ... | ... |
app/views/box_organizer/_link_list_block.rhtml
| 1 | 1 | <strong><%= _('Links') %></strong> |
| 2 | -<div id='edit-link-list-block' style='width:450px'> | |
| 2 | +<div id='edit-link-list-block'> | |
| 3 | 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 | 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 | 19 | <% end %> |
| 17 | 20 | </table> |
| 18 | 21 | </div> |
| ... | ... | @@ -22,8 +25,8 @@ |
| 22 | 25 | content_tag('td', icon_selector('ok')) + |
| 23 | 26 | content_tag('td', text_field_tag('block[links][][name]', '', :maxlength => 20)) + |
| 24 | 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 | 31 | javascript_tag("$('edit-link-list-block').scrollTop = $('edit-link-list-block').scrollHeight") |
| 29 | 32 | end %> | ... | ... |
app/views/content_viewer/view_page.rhtml
| ... | ... | @@ -40,14 +40,6 @@ |
| 40 | 40 | </div> |
| 41 | 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 | 43 | <%= render :partial => 'shared/disabled_enterprise' %> |
| 52 | 44 | |
| 53 | 45 | <% if NOOSFERO_CONF['addthis_enabled'] %> |
| ... | ... | @@ -83,8 +75,17 @@ |
| 83 | 75 | </div> |
| 84 | 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 | 85 | <%= display_source_info(@page) %> |
| 87 | 86 | |
| 87 | +<%= @plugins.dispatch(:article_extra_contents, @page).collect { |content| instance_eval(&content) }.join("") %> | |
| 88 | + | |
| 88 | 89 | <div class="comments" id="comments_list"> |
| 89 | 90 | |
| 90 | 91 | <% if @page.accept_comments? || @comments_count > 0 %> | ... | ... |
app/views/features/_manage_community_fields.rhtml
| 1 | -<h2><%= __('Manage community fields') %></h2> | |
| 2 | - | |
| 3 | 1 | <% labelled_form_for(:environment, @environment, :url => {:action => 'manage_community_fields'}) do |f| %> |
| 4 | 2 | |
| 5 | 3 | <table id='community_fields_conf'> |
| ... | ... | @@ -9,21 +7,37 @@ |
| 9 | 7 | <th><%= _('Required') %></th> |
| 10 | 8 | <th><%= _('Display on creation?') %></th> |
| 11 | 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 | 26 | <% @community_fields.each do |field| %> |
| 13 | 27 | <tr> |
| 14 | 28 | <td><label for="community_fields[<%= field %>][active]"><%= _(field.humanize) %></label></td> |
| 15 | 29 | |
| 16 | 30 | <td> |
| 17 | 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 | 33 | </td> |
| 20 | 34 | <td> |
| 21 | 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 | 37 | </td> |
| 24 | 38 | <td> |
| 25 | 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 | 41 | </td> |
| 28 | 42 | |
| 29 | 43 | </tr> |
| ... | ... | @@ -31,18 +45,18 @@ |
| 31 | 45 | </table> |
| 32 | 46 | |
| 33 | 47 | <script type='text/javascript'> |
| 34 | - var trs = $$('#community_fields_conf tr'); | |
| 48 | + var trs = jQuery('#community_fields_conf tr'); | |
| 35 | 49 | var tr, td2; |
| 36 | - for ( var i=0; tr=trs[i]; i++ ) { | |
| 50 | + for ( var i=2; tr=trs[i]; i++ ) { | |
| 37 | 51 | if ( td2 = tr.getElementsByTagName('td')[1] ) { |
| 38 | - td2.getElementsByTagName('input')[0].onclick(); | |
| 52 | + td2.getElementsByTagName('input')[1].onclick(); | |
| 39 | 53 | } |
| 40 | 54 | } |
| 41 | 55 | </script> |
| 42 | 56 | |
| 43 | 57 | <div> |
| 44 | 58 | <% button_bar do %> |
| 45 | - <%= submit_button('save', _('Save changes')) %> | |
| 59 | + <%= submit_button('save', _('Save changes'), :id=>"save_community_fields") %> | |
| 46 | 60 | <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %> |
| 47 | 61 | <% end %> |
| 48 | 62 | </div> | ... | ... |
app/views/features/_manage_enterprise_fields.rhtml
| 1 | -<h2><%= __('Manage enterprise fields') %></h2> | |
| 2 | - | |
| 3 | 1 | <% labelled_form_for(:environment, @environment, :url => {:action => 'manage_enterprise_fields'}) do |f| %> |
| 4 | 2 | |
| 5 | 3 | <table id='enterprise_fields_conf'> |
| ... | ... | @@ -9,21 +7,37 @@ |
| 9 | 7 | <th><%= _('Required') %></th> |
| 10 | 8 | <th><%= _('Display on registration?') %></th> |
| 11 | 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 | 26 | <% @enterprise_fields.each do |field| %> |
| 13 | 27 | <tr> |
| 14 | 28 | |
| 15 | 29 | <td><label for="enterprise_fields[<%= field %>][active]"><%= _(field.humanize) %></label></td> |
| 16 | 30 | <td> |
| 17 | 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 | 33 | </td> |
| 20 | 34 | <td> |
| 21 | 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 | 37 | </td> |
| 24 | 38 | <td> |
| 25 | 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 | 41 | </td> |
| 28 | 42 | |
| 29 | 43 | </tr> |
| ... | ... | @@ -31,18 +45,18 @@ |
| 31 | 45 | </table> |
| 32 | 46 | |
| 33 | 47 | <script type='text/javascript'> |
| 34 | - var trs = $$('#enterprise_fields_conf tr'); | |
| 48 | + var trs = jQuery('#enterprise_fields_conf tr'); | |
| 35 | 49 | var tr, td2; |
| 36 | - for ( var i=0; tr=trs[i]; i++ ) { | |
| 50 | + for ( var i=2; tr=trs[i]; i++ ) { | |
| 37 | 51 | if ( td2 = tr.getElementsByTagName('td')[1] ) { |
| 38 | - td2.getElementsByTagName('input')[0].onclick(); | |
| 52 | + td2.getElementsByTagName('input')[1].onclick(); | |
| 39 | 53 | } |
| 40 | 54 | } |
| 41 | 55 | </script> |
| 42 | 56 | |
| 43 | 57 | <div> |
| 44 | 58 | <% button_bar do %> |
| 45 | - <%= submit_button('save', _('Save changes')) %> | |
| 59 | + <%= submit_button('save', _('Save changes'), :id=>"save_enterprise_fields") %> | |
| 46 | 60 | <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %> |
| 47 | 61 | <% end %> |
| 48 | 62 | </div> | ... | ... |
app/views/features/_manage_person_fields.rhtml
| 1 | -<h2><%= _('Manage person fields') %></h2> | |
| 2 | - | |
| 3 | 1 | <% labelled_form_for(:environment, @environment, :url => {:action => 'manage_person_fields'}) do |f| %> |
| 4 | 2 | |
| 5 | 3 | <table id='person_fields_conf'> |
| ... | ... | @@ -9,31 +7,48 @@ |
| 9 | 7 | <th><%= _('Required') %></th> |
| 10 | 8 | <th><%= _('Display on signup?') %></th> |
| 11 | 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 | 26 | <% @person_fields.each do |field| %> |
| 13 | 27 | <tr> |
| 14 | 28 | <td><label for="person_fields[<%= field %>][active]"><%= _(field.humanize) %></label></td> |
| 15 | 29 | <td> |
| 16 | 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 | 32 | </td> |
| 19 | 33 | <td> |
| 20 | 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 | 36 | </td> |
| 23 | 37 | <td> |
| 24 | 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 | 40 | </td> |
| 27 | 41 | </tr> |
| 28 | 42 | <% end %> |
| 29 | 43 | </table> |
| 30 | 44 | |
| 31 | 45 | <script type='text/javascript'>// <!-- |
| 32 | - var trs = $$('#person_fields_conf tr'); | |
| 46 | + var trs = jQuery('#person_fields_conf tr'); | |
| 47 | + | |
| 33 | 48 | var tr, td2; |
| 34 | - for ( var i=0; tr=trs[i]; i++ ) { | |
| 49 | + for ( var i=2; tr=trs[i]; i++ ) { | |
| 35 | 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 | 56 | |
| 42 | 57 | <div> |
| 43 | 58 | <% button_bar do %> |
| 44 | - <%= submit_button('save', _('Save changes')) %> | |
| 59 | + <%= submit_button('save', _('Save changes'), :id=>"save_person_fields") %> | |
| 45 | 60 | <%= button :back, _('Back to admin panel'), :controller => 'admin_panel', :action => 'index' %> |
| 46 | 61 | <% end %> |
| 47 | 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 | 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 | 2 | <% title = @title ? @title : _('Current members') %> |
| 3 | 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 | 3 | <% if !@current_category.nil? %> |
| 3 | - <h3 class="box-title"><%= _('Current category:') %></h3> | |
| 4 | 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 | 13 | categories = [@current_category] |
| 7 | 14 | categories.push(@current_category) while @current_category = @current_category.parent |
| 8 | 15 | %> |
| 9 | 16 | <%= categories.compact.reverse.map{|i| |
| 10 | - link_to_remote(i.name, | |
| 17 | + link_to_remote(i.name, | |
| 11 | 18 | :update => "select-categories", |
| 12 | 19 | :url => { :action => 'update_categories', :category_id => i.id, :id => @object }, |
| 13 | 20 | :loaded => visual_effect(:highlight, "select-categories"), |
| 14 | 21 | :class => 'select-current-category-link')}.join(' → ') |
| 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 | 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 | 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 | 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 %> | |
| 45 | -<% end %> | |
| 32 | +<div class="toplevel-categories"> | |
| 33 | + <%= render :partial => 'shared/select_subcategories', :locals => {:object_name => object_name, :categories => @categories} %> | |
| 46 | 34 | </div> | ... | ... |
| ... | ... | @@ -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> | ... | ... |
| ... | ... | @@ -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 | 19 | <td class='actions'> |
| 20 | 20 | <div class="members-buttons-cell"> |
| 21 | 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 | 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 | 25 | <% end %> |
| 26 | 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 | 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 | 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 | 33 | </td> |
| 33 | 34 | </tr> |
| 34 | 35 | <% end %> | ... | ... |
debian/changelog
| ... | ... | @@ -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" | ... | ... |
| ... | ... | @@ -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
lib/noosfero/core_ext.rb
lib/noosfero/plugin.rb
| ... | ... | @@ -349,6 +349,12 @@ class Noosfero::Plugin |
| 349 | 349 | [] |
| 350 | 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 | 358 | # -> Adds fields to the signup form |
| 353 | 359 | # returns = lambda block that creates html code |
| 354 | 360 | def signup_extra_contents | ... | ... |
lib/noosfero/plugin/routes.rb
| ... | ... | @@ -15,12 +15,16 @@ Dir.glob(File.join(Rails.root, plugins_root, '*', 'controllers')) do |controller |
| 15 | 15 | controllers_by_folder.each do |folder, controllers| |
| 16 | 16 | controllers.each do |controller| |
| 17 | 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 | 23 | end |
| 20 | 24 | end |
| 21 | 25 | |
| 22 | 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 | 29 | map.connect 'admin/plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_admin' |
| 26 | 30 | end | ... | ... |
| ... | ... | @@ -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 @@ |
| 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 @@ |
| 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
plugins/comment_classification/controllers/comment_classification_plugin_myprofile_controller.rb
0 → 100644
| ... | ... | @@ -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 @@ |
| 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 @@ |
| 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 @@ |
| 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 @@ |
| 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 | ... | ... |
| ... | ... | @@ -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" | ... | ... |
| ... | ... | @@ -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 @@ |
| 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 @@ |
| 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 @@ |
| 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 @@ |
| 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 @@ |
| 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,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/public/images/comment-classification.png
0 → 100644
4.15 KB
| ... | ... | @@ -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 @@ |
| 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 @@ |
| 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 @@ |
| 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 @@ |
| 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
plugins/comment_classification/views/comment_classification_plugin_labels/edit.rhtml
0 → 100644
plugins/comment_classification/views/comment_classification_plugin_labels/index.rhtml
0 → 100644
| ... | ... | @@ -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 @@ |
| 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 @@ |
| 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
plugins/comment_classification/views/comment_classification_plugin_status/_form.rhtml
0 → 100644
| ... | ... | @@ -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
plugins/comment_classification/views/comment_classification_plugin_status/edit.rhtml
0 → 100644
plugins/comment_classification/views/comment_classification_plugin_status/index.rhtml
0 → 100644
| ... | ... | @@ -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
plugins/container_block/lib/container_block_plugin/container_block.rb
| ... | ... | @@ -7,6 +7,16 @@ class ContainerBlockPlugin::ContainerBlock < Block |
| 7 | 7 | settings_items :container_box_id, :type => Integer, :default => nil |
| 8 | 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 | 20 | def self.description |
| 11 | 21 | _('Container') |
| 12 | 22 | end |
| ... | ... | @@ -15,6 +25,10 @@ class ContainerBlockPlugin::ContainerBlock < Block |
| 15 | 25 | _('This block acts as a container for another blocks') |
| 16 | 26 | end |
| 17 | 27 | |
| 28 | + def cacheable? | |
| 29 | + false | |
| 30 | + end | |
| 31 | + | |
| 18 | 32 | def layout_template |
| 19 | 33 | nil |
| 20 | 34 | end |
| ... | ... | @@ -24,8 +38,9 @@ class ContainerBlockPlugin::ContainerBlock < Block |
| 24 | 38 | end |
| 25 | 39 | |
| 26 | 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 | 44 | save! |
| 30 | 45 | end |
| 31 | 46 | ... | ... |
| ... | ... | @@ -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 | 7 | #content .boxes .container-block-plugin_container-block .container_block_child, .container-block-plugin_container-block .block-outer { |
| 2 | 8 | display: inline-block; |
| 3 | 9 | vertical-align: top; |
| ... | ... | @@ -17,14 +23,10 @@ |
| 17 | 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 | 26 | #content .boxes .container-block-plugin_container-block .block .ui-resizable-handle { |
| 25 | 27 | width: 10px; |
| 26 | 28 | height: 28px; |
| 27 | - z-index: 0; | |
| 29 | + z-index: 1000; | |
| 28 | 30 | } |
| 29 | 31 | |
| 30 | 32 | #content .boxes .container-block-plugin_container-block .block .ui-resizable-e { |
| ... | ... | @@ -37,6 +39,21 @@ |
| 37 | 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 | 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 < ActionController::TestCase |
| 31 | 31 | assert_tag :div, :attributes => { :class => 'block container-block-plugin_container-block' } |
| 32 | 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 | 41 | should 'display container children' do |
| 35 | 42 | c1 = RawHTMLBlock.create!(:box => @block.container_box, :html => 'child1 content') |
| 36 | 43 | c2 = RawHTMLBlock.create!(:box => @block.container_box, :html => 'child2 content') | ... | ... |
plugins/container_block/test/unit/block_test.rb
| ... | ... | @@ -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 < ActiveSupport::TestCase |
| 20 | 20 | assert @block.container_box_id |
| 21 | 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 | 28 | should 'return created box' do |
| 24 | 29 | @block.save! |
| 25 | 30 | assert @block.container_box |
| ... | ... | @@ -89,4 +94,27 @@ class ContainerBlockPlugin::ContainerBlockTest < ActiveSupport::TestCase |
| 89 | 94 | end |
| 90 | 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 | 120 | end | ... | ... |
plugins/container_block/test/unit/environment_test.rb
| ... | ... | @@ -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 | -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 | 1 | <% edit_mode = @controller.send(:boxes_editor?) && @controller.send(:uses_design_blocks?) %> |
| 2 | 2 | <% box_decorator = edit_mode ? self : BoxesHelper::DontMoveBlocks %> |
| 3 | 3 | |
| 4 | +<%= block_title(block.title) %> | |
| 4 | 5 | |
| 5 | 6 | <div class="box" id="box-<%= block.container_box.id %>"> |
| 6 | 7 | <%= display_box_content(block.container_box, nil) %> |
| ... | ... | @@ -15,8 +16,18 @@ |
| 15 | 16 | </style> |
| 16 | 17 | |
| 17 | 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 | 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 | 32 | :with => "containerChildrenWidth(#{block.id}, #{block.container_box.id})", |
| 22 | 33 | :html => {:class => "button icon-save container_block_save", :id => "container_block_save_#{block.id}", :title => _('Save') }, |
| ... | ... | @@ -24,37 +35,4 @@ |
| 24 | 35 | :loaded => "close_loading();", |
| 25 | 36 | :complete => "display_notice(request.responseText);"%> |
| 26 | 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 | 38 | <% end %> | ... | ... |
plugins/context_content/views/blocks/_more.rhtml
| 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 | 4 | <% end %> | ... | ... |
plugins/display_content/lib/display_content_block.rb
| ... | ... | @@ -61,9 +61,12 @@ class DisplayContentBlock < Block |
| 61 | 61 | |
| 62 | 62 | VALID_CONTENT = ['RawHTMLArticle', 'TextArticle', 'TextileArticle', 'TinyMceArticle', 'Folder', 'Blog', 'Forum'] |
| 63 | 63 | |
| 64 | + include Noosfero::Plugin::HotSpot | |
| 65 | + | |
| 64 | 66 | def articles_of_parent(parent = nil) |
| 65 | 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 | 70 | end |
| 68 | 71 | |
| 69 | 72 | include ActionController::UrlWriter | ... | ... |
plugins/display_content/test/unit/display_content_block_test.rb
| ... | ... | @@ -238,6 +238,7 @@ class DisplayContentBlockTest < ActiveSupport::TestCase |
| 238 | 238 | block.nodes= [a1.id, a2.id, a3.id] |
| 239 | 239 | box = mock() |
| 240 | 240 | box.stubs(:owner).returns(profile) |
| 241 | + box.stubs(:environment).returns(Environment.default) | |
| 241 | 242 | block.stubs(:box).returns(box) |
| 242 | 243 | assert_equal [], [a1, a2] - block.articles_of_parent |
| 243 | 244 | assert_equal [], block.articles_of_parent - [a1, a2] |
| ... | ... | @@ -253,6 +254,7 @@ class DisplayContentBlockTest < ActiveSupport::TestCase |
| 253 | 254 | block = DisplayContentBlock.new |
| 254 | 255 | box = mock() |
| 255 | 256 | box.stubs(:owner).returns(profile) |
| 257 | + box.stubs(:environment).returns(Environment.default) | |
| 256 | 258 | block.stubs(:box).returns(box) |
| 257 | 259 | assert_equal [], [a3] - block.articles_of_parent(a2) |
| 258 | 260 | assert_equal [], block.articles_of_parent(a2) - [a3] |
| ... | ... | @@ -270,6 +272,7 @@ class DisplayContentBlockTest < ActiveSupport::TestCase |
| 270 | 272 | box = mock() |
| 271 | 273 | block.stubs(:box).returns(box) |
| 272 | 274 | box.stubs(:owner).returns(environment) |
| 275 | + box.stubs(:environment).returns(Environment.default) | |
| 273 | 276 | environment.stubs(:portal_community).returns(profile) |
| 274 | 277 | |
| 275 | 278 | assert_equal [], [a1, a2] - block.articles_of_parent |
| ... | ... | @@ -288,6 +291,7 @@ class DisplayContentBlockTest < ActiveSupport::TestCase |
| 288 | 291 | box = mock() |
| 289 | 292 | block.stubs(:box).returns(box) |
| 290 | 293 | box.stubs(:owner).returns(environment) |
| 294 | + box.stubs(:environment).returns(Environment.default) | |
| 291 | 295 | environment.stubs(:portal_community).returns(profile) |
| 292 | 296 | |
| 293 | 297 | assert_equal [], [a3] - block.articles_of_parent(a2) |
| ... | ... | @@ -301,6 +305,7 @@ class DisplayContentBlockTest < ActiveSupport::TestCase |
| 301 | 305 | box = mock() |
| 302 | 306 | block.stubs(:box).returns(box) |
| 303 | 307 | box.stubs(:owner).returns(environment) |
| 308 | + box.stubs(:environment).returns(Environment.default) | |
| 304 | 309 | |
| 305 | 310 | assert_equal [], block.articles_of_parent() |
| 306 | 311 | end |
| ... | ... | @@ -316,6 +321,7 @@ class DisplayContentBlockTest < ActiveSupport::TestCase |
| 316 | 321 | block = DisplayContentBlock.new |
| 317 | 322 | box = mock() |
| 318 | 323 | box.stubs(:owner).returns(profile) |
| 324 | + box.stubs(:environment).returns(Environment.default) | |
| 319 | 325 | block.stubs(:box).returns(box) |
| 320 | 326 | assert_equal [], [a2] - block.articles_of_parent |
| 321 | 327 | assert_equal [], block.articles_of_parent - [a2] |
| ... | ... | @@ -334,6 +340,7 @@ class DisplayContentBlockTest < ActiveSupport::TestCase |
| 334 | 340 | block = DisplayContentBlock.new |
| 335 | 341 | box = mock() |
| 336 | 342 | box.stubs(:owner).returns(profile) |
| 343 | + box.stubs(:environment).returns(Environment.default) | |
| 337 | 344 | block.stubs(:box).returns(box) |
| 338 | 345 | assert_equal [a1], block.articles_of_parent |
| 339 | 346 | end |
| ... | ... | @@ -526,4 +533,28 @@ class DisplayContentBlockTest < ActiveSupport::TestCase |
| 526 | 533 | assert_equivalent [f1.id, a1.id, a2.id, a3.id], block.nodes |
| 527 | 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 | 560 | end | ... | ... |
plugins/mark_comment_as_read/controllers/mark_comment_as_read_plugin_profile_controller.rb
0 → 100644
| ... | ... | @@ -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 @@ |
| 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 @@ |
| 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 @@ |
| 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
plugins/mark_comment_as_read/public/mark_comment_as_read.js
0 → 100644
| ... | ... | @@ -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/test/functional/mark_comment_as_read_plugin_profile_controller_test.rb
0 → 100644
| ... | ... | @@ -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 @@ |
| 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 @@ |
| 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 | 1 | (function($) { |
| 2 | 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 | 4 | $('.post-comment-button').livequery(function() { |
| 5 | 5 | $(this).show(); |
| 6 | 6 | }); |
| ... | ... | @@ -8,7 +8,7 @@ |
| 8 | 8 | $(this).show(); |
| 9 | 9 | }); |
| 10 | 10 | $('.comment-footer').livequery(function() { |
| 11 | - $(this).show(); | |
| 11 | + $(this).show(); | |
| 12 | 12 | }); |
| 13 | 13 | } |
| 14 | 14 | }); | ... | ... |