Commit 3ea04c54b00333b383bb1ac250c1f586ba822231

Authored by Rodrigo Souto
2 parents 29866897 d66fe2c0

Merge commit 'refs/merge-requests/188' of git://gitorious.org/noosfero/noosfero …

…into merge-requests/188
app/helpers/application_helper.rb
... ... @@ -30,6 +30,10 @@ module ApplicationHelper
30 30  
31 31 include AccountHelper
32 32  
  33 + include BlogHelper
  34 +
  35 + include ContentViewerHelper
  36 +
33 37 def locale
34 38 (@page && !@page.language.blank?) ? @page.language : FastGettext.locale
35 39 end
... ... @@ -994,6 +998,36 @@ module ApplicationHelper
994 998 content
995 999 end
996 1000  
  1001 + # Please, use link_to by default!
  1002 + # This method was created to work around to inexplicable
  1003 + # chain of problems when display_short_format was called
  1004 + # from Article model for an ArticleBlock.
  1005 + def link_to_article(text, article, anchor=nil)
  1006 + if article.profile.domains.empty?
  1007 + href = "/#{article.url[:profile]}/"
  1008 + else
  1009 + href = "http://#{article.profile.domains.first.name}/"
  1010 + end
  1011 + href += article.url[:page].join('/')
  1012 + href += '#' + anchor if anchor
  1013 + content_tag('a', text, :href => href)
  1014 + end
  1015 +
  1016 + def display_short_format(article, options={})
  1017 + options[:comments_link] ||= true
  1018 + options[:read_more_link] ||= true
  1019 + html = content_tag('div',
  1020 + article.lead +
  1021 + content_tag('div',
  1022 + (options[:comments_link] ? link_to_comments(article) : '') +
  1023 + (options[:read_more_link] ? link_to_article( _('Read more'), article) : ''),
  1024 + :class => 'read-more'
  1025 + ),
  1026 + :class => 'short-post'
  1027 + )
  1028 + html
  1029 + end
  1030 +
997 1031 def colorpicker_field(object_name, method, options = {})
998 1032 text_field(object_name, method, options.merge(:class => 'colorpicker_field'))
999 1033 end
... ...
app/helpers/blog_helper.rb
... ... @@ -18,7 +18,8 @@ module BlogHelper
18 18 pagination = will_paginate(articles, {
19 19 :param_name => 'npage',
20 20 :previous_label => _('« Newer posts'),
21   - :next_label => _('Older posts »')
  21 + :next_label => _('Older posts »'),
  22 + :params => {:action=>"view_page", :page=>articles.first.parent.path.split('/'), :controller=>"content_viewer"}
22 23 })
23 24 content = []
24 25 artic_len = articles.length
... ... @@ -46,18 +47,6 @@ module BlogHelper
46 47 article_title(article, :no_comments => no_comments) + html
47 48 end
48 49  
49   - def display_short_format(article)
50   - html = content_tag('div',
51   - article.lead +
52   - content_tag('div',
53   - link_to_comments(article) +
54   - link_to( _('Read more'), article.url),
55   - :class => 'read-more'),
56   - :class => 'short-post'
57   - )
58   - html
59   - end
60   -
61 50 def display_full_format(article)
62 51 html = article_to_html(article)
63 52 html = content_tag('p', html) if ! html.include?('</p>')
... ...
app/helpers/content_viewer_helper.rb
... ... @@ -2,6 +2,7 @@ module ContentViewerHelper
2 2  
3 3 include BlogHelper
4 4 include ForumHelper
  5 + include ActionView::Helpers::TagHelper
5 6  
6 7 def number_of_comments(article)
7 8 n = article.comments.without_spam.count
... ... @@ -36,7 +37,7 @@ module ContentViewerHelper
36 37  
37 38 def link_to_comments(article, args = {})
38 39 return '' unless article.accept_comments?
39   - link_to(number_of_comments(article), article.url.merge(:anchor => 'comments_list') )
  40 + link_to_article number_of_comments(article), article, 'comments_list'
40 41 end
41 42  
42 43 def article_translations(article)
... ...
app/helpers/dates_helper.rb
... ... @@ -23,11 +23,13 @@ module DatesHelper
23 23 end
24 24  
25 25 # formats a date for displaying.
26   - def show_date(date, use_numbers = false)
  26 + def show_date(date, use_numbers = false, year=true)
