refinerycms-images 2.1.5 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/refinery/admin/images_controller.rb +62 -49
  3. data/app/helpers/refinery/admin/images_helper.rb +6 -6
  4. data/app/models/refinery/image.rb +16 -61
  5. data/app/models/refinery/thumbnail_dimensions.rb +97 -0
  6. data/app/views/refinery/admin/images/_actions.html.erb +6 -7
  7. data/app/views/refinery/admin/images/_form.html.erb +30 -12
  8. data/app/views/refinery/admin/images/_grid_view.html.erb +9 -16
  9. data/app/views/refinery/admin/images/_list_view.html.erb +4 -4
  10. data/app/views/refinery/admin/images/_list_view_image.html.erb +24 -15
  11. data/app/views/refinery/admin/images/index.html.erb +3 -3
  12. data/app/views/refinery/admin/images/insert.html.erb +1 -1
  13. data/config/locales/ca.yml +44 -0
  14. data/config/locales/cs.yml +5 -0
  15. data/config/locales/de.yml +5 -0
  16. data/config/locales/en.yml +4 -0
  17. data/config/locales/fr.yml +4 -0
  18. data/config/locales/it.yml +4 -14
  19. data/config/locales/nl.yml +1 -1
  20. data/config/routes.rb +1 -1
  21. data/db/migrate/20140814073957_add_title_and_alt_to_refinery_images.rb +8 -0
  22. data/db/migrate/20150430171341_translate_refinery_images.rb +22 -0
  23. data/lib/generators/refinery/images/templates/config/initializers/refinery/images.rb.erb +2 -5
  24. data/lib/refinery/images.rb +4 -1
  25. data/lib/refinery/images/configuration.rb +4 -6
  26. data/lib/refinery/images/dragonfly.rb +38 -27
  27. data/lib/refinery/images/engine.rb +2 -3
  28. data/license.md +1 -1
  29. data/refinerycms-images.gemspec +6 -3
  30. data/spec/factories/image.rb +6 -2
  31. data/spec/features/refinery/admin/images_spec.rb +49 -136
  32. data/spec/lib/generators/refinery/images/images_generator_spec.rb +1 -1
  33. data/spec/lib/refinery/images/dragonfly_spec.rb +34 -0
  34. data/spec/models/refinery/image_spec.rb +81 -43
  35. data/spec/models/refinery/thumbnail_dimensions_spec.rb +18 -0
  36. data/spec/support/shared contexts/admin_images_tab.rb +17 -0
  37. data/spec/support/shared contexts/many_images.rb +5 -0
  38. data/spec/support/shared contexts/no_images.rb +3 -0
  39. data/spec/support/shared contexts/one_image.rb +3 -0
  40. data/spec/support/shared contexts/visual_editor_add_image.rb +31 -0
  41. data/spec/support/shared examples/image_deleter.rb +31 -0
  42. data/spec/support/shared examples/image_editor.rb +3 -0
  43. data/spec/support/shared examples/image_indexer.rb +118 -0
  44. data/spec/support/shared examples/image_inserter.rb +53 -0
  45. data/spec/support/shared examples/image_previewer.rb +41 -0
  46. data/spec/support/shared examples/image_translator.rb +31 -0
  47. data/spec/support/shared examples/image_uploader.rb +37 -0
  48. data/spec/support/spec_helper.rb +19 -0
  49. data/test.html +126 -0
  50. metadata +64 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b7a9716eb904f61c3ff4856a2b22006036233e16
4
- data.tar.gz: c0ae0f912c6adea630e3ca712916429cedc61d46
3
+ metadata.gz: 6520739bb59acf9b68122d223d3df823f96d8d18
4
+ data.tar.gz: 7845f6b085ab9282114f097f00e477c43a3c6704
5
5
  SHA512:
6
- metadata.gz: 345fdcd45d4d46f77287c56ac29aa315b39ae2b02a3013bd7095fbbed44de0a31917a7def064b3548cc1dd1bbd359fe4429f6d5d59c16aca3711eabfb0538eed
7
- data.tar.gz: 5f749f072bc2b9e3748da2ca94ac0761cc4c4aa6a62ea7d92d392587fd8eb47d2d18aa1b4cfbcda250f366a0c6445fe99c6d206162082a9f1e6da456c88c23e3
6
+ metadata.gz: 6f5983c92699bdec5da908a307ec6797da7ed711197e260b0a7b20024bed246dfbd5b2cb2bf37691ec7b57c143c49ddd4fdfe8e7b6c61e1a07b66b982911b585
7
+ data.tar.gz: 49e4348699512a24ba728f8affa5bf49d7e1dbcb45573e79f57f77928e5151a67de95b85b6402737d4bc6913a1516dbaa22f9eaca9de9e492b4f0d33b07df151
@@ -3,23 +3,23 @@ module Refinery
3
3
  class ImagesController < ::Refinery::AdminController
