refinerycms-images 4.0.3 → 4.1.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 +48 -9
- data/app/helpers/refinery/admin/images_helper.rb +12 -6
- data/app/models/refinery/image.rb +20 -12
- data/app/presenters/refinery/admin/grid_presenter.rb +42 -0
- data/app/presenters/refinery/admin/group_presenter.rb +68 -0
- data/app/presenters/refinery/admin/image_presenter.rb +145 -0
- data/app/presenters/refinery/admin/list_presenter.rb +23 -0
- data/app/views/refinery/admin/images/_crop.html.erb +7 -0
- data/app/views/refinery/admin/images/_existing_image.html.erb +52 -27
- data/app/views/refinery/admin/images/_form.html.erb +60 -12
- data/app/views/refinery/admin/images/_image.html.erb +5 -0
- data/app/views/refinery/admin/images/_list_view.html.erb +2 -2
- data/app/views/refinery/admin/images/destroy_crop.js.erb +18 -0
- data/config/locales/en.yml +11 -1
- data/config/locales/fr.yml +10 -0
- data/config/locales/sk.yml +17 -1
- data/config/routes.rb +6 -4
- data/db/migrate/20150430171341_translate_refinery_images.rb +13 -17
- data/db/migrate/20180711122352_add_parent_id_to_refinery_images.rb +5 -0
- data/lib/generators/refinery/images/templates/config/initializers/refinery/images.rb.erb +5 -2
- data/lib/refinery/images/configuration.rb +13 -7
- data/lib/refinery/images/validators/image_size_validator.rb +8 -8
- data/lib/refinery/images/validators/image_update_validator.rb +3 -3
- data/lib/refinery/images.rb +3 -3
- data/lib/refinerycms/images.rb +1 -0
- data/lib/refinerycms-images.rb +0 -1
- data/refinerycms-images.gemspec +13 -20
- data/spec/factories/image.rb +3 -3
- data/spec/support/shared_contexts/admin_images_tab.rb +1 -1
- data/spec/support/shared_contexts/grid_view.rb +8 -0
- data/spec/support/shared_contexts/list_view.rb +12 -0
- data/spec/support/shared_examples/image_deleter.rb +1 -1
- data/spec/support/shared_examples/image_previewer.rb +1 -1
- data/spec/support/shared_examples/image_translator.rb +1 -1
- data/spec/support/shared_examples/image_uploader.rb +6 -3
- data/spec/{features → system}/refinery/admin/dialog_spec.rb +1 -1
- data/spec/{features → system}/refinery/admin/images_spec.rb +13 -1
- metadata +31 -87
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9843f043fac07905d1893351f1f570530acb3e5864bfb33340f8a8144cf83d4f
|
|
4
|
+
data.tar.gz: 10dbda158cc2298e77cf3b5340a32a0b238093dec5b4be4a493576caf2d022e4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: baf1f003fc65d7deb38c1ce79b2559d8b6955aa9755fe7f87360bad8a7dfea512bb9dc286ff1aaaba8732b2c7af11c59da902787292fb9259bb9163c723dadc4
|
|
7
|
+
data.tar.gz: d0ca50f9d0333d4dd8fb22d43294e948f660cc40d00114d4d995478d7d195390d50e907da36cc2d3d8870a5c2cb2348833d41ac9724ac373922daeb3a0f7fe34
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'will_paginate/array'
|
|
4
|
+
|
|
1
5
|
module Refinery
|
|
2
6
|
module Admin
|
|
3
7
|
class ImagesController < ::Refinery::AdminController
|
|
4
8
|
|
|
5
9
|
crudify :'refinery/image',
|
|
6
|
-
include: [:translations],
|
|
10
|
+
include: [:translations, :crops],
|
|
7
11
|
order: "updated_at DESC",
|
|
8
|
-
sortable: false
|
|
12
|
+
sortable: false,
|
|
13
|
+
conditions: 'parent_id IS NULL',
|
|
14
|
+
find_actions: [:update, :destroy, :edit]
|
|
9
15
|
|
|
10
16
|
before_action :change_list_mode_if_specified, :init_dialog
|
|
11
17
|
|
|
@@ -18,7 +24,6 @@ module Refinery
|
|
|
18
24
|
# This renders the image insert dialog
|
|
19
25
|
def insert
|
|
20
26
|
self.new if @image.nil?
|
|
21
|
-
|
|
22
27
|
@url_override = refinery.admin_images_path(request.query_parameters.merge(insert: true))
|
|
23
28
|
|
|
24
29
|
if params[:conditions].present?
|
|
@@ -42,8 +47,10 @@ module Refinery
|
|
|
42
47
|
begin
|
|
43
48
|
if params[:image].present? && params[:image][:image].is_a?(Array)
|
|
44
49
|
params[:image][:image].each do |image|
|
|
45
|
-
|
|
46
|
-
@images <<
|
|
50
|
+
image_title = params[:image][:image_title].presence || auto_title(image.original_filename)
|
|
51
|
+
@images << @image = ::Refinery::Image.create(
|
|
52
|
+
image_params.merge(image_title: image_title, image: image)
|
|
53
|
+
)
|
|
47
54
|
end
|
|
48
55
|
else
|
|
49
56
|
@images << (@image = ::Refinery::Image.create(image_params))
|
|
@@ -91,7 +98,7 @@ module Refinery
|
|
|
91
98
|
if request.xhr?
|
|
92
99
|
render partial: '/refinery/message'
|
|
93
100
|
else
|
|
94
|
-
|
|
101
|
+
redirect_back(fallback_location: { action: 'edit' })
|
|
95
102
|
end
|
|
96
103
|
else
|
|
97
104
|
redirect_back_or_default refinery.admin_images_path
|
|
@@ -110,6 +117,39 @@ module Refinery
|
|
|
110
117
|
end
|
|
111
118
|
end
|
|
112
119
|
|
|
120
|
+
def crop
|
|
121
|
+
parent_image = ::Refinery::Image.find_by_id(params[:image_id])
|
|
122
|
+
|
|
123
|
+
cropped_image = ::Refinery::Image.new(
|
|
124
|
+
parent_id: parent_image.id,
|
|
125
|
+
image: params[:image]
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
if cropped_image.valid? && cropped_image.save!
|
|
129
|
+
flash.notice = ::I18n.t('refinery.admin.images.form.crop_success')
|
|
130
|
+
render json: {
|
|
131
|
+
message: ::I18n.t('refinery.admin.images.form.crop_success'),
|
|
132
|
+
crop: render_to_string('/refinery/admin/images/_crop', layout: false, locals: { crop: cropped_image})
|
|
133
|
+
}
|
|
134
|
+
else
|
|
135
|
+
flash.now[:error] = ::I18n.t('refinery.admin.images.form.crop_error')
|
|
136
|
+
render json: { message: ::I18n.t('refinery.admin.images.form.crop_error') }
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def destroy_crop
|
|
141
|
+
@image = Refinery::Image.find_by_id(params[:image_id])
|
|
142
|
+
title = @image.parent.image_name
|
|
143
|
+
|
|
144
|
+
if @image.destroy
|
|
145
|
+
flash.notice = t('destroyed', scope: 'refinery.crudify', what: title)
|
|
146
|
+
|
|
147
|
+
respond_to do |format|
|
|
148
|
+
format.js { render "/refinery/admin/images/destroy_crop", locals: { image_id: @image.id } }
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
113
153
|
protected
|
|
114
154
|
|
|
115
155
|
def init_dialog
|
|
@@ -130,7 +170,7 @@ module Refinery
|
|
|
130
170
|
end
|
|
131
171
|
|
|
132
172
|
def paginate_images
|
|
133
|
-
@images = @images.paginate(page: params[:page], per_page: Image.per_page(from_dialog?, !@app_dialog))
|
|
173
|
+
@images = @images.root.paginate(page: params[:page], per_page: Image.per_page(from_dialog?, !@app_dialog))
|
|
134
174
|
end
|
|
135
175
|
|
|
136
176
|
def restrict_controller
|
|
@@ -149,10 +189,9 @@ module Refinery
|
|
|
149
189
|
|
|
150
190
|
def permitted_image_params
|
|
151
191
|
[
|
|
152
|
-
:
|
|
192
|
+
{ image: [] }, :image_size, :image_title, :image_alt
|
|
153
193
|
]
|
|
154
194
|
end
|
|
155
|
-
|
|
156
195
|
end
|
|
157
196
|
end
|
|
158
197
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Refinery
|
|
2
4
|
module Admin
|
|
3
5
|
module ImagesHelper
|
|
@@ -7,17 +9,21 @@ module Refinery
|
|
|
7
9
|
end
|
|
8
10
|
end
|
|
9
11
|
|
|
12
|
+
def locale_text_icon(text)
|
|
13
|
+
text
|
|
14
|
+
end
|
|
15
|
+
|
|
10
16
|
def thumbnail_urls(image)
|
|
11
|
-
|
|
12
|
-
:
|
|
13
|
-
:
|
|
17
|
+
thumbnails = {
|
|
18
|
+
original: image_path(image.url),
|
|
19
|
+
grid: image_path(image.thumbnail(geometry: '135x135#c').url)
|
|
14
20
|
}
|
|
15
21
|
|
|
16
|
-
Refinery::Images.user_image_sizes.sort_by{ |key, geometry| geometry}.each do |size, pixels|
|
|
17
|
-
|
|
22
|
+
Refinery::Images.user_image_sizes.sort_by { |key, geometry| geometry }.each do |size, pixels|
|
|
23
|
+
thumbnails[size.to_s.parameterize] = image_path(image.thumbnail(geometry: pixels).url)
|
|
18
24
|
end
|
|
19
25
|
|
|
20
|
-
|
|
26
|
+
{ data: thumbnails }
|
|
21
27
|
end
|
|
22
28
|
end
|
|
23
29
|
end
|
|
@@ -2,24 +2,32 @@ require 'dragonfly'
|
|
|
2
2
|
|
|
3
3
|
module Refinery
|
|
4
4
|
class Image < Refinery::Core::BaseModel
|
|
5
|
+
extend Mobility
|
|
5
6
|
translates :image_title, :image_alt
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
attribute :image_alt
|
|
9
|
-
|
|
10
|
-
dragonfly_accessor :image, :app => :refinery_images
|
|
8
|
+
dragonfly_accessor :image, app: :refinery_images
|
|
11
9
|
|
|
12
10
|
include Images::Validators
|
|
13
11
|
|
|
14
|
-
validates :image, :
|
|
12
|
+
validates :image, presence: true
|
|
15
13
|
validates_with ImageSizeValidator
|
|
16
|
-
validates_with ImageUpdateValidator, :
|
|
14
|
+
validates_with ImageUpdateValidator, on: :update
|
|
17
15
|
validates_property :mime_type,
|
|
18
|
-
:
|
|
19
|
-
:
|
|
20
|
-
:
|
|
16
|
+
of: :image,
|
|
17
|
+
in: ::Refinery::Images.allowed_mime_types,
|
|
18
|
+
message: ->(mime_type, image){
|
|
19
|
+
::I18n.t(:incorrect_format,
|
|
20
|
+
scope: 'activerecord.errors.models.refinery/image',
|
|
21
|
+
actual: mime_type,
|
|
22
|
+
valid_types: ::Refinery::Images.allowed_mime_types_msg)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
delegate :size, :mime_type, :url, :width, :height, to: :image
|
|
26
|
+
|
|
27
|
+
has_many :crops, class_name: '::Refinery::Image', foreign_key: 'parent_id', dependent: :destroy
|
|
28
|
+
belongs_to :parent, class_name: '::Refinery::Image', foreign_key: 'parent_id', optional: true
|
|
21
29
|
|
|
22
|
-
|
|
30
|
+
scope :root, -> { where(parent_id: nil) }
|
|
23
31
|
|
|
24
32
|
class << self
|
|
25
33
|
# How many images per page should be displayed?
|
|
@@ -38,7 +46,7 @@ module Refinery
|
|
|
38
46
|
|
|
39
47
|
# Get a thumbnail job object given a geometry and whether to strip image profiles and comments.
|
|
40
48
|
def thumbnail(options = {})
|
|
41
|
-
options = { :
|
|
49
|
+
options = { geometry: nil, strip: false }.merge(options)
|
|
42
50
|
geometry = convert_to_geometry(options[:geometry])
|
|
43
51
|
thumbnail = image
|
|
44
52
|
thumbnail = thumbnail.thumb(geometry) if geometry
|
|
@@ -49,7 +57,7 @@ module Refinery
|
|
|
49
57
|
# Intelligently works out dimensions for a thumbnail of this image based on the Dragonfly geometry string.
|
|
50
58
|
def thumbnail_dimensions(geometry)
|
|
51
59
|
dimensions = ThumbnailDimensions.new(geometry, image.width, image.height)
|
|
52
|
-
{ :
|
|
60
|
+
{ width: dimensions.width, height: dimensions.height }
|
|
53
61
|
end
|
|
54
62
|
|
|
55
63
|
# Returns a titleized version of the filename
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module Refinery
|
|
2
|
+
module Admin
|
|
3
|
+
|
|
4
|
+
# Refinery::Admin::GridPresenter is a class intended for presenting
|
|
5
|
+
# grouped records in a grid format within the Refinery CMS admin interface.
|
|
6
|
+
#
|
|
7
|
+
# It inherits from Refinery::Admin::GroupPresenter and overrides specific
|
|
8
|
+
# properties to provide custom behavior suitable for grid presentations.
|
|
9
|
+
#
|
|
10
|
+
# The primary features provided by this class include:
|
|
11
|
+
# - Custom grouping of records based on predefined logic.
|
|
12
|
+
# - Control over headers, identity keys, and displayed content organization.
|
|
13
|
+
#
|
|
14
|
+
# == Inclusions
|
|
15
|
+
# This class includes the following modules to extend functionality:
|
|
16
|
+
# - Refinery::Admin::ImagesHelper: Provides helper methods for working with images.
|
|
17
|
+
# - ActionView::Helpers::TagHelper: Supplies methods for creating HTML tags.
|
|
18
|
+
#
|
|
19
|
+
# == Attributes
|
|
20
|
+
# - @group_headers: Controls whether headers for each record group are displayed. Defaults to `false`.
|
|
21
|
+
# - @identity_keys: Represents the keys used to identify and present record attributes, including thumbnail, title, and alt text attributes.
|
|
22
|
+
# - @header: Stores header configurations, initialized as `nil`.
|
|
23
|
+
# - @groups: A lambda function designed to group records by associating them with the current date.
|
|
24
|
+
#
|
|
25
|
+
# == Initialization
|
|
26
|
+
# When initialized, `GridPresenter` accepts an execution `context` (e.g., a controller, view, etc.)
|
|
27
|
+
# and propagates this context to the superclass.
|
|
28
|
+
class GridPresenter < GroupPresenter
|
|
29
|
+
include Refinery::Admin::ImagesHelper
|
|
30
|
+
include ActionView::Helpers::TagHelper
|
|
31
|
+
|
|
32
|
+
def initialize(context)
|
|
33
|
+
super(context)
|
|
34
|
+
@group_headers = false
|
|
35
|
+
@identity_keys = [:thumbnail, :title, :alt]
|
|
36
|
+
@header = nil
|
|
37
|
+
@groups = ->(records) { [[Date.today, records]] }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
module Refinery
|
|
2
|
+
module Admin
|
|
3
|
+
|
|
4
|
+
# Refinery::Admin::GroupPresenter
|
|
5
|
+
#
|
|
6
|
+
# This class represents a presenter for organizing and displaying
|
|
7
|
+
# groups with associated metadata in a structured format.
|
|
8
|
+
#
|
|
9
|
+
# The presenter utilizes several helper modules for enhanced
|
|
10
|
+
# functionality and template rendering support.
|
|
11
|
+
#
|
|
12
|
+
# == Includes:
|
|
13
|
+
# * `Refinery::Admin::ImagesHelper` - Provides image-related functionality.
|
|
14
|
+
# * `ActionView::Helpers::TagHelper` - Used to create HTML-like tags dynamically.
|
|
15
|
+
#
|
|
16
|
+
# == Attributes:
|
|
17
|
+
# * `context` [Object] - Represents the context within which the presenter operates.
|
|
18
|
+
# * `groups` [Object] - Holds a collection of groups to be managed.
|
|
19
|
+
# * `group_classes` [Array] - Provides a list of CSS class names applied to the group tag.
|
|
20
|
+
# * `group_header` [Proc] - Callable object (e.g., lambda) to determine the header for each group.
|
|
21
|
+
# * `group_headers` [Boolean] - Controls whether group headers are displayed.
|
|
22
|
+
# * `group_tag` [Symbol] - Defines the tag used to wrap groups, e.g., `:ul`.
|
|
23
|
+
# * `group_wrapper` [Proc] - Customizable wrapper for rendering group collections.
|
|
24
|
+
# * `header` [Proc] - Callable object to format the header for individual groups.
|
|
25
|
+
# * `header_tag` [Symbol] - Specifies the tag for rendering headers, e.g., `:h3`.
|
|
26
|
+
# * `identity_keys` [Object] - Additional attribute for handling unique identity keys.
|
|
27
|
+
#
|
|
28
|
+
# == Public Instance Methods:
|
|
29
|
+
# - `initialize(context)`
|
|
30
|
+
# Initializes a new instance of the presenter within a given context,
|
|
31
|
+
# setting default values for various attributes like headers and tags.
|
|
32
|
+
#
|
|
33
|
+
# - `group_wrapper(&block)`
|
|
34
|
+
# Wraps the rendering of groups using a specified tag.
|
|
35
|
+
# This is customizable via the `group_tag` and `group_classes` attributes.
|
|
36
|
+
# A block must be passed to render the inner contents.
|
|
37
|
+
#
|
|
38
|
+
# - `group_header(date)`
|
|
39
|
+
# Constructs a header for individual groups based on a provided date.
|
|
40
|
+
# The format of the header is defined by the `header` callable and
|
|
41
|
+
# displayed using the specified `header_tag`.
|
|
42
|
+
class GroupPresenter
|
|
43
|
+
include Refinery::Admin::ImagesHelper
|
|
44
|
+
include ActionView::Helpers::TagHelper
|
|
45
|
+
|
|
46
|
+
attr_accessor :context, :groups, :group_classes, :group_header, :group_headers, :group_tag, :group_wrapper,
|
|
47
|
+
:header, :header_tag, :identity_keys
|
|
48
|
+
|
|
49
|
+
def initialize(context)
|
|
50
|
+
@context = context
|
|
51
|
+
@group_headers = true
|
|
52
|
+
@group_tag = :ul
|
|
53
|
+
@group_classes = [:image_group]
|
|
54
|
+
@header_tag = :h3
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def group_wrapper(&block)
|
|
58
|
+
context.tag group_tag, class: group_classes do
|
|
59
|
+
yield block
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def group_header(date)
|
|
64
|
+
tag.send(header_tag, header.call(date), class: :group_header)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
module Refinery
|
|
2
|
+
module Admin
|
|
3
|
+
|
|
4
|
+
# Refinery::Admin::ImagePresenter
|
|
5
|
+
#
|
|
6
|
+
# This class represents a presenter for managing and displaying image data
|
|
7
|
+
# in the Refinery admin interface. It provides methods to format image-related
|
|
8
|
+
# data for display and to generate necessary HTML components for interacting
|
|
9
|
+
# with images in the admin UI.
|
|
10
|
+
#
|
|
11
|
+
# === Includes
|
|
12
|
+
# - ActionView::RecordIdentifier: Provides methods for DOM ID generation for records.
|
|
13
|
+
# - ActionView::Helpers::UrlHelper: Allows generation of URLs and links.
|
|
14
|
+
# - ActionView::Helpers::TagHelper: Provides methods for generating HTML tags.
|
|
15
|
+
# - ActionView::Context: Allows rendering within the correct context.
|
|
16
|
+
# - Refinery::TranslationHelper: Adds support for translation-related helper methods.
|
|
17
|
+
# - Refinery::Admin::ImagesHelper: Includes specific helper methods for working with images.
|
|
18
|
+
# - Refinery::ActionHelper: Provides additional action-based helper methods.
|
|
19
|
+
#
|
|
20
|
+
# === Attributes
|
|
21
|
+
# - `image` [Reader]: The image object being presented.
|
|
22
|
+
# - `context` [Reader]: Context of the current view, often required for generating paths and URLs.
|
|
23
|
+
# - `index_keys` [Reader]: Used to specify the attributes displayed in the index table for images.
|
|
24
|
+
# - `i18n_scope` [Reader]: Specifies the internationalization scope for localization of text.
|
|
25
|
+
# - `title` [Writer]: Sets the title for the image.
|
|
26
|
+
# - `alt` [Writer]: Sets the alt text for the image.
|
|
27
|
+
# - `filename` [Writer]: Sets the filename for the image.
|
|
28
|
+
# - `translations` [Writer]: Stores translations for the image fields.
|
|
29
|
+
# - `edit_attributes` [Writer]: Stores attributes to be used for editing the image.
|
|
30
|
+
# - `delete_attributes` [Writer]: Stores attributes to be used for deleting the image.
|
|
31
|
+
# - `preview_attributes` [Writer]: Stores attributes for image preview options.
|
|
32
|
+
#
|
|
33
|
+
# === Constants
|
|
34
|
+
# - `IndexEntry`: Defines a structure to hold index entry data, including the image ID,
|
|
35
|
+
# edit link, text elements, locales, and actionable items.
|
|
36
|
+
#
|
|
37
|
+
# === Instance Methods
|
|
38
|
+
#
|
|
39
|
+
# - `initialize(image, context, scope = nil)`:
|
|
40
|
+
# Constructor that initializes the ImagePresenter with the given image object, view context,
|
|
41
|
+
# and optional internationalization scope.
|
|
42
|
+
#
|
|
43
|
+
# - `index_entry(index_keys)`:
|
|
44
|
+
# Generates an index entry for the image, including its ID, edit link, text elements,
|
|
45
|
+
# and actions. Accepts an array of keys for specifying index fields.
|
|
46
|
+
# These keys differ between the grid_view and list_view, and other views could be added
|
|
47
|
+
#
|
|
48
|
+
# - `link_to_edit(edit_key)`:
|
|
49
|
+
# Creates a link to edit the image, using the given key for determining the "text" of the link.
|
|
50
|
+
#
|
|
51
|
+
# - `text_elements(keys)`:
|
|
52
|
+
# Generates text elements for display based on the provided keys, wrapping them in HTML spans.
|
|
53
|
+
#
|
|
54
|
+
# - `thumbnail`:
|
|
55
|
+
# Returns the thumbnail for the image, including specific attributes such as its
|
|
56
|
+
# URL, description (alt) and title
|
|
57
|
+
class ImagePresenter < Refinery::BasePresenter
|
|
58
|
+
include ActionView::RecordIdentifier
|
|
59
|
+
include ActionView::Helpers::UrlHelper
|
|
60
|
+
include ActionView::Helpers::TagHelper
|
|
61
|
+
include ActionView::Context
|
|
62
|
+
|
|
63
|
+
include Refinery::TranslationHelper
|
|
64
|
+
include Refinery::Admin::ImagesHelper
|
|
65
|
+
include Refinery::ActionHelper
|
|
66
|
+
|
|
67
|
+
attr_reader :image, :context, :index_keys, :i18n_scope
|
|
68
|
+
attr_writer :title, :alt, :filename, :translations, :edit_attributes, :delete_attributes, :preview_attributes
|
|
69
|
+
delegate_missing_to :image
|
|
70
|
+
delegate :t, to: :context
|
|
71
|
+
|
|
72
|
+
IndexEntry = Struct.new('ImageEntry', :id, :edit_link, :text_elements, :locales, :actions)
|
|
73
|
+
|
|
74
|
+
def initialize(image, context, scope = nil)
|
|
75
|
+
super(image)
|
|
76
|
+
@image = image
|
|
77
|
+
@context = context
|
|
78
|
+
@i18n_scope = scope || 'refinery.admin.images'
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def index_entry(index_keys)
|
|
82
|
+
edit_key, *text_keys = index_keys
|
|
83
|
+
IndexEntry.new(
|
|
84
|
+
id: image.id,
|
|
85
|
+
edit_link: link_to_edit(index_keys[0]),
|
|
86
|
+
text_elements: text_elements(index_keys[1..]),
|
|
87
|
+
actions: tag.span( image_actions, class: :actions)
|
|
88
|
+
)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def link_to_edit(edit_key)
|
|
92
|
+
link_to(self.send(edit_key),
|
|
93
|
+
context.edit_admin_image_path(image),
|
|
94
|
+
{ title: ::I18n.t('.edit', title: image.title, scope: i18n_scope), class: :edit_link})
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def text_elements(keys)
|
|
98
|
+
keys.reduce(ActiveSupport::SafeBuffer.new) do |buffer, key|
|
|
99
|
+
buffer << tag.span(self.send(key), title: ::I18n.t(key, scope: i18n_scope), class: key)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def thumbnail
|
|
104
|
+
tag.img src: image.thumbnail(geometry: Refinery::Images.admin_image_sizes[:grid], strip: true).url(only_path: true),
|
|
105
|
+
alt: image.alt, title: image.title, class: :thumbnail
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def title
|
|
109
|
+
translated_field(image, :title)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def alt
|
|
113
|
+
alt_text = translated_field(@image, :alt)
|
|
114
|
+
alt_text unless alt_text === translated_field(image, :title)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def filename
|
|
118
|
+
image.image_name
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def image_actions
|
|
122
|
+
[*edit_actions, delete_action, preview_action].reduce(ActiveSupport::SafeBuffer.new) do |buffer, action|
|
|
123
|
+
buffer << action
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def edit_actions
|
|
128
|
+
translated_locales = locales_with_translated_field(image, :image_title)
|
|
129
|
+
edit_in_locales(context.edit_admin_image_path(image), translated_locales)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def preview_action(options = {})
|
|
133
|
+
action_icon(:preview, image.url, ::I18n.t('.view_live_html', scope: i18n_scope),
|
|
134
|
+
options: options)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def delete_action(options = {})
|
|
138
|
+
action_icon(:delete, context.admin_image_path(image),
|
|
139
|
+
::I18n.t('.delete', scope: i18n_scope),
|
|
140
|
+
data: { confirm: ::I18n.t('message', scope: 'refinery.admin.delete', title: image.title) },
|
|
141
|
+
**options )
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Refinery
|
|
2
|
+
module Admin
|
|
3
|
+
class ListPresenter < GroupPresenter
|
|
4
|
+
include Refinery::Admin::ImagesHelper
|
|
5
|
+
include ActionView::Helpers::TagHelper
|
|
6
|
+
|
|
7
|
+
# Initialize the presenter with a context, a lambda for headers, and a lambda for groups.
|
|
8
|
+
#
|
|
9
|
+
# @param context [Object] An object that provides the necessary methods for grouping and rendering.
|
|
10
|
+
# @param header [Proc] Callable for formatting group headers.
|
|
11
|
+
# @param groups [Proc] Callable for grouping records.
|
|
12
|
+
def initialize(context,
|
|
13
|
+
header: ->(date) { localized(date) },
|
|
14
|
+
groups: ->(records) { context.group_by_date(records, :updated_at) })
|
|
15
|
+
super(context)
|
|
16
|
+
@identity_keys = [:title, :filename, :alt]
|
|
17
|
+
@group_headers = true
|
|
18
|
+
@header = header
|
|
19
|
+
@groups = groups
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<%= content_tag :li, id: "crop_#{crop.id}" do %>
|
|
2
|
+
<%= image_fu crop, '255x255', class: 'brown_border' %>
|
|
3
|
+
<%= action_icon :delete, refinery.admin_image_crop_path(crop), t('delete', scope: 'refinery.admin.images'),
|
|
4
|
+
class: 'confirm-delete',
|
|
5
|
+
data: { confirm: t('message', scope: 'refinery.admin.delete', title: t('.delete_crop', title: crop.parent.title, id: crop.id) ) },
|
|
6
|
+
remote: true %>
|
|
7
|
+
<% end %>
|
|
@@ -2,25 +2,49 @@
|
|
|
2
2
|
<%= render '/refinery/admin/search', :url => refinery.insert_admin_images_path(params.to_unsafe_h.dup.except('image')) %>
|
|
3
3
|
<input type="hidden" name="selected_image" id="selected_image" />
|
|
4
4
|
<div id="existing_image_area_content" class="clearfix">
|
|
5
|
-
<% if @images.any? %>
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
<%
|
|
19
|
-
|
|
20
|
-
|
|
5
|
+
<% if @images.any? %>
|
|
6
|
+
<ul class="clearfix">
|
|
7
|
+
<% @images.each do |image| -%>
|
|
8
|
+
<%= content_tag :li, class: ('selected' if @image_id == image.id) do %>
|
|
9
|
+
<%= image_fu(image, '106x106#c',
|
|
10
|
+
alt: image.title,
|
|
11
|
+
title: image.title,
|
|
12
|
+
id: dom_id(image),
|
|
13
|
+
data: {
|
|
14
|
+
id: image.id,
|
|
15
|
+
**thumbnail_urls(image)[:data]
|
|
16
|
+
})-%>
|
|
17
|
+
|
|
18
|
+
<% if image.crops.any? %>
|
|
19
|
+
<div class="crops">
|
|
20
|
+
<ul class="clearfix">
|
|
21
|
+
<% image.crops.each do |crop| %>
|
|
22
|
+
<%= content_tag :li, class: ('selected' if @image_id == image.id) do %>
|
|
23
|
+
<%= image_fu(crop, '106x106>',
|
|
24
|
+
alt: crop.parent.alt,
|
|
25
|
+
title: crop.parent.title,
|
|
26
|
+
id: "image_#{crop.id}",
|
|
27
|
+
data: {
|
|
28
|
+
id: crop.id,
|
|
29
|
+
**thumbnail_urls(crop)[:data]
|
|
30
|
+
}) %>
|
|
31
|
+
<% end %>
|
|
32
|
+
<% end %>
|
|
33
|
+
</ul>
|
|
34
|
+
</div>
|
|
35
|
+
<% end %>
|
|
36
|
+
<% end %>
|
|
37
|
+
<% end %>
|
|
38
|
+
</ul>
|
|
39
|
+
<% elsif searching? %>
|
|
40
|
+
<%= t('no_results', :scope => 'refinery.admin.search') %>
|
|
41
|
+
<% end %>
|
|
21
42
|
</div>
|
|
43
|
+
|
|
22
44
|
<%= will_paginate @images, :params => params.to_unsafe_h.dup.merge(:action => "insert") %>
|
|
23
45
|
|
|
46
|
+
<div id="existing_image_area_crops" class="clearfix"></div>
|
|
47
|
+
|
|
24
48
|
<% unless @app_dialog or @images.empty? %>
|
|
25
49
|
<div id="existing_image_size_area" class="clearfix">
|
|
26
50
|
<input type="hidden" name="selected_image_size" id="selected_image_size" />
|
|
@@ -30,22 +54,23 @@
|
|
|
30
54
|
<%= t('.resize_image') %>
|
|
31
55
|
</label>
|
|
32
56
|
</p>
|
|
33
|
-
|
|
57
|
+
|
|
58
|
+
<%= select :resize, nil, nil, { prompt: t('.select_resize') }, { id: 'resize'} do %>
|
|
34
59
|
<%
|
|
35
60
|
Refinery::Images.user_image_sizes.sort_by { |key, geometry| geometry.to_i }.each_with_index do |(size, pixels), index|
|
|
36
61
|
safe_pixels = pixels.to_s.gsub(/[<>=]/, '')
|
|
37
62
|
# (parndt): ' selected' if size.to_s == 'medium' is not very generic, but I
|
|
38
63
|
# can't think of a decent way of making it so for even sets (e.g. 2,4,6,8,etc image sizes).
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
:
|
|
43
|
-
:
|
|
44
|
-
:
|
|
45
|
-
:
|
|
46
|
-
|
|
47
|
-
<% end
|
|
48
|
-
|
|
64
|
+
%>
|
|
65
|
+
<%= content_tag :option,
|
|
66
|
+
"#{size} image (#{safe_pixels})",
|
|
67
|
+
value: size.to_s.parameterize,
|
|
68
|
+
id: "image_dialog_size_#{index}",
|
|
69
|
+
data: { geometry: pixels, size: size.to_s.parameterize },
|
|
70
|
+
selected: (true if size.to_s == 'medium')
|
|
71
|
+
%>
|
|
72
|
+
<% end %>
|
|
73
|
+
<% end %>
|
|
49
74
|
</div>
|
|
50
75
|
<% end %>
|
|
51
76
|
|