alchemy_cms 8.0.0.b → 8.0.0.c

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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/builds/alchemy/admin.css +1 -1
  3. data/app/assets/images/alchemy/element_icons/layout-bottom-2-line.svg +1 -0
  4. data/app/components/alchemy/admin/link_dialog/tabs.rb +1 -1
  5. data/app/components/alchemy/admin/locale_select.rb +38 -0
  6. data/app/controllers/alchemy/admin/pages_controller.rb +1 -1
  7. data/app/controllers/alchemy/admin/pictures_controller.rb +11 -5
  8. data/app/controllers/alchemy/admin/resources_controller.rb +1 -1
  9. data/app/decorators/alchemy/ingredient_editor.rb +9 -1
  10. data/app/helpers/alchemy/admin/base_helper.rb +0 -7
  11. data/app/helpers/alchemy/admin/form_helper.rb +2 -1
  12. data/app/models/alchemy/element_definition.rb +3 -2
  13. data/app/models/alchemy/ingredients/boolean.rb +2 -1
  14. data/app/models/alchemy/page/publisher.rb +1 -1
  15. data/app/models/alchemy/resource.rb +15 -2
  16. data/app/models/alchemy/storage_adapter/dragonfly.rb +2 -2
  17. data/app/stylesheets/alchemy/admin/dashboard.scss +13 -0
  18. data/app/stylesheets/alchemy/admin/elements.scss +1 -1
  19. data/app/stylesheets/alchemy/admin/nodes.scss +6 -2
  20. data/app/stylesheets/alchemy/admin/sitemap.scss +6 -17
  21. data/app/views/alchemy/admin/dashboard/index.html.erb +1 -1
  22. data/app/views/alchemy/admin/dashboard/info.html.erb +36 -6
  23. data/app/views/alchemy/admin/elements/_header.html.erb +8 -9
  24. data/app/views/alchemy/admin/nodes/_form.html.erb +5 -1
  25. data/app/views/alchemy/admin/pictures/_archive.html.erb +1 -1
  26. data/app/views/alchemy/admin/pictures/_form.html.erb +10 -5
  27. data/app/views/alchemy/admin/pictures/_picture.html.erb +15 -10
  28. data/app/views/alchemy/admin/pictures/show.html.erb +11 -13
  29. data/app/views/alchemy/admin/pictures/update.turbo_stream.erb +1 -1
  30. data/app/views/alchemy/admin/uploader/_button.html.erb +1 -1
  31. data/app/views/layouts/alchemy/admin.html.erb +3 -6
  32. data/lib/alchemy/configuration/base_option.rb +18 -5
  33. data/lib/alchemy/configuration/boolean_option.rb +2 -5
  34. data/lib/alchemy/configuration/collection_option.rb +69 -0
  35. data/lib/alchemy/configuration/configuration_option.rb +35 -0
  36. data/lib/alchemy/configuration/pathname_option.rb +12 -0
  37. data/lib/alchemy/configuration.rb +44 -6
  38. data/lib/alchemy/configurations/importmap.rb +11 -0
  39. data/lib/alchemy/configurations/mailer.rb +2 -2
  40. data/lib/alchemy/configurations/main.rb +141 -3
  41. data/lib/alchemy/configurations/uploader.rb +2 -2
  42. data/lib/alchemy/deprecation.rb +1 -1
  43. data/lib/alchemy/engine.rb +27 -14
  44. data/lib/alchemy/test_support/config_stubbing.rb +13 -4
  45. data/lib/alchemy/test_support/factories/language_factory.rb +8 -4
  46. data/lib/alchemy/test_support/factories/page_factory.rb +1 -0
  47. data/lib/alchemy/version.rb +1 -1
  48. data/lib/alchemy.rb +16 -160
  49. data/lib/generators/alchemy/install/templates/alchemy.rb.tt +78 -7
  50. data/lib/tasks/alchemy/assets.rake +1 -1
  51. metadata +7 -6
  52. data/app/assets/images/alchemy/element_icons/default.svg +0 -1
  53. data/lib/alchemy/configuration/class_set_option.rb +0 -46
  54. data/lib/alchemy/configuration/integer_list_option.rb +0 -13
  55. data/lib/alchemy/configuration/list_option.rb +0 -22
  56. data/lib/alchemy/configuration/string_list_option.rb +0 -13
