Commit 9b87b01fa706c63b94e19ddc690a0dc302f98ebb
1 parent
d74aa7ba
Exists in
staging
and in
26 other branches
recent_content_plugin: display the last articles published in your blog.
(ActionItem2848) Signed-off-by: David Carlos <ddavidcarlos1392@gmail.com> Signed-off-by: Gabriela Navarro <navarro1703@gmail.com> Signed-off-by: Marcos Ramos <ms.ramos@outlook.com> Signed-off-by: Valessio Brito <contato@valessiobrito.com.br>
Showing
12 changed files
with
436 additions
and
0 deletions
Show diff stats
| ... | ... | @@ -0,0 +1,69 @@ |
| 1 | +README - RecentContent (RecentContent Plugin) | |
| 2 | +================================ | |
| 3 | + | |
| 4 | +RecentContent is a plugin that provides a blog which displays the content posted inside a blog choosen by the user. | |
| 5 | + | |
| 6 | +The RecentContent block will be available for all layout columns of communities, people, enterprises and environments. | |
| 7 | + | |
| 8 | +The articles posted from the choosen blog are displayed as a list with a link for the title and optionally the abstract/lead content. | |
| 9 | + | |
| 10 | +If the choosen blog has a cover image, the user can configure the block to show the same image displayed on that blog. | |
| 11 | + | |
| 12 | +Galleries and folders are not displayed in this block. | |
| 13 | + | |
| 14 | +INSTALL | |
| 15 | +======= | |
| 16 | + | |
| 17 | +Enable Plugin | |
| 18 | +------------- | |
| 19 | + | |
| 20 | +Also, you need to enable RecentContent Plugin at your Noosfero: | |
| 21 | + | |
| 22 | +cd <your_noosfero_dir> | |
| 23 | +./script/noosfero-plugins enable recent_content | |
| 24 | + | |
| 25 | +Active Plugin | |
| 26 | +------------- | |
| 27 | + | |
| 28 | +As a Noosfero administrator user, go to administrator panel: | |
| 29 | + | |
| 30 | +- Click on "Enable/disable plugins" option | |
| 31 | +- Click on "Recent Content Plugin" check-box | |
| 32 | + | |
| 33 | +DEVELOPMENT | |
| 34 | +=========== | |
| 35 | + | |
| 36 | +Get the Recent Content (Noosfero with Recent Content Plugin) development repository: | |
| 37 | + | |
| 38 | +$ git clone https://github.com/fga-unb/noosfero/tree/AI2848-block_recent_articles | |
| 39 | + | |
| 40 | +Running RecentContent tests | |
| 41 | +-------------------- | |
| 42 | + | |
| 43 | +$ rake test:noosfero_plugins:recent_content | |
| 44 | + | |
| 45 | + | |
| 46 | +Get Involved | |
| 47 | +============ | |
| 48 | + | |
| 49 | +If you found any bug and/or want to collaborate, please send an e-mail to contato@valessiobrito.com.br | |
| 50 | + | |
| 51 | +LICENSE | |
| 52 | +======= | |
| 53 | + | |
| 54 | +Copyright (c) The Author developers. | |
| 55 | + | |
| 56 | +See Noosfero license. | |
| 57 | + | |
| 58 | + | |
| 59 | +AUTHORS | |
| 60 | +======= | |
| 61 | + David Carlos (ddavidcarlos1392 at gmail.com) | |
| 62 | + Gabriela Navarro (navarro1703 at gmail.com) | |
| 63 | + Marcos Ramos (ms.ramos at outlook.com) | |
| 64 | + Valessio Brito (contato at valessiobrito.com.br) | |
| 65 | + | |
| 66 | +ACKNOWLEDGMENTS | |
| 67 | +=============== | |
| 68 | + | |
| 69 | +The author have been supported by FGA - UnB and Lappis | ... | ... |
plugins/recent_content/features/add_recent_content.feature
0 → 100644
| ... | ... | @@ -0,0 +1,91 @@ |
| 1 | +Feature: | |
| 2 | + As a logged user | |
| 3 | + I want to manage a recent content block | |
| 4 | + | |
| 5 | +Background: | |
| 6 | + Given the following users | |
| 7 | + | login | name | | |
| 8 | + | joaosilva | Joao Silva | | |
| 9 | + And the following plugin | |
| 10 | + | klass | | |
| 11 | + | RecentContent | | |
| 12 | + And plugin RecentContent is enabled on environment | |
| 13 | + And the following blocks | |
| 14 | + | owner | type | | |
| 15 | + | joaosilva | RecentContentBlock | | |
| 16 | + And the following articles | |
| 17 | + | owner | parent | name | body | abstract | | |
| 18 | + | joaosilva | JSilva blog | post #1 | Primeiro post do joao silva | Resumo 1 | | |
| 19 | + | joaosilva | JSilva blog | post #2 | Segundo post do joao silva | Resumo 2 | | |
| 20 | + | joaosilva | JSilva blog | post #3 | Terceiro post do joao silva | Resumo 3 | | |
| 21 | + | joaosilva | JSilva blog | post #4 | Quarto post do joao silva | Resumo 4 | | |
| 22 | + | joaosilva | JSilva blog | post #5 | Quinto post do joao silva | Resumo 5 | | |
| 23 | + | joaosilva | JSilva blog | post #6 | Sexto post do joao silva | Resumo 6 | | |
| 24 | + And I am logged in as "joaosilva" | |
| 25 | + Given I go to joaosilva's control panel | |
| 26 | + And I follow "Edit sideboxes" | |
| 27 | + And I follow "Add a block" | |
| 28 | + And I choose "Recent content" | |
| 29 | + And I press "Add" | |
| 30 | + | |
| 31 | + Scenario: the block is being displayed | |
| 32 | + Then I should see "This is the recent content block. Please edit it to show the content you want." | |
| 33 | + | |
| 34 | + Scenario: a user should be redirected to the post page when the link is clicked | |
| 35 | + When I follow "Edit" within ".recent-content-block" | |
| 36 | + And I select "JSilva blog" from "Choose which blog should be displayed" | |
| 37 | + And I select "Title only" from "Choose how the content should be displayed" | |
| 38 | + And I fill in "Choose how many items will be displayed" with "3" | |
| 39 | + And I press "Save" | |
| 40 | + And I follow "post #4" within ".recent-content-block" | |
| 41 | + Then I should be on /joaosilva/jsilva-blog/post-4 | |
| 42 | + | |
| 43 | + Scenario: a user should be redirected to the blog page when the "view all" is clicked | |
| 44 | + When I follow "Edit" within ".recent-content-block" | |
| 45 | + And I select "JSilva blog" from "Choose which blog should be displayed" | |
| 46 | + And I select "Title only" from "Choose how the content should be displayed" | |
| 47 | + And I fill in "Choose how many items will be displayed" with "2" | |
| 48 | + And I press "Save" | |
| 49 | + And I follow "View All" | |
| 50 | + Then I should be on /joaosilva/jsilva-blog | |
| 51 | + | |
| 52 | + Scenario: a user should see only titles if the block was configured for it | |
| 53 | + When I follow "Edit" within ".recent-content-block" | |
| 54 | + And I select "JSilva blog" from "Choose which blog should be displayed" | |
| 55 | + And I select "Title only" from "Choose how the content should be displayed" | |
| 56 | + And I fill in "Choose how many items will be displayed" with "3" | |
| 57 | + And I press "Save" | |
| 58 | + Then I should see "post #6" within ".recent-content-block" | |
| 59 | + | |
| 60 | + Scenario: a user should see titles and abstract if the block was configured for it | |
| 61 | + When I follow "Edit" within ".recent-content-block" | |
| 62 | + And I select "JSilva blog" from "Choose which blog should be displayed" | |
| 63 | + And I select "Title and abstract" from "Choose how the content should be displayed" | |
| 64 | + And I fill in "Choose how many items will be displayed" with "6" | |
| 65 | + And I press "Save" | |
| 66 | + Then I should see "Resumo 5" within ".recent-content-block" | |
| 67 | + | |
| 68 | + Scenario: a user should see full content if the block was configured for it | |
| 69 | + When I follow "Edit" within ".recent-content-block" | |
| 70 | + And I select "JSilva blog" from "Choose which blog should be displayed" | |
| 71 | + And I select "Full content" from "Choose how the content should be displayed" | |
| 72 | + And I fill in "Choose how many items will be displayed" with "6" | |
| 73 | + And I press "Save" | |
| 74 | + Then I should see "Quinto post do joao silva" within ".recent-content-block" | |
| 75 | + | |
| 76 | + # the step for attaching a file on the input only works with capybara 1.1.2, but it requires rails 1.9.3 | |
| 77 | + @selenium-fixme | |
| 78 | + Scenario: the user should see the blog cover image if configured and the image is available | |
| 79 | + Given I go to joaosilva's control panel | |
| 80 | + And I follow "Configure blog" | |
| 81 | + And I attach the file "public/images/rails.png" to "Uploaded data" | |
| 82 | + And I press "Save" | |
| 83 | + When I go to joaosilva's control panel | |
| 84 | + And I follow "Edit sideboxes" | |
| 85 | + And I follow "Edit" within ".recent-content-block" | |
| 86 | + And I select "JSilva blog" from "Choose which blog should be displayed" | |
| 87 | + And I select "Title only" from "Choose how the content should be displayed" | |
| 88 | + And I fill in "Choose how many items will be displayed" with "3" | |
| 89 | + And I check "Display blog cover image" | |
| 90 | + And I press "Save" | |
| 91 | + Then there should be a div with class "recent-content-cover" | ... | ... |
| ... | ... | @@ -0,0 +1,58 @@ |
| 1 | +class RecentContentBlock < Block | |
| 2 | + | |
| 3 | + settings_items :presentation_mode, :type => String, :default => 'title_only' | |
| 4 | + settings_items :total_items, :type => Integer, :default => 5 | |
| 5 | + settings_items :show_blog_picture, :type => :boolean, :default => false | |
| 6 | + settings_items :selected_folder, :type => Integer | |
| 7 | + | |
| 8 | + VALID_CONTENT = ['RawHTMLArticle', 'TextArticle', 'TextileArticle', 'TinyMceArticle'] | |
| 9 | + | |
| 10 | + def self.description | |
| 11 | + _('Recent content') | |
| 12 | + end | |
| 13 | + | |
| 14 | + def help | |
| 15 | + _('This block displays all articles inside the blog you choose. You can edit the block to select which of your blogs is going to be displayed in the block.') | |
| 16 | + end | |
| 17 | + | |
| 18 | + def articles_of_folder(folder, limit) | |
| 19 | + holder.articles.all(:conditions => {:type => VALID_CONTENT, :parent_id => folder.id}, | |
| 20 | + :order => 'created_at DESC', | |
| 21 | + :limit => limit ) | |
| 22 | + end | |
| 23 | + | |
| 24 | + def holder | |
| 25 | + return nil if self.box.nil? || self.box.owner.nil? | |
| 26 | + if self.box.owner.kind_of?(Environment) | |
| 27 | + return nil if self.box.owner.portal_community.nil? | |
| 28 | + self.box.owner.portal_community | |
| 29 | + else | |
| 30 | + self.box.owner | |
| 31 | + end | |
| 32 | + end | |
| 33 | + | |
| 34 | + def parents | |
| 35 | + selected = self.holder.articles.all(:conditions => {:type => 'Blog'}) | |
| 36 | + end | |
| 37 | + | |
| 38 | + def root | |
| 39 | + unless self.selected_folder.nil? | |
| 40 | + holder.articles.where(:id => self.selected_folder).first | |
| 41 | + end | |
| 42 | + end | |
| 43 | + | |
| 44 | + include ActionController::UrlWriter | |
| 45 | + include DatesHelper | |
| 46 | + | |
| 47 | + def content(args={}) | |
| 48 | + block = self | |
| 49 | + lambda do | |
| 50 | + render :file => 'blocks/recent_content_block', :locals => {:root => block.root, :block => block} | |
| 51 | + end | |
| 52 | + end | |
| 53 | + | |
| 54 | + def mode?(attr) | |
| 55 | + attr == self.presentation_mode | |
| 56 | + end | |
| 57 | + | |
| 58 | +end | ... | ... |
| ... | ... | @@ -0,0 +1,27 @@ |
| 1 | +require_dependency File.dirname(__FILE__) + '/recent_content_block' | |
| 2 | + | |
| 3 | +class RecentContentPlugin < Noosfero::Plugin | |
| 4 | + | |
| 5 | + def self.plugin_name | |
| 6 | + "Recent Content Plugin" | |
| 7 | + end | |
| 8 | + | |
| 9 | + def self.plugin_description | |
| 10 | + _("A plugin that adds a block where you can display the content of any of your blogs.") | |
| 11 | + end | |
| 12 | + | |
| 13 | + def self.extra_blocks | |
| 14 | + { | |
| 15 | + RecentContentBlock => {:position => ['1','2','3'] } | |
| 16 | + } | |
| 17 | + end | |
| 18 | + | |
| 19 | + def self.has_admin_url? | |
| 20 | + false | |
| 21 | + end | |
| 22 | + | |
| 23 | + def stylesheet? | |
| 24 | + true | |
| 25 | + end | |
| 26 | + | |
| 27 | +end | ... | ... |
88 Bytes
| ... | ... | @@ -0,0 +1,35 @@ |
| 1 | +#content .recent-content-block { | |
| 2 | + padding: 10px 0px 10px 10px; | |
| 3 | + overflow: hidden; | |
| 4 | +} | |
| 5 | +.recent-content-block ul { | |
| 6 | + margin: 0px; | |
| 7 | + padding: 0px 0px 0px 20px; | |
| 8 | +} | |
| 9 | +.recent-content-block li { | |
| 10 | + margin: 0px; | |
| 11 | + padding: 0px; | |
| 12 | +} | |
| 13 | +.recent-content-block a { | |
| 14 | + text-decoration: none; | |
| 15 | +} | |
| 16 | +.recent-content-block .block-footer-content { | |
| 17 | + font-size: 10px; | |
| 18 | +} | |
| 19 | +.recent-content-block .block-footer-content a:hover { | |
| 20 | + text-decoration: underline; | |
| 21 | +} | |
| 22 | +.recent-content-block li { | |
| 23 | + list-style-image: url('images/li-recent.gif'); | |
| 24 | + padding: 5px 0px; | |
| 25 | +} | |
| 26 | +.recent-content-cover { | |
| 27 | + overflow: hidden; | |
| 28 | + display: block; | |
| 29 | + width: 100%; | |
| 30 | + max-height: 90px; | |
| 31 | +} | |
| 32 | +.recent-content-cover img { | |
| 33 | + width: 100%; | |
| 34 | +} | |
| 35 | + | ... | ... |
| ... | ... | @@ -0,0 +1 @@ |
| 1 | +require File.dirname(__FILE__) + '/../../../test/test_helper' | ... | ... |
plugins/recent_content/test/unit/recent_content_block_test.rb
0 → 100644
| ... | ... | @@ -0,0 +1,75 @@ |
| 1 | +require File.dirname(__FILE__) + '/../test_helper' | |
| 2 | +class RecentContentBlockTest < ActiveSupport::TestCase | |
| 3 | + | |
| 4 | + INVALID_KIND_OF_ARTICLE = [EnterpriseHomepage, RssFeed, UploadedFile, Gallery, Folder, Blog, Forum] | |
| 5 | + VALID_KIND_OF_ARTICLE = [RawHTMLArticle, TextArticle, TextileArticle, TinyMceArticle] | |
| 6 | + | |
| 7 | + should 'describe itself' do | |
| 8 | + assert_not_equal Block.description, RecentContentBlock.description | |
| 9 | + end | |
| 10 | + | |
| 11 | + should 'is editable' do | |
| 12 | + block = RecentContentBlock.new | |
| 13 | + assert block.editable? | |
| 14 | + end | |
| 15 | + | |
| 16 | + should 'blog_picture be false by default' do | |
| 17 | + block = RecentContentBlock.new | |
| 18 | + assert !block.show_blog_picture | |
| 19 | + end | |
| 20 | + | |
| 21 | + should 'blog_picture is being stored and restored from database as true' do | |
| 22 | + block = RecentContentBlock.new | |
| 23 | + block.show_blog_picture = true | |
| 24 | + block.save | |
| 25 | + block.reload | |
| 26 | + | |
| 27 | + assert block.show_blog_picture | |
| 28 | + end | |
| 29 | + | |
| 30 | + should 'blog_picture is being stored and restored from database as false' do | |
| 31 | + block = RecentContentBlock.new | |
| 32 | + block.show_blog_picture = false | |
| 33 | + block.save | |
| 34 | + block.reload | |
| 35 | + | |
| 36 | + assert !block.show_blog_picture | |
| 37 | + end | |
| 38 | + | |
| 39 | + should 'root be nil for new blocks' do | |
| 40 | + block = RecentContentBlock.new | |
| 41 | + | |
| 42 | + assert block.root.nil? | |
| 43 | + end | |
| 44 | + | |
| 45 | + should 'root be a Blog when it is configured for' do | |
| 46 | + profile = create_user('testuser').person | |
| 47 | + | |
| 48 | + root = fast_create(Blog, :name => 'test-blog', :profile_id => profile.id) | |
| 49 | + | |
| 50 | + block = RecentContentBlock.new | |
| 51 | + block.stubs(:holder).returns(profile) | |
| 52 | + block.selected_folder = root.id | |
| 53 | + | |
| 54 | + assert block.root.id == root.id | |
| 55 | + end | |
| 56 | + | |
| 57 | + should 'return last articles inside a folder' do | |
| 58 | + profile = create_user('testuser').person | |
| 59 | + | |
| 60 | + Article.delete_all | |
| 61 | + | |
| 62 | + root = fast_create(Blog, :name => 'test-blog', :profile_id => profile.id) | |
| 63 | + | |
| 64 | + a1 = fast_create(TextileArticle, :name => 'article #1', :profile_id => profile.id, :parent_id => root.id) | |
| 65 | + a2 = fast_create(TextileArticle, :name => 'article #2', :profile_id => profile.id, :parent_id => root.id) | |
| 66 | + a3 = fast_create(TextileArticle, :name => 'article #3', :profile_id => profile.id, :parent_id => root.id) | |
| 67 | + | |
| 68 | + block = RecentContentBlock.new | |
| 69 | + block.stubs(:holder).returns(profile) | |
| 70 | + | |
| 71 | + assert block.articles_of_folder(root,2) == [a3, a2] | |
| 72 | + assert block.articles_of_folder(root,3) == [a3, a2, a1] | |
| 73 | + end | |
| 74 | + | |
| 75 | +end | ... | ... |
plugins/recent_content/views/blocks/recent_content_block.rhtml
0 → 100644
| ... | ... | @@ -0,0 +1,45 @@ |
| 1 | +<% unless root.nil? %> | |
| 2 | + <div id="recent-content-block"> | |
| 3 | + <% children = block.articles_of_folder(root, block.total_items)%> | |
| 4 | + <div class="recent-content"> | |
| 5 | + <%= block_title(block.title.blank? ? _("Recent content") : block.title ) %> | |
| 6 | + <% if block.show_blog_picture and !root.image.nil? %> | |
| 7 | + <div class="recent-content-cover"> | |
| 8 | + <%= image_tag(root.image.public_filename(:big)) %> | |
| 9 | + </div> | |
| 10 | + <% end %> | |
| 11 | + </div> | |
| 12 | + <% if block.mode?('title_only') %> | |
| 13 | + <div class="recent-content-title"> | |
| 14 | + <ul> | |
| 15 | + <% childr"A plugin that adds a block where you can display the content of any of your blogs"en.each do |item| %> | |
| 16 | + <li> <%= link_to(h(item.title), item.url)%></li> | |
| 17 | + <% end %> | |
| 18 | + </ul> | |
| 19 | + </div> | |
| 20 | + <% elsif block.mode?('title_and_abstract') %> | |
| 21 | + <div class="recent-content-abstract"> | |
| 22 | + <% children.each do |item| %> | |
| 23 | + <h2><%= link_to(item.title,item.url, :class => 'post-title')%></h2> | |
| 24 | + <span class="post-date"><%= show_date(item.published_at, true)%></span> | |
| 25 | + <div class="headline"><%=item.lead%></div> | |
| 26 | + <p class="highlighted-news-read-more"><%= link_to(_('Read more'), item.url) %></p> | |
| 27 | + <% end %> | |
| 28 | + </div> | |
| 29 | + <% else %> | |
| 30 | + <div class="recent-content-full"> | |
| 31 | + <% children.each do |item| %> | |
| 32 | + <h2><%= link_to(item.title,item.url, :class => 'post-title')%></h2> | |
| 33 | + <span class="post-date"><%= show_date(item.published_at, true)%></span> | |
| 34 | + <div class="headline"><%=item.body%></div> | |
| 35 | + <p class="highlighted-news-read-more"><%= link_to(_('Read more'), item.url) %></p> | |
| 36 | + <% end %> | |
| 37 | + </div> | |
| 38 | + <% end %> | |
| 39 | + <%= link_to _('View All'), :profile => profile.identifier, :controller => 'content_viewer', :action => 'view_page', :page => block.root.path %> | |
| 40 | + </div> | |
| 41 | +<% else %> | |
| 42 | + <span class="alert-block"> | |
| 43 | + <%= _('This is the recent content block. Please edit it to show the content you want.') %> | |
| 44 | + </span> | |
| 45 | +<% end %> | ... | ... |
plugins/recent_content/views/box_organizer/_recent_content_block.rhtml
0 → 100644
| ... | ... | @@ -0,0 +1,33 @@ |
| 1 | +<% blogs = @block.parents %> | |
| 2 | +<% if blogs.empty? %> | |
| 3 | + <h3><%= _('No blogs found. Please add a blog in order to configure this block.') %></h3> | |
| 4 | +<% end %> | |
| 5 | +<%= | |
| 6 | +labelled_form_field(_('Choose which blog should be displayed'), | |
| 7 | + select_tag( | |
| 8 | + 'block[selected_folder]', | |
| 9 | + options_for_select(blogs.map {|node| [node.title, node.id]}, @block.selected_folder) | |
| 10 | + ) | |
| 11 | +) | |
| 12 | +%> | |
| 13 | +<%= | |
| 14 | +labelled_form_field(_('Choose how the content should be displayed'), | |
| 15 | + select_tag( | |
| 16 | + 'block[presentation_mode]', | |
| 17 | + options_for_select( | |
| 18 | + { | |
| 19 | + _("Title only") => "title_only", | |
| 20 | + _("Title and abstract") => "title_and_abstract", | |
| 21 | + _("Full content") => "full_content" | |
| 22 | + }, | |
| 23 | + @block.presentation_mode | |
| 24 | + ) | |
| 25 | + ) | |
| 26 | +) | |
| 27 | +%> | |
| 28 | +<%= labelled_form_field(_('Choose how many items will be displayed'), | |
| 29 | + text_field_tag('block[total_items]', | |
| 30 | + @block.total_items, :size => 3, :maxlength => 5) | |
| 31 | + ) | |
| 32 | +%> | |
| 33 | +<%= labelled_check_box _('Display blog cover image'), 'block[show_blog_picture]', true, @block.show_blog_picture %> | ... | ... |