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 14 _('Edit blog')
15 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 38 end
... ...
app/helpers/content_viewer_helper.rb
1 1 module ContentViewerHelper
2 2  
3 3 include GetText
  4 + include BlogHelper
4 5  
5 6 def number_of_comments(article)
6 7 n = article.comments.size
... ... @@ -24,37 +25,10 @@ module ContentViewerHelper
24 25 title
25 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 28 def article_to_html(article)
44   - content = article.to_html
  29 + content = article.to_html(:page => params[:npage])
45 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 32 end
59 33  
60 34 end
... ...
app/models/article.rb
... ... @@ -127,7 +127,7 @@ class Article &lt; ActiveRecord::Base
127 127 # The implementation in this class just provides the +body+ attribute as the
128 128 # HTML. Other article types can override this method to provide customized
129 129 # views of themselves.
130   - def to_html
  130 + def to_html(options = {})
131 131 body
132 132 end
133 133  
... ...
app/models/blog.rb
... ... @@ -28,8 +28,8 @@ class Blog &lt; Folder
28 28  
29 29 # FIXME isn't this too much including just to be able to generate some HTML?
30 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 33 end
34 34  
35 35 def folder?
... ... @@ -52,4 +52,16 @@ class Blog &lt; Folder
52 52 end
53 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 67 end
... ...
app/models/enterprise_homepage.rb
... ... @@ -20,7 +20,7 @@ class EnterpriseHomepage &lt; Article
20 20 include EnterpriseHomepageHelper
21 21 include CatalogHelper
22 22  
23   - def to_html
  23 + def to_html(options ={})
24 24 products = self.profile.products
25 25 display_profile_info(self.profile) + content_tag('div', self.body || '') +
26 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 58 include ActionController::UrlWriter
59 59 include DatesHelper
60 60  
61   - def to_html
  61 + def to_html(options = {})
62 62  
63 63 result = ''
64 64 html = Builder::XmlMarkup.new(:target => result)
... ...
app/models/folder.rb
... ... @@ -34,7 +34,7 @@ class Folder &lt; Article
34 34 include FolderHelper
35 35 include DatesHelper
36 36  
37   - def to_html
  37 + def to_html(options = {})
38 38 send(view_as)
39 39 end
40 40  
... ...
app/models/rss_feed.rb
... ... @@ -50,7 +50,7 @@ class RssFeed &lt; Article
50 50 validates_inclusion_of :feed_item_description, :in => [ 'body', 'abstract' ], :if => :feed_item_description
51 51  
52 52 # TODO
53   - def to_html
  53 + def to_html(options = {})
54 54 end
55 55  
56 56 # RSS feeds have type =text/xml=.
... ... @@ -61,7 +61,7 @@ class RssFeed &lt; Article
61 61 include ActionController::UrlWriter
62 62 def fetch_articles
63 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 65 end
66 66  
67 67 articles =
... ...
app/models/textile_article.rb
... ... @@ -8,7 +8,7 @@ class TextileArticle &lt; TextArticle
8 8 _('Accessible alternative for visually impaired users.')
9 9 end
10 10  
11   - def to_html
  11 + def to_html(options ={})
12 12 RedCloth.new(self.body|| '').to_html
13 13 end
14 14  
... ...
app/models/uploaded_file.rb
... ... @@ -50,7 +50,7 @@ class UploadedFile &lt; Article
50 50 # FIXME isn't this too much including just to be able to generate some HTML?
51 51 include ActionView::Helpers::TagHelper
52 52  
53   - def to_html
  53 + def to_html(options = {})
54 54 tag('img', :src => public_filename, :class => css_class_name, :style => 'max-width: 100%') if image?
55 55 end
56 56  
... ...
app/views/content_viewer/blog_page.rhtml 0 → 100644
... ... @@ -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 202  
203 203 #content #article .pagination .prev_page {
204 204 position: absolute;
205   - right: 0;
  205 + left: 0;
206 206 }
207 207  
208 208 #content #article .pagination .next_page {
209 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 6  
7 7 def setup
8 8 stubs(:show_date).returns('')
  9 + @environment = Environment.default
9 10 @profile = create_user('blog_helper_test').person
  11 + @blog = Blog.create!(:profile => profile, :name => 'Blog test')
10 12 end
  13 +
11 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 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 69 end
... ...
test/unit/content_viewer_helper_test.rb
... ... @@ -56,7 +56,7 @@ class ContentViewerHelperTest &lt; Test::Unit::TestCase
56 56 should 'not list feed article' do
57 57 profile.articles << Blog.new(:name => 'Blog test')
58 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 60 assert_no_match /feed/, result
61 61 end
62 62  
... ... @@ -75,10 +75,11 @@ class ContentViewerHelperTest &lt; Test::Unit::TestCase
75 75  
76 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 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 83 end
83 84  
84 85 end
... ...
test/unit/rss_feed_test.rb
... ... @@ -121,6 +121,20 @@ class RssFeedTest &lt; Test::Unit::TestCase
121 121 assert_equal [posts[5], posts[4], posts[3], posts[2], posts[1]], feed.fetch_articles
122 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 138 should 'provide link to profile' do
125 139 profile = create_user('testuser').person
126 140 feed = RssFeed.new(:name => 'testfeed')
... ...