data/lib/alchemy.rb CHANGED
@@ -35,170 +35,26 @@ module Alchemy
35
35
  end
36
36
  deprecate enable_searchable: enable_searchable_deprecation_msg, deprecator: Alchemy::Deprecation
37
37
 
38
- # Define page preview sources
39
- #
40
- # A preview source is a Ruby class returning an URL
41
- # that is used as source for the preview frame in the
42
- # admin UI.
43
- #
44
- # == Example
45
- #
46
- # # lib/acme/preview_source.rb
47
- # class Acme::PreviewSource < Alchemy::Admin::PreviewUrl
48
- # def url_for(page)
49
- # if page.site.name == "Next"
50
- # "https://user:#{ENV['PREVIEW_HTTP_PASS']}@next.acme.com"
51
- # else
52
- # "https://www.acme.com"
53
- # end
54
- # end
55
- # end
56
- #
57
- # # config/initializers/alchemy.rb
58
- # require "acme/preview_source"
59
- # Alchemy.preview_sources << Acme::PreviewSource
60
- #
61
- # # config/locales/de.yml
62
- # de:
63
- # activemodel:
64
- # models:
65
- # acme/preview_source: Acme Vorschau
66
- #
67
- def preview_sources
68
- @_preview_sources ||= Set.new << Alchemy::Admin::PreviewUrl
69
- end
70
-
71
- def preview_sources=(sources)
72
- @_preview_sources = Array(sources)
73
- end
74
-
75
- # Additional JS modules to be imported in the Alchemy admin UI
76
- #
77
- # Be sure to also pin the modules with +Alchemy.importmap+.
78
- #
79
- # == Example
80
- #
81
- # Alchemy.importmap.pin "flatpickr/de",
82
- # to: "https://ga.jspm.io/npm:flatpickr@4.6.13/dist/l10n/de.js"
83
- #
84
- # Alchemy.admin_js_imports << "flatpickr/de"
85
- #
86
- def admin_js_imports
87
- @_admin_js_imports ||= Set.new
88
- end
38
+ delegate :preview_sources, to: :config
39
+ delegate :preview_sources=, to: :config
40
+ deprecate preview_sources: "Use `Alchemy.config.preview_sources` instead.", deprecator: Alchemy::Deprecation
41
+ deprecate :preview_sources= => "Use `Alchemy.config.preview_sources=` instead.", :deprecator => Alchemy::Deprecation
89
42
 
90
- def admin_js_imports=(sources)
91
- @_admin_js_imports = Set[sources]
92
- end
43
+ delegate :admin_js_imports, to: :config
44
+ delegate :admin_js_imports=, to: :config
45
+ deprecate admin_js_imports: "Use `Alchemy.config.admin_js_imports` instead", deprecator: Alchemy::Deprecation
46
+ deprecate :admin_js_imports= => "Use `Alchemy.config.admin_js_imports=` instead", :deprecator => Alchemy::Deprecation
93
47
 
