Commit 77d6fa0d4dbace32bc2ab87ac88e8bb657859c25

Authored by Daniela Feitosa
Committed by Antonio Terceiro
1 parent 445b9833

Add Profile Members Headlines plugin

app/models/person.rb
@@ -21,6 +21,12 @@ class Person < Profile @@ -21,6 +21,12 @@ class Person < Profile
21 { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => [conditions] } 21 { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => [conditions] }
22 } 22 }
23 23
  24 + scope :by_role, lambda { |roles|
  25 + roles = [roles] unless roles.kind_of?(Array)
  26 + { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => ['role_assignments.role_id IN (?)',
  27 +roles] }
  28 + }
  29 +
24 def has_permission_with_plugins?(permission, profile) 30 def has_permission_with_plugins?(permission, profile)
25 permissions = [has_permission_without_plugins?(permission, profile)] 31 permissions = [has_permission_without_plugins?(permission, profile)]
26 permissions += plugins.map do |plugin| 32 permissions += plugins.map do |plugin|
app/models/profile.rb
@@ -108,8 +108,8 @@ class Profile < ActiveRecord::Base @@ -108,8 +108,8 @@ class Profile < ActiveRecord::Base
108 alias_method_chain :count, :distinct 108 alias_method_chain :count, :distinct
109 end 109 end
110 110
111 - def members_by_role(role)  
112 - Person.members_of(self).all(:conditions => ['role_assignments.role_id = ?', role.id]) 111 + def members_by_role(roles)
  112 + Person.members_of(self).by_role(roles)
113 end 113 end
114 114
115 acts_as_having_boxes 115 acts_as_having_boxes
plugins/profile_members_headlines/README.md 0 → 100644
@@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
  1 +README - Profile Members Headlines (ProfileMembersHeadlines Plugin)
  2 +===================================================================
  3 +
  4 +ProfileMembersHeadlines is a plugin that allow users to add a block that
  5 +displays the most recent post from members with the defined roles.
  6 +
  7 +The user also can configure the limit of headlines.
  8 +
  9 +This block will be available for all layout columns of communities and enterprises.
  10 +
  11 +INSTALL
  12 +=======
  13 +
  14 +Enable Plugin
  15 +-------------
  16 +
  17 +Also, you need to enable ProfileMembersHeadlines Plugin at you Noosfero:
  18 +
  19 +cd <your_noosfero_dir>
  20 +./script/noosfero-plugins enable profile_members_headlines
  21 +
  22 +Active Plugin
  23 +-------------
  24 +
  25 +As a Noosfero administrator user, go to administrator panel:
  26 +
  27 +- Click on "Enable/disable plugins" option
  28 +- Click on "Profile Members Headlines Plugin" checkbox
  29 +
  30 +Running DisplayContent tests
  31 +--------------------
  32 +
  33 +$ rake test:noosfero_plugins:profile_members_headlines_plugin
  34 +
  35 +LICENSE
  36 +=======
  37 +
  38 +See Noosfero license.
plugins/profile_members_headlines/lib/ext/person.rb 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +require_dependency 'person'
  2 +class Person
  3 +
  4 + def has_headline?
  5 + !headline.nil?
  6 + end
  7 +
  8 + def headline
  9 + return nil unless blog
  10 + blog.posts.published.first
  11 + end
  12 +
  13 +end
plugins/profile_members_headlines/lib/profile_members_headlines_block.rb 0 → 100644
@@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
  1 +class ProfileMembersHeadlinesBlock < Block
  2 +
  3 + settings_items :interval, :type => 'integer', :default => 10
  4 + settings_items :limit, :type => 'integer', :default => 10
  5 + settings_items :navigation, :type => 'boolean', :default => true
  6 + settings_items :filtered_roles, :type => Array, :default => []
  7 +
  8 + attr_accessible :interval, :limit, :navigation, :filtered_roles
  9 +
  10 + def self.description
  11 + _('Display headlines from members of a community')
  12 + end
  13 +
  14 + def help
  15 + _('This block displays one post from members of a community.')
  16 + end
  17 +
  18 + include Noosfero::Plugin::HotSpot
  19 +
  20 + def default_title
  21 + _('Profile members headlines')
  22 + end
  23 +
  24 + def filtered_roles=(array)
  25 + self.settings[:filtered_roles] = array.map(&:to_i).select { |r| !r.to_i.zero? }
  26 + end
  27 +
  28 + def authors_list
  29 + result = owner.members_by_role(filtered_roles).public.includes([:image,:domains,:preferred_domain,:environment]).order('updated_at DESC')
  30 +
  31 + result.all(:limit => limit * 5).select { |p| p.has_headline?
  32 +}.slice(0..limit-1)
  33 + end
  34 +
  35 + def content(args={})
  36 + block = self
  37 + members = authors_list
  38 + proc do
  39 + render :file => 'blocks/headlines', :locals => { :block => block, :members => members }
  40 + end
  41 + end
  42 +
  43 +end
