Commit 3e7250494a6552a03f6924fc3f22fcb4627f8b23
1 parent
89c5fafb
Exists in
master
and in
29 other branches
Improve blog posts listing
A help for armengeless themes.
Showing
9 changed files
with
97 additions
and
39 deletions
Show diff stats
app/helpers/blog_helper.rb
| ... | ... | @@ -17,28 +17,28 @@ module BlogHelper |
| 17 | 17 | _('Configure blog') |
| 18 | 18 | end |
| 19 | 19 | |
| 20 | - def list_posts(articles, format = 'full', paginate = true) | |
| 20 | + def list_posts(articles, conf = { format: 'full', paginate: true }) | |
| 21 | 21 | pagination = will_paginate(articles, { |
| 22 | 22 | :param_name => 'npage', |
| 23 | 23 | :previous_label => _('« Newer posts'), |
| 24 | 24 | :next_label => _('Older posts »'), |
| 25 | 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 | 27 | content = [] |
| 28 | 28 | artic_len = articles.length |
| 29 | 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 | 31 | position = (i%2 == 0) ? 'odd-post' : 'even-post' |
| 32 | 32 | css_add << 'first' if i == 0 |
| 33 | 33 | css_add << 'last' if i == (artic_len-1) |
| 34 | 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 | 43 | content.join("\n<hr class='sep-posts'/>\n") + (pagination or '') |
| 44 | 44 | end |
| ... | ... | @@ -46,7 +46,16 @@ module BlogHelper |
| 46 | 46 | def display_post(article, format = 'full') |
| 47 | 47 | no_comments = (format == 'full') ? false : true |
| 48 | 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 | 59 | title + html |
| 51 | 60 | end |
| 52 | 61 | ... | ... |
app/models/article.rb
| ... | ... | @@ -769,7 +769,9 @@ class Article < ActiveRecord::Base |
| 769 | 769 | end |
| 770 | 770 | |
| 771 | 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 | 775 | img.nil? ? '' : img['src'] |
| 774 | 776 | end |
| 775 | 777 | ... | ... |
app/models/blog.rb
| ... | ... | @@ -76,7 +76,7 @@ class Blog < Folder |
| 76 | 76 | end |
| 77 | 77 | |
| 78 | 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 | 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 | 64 | <%= labelled_check_box(_('Remove cover image'),'remove_image',true,false)%> |
| 65 | 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 | 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 | 18 | format = inside_block.visualization_format |
| 19 | 19 | paginate = false |
| 20 | 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 | 26 | </div> | ... | ... |
public/stylesheets/application.css
| ... | ... | @@ -1483,6 +1483,14 @@ a.comment-picture { |
| 1483 | 1483 | #content .title { |
| 1484 | 1484 | margin-bottom: 2px; |
| 1485 | 1485 | } |
| 1486 | +.blog-post .post-pic { | |
| 1487 | + background-position: 50% 40%; | |
| 1488 | + background-size: cover; | |
| 1489 | + height: 150px; | |
| 1490 | +} | |
| 1491 | +.blog-post .post-pic.empty { | |
| 1492 | + display: none; | |
| 1493 | +} | |
| 1486 | 1494 | .metadata, .blog-post .metadata { |
| 1487 | 1495 | display: block; |
| 1488 | 1496 | text-align: center; | ... | ... |
test/functional/content_viewer_controller_test.rb
| ... | ... | @@ -780,6 +780,20 @@ class ContentViewerControllerTest < ActionController::TestCase |
| 780 | 780 | assert_no_tag :tag => 'div', :attributes => { :class => 'short-post'}, :content => /Anything/ |
| 781 | 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 | 797 | should 'display link to edit blog for allowed' do |
| 784 | 798 | blog = fast_create(Blog, :profile_id => profile.id, :path => 'blog') |
| 785 | 799 | login_as(profile.identifier) | ... | ... |
test/unit/article_test.rb
| ... | ... | @@ -1715,6 +1715,18 @@ class ArticleTest < ActiveSupport::TestCase |
| 1715 | 1715 | assert_equal 'bar.png', a.first_image |
| 1716 | 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 | 1730 | should 'not get first image from anywhere' do |
| 1719 | 1731 | a = fast_create(Article, :body => '<p>Foo</p><p>Bar</p>') |
| 1720 | 1732 | assert_equal '', a.first_image | ... | ... |
test/unit/blog_helper_test.rb
| ... | ... | @@ -20,30 +20,36 @@ class BlogHelperTest < ActionView::TestCase |
| 20 | 20 | def _(s); s; end |
| 21 | 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 | 53 | end |
| 48 | 54 | |
| 49 | 55 | ... | ... |