94
- # Additional importmaps to be included in the Alchemy admin UI
95
- #
96
- # Be sure to also pin modules with +Alchemy.importmap+.
97
- #
98
- # == Example
99
- #
100
- # # config/alchemy/importmap.rb
101
- # Alchemy.importmap.pin "alchemy_solidus", to: "alchemy_solidus.js", preload: true
102
- # Alchemy.importmap.pin_all_from Alchemy::Solidus::Engine.root.join("app/javascript/alchemy_solidus"),
103
- # under: "alchemy_solidus",
104
- # preload: true
105
- #
106
- # # lib/alchemy/solidus/engine.rb
107
- # initializer "alchemy_solidus.assets", before: "alchemy.importmap" do |app|
108
- # Alchemy.admin_importmaps.add({
109
- # importmap_path: root.join("config/importmap.rb"),
110
- # source_paths: [
111
- # root.join("app/javascript")
112
- # ],
113
- # name: "alchemy_solidus"
114
- # })
115
- # app.config.assets.precompile << "alchemy_solidus/manifest.js"
116
- # end
117
- #
118
- # @return [Set<Hash>]
119
- def admin_importmaps
120
- @_admin_importmaps ||= Set.new([{
121
- importmap_path: Engine.root.join("config/importmap.rb"),
122
- source_paths: [
123
- Engine.root.join("app/javascript"),
124
- Engine.root.join("vendor/javascript")
125
- ],
126
- name: "alchemy_admin"
127
- }])
128
- end
48
+ delegate :admin_importmaps, to: :config
49
+ deprecate admin_importmaps: "Use Alchemy.config.admin_importmaps instead", deprecator: Alchemy::Deprecation
129
50
 
130
- # Additional stylesheets to be included in the Alchemy admin UI
131
- #
132
- # == Example
133
- #
134
- # # lib/alchemy/devise/engine.rb
135
- # initializer "alchemy.devise.stylesheets", before: "alchemy.admin_stylesheets" do
136
- # Alchemy.admin_stylesheets << "alchemy/devise/admin.css"
137
- # end
138
- #
139
- # @return [Set<String>]
140
- def admin_stylesheets
141
- @_admin_stylesheets ||= Set.new(["alchemy/admin/custom.css"])
142
- end
51
+ delegate :admin_stylesheets, to: :config
52
+ deprecate admin_stylesheets: "Use Alchemy.config.admin_stylesheets instead", deprecator: Alchemy::Deprecation
143
53
 
144
- # Define page publish targets
145
- #
146
- # A publish target is a ActiveJob that gets performed
147
- # whenever a user clicks the publish page button.
148
- #
149
- # Use this to trigger deployment hooks of external
150
- # services in an asychronous way.
151
- #
152
- # == Example
153
- #
154
- # # app/jobs/publish_job.rb
155
- # class PublishJob < ApplicationJob
156
- # def perform(page)
157
- # RestClient.post(ENV['BUILD_HOOK_URL'])
158
- # end
159
- # end
160
- #
161
- # # config/initializers/alchemy.rb
162
- # Alchemy.publish_targets << PublishJob
163
- #
164
- def publish_targets
165
- @_publish_targets ||= Set.new
166
- end
54
+ delegate :publish_targets, to: :config
55
+ deprecate publish_targets: "Use Alchemy.config.publish_targets instead", deprecator: Alchemy::Deprecation
167
56
 
168
- # Configure tabs in the link dialog
169
- #
170
- # With this configuration that tabs in the link dialog can be extended
171
- # without overwriting or defacing the Admin Interface.
172
- #
173
- # == Example
174
- #
175
- # # components/acme/link_tab.rb
176
- # module Acme
177
- # class LinkTab < ::Alchemy::Admin::LinkDialog::BaseTab
178
- # def title
179
- # "Awesome Tab Title"
180
- # end
181
- #
182
- # def name
183
- # :unique_name
184
- # end
185
- #
186
- # def fields
187
- # [ title_input, target_select ]
188
- # end
189
- # end
190
- # end
191
- #
192
- # # config/initializers/alchemy.rb
193
- # Alchemy.link_dialog_tabs << Acme::LinkTab
194
- #
195
- def link_dialog_tabs
196
- @_link_dialog_tabs ||= Set.new([
197
- Alchemy::Admin::LinkDialog::InternalTab,
198
- Alchemy::Admin::LinkDialog::AnchorTab,
199
- Alchemy::Admin::LinkDialog::ExternalTab,
200
- Alchemy::Admin::LinkDialog::FileTab
201
- ])
202
- end
57
+ delegate :link_dialog_tabs, to: :config
58
+ deprecate link_dialog_tabs: "Use Alchemy.config.link_dialog_tabs instead", deprecator: Alchemy::Deprecation
203
59
  end
