Commit d7f514c234162fb6fbed0648c89d453897fdc2a9
Exists in
master
and in
29 other branches
Merge branch 'AI2888-context_block' of /mnt/ebs/repositories/participa/noosfero
Showing
15 changed files
with
638 additions
and
16 deletions
Show diff stats
app/models/article.rb
... | ... | @@ -288,6 +288,11 @@ class Article < ActiveRecord::Base |
288 | 288 | 'text-html' |
289 | 289 | end |
290 | 290 | |
291 | + # TODO Migrate the class method icon_name to instance methods. | |
292 | + def icon_name | |
293 | + self.class.icon_name(self) | |
294 | + end | |
295 | + | |
291 | 296 | def mime_type |
292 | 297 | 'text/html' |
293 | 298 | end |
... | ... | @@ -350,22 +355,6 @@ class Article < ActiveRecord::Base |
350 | 355 | true |
351 | 356 | end |
352 | 357 | |
353 | - def folder? | |
354 | - false | |
355 | - end | |
356 | - | |
357 | - def blog? | |
358 | - false | |
359 | - end | |
360 | - | |
361 | - def forum? | |
362 | - false | |
363 | - end | |
364 | - | |
365 | - def uploaded_file? | |
366 | - false | |
367 | - end | |
368 | - | |
369 | 358 | def has_posts? |
370 | 359 | false |
371 | 360 | end |
... | ... | @@ -464,6 +453,7 @@ class Article < ActiveRecord::Base |
464 | 453 | named_scope :galleries, :conditions => { :type => 'Gallery' } |
465 | 454 | named_scope :images, :conditions => { :is_image => true } |
466 | 455 | named_scope :text_articles, :conditions => [ 'articles.type IN (?)', text_article_types ] |
456 | + named_scope :with_types, lambda { |types| { :conditions => [ 'articles.type IN (?)', types ] } } | |
467 | 457 | |
468 | 458 | named_scope :more_popular, :order => 'hits DESC' |
469 | 459 | named_scope :more_comments, :order => "comments_count DESC" |
... | ... | @@ -596,6 +586,22 @@ class Article < ActiveRecord::Base |
596 | 586 | false |
597 | 587 | end |
598 | 588 | |
589 | + def folder? | |
590 | + false | |
591 | + end | |
592 | + | |
593 | + def blog? | |
594 | + false | |
595 | + end | |
596 | + | |
597 | + def forum? | |
598 | + false | |
599 | + end | |
600 | + | |
601 | + def uploaded_file? | |
602 | + false | |
603 | + end | |
604 | + | |
599 | 605 | def author |
600 | 606 | if versions.empty? |
601 | 607 | last_changed_by | ... | ... |
plugins/context_content/controllers/profile/context_content_plugin_profile_controller.rb
0 → 100644
... | ... | @@ -0,0 +1,19 @@ |
1 | +class ContextContentPluginProfileController < ProfileController | |
2 | + append_view_path File.join(File.dirname(__FILE__) + '/../../views') | |
3 | + | |
4 | + def view_content | |
5 | + block = Block.find(params[:id]) | |
6 | + p = params[:page].to_i | |
7 | + contents = block.contents(profile.articles.find(params[:article_id]), p) | |
8 | + | |
9 | + if contents | |
10 | + render :update do |page| | |
11 | + page.replace_html "context_content_#{block.id}", :file => "blocks/context_content", :locals => {:block => block, :contents => contents} | |
12 | + page.replace_html "context_content_more_#{block.id}", :partial => 'blocks/more', :locals => {:block => block, :contents => contents, :article_id => params[:article_id] } | |
13 | + end | |
14 | + else | |
15 | + render :text => "invalid page", :status => 500 | |
16 | + end | |
17 | + end | |
18 | + | |
19 | +end | ... | ... |
... | ... | @@ -0,0 +1,21 @@ |
1 | +class ContextContentPlugin < Noosfero::Plugin | |
2 | + | |
3 | + def self.plugin_name | |
4 | + "Display Context Content" | |
5 | + end | |
6 | + | |
7 | + def self.plugin_description | |
8 | + _("A plugin that display content based on page context.") | |
9 | + end | |
10 | + | |
11 | + def self.extra_blocks | |
12 | + { | |
13 | + ContextContentPlugin::ContextContentBlock => { :type => [Person, Community, Enterprise] } | |
14 | + } | |
15 | + end | |
16 | + | |
17 | + def stylesheet? | |
18 | + true | |
19 | + end | |
20 | + | |
21 | +end | ... | ... |
plugins/context_content/lib/context_content_plugin/context_content_block.rb
0 → 100644
... | ... | @@ -0,0 +1,96 @@ |
1 | +class ContextContentPlugin::ContextContentBlock < Block | |
2 | + | |
3 | + settings_items :show_name, :type => :boolean, :default => true | |
4 | + settings_items :show_image, :type => :boolean, :default => true | |
5 | + settings_items :show_parent_content, :type => :boolean, :default => true | |
6 | + settings_items :types, :type => Array, :default => ['UploadedFile'] | |
7 | + settings_items :limit, :type => :integer, :default => 6 | |
8 | + | |
9 | + alias :profile :owner | |
10 | + | |
11 | + include Noosfero::Plugin::HotSpot | |
12 | + | |
13 | + def self.description | |
14 | + _('Display context content') | |
15 | + end | |
16 | + | |
17 | + def help | |
18 | + _('This block displays content based on context.') | |
19 | + end | |
20 | + | |
21 | + def available_content_types | |
22 | + @available_content_types ||= [UploadedFile, Event, TinyMceArticle, TextileArticle, RawHTMLArticle, Folder, Blog, Forum, Gallery, RssFeed] + plugins.dispatch(:content_types) | |
23 | + checked_types = types.map {|t| t.constantize} | |
24 | + checked_types + (@available_content_types - checked_types) | |
25 | + end | |
26 | + | |
27 | + def first_content_types | |
28 | + available_content_types.first(first_types_count) | |
29 | + end | |
30 | + | |
31 | + def more_content_types | |
32 | + available_content_types.drop(first_types_count) | |
33 | + end | |
34 | + | |
35 | + def first_types_count | |
36 | + [2, types.length].max | |
37 | + end | |
38 | + | |
39 | + def types=(new_types) | |
40 | + settings[:types] = new_types.reject(&:blank?) | |
41 | + end | |
42 | + | |
43 | + def content_image(content) | |
44 | + block = self | |
45 | + lambda do | |
46 | + if content.image? | |
47 | + image_tag(content.public_filename(:thumb)) | |
48 | + else | |
49 | + extra_class = content.uploaded_file? ? "extension-#{content.extension}" : '' | |
50 | + klasses = [content.icon_name].flatten.map{|name| 'icon-'+name}.join(' ') | |
51 | + content_tag 'div', '', :class => "context-icon #{klasses} #{extra_class}" | |
52 | + end | |
53 | + end | |
54 | + end | |
55 | + | |
56 | + def contents(page, p=1) | |
57 | + return @children unless @children.blank? | |
58 | + if page | |
59 | + @children = page.children.with_types(types).paginate(:per_page => limit, :page => p) | |
60 | + (@children.blank? && show_parent_content) ? contents(page.parent, p) : @children | |
61 | + else | |
62 | + nil | |
63 | + end | |
64 | + end | |
65 | + | |
66 | + def footer | |
67 | + block = self | |
68 | + lambda do | |
69 | + contents = block.contents(@page) | |
70 | + if contents | |
71 | + content_tag('div', | |
72 | + render(:partial => 'blocks/more', :locals => {:block => block, :contents => contents, :article_id => @page.id}), :id => "context_content_more_#{block.id}", :class => "more_button") | |
73 | + else | |
74 | + '' | |
75 | + end | |
76 | + end | |
77 | + end | |
78 | + | |
79 | + def content(args={}) | |
80 | + block = self | |
81 | + lambda do | |
82 | + contents = block.contents(@page) | |
83 | + if !contents.blank? | |
84 | + block_title(block.title) + content_tag('div', | |
85 | + render(:file => 'blocks/context_content', :locals => {:block => block, :contents => contents}), :class => 'contents', :id => "context_content_#{block.id}") | |
86 | + else | |
87 | + '' | |
88 | + end | |
89 | + end | |
90 | + end | |
91 | + | |
92 | + def cacheable? | |
93 | + false | |
94 | + end | |
95 | + | |
96 | +end | ... | ... |
... | ... | @@ -0,0 +1,54 @@ |
1 | +.context-content-plugin_context-content-block .contents .item img { | |
2 | + width: 100%; | |
3 | + max-height: 60px; | |
4 | +} | |
5 | + | |
6 | +.context-content-plugin_context-content-block .contents .item .image { | |
7 | + height: 60px; | |
8 | +} | |
9 | + | |
10 | +.context-content-plugin_context-content-block .contents .item .context-icon { | |
11 | + background-repeat: no-repeat; | |
12 | + background-position: center; | |
13 | + height: 100%; | |
14 | +} | |
15 | + | |
16 | +.context-content-plugin_context-content-block .contents .item { | |
17 | + width: 60px; | |
18 | + height: 95px; | |
19 | + display: inline-block; | |
20 | + vertical-align: top; | |
21 | + margin: 5px; | |
22 | + list-style-type: none; | |
23 | + border: 1px solid #FFF; | |
24 | + padding: 5px; | |
25 | +} | |
26 | + | |
27 | +.context-content-plugin_context-content-block .contents .item:hover { | |
28 | + border: 1px solid #CCC; | |
29 | + -moz-border-radius: 5px; | |
30 | + -webkit-border-radius: 5px; | |
31 | + background: #EEE; | |
32 | + text-decoration: none; | |
33 | +} | |
34 | + | |
35 | +.context-content-plugin_context-content-block .contents .item .name { | |
36 | + text-align: center; | |
37 | + font-size: 8pt; | |
38 | + word-wrap: break-word; | |
39 | +} | |
40 | + | |
41 | +.context-content-plugin_context-content-block .contents .item a { | |
42 | + text-decoration: none; | |
43 | +} | |
44 | + | |
45 | +#content .context-content-plugin_context-content-block .contents .item .icon-text-html { background-image: url(/designs/icons/default/Tango/32x32/mimetypes/text-html.png) } | |
46 | +#content .context-content-plugin_context-content-block .contents .item .icon-application-pdf { background-image: url(/designs/icons/default/Tango/32x32/mimetypes/gnome-mime-application-pdf.png) } | |
47 | +#content .context-content-plugin_context-content-block .contents .item .icon-application-vnd-oasis-opendocument-text { background-image: url(/designs/icons/default/Tango/32x32/mimetypes/gnome-mime-application-vnd.oasis.opendocument.text.png) } | |
48 | +#content .context-content-plugin_context-content-block .contents .item .icon-folder { background-image: url(/designs/icons/default/Tango/32x32/places/folder.png) } | |
49 | +#content .context-content-plugin_context-content-block .contents .item .icon-text-plain { background-image: url(/designs/icons/default/Tango/32x32/mimetypes/text-x-generic.png) } | |
50 | +#content .context-content-plugin_context-content-block .contents .item .icon-blog { background-image: url(/designs/icons/default/mod/32x32/apps/text-editor.png) } | |
51 | +#content .context-content-plugin_context-content-block .contents .item .icon-forum { background-image: url(/designs/icons/default/Tango/32x32/apps/system-users.png) } | |
52 | +#content .context-content-plugin_context-content-block .contents .item .icon-gallery { background-image: url(/designs/icons/default/Tango/32x32/mimetypes/image-x-generic.png) } | |
53 | +#content .context-content-plugin_context-content-block .contents .item .icon-rss-feed { background-image: url(/images/icons-mime/rss-feed.png) } | |
54 | +#content .context-content-plugin_context-content-block .contents .item .icon-event { background-image: url(/designs/icons/default/Tango/32x32/mimetypes/stock_calendar.png) } | ... | ... |
plugins/context_content/test/functional/content_viewer_controller_test.rb
0 → 100644
... | ... | @@ -0,0 +1,46 @@ |
1 | +require 'test_helper' | |
2 | + | |
3 | +class ContentViewerController | |
4 | + append_view_path File.join(File.dirname(__FILE__) + '/../../views') | |
5 | + def rescue_action(e) | |
6 | + raise e | |
7 | + end | |
8 | +end | |
9 | + | |
10 | +class ContentViewerControllerTest < ActionController::TestCase | |
11 | + | |
12 | + def setup | |
13 | + @profile = fast_create(Community) | |
14 | + @page = fast_create(Folder, :profile_id => @profile.id) | |
15 | + | |
16 | + box = Box.create!(:owner => @profile) | |
17 | + @block = ContextContentPlugin::ContextContentBlock.new(:box => box) | |
18 | + @block.types = ['TinyMceArticle'] | |
19 | + @block.limit = 1 | |
20 | + @block.save! | |
21 | + end | |
22 | + | |
23 | + should 'do not display context content block if it has no contents' do | |
24 | + get :view_page, @page.url | |
25 | + assert_no_tag 'div', :attributes => {:id => "context_content_#{@block.id}", :class => 'contents'} | |
26 | + assert_no_tag 'div', :attributes => {:id => "context_content_more_#{@block.id}", :class => 'more_button'} | |
27 | + end | |
28 | + | |
29 | + should 'display context content block if it has contents' do | |
30 | + article = fast_create(TinyMceArticle, :parent_id => @page.id, :profile_id => @profile.id, :name => 'article1') | |
31 | + get :view_page, @page.url | |
32 | + assert_tag 'div', :attributes => {:id => "context_content_#{@block.id}", :class => 'contents'} | |
33 | + assert_no_tag 'div', :attributes => {:id => "context_content_more_#{@block.id}", :class => 'more_button'}, :descendant => {:tag => 'a'} | |
34 | + assert_match /article1/, @response.body | |
35 | + end | |
36 | + | |
37 | + should 'display context content block with pagination' do | |
38 | + article1 = fast_create(TinyMceArticle, :parent_id => @page.id, :profile_id => @profile.id) | |
39 | + article2 = fast_create(TinyMceArticle, :parent_id => @page.id, :profile_id => @profile.id) | |
40 | + get :view_page, @page.url | |
41 | + assert_tag 'div', :attributes => {:id => "context_content_#{@block.id}", :class => 'contents'} | |
42 | + assert_tag 'div', :attributes => {:id => "context_content_more_#{@block.id}", :class => 'more_button'}, :descendant => {:tag => 'a', :attributes => {:class => 'button icon-button icon-left disabled'} } | |
43 | + assert_tag 'div', :attributes => {:id => "context_content_more_#{@block.id}", :class => 'more_button'}, :descendant => {:tag => 'a', :attributes => {:class => 'button icon-button icon-right'} } | |
44 | + end | |
45 | + | |
46 | +end | ... | ... |
plugins/context_content/test/functional/context_content_plugin_profile_controller_test.rb
0 → 100644
... | ... | @@ -0,0 +1,43 @@ |
1 | +require 'test_helper' | |
2 | + | |
3 | +class ContextContentPluginProfileControllerTest < ActionController::TestCase | |
4 | + | |
5 | + class ContextContentPluginProfileController; def rescue_action(e) raise e end; end | |
6 | + | |
7 | + def setup | |
8 | + @profile = fast_create(Community) | |
9 | + @block = ContextContentPlugin::ContextContentBlock.new | |
10 | + @block.types = ['TinyMceArticle'] | |
11 | + @block.limit = 1 | |
12 | + @block.save! | |
13 | + @page = fast_create(Folder, :profile_id => @profile.id) | |
14 | + end | |
15 | + | |
16 | + should 'render response error if contents is nil' do | |
17 | + xhr :get, :view_content, :id => @block.id, :article_id => @page.id, :page => 1, :profile => @profile.identifier | |
18 | + assert_response 500 | |
19 | + end | |
20 | + | |
21 | + should 'render error if page do not exists' do | |
22 | + article = fast_create(TinyMceArticle, :parent_id => @page.id, :profile_id => @profile.id) | |
23 | + xhr :get, :view_content, :id => @block.id, :article_id => @page.id, :page => 2, :profile => @profile.identifier | |
24 | + assert_response 500 | |
25 | + end | |
26 | + | |
27 | + should 'replace div with content for page passed as parameter' do | |
28 | + article1 = fast_create(TinyMceArticle, :parent_id => @page.id, :profile_id => @profile.id, :name => 'article1') | |
29 | + article2 = fast_create(TinyMceArticle, :parent_id => @page.id, :profile_id => @profile.id, :name => 'article2') | |
30 | + xhr :get, :view_content, :id => @block.id, :article_id => @page.id, :page => 2, :profile => @profile.identifier | |
31 | + assert_response :success | |
32 | + assert_match /context_content_#{@block.id}/, @response.body | |
33 | + assert_match /context_content_more_#{@block.id}/, @response.body | |
34 | + assert_match /article2/, @response.body | |
35 | + end | |
36 | + | |
37 | + should 'do not render pagination buttons if it has only one page' do | |
38 | + article1 = fast_create(TinyMceArticle, :parent_id => @page.id, :profile_id => @profile.id, :name => 'article1') | |
39 | + xhr :get, :view_content, :id => @block.id, :article_id => @page.id, :page => 2, :profile => @profile.identifier | |
40 | + assert_no_match /context_content_more_#{@block.id}/, @response.body | |
41 | + end | |
42 | + | |
43 | +end | ... | ... |
plugins/context_content/test/functional/profile_design_controller_test.rb
0 → 100644
... | ... | @@ -0,0 +1,54 @@ |
1 | +require 'test_helper' | |
2 | + | |
3 | +class ProfileDesignController | |
4 | + append_view_path File.join(File.dirname(__FILE__) + '/../../views') | |
5 | + def rescue_action(e) | |
6 | + raise e | |
7 | + end | |
8 | +end | |
9 | + | |
10 | +class ProfileDesignControllerTest < ActionController::TestCase | |
11 | + | |
12 | + def setup | |
13 | + Environment.delete_all | |
14 | + @environment = Environment.create(:name => 'testenv', :is_default => true) | |
15 | + @environment.enabled_plugins = ['ContextContentPlugin'] | |
16 | + @environment.save! | |
17 | + | |
18 | + @profile = fast_create(Community, :environment_id => @environment.id) | |
19 | + @page = fast_create(Folder, :profile_id => @profile.id) | |
20 | + | |
21 | + box = Box.create!(:owner => @profile) | |
22 | + @block = ContextContentPlugin::ContextContentBlock.new(:box => box) | |
23 | + @block.types = ['TinyMceArticle'] | |
24 | + @block.limit = 1 | |
25 | + @block.save! | |
26 | + | |
27 | + user = create_user('testinguser') | |
28 | + @profile.add_admin(user.person) | |
29 | + login_as(user.login) | |
30 | + end | |
31 | + | |
32 | + should 'be able to edit context content block' do | |
33 | + get :edit, :id => @block.id, :profile => @profile.identifier | |
34 | + assert_tag :tag => 'input', :attributes => { :id => 'block_title' } | |
35 | + assert_tag :tag => 'input', :attributes => { :id => 'block_show_image' } | |
36 | + assert_tag :tag => 'input', :attributes => { :id => 'block_show_name' } | |
37 | + assert_tag :tag => 'input', :attributes => { :id => 'block_show_parent_content' } | |
38 | + assert_tag :tag => 'input', :attributes => { :id => 'block_types' } | |
39 | + end | |
40 | + | |
41 | + should 'be able to save TrackListBlock' do | |
42 | + @block.show_image = false | |
43 | + @block.show_name = false | |
44 | + @block.show_parent_content = false | |
45 | + @block.save! | |
46 | + get :edit, :id => @block.id, :profile => @profile.identifier | |
47 | + post :save, :id => @block.id, :block => {:title => 'context', :show_image => '0', :show_name => '0', :show_parent_content => '0', :types => ['TinyMceArticle', '', nil, 'Folder'] }, :profile => @profile.identifier | |
48 | + @block.reload | |
49 | + assert_equal 'context', @block.title | |
50 | + assert !@block.show_image && !@block.show_name && !@block.show_parent_content | |
51 | + assert_equal ['TinyMceArticle', 'Folder'], @block.types | |
52 | + end | |
53 | + | |
54 | +end | ... | ... |
plugins/context_content/test/unit/context_content_block_test.rb
0 → 100644
... | ... | @@ -0,0 +1,181 @@ |
1 | +require 'test_helper' | |
2 | + | |
3 | +class ContextContentBlockTest < ActiveSupport::TestCase | |
4 | + | |
5 | + def setup | |
6 | + Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([]) | |
7 | + @block = ContextContentPlugin::ContextContentBlock.create! | |
8 | + @block.types = ['TinyMceArticle'] | |
9 | + end | |
10 | + | |
11 | + should 'describe itself' do | |
12 | + assert_not_equal Block.description, ContextContentPlugin::ContextContentBlock.description | |
13 | + end | |
14 | + | |
15 | + should 'has a help' do | |
16 | + assert @block.help | |
17 | + end | |
18 | + | |
19 | + should 'return nothing if page is nil' do | |
20 | + assert_equal nil, @block.contents(nil) | |
21 | + end | |
22 | + | |
23 | + should 'render nothing if it has no content to show' do | |
24 | + assert_equal '', instance_eval(&@block.content) | |
25 | + end | |
26 | + | |
27 | + should 'render context content block view' do | |
28 | + @page = fast_create(Folder) | |
29 | + article = fast_create(TinyMceArticle, :parent_id => @page.id) | |
30 | + expects(:block_title).with(@block.title).returns('').once | |
31 | + expects(:content_tag).returns('').once | |
32 | + expects(:render).with(:file => 'blocks/context_content', :locals => {:block => @block, :contents => [article]}) | |
33 | + instance_eval(&@block.content) | |
34 | + end | |
35 | + | |
36 | + should 'return children of page' do | |
37 | + folder = fast_create(Folder) | |
38 | + article = fast_create(TinyMceArticle, :parent_id => folder.id) | |
39 | + assert_equal [article], @block.contents(folder) | |
40 | + end | |
41 | + | |
42 | + should 'limit number of children to display' do | |
43 | + @block.limit = 2 | |
44 | + folder = fast_create(Folder) | |
45 | + article1 = fast_create(TinyMceArticle, :parent_id => folder.id) | |
46 | + article2 = fast_create(TinyMceArticle, :parent_id => folder.id) | |
47 | + article3 = fast_create(TinyMceArticle, :parent_id => folder.id) | |
48 | + assert_equal 2, @block.contents(folder).length | |
49 | + end | |
50 | + | |
51 | + should 'show contents for next page' do | |
52 | + @block.limit = 2 | |
53 | + folder = fast_create(Folder) | |
54 | + article1 = fast_create(TinyMceArticle, :parent_id => folder.id) | |
55 | + article2 = fast_create(TinyMceArticle, :parent_id => folder.id) | |
56 | + article3 = fast_create(TinyMceArticle, :parent_id => folder.id) | |
57 | + assert_equal [article3], @block.contents(folder, 2) | |
58 | + end | |
59 | + | |
60 | + should 'show parent contents for next page' do | |
61 | + @block.limit = 2 | |
62 | + folder = fast_create(Folder) | |
63 | + article1 = fast_create(TinyMceArticle, :parent_id => folder.id) | |
64 | + article2 = fast_create(TinyMceArticle, :parent_id => folder.id) | |
65 | + article3 = fast_create(TinyMceArticle, :parent_id => folder.id) | |
66 | + assert_equal [article3], @block.contents(article1, 2) | |
67 | + end | |
68 | + | |
69 | + should 'return parent children if page has no children' do | |
70 | + folder = fast_create(Folder) | |
71 | + article = fast_create(TinyMceArticle, :parent_id => folder.id) | |
72 | + assert_equal [article], @block.contents(article) | |
73 | + end | |
74 | + | |
75 | + should 'do not return parent children if show_parent_content is false' do | |
76 | + @block.show_parent_content = false | |
77 | + folder = fast_create(Folder) | |
78 | + article = fast_create(TinyMceArticle, :parent_id => folder.id) | |
79 | + assert_equal [], @block.contents(article) | |
80 | + end | |
81 | + | |
82 | + should 'return nil if a page has no parent' do | |
83 | + folder = fast_create(Folder) | |
84 | + assert_equal nil, @block.contents(folder) | |
85 | + end | |
86 | + | |
87 | + should 'return available content types with checked types first' do | |
88 | + @block.types = ['TinyMceArticle', 'Folder'] | |
89 | + assert_equal [TinyMceArticle, Folder, UploadedFile, Event, TextileArticle, RawHTMLArticle, Blog, Forum, Gallery, RssFeed], @block.available_content_types | |
90 | + end | |
91 | + | |
92 | + should 'return available content types' do | |
93 | + @block.types = [] | |
94 | + assert_equal [UploadedFile, Event, TinyMceArticle, TextileArticle, RawHTMLArticle, Folder, Blog, Forum, Gallery, RssFeed], @block.available_content_types | |
95 | + end | |
96 | + | |
97 | + should 'return first 2 content types' do | |
98 | + assert_equal 2, @block.first_content_types.length | |
99 | + end | |
100 | + | |
101 | + should 'return all but first 2 content types' do | |
102 | + assert_equal @block.available_content_types.length - 2, @block.more_content_types.length | |
103 | + end | |
104 | + | |
105 | + should 'return 2 as default value for first_types_count' do | |
106 | + assert_equal 2, @block.first_types_count | |
107 | + end | |
108 | + | |
109 | + should 'return types length if it has more than 2 selected types' do | |
110 | + @block.types = ['UploadedFile', 'Event', 'Folder'] | |
111 | + assert_equal 3, @block.first_types_count | |
112 | + end | |
113 | + | |
114 | + should 'return selected types at first_content_types' do | |
115 | + @block.types = ['UploadedFile', 'Event', 'Folder'] | |
116 | + assert_equal [UploadedFile, Event, Folder], @block.first_content_types | |
117 | + assert_equal @block.available_content_types - [UploadedFile, Event, Folder], @block.more_content_types | |
118 | + end | |
119 | + | |
120 | + should 'include plugin content at available content types' do | |
121 | + class SomePluginContent;end | |
122 | + class SomePlugin; def content_types; SomePluginContent end end | |
123 | + Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([SomePlugin.new]) | |
124 | + | |
125 | + @block.types = [] | |
126 | + assert_equal [UploadedFile, Event, TinyMceArticle, TextileArticle, RawHTMLArticle, Folder, Blog, Forum, Gallery, RssFeed, SomePluginContent], @block.available_content_types | |
127 | + end | |
128 | + | |
129 | + should 'display thumbnail for image content' do | |
130 | + content = UploadedFile.new(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png')) | |
131 | + content = FilePresenter.for(content) | |
132 | + expects(:image_tag).once | |
133 | + instance_eval(&@block.content_image(content)) | |
134 | + end | |
135 | + | |
136 | + should 'display div as content image for content that is not a image' do | |
137 | + content = fast_create(Folder) | |
138 | + content = FilePresenter.for(content) | |
139 | + expects(:content_tag).once | |
140 | + instance_eval(&@block.content_image(content)) | |
141 | + end | |
142 | + | |
143 | + should 'display div with extension class for uploaded file that is not a image' do | |
144 | + content = UploadedFile.new(:uploaded_data => fixture_file_upload('/files/test.txt', 'text/plain')) | |
145 | + content = FilePresenter.for(content) | |
146 | + expects(:content_tag).with('div', '', :class => "context-icon icon-text icon-text-plain extension-txt").once | |
147 | + instance_eval(&@block.content_image(content)) | |
148 | + end | |
149 | + | |
150 | + should 'do not display pagination links if page is nil' do | |
151 | + @page = nil | |
152 | + assert_equal '', instance_eval(&@block.footer) | |
153 | + end | |
154 | + | |
155 | + should 'do not display pagination links if it has until one page' do | |
156 | + assert_equal '', instance_eval(&@block.footer) | |
157 | + end | |
158 | + | |
159 | + should 'display pagination links if it has more than one page' do | |
160 | + @block.limit = 2 | |
161 | + @page = fast_create(Folder) | |
162 | + article1 = fast_create(TinyMceArticle, :parent_id => @page.id) | |
163 | + article2 = fast_create(TinyMceArticle, :parent_id => @page.id) | |
164 | + article3 = fast_create(TinyMceArticle, :parent_id => @page.id) | |
165 | + expects(:content_tag).once | |
166 | + expects(:render).with(:partial => 'blocks/more', :locals => {:block => @block, :contents => [article1, article2], :article_id => @page.id}).once | |
167 | + instance_eval(&@block.footer) | |
168 | + end | |
169 | + | |
170 | + should 'return box owner on profile method call' do | |
171 | + profile = fast_create(Community) | |
172 | + box = Box.create(:owner_type => 'Profile', :owner_id => profile.id) | |
173 | + block = ContextContentPlugin::ContextContentBlock.create!(:box => box) | |
174 | + assert_equal profile, block.profile | |
175 | + end | |
176 | + | |
177 | + should 'not be cacheable' do | |
178 | + assert !@block.cacheable? | |
179 | + end | |
180 | + | |
181 | +end | ... | ... |
plugins/context_content/test/unit/context_content_plugin_test.rb
0 → 100644
... | ... | @@ -0,0 +1,48 @@ |
1 | +require 'test_helper' | |
2 | + | |
3 | +class ContextContentPluginTest < ActiveSupport::TestCase | |
4 | + | |
5 | + include Noosfero::Plugin::HotSpot | |
6 | + | |
7 | + def setup | |
8 | + @environment = fast_create(Environment) | |
9 | + @environment.enable_plugin(ContextContentPlugin) | |
10 | + end | |
11 | + | |
12 | + attr_reader :environment | |
13 | + | |
14 | + should 'has a name' do | |
15 | + assert_not_equal Noosfero::Plugin.plugin_name, ContextContentPlugin.plugin_name | |
16 | + end | |
17 | + | |
18 | + should 'describe itself' do | |
19 | + assert_not_equal Noosfero::Plugin.plugin_description, ContextContentPlugin.plugin_description | |
20 | + end | |
21 | + | |
22 | + should 'return ContextContentBlock in extra_blocks class method' do | |
23 | + assert ContextContentPlugin.extra_blocks.keys.include?(ContextContentPlugin::ContextContentBlock) | |
24 | + end | |
25 | + | |
26 | + should 'return false for class method has_admin_url?' do | |
27 | + assert !ContextContentPlugin.has_admin_url? | |
28 | + end | |
29 | + | |
30 | + should 'ContextContentBlock not available for environment' do | |
31 | + assert_not_includes plugins.dispatch(:extra_blocks, :type => Environment), ContextContentPlugin::ContextContentBlock | |
32 | + end | |
33 | + | |
34 | + should 'ContextContentBlock available for community' do | |
35 | + assert_includes plugins.dispatch(:extra_blocks, :type => Community), ContextContentPlugin::ContextContentBlock | |
36 | + end | |
37 | + | |
38 | + should 'has stylesheet' do | |
39 | + assert ContextContentPlugin.new.stylesheet? | |
40 | + end | |
41 | + | |
42 | + [Person, Community, Enterprise].each do |klass| | |
43 | + should "ContextContentBlock be available for #{klass.name}" do | |
44 | + assert_includes plugins.dispatch(:extra_blocks, :type => klass), ContextContentPlugin::ContextContentBlock | |
45 | + end | |
46 | + end | |
47 | + | |
48 | +end | ... | ... |
... | ... | @@ -0,0 +1,4 @@ |
1 | +<% if contents.total_pages > 1 %> | |
2 | + <%= link_to_remote(nil, :url => {:id => block.id, :controller => 'context_content_plugin_profile', :action => 'view_content', :page => contents.previous_page, :article_id => article_id }, :html => {:class => "button icon-button icon-left #{contents.previous_page ? '':'disabled'}".strip}, :condition => "#{!contents.previous_page.nil?}", :success => "jQuery('#context_content_#{block.id}').effect('slide', {direction: 'left'});" )%> | |
3 | + <%= link_to_remote(nil, :url => {:id => block.id, :controller => 'context_content_plugin_profile', :action => 'view_content', :page => contents.next_page, :article_id => article_id }, :html => {:class => "button icon-button icon-right #{contents.next_page ? '':'disabled'}".strip}, :condition => "#{!contents.next_page.nil?}", :success => "jQuery('#context_content_#{block.id}').effect('slide', {direction: 'right'});" )%> | |
4 | +<% end %> | ... | ... |
plugins/context_content/views/blocks/context_content.rhtml
0 → 100644
... | ... | @@ -0,0 +1,13 @@ |
1 | +<% contents.each do |content| %> | |
2 | + <% content = FilePresenter.for(content) %> | |
3 | + <span class="item"> | |
4 | + <a href="<%= url_for(content.view_url) %>"> | |
5 | + <div class="image"> | |
6 | + <%= instance_eval(&block.content_image(content)) if block.show_image %> | |
7 | + </div> | |
8 | + <% if block.show_name %> | |
9 | + <div class="name"><%= short_filename(content.name, 30) %></div> | |
10 | + <% end %> | |
11 | + </a> | |
12 | + </span> | |
13 | +<% end %> | ... | ... |
plugins/context_content/views/box_organizer/context_content_plugin/_context_content_block.rhtml
0 → 100644
... | ... | @@ -0,0 +1,23 @@ |
1 | +<div id='edit-context-content-block'> | |
2 | + <%= labelled_form_field _('Limit of items'), text_field(:block, :limit, :size => 3) %> | |
3 | + <%= labelled_form_field check_box(:block, :show_name) + _('Show content name'), '' %> | |
4 | + <%= labelled_form_field check_box(:block, :show_image) + _('Show content image'), '' %> | |
5 | + <%= labelled_form_field check_box(:block, :show_parent_content) + _('Show parent content when children is empty'), '' %> | |
6 | + | |
7 | + <br/> | |
8 | + <%= label :block, :types, _('Display content types:'), :class => 'formlabel' %> | |
9 | + <div class="content_types"> | |
10 | + <% @block.first_content_types.each do |type| %> | |
11 | + <%= labelled_form_field check_box(:block, 'types', {:multiple => true}, type.name, nil) + _(type.short_description), '' %> | |
12 | + <% end %> | |
13 | + <% if !@block.more_content_types.empty? %> | |
14 | + <a href="#" onclick="jQuery('.content_types .more').toggle(); return false;"><%= _('more') %></a> | |
15 | + <% end %> | |
16 | + <div class="more" style="display: none"> | |
17 | + <% @block.more_content_types.each do |type| %> | |
18 | + <%= labelled_form_field check_box(:block, 'types', {:multiple => true}, type.name, nil) + _(type.short_description), '' %> | |
19 | + <% end %> | |
20 | + </div> | |
21 | + </div> | |
22 | + <br/> | |
23 | +</div> | ... | ... |
plugins/context_content/views/profile_design/context_content_plugin
0 → 120000
test/unit/article_test.rb
... | ... | @@ -1773,4 +1773,17 @@ class ArticleTest < ActiveSupport::TestCase |
1773 | 1773 | end |
1774 | 1774 | end |
1775 | 1775 | |
1776 | + should 'return articles with specific types' do | |
1777 | + Article.delete_all | |
1778 | + | |
1779 | + c1 = fast_create(TinyMceArticle, :name => 'Testing article 1', :body => 'Article body 1', :profile_id => profile.id) | |
1780 | + c2 = fast_create(TextArticle, :name => 'Testing article 2', :body => 'Article body 2', :profile_id => profile.id) | |
1781 | + c3 = fast_create(Event, :name => 'Testing article 3', :body => 'Article body 3', :profile_id => profile.id) | |
1782 | + c4 = fast_create(RssFeed, :name => 'Testing article 4', :body => 'Article body 4', :profile_id => profile.id) | |
1783 | + c5 = fast_create(TextileArticle, :name => 'Testing article 5', :body => 'Article body 5', :profile_id => profile.id) | |
1784 | + | |
1785 | + assert_equivalent [c1,c2], Article.with_types(['TinyMceArticle', 'TextArticle']) | |
1786 | + assert_equivalent [c3], Article.with_types(['Event']) | |
1787 | + end | |
1788 | + | |
1776 | 1789 | end | ... | ... |