refinerycms-images 0.9.9.1

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 (53) hide show
  1. data/app/controllers/admin/images_controller.rb +108 -0
  2. data/app/helpers/admin/images_helper.rb +27 -0
  3. data/app/models/image.rb +72 -0
  4. data/app/views/admin/images/_existing_image.html.erb +73 -0
  5. data/app/views/admin/images/_form.html.erb +54 -0
  6. data/app/views/admin/images/_grid_view.html.erb +19 -0
  7. data/app/views/admin/images/_images.html.erb +2 -0
  8. data/app/views/admin/images/_list_view.html.erb +10 -0
  9. data/app/views/admin/images/_list_view_image.html.erb +17 -0
  10. data/app/views/admin/images/edit.html.erb +1 -0
  11. data/app/views/admin/images/index.html.erb +38 -0
  12. data/app/views/admin/images/insert.html.erb +47 -0
  13. data/app/views/admin/images/new.html.erb +1 -0
  14. data/config/locales/cs.yml +41 -0
  15. data/config/locales/da.yml +41 -0
  16. data/config/locales/de.yml +41 -0
  17. data/config/locales/el.yml +41 -0
  18. data/config/locales/en.yml +41 -0
  19. data/config/locales/es.yml +40 -0
  20. data/config/locales/fr.yml +41 -0
  21. data/config/locales/it.yml +47 -0
  22. data/config/locales/lolcat.yml +41 -0
  23. data/config/locales/lt.yml +41 -0
  24. data/config/locales/lv.yml +41 -0
  25. data/config/locales/nb.yml +42 -0
  26. data/config/locales/nl.yml +40 -0
  27. data/config/locales/pl.yml +42 -0
  28. data/config/locales/pt-BR.yml +42 -0
  29. data/config/locales/rs.yml +42 -0
  30. data/config/locales/ru.yml +41 -0
  31. data/config/locales/sl.yml +40 -0
  32. data/config/locales/sv.yml +41 -0
  33. data/config/locales/vi.yml +41 -0
  34. data/config/locales/zh-CN.yml +41 -0
  35. data/config/locales/zh-TW.yml +41 -0
  36. data/config/routes.rb +12 -0
  37. data/db/migrate/20100913234707_create_refinerycms_images_schema.rb +23 -0
  38. data/features/manage_images.feature +49 -0
  39. data/features/step_definitions/image_steps.rb +40 -0
  40. data/features/support/factories.rb +5 -0
  41. data/features/support/paths.rb +17 -0
  42. data/features/uploads/beach.jpeg +0 -0
  43. data/features/uploads/id-rather-be-here.jpg +0 -0
  44. data/features/uploads/refinery_is_awesome.txt +1 -0
  45. data/lib/gemspec.rb +35 -0
  46. data/lib/generators/refinerycms_images_generator.rb +8 -0
  47. data/lib/refinerycms-images.rb +69 -0
  48. data/license.md +21 -0
  49. data/readme.md +34 -0
  50. data/refinerycms-images.gemspec +97 -0
  51. data/spec/models/image_spec.rb +87 -0
  52. data/spec/uploads/beach.jpeg +0 -0
  53. metadata +142 -0