204
60
  end
@@ -137,8 +137,8 @@ Alchemy.configure do |config|
137
137
  # mailer.mail_from = <%= @default_config.mailer.mail_from.inspect %>
138
138
  # mailer.mail_to = <%= @default_config.mailer.mail_to.inspect %>
139
139
  # mailer.subject = <%= @default_config.mailer.subject.inspect %>
140
- # mailer.fields = <%= @default_config.mailer.fields.inspect %>
141
- # mailer.validate_fields = <%= @default_config.mailer.validate_fields.inspect %>
140
+ # mailer.fields = <%= @default_config.mailer.fields.map(&:to_s) %>
141
+ # mailer.validate_fields = <%= @default_config.mailer.validate_fields.map(&:to_s) %>
142
142
  # end
143
143
 
144
144
  # === User roles
@@ -157,7 +157,7 @@ Alchemy.configure do |config|
157
157
  # user_roles:
158
158
  # rolename: Name of the role
159
159
  #
160
- # config.user_roles = <%= @default_config.user_roles.inspect %>
160
+ # config.user_roles = <%= @default_config.user_roles.map(&:to_s) %>
161
161
 
162
162
  # === Uploader Settings
163
163
  #
@@ -170,8 +170,8 @@ Alchemy.configure do |config|
170
170
  # uploader.upload_limit = <%= @default_config.uploader.upload_limit.inspect %>
171
171
  # uploader.file_size_limit = <%= @default_config.uploader.file_size_limit.inspect %>
172
172
  # uploader.allowed_filetypes.tap do |file_types|
173
- # file_types.alchemy_attachments = <%= @default_config.uploader.allowed_filetypes.alchemy_attachments.inspect %>
174
- # file_types.alchemy_pictures = <%= @default_config.uploader.allowed_filetypes.alchemy_pictures.inspect %>
173
+ # file_types.alchemy_attachments = <%= @default_config.uploader.allowed_filetypes.alchemy_attachments.map(&:to_s) %>
174
+ # file_types.alchemy_pictures = <%= @default_config.uploader.allowed_filetypes.alchemy_pictures.map(&:to_s) %>
175
175
  # end
176
176
  # end
177
177
 
@@ -186,15 +186,86 @@ Alchemy.configure do |config|
186
186
  #
187
187
  # jQuery(a[data-link-target="overlay"]).dialog();
188
188
  #
189
- # config.link_target_options = <%= @default_config.link_target_options.inspect %>
189
+ # config.link_target_options = <%= @default_config.link_target_options.map(&:to_s) %>
190
+
191
+ # === Format matchers
192
+ #
193
+ # Named aliases for regular expressions that can be used in various places.
194
+ # The most common use case is the format validation of ingredients, or attribute validations of your individual models.
195
+ #
196
+ # == Example:
197
+ #
198
+ # validates_format_of :url, with: Alchemy.config.format_matchers.url
199
+ #
200
+ # config.format_matchers.tap do |format|
201
+ # format.email = <%= @default_config.format_matchers.email.inspect %>
202
+ # format.url = <%= @default_config.format_matchers.url.inspect %>
203
+ # format.link_url = <%= @default_config.format_matchers.link_url.inspect %>
204
+ # end
190
205
 
191
206
  # The layout used for rendering the +alchemy/admin/pages#show+ action.
192
207
  # config.admin_page_preview_layout = <%= @default_config.admin_page_preview_layout.inspect %>
193
208
 
194
209
  # The sizes for the preview size select in the page editor.