plugins/profile_members_headlines/lib/profile_members_headlines_plugin.rb 0 → 100644
@@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
  1 +require_dependency File.dirname(__FILE__) + '/profile_members_headlines_block'
  2 +require 'ext/person'
  3 +
  4 +class ProfileMembersHeadlinesPlugin < Noosfero::Plugin
  5 +
  6 + def self.plugin_name
  7 + "Profile Members Headlines Plugin"
  8 + end
  9 +
  10 + def self.plugin_description
  11 + _("A plugin that adds a block where you can display posts from members.")
  12 + end
  13 +
  14 + def self.extra_blocks
  15 + { ProfileMembersHeadlinesBlock => { :type => [Community], :position =>
  16 +['1'] }}
  17 + end
  18 +
  19 + def stylesheet?
  20 + true
  21 + end
  22 +
  23 +end
plugins/profile_members_headlines/public/images/calendario-ico.png 0 → 100644

379 Bytes

plugins/profile_members_headlines/public/style.css 0 → 100644
@@ -0,0 +1,59 @@ @@ -0,0 +1,59 @@
  1 +.profile-members-headlines-block {
  2 + width: 100%;
  3 +}
  4 +
  5 +.profile-members-headlines-block .headlines-container {
  6 + height: 180px;
  7 +}
  8 +
  9 +.profile-members-headlines-block .headlines-container .author,
  10 +.profile-members-headlines-block .headlines-container .post {
  11 + vertical-align: top;
  12 + min-width: 150px;
  13 +}
  14 +
  15 +.profile-members-headlines-block .headlines-container .author {
  16 + position: absolute;
  17 +}
  18 +
  19 +.profile-members-headlines-block .headlines-container .author p {
  20 + text-align: center;
  21 +}
  22 +
  23 +.profile-members-headlines-block .headlines-container .post {
  24 + margin-left: 160px;
  25 +}
  26 +
  27 +.profile-members-headlines-block #content .headlines-container h4 {
  28 + margin-top: 15px;
  29 + font-weight: bold;
  30 +}
  31 +
  32 +.profile-members-headlines-block .headlines-container a {
  33 + text-decoration: none;
  34 +}
  35 +
  36 +.profile-members-headlines-block .headlines-container a:hover {
  37 + text-decoration: underline;
  38 +}
  39 +
  40 +.profile-members-headlines-block .headlines-container .post .date {
  41 + margin-top: 15px;
  42 +}
  43 +
  44 +.profile-members-headlines-block .headlines-block-pager {
  45 + text-align: center;
  46 +}
  47 +
  48 +.profile-members-headlines-block .headlines-block-pager a {
  49 + padding: 0px 5px;
  50 +}
  51 +
  52 +.profile-members-headlines-block .headlines-block-pager a.activeSlide {
  53 + text-decoration: none;
  54 +}
  55 +
  56 +.profile-members-headlines-block .headlines-block-pager a.activeSlide:visited,
  57 +.profile-members-headlines-block .headlines-block-pager a.activeSlide {
  58 + color: #000;
  59 +}
