sweet_portfolio 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. data/.document +5 -0
  2. data/.powrc +4 -0
  3. data/.ruby-version +1 -0
  4. data/.travis.yml +2 -0
  5. data/Gemfile +11 -0
  6. data/LICENSE +20 -0
  7. data/README.md +37 -0
  8. data/Rakefile +21 -0
  9. data/VERSION +1 -0
  10. data/app/assets/images/sweet_portfolio/blank.gif +0 -0
  11. data/app/assets/images/sweet_portfolio/border.png +0 -0
  12. data/app/assets/images/sweet_portfolio/controls.png +0 -0
  13. data/app/assets/images/sweet_portfolio/fancybox_loading.gif +0 -0
  14. data/app/assets/images/sweet_portfolio/fancybox_overlay.png +0 -0
  15. data/app/assets/images/sweet_portfolio/fancybox_sprite.png +0 -0
  16. data/app/assets/images/sweet_portfolio/jcrop.gif +0 -0
  17. data/app/assets/images/sweet_portfolio/loading.gif +0 -0
  18. data/app/assets/images/sweet_portfolio/loading_background.png +0 -0
  19. data/app/assets/images/sweet_portfolio/overlay.png +0 -0
  20. data/app/assets/javascripts/sweet_portfolio/jquery.colorbox.js +4 -0
  21. data/app/assets/javascripts/sweet_portfolio/jquery.fancybox-media.js +196 -0
  22. data/app/assets/javascripts/sweet_portfolio/jquery.fancybox-thumbs.js +162 -0
  23. data/app/assets/javascripts/sweet_portfolio/jquery.fancybox.pack.js +45 -0
  24. data/app/assets/javascripts/sweet_portfolio/jquery.jcrop.js +246 -0
  25. data/app/assets/stylesheets/sweet_portfolio/colorbox.css +61 -0
  26. data/app/assets/stylesheets/sweet_portfolio/jquery.fancybox-thumbs.css +54 -0
  27. data/app/assets/stylesheets/sweet_portfolio/jquery.fancybox.css +249 -0
  28. data/app/assets/stylesheets/sweet_portfolio/jquery.jcrop.css +32 -0
  29. data/app/controllers/admin/gallery/base_controller.rb +3 -0
  30. data/app/controllers/admin/gallery/galleries_controller.rb +72 -0
  31. data/app/controllers/admin/gallery/photos_controller.rb +90 -0
  32. data/app/controllers/application_controller.rb +7 -0
  33. data/app/helpers/gallery/application_helper.rb +12 -0
  34. data/app/models/gallery/gallery.rb +33 -0
  35. data/app/models/gallery/photo.rb +83 -0
  36. data/app/views/admin/gallery/_navigation.html.erb +1 -0
  37. data/app/views/admin/gallery/galleries/_form.html.haml +15 -0
  38. data/app/views/admin/gallery/galleries/edit.html.haml +5 -0
  39. data/app/views/admin/gallery/galleries/index.html.haml +28 -0
  40. data/app/views/admin/gallery/galleries/new.html.haml +5 -0
  41. data/app/views/admin/gallery/photos/_form.html.haml +12 -0
  42. data/app/views/admin/gallery/photos/crop.html.haml +50 -0
  43. data/app/views/admin/gallery/photos/edit.html.haml +5 -0
  44. data/app/views/admin/gallery/photos/index.html.haml +19 -0
  45. data/app/views/admin/gallery/photos/new.html.haml +5 -0
  46. data/app/views/layouts/gallery/application.html.haml +12 -0
  47. data/config.ru +4 -0
  48. data/config/application.rb +51 -0
  49. data/config/boot.rb +13 -0
  50. data/config/database.yml +16 -0
  51. data/config/environment.rb +5 -0
  52. data/config/environments/development.rb +25 -0
  53. data/config/environments/production.rb +52 -0
  54. data/config/environments/test.rb +39 -0
  55. data/config/initializers/paperclip.rb +3 -0
  56. data/config/initializers/sweet_portfolio.rb +12 -0
  57. data/config/routes.rb +3 -0
  58. data/db/migrate/01_create_sweet_portfolio.rb +37 -0
  59. data/lib/generators/sweet_portfolio/README +10 -0
  60. data/lib/generators/sweet_portfolio/sweet_portfolio.rb +37 -0
  61. data/lib/paperclip_processors/cropper.rb +31 -0
  62. data/lib/sweet_portfolio.rb +28 -0
  63. data/lib/sweet_portfolio/configuration.rb +26 -0
  64. data/lib/sweet_portfolio/engine.rb +21 -0
  65. data/lib/sweet_portfolio/form_builder.rb +50 -0
  66. data/lib/sweet_portfolio/routing.rb +21 -0
  67. data/lib/tasks/sweet_portfolio.rake +4 -0
  68. data/script/rails +6 -0
  69. data/sweet_portfolio.gemspec +134 -0
  70. data/test/fixtures/files/default.jpg +0 -0
  71. data/test/fixtures/files/default.txt +1 -0
  72. data/test/fixtures/files/default2.jpg +0 -0
  73. data/test/fixtures/gallery/galleries.yml +11 -0
  74. data/test/fixtures/gallery/photos.yml +8 -0
  75. data/test/functional/admin/gallery/galleries_controller_test.rb +107 -0
  76. data/test/functional/admin/gallery/photos_controller_test.rb +224 -0
  77. data/test/test_helper.rb +39 -0
  78. data/test/unit/configuration_test.rb +16 -0
  79. data/test/unit/gallery_test.rb +38 -0
  80. data/test/unit/photo_test.rb +40 -0
  81. metadata +228 -0