@@ -0,0 +1,108 @@
1
+ module Admin
2
+ class ImagesController < Admin::BaseController
3
+
4
+ include Admin::ImagesHelper
5
+
6
+ crudify :image,
7
+ :order => "created_at DESC",
8
+ :sortable => false
9
+
10
+ before_filter :change_list_mode_if_specified, :init_dialog
11
+
12
+ def index
13
+ search_all_images if searching?
14
+ paginate_all_images
15
+
16
+ render :partial => 'images' if request.xhr?
17
+ end
18
+
19
+ def new
20
+ @image = Image.new if @image.nil?
21
+
22
+ @url_override = admin_images_url(:dialog => from_dialog?)
23
+ end
24
+
25
+ # This renders the image insert dialog
26
+ def insert
27
+ self.new if @image.nil?
28
+
29
+ @url_override = admin_images_url(:dialog => from_dialog?, :insert => true)
30
+
31
+ if params[:conditions].present?
32
+ extra_condition = params[:conditions].split(',')
33
+
34
+ extra_condition[1] = true if extra_condition[1] == "true"
35
+ extra_condition[1] = false if extra_condition[1] == "false"
36
+ extra_condition[1] = nil if extra_condition[1] == "nil"
37
+ end
38
+
39
+ find_all_images(({extra_condition[0].to_sym => extra_condition[1]} if extra_condition.present?))
40
+ search_all_images if searching?
41
+
42
+ paginate_images
43
+
44
+ render :action => "insert"
45
+ end
46
+
47
+ def create
48
+ @images = []
49
+ begin
50
+ unless params[:image].present? and params[:image][:image].is_a?(Array)
51
+ @images << (@image = Image.create(params[:image]))
52
+ else
53
+ params[:image][:image].each do |image|
54
+ @images << (@image = Image.create(:image => image))
55
+ end
56
+ end
57
+ rescue Dragonfly::FunctionManager::UnableToHandle
58
+ logger.warn($!.message)
59
+ @image = Image.new
60
+ end
61
+
62
+ unless params[:insert]
63
+ if @images.all?{|i| i.valid?}
64
+ flash.notice = t('created', :scope => 'refinery.crudify', :what => "'#{@images.collect{|i| i.title}.join("', '")}'")
65
+ unless from_dialog?
66
+ redirect_to :action => 'index'
67
+ else
68
+ render :text => "<script>parent.window.location = '#{admin_images_url}';</script>"
69
+ end
70
+ else
71
+ self.new # important for dialogs
72
+ render :action => 'new'
73
+ end
74
+ else
75
+ if @images.all?{|i| i.valid?}
76
+ @image_id = @image.id if @image.persisted?
77
+ @image = nil
78
+ end
79
+ self.insert
80
+ end
81
+ end
82
+
83
+ protected
84
+
85
+ def init_dialog
86
+ @app_dialog = params[:app_dialog].present?
87
+ @field = params[:field]
88
+ @update_image = params[:update_image]
89
+ @thumbnail = params[:thumbnail]
90
+ @callback = params[:callback]
91
+ @conditions = params[:conditions]
92
+ end
93
+
94
+ def paginate_images
95
+ @images = @images.paginate(:page => (@paginate_page_number ||= params[:page]),
96
+ :per_page => Image.per_page(from_dialog?, !@app_dialog))
97
+ end
98
+
99
+ def restrict_controller
100
+ super unless action_name == 'insert'
101
+ end
102
+
103
+ def store_current_location!
104
+ super unless action_name == 'insert' or from_dialog?
105
+ end
106
+
107
+ end
108
+ end
@@ -0,0 +1,27 @@
1
+ module Admin
2
+ module ImagesHelper
3
+
4
+ def image_views
5
+ RefinerySetting.find_or_set(:image_views, [:grid, :list])
6
+ end
7
+
8
+ def current_image_view
9
+ RefinerySetting.find_or_set(:preferred_image_view, :grid)
10
+ end
11
+
12
+ def other_image_views
13
+ image_views.reject {|image_view| image_view.to_s == current_image_view.to_s }
14
+ end
15
+
16
+ def change_list_mode_if_specified
17
+ if action_name == 'index' and params[:view].present? and image_views.include?(params[:view].to_sym)
18
+ RefinerySetting.set(:preferred_image_view, params[:view])
19
+ end
20
+ end
21
+
22
+ def images_paginator(collection, dialog = false)
23
+ will_paginate collection, :renderer => Refinery::LinkRenderer
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,72 @@
1
+ # encoding: utf-8
2
+
3
+ class Image < ActiveRecord::Base
4
+
5
+ # What is the max image size a user can upload
6
+ MAX_SIZE_IN_MB = 5
7
+
8
+ image_accessor :image
9
+
10
+ validates :image, :presence => {},
11
+ :length => { :maximum => MAX_SIZE_IN_MB.megabytes }
12
+ validates_property :mime_type, :of => :image, :in => %w(image/jpeg image/png image/gif image/tiff),
13
+ :message => :incorrect_format
14
+
15
+ # Docs for acts_as_indexed http://github.com/dougal/acts_as_indexed
16
+ acts_as_indexed :fields => [:title]
17
+
18
+ # when a dialog pops up with images, how many images per page should there be
19
+ PAGES_PER_DIALOG = 18
20
+
21
+ # when a dialog pops up with images, but that dialog has image resize options
22
+ # how many images per page should there be
23
+ PAGES_PER_DIALOG_THAT_HAS_SIZE_OPTIONS = 12
24
+
25
+ # when listing images out in the admin area, how many images should show per page
26
+ PAGES_PER_ADMIN_INDEX = 20
27
+
28
+ delegate :size, :mime_type, :url, :width, :height, :to => :image
29
+
30
+ class << self
31
+ # How many images per page should be displayed?
32
+ def per_page(dialog = false, has_size_options = false)
33
+ if dialog
34
+ unless has_size_options
35
+ PAGES_PER_DIALOG
36
+ else
37
+ PAGES_PER_DIALOG_THAT_HAS_SIZE_OPTIONS
38
+ end
39
+ else
40
+ PAGES_PER_ADMIN_INDEX
41
+ end
42
+ end
43
+
44
+ def user_image_sizes
45
+ RefinerySetting.find_or_set(:user_image_sizes, {
46
+ :small => '110x110>',
47
+ :medium => '225x255>',
48
+ :large => '450x450>'
49
+ }, :destroyable => false)
50
+ end
51
+ end
52
+
53
+ # Get a thumbnail job object given a geometry.
54
+ def thumbnail(geometry = nil)
55
+ if geometry.is_a?(Symbol) and self.class.user_image_sizes.keys.include?(geometry)
56
+ geometry = self.class.user_image_sizes[geometry]
57
+ end
58
+
59
+ if geometry.present? && !geometry.is_a?(Symbol)
60
+ image.thumb(geometry)
61
+ else
62
+ image
63
+ end
64
+ end
65
+
66
+ # Returns a titleized version of the filename
67
+ # my_file.jpg returns My File
68
+ def title
69
+ CGI::unescape(image_name.to_s).gsub(/\.\w+$/, '').titleize
70
+ end
71
+
72
+ end
@@ -0,0 +1,73 @@
1
+ <div id='existing_image_area' class='dialog_area' <%= "style='display:none;'" if @image.errors.any? %>>
2
+ <%= render :partial => '/shared/admin/search',
3
+ :locals => {:url => insert_admin_images_url(params.dup.delete(:image))} %>
4
+ <input type='hidden' name='selected_image' id='selected_image' />
5
+ <div id='existing_image_area_content' class='clearfix'>
6
+ <% if @images.any? %>
7
+ <ul>
8
+ <%
9
+ @images.each do |image|
10
+ thumbnail_urls = {
11
+ :"data-original" => image.url,
12
+ :"data-grid" => image.thumbnail('135x135#c').url
13
+ }
14
+ ::Image.user_image_sizes.sort_by{|key,geometry| geometry}.each do |size, pixels|
15
+ thumbnail_urls[:"data-#{size.to_s.parameterize}"] = image.thumbnail(pixels).url
16
+ end
17
+ -%>
18
+ <li<%= " class='selected'" if @image_id == image.id %>>
19
+ <%= image_fu(image, '106x106#c', {
20
+ :alt => image.title,
21
+ :title => image.title,
22
+ :id => "image_#{image.id}",
23
+ :'data-id' => image.id
24
+ }.merge(thumbnail_urls)) -%>
25
+ </li>
26
+ <% end -%>
27
+ </ul>
28
+ <% elsif searching? %>
29
+ <%= t('no_results', :scope => 'shared.admin.search') %>
30
+ <% end %>
31
+ </div>
32
+
33
+ <%= images_paginator @images, from_dialog? %>
34
+
35
+ <% unless @app_dialog or @images.empty? %>
36
+ <div id='existing_image_size_area' class='clearfix'>
37
+ <input type='hidden' name='selected_image_size' id='selected_image_size' />
38
+ <p>
39
+ <input type="checkbox" id="wants_to_resize_image" name="wants_to_resize_image" value="1" checked="checked" />
40
+ <label for='wants_to_resize_image' class='stripped' style='font-weight: bold;'>
41
+ <%= t('.resize_image') %>
42
+ </label>
43
+ </p>
44
+ <ul>
45
+ <%
46
+ ::Image.user_image_sizes.sort_by { |key, geometry| geometry }.each_with_index do |(size, pixels), index|
47
+ safe_pixels = pixels.to_s.gsub(/[<>=]/, '')
48
+ # (parndt): ' selected' if size.to_s == 'medium' is not very generic, but I
49
+ # can't think of a decent way of making it so for even sets (e.g. 2,4,6,8,etc image sizes).
50
+ -%>
51
+ <li id="image_dialog_size_<%= index %>" class="image_dialog_size<%= ' selected' if size.to_s == 'medium' %>">
52
+ <%= link_to size.to_s, "##{size}",
53
+ :'data-geometry' => pixels,
54
+ :'data-size' => size.to_s.parameterize,
55
+ :title => "#{size} image (#{safe_pixels})",
56
+ :tooltip => "#{size} image (#{safe_pixels})" %>
57
+ </li>
58
+ <% end -%>
59
+ </ul>
60
+ </div>
61
+ <% end %>
62
+
63
+ <%= render :partial => "/shared/admin/form_actions",
64
+ :locals => {
65
+ :f => nil,
66
+ :cancel_url => '',
67
+ :submit_button_text => t('.button_text'),
68
+ :hide_submit => @images.empty?,
69
+ :hide_cancel => false,
70
+ :hide_delete => true,
71
+ :cancel_title => nil
72
+ } if @app_dialog or @images.any? or searching? %>
73
+ </div>
@@ -0,0 +1,54 @@
1
+ <%= form_for [:admin, @image], :url => @url_override || @url, :html => {:multipart => true} do |f| %>
2
+
3
+ <%= render :partial => "/shared/admin/error_messages",
4
+ :locals => {
5
+ :object => @image,
6
+ :include_object_name => false
7
+ } %>
8
+
9
+ <div class='field'>
10
+ <% if action_name =~ /(edit)|(update)/ %>
11
+ <p>
12
+ <%= t('.use_current_image') %>
13
+ <em><%= t('.or') %></em><%= t('.replace_image') %>
14
+ </p>
15
+ <p>
16
+ <%= f.file_field :image %>
17
+ </p>
18
+ <% else %>
19
+ <% # we must only hint at multiple when it's a new record otherwise update fails. %>
20
+ <%= f.file_field :image, :multiple => true %>
21
+ <% end %>
22
+ </div>
23
+
24
+ <div class='field'>
25
+ <label><%= t('.maximum_image_size', :megabytes => Image::MAX_SIZE_IN_MB) %></label>
26
+ </div>
27
+
28
+ <input type='hidden' name='wymeditor' value='<%= params[:wymeditor] %>'>
29
+
30
+ <%= render :partial => "/shared/admin/form_actions",
31
+ :locals => {
32
+ :f => f,
33
+ :continue_editing => false,
34
+ :hide_cancel => (@app_dialog or action_name == "insert" or from_dialog?),
35
+ :delete_title => t('delete', :scope => 'admin.images'),
36
+ :delete_confirmation => t('message', :scope => 'shared.admin.delete', :title => @image.image_name)
37
+ } -%>
38
+
39
+ <% if @app_dialog %>
40
+ <input type='hidden' name='app_dialog' value='<%= @app_dialog %>' />
41
+ <input type='hidden' name='field' value='<%= @field %>' />
42
+ <input type='hidden' name='update_image' value='<%= @update_image %>' />
43
+ <input type='hidden' name='thumbnail' value='<%= @thumbnail %>' />
44
+ <input type='hidden' name='callback' value='<%= @callback %>' />
45
+ <input type='hidden' name='conditions' value='<%= @conditions %>' />
46
+ <% end %>
47
+ <% end %>
48
+
49
+ <% if action_name =~ /(edit)|(update)/ %>
50
+ <div id='existing_image'>
51
+ <label><%=t('.current_image') %></label>
52
+ <%= image_fu @image, '225x255>', :class => "brown_border" %>
53
+ </div>
54
+ <% end %>
@@ -0,0 +1,19 @@
1
+ <ul id="image_grid" class="<%= ['clearfix', 'pagination_frame', pagination_css_class].compact.join(' ') %>">
2
+ <% @images.each_with_index do |image, index| -%>
3
+ <li id="image_<%= image.id %>" class='image_<%= index % 5 %>'>
4
+ <%= image_fu image, '135x135#c', :title => image.title %>
5
+ <span class='actions'>
6
+ <%= link_to refinery_icon_tag('eye.png'), image.url,
7
+ :target => "_blank",
8
+ :title => t('.view_live_html') %>
9
+ <%= link_to refinery_icon_tag('application_edit.png'), edit_admin_image_path(image),
10
+ :title => t('edit', :scope => 'admin.images') %>
11
+ <%= link_to refinery_icon_tag('delete.png'), admin_image_path(image),
12
+ :class => "cancel confirm-delete",
13
+ :title => t('delete', :scope => 'admin.images'),
14
+ :confirm => t('message', :scope => 'shared.admin.delete', :title => image.title),
15
+ :method => :delete %>
16
+ </span>
17
+ </li>
18
+ <% end -%>
19
+ </ul>
@@ -0,0 +1,2 @@
1
+ <%= will_paginate @images %>
2
+ <%= render :partial => "#{current_image_view}_view" %>
@@ -0,0 +1,10 @@
1
+ <div class="<%= ['clearfix', 'pagination_frame', pagination_css_class].compact.join(' ') %>">
2
+ <% group_by_date(@images).each do |container| %>
3
+ <% date_time = (image_group = container.last).first.created_at %>
4
+ <% date = Date.parse(date_time.to_s) %>
5
+ <h3><%= l(date, :format => :long ) %></h3>
6
+ <ul>
7
+ <%= render :partial => 'list_view_image', :collection => image_group %>
8
+ </ul>
9
+ <% end %>
10
+ </div>
@@ -0,0 +1,17 @@
1
+ <li id="sortable_<%= list_view_image.id %>" class='clearfix record <%= cycle("on", "on-hover") %>'>
2
+ <span class='title'>
3
+ <%= list_view_image.title %> <span class="preview">&nbsp;</span>
4
+ </span>
5
+ <span class='actions'>
6
+ <%= link_to refinery_icon_tag('eye.png'), list_view_image.url,
7
+ :target => "_blank",
8
+ :title => "#{image_fu list_view_image, '96x96#c', :size => '96x96'}" %>
9
+ <%= link_to refinery_icon_tag('application_edit.png'), edit_admin_image_path(list_view_image),
10
+ :title => t('edit', :scope => 'admin.images') %>
11
+ <%= link_to refinery_icon_tag('delete.png'), admin_image_path(list_view_image),
12
+ :class => "cancel confirm-delete",
13
+ :title => t('delete', :scope => 'admin.images'),
14
+ :confirm => t('message', :scope => 'shared.admin.delete', :title => list_view_image.title),
15
+ :method => :delete %>
16
+ </span>
17
+ </li>
@@ -0,0 +1 @@
1
+ <%= render :partial => "form" %>
@@ -0,0 +1,38 @@
1
+ <div id='records'>
2
+ <% if searching? %>
3
+ <h2><%= t('results_for', :scope => 'shared.admin.search', :query => params[:search]) %></h2>
4
+ <% end %>
5
+ <% if @images.any? %>
6
+ <div class='pagination_container'>
7
+ <%= render :partial => 'images' %>
8
+ </div>
9
+ <% else %>
10
+ <p>
11
+ <% unless searching? %>
12
+ <strong>
13
+ <%= t('.no_images_yet') %>
14
+ </strong>
15
+ <% else %>
16
+ <%= t('no_results', :scope => 'shared.admin.search') %>
17
+ <% end %>
18
+ </p>
19
+ <% end %>
20
+ </div>
21
+ <div id='actions'>
22
+ <ul>
23
+ <li>
24
+ <%= render :partial => "/shared/admin/search", :locals => {:url => admin_images_url} %>
25
+ </li>
26
+ <li>
27
+ <%= link_to t('.create_new_image'), new_admin_image_url(:dialog => true, :width => 600, :height => 300),
28
+ :class => "add_icon" %>
29
+ </li>
30
+ <% other_image_views.each do |image_view| %>
31
+ <li>
32
+ <%= link_to t('switch_to', :scope => 'admin.images.index.view', :view_name => t("#{image_view}", :scope => 'admin.images.index.view')),
33
+ admin_images_url(:view => image_view, :page => params[:page]),
34
+ :class => "reorder_icon" %>
35
+ </li>
36
+ <% end %>
37
+ </ul>
38
+ </div>
@@ -0,0 +1,47 @@
1
+ <% user_can_modify_images = ::Refinery::Plugins.active.names.include?("refinery_images") %>
2
+ <div id='dialog_menu_left'>
3
+ <% if (any_images = @images.any?) or searching? %>
4
+ <span id="existing_image_radio" class="radio<%= " selected_radio" if (no_errors = @image.errors.empty?) %>">
5
+ <input type='radio' name='image_type' value='existing_image' id='image_type_existing'<%= " checked='true'" if no_errors or searching? %> />
6
+ <label for='image_type_existing' class='stripped'><%= t('.existing_image') %></label>
7
+ </span>
8
+ <% end %>
9
+ <% if user_can_modify_images %>
10
+ <span id="upload_image_radio" class="radio<%= " selected_radio" if !no_errors and !any_images %>">
11
+ <input type='radio' name='image_type' value='upload_image' id='image_type_upload'<%= " checked='true'" if (!any_images or !no_errors) and !searching? %> />
12
+ <label for='image_type_upload' class='stripped'><%= t('.new_image') %></label>
13
+ </span>
14
+ <% end %>
15
+ </div>
16
+
17
+ <div id='dialog_main'>
18
+ <% if any_images or user_can_modify_images %>
19
+ <%= render :partial => "existing_image" if any_images or searching? %>
20
+
21
+ <% if user_can_modify_images %>
22
+ <div id='upload_image_area' class='dialog_area'<%= " style='display:none;'" if any_images and (no_errors or searching?) %>>
23
+ <%= render :partial => "form", :locals => {:insert => true} %>
24
+ </div>
25
+ <% end %>
26
+ <% else %>
27
+ <% flash.now[:error] = t('no_images_yet', :scope => 'admin.images.index').split('.').first.html_safe + "." %>
28
+ <%= render :partial => "/shared/admin/form_actions",
29
+ :locals => {
30
+ :f => nil,
31
+ :cancel_url => '',
32
+ :hide_cancel => false,
33
+ :hide_delete => true,
34
+ :hide_submit => true,
35
+ :cancel_button_text => t('close', :scope => 'shared.admin.form_actions'),
36
+ :cancel_title => nil
37
+ } %>
38
+ <% end %>
39
+ </div>
40
+
41
+ <% content_for :javascripts do %>
42
+ <script>
43
+ $(document).ready(function(){
44
+ image_dialog.init(<%= @callback.present? ? "self.parent.#{@callback}" : "null" %>);
45
+ });
46
+ </script>
47
+ <% end %>