alchemy_cms 8.4.2 → 8.4.3

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.
@@ -11,10 +11,13 @@ module Alchemy
11
11
  private
12
12
 
13
13
  def get_widget(id)
14
- "#{MODULE_NAMESPACE}::#{id.camelcase}".constantize
15
- rescue NameError => e
14
+ widget = "#{MODULE_NAMESPACE}::#{id.camelcase}".safe_constantize
15
+ # Constant lookup also finds classes in the ancestors of a widget,
16
+ # e.g. "system_info/template" resolves to a ViewComponent internal.
17
+ return widget if widget.is_a?(Class) && widget.module_parent_name == MODULE_NAMESPACE
18
+
16
19
  Alchemy::Logger.error "No dashboard widget found for id: #{id}"
17
- raise ActionController::RoutingError, e.message
20
+ raise ActionController::RoutingError, "No dashboard widget found for id: #{id}"
18
21
  end
19
22
  end
20
23
  end
@@ -9,7 +9,7 @@ module Alchemy
9
9
  include Alchemy::ControllerActions
10
10
  include Alchemy::Modules
11
11
 
12
- protect_from_forgery
12
+ protect_from_forgery prepend: true
13
13
 
14
14
  before_action :mailer_set_url_options
15
15
  before_action :set_locale
@@ -258,6 +258,12 @@ module Alchemy
258
258
  ].compact
259
259
  end
260
260
 
261
+ # Restores the elements window width the user dragged it to.
262
+ def alchemy_body_style
263
+ width = cookies["alchemy-elements-window-width"]
264
+ "--elements-window-width: #{width}px" if width&.match?(/\A\d+(\.\d+)?\z/)
265
+ end
266
+
261
267
  # (internal) Returns options for the clipboard select tag
262
268
  def clipboard_select_tag_options(items)
263
269
  options = items.map do |item|
@@ -18,10 +18,24 @@ module Alchemy
18
18
  before_create :build_ingredients,
19
19
  unless: -> { autogenerate_ingredients == false }
20
20
 
21
- accepts_nested_attributes_for :ingredients
21
+ accepts_nested_attributes_for :ingredients, reject_if: ->(attributes) { attributes[:id].blank? }
22
22
  validates_associated :ingredients, on: :update
23
23
  end
24
24
 
25
+ # Only the editable attributes of each ingredient's own class are
26
+ # assigned, so +type+, +role+ or +related_object_type+ can never be.
27
+ def ingredients_attributes=(attributes)
28
+ attributes = attributes.to_h if attributes.respond_to?(:permitted?)
29
+ if attributes.is_a?(Hash) && !attributes.key?("id") && !attributes.key?(:id)
30
+ attributes = attributes.values
31
+ end
32
+ super(Array.wrap(attributes).map { |ingredient_attributes|
33
+ ingredient_attributes = ingredient_attributes.to_h.with_indifferent_access
34
+ ingredient = ingredients.detect { _1.id.to_s == ingredient_attributes[:id].to_s }
35
+ ingredient_attributes.slice(:id, *ingredient&.class&.editable_attributes)
36
+ })
37
+ end
38
+
25
39
  # The value of an ingredient of the element by role
26
40
  def value_for(role)
27
41
  ingredient_by_role(role)&.value
@@ -34,6 +34,8 @@ module Alchemy
34
34
 
35
35
  attribute :data, :json
36
36
 
37
+ class_attribute :related_object_id_alias, instance_accessor: false
38
+
37
39
  belongs_to :element, touch: true, class_name: "Alchemy::Element", inverse_of: :ingredients
38
40
  belongs_to :related_object, polymorphic: true, optional: true
39
41
 
@@ -72,6 +74,7 @@ module Alchemy
72
74
  # @param [String|Symbol] The name of the alias
73
75
  # @param [String] The class name of the related object
74
76
  def related_object_alias(name, class_name:)
77
+ self.related_object_id_alias = :"#{name}_id"
75
78
  alias_method name, :related_object
76
79
  alias_method :"#{name}=", :related_object=
77
80
 
@@ -116,6 +119,11 @@ module Alchemy
116
119
  def allowed_settings
117
120
  @allowed_settings ||= []
118
121
  end
122
+
123
+ # Attributes editors may assign through the element form
124
+ def editable_attributes
125
+ [:value, *stored_attributes[:data], related_object_id_alias].compact
126
+ end
119
127
  end
120
128
 
121
129
  # The value or the related object if present
@@ -19,7 +19,8 @@ alchemy-uploader {
19
19
 
20
20
  .resources-table-wrapper {
21
21
  width: 100%;
22
- height: 100%;
22
+ flex: 1;
23
+ min-height: 0;
23
24
  overflow-x: auto;
24
25
  padding: var(--spacing-2);
25
26
  }
@@ -115,6 +115,8 @@ div#overlay_text_box {
115
115
  }
116
116
 
117
117
  &:has(.resources-table-wrapper) {
118
+ display: flex;
119
+ flex-direction: column;
118
120
  padding-top: var(--top-menu-height);
119
121
  padding-right: 0;
120
122
  padding-bottom: 0;
@@ -65,8 +65,8 @@ alchemy-sitemap {
65
65
  }
66
66
 
67
67
  #alchemy_pages_tree {
68
- display: block;
69
- height: calc(100vh - var(--top-menu-height) - var(--spacing-3));
68
+ display: flow-root;
69
+ height: 100%;
70
70
  position: relative;
71
71
  }
72
72
 
@@ -37,7 +37,7 @@
37
37
  </head>
38
38
  <%= content_tag :body, id: 'alchemy',
39
39
  class: alchemy_body_class,
40
- style: cookies["alchemy-elements-window-width"] && "--elements-window-width: #{cookies["alchemy-elements-window-width"]}px" do %>
40
+ style: alchemy_body_style do %>
41
41
  <noscript>
42
42
  <h1><%= Alchemy.t(:javascript_disabled_headline) %></h1>
43
43
  <p><%= Alchemy.t(:javascript_disabled_text) %></p>
@@ -3,7 +3,7 @@
3
3
  module Alchemy
4
4
  extend self
5
5
 
6
- VERSION = "8.4.2"
6
+ VERSION = "8.4.3"
7
7
 
8
8
  def version
9
9
  VERSION
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: 8.4.2
4
+ version: 8.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas von Deyen