Commit d9eb363116e58df526147cfdc1d529caa203484f
1 parent
6602995b
Exists in
master
and in
28 other branches
Adding new features to SlideshowBlock, and blocks in general
* added option to shuffle images * added navigation buttons * other changes: * Removed "toggle visibility" button and action in BoxOrganizer Controller * Bock#visible? now receives an optional context so that blocks can decide where they must be shown or not * BoxesHelper now passes the context into the Block#visible? method * Added title to Uploaded files and displaying it instead of the description when viewing files (ActionItem1358)
Showing
24 changed files
with
323 additions
and
95 deletions
Show diff stats
app/controllers/box_organizer_controller.rb
@@ -100,13 +100,6 @@ class BoxOrganizerController < ApplicationController | @@ -100,13 +100,6 @@ class BoxOrganizerController < ApplicationController | ||
100 | end | 100 | end |
101 | end | 101 | end |
102 | 102 | ||
103 | - def toggle_visibility | ||
104 | - @block = boxes_holder.blocks.find(params[:id]) | ||
105 | - @block.visible = !@block.visible? | ||
106 | - @block.save | ||
107 | - redirect_to :action => 'index' | ||
108 | - end | ||
109 | - | ||
110 | protected :boxes_editor? | 103 | protected :boxes_editor? |
111 | 104 | ||
112 | end | 105 | end |
app/helpers/boxes_helper.rb
@@ -59,10 +59,11 @@ module BoxesHelper | @@ -59,10 +59,11 @@ module BoxesHelper | ||
59 | end | 59 | end |
60 | 60 | ||
61 | def display_box_content(box, main_content) | 61 | def display_box_content(box, main_content) |
62 | - box_decorator.select_blocks(box.blocks).map { |item| display_block(item, main_content) }.join("\n") + box_decorator.block_target(box) | 62 | + context = { :article => @page } |
63 | + box_decorator.select_blocks(box.blocks, context).map { |item| display_block(item, main_content) }.join("\n") + box_decorator.block_target(box) | ||
63 | end | 64 | end |
64 | 65 | ||
65 | - def select_blocks(arr) | 66 | + def select_blocks(arr, context) |
66 | arr | 67 | arr |
67 | end | 68 | end |
68 | 69 | ||
@@ -83,7 +84,7 @@ module BoxesHelper | @@ -83,7 +84,7 @@ module BoxesHelper | ||
83 | end | 84 | end |
84 | 85 | ||
85 | options = { | 86 | options = { |
86 | - :class => classes = ['block', block.css_classes ].uniq.join(' '), | 87 | + :class => classes = ['block', block_css_classes(block) ].uniq.join(' '), |
87 | :id => "block-#{block.id}" | 88 | :id => "block-#{block.id}" |
88 | } | 89 | } |
89 | if ( block.respond_to? 'help' ) | 90 | if ( block.respond_to? 'help' ) |
@@ -134,8 +135,8 @@ module BoxesHelper | @@ -134,8 +135,8 @@ module BoxesHelper | ||
134 | def self.block_edit_buttons(block) | 135 | def self.block_edit_buttons(block) |
135 | '' | 136 | '' |
136 | end | 137 | end |
137 | - def self.select_blocks(arr) | ||
138 | - arr.select(&:visible?) | 138 | + def self.select_blocks(arr, context) |
139 | + arr.select { |block| block.visible?(context) } | ||
139 | end | 140 | end |
140 | end | 141 | end |
141 | 142 | ||
@@ -201,7 +202,6 @@ module BoxesHelper | @@ -201,7 +202,6 @@ module BoxesHelper | ||
201 | end | 202 | end |
202 | 203 | ||
203 | if !block.main? | 204 | if !block.main? |
204 | - buttons << icon_button(:eyes, _('Toggle block visibility'), {:action => 'toggle_visibility', :id => block.id}) | ||
205 | buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')}) | 205 | buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')}) |
206 | end | 206 | end |
207 | 207 | ||
@@ -217,8 +217,18 @@ module BoxesHelper | @@ -217,8 +217,18 @@ module BoxesHelper | ||
217 | end | 217 | end |
218 | 218 | ||
219 | def import_blocks_stylesheets(options = {}) | 219 | def import_blocks_stylesheets(options = {}) |
220 | - @blocks_css_files ||= current_blocks.map{|b|'blocks/' + b.css_class_name}.uniq | 220 | + @blocks_css_files ||= current_blocks.map{|b|'blocks/' + block_css_class_name(b)}.uniq |
221 | stylesheet_import(@blocks_css_files, options) | 221 | stylesheet_import(@blocks_css_files, options) |
222 | end | 222 | end |
223 | 223 | ||
224 | + def block_css_class_name(block) | ||
225 | + block.class.name.underscore.gsub('_', '-') | ||
226 | + end | ||
227 | + def block_css_classes(block) | ||
228 | + classes = block_css_class_name(block) | ||
229 | + classes += ' invisible-block' if block.display == 'never' | ||
230 | + classes | ||
231 | + end | ||
232 | + | ||
233 | + | ||
224 | end | 234 | end |
app/helpers/content_viewer_helper.rb
@@ -13,7 +13,7 @@ module ContentViewerHelper | @@ -13,7 +13,7 @@ module ContentViewerHelper | ||
13 | end | 13 | end |
14 | 14 | ||
15 | def article_title(article, args = {}) | 15 | def article_title(article, args = {}) |
16 | - title = article.abstract if article.kind_of?(UploadedFile) && article.image? | 16 | + title = article.display_title if article.kind_of?(UploadedFile) && article.image? |
17 | title = article.title if title.blank? | 17 | title = article.title if title.blank? |
18 | title = content_tag('h1', title, :class => 'title') | 18 | title = content_tag('h1', title, :class => 'title') |
19 | if article.belongs_to_blog? | 19 | if article.belongs_to_blog? |
@@ -35,4 +35,9 @@ module ContentViewerHelper | @@ -35,4 +35,9 @@ module ContentViewerHelper | ||
35 | link_to( number_of_comments(article), article.url.merge(:anchor => 'comments_list') ) | 35 | link_to( number_of_comments(article), article.url.merge(:anchor => 'comments_list') ) |
36 | end | 36 | end |
37 | 37 | ||
38 | + def image_label(image) | ||
39 | + text = image.title || image.abstract | ||
40 | + text && (text.first(40) + (text.size > 40 ? '…' : '')) | ||
41 | + end | ||
42 | + | ||
38 | end | 43 | end |
app/models/block.rb
@@ -11,14 +11,46 @@ class Block < ActiveRecord::Base | @@ -11,14 +11,46 @@ class Block < ActiveRecord::Base | ||
11 | belongs_to :box | 11 | belongs_to :box |
12 | 12 | ||
13 | acts_as_having_settings | 13 | acts_as_having_settings |
14 | - settings_items :visible, :type => :boolean, :default => true | ||
15 | 14 | ||
16 | named_scope :enabled, :conditions => { :enabled => true } | 15 | named_scope :enabled, :conditions => { :enabled => true } |
17 | 16 | ||
18 | - def visible? | ||
19 | - visible | 17 | + # Determines whether a given block must be visible. Optionally a |
18 | + # <tt>context</tt> must be specified. <tt>context</tt> must be a hash, and | ||
19 | + # may contain the following keys: | ||
20 | + # | ||
21 | + # * <tt>:article</tt>: the article being viewed currently | ||
22 | + def visible?(context = nil) | ||
23 | + if settings[:visible] == false || display == 'never' | ||
24 | + return false | ||
25 | + end | ||
26 | + if context && context[:article] && display == 'home_page_only' | ||
27 | + return context[:article] == owner.home_page | ||
28 | + end | ||
29 | + true | ||
30 | + end | ||
31 | + | ||
32 | + # The condition for displaying a block. It can assume the following values: | ||
33 | + # | ||
34 | + # * <tt>'always'</tt>: the block is always displayed | ||
35 | + # * <tt>'never'</tt>: the block is hidden (it does not appear for visitors) | ||
36 | + # * <tt>'home_page_only'</tt> the block is displayed only when viewing the | ||
37 | + # homepage of its owner. | ||
38 | + def display | ||
39 | + if settings[:visible] == false | ||
40 | + 'never' | ||
41 | + else | ||
42 | + settings[:display] || 'always' | ||
43 | + end | ||
44 | + end | ||
45 | + | ||
46 | + # Sets the <tt>value</tt> attribute. | ||
47 | + def display=(value) | ||
48 | + settings[:display] = value | ||
49 | + # clear the old setting | ||
50 | + settings[:visible] = nil | ||
20 | end | 51 | end |
21 | 52 | ||
53 | + | ||
22 | # returns the description of the block, used when the user sees a list of | 54 | # returns the description of the block, used when the user sees a list of |
23 | # blocks to choose one to include in the design. | 55 | # blocks to choose one to include in the design. |
24 | # | 56 | # |
@@ -66,16 +98,6 @@ class Block < ActiveRecord::Base | @@ -66,16 +98,6 @@ class Block < ActiveRecord::Base | ||
66 | box ? box.owner : nil | 98 | box ? box.owner : nil |
67 | end | 99 | end |
68 | 100 | ||
69 | - def css_class_name | ||
70 | - self.class.name.underscore.gsub('_', '-') | ||
71 | - end | ||
72 | - | ||
73 | - def css_classes | ||
74 | - classes = css_class_name | ||
75 | - classes += ' invisible-block' unless visible? | ||
76 | - classes | ||
77 | - end | ||
78 | - | ||
79 | def default_title | 101 | def default_title |
80 | '' | 102 | '' |
81 | end | 103 | end |
app/models/slideshow_block.rb
@@ -2,9 +2,11 @@ class SlideshowBlock < Block | @@ -2,9 +2,11 @@ class SlideshowBlock < Block | ||
2 | 2 | ||
3 | settings_items :gallery_id, :type => 'integer' | 3 | settings_items :gallery_id, :type => 'integer' |
4 | settings_items :interval, :type => 'integer', :default => 4 | 4 | settings_items :interval, :type => 'integer', :default => 4 |
5 | + settings_items :shuffle, :type => 'boolean', :default => false | ||
6 | + settings_items :navigation, :type => 'boolean', :default => false | ||
5 | 7 | ||
6 | def self.description | 8 | def self.description |
7 | - _('Display images from gallery as slideshow') | 9 | + _('Slideshow block') |
8 | end | 10 | end |
9 | 11 | ||
10 | def gallery | 12 | def gallery |
@@ -12,35 +14,18 @@ class SlideshowBlock < Block | @@ -12,35 +14,18 @@ class SlideshowBlock < Block | ||
12 | end | 14 | end |
13 | 15 | ||
14 | def content | 16 | def content |
17 | + block = self | ||
15 | if gallery | 18 | if gallery |
16 | images = gallery.images | 19 | images = gallery.images |
17 | - block_id = id | ||
18 | - block_title = title | ||
19 | - lambda do | ||
20 | - block_title(block_title) + | ||
21 | - content_tag('div', | ||
22 | - images.map do |i| | ||
23 | - link_to( | ||
24 | - content_tag('div', '', :style => "background-image: url(#{i.public_filename(:thumb)})"), | ||
25 | - (i.external_link || i.view_url), :target => '_blank' | ||
26 | - ) | ||
27 | - end.join("\n"), | ||
28 | - :class => 'slideshow-container' | ||
29 | - ) | 20 | + if shuffle |
21 | + images = images.shuffle | ||
30 | end | 22 | end |
31 | - else | ||
32 | lambda do | 23 | lambda do |
33 | - content_tag('em', _('Please select a gallery to display its images.')) | 24 | + render :file => 'blocks/slideshow', :locals => { :block => block, :images => images } |
34 | end | 25 | end |
35 | - end | ||
36 | - end | ||
37 | - | ||
38 | - def footer | ||
39 | - if gallery | ||
40 | - block_id = id | ||
41 | - interval_sec = interval * 1000 | 26 | + else |
42 | lambda do | 27 | lambda do |
43 | - javascript_tag("jQuery('#block-#{block_id} .slideshow-container').cycle({fx: 'fade', timeout: #{interval_sec}})") | 28 | + render :file => 'blocks/slideshow', :locals => { :block => block, :images => nil } |
44 | end | 29 | end |
45 | end | 30 | end |
46 | end | 31 | end |
app/models/uploaded_file.rb
@@ -4,6 +4,13 @@ | @@ -4,6 +4,13 @@ | ||
4 | # of the file itself is kept. (FIXME?) | 4 | # of the file itself is kept. (FIXME?) |
5 | class UploadedFile < Article | 5 | class UploadedFile < Article |
6 | 6 | ||
7 | + settings_items :title, :type => 'string' | ||
8 | + validates_size_of :title, :maximum => 60, :if => (lambda { |file| !file.title.blank? }) | ||
9 | + | ||
10 | + def display_title | ||
11 | + title.blank? ? name : title | ||
12 | + end | ||
13 | + | ||
7 | def self.max_size | 14 | def self.max_size |
8 | UploadedFile.attachment_options[:max_size] | 15 | UploadedFile.attachment_options[:max_size] |
9 | end | 16 | end |
@@ -74,11 +81,14 @@ class UploadedFile < Article | @@ -74,11 +81,14 @@ class UploadedFile < Article | ||
74 | :class => 'gallery-navigation' | 81 | :class => 'gallery-navigation' |
75 | ) | 82 | ) |
76 | end.to_s + | 83 | end.to_s + |
77 | - tag('img', :src => article.public_filename(:display), :class => article.css_class_name, :style => 'max-width: 100%') | 84 | + tag('img', :src => article.public_filename(:display), :class => article.css_class_name, :style => 'max-width: 100%') + |
85 | + content_tag('p', article.abstract, :class => 'uploaded-file-description') | ||
86 | + | ||
78 | end | 87 | end |
79 | else | 88 | else |
80 | lambda do | 89 | lambda do |
81 | - content_tag('ul', content_tag('li', link_to(article.name, article.url, :class => article.css_class_name))) | 90 | + content_tag('ul', content_tag('li', link_to(article.name, article.url, :class => article.css_class_name))) + |
91 | + content_tag('p', article.abstract, :class => 'uploaded-file-description') | ||
82 | end | 92 | end |
83 | end | 93 | end |
84 | end | 94 | end |
@@ -0,0 +1,49 @@ | @@ -0,0 +1,49 @@ | ||
1 | +<%= block_title(block.title) %> | ||
2 | +<% if images %> | ||
3 | + <% description = images.any? { |img| !img.abstract.blank? } %> | ||
4 | + <div class='slideshow-border<%= (description ? ' with-descriptions' : '')%>'> | ||
5 | + <div class='slideshow-container'> | ||
6 | + <% images.each do |img| %> | ||
7 | + <a href="<%= url_for(img.external_link.blank? ? img.view_url: img.external_link) %>"> | ||
8 | + <%= content_tag('div', '', :style => "background-image: url(#{img.public_filename(:thumb)})", :title => (img.abstract.blank? ? '' : img.abstract)) %> | ||
9 | + <% if !img.abstract.blank? %> | ||
10 | + <span class='image-description'><%= img.abstract %></span> | ||
11 | + <% end %> | ||
12 | + </a> | ||
13 | + <% end %> | ||
14 | + </div> | ||
15 | + <% if block.navigation %> | ||
16 | + <div class='slideshow-block-navigation'> | ||
17 | + <%= link_to _('Previous'), '#', :class => 'icon-media-prev' %> | ||
18 | + <% if block.interval > 0 %> | ||
19 | + <%= link_to ' ', '#', :class => 'icon-media-pause', :onclick => "togglePlayback('#block-#{block.id} .slideshow-container', this); return false;" %> | ||
20 | + <% end %> | ||
21 | + <%= link_to _('Next'), '#', :class => 'icon-media-next' %> | ||
22 | + </div> | ||
23 | + <% end %> | ||
24 | + </div> | ||
25 | + <script type="text/javascript"> | ||
26 | + (function($) { | ||
27 | + var options = {fx: 'fade', pause: 1, fastOnEvent: 1, timeout: <%= block.interval * 1000 %>}; | ||
28 | + <% if block.navigation %> | ||
29 | + options.prev = '#block-<%= block.id %> .icon-media-prev'; | ||
30 | + options.next = '#block-<%= block.id %> .icon-media-next'; | ||
31 | + <% end %> | ||
32 | + $('#block-<%= block.id %> .slideshow-container').cycle(options); | ||
33 | + })(jQuery); | ||
34 | + | ||
35 | + function togglePlayback(slideshow, button) { | ||
36 | + var $ = jQuery; | ||
37 | + if (button.className == 'icon-media-pause') { | ||
38 | + button.className = 'icon-media-play'; | ||
39 | + $(slideshow).cycle('pause'); | ||
40 | + } else { | ||
41 | + button.className = 'icon-media-pause'; | ||
42 | + $(slideshow).cycle('resume'); | ||
43 | + } | ||
44 | + } | ||
45 | + </script> | ||
46 | +<% else %> | ||
47 | + <em><%= _('Please, edit this block and select an image gallery.') %></em> | ||
48 | +<% end %> | ||
49 | + |
app/views/box_organizer/_slideshow_block.rhtml
@@ -3,4 +3,8 @@ | @@ -3,4 +3,8 @@ | ||
3 | [ _('%{gallery} (%{count} images)') % {:gallery => item.path, :count => item.images.count}, item.id ] | 3 | [ _('%{gallery} (%{count} images)') % {:gallery => item.path, :count => item.images.count}, item.id ] |
4 | }) %> | 4 | }) %> |
5 | 5 | ||
6 | -<%= labelled_form_field _('Seconds between image transitions'), select('block', 'interval', [1, 2, 3, 4, 5, 10, 20, 30, 60] ) %> | 6 | +<%= 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]}) %> |
7 | + | ||
8 | +<%= labelled_form_field check_box(:block, :shuffle) + _('Show images in random order'), '' %> | ||
9 | + | ||
10 | +<%= labelled_form_field check_box(:block, :navigation) + _('Display navigation buttons'), '' %> |
app/views/box_organizer/edit.rhtml
@@ -6,6 +6,18 @@ | @@ -6,6 +6,18 @@ | ||
6 | 6 | ||
7 | <%= render :partial => partial_for_class(@block.class) %> | 7 | <%= render :partial => partial_for_class(@block.class) %> |
8 | 8 | ||
9 | + <%= labelled_form_field _('Display this block:'), '' %> | ||
10 | + <div style='margin-left: 10px'> | ||
11 | + <%= radio_button(:block, :display, 'always') %> | ||
12 | + <%= label_tag('block_display_always', _('In all pages')) %> | ||
13 | + <br/> | ||
14 | + <%= radio_button(:block, :display, 'home_page_only') %> | ||
15 | + <%= label_tag('block_display_home_page_only', _('Only in the homepage')) %> | ||
16 | + <br/> | ||
17 | + <%= radio_button(:block, :display, 'never') %> | ||
18 | + <%= label_tag('block_display_never', _("Don't display")) %> | ||
19 | + </div> | ||
20 | + | ||
9 | <% button_bar do %> | 21 | <% button_bar do %> |
10 | <%= submit_button(:save, _('Save')) %> | 22 | <%= submit_button(:save, _('Save')) %> |
11 | <%= lightbox_close_button(_('Cancel')) %> | 23 | <%= lightbox_close_button(_('Cancel')) %> |
app/views/cms/_uploaded_file.rhtml
1 | -<%= labelled_form_field(_('Describe this file:'), text_area(:article, :abstract, :rows => 3, :cols => 64)) %> | 1 | +<%= labelled_form_field(_('Title'), text_field(:article, :title, :maxlength => 60)) %> |
2 | +<%= labelled_form_field(_('Description'), text_area(:article, :abstract, :rows => 3, :cols => 64)) %> | ||
2 | <% if @article.image? %> | 3 | <% if @article.image? %> |
3 | <%= f.text_field(:external_link, :size => 64) %> | 4 | <%= f.text_field(:external_link, :size => 64) %> |
4 | <% end %> | 5 | <% end %> |
app/views/content_viewer/_uploaded_file.rhtml
1 | <% if uploaded_file.image? %> | 1 | <% if uploaded_file.image? %> |
2 | - <div> <%= link_to image_tag(uploaded_file.public_filename(:thumb), :alt => uploaded_file.abstract), uploaded_file.view_url %> </div> | 2 | + <div> <%= link_to image_tag(uploaded_file.public_filename(:thumb), :alt => uploaded_file.display_title), uploaded_file.view_url %> </div> |
3 | + <span><%= image_label(uploaded_file) %></span> | ||
3 | <% else %> | 4 | <% else %> |
4 | <%= render :partial => 'article', :object => uploaded_file %> | 5 | <%= render :partial => 'article', :object => uploaded_file %> |
5 | <% end %> | 6 | <% end %> |
6 | - |
app/views/content_viewer/image_gallery.rhtml
@@ -8,7 +8,6 @@ | @@ -8,7 +8,6 @@ | ||
8 | <% @images.each do |a| %> | 8 | <% @images.each do |a| %> |
9 | <% content_tag('li', :title => a.abstract, :class => 'image-gallery-item' ) do %> | 9 | <% content_tag('li', :title => a.abstract, :class => 'image-gallery-item' ) do %> |
10 | <%= render :partial => partial_for_class(a.class), :object => a %> | 10 | <%= render :partial => partial_for_class(a.class), :object => a %> |
11 | - <span><%= a.abstract && (a.abstract.first(40) + (a.abstract.size > 40 ? '…' : ''))%></span> | ||
12 | <% end %> | 11 | <% end %> |
13 | <% end %> | 12 | <% end %> |
14 | </ul> | 13 | </ul> |
app/views/content_viewer/view_page.rhtml
@@ -19,7 +19,7 @@ | @@ -19,7 +19,7 @@ | ||
19 | </div> | 19 | </div> |
20 | <% end %> | 20 | <% end %> |
21 | 21 | ||
22 | -<div> | 22 | +<div<%= " class='logged-in'" if user %>> |
23 | <%= article_title(@page, :no_link => true) %> | 23 | <%= article_title(@page, :no_link => true) %> |
24 | <div id="article-actions"> | 24 | <div id="article-actions"> |
25 | <% if @page.allow_post_content?(user) %> | 25 | <% if @page.allow_post_content?(user) %> |
lib/tasks/release.rake
@@ -10,7 +10,7 @@ namespace :noosfero do | @@ -10,7 +10,7 @@ namespace :noosfero do | ||
10 | end | 10 | end |
11 | 11 | ||
12 | version = Noosfero::VERSION | 12 | version = Noosfero::VERSION |
13 | - desc 'checks if there is already a tag for the curren version' | 13 | + desc 'checks if there is already a tag for the current version' |
14 | task :check_tag do | 14 | task :check_tag do |
15 | sh "git tag | grep '^#{version}$' >/dev/null" do |ok, res| | 15 | sh "git tag | grep '^#{version}$' >/dev/null" do |ok, res| |
16 | if ok | 16 | if ok |
public/designs/icons/tango/style.css
@@ -64,3 +64,8 @@ | @@ -64,3 +64,8 @@ | ||
64 | .icon-slideshow { background-image: url(Tango/16x16/mimetypes/x-office-presentation.png) } | 64 | .icon-slideshow { background-image: url(Tango/16x16/mimetypes/x-office-presentation.png) } |
65 | .icon-photos { background-image: url(Tango/16x16/devices/camera-photo.png) } | 65 | .icon-photos { background-image: url(Tango/16x16/devices/camera-photo.png) } |
66 | 66 | ||
67 | +.icon-media-pause { background-image: url(Tango/16x16/actions/media-playback-pause.png) } | ||
68 | +.icon-media-play { background-image: url(Tango/16x16/actions/media-playback-start.png) } | ||
69 | +.icon-media-prev { background-image: url(Tango/16x16/actions/media-skip-backward.png) } | ||
70 | +.icon-media-next { background-image: url(Tango/16x16/actions/media-skip-forward.png) } | ||
71 | + |
public/designs/themes/base/article.css
@@ -16,8 +16,12 @@ hr.pre-posts, hr.sep-posts { | @@ -16,8 +16,12 @@ hr.pre-posts, hr.sep-posts { | ||
16 | overflow: visible; | 16 | overflow: visible; |
17 | } | 17 | } |
18 | 18 | ||
19 | +#article .logged-in h1 { | ||
20 | + margin-top: 25px; | ||
21 | +} | ||
22 | + | ||
19 | #article-actions { | 23 | #article-actions { |
20 | - top: -18px; | 24 | + top: -28px; |
21 | } | 25 | } |
22 | 26 | ||
23 | #article-actions a.button, | 27 | #article-actions a.button, |
public/stylesheets/blocks/slideshow-block.css
1 | .slideshow-block .slideshow-container { | 1 | .slideshow-block .slideshow-container { |
2 | - margin: auto; | 2 | + margin-bottom: 10px; |
3 | +} | ||
4 | + | ||
5 | +.slideshow-block .slideshow-container a { | ||
6 | + width: 100%; | ||
7 | + display: block; | ||
8 | + text-decoration: none; | ||
9 | +} | ||
10 | +.slideshow-block .slideshow-container a:hover { | ||
11 | + text-decoration: none; | ||
3 | } | 12 | } |
4 | 13 | ||
5 | .slideshow-block .slideshow-container div { | 14 | .slideshow-block .slideshow-container div { |
6 | - width: 130px; | ||
7 | height: 130px; | 15 | height: 130px; |
8 | background-position: 50% 50%; | 16 | background-position: 50% 50%; |
9 | background-repeat: no-repeat; | 17 | background-repeat: no-repeat; |
10 | - margin: auto; | 18 | +} |
19 | + | ||
20 | +.slideshow-block .with-descriptions { | ||
21 | + border: 1px solid #ddd; | ||
22 | +} | ||
23 | + | ||
24 | +.slideshow-block .image-description { | ||
25 | + display: block; | ||
26 | + padding: 10px; | ||
27 | + height: 34px; | ||
28 | + overflow: hidden; | ||
29 | + border-top: 1px solid #ddd; | ||
30 | + background-color: white; | ||
31 | + color: black; | ||
11 | } | 32 | } |
12 | 33 | ||
13 | .msie .slideshow-block .slideshow-container div { | 34 | .msie .slideshow-block .slideshow-container div { |
14 | cursor: pointer; | 35 | cursor: pointer; |
15 | } | 36 | } |
37 | + | ||
38 | +.slideshow-block { | ||
39 | + text-align: center; | ||
40 | +} | ||
41 | + | ||
42 | +.slideshow-block .slideshow-block-navigation { | ||
43 | + margin: 8px 0px; | ||
44 | +} | ||
45 | +.slideshow-block .slideshow-block-navigation a { | ||
46 | + background-color: white; | ||
47 | + background-repeat: no-repeat; | ||
48 | + border: 1px solid #ddd; | ||
49 | + padding: 2px; | ||
50 | + text-decoration: none; | ||
51 | + font-variant: small-caps; | ||
52 | + font-size: 10px; | ||
53 | +} | ||
54 | +.slideshow-block .slideshow-block-navigation a:hover { | ||
55 | + text-decoration: none; | ||
56 | + border-color: #999; | ||
57 | +} | ||
58 | + | ||
59 | +.slideshow-block .slideshow-block-navigation .icon-media-prev { | ||
60 | + padding-left: 18px; | ||
61 | + background-position: left; | ||
62 | +} | ||
63 | +.slideshow-block .slideshow-block-navigation .icon-media-next { | ||
64 | + padding-right: 18px; | ||
65 | + background-position: right; | ||
66 | + | ||
67 | +} | ||
68 | +.slideshow-block .slideshow-block-navigation .icon-media-pause, | ||
69 | +.slideshow-block .slideshow-block-navigation .icon-media-play { | ||
70 | + background-position: 50% 50%; | ||
71 | + display: inline-block; | ||
72 | + width: 16px; | ||
73 | +} |
public/stylesheets/controller_content_viewer.css
@@ -65,3 +65,10 @@ div#article-parent { | @@ -65,3 +65,10 @@ div#article-parent { | ||
65 | #article .gallery-navigation .total-of-images { | 65 | #article .gallery-navigation .total-of-images { |
66 | font-weight: bold; | 66 | font-weight: bold; |
67 | } | 67 | } |
68 | + | ||
69 | +#article .uploaded-file-description { | ||
70 | + background: #f6f6f6; | ||
71 | + border-top: 1px solid #ccc; | ||
72 | + border-bottom: 1px solid #ccc; | ||
73 | + padding: 1em; | ||
74 | +} |
test/functional/application_controller_test.rb
@@ -406,7 +406,7 @@ class ApplicationControllerTest < Test::Unit::TestCase | @@ -406,7 +406,7 @@ class ApplicationControllerTest < Test::Unit::TestCase | ||
406 | p = create_user_full('test_user').person | 406 | p = create_user_full('test_user').person |
407 | @controller.expects(:profile).at_least_once.returns(p) | 407 | @controller.expects(:profile).at_least_once.returns(p) |
408 | b = p.blocks[1] | 408 | b = p.blocks[1] |
409 | - b.expects(:visible).returns(false) | 409 | + b.expects(:visible?).returns(false) |
410 | b.save! | 410 | b.save! |
411 | 411 | ||
412 | get :index, :profile => p.identifier | 412 | get :index, :profile => p.identifier |
test/functional/profile_design_controller_test.rb
@@ -285,15 +285,6 @@ class ProfileDesignControllerTest < Test::Unit::TestCase | @@ -285,15 +285,6 @@ class ProfileDesignControllerTest < Test::Unit::TestCase | ||
285 | assert_no_tag :tag => 'input', :attributes => { :id => 'type_blogarchivesblock', :value => 'BlogArchivesBlock' } | 285 | assert_no_tag :tag => 'input', :attributes => { :id => 'type_blogarchivesblock', :value => 'BlogArchivesBlock' } |
286 | end | 286 | end |
287 | 287 | ||
288 | - should 'toggle block visibility' do | ||
289 | - state = @b1.visible? | ||
290 | - get :toggle_visibility, :id => @b1.id, :profile => holder.identifier | ||
291 | - block = Block.find(@b1.id) | ||
292 | - | ||
293 | - assert_equal block, assigns(:block) | ||
294 | - assert_equal !state, block.visible? | ||
295 | - end | ||
296 | - | ||
297 | should 'offer to create feed reader block' do | 288 | should 'offer to create feed reader block' do |
298 | get :add_block, :profile => 'designtestuser' | 289 | get :add_block, :profile => 'designtestuser' |
299 | assert_tag :tag => 'input', :attributes => { :id => 'type_feedreaderblock', :value => 'FeedReaderBlock' } | 290 | assert_tag :tag => 'input', :attributes => { :id => 'type_feedreaderblock', :value => 'FeedReaderBlock' } |
test/unit/block_test.rb
@@ -22,12 +22,6 @@ class BlockTest < Test::Unit::TestCase | @@ -22,12 +22,6 @@ class BlockTest < Test::Unit::TestCase | ||
22 | assert_nil Block.new.owner | 22 | assert_nil Block.new.owner |
23 | end | 23 | end |
24 | 24 | ||
25 | - should 'generate CSS class name' do | ||
26 | - block = Block.new | ||
27 | - block.class.expects(:name).returns('SomethingBlock') | ||
28 | - assert_equal 'something-block', block.css_class_name | ||
29 | - end | ||
30 | - | ||
31 | should 'provide no footer by default' do | 25 | should 'provide no footer by default' do |
32 | assert_nil Block.new.footer | 26 | assert_nil Block.new.footer |
33 | end | 27 | end |
@@ -52,12 +46,18 @@ class BlockTest < Test::Unit::TestCase | @@ -52,12 +46,18 @@ class BlockTest < Test::Unit::TestCase | ||
52 | assert_equal 'my title', b.view_title | 46 | assert_equal 'my title', b.view_title |
53 | end | 47 | end |
54 | 48 | ||
55 | - should 'have a visible setting' do | 49 | + should 'be backwards compatible with old "visible" setting' do |
56 | b = Block.new | 50 | b = Block.new |
57 | - assert b.visible? | ||
58 | - b.visible = false | ||
59 | - b.save | 51 | + b.settings[:visible] = false |
60 | assert !b.visible? | 52 | assert !b.visible? |
53 | + assert_equal 'never', b.display | ||
54 | + end | ||
55 | + | ||
56 | + should 'clean old "visible setting" when display is set' do | ||
57 | + b = Block.new | ||
58 | + b.settings[:visible] = false | ||
59 | + b.display = 'never' | ||
60 | + assert_nil b.settings[:visible] | ||
61 | end | 61 | end |
62 | 62 | ||
63 | should 'be cacheable' do | 63 | should 'be cacheable' do |
@@ -80,4 +80,24 @@ class BlockTest < Test::Unit::TestCase | @@ -80,4 +80,24 @@ class BlockTest < Test::Unit::TestCase | ||
80 | assert_not_includes Block.enabled, block2 | 80 | assert_not_includes Block.enabled, block2 |
81 | end | 81 | end |
82 | 82 | ||
83 | + should 'be displayed everywhere by default' do | ||
84 | + assert_equal true, Block.new.visible? | ||
85 | + end | ||
86 | + | ||
87 | + should 'not display when set to hidden' do | ||
88 | + assert_equal false, Block.new(:display => 'never').visible? | ||
89 | + assert_equal false, Block.new(:display => 'never').visible?(:article => Article.new) | ||
90 | + end | ||
91 | + | ||
92 | + should 'be able to be displayed only in the homepage' do | ||
93 | + profile = Profile.new | ||
94 | + home_page = Article.new | ||
95 | + profile.home_page = home_page | ||
96 | + block = Block.new(:display => 'home_page_only') | ||
97 | + block.stubs(:owner).returns(profile) | ||
98 | + | ||
99 | + assert_equal true, block.visible?(:article => home_page) | ||
100 | + assert_equal false, block.visible?(:article => Article.new) | ||
101 | + end | ||
102 | + | ||
83 | end | 103 | end |
test/unit/boxes_helper_test.rb
@@ -41,7 +41,7 @@ class BoxesHelperTest < Test::Unit::TestCase | @@ -41,7 +41,7 @@ class BoxesHelperTest < Test::Unit::TestCase | ||
41 | p = create_user_with_blocks | 41 | p = create_user_with_blocks |
42 | 42 | ||
43 | b = p.blocks.select{|bk| !bk.kind_of?(MainBlock) }[0] | 43 | b = p.blocks.select{|bk| !bk.kind_of?(MainBlock) }[0] |
44 | - b.visible = false; b.save! | 44 | + b.display = 'never'; b.save! |
45 | box = b.box | 45 | box = b.box |
46 | box.expects(:blocks).returns([b]) | 46 | box.expects(:blocks).returns([b]) |
47 | expects(:display_block).with(b, '') | 47 | expects(:display_block).with(b, '') |
@@ -55,7 +55,7 @@ class BoxesHelperTest < Test::Unit::TestCase | @@ -55,7 +55,7 @@ class BoxesHelperTest < Test::Unit::TestCase | ||
55 | p = create_user_with_blocks | 55 | p = create_user_with_blocks |
56 | 56 | ||
57 | b = p.blocks.select{|bk| !bk.kind_of?(MainBlock) }[0] | 57 | b = p.blocks.select{|bk| !bk.kind_of?(MainBlock) }[0] |
58 | - b.visible = false; b.save! | 58 | + b.display = 'never'; b.save! |
59 | box = b.box | 59 | box = b.box |
60 | box.expects(:blocks).returns([b]) | 60 | box.expects(:blocks).returns([b]) |
61 | expects(:display_block).with(b, '').never | 61 | expects(:display_block).with(b, '').never |
@@ -85,4 +85,13 @@ class BoxesHelperTest < Test::Unit::TestCase | @@ -85,4 +85,13 @@ class BoxesHelperTest < Test::Unit::TestCase | ||
85 | assert_tag_in_string insert_boxes('main content'), :tag => "div", :attributes => { :id => 'profile-footer' }, :content => 'my custom footer' | 85 | assert_tag_in_string insert_boxes('main content'), :tag => "div", :attributes => { :id => 'profile-footer' }, :content => 'my custom footer' |
86 | end | 86 | end |
87 | 87 | ||
88 | + should 'calculate CSS class names correctly' do | ||
89 | + assert_equal 'slideshow-block', block_css_class_name(SlideshowBlock.new) | ||
90 | + assert_equal 'main-block', block_css_class_name(MainBlock.new) | ||
91 | + end | ||
92 | + | ||
93 | + should 'add invisible CSS class name for invisible blocks' do | ||
94 | + assert !block_css_classes(Block.new(:display => 'always')).split.any? { |item| item == 'invisible-block'} | ||
95 | + assert block_css_classes(Block.new(:display => 'never')).split.any? { |item| item == 'invisible-block'} | ||
96 | + end | ||
88 | end | 97 | end |
test/unit/slideshow_block_test.rb
@@ -20,15 +20,35 @@ class SlideshowBlockTest < ActiveSupport::TestCase | @@ -20,15 +20,35 @@ class SlideshowBlockTest < ActiveSupport::TestCase | ||
20 | assert_equal 4, slideshow.interval | 20 | assert_equal 4, slideshow.interval |
21 | end | 21 | end |
22 | 22 | ||
23 | - should 'not invoke javascript when has no gallery' do | ||
24 | - slideshow_block = SlideshowBlock.new() | ||
25 | - assert_nil slideshow_block.footer | 23 | + should 'list in the same order' do |
24 | + gallery = mock | ||
25 | + images = [] | ||
26 | + images.expects(:shuffle).never | ||
27 | + gallery.stubs(:images).returns(images) | ||
28 | + | ||
29 | + block = SlideshowBlock.new | ||
30 | + block.stubs(:gallery).returns(gallery) | ||
31 | + block.content | ||
26 | end | 32 | end |
27 | 33 | ||
28 | - should 'invoke javascript when has gallery' do | ||
29 | - gallery = fast_create(Folder, :profile_id => profile.id) | ||
30 | - slideshow_block = SlideshowBlock.new(:gallery_id => gallery.id) | ||
31 | - assert_not_nil slideshow_block.footer | 34 | + should 'list in random order' do |
35 | + gallery = mock | ||
36 | + images = [] | ||
37 | + shuffled = [] | ||
38 | + gallery.stubs(:images).returns(images) | ||
39 | + images.expects(:shuffle).once.returns(shuffled) | ||
40 | + | ||
41 | + block = SlideshowBlock.new(:shuffle => true) | ||
42 | + block.stubs(:gallery).returns(gallery) | ||
43 | + block.content | ||
44 | + end | ||
45 | + | ||
46 | + should 'not shuffle by default' do | ||
47 | + assert_equal false, SlideshowBlock.new.shuffle | ||
48 | + end | ||
49 | + | ||
50 | + should 'not display navigation by default' do | ||
51 | + assert_equal false, SlideshowBlock.new.navigation | ||
32 | end | 52 | end |
33 | 53 | ||
34 | end | 54 | end |
test/unit/uploaded_file_test.rb
@@ -113,10 +113,34 @@ class UploadedFileTest < Test::Unit::TestCase | @@ -113,10 +113,34 @@ class UploadedFileTest < Test::Unit::TestCase | ||
113 | p = create_user('test_user').person | 113 | p = create_user('test_user').person |
114 | file = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/test.txt', 'text/plain'), :profile => p) | 114 | file = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/test.txt', 'text/plain'), :profile => p) |
115 | 115 | ||
116 | - stubs(:content_tag) | 116 | + stubs(:content_tag).returns('link') |
117 | expects(:link_to).with(file.name, file.url, :class => file.css_class_name) | 117 | expects(:link_to).with(file.name, file.url, :class => file.css_class_name) |
118 | 118 | ||
119 | instance_eval(&file.to_html) | 119 | instance_eval(&file.to_html) |
120 | end | 120 | end |
121 | 121 | ||
122 | + should 'have title' do | ||
123 | + assert_equal 'my title', UploadedFile.new(:title => 'my title').title | ||
124 | + end | ||
125 | + | ||
126 | + should 'limit title to 140 characters' do | ||
127 | + upload = UploadedFile.new | ||
128 | + | ||
129 | + upload.title = '+' * 61; upload.valid? | ||
130 | + assert upload.errors[:title] | ||
131 | + | ||
132 | + upload.title = '+' * 60; upload.valid? | ||
133 | + assert !upload.errors[:title] | ||
134 | + | ||
135 | + end | ||
136 | + | ||
137 | + should 'always provide a display title' do | ||
138 | + upload = UploadedFile.new(:uploaded_data => fixture_file_upload('/files/test.txt', 'text/plain')) | ||
139 | + assert_equal 'test.txt', upload.display_title | ||
140 | + upload.title = 'My text file' | ||
141 | + assert_equal 'My text file', upload.display_title | ||
142 | + upload.title = '' | ||
143 | + assert_equal 'test.txt', upload.display_title | ||
144 | + end | ||
145 | + | ||
122 | end | 146 | end |