alchemy_cms 3.4.2 → 3.5.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/.codeclimate.yml +9 -3
- data/.teatro.yml +1 -0
- data/.travis.yml +14 -17
- data/CHANGELOG.md +44 -6
- data/Gemfile +7 -4
- data/README.md +60 -10
- data/Rakefile +1 -1
- data/alchemy_cms.gemspec +5 -8
- data/app/assets/javascripts/alchemy/admin.js +2 -0
- data/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee +1 -0
- data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +1 -0
- data/app/assets/javascripts/alchemy/alchemy.hotkeys.js.coffee +1 -1
- data/app/assets/javascripts/alchemy/alchemy.initializer.js.coffee +9 -7
- data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +1 -0
- data/app/assets/javascripts/alchemy/alchemy.preview_window.js.coffee +11 -7
- data/app/assets/javascripts/alchemy/alchemy.sitemap.js.coffee +1 -1
- data/app/assets/javascripts/alchemy/alchemy.tinymce.js.coffee +8 -3
- data/app/assets/javascripts/alchemy/alchemy.tooltips.coffee +10 -0
- data/app/assets/javascripts/alchemy/alchemy.uploader.js.coffee +104 -73
- data/app/assets/stylesheets/alchemy/_defaults.scss +1 -4
- data/app/assets/stylesheets/alchemy/_extends.scss +13 -35
- data/app/assets/stylesheets/alchemy/_mixins.scss +82 -18
- data/app/assets/stylesheets/alchemy/_variables.scss +21 -8
- data/app/assets/stylesheets/alchemy/admin.scss +4 -0
- data/app/assets/stylesheets/alchemy/archive.scss +8 -12
- data/app/assets/stylesheets/alchemy/attachments.scss +39 -0
- data/app/assets/stylesheets/alchemy/base.scss +26 -15
- data/app/assets/stylesheets/alchemy/buttons.scss +59 -31
- data/app/assets/stylesheets/alchemy/dashboard.scss +3 -3
- data/app/assets/stylesheets/alchemy/dialogs.scss +10 -8
- data/app/assets/stylesheets/alchemy/elements.scss +65 -41
- data/app/assets/stylesheets/alchemy/errors.scss +7 -0
- data/app/assets/stylesheets/alchemy/flash.scss +1 -1
- data/app/assets/stylesheets/alchemy/form_fields.scss +0 -37
- data/app/assets/stylesheets/alchemy/forms.scss +18 -27
- data/app/assets/stylesheets/alchemy/frame.scss +104 -204
- data/app/assets/stylesheets/alchemy/hints.scss +62 -0
- data/app/assets/stylesheets/alchemy/icon-font.scss +2 -1
- data/app/assets/stylesheets/alchemy/icons.scss +9 -4
- data/app/assets/stylesheets/alchemy/image_library.scss +6 -6
- data/app/assets/stylesheets/alchemy/jquery-ui.scss +6 -4
- data/app/assets/stylesheets/alchemy/lists.scss +0 -1
- data/app/assets/stylesheets/alchemy/menubar.scss +3 -4
- data/app/assets/stylesheets/alchemy/modules.scss +0 -6
- data/app/assets/stylesheets/alchemy/navigation.scss +242 -0
- data/app/assets/stylesheets/alchemy/pagination.scss +3 -3
- data/app/assets/stylesheets/alchemy/print.scss +1 -0
- data/app/assets/stylesheets/alchemy/resource_info.scss +45 -0
- data/app/assets/stylesheets/alchemy/search.scss +72 -1
- data/app/assets/stylesheets/alchemy/selects.scss +38 -44
- data/app/assets/stylesheets/alchemy/sitemap.scss +89 -79
- data/app/assets/stylesheets/alchemy/tables.scss +6 -10
- data/app/assets/stylesheets/alchemy/toolbar.scss +7 -36
- data/app/assets/stylesheets/alchemy/upload.scss +12 -3
- data/app/assets/stylesheets/tinymce/skins/alchemy/content.min.css.scss +6 -3
- data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce-small.svg +58 -170
- data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce-small.ttf +0 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce-small.woff +0 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce.svg +124 -148
- data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce.ttf +0 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce.woff +0 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/skin.min.css.scss +426 -144
- data/app/controllers/alchemy/admin/attachments_controller.rb +24 -16
- data/app/controllers/alchemy/admin/clipboard_controller.rb +1 -1
- data/app/controllers/alchemy/admin/essence_files_controller.rb +1 -1
- data/app/controllers/alchemy/admin/essence_pictures_controller.rb +9 -8
- data/app/controllers/alchemy/admin/layoutpages_controller.rb +1 -0
- data/app/controllers/alchemy/admin/pages_controller.rb +2 -2
- data/app/controllers/alchemy/admin/resources_controller.rb +2 -2
- data/app/controllers/alchemy/admin/tags_controller.rb +1 -1
- data/app/controllers/alchemy/api/pages_controller.rb +16 -0
- data/app/controllers/alchemy/messages_controller.rb +1 -1
- data/app/controllers/concerns/alchemy/admin/uploader_responses.rb +2 -2
- data/app/helpers/alchemy/admin/attachments_helper.rb +11 -0
- data/app/helpers/alchemy/admin/base_helper.rb +37 -4
- data/app/helpers/alchemy/admin/contents_helper.rb +11 -4
- data/app/helpers/alchemy/admin/elements_helper.rb +0 -19
- data/app/helpers/alchemy/admin/essences_helper.rb +7 -30
- data/app/helpers/alchemy/admin/navigation_helper.rb +13 -51
- data/app/helpers/alchemy/admin/pages_helper.rb +21 -16
- data/app/helpers/alchemy/admin/pictures_helper.rb +9 -0
- data/app/helpers/alchemy/deprecated_pages_helper.rb +54 -0
- data/app/helpers/alchemy/essences_helper.rb +1 -1
- data/app/helpers/alchemy/pages_helper.rb +8 -109
- data/app/helpers/alchemy/url_helper.rb +8 -13
- data/app/models/alchemy/attachment.rb +7 -4
- data/app/models/alchemy/cell.rb +2 -2
- data/app/models/alchemy/content.rb +2 -2
- data/app/models/alchemy/content/factory.rb +12 -9
- data/app/models/alchemy/element.rb +6 -3
- data/app/models/alchemy/essence_file.rb +1 -1
- data/app/models/alchemy/essence_picture.rb +37 -47
- data/app/models/alchemy/essence_picture_view.rb +8 -1
- data/app/models/alchemy/folded_page.rb +3 -2
- data/app/models/alchemy/legacy_page_url.rb +3 -3
- data/app/models/alchemy/page.rb +50 -5
- data/app/models/alchemy/page/fixed_attributes.rb +63 -0
- data/app/models/alchemy/page/page_elements.rb +10 -7
- data/app/models/alchemy/page/page_natures.rb +19 -0
- data/app/models/alchemy/picture.rb +1 -0
- data/app/models/alchemy/picture/transformations.rb +1 -1
- data/app/models/alchemy/picture/url.rb +82 -0
- data/app/serializers/alchemy/page_tree_serializer.rb +29 -8
- data/app/views/alchemy/_edit_mode.html.erb +2 -0
- data/app/views/alchemy/_menubar.html.erb +1 -1
- data/app/views/alchemy/_preview_mode_code.html.erb +6 -0
- data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +1 -1
- data/app/views/alchemy/admin/attachments/_attachment.html.erb +25 -5
- data/app/views/alchemy/admin/attachments/_replace_button.html.erb +26 -0
- data/app/views/alchemy/admin/attachments/index.html.erb +1 -1
- data/app/views/alchemy/admin/attachments/show.html.erb +52 -0
- data/app/views/alchemy/admin/elements/_element_header.html.erb +6 -3
- data/app/views/alchemy/admin/elements/create.js.erb +0 -2
- data/app/views/alchemy/admin/elements/trash.js.erb +0 -1
- data/app/views/alchemy/admin/elements/update.js.erb +0 -2
- data/app/views/alchemy/admin/essence_pictures/crop.html.erb +1 -4
- data/app/views/alchemy/admin/essence_pictures/edit.html.erb +1 -1
- data/app/views/alchemy/admin/languages/index.html.erb +1 -0
- data/app/views/alchemy/admin/layoutpages/_layoutpage.html.erb +26 -27
- data/app/views/alchemy/admin/layoutpages/edit.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_form.html.erb +13 -40
- data/app/views/alchemy/admin/pages/_locked_page.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_page.html.erb +119 -61
- data/app/views/alchemy/admin/pages/_page_for_links.html.erb +4 -2
- data/app/views/alchemy/admin/pages/_page_infos.html.erb +12 -12
- data/app/views/alchemy/admin/pages/_page_status.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_publication_fields.html.erb +35 -0
- data/app/views/alchemy/admin/pages/edit.html.erb +13 -2
- data/app/views/alchemy/admin/pages/index.html.erb +3 -8
- data/app/views/alchemy/admin/pages/info.html.erb +15 -2
- data/app/views/alchemy/admin/pages/sort.js.erb +1 -1
- data/app/views/alchemy/admin/pages/update.js.erb +1 -14
- data/app/views/alchemy/admin/partials/_main_navigation_entry.html.erb +12 -8
- data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +4 -4
- data/app/views/alchemy/admin/partials/_search_form.html.erb +1 -1
- data/app/views/alchemy/admin/partials/_sub_navigation.html.erb +9 -6
- data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +1 -1
- data/app/views/alchemy/admin/pictures/_picture.html.erb +1 -6
- data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +1 -6
- data/app/views/alchemy/admin/pictures/index.html.erb +1 -1
- data/app/views/alchemy/admin/pictures/show.html.erb +1 -6
- data/app/views/alchemy/admin/uploader/_button.html.erb +4 -4
- data/app/views/alchemy/base/500.html.erb +15 -1
- data/app/views/alchemy/essences/_essence_boolean_editor.html.erb +13 -15
- data/app/views/alchemy/essences/_essence_boolean_view.html.erb +1 -3
- data/app/views/alchemy/essences/_essence_date_editor.html.erb +0 -2
- data/app/views/alchemy/essences/_essence_date_view.html.erb +0 -2
- data/app/views/alchemy/essences/_essence_file_editor.html.erb +2 -7
- data/app/views/alchemy/essences/_essence_file_view.html.erb +1 -3
- data/app/views/alchemy/essences/_essence_html_editor.html.erb +0 -2
- data/app/views/alchemy/essences/_essence_html_view.html.erb +1 -3
- data/app/views/alchemy/essences/_essence_link_editor.html.erb +0 -2
- data/app/views/alchemy/essences/_essence_link_view.html.erb +0 -2
- data/app/views/alchemy/essences/_essence_picture_editor.html.erb +47 -49
- data/app/views/alchemy/essences/_essence_picture_view.html.erb +1 -3
- data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +0 -2
- data/app/views/alchemy/essences/_essence_richtext_view.html.erb +1 -3
- data/app/views/alchemy/essences/_essence_select_editor.html.erb +27 -29
- data/app/views/alchemy/essences/_essence_select_view.html.erb +1 -3
- data/app/views/alchemy/essences/_essence_text_editor.html.erb +17 -19
- data/app/views/alchemy/essences/_essence_text_view.html.erb +0 -2
- data/app/views/alchemy/pages/_meta_data.html.erb +9 -0
- data/app/views/layouts/alchemy/admin.html.erb +9 -11
- data/bin/alchemy +1 -2
- data/config/alchemy/config.yml +1 -1
- data/config/alchemy/modules.yml +0 -16
- data/config/initializers/dragonfly.rb +0 -18
- data/config/initializers/mini_profiler.rb +6 -0
- data/config/locales/alchemy.de.yml +9 -1
- data/config/locales/alchemy.en.yml +7 -1
- data/config/locales/alchemy.es.yml +6 -0
- data/config/locales/alchemy.fr.yml +2 -0
- data/config/locales/alchemy.it.yml +3 -1
- data/config/locales/alchemy.nl.yml +2 -0
- data/config/locales/alchemy.ru.yml +2 -0
- data/config/routes.rb +3 -8
- data/db/migrate/20160912223112_add_index_to_alchemy_pages_rgt.rb +9 -0
- data/db/migrate/20160927205604_add_foreign_key_indices_and_null_constraints.rb +20 -0
- data/db/migrate/20160928080104_add_foreign_keys.rb +27 -0
- data/lib/alchemy/admin/locale.rb +4 -3
- data/lib/alchemy/engine.rb +2 -4
- data/lib/alchemy/errors.rb +9 -2
- data/lib/alchemy/forms/builder.rb +8 -0
- data/lib/alchemy/modules.rb +20 -19
- data/lib/alchemy/permissions.rb +15 -4
- data/lib/alchemy/resources_helper.rb +4 -2
- data/lib/alchemy/sass_support.rb +9 -0
- data/lib/alchemy/seeder.rb +89 -1
- data/lib/alchemy/test_support/essence_shared_examples.rb +2 -0
- data/lib/alchemy/test_support/factories/attachment_factory.rb +1 -1
- data/lib/alchemy/test_support/factories/content_factory.rb +1 -0
- data/lib/alchemy/test_support/factories/element_factory.rb +1 -0
- data/lib/alchemy/test_support/factories/picture_factory.rb +1 -1
- data/lib/alchemy/test_support/fixtures/image.png +0 -0
- data/lib/alchemy/tinymce.rb +2 -6
- data/lib/alchemy/upgrader.rb +4 -55
- data/lib/alchemy/upgrader/tasks/install_dragonfly_config.rb +14 -0
- data/lib/alchemy/upgrader/three_point_five.rb +32 -0
- data/lib/alchemy/upgrader/three_point_four.rb +2 -8
- data/lib/alchemy/upgrader/three_point_one.rb +30 -30
- data/lib/alchemy/upgrader/three_point_three.rb +31 -31
- data/lib/alchemy/upgrader/three_point_two.rb +25 -25
- data/lib/alchemy/upgrader/three_point_zero.rb +59 -59
- data/lib/alchemy/version.rb +1 -1
- data/lib/rails/generators/alchemy/elements/templates/view.html.erb +1 -1
- data/lib/rails/generators/alchemy/elements/templates/view.html.haml +1 -1
- data/lib/rails/generators/alchemy/elements/templates/view.html.slim +1 -1
- data/lib/rails/generators/alchemy/essence/templates/editor.html.erb +1 -3
- data/lib/rails/generators/alchemy/install/files/_article_view.html.erb +1 -1
- data/lib/rails/generators/alchemy/install/files/application.html.erb +3 -4
- data/lib/rails/generators/alchemy/install/install_generator.rb +4 -0
- data/lib/rails/generators/alchemy/install/templates/dragonfly.rb.tt +35 -0
- data/lib/rails/generators/alchemy/module/module_generator.rb +1 -1
- data/lib/tasks/alchemy/db.rake +6 -0
- data/lib/tasks/alchemy/tidy.rake +85 -0
- data/lib/tasks/alchemy/upgrade.rake +165 -16
- data/vendor/assets/javascripts/clipboard.min.js +7 -0
- data/vendor/assets/javascripts/fileupload/jquery.fileupload-process.js +4 -4
- data/vendor/assets/javascripts/fileupload/jquery.fileupload-validate.js +2 -2
- data/vendor/assets/javascripts/fileupload/jquery.fileupload.js +29 -14
- data/vendor/assets/javascripts/fileupload/jquery.iframe-transport.js +2 -2
- data/vendor/assets/javascripts/tinymce/langs/es.js +2 -2
- data/vendor/assets/javascripts/tinymce/langs/fr.js +1 -1
- data/vendor/assets/javascripts/tinymce/langs/it.js +1 -1
- data/vendor/assets/javascripts/tinymce/langs/nl.js +3 -3
- data/vendor/assets/javascripts/tinymce/tinymce.min.js +15 -12
- metadata +44 -88
- data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/readme.md +0 -1
- data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce-small.eot +0 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce.eot +0 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/img/wline.gif +0 -0
- data/app/assets/stylesheets/tinymce/skins/alchemy/skin.ie7.min.css +0 -1
- data/app/controllers/alchemy/pictures_controller.rb +0 -97
- data/app/views/alchemy/admin/elements/_refresh_editor.js.erb +0 -8
- data/vendor/assets/javascripts/tinymce/plugins/anchor/plugin.min.js +0 -1
- data/vendor/assets/javascripts/tinymce/plugins/autoresize/plugin.min.js +0 -1
- data/vendor/assets/javascripts/tinymce/plugins/charmap/plugin.min.js +0 -1
- data/vendor/assets/javascripts/tinymce/plugins/code/plugin.min.js +0 -1
- data/vendor/assets/javascripts/tinymce/plugins/directionality/plugin.min.js +0 -1
- data/vendor/assets/javascripts/tinymce/plugins/fullscreen/plugin.min.js +0 -1
- data/vendor/assets/javascripts/tinymce/plugins/hr/plugin.min.js +0 -1
- data/vendor/assets/javascripts/tinymce/plugins/link/plugin.min.js +0 -1
- data/vendor/assets/javascripts/tinymce/plugins/paste/plugin.min.js +0 -1
- data/vendor/assets/javascripts/tinymce/plugins/tabfocus/plugin.min.js +0 -1
- data/vendor/assets/javascripts/tinymce/plugins/table/plugin.min.js +0 -1
- data/vendor/assets/javascripts/tinymce/themes/modern/theme.min.js +0 -1
|
@@ -25,7 +25,7 @@ module Alchemy
|
|
|
25
25
|
class EssencePicture < ActiveRecord::Base
|
|
26
26
|
acts_as_essence ingredient_column: 'picture'
|
|
27
27
|
|
|
28
|
-
belongs_to :picture
|
|
28
|
+
belongs_to :picture, required: false
|
|
29
29
|
delegate :image_file_width, :image_file_height, :image_file, to: :picture
|
|
30
30
|
before_save :fix_crop_values
|
|
31
31
|
before_save :replace_newlines
|
|
@@ -56,7 +56,37 @@ module Alchemy
|
|
|
56
56
|
#
|
|
57
57
|
def picture_url(options = {})
|
|
58
58
|
return if picture.nil?
|
|
59
|
-
|
|
59
|
+
|
|
60
|
+
options = {
|
|
61
|
+
format: picture.default_render_format,
|
|
62
|
+
crop_from: crop_from,
|
|
63
|
+
crop_size: crop_size
|
|
64
|
+
}.merge(options)
|
|
65
|
+
|
|
66
|
+
picture.url(options)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Renders a thumbnail representation of the assigned image
|
|
70
|
+
#
|
|
71
|
+
# It takes cropping values into account, so it always represents the current
|
|
72
|
+
# image displayed in the frontend.
|
|
73
|
+
#
|
|
74
|
+
def thumbnail_url(options = {})
|
|
75
|
+
return if picture.nil?
|
|
76
|
+
|
|
77
|
+
crop = crop_values_present? || content.settings_value(:crop, options)
|
|
78
|
+
size = render_size || content.settings_value(:size, options)
|
|
79
|
+
|
|
80
|
+
options = {
|
|
81
|
+
size: thumbnail_size(size, crop),
|
|
82
|
+
crop: !!crop,
|
|
83
|
+
crop_from: crop_from.presence,
|
|
84
|
+
crop_size: crop_size.presence,
|
|
85
|
+
flatten: true,
|
|
86
|
+
format: picture.image_file_format
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
picture.url(options)
|
|
60
90
|
end
|
|
61
91
|
|
|
62
92
|
# The name of the picture used as preview text in element editor views.
|
|
@@ -88,11 +118,15 @@ module Alchemy
|
|
|
88
118
|
def allow_image_cropping?(options = {})
|
|
89
119
|
content && content.settings_value(:crop, options) && picture &&
|
|
90
120
|
picture.can_be_cropped_to(
|
|
91
|
-
content.settings_value(:
|
|
121
|
+
content.settings_value(:size, options),
|
|
92
122
|
content.settings_value(:upsample, options)
|
|
93
123
|
)
|
|
94
124
|
end
|
|
95
125
|
|
|
126
|
+
def crop_values_present?
|
|
127
|
+
crop_from.present? && crop_size.present?
|
|
128
|
+
end
|
|
129
|
+
|
|
96
130
|
private
|
|
97
131
|
|
|
98
132
|
def fix_crop_values
|
|
@@ -114,49 +148,5 @@ module Alchemy
|
|
|
114
148
|
return nil if caption.nil?
|
|
115
149
|
caption.gsub!(/(\r\n|\r|\n)/, "<br/>")
|
|
116
150
|
end
|
|
117
|
-
|
|
118
|
-
# Returns Alchemy's url helpers.
|
|
119
|
-
def routes
|
|
120
|
-
@routes ||= Engine.routes.url_helpers
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
# Params for picture_path and picture_url methods
|
|
124
|
-
#
|
|
125
|
-
# @see +picture_url+ for options
|
|
126
|
-
#
|
|
127
|
-
def picture_params(options = {})
|
|
128
|
-
return {} if picture.nil?
|
|
129
|
-
|
|
130
|
-
params = {
|
|
131
|
-
id: picture.id,
|
|
132
|
-
name: picture.urlname,
|
|
133
|
-
format: picture.default_render_format
|
|
134
|
-
}.merge(options)
|
|
135
|
-
|
|
136
|
-
if options[:crop] && crop_from.present? && crop_size.present?
|
|
137
|
-
params = {
|
|
138
|
-
crop: true,
|
|
139
|
-
crop_from: crop_from,
|
|
140
|
-
crop_size: crop_size
|
|
141
|
-
}.merge(params)
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
params = clean_picture_params(params)
|
|
145
|
-
params.merge(sh: picture.security_token(params))
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
# Ensures correct and clean params for show picture path.
|
|
149
|
-
#
|
|
150
|
-
def clean_picture_params(params)
|
|
151
|
-
if params[:crop] == true
|
|
152
|
-
params[:crop] = 'crop'
|
|
153
|
-
end
|
|
154
|
-
if params[:image_size]
|
|
155
|
-
params[:size] = params.delete(:image_size)
|
|
156
|
-
end
|
|
157
|
-
secure_attributes = PictureAttributes::SECURE_ATTRIBUTES.dup
|
|
158
|
-
secure_attributes += %w(name format sh)
|
|
159
|
-
params.delete_if { |k, v| !secure_attributes.include?(k.to_s) || v.blank? }
|
|
160
|
-
end
|
|
161
151
|
end
|
|
162
152
|
end
|
|
@@ -15,6 +15,13 @@ module Alchemy
|
|
|
15
15
|
def initialize(content, options = {}, html_options = {})
|
|
16
16
|
@content = content
|
|
17
17
|
@options = DEFAULT_OPTIONS.merge(content.settings).merge(options)
|
|
18
|
+
if @options[:image_size].present?
|
|
19
|
+
ActiveSupport::Deprecation.warn(
|
|
20
|
+
"Passing `image_size` to EssencePicture is deprecated. Please use `size` instead.",
|
|
21
|
+
caller.unshift
|
|
22
|
+
)
|
|
23
|
+
@options[:size] = @options.delete(:image_size)
|
|
24
|
+
end
|
|
18
25
|
@html_options = html_options
|
|
19
26
|
@essence = content.essence
|
|
20
27
|
@picture = essence.picture
|
|
@@ -49,7 +56,7 @@ module Alchemy
|
|
|
49
56
|
|
|
50
57
|
def img_tag
|
|
51
58
|
@_img_tag ||= image_tag(
|
|
52
|
-
essence.picture_url(options), {
|
|
59
|
+
essence.picture_url(options.except(*DEFAULT_OPTIONS.keys)), {
|
|
53
60
|
alt: essence.alt_tag.presence,
|
|
54
61
|
title: essence.title.presence,
|
|
55
62
|
class: caption ? nil : essence.css_class.presence
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
|
|
11
11
|
module Alchemy
|
|
12
12
|
class FoldedPage < ActiveRecord::Base
|
|
13
|
-
belongs_to :page
|
|
14
|
-
belongs_to :user,
|
|
13
|
+
belongs_to :page, required: true
|
|
14
|
+
belongs_to :user, required: true,
|
|
15
|
+
class_name: Alchemy.user_class_name
|
|
15
16
|
end
|
|
16
17
|
end
|
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
#
|
|
11
11
|
|
|
12
12
|
class Alchemy::LegacyPageUrl < ActiveRecord::Base
|
|
13
|
-
belongs_to :page,
|
|
13
|
+
belongs_to :page,
|
|
14
|
+
class_name: 'Alchemy::Page',
|
|
15
|
+
required: true
|
|
14
16
|
|
|
15
|
-
validates :page_id,
|
|
16
|
-
presence: true
|
|
17
17
|
validates :urlname,
|
|
18
18
|
presence: true,
|
|
19
19
|
format: {with: /\A[:\.\w\-+_\/\?&%;=]*\z/}
|
data/app/models/alchemy/page.rb
CHANGED
|
@@ -87,7 +87,7 @@ module Alchemy
|
|
|
87
87
|
|
|
88
88
|
stampable stamper_class_name: Alchemy.user_class_name
|
|
89
89
|
|
|
90
|
-
belongs_to :language
|
|
90
|
+
belongs_to :language, required: false
|
|
91
91
|
|
|
92
92
|
has_one :site, through: :language
|
|
93
93
|
has_many :site_languages, through: :site, source: :languages
|
|
@@ -115,9 +115,12 @@ module Alchemy
|
|
|
115
115
|
unless: :systempage?
|
|
116
116
|
|
|
117
117
|
before_save :set_published_at,
|
|
118
|
-
if: -> {
|
|
118
|
+
if: -> { public_on.present? && published_at.nil? },
|
|
119
119
|
unless: :systempage?
|
|
120
120
|
|
|
121
|
+
before_save :set_fixed_attributes,
|
|
122
|
+
if: -> { fixed_attributes.any? }
|
|
123
|
+
|
|
121
124
|
before_create :set_language_from_parent_or_default,
|
|
122
125
|
if: -> { language_id.blank? },
|
|
123
126
|
unless: :systempage?
|
|
@@ -336,7 +339,7 @@ module Alchemy
|
|
|
336
339
|
def fold!(user_id, status)
|
|
337
340
|
folded_page = folded_pages.find_or_create_by(user_id: user_id)
|
|
338
341
|
folded_page.folded = status
|
|
339
|
-
folded_page.save
|
|
342
|
+
folded_page.save!
|
|
340
343
|
end
|
|
341
344
|
|
|
342
345
|
def set_restrictions_to_child_pages
|
|
@@ -382,8 +385,8 @@ module Alchemy
|
|
|
382
385
|
current_time = Time.current
|
|
383
386
|
update_columns(
|
|
384
387
|
published_at: current_time,
|
|
385
|
-
public_on: current_time,
|
|
386
|
-
public_until: nil
|
|
388
|
+
public_on: already_public_for?(current_time) ? public_on : current_time,
|
|
389
|
+
public_until: still_public_for?(current_time) ? public_until : nil
|
|
387
390
|
)
|
|
388
391
|
end
|
|
389
392
|
|
|
@@ -406,8 +409,50 @@ module Alchemy
|
|
|
406
409
|
update_columns(hash)
|
|
407
410
|
end
|
|
408
411
|
|
|
412
|
+
# Holds an instance of +FixedAttributes+
|
|
413
|
+
def fixed_attributes
|
|
414
|
+
@_fixed_attributes ||= Alchemy::Page::FixedAttributes.new(self)
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
# True if given attribute name is defined as fixed
|
|
418
|
+
def attribute_fixed?(name)
|
|
419
|
+
fixed_attributes.fixed?(name)
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
# Checks the current page's list of editors, if defined.
|
|
423
|
+
#
|
|
424
|
+
# This allows us to pass in a user and see if any of their roles are enable
|
|
425
|
+
# them to make edits
|
|
426
|
+
#
|
|
427
|
+
def editable_by?(user)
|
|
428
|
+
return true unless has_limited_editors?
|
|
429
|
+
(editor_roles & user.alchemy_roles).any?
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
# Returns the value of +public_on+ attribute
|
|
433
|
+
#
|
|
434
|
+
# If it's a fixed attribute then the fixed value is returned instead
|
|
435
|
+
#
|
|
436
|
+
def public_on
|
|
437
|
+
attribute_fixed?(:public_on) ? fixed_attributes[:public_on] : self[:public_on]
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
# Returns the value of +public_until+ attribute
|
|
441
|
+
#
|
|
442
|
+
# If it's a fixed attribute then the fixed value is returned instead
|
|
443
|
+
#
|
|
444
|
+
def public_until
|
|
445
|
+
attribute_fixed?(:public_until) ? fixed_attributes[:public_until] : self[:public_until]
|
|
446
|
+
end
|
|
447
|
+
|
|
409
448
|
private
|
|
410
449
|
|
|
450
|
+
def set_fixed_attributes
|
|
451
|
+
fixed_attributes.all.each do |attribute, value|
|
|
452
|
+
send("#{attribute}=", value)
|
|
453
|
+
end
|
|
454
|
+
end
|
|
455
|
+
|
|
411
456
|
# Returns the next or previous page on the same level or nil.
|
|
412
457
|
#
|
|
413
458
|
# @param [String]
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
module Alchemy
|
|
2
|
+
# = Fixed page attributes
|
|
3
|
+
#
|
|
4
|
+
# Fixed page attributes are not allowed to be changed by the user.
|
|
5
|
+
#
|
|
6
|
+
# Define fixed page attributes on the page layout definition of a page.
|
|
7
|
+
#
|
|
8
|
+
# == Example
|
|
9
|
+
#
|
|
10
|
+
# # page_layout.yml
|
|
11
|
+
# - name: Index
|
|
12
|
+
# unique: true
|
|
13
|
+
# fixed_attributes:
|
|
14
|
+
# - public_on: nil
|
|
15
|
+
# - public_until: nil
|
|
16
|
+
# - visible: false
|
|
17
|
+
#
|
|
18
|
+
class Page::FixedAttributes
|
|
19
|
+
attr_reader :page
|
|
20
|
+
|
|
21
|
+
def initialize(page)
|
|
22
|
+
@page = page
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# All fixed attributes defined on page
|
|
26
|
+
#
|
|
27
|
+
# Aliased as +#all+
|
|
28
|
+
#
|
|
29
|
+
# @return Hash
|
|
30
|
+
#
|
|
31
|
+
def attributes
|
|
32
|
+
@_attributes ||= page.definition.fetch('fixed_attributes', {}).symbolize_keys
|
|
33
|
+
end
|
|
34
|
+
alias_method :all, :attributes
|
|
35
|
+
|
|
36
|
+
# True if fixed attributes are defined on page
|
|
37
|
+
#
|
|
38
|
+
# Aliased as +#present?+
|
|
39
|
+
#
|
|
40
|
+
# @return Boolean
|
|
41
|
+
#
|
|
42
|
+
def any?
|
|
43
|
+
attributes.present?
|
|
44
|
+
end
|
|
45
|
+
alias_method :present?, :any?
|
|
46
|
+
|
|
47
|
+
# True if given attribute name is defined on page
|
|
48
|
+
#
|
|
49
|
+
# @return Boolean
|
|
50
|
+
#
|
|
51
|
+
def fixed?(name)
|
|
52
|
+
return false if name.nil?
|
|
53
|
+
attributes.key?(name.to_sym)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Returns the attribute by key
|
|
57
|
+
#
|
|
58
|
+
def [](name)
|
|
59
|
+
return nil if name.nil?
|
|
60
|
+
attributes[name.to_sym]
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -24,13 +24,6 @@ module Alchemy
|
|
|
24
24
|
after_create :autogenerate_elements, unless: -> { systempage? || do_not_autogenerate }
|
|
25
25
|
after_update :trash_not_allowed_elements!, if: :page_layout_changed?
|
|
26
26
|
after_update :autogenerate_elements, if: :page_layout_changed?
|
|
27
|
-
|
|
28
|
-
after_destroy do
|
|
29
|
-
elements.each do |element|
|
|
30
|
-
next if element.trashed?
|
|
31
|
-
element.destroy
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
27
|
end
|
|
35
28
|
|
|
36
29
|
module ClassMethods
|
|
@@ -150,6 +143,16 @@ module Alchemy
|
|
|
150
143
|
@_element_definitions ||= element_definitions_by_name(element_definition_names)
|
|
151
144
|
end
|
|
152
145
|
|
|
146
|
+
# All element definitions defined for page's page layout including nestable element definitions
|
|
147
|
+
#
|
|
148
|
+
def descendent_element_definitions
|
|
149
|
+
definitions = element_definitions_by_name(element_definition_names)
|
|
150
|
+
definitions.select { |d| d.key?('nestable_elements') }.each do |d|
|
|
151
|
+
definitions += element_definitions_by_name(d['nestable_elements'])
|
|
152
|
+
end
|
|
153
|
+
definitions.uniq { |d| d['name'] }
|
|
154
|
+
end
|
|
155
|
+
|
|
153
156
|
# All names of elements that are defined in the corresponding
|
|
154
157
|
# page and cell definition.
|
|
155
158
|
#
|
|
@@ -33,6 +33,25 @@ module Alchemy
|
|
|
33
33
|
definition["feed"]
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
+
# Returns an Array of Alchemy roles which are able to edit this template
|
|
37
|
+
#
|
|
38
|
+
# # config/alchemy/page_layouts.yml
|
|
39
|
+
# - name: contact
|
|
40
|
+
# editable_by:
|
|
41
|
+
# - freelancer
|
|
42
|
+
# - admin
|
|
43
|
+
#
|
|
44
|
+
# @returns Array
|
|
45
|
+
#
|
|
46
|
+
def has_limited_editors?
|
|
47
|
+
definition["editable_by"].present?
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def editor_roles
|
|
51
|
+
return unless has_limited_editors?
|
|
52
|
+
definition["editable_by"]
|
|
53
|
+
end
|
|
54
|
+
|
|
36
55
|
# Returns true or false if the pages definition for config/alchemy/page_layouts.yml contains redirects_to_external: true
|
|
37
56
|
def redirects_to_external?
|
|
38
57
|
!!definition["redirects_to_external"]
|
|
@@ -26,6 +26,7 @@ module Alchemy
|
|
|
26
26
|
include Alchemy::Touching
|
|
27
27
|
include Alchemy::Picture::Sweeping
|
|
28
28
|
include Alchemy::Picture::Transformations
|
|
29
|
+
include Alchemy::Picture::Url
|
|
29
30
|
|
|
30
31
|
has_many :essence_pictures, class_name: 'Alchemy::EssencePicture', foreign_key: 'picture_id'
|
|
31
32
|
has_many :contents, through: :essence_pictures
|
|
@@ -120,7 +120,7 @@ module Alchemy
|
|
|
120
120
|
# Returns true if the class we're included in has a meaningful render_size attribute
|
|
121
121
|
#
|
|
122
122
|
def render_size?
|
|
123
|
-
respond_to?(:render_size) &&
|
|
123
|
+
respond_to?(:render_size) && render_size.present?
|
|
124
124
|
end
|
|
125
125
|
|
|
126
126
|
# Returns true if the class we're included in has a meaningful crop_size attribute
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
module Alchemy
|
|
2
|
+
module Picture::Url
|
|
3
|
+
TRANSFORMATION_OPTIONS = [
|
|
4
|
+
:crop,
|
|
5
|
+
:crop_from,
|
|
6
|
+
:crop_size,
|
|
7
|
+
:flatten,
|
|
8
|
+
:format,
|
|
9
|
+
:quality,
|
|
10
|
+
:size,
|
|
11
|
+
:upsample
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
# Returns a path to picture for use inside a image_tag helper.
|
|
15
|
+
#
|
|
16
|
+
# Any additional options are passed to the url_helper, so you can add arguments to your url.
|
|
17
|
+
#
|
|
18
|
+
# Example:
|
|
19
|
+
#
|
|
20
|
+
# <%= image_tag picture.url(size: '320x200', format: 'png') %>
|
|
21
|
+
#
|
|
22
|
+
def url(options = {})
|
|
23
|
+
image = image_file
|
|
24
|
+
|
|
25
|
+
raise MissingImageFileError, "Missing image file for #{inspect}" if image.nil?
|
|
26
|
+
|
|
27
|
+
image = processed_image(image, options)
|
|
28
|
+
image = encoded_image(image, options)
|
|
29
|
+
|
|
30
|
+
image.url(options.except(*TRANSFORMATION_OPTIONS).merge(name: name))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
# Returns the processed image dependent of size and cropping parameters
|
|
36
|
+
def processed_image(image, options = {})
|
|
37
|
+
size = options[:size]
|
|
38
|
+
upsample = !!options[:upsample]
|
|
39
|
+
|
|
40
|
+
return image unless size.present? && has_convertible_format?
|
|
41
|
+
|
|
42
|
+
if options[:crop_size].present? && options[:crop_from].present? || options[:crop].present?
|
|
43
|
+
crop(size, options[:crop_from], options[:crop_size], upsample)
|
|
44
|
+
else
|
|
45
|
+
resize(size, upsample)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Returns the encoded image
|
|
50
|
+
#
|
|
51
|
+
# Flatten animated gifs, only if converting to a different format.
|
|
52
|
+
# Can be overwritten via +options[:flatten]+.
|
|
53
|
+
#
|
|
54
|
+
def encoded_image(image, options = {})
|
|
55
|
+
target_format = options[:format] || default_render_format
|
|
56
|
+
raise WrongImageFormatError if !target_format.in?(Alchemy::Picture.allowed_filetypes)
|
|
57
|
+
|
|
58
|
+
options = {
|
|
59
|
+
flatten: target_format != 'gif' && image_file_format == 'gif'
|
|
60
|
+
}.merge(options)
|
|
61
|
+
|
|
62
|
+
encoding_options = []
|
|
63
|
+
|
|
64
|
+
if target_format =~ /jpe?g/
|
|
65
|
+
quality = options[:quality] || Config.get(:output_image_jpg_quality)
|
|
66
|
+
encoding_options << "-quality #{quality}"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
if options[:flatten]
|
|
70
|
+
encoding_options << '-flatten'
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
convertion_needed = target_format != image_file_format || encoding_options.present?
|
|
74
|
+
|
|
75
|
+
if has_convertible_format? && convertion_needed
|
|
76
|
+
image = image.encode(target_format, encoding_options.join(' '))
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
image
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|