27 27 if date && use_numbers
28   - _('%{month}/%{day}/%{year}') % { :day => date.day, :month => date.month, :year => date.year }
  28 + date_format = year ? _('%{month}/%{day}/%{year}') : _('%{month}/%{day}')
  29 + date_format % { :day => date.day, :month => date.month, :year => date.year }
29 30 elsif date
30   - _('%{month} %{day}, %{year}') % { :day => date.day, :month => month_name(date.month), :year => date.year }
  31 + date_format = year ? _('%{month_name} %{day}, %{year}') : _('%{month_name} %{day}')
  32 + date_format % { :day => date.day, :month_name => month_name(date.month), :year => date.year }
31 33 else
32 34 ''
33 35 end
... ... @@ -46,7 +48,27 @@ module DatesHelper
46 48 if (date1 == date2) || (date2.nil?)
47 49 show_date(date1, use_numbers)
48 50 else
49   - _('from %{date1} to %{date2}') % {:date1 => show_date(date1, use_numbers), :date2 => show_date(date2, use_numbers)}
  51 + if date1.year == date2.year
  52 + if date1.month == date2.month
  53 + _('from %{month} %{day1} to %{day2}, %{year}') % {
  54 + :day1 => date1.day,
  55 + :day2 => date2.day,
  56 + :month => use_numbers ? date1.month : month_name(date1.month),
  57 + :year => date1.year
  58 + }
  59 + else
  60 + _('from %{date1} to %{date2}, %{year}') % {
  61 + :date1 => show_date(date1, use_numbers, false),
  62 + :date2 => show_date(date2, use_numbers, false),
  63 + :year => date1.year
  64 + }
  65 + end
  66 + else
  67 + _('from %{date1} to %{date2}') % {
  68 + :date1 => show_date(date1, use_numbers),
  69 + :date2 => show_date(date2, use_numbers)
  70 + }
  71 + end
50 72 end
51 73 end
52 74  
... ...
app/models/article.rb
... ... @@ -236,8 +236,13 @@ class Article &lt; ActiveRecord::Base
236 236 # The implementation in this class just provides the +body+ attribute as the
237 237 # HTML. Other article types can override this method to provide customized
238 238 # views of themselves.
  239 + # (To override short format representation, override the lead method)
239 240 def to_html(options = {})
240   - body || ''
  241 + if options[:format] == 'short'
  242 + display_short_format(self)
  243 + else
  244 + body || ''
  245 + end
241 246 end
242 247  
243 248 include ApplicationHelper
... ...
app/models/article_block.rb
... ... @@ -12,7 +12,11 @@ class ArticleBlock &lt; Block
12 12 block = self
13 13 lambda do
14 14 block_title(block.title) +
15   - (block.article ? article_to_html(block.article, :gallery_view => false) : _('Article not selected yet.'))
  15 + (block.article ? article_to_html(block.article,
  16 + :gallery_view => false,
  17 + :inside_block => block, # For Blogs and folders
  18 + :format => block.visualization_format # For Articles and contents
  19 + ) : _('Article not selected yet.'))
16 20 end
17 21 end
18 22  
... ... @@ -49,4 +53,14 @@ class ArticleBlock &lt; Block
49 53 self.box.owner.kind_of?(Environment) ? self.box.owner.portal_community.articles : self.box.owner.articles
50 54 end
51 55  
  56 + def posts_per_page
  57 + self.settings[:posts_per_page] or 1
  58 + end
  59 +
  60 + def posts_per_page= value
  61 + value = value.to_i
  62 + self.settings[:posts_per_page] = value if value > 0
  63 + end
  64 +
  65 + settings_items :visualization_format, :type => :string, :default => 'short'
52 66 end
... ...
app/models/blog.rb
... ... @@ -24,8 +24,9 @@ class Blog &lt; Folder
24 24 # FIXME isn't this too much including just to be able to generate some HTML?
25 25 include ActionView::Helpers::TagHelper
26 26 def to_html(options = {})
  27 + me = self
27 28 lambda do
28   - render :file => 'content_viewer/blog_page'
  29 + render :file => 'content_viewer/blog_page', :locals => { :blog=>me, :inside_block=>options[:inside_block] }
29 30 end
30 31 end
31 32  
... ...
app/models/event.rb
... ... @@ -104,18 +104,30 @@ class Event &lt; Article
104 104 }
105 105 }
106 106  
  107 + # TODO: some good soul, please clean this ugly hack:
107 108 if self.body
108 109 html.div('_____XXXX_DESCRIPTION_GOES_HERE_XXXX_____', :class => 'event-description')
109 110 end
110 111 }
111 112  
112 113 if self.body
113   - result.sub!('_____XXXX_DESCRIPTION_GOES_HERE_XXXX_____', self.body)
  114 + if options[:format] == 'short'
  115 + result.sub!('_____XXXX_DESCRIPTION_GOES_HERE_XXXX_____', display_short_format(self))
  116 + else
  117 + result.sub!('_____XXXX_DESCRIPTION_GOES_HERE_XXXX_____', self.body)
  118 + end
114 119 end
115 120  
116 121 result
117 122 end
118 123  
  124 + def lead
  125 + content_tag('div',
  126 + show_period(start_date, end_date),
  127 + :class => 'event-dates'
  128 + ) + super
  129 + end
  130 +
119 131 def event?
120 132 true
121 133 end
... ...
app/views/box_organizer/_article_block.rhtml
1   -<div class='article-block-edition'>
  1 +<div class="article-block-edition">
2 2 <% if @block.box.owner.kind_of?(Environment) and @block.box.owner.portal_community.nil? %>
3   - <p id='no_portal_community'>
  3 + <p id="no_portal_community">
4 4 <%= _("You don't have an community defined as the portal community. Define it before use this block properly.") %>
5 5 </p>
6 6 <% else %>
7   - <% articles = @block.available_articles.select {|article| !article.folder? } %>
8   - <%= select_tag('block[article_id]', options_for_select_with_title(articles.map {|item| [item.path, item.id]}, @block.article ? @block.article.id : nil)) %>
  7 + <%
  8 + articles = @block.available_articles.select {|a| !a.folder? || a.blog? }
  9 + firstText = articles[articles.find_index{|a| a.kind_of?TextArticle}||-1]
  10 + selected = @block.article || firstText
  11 + %>
  12 + <%= select_tag(
  13 + 'block[article_id]',
  14 + options_for_select_with_title(articles.map {|item| [item.path, item.id]}, selected.id),
  15 + :onchange => 'this.changedTo(this.value)'
  16 + )%>
  17 + <div id="block_blog_options" style="display:none">
  18 + <%= labelled_form_field(
  19 + _('Number of posts:'),
  20 + text_field_tag('block[posts_per_page]', @block.posts_per_page)
  21 + )%>
  22 + </div>
  23 + <%= labelled_form_field(
  24 + _('How to display this content:'),
  25 + select_tag(
  26 + 'block[visualization_format]',
  27 + options_for_select([[_('Lead'), 'short'], [_('Full post'), 'full']], @block.visualization_format)
  28 + )
  29 + )%>
  30 + <% blogs = @block.available_articles.select{|a|a.blog?} %>
  31 + <script>
  32 + var select = jQuery("#block_article_id")[0];
  33 + select.blogs = <%= blogs.map{|b| b.id.to_s }.to_json %>;
  34 + select.changedTo = function(articleId) {
  35 + var blogSelected = this.blogs.indexOf(articleId) != -1;
  36 + jQuery("#block_blog_options").toggle(blogSelected);
  37 + }
  38 + select.changedTo('<%= selected.id %>');
  39 + </script>
9 40 <% end %>
10 41 </div>
... ...
app/views/content_viewer/blog_page.rhtml
1   -<% add_rss_feed_to_head(@page.name, @page.feed.url) if @page.blog? && @page.feed %>
  1 +<% add_rss_feed_to_head(blog.name, blog.feed.url) if blog.blog? && blog.feed %>
2 2  
3   -<%= content_tag('em', _('(external feed was not loaded yet)'), :id => 'external-feed-info', :class => 'metadata') if @page.blog? && @page.external_feed && @page.external_feed.enabled && @page.external_feed.fetched_at.nil? %>
  3 +<%= content_tag('em', _('(external feed was not loaded yet)'), :id => 'external-feed-info', :class => 'metadata') if blog.blog? && blog.external_feed && blog.external_feed.enabled && blog.external_feed.fetched_at.nil? %>
4 4  
5 5 <div>
6 6 <div class='blog-description'>
7   - <%= @page.body %>
  7 + <%= blog.body %>