195
- # config.page_preview_sizes = <%= @default_config.page_preview_sizes.inspect %>
210
+ # config.page_preview_sizes = <%= @default_config.page_preview_sizes.map(&:to_s) %>
211
+
212
+ # Enable full text search configuration
213
+ #
214
+ # It enables a searchable checkbox in the page form to toggle
215
+ # the searchable field. These information can used in a search
216
+ # plugin (e.g. https://github.com/AlchemyCMS/alchemy-pg_search).
217
+ #
218
+ # == Example
219
+ #
220
+ # # config/initializers/alchemy.rb
221
+ # Alchemy.config.page_searchable_checkbox = true
222
+ #
223
+ # config.show_page_searchable_checkbox = <%= @default_config.show_page_searchable_checkbox.inspect %>
196
224
 
197
225
  # The storage adapter for Pictures and Attachments
198
226
  #
199
227
  config.storage_adapter = <%= @default_config.storage_adapter.inspect %>
228
+
229
+ # Additional JS modules to be imported in the Alchemy admin UI
230
+ #
231
+ # Be sure to also pin the modules with +Alchemy.importmap+.
232
+ #
233
+ # == Example
234
+ #
235
+ # Alchemy.importmap.pin "flatpickr/de",
236
+ # to: "https://ga.jspm.io/npm:flatpickr@4.6.13/dist/l10n/de.js"
237
+ #
238
+ # config.admin_js_imports << "flatpickr/de"
239
+
240
+ # Additional importmaps to be included in the Alchemy admin UI
241
+ #
242
+ # Be sure to also pin modules with +Alchemy.importmap+.
243
+ #
244
+ # config.admin_importmaps.add(
245
+ # importmap_path: root.join("config/importmap.rb"),
246
+ # source_paths: [
247
+ # root.join("app/javascript")
248
+ # ],
249
+ # name: "admin_extension"
250
+ # )
251
+
252
+ # Additional stylesheets to be included in the Alchemy admin UI
253
+ # config.admin_stylesheets.add("my_app/admin_extension")
254
+
255
+ # Define page publish targets
256
+ #
257
+ # A publish target is a ActiveJob that gets performed
258
+ # whenever a user clicks the publish page button.
259
+ #
260
+ # Use this to trigger deployment hooks of external
261
+ # services in an asychronous way.
262
+ #
263
+ # config.publish_targets << "MyPublishJob"
264
+
265
+ # Configure tabs in the link dialog
266
+ #
267
+ # With this configuration that tabs in the link dialog can be extended
268
+ # without overwriting or defacing the Admin Interface.
269
+ #
270
+ # config.link_dialog_tabs << "Acme::LinkTab"
200
271
  end
@@ -6,7 +6,7 @@ if Rake::Task.task_defined?("assets:precompile") && defined?(Propshaft)
6
6
  manifest.select { |k| k.include?("tinymce/") }.each do |k, v|
7
7
  Propshaft.logger.info "Copying #{v} to #{k}"
8
8
  FileUtils.cp(
9
- assets_path.join(v),
9
+ assets_path.join(v.dig("digested_path") || v),
10
10
  assets_path.join(k)
11
11
  )
12
12
  end
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.0.0.b
4
+ version: 8.0.0.c
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas von Deyen
@@ -660,7 +660,7 @@ files:
660
660
  - app/assets/config/alchemy_manifest.js
661
661
  - app/assets/images/alchemy/alchemy-logo.png
662
662
  - app/assets/images/alchemy/alchemy-logo.svg
663
- - app/assets/images/alchemy/element_icons/default.svg
663
+ - app/assets/images/alchemy/element_icons/layout-bottom-2-line.svg
664
664
  - app/assets/images/alchemy/favicon.ico
665
665
  - app/assets/images/alchemy/icon-white.svg
666
666
  - app/assets/images/alchemy/icon.svg
@@ -676,6 +676,7 @@ files:
676
676
  - app/components/alchemy/admin/link_dialog/internal_tab.rb
677
677
  - app/components/alchemy/admin/link_dialog/tabs.rb
678
678
  - app/components/alchemy/admin/list_filter.rb
679
+ - app/components/alchemy/admin/locale_select.rb
679
680
  - app/components/alchemy/admin/message.rb