plugins/profile_members_headlines/test/test_helper.rb 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +require File.dirname(__FILE__) + '/../../../test/test_helper'
plugins/profile_members_headlines/test/unit/profile_members_headlines_block_test.rb 0 → 100644
@@ -0,0 +1,81 @@ @@ -0,0 +1,81 @@
  1 +require 'test_helper'
  2 +
  3 +class ProfileMembersHeadlinesBlockTest < ActiveSupport::TestCase
  4 +
  5 + include Noosfero::Plugin::HotSpot
  6 +
  7 + def setup
  8 + @environment = fast_create(Environment)
  9 + @environment.enable_plugin(ProfileMembersHeadlinesPlugin)
  10 +
  11 + @member1 = fast_create(Person)
  12 + @member2 = fast_create(Person)
  13 + @community = fast_create(Community)
  14 + community.add_member member1
  15 + community.add_member member2
  16 + end
  17 + attr_accessor :environment, :community, :member1, :member2
  18 +
  19 + should 'inherit from Block' do
  20 + assert_kind_of Block, ProfileMembersHeadlinesBlock.new
  21 + end
  22 +
  23 + should 'describe itself' do
  24 + assert_not_equal Block.description, ProfileMembersHeadlinesBlock.description
  25 + end
  26 +
  27 + should 'provide a default title' do
  28 + assert_not_equal Block.new.default_title, ProfileMembersHeadlinesBlock.new.default_title
  29 + end
  30 +
  31 + should 'not have authors if they have no blog' do
  32 + block = ProfileMembersHeadlinesBlock.create
  33 + block.stubs(:owner).returns(community)
  34 +
  35 + self.expects(:render).with(:file => 'blocks/headlines', :locals => { :block => block, :members => []}).returns('file-without-authors-and-headlines')
  36 + assert_equal 'file-without-authors-and-headlines', instance_eval(&block.content)
  37 + end
  38 +
  39 + should 'display headlines file' do
  40 + block = ProfileMembersHeadlinesBlock.create
  41 + block.stubs(:owner).returns(community)
  42 + blog = fast_create(Blog, :profile_id => member1.id)
  43 + post = fast_create(TinyMceArticle, :name => 'headlines', :profile_id => member1.id, :parent_id => blog.id)
  44 + self.expects(:render).with(:file => 'blocks/headlines', :locals => { :block => block, :members => []}).returns('file-with-authors-and-headlines')
  45 + assert_equal 'file-with-authors-and-headlines', instance_eval(&block.content)
  46 + end
  47 +
  48 + should 'select only authors with articles and selected roles to display' do
  49 + role = Role.create!(:name => 'role1')
  50 + community.affiliate(member1, role)
  51 + block = ProfileMembersHeadlinesBlock.new(:limit => 1, :filtered_roles => [role.id])
  52 + block.expects(:owner).returns(community)
  53 + blog = fast_create(Blog, :profile_id => member1.id)
  54 + post = fast_create(TinyMceArticle, :name => 'headlines', :profile_id => member1.id, :parent_id => blog.id)
  55 + assert_equal [member1], block.authors_list
  56 + end
  57 +
  58 + should 'not select private authors to display' do
  59 + block = ProfileMembersHeadlinesBlock.new(:limit => 1)
  60 + block.expects(:owner).returns(community)
  61 + private_author = fast_create(Person, :public_profile => false)
  62 + blog = fast_create(Blog, :profile_id => private_author.id)
  63 + post = fast_create(TinyMceArticle, :name => 'headlines', :profile_id => private_author.id, :parent_id => blog.id)
  64 + assert_equal [], block.authors_list
  65 + end
  66 +
  67 + should 'filter authors by roles to display' do
  68 + role = Role.create!(:name => 'role1')
  69 + author = fast_create(Person)
  70 + community.affiliate(author, role)
  71 +
  72 + block = ProfileMembersHeadlinesBlock.new(:limit => 3, :filtered_roles =>
  73 +[role.id])
  74 + block.stubs(:owner).returns(community)
  75 + community.members.each do |member|
  76 + blog = fast_create(Blog, :profile_id => member.id)
  77 + post = fast_create(TinyMceArticle, :name => 'headlines', :profile_id => member.id, :parent_id => blog.id)
  78 + end
  79 + assert_equal [author], block.authors_list
  80 + end
  81 +end
plugins/profile_members_headlines/test/unit/profile_members_headlines_plugin_test.rb 0 → 100644
@@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
  1 +require 'test_helper'
  2 +
  3 +class ProfileMembersHeadlinesPluginTest < ActiveSupport::TestCase
  4 +
  5 + include Noosfero::Plugin::HotSpot
  6 +
  7 + def setup
  8 + @environment = fast_create(Environment)
  9 + @environment.enable_plugin(ProfileMembersHeadlinesPlugin)
  10 + end
  11 + attr_accessor :environment
  12 +
  13 + should 'has a name' do
  14 + assert_not_equal Noosfero::Plugin.plugin_name, ProfileMembersHeadlinesPlugin.plugin_name
  15 + end
  16 +
  17 + should 'describe itself' do
  18 + assert_not_equal Noosfero::Plugin.plugin_description, ProfileMembersHeadlinesPlugin.plugin_description
  19 + end
  20 +
  21 + should 'return ProfileMembersHeadlinesBlock in extra_blocks class method' do
  22 + assert ProfileMembersHeadlinesPlugin.extra_blocks.keys.include?(ProfileMembersHeadlinesBlock)
  23 + end
  24 +
  25 + should 'ProfileMembersHeadlinesBlock not available for environment' do
  26 + assert_not_includes plugins.dispatch(:extra_blocks, :type => Environment), ProfileMembersHeadlinesBlock
  27 + end
  28 +
  29 + should 'ProfileMembersHeadlinesBlock not available for people' do
  30 + assert_not_includes plugins.dispatch(:extra_blocks, :type => Person), ProfileMembersHeadlinesBlock
  31 + end
  32 +
  33 + should "ProfileMembersHeadlinesBlock be available for community" do
  34 + assert_includes plugins.dispatch(:extra_blocks, :type => Community), ProfileMembersHeadlinesBlock
  35 + end
  36 +
  37 + should 'has stylesheet' do
  38 + assert ProfileMembersHeadlinesPlugin.new.stylesheet?
  39 + end
  40 +
  41 +end
