alchemy_cms 4.1.2 → 4.2.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/.github/ISSUE_TEMPLATE/Bug_report.md +0 -5
- data/.rubocop.yml +4 -1
- data/.travis.yml +3 -3
- data/CHANGELOG.md +29 -10
- data/Gemfile +5 -7
- data/README.md +114 -62
- data/Rakefile +2 -2
- data/alchemy_cms.gemspec +5 -5
- data/app/assets/images/alchemy/icon.svg +1 -1
- data/app/assets/javascripts/alchemy/admin.js +2 -0
- data/app/assets/javascripts/alchemy/alchemy.base.js.coffee +0 -24
- data/app/assets/javascripts/alchemy/alchemy.datepicker.js.coffee +11 -9
- data/app/assets/javascripts/alchemy/alchemy.dragndrop.js.coffee +7 -24
- data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +9 -8
- data/app/assets/javascripts/alchemy/alchemy.fixed_elements.js +38 -0
- data/app/assets/javascripts/alchemy/alchemy.sitemap.js.coffee +2 -4
- data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +1 -1
- data/app/assets/stylesheets/alchemy/_mixins.scss +2 -1
- data/app/assets/stylesheets/alchemy/_variables.scss +7 -2
- data/app/assets/stylesheets/alchemy/admin.scss +2 -1
- data/app/assets/stylesheets/alchemy/archive.scss +18 -4
- data/app/assets/stylesheets/alchemy/buttons.scss +1 -1
- data/app/assets/stylesheets/alchemy/dialogs.scss +1 -1
- data/app/assets/stylesheets/alchemy/elements.scss +154 -90
- data/app/assets/stylesheets/alchemy/filter_field.scss +30 -0
- data/app/assets/stylesheets/alchemy/flatpickr.scss +839 -0
- data/app/assets/stylesheets/alchemy/forms.scss +5 -1
- data/app/assets/stylesheets/alchemy/frame.scss +6 -14
- data/app/assets/stylesheets/alchemy/navigation.scss +109 -98
- data/app/assets/stylesheets/alchemy/search.scss +11 -29
- data/app/assets/stylesheets/alchemy/tables.scss +0 -23
- data/app/assets/stylesheets/alchemy/tags.scss +4 -27
- data/app/assets/stylesheets/alchemy/toolbar.scss +12 -2
- data/app/assets/stylesheets/tinymce/skins/alchemy/skin.min.css.scss +4 -33
- data/app/controllers/alchemy/admin/attachments_controller.rb +1 -12
- data/app/controllers/alchemy/admin/contents_controller.rb +2 -24
- data/app/controllers/alchemy/admin/elements_controller.rb +11 -49
- data/app/controllers/alchemy/admin/pages_controller.rb +1 -1
- data/app/controllers/alchemy/admin/pictures_controller.rb +1 -14
- data/app/controllers/alchemy/api/contents_controller.rb +1 -1
- data/app/controllers/alchemy/api/elements_controller.rb +1 -1
- data/app/controllers/alchemy/api/pages_controller.rb +1 -1
- data/app/controllers/concerns/alchemy/admin/archive_overlay.rb +20 -0
- data/app/helpers/alchemy/admin/base_helper.rb +8 -18
- data/app/helpers/alchemy/admin/elements_helper.rb +55 -85
- data/app/helpers/alchemy/admin/pictures_helper.rb +0 -23
- data/app/helpers/alchemy/elements_helper.rb +80 -120
- data/app/helpers/alchemy/pages_helper.rb +5 -24
- data/app/models/alchemy/content.rb +0 -1
- data/app/models/alchemy/content/factory.rb +33 -57
- data/app/models/alchemy/element.rb +46 -66
- data/app/models/alchemy/element/element_contents.rb +2 -2
- data/app/models/alchemy/page.rb +34 -4
- data/app/models/alchemy/page/page_elements.rb +30 -122
- data/app/serializers/alchemy/attachment_serializer.rb +0 -2
- data/app/serializers/alchemy/content_serializer.rb +0 -2
- data/app/serializers/alchemy/element_serializer.rb +0 -3
- data/app/serializers/alchemy/essence_boolean_serializer.rb +0 -2
- data/app/serializers/alchemy/essence_date_serializer.rb +0 -2
- data/app/serializers/alchemy/essence_file_serializer.rb +0 -2
- data/app/serializers/alchemy/essence_html_serializer.rb +0 -2
- data/app/serializers/alchemy/essence_link_serializer.rb +0 -2
- data/app/serializers/alchemy/essence_picture_serializer.rb +0 -2
- data/app/serializers/alchemy/essence_richtext_serializer.rb +0 -2
- data/app/serializers/alchemy/essence_select_serializer.rb +0 -2
- data/app/serializers/alchemy/essence_text_serializer.rb +0 -2
- data/app/serializers/alchemy/legacy_element_serializer.rb +0 -3
- data/app/serializers/alchemy/page_serializer.rb +2 -8
- data/app/serializers/alchemy/page_tree_serializer.rb +1 -1
- data/app/serializers/alchemy/picture_serializer.rb +0 -2
- data/app/views/alchemy/admin/clipboard/index.html.erb +2 -2
- data/app/views/alchemy/admin/clipboard/insert.js.erb +9 -12
- data/app/views/alchemy/admin/contents/create.js.erb +4 -30
- data/app/views/alchemy/admin/elements/_element.html.erb +27 -12
- data/app/views/alchemy/admin/elements/_element_toolbar.html.erb +1 -1
- data/app/views/alchemy/admin/elements/_new_element_form.html.erb +0 -10
- data/app/views/alchemy/admin/elements/create.js.erb +12 -12
- data/app/views/alchemy/admin/elements/fold.js.erb +1 -1
- data/app/views/alchemy/admin/elements/index.html.erb +20 -19
- data/app/views/alchemy/admin/elements/publish.js.erb +5 -0
- data/app/views/alchemy/admin/elements/trash.js.erb +4 -1
- data/app/views/alchemy/admin/essence_pictures/assign.js.erb +0 -7
- data/app/views/alchemy/admin/essence_pictures/destroy.js.erb +0 -22
- data/app/views/alchemy/admin/pages/_publication_fields.html.erb +2 -4
- data/app/views/alchemy/admin/pages/edit.html.erb +1 -1
- data/app/views/alchemy/admin/pages/index.html.erb +14 -10
- data/app/views/alchemy/admin/partials/_language_tree_select.html.erb +1 -1
- data/app/views/alchemy/admin/partials/_main_navigation_entry.html.erb +1 -1
- data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +7 -5
- data/app/views/alchemy/admin/partials/_routes.html.erb +0 -1
- data/app/views/alchemy/admin/partials/_search_form.html.erb +6 -4
- data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +6 -3
- data/app/views/alchemy/admin/pictures/index.html.erb +1 -1
- data/app/views/alchemy/admin/trash/index.html.erb +8 -7
- data/app/views/alchemy/elements/_editor_not_found.html.erb +1 -1
- data/app/views/alchemy/essences/_essence_picture_editor.html.erb +4 -19
- data/app/views/layouts/alchemy/admin.html.erb +1 -0
- data/bin/rspec +0 -5
- data/config/alchemy/config.yml +3 -0
- data/config/brakeman.ignore +1 -1
- data/config/locales/alchemy.en.yml +6 -12
- data/config/routes.rb +1 -5
- data/db/migrate/20180226123013_alchemy_four_point_zero.rb +0 -29
- data/db/migrate/20180519204655_add_fixed_to_alchemy_elements.rb +6 -0
- data/lib/alchemy/admin/locale.rb +1 -1
- data/lib/alchemy/cache_digests/template_tracker.rb +4 -27
- data/lib/alchemy/elements_finder.rb +111 -0
- data/lib/alchemy/errors.rb +0 -4
- data/lib/alchemy/modules.rb +49 -18
- data/lib/alchemy/tasks/tidy.rb +3 -40
- data/lib/alchemy/test_support/controller_requests.rb +1 -1
- data/lib/alchemy/test_support/essence_shared_examples.rb +1 -1
- data/lib/alchemy/test_support/factories/attachment_factory.rb +5 -3
- data/lib/alchemy/test_support/factories/content_factory.rb +4 -4
- data/lib/alchemy/test_support/factories/dummy_user_factory.rb +5 -5
- data/lib/alchemy/test_support/factories/element_factory.rb +12 -7
- data/lib/alchemy/test_support/factories/essence_text_factory.rb +1 -1
- data/lib/alchemy/test_support/factories/language_factory.rb +13 -13
- data/lib/alchemy/test_support/factories/page_factory.rb +18 -17
- data/lib/alchemy/test_support/factories/picture_factory.rb +6 -4
- data/lib/alchemy/test_support/factories/site_factory.rb +6 -6
- data/lib/alchemy/tinymce.rb +1 -1
- data/lib/alchemy/upgrader/four_point_two.rb +68 -0
- data/lib/alchemy/upgrader/tasks/cells_migration.rb +41 -0
- data/lib/alchemy/upgrader/tasks/cells_upgrader.rb +146 -0
- data/lib/alchemy/upgrader/tasks/picture_gallery_migration.rb +65 -0
- data/lib/alchemy/upgrader/tasks/picture_gallery_upgrader.rb +195 -0
- data/lib/alchemy/version.rb +1 -1
- data/lib/alchemy_cms.rb +1 -0
- data/lib/rails/generators/alchemy/elements/elements_generator.rb +1 -0
- data/lib/rails/generators/alchemy/elements/templates/editor.html.erb +0 -3
- data/lib/rails/generators/alchemy/elements/templates/editor.html.haml +0 -3
- data/lib/rails/generators/alchemy/elements/templates/editor.html.slim +0 -3
- data/lib/rails/generators/alchemy/elements/templates/view.html.erb +3 -14
- data/lib/rails/generators/alchemy/elements/templates/view.html.haml +3 -10
- data/lib/rails/generators/alchemy/elements/templates/view.html.slim +3 -10
- data/lib/tasks/alchemy/tidy.rake +1 -23
- data/lib/tasks/alchemy/upgrade.rake +44 -1
- data/vendor/assets/javascripts/flatpickr/flatpickr.min.js +2 -0
- data/vendor/assets/javascripts/tinymce/license.txt +0 -0
- data/vendor/assets/javascripts/tinymce/tinymce.min.js +2 -2
- metadata +25 -31
- data/app/assets/stylesheets/alchemy/jquery.datetimepicker.scss +0 -478
- data/app/models/alchemy/cell.rb +0 -95
- data/app/models/alchemy/page/page_cells.rb +0 -69
- data/app/serializers/alchemy/cell_serializer.rb +0 -19
- data/app/views/alchemy/admin/contents/new.html.erb +0 -11
- data/app/views/alchemy/admin/contents/order.js.erb +0 -3
- data/app/views/alchemy/admin/elements/_add_picture.html.erb +0 -14
- data/app/views/alchemy/admin/elements/_picture_gallery_editor.html.erb +0 -24
- data/bin/spring +0 -16
- data/lib/alchemy/test_support/factories/cell_factory.rb +0 -9
- data/vendor/assets/javascripts/date-formatter.js +0 -161
- data/vendor/assets/javascripts/jquery_plugins/jquery.datetimepicker.full.min.js +0 -2
|
@@ -3,29 +3,6 @@
|
|
|
3
3
|
module Alchemy
|
|
4
4
|
module Admin
|
|
5
5
|
module PicturesHelper
|
|
6
|
-
def create_or_assign_url(picture_to_assign, options)
|
|
7
|
-
if @content.nil?
|
|
8
|
-
{
|
|
9
|
-
controller: :contents,
|
|
10
|
-
action: :create,
|
|
11
|
-
picture_id: picture_to_assign.id,
|
|
12
|
-
content: {
|
|
13
|
-
essence_type: "Alchemy::EssencePicture",
|
|
14
|
-
element_id: @element.id
|
|
15
|
-
},
|
|
16
|
-
options: options
|
|
17
|
-
}
|
|
18
|
-
else
|
|
19
|
-
{
|
|
20
|
-
controller: :essence_pictures,
|
|
21
|
-
action: :assign,
|
|
22
|
-
picture_id: picture_to_assign.id,
|
|
23
|
-
content_id: @content.id,
|
|
24
|
-
options: options
|
|
25
|
-
}
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
6
|
def preview_size(size)
|
|
30
7
|
case size
|
|
31
8
|
when 'small' then '80x60'
|
|
@@ -10,7 +10,7 @@ module Alchemy
|
|
|
10
10
|
include Alchemy::UrlHelper
|
|
11
11
|
include Alchemy::ElementsBlockHelper
|
|
12
12
|
|
|
13
|
-
# Renders
|
|
13
|
+
# Renders elements from given page
|
|
14
14
|
#
|
|
15
15
|
# == Examples:
|
|
16
16
|
#
|
|
@@ -29,12 +29,6 @@ module Alchemy
|
|
|
29
29
|
# <%= render_elements from_page: 'footer' %>
|
|
30
30
|
# </footer>
|
|
31
31
|
#
|
|
32
|
-
# === Render elements from cell:
|
|
33
|
-
#
|
|
34
|
-
# <aside>
|
|
35
|
-
# <%= render_elements from_cell: 'sidebar' %>
|
|
36
|
-
# </aside>
|
|
37
|
-
#
|
|
38
32
|
# === Fallback to elements from global page:
|
|
39
33
|
#
|
|
40
34
|
# You can use the fallback option as an override for elements that are stored on another page.
|
|
@@ -51,69 +45,85 @@ module Alchemy
|
|
|
51
45
|
# with: 'contact_teaser'
|
|
52
46
|
# }) %>
|
|
53
47
|
#
|
|
54
|
-
#
|
|
55
|
-
#
|
|
48
|
+
# === Custom elements finder:
|
|
49
|
+
#
|
|
50
|
+
# Having a custom element finder class:
|
|
51
|
+
#
|
|
52
|
+
# class MyCustomNewsArchive
|
|
53
|
+
# def elements(page:)
|
|
54
|
+
# news_page.elements.available.named('news').order(created_at: :desc)
|
|
55
|
+
# end
|
|
56
|
+
#
|
|
57
|
+
# private
|
|
58
|
+
#
|
|
59
|
+
# def news_page
|
|
60
|
+
# Alchemy::Page.where(page_layout: 'news-archive')
|
|
61
|
+
# end
|
|
62
|
+
# end
|
|
56
63
|
#
|
|
64
|
+
# In your view:
|
|
65
|
+
#
|
|
66
|
+
# <div class="news-archive">
|
|
67
|
+
# <%= render_elements finder: MyCustomNewsArchive.new %>
|
|
68
|
+
# </div>
|
|
69
|
+
#
|
|
70
|
+
# @option options [Alchemy::Page|String] :from_page (@page)
|
|
71
|
+
# The page the elements are rendered from. You can pass a page_layout String or a {Alchemy::Page} object.
|
|
72
|
+
# @option options [Array<String>|String] :only
|
|
73
|
+
# A list of element names only to be rendered.
|
|
74
|
+
# @option options [Array<String>|String] :except
|
|
75
|
+
# A list of element names not to be rendered.
|
|
57
76
|
# @option options [Number] :count
|
|
58
77
|
# The amount of elements to be rendered (begins with first element found)
|
|
59
|
-
# @option options [
|
|
60
|
-
#
|
|
78
|
+
# @option options [Number] :offset
|
|
79
|
+
# The offset to begin loading elements from
|
|
61
80
|
# @option options [Hash] :fallback
|
|
62
81
|
# Define elements that are rendered from another page.
|
|
63
|
-
# @option options [
|
|
64
|
-
# The cell the elements are rendered from. You can pass a {Alchemy::Cell} name String or a {Alchemy::Cell} object.
|
|
65
|
-
# @option options [Alchemy::Page or String] :from_page (@page)
|
|
66
|
-
# The page the elements are rendered from. You can pass a page_layout String or a {Alchemy::Page} object.
|
|
67
|
-
# @option options [Array or String] :only ([])
|
|
68
|
-
# A list of element names only to be rendered.
|
|
69
|
-
# @option options [Boolean] :random
|
|
82
|
+
# @option options [Boolean] :random (false)
|
|
70
83
|
# Randomize the output of elements
|
|
71
|
-
# @option options [Boolean] :reverse
|
|
84
|
+
# @option options [Boolean] :reverse (false)
|
|
72
85
|
# Reverse the rendering order
|
|
73
|
-
# @option options [String] :sort_by
|
|
74
|
-
# The name of a {Alchemy::Content} to sort the elements by
|
|
75
86
|
# @option options [String] :separator
|
|
76
|
-
# A string that will be used to join the element partials.
|
|
87
|
+
# A string that will be used to join the element partials.
|
|
88
|
+
# @option options [Class] :finder (Alchemy::ElementsFinder)
|
|
89
|
+
# A class instance that will return elements that get rendered.
|
|
90
|
+
# Use this for your custom element loading logic in views.
|
|
77
91
|
#
|
|
78
92
|
def render_elements(options = {})
|
|
79
93
|
options = {
|
|
80
94
|
from_page: @page,
|
|
81
|
-
render_format: 'html'
|
|
82
|
-
reverse: false
|
|
95
|
+
render_format: 'html'
|
|
83
96
|
}.update(options)
|
|
84
97
|
|
|
85
|
-
|
|
98
|
+
if options[:sort_by]
|
|
99
|
+
Alchemy::Deprecation.warn "options[:sort_by] has been removed without replacement. " \
|
|
100
|
+
"Please implement your own element sorting by passing a custom finder instance to options[:finder]."
|
|
101
|
+
end
|
|
86
102
|
|
|
87
|
-
if
|
|
88
|
-
|
|
89
|
-
|
|
103
|
+
if options[:from_cell]
|
|
104
|
+
Alchemy::Deprecation.warn "options[:from_cell] has been removed without replacement. " \
|
|
105
|
+
"Please `render element.nested_elements.available` instead."
|
|
90
106
|
end
|
|
91
107
|
|
|
92
|
-
|
|
108
|
+
finder = options[:finder] || Alchemy::ElementsFinder.new(options)
|
|
109
|
+
elements = finder.elements(page: options[:from_page])
|
|
93
110
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
options.delete(:sort_by),
|
|
98
|
-
options[:reverse]
|
|
99
|
-
)
|
|
111
|
+
buff = []
|
|
112
|
+
elements.each_with_index do |element, i|
|
|
113
|
+
buff << render_element(element, options, i + 1)
|
|
100
114
|
end
|
|
101
|
-
|
|
102
|
-
render_element_view_partials(elements, options)
|
|
115
|
+
buff.join(options[:separator]).html_safe
|
|
103
116
|
end
|
|
104
117
|
|
|
105
|
-
# This helper renders a {Alchemy::Element} partial.
|
|
106
|
-
#
|
|
107
|
-
# A element has always two partials:
|
|
118
|
+
# This helper renders a {Alchemy::Element} view partial.
|
|
108
119
|
#
|
|
109
|
-
#
|
|
110
|
-
# 2. A editor partial (This is the form presented to the website editor while in page edit mode)
|
|
120
|
+
# A element view partial is the html snippet presented to the website visitor.
|
|
111
121
|
#
|
|
112
|
-
# The
|
|
122
|
+
# The partial is located in <tt>app/views/alchemy/elements</tt>.
|
|
113
123
|
#
|
|
114
124
|
# == View partial naming
|
|
115
125
|
#
|
|
116
|
-
# The
|
|
126
|
+
# The partial has to be named after the name of the element as defined in the <tt>elements.yml</tt> file and has to be suffixed with <tt>_view</tt>.
|
|
117
127
|
#
|
|
118
128
|
# === Example
|
|
119
129
|
#
|
|
@@ -125,10 +135,9 @@ module Alchemy
|
|
|
125
135
|
# - name: text
|
|
126
136
|
# type: EssenceText
|
|
127
137
|
#
|
|
128
|
-
# Then your element view
|
|
138
|
+
# Then your element view partial has to be named like:
|
|
129
139
|
#
|
|
130
|
-
# app/views/alchemy/elements/
|
|
131
|
-
# app/views/alchemy/elements/_headline_view.html.erb
|
|
140
|
+
# app/views/alchemy/elements/_headline_view.html.{erb|haml|slim}
|
|
132
141
|
#
|
|
133
142
|
# === Element partials generator
|
|
134
143
|
#
|
|
@@ -142,41 +151,45 @@ module Alchemy
|
|
|
142
151
|
#
|
|
143
152
|
# @param [Alchemy::Element] element
|
|
144
153
|
# The element you want to render the view for
|
|
145
|
-
# @param [Symbol] part
|
|
146
|
-
# The type of element partial (<tt>:editor</tt> or <tt>:view</tt>) you want to render
|
|
147
154
|
# @param [Hash] options
|
|
148
155
|
# Additional options
|
|
149
156
|
# @param [Number] counter
|
|
150
157
|
# a counter
|
|
151
158
|
#
|
|
152
|
-
# @note If the view partial is not found
|
|
153
|
-
#
|
|
159
|
+
# @note If the view partial is not found
|
|
160
|
+
# <tt>alchemy/elements/_view_not_found.html.erb</tt> gets rendered.
|
|
154
161
|
#
|
|
155
|
-
def render_element(
|
|
162
|
+
def render_element(*args)
|
|
163
|
+
if args.length == 4
|
|
164
|
+
element, _part, options, counter = *args
|
|
165
|
+
Alchemy::Deprecation.warn "passing a `part` parameter as second argument to `render_element` has been removed without replacement. " \
|
|
166
|
+
"You can safely remove it."
|
|
167
|
+
else
|
|
168
|
+
element, options, counter = *args
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
options ||= {}
|
|
172
|
+
counter ||= 1
|
|
173
|
+
|
|
156
174
|
if element.nil?
|
|
157
175
|
warning('Element is nil')
|
|
158
|
-
render "alchemy/elements
|
|
176
|
+
render "alchemy/elements/view_not_found", {name: 'nil'}
|
|
159
177
|
return
|
|
160
178
|
end
|
|
161
179
|
|
|
162
|
-
|
|
180
|
+
element.store_page(@page)
|
|
181
|
+
|
|
182
|
+
render element, {
|
|
163
183
|
element: element,
|
|
164
184
|
counter: counter,
|
|
165
|
-
options: options
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
element.store_page(@page) if part.to_sym == :view
|
|
170
|
-
render "alchemy/elements/#{element.name}_#{part}", options
|
|
185
|
+
options: options
|
|
186
|
+
}.merge(options.delete(:locals) || {})
|
|
171
187
|
rescue ActionView::MissingTemplate => e
|
|
172
188
|
warning(%(
|
|
173
|
-
Element
|
|
189
|
+
Element view partial not found for #{element.name}.\n
|
|
174
190
|
#{e}
|
|
175
191
|
))
|
|
176
|
-
render "alchemy/elements
|
|
177
|
-
name: element.name,
|
|
178
|
-
error: "Element #{part} partial not found.<br>Use <code>rails generate alchemy:elements</code> to generate it."
|
|
179
|
-
}
|
|
192
|
+
render "alchemy/elements/view_not_found", name: element.name
|
|
180
193
|
end
|
|
181
194
|
|
|
182
195
|
# Returns a string for the id attribute of a html element for the given element
|
|
@@ -239,14 +252,14 @@ module Alchemy
|
|
|
239
252
|
end
|
|
240
253
|
|
|
241
254
|
# Sort given elements by content.
|
|
242
|
-
#
|
|
255
|
+
# @deprecated
|
|
243
256
|
# @param [Array] elements - The elements you want to sort
|
|
244
257
|
# @param [String] content_name - The name of the content you want to sort by
|
|
245
258
|
# @param [Boolean] reverse - Reverse the sorted elements order
|
|
246
259
|
#
|
|
247
260
|
# @return [Array]
|
|
248
|
-
#
|
|
249
261
|
def sort_elements_by_content(elements, content_name, reverse = false)
|
|
262
|
+
Alchemy::Deprecation.warn "options[:sort_by] is deprecated. Please implement your own element sorting."
|
|
250
263
|
sorted_elements = elements.sort_by do |element|
|
|
251
264
|
content = element.content_by_name(content_name)
|
|
252
265
|
content ? content.ingredient.to_s : ''
|
|
@@ -254,58 +267,5 @@ module Alchemy
|
|
|
254
267
|
|
|
255
268
|
reverse ? sorted_elements.reverse : sorted_elements
|
|
256
269
|
end
|
|
257
|
-
|
|
258
|
-
private
|
|
259
|
-
|
|
260
|
-
def pages_holding_elements(page)
|
|
261
|
-
case page
|
|
262
|
-
when String
|
|
263
|
-
Language.current.pages.where(
|
|
264
|
-
page_layout: page,
|
|
265
|
-
restricted: false
|
|
266
|
-
).to_a
|
|
267
|
-
when Page
|
|
268
|
-
page
|
|
269
|
-
end
|
|
270
|
-
end
|
|
271
|
-
|
|
272
|
-
def collect_elements_from_pages(page, options)
|
|
273
|
-
if page.is_a? Array
|
|
274
|
-
elements = page.collect { |p| p.find_elements(options) }.flatten
|
|
275
|
-
else
|
|
276
|
-
elements = page.find_elements(options)
|
|
277
|
-
end
|
|
278
|
-
if fallback_required?(elements, options)
|
|
279
|
-
elements += fallback_elements(options)
|
|
280
|
-
end
|
|
281
|
-
elements
|
|
282
|
-
end
|
|
283
|
-
|
|
284
|
-
def fallback_required?(elements, options)
|
|
285
|
-
options[:fallback] && elements.detect { |e| e.name == options[:fallback][:for] }.nil?
|
|
286
|
-
end
|
|
287
|
-
|
|
288
|
-
def fallback_elements(options)
|
|
289
|
-
fallback_options = options.delete(:fallback)
|
|
290
|
-
case fallback_options[:from]
|
|
291
|
-
when String
|
|
292
|
-
page = Language.current.pages.find_by(
|
|
293
|
-
page_layout: fallback_options[:from],
|
|
294
|
-
restricted: false
|
|
295
|
-
)
|
|
296
|
-
when Page
|
|
297
|
-
page = fallback_options[:from]
|
|
298
|
-
end
|
|
299
|
-
return [] if page.blank?
|
|
300
|
-
page.elements.not_trashed.named(fallback_options[:with].presence || fallback_options[:for])
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
def render_element_view_partials(elements, options = {})
|
|
304
|
-
buff = []
|
|
305
|
-
elements.each_with_index do |element, i|
|
|
306
|
-
buff << render_element(element, :view, options, i + 1)
|
|
307
|
-
end
|
|
308
|
-
buff.join(options[:separator]).html_safe
|
|
309
|
-
end
|
|
310
270
|
end
|
|
311
271
|
end
|
|
@@ -294,30 +294,11 @@ module Alchemy
|
|
|
294
294
|
"#{@page.robot_index? ? '' : 'no'}index, #{@page.robot_follow? ? '' : 'no'}follow"
|
|
295
295
|
end
|
|
296
296
|
|
|
297
|
-
#
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
# === Options are:
|
|
301
|
-
#
|
|
302
|
-
# from_page: Alchemy::Page # Alchemy::Page object from which the elements are rendered from.
|
|
303
|
-
# locals: Hash # Hash of variables that will be available in the partial. Example: {user: var1, product: var2}
|
|
304
|
-
#
|
|
305
|
-
def render_cell(name, options = {})
|
|
306
|
-
default_options = {
|
|
307
|
-
from_page: @page,
|
|
308
|
-
locals: {}
|
|
309
|
-
}
|
|
310
|
-
options = default_options.merge(options)
|
|
311
|
-
cell = options[:from_page].cells.find_by_name(name)
|
|
312
|
-
return "" if cell.blank?
|
|
313
|
-
render partial: "alchemy/cells/#{name}", locals: {cell: cell}.merge(options[:locals])
|
|
314
|
-
end
|
|
315
|
-
|
|
316
|
-
# Returns true or false if no elements are in the cell found by name.
|
|
317
|
-
def cell_empty?(name)
|
|
318
|
-
cell = @page.cells.find_by_name(name)
|
|
319
|
-
return true if cell.blank?
|
|
320
|
-
cell.elements.not_trashed.empty?
|
|
297
|
+
# @deprecated
|
|
298
|
+
def render_cell(name, _options = {})
|
|
299
|
+
render_elements(only: name, fixed: true)
|
|
321
300
|
end
|
|
301
|
+
deprecate render_cell: 'Use render_elements(only: <cell-name>, fixed: true) instead',
|
|
302
|
+
deprecator: Alchemy::Deprecation
|
|
322
303
|
end
|
|
323
304
|
end
|
|
@@ -45,7 +45,6 @@ module Alchemy
|
|
|
45
45
|
scope :essence_htmls, -> { where(essence_type: "Alchemy::EssenceHtml") }
|
|
46
46
|
scope :essence_links, -> { where(essence_type: "Alchemy::EssenceLink") }
|
|
47
47
|
scope :essence_pictures, -> { where(essence_type: "Alchemy::EssencePicture") }
|
|
48
|
-
scope :gallery_pictures, -> { essence_pictures.where("#{table_name}.name LIKE 'essence_picture_%'") }
|
|
49
48
|
scope :essence_richtexts, -> { where(essence_type: "Alchemy::EssenceRichtext") }
|
|
50
49
|
scope :essence_selects, -> { where(essence_type: "Alchemy::EssenceSelect") }
|
|
51
50
|
scope :essence_texts, -> { where(essence_type: "Alchemy::EssenceText") }
|
|
@@ -11,19 +11,21 @@ module Alchemy
|
|
|
11
11
|
|
|
12
12
|
# Builds a new content as descriped in the elements.yml file.
|
|
13
13
|
#
|
|
14
|
-
# @param [Alchemy::Element]
|
|
15
|
-
# The element the content is for
|
|
16
14
|
# @param [Hash]
|
|
17
15
|
# The content definition used for finding the content in +elements.yml+ file
|
|
18
16
|
#
|
|
19
|
-
def
|
|
20
|
-
|
|
17
|
+
def new(attributes = {})
|
|
18
|
+
element = attributes[:element] || Element.find_by(id: attributes[:element_id])
|
|
19
|
+
return super if attributes.empty? || element.nil?
|
|
20
|
+
|
|
21
|
+
definition = element.content_definition_for(attributes[:name])
|
|
21
22
|
if definition.blank?
|
|
22
|
-
raise ContentDefinitionError, "No definition found in elements.yml for #{
|
|
23
|
-
else
|
|
24
|
-
new(name: definition['name'], element_id: element.id)
|
|
23
|
+
raise ContentDefinitionError, "No definition found in elements.yml for #{attributes.inspect} and #{element.inspect}"
|
|
25
24
|
end
|
|
25
|
+
super(name: definition['name'], element_id: element.id)
|
|
26
26
|
end
|
|
27
|
+
alias_method :build, :new
|
|
28
|
+
deprecate build: :new, deprecator: Alchemy::Deprecation
|
|
27
29
|
|
|
28
30
|
# Creates a new content from elements definition in the +elements.yml+ file.
|
|
29
31
|
#
|
|
@@ -32,12 +34,20 @@ module Alchemy
|
|
|
32
34
|
#
|
|
33
35
|
# @return [Alchemy::Content]
|
|
34
36
|
#
|
|
35
|
-
def
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
def create(*args)
|
|
38
|
+
attributes = args.last || {}
|
|
39
|
+
if args.length > 1
|
|
40
|
+
Alchemy::Deprecation.warn 'Passing an element as first argument to Alchemy::Content.create is deprecated! Pass an attribute hash with element inside instead.'
|
|
41
|
+
element = args.first
|
|
42
|
+
else
|
|
43
|
+
element = attributes[:element]
|
|
44
|
+
end
|
|
45
|
+
new(attributes.merge(element: element)).tap do |content|
|
|
46
|
+
content.create_essence!(attributes[:essence_type])
|
|
38
47
|
end
|
|
39
|
-
content
|
|
40
48
|
end
|
|
49
|
+
alias_method :create_from_scratch, :create
|
|
50
|
+
deprecate create_from_scratch: :create, deprecator: Alchemy::Deprecation
|
|
41
51
|
|
|
42
52
|
# Creates a copy of source and also copies the associated essence.
|
|
43
53
|
#
|
|
@@ -50,60 +60,26 @@ module Alchemy
|
|
|
50
60
|
#
|
|
51
61
|
def copy(source, differences = {})
|
|
52
62
|
new_content = Content.new(
|
|
53
|
-
source.attributes.
|
|
63
|
+
source.attributes.
|
|
64
|
+
except(*SKIPPED_ATTRIBUTES_ON_COPY).
|
|
65
|
+
merge(differences.with_indifferent_access)
|
|
54
66
|
)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
67
|
+
new_essence = source.essence.class.create!(
|
|
68
|
+
source.essence.attributes.
|
|
69
|
+
except(*SKIPPED_ATTRIBUTES_ON_COPY)
|
|
58
70
|
)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
# Returns the content definition for building a content.
|
|
65
|
-
#
|
|
66
|
-
# 1. It looks in the element's contents definition
|
|
67
|
-
# 2. It builds a definition hash from essence type, if the the name key is not present
|
|
68
|
-
#
|
|
69
|
-
def content_definition(element, essence_hash)
|
|
70
|
-
# No name given. We build the content from essence type.
|
|
71
|
-
if essence_hash[:name].blank? && essence_hash[:essence_type].present?
|
|
72
|
-
content_definition_from_essence_type(element, essence_hash[:essence_type])
|
|
73
|
-
else
|
|
74
|
-
element.content_definition_for(essence_hash[:name])
|
|
71
|
+
new_content.tap do |content|
|
|
72
|
+
content.essence = new_essence
|
|
73
|
+
content.save
|
|
75
74
|
end
|
|
76
75
|
end
|
|
77
76
|
|
|
78
|
-
# Returns a hash for building a content from essence type.
|
|
79
|
-
#
|
|
80
|
-
# @param [Alchemy::Element]
|
|
81
|
-
# The element the content is for.
|
|
82
|
-
# @param [String]
|
|
83
|
-
# The essence type the content is from
|
|
84
|
-
#
|
|
85
|
-
def content_definition_from_essence_type(element, essence_type)
|
|
86
|
-
{
|
|
87
|
-
'type' => essence_type,
|
|
88
|
-
'name' => content_name_from_element_and_essence_type(element, essence_type)
|
|
89
|
-
}
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
# A name for content from its essence type and amount of same essences in element.
|
|
93
|
-
#
|
|
94
|
-
# Example:
|
|
95
|
-
#
|
|
96
|
-
# essence_picture_1
|
|
97
|
-
#
|
|
98
|
-
def content_name_from_element_and_essence_type(element, essence_type)
|
|
99
|
-
essences_of_same_type = element.contents.where(essence_type: normalize_essence_type(essence_type))
|
|
100
|
-
"#{essence_type.classify.demodulize.underscore}_#{essences_of_same_type.count + 1}"
|
|
101
|
-
end
|
|
102
|
-
|
|
103
77
|
# Returns all content definitions from elements.yml
|
|
104
78
|
#
|
|
105
79
|
def definitions
|
|
106
|
-
Element.definitions.
|
|
80
|
+
definitions = Element.definitions.flat_map { |e| e['contents'] }
|
|
81
|
+
definitions.compact!
|
|
82
|
+
definitions
|
|
107
83
|
end
|
|
108
84
|
|
|
109
85
|
# Returns a normalized Essence type
|