680
681
  - app/components/alchemy/admin/node_select.rb
681
682
  - app/components/alchemy/admin/page_select.rb
@@ -1235,17 +1236,17 @@ files:
1235
1236
  - lib/alchemy/configuration/base_option.rb
1236
1237
  - lib/alchemy/configuration/boolean_option.rb
1237
1238
  - lib/alchemy/configuration/class_option.rb
1238
- - lib/alchemy/configuration/class_set_option.rb
1239
- - lib/alchemy/configuration/integer_list_option.rb
1239
+ - lib/alchemy/configuration/collection_option.rb
1240
+ - lib/alchemy/configuration/configuration_option.rb
1240
1241
  - lib/alchemy/configuration/integer_option.rb
1241
- - lib/alchemy/configuration/list_option.rb
1242
+ - lib/alchemy/configuration/pathname_option.rb
1242
1243
  - lib/alchemy/configuration/regexp_option.rb
1243
- - lib/alchemy/configuration/string_list_option.rb
1244
1244
  - lib/alchemy/configuration/string_option.rb
1245
1245
  - lib/alchemy/configuration_methods.rb
1246
1246
  - lib/alchemy/configurations/default_language.rb
1247
1247
  - lib/alchemy/configurations/default_site.rb
1248
1248
  - lib/alchemy/configurations/format_matchers.rb
1249
+ - lib/alchemy/configurations/importmap.rb
1249
1250
  - lib/alchemy/configurations/mailer.rb
1250
1251
  - lib/alchemy/configurations/main.rb
1251
1252
  - lib/alchemy/configurations/page_cache.rb
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M5 19H19V5H5V19ZM3 4C3 3.44772 3.44772 3 4 3H20C20.5523 3 21 3.44772 21 4V20C21 20.5523 20.5523 21 20 21H4C3.44772 21 3 20.5523 3 20V4ZM7 9H17V7H7V9ZM17 13H7V11H17V13ZM7 17H17V15H7V17Z"></path></svg>
@@ -1,46 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "alchemy/configuration/base_option"
4
-
5
- module Alchemy
6
- class Configuration
7
- class ClassSetOption < BaseOption
8
- include Enumerable
9
-
10
- def value = self
11
-
12
- def <<(klass)
13
- @value << klass.to_s
14
- end
15
-
16
- def concat(klasses)
17
- klasses.each do |klass|
18
- self << klass
19
- end
20
-
21
- self
22
- end
23
-
24
- delegate :clear, :empty?, to: :@value
25
-
26
- def delete(object)
27
- @value.delete(object.to_s)
28
- end
29
-
30
- def each
31
- @value.each do |klass|
32
- yield klass.constantize
33
- end
34
- end
35
-
36
- def as_json = @value
37
-
38
- private
39
-
40
- def validate(value)
41
- raise TypeError, "each #{name} must be set as a String" unless value.all? { _1.is_a?(String) }
42
- value
43
- end
44
- end
45
- end
46
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "alchemy/configuration/list_option"
4
-
5
- module Alchemy
6
- class Configuration
7
- class IntegerListOption < ListOption
8
- def self.item_class
9
- Integer
10
- end
11
- end
12
- end
13
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "alchemy/configuration/base_option"
4
-
5
- module Alchemy
6
- class Configuration
7
- class ListOption < BaseOption
8
- def self.item_class
9
- raise NotImplementedError
10
- end
11
-
12
- private
13
-
14
- def validate(value)
15
- unless value.is_a?(Array) && value.all? { _1.is_a?(self.class.item_class) }
16
- raise TypeError, "#{@name} must be an Array of #{self.class.item_class.name.downcase.pluralize}, given #{value.inspect}"
17
- end
18
- value
19
- end
20
- end
21
- end
22
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "alchemy/configuration/list_option"
4
-
5
- module Alchemy
6
- class Configuration
7
- class StringListOption < ListOption
8
- def self.item_class
9
- String
10
- end
11
- end
12
- end
13
- end