Commit fe596c845d2dc4bbf2b3ef355077abfec5436408

Authored by Rodrigo Souto
2 parents 42e1b8af 3e725049

Merge branch 'post-pic' into 'next'

Improve blog posts listing

A help for armengeless themes.

See merge request !543
app/helpers/blog_helper.rb
@@ -17,28 +17,28 @@ module BlogHelper @@ -17,28 +17,28 @@ module BlogHelper
17 _('Configure blog') 17 _('Configure blog')
18 end 18 end
19 19
20 - def list_posts(articles, format = 'full', paginate = true) 20 + def list_posts(articles, conf = { format: 'full', paginate: true })
21 pagination = will_paginate(articles, { 21 pagination = will_paginate(articles, {
22 :param_name => 'npage', 22 :param_name => 'npage',
23 :previous_label => _('« Newer posts'), 23 :previous_label => _('« Newer posts'),
24 :next_label => _('Older posts »'), 24 :next_label => _('Older posts »'),
25 :params => {:action=>"view_page", :page=>articles.first.parent.path.split('/'), :controller=>"content_viewer"} 25 :params => {:action=>"view_page", :page=>articles.first.parent.path.split('/'), :controller=>"content_viewer"}
26 - }) if articles.present? && paginate 26 + }) if articles.present? && conf[:paginate]
27 content = [] 27 content = []
28 artic_len = articles.length 28 artic_len = articles.length
29 articles.each_with_index{ |art,i| 29 articles.each_with_index{ |art,i|
30 - css_add = [ 'position-'+(i+1).to_s() ] 30 + css_add = [ 'blog-post', 'position-'+(i+1).to_s() ]
31 position = (i%2 == 0) ? 'odd-post' : 'even-post' 31 position = (i%2 == 0) ? 'odd-post' : 'even-post'
32 css_add << 'first' if i == 0 32 css_add << 'first' if i == 0
33 css_add << 'last' if i == (artic_len-1) 33 css_add << 'last' if i == (artic_len-1)
34 css_add << 'not-published' if !art.published? 34 css_add << 'not-published' if !art.published?
35 - css_add << position + '-inner'  
36 - content << content_tag('div',  
37 - content_tag('div',  
38 - display_post(art, format).html_safe + '<br style="clear:both"/>'.html_safe,  
39 - :class => 'blog-post ' + css_add.join(' '),  
40 - :id => "post-#{art.id}"), :class => position  
41 - ) 35 + css_add << position
  36 + content << (content_tag 'div', id: "post-#{art.id}", class: css_add do
  37 + content_tag 'div', class: position + '-inner blog-post-inner' do
  38 + display_post(art, conf[:format]).html_safe +
  39 + '<br style="clear:both"/>'.html_safe
  40 + end
  41 + end)
42 } 42 }
43 content.join("\n<hr class='sep-posts'/>\n") + (pagination or '') 43 content.join("\n<hr class='sep-posts'/>\n") + (pagination or '')
44 end 44 end
@@ -46,7 +46,16 @@ module BlogHelper @@ -46,7 +46,16 @@ module BlogHelper
46 def display_post(article, format = 'full') 46 def display_post(article, format = 'full')
47 no_comments = (format == 'full') ? false : true 47 no_comments = (format == 'full') ? false : true
48 title = article_title(article, :no_comments => no_comments) 48 title = article_title(article, :no_comments => no_comments)
49 - html = send("display_#{format}_format", FilePresenter.for(article)).html_safe 49 + method = "display_#{format.split('+')[0]}_format"
  50 + html = send(method, FilePresenter.for(article)).html_safe
  51 + if format.split('+')[1] == 'pic'
  52 + img = article.first_image
  53 + if img.blank?
  54 + '<div class="post-pic empty"></div>'
  55 + else
  56 + '<div class="post-pic" style="background-image:url('+img+')"></div>'
  57 + end
  58 + end.to_s +
50 title + html 59 title + html
51 end 60 end
52 61
app/models/article.rb
@@ -769,7 +769,9 @@ class Article &lt; ActiveRecord::Base @@ -769,7 +769,9 @@ class Article &lt; ActiveRecord::Base
769 end 769 end
770 770
771 def first_image 771 def first_image
772 - img = Nokogiri::HTML.fragment(self.lead.to_s).css('img[src]').first || Nokogiri::HTML.fragment(self.body.to_s).search('img').first 772 + img = ( image.present? && { 'src' => image.public_filename } ) ||
  773 + Nokogiri::HTML.fragment(self.lead.to_s).css('img[src]').first ||
  774 + Nokogiri::HTML.fragment(self.body.to_s).search('img').first
