Commit cb67a972189432ac6d5d0b1e9b3ef13f9d3cff40

Authored by Daniela Feitosa
Committed by Antonio Terceiro
1 parent d2c9927d

ActionItem904: removing unpublished posts from blogs and feeds

* For blog owner, unpublished articles are listed with hachures and opacity
app/helpers/blog_helper.rb
@@ -14,4 +14,25 @@ module BlogHelper @@ -14,4 +14,25 @@ module BlogHelper
14 _('Edit blog') 14 _('Edit blog')
15 end 15 end
16 16
  17 + def list_posts(user, articles)
  18 + pagination = will_paginate(articles, {
  19 + :param_name => 'npage',
  20 + :prev_label => _('« Newer posts'),
  21 + :next_label => _('Older posts »')
  22 + })
  23 + content = []
  24 + articles.map{ |i|
  25 + css_add = ''
  26 + if i.published? || (user==i.profile)
  27 + css_add = '-not-published' if !i.published?
  28 + content << content_tag('div', display_post(i), :class => 'blog-post' + css_add, :id => "post-#{i.id}")
  29 + end
  30 + }
  31 + content.join("\n") + (pagination or '')
  32 + end
  33 +
  34 + def display_post(article)
  35 + article_title(article) + content_tag('p', article.to_html) +
  36 + content_tag('p', link_to( number_of_comments(article), article.url.merge(:form => 'opened', :anchor => 'comment_form') ), :class => 'metadata')
  37 + end
17 end 38 end
app/helpers/content_viewer_helper.rb
1 module ContentViewerHelper 1 module ContentViewerHelper
2 2
3 include GetText 3 include GetText
  4 + include BlogHelper
4 5
5 def number_of_comments(article) 6 def number_of_comments(article)
6 n = article.comments.size 7 n = article.comments.size
@@ -24,37 +25,10 @@ module ContentViewerHelper @@ -24,37 +25,10 @@ module ContentViewerHelper
24 title 25 title
25 end 26 end
26 27
27 - def list_posts(articles)  
28 - pagination = will_paginate(articles, {  
29 - :param_name => 'npage',  
30 - :page_links => false,  
31 - :prev_label => _('Newer posts &raquo;'),  
32 - :next_label => _('&laquo; Older posts')  
33 - })  
34 - articles.map{ |i| content_tag('div', display_post(i), :class => 'blog-post', :id => "post-#{i.id}") }.join("\n") +  
35 - (pagination or '')  
36 - end  
37 -  
38 - def display_post(article)  
39 - article_title(article) + content_tag('p', article.to_html) +  
40 - content_tag('p', link_to( number_of_comments(article), article.url.merge(:form => 'opened', :anchor => 'comment_form') ), :class => 'metadata')  
41 - end  
42 -  
43 def article_to_html(article) 28 def article_to_html(article)
44 - content = article.to_html 29 + content = article.to_html(:page => params[:npage])
45 return self.instance_eval(&content) if content.kind_of?(Proc) 30 return self.instance_eval(&content) if content.kind_of?(Proc)
46 -  
47 - if article.blog?  
48 - children = if article.filter and article.filter[:year] and article.filter[:month]  
49 - filter_date = DateTime.parse("#{article.filter[:year]}-#{article.filter[:month]}-01")  
50 - article.posts.paginate :page => params[:npage], :per_page => article.posts_per_page, :conditions => [ 'created_at between ? and ?', filter_date, filter_date + 1.month - 1.day ]  
51 - else  
52 - article.posts.paginate :page => params[:npage], :per_page => article.posts_per_page  
53 - end  
54 - content + (children.compact.empty? ? content_tag('em', _('(no posts)')) : list_posts(children))  
55 - else  
56 - content  
57 - end 31 + content
58 end 32 end
59 33
60 end 34 end
app/models/article.rb
@@ -127,7 +127,7 @@ class Article &lt; ActiveRecord::Base @@ -127,7 +127,7 @@ class Article &lt; ActiveRecord::Base
127 # The implementation in this class just provides the +body+ attribute as the 127 # The implementation in this class just provides the +body+ attribute as the
128 # HTML. Other article types can override this method to provide customized 128 # HTML. Other article types can override this method to provide customized
129 # views of themselves. 129 # views of themselves.
130 - def to_html 130 + def to_html(options = {})
131 body 131 body
132 end 132 end
133 133
app/models/blog.rb
@@ -28,8 +28,8 @@ class Blog &lt; Folder @@ -28,8 +28,8 @@ class Blog &lt; Folder
28 28
29 # FIXME isn't this too much including just to be able to generate some HTML? 29 # FIXME isn't this too much including just to be able to generate some HTML?
30 include ActionView::Helpers::TagHelper 30 include ActionView::Helpers::TagHelper
31 - def to_html  
32 - content_tag('div', body) + tag('hr') 31 + def to_html(options = {})
  32 + posts_list(options[:page])
