Commit 553f852ef8639e0b62cb928c9fcc3a9fd72435db
Committed by
Joenio Costa
1 parent
d273adf7
Exists in
master
and in
29 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 | 3 | protect 'edit_environment_design', :environment |
4 | 4 | |
5 | 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 | 7 | end |
8 | 8 | |
9 | 9 | end | ... | ... |
app/controllers/my_profile/profile_design_controller.rb
... | ... | @@ -23,6 +23,7 @@ class ProfileDesignController < BoxOrganizerController |
23 | 23 | # blocks exclusive for enterprises |
24 | 24 | if profile.enterprise? |
25 | 25 | blocks << DisabledEnterpriseMessageBlock |
26 | + blocks << HighlightsBlock | |
26 | 27 | end |
27 | 28 | |
28 | 29 | # product block exclusive for enterprises in environments that permits it | ... | ... |
... | ... | @@ -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 @@ |
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 @@ |
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 | 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 | 6 | |
7 | 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 | 11 | def setup |
12 | 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 | 5 | |
6 | 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 | 16 | attr_reader :holder |
9 | 17 | def setup |
10 | 18 | @controller = ProfileDesignController.new |
... | ... | @@ -324,4 +332,69 @@ class ProfileDesignControllerTest < Test::Unit::TestCase |
324 | 332 | assert_tag :tag => 'div', :attributes => {:id => 'access-denied'} |
325 | 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 | 400 | end | ... | ... |
... | ... | @@ -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 | ... | ... |