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 @@ |
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 @@ |
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 @@ |
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 @@ |
1 | +require File.dirname(__FILE__) + '/../../../test/test_helper' | ... | ... |
plugins/context_content/test/unit/context_content_block_test.rb
0 → 100644
... | ... | @@ -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 @@ |
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 @@ |
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 @@ |
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> | ... | ... |