diff --git a/app/controllers/my_profile/cms_controller.rb b/app/controllers/my_profile/cms_controller.rb
index 043368b..e101e2d 100644
--- a/app/controllers/my_profile/cms_controller.rb
+++ b/app/controllers/my_profile/cms_controller.rb
@@ -132,7 +132,8 @@ class CmsController < MyProfileController
def upload_files
@uploaded_files = []
- @parent = check_parent(params[:parent_id])
+ @article = @parent = check_parent(params[:parent_id])
+ record_coming_from_public_view if @article
if request.post? && params[:uploaded_files]
params[:uploaded_files].each do |file|
@uploaded_files << UploadedFile.create(:uploaded_data => file, :profile => profile, :parent => @parent) unless file == ''
@@ -141,11 +142,15 @@ class CmsController < MyProfileController
if @errors.any?
render :action => 'upload_files', :parent_id => @parent_id
else
- redirect_to( if @parent
- {:action => 'view', :id => @parent.id}
+ if params[:back_to]
+ redirect_back
else
- {:action => 'index'}
- end)
+ redirect_to( if @parent
+ {:action => 'view', :id => @parent.id}
+ else
+ {:action => 'index'}
+ end)
+ end
end
end
end
@@ -209,7 +214,7 @@ class CmsController < MyProfileController
def record_coming_from_public_view
referer = request.referer
- if (maybe_ssl(url_for(@article.url)).include?(referer)) || (@article == @profile.home_page && maybe_ssl(url_for(@profile.url)).include?(referer))
+ if (maybe_ssl(url_for(@article.url)).include?(referer)) || (@article == profile.home_page && maybe_ssl(url_for(profile.url)).include?(referer))
@back_to = 'public_view'
@back_url = @article.url
end
diff --git a/app/controllers/public/content_viewer_controller.rb b/app/controllers/public/content_viewer_controller.rb
index 68f02ae..608e682 100644
--- a/app/controllers/public/content_viewer_controller.rb
+++ b/app/controllers/public/content_viewer_controller.rb
@@ -55,7 +55,7 @@ class ContentViewerController < ApplicationController
# At this point the page will be showed
@page.hit
- if @page.mime_type != 'text/html'
+ unless @page.mime_type == 'text/html' || (@page.image? && params[:view])
headers['Content-Type'] = @page.mime_type
data = @page.data
@@ -82,6 +82,10 @@ class ContentViewerController < ApplicationController
@page.filter = {:year => year, :month => month}
end
+ if @page.folder? && @page.view_as == 'image_gallery'
+ @images = @page.images.paginate(:per_page => 12, :page => params[:npage])
+ end
+
@comments = @page.comments(true)
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index ad28396..c107be8 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -139,10 +139,10 @@ module ApplicationHelper
link_to text, p.admin_url.merge(url), options
end
- def link_to_document(doc, text = nil)
+ def link_to_document(doc, text = nil, html_options = {}, url_options = {})
text ||= doc.title
path = doc.path.split(/\//)
- link_to text, homepage_path(:profile => doc.profile.identifier , :page => path)
+ link_to text, homepage_path({:profile => doc.profile.identifier , :page => path, :view => true}.merge(url_options)), html_options
end
def link_if_permitted(link, permission = nil, target = nil)
diff --git a/app/helpers/content_viewer_helper.rb b/app/helpers/content_viewer_helper.rb
index 6a0c3b4..6b3dcbc 100644
--- a/app/helpers/content_viewer_helper.rb
+++ b/app/helpers/content_viewer_helper.rb
@@ -12,7 +12,9 @@ module ContentViewerHelper
end
def article_title(article, args = {})
- title = content_tag('h1', article.title, :class => 'title')
+ title = article.abstract if article.kind_of?(UploadedFile) && article.image?
+ title = article.title if title.blank?
+ title = content_tag('h1', title, :class => 'title')
if article.belongs_to_blog?
unless args[:no_link]
title = content_tag('h3', link_to(article.name, article.url), :class => 'title')
@@ -39,6 +41,9 @@ module ContentViewerHelper
end
def article_to_html(article)
+ content = article.to_html
+ return self.instance_eval(&content) if content.kind_of?(Proc)
+
if article.blog?
children = if article.filter and article.filter[:year] and article.filter[:month]
filter_date = DateTime.parse("#{article.filter[:year]}-#{article.filter[:month]}-01")
@@ -46,9 +51,9 @@ module ContentViewerHelper
else
article.posts.paginate :page => params[:npage], :per_page => article.posts_per_page
end
- article.to_html + (children.compact.empty? ? content_tag('em', _('(no posts)')) : list_posts(children))
+ content + (children.compact.empty? ? content_tag('em', _('(no posts)')) : list_posts(children))
else
- article.to_html
+ content
end
end
diff --git a/app/helpers/folder_helper.rb b/app/helpers/folder_helper.rb
index 3add4fb..004dfa1 100644
--- a/app/helpers/folder_helper.rb
+++ b/app/helpers/folder_helper.rb
@@ -11,7 +11,7 @@ module FolderHelper
def display_article_in_listing(article, recursive = false, level = 0)
result = content_tag(
'tr',
- content_tag('td', link_to((' ' * (level * 4) ) + image_tag(icon_for_article(article)) + article.name, article.url))+
+ content_tag('td', link_to((' ' * (level * 4) ) + image_tag(icon_for_article(article)) + article.name, article.url.merge(:view => true)))+
content_tag('td', show_date(article.updated_at), :class => 'last-update'),
:class => 'sitemap-item'
)
@@ -35,4 +35,30 @@ module FolderHelper
end
end
+ def custom_options_for_article(article)
+ @article = article
+ content_tag('h4', _('Options')) +
+ content_tag('div',
+ content_tag(
+ 'div',
+ check_box(:article, :published) +
+ content_tag('label', _('This article must be published (visible to other people)'), :for => 'article_published')
+ ) + (article.can_display_hits? ?
+ content_tag(
+ 'div',
+ check_box(:article, :display_hits) +
+ content_tag('label', _('I want this article to display the number of hits it received'), :for => 'article_display_hits')
+ ) : '') +
+ hidden_field_tag('article[accept_comments]', 0)
+ )
+ end
+
+ def cms_label_for_new_children
+ _('New article')
+ end
+
+ def cms_label_for_edit
+ _('Edit folder')
+ end
+
end
diff --git a/app/models/article.rb b/app/models/article.rb
index df48c6b..4235a61 100644
--- a/app/models/article.rb
+++ b/app/models/article.rb
@@ -29,6 +29,10 @@ class Article < ActiveRecord::Base
end
end
+ def css_class_name
+ self.class.name.underscore.dasherize
+ end
+
def pending_categorizations
@pending_categorizations ||= []
end
@@ -232,6 +236,14 @@ class Article < ActiveRecord::Base
can_display_hits? && display_hits
end
+ def image?
+ false
+ end
+
+ def display_as_gallery?
+ false
+ end
+
private
def sanitize_tag_list
diff --git a/app/models/folder.rb b/app/models/folder.rb
index 3346fa5..89e55b8 100644
--- a/app/models/folder.rb
+++ b/app/models/folder.rb
@@ -2,6 +2,18 @@ class Folder < Article
acts_as_having_settings :field => :setting
+ settings_items :view_as, :type => :string, :default => 'folder'
+
+ def self.select_views
+ [[_('Folder'), 'folder'], [_('Image gallery'), 'image_gallery']]
+ end
+
+ def self.views
+ select_views.map(&:last)
+ end
+
+ validates_inclusion_of :view_as, :in => self.views
+
def self.short_description
_('Folder')
end
@@ -21,16 +33,41 @@ class Folder < Article
include ActionView::Helpers::AssetTagHelper
include FolderHelper
include DatesHelper
+
def to_html
+ send(view_as)
+ end
+
+ def folder
content_tag('div', body) + tag('hr') + (children.empty? ? content_tag('em', _('(empty folder)')) : list_articles(children))
end
+ def image_gallery
+ article = self
+ lambda do
+ render :file => 'content_viewer/image_gallery', :locals => {:article => article}
+ end
+ end
+
def folder?
true
end
+ def display_as_gallery?
+ view_as == 'image_gallery'
+ end
+
def can_display_hits?
false
end
+ def accept_comments?
+ false
+ end
+
+ has_many :images, :class_name => 'Article',
+ :foreign_key => 'parent_id',
+ :order => 'type, name',
+ :conditions => ['type = ? and content_type in (?) or type = ?', 'UploadedFile', UploadedFile.content_types, 'Folder']
+
end
diff --git a/app/models/uploaded_file.rb b/app/models/uploaded_file.rb
index 75303ec..0937d00 100644
--- a/app/models/uploaded_file.rb
+++ b/app/models/uploaded_file.rb
@@ -10,7 +10,7 @@ class UploadedFile < Article
# :min_size => 2.megabytes
# :max_size => 5.megabytes
has_attachment :storage => :file_system,
- :thumbnails => { :icon => [24,24] },
+ :thumbnails => { :icon => [24,24], :thumb => '130x130>' },
:thumbnail_class => Thumbnail,
:max_size => 5.megabytes,
:resize_to => '640x480>'
@@ -47,6 +47,13 @@ class UploadedFile < Article
File.read(self.full_filename)
end
+ # FIXME isn't this too much including just to be able to generate some HTML?
+ include ActionView::Helpers::TagHelper
+
+ def to_html
+ tag('img', :src => public_filename, :class => css_class_name, :style => 'max-width: 100%') if image?
+ end
+
def allow_children?
false
end
@@ -55,4 +62,7 @@ class UploadedFile < Article
false
end
+ def display_as_gallery?
+ self.parent && self.parent.folder? && self.parent.display_as_gallery?
+ end
end
diff --git a/app/views/cms/_folder.rhtml b/app/views/cms/_folder.rhtml
index 3f92896..2738a8e 100644
--- a/app/views/cms/_folder.rhtml
+++ b/app/views/cms/_folder.rhtml
@@ -4,5 +4,6 @@
<%= render :file => 'shared/tiny_mce' %>
<%= required f.text_field('name', :size => '64') %>
+<%= labelled_form_field(_('Folder type'), f.select(:view_as, Folder.select_views)) %>
<%= labelled_form_field(_('Description:'), text_area(:article, :body, :cols => 64)) %>
diff --git a/app/views/cms/upload_files.rhtml b/app/views/cms/upload_files.rhtml
index 12d79c3..6e5898b 100644
--- a/app/views/cms/upload_files.rhtml
+++ b/app/views/cms/upload_files.rhtml
@@ -26,9 +26,15 @@
<%= hidden_field_tag('parent_id', @parent.id) if @parent %>
+ <%= hidden_field_tag('back_to', @back_to) if @back_to %>
+
<% button_bar do %>
<%= add_upload_file_field _('More files') %>
- <%= submit_button :save, _('Upload'), :cancel => {:action => (@parent ? 'view' : 'index'), :id => @parent } %>
+ <% if @back_url %>
+ <%= submit_button :save, _('Upload'), :cancel => @back_url %>
+ <% else %>
+ <%= submit_button :save, _('Upload'), :cancel => {:action => (@parent ? 'view' : 'index'), :id => @parent } %>
+ <% end %>
<% end %>
<% end %>
diff --git a/app/views/cms/view.rhtml b/app/views/cms/view.rhtml
index 0e00b95..6c49c78 100644
--- a/app/views/cms/view.rhtml
+++ b/app/views/cms/view.rhtml
@@ -7,7 +7,7 @@
<%= icon('cms') %>
<%= link_to profile.identifier, :action => 'index' %>
- <%= @article.hierarchy.map {|item| " / " + ((item == @article) ? item.name : link_to(item.name, :id => item.id)) } %>
+ <%= @article.hierarchy.map {|item| " / " + ((item == @article) ? item.name : link_to_document(item)) } %>
<% end %>
@@ -42,7 +42,7 @@
<%= link_to _('Properties'), :action => 'edit', :id => folder.id %>
- <%= link_to _('Public view'), folder.url %>
+ <%= link_to_document(folder, _('Public view')) %>
<%= link_to _('Use as homepage'), { :action => 'set_home_page', :id => folder.id }, :method => :post %>
<%= link_to _('Delete'), { :action => 'destroy', :id => folder.id }, :method => :post, :confirm => _('Are you sure that you want to remove this folder? Note that all the items inside it will also be removed!') %>
|
@@ -68,7 +68,7 @@
<%= link_to _('Edit'), :action => 'edit', :id => item.id %>
- <%= link_to _('Public view'), item.url %>
+ <%= link_to_document(item, _('Public view')) %>
<%= link_to _('Spread this'), :action => 'publish', :id => item.id %>
<%= link_to _('Use as homepage'), { :action => 'set_home_page', :id => item.id }, :method => :post %>
<%= link_to _('Delete'), { :action => 'destroy', :id => item.id }, :method => :post, :confirm => _('Are you sure that you want to remove this item?') %>
diff --git a/app/views/content_viewer/_article.rhtml b/app/views/content_viewer/_article.rhtml
new file mode 100644
index 0000000..6550dfb
--- /dev/null
+++ b/app/views/content_viewer/_article.rhtml
@@ -0,0 +1,2 @@
+<%= link_to_document(article, '', :class => article.css_class_name) %>
+<%= link_to_document(article) %>
diff --git a/app/views/content_viewer/_uploaded_file.rhtml b/app/views/content_viewer/_uploaded_file.rhtml
new file mode 100644
index 0000000..410d39d
--- /dev/null
+++ b/app/views/content_viewer/_uploaded_file.rhtml
@@ -0,0 +1,6 @@
+<% if uploaded_file.image? %>
+ <%= link_to_document(uploaded_file, image_tag(uploaded_file.public_filename(:thumb))) %>
+<% else %>
+ <%= render :partial => 'article', :object => uploaded_file %>
+<% end %>
+
diff --git a/app/views/content_viewer/image_gallery.rhtml b/app/views/content_viewer/image_gallery.rhtml
new file mode 100644
index 0000000..ec431ba
--- /dev/null
+++ b/app/views/content_viewer/image_gallery.rhtml
@@ -0,0 +1,35 @@
+
+ <% if params[:slideshow] %>
+ <%= button('', _('View as gallery'), @page.url)%>
+
+
+ <% @images.each do |img| %>
+ <%= image_tag(url_for(img.url), :alt => (img.abstract.blank? ? img.name : img.abstract)) if img.image? %>
+ <% end %>
+
+
+
+
+
+
+
+ <% else %>
+ <%= button('', _('View as slideshow'), @page.url.merge(:slideshow => true))%>
+
+ <% @images.each do |a| %>
+ -
+ <%= render :partial => partial_for_class(a.class), :object => a %>
+ <%= a.abstract %>
+
+ <% end %>
+
+ <% end %>
+
+ <%= will_paginate @images, :param_name => 'npage' %>
+
diff --git a/app/views/content_viewer/view_page.rhtml b/app/views/content_viewer/view_page.rhtml
index f970689..93bc494 100644
--- a/app/views/content_viewer/view_page.rhtml
+++ b/app/views/content_viewer/view_page.rhtml
@@ -48,7 +48,11 @@
{ :controller => 'cms', :action => 'publish', :id => @page },
:class => 'button with-text icon-spread' %>
<% end %>
- <%= lightbox_button(:new, label_for_new_article(@page), :controller => 'cms', :action => 'new', :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent))) %>
+ <% if @page.display_as_gallery? %>
+ <%= button('upload-file', _('Upload files'), :controller => 'cms', :action => 'upload_files', :parent_id => (@page.folder? ? @page : @page.parent)) %>
+ <% else %>
+ <%= lightbox_button(:new, label_for_new_article(@page), :controller => 'cms', :action => 'new', :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent))) %>
+ <% end %>
<% end %>
<% end %>
@@ -79,7 +83,7 @@
<% end %>
-
+ ">
<%= article_to_html(@page) %>
diff --git a/public/images/icons-mime/empty.png b/public/images/icons-mime/empty.png
new file mode 100644
index 0000000..9f56b72
Binary files /dev/null and b/public/images/icons-mime/empty.png differ
diff --git a/public/javascripts/jquery.aslideshow.js b/public/javascripts/jquery.aslideshow.js
new file mode 100644
index 0000000..8e64f6b
--- /dev/null
+++ b/public/javascripts/jquery.aslideshow.js
@@ -0,0 +1,645 @@
+/**
+ * jQuery (a)Slideshow plugin
+ *
+ * Copyright (c) 2008 Trent Foley
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * @author Anton Shevchuk AntonShevchuk@gmail.com
+ * @version 0.5.5
+ */
+;(function($) {
+ defaults = {
+ width:320, // width in px
+ height:240, // height in px
+ index:0, // start from frame number N
+ time:3000, // time out beetwen slides
+ title:true, // show title
+ titleshow:false,// always show title
+ panel:true, // show controls panel
+ play:false, // play slideshow
+ loop:true,
+ effect:'fade', // aviable fade, scrollUp/Down/Left/Right, zoom, zoomFade, growX, growY
+ effecttime:1000,// aviable fast,slow,normal and any valid fx speed value
+ filter:true, // remove , empty , and other stuff
+ nextclick:false, // bind content click next slide
+ playclick:false, // bind content click play/stop
+ playhover:false, // bind content hover play/stop
+ playhoverr:false, // bind content hover stop/play (reverse of playhover)
+ playframe:true, // show frame "Play Now!"
+ fullscreen:false, // in full window size
+ imgresize:false, // resize image to slideshow window
+ imgcenter:true, // set image to center // TODO
+ imgajax:true, // load images from links
+ linkajax:false, // load html from links
+ help:'Plugin homepage: (a)Slideshow '+
+ 'Author homepage: Anton Shevchuk',
+
+ controls :{ // show/hide controls elements
+ 'hide':true, // show controls bar on mouse hover
+ 'first':true, // goto first frame
+ 'prev':true, // goto previouse frame (if it first go to last)
+ 'play':true, // play slideshow
+ 'next':true, // goto next frame (if it last go to first)
+ 'last':true, // goto last frame
+ 'help':true, // show help message
+ 'counter':true // show slide counter
+ }
+ };
+ /**
+ * Create a new instance of slideshow.
+ *
+ * @classDescription This class creates a new slideshow and manipulate it
+ *
+ * @return {Object} Returns a new slideshow object.
+ * @constructor
+ */
+ $.fn.slideshow = function(settings) {
+
+ var _slideshow = this;
+
+ /*
+ * Construct
+ */
+ this.each(function(){
+
+ var ext = $(this);
+
+ this.playFlag = false;
+ this.playId = null;
+ this.length = 0;
+ this.inited = new Array();
+
+ /**
+ * Build Html
+ * @method
+ */
+ this.build = function () {
+ var _self = this;
+
+ ext.wrapInner(' ');
+ ext = ext.find('.slideshow');
+
+ // filter content
+ if (this.options.filter) {
+ ext.find('.slideshow-content > br').remove();
+ ext.find('.slideshow-content > p:empty').remove();
+ ext.find('.slideshow-content > div:empty').remove();
+ }
+
+
+ // fullscreen
+ if (this.options.fullscreen) {
+ $('body').css({overflow:'hidden', padding:0});
+
+ this.options.width = $(window).width();
+ this.options.height = ($(window).height()>$(document).height())?$(window).height():$(document).height();
+
+// this.options.width = this.options.width;
+// this.options.height = this.options.height;
+
+ ext.addClass('slideshow-fullscreen');
+ }
+
+ this.length = ext.find('.slideshow-content > *').length;
+
+ // build title
+ if (this.options.title) {
+ ext.prepend(' ');
+
+ if (!this.options.titleshow) {
+ ext.find('.slideshow-label-place').hover(function(){
+ $(this).find('.slideshow-label').fadeIn();
+ }, function() {
+ $(this).find('.slideshow-label').fadeOut();
+ });
+ ext.find('.slideshow-label').hide();
+ }
+
+
+ ext.find('.slideshow-label-place').css('width', this.options.width);
+ }
+
+ // build panel
+ if (this.options.panel) {
+ ext.append(' ');
+ panel = ext.find('.slideshow-panel');
+ if (this.options.controls.first)
+ panel.append(' First');
+
+ if (this.options.controls.prev)
+ panel.append(' Prev');
+
+ if (this.options.controls.play)
+ panel.append(' Play');
+
+ if (this.options.controls.next)
+ panel.append(' Next');
+
+ if (this.options.controls.last)
+ panel.append(' Last');
+
+ if (this.options.controls.help) {
+ panel.append(' Help');
+ panel.prepend(' '+this.options.help+' ');
+
+// panel.find('.slideshow-help').css('width', this.options.width - 4 + 'px');
+ }
+
+
+ if (this.options.controls.counter) {
+ panel.append(' '+(this.options.index+1)+' / '+this.length+'');
+ }
+
+ if (this.options.controls.hide) {
+ ext.find('.slideshow-panel-place').hover(function(){
+ $(this).find('.slideshow-panel').fadeIn();
+ }, function() {
+ $(this).find('.slideshow-panel').fadeOut();
+ });
+ panel.hide();
+ }
+
+
+ ext.find('.slideshow-panel-place').css('width', this.options.width);
+ }
+
+ /**
+ * Set Size Options
+ */
+ ext.css('width', this.options.width + 'px');
+// ext.css('height', this.options.height + 'px');
+
+ ext.find('.slideshow-content').css('width', this.options.width);
+ ext.find('.slideshow-content').css('height', this.options.height);
+
+ /**
+ * Change children styles
+ */
+ ext.find('.slideshow-content > *').each(function(){
+ _self._build($(this));
+ });
+
+ // init slide (replace by ajax etc)
+ this.init(this.options.index);
+
+ // hide all slides
+ ext.find('.slideshow-content > *:not(:eq('+this.options.index+'))').hide();
+
+ // show label
+ this.label();
+
+ // add playframe
+ if (this.options.playframe) {
+ ext.find('.slideshow-content').append(' ');
+ }
+
+ // bind all events
+ this.events();
+
+ return true;
+ };
+
+ /**
+ * Change CSS for every entity
+ */
+ this._build = function(el){
+ el.css({margin :0,
+ position: 'absolute',
+ left: (this.options.width/2 - el.attr('width')/2),
+ top : (this.options.height/2 - el.attr('height')/2),
+ overflow:'hidden'
+ });
+
+ if (el.is('img') && this.options.imgresize || el.is(':not(img)')){
+ el.css({width:'100%',height:'100%'});
+ }
+ };
+
+ /**
+ * Bind Events
+ */
+ this.events = function() {
+
+ var _self = this;
+
+ /**
+ * Go to next slide on content click (optional)
+ */
+ if (_self.options.nextclick)
+ ext.find('.slideshow-content').click(function(){
+ _self.stop();
+ _self.next();
+ return false;
+ });
+
+ /**
+ * Goto first slide button
+ */
+ if (this.options.controls.first)
+ ext.find('a.first').click(function(){
+ _self.stop();
+ _self.goSlide(0);
+ return false;
+ });
+
+ /**
+ * Goto previouse slide button
+ */
+ if (this.options.controls.prev)
+ ext.find('a.prev').click(function(){
+ _self.stop();
+ _self.prev();
+ return false;
+ });
+
+ /**
+ * Play slideshow button
+ */
+ if (this.options.controls.play)
+ ext.find('a.play').click(function(){
+ if (_self.playFlag) {
+ _self.stop();
+ } else {
+ _self.play();
+ }
+ return false;
+ });
+
+ /**
+ * Goto next slide button
+ */
+ if (this.options.controls.next)
+ ext.find('a.next').click(function(){
+ _self.stop();
+ _self.next();
+ return false;
+ });
+
+ /**
+ * Goto last slide button
+ */
+ if (this.options.controls.last)
+ ext.find('a.last').click(function(){
+ _self.stop();
+ _self.goSlide(_self.length-1);
+ return false;
+ });
+
+ /**
+ * Show help message
+ */
+ if (this.options.controls.help)
+ ext.find('a.help').click(function(){
+ _self.stop();
+ ext.find('.slideshow-help').slideToggle();
+ return false;
+ });
+
+ /**
+ * Show playframe
+ */
+ if (this.options.playframe)
+ ext.find('.slideshow-frame').click(function(){
+ ext.find('.slideshow-frame').remove();
+ ext.find('.slideshow-shadow').remove();
+
+ if (_self.options.playclick)
+ setTimeout(function(ms){ _self.play() }, _self.options.time);
+ return false;
+ });
+
+ /**
+ * Play/stop on slideshow hover
+ */
+ if (this.options.playhover)
+ ext.hover(function(){
+ if (!_self.playFlag) {
+ _self.play();
+ }
+ }, function(){
+ if (_self.playFlag) {
+ _self.stop();
+ }
+ });
+
+
+ /**
+ * Stop/Play on slideshow hover
+ */
+ if (this.options.playhoverr)
+ ext.hover(function(){
+ if (_self.playFlag) {
+ _self.stop();
+ }
+ }, function(){
+ if (!_self.playFlag) {
+ _self.play();
+ }
+ });
+ };
+
+ /**
+ * Find and show label of slide
+ * @method
+ */
+ this.label = function () {
+ if (!this.options.title) return false;
+
+ label = '';
+
+ current = ext.find('.slideshow-content > *:eq('+this.options.index +')');
+
+ if (current.attr('alt')) {
+ label = current.attr('alt');
+ } else if (current.attr('title')) {
+ label = current.attr('title');
+ }else if (current.find('label:first').length>0) {
+ current.find('label:first').hide();
+ label = current.find('label:first').html();
+ }
+
+ ext.find('.slideshow-label').html(label);
+ };
+
+ /**
+ * Goto previous slide
+ * @method
+ */
+ this.prev = function () {
+ if (this.options.index == 0) {
+ i = (this.length-1);
+ } else {
+ i = this.options.index - 1;
+ }
+
+ this.goSlide(i);
+ };
+
+
+ /**
+ * Play Slideshow
+ * @method
+ */
+ this.play = function () {
+ var _self = this;
+ this.playFlag = true;
+ this.playId = setTimeout(function(ms){ _self._play() }, this.options.time);
+ ext.find('a.play').addClass('stop');
+ };
+
+ /**
+ * Play Slideshow
+ * @method
+ */
+ this._play = function () {
+ var _self = this;
+ this.next();
+ if (this.playFlag) {
+ if (this.options.index == (this.length-1) && !this.options.loop) { this.stop();return false; }
+ this.playId = setTimeout(function(ms){ _self._play() }, this.options.time);
+ }
+ };
+
+ /**
+ * Stop Slideshow
+ * @method
+ */
+ this.stop = function () {
+ ext.find('a.play').removeClass('stop');
+ this.playFlag = false;
+ clearTimeout(this.playId);
+ };
+
+ /**
+ * Goto next slide
+ * @method
+ */
+ this.next = function () {
+ if (this.options.index == (this.length-1)) {
+ i = 0;
+ } else {
+ i = this.options.index + 1;
+ }
+ this.goSlide(i);
+ };
+
+ /**
+ * Init N-slide
+ * @method
+ * @param {Integer} n
+ */
+ this.init = function (index) {
+ // initialize only ones
+ for (var i = 0, loopCnt = this.inited.length; i < loopCnt; i++) {
+ if (this.inited[i] === index) {
+ return true;
+ }
+ }
+
+ // index to inited stack
+ this.inited.push(index);
+
+ // current slide
+ slide = ext.find('.slideshow-content > *:eq('+index+')');
+
+ var _self = this;
+ /**
+ * Replace A to content from HREF
+ */
+ if (slide.get(0).tagName == 'A') {
+ var href = slide.attr('href');
+
+ var title = slide.attr('title');
+ title = title.replace(/\"/i,'\''); // if you use single quotes for tag attribs
+
+ var domain = document.domain;
+ domain = domain.replace(/\./i,"\."); // for strong check domain name
+
+ var reimage = new RegExp("\.(png|gif|jpg|jpeg|svg)$", "i");
+ var relocal = new RegExp("^((https?:\/\/"+domain+")|(?!http:\/\/))", "i");
+
+
+ if (this.options.imgajax && reimage.test(href)) {
+ slide.replaceWith('  ');
+ } else if (this.options.linkajax && relocal.test(href)) {
+ $.get(href, function(data){
+ slide.replaceWith(' '+data+' ');
+ });
+ } else { // nothing else
+// slide.wrap(' ');
+ }
+
+ slide = ext.find('.slideshow-content > *:eq('+index+')');
+
+ // reset css
+ this._build(slide);
+ }
+
+ /**
+ * Play/stop on content click (like image and other)
+ */
+ if (this.options.playclick)
+ $(slide).click(function(){
+ if (_self.playFlag) {
+ _self.stop();
+ } else {
+ _self.play();
+ }
+ return false;
+ });
+ };
+
+ /**
+ * Goto N-slide
+ * @method
+ * @param {Integer} n
+ */
+ this.goSlide = function (n) {
+
+ if (this.options.index == n) return;
+
+ this.init(n);
+
+ var next = ext.find('.slideshow-content > *:eq('+n+')');
+ var prev = ext.find('.slideshow-content > *:eq('+this.options.index+')');
+
+ // restore next slide after all effects, set z-index = 0 for prev slide
+ prev.css({zIndex:0});
+ if (this.options.imgresize) {
+ next.css({zIndex:1, top: 0, left: 0, opacity: 1, width: this.options.width, height: this.options.height});
+ } else {
+ next.css({zIndex:1, top: (this.options.height/2 - next.attr('height')/2), left: (this.options.width/2 - next.attr('width')/2), opacity: 1});
+ }
+
+ this.options.index = n;
+
+ if (this.options.effect == 'random' ) {
+ var r = Math.random();
+ r = Math.floor(r*12);
+ } else {
+ r = -1;
+ }
+ // effect between slides
+ switch (true) {
+ case (this.options.effect == 'scrollUp' || r == 0):
+ prev.css({width:'100%'});
+ next.css({top:0, height:0});
+
+ prevAni = {height: 0, top:this.options.height};
+ break;
+ case (this.options.effect == 'scrollDown' || r == 1):
+ prev.css({width:'100%'});
+ next.css({top:this.options.height,height:0});
+
+ prevAni = {height: 0, top:0};
+ break;
+ case (this.options.effect == 'scrollRight' || r == 2):
+ prev.css({right:0,left:'',height:'100%'});
+ next.css({right:'',left:0,height:'100%',width:'0%'});
+
+ prevAni = {width: 0};
+ break;
+ case (this.options.effect == 'scrollLeft' || r == 3):
+ prev.css({right:'',left:0,height:'100%'});
+ next.css({right:0,left:'',height:'100%',width:'0%'});
+
+ prevAni = {width: 0};
+ break;
+ case (this.options.effect == 'growX' || r == 4):
+ next.css({zIndex:2,opacity: 1,left: this.options.width/2, width: '0%', height:'100%'});
+
+ prevAni = {opacity: 0.8};
+ break;
+
+ case (this.options.effect == 'growY' || r == 5):
+ next.css({opacity: 1,top: this.options.height/2, width:'100%', height: '0%'});
+
+ prevAni = {opacity: 0.8};
+ break;
+
+ case (this.options.effect == 'zoom' || r == 6):
+ next.css({width: 0, height: 0, top: this.options.height/2, left: this.options.width/2});
+
+ prevAni = {width: 0, height: 0, top: this.options.height/2, left: this.options.width/2};
+ break;
+
+ case (this.options.effect == 'zoomFade' || r == 7):
+ next.css({zIndex:1, opacity: 0,width: 0, height: 0, top: this.options.height/2, left: this.options.width/2});
+
+ prevAni = {opacity: 0, width: 0, height: 0, top: this.options.height/2, left: this.options.width/2};
+ break;
+
+ case (this.options.effect == 'zoomTL' || r == 8):
+ next.css({zIndex:1, opacity: 0,width: this.options.width/2, height: this.options.height/2, top:0, left: 0});
+
+ prevAni = {opacity: 0, width: 0, height: 0, top: this.options.height, left: this.options.width};
+ break;
+ case (this.options.effect == 'zoomBR' || r == 9):
+ next.css({zIndex:1, opacity: 0,width: this.options.width/2, height: this.options.height/2, top: this.options.height/2, left: this.options.width/2});
+
+ prevAni = {opacity: 0, width: 0, height: 0, top: 0, left: 0};
+ break;
+ case (this.options.effect == 'fade' || r == 10):
+ default:
+ prev.css({zIndex:0, opacity: 1});
+ next.css({zIndex:1, opacity: 0});
+
+ prevAni = {opacity: 0};
+ break;
+ }
+
+ var _self = this;
+
+ prev.animate(prevAni,this.options.effecttime);
+
+ // play next slide animation, hide prev slide, update label, update counter
+ next.show().animate({opacity: 1}, this.options.effecttime, function () { prev.hide(); _self.label(); _self.counter(); });
+ };
+
+ /**
+ * Update counter data
+ * @method
+ */
+ this.counter = function () {
+ if (this.options.controls.counter)
+ ext.find('.slideshow-panel span.counter').html((this.options.index+1) + ' / ' + this.length);
+
+ };
+
+ // Now initialize the slideshow
+ this.options = $.extend({}, defaults, settings);
+
+ if (typeof(settings) != 'undefined') {
+ if (typeof(settings.controls) != 'undefined')
+ this.options.controls = $.extend({}, defaults.controls, settings.controls);
+ }
+
+ this.build();
+
+ /**
+ * Show slideshow
+ */
+ ext.show();
+
+ /**
+ * Check play option
+ */
+ if (this.options.play) {
+ this.play();
+ }
+
+ return ext;
+ });
+
+ /**
+ * external functions - append to $
+ */
+ _slideshow.playSlide = function(){ _slideshow.each(function () { this.play(); }) };
+ _slideshow.stopSlide = function(){ _slideshow.each(function () { this.stop(); }) };
+ _slideshow.nextSlide = function(){ _slideshow.each(function () { this.next(); }) };
+ _slideshow.prevSlide = function(){ _slideshow.each(function () { this.prev(); }) };
+
+ return this;
+ }
+})(jQuery);
diff --git a/public/javascripts/jquery.aslideshow/simple/images/big-play.png b/public/javascripts/jquery.aslideshow/simple/images/big-play.png
new file mode 100644
index 0000000..f729acb
Binary files /dev/null and b/public/javascripts/jquery.aslideshow/simple/images/big-play.png differ
diff --git a/public/javascripts/jquery.aslideshow/simple/images/buttons.png b/public/javascripts/jquery.aslideshow/simple/images/buttons.png
new file mode 100644
index 0000000..e8ef1ca
Binary files /dev/null and b/public/javascripts/jquery.aslideshow/simple/images/buttons.png differ
diff --git a/public/javascripts/jquery.aslideshow/simple/styles.css b/public/javascripts/jquery.aslideshow/simple/styles.css
new file mode 100644
index 0000000..7137ac4
--- /dev/null
+++ b/public/javascripts/jquery.aslideshow/simple/styles.css
@@ -0,0 +1,180 @@
+.slideshow, .slideshow-label, .slideshow-content, .slideshow-panel {
+ font:12px Verdana, Tahoma, sans-serif;
+}
+
+.slideshow {
+ padding:0;
+ border:0;
+ position:relative;
+ display:none; /* Set to "none" for not preview slideshow content */
+}
+
+.slideshow-fullscreen {
+ position:absolute;
+ top:0;
+ left:0;
+ padding:0;
+ border:0;
+ overflow:hidden;
+}
+
+.slideshow-label-place {
+ padding:0;
+ position:absolute;
+ top:0px;
+ left:0px;
+ z-index:100;
+ height:30px;
+}
+ .slideshow-label {
+ z-index:101;
+ color:#fff;
+ width:100%;
+ height:100%;
+ line-height:30px;
+ text-indent:8px;
+ font-weight:bold
+ }
+
+.slideshow-panel-place {
+ padding:0;
+ position:absolute;
+ bottom:-29px;
+ left:0px;
+ z-index:100;
+ height:28px;
+}
+
+
+ .slideshow-panel {
+ z-index:101;
+ width:100%;
+ height:100%;
+ }
+
+ .slideshow-panel a.slideshowbutton {
+ display: block;
+ width:26px;
+ height:26px;
+ float:left;
+ text-indent:-99999%;
+ overflow:hidden;
+ outline: 0; /* @ Firefox, prevent dotted border after click */
+ background-image:url(images/buttons.png);
+ background-repeat:no-repeat;
+ border:1px solid transparent
+ }
+
+ .slideshow-panel a.slideshowbutton:hover {
+ border:1px solid #777;
+ }
+
+
+ .slideshow-panel a.first {
+ background-position: 0 0
+ }
+
+ .slideshow-panel a.prev {
+ background-position: -24px 0
+ }
+
+ .slideshow-panel a.play {
+ background-position: -48px 0
+ }
+
+ .slideshow-panel a.stop {
+ background-position: -72px 0
+ }
+
+ .slideshow-panel a.next {
+ background-position: -96px 0
+ }
+
+ .slideshow-panel a.last {
+ background-position: -120px 0
+ }
+
+ .slideshow-panel a.help {
+ position:relative;
+ background-position: -144px 0
+ }
+
+ .slideshow-panel span.counter {
+ float:right;
+ display: block;
+ /*width:26px;*/
+ height:26px;
+ line-height:26px;
+ padding:0 4px;
+ color: white;
+ }
+
+
+.slideshow-help {
+ position:absolute;
+ bottom:28px;
+ left:0px;
+ z-index:101;
+ background-color:#ff9;
+ display:none;
+ opacity: 0.9;
+ width:100%;
+}
+
+.slideshow-content {
+ padding:0;
+ background-color:#fff;
+ color:#333;
+ overflow:hidden;
+ position:relative;
+ width:100%;
+ height:100%;
+}
+
+ /* Some Content Changes */
+ .slideshow-content p {
+ padding:0;
+ overflow:auto;
+ }
+
+.slideshow-frame {
+ position:absolute;
+ top:0px;
+ left:0px;
+ background:url(images/big-play.png) 50% 50% no-repeat;
+ z-index:201;
+ cursor:pointer;
+ width:100%;
+ height:100%;
+}
+
+.slideshow-shadow{
+ position:absolute;
+ top:0px;
+ left:0px;
+ z-index:200;
+ width:100%;
+ height:100%;
+}
+
+.slideshow-opacity{
+ background-color: black;
+}
+ *:first-child+html .slideshow-opacity, * html .slideshow-opacity {
+ zoom:1;
+ background:#000;
+ filter:alpha(opacity=50);
+ }
+ * html .slideshow-opacity {
+ zoom:1;
+ background:#000;
+ filter:alpha(opacity=50);
+ }
+
+ *:first-child+html .slideshow-opacity *{
+ position:relative;
+ }
+
+ * html .slideshow-opacity *{
+ position:relative;
+ }
diff --git a/public/stylesheets/controller_content_viewer.css b/public/stylesheets/controller_content_viewer.css
index d6e3169..d7b0474 100644
--- a/public/stylesheets/controller_content_viewer.css
+++ b/public/stylesheets/controller_content_viewer.css
@@ -1,4 +1,5 @@
@import url('products.css');
+@import url('folder.css');
/************* enterprise homepage style *****************/
@@ -45,3 +46,7 @@ div#article-parent {
text-align: right;
font-style: italic;
}
+
+.article-body-uploaded-file {
+ text-align: center;
+}
diff --git a/public/stylesheets/controller_search.css b/public/stylesheets/controller_search.css
index 5f0f6bb..6cae428 100644
--- a/public/stylesheets/controller_search.css
+++ b/public/stylesheets/controller_search.css
@@ -1,3 +1,5 @@
+@import url(pagination.css);
+
#search-page {
position: relative; /* to the text appear on MSIE 6 */
}
@@ -280,27 +282,3 @@
height: 150px;
overflow: auto;
}
-
-/* * * Pagination * * * * * * * * * * * */
-
-.pagination {
- text-align: center;
- clear: both;
-}
-
-.pagination .disabled {
- color: #888;
-}
-
-.pagination .current {
- font-weight: bold;
-}
-
-.pagination a {
- text-decoration: none;
-}
-
-.pagination a:hover {
- color: #026;
-}
-
diff --git a/public/stylesheets/folder.css b/public/stylesheets/folder.css
new file mode 100644
index 0000000..b60b4b0
--- /dev/null
+++ b/public/stylesheets/folder.css
@@ -0,0 +1,68 @@
+@import url(pagination.css);
+
+.image-gallery {
+ text-align: center;
+}
+
+.image-gallery ul {
+ padding: 0px;
+}
+
+.image-gallery-item {
+ width: 142px;
+ height: 154px;
+ list-style: none;
+ margin: 5px;
+ float: left;
+ overflow: hidden;
+}
+
+.image-gallery-item span {
+ text-align: center;
+ font-size: 11px;
+}
+
+.image-gallery-item span a {
+ text-decoration: none;
+ color: #000
+}
+
+.image-gallery-item img {
+ padding: 2px;
+ border: 1px solid;
+}
+
+.image-gallery-item .folder, .image-gallery-item .uploaded-file {
+ width: 120px;
+ height: 120px;
+ border: 1px solid;
+}
+
+.image-gallery-item .folder {
+ background: transparent url('../images/icons-app/gtk-folder.png') no-repeat 50% 43%;
+ display: block;
+ color: #DB8;
+}
+
+.image-gallery-item .folder:hover {
+ border: 4px solid;
+ width: 114px;
+ height: 114px;
+ background-color: #FF9
+}
+
+.image-gallery-item .uploaded-file {
+ background: transparent url('../images/icons-mime/empty.png') no-repeat 50% 43%;
+}
+
+#content #article .image-gallery .pagination .prev_page {
+ position: relative;
+ left: auto;
+ right: auto;
+}
+
+#content #article .image-gallery .pagination .next_page {
+ position: relative;
+ right: auto;
+ left: auto;
+}
diff --git a/public/stylesheets/pagination.css b/public/stylesheets/pagination.css
new file mode 100644
index 0000000..5ba9dde
--- /dev/null
+++ b/public/stylesheets/pagination.css
@@ -0,0 +1,20 @@
+.pagination {
+ text-align: center;
+ clear: both;
+}
+
+.pagination .disabled {
+ color: #888;
+}
+
+.pagination .current {
+ font-weight: bold;
+}
+
+.pagination a {
+ text-decoration: none;
+}
+
+.pagination a:hover {
+ color: #026;
+}
diff --git a/test/functional/cms_controller_test.rb b/test/functional/cms_controller_test.rb
index ae2c2cf..c33e663 100644
--- a/test/functional/cms_controller_test.rb
+++ b/test/functional/cms_controller_test.rb
@@ -190,6 +190,7 @@ class CmsControllerTest < Test::Unit::TestCase
post :new, :type => UploadedFile.name, :profile => profile.identifier, :article => { :uploaded_data => fixture_file_upload('/files/test.txt', 'text/plain')}
end
assert_not_nil profile.articles.find_by_path('test.txt')
+ assigns(:article).destroy
end
should 'be able to update an uploaded file' do
@@ -816,4 +817,53 @@ class CmsControllerTest < Test::Unit::TestCase
get :edit, :profile => profile.identifier, :id => profile.blog.id
assert_tag :tag => 'a', :content => 'Cancel', :attributes => { :href => /\/myprofile\/#{profile.identifier}/ }
end
+
+ should 'create icon upload file in folder' do
+ f = Folder.create!(:name => 'test_folder', :profile => profile, :view_as => 'image_gallery')
+ post :new, :profile => profile.identifier,
+ :type => UploadedFile.name,
+ :parent_id => f.id,
+ :article => {:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png')}
+
+ assert File.exists?(assigns(:article).icon_name)
+ assigns(:article).destroy
+ end
+
+ should 'create icon upload file' do
+ post :new, :profile => profile.identifier,
+ :type => UploadedFile.name,
+ :article => {:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png')}
+
+ assert File.exists?(assigns(:article).icon_name)
+ assigns(:article).destroy
+ end
+
+ should 'record when coming from public view on upload files' do
+ folder = Folder.create!(:name => 'testfolder', :profile => profile)
+
+ @request.expects(:referer).returns("http://colivre.net/#{profile.identifier}/#{folder.slug}")
+
+ get :upload_files, :profile => profile.identifier, :parent_id => folder.id
+ assert_tag :tag => 'input', :attributes => { :type => 'hidden', :name => 'back_to', :value => 'public_view' }
+ assert_tag :tag => 'a', :descendant => { :content => 'Cancel' }, :attributes => { :href => /^https?:\/\/colivre.net\/#{profile.identifier}\/#{folder.slug}/ }
+ end
+
+ should 'detect when comming from home page to upload files' do
+ folder = Folder.create!(:name => 'testfolder', :profile => profile)
+ profile.expects(:home_page).returns(folder).at_least_once
+
+ @request.expects(:referer).returns("http://colivre.net/#{profile.identifier}").at_least_once
+ @controller.stubs(:profile).returns(profile)
+ get :upload_files, :profile => profile.identifier, :parent_id => folder.id
+ assert_tag :tag => 'input', :attributes => { :type => 'hidden', :name => 'back_to', :value => 'public_view' }
+ assert_tag :tag => 'a', :descendant => { :content => 'Cancel' }, :attributes => { :href => /^https?:\/\/colivre.net\/#{profile.identifier}\/#{profile.home_page.slug}$/ }
+ end
+
+ should 'go back to public view when upload files coming from there' do
+ folder = Folder.create!(:name => 'test_folder', :profile => profile)
+
+ post :upload_files, :profile => profile.identifier, :parent_id => folder.id, :back_to => 'public_view', :uploaded_files => [fixture_file_upload('files/rails.png', 'image/png')]
+ assert_template nil
+ assert_redirected_to folder.url
+ end
end
diff --git a/test/functional/content_viewer_controller_test.rb b/test/functional/content_viewer_controller_test.rb
index 58d8090..f5f90e9 100644
--- a/test/functional/content_viewer_controller_test.rb
+++ b/test/functional/content_viewer_controller_test.rb
@@ -658,4 +658,45 @@ class ContentViewerControllerTest < Test::Unit::TestCase
assert_equal 1, a.hits
end
+ should 'render html for image when view' do
+ file = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => profile)
+ get :view_page, :profile => profile.identifier, :page => file.explode_path, :view => true
+
+ assert_response :success
+ assert_template 'view_page'
+ end
+
+ should 'download data for image when not view' do
+ file = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => profile)
+ get :view_page, :profile => profile.identifier, :page => file.explode_path
+
+ assert_response :success
+ assert_template nil
+ end
+
+ should "display 'Upload files' when create children of image gallery" do
+ login_as(profile.identifier)
+ f = Folder.create!(:name => 'gallery', :profile => profile, :view_as => 'image_gallery')
+ get :view_page, :profile => profile.identifier, :page => f.explode_path
+ assert_tag :tag => 'a', :content => 'Upload files', :attributes => {:href => /parent_id=#{f.id}/}
+ end
+
+ should "display 'New article' when showing folder child of image gallery" do
+ login_as(profile.identifier)
+ folder1 = Folder.create!(:name => 'gallery1', :profile => profile, :view_as => 'image_gallery')
+ folder1.children << folder2 = Folder.new(:name => 'gallery2', :profile => profile)
+
+ get :view_page, :profile => profile.identifier, :page => folder2.explode_path
+ assert_no_tag :tag => 'a', :content => 'Upload files', :attributes => {:href => /parent_id=#{folder2.id}/}
+ assert_tag :tag => 'a', :content => 'New article', :attributes => {:href =>/parent_id=#{folder2.id}/}
+ end
+
+ should "display 'Upload files' to image gallery when showing its children" do
+ login_as(profile.identifier)
+ folder = Folder.create!(:name => 'gallery', :profile => profile, :view_as => 'image_gallery')
+ file = UploadedFile.create!(:profile => profile, :parent => folder, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'))
+ get :view_page, :profile => profile.identifier, :page => file.explode_path, :view => true
+
+ assert_tag :tag => 'a', :content => 'Upload files', :attributes => {:href => /parent_id=#{folder.id}/}
+ end
end
diff --git a/test/unit/folder_test.rb b/test/unit/folder_test.rb
index 97fd9eb..147fb29 100644
--- a/test/unit/folder_test.rb
+++ b/test/unit/folder_test.rb
@@ -25,8 +25,8 @@ class FolderTest < ActiveSupport::TestCase
f.children.create!(:profile => p, :name => 'otherarticle')
f.reload
- assert_tag_in_string f.to_html, :tag => 'td', :descendant => { :tag => 'a', :attributes => { :href => /.*\/testuser\/f\/onearticle$/ } }, :content => /onearticle/
- assert_tag_in_string f.to_html, :tag => 'td', :descendant => { :tag => 'a', :attributes => { :href => /.*\/testuser\/f\/otherarticle$/ } }, :content => /otherarticle/
+ assert_tag_in_string f.to_html, :tag => 'td', :descendant => { :tag => 'a', :attributes => { :href => /.*\/testuser\/f\/onearticle(\?|$)/ } }, :content => /onearticle/
+ assert_tag_in_string f.to_html, :tag => 'td', :descendant => { :tag => 'a', :attributes => { :href => /.*\/testuser\/f\/otherarticle(\?|$)/ } }, :content => /otherarticle/
end
should 'explictly advise if empty' do
@@ -52,4 +52,59 @@ class FolderTest < ActiveSupport::TestCase
assert_equal false, a.can_display_hits?
end
+ should 'be viewed as image gallery' do
+ p = create_user('test_user').person
+ f = Folder.create!(:name => 'Test folder', :profile => p)
+ f.view_as = 'image_gallery'; f.save!
+ f.reload
+
+ assert_equal 'image_gallery', f.view_as
+ end
+
+ should 'not allow view as bogus' do
+ p = create_user('test_user').person
+ f = Folder.create!(:name => 'Test folder', :profile => p)
+ f.view_as = 'bogus'
+ assert !f.save
+ end
+
+ should 'view as folder by default' do
+ p = create_user('test_user').person
+ f = Folder.create!(:name => 'Test folder', :profile => p)
+ f.expects(:folder)
+ f.to_html
+
+ assert_equal 'folder', f.view_as
+ end
+
+ should 'have images that are only images or other folders' do
+ p = create_user('test_user').person
+ f = Folder.create!(:name => 'Test folder', :profile => p)
+ file = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/test.txt', 'text/plain'), :parent => f, :profile => p)
+ image = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :parent => f, :profile => p)
+ folder = Folder.create!(:name => 'child test folder', :parent => f, :profile => p)
+
+ assert_equivalent [folder, image], f.images
+ end
+
+ should 'bring folders first in alpha order in images listing' do
+ p = create_user('test_user').person
+ f = Folder.create!(:name => 'Test folder', :profile => p)
+ folder1 = Folder.create!(:name => 'child test folder 1', :parent => f, :profile => p)
+ image = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :parent => f, :profile => p)
+ folder2 = Folder.create!(:name => 'child test folder 2', :parent => f, :profile => p)
+ folder3 = Folder.create!(:name => 'another child test folder', :parent => f, :profile => p)
+
+ assert_equal [folder3.id, folder1.id, folder2.id, image.id], f.images.map(&:id)
+ end
+
+ should 'images support pagination' do
+ p = create_user('test_user').person
+ f = Folder.create!(:name => 'Test folder', :profile => p)
+ folder = Folder.create!(:name => 'child test folder', :parent => f, :profile => p)
+ image = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :parent => f, :profile => p)
+
+ assert_equal [image], f.images.paginate(:page => 2, :per_page => 1)
+ end
+
end
diff --git a/test/unit/uploaded_file_test.rb b/test/unit/uploaded_file_test.rb
index 080cbe0..f094bed 100644
--- a/test/unit/uploaded_file_test.rb
+++ b/test/unit/uploaded_file_test.rb
@@ -85,4 +85,21 @@ class UploadedFileTest < Test::Unit::TestCase
assert f.valid?
end
+ should 'create icon when created in folder' do
+ p = create_user('test_user').person
+ f = Folder.create!(:name => 'test_folder', :profile => p)
+ file = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :parent_id => f.id, :profile => p)
+
+ assert File.exists?(file.public_filename(:icon))
+ file.destroy
+ end
+
+ should 'create icon when not created in folder' do
+ p = create_user('test_user').person
+ file = UploadedFile.create!(:uploaded_data => fixture_file_upload('/files/rails.png', 'image/png'), :profile => p)
+
+ assert File.exists?(file.public_filename(:icon))
+ file.destroy
+ end
+
end
diff --git a/vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu.rb b/vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu.rb
index 8a136d0..3432684 100644
--- a/vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu.rb
+++ b/vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu.rb
@@ -220,7 +220,11 @@ module Technoweenie # :nodoc:
# Returns true/false if an attachment is thumbnailable. A thumbnailable attachment has an image content type and the parent_id attribute.
def thumbnailable?
- image? && respond_to?(:parent_id) && parent_id.nil?
+ image? && !is_thumbnail?
+ end
+
+ def is_thumbnail?
+ (thumbnail_class == self.class) && !(respond_to?(:parent_id) && parent_id.nil?)
end
# Returns the class used to create new thumbnails for this attachment.
@@ -389,7 +393,7 @@ module Technoweenie # :nodoc:
# Initializes a new thumbnail with the given suffix.
def find_or_initialize_thumbnail(file_name_suffix)
- respond_to?(:parent_id) ?
+ thumbnail_class.columns.map(&:name).include?('parent_id') ?
thumbnail_class.find_or_initialize_by_thumbnail_and_parent_id(file_name_suffix.to_s, id) :
thumbnail_class.find_or_initialize_by_thumbnail(file_name_suffix.to_s)
end
@@ -402,7 +406,7 @@ module Technoweenie # :nodoc:
# Cleans up after processing. Thumbnails are created, the attachment is stored to the backend, and the temp_paths are cleared.
def after_process_attachment
if @saved_attachment
- if respond_to?(:process_attachment_with_processing) && thumbnailable? && !attachment_options[:thumbnails].blank? && parent_id.nil?
+ if respond_to?(:process_attachment_with_processing) && thumbnailable? && !attachment_options[:thumbnails].blank?
temp_file = temp_path || create_temp_file
attachment_options[:thumbnails].each { |suffix, size| create_or_update_thumbnail(temp_file, suffix, *size) }
end
diff --git a/vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/backends/file_system_backend.rb b/vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/backends/file_system_backend.rb
index 464b9c7..a714a86 100644
--- a/vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/backends/file_system_backend.rb
+++ b/vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/backends/file_system_backend.rb
@@ -28,7 +28,7 @@ module Technoweenie # :nodoc:
# The attachment ID used in the full path of a file
def attachment_path_id
- ((respond_to?(:parent_id) && parent_id) || id).to_i
+ (is_thumbnail? && respond_to?(:parent_id)) ? parent_id : id
end
# overrwrite this to do your own app-specific partitioning.
@@ -94,4 +94,4 @@ module Technoweenie # :nodoc:
end
end
end
-end
\ No newline at end of file
+end
--
libgit2 0.21.2 |