33 end 33 end
34 34
35 def folder? 35 def folder?
@@ -52,4 +52,16 @@ class Blog &lt; Folder @@ -52,4 +52,16 @@ class Blog &lt; Folder
52 end 52 end
53 end 53 end
54 54
  55 + def posts_list(npage)
  56 + article = self
  57 + children = if filter and filter[:year] and filter[:month]
  58 + filter_date = DateTime.parse("#{filter[:year]}-#{filter[:month]}-01")
  59 + posts.paginate :page => npage, :per_page => posts_per_page, :conditions => [ 'created_at between ? and ?', filter_date, filter_date + 1.month - 1.day ]
  60 + else
  61 + posts.paginate :page => npage, :per_page => posts_per_page
  62 + end
  63 + lambda do
  64 + render :file => 'content_viewer/blog_page', :locals => {:article => article, :children => children}
  65 + end
  66 + end
55 end 67 end
app/models/enterprise_homepage.rb
@@ -20,7 +20,7 @@ class EnterpriseHomepage &lt; Article @@ -20,7 +20,7 @@ class EnterpriseHomepage &lt; Article
20 include EnterpriseHomepageHelper 20 include EnterpriseHomepageHelper
21 include CatalogHelper 21 include CatalogHelper
22 22
23 - def to_html 23 + def to_html(options ={})
24 products = self.profile.products 24 products = self.profile.products
25 display_profile_info(self.profile) + content_tag('div', self.body || '') + 25 display_profile_info(self.profile) + content_tag('div', self.body || '') +
26 (self.profile.environment.enabled?('disable_products_for_enterprises') ? '' : display_products_list(self.profile, products)) 26 (self.profile.environment.enabled?('disable_products_for_enterprises') ? '' : display_products_list(self.profile, products))
app/models/event.rb
@@ -58,7 +58,7 @@ class Event &lt; Article @@ -58,7 +58,7 @@ class Event &lt; Article
58 include ActionController::UrlWriter 58 include ActionController::UrlWriter
59 include DatesHelper 59 include DatesHelper
60 60
61 - def to_html 61 + def to_html(options = {})
62 62
63 result = '' 63 result = ''
64 html = Builder::XmlMarkup.new(:target => result) 64 html = Builder::XmlMarkup.new(:target => result)
app/models/folder.rb
@@ -34,7 +34,7 @@ class Folder &lt; Article @@ -34,7 +34,7 @@ class Folder &lt; Article
34 include FolderHelper 34 include FolderHelper
35 include DatesHelper 35 include DatesHelper
36 36
37 - def to_html 37 + def to_html(options = {})
38 send(view_as) 38 send(view_as)
39 end 39 end
40 40
app/models/rss_feed.rb
@@ -50,7 +50,7 @@ class RssFeed &lt; Article @@ -50,7 +50,7 @@ class RssFeed &lt; Article
50 validates_inclusion_of :feed_item_description, :in => [ 'body', 'abstract' ], :if => :feed_item_description 50 validates_inclusion_of :feed_item_description, :in => [ 'body', 'abstract' ], :if => :feed_item_description
51 51
52 # TODO 52 # TODO
53 - def to_html 53 + def to_html(options = {})
54 end 54 end
55 55
56 # RSS feeds have type =text/xml=. 56 # RSS feeds have type =text/xml=.
@@ -61,7 +61,7 @@ class RssFeed &lt; Article @@ -61,7 +61,7 @@ class RssFeed &lt; Article
61 include ActionController::UrlWriter 61 include ActionController::UrlWriter
62 def fetch_articles 62 def fetch_articles
63 if parent && parent.blog? 63 if parent && parent.blog?
64 - return parent.posts.find(:all, :limit => self.limit, :order => 'id desc') 64 + return parent.posts.find(:all, :conditions => ['published = ?', true], :limit => self.limit, :order => 'id desc')
65 end 65 end
66 66
67 articles = 67 articles =
app/models/textile_article.rb
@@ -8,7 +8,7 @@ class TextileArticle &lt; TextArticle @@ -8,7 +8,7 @@ class TextileArticle &lt; TextArticle
8 _('Accessible alternative for visually impaired users.') 8 _('Accessible alternative for visually impaired users.')
9 end 9 end
10 10
11 - def to_html 11 + def to_html(options ={})
12 RedCloth.new(self.body|| '').to_html 12 RedCloth.new(self.body|| '').to_html
13 end 13 end
14 14
app/models/uploaded_file.rb
@@ -50,7 +50,7 @@ class UploadedFile &lt; Article @@ -50,7 +50,7 @@ class UploadedFile &lt; Article
50 # FIXME isn't this too much including just to be able to generate some HTML? 50 # FIXME isn't this too much including just to be able to generate some HTML?
51 include ActionView::Helpers::TagHelper 51 include ActionView::Helpers::TagHelper
52 52
53 - def to_html 53 + def to_html(options = {})
54 tag('img', :src => public_filename, :class => css_class_name, :style => 'max-width: 100%') if image? 54 tag('img', :src => public_filename, :class => css_class_name, :style => 'max-width: 100%') if image?
55 end 55 end
56 56
app/views/content_viewer/blog_page.rhtml 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +<div><%= article.body %></div>
  2 +<hr/>
  3 +<%= (children.compact.empty? ? content_tag('em', _('(no posts)')) : list_posts(user, children)) %>
  4 +
  5 +
