Commit 9b87b01fa706c63b94e19ddc690a0dc302f98ebb
1 parent
d74aa7ba
Exists in
master
and in
29 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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 %> |