alchemy_cms 3.3.3 → 3.4.0.rc1
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/.travis.yml +1 -1
- data/CHANGELOG.md +42 -4
- data/README.md +7 -3
- data/alchemy_cms.gemspec +1 -0
- data/app/assets/javascripts/alchemy/{alchemy.js → admin.js} +1 -2
- data/app/assets/javascripts/alchemy/alchemy.datepicker.js.coffee +28 -25
- data/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee +1 -0
- data/app/assets/javascripts/alchemy/alchemy.i18n.js.coffee +7 -1
- data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +1 -1
- data/app/assets/javascripts/alchemy/alchemy.sitemap.js.coffee +26 -0
- data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +56 -1
- data/app/assets/stylesheets/alchemy/_variables.scss +1 -0
- data/app/assets/stylesheets/alchemy/admin.scss +2 -1
- data/app/assets/stylesheets/alchemy/archive.scss +7 -0
- data/app/assets/stylesheets/alchemy/base.scss +0 -42
- data/app/assets/stylesheets/alchemy/buttons.scss +2 -1
- data/app/assets/stylesheets/alchemy/form_fields.scss +9 -0
- data/app/assets/stylesheets/alchemy/forms.scss +36 -10
- data/app/assets/stylesheets/alchemy/frame.scss +12 -1
- data/app/assets/stylesheets/alchemy/icons.scss +1 -1
- data/app/assets/stylesheets/alchemy/jquery-ui.scss +0 -260
- data/app/assets/stylesheets/alchemy/jquery.datetimepicker.scss +507 -0
- data/app/assets/stylesheets/alchemy/lists.scss +62 -0
- data/app/assets/stylesheets/alchemy/selects.scss +9 -2
- data/app/assets/stylesheets/alchemy/sitemap.scss +28 -51
- data/app/assets/stylesheets/alchemy/toolbar.scss +0 -2
- data/app/controllers/alchemy/admin/attachments_controller.rb +4 -6
- data/app/controllers/alchemy/admin/base_controller.rb +2 -2
- data/app/controllers/alchemy/admin/dashboard_controller.rb +2 -2
- data/app/controllers/alchemy/admin/languages_controller.rb +5 -0
- data/app/controllers/alchemy/admin/pages_controller.rb +14 -5
- data/app/controllers/alchemy/admin/resources_controller.rb +17 -1
- data/app/controllers/alchemy/base_controller.rb +1 -0
- data/app/controllers/alchemy/messages_controller.rb +1 -1
- data/app/controllers/alchemy/pages_controller.rb +16 -26
- data/app/controllers/alchemy/pictures_controller.rb +23 -10
- data/app/controllers/concerns/alchemy/page_redirects.rb +7 -7
- data/app/helpers/alchemy/admin/base_helper.rb +22 -19
- data/app/helpers/alchemy/admin/essences_helper.rb +26 -11
- data/app/helpers/alchemy/admin/pages_helper.rb +2 -1
- data/app/helpers/alchemy/essences_helper.rb +0 -35
- data/app/helpers/alchemy/url_helper.rb +1 -1
- data/app/mailers/alchemy/base_mailer.rb +18 -0
- data/app/mailers/alchemy/{messages.rb → messages_mailer.rb} +1 -1
- data/app/models/alchemy/attachment.rb +9 -0
- data/app/models/alchemy/cell.rb +1 -1
- data/app/models/alchemy/essence_picture.rb +4 -1
- data/app/models/alchemy/essence_picture_view.rb +68 -0
- data/app/models/alchemy/language.rb +8 -10
- data/app/models/alchemy/language/code.rb +4 -1
- data/app/models/alchemy/page.rb +69 -26
- data/app/models/alchemy/page/page_natures.rb +22 -0
- data/app/models/alchemy/page/page_scopes.rb +20 -6
- data/app/models/alchemy/picture.rb +37 -4
- data/app/models/alchemy/site.rb +8 -0
- data/app/serializers/alchemy/page_tree_serializer.rb +1 -1
- data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +9 -6
- data/app/views/alchemy/admin/attachments/_file_to_assign.html.erb +11 -9
- data/app/views/alchemy/admin/attachments/_filter_bar.html.erb +32 -0
- data/app/views/alchemy/admin/attachments/_overlay_file_list.html.erb +14 -2
- data/app/views/alchemy/admin/attachments/index.html.erb +10 -9
- data/app/views/alchemy/admin/dashboard/_locked_pages.html.erb +20 -9
- data/app/views/alchemy/admin/dashboard/_recent_pages.html.erb +11 -1
- data/app/views/alchemy/admin/languages/_form.html.erb +1 -0
- data/app/views/alchemy/admin/languages/index.html.erb +7 -8
- data/app/views/alchemy/admin/layoutpages/_layoutpage.html.erb +1 -1
- data/app/views/alchemy/admin/layoutpages/index.html.erb +2 -2
- data/app/views/alchemy/admin/pages/_current_page.html.erb +4 -0
- data/app/views/alchemy/admin/pages/_form.html.erb +16 -1
- data/app/views/alchemy/admin/pages/_locked_page.html.erb +2 -12
- data/app/views/alchemy/admin/pages/_page.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_page_for_links.html.erb +2 -2
- data/app/views/alchemy/admin/pages/_page_status.html.erb +23 -11
- data/app/views/alchemy/admin/pages/edit.html.erb +2 -1
- data/app/views/alchemy/admin/pages/index.html.erb +2 -2
- data/app/views/alchemy/admin/partials/_language_tree_select.html.erb +3 -0
- data/app/views/alchemy/admin/partials/_site_select.html.erb +9 -0
- data/app/views/alchemy/admin/pictures/_picture.html.erb +6 -1
- data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +2 -1
- data/app/views/alchemy/admin/pictures/show.html.erb +1 -1
- data/app/views/alchemy/admin/resources/_filter_bar.html.erb +31 -0
- data/app/views/alchemy/admin/resources/_form.html.erb +6 -0
- data/app/views/alchemy/admin/resources/_tag_list.html.erb +16 -0
- data/app/views/alchemy/admin/resources/index.html.erb +13 -1
- data/app/views/alchemy/essences/_essence_file_view.html.erb +2 -5
- data/app/views/alchemy/essences/_essence_picture_view.html.erb +5 -3
- data/app/views/alchemy/{messages → messages_mailer}/contact_form_mail.de.text.erb +0 -0
- data/app/views/alchemy/{messages → messages_mailer}/contact_form_mail.en.text.erb +0 -0
- data/app/views/alchemy/{messages → messages_mailer}/contact_form_mail.es.text.erb +0 -0
- data/app/views/alchemy/{messages → messages_mailer}/new.html.erb +0 -0
- data/app/views/layouts/alchemy/admin.html.erb +3 -8
- data/config/alchemy/config.yml +4 -3
- data/config/initializers/assets.rb +2 -2
- data/config/initializers/dragonfly.rb +3 -0
- data/config/initializers/mime_types.rb +1 -0
- data/config/locales/alchemy.de.yml +10 -2
- data/config/locales/alchemy.en.yml +6 -2
- data/config/locales/alchemy.es.yml +6 -3
- data/config/locales/alchemy.fr.yml +6 -2
- data/config/locales/alchemy.it.yml +937 -0
- data/config/locales/alchemy.nl.yml +6 -2
- data/config/locales/alchemy.ru.yml +3 -2
- data/config/locales/simple_form.it.yml +25 -0
- data/db/migrate/20160108174834_add_timebased_publishing_columns_to_pages.rb +32 -0
- data/db/migrate/20160422195310_add_image_file_format_to_alchemy_pictures.rb +21 -0
- data/db/migrate/20160617224938_change_alchemy_pages_locked_to_locked_at.rb +22 -0
- data/lib/alchemy/ability_helper.rb +23 -0
- data/lib/alchemy/configuration_methods.rb +2 -2
- data/lib/alchemy/controller_actions.rb +4 -33
- data/lib/alchemy/engine.rb +1 -0
- data/lib/alchemy/resource.rb +30 -13
- data/lib/alchemy/resources_helper.rb +17 -0
- data/lib/alchemy/test_support/factories/page_factory.rb +7 -2
- data/lib/alchemy/upgrader.rb +1 -0
- data/lib/alchemy/upgrader/tasks/install_asset_manifests.rb +15 -0
- data/lib/alchemy/upgrader/three_point_four.rb +16 -0
- data/lib/alchemy/version.rb +1 -1
- data/lib/rails/generators/alchemy/elements/elements_generator.rb +8 -7
- data/lib/rails/generators/alchemy/essence/essence_generator.rb +2 -6
- data/lib/rails/generators/alchemy/install/files/all.css +11 -0
- data/lib/rails/generators/alchemy/install/files/all.js +11 -0
- data/lib/rails/generators/alchemy/install/files/{alchemy.elements.css.scss → article.scss} +0 -0
- data/lib/rails/generators/alchemy/install/install_generator.rb +20 -19
- data/lib/rails/generators/alchemy/module/module_generator.rb +3 -5
- data/lib/rails/generators/alchemy/page_layouts/page_layouts_generator.rb +7 -6
- data/lib/rails/generators/alchemy/site_layouts/site_layouts_generator.rb +7 -6
- data/vendor/assets/javascripts/date-formatter.js +161 -0
- data/vendor/assets/javascripts/jquery_plugins/jquery.datetimepicker.full.min.js +2 -0
- data/vendor/assets/javascripts/tinymce/langs/it.js +219 -0
- metadata +48 -13
- data/app/assets/javascripts/alchemy/alchemy.custom.js +0 -1
- data/app/assets/stylesheets/alchemy/custom.scss +0 -1
|
@@ -68,7 +68,7 @@ module Alchemy
|
|
|
68
68
|
@page = @element.page
|
|
69
69
|
@root_page = @page.get_language_root
|
|
70
70
|
if @message.valid?
|
|
71
|
-
|
|
71
|
+
MessagesMailer.contact_form_mail(@message, mail_to, mail_from, subject).deliver
|
|
72
72
|
redirect_to_success_page
|
|
73
73
|
else
|
|
74
74
|
render template: 'alchemy/pages/show'
|
|
@@ -26,6 +26,8 @@ module Alchemy
|
|
|
26
26
|
if: :run_on_page_layout_callbacks?,
|
|
27
27
|
only: [:index, :show]
|
|
28
28
|
|
|
29
|
+
before_action :set_expiration_headers, only: [:index, :show], if: -> { @page }
|
|
30
|
+
|
|
29
31
|
rescue_from ActionController::UnknownFormat, with: :page_not_found!
|
|
30
32
|
|
|
31
33
|
# == The index action gets invoked if one requests '/' or '/:locale'
|
|
@@ -35,7 +37,7 @@ module Alchemy
|
|
|
35
37
|
# Loads the current language root page. The current language is either loaded via :locale
|
|
36
38
|
# parameter or, if that's missing, the default language is used.
|
|
37
39
|
#
|
|
38
|
-
# If this page is not published then it
|
|
40
|
+
# If this page is not published then it redirects to the first published descendant it finds.
|
|
39
41
|
#
|
|
40
42
|
# If no public page can be found it renders a 404 error.
|
|
41
43
|
#
|
|
@@ -45,8 +47,7 @@ module Alchemy
|
|
|
45
47
|
raise "Remove deprecated `redirect_index` configuration!" if Alchemy.version == "4.0.0.rc1"
|
|
46
48
|
redirect_permanently_to page_redirect_url
|
|
47
49
|
else
|
|
48
|
-
|
|
49
|
-
render_page if render_fresh_page?
|
|
50
|
+
show
|
|
50
51
|
end
|
|
51
52
|
end
|
|
52
53
|
|
|
@@ -84,13 +85,13 @@ module Alchemy
|
|
|
84
85
|
#
|
|
85
86
|
# Loads the current public language root page.
|
|
86
87
|
#
|
|
87
|
-
# If the root page is not public it
|
|
88
|
+
# If the root page is not public it redirects to the first published child.
|
|
88
89
|
# This can be configured via +redirect_to_public_child+ [default: true]
|
|
89
90
|
#
|
|
90
91
|
# If no index page and no admin users are present we show the "Welcome to Alchemy" page.
|
|
91
92
|
#
|
|
92
93
|
def load_index_page
|
|
93
|
-
@page ||=
|
|
94
|
+
@page ||= Language.current_root_page
|
|
94
95
|
render template: 'alchemy/welcome', layout: false if signup_required?
|
|
95
96
|
end
|
|
96
97
|
|
|
@@ -110,26 +111,6 @@ module Alchemy
|
|
|
110
111
|
)
|
|
111
112
|
end
|
|
112
113
|
|
|
113
|
-
# Returns the current language root page, if it's published.
|
|
114
|
-
#
|
|
115
|
-
# Otherwise it returns nil.
|
|
116
|
-
#
|
|
117
|
-
def public_root_page
|
|
118
|
-
@root_page ||= Language.current_root_page
|
|
119
|
-
@root_page if @root_page && @root_page.public?
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
# Returns the first public child of the current language root page.
|
|
123
|
-
#
|
|
124
|
-
# If +redirect_to_public_child+ is configured to +false+ it returns +nil+.
|
|
125
|
-
#
|
|
126
|
-
def first_public_child
|
|
127
|
-
if Alchemy::Config.get(:redirect_to_public_child)
|
|
128
|
-
return unless @root_page
|
|
129
|
-
@root_page.descendants.published.first
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
|
|
133
114
|
# Redirects to given url with 301 status
|
|
134
115
|
def redirect_permanently_to(url)
|
|
135
116
|
redirect_to url, status: :moved_permanently
|
|
@@ -170,6 +151,14 @@ module Alchemy
|
|
|
170
151
|
end
|
|
171
152
|
end
|
|
172
153
|
|
|
154
|
+
def set_expiration_headers
|
|
155
|
+
if @page.cache_page?
|
|
156
|
+
expires_in @page.expiration_time, public: !@page.restricted
|
|
157
|
+
else
|
|
158
|
+
expires_now
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
173
162
|
def set_root_page
|
|
174
163
|
@root_page ||= Language.current_root_page
|
|
175
164
|
end
|
|
@@ -200,7 +189,8 @@ module Alchemy
|
|
|
200
189
|
def render_fresh_page?
|
|
201
190
|
!@page.cache_page? || stale?(etag: page_etag,
|
|
202
191
|
last_modified: @page.published_at,
|
|
203
|
-
public: !@page.restricted
|
|
192
|
+
public: !@page.restricted,
|
|
193
|
+
template: 'pages/show')
|
|
204
194
|
end
|
|
205
195
|
|
|
206
196
|
def page_not_found!
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module Alchemy
|
|
2
2
|
class PicturesController < Alchemy::BaseController
|
|
3
|
-
ALLOWED_IMAGE_TYPES = %w(png jpeg gif)
|
|
3
|
+
ALLOWED_IMAGE_TYPES = %w(png jpeg gif svg)
|
|
4
4
|
|
|
5
5
|
caches_page :show, :thumbnail, :zoom
|
|
6
6
|
|
|
@@ -25,7 +25,7 @@ module Alchemy
|
|
|
25
25
|
@size = params[:size]
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
respond_to { |format| send_image(processed_image, format) }
|
|
28
|
+
respond_to { |format| send_image(processed_image, format, flatten: true) }
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def zoom
|
|
@@ -45,20 +45,29 @@ module Alchemy
|
|
|
45
45
|
false
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
-
def send_image(image, format)
|
|
48
|
+
def send_image(image, format, opts = {})
|
|
49
49
|
request.session_options[:skip] = true
|
|
50
50
|
ALLOWED_IMAGE_TYPES.each do |type|
|
|
51
|
+
# Flatten animated gifs, only if converting to a different format.
|
|
52
|
+
# Can be overwritten via +options[:flatten]+.
|
|
53
|
+
options = {
|
|
54
|
+
flatten: type != "gif" && image.ext == 'gif'
|
|
55
|
+
}.merge(opts)
|
|
56
|
+
|
|
51
57
|
format.send(type) do
|
|
52
|
-
|
|
58
|
+
encoding_options = []
|
|
53
59
|
if type == 'jpeg'
|
|
54
60
|
quality = params[:quality] || Config.get(:output_image_jpg_quality)
|
|
55
|
-
|
|
61
|
+
encoding_options << "-quality #{quality}"
|
|
62
|
+
end
|
|
63
|
+
if options[:flatten]
|
|
64
|
+
encoding_options << "-flatten"
|
|
56
65
|
end
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
66
|
+
if @picture.has_convertible_format?
|
|
67
|
+
render text: image.encode(type, encoding_options.join(' ')).data
|
|
68
|
+
else
|
|
69
|
+
render text: image.data
|
|
60
70
|
end
|
|
61
|
-
render text: image.encode(type, options.join(' ')).data
|
|
62
71
|
end
|
|
63
72
|
end
|
|
64
73
|
end
|
|
@@ -70,7 +79,7 @@ module Alchemy
|
|
|
70
79
|
if @image.nil?
|
|
71
80
|
raise MissingImageFileError, "Missing image file for #{@picture.inspect}"
|
|
72
81
|
end
|
|
73
|
-
if
|
|
82
|
+
if resizable?
|
|
74
83
|
if params[:crop_size].present? && params[:crop_from].present? || params[:crop].present?
|
|
75
84
|
@picture.crop(@size, params[:crop_from], params[:crop_size], @upsample)
|
|
76
85
|
else
|
|
@@ -80,5 +89,9 @@ module Alchemy
|
|
|
80
89
|
@image
|
|
81
90
|
end
|
|
82
91
|
end
|
|
92
|
+
|
|
93
|
+
def resizable?
|
|
94
|
+
@size.present? && @picture.has_convertible_format?
|
|
95
|
+
end
|
|
83
96
|
end
|
|
84
97
|
end
|
|
@@ -36,10 +36,14 @@ module Alchemy
|
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def public_child_redirect_url
|
|
39
|
-
return
|
|
39
|
+
return if @page.public?
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
if configuration(:redirect_to_public_child)
|
|
42
|
+
@page = @page.descendants.published.not_restricted.first
|
|
43
|
+
@page ? page_redirect_url : page_not_found!
|
|
44
|
+
else
|
|
45
|
+
page_not_found!
|
|
46
|
+
end
|
|
43
47
|
end
|
|
44
48
|
|
|
45
49
|
def controller_and_action_url
|
|
@@ -65,9 +69,5 @@ module Alchemy
|
|
|
65
69
|
def locale_prefix_missing?
|
|
66
70
|
multi_language? && params[:locale].blank? && !default_locale?
|
|
67
71
|
end
|
|
68
|
-
|
|
69
|
-
def redirect_to_public_child?
|
|
70
|
-
configuration(:redirect_to_public_child) && !@page.public?
|
|
71
|
-
end
|
|
72
72
|
end
|
|
73
73
|
end
|
|
@@ -332,38 +332,41 @@ module Alchemy
|
|
|
332
332
|
|
|
333
333
|
# Renders a textfield ready to display a datepicker
|
|
334
334
|
#
|
|
335
|
-
# Uses a HTML5
|
|
335
|
+
# Uses a HTML5 +<input type="date">+ field.
|
|
336
|
+
# A Javascript observer converts this into a fancy Datepicker.
|
|
337
|
+
# If you pass +'datetime'+ as +:type+ the datepicker will also have a Time select.
|
|
336
338
|
#
|
|
337
|
-
#
|
|
339
|
+
# The date value gets localized via +I18n.l+. The format on Time and Date is +datepicker+
|
|
340
|
+
# or +datetimepicker+, if you pass another +type+.
|
|
341
|
+
#
|
|
342
|
+
# === Date Example
|
|
338
343
|
#
|
|
339
344
|
# <%= alchemy_datepicker(@person, :birthday) %>
|
|
340
345
|
#
|
|
346
|
+
# === Datetime Example
|
|
347
|
+
#
|
|
348
|
+
# <%= alchemy_datepicker(@page, :public_on, type: 'datetime') %>
|
|
349
|
+
#
|
|
341
350
|
# @param [ActiveModel::Base] object
|
|
342
351
|
# An instance of a model
|
|
343
352
|
# @param [String or Symbol] method
|
|
344
353
|
# The attribute method to be called for the date value
|
|
345
354
|
#
|
|
346
|
-
# @option html_options [String] :type (
|
|
355
|
+
# @option html_options [String] :type (date)
|
|
347
356
|
# The type of text field
|
|
348
|
-
# @option html_options [String] :class (
|
|
357
|
+
# @option html_options [String] :class (type)
|
|
349
358
|
# CSS classes of the input field
|
|
350
|
-
# @option html_options [String] :value (
|
|
351
|
-
# The value the input displays
|
|
359
|
+
# @option html_options [String] :value (value of method on object)
|
|
360
|
+
# The value the input displays. If you pass a String its parsed with +Time.parse+
|
|
352
361
|
#
|
|
353
362
|
def alchemy_datepicker(object, method, html_options = {})
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
end
|
|
362
|
-
text_field object.class.name.underscore.to_sym, method.to_sym, html_options.merge({
|
|
363
|
-
type: 'date',
|
|
364
|
-
class: 'date',
|
|
365
|
-
value: value
|
|
366
|
-
})
|
|
363
|
+
type = html_options.delete(:type) || 'date'
|
|
364
|
+
date = html_options.delete(:value) || object.send(method.to_sym).presence
|
|
365
|
+
date = Time.zone.parse(date) if date.is_a?(String)
|
|
366
|
+
value = date ? l(date, format: "#{type}picker".to_sym) : nil
|
|
367
|
+
|
|
368
|
+
text_field object.class.name.demodulize.underscore.to_sym,
|
|
369
|
+
method.to_sym, {type: type, class: type, value: value}.merge(html_options)
|
|
367
370
|
end
|
|
368
371
|
|
|
369
372
|
# Merges the params-hash with the given hash
|
|
@@ -57,25 +57,40 @@ module Alchemy
|
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
def essence_picture_thumbnail(content, options)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
ingredient = content.ingredient
|
|
61
|
+
essence = content.essence
|
|
62
|
+
return if ingredient.blank?
|
|
63
|
+
|
|
64
|
+
crop = !(essence.crop_size.blank? && essence.crop_from.blank?) ||
|
|
65
|
+
(
|
|
66
|
+
content.settings_value(:crop, options) == true ||
|
|
67
|
+
content.settings_value(:crop, options) == "true"
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
size = if essence.render_size.blank?
|
|
71
|
+
content.settings_value(:size, options)
|
|
72
|
+
else
|
|
73
|
+
essence.render_size
|
|
74
|
+
end
|
|
75
|
+
|
|
63
76
|
image_options = {
|
|
64
|
-
size:
|
|
65
|
-
crop_from:
|
|
66
|
-
crop_size:
|
|
77
|
+
size: essence.thumbnail_size(size, crop),
|
|
78
|
+
crop_from: essence.crop_from.blank? ? nil : essence.crop_from,
|
|
79
|
+
crop_size: essence.crop_size.blank? ? nil : essence.crop_size,
|
|
67
80
|
crop: crop ? 'crop' : nil,
|
|
68
81
|
upsample: content.settings_value(:upsample, options)
|
|
69
82
|
}
|
|
83
|
+
|
|
70
84
|
image_tag(
|
|
71
85
|
alchemy.thumbnail_path({
|
|
72
|
-
id:
|
|
73
|
-
name:
|
|
74
|
-
sh:
|
|
86
|
+
id: ingredient.id,
|
|
87
|
+
name: ingredient.urlname,
|
|
88
|
+
sh: ingredient.security_token(image_options),
|
|
89
|
+
format: ingredient.image_file_format
|
|
75
90
|
}.merge(image_options)),
|
|
76
|
-
alt:
|
|
91
|
+
alt: ingredient.name,
|
|
77
92
|
class: 'img_paddingtop',
|
|
78
|
-
title: Alchemy.t(:image_name) + ": #{
|
|
93
|
+
title: Alchemy.t(:image_name) + ": #{ingredient.name}"
|
|
79
94
|
)
|
|
80
95
|
end
|
|
81
96
|
|
|
@@ -22,7 +22,8 @@ module Alchemy
|
|
|
22
22
|
def combined_page_status(page)
|
|
23
23
|
page.status.map do |state, _value|
|
|
24
24
|
next if state == :locked
|
|
25
|
-
|
|
25
|
+
css_class = page.send("#{state}?") ? "page_status #{state}" : "page_status not_#{state}"
|
|
26
|
+
val = content_tag(:span, '', class: css_class)
|
|
26
27
|
val + page.status_title(state)
|
|
27
28
|
end.delete_if(&:blank?).join("<br>").html_safe
|
|
28
29
|
end
|
|
@@ -86,40 +86,5 @@ module Alchemy
|
|
|
86
86
|
def render_essence_view(content, options = {}, html_options = {})
|
|
87
87
|
render_essence(content, :view, {for_view: options}, html_options)
|
|
88
88
|
end
|
|
89
|
-
|
|
90
|
-
# Renders a essence picture
|
|
91
|
-
#
|
|
92
|
-
def render_essence_picture_view(content, options, html_options)
|
|
93
|
-
options = {
|
|
94
|
-
show_caption: true,
|
|
95
|
-
disable_link: false
|
|
96
|
-
}.update(content.settings).update(options)
|
|
97
|
-
return if content.ingredient.blank?
|
|
98
|
-
if content.essence.caption.present? && options[:show_caption]
|
|
99
|
-
caption = content_tag(:figcaption, content.essence.caption, id: "#{dom_id(content.ingredient)}_caption", class: "image_caption")
|
|
100
|
-
end
|
|
101
|
-
img_tag = image_tag(
|
|
102
|
-
content.essence.picture_url(options), {
|
|
103
|
-
alt: (content.essence.alt_tag.blank? ? nil : content.essence.alt_tag),
|
|
104
|
-
title: (content.essence.title.blank? ? nil : content.essence.title),
|
|
105
|
-
class: (caption || content.essence.css_class.blank? ? nil : content.essence.css_class)
|
|
106
|
-
}.merge(caption ? {} : html_options)
|
|
107
|
-
)
|
|
108
|
-
output = caption ? img_tag + caption : img_tag
|
|
109
|
-
if content.essence.link.present? && !options[:disable_link]
|
|
110
|
-
output = link_to(url_for(content.essence.link), {
|
|
111
|
-
title: content.essence.link_title.blank? ? nil : content.essence.link_title,
|
|
112
|
-
target: (content.essence.link_target == "blank" ? "_blank" : nil),
|
|
113
|
-
'data-link-target' => content.essence.link_target.blank? ? nil : content.essence.link_target
|
|
114
|
-
}) do
|
|
115
|
-
output
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
if caption
|
|
119
|
-
content_tag(:figure, output, {class: content.essence.css_class.blank? ? nil : content.essence.css_class}.merge(html_options))
|
|
120
|
-
else
|
|
121
|
-
output
|
|
122
|
-
end
|
|
123
|
-
end
|
|
124
89
|
end
|
|
125
90
|
end
|
|
@@ -43,7 +43,7 @@ module Alchemy
|
|
|
43
43
|
url_params = {
|
|
44
44
|
id: picture.id,
|
|
45
45
|
name: picture.urlname,
|
|
46
|
-
format:
|
|
46
|
+
format: picture.default_render_format,
|
|
47
47
|
sh: picture.security_token(optional_params)
|
|
48
48
|
}
|
|
49
49
|
url_params.update(optional_params.update(crop: optional_params[:crop] ? 'crop' : nil))
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Alchemy
|
|
2
|
+
begin
|
|
3
|
+
base_class = Object.const_get('::ApplicationMailer')
|
|
4
|
+
rescue NameError
|
|
5
|
+
base_class = ActionMailer::Base
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# The +BaseMailer+ is the class all Alchemy mailers inherit from.
|
|
9
|
+
#
|
|
10
|
+
# Itself inherits from +ApplicationMailer+ when it is defined, or
|
|
11
|
+
# as a fallback from +ActionMailer::Base+.
|
|
12
|
+
#
|
|
13
|
+
# +ApplicationMailer+ is the Rails standard for registering helpers and
|
|
14
|
+
# setting the default layout. It is only generated though, when you
|
|
15
|
+
# +rails generate+ a mailer.
|
|
16
|
+
#
|
|
17
|
+
class BaseMailer < base_class; end
|
|
18
|
+
end
|
|
@@ -39,6 +39,13 @@ module Alchemy
|
|
|
39
39
|
def allowed_filetypes
|
|
40
40
|
Config.get(:uploader).fetch('allowed_filetypes', {}).fetch('alchemy/attachments', [])
|
|
41
41
|
end
|
|
42
|
+
|
|
43
|
+
def file_types_for_select
|
|
44
|
+
file_types = Alchemy::Attachment.pluck(:file_mime_type).uniq.map do |type|
|
|
45
|
+
[Alchemy.t(type, scope: 'mime_types'), type]
|
|
46
|
+
end
|
|
47
|
+
file_types.sort_by(&:first)
|
|
48
|
+
end
|
|
42
49
|
end
|
|
43
50
|
|
|
44
51
|
validates_presence_of :file
|
|
@@ -56,6 +63,8 @@ module Alchemy
|
|
|
56
63
|
|
|
57
64
|
after_update :touch_contents
|
|
58
65
|
|
|
66
|
+
scope :with_file_type, ->(file_type) { where(file_mime_type: file_type) }
|
|
67
|
+
|
|
59
68
|
# Instance methods
|
|
60
69
|
|
|
61
70
|
def to_jq_upload
|
data/app/models/alchemy/cell.rb
CHANGED
|
@@ -28,7 +28,7 @@ module Alchemy
|
|
|
28
28
|
belongs_to :page
|
|
29
29
|
validates_uniqueness_of :name, scope: 'page_id'
|
|
30
30
|
validates_format_of :name, with: /\A[a-z0-9_-]+\z/
|
|
31
|
-
has_many :elements, -> {
|
|
31
|
+
has_many :elements, -> { order(:position) }, dependent: :destroy
|
|
32
32
|
|
|
33
33
|
class << self
|
|
34
34
|
def definitions
|
|
@@ -126,11 +126,13 @@ module Alchemy
|
|
|
126
126
|
#
|
|
127
127
|
def picture_params(options = {})
|
|
128
128
|
return {} if picture.nil?
|
|
129
|
+
|
|
129
130
|
params = {
|
|
130
131
|
id: picture.id,
|
|
131
132
|
name: picture.urlname,
|
|
132
|
-
format:
|
|
133
|
+
format: picture.default_render_format
|
|
133
134
|
}.merge(options)
|
|
135
|
+
|
|
134
136
|
if options[:crop] && crop_from.present? && crop_size.present?
|
|
135
137
|
params = {
|
|
136
138
|
crop: true,
|
|
@@ -138,6 +140,7 @@ module Alchemy
|
|
|
138
140
|
crop_size: crop_size
|
|
139
141
|
}.merge(params)
|
|
140
142
|
end
|
|
143
|
+
|
|
141
144
|
params = clean_picture_params(params)
|
|
142
145
|
params.merge(sh: picture.security_token(params))
|
|
143
146
|
end
|