public/stylesheets/article.css
@@ -202,10 +202,38 @@ @@ -202,10 +202,38 @@
202 202
203 #content #article .pagination .prev_page { 203 #content #article .pagination .prev_page {
204 position: absolute; 204 position: absolute;
205 - right: 0; 205 + left: 0;
206 } 206 }
207 207
208 #content #article .pagination .next_page { 208 #content #article .pagination .next_page {
209 position: absolute; 209 position: absolute;
210 - left: 0; 210 + right: 0;
  211 +}
  212 +.msie6 #content #article .pagination .prev_page,
  213 +.msie6 #content #article .pagination .next_page {
  214 + position: relative;
  215 + display: inline;
  216 +}
  217 +
  218 +/* NOT PUBLISHED BLOG POSTS */
  219 +
  220 +.blog-post-not-published {
  221 + background: url(/images/hachure.png);
  222 + opacity: 0.25;
  223 + filter: alpha(opacity=25);
  224 + zoom: 1;
  225 +}
  226 +
  227 +.blog-post-not-published a {
  228 + text-decoration: none;
  229 +}
  230 +
  231 +#content .blog-post-not-published .created-at {
  232 + text-align: left;
  233 +}
  234 +
  235 +.blog-post-not-published .metadata {
  236 + display: block;
  237 + text-align: center;
  238 + font-size: small;
211 } 239 }
test/unit/blog_helper_test.rb
@@ -6,12 +6,64 @@ class BlogHelperTest &lt; Test::Unit::TestCase @@ -6,12 +6,64 @@ class BlogHelperTest &lt; Test::Unit::TestCase
6 6
7 def setup 7 def setup
8 stubs(:show_date).returns('') 8 stubs(:show_date).returns('')
  9 + @environment = Environment.default
9 @profile = create_user('blog_helper_test').person 10 @profile = create_user('blog_helper_test').person
  11 + @blog = Blog.create!(:profile => profile, :name => 'Blog test')
10 end 12 end
  13 +
11 attr :profile 14 attr :profile
  15 + attr :blog
  16 +
  17 + def _(s); s; end
  18 +
  19 + should 'list published posts with class blog-post' do
  20 + blog.children << published_post = TextileArticle.create!(:name => 'Post', :profile => profile, :parent => blog, :published => true)
12 21
13 - should 'add real tests' do  
14 - assert true 22 + expects(:display_post).with(anything).returns('POST')
  23 + expects(:content_tag).with('div', 'POST', :class => 'blog-post', :id => "post-#{published_post.id}").returns('RESULT')
  24 +
  25 + assert_equal 'RESULT', list_posts(profile, blog.posts)