4
4
 
5
5
  crudify :'refinery/image',
6
- :order => "created_at DESC",
7
- :sortable => false,
8
- :xhr_paging => true
6
+ include: [:translations],
7
+ order: "updated_at DESC",
8
+ sortable: false
9
9
 
10
- before_filter :change_list_mode_if_specified, :init_dialog
10
+ before_action :change_list_mode_if_specified, :init_dialog
11
11
 
12
12
  def new
13
13
  @image = ::Refinery::Image.new if @image.nil?
14
14
 
15
- @url_override = refinery.admin_images_path(:dialog => from_dialog?)
15
+ @url_override = refinery.admin_images_path(dialog: from_dialog?)
16
16
  end
17
17
 
18
18
  # This renders the image insert dialog
19
19
  def insert
20
20
  self.new if @image.nil?
21
21
 
22
- @url_override = refinery.admin_images_path(request.query_parameters.merge(:insert => true))
22
+ @url_override = refinery.admin_images_path(request.query_parameters.merge(insert: true))
23
23
 
24
24
  if params[:conditions].present?
25
25
  extra_condition = params[:conditions].split(',')
@@ -34,86 +34,83 @@ module Refinery
34
34
 
35
35
  paginate_images
36
36
 
37
- render :action => "insert"
37
+ render 'insert'
38
38
  end
39
39
 
40
40
  def create
41
41
  @images = []
42
42
  begin
43
- unless params[:image].present? and params[:image][:image].is_a?(Array)
44
- @images << (@image = ::Refinery::Image.create(params[:image]))
45
- else
43
+ if params[:image].present? && params[:image][:image].is_a?(Array)
46
44
  params[:image][:image].each do |image|
47
- @images << (@image = ::Refinery::Image.create({:image => image}.merge(params[:image].except(:image))))
45
+ params[:image][:image_title] = params[:image][:image_title].presence || auto_title(image.original_filename)
46
+ @images << (@image = ::Refinery::Image.create({image: image}.merge(image_params.except(:image))))
48
47
  end
48
+ else
49
+ @images << (@image = ::Refinery::Image.create(image_params))
49
50
  end
50
- rescue Dragonfly::FunctionManager::UnableToHandle
51
+ rescue NotImplementedError
51
52
  logger.warn($!.message)
52
53
  @image = ::Refinery::Image.new
53
54
  end
54
55
 
55
- unless params[:insert]
56
+ if params[:insert]
57
+ # if all uploaded images are ok redirect page back to dialog, else show current page with error
56
58
  if @images.all?(&:valid?)
57
- flash.notice = t('created', :scope => 'refinery.crudify', :what => "'#{@images.map(&:title).join("', '")}'")
59
+ @image_id = @image.id if @image.persisted?
60
+ @image = nil
61
+ end
62
+
63
+ self.insert
64
+ else
65
+ if @images.all?(&:valid?)
66
+ flash.notice = t('created', scope: 'refinery.crudify', what: "'#{@images.map(&:image_title).join("', '")}'")
58
67
  if from_dialog?
59
68
  @dialog_successful = true
60
- render :nothing => true, :layout => true
69
+ render '/refinery/admin/dialog_success', layout: true
61
70
  else
62
71
  redirect_to refinery.admin_images_path
63
72
  end
64
73
  else
65
74
  self.new # important for dialogs
66
- render :action => 'new'
75
+ render 'new'
67
76
  end
68
- else
69
- # if all uploaded images are ok redirect page back to dialog, else show current page with error
70
- if @images.all?(&:valid?)
71
- @image_id = @image.id if @image.persisted?
72
- @image = nil
73
- end
74
-
75
- self.insert
76
77
  end
77
78
  end
78
79
 
79
80
  def update
80
- attributes_before_assignment = @image.attributes
81
- @image.attributes = params[:image]
81
+ @image.attributes = image_params
82
82
  if @image.valid? && @image.save
83
- flash.notice = t(
84
- 'refinery.crudify.updated',
85
- :what => "'#{@image.title}'"
86
- )
83
+ flash.notice = t('refinery.crudify.updated', what: "'#{@image.title}'")
87
84
 
