+
"> <%= 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(''); + + if (this.options.controls.play) + panel.append('Play'); + + if (this.options.controls.next) + panel.append(''); + + 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(''+title+''); + } 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