diff --git a/app/models/person.rb b/app/models/person.rb index df39448..c644d70 100644 --- a/app/models/person.rb +++ b/app/models/person.rb @@ -21,6 +21,12 @@ class Person < Profile { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => [conditions] } } + scope :by_role, lambda { |roles| + roles = [roles] unless roles.kind_of?(Array) + { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => ['role_assignments.role_id IN (?)', +roles] } + } + def has_permission_with_plugins?(permission, profile) permissions = [has_permission_without_plugins?(permission, profile)] permissions += plugins.map do |plugin| diff --git a/app/models/profile.rb b/app/models/profile.rb index ab73f42..490a672 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -108,8 +108,8 @@ class Profile < ActiveRecord::Base alias_method_chain :count, :distinct end - def members_by_role(role) - Person.members_of(self).all(:conditions => ['role_assignments.role_id = ?', role.id]) + def members_by_role(roles) + Person.members_of(self).by_role(roles) end acts_as_having_boxes diff --git a/plugins/profile_members_headlines/README.md b/plugins/profile_members_headlines/README.md new file mode 100644 index 0000000..2a262e7 --- /dev/null +++ b/plugins/profile_members_headlines/README.md @@ -0,0 +1,38 @@ +README - Profile Members Headlines (ProfileMembersHeadlines Plugin) +=================================================================== + +ProfileMembersHeadlines is a plugin that allow users to add a block that +displays the most recent post from members with the defined roles. + +The user also can configure the limit of headlines. + +This block will be available for all layout columns of communities and enterprises. + +INSTALL +======= + +Enable Plugin +------------- + +Also, you need to enable ProfileMembersHeadlines Plugin at you Noosfero: + +cd +./script/noosfero-plugins enable profile_members_headlines + +Active Plugin +------------- + +As a Noosfero administrator user, go to administrator panel: + +- Click on "Enable/disable plugins" option +- Click on "Profile Members Headlines Plugin" checkbox + +Running DisplayContent tests +-------------------- + +$ rake test:noosfero_plugins:profile_members_headlines_plugin + +LICENSE +======= + +See Noosfero license. diff --git a/plugins/profile_members_headlines/lib/ext/person.rb b/plugins/profile_members_headlines/lib/ext/person.rb new file mode 100644 index 0000000..17ce0de --- /dev/null +++ b/plugins/profile_members_headlines/lib/ext/person.rb @@ -0,0 +1,13 @@ +require_dependency 'person' +class Person + + def has_headline? + !headline.nil? + end + + def headline + return nil unless blog + blog.posts.published.first + end + +end diff --git a/plugins/profile_members_headlines/lib/profile_members_headlines_block.rb b/plugins/profile_members_headlines/lib/profile_members_headlines_block.rb new file mode 100644 index 0000000..2f01b05 --- /dev/null +++ b/plugins/profile_members_headlines/lib/profile_members_headlines_block.rb @@ -0,0 +1,43 @@ +class ProfileMembersHeadlinesBlock < Block + + settings_items :interval, :type => 'integer', :default => 10 + settings_items :limit, :type => 'integer', :default => 10 + settings_items :navigation, :type => 'boolean', :default => true + settings_items :filtered_roles, :type => Array, :default => [] + + attr_accessible :interval, :limit, :navigation, :filtered_roles + + def self.description + _('Display headlines from members of a community') + end + + def help + _('This block displays one post from members of a community.') + end + + include Noosfero::Plugin::HotSpot + + def default_title + _('Profile members headlines') + end + + def filtered_roles=(array) + self.settings[:filtered_roles] = array.map(&:to_i).select { |r| !r.to_i.zero? } + end + + def authors_list + result = owner.members_by_role(filtered_roles).public.includes([:image,:domains,:preferred_domain,:environment]).order('updated_at DESC') + + result.all(:limit => limit * 5).select { |p| p.has_headline? +}.slice(0..limit-1) + end + + def content(args={}) + block = self + members = authors_list + proc do + render :file => 'blocks/headlines', :locals => { :block => block, :members => members } + end + end + +end diff --git a/plugins/profile_members_headlines/lib/profile_members_headlines_plugin.rb b/plugins/profile_members_headlines/lib/profile_members_headlines_plugin.rb new file mode 100644 index 0000000..af69779 --- /dev/null +++ b/plugins/profile_members_headlines/lib/profile_members_headlines_plugin.rb @@ -0,0 +1,23 @@ +require_dependency File.dirname(__FILE__) + '/profile_members_headlines_block' +require 'ext/person' + +class ProfileMembersHeadlinesPlugin < Noosfero::Plugin + + def self.plugin_name + "Profile Members Headlines Plugin" + end + + def self.plugin_description + _("A plugin that adds a block where you can display posts from members.") + end + + def self.extra_blocks + { ProfileMembersHeadlinesBlock => { :type => [Community], :position => +['1'] }} + end + + def stylesheet? + true + end + +end diff --git a/plugins/profile_members_headlines/public/images/calendario-ico.png b/plugins/profile_members_headlines/public/images/calendario-ico.png new file mode 100644 index 0000000..a9e11ab Binary files /dev/null and b/plugins/profile_members_headlines/public/images/calendario-ico.png differ diff --git a/plugins/profile_members_headlines/public/style.css b/plugins/profile_members_headlines/public/style.css new file mode 100644 index 0000000..cdba98d --- /dev/null +++ b/plugins/profile_members_headlines/public/style.css @@ -0,0 +1,59 @@ +.profile-members-headlines-block { + width: 100%; +} + +.profile-members-headlines-block .headlines-container { + height: 180px; +} + +.profile-members-headlines-block .headlines-container .author, +.profile-members-headlines-block .headlines-container .post { + vertical-align: top; + min-width: 150px; +} + +.profile-members-headlines-block .headlines-container .author { + position: absolute; +} + +.profile-members-headlines-block .headlines-container .author p { + text-align: center; +} + +.profile-members-headlines-block .headlines-container .post { + margin-left: 160px; +} + +.profile-members-headlines-block #content .headlines-container h4 { + margin-top: 15px; + font-weight: bold; +} + +.profile-members-headlines-block .headlines-container a { + text-decoration: none; +} + +.profile-members-headlines-block .headlines-container a:hover { + text-decoration: underline; +} + +.profile-members-headlines-block .headlines-container .post .date { + margin-top: 15px; +} + +.profile-members-headlines-block .headlines-block-pager { + text-align: center; +} + +.profile-members-headlines-block .headlines-block-pager a { + padding: 0px 5px; +} + +.profile-members-headlines-block .headlines-block-pager a.activeSlide { + text-decoration: none; +} + +.profile-members-headlines-block .headlines-block-pager a.activeSlide:visited, +.profile-members-headlines-block .headlines-block-pager a.activeSlide { + color: #000; +} diff --git a/plugins/profile_members_headlines/test/test_helper.rb b/plugins/profile_members_headlines/test/test_helper.rb new file mode 100644 index 0000000..cca1fd3 --- /dev/null +++ b/plugins/profile_members_headlines/test/test_helper.rb @@ -0,0 +1 @@ +require File.dirname(__FILE__) + '/../../../test/test_helper' diff --git a/plugins/profile_members_headlines/test/unit/profile_members_headlines_block_test.rb b/plugins/profile_members_headlines/test/unit/profile_members_headlines_block_test.rb new file mode 100644 index 0000000..6d05d84 --- /dev/null +++ b/plugins/profile_members_headlines/test/unit/profile_members_headlines_block_test.rb @@ -0,0 +1,81 @@ +require 'test_helper' + +class ProfileMembersHeadlinesBlockTest < ActiveSupport::TestCase + + include Noosfero::Plugin::HotSpot + + def setup + @environment = fast_create(Environment) + @environment.enable_plugin(ProfileMembersHeadlinesPlugin) + + @member1 = fast_create(Person) + @member2 = fast_create(Person) + @community = fast_create(Community) + community.add_member member1 + community.add_member member2 + end + attr_accessor :environment, :community, :member1, :member2 + + should 'inherit from Block' do + assert_kind_of Block, ProfileMembersHeadlinesBlock.new + end + + should 'describe itself' do + assert_not_equal Block.description, ProfileMembersHeadlinesBlock.description + end + + should 'provide a default title' do + assert_not_equal Block.new.default_title, ProfileMembersHeadlinesBlock.new.default_title + end + + should 'not have authors if they have no blog' do + block = ProfileMembersHeadlinesBlock.create + block.stubs(:owner).returns(community) + + self.expects(:render).with(:file => 'blocks/headlines', :locals => { :block => block, :members => []}).returns('file-without-authors-and-headlines') + assert_equal 'file-without-authors-and-headlines', instance_eval(&block.content) + end + + should 'display headlines file' do + block = ProfileMembersHeadlinesBlock.create + block.stubs(:owner).returns(community) + blog = fast_create(Blog, :profile_id => member1.id) + post = fast_create(TinyMceArticle, :name => 'headlines', :profile_id => member1.id, :parent_id => blog.id) + self.expects(:render).with(:file => 'blocks/headlines', :locals => { :block => block, :members => []}).returns('file-with-authors-and-headlines') + assert_equal 'file-with-authors-and-headlines', instance_eval(&block.content) + end + + should 'select only authors with articles and selected roles to display' do + role = Role.create!(:name => 'role1') + community.affiliate(member1, role) + block = ProfileMembersHeadlinesBlock.new(:limit => 1, :filtered_roles => [role.id]) + block.expects(:owner).returns(community) + blog = fast_create(Blog, :profile_id => member1.id) + post = fast_create(TinyMceArticle, :name => 'headlines', :profile_id => member1.id, :parent_id => blog.id) + assert_equal [member1], block.authors_list + end + + should 'not select private authors to display' do + block = ProfileMembersHeadlinesBlock.new(:limit => 1) + block.expects(:owner).returns(community) + private_author = fast_create(Person, :public_profile => false) + blog = fast_create(Blog, :profile_id => private_author.id) + post = fast_create(TinyMceArticle, :name => 'headlines', :profile_id => private_author.id, :parent_id => blog.id) + assert_equal [], block.authors_list + end + + should 'filter authors by roles to display' do + role = Role.create!(:name => 'role1') + author = fast_create(Person) + community.affiliate(author, role) + + block = ProfileMembersHeadlinesBlock.new(:limit => 3, :filtered_roles => +[role.id]) + block.stubs(:owner).returns(community) + community.members.each do |member| + blog = fast_create(Blog, :profile_id => member.id) + post = fast_create(TinyMceArticle, :name => 'headlines', :profile_id => member.id, :parent_id => blog.id) + end + assert_equal [author], block.authors_list + end +end diff --git a/plugins/profile_members_headlines/test/unit/profile_members_headlines_plugin_test.rb b/plugins/profile_members_headlines/test/unit/profile_members_headlines_plugin_test.rb new file mode 100644 index 0000000..03dd07e --- /dev/null +++ b/plugins/profile_members_headlines/test/unit/profile_members_headlines_plugin_test.rb @@ -0,0 +1,41 @@ +require 'test_helper' + +class ProfileMembersHeadlinesPluginTest < ActiveSupport::TestCase + + include Noosfero::Plugin::HotSpot + + def setup + @environment = fast_create(Environment) + @environment.enable_plugin(ProfileMembersHeadlinesPlugin) + end + attr_accessor :environment + + should 'has a name' do + assert_not_equal Noosfero::Plugin.plugin_name, ProfileMembersHeadlinesPlugin.plugin_name + end + + should 'describe itself' do + assert_not_equal Noosfero::Plugin.plugin_description, ProfileMembersHeadlinesPlugin.plugin_description + end + + should 'return ProfileMembersHeadlinesBlock in extra_blocks class method' do + assert ProfileMembersHeadlinesPlugin.extra_blocks.keys.include?(ProfileMembersHeadlinesBlock) + end + + should 'ProfileMembersHeadlinesBlock not available for environment' do + assert_not_includes plugins.dispatch(:extra_blocks, :type => Environment), ProfileMembersHeadlinesBlock + end + + should 'ProfileMembersHeadlinesBlock not available for people' do + assert_not_includes plugins.dispatch(:extra_blocks, :type => Person), ProfileMembersHeadlinesBlock + end + + should "ProfileMembersHeadlinesBlock be available for community" do + assert_includes plugins.dispatch(:extra_blocks, :type => Community), ProfileMembersHeadlinesBlock + end + + should 'has stylesheet' do + assert ProfileMembersHeadlinesPlugin.new.stylesheet? + end + +end diff --git a/plugins/profile_members_headlines/views/blocks/headlines.html.erb b/plugins/profile_members_headlines/views/blocks/headlines.html.erb new file mode 100644 index 0000000..0ca0d70 --- /dev/null +++ b/plugins/profile_members_headlines/views/blocks/headlines.html.erb @@ -0,0 +1,39 @@ +<%= block_title(block.title) %> + +<% unless members.empty? %> +
+ <% members.each do |member| %> +
+ <% headline = member.headline %> + <%= link_to_profile(profile_image(member, :big) + content_tag(:p, member.short_name), member.identifier, {:class => 'author'}) %> +
+

