diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 7d51312..665dbfc 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,5 +1,9 @@ class ApplicationController < ActionController::Base + # Preload FilePresenters to allow `FilePresenter.for()` to work + FilePresenter::Generic + FilePresenter::Image + before_filter :setup_multitenancy before_filter :detect_stuff_by_domain before_filter :init_noosfero_plugins diff --git a/app/controllers/public/content_viewer_controller.rb b/app/controllers/public/content_viewer_controller.rb index 602eea8..65afef8 100644 --- a/app/controllers/public/content_viewer_controller.rb +++ b/app/controllers/public/content_viewer_controller.rb @@ -55,7 +55,9 @@ class ContentViewerController < ApplicationController # At this point the page will be showed @page.hit - unless @page.mime_type == 'text/html' || (@page.image? && params[:view]) + @page = FilePresenter.for @page + + unless @page.mime_type == 'text/html' || params[:view] headers['Content-Type'] = @page.mime_type data = @page.data diff --git a/app/helpers/folder_helper.rb b/app/helpers/folder_helper.rb index 7dd4dff..6838894 100644 --- a/app/helpers/folder_helper.rb +++ b/app/helpers/folder_helper.rb @@ -21,6 +21,7 @@ module FolderHelper end def display_article_in_listing(article, recursive = false, level = 0) + article = FilePresenter.for article article_link = if article.image? link_to(' ' * (level * 4) + image_tag(icon_for_article(article)) + short_filename(article.name), article.url.merge(:view => true)) else @@ -40,12 +41,12 @@ module FolderHelper end def icon_for_article(article) - icon = article.class.icon_name(article) + icon = article.icon_name || article.class.icon_name(article) if (icon =~ /\//) icon else - klasses = 'icon icon-' + icon - if article.kind_of?(UploadedFile) + klasses = 'icon ' + [icon].flatten.map{|name| 'icon-'+name}.join(' ') + if article.kind_of?(UploadedFile) || article.kind_of?(FilePresenter) klasses += ' icon-upload-file' end klasses diff --git a/app/models/article.rb b/app/models/article.rb index a806117..14d7a89 100644 --- a/app/models/article.rb +++ b/app/models/article.rb @@ -133,8 +133,12 @@ class Article < ActiveRecord::Base end end + def css_class_list + [self.class.name.underscore.dasherize] + end + def css_class_name - self.class.name.underscore.dasherize + [css_class_list].flatten.compact.join(' ') end def pending_categorizations @@ -314,7 +318,7 @@ class Article < ActiveRecord::Base end def view_url - @view_url ||= image? ? url.merge(:view => true) : url + @view_url ||= is_a?(UploadedFile) ? url.merge(:view => true) : url end def allow_children? diff --git a/app/models/uploaded_file.rb b/app/models/uploaded_file.rb index 5be009e..e45d758 100644 --- a/app/models/uploaded_file.rb +++ b/app/models/uploaded_file.rb @@ -61,11 +61,13 @@ class UploadedFile < Article postgresql_attachment_fu def self.icon_name(article = nil) - if article - article.image? ? article.public_filename(:icon) : (article.mime_type ? article.mime_type.gsub(/[\/+.]/, '-') : 'upload-file') - else - 'upload-file' - end + warn = ('='*80) + "\n" + + 'The method `UploadedFile.icon_name(obj)` is deprecated. ' + + 'You must to encapsulate UploadedFile with `FilePresenter.for()`.' + + "\n" + ('='*80) + Rails.logger.warn warn if Rails.logger + puts warn + 'upload-file' end def mime_type @@ -91,40 +93,26 @@ class UploadedFile < Article end def to_html(options = {}) + warn = ('='*80) + "\n" + + 'The method `UploadedFile::to_html()` is deprecated. ' + + 'You must to encapsulate UploadedFile with `FilePresenter.for()`.' + + "\n" + ('='*80) + Rails.logger.warn warn if Rails.logger + puts warn article = self if image? lambda do - if article.gallery? && options[:gallery_view] - images = article.parent.images - current_index = images.index(article) - total_of_images = images.count - - link_to_previous = if current_index >= 1 - link_to(_('« Previous'), images[current_index - 1].view_url, :class => 'left') - else - content_tag('span', _('« Previous'), :class => 'left') - end - - link_to_next = if current_index < total_of_images - 1 - link_to(_('Next »'), images[current_index + 1].view_url, :class => 'right') - else - content_tag('span', _('Next »'), :class => 'right') - end - - content_tag( - 'div', - link_to_previous + (content_tag('span', _('image %d of %d'), :class => 'total-of-images') % [current_index + 1, total_of_images]).html_safe + link_to_next, - :class => 'gallery-navigation' - ) - end.to_s + - image_tag(article.public_filename(:display), :class => article.css_class_name, :style => 'max-width: 100%') + - content_tag('p', article.abstract, :class => 'uploaded-file-description') - + image_tag(article.public_filename(:display), + :class => article.css_class_name, + :style => 'max-width: 100%') + + content_tag('div', article.abstract, :class => 'uploaded-file-description') end else lambda do - content_tag('ul', content_tag('li', link_to(article.name, article.url, :class => article.css_class_name))) + - content_tag('p', article.abstract, :class => 'uploaded-file-description') + content_tag('div', + link_to(article.name, article.url), + :class => article.css_class_name) + + content_tag('div', article.abstract, :class => 'uploaded-file-description') end end end diff --git a/app/views/file_presenter/_generic.html.erb b/app/views/file_presenter/_generic.html.erb new file mode 100644 index 0000000..f8ecbcf --- /dev/null +++ b/app/views/file_presenter/_generic.html.erb @@ -0,0 +1,9 @@ + + Download + <%= link_to generic.filename, generic.public_filename %> + + +
+ <%= generic.abstract %> +
+ diff --git a/app/views/file_presenter/_image.html.erb b/app/views/file_presenter/_image.html.erb new file mode 100644 index 0000000..10af690 --- /dev/null +++ b/app/views/file_presenter/_image.html.erb @@ -0,0 +1,37 @@ +<% if image.gallery? && options[:gallery_view] %> +<% + images = image.parent.images + current_index = images.index(image.encapsulated_file) + total_of_images = images.count + link_to_previous = if current_index >= 1 + link_to(_('« Previous'), images[current_index - 1].view_url, :class => 'previous') + else + content_tag('span', _('« Previous'), :class => 'previous') + end + + link_to_next = if current_index < total_of_images - 1 + link_to(_('Next »'), images[current_index + 1].view_url, :class => 'next') + else + content_tag('span', _('Next »'), :class => 'next') + end +%> + + + +<% end %> + +<%# image_tag(article.public_filename(:display), :class => article.css_class_name, :style => 'max-width: 100%') %> + + + +
+ <%= image.class %> + <%= image.abstract %> +
+ diff --git a/lib/file_presenter.rb b/lib/file_presenter.rb new file mode 100644 index 0000000..1554a8f --- /dev/null +++ b/lib/file_presenter.rb @@ -0,0 +1,90 @@ +# All file presenters must extends `FilePresenter` not only to ensure the +# same interface, but also to make `FilePresenter.for(file)` to work. +class FilePresenter + + # Will return a encapsulated `UploadedFile` or the same object if no + # one accepts it. That behave allow to give any model to this class, + # like a Article and have no trouble with that. + def self.for(f) + return f if f.is_a? FilePresenter + klass = FilePresenter.subclasses.sort_by {|class_name| + class_name.constantize.accepts?(f) || 0 + }.last.constantize + klass.accepts?(f) ? klass.new(f) : f + end + + def initialize(f) + @file = f + end + + # Allows to use the original `UploadedFile` reference. + def encapsulated_file + @file + end + + # This method must be overridden in subclasses. + # + # If the class accepts the file, return a number that represents the + # priority the class should be given to handle that file. Higher numbers + # mean higher priority. + # + # If the class does not accept the file, return false. + def self.accepts?(f) + nil + end + + # Define the css classes to style the page fragment with the file related + # content. If you want other classes to identify this area to your + # customized presenter, so do this: + # def css_class_list + # [super, 'myclass'].flatten + # end + def css_class_list + [ @file.css_class_list, + 'file-' + self.class.to_s.split(/:+/).map(&:underscore)[1..-1].join('-'), + 'content-type_' + self.content_type.split('/')[0], + 'content-type_' + self.content_type.gsub(/[^a-z0-9]/i,'-') + ].flatten + end + + # Enable file presenter to customize the css classes on view_page.rhtml + # You may not overwrite this method on your customized presenter. + def css_class_name + [css_class_list].flatten.compact.join(' ') + end + + # The generic icon class-name or the specific file path. + # You may replace this method on your custom FilePresenter. + # See the current used icons class-names in public/designs/icons/tango/style.css + def icon_name + if mime_type + [ mime_type.split('/')[0], mime_type.gsub(/[^a-z0-9]/i, '-') ] + else + 'upload-file' + end + end + + # Automatic render `file_presenter/.html.erb` to display your + # custom presenter html content. + # You may not overwrite this method on your customized presenter. + # A variable with the same presenter name will be created to refer + # to the file object. + # Example: + # The `FilePresenter::Image` render `file_presenter/image.html.erb` + # inside the `file_presenter/image.html.erb` you can access the + # required `FilePresenter::Image` instance in the `image` variable. + def to_html(options = {}) + file = self + lambda do + render :partial => file.class.to_s.underscore, + :locals => { :options => options }, + :object => file + end + end + + # That makes the presenter to works like any other `UploadedFile` instance. + def method_missing(m, *args) + @file.send(m, *args) + end + +end diff --git a/lib/file_presenter/generic.rb b/lib/file_presenter/generic.rb new file mode 100644 index 0000000..5a81690 --- /dev/null +++ b/lib/file_presenter/generic.rb @@ -0,0 +1,11 @@ +# Made to encapsulate any UploadedFile +class FilePresenter::Generic < FilePresenter + def initialize(f) + @file = f + end + + # if returns low priority, because it is generic. + def self.accepts?(f) + 1 if f.is_a? UploadedFile + end +end diff --git a/lib/file_presenter/image.rb b/lib/file_presenter/image.rb new file mode 100644 index 0000000..1192715 --- /dev/null +++ b/lib/file_presenter/image.rb @@ -0,0 +1,13 @@ +class FilePresenter::Image < FilePresenter + def initialize(f) + @file = f + end + + def self.accepts?(f) + f.image? ? 10 : nil + end + + def icon_name + article.public_filename :icon + end +end diff --git a/plugins/html5_video/lib/file_presenter/video.rb b/plugins/html5_video/lib/file_presenter/video.rb new file mode 100644 index 0000000..53ad7d8 --- /dev/null +++ b/plugins/html5_video/lib/file_presenter/video.rb @@ -0,0 +1,10 @@ +class FilePresenter::Video < FilePresenter + def initialize(f) + @file = f + end + + def self.accepts?(f) + return nil if f.content_type.nil? + ( f.content_type[0..4] == 'video' ) ? 10 : nil + end +end diff --git a/plugins/html5_video/lib/html5_video_plugin.rb b/plugins/html5_video/lib/html5_video_plugin.rb new file mode 100644 index 0000000..953e511 --- /dev/null +++ b/plugins/html5_video/lib/html5_video_plugin.rb @@ -0,0 +1,13 @@ +class Html5VideoPlugin < Noosfero::Plugin + + FilePresenter::Video + + def self.plugin_name + "HTML5 Video" + end + + def self.plugin_description + _("A plugin to enable the video suport, with auto conversion for the web.") + end + +end diff --git a/plugins/html5_video/views/file_presenter/_video.html.erb b/plugins/html5_video/views/file_presenter/_video.html.erb new file mode 100644 index 0000000..abf9b0c --- /dev/null +++ b/plugins/html5_video/views/file_presenter/_video.html.erb @@ -0,0 +1,8 @@ + + +
+ <%= video.abstract %> +
+ diff --git a/public/designs/icons/tango/style.css b/public/designs/icons/tango/style.css index 1881f0c..b836906 100644 --- a/public/designs/icons/tango/style.css +++ b/public/designs/icons/tango/style.css @@ -80,7 +80,7 @@ .icon-application-postscript { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-postscript.png) } .icon-application-pdf { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-pdf.png) } .icon-application-ogg { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-ogg.png) } -.icon-video-mpeg { background-image: url(Tango/16x16/mimetypes/video-x-generic.png) } +.icon-video, .icon-video-mpeg { background-image: url(Tango/16x16/mimetypes/video-x-generic.png) } .icon-application-vnd-oasis-opendocument-text { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-vnd.oasis.opendocument.text.png) } .icon-application-vnd-oasis-opendocument-spreadsheet { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-vnd.oasis.opendocument.spreadsheet.png) } .icon-application-vnd-oasis-opendocument-presentation { background-image: url(Tango/16x16/mimetypes/gnome-mime-application-vnd.oasis.opendocument.presentation.png) } diff --git a/public/designs/themes/base/style.css b/public/designs/themes/base/style.css index 83a836f..0a81666 100644 --- a/public/designs/themes/base/style.css +++ b/public/designs/themes/base/style.css @@ -822,12 +822,6 @@ div#notice { margin-bottom: 0px; } -X.sep { - background: url(imgs/blog-sep.png) 50% 50% repeat-x; - padding: 10px 20px; - margin: 10px -19px; -} - /* ==> search-results.css <== */ @@ -1019,6 +1013,46 @@ hr.pre-posts, hr.sep-posts { background: #FFF; } +/************* uploaded file *****************/ + +#article .gallery-navigation { + padding: 10px 0; +} + +#article .gallery-navigation .previous { + margin-right: 10px; +} + +#article .gallery-navigation .next { + margin-left: 10px; +} + +#article .gallery-navigation .total-of-images { + font-weight: bold; +} + +#article .uploaded-file-description { + background: #f6f6f6; + border-top: 1px solid #ccc; + border-bottom: 1px solid #ccc; + padding: 1em; +} +#article .uploaded-file-description.empty { + display: none; +} + +#article.file-generic .download-link { + display: block; + margin-bottom: 10px; +} +#article.file-generic .download-link span { + font-size: 150%; + padding-right: 5px; +} +#article.file-generic .download-link a { + font-size: 180%; + text-decoration: none; +} /**************************** Comments *******************************/ diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css index 081eb01..919b172 100644 --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -1534,14 +1534,15 @@ a.button.disabled, input.disabled { .map { clear: both; } + /*********************************************************** * style for blocks ***********************************************************/ - #content .communities-block .profile-image { - float: none; - padding-left: 0px; - max-width: none; +#content .communities-block .profile-image { + float: none; + padding-left: 0px; + max-width: none; } #content .communities-block .vcard .profile_link { text-align: center; @@ -3313,26 +3314,7 @@ div#article-parent { .article-body-uploaded-file { text-align: center; } -/************* uploaded file *****************/ -#article .gallery-navigation { - padding: 10px 0; -} -#article .gallery-navigation .left { - margin-right: 10px; -} -#article .gallery-navigation .right { - margin-left: 10px; -} -#article .gallery-navigation .total-of-images { - font-weight: bold; -} -#article .uploaded-file-description { - background: #f6f6f6; - border-top: 1px solid #ccc; - border-bottom: 1px solid #ccc; - padding: 1em; -} /* ==> public/stylesheets/controller_events.css <== */ #agenda { position: relative; -- libgit2 0.21.2