spud_photos 0.1.5 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/README.markdown +22 -2
  2. data/Rakefile +2 -14
  3. data/app/assets/javascripts/spud/admin/photos.js +36 -50
  4. data/app/assets/stylesheets/spud/admin/photos.css +1 -0
  5. data/app/controllers/photo_albums_controller.rb +6 -0
  6. data/app/controllers/photo_galleries_controller.rb +6 -0
  7. data/app/controllers/spud/admin/photo_albums_controller.rb +1 -0
  8. data/app/controllers/spud/admin/photo_galleries_controller.rb +1 -0
  9. data/app/controllers/spud/admin/photos_controller.rb +1 -0
  10. data/app/models/spud_photo.rb +4 -2
  11. data/app/models/spud_photo_sweeper.rb +33 -0
  12. data/app/views/spud/admin/photos/_form.html.erb +0 -5
  13. data/lib/spud_photos/configuration.rb +4 -1
  14. data/lib/spud_photos/version.rb +1 -1
  15. metadata +154 -74
  16. data/test/dummy/README.rdoc +0 -261
  17. data/test/dummy/Rakefile +0 -7
  18. data/test/dummy/app/assets/javascripts/application.js +0 -15
  19. data/test/dummy/app/assets/stylesheets/application.css +0 -13
  20. data/test/dummy/app/controllers/application_controller.rb +0 -3
  21. data/test/dummy/app/helpers/application_helper.rb +0 -2
  22. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  23. data/test/dummy/config/application.rb +0 -56
  24. data/test/dummy/config/boot.rb +0 -10
  25. data/test/dummy/config/database.yml +0 -15
  26. data/test/dummy/config/environment.rb +0 -5
  27. data/test/dummy/config/environments/development.rb +0 -37
  28. data/test/dummy/config/environments/production.rb +0 -67
  29. data/test/dummy/config/environments/test.rb +0 -37
  30. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  31. data/test/dummy/config/initializers/inflections.rb +0 -15
  32. data/test/dummy/config/initializers/mime_types.rb +0 -5
  33. data/test/dummy/config/initializers/secret_token.rb +0 -7
  34. data/test/dummy/config/initializers/session_store.rb +0 -8
  35. data/test/dummy/config/initializers/wrap_parameters.rb +0 -14
  36. data/test/dummy/config/locales/en.yml +0 -5
  37. data/test/dummy/config/routes.rb +0 -4
  38. data/test/dummy/config.ru +0 -4
  39. data/test/dummy/public/404.html +0 -26
  40. data/test/dummy/public/422.html +0 -26
  41. data/test/dummy/public/500.html +0 -25
  42. data/test/dummy/public/favicon.ico +0 -0
  43. data/test/dummy/script/rails +0 -6
data/README.markdown CHANGED
@@ -30,7 +30,7 @@ Spud Photos accepts the following configuration options:
30
30
  :large => '400x400#',
31
31
  :huge => '600x600'
32
32
  }
33
- self.paperclip_storage = :filesystem #use :s3 to use s3 storage (aws gem required)
33
+ config.paperclip_storage = :filesystem #use :s3 to use s3 storage (aws gem required)
34
34
  config.s3_credentials = "#{Rails.root}/config/s3.yml"
35
35
  config.storage_path = ":rails_root/public/system/spud_photos/:id/:style/:basename.:extension"
36
36
  config.storage_url = "/system/spud_photos/:id/:style/:basename.:extension"
@@ -52,4 +52,24 @@ __NOTE:__ The built-in views are likely to undergo changes as features are added
52
52
 
53
53
 
54
54
  [1]:https://github.com/davydotcom/spud_core_admin