@@ -0,0 +1,32 @@
1
+ /* Fixes issue here http://code.google.com/p/jcrop/issues/detail?id=1 */
2
+ .jcrop-holder { text-align: left; }
3
+
4
+ .jcrop-vline, .jcrop-hline {
5
+ font-size: 0px;
6
+ position: absolute;
7
+ background: white url('/assets/sweet_portfolio/jcrop.gif') top left repeat;
8
+ }
9
+ .jcrop-vline { height: 100%; width: 1px !important; }
10
+ .jcrop-hline { width: 100%; height: 1px !important; }
11
+ .jcrop-vline.right { right: 0px; }
12
+ .jcrop-hline.bottom { bottom: 0px; }
13
+ .jcrop-handle {
14
+ font-size: 1px;
15
+ width: 7px !important;
16
+ height: 7px !important;
17
+ border: 1px #eee solid;
18
+ background-color: #333;
19
+ }
20
+
21
+ .jcrop-tracker { width: 100%; height: 100%; }
22
+
23
+ .custom .jcrop-vline,
24
+ .custom .jcrop-hline {
25
+ background: yellow;
26
+ }
27
+ .custom .jcrop-handle {
28
+ border-color: black;
29
+ background-color: #C7BB00;
30
+ -moz-border-radius: 3px;
31
+ -webkit-border-radius: 3px;
32
+ }
@@ -0,0 +1,3 @@
1
+ class Admin::Gallery::BaseController < SweetPortfolio.config.admin_controller.to_s.constantize
2
+ # ...
3
+ end
@@ -0,0 +1,72 @@
1
+ class Admin::Gallery::GalleriesController < Admin::Gallery::BaseController
2
+
3
+ before_filter :load_gallery, :except => [:index, :new, :create, :reorder]
4
+ before_filter :build_gallery, :only => [:new, :create]
5
+
6
+ def index
7
+ if params[:category].present?
8
+ @galleries = Gallery::Gallery.for_category(params[:category]).all
9
+ else
10
+ @galleries = Gallery::Gallery.all
11
+ end
12
+ end
13
+
14
+ def new
15
+ render
16
+ end
17
+
18
+ def create
19
+ @gallery.save!
20
+ flash[:notice] = 'Gallery created'
21
+ redirect_to :action => :index
22
+ rescue ActiveRecord::RecordInvalid
23
+ flash.now[:error] = 'Failed to create Gallery'
24
+ render :action => :new
25
+ end
26
+
27
+ def show
28
+ render
29
+ end
30
+
31
+ def edit
32
+ render
33
+ end
34
+
35
+ def update
36
+ @gallery.update_attributes!(params[:gallery])
37
+ flash[:notice] = 'Gallery updated'
38
+ redirect_to :action => :index
39
+ rescue ActiveRecord::RecordInvalid
40
+ flash.now[:error] = 'Failed to update Gallery'
41
+ render :action => :edit
42
+ end
43
+
44
+ def destroy
45
+ @gallery.destroy
46
+ flash[:notice] = 'Gallery deleted'
47
+ redirect_to :action => :index
48
+ end
49
+
50
+ def reorder
51
+ (params[:gallery_gallery] || []).each_with_index do |id, index|
52
+ if (gallery = Gallery::Gallery.find_by_id(id))
53
+ gallery.update_attribute(:position, index)
54
+ end
55
+ end
56
+ render :nothing => true
57
+ end
58
+
59
+ protected
60
+
61
+ def load_gallery
62
+ @gallery = Gallery::Gallery.find(params[:id])
63
+ rescue ActiveRecord::RecordNotFound
64
+ flash[:error] = 'Gallery not found'
65
+ redirect_to :action => :index
66
+ end
67
+
68
+ def build_gallery
69
+ @gallery = Gallery::Gallery.new(params[:gallery])
70
+ end
71
+
72
+ end
@@ -0,0 +1,90 @@
1
+ class Admin::Gallery::PhotosController < Admin::Gallery::BaseController
2
+
3
+ before_filter :load_gallery
4
+ before_filter :load_photo, :only => [:edit, :update, :destroy, :crop]
5
+ before_filter :build_photo, :only => [:new, :create]
6
+
7
+ def index
8
+ @photos = @gallery.photos
9
+ end
10
+
11
+ def new
12
+ render
13
+ end
14
+
15
+ def create
16
+ file_array = params[:gallery_photo][:image] || [nil]
17
+
18
+ file_array.each_with_index do |file, i|
19
+ file_params = params[:gallery_photo].merge(:image => file)
20
+
21
+ title = (file_params[:title].blank? && file_params[:image] ?
22
+ file_params[:image].original_filename :
23
+ file_params[:title]
24
+ )
25
+ title = title + " #{i + 1}" if file_params[:title] == title && file_array.size > 1
26
+
27
+ @photo = Gallery::Photo.new({:gallery => @gallery}.merge(file_params.merge(:title => title) || {}))
28
+ @photo.save!
29
+ end
30
+
31
+ flash[:notice] = 'Photo created'
32
+ redirect_to :action => :index
33
+ rescue ActiveRecord::RecordInvalid
34
+ flash[:error] = 'Failed to create Photo'
35
+ render :action => :new
36
+ end
37
+
38
+ def edit
39
+ render
40
+ end
41
+
42
+ def update
43
+ @photo.update_attributes!(params[:gallery_photo])
44
+ flash[:notice] = 'Photo updated'
45
+ redirect_to :action => :index
46
+ rescue ActiveRecord::RecordInvalid
47
+ flash.now[:error] = 'Failed to updated Photo'
48
+ render :action => :edit
49
+ end
50
+
51
+ def destroy
52
+ @photo.destroy
53
+ flash[:notice] = 'Photo deleted'
54
+ redirect_to :action => :index
55
+ end
56
+
57
+ def reorder
58
+ (params[:gallery_photo] || []).each_with_index do |id, index|
59
+ if (photo = Gallery::Photo.find_by_id(id))
60
+ photo.update_attribute(:position, index)
61
+ end
62
+ end
63
+ render :nothing => true
64
+ end
65
+
66
+ def crop
67
+ render
68
+ end
69
+
70
+ protected
71
+
72
+ def load_gallery
73
+ @gallery = Gallery::Gallery.find(params[:gallery_id])
74
+ rescue ActiveRecord::RecordNotFound
75
+ flash[:error] = 'Gallery not found'
76
+ redirect_to admin_gallery_galleries_path
77
+ end
78
+
79
+ def load_photo
80
+ @photo = @gallery.photos.find(params[:id])
81
+ rescue ActiveRecord::RecordNotFound
82
+ flash[:error] = 'Photo not found'
83
+ redirect_to :action => :index
84
+ end
85
+
86
+ def build_photo
87
+ @photo = Gallery::Photo.new({:gallery => @gallery}.merge(params[:sofa_gallery_photo] || {}))
88
+ end
89
+
90
+ end
@@ -0,0 +1,7 @@
1
+ class ApplicationController < ActionController::Base
2
+
3
+ protect_from_forgery
4
+
5
+ layout 'gallery/application'
6
+
7
+ end
@@ -0,0 +1,12 @@
1
+ module Gallery::ApplicationHelper
2
+
3
+ def sweet_portfolio_form_for(record_or_name_or_array, *args, &proc)
4
+ options = args.extract_options!
5
+ form_for(
6
+ record_or_name_or_array,
7
+ *(args << options.merge(:builder => SweetPortfolio.config.form_builder.to_s.constantize)),
8
+ &proc
9
+ )
10
+ end
11
+
12
+ end
@@ -0,0 +1,33 @@
1
+ class Gallery::Gallery < ActiveRecord::Base
2
+
3
+ cms_is_categorized if defined?(ComfortableMexicanSofa)
4
+
5
+ self.table_name = :gallery_galleries
6
+
7
+ # -- Relationships --------------------------------------------------------
8
+ has_many :photos, :dependent => :destroy
9
+
10
+ # -- Validations ----------------------------------------------------------
11
+ validates :title,
12
+ :presence => true
13
+ attr_accessible :title, :identifier, :description, :full_width, :full_height, :force_ratio_full, :thumb_width, :thumb_height, :force_ratio_thumb, :short_description, :category_ids
14
+
15
+ validates :identifier,
16
+ :presence => true,
17
+ :uniqueness => true,
18
+ :format => { :with => /^\w[a-z0-9_-]*$/i }
19
+
20
+ # -- Callbacks ------------------------------------------------------------
21
+ before_create :assign_position
22
+
23
+ # -- Scopes ---------------------------------------------------------------
24
+ default_scope order('gallery_galleries.position')
25
+
26
+ private
27
+
28
+ def assign_position
29
+ max = Gallery::Gallery.maximum(:position).to_i
30
+ self.position = max ? max + 1 : 0
31
+ end
32
+
33
+ end
@@ -0,0 +1,83 @@
1
+ class Gallery::Photo < ActiveRecord::Base
2
+
3
+ self.table_name = :gallery_photos
4
+
5
+ upload_options = (SweetPortfolio.config.upload_options || {}).merge(
6
+ :styles => lambda { |image|
7
+ g = image.instance.gallery
8
+ f_settings = "#{g.full_width}x#{g.full_height}#{g.force_ratio_full?? '#' : '>'}"
9
+ t_settings = "#{g.thumb_width}x#{g.thumb_height}#{g.force_ratio_thumb?? '#' : '>'}"
10
+ {
11
+ :full => { :geometry => f_settings, :processors => [:full_cropper] },
12
+ :thumb => { :geometry => t_settings, :processors => [:thumb_cropper] },
13
+ :admin_full => '800x600>',
14
+ :admin_thumb => '40x30#'
15
+ }
16
+ }
17
+ )
18
+ has_attached_file :image, upload_options
19
+
20
+ attr_accessor :thumb_crop_x, :thumb_crop_y, :thumb_crop_w, :thumb_crop_h,
21
+ :full_crop_x, :full_crop_y, :full_crop_w, :full_crop_h
22
+
23
+ # -- Relationships --------------------------------------------------------
24
+ belongs_to :gallery
25
+
26
+ # -- Callbacks ------------------------------------------------------------
27
+ before_create :assign_position
28
+ after_update :reprocess_image, :if => :cropping?
29
+
30
+ # -- Validations ----------------------------------------------------------
31
+ validates :gallery_id,
32
+ :presence => true
33
+ validates_attachment_presence :image,
34
+ :message => 'There was no file uploaded!'
35
+ validates_attachment_content_type :image,
36
+ :content_type => %w(image/jpeg image/pjpeg image/gif image/png image/x-png),
37
+ :message => 'Please only upload .jpg, .jpeg, .gif or .png files.'
38
+ validates_attachment_size :image,
39
+ :less_than => 5.megabytes
40
+
41
+ attr_accessible :gallery, :title, :description, :image, :embed_code
42
+
43
+ # -- Scopes ---------------------------------------------------------------
44
+ default_scope order('gallery_photos.position')
45
+
46
+ # -- Instance Methods -----------------------------------------------------
47
+ def image_geometry(style = :original)
48
+ @geometry ||= {}
49
+ @geometry[style] ||= Paperclip::Geometry.from_file(image.path(style))
50
+ end
51
+
52
+ def force_aspect?
53
+ self.gallery.force_ratio_full? || self.gallery.force_ratio_thumb?
54
+ end
55
+
56
+ def cropping?
57
+ cropping_thumb? || cropping_full?
58
+ end
59
+
60
+ def cropping_thumb?
61
+ !thumb_crop_x.blank? && !thumb_crop_y.blank? && !thumb_crop_w.blank? && !thumb_crop_h.blank?
62
+ end
63
+
64
+ def cropping_full?
65
+ !full_crop_x.blank? && !full_crop_y.blank? && !full_crop_w.blank? && !full_crop_h.blank?
66
+ end
67
+
68
+ def has_media?
69
+ self.embed_code.present?
70
+ end
71
+
72
+ private
73
+
74
+ def assign_position
75
+ max = self.gallery.photos.maximum(:position)
76
+ self.position = max ? max + 1 : 0
77
+ end
78
+
79
+ def reprocess_image
80
+ image.reprocess!
81
+ end
82
+
83
+ end
@@ -0,0 +1 @@
1
+ <li><%= active_link_to 'Galleries', admin_gallery_galleries_path %></li>
@@ -0,0 +1,15 @@
1
+
2
+ = form.text_field :title, :data => {:slugify => @gallery.new_record?}
3
+ = form.text_field :identifier, :data => {:slug => true}
4
+ = form.text_area :description, :"data-rich-text" => "true"
5
+ = form.text_area :short_description, :"data-rich-text" => "true"
6
+ = form.text_field :full_width
7
+ = form.text_field :full_height
8
+ = form.check_box :force_ratio_full, :label => "Force Ratio"
9
+ = form.text_field :thumb_width
10
+ = form.text_field :thumb_height
11
+ = form.check_box :force_ratio_thumb, :label => "Force Ratio"
12
+ = render :partial => 'cms_admin/categories/form', :object => form if defined?(ComfortableMexicanSofa)
13
+
14
+ .form-actions
15
+ = form.submit @gallery.new_record?? 'Create post' : 'Update post', :class => 'btn btn-primary'
@@ -0,0 +1,5 @@
1
+ .page-header
2
+ %h2= "Editing #{@gallery.title}"
3
+
4
+ = comfy_form_for @gallery, :as => :gallery, :url => { :action => :update } do |form|
5
+ = render form
@@ -0,0 +1,28 @@
1
+
2
+
3
+ .page-header
4
+ = link_to 'Add new gallery', new_admin_gallery_gallery_path, :class => 'btn pull-right'
5
+ %h2 Galleries
6
+
7
+ = render :partial => 'cms_admin/categories/index', :object => 'Gallery::Gallery' if defined?(ComfortableMexicanSofa)
8
+
9
+ %br/
10
+ %table.table.table-hover.table-bordered
11
+ %tr
12
+ %th Preview
13
+ %th Name
14
+ %th Actions
15
+ %tbody.sortable
16
+ - @galleries.each do |gallery|
17
+ %tr{:id => dom_id(gallery)}
18
+ %td
19
+ .dragger{:style => "cursor: move;"}
20
+ - gallery.photos.limit(1).each do |photo|
21
+ = image_tag(photo.image.url(:admin_thumb))
22
+ %td.main
23
+ = link_to gallery.title, admin_gallery_gallery_photos_path(gallery)
24
+ %td
25
+ .btn-group
26
+ = link_to 'Show Photos', admin_gallery_gallery_photos_path(gallery), :class => 'btn btn-small'
27
+ = link_to 'Edit', edit_admin_gallery_gallery_path(gallery), :class => 'btn btn-small'
28
+ = link_to 'Delete', admin_gallery_gallery_path(gallery), :method => :delete, :confirm => 'Are you sure?', :class => 'btn btn-small btn-danger'
@@ -0,0 +1,5 @@
1
+ .page-header
2
+ %h2= "New Gallery"
3
+
4
+ = comfy_form_for @gallery, :as => :gallery, :url => { :action => :create } do |form|
5
+ = render form
@@ -0,0 +1,12 @@
1
+ = form.text_field :title
2
+ - if @photo.image? && @photo.id.present?
3
+ = form.element 'Current Image' do
4
+ = image_tag(@photo.image.url(:thumb))
5
+ %br/
6
+ = link_to 'Crop Image', crop_admin_gallery_gallery_photo_path(@gallery, @photo) if @photo.force_aspect?
7
+ = form.file_field :image, :multiple => true
8
+ = form.text_area :description, :"data-rich-text" => "true"
9
+ = form.text_area :embed_code, :class => 'short'
10
+
11
+ .form-actions
12
+ = form.submit 'Save', :class => 'btn btn-primary'
@@ -0,0 +1,50 @@
1
+ - content_for :head do
2
+ = stylesheet_link_tag 'sweet_portfolio/jquery.jcrop.css'
3
+ = javascript_include_tag 'sweet_portfolio/jquery.jcrop.js'
4
+ %script{:charset => "utf-8", :type => "text/javascript"}
5
+ $(function(){
6
+ $('#crop_full').Jcrop({
7
+ onChange: update_full_crop,
8
+ onSelect: update_full_crop,
9
+ aspectRatio: <haml:loud> @photo.gallery.force_ratio_full?? (@photo.gallery.full_width.to_f / @photo.gallery.full_height) : 'null' </haml:loud>
10
+ });
11
+
12
+ $('#crop_thumb').Jcrop({
13
+ onChange: update_thumb_crop,
14
+ onSelect: update_thumb_crop,
15
+ aspectRatio: <haml:loud> @photo.gallery.force_ratio_thumb?? (@photo.gallery.thumb_width.to_f / @photo.gallery.thumb_height) : 'null' </haml:loud>
16
+ });
17
+ });
18
+
19
+
20
+ function update_full_crop(coords) {
21
+ var ratio = <haml:loud> @photo.image_geometry(:original).width </haml:loud> / <haml:loud> @photo.image_geometry(:admin_full).width </haml:loud>;
22
+ $('#full_crop_x').val(coords.x * ratio);
23
+ $('#full_crop_y').val(coords.y * ratio);
24
+ $('#full_crop_w').val(coords.w * ratio);
25
+ $('#full_crop_h').val(coords.h * ratio);
26
+ }
27
+
28
+ function update_thumb_crop(coords) {
29
+ var ratio = <haml:loud> @photo.image_geometry(:original).width </haml:loud> / <haml:loud> @photo.image_geometry(:admin_full).width </haml:loud>;
30
+ $('#thumb_crop_x').val(coords.x * ratio);
31
+ $('#thumb_crop_y').val(coords.y * ratio);
32
+ $('#thumb_crop_w').val(coords.w * ratio);
33
+ $('#thumb_crop_h').val(coords.h * ratio);
34
+ }
35
+
36
+ %h1 Crop Photo
37
+ = comfy_form_for @photo, :as => :photo, :url => { :action => :update } do |form|
38
+ - if @photo.gallery.force_ratio_full?
39
+ = form.element 'Full Size' do
40
+ = image_tag @photo.image.url(:admin_full), :id => 'crop_full'
41
+ %br/
42
+ - if @photo.gallery.force_ratio_thumb?
43
+ = form.element 'Thumbnail' do
44
+ = image_tag @photo.image.url(:admin_full), :id => 'crop_thumb'
45
+ - [:full_crop_x, :full_crop_y, :full_crop_w, :full_crop_h].each do |attr|
46
+ = form.hidden_field attr, :id => attr
47
+ - [:thumb_crop_x, :thumb_crop_y, :thumb_crop_w, :thumb_crop_h].each do |attr|
48
+ = form.hidden_field attr, :id => attr
49
+ .form-actions
50
+ = form.submit 'Save', :class => 'btn btn-primary'