alchemy_cms 6.0.5 → 6.0.6
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.
Potentially problematic release.
This version of alchemy_cms might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +26 -0
- data/app/assets/stylesheets/alchemy/elements.scss +35 -0
- data/app/controllers/alchemy/admin/pages_controller.rb +5 -1
- data/app/controllers/alchemy/pages_controller.rb +19 -5
- data/app/decorators/alchemy/element_editor.rb +23 -0
- data/app/jobs/alchemy/publish_page_job.rb +4 -1
- data/app/models/alchemy/eager_loading.rb +39 -0
- data/app/models/alchemy/page/publisher.rb +4 -1
- data/app/models/alchemy/page.rb +2 -7
- data/app/models/alchemy/page_version.rb +1 -1
- data/app/views/alchemy/admin/elements/_element.html.erb +34 -5
- data/lib/alchemy/errors.rb +8 -2
- data/lib/alchemy/upgrader/tasks/ingredients_migrator.rb +1 -1
- data/lib/alchemy/version.rb +1 -1
- data/lib/tasks/alchemy/thumbnails.rake +24 -0
- data/package.json +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ac4238ff0e22f613444f1ae9124a20bf4e884f2f7c4f8fe05c1e8d0bd147cad7
|
4
|
+
data.tar.gz: 02e2877398db81eb4c58a1afbad4c0355020da0fb7505c895d493d40a93223d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2bacfe8d1e126cc3a3e31f5dfdb1346efb1398adf33dac32e4e58731bcfd11580d51544797a59d563361ee28c5d4a37a76a7659b7534651a574c7903820cc994
|
7
|
+
data.tar.gz: '04198e8f916fd87a5a1587129b86480cde12cbab889acfa2baaf23a34ed966292cc24312c1b731648c556e27fc3045b0a5b56d43ab6124abacbcb33cdf05fab2'
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## 6.0.6 (2022-05-30)
|
2
|
+
|
3
|
+
- Add task to eagerly generate ingredients pictures thumbnails [#2342](https://github.com/AlchemyCMS/alchemy_cms/pull/2342) ([tvdeyen](https://github.com/tvdeyen))
|
4
|
+
- Add spec for ingredients migrator; fix preloading in Rails 6.1+ [#2340](https://github.com/AlchemyCMS/alchemy_cms/pull/2340) ([mamhoff](https://github.com/mamhoff))
|
5
|
+
- Extract element ingredient migrator [#2337](https://github.com/AlchemyCMS/alchemy_cms/pull/2337) ([tvdeyen](https://github.com/tvdeyen))
|
6
|
+
- Update published_at only after page has been published. [#2331](https://github.com/AlchemyCMS/alchemy_cms/pull/2331) ([pascalbetz](https://github.com/pascalbetz))
|
7
|
+
- Add element groups functionality for cleaning up editors [#2124](https://github.com/AlchemyCMS/alchemy_cms/pull/2124) ([dbwinger](https://github.com/dbwinger))
|
8
|
+
- Eagerload at the controller or job layer [#2313](https://github.com/AlchemyCMS/alchemy_cms/pull/2313) ([mamhoff](https://github.com/mamhoff))
|
9
|
+
|
1
10
|
## 6.0.5 (2022-05-11)
|
2
11
|
|
3
12
|
- Extract element ingredient migrator [#2337](https://github.com/AlchemyCMS/alchemy_cms/pull/2337) ([tvdeyen](https://github.com/tvdeyen))
|
@@ -15,6 +15,7 @@ Alchemy.ElementEditors =
|
|
15
15
|
init: ->
|
16
16
|
@element_area = $("#element_area")
|
17
17
|
@bindEvents()
|
18
|
+
@expandContentGroups()
|
18
19
|
return
|
19
20
|
|
20
21
|
# Binds click events on several DOM elements from element editors
|
@@ -36,12 +37,20 @@ Alchemy.ElementEditors =
|
|
36
37
|
# Binds the custom SaveElement event
|
37
38
|
@element_area.on "SaveElement.Alchemy", '.element-editor', (e, data) =>
|
38
39
|
@onSaveElement(e, data)
|
40
|
+
@element_area.on "click", '[data-toggle-content-group]', (e) =>
|
41
|
+
@onToggleContentGroup(e)
|
39
42
|
# Listen to postMessage messages from the preview frame
|
40
43
|
window.addEventListener 'message', (e) =>
|
41
44
|
@onMessage(e.data)
|
42
45
|
true
|
43
46
|
return
|
44
47
|
|
48
|
+
# Expands content groups that are stored in sessionStorage as expanded
|
49
|
+
expandContentGroups: ->
|
50
|
+
if $expanded_content_groups = sessionStorage.getItem('Alchemy.expanded_content_groups')
|
51
|
+
for header_id in JSON.parse($expanded_content_groups) then do (header_id) =>
|
52
|
+
$('#' + header_id).closest('.content-group').addClass('expanded');
|
53
|
+
|
45
54
|
# Selects and scrolls to element with given id in the preview window.
|
46
55
|
#
|
47
56
|
focusElementPreview: (element_id) ->
|
@@ -170,6 +179,23 @@ Alchemy.ElementEditors =
|
|
170
179
|
Alchemy.Buttons.enable($element)
|
171
180
|
true
|
172
181
|
|
182
|
+
# Toggle visibility of the content fields in the group
|
183
|
+
onToggleContentGroup: (event) ->
|
184
|
+
$group_div = $(event.currentTarget).closest('.content-group');
|
185
|
+
$group_div.toggleClass('expanded');
|
186
|
+
|
187
|
+
$expanded_content_groups = JSON.parse(sessionStorage.getItem('Alchemy.expanded_content_groups') || '[]');
|
188
|
+
# Add or remove depending on whether this content group is expanded
|
189
|
+
if $group_div.hasClass('expanded')
|
190
|
+
if $expanded_content_groups.indexOf(event.currentTarget.id) == -1
|
191
|
+
$expanded_content_groups.push(event.currentTarget.id);
|
192
|
+
else
|
193
|
+
$expanded_content_groups = $expanded_content_groups.filter (value) ->
|
194
|
+
value != event.currentTarget.id
|
195
|
+
|
196
|
+
sessionStorage.setItem('Alchemy.expanded_content_groups', JSON.stringify($expanded_content_groups))
|
197
|
+
false
|
198
|
+
|
173
199
|
# Event handlers
|
174
200
|
|
175
201
|
onMessage: (data) ->
|
@@ -414,6 +414,41 @@
|
|
414
414
|
}
|
415
415
|
}
|
416
416
|
|
417
|
+
.content-group {
|
418
|
+
width: 100%;
|
419
|
+
padding: $default-padding 0;
|
420
|
+
position: relative;
|
421
|
+
border-bottom: 1px solid $medium-gray;
|
422
|
+
|
423
|
+
&:last-child {
|
424
|
+
border-bottom: none;
|
425
|
+
padding-bottom: 0;
|
426
|
+
}
|
427
|
+
|
428
|
+
.content-group-header {
|
429
|
+
display: flex;
|
430
|
+
align-items: center;
|
431
|
+
justify-content: space-between;
|
432
|
+
font-weight: bold;
|
433
|
+
text-decoration: none;
|
434
|
+
padding: $default-padding 1px;
|
435
|
+
}
|
436
|
+
|
437
|
+
.content-group-contents {
|
438
|
+
display: none;
|
439
|
+
}
|
440
|
+
|
441
|
+
&.expanded {
|
442
|
+
.content-group-contents {
|
443
|
+
display: block;
|
444
|
+
}
|
445
|
+
|
446
|
+
.content-group-expand {
|
447
|
+
@extend .fa-angle-up;
|
448
|
+
}
|
449
|
+
}
|
450
|
+
}
|
451
|
+
|
417
452
|
.element-content-editors,
|
418
453
|
.element-ingredient-editors {
|
419
454
|
display: flex;
|
@@ -324,7 +324,7 @@ module Alchemy
|
|
324
324
|
end
|
325
325
|
|
326
326
|
def load_resource
|
327
|
-
@page = Page.find(params[:id])
|
327
|
+
@page = Page.includes(page_includes).find(params[:id])
|
328
328
|
end
|
329
329
|
|
330
330
|
def pages_from_raw_request
|
@@ -402,6 +402,10 @@ module Alchemy
|
|
402
402
|
def set_preview_mode
|
403
403
|
@preview_mode = true
|
404
404
|
end
|
405
|
+
|
406
|
+
def page_includes
|
407
|
+
Alchemy::EagerLoading.page_includes(version: :draft_version)
|
408
|
+
end
|
405
409
|
end
|
406
410
|
end
|
407
411
|
end
|
@@ -104,7 +104,14 @@ module Alchemy
|
|
104
104
|
# If no index page and no admin users are present we show the "Welcome to Alchemy" page.
|
105
105
|
#
|
106
106
|
def load_index_page
|
107
|
-
@page ||=
|
107
|
+
@page ||= begin
|
108
|
+
Alchemy::Page.
|
109
|
+
contentpages.
|
110
|
+
language_roots.
|
111
|
+
where(language: Language.current).
|
112
|
+
includes(page_includes).
|
113
|
+
first
|
114
|
+
end
|
108
115
|
render template: "alchemy/welcome", layout: false if signup_required?
|
109
116
|
end
|
110
117
|
|
@@ -120,10 +127,13 @@ module Alchemy
|
|
120
127
|
def load_page
|
121
128
|
page_not_found! unless Language.current
|
122
129
|
|
123
|
-
@page ||=
|
124
|
-
|
125
|
-
|
126
|
-
|
130
|
+
@page ||= begin
|
131
|
+
Alchemy::Page.
|
132
|
+
contentpages.
|
133
|
+
where(language: Language.current).
|
134
|
+
includes(page_includes).
|
135
|
+
find_by(urlname: params[:urlname])
|
136
|
+
end
|
127
137
|
end
|
128
138
|
|
129
139
|
def enforce_locale
|
@@ -234,5 +244,9 @@ module Alchemy
|
|
234
244
|
def page_not_found!
|
235
245
|
not_found_error!("Alchemy::Page not found \"#{request.fullpath}\"")
|
236
246
|
end
|
247
|
+
|
248
|
+
def page_includes
|
249
|
+
Alchemy::EagerLoading.page_includes(version: :public_version)
|
250
|
+
end
|
237
251
|
end
|
238
252
|
end
|
@@ -36,6 +36,29 @@ module Alchemy
|
|
36
36
|
element.definition.fetch(:ingredients, []).any?
|
37
37
|
end
|
38
38
|
|
39
|
+
# Returns the translated content/ingredient group for displaying in admin editor group headings
|
40
|
+
#
|
41
|
+
# Translate it in your locale yml file:
|
42
|
+
#
|
43
|
+
# alchemy:
|
44
|
+
# element_groups:
|
45
|
+
# foo: Bar
|
46
|
+
#
|
47
|
+
# Optionally you can scope your ingredient role to an element:
|
48
|
+
#
|
49
|
+
# alchemy:
|
50
|
+
# element_groups:
|
51
|
+
# article:
|
52
|
+
# foo: Baz
|
53
|
+
#
|
54
|
+
def translated_group(group)
|
55
|
+
Alchemy.t(
|
56
|
+
group,
|
57
|
+
scope: "element_groups.#{element.name}",
|
58
|
+
default: Alchemy.t("element_groups.#{group}", default: group.humanize),
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
39
62
|
# CSS classes for the element editor partial.
|
40
63
|
def css_classes
|
41
64
|
[
|
@@ -4,7 +4,10 @@ module Alchemy
|
|
4
4
|
class PublishPageJob < BaseJob
|
5
5
|
queue_as :default
|
6
6
|
|
7
|
-
def perform(
|
7
|
+
def perform(page_id, public_on:)
|
8
|
+
page = Alchemy::Page.includes(
|
9
|
+
Alchemy::EagerLoading.page_includes(version: :draft_version)
|
10
|
+
).find(page_id)
|
8
11
|
Alchemy::Page::Publisher.new(page).publish!(public_on: public_on)
|
9
12
|
end
|
10
13
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Alchemy
|
4
|
+
# Eager loading parameters for loading pages
|
5
|
+
class EagerLoading
|
6
|
+
PAGE_VERSIONS = %i[draft_version public_version]
|
7
|
+
|
8
|
+
class << self
|
9
|
+
# Eager loading parameters for {ActiveRecord::Base.includes}
|
10
|
+
#
|
11
|
+
# Pass this to +includes+ whereever you load an {Alchemy::Page}
|
12
|
+
#
|
13
|
+
# Alchemy::Page.includes(Alchemy::EagerLoading.page_includes).find_by(urlname: "my-page")
|
14
|
+
#
|
15
|
+
# @param version [Symbol] Type of page version to eager load
|
16
|
+
# @return [Array]
|
17
|
+
def page_includes(version: :public_version)
|
18
|
+
raise UnsupportedPageVersion unless version.in? PAGE_VERSIONS
|
19
|
+
|
20
|
+
[
|
21
|
+
:tags,
|
22
|
+
{
|
23
|
+
language: :site,
|
24
|
+
version => {
|
25
|
+
elements: [
|
26
|
+
:page,
|
27
|
+
:touchable_pages,
|
28
|
+
{
|
29
|
+
ingredients: :related_object,
|
30
|
+
contents: :essence,
|
31
|
+
},
|
32
|
+
],
|
33
|
+
},
|
34
|
+
},
|
35
|
+
]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -12,7 +12,9 @@ module Alchemy
|
|
12
12
|
|
13
13
|
# Copies all currently visible elements to the public version of page
|
14
14
|
#
|
15
|
-
# Creates a new published version if none exists yet
|
15
|
+
# Creates a new published version if none exists yet and updates
|
16
|
+
# the `published_at` timestamp of the page.
|
17
|
+
# `published_at` is used as a cache key.
|
16
18
|
#
|
17
19
|
# Sends a publish notification to all registered publish targets
|
18
20
|
#
|
@@ -32,6 +34,7 @@ module Alchemy
|
|
32
34
|
end
|
33
35
|
end
|
34
36
|
end
|
37
|
+
page.update(published_at: public_on)
|
35
38
|
end
|
36
39
|
|
37
40
|
Alchemy.publish_targets.each { |p| p.perform_later(page) }
|
data/app/models/alchemy/page.rb
CHANGED
@@ -457,15 +457,10 @@ module Alchemy
|
|
457
457
|
end
|
458
458
|
end
|
459
459
|
|
460
|
-
# Creates a public version of the page.
|
461
|
-
#
|
462
|
-
# Sets the +published_at+ value to current time
|
463
|
-
#
|
464
|
-
# The +published_at+ attribute is used as +cache_key+.
|
460
|
+
# Creates a public version of the page in the background.
|
465
461
|
#
|
466
462
|
def publish!(current_time = Time.current)
|
467
|
-
|
468
|
-
PublishPageJob.perform_later(self, public_on: current_time)
|
463
|
+
PublishPageJob.perform_later(id, public_on: current_time)
|
469
464
|
end
|
470
465
|
|
471
466
|
# Sets the public_on date on the published version
|
@@ -23,15 +23,44 @@
|
|
23
23
|
html: {id: "element_#{element.id}_form".html_safe, class: 'element-content'} do |f| %>
|
24
24
|
|
25
25
|
<div id="element_<%= element.id %>_errors" class="element_errors"></div>
|
26
|
+
|
27
|
+
<!-- Ingredients -->
|
26
28
|
<% if element.has_ingredients_defined? %>
|
27
29
|
<div class="element-ingredient-editors">
|
28
|
-
<%= render element.ingredients, element_form: f %>
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
<%= render element.ingredients.select { |i| !i.definition[:group] }, element_form: f %>
|
31
|
+
|
32
|
+
<!-- Each ingredient group -->
|
33
|
+
<% element.ingredients.select { |i| i.definition[:group] }.group_by { |i| i.definition[:group] }.each do |group, ingredients| %>
|
34
|
+
<div class="content-group">
|
35
|
+
<%= link_to '#', id: "element_#{element.id}_content_group_#{group.parameterize.underscore}_header", class: 'content-group-header', data: { toggle_content_group: true } do %>
|
36
|
+
<%= element.translated_group group %>
|
37
|
+
<i class="content-group-expand icon fa-fw fa-angle-down fas"></i>
|
38
|
+
<% end %>
|
39
|
+
<%= content_tag :div, id: "element_#{element.id}_content_group_#{group.parameterize.underscore}", class: 'content-group-contents' do %>
|
40
|
+
<%= render ingredients, element_form: f %>
|
41
|
+
<% end %>
|
42
|
+
</div>
|
43
|
+
<% end %>
|
33
44
|
</div>
|
34
45
|
<% end %>
|
46
|
+
<!-- Contents -->
|
47
|
+
<div id="element_<%= element.id %>_content" class="element-content-editors">
|
48
|
+
<%= render element.contents.select { |c| !c.definition[:group] } %>
|
49
|
+
|
50
|
+
<!-- Each content group -->
|
51
|
+
<% element.contents.select { |c| c.definition[:group] }.group_by { |c| c.definition[:group] }.each do |group, contents| %>
|
52
|
+
<div class="content-group">
|
53
|
+
<%= link_to '#', id: "element_#{element.id}_content_group_#{group.parameterize.underscore}_header", class: 'content-group-header', data: { toggle_content_group: true } do %>
|
54
|
+
<%= element.translated_group group %>
|
55
|
+
<i class="content-group-expand icon fa-fw fa-angle-down fas"></i>
|
56
|
+
<% end %>
|
57
|
+
<%= content_tag :div, id: "element_#{element.id}_content_group_#{group.parameterize.underscore}", class: 'content-group-contents' do %>
|
58
|
+
<%= render contents, element_form: f %>
|
59
|
+
<% end %>
|
60
|
+
</div>
|
61
|
+
<% end %>
|
62
|
+
</div>
|
63
|
+
|
35
64
|
<% if element.taggable? %>
|
36
65
|
<div class="autocomplete_tag_list">
|
37
66
|
<%= f.label :tag_list %>
|
data/lib/alchemy/errors.rb
CHANGED
@@ -11,7 +11,7 @@ module Alchemy
|
|
11
11
|
# Raised if no default language configuration can be found.
|
12
12
|
def message
|
13
13
|
"No default language configuration found!" \
|
14
|
-
|
14
|
+
" Please ensure that you have a 'default_language' defined in Alchemy configuration file."
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
@@ -19,7 +19,7 @@ module Alchemy
|
|
19
19
|
# Raised if no default site configuration can be found.
|
20
20
|
def message
|
21
21
|
"No default site configuration found!" \
|
22
|
-
|
22
|
+
" Please ensure that you have a 'default_site' defined in Alchemy configuration file."
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
@@ -90,4 +90,10 @@ module Alchemy
|
|
90
90
|
"You need to provide a current_user method in your ApplicationController that returns the current authenticated user."
|
91
91
|
end
|
92
92
|
end
|
93
|
+
|
94
|
+
class UnsupportedPageVersion < StandardError
|
95
|
+
def message
|
96
|
+
"Unknown Version! Please use one of #{Alchemy::EagerLoading::PAGE_VERSIONS.join(", ")}"
|
97
|
+
end
|
98
|
+
end
|
93
99
|
end
|
@@ -16,7 +16,7 @@ module Alchemy::Upgrader::Tasks
|
|
16
16
|
# eager load all elements that have ingredients defined but no ingredient records yet.
|
17
17
|
all_elements = Alchemy::Element
|
18
18
|
.named(elements_with_ingredients.map { |d| d[:name] })
|
19
|
-
.
|
19
|
+
.preload(contents: :essence)
|
20
20
|
.left_outer_joins(:ingredients).where(alchemy_ingredients: { id: nil })
|
21
21
|
.to_a
|
22
22
|
elements_with_ingredients.map do |element_definition|
|
data/lib/alchemy/version.rb
CHANGED
@@ -35,5 +35,29 @@ namespace :alchemy do
|
|
35
35
|
|
36
36
|
puts "Done!"
|
37
37
|
end
|
38
|
+
|
39
|
+
desc "Generates thumbnails for Alchemy Picture Ingredients (set ELEMENTS=element1,element2 to only generate thumbnails for a subset of elements)."
|
40
|
+
task ingredient_picture_thumbnails: :environment do
|
41
|
+
ingredient_pictures = Alchemy::Ingredients::Picture.
|
42
|
+
joins(:element).
|
43
|
+
preload({ related_object: :thumbs }).
|
44
|
+
merge(Alchemy::Element.available)
|
45
|
+
|
46
|
+
if ENV["ELEMENTS"].present?
|
47
|
+
ingredient_pictures = ingredient_pictures.merge(
|
48
|
+
Alchemy::Element.named(ENV["ELEMENTS"].split(","))
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
puts "Regenerate #{ingredient_pictures.count} ingredient picture thumbnails."
|
53
|
+
puts "Please wait..."
|
54
|
+
|
55
|
+
ingredient_pictures.find_each do |ingredient_picture|
|
56
|
+
puts ingredient_picture.picture_url
|
57
|
+
puts ingredient_picture.thumbnail_url
|
58
|
+
end
|
59
|
+
|
60
|
+
puts "Done!"
|
61
|
+
end
|
38
62
|
end
|
39
63
|
end
|
data/package.json
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alchemy_cms
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.0.
|
4
|
+
version: 6.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas von Deyen
|
@@ -13,7 +13,7 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date: 2022-05-
|
16
|
+
date: 2022-05-30 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: actionmailer
|
@@ -916,6 +916,7 @@ files:
|
|
916
916
|
- app/models/alchemy/base_record.rb
|
917
917
|
- app/models/alchemy/content.rb
|
918
918
|
- app/models/alchemy/content/factory.rb
|
919
|
+
- app/models/alchemy/eager_loading.rb
|
919
920
|
- app/models/alchemy/element.rb
|
920
921
|
- app/models/alchemy/element/definitions.rb
|
921
922
|
- app/models/alchemy/element/element_contents.rb
|