773 img.nil? ? '' : img['src'] 775 img.nil? ? '' : img['src']
774 end 776 end
775 777
app/models/blog.rb
@@ -76,7 +76,7 @@ class Blog &lt; Folder @@ -76,7 +76,7 @@ class Blog &lt; Folder
76 end 76 end
77 77
78 settings_items :visualization_format, :type => :string, :default => 'full' 78 settings_items :visualization_format, :type => :string, :default => 'full'
79 - validates_inclusion_of :visualization_format, :in => [ 'full', 'short' ], :if => :visualization_format 79 + validates_inclusion_of :visualization_format, :in => [ 'full', 'short', 'short+pic' ], :if => :visualization_format
80 80
81 settings_items :display_posts_in_current_language, :type => :boolean, :default => false 81 settings_items :display_posts_in_current_language, :type => :boolean, :default => false
82 82
app/views/cms/_blog.html.erb
@@ -64,7 +64,11 @@ @@ -64,7 +64,11 @@
64 <%= labelled_check_box(_('Remove cover image'),'remove_image',true,false)%> 64 <%= labelled_check_box(_('Remove cover image'),'remove_image',true,false)%>
65 <% end %> 65 <% end %>
66 66
67 -<%= labelled_form_field(_('How to display posts:'), f.select(:visualization_format, [ [ _('Full post'), 'full'], [ _('First paragraph'), 'short'] ])) %> 67 +<%= labelled_form_field(_('How to display posts:'), f.select(:visualization_format, [
  68 + [ _('Full post'), 'full'],
  69 + [ _('First paragraph'), 'short'],
  70 + [ _('First paragraph, with post picture'), 'short+pic']
  71 +])) %>
68 72
69 <%= labelled_form_field(_('Posts per page:'), f.select(:posts_per_page, Blog.posts_per_page_options)) %> 73 <%= labelled_form_field(_('Posts per page:'), f.select(:posts_per_page, Blog.posts_per_page_options)) %>
70 74
app/views/content_viewer/blog_page.html.erb
@@ -18,6 +18,9 @@ @@ -18,6 +18,9 @@
18 format = inside_block.visualization_format 18 format = inside_block.visualization_format
19 paginate = false 19 paginate = false
20 end 20 end
21 - (blog.empty? ? content_tag('em', _('(no posts)')) : list_posts(posts, format, paginate)) 21 + (blog.empty? ?
  22 + content_tag('em', _('(no posts)')) :
  23 + list_posts(posts, format: format, paginate: paginate)
  24 + )
22 %> 25 %>
23 </div> 26 </div>
public/stylesheets/application.css
@@ -1501,6 +1501,14 @@ a.comment-picture { @@ -1501,6 +1501,14 @@ a.comment-picture {
1501 #content .title { 1501 #content .title {
1502 margin-bottom: 2px; 1502 margin-bottom: 2px;
1503 } 1503 }
  1504 +.blog-post .post-pic {
  1505 + background-position: 50% 40%;
  1506 + background-size: cover;
  1507 + height: 150px;
  1508 +}
  1509 +.blog-post .post-pic.empty {
  1510 + display: none;
  1511 +}