8 8 </div>
9 9 </div>
10 10 <hr class="pre-posts"/>
11 11 <div class="blog-posts">
12   - <%= (@page.empty? ? content_tag('em', _('(no posts)')) : list_posts(@posts, @page.visualization_format)) %>
  12 + <%=
  13 + posts = @posts
  14 + format = blog.visualization_format
  15 + if inside_block
  16 + posts = blog.posts.paginate(:page=>1, :per_page=>inside_block.posts_per_page)
  17 + format = inside_block.visualization_format
  18 + end
  19 + (blog.empty? ? content_tag('em', _('(no posts)')) : list_posts(posts, format))
  20 + %>
13 21 </div>
... ...
test/integration/blocks_integration_test.rb 0 → 100644
... ... @@ -0,0 +1,56 @@
  1 +require "#{File.dirname(__FILE__)}/../test_helper"
  2 +
  3 +class BlocksIntegrationTest < ActionController::IntegrationTest
  4 + def blog_on_article_block_bootstrap
  5 + profile = fast_create(Profile)
  6 + blog = fast_create(Blog, :name => 'Blog', :profile_id => profile.id)
  7 + fast_create(TinyMceArticle, :name => "First Post", :profile_id => profile.id, :parent_id => blog.id, :body => '<p> Wasserstoffbombe </p>')
  8 + fast_create(TinyMceArticle, :name => "A Post", :profile_id => profile.id, :parent_id => blog.id, :body => '<p>Lorem ipsum dolor sit amet</p> <p>Second paragraph</p>')
  9 + block = ArticleBlock.new
  10 + block.article = blog
  11 + profile.boxes << Box.new
  12 + profile.boxes.first.blocks << block
  13 + return block
  14 + end
  15 +
  16 + should 'allow blog as article block content' do
  17 + block = blog_on_article_block_bootstrap
  18 + get "/profile/#{block.owner.identifier}"
  19 + assert_match(/Lorem ipsum dolor sit amet/, @response.body)
  20 + end
  21 +
  22 + should 'display short version for block posts on article block' do
  23 + block = blog_on_article_block_bootstrap
  24 + get "/profile/#{block.owner.identifier}"
  25 + assert_no_match(/Second paragraph/, @response.body)
  26 + end
  27 +
  28 + should 'display full version for block posts on article block' do
  29 + block = blog_on_article_block_bootstrap
  30 + block.visualization_format = 'full'
  31 + block.save!
  32 + get "/profile/#{block.owner.identifier}"
  33 + assert_match(/Second paragraph/, @response.body)
  34 + end
  35 +
  36 + should 'display configured number of blog posts on article block' do
  37 + block = blog_on_article_block_bootstrap
  38 + block.posts_per_page = 2
  39 + block.save!
  40 + get "/profile/#{block.owner.identifier}"
  41 + assert_match(/Lorem ipsum dolor sit amet/, @response.body)
  42 + assert_match(/Wasserstoffbombe/, @response.body)
  43 + end
  44 +
  45 + should 'link correctly in pagination' do
  46 + block = blog_on_article_block_bootstrap
  47 + p = block.owner
  48 + b = block.article
  49 + f = fast_create(Folder, :name => 'Folder1', :profile_id => p.id)
  50 + b.parent = f
  51 + b.save!
  52 + get "/profile/#{block.owner.identifier}"
  53 + assert_tag :tag => 'a', :attributes => { :href => "/#{p.identifier}/#{f.slug}/#{b.slug}?npage=2" }
  54 + end
  55 +
  56 +end
... ...
test/unit/application_helper_test.rb
... ... @@ -657,6 +657,43 @@ class ApplicationHelperTest &lt; ActiveSupport::TestCase
657 657 assert_not_nil add_zoom_to_images
658 658 end
659 659  
  660 + should 'link to article' do
  661 + c = fast_create(Community)
  662 + a = fast_create(TinyMceArticle, :profile_id => c.id)
  663 + assert_equal(
  664 + "<a href=\"/#{c.identifier}/#{a.slug}\">x</a>",
  665 + link_to_article('x', a) )
  666 + end
  667 +
  668 + should 'link to article, with anchor' do
  669 + c = fast_create(Community)
  670 + a = fast_create(TinyMceArticle, :profile_id => c.id)
  671 + assert_equal(
  672 + "<a href=\"/#{c.identifier}/#{a.slug}#place\">x</a>",
  673 + link_to_article('x', a, 'place') )
  674 + end
  675 +
  676 + should 'link to article, in a blog' do
  677 + c = fast_create(Community)
  678 + b = fast_create(Blog, :profile_id => c.id)
  679 + a = fast_create(TinyMceArticle, :profile_id => c.id, :parent_id => b.id)
  680 + a.save! # needed to link to the parent blog
  681 + assert_equal(
  682 + "<a href=\"/#{c.identifier}/#{b.slug}/#{a.slug}\">x</a>",
  683 + link_to_article('x', a) )
  684 + end
  685 +
  686 + should 'link to article, in a profile with domain' do
  687 + c = fast_create(Community)
  688 + c.domains << Domain.new(:name=>'domain.xyz')
  689 + b = fast_create(Blog, :profile_id => c.id)
  690 + a = fast_create(TinyMceArticle, :profile_id => c.id, :parent_id => b.id)
  691 + a.save!
  692 + assert_equal(
  693 + "<a href=\"http://domain.xyz/#{b.slug}/#{a.slug}\">x</a>",
  694 + link_to_article('x', a) )
  695 + end
  696 +
