Commit a3b43b3b8f4f96aea89b12ee97f08fd5211813e4
1 parent
745bd505
Exists in
master
and in
22 other branches
Plugin to create a block that display content based on page context
Showing
9 changed files
with
299 additions
and
0 deletions
Show diff stats
@@ -0,0 +1,68 @@ | @@ -0,0 +1,68 @@ | ||
1 | +class 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 | + | ||
8 | + settings_items :limit, :type => :integer, :default => 6 | ||
9 | + | ||
10 | + include Noosfero::Plugin::HotSpot | ||
11 | + | ||
12 | + def self.description | ||
13 | + _('Display context content') | ||
14 | + end | ||
15 | + | ||
16 | + def help | ||
17 | + _('This block displays content based on context.') | ||
18 | + end | ||
19 | + | ||
20 | + def available_content_types | ||
21 | + @available_content_types ||= [TinyMceArticle, TextileArticle, RawHTMLArticle, Event, Folder, Blog, UploadedFile, Forum, Gallery, RssFeed] + plugins.dispatch(:content_types) | ||
22 | + end | ||
23 | + | ||
24 | + def types=(new_types) | ||
25 | + settings[:types] = new_types.reject(&:blank?) | ||
26 | + end | ||
27 | + | ||
28 | + def content_image(content) | ||
29 | + block = self | ||
30 | + lambda do | ||
31 | + if content.image? | ||
32 | + image_tag(content.public_filename(:thumb)) | ||
33 | + else | ||
34 | + extra_class = content.kind_of?(UploadedFile) ? "extension-#{content.extension}" : '' | ||
35 | + content_tag 'div', '', :class => "context-icon icon-#{content.class.icon_name(content)} #{extra_class}" | ||
36 | + end | ||
37 | + end | ||
38 | + end | ||
39 | + | ||
40 | + def contents(page) | ||
41 | + if page | ||
42 | + children = page.children.with_types(types).limit(limit) | ||
43 | + (children.blank? && show_parent_content) ? contents(page.parent) : children | ||
44 | + else | ||
45 | + nil | ||
46 | + end | ||
47 | + end | ||
48 | + | ||
49 | +# FIXME | ||
50 | +# def footer | ||
51 | +# lambda do | ||
52 | +# link_to(_('View all'), '') | ||
53 | +# end | ||
54 | +# end | ||
55 | + | ||
56 | + def content(args={}) | ||
57 | + block = self | ||
58 | + lambda do | ||
59 | + contents = block.contents(@page) | ||
60 | + if !contents.blank? | ||
61 | + render :file => 'blocks/context_content', :locals => {:block => block, :contents => contents} | ||
62 | + else | ||
63 | + '' | ||
64 | + end | ||
65 | + end | ||
66 | + end | ||
67 | + | ||
68 | +end |
@@ -0,0 +1,21 @@ | @@ -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 | + ContextContentBlock => { :type => [Person, Community, Enterprise] } | ||
14 | + } | ||
15 | + end | ||
16 | + | ||
17 | + def stylesheet? | ||
18 | + true | ||
19 | + end | ||
20 | + | ||
21 | +end |
@@ -0,0 +1,38 @@ | @@ -0,0 +1,38 @@ | ||
1 | +.context-content-block .contents .item img { | ||
2 | + width: 100%; | ||
3 | +} | ||
4 | + | ||
5 | +.context-content-block .contents .item .context-icon { | ||
6 | + background-size: cover; | ||
7 | + background-repeat: no-repeat; | ||
8 | + background-position: center; | ||
9 | + height: 60px; | ||
10 | +} | ||
11 | + | ||
12 | +.context-content-block .contents .item { | ||
13 | + width: 60px; | ||
14 | + display: inline-block; | ||
15 | + vertical-align: top; | ||
16 | + margin: 5px; | ||
17 | + list-style-type: none; | ||
18 | + border: 1px solid #FFF; | ||
19 | + padding: 5px; | ||
20 | +} | ||
21 | + | ||
22 | +.context-content-block .contents .item:hover { | ||
23 | + border: 1px solid #CCC; | ||
24 | + -moz-border-radius: 5px; | ||
25 | + -webkit-border-radius: 5px; | ||
26 | + background: #EEE; | ||
27 | + text-decoration: none; | ||
28 | +} | ||
29 | + | ||
30 | +.context-content-block .contents .item .name { | ||
31 | + text-align: center; | ||
32 | + font-size: 8pt; | ||
33 | + word-wrap: break-word; | ||
34 | +} | ||
35 | + | ||
36 | +.context-content-block .contents .item a { | ||
37 | + text-decoration: none; | ||
38 | +} |
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../test/test_helper' |
plugins/context_content/test/unit/context_content_block_test.rb
0 → 100644
@@ -0,0 +1,97 @@ | @@ -0,0 +1,97 @@ | ||
1 | +require File.dirname(__FILE__) + '/../test_helper' | ||
2 | + | ||
3 | +class ContextContentBlockTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([]) | ||
7 | + @block = ContextContentBlock.create! | ||
8 | + @block.types = ['TinyMceArticle'] | ||
9 | + end | ||
10 | + | ||
11 | + should 'describe itself' do | ||
12 | + assert_not_equal Block.description, 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(:render).with(:file => 'blocks/context_content', :locals => {:block => @block, :contents => [article]}) | ||
31 | + instance_eval(&@block.content) | ||
32 | + end | ||
33 | + | ||
34 | + should 'return children of page' do | ||
35 | + folder = fast_create(Folder) | ||
36 | + article = fast_create(TinyMceArticle, :parent_id => folder.id) | ||
37 | + assert_equal [article], @block.contents(folder) | ||
38 | + end | ||
39 | + | ||
40 | + should 'limit number of children to display' do | ||
41 | + @block.limit = 2 | ||
42 | + folder = fast_create(Folder) | ||
43 | + article1 = fast_create(TinyMceArticle, :parent_id => folder.id) | ||
44 | + article2 = fast_create(TinyMceArticle, :parent_id => folder.id) | ||
45 | + article3 = fast_create(TinyMceArticle, :parent_id => folder.id) | ||
46 | + assert_equivalent [article1, article2], @block.contents(folder) | ||
47 | + end | ||
48 | + | ||
49 | + should 'return parent children if page has no children' do | ||
50 | + folder = fast_create(Folder) | ||
51 | + article = fast_create(TinyMceArticle, :parent_id => folder.id) | ||
52 | + assert_equal [article], @block.contents(article) | ||
53 | + end | ||
54 | + | ||
55 | + should 'do not return parent children if show_parent_content is false' do | ||
56 | + @block.show_parent_content = false | ||
57 | + folder = fast_create(Folder) | ||
58 | + article = fast_create(TinyMceArticle, :parent_id => folder.id) | ||
59 | + assert_equal [], @block.contents(article) | ||
60 | + end | ||
61 | + | ||
62 | + should 'return nil if a page has no parent' do | ||
63 | + folder = fast_create(Folder) | ||
64 | + assert_equal nil, @block.contents(folder) | ||
65 | + end | ||
66 | + | ||
67 | + should 'return available content types' do | ||
68 | + assert_equal [TinyMceArticle, TextileArticle, RawHTMLArticle, Event, Folder, Blog, UploadedFile, Forum, Gallery, RssFeed], @block.available_content_types | ||
69 | + end | ||
70 | + | ||
71 | + should 'include plugin content at available content types' do | ||
72 | + class SomePluginContent;end | ||
73 | + class SomePlugin; def content_types; SomePluginContent end end | ||
74 | + Noosfero::Plugin::Manager.any_instance.stubs(:enabled_plugins).returns([SomePlugin.new]) | ||
75 | + | ||
76 | + assert_equal [TinyMceArticle, TextileArticle, RawHTMLArticle, Event, Folder, Blog, UploadedFile, Forum, Gallery, RssFeed, SomePluginContent], @block.available_content_types | ||
77 | + end | ||
78 | + | ||
79 | + should 'display thumbnail for image content' do | ||
80 | + content = UploadedFile.new(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png')) | ||
81 | + expects(:image_tag).once | ||
82 | + instance_eval(&@block.content_image(content)) | ||
83 | + end | ||
84 | + | ||
85 | + should 'display div as content image for content that is not a image' do | ||
86 | + content = fast_create(Folder) | ||
87 | + expects(:content_tag).once | ||
88 | + instance_eval(&@block.content_image(content)) | ||
89 | + end | ||
90 | + | ||
91 | + should 'display div with extension class for uploaded file that is not a image' do | ||
92 | + content = UploadedFile.new(:uploaded_data => fixture_file_upload('/files/test.txt', 'text/plain')) | ||
93 | + expects(:content_tag).with('div', '', :class => "context-icon icon-text-plain extension-txt").once | ||
94 | + instance_eval(&@block.content_image(content)) | ||
95 | + end | ||
96 | + | ||
97 | +end |
plugins/context_content/test/unit/context_content_plugin_test.rb
0 → 100644
@@ -0,0 +1,48 @@ | @@ -0,0 +1,48 @@ | ||
1 | +require File.dirname(__FILE__) + '/../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?(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), ContextContentBlock | ||
32 | + end | ||
33 | + | ||
34 | + should 'ContextContentBlock available for community' do | ||
35 | + assert_includes plugins.dispatch(:extra_blocks, :type => Community), 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), ContextContentBlock | ||
45 | + end | ||
46 | + end | ||
47 | + | ||
48 | +end |
plugins/context_content/views/blocks/context_content.rhtml
0 → 100644
@@ -0,0 +1,14 @@ | @@ -0,0 +1,14 @@ | ||
1 | +<%= block_title(block.title) %> | ||
2 | + | ||
3 | +<div class="contents"> | ||
4 | +<% contents.each do |content| %> | ||
5 | + <span class="item"> | ||
6 | + <a href="<%= url_for(content.view_url) %>"> | ||
7 | + <%= instance_eval(&block.content_image(content)) if block.show_image %> | ||
8 | + <% if block.show_name %> | ||
9 | + <div class="name"><%= short_filename(content.name) %></div> | ||
10 | + <% end %> | ||
11 | + </a> | ||
12 | + </span> | ||
13 | +<% end %> | ||
14 | +</div> |
plugins/context_content/views/box_organizer/_context_content_block.rhtml
0 → 100644
@@ -0,0 +1,11 @@ | @@ -0,0 +1,11 @@ | ||
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 | + <p>Display content types:</p> | ||
8 | + <% @block.available_content_types.each do |type| %> | ||
9 | + <%= labelled_form_field check_box(:block, 'types', {:multiple => true}, type.name, nil) + _(type.short_description), '' %> | ||
10 | + <% end %> | ||
11 | +</div> |