Commit fe596c845d2dc4bbf2b3ef355077abfec5436408
Exists in
master
and in
29 other branches
Merge branch 'post-pic' into 'next'
Improve blog posts listing A help for armengeless themes. See merge request !543
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
... | ... | @@ -1501,6 +1501,14 @@ a.comment-picture { |
1501 | 1501 | #content .title { |
1502 | 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 | 1512 | .metadata, .blog-post .metadata { |
1505 | 1513 | display: block; |
1506 | 1514 | 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 | ... | ... |