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 @@ |
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 %> | ... | ... |