alchemy_cms 6.0.0 → 6.0.1
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/workflows/ci.yml +7 -0
- data/CHANGELOG.md +21 -0
- data/Gemfile +12 -0
- data/README.md +4 -3
- data/app/controllers/alchemy/admin/elements_controller.rb +18 -11
- data/app/controllers/alchemy/admin/pages_controller.rb +9 -4
- data/app/controllers/alchemy/api/base_controller.rb +4 -3
- data/app/controllers/alchemy/api/nodes_controller.rb +1 -0
- data/app/controllers/alchemy/base_controller.rb +7 -0
- data/app/controllers/alchemy/messages_controller.rb +0 -3
- data/app/controllers/alchemy/pages_controller.rb +0 -7
- data/app/helpers/alchemy/elements_helper.rb +17 -12
- data/app/models/alchemy/element.rb +13 -6
- data/app/models/alchemy/ingredient.rb +4 -0
- data/app/models/alchemy/ingredient_validator.rb +1 -1
- data/app/models/alchemy/language.rb +1 -1
- data/app/models/alchemy/page/page_elements.rb +2 -2
- data/app/models/alchemy/page/page_naming.rb +1 -1
- data/app/models/alchemy/page.rb +1 -1
- data/app/models/alchemy/picture/transformations.rb +2 -2
- data/app/models/alchemy/picture_variant.rb +3 -1
- data/app/models/alchemy/site.rb +1 -1
- data/app/views/alchemy/admin/clipboard/insert.js.erb +13 -0
- data/app/views/alchemy/admin/elements/_add_nested_element_form.html.erb +27 -0
- data/app/views/alchemy/admin/elements/_element.html.erb +1 -23
- data/app/views/alchemy/admin/elements/_form.html.erb +5 -1
- data/app/views/alchemy/essences/_essence_node_editor.html.erb +1 -1
- data/config/initializers/dragonfly.rb +2 -0
- data/lib/alchemy/config.rb +5 -1
- data/lib/alchemy/controller_actions.rb +2 -1
- data/lib/alchemy/dragonfly/processors/thumbnail.rb +27 -0
- data/lib/alchemy/element_definition.rb +2 -3
- data/lib/alchemy/elements_finder.rb +1 -2
- data/lib/alchemy/essence.rb +1 -1
- data/lib/alchemy/page_layout.rb +5 -1
- data/lib/alchemy/permissions.rb +2 -2
- data/lib/alchemy/version.rb +1 -1
- data/lib/alchemy.rb +2 -4
- data/lib/generators/alchemy/base.rb +7 -3
- data/lib/generators/alchemy/install/install_generator.rb +4 -1
- data/package.json +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0ccd47bae7272d0d8cb44b6d9c63cd8b72df01f086eff929819164d267af6bf1
|
|
4
|
+
data.tar.gz: d18a5f8105f242cef352e0c57d6d21743aedfdd75cc373bbf4205fd3d2cac5f1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 81b2e1e18d80a8cce6316286e91063e9363ded99c991de526f0155d98f9954a3986487bec834205847f364c883ecb8959777a55fbe14fdfdb9409f32818376fa
|
|
7
|
+
data.tar.gz: 39086e8836ff34ec6eb7abf76403b2f6a0515e6d46e6f77f76fe81b480f6a9cba65ae1ba3e0af390f79d8234d42f5ab218fd50ea14643e3ac8d89594de8bb1a2
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -16,10 +16,17 @@ jobs:
|
|
|
16
16
|
- "2.6"
|
|
17
17
|
- "2.7"
|
|
18
18
|
- "3.0"
|
|
19
|
+
- "3.1"
|
|
19
20
|
database:
|
|
20
21
|
- mysql
|
|
21
22
|
- postgresql
|
|
22
23
|
exclude:
|
|
24
|
+
- rails: "6.0"
|
|
25
|
+
ruby: "3.1"
|
|
26
|
+
database: mysql
|
|
27
|
+
- rails: "6.0"
|
|
28
|
+
ruby: "3.1"
|
|
29
|
+
database: postgresql
|
|
23
30
|
- rails: "7.0"
|
|
24
31
|
ruby: "2.6"
|
|
25
32
|
database: mysql
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
## 6.0.1 (2022-04-26)
|
|
2
|
+
|
|
3
|
+
- Allow passing a different partial to `render_element` [#2322](https://github.com/AlchemyCMS/alchemy_cms/pull/2322) ([mamhoff](https://github.com/mamhoff))
|
|
4
|
+
- Allow render_elements to take a block [#2321](https://github.com/AlchemyCMS/alchemy_cms/pull/2321) ([mamhoff](https://github.com/mamhoff))
|
|
5
|
+
- Remove old unused root_page ivar [#2320](https://github.com/AlchemyCMS/alchemy_cms/pull/2320) ([tvdeyen](https://github.com/tvdeyen))
|
|
6
|
+
- Raise on non-existing locale [#2319](https://github.com/AlchemyCMS/alchemy_cms/pull/2319) ([mamhoff](https://github.com/mamhoff))
|
|
7
|
+
- chore: Remove unnecessary puts from spec [#2318](https://github.com/AlchemyCMS/alchemy_cms/pull/2318) ([tvdeyen](https://github.com/tvdeyen))
|
|
8
|
+
- Fix gif resizing [#2315](https://github.com/AlchemyCMS/alchemy_cms/pull/2315) ([kulturbande](https://github.com/kulturbande))
|
|
9
|
+
- Refactor: Use page version's element repository rather than a new one [#2312](https://github.com/AlchemyCMS/alchemy_cms/pull/2312) ([mamhoff](https://github.com/mamhoff))
|
|
10
|
+
- Deprecate Alchemy::Element.available [#2309](https://github.com/AlchemyCMS/alchemy_cms/pull/2309) ([mamhoff](https://github.com/mamhoff))
|
|
11
|
+
- Explicitly set "store" for MariaDB [#2308](https://github.com/AlchemyCMS/alchemy_cms/pull/2308) ([mamhoff](https://github.com/mamhoff))
|
|
12
|
+
- Set preview mode earlier [#2307](https://github.com/AlchemyCMS/alchemy_cms/pull/2307) ([mamhoff](https://github.com/mamhoff))
|
|
13
|
+
- Fix updating the public_on date on persisted pages [#2305](https://github.com/AlchemyCMS/alchemy_cms/pull/2305) ([mamhoff](https://github.com/mamhoff))
|
|
14
|
+
- Allow opting out of Turbolinks in non-Alchemy controllers [#2302](https://github.com/AlchemyCMS/alchemy_cms/pull/2302) ([dssjoblom](https://github.com/dssjoblom))
|
|
15
|
+
- Explicitly validate uniqueness without case sensitivity [#2300](https://github.com/AlchemyCMS/alchemy_cms/pull/2300) ([mamhoff](https://github.com/mamhoff))
|
|
16
|
+
- Fix frozen string error when mixing template engines [#2299](https://github.com/AlchemyCMS/alchemy_cms/pull/2299) ([gr8bit](https://github.com/gr8bit))
|
|
17
|
+
- Do not flatten gifs if converted to webp [#2293](https://github.com/AlchemyCMS/alchemy_cms/pull/2293) ([tvdeyen](https://github.com/tvdeyen))
|
|
18
|
+
- Allow pasting into parent element with only one nested element type [#2292](https://github.com/AlchemyCMS/alchemy_cms/pull/2292) ([dbwinger](https://github.com/dbwinger))
|
|
19
|
+
- Restrict Node select to the site/language of the page being edited [#2277](https://github.com/AlchemyCMS/alchemy_cms/pull/2277) ([dbwinger](https://github.com/dbwinger))
|
|
20
|
+
- Add Ruby 3.1 support [#2229](https://github.com/AlchemyCMS/alchemy_cms/pull/2229) ([tvdeyen](https://github.com/tvdeyen))
|
|
21
|
+
|
|
1
22
|
## 6.0.0 (2022-04-11)
|
|
2
23
|
|
|
3
24
|
- [ruby - main] Allow ransack version 3.0.1 [#2287](https://github.com/AlchemyCMS/alchemy_cms/pull/2287) ([depfu](https://github.com/apps/depfu))
|
data/Gemfile
CHANGED
|
@@ -48,3 +48,15 @@ group :development, :test do
|
|
|
48
48
|
gem "brakeman", require: false
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
|
+
|
|
52
|
+
# Ruby 3.1 split out the net-smtp gem
|
|
53
|
+
# Necessary until https://github.com/mikel/mail/pull/1439
|
|
54
|
+
# got merged and released.
|
|
55
|
+
if Gem.ruby_version >= Gem::Version.new("3.1.0")
|
|
56
|
+
if rails_version.to_s.match?(/6.1/)
|
|
57
|
+
# Rails 6.1 needs this as well
|
|
58
|
+
gem "net-pop", "~> 0.1.0", require: false
|
|
59
|
+
gem "net-imap", "~> 0.2.0", require: false
|
|
60
|
+
end
|
|
61
|
+
gem "net-smtp", "~> 0.3.0", require: false
|
|
62
|
+
end
|
data/README.md
CHANGED
|
@@ -18,7 +18,7 @@ Alchemy is an open source CMS engine written in Ruby on Rails.
|
|
|
18
18
|
|
|
19
19
|
Read more about Alchemy on the [website](https://alchemy-cms.com) and in the [guidelines](https://guides.alchemy-cms.com).
|
|
20
20
|
|
|
21
|
-
**CAUTION: This main branch is a development branch that *can* contain bugs. For productive environments you should use the [current Ruby gem version](https://rubygems.org/gems/alchemy_cms), or the [latest stable branch (
|
|
21
|
+
**CAUTION: This main branch is a development branch that *can* contain bugs. For productive environments you should use the [current Ruby gem version](https://rubygems.org/gems/alchemy_cms), or the [latest stable branch (6.0-stable)](https://github.com/AlchemyCMS/alchemy_cms/tree/6.0-stable).**
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
## ✅ Features
|
|
@@ -27,6 +27,7 @@ Read more about Alchemy on the [website](https://alchemy-cms.com) and in the [gu
|
|
|
27
27
|
- A rich RESTful API
|
|
28
28
|
- Intuitive admin interface with live preview
|
|
29
29
|
- Multi language and multi domain
|
|
30
|
+
- Page versioning
|
|
30
31
|
- SEO friendly urls
|
|
31
32
|
- User Access Control
|
|
32
33
|
- Build in contact form mailer
|
|
@@ -51,9 +52,9 @@ or visit the existing demo at https://alchemy-demo.herokuapp.com
|
|
|
51
52
|
|
|
52
53
|
## 🚂 Rails Version
|
|
53
54
|
|
|
54
|
-
**This version of AlchemyCMS runs with Rails 6.0**
|
|
55
|
+
**This version of AlchemyCMS runs with Rails 7.0, 6.1 and 6.0**
|
|
55
56
|
|
|
56
|
-
* For a Rails 5.2 compatible version use the [`5.
|
|
57
|
+
* For a Rails 5.2 compatible version use the [`5.3-stable` branch](https://github.com/AlchemyCMS/alchemy_cms/tree/5.3-stable).
|
|
57
58
|
* For a Rails 5.0 or 5.1 compatible version use the [`4.5-stable` branch](https://github.com/AlchemyCMS/alchemy_cms/tree/4.5-stable).
|
|
58
59
|
* For a Rails 4.2 compatible version use the [`3.6-stable` branch](https://github.com/AlchemyCMS/alchemy_cms/tree/3.6-stable).
|
|
59
60
|
* For a Rails 4.0/4.1 compatible version use the [`3.1-stable` branch](https://github.com/AlchemyCMS/alchemy_cms/tree/3.1-stable).
|
|
@@ -12,6 +12,7 @@ module Alchemy
|
|
|
12
12
|
elements = @page_version.elements.order(:position).includes(*element_includes)
|
|
13
13
|
@elements = elements.not_nested.unfixed
|
|
14
14
|
@fixed_elements = elements.not_nested.fixed
|
|
15
|
+
load_clipboard_items
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
def new
|
|
@@ -20,8 +21,7 @@ module Alchemy
|
|
|
20
21
|
@parent_element = Element.find_by(id: params[:parent_element_id])
|
|
21
22
|
@elements = @page.available_elements_within_current_scope(@parent_element)
|
|
22
23
|
@element = @page_version.elements.build
|
|
23
|
-
|
|
24
|
-
@clipboard_items = Element.all_from_clipboard_for_page(@clipboard, @page)
|
|
24
|
+
load_clipboard_items
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
# Creates a element as discribed in config/alchemy/elements.yml on page via AJAX.
|
|
@@ -44,8 +44,7 @@ module Alchemy
|
|
|
44
44
|
else
|
|
45
45
|
@element.page_version = @page_version
|
|
46
46
|
@elements = @page.available_element_definitions
|
|
47
|
-
|
|
48
|
-
@clipboard_items = Element.all_from_clipboard_for_page(@clipboard, @page)
|
|
47
|
+
load_clipboard_items
|
|
49
48
|
render :new
|
|
50
49
|
end
|
|
51
50
|
end
|
|
@@ -126,19 +125,27 @@ module Alchemy
|
|
|
126
125
|
@element = Element.find(params[:id])
|
|
127
126
|
end
|
|
128
127
|
|
|
128
|
+
def load_clipboard_items
|
|
129
|
+
@clipboard = get_clipboard("elements")
|
|
130
|
+
@clipboard_items = Element.all_from_clipboard_for_page(@clipboard, @page)
|
|
131
|
+
end
|
|
132
|
+
|
|
129
133
|
def element_from_clipboard
|
|
130
134
|
@element_from_clipboard ||= begin
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
135
|
+
@clipboard = get_clipboard("elements")
|
|
136
|
+
@clipboard.detect { |item| item["id"].to_i == params[:paste_from_clipboard].to_i }
|
|
137
|
+
end
|
|
134
138
|
end
|
|
135
139
|
|
|
136
140
|
def paste_element_from_clipboard
|
|
137
141
|
@source_element = Element.find(element_from_clipboard["id"])
|
|
138
|
-
element = Element.copy(
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
+
element = Element.copy(
|
|
143
|
+
@source_element,
|
|
144
|
+
{
|
|
145
|
+
parent_element_id: create_element_params[:parent_element_id],
|
|
146
|
+
page_version_id: @page_version.id,
|
|
147
|
+
}
|
|
148
|
+
)
|
|
142
149
|
if element_from_clipboard["action"] == "cut"
|
|
143
150
|
@cut_element_id = @source_element.id
|
|
144
151
|
@clipboard.delete_if { |item| item["id"] == @source_element.id.to_s }
|
|
@@ -23,9 +23,7 @@ module Alchemy
|
|
|
23
23
|
before_action :set_root_page,
|
|
24
24
|
only: [:index, :show, :order]
|
|
25
25
|
|
|
26
|
-
before_action :
|
|
27
|
-
if: :run_on_page_layout_callbacks?,
|
|
28
|
-
only: [:show]
|
|
26
|
+
before_action :set_preview_mode, only: [:show]
|
|
29
27
|
|
|
30
28
|
before_action :load_languages_and_layouts,
|
|
31
29
|
unless: -> { @page_root },
|
|
@@ -35,6 +33,10 @@ module Alchemy
|
|
|
35
33
|
|
|
36
34
|
before_action :set_page_version, only: [:show, :edit]
|
|
37
35
|
|
|
36
|
+
before_action :run_on_page_layout_callbacks,
|
|
37
|
+
if: :run_on_page_layout_callbacks?,
|
|
38
|
+
only: [:show]
|
|
39
|
+
|
|
38
40
|
def index
|
|
39
41
|
@query = @current_language.pages.contentpages.ransack(search_filter_params[:q])
|
|
40
42
|
|
|
@@ -64,7 +66,6 @@ module Alchemy
|
|
|
64
66
|
# Used by page preview iframe in Page#edit view.
|
|
65
67
|
#
|
|
66
68
|
def show
|
|
67
|
-
@preview_mode = true
|
|
68
69
|
Page.current_preview = @page
|
|
69
70
|
# Setting the locale to pages language, so the page content has it's correct translations.
|
|
70
71
|
::I18n.locale = @page.language.locale
|
|
@@ -397,6 +398,10 @@ module Alchemy
|
|
|
397
398
|
@languages_with_page_tree = Language.on_current_site.with_root_page
|
|
398
399
|
@page_layouts = PageLayout.layouts_for_select(@language.id)
|
|
399
400
|
end
|
|
401
|
+
|
|
402
|
+
def set_preview_mode
|
|
403
|
+
@preview_mode = true
|
|
404
|
+
end
|
|
400
405
|
end
|
|
401
406
|
end
|
|
402
407
|
end
|
|
@@ -5,17 +5,18 @@ module Alchemy
|
|
|
5
5
|
layout false
|
|
6
6
|
respond_to :json
|
|
7
7
|
|
|
8
|
-
rescue_from CanCan::AccessDenied,
|
|
8
|
+
rescue_from CanCan::AccessDenied, with: :render_not_authorized
|
|
9
9
|
rescue_from ActiveRecord::RecordNotFound, with: :render_not_found
|
|
10
|
+
rescue_from ActionController::RoutingError, with: :render_not_found
|
|
10
11
|
|
|
11
12
|
private
|
|
12
13
|
|
|
13
14
|
def render_not_authorized
|
|
14
|
-
render json: {error: "Not authorized"}, status: 403
|
|
15
|
+
render json: { error: "Not authorized" }, status: 403
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
def render_not_found
|
|
18
|
-
render json: {error: "Record not found"}, status: 404
|
|
19
|
+
render json: { error: "Record not found" }, status: 404
|
|
19
20
|
end
|
|
20
21
|
end
|
|
21
22
|
end
|
|
@@ -9,6 +9,13 @@ module Alchemy
|
|
|
9
9
|
include Alchemy::ControllerActions
|
|
10
10
|
include Alchemy::Modules
|
|
11
11
|
|
|
12
|
+
# Include Turbolinks explicitly in case Alchemy is embedded into a
|
|
13
|
+
# larger application that doesn't work with Turbolinks. The app
|
|
14
|
+
# can then set config.turbolinks.auto_include = false so that
|
|
15
|
+
# Turbolinks is not included in the app controllers.
|
|
16
|
+
include Turbolinks::Controller
|
|
17
|
+
::ActionDispatch::Assertions.include ::Turbolinks::Assertions
|
|
18
|
+
|
|
12
19
|
protect_from_forgery
|
|
13
20
|
|
|
14
21
|
before_action :mailer_set_url_options
|
|
@@ -62,7 +62,6 @@ module Alchemy
|
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
@page = @element.page
|
|
65
|
-
@root_page = @page.get_language_root
|
|
66
65
|
if @message.valid?
|
|
67
66
|
MessagesMailer.contact_form_mail(@message, mail_to, mail_from, subject).deliver
|
|
68
67
|
redirect_to_success_page
|
|
@@ -122,8 +121,6 @@ module Alchemy
|
|
|
122
121
|
if @page.blank?
|
|
123
122
|
raise "Page for page_layout #{mailer_config["page_layout_name"]} not found"
|
|
124
123
|
end
|
|
125
|
-
|
|
126
|
-
@root_page = @page.get_language_root
|
|
127
124
|
end
|
|
128
125
|
|
|
129
126
|
def message_params
|
|
@@ -32,9 +32,6 @@ module Alchemy
|
|
|
32
32
|
if: :locale_prefix_missing?,
|
|
33
33
|
only: [:index, :show]
|
|
34
34
|
|
|
35
|
-
# We only need to set the +@root_page+ if we are sure that no more redirects happen.
|
|
36
|
-
before_action :set_root_page, only: [:index, :show]
|
|
37
|
-
|
|
38
35
|
# Page layout callbacks need to run after all other callbacks
|
|
39
36
|
before_action :run_on_page_layout_callbacks,
|
|
40
37
|
if: :run_on_page_layout_callbacks?,
|
|
@@ -199,10 +196,6 @@ module Alchemy
|
|
|
199
196
|
end
|
|
200
197
|
end
|
|
201
198
|
|
|
202
|
-
def set_root_page
|
|
203
|
-
@root_page ||= Language.current_root_page
|
|
204
|
-
end
|
|
205
|
-
|
|
206
199
|
def signup_required?
|
|
207
200
|
if Alchemy.user_class.respond_to?(:admins)
|
|
208
201
|
Alchemy.user_class.admins.empty? && @page.nil?
|
|
@@ -70,7 +70,7 @@ module Alchemy
|
|
|
70
70
|
# A class instance that will return elements that get rendered.
|
|
71
71
|
# Use this for your custom element loading logic in views.
|
|
72
72
|
#
|
|
73
|
-
def render_elements(options = {})
|
|
73
|
+
def render_elements(options = {}, &blk)
|
|
74
74
|
options = {
|
|
75
75
|
from_page: @page,
|
|
76
76
|
render_format: "html",
|
|
@@ -86,11 +86,12 @@ module Alchemy
|
|
|
86
86
|
|
|
87
87
|
elements = finder.elements(page_version: page_version)
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
default_rendering = ->(element, i) { render_element(element, options, i + 1) }
|
|
90
|
+
if block_given?
|
|
91
|
+
elements.map.with_index(&blk)
|
|
92
|
+
else
|
|
93
|
+
elements.map.with_index(&default_rendering)
|
|
94
|
+
end.join(options[:separator]).html_safe
|
|
94
95
|
end
|
|
95
96
|
|
|
96
97
|
# This helper renders a {Alchemy::Element} view partial.
|
|
@@ -125,7 +126,7 @@ module Alchemy
|
|
|
125
126
|
#
|
|
126
127
|
# == Usage
|
|
127
128
|
#
|
|
128
|
-
# <%= render_element(Alchemy::Element.
|
|
129
|
+
# <%= render_element(Alchemy::Element.published.named(:headline).first) %>
|
|
129
130
|
#
|
|
130
131
|
# @param [Alchemy::Element] element
|
|
131
132
|
# The element you want to render the view for
|
|
@@ -146,11 +147,15 @@ module Alchemy
|
|
|
146
147
|
|
|
147
148
|
element.store_page(@page)
|
|
148
149
|
|
|
149
|
-
render
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
150
|
+
render(
|
|
151
|
+
partial: options[:partial] || element.to_partial_path,
|
|
152
|
+
object: element,
|
|
153
|
+
locals: {
|
|
154
|
+
element: element,
|
|
155
|
+
counter: counter,
|
|
156
|
+
options: options.except(:locals, :partial),
|
|
157
|
+
}.merge(options[:locals] || {}),
|
|
158
|
+
)
|
|
154
159
|
rescue ActionView::MissingTemplate => e
|
|
155
160
|
warning(%(
|
|
156
161
|
Element view partial not found for #{element.name}.\n
|
|
@@ -70,7 +70,7 @@ module Alchemy
|
|
|
70
70
|
dependent: :destroy
|
|
71
71
|
|
|
72
72
|
has_many :nested_elements,
|
|
73
|
-
-> { order(:position).
|
|
73
|
+
-> { order(:position).published },
|
|
74
74
|
class_name: "Alchemy::Element",
|
|
75
75
|
foreign_key: :parent_element_id,
|
|
76
76
|
dependent: :destroy,
|
|
@@ -159,7 +159,7 @@ module Alchemy
|
|
|
159
159
|
end
|
|
160
160
|
|
|
161
161
|
def all_from_clipboard(clipboard)
|
|
162
|
-
return
|
|
162
|
+
return none if clipboard.nil?
|
|
163
163
|
|
|
164
164
|
where(id: clipboard.collect { |e| e["id"] })
|
|
165
165
|
end
|
|
@@ -167,12 +167,19 @@ module Alchemy
|
|
|
167
167
|
# All elements in clipboard that could be placed on page
|
|
168
168
|
#
|
|
169
169
|
def all_from_clipboard_for_page(clipboard, page)
|
|
170
|
-
return
|
|
170
|
+
return none if clipboard.nil? || page.nil?
|
|
171
171
|
|
|
172
|
-
all_from_clipboard(clipboard).
|
|
173
|
-
page.available_element_names.include?(ce.name)
|
|
174
|
-
}
|
|
172
|
+
all_from_clipboard(clipboard).where(name: page.available_element_names)
|
|
175
173
|
end
|
|
174
|
+
|
|
175
|
+
# All elements in clipboard that could be placed as a child of `parent_element`
|
|
176
|
+
def all_from_clipboard_for_parent_element(clipboard, parent_element)
|
|
177
|
+
return none if clipboard.nil? || parent_element.nil?
|
|
178
|
+
|
|
179
|
+
all_from_clipboard(clipboard).where(name: parent_element.definition["nestable_elements"])
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
deprecate available: :published, deprecator: Alchemy::Deprecation
|
|
176
183
|
end
|
|
177
184
|
|
|
178
185
|
# Returns next public element from same page.
|
|
@@ -6,6 +6,10 @@ module Alchemy
|
|
|
6
6
|
|
|
7
7
|
include Hints
|
|
8
8
|
|
|
9
|
+
# MariaDB needs to be told explicitly to use `data` as a JSON store. All other databases
|
|
10
|
+
# can do this natively.
|
|
11
|
+
store :data, coder: JSON
|
|
12
|
+
|
|
9
13
|
self.table_name = "alchemy_ingredients"
|
|
10
14
|
|
|
11
15
|
belongs_to :element, touch: true, class_name: "Alchemy::Element", inverse_of: :ingredients
|
|
@@ -88,7 +88,7 @@ module Alchemy
|
|
|
88
88
|
|
|
89
89
|
def duplicates
|
|
90
90
|
ingredient.class
|
|
91
|
-
.joins(:element).merge(Alchemy::Element.
|
|
91
|
+
.joins(:element).merge(Alchemy::Element.published)
|
|
92
92
|
.where(Alchemy::Element.table_name => { name: ingredient.element.name })
|
|
93
93
|
.where(value: ingredient.value)
|
|
94
94
|
.where.not(id: ingredient.id)
|
|
@@ -38,7 +38,7 @@ module Alchemy
|
|
|
38
38
|
|
|
39
39
|
validates :language_code,
|
|
40
40
|
presence: true,
|
|
41
|
-
uniqueness: { scope: [:site_id, :country_code] },
|
|
41
|
+
uniqueness: { scope: [:site_id, :country_code], case_sensitive: false },
|
|
42
42
|
format: { with: /\A[a-z]{2}\z/, if: -> { language_code.present? } }
|
|
43
43
|
|
|
44
44
|
validates :country_code,
|
|
@@ -15,8 +15,8 @@ module Alchemy
|
|
|
15
15
|
source: :elements,
|
|
16
16
|
) do
|
|
17
17
|
has_many :all_elements
|
|
18
|
-
has_many :elements, -> { not_nested.unfixed.
|
|
19
|
-
has_many :fixed_elements, -> { fixed.
|
|
18
|
+
has_many :elements, -> { not_nested.unfixed.published }
|
|
19
|
+
has_many :fixed_elements, -> { fixed.published }
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
has_many :contents, through: :elements
|
|
@@ -15,7 +15,7 @@ module Alchemy
|
|
|
15
15
|
validates :name,
|
|
16
16
|
presence: true
|
|
17
17
|
validates :urlname,
|
|
18
|
-
uniqueness: { scope: [:language_id, :layoutpage], if: -> { urlname.present? } },
|
|
18
|
+
uniqueness: { scope: [:language_id, :layoutpage], if: -> { urlname.present? }, case_sensitive: false },
|
|
19
19
|
exclusion: { in: RESERVED_URLNAMES },
|
|
20
20
|
length: { minimum: 3, if: -> { urlname.present? } }
|
|
21
21
|
|
data/app/models/alchemy/page.rb
CHANGED
|
@@ -117,7 +117,7 @@ module Alchemy
|
|
|
117
117
|
has_many :nodes, class_name: "Alchemy::Node", inverse_of: :page
|
|
118
118
|
has_many :versions, class_name: "Alchemy::PageVersion", inverse_of: :page, dependent: :destroy
|
|
119
119
|
has_one :draft_version, -> { drafts }, class_name: "Alchemy::PageVersion"
|
|
120
|
-
has_one :public_version, -> { published }, class_name: "Alchemy::PageVersion"
|
|
120
|
+
has_one :public_version, -> { published }, class_name: "Alchemy::PageVersion", autosave: -> { persisted? }
|
|
121
121
|
|
|
122
122
|
before_validation :set_language,
|
|
123
123
|
if: -> { language.nil? }
|
|
@@ -30,7 +30,7 @@ module Alchemy
|
|
|
30
30
|
# Returns the rendered resized image using imagemagick directly.
|
|
31
31
|
#
|
|
32
32
|
def resize(size, upsample = false)
|
|
33
|
-
image_file.
|
|
33
|
+
image_file.thumbnail(upsample ? size : "#{size}>")
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
# Returns true if picture's width is greater than it's height
|
|
@@ -119,7 +119,7 @@ module Alchemy
|
|
|
119
119
|
if is_smaller_than?(dimensions) && upsample == false
|
|
120
120
|
dimensions = reduce_to_image(dimensions)
|
|
121
121
|
end
|
|
122
|
-
image_file.
|
|
122
|
+
image_file.thumbnail("#{dimensions_to_string(dimensions)}#")
|
|
123
123
|
end
|
|
124
124
|
|
|
125
125
|
# Use imagemagick to custom crop an image. Uses -thumbnail for better performance when resizing.
|
|
@@ -13,6 +13,8 @@ module Alchemy
|
|
|
13
13
|
include Alchemy::Logger
|
|
14
14
|
include Alchemy::Picture::Transformations
|
|
15
15
|
|
|
16
|
+
ANIMATED_IMAGE_FORMATS = %w[gif webp]
|
|
17
|
+
|
|
16
18
|
attr_reader :picture, :render_format
|
|
17
19
|
|
|
18
20
|
def_delegators :@picture,
|
|
@@ -86,7 +88,7 @@ module Alchemy
|
|
|
86
88
|
end
|
|
87
89
|
|
|
88
90
|
options = {
|
|
89
|
-
flatten: render_format
|
|
91
|
+
flatten: !render_format.in?(ANIMATED_IMAGE_FORMATS) && picture.image_file_format == "gif",
|
|
90
92
|
}.with_indifferent_access.merge(options)
|
|
91
93
|
|
|
92
94
|
encoding_options = []
|
data/app/models/alchemy/site.rb
CHANGED
|
@@ -14,3 +14,16 @@
|
|
|
14
14
|
Alchemy.growl('<%= j Alchemy.t("item copied to clipboard", name: @item.class.name == "Alchemy::Element" ? @item.display_name_with_preview_text : @item.name) %>')
|
|
15
15
|
<% end -%>
|
|
16
16
|
$('#clipboard_button .icon').removeClass('fa-clipboard').addClass('fa-paste');
|
|
17
|
+
|
|
18
|
+
<%# Update add nested element forms for any elements that accept ONLY this as a nested element %>
|
|
19
|
+
<% if @item.class == Alchemy::Element %>
|
|
20
|
+
if (window.location.pathname == "<%= edit_admin_page_path(@item.page.id) %>") {
|
|
21
|
+
<%
|
|
22
|
+
@item.page.draft_version.elements.expanded.select do |element|
|
|
23
|
+
element.definition["nestable_elements"] == [@item.name]
|
|
24
|
+
end.each do |element|
|
|
25
|
+
%>
|
|
26
|
+
$(".add-nested-element[data-element-id='<%= element.id %>']").replaceWith('<%= j render "alchemy/admin/elements/add_nested_element_form", element: element %>')
|
|
27
|
+
<% end %>
|
|
28
|
+
}
|
|
29
|
+
<% end %>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<%= content_tag :div, class: 'add-nested-element', data: { element_id: element.id } do %>
|
|
2
|
+
<% if element.expanded? || element.fixed? %>
|
|
3
|
+
<% if element.nestable_elements.length == 1 &&
|
|
4
|
+
(nestable_element = element.nestable_elements.first) &&
|
|
5
|
+
Alchemy::Element.all_from_clipboard_for_parent_element(get_clipboard("elements"), element).none?
|
|
6
|
+
%>
|
|
7
|
+
<%= form_for [:admin, Alchemy::Element.new(name: nestable_element)],
|
|
8
|
+
remote: true, html: { class: 'add-nested-element-form', id: nil } do |f| %>
|
|
9
|
+
<%= f.hidden_field :name %>
|
|
10
|
+
<%= f.hidden_field :page_version_id, value: element.page_version_id %>
|
|
11
|
+
<%= f.hidden_field :parent_element_id, value: element.id %>
|
|
12
|
+
<button class="button add-nestable-element-button" data-alchemy-button>
|
|
13
|
+
<%= Alchemy.t(:add_nested_element, name: Alchemy.t(nestable_element, scope: 'element_names')) %>
|
|
14
|
+
</button>
|
|
15
|
+
<% end %>
|
|
16
|
+
<% else %>
|
|
17
|
+
<%= link_to_dialog (nestable_element ? Alchemy.t(:add_nested_element, name: Alchemy.t(nestable_element, scope: 'element_names')) : Alchemy.t("New Element")),
|
|
18
|
+
alchemy.new_admin_element_path(
|
|
19
|
+
parent_element_id: element.id,
|
|
20
|
+
page_version_id: element.page_version_id
|
|
21
|
+
), {
|
|
22
|
+
size: "320x125",
|
|
23
|
+
title: Alchemy.t("New Element")
|
|
24
|
+
}, class: "button add-nestable-element-button" %>
|
|
25
|
+
<% end %>
|
|
26
|
+
<% end %>
|
|
27
|
+
<% end %>
|
|
@@ -55,29 +55,7 @@
|
|
|
55
55
|
} %>
|
|
56
56
|
<% end %>
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
<% if element.nestable_elements.length == 1 %>
|
|
60
|
-
<% nestable_element = element.nestable_elements.first %>
|
|
61
|
-
<%= form_for [:admin, Alchemy::Element.new(name: nestable_element)],
|
|
62
|
-
remote: true, html: { class: 'add-nested-element-form', id: nil } do |f| %>
|
|
63
|
-
<%= f.hidden_field :name %>
|
|
64
|
-
<%= f.hidden_field :page_version_id, value: element.page_version_id %>
|
|
65
|
-
<%= f.hidden_field :parent_element_id, value: element.id %>
|
|
66
|
-
<button class="button add-nestable-element-button" data-alchemy-button>
|
|
67
|
-
<%= Alchemy.t(:add_nested_element) % { name: Alchemy.t(nestable_element, scope: 'element_names') } %>
|
|
68
|
-
</button>
|
|
69
|
-
<% end %>
|
|
70
|
-
<% else %>
|
|
71
|
-
<%= link_to_dialog Alchemy.t("New Element"),
|
|
72
|
-
alchemy.new_admin_element_path(
|
|
73
|
-
parent_element_id: element.id,
|
|
74
|
-
page_version_id: element.page_version_id
|
|
75
|
-
), {
|
|
76
|
-
size: "320x125",
|
|
77
|
-
title: Alchemy.t("New Element")
|
|
78
|
-
}, class: "button add-nestable-element-button" %>
|
|
79
|
-
<% end %>
|
|
80
|
-
<% end %>
|
|
58
|
+
<%= render "alchemy/admin/elements/add_nested_element_form", element: element %>
|
|
81
59
|
</div>
|
|
82
60
|
<% end %>
|
|
83
61
|
<% end %>
|
|
@@ -9,7 +9,11 @@
|
|
|
9
9
|
label: Alchemy.t(:element_of_type),
|
|
10
10
|
collection: elements_for_select(@elements),
|
|
11
11
|
prompt: Alchemy.t(:select_element),
|
|
12
|
-
|
|
12
|
+
selected: (@elements.first if @elements.count == 1),
|
|
13
|
+
input_html: {class: 'alchemy_selectbox', autofocus: true, disabled: @elements.count == 1} %>
|
|
14
|
+
<% if @elements.count == 1 %>
|
|
15
|
+
<%= form.hidden_field :name, value: @elements.first[:name] %>
|
|
16
|
+
<% end %>
|
|
13
17
|
<%= form.hidden_field :parent_element_id, value: @parent_element.try(:id) %>
|
|
14
18
|
<%= form.submit Alchemy.t(:add) %>
|
|
15
19
|
<%- end -%>
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
}) %>
|
|
18
18
|
$('#<%= essence_node_editor.form_field_id %>').alchemyNodeSelect({
|
|
19
19
|
placeholder: "<%= Alchemy.t(:search_node) %>",
|
|
20
|
-
url: "<%= alchemy.api_nodes_path %>",
|
|
20
|
+
url: "<%= alchemy.api_nodes_path(language_id: essence_node_editor.page&.language_id) %>",
|
|
21
21
|
query_params: <%== query_params.to_json %>,
|
|
22
22
|
<% if essence_node_editor.essence.node %>
|
|
23
23
|
<% serialized_node = ActiveModelSerializers::SerializableResource.new(essence_node_editor.essence.node, include: :ancestors) %>
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
require "dragonfly_svg"
|
|
3
3
|
require "alchemy/dragonfly/processors/crop_resize"
|
|
4
4
|
require "alchemy/dragonfly/processors/auto_orient"
|
|
5
|
+
require "alchemy/dragonfly/processors/thumbnail"
|
|
5
6
|
|
|
6
7
|
# Logger
|
|
7
8
|
Dragonfly.logger = Rails.logger
|
|
@@ -18,4 +19,5 @@ Dragonfly::ImageMagick::Processors::Encode::WHITELISTED_ARGS << "flatten"
|
|
|
18
19
|
Rails.application.config.after_initialize do
|
|
19
20
|
Dragonfly.app(:alchemy_pictures).add_processor(:crop_resize, Alchemy::Dragonfly::Processors::CropResize.new)
|
|
20
21
|
Dragonfly.app(:alchemy_pictures).add_processor(:auto_orient, Alchemy::Dragonfly::Processors::AutoOrient.new)
|
|
22
|
+
Dragonfly.app(:alchemy_pictures).add_processor(:thumbnail, Alchemy::Dragonfly::Processors::Thumbnail.new)
|
|
21
23
|
end
|
data/lib/alchemy/config.rb
CHANGED
|
@@ -55,7 +55,11 @@ module Alchemy
|
|
|
55
55
|
# If it does not exist, or its empty, it returns an empty Hash.
|
|
56
56
|
#
|
|
57
57
|
def read_file(file)
|
|
58
|
-
YAML.safe_load(
|
|
58
|
+
YAML.safe_load(
|
|
59
|
+
ERB.new(File.read(file)).result,
|
|
60
|
+
permitted_classes: YAML_PERMITTED_CLASSES,
|
|
61
|
+
aliases: true,
|
|
62
|
+
) || {}
|
|
59
63
|
rescue Errno::ENOENT
|
|
60
64
|
{}
|
|
61
65
|
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "dragonfly/image_magick/processors/thumb"
|
|
4
|
+
|
|
5
|
+
module Alchemy
|
|
6
|
+
module Dragonfly
|
|
7
|
+
module Processors
|
|
8
|
+
class Thumbnail < ::Dragonfly::ImageMagick::Processors::Thumb
|
|
9
|
+
def call(content, geometry, opts = {})
|
|
10
|
+
# store content into an instance variable to use it in args_for_geometry - method
|
|
11
|
+
@content = content
|
|
12
|
+
super
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# due to a missing ImageMagick parameter animated GIFs were broken with the default
|
|
17
|
+
# Dragonfly Thumb processor
|
|
18
|
+
def args_for_geometry(geometry)
|
|
19
|
+
# resize all frames in a GIF
|
|
20
|
+
# @link https://imagemagick.org/script/command-line-options.php#coalesce
|
|
21
|
+
# @link https://imagemagick.org/script/command-line-options.php#deconstruct
|
|
22
|
+
@content&.mime_type == "image/gif" ? "-coalesce #{super} -deconstruct" : super
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -50,9 +50,8 @@ module Alchemy
|
|
|
50
50
|
if File.exist?(definitions_file_path)
|
|
51
51
|
YAML.safe_load(
|
|
52
52
|
ERB.new(File.read(definitions_file_path)).result,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
true
|
|
53
|
+
permitted_classes: YAML_PERMITTED_CLASSES,
|
|
54
|
+
aliases: true,
|
|
56
55
|
) || []
|
|
57
56
|
else
|
|
58
57
|
raise LoadError,
|
|
@@ -54,8 +54,7 @@ module Alchemy
|
|
|
54
54
|
def find_elements(page_version)
|
|
55
55
|
return Alchemy::ElementsRepository.none unless page_version
|
|
56
56
|
|
|
57
|
-
elements =
|
|
58
|
-
elements = elements.not_nested
|
|
57
|
+
elements = page_version.element_repository.visible.not_nested
|
|
59
58
|
elements = options[:fixed] ? elements.fixed : elements.unfixed
|
|
60
59
|
|
|
61
60
|
if options[:only]
|
data/lib/alchemy/essence.rb
CHANGED
|
@@ -41,7 +41,7 @@ module Alchemy #:nodoc:
|
|
|
41
41
|
has_one :element, through: :content, class_name: "Alchemy::Element"
|
|
42
42
|
has_one :page, through: :element, class_name: "Alchemy::Page"
|
|
43
43
|
|
|
44
|
-
scope :available, -> { joins(:element).merge(Alchemy::Element.
|
|
44
|
+
scope :available, -> { joins(:element).merge(Alchemy::Element.published) }
|
|
45
45
|
scope :from_element, ->(name) { joins(:element).where(Element.table_name => { name: name }) }
|
|
46
46
|
|
|
47
47
|
delegate :restricted?, to: :page, allow_nil: true
|
data/lib/alchemy/page_layout.rb
CHANGED
|
@@ -151,7 +151,11 @@ module Alchemy
|
|
|
151
151
|
#
|
|
152
152
|
def read_definitions_file
|
|
153
153
|
if File.exist?(layouts_file_path)
|
|
154
|
-
YAML.safe_load(
|
|
154
|
+
YAML.safe_load(
|
|
155
|
+
ERB.new(File.read(layouts_file_path)).result,
|
|
156
|
+
permitted_classes: YAML_PERMITTED_CLASSES,
|
|
157
|
+
aliases: true,
|
|
158
|
+
) || []
|
|
155
159
|
else
|
|
156
160
|
raise LoadError, "Could not find page_layouts.yml file! Please run `rails generate alchemy:install`"
|
|
157
161
|
end
|
data/lib/alchemy/permissions.rb
CHANGED
|
@@ -41,7 +41,7 @@ module Alchemy
|
|
|
41
41
|
c.public? && !c.restricted?
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
can :read, Alchemy::Element, Alchemy::Element.
|
|
44
|
+
can :read, Alchemy::Element, Alchemy::Element.published.not_restricted do |e|
|
|
45
45
|
e.public? && !e.restricted?
|
|
46
46
|
end
|
|
47
47
|
|
|
@@ -68,7 +68,7 @@ module Alchemy
|
|
|
68
68
|
c.public?
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
-
can :read, Alchemy::Element, Alchemy::Element.
|
|
71
|
+
can :read, Alchemy::Element, Alchemy::Element.published do |e|
|
|
72
72
|
e.public?
|
|
73
73
|
end
|
|
74
74
|
|
data/lib/alchemy/version.rb
CHANGED
data/lib/alchemy.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require "alchemy/admin/preview_url"
|
|
4
4
|
|
|
5
5
|
module Alchemy
|
|
6
|
-
|
|
6
|
+
YAML_PERMITTED_CLASSES = %w[Symbol Date Regexp]
|
|
7
7
|
|
|
8
8
|
# Define page preview sources
|
|
9
9
|
#
|
|
@@ -35,9 +35,7 @@ module Alchemy
|
|
|
35
35
|
# acme/preview_source: Acme Vorschau
|
|
36
36
|
#
|
|
37
37
|
def self.preview_sources
|
|
38
|
-
@_preview_sources ||=
|
|
39
|
-
Set.new << Alchemy::Admin::PreviewUrl
|
|
40
|
-
end
|
|
38
|
+
@_preview_sources ||= Set.new << Alchemy::Admin::PreviewUrl
|
|
41
39
|
end
|
|
42
40
|
|
|
43
41
|
# Define page publish targets
|
|
@@ -17,8 +17,8 @@ module Alchemy
|
|
|
17
17
|
# source and destination file names to use that engine.
|
|
18
18
|
if ext != template_engine.to_s
|
|
19
19
|
say_status :warning, "View uses unexpected template engine '#{ext}'.", :cyan
|
|
20
|
-
destination.gsub
|
|
21
|
-
source.gsub
|
|
20
|
+
destination = destination.gsub(/#{template_engine}$/, ext)
|
|
21
|
+
source = source.gsub(/#{template_engine}$/, ext)
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
|
|
@@ -33,7 +33,11 @@ module Alchemy
|
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def load_alchemy_yaml(name)
|
|
36
|
-
YAML.safe_load(
|
|
36
|
+
YAML.safe_load(
|
|
37
|
+
ERB.new(File.read(Rails.root.join("config", "alchemy", name))).result,
|
|
38
|
+
permitted_classes: YAML_PERMITTED_CLASSES,
|
|
39
|
+
aliases: true,
|
|
40
|
+
)
|
|
37
41
|
rescue Errno::ENOENT
|
|
38
42
|
puts "\nERROR: Could not read config/alchemy/#{name} file. Please run: `rails generate alchemy:install`"
|
|
39
43
|
end
|
|
@@ -98,7 +98,10 @@ module Alchemy
|
|
|
98
98
|
end
|
|
99
99
|
|
|
100
100
|
def copy_alchemy_entry_point
|
|
101
|
-
webpack_config = YAML.
|
|
101
|
+
webpack_config = YAML.safe_load(
|
|
102
|
+
File.read(app_root.join("config", "webpacker.yml")),
|
|
103
|
+
aliases: true
|
|
104
|
+
)[Rails.env]
|
|
102
105
|
copy_file "alchemy_admin.js",
|
|
103
106
|
app_root.join(webpack_config["source_path"], webpack_config["source_entry_path"], "alchemy/admin.js")
|
|
104
107
|
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.1
|
|
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-04-
|
|
16
|
+
date: 2022-04-26 00:00:00.000000000 Z
|
|
17
17
|
dependencies:
|
|
18
18
|
- !ruby/object:Gem::Dependency
|
|
19
19
|
name: actionmailer
|
|
@@ -1037,6 +1037,7 @@ files:
|
|
|
1037
1037
|
- app/views/alchemy/admin/dashboard/help.html.erb
|
|
1038
1038
|
- app/views/alchemy/admin/dashboard/index.html.erb
|
|
1039
1039
|
- app/views/alchemy/admin/dashboard/info.html.erb
|
|
1040
|
+
- app/views/alchemy/admin/elements/_add_nested_element_form.html.erb
|
|
1040
1041
|
- app/views/alchemy/admin/elements/_element.html.erb
|
|
1041
1042
|
- app/views/alchemy/admin/elements/_footer.html.erb
|
|
1042
1043
|
- app/views/alchemy/admin/elements/_form.html.erb
|
|
@@ -1303,6 +1304,7 @@ files:
|
|
|
1303
1304
|
- lib/alchemy/deprecation.rb
|
|
1304
1305
|
- lib/alchemy/dragonfly/processors/auto_orient.rb
|
|
1305
1306
|
- lib/alchemy/dragonfly/processors/crop_resize.rb
|
|
1307
|
+
- lib/alchemy/dragonfly/processors/thumbnail.rb
|
|
1306
1308
|
- lib/alchemy/element_definition.rb
|
|
1307
1309
|
- lib/alchemy/elements_finder.rb
|
|
1308
1310
|
- lib/alchemy/engine.rb
|