sofa_gallery 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +106 -0
- data/LICENSE +20 -0
- data/README.md +30 -0
- data/Rakefile +21 -0
- data/VERSION +1 -0
- data/app/assets/images/sofa_gallery/jcrop.gif +0 -0
- data/app/assets/javascripts/sofa_gallery/application.js +15 -0
- data/app/assets/javascripts/sofa_gallery/jquery.jcrop.js +246 -0
- data/app/assets/javascripts/sofa_gallery/jquery.js +18 -0
- data/app/assets/javascripts/sofa_gallery/jquery_ui.js +248 -0
- data/app/assets/javascripts/sofa_gallery/rails.js +315 -0
- data/app/assets/stylesheets/sofa_gallery/application.css +68 -0
- data/app/assets/stylesheets/sofa_gallery/jquery.jcrop.css +32 -0
- data/app/assets/stylesheets/sofa_gallery/reset.css +1 -0
- data/app/controllers/application_controller.rb +6 -0
- data/app/controllers/gallery_admin/base_controller.rb +3 -0
- data/app/controllers/gallery_admin/galleries_controller.rb +59 -0
- data/app/controllers/gallery_admin/photos_controller.rb +76 -0
- data/app/helpers/sofa_gallery_helper.rb +11 -0
- data/app/models/sofa/gallery.rb +17 -0
- data/app/models/sofa/photo.rb +64 -0
- data/app/views/gallery_admin/_navigation.html.erb +1 -0
- data/app/views/gallery_admin/galleries/_form.html.erb +11 -0
- data/app/views/gallery_admin/galleries/edit.html.erb +5 -0
- data/app/views/gallery_admin/galleries/index.html.erb +28 -0
- data/app/views/gallery_admin/galleries/new.html.erb +5 -0
- data/app/views/gallery_admin/photos/_form.html.erb +13 -0
- data/app/views/gallery_admin/photos/crop.html.erb +32 -0
- data/app/views/gallery_admin/photos/edit.html.erb +5 -0
- data/app/views/gallery_admin/photos/index.html.erb +24 -0
- data/app/views/gallery_admin/photos/new.html.erb +5 -0
- data/app/views/layouts/gallery_admin/application.html.erb +16 -0
- data/config.ru +4 -0
- data/config/application.rb +51 -0
- data/config/boot.rb +13 -0
- data/config/database.yml +16 -0
- data/config/environment.rb +5 -0
- data/config/environments/development.rb +25 -0
- data/config/environments/production.rb +52 -0
- data/config/environments/test.rb +39 -0
- data/config/initializers/paperclip.rb +3 -0
- data/config/initializers/sofa_gallery.rb +15 -0
- data/config/routes.rb +12 -0
- data/db/migrate/01_create_sofa_gallery.rb +35 -0
- data/lib/generators/README +10 -0
- data/lib/generators/sofa_gallery_generator.rb +33 -0
- data/lib/paperclip_processors/cropper.rb +18 -0
- data/lib/sofa_gallery.rb +23 -0
- data/lib/sofa_gallery/configuration.rb +26 -0
- data/lib/sofa_gallery/engine.rb +21 -0
- data/lib/sofa_gallery/form_builder.rb +50 -0
- data/script/rails +6 -0
- data/sofa_gallery.gemspec +113 -0
- data/test/fixtures/files/default.jpg +0 -0
- data/test/fixtures/files/default.txt +1 -0
- data/test/fixtures/sofa/galleries.yml +10 -0
- data/test/fixtures/sofa/photos.yml +9 -0
- data/test/functional/galleries_controller_test.rb +87 -0
- data/test/functional/photos_controller_test.rb +123 -0
- data/test/test_helper.rb +36 -0
- data/test/unit/configuration_test.rb +18 -0
- data/test/unit/gallery_test.rb +33 -0
- data/test/unit/photo_test.rb +29 -0
- metadata +167 -0
@@ -0,0 +1,68 @@
|
|
1
|
+
/*
|
2
|
+
= require sofa_gallery/reset.css
|
3
|
+
*/
|
4
|
+
|
5
|
+
body {
|
6
|
+
padding: 25px;
|
7
|
+
font: 13px/18px Arial, sans-serif;
|
8
|
+
}
|
9
|
+
h1 {
|
10
|
+
font: bold 26px/34px Arial, sans-serif;
|
11
|
+
margin-bottom: 15px;
|
12
|
+
}
|
13
|
+
a {
|
14
|
+
color: #3875D7;
|
15
|
+
text-decoration: none;
|
16
|
+
}
|
17
|
+
a:hover {
|
18
|
+
text-decoration: underline;
|
19
|
+
}
|
20
|
+
table.formatted td,
|
21
|
+
table.formatted th {
|
22
|
+
padding: 2px 5px;
|
23
|
+
border-bottom: 1px dotted #ccc;
|
24
|
+
}
|
25
|
+
table.formatted th {
|
26
|
+
background-color: #666;
|
27
|
+
color: #fff;
|
28
|
+
}
|
29
|
+
table.formatted td img {
|
30
|
+
float: left;
|
31
|
+
border: 1px solid #ccc;
|
32
|
+
padding: 2px;
|
33
|
+
margin-right: 2px;
|
34
|
+
}
|
35
|
+
table.formatted td .sublabel {
|
36
|
+
font-size: 11px;
|
37
|
+
line-height: 11px;
|
38
|
+
color: #888;
|
39
|
+
}
|
40
|
+
|
41
|
+
.form_element {
|
42
|
+
overflow: hidden;
|
43
|
+
margin-bottom: 5px;
|
44
|
+
}
|
45
|
+
.form_element .label {
|
46
|
+
width: 125px;
|
47
|
+
float: left;
|
48
|
+
text-align: right;
|
49
|
+
}
|
50
|
+
.form_element .value,
|
51
|
+
.form_element .errors {
|
52
|
+
margin-left: 135px;
|
53
|
+
}
|
54
|
+
.form_element .value input[type='text'],
|
55
|
+
.form_element .value textarea {
|
56
|
+
width: 400px;
|
57
|
+
}
|
58
|
+
|
59
|
+
.jcrop-holder {
|
60
|
+
margin-bottom: 15px;
|
61
|
+
}
|
62
|
+
|
63
|
+
.flash{
|
64
|
+
border: 2px solid #ccc;
|
65
|
+
padding: 10px;
|
66
|
+
margin-bottom: 15px;
|
67
|
+
text-align: center;
|
68
|
+
}
|
@@ -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/sofa_gallery/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 @@
|
|
1
|
+
html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var,optgroup{font-style:inherit;font-weight:inherit;}del,ins{text-decoration:none;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:baseline;}sub{vertical-align:baseline;}legend{color:#000;}input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;}input,button,textarea,select{*font-size:100%;}
|
@@ -0,0 +1,59 @@
|
|
1
|
+
class GalleryAdmin::GalleriesController < GalleryAdmin::BaseController
|
2
|
+
|
3
|
+
before_filter :load_gallery, :except => [:index, :new, :create]
|
4
|
+
before_filter :build_gallery, :only => [:new, :create]
|
5
|
+
|
6
|
+
def index
|
7
|
+
@galleries = Sofa::Gallery.all
|
8
|
+
end
|
9
|
+
|
10
|
+
def new
|
11
|
+
render
|
12
|
+
end
|
13
|
+
|
14
|
+
def create
|
15
|
+
@gallery.save!
|
16
|
+
flash[:notice] = 'Gallery created'
|
17
|
+
redirect_to :action => :index
|
18
|
+
rescue ActiveRecord::RecordInvalid
|
19
|
+
flash.now[:error] = 'Failed to create Gallery'
|
20
|
+
render :action => :new
|
21
|
+
end
|
22
|
+
|
23
|
+
def show
|
24
|
+
render
|
25
|
+
end
|
26
|
+
|
27
|
+
def edit
|
28
|
+
render
|
29
|
+
end
|
30
|
+
|
31
|
+
def update
|
32
|
+
@gallery.update_attributes!(params[:gallery])
|
33
|
+
flash[:notice] = 'Gallery updated'
|
34
|
+
redirect_to :action => :index
|
35
|
+
rescue ActiveRecord::RecordInvalid
|
36
|
+
flash.now[:error] = 'Failed to update Gallery'
|
37
|
+
render :action => :edit
|
38
|
+
end
|
39
|
+
|
40
|
+
def destroy
|
41
|
+
@gallery.destroy
|
42
|
+
flash[:notice] = 'Gallery deleted'
|
43
|
+
redirect_to :action => :index
|
44
|
+
end
|
45
|
+
|
46
|
+
protected
|
47
|
+
|
48
|
+
def load_gallery
|
49
|
+
@gallery = Sofa::Gallery.find(params[:id])
|
50
|
+
rescue ActiveRecord::RecordNotFound
|
51
|
+
flash[:error] = 'Gallery not found'
|
52
|
+
redirect_to :action => :index
|
53
|
+
end
|
54
|
+
|
55
|
+
def build_gallery
|
56
|
+
@gallery = Sofa::Gallery.new(params[:gallery])
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
class GalleryAdmin::PhotosController < GalleryAdmin::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
|
+
@photo.save!
|
17
|
+
flash[:notice] = 'Photo created'
|
18
|
+
redirect_to :action => :index
|
19
|
+
rescue ActiveRecord::RecordInvalid
|
20
|
+
flash[:error] = 'Failed to create Photo'
|
21
|
+
render :action => :new
|
22
|
+
end
|
23
|
+
|
24
|
+
def edit
|
25
|
+
render
|
26
|
+
end
|
27
|
+
|
28
|
+
def update
|
29
|
+
@photo.update_attributes!(params[:photo])
|
30
|
+
flash[:notice] = 'Photo updated'
|
31
|
+
redirect_to :action => :index
|
32
|
+
rescue ActiveRecord::RecordInvalid
|
33
|
+
flash.now[:error] = 'Failed to updated Photo'
|
34
|
+
render :action => :edit
|
35
|
+
end
|
36
|
+
|
37
|
+
def destroy
|
38
|
+
@photo.destroy
|
39
|
+
flash[:notice] = 'Photo deleted'
|
40
|
+
redirect_to :action => :index
|
41
|
+
end
|
42
|
+
|
43
|
+
def reorder
|
44
|
+
(params[:sofa_photo] || []).each_with_index do |id, index|
|
45
|
+
if (photo = Sofa::Photo.find_by_id(id))
|
46
|
+
photo.update_attribute(:position, index)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
render :nothing => true
|
50
|
+
end
|
51
|
+
|
52
|
+
def crop
|
53
|
+
render
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
|
58
|
+
def load_gallery
|
59
|
+
@gallery = Sofa::Gallery.find(params[:gallery_id])
|
60
|
+
rescue ActiveRecord::RecordNotFound
|
61
|
+
flash[:error] = 'Gallery not found'
|
62
|
+
redirect_to gallery_admin_galleries_path
|
63
|
+
end
|
64
|
+
|
65
|
+
def load_photo
|
66
|
+
@photo = @gallery.photos.find(params[:id])
|
67
|
+
rescue ActiveRecord::RecordNotFound
|
68
|
+
flash[:error] = 'Photo not found'
|
69
|
+
redirect_to :action => :index
|
70
|
+
end
|
71
|
+
|
72
|
+
def build_photo
|
73
|
+
@photo = Sofa::Photo.new({:gallery => @gallery}.merge(params[:photo] || {}))
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module SofaGalleryHelper
|
2
|
+
|
3
|
+
def gallery_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 => SofaGallery.config.form_builder.to_s.constantize)),
|
8
|
+
&proc
|
9
|
+
)
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Sofa::Gallery < ActiveRecord::Base
|
2
|
+
|
3
|
+
set_table_name :sofa_galleries
|
4
|
+
|
5
|
+
# -- Relationships --------------------------------------------------------
|
6
|
+
has_many :photos, :dependent => :destroy
|
7
|
+
|
8
|
+
# -- Validations ----------------------------------------------------------
|
9
|
+
validates :title,
|
10
|
+
:presence => true
|
11
|
+
|
12
|
+
validates :slug,
|
13
|
+
:presence => true,
|
14
|
+
:uniqueness => true,
|
15
|
+
:format => { :with => /^\w[a-z0-9_-]*$/i }
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class Sofa::Photo < ActiveRecord::Base
|
2
|
+
|
3
|
+
set_table_name :sofa_photos
|
4
|
+
|
5
|
+
upload_options = (SofaGallery.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?? '#' : '>'}"
|
9
|
+
t_settings = "#{g.thumb_width}x#{g.thumb_height}#{g.force_ratio?? '#' : '>'}"
|
10
|
+
{
|
11
|
+
:full => { :geometry => f_settings, :processors => [:cropper] },
|
12
|
+
:thumb => { :geometry => t_settings, :processors => [:cropper] },
|
13
|
+
:admin_full => '800x600>',
|
14
|
+
:admin_thumb => '40x30#'
|
15
|
+
}
|
16
|
+
}
|
17
|
+
)
|
18
|
+
has_attached_file :image, upload_options
|
19
|
+
|
20
|
+
attr_accessor :crop_x, :crop_y, :crop_w, :crop_h
|
21
|
+
|
22
|
+
# -- Relationships --------------------------------------------------------
|
23
|
+
belongs_to :gallery
|
24
|
+
|
25
|
+
# -- Callbacks ------------------------------------------------------------
|
26
|
+
before_create :assign_position
|
27
|
+
after_update :reprocess_image, :if => :cropping?
|
28
|
+
|
29
|
+
# -- Validations ----------------------------------------------------------
|
30
|
+
validates :gallery_id,
|
31
|
+
:presence => true
|
32
|
+
validates_attachment_presence :image,
|
33
|
+
:message => 'There was no file uploaded!'
|
34
|
+
validates_attachment_content_type :image,
|
35
|
+
:content_type => %w(image/jpeg image/pjpeg image/gif image/png image/x-png),
|
36
|
+
:message => 'Please only upload .jpg, .jpeg, .gif or .png files.'
|
37
|
+
validates_attachment_size :image,
|
38
|
+
:less_than => 5.megabytes
|
39
|
+
|
40
|
+
# -- Scopes ---------------------------------------------------------------
|
41
|
+
default_scope order(:position)
|
42
|
+
|
43
|
+
# -- Instance Methods -----------------------------------------------------
|
44
|
+
def image_geometry(style = :original)
|
45
|
+
@geometry ||= {}
|
46
|
+
@geometry[style] ||= Paperclip::Geometry.from_file(image.path(style))
|
47
|
+
end
|
48
|
+
|
49
|
+
def cropping?
|
50
|
+
!crop_x.blank? && !crop_y.blank? && !crop_w.blank? && !crop_h.blank?
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def assign_position
|
56
|
+
max = self.gallery.photos.maximum(:position)
|
57
|
+
self.position = max ? max + 1 : 0
|
58
|
+
end
|
59
|
+
|
60
|
+
def reprocess_image
|
61
|
+
image.reprocess!
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<li><%= active_link_to 'Galleries', gallery_admin_galleries_path %></li>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<%= form.text_field :title, :id => (@gallery.new_record?? 'slugify' : nil)%>
|
2
|
+
<%= form.text_field :slug, :id => 'slug' %>
|
3
|
+
<%= form.text_area :description%>
|
4
|
+
|
5
|
+
<%= form.text_field :full_width %>
|
6
|
+
<%= form.text_field :full_height %>
|
7
|
+
<%= form.text_field :thumb_width %>
|
8
|
+
<%= form.text_field :thumb_height %>
|
9
|
+
<%= form.check_box :force_ratio %>
|
10
|
+
|
11
|
+
<%= form.submit 'Save'%>
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<%= link_to 'Add new gallery', new_gallery_admin_gallery_path, :class => 'big button' %>
|
2
|
+
|
3
|
+
<h1>Galleries</h1>
|
4
|
+
|
5
|
+
<table class='formatted'>
|
6
|
+
<% @galleries.each do |gallery| %>
|
7
|
+
<tr>
|
8
|
+
<td>
|
9
|
+
<div class='title'>
|
10
|
+
<%= link_to gallery.title, gallery_admin_gallery_photos_path(gallery) %>
|
11
|
+
</div>
|
12
|
+
<div class='sublabel'>
|
13
|
+
<%= gallery.slug %>
|
14
|
+
</div>
|
15
|
+
</td>
|
16
|
+
<td class='main'>
|
17
|
+
<% gallery.photos.limit(5).each do |photo| %>
|
18
|
+
<%= image_tag(photo.image.url(:admin_thumb)) %>
|
19
|
+
<% end %>
|
20
|
+
</td>
|
21
|
+
<td class='action_links'>
|
22
|
+
<%= link_to 'Show Photos', gallery_admin_gallery_photos_path(gallery) %>
|
23
|
+
<%= link_to 'Edit', edit_gallery_admin_gallery_path(gallery) %>
|
24
|
+
<%= link_to 'Delete', gallery_admin_gallery_path(gallery), :method => :delete, :confirm => 'Are you sure?' %>
|
25
|
+
</td>
|
26
|
+
</tr>
|
27
|
+
<% end %>
|
28
|
+
</table>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<%= form.text_field :title, :id => (@photo.new_record?? 'slugify' : nil) %>
|
2
|
+
<%= form.text_field :slug, :id => 'slug' %>
|
3
|
+
<% if @photo.image? %>
|
4
|
+
<%= form.simple_field 'Current Image' do %>
|
5
|
+
<%= image_tag(@photo.image.url(:thumb)) %>
|
6
|
+
<br/>
|
7
|
+
<%= link_to 'Crop Image', crop_gallery_admin_gallery_photo_path(@gallery, @photo) %>
|
8
|
+
<% end %>
|
9
|
+
<% end %>
|
10
|
+
<%= form.file_field :image %>
|
11
|
+
<%= form.text_area :description %>
|
12
|
+
|
13
|
+
<%= form.submit 'Save'%>
|
@@ -0,0 +1,32 @@
|
|
1
|
+
<% content_for :head do %>
|
2
|
+
<%= stylesheet_link_tag 'sofa_gallery/jquery.jcrop.css' %>
|
3
|
+
<%= javascript_include_tag 'sofa_gallery/jquery.jcrop.js' %>
|
4
|
+
<script type="text/javascript" charset="utf-8">
|
5
|
+
$(function(){
|
6
|
+
$('#cropbox').Jcrop({
|
7
|
+
onChange: update_crop,
|
8
|
+
onSelect: update_crop,
|
9
|
+
aspectRatio: <%= @photo.gallery.force_ratio?? (@photo.gallery.full_width.to_f / @photo.gallery.full_height) : 'null' %>
|
10
|
+
});
|
11
|
+
});
|
12
|
+
|
13
|
+
function update_crop(coords) {
|
14
|
+
var ratio = <%= @photo.image_geometry(:original).width %> / <%= @photo.image_geometry(:admin_full).width %>;
|
15
|
+
$('#crop_x').val(coords.x * ratio);
|
16
|
+
$('#crop_y').val(coords.y * ratio);
|
17
|
+
$('#crop_w').val(coords.w * ratio);
|
18
|
+
$('#crop_h').val(coords.h * ratio);
|
19
|
+
}
|
20
|
+
</script>
|
21
|
+
<% end %>
|
22
|
+
|
23
|
+
<h1> Crop Photo </h1>
|
24
|
+
|
25
|
+
<%= image_tag @photo.image.url(:admin_full), :id => 'cropbox' %>
|
26
|
+
|
27
|
+
<%= gallery_form_for @photo, :as => :photo, :url => { :action => :update } do |form| %>
|
28
|
+
<% [:crop_x, :crop_y, :crop_w, :crop_h].each do |attr| %>
|
29
|
+
<%= form.hidden_field attr, :id => attr %>
|
30
|
+
<% end %>
|
31
|
+
<%= form.submit 'Crop' %>
|
32
|
+
<% end %>
|