refinerycms-images 2.1.5 → 3.0.0

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 (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>