plugins/profile_members_headlines/views/blocks/headlines.html.erb 0 → 100644
@@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
  1 +<%= block_title(block.title) %>
  2 +
  3 +<% unless members.empty? %>
  4 + <div class='headlines-container'>
  5 + <% members.each do |member| %>
  6 + <div>
  7 + <% headline = member.headline %>
  8 + <%= link_to_profile(profile_image(member, :big) + content_tag(:p, member.short_name), member.identifier, {:class => 'author'}) %>
  9 + <div class='post'>
  10 + <h4><%= link_to(headline.title, headline.url, :class => 'title') %></h4>
  11 + <div class='lead'>
  12 + <%= headline.short_lead %>
  13 + </div>
  14 + <div class='date'>
  15 + <%= show_date(headline.published_at) %>
  16 + </div>
  17 + <div class='tags'>
  18 + <%= headline.tags.map { |t| link_to(t, :controller => 'profile', :profile => member.identifier, :action => 'tags', :id => t.name ) }.join("\n") %>
  19 + </div>
  20 + </div>
  21 + </div>
  22 + <% end %>
  23 + </div>
  24 + <% if block.navigation %>
  25 + <div class='headlines-block-pager'>
  26 + </div>
  27 + <% end %>
  28 +
  29 + <script>
  30 + (function($) {
  31 + var options = {fx: 'fade', pause: 1, fastOnEvent: 1, timeout: <%= block.interval * 1000 %>};
  32 + options.pager = '#block-<%= block.id %> .headlines-block-pager';
  33 + $('#block-<%= block.id %> .headlines-container').cycle(options);
  34 + })(jQuery);
  35 + </script>
  36 +<% else %>
  37 + <em><%= _('No headlines to be shown.') %></em>
  38 +<% end %>
  39 +
plugins/profile_members_headlines/views/box_organizer/_profile_members_headlines_block.html.erb 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +<div id="profile_members_headlines_plugin">
  2 +
  3 + <%= labelled_form_field _('Headlines transition:'), select('block', 'interval', [[_('No automatic transition'), 0]] + [1, 2, 3, 4, 5, 10, 20, 30, 60].map {|item| [n_('Every 1 second', 'Every %d seconds', item) % item, item]}) %>
  4 +
  5 + <%= labelled_form_field check_box(:block, :navigation) + _('Display navigation buttons'), '' %>
  6 + <%= labelled_form_field _('Limit of headlines'), text_field(:block, :limit, :size => 3) %>
  7 +
  8 + <%= label :block, :filtered_roles, _('Choose which roles should be displayed:'), :class => 'formlabel' %>
  9 +
  10 + <% Profile::Roles.organization_member_roles(environment).each do |role| %>
  11 + <%= labelled_check_box(role.name, 'block[filtered_roles][]', role.id, @block.filtered_roles.include?(role.id)) %>
  12 + <% end %>
  13 +</div>
plugins/profile_members_headlines/views/profile_design 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +box_organizer/
0 \ No newline at end of file 2 \ No newline at end of file
test/unit/organization_test.rb
@@ -383,6 +383,33 @@ class OrganizationTest &lt; ActiveSupport::TestCase @@ -383,6 +383,33 @@ class OrganizationTest &lt; ActiveSupport::TestCase
383 assert !organization.errors[:cnpj.to_s].present? 383 assert !organization.errors[:cnpj.to_s].present?
384 end 384 end
385 385
  386 + should 'get members by role' do
  387 + community = fast_create(Community)
  388 + role1 = Role.create!(:name => 'role1')
  389 + person1 = fast_create(Person)
  390 + community.affiliate(person1, role1)
  391 + role2 = Role.create!(:name => 'role2')
  392 + person2 = fast_create(Person)
  393 + community.affiliate(person2, role2)
  394 +
  395 + assert_equal [person1], community.members_by_role([role1])
  396 + end
  397 +
  398 + should 'get members by more than one role' do
  399 + community = fast_create(Community)
  400 + role1 = Role.create!(:name => 'role1')
  401 + person1 = fast_create(Person)
  402 + community.affiliate(person1, role1)
  403 + role2 = Role.create!(:name => 'role2')
  404 + person2 = fast_create(Person)
  405 + community.affiliate(person2, role2)
  406 + role3 = Role.create!(:name => 'role3')
  407 + person3 = fast_create(Person)
  408 + community.affiliate(person3, role3)
  409 +
  410 + assert_equal [person2, person3], community.members_by_role([role2, role3])
  411 + end
  412 +
386 should 'return members by role in a json format' do 413 should 'return members by role in a json format' do
387 organization = fast_create(Organization) 414 organization = fast_create(Organization)
388 p1 = create_user('person-1').person 415 p1 = create_user('person-1').person