660 697 protected
661 698 include NoosferoTestHelper
662 699  
... ...
test/unit/article_test.rb
... ... @@ -97,6 +97,21 @@ class ArticleTest &lt; ActiveSupport::TestCase
97 97 assert_equal '', a.to_html
98 98 end
99 99  
  100 + should 'provide short html version' do
  101 + a = fast_create(Article, :body => 'full body', :abstract => 'lead')
  102 + a.stubs(:url).returns({:x=>'none'})
  103 + a.stubs(:link_to).returns('<link>')
  104 + def a.content_tag (tag, content, c=nil)
  105 + "<#{tag}>#{content}</#{tag}>"
  106 + end
  107 + assert_match /<div>lead.*/, a.to_html(:format=>'short')
  108 + end
  109 +
  110 + should 'provide full html version' do
  111 + a = fast_create(Article, :body => 'full body', :abstract => 'lead')
  112 + assert_equal 'full body', a.to_html(:format=>'full body')
  113 + end
  114 +
100 115 should 'provide first paragraph of HTML version' do
101 116 profile = create_user('testinguser').person
102 117 a = fast_create(Article, :name => 'my article', :profile_id => profile.id)
... ...
test/unit/dates_helper_test.rb
... ... @@ -10,20 +10,40 @@ class DatesHelperTest &lt; ActiveSupport::TestCase
10 10 end
11 11  
12 12 should 'display date with translation' do
13   - expects(:_).with('%{month} %{day}, %{year}').returns('%{day} de %{month} de %{year}')
  13 + expects(:_).with('%{month_name} %{day}, %{year}').returns('%{day} de %{month_name} de %{year}')
14 14 expects(:_).with('January').returns('Janeiro')
15 15 assert_equal '11 de Janeiro de 2008', show_date(Date.new(2008, 1, 11))
16 16 end
17 17  
18 18 should 'generate period with two dates' do
19 19 date1 = mock
  20 + date1.stubs(:year).returns('A')
20 21 expects(:show_date).with(date1, anything).returns('XXX')
21 22 date2 = mock
  23 + date2.stubs(:year).returns('B')
22 24 expects(:show_date).with(date2, anything).returns('YYY')
23 25 expects(:_).with('from %{date1} to %{date2}').returns('from %{date1} to %{date2}')
24 26 assert_equal 'from XXX to YYY', show_period(date1, date2)
25 27 end
26 28  
  29 + should 'generate period with in two diferent years' do
  30 + date1 = Date.new(1920, 1, 2)
  31 + date2 = Date.new(1992, 4, 6)
  32 + assert_equal 'from January 2, 1920 to April 6, 1992', show_period(date1, date2)
  33 + end
  34 +
  35 + should 'generate period with in two diferent months of the same year' do
  36 + date1 = Date.new(2013, 2, 1)
  37 + date2 = Date.new(2013, 3, 1)
  38 + assert_equal 'from February 1 to March 1, 2013', show_period(date1, date2)
  39 + end
  40 +
  41 + should 'generate period with in two days of the same month' do
  42 + date1 = Date.new(2013, 3, 27)
  43 + date2 = Date.new(2013, 3, 28)
  44 + assert_equal 'from March 27 to 28, 2013', show_period(date1, date2)
  45 + end
  46 +
27 47 should 'generate period with two equal dates' do
28 48 date1 = mock
29 49 expects(:show_date).with(date1, anything).returns('XXX')
... ...