88
- unless from_dialog?
89
- unless params[:continue_editing] =~ /true|on|1/
90
- redirect_back_or_default refinery.admin_images_path
91
- else
92
- unless request.xhr?
93
- redirect_to :back
94
- else
95
- render :partial => '/refinery/message'
96
- end
97
- end
98
- else
85
+ if from_dialog?
99
86
  self.index
100
87
  @dialog_successful = true
101
88
  render :index
89
+ else
90
+ if params[:continue_editing] =~ /true|on|1/
91
+ if request.xhr?
92
+ render partial: '/refinery/message'
93
+ else
94
+ redirect_to :back
95
+ end
96
+ else
97
+ redirect_back_or_default refinery.admin_images_path
98
+ end
102
99
  end
103
100
  else
104
101
  @thumbnail = Image.find params[:id]
105
- unless request.xhr?
106
- render :action => 'edit'
107
- else
108
- render :partial => '/refinery/admin/error_messages', :locals => {
109
- :object => @image,
110
- :include_object_name => true
102
+ if request.xhr?
103
+ render partial: '/refinery/admin/error_messages', locals: {
104
+ object: @image,
105
+ include_object_name: true
111
106
  }
107
+ else
108
+ render 'edit'
112
109
  end
113
110
  end
114
111
  end
115
112
 
116
- protected
113
+ protected
117
114
 
118
115
  def init_dialog
119
116
  @app_dialog = params[:app_dialog].present?
@@ -132,13 +129,29 @@ module Refinery
132
129
  end
133
130
 
134
131
  def paginate_images
135
- @images = @images.paginate(:page => params[:page], :per_page => Image.per_page(from_dialog?, !@app_dialog))
132
+ @images = @images.paginate(page: params[:page], per_page: Image.per_page(from_dialog?, !@app_dialog))
136
133
  end
137
134
 
138
135
  def restrict_controller
139
136
  super unless action_name == 'insert'
140
137
  end
141
138
 
139
+ def auto_title(filename)
140
+ CGI::unescape(filename.to_s).gsub(/\.\w+$/, '').titleize
141
+ end
142
+
143
+ def image_params
144
+ params.require(:image).permit(permitted_image_params)
145
+ end
146
+
147
+ private
148
+
149
+ def permitted_image_params
150
+ [
151
+ :image, :image_size, :image_title, :image_alt
152
+ ]
153
+ end
154
+
142
155
  end
143
156
  end
144
157
  end
@@ -2,19 +2,19 @@ module Refinery
2
2
  module Admin
3
3
  module ImagesHelper
4
4
  def other_image_views
5
- Refinery::Images.image_views.reject { |image_view|
5
+ Refinery::Images.image_views.reject do |image_view|
6
6
  image_view.to_s == Refinery::Images.preferred_image_view.to_s
7
- }
7
+ end
8
8
  end
9
9
 
10
10
  def thumbnail_urls(image)
11
11
  thumbnail_urls = {
12
- :"data-original" => asset_paths.compute_public_path(image.url, ''),
13
- :"data-grid" => asset_paths.compute_public_path(image.thumbnail(:geometry => '135x135#c').url, '')
12
+ :"data-original" => image_path(image.url),
13
+ :"data-grid" => image_path(image.thumbnail(:geometry => '135x135#c').url)
14
14
  }
15
15
 
16
- Refinery::Images.user_image_sizes.sort_by{|key,geometry| geometry}.each do |size, pixels|
17
- thumbnail_urls[:"data-#{size.to_s.parameterize}"] = asset_paths.compute_public_path(image.thumbnail(:geometry => pixels).url, '')
16
+ Refinery::Images.user_image_sizes.sort_by{ |key, geometry| geometry}.each do |size, pixels|
17
+ thumbnail_urls[:"data-#{size.to_s.parameterize}"] = image_path(image.thumbnail(:geometry => pixels).url)
18
18
  end
19
19
 
20
20
  thumbnail_urls
@@ -2,11 +2,11 @@ require 'dragonfly'
2
2
 
3
3
  module Refinery
4
4
  class Image < Refinery::Core::BaseModel
5
- ::Refinery::Images::Dragonfly.setup!
5
+ translates :image_title, :image_alt
6
6
 
7
- include Images::Validators
7
+ dragonfly_accessor :image, :app => :refinery_images
8
8
 
9
- image_accessor :image
9
+ include Images::Validators
10
10
 
11
11
  validates :image, :presence => true
12
12
  validates_with ImageSizeValidator
@@ -16,19 +16,16 @@ module Refinery
16
16
  :in => ::Refinery::Images.whitelisted_mime_types,
17
17
  :message => :incorrect_format
18
18
 
19
- # allows Mass-Assignment
20
- attr_accessible :id, :image, :image_size
21
-
22
19
  delegate :size, :mime_type, :url, :width, :height, :to => :image
23
20
 
24
21
  class << self
25
22
  # How many images per page should be displayed?
26
23
  def per_page(dialog = false, has_size_options = false)
27
24
  if dialog
28
- unless has_size_options
29
- Images.pages_per_dialog
30
- else
25
+ if has_size_options
31
26
  Images.pages_per_dialog_that_have_size_options
27
+ else
28
+ Images.pages_per_dialog
32
29
  end
33
30
  else
34
31
  Images.pages_per_admin_index
@@ -38,71 +35,29 @@ module Refinery
38
35
 
39
36
  # Get a thumbnail job object given a geometry and whether to strip image profiles and comments.
40
37
  def thumbnail(options = {})
41
- if options.is_a?(String) || options.is_a?(Symbol)
42
- Refinery.deprecate 'Refinery::Image#thumbnail(geometry)',
43
- :when => '2.2',
44
- :replacement => 'Refinery::Image#thumbnail(:geometry => value)'
45
- options = { :geometry => options }
46
- end
47
-
48
- options = { :geometry => :no_geometry, :strip => true }.merge(options)
38
+ options = { :geometry => nil, :strip => false }.merge(options)
49
39
  geometry = convert_to_geometry(options[:geometry])
50
40
  thumbnail = image
51
- thumbnail = thumbnail.thumb(geometry) unless geometry.is_a?(Symbol)
41
+ thumbnail = thumbnail.thumb(geometry) if geometry
52
42
  thumbnail = thumbnail.strip if options[:strip]
53
43
  thumbnail
54
44
  end
55
45
 
56
46
  # Intelligently works out dimensions for a thumbnail of this image based on the Dragonfly geometry string.
57
47
  def thumbnail_dimensions(geometry)
58
- geometry = if geometry.is_a?(Symbol) && Refinery::Images.user_image_sizes.keys.include?(geometry)
59
- Refinery::Images.user_image_sizes[geometry]
60
- else
61
- geometry.to_s
62
- end
63
-
64
- width = original_width = self.image_width.to_f
65
- height = original_height = self.image_height.to_f
66
- geometry_width, geometry_height = geometry.split(%r{\#{1,2}|\+|>|!|x}im)[0..1].map(&:to_f)
67
- if (original_width * original_height > 0) && ::Dragonfly::ImageMagick::Processor::THUMB_GEOMETRY === geometry
68
- if ::Dragonfly::ImageMagick::Processor::RESIZE_GEOMETRY === geometry
69
- if geometry !~ %r{\d+x\d+>} || (%r{\d+x\d+>} === geometry && (width > geometry_width.to_f || height > geometry_height.to_f))
70
- # Try scaling with width factor first. (wf = width factor)
71
- wf_width = (original_width * geometry_width / width).round
72
- wf_height = (original_height * geometry_width / width).round
73
-
74
- # Scale with height factor (hf = height factor)
75
- hf_width = (original_width * geometry_height / height).round
76
- hf_height = (original_height * geometry_height / height).round
77
-
78
- # Take the highest value that doesn't exceed either axis limit.
79
- use_wf = wf_width <= geometry_width && wf_height <= geometry_height
80
- if use_wf && hf_width <= geometry_width && hf_height <= geometry_height
81
- use_wf = wf_width * wf_height > hf_width * hf_height
82
- end
83
-
84
- if use_wf
85
- width = wf_width
86
- height = wf_height
87
- else
88
- width = hf_width
89
- height = hf_height
90
- end
91
- end
92
- else
93
- # cropping
94
- width = geometry_width
95
- height = geometry_height
96
- end
97
- end
98
-
99
- { :width => width.to_i, :height => height.to_i }
48
+ dimensions = ThumbnailDimensions.new(geometry, image.width, image.height)
49
+ { :width => dimensions.width, :height => dimensions.height }
100
50
  end
101
51
 
102
52
  # Returns a titleized version of the filename
103
53
  # my_file.jpg returns My File
54
+
104
55
  def title
105
- CGI::unescape(image_name.to_s).gsub(/\.\w+$/, '').titleize
56
+ image_title.presence || CGI::unescape(image_name.to_s).gsub(/\.\w+$/, '').titleize
57
+ end
58
+
59
+ def alt
60
+ image_alt.presence || title
106
61
  end
107
62
 
108
63
  private
@@ -0,0 +1,97 @@
1
+ module Refinery
2
+ class ThumbnailDimensions
3
+
4
+ attr_accessor :width, :height, :geometry, :original_width, :original_height
5
+
6
+ def initialize(geometry, original_width, original_height)
7
+ @geometry = Geometry.new(geometry)
8
+
9
+ @original_width = original_width.to_f
10
+ @original_height = original_height.to_f
11
+
12
+ process
13
+ end
14
+
15
+ def process
16
+ if valid_geometry && resize_geometry && resize_necessary
17
+ scale
18
+ elsif valid_geometry && !resize_geometry
19
+ crop
20
+ else
21
+ original_dimensions
22
+ end
23
+ end
24
+
25
+ def valid_geometry
26
+ (original_width * original_height > 0) && thumb_geometry === geometry.geometry
27
+ end
28
+
29
+ def resize_geometry
30
+ ::Dragonfly::ImageMagick::Processors::Thumb::RESIZE_GEOMETRY === geometry.geometry
31
+ end
32
+
33
+ def resize_necessary
34
+ !geometry.custom? ||
35
+ (geometry.custom? &&
36
+ (original_width > geometry.width ||
37
+ original_height > geometry.height))
38
+ end
39
+
40
+ def original_dimensions
41
+ @width = original_width
42
+ @height = original_height
43
+ end
44
+
45
+ def crop
46
+ @width = geometry.width
47
+ @height = geometry.height
48
+ end
49
+
50
+ def scale
51
+ # Try scaling with width factor first. (wf = width factor)
52
+ wf_width = geometry.width.round
53
+ wf_height = (original_height * geometry.width / original_width).round
54
+
55
+ # Scale with height factor (hf = height factor)
56
+ hf_width = (original_width * geometry.height / original_height).round
57
+ hf_height = geometry.height.round
58
+
59
+ # Take the highest value that doesn't exceed either axis limit.
60
+ use_wf = wf_width > 0 && wf_width <= geometry.width && wf_height <= geometry.height
61
+ if use_wf && hf_width <= geometry.width && hf_height <= geometry.height
62
+ use_wf = wf_width * wf_height > hf_width * hf_height
63
+ end
64
+
65
+ if use_wf
66
+ @width = wf_width
67
+ @height = wf_height
68
+ else
69
+ @width = hf_width
70
+ @height = hf_height
71
+ end
72
+ end
73
+
74
+ def thumb_geometry
75
+ Regexp.union(::Dragonfly::ImageMagick::Processors::Thumb::RESIZE_GEOMETRY,
76
+ ::Dragonfly::ImageMagick::Processors::Thumb::CROPPED_RESIZE_GEOMETRY,
77
+ ::Dragonfly::ImageMagick::Processors::Thumb::CROP_GEOMETRY)
78
+ end
79
+
80
+ class Geometry
81
+ attr_reader :geometry, :height, :width
82
+ def initialize(geometry)
83
+ @geometry = if geometry.is_a?(Symbol) && Refinery::Images.user_image_sizes.keys.include?(geometry)
84
+ Refinery::Images.user_image_sizes[geometry]
85
+ else
86
+ geometry.to_s
87
+ end
88
+
89
+ @width, @height = @geometry.split(%r{\#{1,2}|\+|>|!|x}im)[0..1].map(&:to_f)
90
+ end
91
+
92
+ def custom?
93
+ %r{\d+x\d+>} === geometry
94
+ end
95
+ end
96
+ end
97
+ end
@@ -1,15 +1,14 @@
1
1
  <ul>
2
+ <li><%= render '/refinery/admin/search', url: refinery.admin_images_path -%></li>
2
3
  <li>
3
- <%= render '/refinery/admin/search', :url => refinery.admin_images_path %>
4
- </li>
5
- <li>
6
- <%= link_to t('.create_new_image'), refinery.new_admin_image_path(:dialog => true), :class => 'add_icon' %>
4
+ <%= action_label :add, refinery.new_admin_image_path(dialog: true), t('.create_new_image') %>
7
5
  </li>
8
6
  <% other_image_views.each do |image_view| %>
9
7
  <li>
10
- <%= link_to t('switch_to', :scope => 'refinery.admin.images.index.view', :view_name => t("#{image_view}", :scope => 'refinery.admin.images.index.view')),
11
- refinery.admin_images_path(:view => image_view, :page => params[:page]),
12
- :class => 'reorder_icon' %>
8
+ <%= action_label :"switch_view_#{image_view}",
9
+ refinery.admin_images_path(view: image_view, page: params[:page]),
10
+ t('switch_to', scope: 'refinery.admin.images.index.view', view_name: t("#{image_view}", scope: 'refinery.admin.images.index.view'))
11
+ %>
13
12
  </li>
14
13
  <% end %>
15
14
  </ul>