15 end 26 end
16 27
  28 + should 'list unpublished posts to owner with a different class' do
  29 + blog.children << unpublished_post = TextileArticle.create!(:name => 'Post', :profile => profile, :parent => blog, :published => false)
  30 +
  31 + expects(:display_post).with(anything).returns('POST')
  32 + expects(:content_tag).with('div', 'POST', :class => 'blog-post-not-published', :id => "post-#{unpublished_post.id}").returns('RESULT')
  33 +
  34 + assert_equal 'RESULT', list_posts(profile, blog.posts)
  35 + end
  36 +
  37 + should 'not list unpublished posts to not owner' do
  38 + blog.children << unpublished_post = TextileArticle.create!(:name => 'First post', :profile => profile, :parent => blog, :published => false)
  39 +
  40 + blog.children << published_post = TextileArticle.create!(:name => 'Second post', :profile => profile, :parent => blog, :published => true)
  41 +
  42 + expects(:display_post).with(anything).returns('POST')
  43 + expects(:content_tag).with('div', 'POST', :class => 'blog-post', :id => "post-#{published_post.id}").returns('RESULT')
  44 + expects(:content_tag).with('div', 'POST', :class => 'blog-post-not-published', :id => "post-#{unpublished_post.id}").never
  45 +
  46 + assert_equal 'RESULT', list_posts(nil, blog.posts)
  47 + end
  48 +
  49 + should 'display post' do
  50 + blog.children << article = TextileArticle.create!(:name => 'Second post', :profile => profile, :parent => blog, :published => true)
  51 + expects(:article_title).with(article).returns('TITLE')
  52 + expects(:content_tag).with('p', article.to_html).returns(' TO_HTML')
  53 + expects(:number_of_comments).with(article).returns('NUMBER OF COMMENTS')
  54 + expects(:content_tag).with('p', 'NUMBER OF COMMENTS', anything).returns(' COMMENTS').at_least_once
  55 +
  56 + assert_equal 'TITLE TO_HTML COMMENTS', display_post(article)
  57 + end
  58 +
  59 + def will_paginate(arg1, arg2)
  60 + end
  61 +
  62 + def link_to(content, url)
  63 + content
  64 + end
  65 +
  66 + def content_tag(tag, content, options = {})
  67 + "<#{tag}>#{content}</#{tag}>"
  68 + end
17 end 69 end
test/unit/content_viewer_helper_test.rb
@@ -56,7 +56,7 @@ class ContentViewerHelperTest &lt; Test::Unit::TestCase @@ -56,7 +56,7 @@ class ContentViewerHelperTest &lt; Test::Unit::TestCase
56 should 'not list feed article' do 56 should 'not list feed article' do
57 profile.articles << Blog.new(:name => 'Blog test') 57 profile.articles << Blog.new(:name => 'Blog test')
58 assert_includes profile.blog.children.map{|i| i.class}, RssFeed 58 assert_includes profile.blog.children.map{|i| i.class}, RssFeed
59 - result = list_posts(profile.blog.posts) 59 + result = list_posts(nil, profile.blog.posts)
60 assert_no_match /feed/, result 60 assert_no_match /feed/, result
61 end 61 end
62 62
@@ -75,10 +75,11 @@ class ContentViewerHelperTest &lt; Test::Unit::TestCase @@ -75,10 +75,11 @@ class ContentViewerHelperTest &lt; Test::Unit::TestCase
75 75
76 self.stubs(:params).returns({:npage => nil}) 76 self.stubs(:params).returns({:npage => nil})
77 77
  78 + expects(:render).with(:file => 'content_viewer/blog_page', :locals => {:article => blog, :children => [nov]}).returns("BLI")
  79 +
78 result = article_to_html(blog) 80 result = article_to_html(blog)
79 81
80 - assert_match /November post/, result  
81 - assert_no_match /September post/, result 82 + assert_equal 'BLI', result
82 end 83 end
83 84
84 end 85 end
test/unit/rss_feed_test.rb
@@ -121,6 +121,20 @@ class RssFeedTest &lt; Test::Unit::TestCase @@ -121,6 +121,20 @@ class RssFeedTest &lt; Test::Unit::TestCase
121 assert_equal [posts[5], posts[4], posts[3], posts[2], posts[1]], feed.fetch_articles 121 assert_equal [posts[5], posts[4], posts[3], posts[2], posts[1]], feed.fetch_articles
122 end 122 end
123 123
  124 + should 'list only published posts from blog' do
  125 + profile = create_user('testuser').person
  126 + blog = Blog.create(:name => 'blog', :profile => profile)
  127 + posts = []
  128 + 5.times do |i|
  129 + posts << TextArticle.create!(:name => "post #{i}", :profile => profile, :parent => blog)
  130 + end
  131 + posts[0].published = false
  132 + posts[0].save!
  133 +
  134 + assert_equal [posts[4], posts[3], posts[2], posts[1]], blog.feed.fetch_articles
  135 + end
  136 +
  137 +
124 should 'provide link to profile' do 138 should 'provide link to profile' do
125 profile = create_user('testuser').person 139 profile = create_user('testuser').person
126 feed = RssFeed.new(:name => 'testfeed') 140 feed = RssFeed.new(:name => 'testfeed')