1504 .metadata, .blog-post .metadata { 1512 .metadata, .blog-post .metadata {
1505 display: block; 1513 display: block;
1506 text-align: center; 1514 text-align: center;
test/functional/content_viewer_controller_test.rb
@@ -780,6 +780,20 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -780,6 +780,20 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
780 assert_no_tag :tag => 'div', :attributes => { :class => 'short-post'}, :content => /Anything/ 780 assert_no_tag :tag => 'div', :attributes => { :class => 'short-post'}, :content => /Anything/
781 end 781 end
782 782
  783 + should 'show only first paragraph with picture of posts if visualization_format is short+pic' do
  784 + login_as(profile.identifier)
  785 +
  786 + blog = Blog.create!(:name => 'A blog test', :profile => profile, :visualization_format => 'short+pic')
  787 +
  788 + blog.posts << TinyMceArticle.create!(:name => 'first post', :parent => blog, :profile => profile, :body => '<p>Content to be displayed.</p> <img src="pic.jpg">')
  789 +
  790 + get :view_page, :profile => profile.identifier, :page => blog.path
  791 +
  792 + assert_select '.blog-post .post-pic' do |el|
  793 + assert_match /background-image:url\(pic.jpg\)/, el.to_s
  794 + end
  795 + end
  796 +
783 should 'display link to edit blog for allowed' do 797 should 'display link to edit blog for allowed' do
784 blog = fast_create(Blog, :profile_id => profile.id, :path => 'blog') 798 blog = fast_create(Blog, :profile_id => profile.id, :path => 'blog')
785 login_as(profile.identifier) 799 login_as(profile.identifier)
test/unit/article_test.rb
@@ -1715,6 +1715,18 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -1715,6 +1715,18 @@ class ArticleTest &lt; ActiveSupport::TestCase
1715 assert_equal 'bar.png', a.first_image 1715 assert_equal 'bar.png', a.first_image
1716 end 1716 end
1717 1717
  1718 + should 'get first image from having_image' do
  1719 + a = fast_create(Article,
  1720 + :body => '<p>Foo</p><p><img src="bar.png" /></p>',
  1721 + :abstract => '<p>Lead</p><p><img src="lead.png" /></p>'
  1722 + )
  1723 + img = {}
  1724 + img.expects(:present?).returns true
  1725 + img.expects(:public_filename).returns 'pic.jpg'
  1726 + a.expects(:image).at_least_once.returns img
  1727 + assert_equal 'pic.jpg', a.first_image
  1728 + end
  1729 +
1718 should 'not get first image from anywhere' do 1730 should 'not get first image from anywhere' do
1719 a = fast_create(Article, :body => '<p>Foo</p><p>Bar</p>') 1731 a = fast_create(Article, :body => '<p>Foo</p><p>Bar</p>')
1720 assert_equal '', a.first_image 1732 assert_equal '', a.first_image
test/unit/blog_helper_test.rb
@@ -20,30 +20,36 @@ class BlogHelperTest &lt; ActionView::TestCase @@ -20,30 +20,36 @@ class BlogHelperTest &lt; ActionView::TestCase
20 def _(s); s; end 20 def _(s); s; end
21 def h(s); s; end 21 def h(s); s; end
22 22
23 - should 'list published posts with class blog-post' do  
24 - blog.children << published_post = create(TextileArticle, :name => 'Post', :profile => profile, :parent => blog, :published => true)  
25 -  
26 - expects(:display_post).with(anything, anything).returns('POST')  
27 - expects(:content_tag).with('div', "POST<br style=\"clear:both\"/>", :class => 'blog-post position-1 first last odd-post-inner', :id => "post-#{published_post.id}").returns('POST')  
28 - expects(:content_tag).with('div', 'POST', {:class => 'odd-post'}).returns('RESULT')  
29 -  
30 - assert_equal 'RESULT', list_posts(blog.posts)  
31 - end  
32 -  
33 - should 'list even/odd posts with a different class' do  
34 - blog.children << older_post = create(TextileArticle, :name => 'First post', :profile => profile, :parent => blog, :published => true)  
35 -  
36 - blog.children << newer_post = create(TextileArticle, :name => 'Second post', :profile => profile, :parent => blog, :published => true)  
37 -  
38 - expects(:display_post).with(anything, anything).returns('POST').times(2)  
39 -  
40 - expects(:content_tag).with('div', "POST<br style=\"clear:both\"/>", :class => 'blog-post position-1 first odd-post-inner', :id => "post-#{newer_post.id}").returns('POST 1')  
41 - expects(:content_tag).with('div', "POST 1", :class => 'odd-post').returns('ODD-POST')  
42 -  
43 - expects(:content_tag).with('div', "POST<br style=\"clear:both\"/>", :class => 'blog-post position-2 last even-post-inner', :id => "post-#{older_post.id}").returns('POST 2')  
44 - expects(:content_tag).with('div', "POST 2", :class => 'even-post').returns('EVEN-POST')  
45 -  
46 - assert_equal "ODD-POST\n<hr class='sep-posts'/>\nEVEN-POST", list_posts(blog.posts) 23 + should 'list blog posts with identifiers and classes' do
  24 + blog.children << older_post = create(TextileArticle, :name => 'First post',
  25 + :profile => profile, :parent => blog, :published => true)
  26 + blog.children << some_post = create(TextileArticle, :name => 'Some post',
  27 + :profile => profile, :parent => blog, :published => true)
  28 + blog.children << hidden_post = create(TextileArticle, :name => 'Hidden post',
  29 + :profile => profile, :parent => blog, :published => false)
  30 + blog.children << newer_post = create(TextileArticle, :name => 'Last post',
  31 + :profile => profile, :parent => blog, :published => true)
  32 +
  33 + def content_tag(tag, content_or_options_with_block = nil, options = nil, &block)
  34 + if block_given?
  35 + options = content_or_options_with_block
  36 + content = block.call
  37 + else
  38 + content = content_or_options_with_block
  39 + end
  40 + options ||= {}
  41 + "<#{tag}#{options.map{|k,v| " #{k}=\"#{[v].flatten.join(' ')}\""}.join}>#{content}</#{tag}>"
  42 + end
  43 +
  44 + html = HTML::Document.new(list_posts(blog.posts)).root
  45 + assert_select html, "div#post-#{newer_post.id}.blog-post.position-1.first.odd-post" +
  46 + " > div.odd-post-inner.blog-post-inner > .title", 'Last post'
  47 + assert_select html, "div#post-#{hidden_post.id}.blog-post.position-2.not-published.even-post" +
  48 + " > div.even-post-inner.blog-post-inner > .title", 'Hidden post'
  49 + assert_select html, "div#post-#{some_post.id}.blog-post.position-3.odd-post" +
  50 + " > div.odd-post-inner.blog-post-inner > .title", 'Some post'
  51 + assert_select html, "div#post-#{older_post.id}.blog-post.position-4.last.even-post" +
  52 + " > div.even-post-inner.blog-post-inner > .title", 'First post'
47 end 53 end
48 54
49 55