<%= link_to(headline.title, headline.url, :class => 'title') %>

+
+ <%= headline.short_lead %> +
+
+ <%= show_date(headline.published_at) %> +
+
+ <%= headline.tags.map { |t| link_to(t, :controller => 'profile', :profile => member.identifier, :action => 'tags', :id => t.name ) }.join("\n") %> +
+
+
+ <% end %> +
+ <% if block.navigation %> +
+
+ <% end %> + + +<% else %> + <%= _('No headlines to be shown.') %> +<% end %> + diff --git a/plugins/profile_members_headlines/views/box_organizer/_profile_members_headlines_block.html.erb b/plugins/profile_members_headlines/views/box_organizer/_profile_members_headlines_block.html.erb new file mode 100644 index 0000000..2967c06 --- /dev/null +++ b/plugins/profile_members_headlines/views/box_organizer/_profile_members_headlines_block.html.erb @@ -0,0 +1,13 @@ +
+ + <%= 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]}) %> + + <%= labelled_form_field check_box(:block, :navigation) + _('Display navigation buttons'), '' %> + <%= labelled_form_field _('Limit of headlines'), text_field(:block, :limit, :size => 3) %> + + <%= label :block, :filtered_roles, _('Choose which roles should be displayed:'), :class => 'formlabel' %> + + <% Profile::Roles.organization_member_roles(environment).each do |role| %> + <%= labelled_check_box(role.name, 'block[filtered_roles][]', role.id, @block.filtered_roles.include?(role.id)) %> + <% end %> +
diff --git a/plugins/profile_members_headlines/views/profile_design b/plugins/profile_members_headlines/views/profile_design new file mode 120000 index 0000000..1b8d625 --- /dev/null +++ b/plugins/profile_members_headlines/views/profile_design @@ -0,0 +1 @@ +box_organizer/ \ No newline at end of file diff --git a/test/unit/organization_test.rb b/test/unit/organization_test.rb index 4ae18d1..d3d2cc3 100644 --- a/test/unit/organization_test.rb +++ b/test/unit/organization_test.rb @@ -383,6 +383,33 @@ class OrganizationTest < ActiveSupport::TestCase assert !organization.errors[:cnpj.to_s].present? end + should 'get members by role' do + community = fast_create(Community) + role1 = Role.create!(:name => 'role1') + person1 = fast_create(Person) + community.affiliate(person1, role1) + role2 = Role.create!(:name => 'role2') + person2 = fast_create(Person) + community.affiliate(person2, role2) + + assert_equal [person1], community.members_by_role([role1]) + end + + should 'get members by more than one role' do + community = fast_create(Community) + role1 = Role.create!(:name => 'role1') + person1 = fast_create(Person) + community.affiliate(person1, role1) + role2 = Role.create!(:name => 'role2') + person2 = fast_create(Person) + community.affiliate(person2, role2) + role3 = Role.create!(:name => 'role3') + person3 = fast_create(Person) + community.affiliate(person3, role3) + + assert_equal [person2, person3], community.members_by_role([role2, role3]) + end + should 'return members by role in a json format' do organization = fast_create(Organization) p1 = create_user('person-1').person -- libgit2 0.21.2