Commit 3c5828873aebe07383b3f786d950e40023c4ea55
Exists in
staging
Merge branch 'master' into staging
Showing
10 changed files
with
140 additions
and
86 deletions
Show diff stats
lib/noosfero/api/entities.rb
| @@ -187,11 +187,16 @@ module Noosfero | @@ -187,11 +187,16 @@ module Noosfero | ||
| 187 | end | 187 | end |
| 188 | end | 188 | end |
| 189 | 189 | ||
| 190 | - class Comment < Entity | ||
| 191 | - root 'comments', 'comment' | 190 | + class CommentBase < Entity |
| 192 | expose :body, :title, :id | 191 | expose :body, :title, :id |
| 193 | expose :created_at, :format_with => :timestamp | 192 | expose :created_at, :format_with => :timestamp |
| 194 | expose :author, :using => Profile | 193 | expose :author, :using => Profile |
| 194 | + expose :reply_of, :using => CommentBase | ||
| 195 | + end | ||
| 196 | + | ||
| 197 | + class Comment < CommentBase | ||
| 198 | + root 'comments', 'comment' | ||
| 199 | + expose :children, as: :replies, :using => Comment | ||
| 195 | end | 200 | end |
| 196 | 201 | ||
| 197 | class User < Entity | 202 | class User < Entity |
lib/noosfero/api/v1/comments.rb
| @@ -2,9 +2,12 @@ module Noosfero | @@ -2,9 +2,12 @@ module Noosfero | ||
| 2 | module API | 2 | module API |
| 3 | module V1 | 3 | module V1 |
| 4 | class Comments < Grape::API | 4 | class Comments < Grape::API |
| 5 | + MAX_PER_PAGE = 20 | ||
| 6 | + | ||
| 5 | before { authenticate! } | 7 | before { authenticate! } |
| 6 | 8 | ||
| 7 | resource :articles do | 9 | resource :articles do |
| 10 | + paginate max_per_page: MAX_PER_PAGE | ||
| 8 | # Collect comments from articles | 11 | # Collect comments from articles |
| 9 | # | 12 | # |
| 10 | # Parameters: | 13 | # Parameters: |
| @@ -17,7 +20,7 @@ module Noosfero | @@ -17,7 +20,7 @@ module Noosfero | ||
| 17 | get ":id/comments" do | 20 | get ":id/comments" do |
| 18 | article = find_article(environment.articles, params[:id]) | 21 | article = find_article(environment.articles, params[:id]) |
| 19 | comments = select_filtered_collection_of(article, :comments, params) | 22 | comments = select_filtered_collection_of(article, :comments, params) |
| 20 | - | 23 | + comments = comments.without_reply if(params[:without_reply].present?) |
| 21 | present comments, :with => Entities::Comment, :current_person => current_person | 24 | present comments, :with => Entities::Comment, :current_person => current_person |
| 22 | end | 25 | end |
| 23 | 26 |
plugins/gallery_block/lib/gallery_block.rb
| @@ -30,12 +30,4 @@ class GalleryBlock < Block | @@ -30,12 +30,4 @@ class GalleryBlock < Block | ||
| 30 | def images | 30 | def images |
| 31 | gallery ? gallery.images : [] | 31 | gallery ? gallery.images : [] |
| 32 | end | 32 | end |
| 33 | - | ||
| 34 | - def content(args={}) | ||
| 35 | - block = self | ||
| 36 | - proc do | ||
| 37 | - render :file => 'gallery_block', :locals => { :block => block } | ||
| 38 | - end | ||
| 39 | - end | ||
| 40 | - | ||
| 41 | end | 33 | end |
plugins/gallery_block/test/unit/gallery_block_test.rb
| @@ -20,3 +20,38 @@ class GalleryBlockTest < ActiveSupport::TestCase | @@ -20,3 +20,38 @@ class GalleryBlockTest < ActiveSupport::TestCase | ||
| 20 | end | 20 | end |
| 21 | 21 | ||
| 22 | end | 22 | end |
| 23 | + | ||
| 24 | +require 'boxes_helper' | ||
| 25 | + | ||
| 26 | +class GalleryBlockViewTest < ActionView::TestCase | ||
| 27 | + include BoxesHelper | ||
| 28 | + | ||
| 29 | + def setup | ||
| 30 | + @community = fast_create(Community) | ||
| 31 | + end | ||
| 32 | + | ||
| 33 | + should 'display the default message for empty gallery' do | ||
| 34 | + block = GalleryBlock.new | ||
| 35 | + block.stubs(:owner).returns(@community) | ||
| 36 | + | ||
| 37 | + ActionView::Base.any_instance.expects(:block_title).returns("") | ||
| 38 | + | ||
| 39 | + content = render_block_content(block) | ||
| 40 | + | ||
| 41 | + assert_match /#{_('Please, edit this block and choose some gallery')}/, content | ||
| 42 | + end | ||
| 43 | + | ||
| 44 | + should "display the gallery's content" do | ||
| 45 | + gallery = fast_create(Gallery, :profile_id => @community.id) | ||
| 46 | + image = create(UploadedFile, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :parent => gallery, :profile => @community) | ||
| 47 | + block = create(GalleryBlock, :gallery_id => gallery.id) | ||
| 48 | + block.stubs(:owner).returns(@community) | ||
| 49 | + | ||
| 50 | + ActionView::Base.any_instance.expects(:block_title).returns("") | ||
| 51 | + | ||
| 52 | + content = render_block_content(block) | ||
| 53 | + | ||
| 54 | + assert_tag_in_string content, tag: 'img', attributes: {src: image.public_filename(:thumb)} | ||
| 55 | + assert_tag_in_string content, tag: 'span', content: _('Next') | ||
| 56 | + end | ||
| 57 | +end |
| @@ -0,0 +1,44 @@ | @@ -0,0 +1,44 @@ | ||
| 1 | +<%= block_title(block.title, block.subtitle) %> | ||
| 2 | + | ||
| 3 | +<% unless block.images.blank? %> | ||
| 4 | + <%= link_to content_tag(:span, _('Previous')), '#', :class => 'gallery-block-prev gallery-block-arrow icon-left' %> | ||
| 5 | + <div class="gallery-block-container"> | ||
| 6 | + <ul class="gallery-list"> | ||
| 7 | + <% block.images.in_groups_of(block.groups_of).each do |group| %> | ||
| 8 | + <li class="gallery-group"> | ||
| 9 | + <div class="gallery-items"> | ||
| 10 | + <ul> | ||
| 11 | + <% group.reject{ |x| x.nil? }.each_with_index do |p, i| %> | ||
| 12 | + <li class="gallery-item"> | ||
| 13 | + <%= link_to image_tag(p.public_filename(:thumb), :alt => p.name, :title => p.name), p.view_url, :class => 'gallery-image' %> | ||
| 14 | + <div class="gallery-image-info position-<%= i + 1 %>" style="display: none"> | ||
| 15 | + <div class="gallery-image-text"> | ||
| 16 | + <h3><%= p.name %></h3> | ||
| 17 | + </div> | ||
| 18 | + </div> | ||
| 19 | + </li> | ||
| 20 | + <% end %> | ||
| 21 | + </ul> | ||
| 22 | + </div> | ||
| 23 | + </li> | ||
| 24 | + <% end %> | ||
| 25 | + </ul> | ||
| 26 | + </div> | ||
| 27 | + <%= link_to content_tag(:span, _('Next')), '#', :class => 'gallery-block-next gallery-block-arrow icon-right' %> | ||
| 28 | + <script type="text/javascript"> | ||
| 29 | + (function($) { | ||
| 30 | + var options = { | ||
| 31 | + fx : 'scrollHorz', | ||
| 32 | + timeout: 0, | ||
| 33 | + prev: '#block-<%= block.id %> .gallery-block-prev', | ||
| 34 | + next: '#block-<%= block.id %> .gallery-block-next', | ||
| 35 | + speed: 2000, | ||
| 36 | + timeout: <%= block.interval * 1000 %> | ||
| 37 | + } | ||
| 38 | + $('#block-<%= block.id %> .gallery-list').cycle(options); | ||
| 39 | + })(jQuery); | ||
| 40 | + </script> | ||
| 41 | + <p class="gallery-block-footer"></p> | ||
| 42 | +<% else %> | ||
| 43 | + <em><%= _('Please, edit this block and choose some gallery') %></em> | ||
| 44 | +<% end %> |
plugins/gallery_block/views/gallery_block.html.erb
| @@ -1,44 +0,0 @@ | @@ -1,44 +0,0 @@ | ||
| 1 | -<%= block_title(block.title, block.subtitle) %> | ||
| 2 | - | ||
| 3 | -<% unless block.images.blank? %> | ||
| 4 | - <%= link_to content_tag(:span, _('Previous')), '#', :class => 'gallery-block-prev gallery-block-arrow icon-left' %> | ||
| 5 | - <div class="gallery-block-container"> | ||
| 6 | - <ul class="gallery-list"> | ||
| 7 | - <% block.images.in_groups_of(block.groups_of).each do |group| %> | ||
| 8 | - <li class="gallery-group"> | ||
| 9 | - <div class="gallery-items"> | ||
| 10 | - <ul> | ||
| 11 | - <% group.reject{ |x| x.nil? }.each_with_index do |p, i| %> | ||
| 12 | - <li class="gallery-item"> | ||
| 13 | - <%= link_to image_tag(p.public_filename(:thumb), :alt => p.name, :title => p.name), p.view_url, :class => 'gallery-image' %> | ||
| 14 | - <div class="gallery-image-info position-<%= i + 1 %>" style="display: none"> | ||
| 15 | - <div class="gallery-image-text"> | ||
| 16 | - <h3><%= p.name %></h3> | ||
| 17 | - </div> | ||
| 18 | - </div> | ||
| 19 | - </li> | ||
| 20 | - <% end %> | ||
| 21 | - </ul> | ||
| 22 | - </div> | ||
| 23 | - </li> | ||
| 24 | - <% end %> | ||
| 25 | - </ul> | ||
| 26 | - </div> | ||
| 27 | - <%= link_to content_tag(:span, _('Next')), '#', :class => 'gallery-block-next gallery-block-arrow icon-right' %> | ||
| 28 | - <script type="text/javascript"> | ||
| 29 | - (function($) { | ||
| 30 | - var options = { | ||
| 31 | - fx : 'scrollHorz', | ||
| 32 | - timeout: 0, | ||
| 33 | - prev: '#block-<%= block.id %> .gallery-block-prev', | ||
| 34 | - next: '#block-<%= block.id %> .gallery-block-next', | ||
| 35 | - speed: 2000, | ||
| 36 | - timeout: <%= block.interval * 1000 %> | ||
| 37 | - } | ||
| 38 | - $('#block-<%= block.id %> .gallery-list').cycle(options); | ||
| 39 | - })(jQuery); | ||
| 40 | - </script> | ||
| 41 | - <p class="gallery-block-footer"></p> | ||
| 42 | -<% else %> | ||
| 43 | - <em><%= _('Please, edit this block and choose some gallery') %></em> | ||
| 44 | -<% end %> |
plugins/profile_description_block/lib/profile_description_block.rb
| @@ -16,24 +16,6 @@ class ProfileDescriptionBlock < Block | @@ -16,24 +16,6 @@ class ProfileDescriptionBlock < Block | ||
| 16 | _('PROFILE DESCRIPTION') | 16 | _('PROFILE DESCRIPTION') |
| 17 | end | 17 | end |
| 18 | 18 | ||
| 19 | - def content(args={}) | ||
| 20 | - description = if self.owner.description.blank? | ||
| 21 | - "Description field is empty or | ||
| 22 | - not enabled on enviroment" | ||
| 23 | - else | ||
| 24 | - self.owner.description | ||
| 25 | - end | ||
| 26 | - block = self | ||
| 27 | - s = show_name | ||
| 28 | - proc do | ||
| 29 | - render( | ||
| 30 | - :file => 'blocks/profile_description', | ||
| 31 | - :locals => { :block => block, :show_name => s , | ||
| 32 | - :description => description} | ||
| 33 | - ) | ||
| 34 | - end | ||
| 35 | - end | ||
| 36 | - | ||
| 37 | def cacheable? | 19 | def cacheable? |
| 38 | false | 20 | false |
| 39 | end | 21 | end |
plugins/profile_description_block/test/unit/profile_description_block_test.rb
| 1 | require 'test_helper' | 1 | require 'test_helper' |
| 2 | 2 | ||
| 3 | class ProfileDescriptionBlockTest < ActiveSupport::TestCase | 3 | class ProfileDescriptionBlockTest < ActiveSupport::TestCase |
| 4 | + should 'describe itself' do | ||
| 5 | + assert_not_equal Block.description, ProfileDescriptionBlock.description | ||
| 6 | + end | ||
| 7 | +end | ||
| 8 | + | ||
| 9 | +require 'boxes_helper' | ||
| 10 | + | ||
| 11 | +class ProfileDescriptionBlockViewTest < ActionView::TestCase | ||
| 12 | + include BoxesHelper | ||
| 13 | + | ||
| 4 | def setup | 14 | def setup |
| 5 | e = Environment.default | 15 | e = Environment.default |
| 6 | e.enabled_plugins = ['ProfileDescriptionPlugin'] | 16 | e.enabled_plugins = ['ProfileDescriptionPlugin'] |
| @@ -10,20 +20,20 @@ class ProfileDescriptionBlockTest < ActiveSupport::TestCase | @@ -10,20 +20,20 @@ class ProfileDescriptionBlockTest < ActiveSupport::TestCase | ||
| 10 | :description => "") | 20 | :description => "") |
| 11 | end | 21 | end |
| 12 | 22 | ||
| 13 | - should 'describe itself' do | ||
| 14 | - assert_not_equal Block.description, ProfileDescriptionBlock.description | ||
| 15 | - end | ||
| 16 | - | ||
| 17 | should "show profile description inside block" do | 23 | should "show profile description inside block" do |
| 18 | new_block = ProfileDescriptionBlock.create! | 24 | new_block = ProfileDescriptionBlock.create! |
| 25 | + | ||
| 19 | @profile.boxes.first.blocks << new_block | 26 | @profile.boxes.first.blocks << new_block |
| 20 | - block_menssage = "Description field is empty" | ||
| 21 | - assert (instance_eval(&Block.last.content).include?(block_menssage)), | 27 | + |
| 28 | + block_message = "Description field is empty" | ||
| 29 | + assert (render_block_content(Block.last).include?(block_message)), | ||
| 22 | "description block doesn't show not found description message" | 30 | "description block doesn't show not found description message" |
| 31 | + | ||
| 23 | description = "This is an test" | 32 | description = "This is an test" |
| 24 | @profile.update_attribute("description", description) | 33 | @profile.update_attribute("description", description) |
| 25 | @profile.save! | 34 | @profile.save! |
| 26 | - assert (instance_eval(&Block.last.content).include?(description)), | 35 | + |
| 36 | + assert (render_block_content(Block.last).include?(description)), | ||
| 27 | "Description block doesn't show profile description" | 37 | "Description block doesn't show profile description" |
| 28 | end | 38 | end |
| 29 | end | 39 | end |
plugins/profile_description_block/views/blocks/profile_description.html.erb
| 1 | <div class = 'profile-description-block'> | 1 | <div class = 'profile-description-block'> |
| 2 | -<div class = "block-title"> | ||
| 3 | - <%= block.title %> | ||
| 4 | -</div> | ||
| 5 | -<div class = "profile-description-block-title"> | ||
| 6 | - <%= description %> | ||
| 7 | -</div> | 2 | + <div class = "block-title"> |
| 3 | + <%= block.title %> | ||
| 4 | + </div> | ||
| 5 | + | ||
| 6 | + <div class = "profile-description-block-title"> | ||
| 7 | + <% if block.owner.description.blank? %> | ||
| 8 | + Description field is empty or not enabled on enviroment | ||
| 9 | + <% else %> | ||
| 10 | + <%= block.owner.description %> | ||
| 11 | + <% end %> | ||
| 12 | + </div> | ||
| 8 | </div> | 13 | </div> |
test/api/comments_test.rb
| @@ -87,4 +87,26 @@ class CommentsTest < ActiveSupport::TestCase | @@ -87,4 +87,26 @@ class CommentsTest < ActiveSupport::TestCase | ||
| 87 | assert_not_nil comment.source | 87 | assert_not_nil comment.source |
| 88 | end | 88 | end |
| 89 | 89 | ||
| 90 | + should 'paginate comments' do | ||
| 91 | + article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing") | ||
| 92 | + 5.times { article.comments.create!(:body => "some comment", :author => user.person) } | ||
| 93 | + params[:per_page] = 3 | ||
| 94 | + | ||
| 95 | + get "/api/v1/articles/#{article.id}/comments?#{params.to_query}" | ||
| 96 | + json = JSON.parse(last_response.body) | ||
| 97 | + assert_equal 200, last_response.status | ||
| 98 | + assert_equal 3, json["comments"].length | ||
| 99 | + end | ||
| 100 | + | ||
| 101 | + should 'return only root comments' do | ||
| 102 | + article = fast_create(Article, :profile_id => user.person.id, :name => "Some thing") | ||
| 103 | + comment1 = article.comments.create!(:body => "some comment", :author => user.person) | ||
| 104 | + comment2 = article.comments.create!(:body => "another comment", :author => user.person, :reply_of_id => comment1.id) | ||
| 105 | + params[:without_reply] = true | ||
| 106 | + | ||
| 107 | + get "/api/v1/articles/#{article.id}/comments?#{params.to_query}" | ||
| 108 | + json = JSON.parse(last_response.body) | ||
| 109 | + assert_equal 200, last_response.status | ||
| 110 | + assert_equal [comment1.id], json["comments"].map { |c| c['id'] } | ||
| 111 | + end | ||
| 90 | end | 112 | end |