55
- [2]:https://github.com/thoughtbot/paperclip
55
+ [2]:https://github.com/thoughtbot/paperclip
56
+
57
+ Testing
58
+ -----------------
59
+
60
+ Spud uses RSpec for testing. Get the tests running with a few short commands:
61
+
62
+ 1. Create and migrate the databases:
63
+
64
+ rake db:create
65
+ rake db:migrate
66
+
67
+ 2. Load the schema in to the test database:
68
+
69
+ rake app:db:test:prepare
70
+
71
+ 3. Run the tests with RSpec
72
+
73
+ rspec spec
74
+
75
+ After the tests have completed the current code coverage stats is available by opening ```/coverage/index.html``` in a browser.
data/Rakefile CHANGED
@@ -20,21 +20,9 @@ RDoc::Task.new(:rdoc) do |rdoc|
20
20
  rdoc.rdoc_files.include('lib/**/*.rb')
21
21
  end
22
22
 
23
- APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
23
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
24
24
  load 'rails/tasks/engine.rake'
25
25
 
26
-
27
-
28
26
  Bundler::GemHelper.install_tasks
29
27
 
30
- require 'rake/testtask'
31
-
32
- Rake::TestTask.new(:test) do |t|
33
- t.libs << 'lib'
34
- t.libs << 'test'
35
- t.pattern = 'test/**/*_test.rb'
36
- t.verbose = false
37
- end
38
-
39
-
40
- task :default => :test
28
+ require 'rake'
@@ -14,12 +14,14 @@ Spud.Admin.Photos = new function(){
14
14
  $('body').on('submit', '#spud_admin_photo_album_form', self.submittedPhotoAlbumForm);
15
15
  $('body').on('submit', '#spud_admin_photo_gallery_form', self.submittedPhotoGalleryForm);
16
16
  $('body').on('submit', '#spud_admin_photo_form', self.submittedPhotoForm);
17
- $('body').on('click', '.spud_admin_photos_btn_remove', self.clickedPhotoRemoveFromAlbum)
17
+ $('body').on('click', '.spud_admin_photos_btn_remove', self.clickedPhotoRemoveFromAlbum);
18
18
  $('body').on('click', '.spud_admin_photo_ui_thumbs_selectable .spud_admin_photo_ui_thumb', self.selectedPhotoUiThumb);
19
19
  $('body').on('click', '#spud_admin_photo_album_action_library', self.clickedPhotoLibrary);
20
20
  $('body').on('click', '#spud_admin_photo_album_action_upload, .spud_admin_photo .spud_admin_photos_btn_edit', self.clickedPhotoAddOrEdit);
21
+ $('body').on('click', '.spud_admin_photo_library_add_selected', self.addSelectedPhotosFromLibrary);
22
+ $('body').on('click', '.spud_admin_photo_library_delete_selected', self.deleteSelectedPhotosFromLibrary);
21
23
 
22
- // html5 drag and drop file
24
+ // html5 drag and drop file
23
25
  if(typeof(FormData) != 'undefined' && typeof(XMLHttpRequest) != 'undefined' && (droparea = document.getElementById('spud_admin_photo_upload_queue'))){
24
26
  html5upload = true;
25
27
  $('#spud_admin_photo_upload_queue').show();
@@ -43,7 +45,7 @@ Spud.Admin.Photos = new function(){
43
45
 
44
46
  this.submittedPhotoGalleryForm = function(e){
45
47
  $('#spud_admin_photo_albums_available .spud_admin_photo_ui_thumb').remove();
46
- }
48
+ };
47
49
 
48
50
  this.clickedPhotoRemoveFromAlbum = function(e){
49
51
  $(this).parents('.spud_admin_photo_ui_thumb').fadeOut(200, function(){
@@ -68,7 +70,7 @@ Spud.Admin.Photos = new function(){
68
70
  var target = $('#spud_admin_photos_selected, #spud_admin_photos');
69
71
  target.prepend(html);
70
72
  }
71
- $('#dialog').dialog('close');
73
+ hideModalDialog();
72
74
  };
73
75
 
74
76
  this.selectedPhotoUiThumb = function(e){
@@ -102,14 +104,15 @@ Spud.Admin.Photos = new function(){
102
104
  });
103
105
  };
104
106
 
105
- /*
107
+ /*
106
108
  * Single-Photo Form Upload
107
109
  -------------------------------- */
108
110
 
109
111
  this.submittedPhotoForm = function(e){
110
112
  // disable submit button
111
- var submit = $(this).find('input[type=submit]');
112
- submit.attr('disabled', 'disabled').val(submit.attr('data-loading-text'));
113
+ // not working in updated bootstrap!
114
+ // var submit = $(this).find('input[type=submit]');
115
+ // submit.attr('disabled', 'disabled').val(submit.attr('data-loading-text'));
113
116
 
114
117
  if(html5upload){
115
118
  // create a FormData object and attach form values
@@ -120,20 +123,21 @@ Spud.Admin.Photos = new function(){
120
123
  fd.append('spud_photo[title]', form.find('#spud_photo_title').val());
121
124
  fd.append('spud_photo[caption]', form.find('#spud_photo_caption').val());
122
125
 
123
- // progress bar to send events to
126
+ // progress bar to send events to
127
+ var progressBar;
124
128
  var file = form.find('#spud_photo_photo')[0].files[0];
125
129
  if(file){
126
- var progressBar = self.progressBarForUpload(file.fileName);
130
+ progressBar = self.progressBarForUpload(file.fileName);
127
131
  fd.append('spud_photo[photo]', file);
128
- form.find('.form-actions').before(progressBar);
132
+ form.append(progressBar);
129
133
  }
130
134
  else{
131
- var progressBar = self.progressBarForUpload('');
135
+ progressBar = self.progressBarForUpload('');
132
136
  }
133
137
 
134
138
  // send FormData object as ajax request
135
139
  var xhr = new XMLHttpRequest();
136
- xhr.upload.addEventListener('progress', function(e){ self.onPhotoUploadProgress(e, progressBar) }, false);
140
+ xhr.upload.addEventListener('progress', function(e){ self.onPhotoUploadProgress(e, progressBar); }, false);
137
141
  xhr.addEventListener('load', function(e){ self.onPhotoUploadComplete(e, progressBar); }, false);
138
142
  xhr.addEventListener('error', function(e){ self.onPhotoUploadFailure(e, progressBar); }, false);
139
143
  xhr.addEventListener('abort', function(e){ self.onPhotoUploadCancel(e, progressBar); }, false);
@@ -144,7 +148,7 @@ Spud.Admin.Photos = new function(){
144
148
  }
145
149
  };
146
150
 
147
- /*
151
+ /*
148
152
  * Upload Progress Monitoring
149
153
  -------------------------------- */
150
154
 
@@ -184,18 +188,14 @@ Spud.Admin.Photos = new function(){
184
188
  var target = $('#spud_admin_photos_selected, #spud_admin_photos');
185
189
  target.prepend(photo.html).fadeIn(200);
186
190
  }
187
- $('#dialog').dialog('close');
191
+ hideModalDialog();
188
192
  }
189
193
  // validation error
190
194
  else{
191
- $('#dialog').html(photo.html);
195
+ $("#modal_window .modal-body").html(photo.html);
192
196
  }
193
197
  };
194
198
 
195
- this.onPhotoUploadCancel = function(e, progressBar){
196
-
197
- };
198
-
199
199
  this.onPhotoUploadCancel = function(e, progressBar){
200
200
  progressBar.find('.spud_admin_photo_progress_status').text('Done!');
201
201
  progressBar.find('.progress').addClass('progress-danger');
@@ -203,7 +203,7 @@ Spud.Admin.Photos = new function(){
203
203
 
204
204
  /*
205
205
  * Photo Upload/Edit Form
206
- ------------------------------- */
206
+ ------------------------------- */
207
207
  this.clickedPhotoAddOrEdit = function(e){
208
208
  var url = this.href;
209
209
  $.ajax({
@@ -214,17 +214,9 @@ Spud.Admin.Photos = new function(){
214
214
  };
215
215
 
216
216
  this.photoUploadFormLoaded = function(html){
217
- var dialog = $("#dialog");
218
- if(dialog.length == 0){
219
- dialog = $('<div id="dialog" style="display:hidden;"></div>').appendTo('body');
220
- }
221
- dialog.html(html);
222
- dialog.dialog({
223
- width: 500,
224
- modal: true,
225
- height: 'auto',
217
+ displayModalDialogWithOptions({
226
218
  title: 'Upload Photo',
227
- buttons: {}
219
+ html: html
228
220
  });
229
221
  };
230
222
 
@@ -242,11 +234,7 @@ Spud.Admin.Photos = new function(){
242
234
  };
243
235
 
244
236
  this.photoLibraryLoaded = function(html){
245
- var dialog = $("#dialog");
246
- if(dialog.length == 0){
247
- dialog = $('<div id="dialog" style="display:hidden;"></div>').appendTo('body');
248
- }
249
- dialog.html(html);
237
+ var dialog = $('#modal_window');
250
238
  $('#spud_admin_photos_selected .spud_admin_photo_ui_thumb').each(function(){
251
239
  var id = $(this).attr('id');
252
240
  var dupe = dialog.find('#'+id);
@@ -254,14 +242,12 @@ Spud.Admin.Photos = new function(){
254
242
  dupe.remove();
255
243
  }
256
244
  });
257
- dialog.dialog({
258
- width: 675,
259
- modal: true,
260
- height: 450,
245
+ displayModalDialogWithOptions({
261
246
  title: 'My Photo Library',
262
- buttons: {
263
- 'Add Selected': self.addSelectedPhotosFromLibrary,
264
- 'Delete Selected': self.deleteSelectedPhotosFromLibrary
247
+ html: html,
248
+ buttons:{
249
+ 'spud_admin_photo_library_add_selected btn-primary': 'Add Selected',
250
+ 'spud_admin_photo_library_delete_selected btn-danger': 'Delete Selected'
265
251
  }
266
252
  });
267
253
  };
@@ -272,11 +258,11 @@ Spud.Admin.Photos = new function(){
272
258
  .prependTo('#spud_admin_photos_selected')
273
259
  .hide()
274
260
  .fadeIn(200);
275
- $(this).dialog('close');
261
+ hideModalDialog();
276
262
  };
277
263
 
278
264
  this.deleteSelectedPhotosFromLibrary = function(e){
279
- var ids = $.map($('.spud_admin_photo_ui_thumb_selected'), function(val, i){
265
+ var ids = $.map($('.spud_admin_photo_ui_thumb_selected'), function(val, i){
280
266
  return $(val).attr('rel');
281
267
  });
282
268
  $.ajax({
@@ -289,10 +275,10 @@ Spud.Admin.Photos = new function(){
289
275
  });
290
276
  },
291
277
  error: function(jqXHR, textStatus, errorThrown){
292
- console.log('An error occurred:')
278
+ console.log('An error occurred:');
293
279
  console.log(arguments);
294
280
  }
295
- })
281
+ });
296
282
 
297
283
  };
298
284
 
@@ -307,7 +293,7 @@ Spud.Admin.Photos = new function(){
307
293
  this.stopDndPropagation = function(e){
308
294
  e.stopPropagation();
309
295
  e.preventDefault();
310
- }
296
+ };
311
297
 
312
298
  // add files to queue. starts queue if not started already
313
299
  this.droppedFile = function(e){
@@ -324,7 +310,7 @@ Spud.Admin.Photos = new function(){
324
310
  if(!this.fileQueueStarted){
325
311
  self.uploadNextPhoto();
326
312
  if(self.fileQueue.length > 0){
327
- self.uploadNextPhoto();
313
+ self.uploadNextPhoto();
328
314
  }
329
315
  }
330
316
  };
@@ -334,7 +320,7 @@ Spud.Admin.Photos = new function(){
334
320
  };
335
321
 
336
322
  this.uploadNextPhoto = function(){
337
- if(self.fileQueue.length == 0){
323
+ if(self.fileQueue.length === 0){
338
324
  self.fileQueueStarted = false;
339
325
  return;
340
326
  }
@@ -352,7 +338,7 @@ Spud.Admin.Photos = new function(){
352
338
  // send formdata as xhr
353
339
  var xhr = new XMLHttpRequest();
354
340
  xhr.upload.addEventListener('progress', function(e){ self.onPhotoUploadProgress(e, progressBar); }, false);
355
- xhr.addEventListener('load', function(e){ self.onQueuedPhotoUploadComplete(e, progressBar) }, false);
341
+ xhr.addEventListener('load', function(e){ self.onQueuedPhotoUploadComplete(e, progressBar); }, false);
356
342
  xhr.addEventListener('error', function(e){ self.onPhotoUploadFailure(e, progressBar); }, false);
357
343
  xhr.addEventListener('abort', function(e){ self.onPhotoUploadCancel(e, progressBar); }, false);
358
344
  xhr.open('POST', '/spud/admin/photos');
@@ -63,6 +63,7 @@
63
63
  white-space: nowrap;
64
64
  overflow: hidden;
65
65
  text-overflow: ellipsis;
66
+ margin: 0;
66
67
  }
67
68
  .spud_admin_photo_ui_thumb_controls{
68
69
  position: absolute;
@@ -3,6 +3,12 @@ class PhotoAlbumsController < ApplicationController
3
3
  respond_to :html, :json, :xml
4
4
  layout Spud::Photos.base_layout
5
5
 
6
+ after_filter :only => [:show, :index] do |c|
7
+ if Spud::Photos.enable_full_page_caching
8
+ c.cache_page(nil, nil, false)
9
+ end
10
+ end
11
+
6
12
  def index
7
13
  if params[:photo_gallery_id]
8
14
  @photo_gallery = SpudPhotoGallery.find_by_url_name(params[:photo_gallery_id])
@@ -3,6 +3,12 @@ class PhotoGalleriesController < ApplicationController
3
3
  respond_to :html, :json, :xml
4
4
  layout Spud::Photos.base_layout
5
5
 
6
+ after_filter :only => [:index] do |c|
7
+ if Spud::Photos.enable_full_page_caching
8
+ c.cache_page(nil, nil, false)
9
+ end
10
+ end
11
+
6
12
  def index
7
13
  @photo_galleries = SpudPhotoGallery.order('created_at desc')
8
14
  respond_with @photo_galleries
@@ -4,6 +4,7 @@ class Spud::Admin::PhotoAlbumsController < Spud::Admin::ApplicationController
4
4
  add_breadcrumb 'Photo Albums', :spud_admin_photo_albums_path
5
5
  respond_to :html, :json, :xml
6
6
  layout 'spud/admin/spud_photos'
7
+ cache_sweeper :spud_photo_sweeper, :only => [:create, :update, :destroy]
7
8
 
8
9
  def index
9
10
  @photo_albums = SpudPhotoAlbum.all
@@ -5,6 +5,7 @@ class Spud::Admin::PhotoGalleriesController < Spud::Admin::ApplicationController
5
5
  add_breadcrumb 'Photo Galleries', :spud_admin_photo_galleries_path
6
6
  respond_to :html, :json, :xml
7
7
  layout 'spud/admin/spud_photos'
8
+ cache_sweeper :spud_photo_sweeper, :only => [:create, :update, :destroy]
8
9
 
9
10
  def index
10
11
  @photo_galleries = SpudPhotoGallery.all
@@ -5,6 +5,7 @@ class Spud::Admin::PhotosController < Spud::Admin::ApplicationController
5
5
  before_filter :get_photo, :only => [:show, :edit, :update, :destroy]
6
6
  respond_to :html, :json, :xml, :js
7
7
  layout false
8
+ cache_sweeper :spud_photo_sweeper, :only => [:create, :update, :destroy]
8
9
 
9
10
  def index
10
11
  @photos = SpudPhoto.all
@@ -9,6 +9,7 @@ class SpudPhoto < ActiveRecord::Base
9
9
 
10
10
  has_attached_file :photo,
11
11
  :styles => lambda { |attachment| attachment.instance.dynamic_styles },
12
+ :convert_options => Spud::Photos.config.convert_options,
12
13
  :storage => Spud::Photos.paperclip_storage,
13
14
  :s3_credentials => Spud::Photos.s3_credentials,
14
15
  :url => Spud::Photos.storage_url,
@@ -17,9 +18,10 @@ class SpudPhoto < ActiveRecord::Base
17
18
  validates_attachment_presence :photo
18
19
 
19
20
  def dynamic_styles
21
+ compress = '-strip -density 72x72'
20
22
  admin_styles = {
21
- :spud_admin_small => '125x125#',
22
- :spud_admin_medium => '300x200'
23
+ :spud_admin_small => {:geometry => '125x125#', :convert_options => compress},
24
+ :spud_admin_medium => {:geometry => '300x200', :convert_options => compress}
23
25
  }
24
26
  return admin_styles.merge(Spud::Photos.config.photo_styles)
25
27
  end
@@ -0,0 +1,33 @@
1
+ class SpudPhotoSweeper < ActionController::Caching::Sweeper
2
+
3
+ observe :spud_photo, :spud_photo_album, :spud_photo_gallery
4
+
5
+ def after_create(record)
6
+ expire_cache_for(record)
7
+ end
8
+
9
+ def before_update(record)
10
+ expire_cache_for(record)
11
+ end
12
+
13
+ def after_destroy(record)
14
+ expire_cache_for(record)
15
+ end
16
+
17
+ private
18
+
19
+ def expire_cache_for(record)
20
+ if Spud::Photos.config.enable_full_page_caching
21
+ cache_path = File.join(ActionController::Base.page_cache_directory, Spud::Photos.config.base_path)
22
+ if File.directory?(cache_path)
23
+ FileUtils.rm_rf(cache_path)
24
+ end
25
+ if !Spud::Photos.config.page_caches_to_sweep.blank?
26
+ Spud::Photos.config.page_caches_to_sweep.each do |route|
27
+ expire_page(route)
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ end
@@ -36,11 +36,6 @@
36
36
  <% end %>
37
37
  </fieldset>
38
38
 
39
- <div class="form-actions">
40
- <%= f.submit "Save Photo", :class=>"btn btn-primary form-btn", "data-loading-text" => "Saving..." %>
41
- <!--or <%=link_to "cancel", request.referer, :class => "btn" %> -->
42
- </div>
43
-
44
39
  <iframe id="spud_admin_photo_form_target" name="spud_admin_photo_form_target" style="display:none;"></iframe>
45
40
 
46
41
  <% end %>
@@ -1,12 +1,13 @@
1
1
  module Spud
2
2
  module Photos
3
3
  include ActiveSupport::Configurable
4
- config_accessor :photo_styles, :galleries_enabled, :base_layout, :base_path,:s3_credentials,:storage_path,:storage_url,:paperclip_storage
4
+ config_accessor :photo_styles, :convert_options, :galleries_enabled, :base_layout, :base_path,:s3_credentials,:storage_path,:storage_url,:paperclip_storage, :enable_full_page_caching, :page_caches_to_sweep
5
5
  self.photo_styles = {
6
6
  :small => '50x50#',
7
7
  :medium => '200x200#',
8
8
  :large => '400x400#'
9
9
  }
10
+ self.convert_options = {}
10
11
  self.galleries_enabled = false
11
12
  self.base_layout = 'application'
12
13
  self.base_path = 'photos'
@@ -14,5 +15,7 @@ module Spud
14
15
  self.s3_credentials = "#{Rails.root}/config/s3.yml"
15
16
  self.storage_path = ":rails_root/public/system/spud_photos/:id/:style/:basename.:extension"
16
17
  self.storage_url = "/system/spud_photos/:id/:style/:basename.:extension"
18
+ self.enable_full_page_caching = false
19
+ self.page_caches_to_sweep = []
17
20
  end
18
21
  end
@@ -1,5 +1,5 @@
1
1
  module Spud
2
2
  module Photos
3
- VERSION = "0.1.5"
3
+ VERSION = "0.9.0"
4
4
  end
5
5
  end