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.
- checksums.yaml +4 -4
- data/app/controllers/refinery/admin/images_controller.rb +62 -49
- data/app/helpers/refinery/admin/images_helper.rb +6 -6
- data/app/models/refinery/image.rb +16 -61
- data/app/models/refinery/thumbnail_dimensions.rb +97 -0
- data/app/views/refinery/admin/images/_actions.html.erb +6 -7
- data/app/views/refinery/admin/images/_form.html.erb +30 -12
- data/app/views/refinery/admin/images/_grid_view.html.erb +9 -16
- data/app/views/refinery/admin/images/_list_view.html.erb +4 -4
- data/app/views/refinery/admin/images/_list_view_image.html.erb +24 -15
- data/app/views/refinery/admin/images/index.html.erb +3 -3
- data/app/views/refinery/admin/images/insert.html.erb +1 -1
- data/config/locales/ca.yml +44 -0
- data/config/locales/cs.yml +5 -0
- data/config/locales/de.yml +5 -0
- data/config/locales/en.yml +4 -0
- data/config/locales/fr.yml +4 -0
- data/config/locales/it.yml +4 -14
- data/config/locales/nl.yml +1 -1
- data/config/routes.rb +1 -1
- data/db/migrate/20140814073957_add_title_and_alt_to_refinery_images.rb +8 -0
- data/db/migrate/20150430171341_translate_refinery_images.rb +22 -0
- data/lib/generators/refinery/images/templates/config/initializers/refinery/images.rb.erb +2 -5
- data/lib/refinery/images.rb +4 -1
- data/lib/refinery/images/configuration.rb +4 -6
- data/lib/refinery/images/dragonfly.rb +38 -27
- data/lib/refinery/images/engine.rb +2 -3
- data/license.md +1 -1
- data/refinerycms-images.gemspec +6 -3
- data/spec/factories/image.rb +6 -2
- data/spec/features/refinery/admin/images_spec.rb +49 -136
- data/spec/lib/generators/refinery/images/images_generator_spec.rb +1 -1
- data/spec/lib/refinery/images/dragonfly_spec.rb +34 -0
- data/spec/models/refinery/image_spec.rb +81 -43
- data/spec/models/refinery/thumbnail_dimensions_spec.rb +18 -0
- data/spec/support/shared contexts/admin_images_tab.rb +17 -0
- data/spec/support/shared contexts/many_images.rb +5 -0
- data/spec/support/shared contexts/no_images.rb +3 -0
- data/spec/support/shared contexts/one_image.rb +3 -0
- data/spec/support/shared contexts/visual_editor_add_image.rb +31 -0
- data/spec/support/shared examples/image_deleter.rb +31 -0
- data/spec/support/shared examples/image_editor.rb +3 -0
- data/spec/support/shared examples/image_indexer.rb +118 -0
- data/spec/support/shared examples/image_inserter.rb +53 -0
- data/spec/support/shared examples/image_previewer.rb +41 -0
- data/spec/support/shared examples/image_translator.rb +31 -0
- data/spec/support/shared examples/image_uploader.rb +37 -0
- data/spec/support/spec_helper.rb +19 -0
- data/test.html +126 -0
- metadata +64 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6520739bb59acf9b68122d223d3df823f96d8d18
|
4
|
+
data.tar.gz: 7845f6b085ab9282114f097f00e477c43a3c6704
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
:
|
7
|
-
:
|
8
|
-
:
|
6
|
+
include: [:translations],
|
7
|
+
order: "updated_at DESC",
|
8
|
+
sortable: false
|
9
9
|
|
10
|
-
|
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(:
|
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(:
|
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
|
37
|
+
render 'insert'
|
38
38
|
end
|
39
39
|
|
40
40
|
def create
|
41
41
|
@images = []
|
42
42
|
begin
|
43
|
-
|
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
|
-
|
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
|
51
|
+
rescue NotImplementedError
|
51
52
|
logger.warn($!.message)
|
52
53
|
@image = ::Refinery::Image.new
|
53
54
|
end
|
54
55
|
|
55
|
-
|
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
|
-
|
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
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
106
|
-
render :
|
107
|
-
|
108
|
-
|
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
|
-
|
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(:
|
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
|
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" =>
|
13
|
-
:"data-grid" =>
|
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}"] =
|
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
|
-
|
5
|
+
translates :image_title, :image_alt
|
6
6
|
|
7
|
-
|
7
|
+
dragonfly_accessor :image, :app => :refinery_images
|
8
8
|
|
9
|
-
|
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
|
-
|
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
|
-
|
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)
|
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
|
-
|
59
|
-
|
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
|
-
<%=
|
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
|
-
<%=
|
11
|
-
|
12
|
-
|
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>
|