tb_photos 1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +15 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.markdown +75 -0
  4. data/Rakefile +28 -0
  5. data/app/assets/images/spud/photos/buttons/cog_16x16.png +0 -0
  6. data/app/assets/images/spud/photos/buttons/x_16x16.png +0 -0
  7. data/app/assets/images/spud/photos/photo_albums_thumb.png +0 -0
  8. data/app/assets/images/spud/photos/photo_albums_thumb@2x.png +0 -0
  9. data/app/assets/javascripts/spud/admin/photos.js +356 -0
  10. data/app/assets/stylesheets/spud/admin/photos.css +128 -0
  11. data/app/controllers/photo_albums_controller.rb +54 -0
  12. data/app/controllers/photo_galleries_controller.rb +17 -0
  13. data/app/controllers/spud/admin/photo_albums_controller.rb +64 -0
  14. data/app/controllers/spud/admin/photo_galleries_controller.rb +53 -0
  15. data/app/controllers/spud/admin/photos_controller.rb +93 -0
  16. data/app/helpers/photo_albums_helper.rb +2 -0
  17. data/app/helpers/photo_galleries_helper.rb +2 -0
  18. data/app/helpers/spud/admin/photo_albums_helper.rb +2 -0
  19. data/app/helpers/spud/admin/photo_galleries_helper.rb +2 -0
  20. data/app/helpers/spud/admin/photos_helper.rb +7 -0
  21. data/app/models/spud_photo.rb +29 -0
  22. data/app/models/spud_photo_album.rb +49 -0
  23. data/app/models/spud_photo_albums_photo.rb +5 -0
  24. data/app/models/spud_photo_galleries_album.rb +5 -0
  25. data/app/models/spud_photo_gallery.rb +36 -0
  26. data/app/models/spud_photo_sweeper.rb +39 -0
  27. data/app/views/layouts/spud/admin/spud_photos.html.erb +8 -0
  28. data/app/views/photo_albums/index.html.erb +24 -0
  29. data/app/views/photo_albums/show.html.erb +27 -0
  30. data/app/views/photo_galleries/index.html.erb +18 -0
  31. data/app/views/spud/admin/photo_albums/_album.html.erb +10 -0
  32. data/app/views/spud/admin/photo_albums/_form.html.erb +36 -0
  33. data/app/views/spud/admin/photo_albums/destroy.js.erb +1 -0
  34. data/app/views/spud/admin/photo_albums/edit.html.erb +1 -0
  35. data/app/views/spud/admin/photo_albums/index.html.erb +9 -0
  36. data/app/views/spud/admin/photo_albums/new.html.erb +1 -0
  37. data/app/views/spud/admin/photo_galleries/_form.html.erb +39 -0
  38. data/app/views/spud/admin/photo_galleries/destroy.js.erb +1 -0
  39. data/app/views/spud/admin/photo_galleries/edit.html.erb +1 -0
  40. data/app/views/spud/admin/photo_galleries/index.html.erb +17 -0
  41. data/app/views/spud/admin/photo_galleries/new.html.erb +1 -0
  42. data/app/views/spud/admin/photos/_form.html.erb +41 -0
  43. data/app/views/spud/admin/photos/_photo.html.erb +13 -0
  44. data/app/views/spud/admin/photos/destroy.js.erb +1 -0
  45. data/app/views/spud/admin/photos/edit.html.erb +1 -0
  46. data/app/views/spud/admin/photos/index.html.erb +3 -0
  47. data/app/views/spud/admin/photos/new.html.erb +1 -0
  48. data/app/views/spud/admin/photos/show.js.erb +5 -0
  49. data/config/routes.rb +24 -0
  50. data/db/migrate/20120228232120_create_spud_photos.rb +13 -0
  51. data/db/migrate/20120228232329_create_spud_photo_albums.rb +15 -0
  52. data/db/migrate/20120228232344_create_spud_photo_galleries.rb +15 -0
  53. data/db/migrate/20120405042046_upgrade_photo_relationships.rb +8 -0
  54. data/db/migrate/20121127210314_rename_order_to_sort_order.rb +6 -0
  55. data/lib/generators/spud/photos/views_generator.rb +14 -0
  56. data/lib/spud_photos/configuration.rb +21 -0
  57. data/lib/spud_photos/engine.rb +37 -0
  58. data/lib/spud_photos/version.rb +5 -0
  59. data/lib/tasks/spud_photos_tasks.rake +4 -0
  60. data/lib/tb_photos.rb +6 -0
  61. metadata +258 -0
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZmE0OWRiMGJhZjFhYzljNGVkZjQxMGFhMzY2N2I4ZTZiMTNjYzFjYw==
5
+ data.tar.gz: !binary |-
6
+ YzlkMWY1OTAzNmFkZDI4OWQ1NzMwM2ViNDA1NTYxOGNkMTVkOGJjYw==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ ZGI5YzQ2YmRiMzI0YmU3YTgyYzBmMDBhN2Y1NGMwM2U5YzIzODNiNWVjZjYx
10
+ ZTUxMTRhOGZlMTI3YjJjNDg1NWE2Nzc5NGRkZjRiMjc3MzEwMDZmODAwMzBi
11
+ ODgxYTU1NjgwMDg5ZjZkYmY1MjMxNWI3Y2FhYjM2ZDA1MzI3OGQ=
12
+ data.tar.gz: !binary |-
13
+ MmFhZmU3NGRmYTdkODJiNGMxMWJiMjgyNTJlNWE1ZWVjMGZiMjg0OTdhYzhi
14
+ M2RiNDM2YWIzMDcyMDQwMzZkY2Q5OWIwNGQ2YTBjOGZkYWJlNDE3YjY4NmU2
15
+ MDk1NTMxMjZiYzIzOWZmZmNjNWU1ZWJjODdjMTdkNzYzZWY3MWI=
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2012 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,75 @@
1
+ # Spud Photos
2
+
3
+ Spud Photos is an engine for creating and managing photo galleries, designed for use with [Spud][1].
4
+
5
+ ## Installation/Usage
6
+
7
+ 1. In your Gemfile add the following
8
+
9
+ gem 'spud_photos'
10
+
11
+ 2. Run bundle install
12
+ 3. Copy in database migrations to your new rails project
13
+
14
+ bundle exec rake railties:install:migrations
15
+ rake db:migrate
16
+
17
+ 4. Run a rails server instance and point your browser to /spud/admin
18
+
19
+ ## Configuration
20
+
21
+ Spud Photos accepts the following configuration options:
22
+
23
+ Spud::Photos.configure do |config|
24
+ config.base_layout = 'application'
25
+ config.galleries_enabled = false
26
+ config.base_path = 'photos'
27
+ config.photo_styles = {
28
+ :small => '50x50#',
29
+ :medium => '200x200#',
30
+ :large => '400x400#',
31
+ :huge => '600x600'
32
+ }
33
+ config.paperclip_storage = :filesystem #use :s3 to use s3 storage (aws gem required)
34
+ config.s3_credentials = "#{Rails.root}/config/s3.yml"
35
+ config.storage_path = ":rails_root/public/system/spud_photos/:id/:style/:basename.:extension"
36
+ config.storage_url = "/system/spud_photos/:id/:style/:basename.:extension"
37
+ end
38
+
39
+ The `photo_styles` option will be passed to [Paperclip][2], so any valid paperclip styles can be added here.
40
+
41
+ ## Galleries
42
+
43
+ A Gallery is just an additional layer of organization above the Album layer. For example, a Gallery called "Vacations" might include Albums titled "Europe", "Hawaii", and "Florida". Galleries are turned off by default.
44
+
45
+ ## Customizing Views
46
+
47
+ A number of built-in views have been provided to help you get started with the frontend display. Customizing these views will require you to copy them into your local application, which can be accomplished by using the views generator.
48
+
49
+ rails generate spud:photos:views
50
+
51
+ __NOTE:__ The built-in views are likely to undergo changes as features are added to the photos engine. If a new version of Spud Photos does not play nicely with your customized views, try backing up your views to an alternate location and running the views generator again to see what has changed.
52
+
53
+
54
+ [1]:https://github.com/davydotcom/spud_core_admin
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 ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'SpudPhotos'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
24
+ load 'rails/tasks/engine.rake'
25
+
26
+ Bundler::GemHelper.install_tasks
27
+
28
+ require 'rake'
@@ -0,0 +1,356 @@
1
+ Spud = (typeof(Spud) == 'undefined') ? {} : Spud;
2
+ Spud.Admin = (typeof(Spud.Admin) == 'undefined') ? {} : Spud.Admin;
3
+
4
+ Spud.Admin.Photos = new function(){
5
+
6
+ var self = this;
7
+ var html5upload = false;
8
+
9
+ this.init = function(){
10
+ // event handlers
11
+ $('.spud_admin_photo_ui_thumbs_sortable').sortable({
12
+ connectWith:'.spud_admin_photo_ui_thumbs_sortable'
13
+ });
14
+ $('body').on('submit', '#spud_admin_photo_album_form', self.submittedPhotoAlbumForm);
15
+ $('body').on('submit', '#spud_admin_photo_gallery_form', self.submittedPhotoGalleryForm);
16
+ $('body').on('submit', '#spud_admin_photo_form', self.submittedPhotoForm);
17
+ $('body').on('click', '.spud_admin_photos_btn_remove', self.clickedPhotoRemoveFromAlbum);
18
+ $('body').on('click', '.spud_admin_photo_ui_thumbs_selectable .spud_admin_photo_ui_thumb', self.selectedPhotoUiThumb);
19
+ $('body').on('click', '#spud_admin_photo_album_action_library', self.clickedPhotoLibrary);
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);
23
+
24
+ // html5 drag and drop file
25
+ if(typeof(FormData) != 'undefined' && typeof(XMLHttpRequest) != 'undefined' && (droparea = document.getElementById('spud_admin_photo_upload_queue'))){
26
+ html5upload = true;
27
+ $('#spud_admin_photo_upload_queue').show();
28
+ droparea.addEventListener('dragenter', self.stopDndPropagation, false);
29
+ droparea.addEventListener('dragexit', self.stopDndPropagation, false);
30
+ droparea.addEventListener('dragover', self.stopDndPropagation, false);
31
+ droparea.addEventListener('drop', self.droppedFile, false);
32
+
33
+ // prevent accidental drops outside the queue
34
+ var body = document.getElementsByTagName("body")[0];
35
+ body.addEventListener('dragenter', self.stopDndPropagation, false);
36
+ body.addEventListener('dragexit', self.stopDndPropagation, false);
37
+ body.addEventListener('dragover', self.stopDndPropagation, false);
38
+ body.addEventListener('drop', self.stopDndPropagation, false);
39
+ }
40
+ };
41
+
42
+ this.submittedPhotoAlbumForm = function(e){
43
+
44
+ };
45
+
46
+ this.submittedPhotoGalleryForm = function(e){
47
+ $('#spud_admin_photo_albums_available .spud_admin_photo_ui_thumb').remove();
48
+ };
49
+
50
+ this.clickedPhotoRemoveFromAlbum = function(e){
51
+ $(this).parents('.spud_admin_photo_ui_thumb').fadeOut(200, function(){
52
+ $(this).remove();
53
+ });
54
+ return false;
55
+ };
56
+
57
+ /* Handle file uploads passed via iframe (legacy support)
58
+ * -------------------------------------------------------- */
59
+
60
+ this.photoLegacyUploadErrors = function(html){
61
+ $('#spud_admin_photo_form').replaceWith(html);
62
+ };
63
+
64
+ this.photoLegacyUploadComplete = function(id, html){
65
+ var element = $('#spud_admin_photo_' + id);
66
+ if(element.length > 0){
67
+ element.replaceWith(html);
68
+ }
69
+ else{
70
+ var target = $('#spud_admin_photos_selected, #spud_admin_photos');
71
+ target.prepend(html);
72
+ }
73
+ hideModalDialog();
74
+ };
75
+
76
+ this.selectedPhotoUiThumb = function(e){
77
+ var thumb = $(this);
78
+ if(thumb.hasClass('spud_admin_photo_ui_thumb_selected')){
79
+ $(this).removeClass('spud_admin_photo_ui_thumb_selected');
80
+ }
81
+ else{
82
+ $(this).addClass('spud_admin_photo_ui_thumb_selected');
83
+ }
84
+ };
85
+
86
+ this.markPhotoAsDeleted = function(photo_id){
87
+ var photo = $('#spud_admin_photo_' + photo_id);
88
+ photo.fadeOut(200, function(){
89
+ photo.remove();
90
+ });
91
+ };
92
+
93
+ this.markPhotoAlbumAsDeleted = function(photo_album_id){
94
+ var photo_album = $('#spud_admin_photo_album_' + photo_album_id);
95
+ photo_album.fadeOut(200, function(){
96
+ photo_album.remove();
97
+ });
98
+ };
99
+
100
+ this.markPhotoGalleryAsDeleted = function(photo_gallery_id){
101
+ var photo_gallery = $('#spud_admin_photo_gallery_' + photo_gallery_id);
102
+ photo_gallery.fadeOut(200, function(){
103
+ photo_gallery.remove();
104
+ });
105
+ };
106
+
107
+ /*
108
+ * Single-Photo Form Upload
109
+ -------------------------------- */
110
+
111
+ this.submittedPhotoForm = function(e){
112
+ // disable submit button
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'));
116
+
117
+ if(html5upload){
118
+ // create a FormData object and attach form values
119
+ var fd = new FormData();
120
+ var form = $(this);
121
+ fd.append('_method', form.find('[name=_method]').val());
122
+ fd.append('authenticity_token', form.find('[name=authenticity_token]').val());
123
+ fd.append('spud_photo[title]', form.find('#spud_photo_title').val());
124
+ fd.append('spud_photo[caption]', form.find('#spud_photo_caption').val());
125
+
126
+ // progress bar to send events to
127
+ var progressBar;
128
+ var file = form.find('#spud_photo_photo')[0].files[0];
129
+ if(file){
130
+ progressBar = self.progressBarForUpload(file.name);
131
+ fd.append('spud_photo[photo]', file);
132
+ form.append(progressBar);
133
+ }
134
+ else{
135
+ progressBar = self.progressBarForUpload('');
136
+ }
137
+
138
+ // send FormData object as ajax request
139
+ var xhr = new XMLHttpRequest();
140
+ xhr.upload.addEventListener('progress', function(e){ self.onPhotoUploadProgress(e, progressBar); }, false);
141
+ xhr.addEventListener('load', function(e){ self.onPhotoUploadComplete(e, progressBar); }, false);
142
+ xhr.addEventListener('error', function(e){ self.onPhotoUploadFailure(e, progressBar); }, false);
143
+ xhr.addEventListener('abort', function(e){ self.onPhotoUploadCancel(e, progressBar); }, false);
144
+ xhr.open('POST', form.attr('action'));
145
+ xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
146
+ xhr.send(fd);
147
+ return false;
148
+ }
149
+ };
150
+
151
+ /*
152
+ * Upload Progress Monitoring
153
+ -------------------------------- */
154
+
155
+ this.progressBarForUpload = function(fileName){
156
+ var html = [
157
+ '<div class="spud_admin_photo_progress">',
158
+ '<h6>',
159
+ '<span class="spud_admin_photo_progress_filename">'+fileName+'</span>: ',
160
+ '<span class="spud_admin_photo_progress_status">Uploading</span>',
161
+ '</h6>',
162
+ '<div class="progress progress-striped active">',
163
+ '<div class="bar" style="width: 0;"></div>',
164
+ '</div>',
165
+ '</div>'
166
+ ].join('');
167
+ return $(html);
168
+ };
169
+
170
+ this.onPhotoUploadProgress = function(e, progressBar){
171
+ var percent = Math.round(e.loaded * 100 / e.total);
172
+ progressBar.find('.bar').css({width: percent + '%'});
173
+ if(percent == 100){
174
+ progressBar.find('.progress').addClass('progress-success');
175
+ progressBar.find('.spud_admin_photo_progress_status').text('Processing');
176
+ }
177
+ };
178
+
179
+ this.onPhotoUploadComplete = function(e, progressBar){
180
+ // success
181
+ var photo = $.parseJSON(e.target.response);
182
+ if(e.target.status == 200){
183
+ progressBar.find('.spud_admin_photo_progress_status').text('Done!');
184
+ progressBar.find('.progress').removeClass('progress-striped active');
185
+ var element = $('#spud_admin_photo_' + photo.id);
186
+ if(element.length > 0){
187
+ element.replaceWith(photo.html);
188
+ }
189
+ else{
190
+ var target = $('#spud_admin_photos_selected, #spud_admin_photos');
191
+ target.prepend(photo.html).fadeIn(200);
192
+ }
193
+ hideModalDialog();
194
+ }
195
+ // validation error
196
+ else{
197
+ $("#modal_window .modal-body").html(photo.html);
198
+ }
199
+ };
200
+
201
+ this.onPhotoUploadCancel = function(e, progressBar){
202
+ progressBar.find('.spud_admin_photo_progress_status').text('Done!');
203
+ progressBar.find('.progress').addClass('progress-danger');
204
+ };
205
+
206
+ /*
207
+ * Photo Upload/Edit Form
208
+ ------------------------------- */
209
+ this.clickedPhotoAddOrEdit = function(e){
210
+ var url = this.href;
211
+ $.ajax({
212
+ url:url,
213
+ success:self.photoUploadFormLoaded
214
+ });
215
+ return false;
216
+ };
217
+
218
+ this.photoUploadFormLoaded = function(html){
219
+ displayModalDialogWithOptions({
220
+ title: 'Upload Photo',
221
+ html: html
222
+ });
223
+ };
224
+
225
+ /*
226
+ * Add From Photo Library
227
+ ------------------------------- */
228
+
229
+ this.clickedPhotoLibrary = function(e){
230
+ var url = this.href;
231
+ $.ajax({
232
+ url:url,
233
+ success:self.photoLibraryLoaded
234
+ });
235
+ return false;
236
+ };
237
+
238
+ this.photoLibraryLoaded = function(html){
239
+ var dialog = $('#modal_window');
240
+ $('#spud_admin_photos_selected .spud_admin_photo_ui_thumb').each(function(){
241
+ var id = $(this).attr('id');
242
+ var dupe = dialog.find('#'+id);
243
+ if(dupe){
244
+ dupe.remove();
245
+ }
246
+ });
247
+ displayModalDialogWithOptions({
248
+ title: 'My Photo Library',
249
+ html: html,
250
+ buttons:{
251
+ 'spud_admin_photo_library_add_selected btn-primary': 'Add Selected',
252
+ 'spud_admin_photo_library_delete_selected btn-danger': 'Delete Selected'
253
+ }
254
+ });
255
+ };
256
+
257
+ this.addSelectedPhotosFromLibrary = function(e){
258
+ $('#spud_admin_photo_library .spud_admin_photo_ui_thumb_selected')
259
+ .removeClass('spud_admin_photo_ui_thumb_selected')
260
+ .prependTo('#spud_admin_photos_selected')
261
+ .hide()
262
+ .fadeIn(200);
263
+ hideModalDialog();
264
+ };
265
+
266
+ this.deleteSelectedPhotosFromLibrary = function(e){
267
+ var ids = $.map($('.spud_admin_photo_ui_thumb_selected'), function(val, i){
268
+ return $(val).attr('rel');
269
+ });
270
+ $.ajax({
271
+ type: 'POST',
272
+ url: '/spud/admin/photos/mass_destroy',
273
+ data: {spud_photo_ids:ids},
274
+ success: function(data, textStatus, jqXHR){
275
+ $('.spud_admin_photo_ui_thumb_selected').fadeOut(200, function(){
276
+ $(this).remove();
277
+ });
278
+ },
279
+ error: function(jqXHR, textStatus, errorThrown){
280
+ console.log('An error occurred:');
281
+ console.log(arguments);
282
+ }
283
+ });
284
+
285
+ };
286
+
287
+ /*
288
+ * Drag & Drop File Upload Queue
289
+ -------------------------------- */
290
+
291
+ this.fileQueue = [];
292
+ this.fileQueueStarted = false;
293
+
294
+ // prevent default browser behavior of opening the dropped file
295
+ this.stopDndPropagation = function(e){
296
+ e.stopPropagation();
297
+ e.preventDefault();
298
+ };
299
+
300
+ // add files to queue. starts queue if not started already
301
+ this.droppedFile = function(e){
302
+ e.stopPropagation();
303
+ e.preventDefault();
304
+ $('#spud_admin_photo_upload_queue').show();
305
+ var files = e.dataTransfer.files;
306
+ var i = 0;
307
+ while(i < files.length){
308
+ self.fileQueue.push(files[i]);
309
+ i++;
310
+ }
311
+ self.updateQueueCountLabel();
312
+ if(!this.fileQueueStarted){
313
+ self.uploadNextPhoto();
314
+ if(self.fileQueue.length > 0){
315
+ self.uploadNextPhoto();
316
+ }
317
+ }
318
+ };
319
+
320
+ this.updateQueueCountLabel = function(){
321
+ $('#spud_admin_photo_upload_queue_label span').text(self.fileQueue.length);
322
+ };
323
+
324
+ this.uploadNextPhoto = function(){
325
+ if(self.fileQueue.length === 0){
326
+ self.fileQueueStarted = false;
327
+ return;
328
+ }
329
+
330
+ // formdata object
331
+ self.fileQueueStarted = true;
332
+ var file = self.fileQueue.pop();
333
+ var fd = new FormData();
334
+ fd.append('spud_photo[photo]', file);
335
+
336
+ // create a progress bar
337
+ var progressBar = self.progressBarForUpload(file.name);
338
+ $('#spud_admin_photo_upload_queue_bars').prepend(progressBar);
339
+
340
+ // send formdata as xhr
341
+ var xhr = new XMLHttpRequest();
342
+ xhr.upload.addEventListener('progress', function(e){ self.onPhotoUploadProgress(e, progressBar); }, false);
343
+ xhr.addEventListener('load', function(e){ self.onQueuedPhotoUploadComplete(e, progressBar); }, false);
344
+ xhr.addEventListener('error', function(e){ self.onPhotoUploadFailure(e, progressBar); }, false);
345
+ xhr.addEventListener('abort', function(e){ self.onPhotoUploadCancel(e, progressBar); }, false);
346
+ xhr.open('POST', '/spud/admin/photos');
347
+ xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
348
+ xhr.send(fd);
349
+ };
350
+
351
+ this.onQueuedPhotoUploadComplete = function(e, progressBar){
352
+ self.onPhotoUploadComplete(e, progressBar);
353
+ self.updateQueueCountLabel();
354
+ self.uploadNextPhoto();
355
+ };
356
+ };
@@ -0,0 +1,128 @@
1
+ /* Thumbnails
2
+ ---------------------------- */
3
+ .spud_admin_photo_ui_thumbs{
4
+ height: 300px;
5
+ padding: 0;
6
+ border: 1px solid #cacaca;
7
+ margin: 15px 0;
8
+ overflow-y: scroll;
9
+ }
10
+ .spud_admin_photo_ui_thumb{
11
+ width: 125px;
12
+ height: 125px;
13
+ float: left;
14
+ background: #666;
15
+ background-clip: content-box;
16
+ margin: 16px;
17
+ position: relative;
18
+ -webkit-touch-callout: none;
19
+ -webkit-user-select: none;
20
+ -khtml-user-select: none;
21
+ -moz-user-select: none;
22
+ -ms-user-select: none;
23
+ user-select: none;
24
+ box-shadow: 0 0 5px black, inset 0 0 50px rgba(0,0,0,0.25);
25
+ border-radius: 15px;
26
+ -webkit-transition-property: box-shadow;
27
+ -webkit-transition-duration: 0.2s;
28
+ -webkit-transition-timing-function: ease-out;
29
+ }
30
+ .spud_admin_photo_ui_thumb_small{
31
+ width: 100px;
32
+ height: 100px;
33
+ background-size: 100px 100px;
34
+ margin: 12px;
35
+ }
36
+ .spud_admin_photo_ui_thumb:hover{
37
+ box-shadow: 0 0 5px black;
38
+ }
39
+ .spud_admin_photo_ui_thumbs_selectable .spud_admin_photo_ui_thumb{
40
+ cursor: pointer;
41
+ }
42
+ .spud_admin_photo_ui_thumbs_selectable .spud_admin_photo_ui_thumb_controls{
43
+ display: none;
44
+ }
45
+ .spud_admin_photo_ui_thumb_selected{
46
+ border: 3px solid #006CCC;
47
+ margin: 13px;
48
+ }
49
+ .spud_admin_photo_ui_thumb_small.spud_admin_photo_ui_thumb_selected{
50
+ margin: 9px;
51
+ }
52
+ .spud_admin_photo_ui_thumbs_sortable .spud_admin_photo_ui_thumb{
53
+ cursor: move;
54
+ }
55
+ .spud_admin_photo_ui_thumb h5{
56
+ font-size: 12px;
57
+ color: white;
58
+ text-align: center;
59
+ background: rgba(0,0,0,0.5);
60
+ padding: 3px 8px;
61
+ border-top-left-radius: 15px;
62
+ border-top-right-radius: 15px;
63
+ white-space: nowrap;
64
+ overflow: hidden;
65
+ text-overflow: ellipsis;
66
+ margin: 0;
67
+ }
68
+ .spud_admin_photo_ui_thumb_controls{
69
+ position: absolute;
70
+ bottom: 0;
71
+ right: 0;
72
+ padding: 4px;
73
+ display: inline-block;
74
+ background: rgba(0,0,0,0.5);
75
+ border-bottom-right-radius: 15px;
76
+ }
77
+ .spud_admin_photos_btn_remove, .spud_admin_photos_btn_delete{
78
+ background: url('/assets/spud/photos/buttons/x_16x16.png');
79
+ height: 16px;
80
+ width: 16px;
81
+ text-indent: -7777px;
82
+ display: inline-block;
83
+ margin: 0 4px;
84
+ }
85
+ .spud_admin_photos_btn_edit{
86
+ background: url('/assets/spud/photos/buttons/cog_16x16.png');
87
+ height: 16px;
88
+ width: 16px;
89
+ text-indent: -7777px;
90
+ display: inline-block;
91
+ margin: 0 4px;
92
+ }
93
+
94
+ /* Upload Queue
95
+ ---------------------------- */
96
+ .spud_admin_photo_progress{
97
+ margin: 10px 0;
98
+ }
99
+ #spud_admin_photo_upload_queue{
100
+ display: none;
101
+ background: white;
102
+ padding: 15px;
103
+ margin: 0 0 0 10px;
104
+ width: 250px;
105
+ height: 270px;
106
+ float: right;
107
+ border: 1px solid #cacaca;
108
+ overflow-y: scroll;
109
+ }
110
+
111
+ /* Gallery Form
112
+ ---------------------------- */
113
+ .spud_admin_photos_selection_left{
114
+ width: 520px;
115
+ margin-right: 18px;
116
+ float: left;
117
+ }
118
+ .spud_admin_photos_selection_right{
119
+ width: 400px;
120
+ float: left;
121
+ }
122
+ .spud_admin_photos_selection_left h4, .spud_admin_photos_selection_right h4{
123
+ font-weight: normal;
124
+ margin: 15px 0;
125
+ }
126
+ #spud_admin_photo_gallery_form .spud_admin_photo_ui_thumb_controls{
127
+ display: none;
128
+ }
@@ -0,0 +1,54 @@
1
+ class PhotoAlbumsController < ApplicationController
2
+
3
+ respond_to :html, :json, :xml
4
+ layout Spud::Photos.base_layout
5
+
6
+ if Spud::Photos.galleries_enabled
7
+ before_filter :get_gallery
8
+ end
9
+
10
+ after_filter :only => [:show, :index] do |c|
11
+ if Spud::Photos.enable_full_page_caching
12
+ c.cache_page(nil, nil, false)
13
+ end
14
+ end
15
+
16
+ def index
17
+ if @photo_gallery
18
+ @photo_albums = @photo_gallery.albums.order('created_at desc')
19
+ else
20
+ @photo_albums = SpudPhotoAlbum.order('created_at desc')
21
+ end
22
+ respond_with @photo_albums
23
+ end
24
+
25
+ def show
26
+ @photo_album = SpudPhotoAlbum.find_by_url_name(params[:id])
27
+ if @photo_album.blank?
28
+ flash[:error] = "Could not find the requested Photo Album"
29
+ if params[:photo_gallery_id]
30
+ redirect_to photo_gallery_photo_albums_path(params[:photo_gallery_id])
31
+ else
32
+ redirect_to photo_albums_path
33
+ end
34
+ else
35
+ respond_with @photo_album
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def get_gallery
42
+ @photo_gallery = SpudPhotoGallery.find_by_url_name(params[:photo_gallery_id])
43
+ if @photo_gallery.blank?
44
+ flash[:error] = "Could not find the requested Photo Gallery"
45
+ if request.xhr?
46
+ render :nothing => true, :status => 404
47
+ else
48
+ redirect_to photo_galleries_path
49
+ end
50
+ return false
51
+ end
52
+ end
53
+
54
+ end