Commit 553f852ef8639e0b62cb928c9fcc3a9fd72435db
Committed by
Joenio Costa
1 parent
d273adf7
Exists in
master
and in
22 other branches
Creating a block to make some images highlighted on environment and enterprises
The user could choose which image It want to see at the moment, each image may also be associated with a link (ActionItem1564)
Showing
9 changed files
with
358 additions
and
2 deletions
Show diff stats
app/controllers/admin/environment_design_controller.rb
@@ -3,7 +3,7 @@ class EnvironmentDesignController < BoxOrganizerController | @@ -3,7 +3,7 @@ class EnvironmentDesignController < BoxOrganizerController | ||
3 | protect 'edit_environment_design', :environment | 3 | protect 'edit_environment_design', :environment |
4 | 4 | ||
5 | def available_blocks | 5 | def available_blocks |
6 | - @available_blocks ||= [ ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock ] | 6 | + @available_blocks ||= [ ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock ] |
7 | end | 7 | end |
8 | 8 | ||
9 | end | 9 | end |
app/controllers/my_profile/profile_design_controller.rb
@@ -23,6 +23,7 @@ class ProfileDesignController < BoxOrganizerController | @@ -23,6 +23,7 @@ class ProfileDesignController < BoxOrganizerController | ||
23 | # blocks exclusive for enterprises | 23 | # blocks exclusive for enterprises |
24 | if profile.enterprise? | 24 | if profile.enterprise? |
25 | blocks << DisabledEnterpriseMessageBlock | 25 | blocks << DisabledEnterpriseMessageBlock |
26 | + blocks << HighlightsBlock | ||
26 | end | 27 | end |
27 | 28 | ||
28 | # product block exclusive for enterprises in environments that permits it | 29 | # product block exclusive for enterprises in environments that permits it |
@@ -0,0 +1,38 @@ | @@ -0,0 +1,38 @@ | ||
1 | +class HighlightsBlock < Block | ||
2 | + | ||
3 | + settings_items :images, :type => Array, :default => [] | ||
4 | + settings_items :interval, :type => 'integer', :default => 4 | ||
5 | + settings_items :shuffle, :type => 'boolean', :default => false | ||
6 | + settings_items :navigation, :type => 'boolean', :default => false | ||
7 | + | ||
8 | + before_save do |block| | ||
9 | + block.images = block.images.delete_if { |i| i[:image_id].blank? and i[:address].blank? and i[:position].blank? and i[:title].blank? } | ||
10 | + block.images.each do |i| | ||
11 | + i[:image_id] = i[:image_id].to_i | ||
12 | + i[:position] = i[:position].to_i | ||
13 | + begin | ||
14 | + file = UploadedFile.find(i[:image_id]) | ||
15 | + i[:image_src] = file.public_filename | ||
16 | + rescue | ||
17 | + i[:image_src] = nil | ||
18 | + end | ||
19 | + end | ||
20 | + end | ||
21 | + | ||
22 | + def self.description | ||
23 | + _('Highlights') | ||
24 | + end | ||
25 | + | ||
26 | + def featured_images | ||
27 | + block_images = images.select{|i| !i[:image_src].nil? }.sort { |x, y| x[:position] <=> y[:position] } | ||
28 | + shuffle ? block_images.shuffle : block_images | ||
29 | + end | ||
30 | + | ||
31 | + def content | ||
32 | + block = self | ||
33 | + lambda do | ||
34 | + render :file => 'blocks/highlights', :locals => { :block => block } | ||
35 | + end | ||
36 | + end | ||
37 | + | ||
38 | +end |
@@ -0,0 +1,29 @@ | @@ -0,0 +1,29 @@ | ||
1 | +<%= block_title(block.title) %> | ||
2 | +<% if !block.featured_images.empty? %> | ||
3 | + <div class='highlights-border'> | ||
4 | + <div class='highlights-container'> | ||
5 | + <% block.featured_images.each do |img| %> | ||
6 | + <a href="<%= img[:address] %>" title="<%= img[:title] %>" class="highlights-image-link"> | ||
7 | + <%= content_tag :img, nil, :src => img[:image_src], :alt => img[:title] %> | ||
8 | + <p class="highlights-label"><%= img[:title] %></p> | ||
9 | + </a> | ||
10 | + <% end %> | ||
11 | + </div> | ||
12 | + <% if block.navigation %> | ||
13 | + <div class='highlights-block-pager'> | ||
14 | + </div> | ||
15 | + <% end %> | ||
16 | + </div> | ||
17 | + <p class="highlights-block-footer"></p> | ||
18 | + <script type="text/javascript"> | ||
19 | + (function($) { | ||
20 | + var options = {fx: 'fade', fastOnEvent: 1, timeout: <%= block.interval * 1000 %>}; | ||
21 | + <% if block.navigation %> | ||
22 | + options.pager = '#block-<%= block.id %> .highlights-block-pager'; | ||
23 | + <% end %> | ||
24 | + $('#block-<%= block.id %> .highlights-container').cycle(options); | ||
25 | + })(jQuery); | ||
26 | + </script> | ||
27 | +<% else %> | ||
28 | + <em><%= _('Please, edit this block and choose some images') %></em> | ||
29 | +<% end %> |
@@ -0,0 +1,32 @@ | @@ -0,0 +1,32 @@ | ||
1 | +<strong><%= _('Highlights') %></strong> | ||
2 | +<div id='edit-highlights-block'> | ||
3 | +<table id='highlights' class='noborder'> | ||
4 | + <tr><th><%= _('Image') %></th><th><%= _('Address') %></th><th><%= _('Position') %></th><th><%= _('Title') %></th></tr> | ||
5 | + <% for image in @block.images do %> | ||
6 | + <tr> | ||
7 | + <td> | ||
8 | + <%= select_tag 'block[images][][image_id]', content_tag(:option) + option_groups_from_collection_for_select(@block.box.owner.articles.select{|article| article.folder? && article.display_as_gallery? } , :images, :name, :id, :name, image[:image_id].to_i), :style => "width: 100px" %></p> | ||
9 | + </td> | ||
10 | + <td><%= text_field_tag 'block[images][][address]', image[:address], :class => 'highlight-address', :size => 10 %></td> | ||
11 | + <td><%= text_field_tag 'block[images][][position]', image[:position], :class => 'highlight-position', :size => 3 %></td> | ||
12 | + <td><%= text_field_tag 'block[images][][title]', image[:title], :class => 'highlight-title', :size => 10 %></td> | ||
13 | + </tr> | ||
14 | + <% end %> | ||
15 | +</table> | ||
16 | +</div> | ||
17 | + | ||
18 | +<%= link_to_function(_('New highlight'), nil, :class => 'button icon-add with-text') do |page| | ||
19 | + page.insert_html :bottom, 'highlights', content_tag('tr', | ||
20 | + content_tag('td', select_tag('block[images][][image_id]', content_tag(:option) + option_groups_from_collection_for_select(@block.box.owner.articles.select{|article| article.folder? && article.display_as_gallery? } , :images, :name, :id, :name), :style => "width: 100px")) + | ||
21 | + content_tag('td', text_field_tag('block[images][][address]', nil, :class => 'highlight-address', :size => 10)) + | ||
22 | + content_tag('td', text_field_tag('block[images][][position]', nil, :class => 'highlight-position', :size => 3)) + | ||
23 | + content_tag('td', text_field_tag('block[images][][title]', nil, :class => 'highlight-position', :size => 10)) | ||
24 | + ) + | ||
25 | + javascript_tag("$('edit-link-list-block').scrollTop = $('edit-link-list-block').scrollHeight") | ||
26 | +end %> | ||
27 | + | ||
28 | +<%= labelled_form_field _('Image transition:'), select('block', 'interval', [[_('No automatic transition'), 0]] + [1, 2, 3, 4, 5, 10, 20, 30, 60].map {|item| [n_('Every 1 second', 'Every %d seconds', item) % item, item]}) %> | ||
29 | + | ||
30 | +<%= labelled_form_field check_box(:block, :shuffle) + _('Show images in random order'), '' %> | ||
31 | + | ||
32 | +<%= labelled_form_field check_box(:block, :navigation) + _('Display navigation buttons'), '' %> |
public/stylesheets/application.css
@@ -3639,3 +3639,56 @@ h1#agenda-title { | @@ -3639,3 +3639,56 @@ h1#agenda-title { | ||
3639 | width: 500px; | 3639 | width: 500px; |
3640 | } | 3640 | } |
3641 | 3641 | ||
3642 | +/* highlights block stuff */ | ||
3643 | + | ||
3644 | +.highlights-block { | ||
3645 | + float: left; | ||
3646 | +} | ||
3647 | + | ||
3648 | +.highlights-block-pager { | ||
3649 | + border: 1px solid #ccc; | ||
3650 | + border-top: 0; | ||
3651 | + display: inline; | ||
3652 | + padding-right: 5px; | ||
3653 | +} | ||
3654 | + | ||
3655 | +.highlights-block-pager a { | ||
3656 | + text-decoration: none; | ||
3657 | + margin-left: 5px; | ||
3658 | +} | ||
3659 | + | ||
3660 | +.highlights-block-pager a.activeSlide:visited, | ||
3661 | +.highlights-block-pager a.activeSlide { | ||
3662 | + color: #000; | ||
3663 | +} | ||
3664 | + | ||
3665 | +.highlights-block a, | ||
3666 | +.highlights-block a:visited { | ||
3667 | + text-decoration: none; | ||
3668 | +} | ||
3669 | + | ||
3670 | +.highlights-image-link { | ||
3671 | + height: 150px; | ||
3672 | + width: 400px; | ||
3673 | + overflow: hidden; | ||
3674 | +} | ||
3675 | + | ||
3676 | +.highlights-label { | ||
3677 | + border: 0; | ||
3678 | + position: absolute; | ||
3679 | + bottom: 0; | ||
3680 | + z-index: 9999; | ||
3681 | + background-color: #000; | ||
3682 | + color: #fff; | ||
3683 | + text-decoration: none; | ||
3684 | + display: block; | ||
3685 | + width: 100%; | ||
3686 | + height: 30px; | ||
3687 | + overflow: hidden; | ||
3688 | + margin: 0; | ||
3689 | + padding: 4px 0; | ||
3690 | +} | ||
3691 | + | ||
3692 | +.highlights-image-link { | ||
3693 | + border: 1px solid #ccc; | ||
3694 | +} |
test/functional/environment_design_controller_test.rb
@@ -6,7 +6,7 @@ class EnvironmentDesignController; def rescue_action(e) raise e end; end | @@ -6,7 +6,7 @@ class EnvironmentDesignController; def rescue_action(e) raise e end; end | ||
6 | 6 | ||
7 | class EnvironmentDesignControllerTest < Test::Unit::TestCase | 7 | class EnvironmentDesignControllerTest < Test::Unit::TestCase |
8 | 8 | ||
9 | - ALL_BLOCKS = [ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock ] | 9 | + ALL_BLOCKS = [ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock ] |
10 | 10 | ||
11 | def setup | 11 | def setup |
12 | @controller = EnvironmentDesignController.new | 12 | @controller = EnvironmentDesignController.new |
test/functional/profile_design_controller_test.rb
@@ -5,6 +5,14 @@ class ProfileDesignController; def rescue_action(e) raise e end; end | @@ -5,6 +5,14 @@ class ProfileDesignController; def rescue_action(e) raise e end; end | ||
5 | 5 | ||
6 | class ProfileDesignControllerTest < Test::Unit::TestCase | 6 | class ProfileDesignControllerTest < Test::Unit::TestCase |
7 | 7 | ||
8 | + COMMOM_BLOCKS = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock] | ||
9 | + PERSON_BLOCKS = COMMOM_BLOCKS + [FriendsBlock, FavoriteEnterprisesBlock, CommunitiesBlock, EnterprisesBlock ] | ||
10 | + PERSON_BLOCKS_WITH_MEMBERS = PERSON_BLOCKS + [MembersBlock] | ||
11 | + PERSON_BLOCKS_WITH_BLOG = PERSON_BLOCKS + [BlogArchivesBlock] | ||
12 | + | ||
13 | + ENTERPRISE_BLOCKS = COMMOM_BLOCKS + [DisabledEnterpriseMessageBlock, HighlightsBlock] | ||
14 | + ENTERPRISE_BLOCKS_WITH_PRODUCTS_ENABLE = ENTERPRISE_BLOCKS + [ProductsBlock] | ||
15 | + | ||
8 | attr_reader :holder | 16 | attr_reader :holder |
9 | def setup | 17 | def setup |
10 | @controller = ProfileDesignController.new | 18 | @controller = ProfileDesignController.new |
@@ -324,4 +332,69 @@ class ProfileDesignControllerTest < Test::Unit::TestCase | @@ -324,4 +332,69 @@ class ProfileDesignControllerTest < Test::Unit::TestCase | ||
324 | assert_tag :tag => 'div', :attributes => {:id => 'access-denied'} | 332 | assert_tag :tag => 'div', :attributes => {:id => 'access-denied'} |
325 | end | 333 | end |
326 | 334 | ||
335 | + should 'the person blocks are all available' do | ||
336 | + profile = mock | ||
337 | + profile.stubs(:has_members?).returns(false) | ||
338 | + profile.stubs(:person?).returns(true) | ||
339 | + profile.stubs(:enterprise?).returns(false) | ||
340 | + profile.stubs(:has_blog?).returns(false) | ||
341 | + environment = mock | ||
342 | + profile.stubs(:environment).returns(environment) | ||
343 | + environment.stubs(:enabled?).returns(false) | ||
344 | + @controller.stubs(:profile).returns(profile) | ||
345 | + assert_equal PERSON_BLOCKS, @controller.available_blocks | ||
346 | + end | ||
347 | + | ||
348 | + should 'the person with members blocks are all available' do | ||
349 | + profile = mock | ||
350 | + profile.stubs(:has_members?).returns(true) | ||
351 | + profile.stubs(:person?).returns(true) | ||
352 | + profile.stubs(:enterprise?).returns(false) | ||
353 | + profile.stubs(:has_blog?).returns(false) | ||
354 | + environment = mock | ||
355 | + profile.stubs(:environment).returns(environment) | ||
356 | + environment.stubs(:enabled?).returns(false) | ||
357 | + @controller.stubs(:profile).returns(profile) | ||
358 | + assert_equal [], @controller.available_blocks - PERSON_BLOCKS_WITH_MEMBERS | ||
359 | + end | ||
360 | + | ||
361 | + should 'the person with blog blocks are all available' do | ||
362 | + profile = mock | ||
363 | + profile.stubs(:has_members?).returns(false) | ||
364 | + profile.stubs(:person?).returns(true) | ||
365 | + profile.stubs(:enterprise?).returns(false) | ||
366 | + profile.stubs(:has_blog?).returns(true) | ||
367 | + environment = mock | ||
368 | + profile.stubs(:environment).returns(environment) | ||
369 | + environment.stubs(:enabled?).returns(false) | ||
370 | + @controller.stubs(:profile).returns(profile) | ||
371 | + assert_equal [], @controller.available_blocks - PERSON_BLOCKS_WITH_BLOG | ||
372 | + end | ||
373 | + | ||
374 | + should 'the enterprise blocks are all available' do | ||
375 | + profile = mock | ||
376 | + profile.stubs(:has_members?).returns(false) | ||
377 | + profile.stubs(:person?).returns(false) | ||
378 | + profile.stubs(:enterprise?).returns(true) | ||
379 | + profile.stubs(:has_blog?).returns(false) | ||
380 | + environment = mock | ||
381 | + profile.stubs(:environment).returns(environment) | ||
382 | + environment.stubs(:enabled?).returns(true) | ||
383 | + @controller.stubs(:profile).returns(profile) | ||
384 | + assert_equal [], @controller.available_blocks - ENTERPRISE_BLOCKS | ||
385 | + end | ||
386 | + | ||
387 | + should 'the enterprise with products for enterprise enable blocks are all available' do | ||
388 | + profile = mock | ||
389 | + profile.stubs(:has_members?).returns(false) | ||
390 | + profile.stubs(:person?).returns(false) | ||
391 | + profile.stubs(:enterprise?).returns(true) | ||
392 | + profile.stubs(:has_blog?).returns(false) | ||
393 | + environment = mock | ||
394 | + profile.stubs(:environment).returns(environment) | ||
395 | + environment.stubs(:enabled?).returns(false) | ||
396 | + @controller.stubs(:profile).returns(profile) | ||
397 | + assert_equal [], @controller.available_blocks - ENTERPRISE_BLOCKS_WITH_PRODUCTS_ENABLE | ||
398 | + end | ||
399 | + | ||
327 | end | 400 | end |
@@ -0,0 +1,130 @@ | @@ -0,0 +1,130 @@ | ||
1 | +require File.dirname(__FILE__) + '/../test_helper' | ||
2 | + | ||
3 | +class HighlightsBlockTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + should 'default describe' do | ||
6 | + assert_not_equal Block.description, HighlightsBlock.description | ||
7 | + end | ||
8 | + | ||
9 | + should 'have field images' do | ||
10 | + h = HighlightsBlock.new | ||
11 | + assert_respond_to h, :images | ||
12 | + end | ||
13 | + | ||
14 | + should 'have field interval' do | ||
15 | + h = HighlightsBlock.new | ||
16 | + assert_respond_to h, :interval | ||
17 | + end | ||
18 | + | ||
19 | + should 'have field shuffle' do | ||
20 | + h = HighlightsBlock.new | ||
21 | + assert_respond_to h, :shuffle | ||
22 | + end | ||
23 | + | ||
24 | + should 'have field navigation' do | ||
25 | + h = HighlightsBlock.new | ||
26 | + assert_respond_to h, :navigation | ||
27 | + end | ||
28 | + | ||
29 | + should 'default value of images' do | ||
30 | + h = HighlightsBlock.new | ||
31 | + assert_equal [], h.images | ||
32 | + end | ||
33 | + | ||
34 | + should 'default interval between transitions is 4 seconds' do | ||
35 | + h = HighlightsBlock.new | ||
36 | + assert_equal 4, h.interval | ||
37 | + end | ||
38 | + | ||
39 | + should 'default value of shuffle' do | ||
40 | + h = HighlightsBlock.new | ||
41 | + assert_equal false, h.shuffle | ||
42 | + end | ||
43 | + | ||
44 | + should 'default value of navigation' do | ||
45 | + h = HighlightsBlock.new | ||
46 | + assert_equal false, h.navigation | ||
47 | + end | ||
48 | + | ||
49 | + should 'is editable' do | ||
50 | + h = HighlightsBlock.new | ||
51 | + assert h.editable? | ||
52 | + end | ||
53 | + | ||
54 | + should 'remove images with blank fields' do | ||
55 | + h = HighlightsBlock.new(:images => [{:image_id => 1, :address => '/address', :position => 1, :title => 'address'}, {:image_id => '', :address => '', :position => '', :title => ''}]) | ||
56 | + h.save! | ||
57 | + assert_equal [{:image_id => 1, :address => '/address', :position => 1, :title => 'address', :image_src => nil}], h.images | ||
58 | + end | ||
59 | + | ||
60 | + should 'be able to update display setting' do | ||
61 | + user = create_user('testinguser').person | ||
62 | + box = fast_create(Box, :owner_id => user.id) | ||
63 | + block = HighlightsBlock.create!(:display => 'never', :box => box) | ||
64 | + assert block.update_attributes!(:display => 'always') | ||
65 | + block.reload | ||
66 | + assert_equal 'always', block.display | ||
67 | + end | ||
68 | + | ||
69 | + should 'display highlights block' do | ||
70 | + block = HighlightsBlock.new | ||
71 | + self.expects(:render).with(:file => 'blocks/highlights', :locals => { :block => block}) | ||
72 | + | ||
73 | + instance_eval(& block.content) | ||
74 | + end | ||
75 | + | ||
76 | + should 'not list non existent image' do | ||
77 | + file = mock() | ||
78 | + UploadedFile.expects(:find).with(1).returns(file) | ||
79 | + file.expects(:public_filename).returns('address') | ||
80 | + block = HighlightsBlock.new(:images => [{:image_id => 1, :address => '/address', :position => 1, :title => 'address'}, {:image_id => '', :address => 'some', :position => '2', :title => 'Some'}]) | ||
81 | + block.save! | ||
82 | + block.reload | ||
83 | + assert_equal 2, block.images.count | ||
84 | + assert_equal [{:image_id => 1, :address => '/address', :position => 1, :title => 'address', :image_src => 'address'}], block.featured_images | ||
85 | + end | ||
86 | + | ||
87 | + should 'list images in order' do | ||
88 | + f1 = mock() | ||
89 | + f1.expects(:public_filename).returns('address') | ||
90 | + UploadedFile.expects(:find).with(1).returns(f1) | ||
91 | + f2 = mock() | ||
92 | + f2.expects(:public_filename).returns('address') | ||
93 | + UploadedFile.expects(:find).with(2).returns(f2) | ||
94 | + f3 = mock() | ||
95 | + f3.expects(:public_filename).returns('address') | ||
96 | + UploadedFile.expects(:find).with(3).returns(f3) | ||
97 | + block = HighlightsBlock.new | ||
98 | + i1 = {:image_id => 1, :address => '/address', :position => 3, :title => 'address'} | ||
99 | + i2 = {:image_id => 2, :address => '/address', :position => 1, :title => 'address'} | ||
100 | + i3 = {:image_id => 3, :address => '/address', :position => 2, :title => 'address'} | ||
101 | + block.images = [i1,i2,i3] | ||
102 | + block.save! | ||
103 | + block.reload | ||
104 | + assert_equal [i1,i2,i3], block.images | ||
105 | + assert_equal [i2,i3,i1], block.featured_images | ||
106 | + end | ||
107 | + | ||
108 | + should 'list images randomically' do | ||
109 | + f1 = mock() | ||
110 | + f1.expects(:public_filename).returns('address') | ||
111 | + UploadedFile.expects(:find).with(1).returns(f1) | ||
112 | + f2 = mock() | ||
113 | + f2.expects(:public_filename).returns('address') | ||
114 | + UploadedFile.expects(:find).with(2).returns(f2) | ||
115 | + f3 = mock() | ||
116 | + f3.expects(:public_filename).returns('address') | ||
117 | + UploadedFile.expects(:find).with(3).returns(f3) | ||
118 | + block = HighlightsBlock.new | ||
119 | + i1 = {:image_id => 1, :address => '/address', :position => 3, :title => 'address'} | ||
120 | + i2 = {:image_id => 2, :address => '/address', :position => 1, :title => 'address'} | ||
121 | + i3 = {:image_id => 3, :address => '/address', :position => 2, :title => 'address'} | ||
122 | + block.images = [i1,i2,i3] | ||
123 | + block.shuffle = true | ||
124 | + block.save! | ||
125 | + block.reload | ||
126 | + assert_equal [i1,i2,i3], block.images | ||
127 | + assert_not_equal [i2,i3,i1], block.featured_images | ||
128 | + end | ||
129 | + | ||
130 | +end |