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.
- checksums.yaml +4 -4
- data/app/assets/builds/alchemy/admin.css +1 -1
- data/app/assets/images/alchemy/element_icons/layout-bottom-2-line.svg +1 -0
- data/app/components/alchemy/admin/link_dialog/tabs.rb +1 -1
- data/app/components/alchemy/admin/locale_select.rb +38 -0
- data/app/controllers/alchemy/admin/pages_controller.rb +1 -1
- data/app/controllers/alchemy/admin/pictures_controller.rb +11 -5
- data/app/controllers/alchemy/admin/resources_controller.rb +1 -1
- data/app/decorators/alchemy/ingredient_editor.rb +9 -1
- data/app/helpers/alchemy/admin/base_helper.rb +0 -7
- data/app/helpers/alchemy/admin/form_helper.rb +2 -1
- data/app/models/alchemy/element_definition.rb +3 -2
- data/app/models/alchemy/ingredients/boolean.rb +2 -1
- data/app/models/alchemy/page/publisher.rb +1 -1
- data/app/models/alchemy/resource.rb +15 -2
- data/app/models/alchemy/storage_adapter/dragonfly.rb +2 -2
- data/app/stylesheets/alchemy/admin/dashboard.scss +13 -0
- data/app/stylesheets/alchemy/admin/elements.scss +1 -1
- data/app/stylesheets/alchemy/admin/nodes.scss +6 -2
- data/app/stylesheets/alchemy/admin/sitemap.scss +6 -17
- data/app/views/alchemy/admin/dashboard/index.html.erb +1 -1
- data/app/views/alchemy/admin/dashboard/info.html.erb +36 -6
- data/app/views/alchemy/admin/elements/_header.html.erb +8 -9
- data/app/views/alchemy/admin/nodes/_form.html.erb +5 -1
- data/app/views/alchemy/admin/pictures/_archive.html.erb +1 -1
- data/app/views/alchemy/admin/pictures/_form.html.erb +10 -5
- data/app/views/alchemy/admin/pictures/_picture.html.erb +15 -10
- data/app/views/alchemy/admin/pictures/show.html.erb +11 -13
- data/app/views/alchemy/admin/pictures/update.turbo_stream.erb +1 -1
- data/app/views/alchemy/admin/uploader/_button.html.erb +1 -1
- data/app/views/layouts/alchemy/admin.html.erb +3 -6
- data/lib/alchemy/configuration/base_option.rb +18 -5
- data/lib/alchemy/configuration/boolean_option.rb +2 -5
- data/lib/alchemy/configuration/collection_option.rb +69 -0
- data/lib/alchemy/configuration/configuration_option.rb +35 -0
- data/lib/alchemy/configuration/pathname_option.rb +12 -0
- data/lib/alchemy/configuration.rb +44 -6
- data/lib/alchemy/configurations/importmap.rb +11 -0
- data/lib/alchemy/configurations/mailer.rb +2 -2
- data/lib/alchemy/configurations/main.rb +141 -3
- data/lib/alchemy/configurations/uploader.rb +2 -2
- data/lib/alchemy/deprecation.rb +1 -1
- data/lib/alchemy/engine.rb +27 -14
- data/lib/alchemy/test_support/config_stubbing.rb +13 -4
- data/lib/alchemy/test_support/factories/language_factory.rb +8 -4
- data/lib/alchemy/test_support/factories/page_factory.rb +1 -0
- data/lib/alchemy/version.rb +1 -1
- data/lib/alchemy.rb +16 -160
- data/lib/generators/alchemy/install/templates/alchemy.rb.tt +78 -7
- data/lib/tasks/alchemy/assets.rake +1 -1
- metadata +7 -6
- data/app/assets/images/alchemy/element_icons/default.svg +0 -1
- data/lib/alchemy/configuration/class_set_option.rb +0 -46
- data/lib/alchemy/configuration/integer_list_option.rb +0 -13
- data/lib/alchemy/configuration/list_option.rb +0 -22
- data/lib/alchemy/configuration/string_list_option.rb +0 -13
|
@@ -9,15 +9,28 @@ module Alchemy
|
|
|
9
9
|
|
|
10
10
|
def initialize(value:, name:, **args)
|
|
11
11
|
@name = name
|
|
12
|
-
|
|
12
|
+
validate(value) unless value.nil?
|
|
13
|
+
@value = value
|
|
13
14
|
end
|
|
14
15
|
attr_reader :name, :value
|
|
15
16
|
|
|
16
|
-
private
|
|
17
|
-
|
|
18
17
|
def validate(value)
|
|
19
|
-
raise
|
|
20
|
-
|
|
18
|
+
raise ConfigurationError.new(name, value, allowed_classes) unless allowed_classes.any? { value.is_a?(_1) }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def allowed_classes
|
|
22
|
+
[self.class.value_class]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def raw_value = @value
|
|
26
|
+
|
|
27
|
+
def ==(other)
|
|
28
|
+
self.class == other.class && raw_value == other.raw_value
|
|
29
|
+
end
|
|
30
|
+
alias_method :eql?, :==
|
|
31
|
+
|
|
32
|
+
def hash
|
|
33
|
+
[self.class, raw_value].hash
|
|
21
34
|
end
|
|
22
35
|
end
|
|
23
36
|
end
|
|
@@ -5,11 +5,8 @@ require "alchemy/configuration/base_option"
|
|
|
5
5
|
module Alchemy
|
|
6
6
|
class Configuration
|
|
7
7
|
class BooleanOption < BaseOption
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def validate(value)
|
|
11
|
-
raise TypeError, "#{name} must be a Boolean, given #{value.inspect}" unless value.is_a?(TrueClass) || value.is_a?(FalseClass)
|
|
12
|
-
value
|
|
8
|
+
def allowed_classes
|
|
9
|
+
[TrueClass, FalseClass]
|
|
13
10
|
end
|
|
14
11
|
end
|
|
15
12
|
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "alchemy/configuration/base_option"
|
|
4
|
+
|
|
5
|
+
module Alchemy
|
|
6
|
+
class Configuration
|
|
7
|
+
class CollectionOption < BaseOption
|
|
8
|
+
include Enumerable
|
|
9
|
+
|
|
10
|
+
def self.value_class
|
|
11
|
+
Enumerable
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
attr_reader :collection_class, :item_class, :item_args
|
|
15
|
+
|
|
16
|
+
def initialize(value:, name:, item_type:, collection_class: Array, **args)
|
|
17
|
+
@collection_class = collection_class
|
|
18
|
+
@item_class = get_item_class(item_type)
|
|
19
|
+
@item_args = args
|
|
20
|
+
value = [] if value.nil?
|
|
21
|
+
collection = @collection_class.new(value.map { |value| to_item(value) })
|
|
22
|
+
super(value: collection, name: name)
|
|
23
|
+
rescue ConfigurationError => configuration_error
|
|
24
|
+
raise ConfigurationError.new(name, configuration_error.value, configuration_error.allowed_classes)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def value
|
|
28
|
+
self
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def <<(value)
|
|
32
|
+
@value << to_item(value)
|
|
33
|
+
end
|
|
34
|
+
alias_method(:add, :<<)
|
|
35
|
+
|
|
36
|
+
def concat(values)
|
|
37
|
+
values.each do |value|
|
|
38
|
+
add(value)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
delegate :join, :[], to: :to_a
|
|
43
|
+
|
|
44
|
+
delegate :clear, :empty?, to: :@value
|
|
45
|
+
|
|
46
|
+
def each(&block)
|
|
47
|
+
@value.each do |option|
|
|
48
|
+
yield option.value
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def to_serializable_array
|
|
53
|
+
to_a.map do |item|
|
|
54
|
+
item.respond_to?(:to_h) ? item.to_h : item
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
def to_item(value)
|
|
61
|
+
@item_class.new(value: value, name: "#{name}_item", **item_args)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def get_item_class(item_type)
|
|
65
|
+
"Alchemy::Configuration::#{item_type.to_s.classify}Option".constantize
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "alchemy/configuration/base_option"
|
|
4
|
+
|
|
5
|
+
module Alchemy
|
|
6
|
+
class Configuration
|
|
7
|
+
class ConfigurationOption < BaseOption
|
|
8
|
+
def self.value_class
|
|
9
|
+
Hash
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
attr_reader :config_class
|
|
13
|
+
|
|
14
|
+
def initialize(value:, name:, config_class:, **args)
|
|
15
|
+
@name = name
|
|
16
|
+
@config_class = config_class
|
|
17
|
+
validate(value)
|
|
18
|
+
@value = if value.is_a?(config_class)
|
|
19
|
+
value
|
|
20
|
+
else
|
|
21
|
+
config_class.new(value)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def validate(value)
|
|
26
|
+
return true if value.is_a?(config_class)
|
|
27
|
+
super
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def allowed_classes
|
|
31
|
+
super + [config_class]
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -4,16 +4,28 @@ require "active_support"
|
|
|
4
4
|
require "active_support/core_ext/string"
|
|
5
5
|
|
|
6
6
|
require "alchemy/configuration/boolean_option"
|
|
7
|
+
require "alchemy/configuration/collection_option"
|
|
8
|
+
require "alchemy/configuration/configuration_option"
|
|
7
9
|
require "alchemy/configuration/class_option"
|
|
8
|
-
require "alchemy/configuration/class_set_option"
|
|
9
10
|
require "alchemy/configuration/integer_option"
|
|
10
|
-
require "alchemy/configuration/
|
|
11
|
+
require "alchemy/configuration/pathname_option"
|
|
11
12
|
require "alchemy/configuration/regexp_option"
|
|
12
|
-
require "alchemy/configuration/string_list_option"
|
|
13
13
|
require "alchemy/configuration/string_option"
|
|
14
14
|
|
|
15
15
|
module Alchemy
|
|
16
16
|
class Configuration
|
|
17
|
+
class ConfigurationError < StandardError
|
|
18
|
+
attr_reader :name, :value, :allowed_classes
|
|
19
|
+
|
|
20
|
+
def initialize(name, value, allowed_classes)
|
|
21
|
+
@name = name
|
|
22
|
+
@value = value
|
|
23
|
+
@allowed_classes = allowed_classes
|
|
24
|
+
expected_classes_message = allowed_classes.map(&:name).to_sentence(two_words_connector: " or ", last_word_connector: ", or ")
|
|
25
|
+
super("Invalid configuration value for #{name}: #{value.inspect} (expected #{expected_classes_message})")
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
17
29
|
def initialize(configuration_hash = {})
|
|
18
30
|
set(configuration_hash)
|
|
19
31
|
end
|
|
@@ -45,7 +57,8 @@ module Alchemy
|
|
|
45
57
|
|
|
46
58
|
def to_h
|
|
47
59
|
self.class.defined_options.map do |option|
|
|
48
|
-
|
|
60
|
+
value = send(option)
|
|
61
|
+
[option, value.respond_to?(:to_serializable_array) ? value.to_serializable_array : value]
|
|
49
62
|
end.concat(
|
|
50
63
|
self.class.defined_configurations.map do |configuration|
|
|
51
64
|
[configuration, send(configuration).to_h]
|
|
@@ -58,6 +71,10 @@ module Alchemy
|
|
|
58
71
|
|
|
59
72
|
def defined_options = []
|
|
60
73
|
|
|
74
|
+
def defined_values
|
|
75
|
+
defined_options + defined_configurations
|
|
76
|
+
end
|
|
77
|
+
|
|
61
78
|
def configuration(name, configuration_class)
|
|
62
79
|
# The defined configurations on a class are all those defined directly on
|
|
63
80
|
# that class as well as those defined on ancestors.
|
|
@@ -99,11 +116,19 @@ module Alchemy
|
|
|
99
116
|
super() + singleton_options
|
|
100
117
|
end
|
|
101
118
|
|
|
102
|
-
define_method(name) do
|
|
119
|
+
define_method("#{name}_option") do
|
|
103
120
|
unless instance_variable_defined?(:"@#{name}")
|
|
104
121
|
send(:"#{name}=", default)
|
|
105
122
|
end
|
|
106
|
-
instance_variable_get(:"@#{name}")
|
|
123
|
+
instance_variable_get(:"@#{name}")
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
define_method(name) do
|
|
127
|
+
send("#{name}_option").value
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
define_method("raw_#{name}") do
|
|
131
|
+
send("#{name}_option").raw_value
|
|
107
132
|
end
|
|
108
133
|
|
|
109
134
|
define_method(:"#{name}=") do |value|
|
|
@@ -111,5 +136,18 @@ module Alchemy
|
|
|
111
136
|
end
|
|
112
137
|
end
|
|
113
138
|
end
|
|
139
|
+
|
|
140
|
+
def hash
|
|
141
|
+
self.class.defined_values.map do |ivar|
|
|
142
|
+
[ivar, send(ivar).hash]
|
|
143
|
+
end.hash
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def ==(other)
|
|
147
|
+
equal?(other) || self.class == other.class && self.class.defined_values.all? do |var|
|
|
148
|
+
send(var) == other.send(var)
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
alias_method :eql?, :==
|
|
114
152
|
end
|
|
115
153
|
end
|
|
@@ -9,8 +9,8 @@ module Alchemy
|
|
|
9
9
|
option :mail_from, :string, default: "your.mail@your-domain.com"
|
|
10
10
|
option :mail_to, :string, default: "your.mail@your-domain.com"
|
|
11
11
|
option :subject, :string, default: "A new contact form message"
|
|
12
|
-
option :fields, :
|
|
13
|
-
option :validate_fields, :
|
|
12
|
+
option :fields, :collection, item_type: :string, default: %w[salutation firstname lastname address zip city phone email message]
|
|
13
|
+
option :validate_fields, :collection, item_type: :string, default: %w[lastname email]
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
end
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require "alchemy/configuration"
|
|
4
4
|
require "alchemy/configurations/default_language"
|
|
5
5
|
require "alchemy/configurations/default_site"
|
|
6
|
+
require "alchemy/configurations/importmap"
|
|
6
7
|
require "alchemy/configurations/format_matchers"
|
|
7
8
|
require "alchemy/configurations/mailer"
|
|
8
9
|
require "alchemy/configurations/page_cache"
|
|
@@ -162,7 +163,7 @@ module Alchemy
|
|
|
162
163
|
# user_roles:
|
|
163
164
|
# rolename: Name of the role
|
|
164
165
|
#
|
|
165
|
-
option :user_roles, :
|
|
166
|
+
option :user_roles, :collection, item_type: :string, default: %w[member author editor admin]
|
|
166
167
|
|
|
167
168
|
# === Uploader Settings
|
|
168
169
|
#
|
|
@@ -184,7 +185,7 @@ module Alchemy
|
|
|
184
185
|
#
|
|
185
186
|
# jQuery(a[data-link-target="overlay"]).dialog();
|
|
186
187
|
#
|
|
187
|
-
option :link_target_options, :
|
|
188
|
+
option :link_target_options, :collection, item_type: :string, default: %w[blank]
|
|
188
189
|
|
|
189
190
|
# === Format matchers
|
|
190
191
|
#
|
|
@@ -201,7 +202,7 @@ module Alchemy
|
|
|
201
202
|
option :admin_page_preview_layout, :string, default: "application"
|
|
202
203
|
|
|
203
204
|
# The sizes for the preview size select in the page editor.
|
|
204
|
-
option :page_preview_sizes, :
|
|
205
|
+
option :page_preview_sizes, :collection, item_type: :integer, default: [360, 640, 768, 1024, 1280, 1440]
|
|
205
206
|
|
|
206
207
|
# Enable full text search configuration
|
|
207
208
|
#
|
|
@@ -218,6 +219,143 @@ module Alchemy
|
|
|
218
219
|
# The storage adapter for Pictures and Attachments
|
|
219
220
|
#
|
|
220
221
|
option :storage_adapter, :string, default: "dragonfly"
|
|
222
|
+
|
|
223
|
+
# Define page preview sources
|
|
224
|
+
#
|
|
225
|
+
# A preview source is a Ruby class returning an URL
|
|
226
|
+
# that is used as source for the preview frame in the
|
|
227
|
+
# admin UI.
|
|
228
|
+
#
|
|
229
|
+
# == Example
|
|
230
|
+
#
|
|
231
|
+
# # lib/acme/preview_source.rb
|
|
232
|
+
# class Acme::PreviewSource < Alchemy::Admin::PreviewUrl
|
|
233
|
+
# def url_for(page)
|
|
234
|
+
# if page.site.name == "Next"
|
|
235
|
+
# "https://user:#{ENV['PREVIEW_HTTP_PASS']}@next.acme.com"
|
|
236
|
+
# else
|
|
237
|
+
# "https://www.acme.com"
|
|
238
|
+
# end
|
|
239
|
+
# end
|
|
240
|
+
# end
|
|
241
|
+
#
|
|
242
|
+
# # config/initializers/alchemy.rb
|
|
243
|
+
# require "acme/preview_source"
|
|
244
|
+
# Alchemy.config.preview_sources << "Acme::PreviewSource"
|
|
245
|
+
#
|
|
246
|
+
# # config/locales/de.yml
|
|
247
|
+
# de:
|
|
248
|
+
# activemodel:
|
|
249
|
+
# models:
|
|
250
|
+
# acme/preview_source: Acme Vorschau
|
|
251
|
+
#
|
|
252
|
+
option :preview_sources, :collection, item_type: :class, collection_class: Set, default: ["Alchemy::Admin::PreviewUrl"]
|
|
253
|
+
|
|
254
|
+
# Additional JS modules to be imported in the Alchemy admin UI
|
|
255
|
+
#
|
|
256
|
+
# Be sure to also pin the modules with +Alchemy.importmap+.
|
|
257
|
+
#
|
|
258
|
+
# == Example
|
|
259
|
+
#
|
|
260
|
+
# Alchemy.importmap.pin "flatpickr/de",
|
|
261
|
+
# to: "https://ga.jspm.io/npm:flatpickr@4.6.13/dist/l10n/de.js"
|
|
262
|
+
#
|
|
263
|
+
# Alchemy.config.admin_js_imports << "flatpickr/de"
|
|
264
|
+
#
|
|
265
|
+
option :admin_js_imports, :collection, item_type: :string, collection_class: Set, default: []
|
|
266
|
+
|
|
267
|
+
# Additional importmaps to be included in the Alchemy admin UI
|
|
268
|
+
#
|
|
269
|
+
# Be sure to also pin modules with +Alchemy.importmap+.
|
|
270
|
+
#
|
|
271
|
+
# == Example
|
|
272
|
+
#
|
|
273
|
+
# # config/alchemy/importmap.rb
|
|
274
|
+
# Alchemy.importmap.pin "alchemy_solidus", to: "alchemy_solidus.js", preload: true
|
|
275
|
+
# Alchemy.importmap.pin_all_from Alchemy::Solidus::Engine.root.join("app/javascript/alchemy_solidus"),
|
|
276
|
+
# under: "alchemy_solidus",
|
|
277
|
+
# preload: true
|
|
278
|
+
#
|
|
279
|
+
# # lib/alchemy/solidus/engine.rb
|
|
280
|
+
# initializer "alchemy_solidus.assets", before: "alchemy.importmap" do |app|
|
|
281
|
+
# Alchemy.admin_importmaps.add({
|
|
282
|
+
# importmap_path: root.join("config/importmap.rb"),
|
|
283
|
+
# source_paths: [
|
|
284
|
+
# root.join("app/javascript")
|
|
285
|
+
# ],
|
|
286
|
+
# name: "alchemy_solidus"
|
|
287
|
+
# })
|
|
288
|
+
# app.config.assets.precompile << "alchemy_solidus/manifest.js"
|
|
289
|
+
# end
|
|
290
|
+
#
|
|
291
|
+
option :admin_importmaps, :collection, collection_class: Set, item_type: :configuration, config_class: Alchemy::Configurations::Importmap, default: []
|
|
292
|
+
|
|
293
|
+
# Additional stylesheets to be included in the Alchemy admin UI
|
|
294
|
+
#
|
|
295
|
+
# == Example
|
|
296
|
+
#
|
|
297
|
+
# # lib/alchemy/devise/engine.rb
|
|
298
|
+
# initializer "alchemy.devise.stylesheets", before: "alchemy.admin_stylesheets" do
|
|
299
|
+
# Alchemy.config.admin_stylesheets << "alchemy/devise/admin.css"
|
|
300
|
+
# end
|
|
301
|
+
#
|
|
302
|
+
option :admin_stylesheets, :collection, collection_class: Set, item_type: :string, default: ["alchemy/admin/custom.css"]
|
|
303
|
+
|
|
304
|
+
# Define page publish targets
|
|
305
|
+
#
|
|
306
|
+
# A publish target is a ActiveJob that gets performed
|
|
307
|
+
# whenever a user clicks the publish page button.
|
|
308
|
+
#
|
|
309
|
+
# Use this to trigger deployment hooks of external
|
|
310
|
+
# services in an asychronous way.
|
|
311
|
+
#
|
|
312
|
+
# == Example
|
|
313
|
+
#
|
|
314
|
+
# # app/jobs/publish_job.rb
|
|
315
|
+
# class PublishJob < ApplicationJob
|
|
316
|
+
# def perform(page)
|
|
317
|
+
# RestClient.post(ENV['BUILD_HOOK_URL'])
|
|
318
|
+
# end
|
|
319
|
+
# end
|
|
320
|
+
#
|
|
321
|
+
# # config/initializers/alchemy.rb
|
|
322
|
+
# Alchemy.config.publish_targets << PublishJob
|
|
323
|
+
#
|
|
324
|
+
option :publish_targets, :collection, collection_class: Set, item_type: :class, default: []
|
|
325
|
+
|
|
326
|
+
# Configure tabs in the link dialog
|
|
327
|
+
#
|
|
328
|
+
# With this configuration that tabs in the link dialog can be extended
|
|
329
|
+
# without overwriting or defacing the Admin Interface.
|
|
330
|
+
#
|
|
331
|
+
# == Example
|
|
332
|
+
#
|
|
333
|
+
# # components/acme/link_tab.rb
|
|
334
|
+
# module Acme
|
|
335
|
+
# class LinkTab < ::Alchemy::Admin::LinkDialog::BaseTab
|
|
336
|
+
# def title
|
|
337
|
+
# "Awesome Tab Title"
|
|
338
|
+
# end
|
|
339
|
+
#
|
|
340
|
+
# def name
|
|
341
|
+
# :unique_name
|
|
342
|
+
# end
|
|
343
|
+
#
|
|
344
|
+
# def fields
|
|
345
|
+
# [ title_input, target_select ]
|
|
346
|
+
# end
|
|
347
|
+
# end
|
|
348
|
+
# end
|
|
349
|
+
#
|
|
350
|
+
# # config/initializers/alchemy.rb
|
|
351
|
+
# Alchemy.config.link_dialog_tabs << "Acme::LinkTab"
|
|
352
|
+
#
|
|
353
|
+
option :link_dialog_tabs, :collection, collection_class: Set, item_type: :class, default: [
|
|
354
|
+
"Alchemy::Admin::LinkDialog::InternalTab",
|
|
355
|
+
"Alchemy::Admin::LinkDialog::AnchorTab",
|
|
356
|
+
"Alchemy::Admin::LinkDialog::ExternalTab",
|
|
357
|
+
"Alchemy::Admin::LinkDialog::FileTab"
|
|
358
|
+
]
|
|
221
359
|
end
|
|
222
360
|
end
|
|
223
361
|
end
|
|
@@ -4,8 +4,8 @@ module Alchemy
|
|
|
4
4
|
module Configurations
|
|
5
5
|
class Uploader < Alchemy::Configuration
|
|
6
6
|
class AllowedFileTypes < Alchemy::Configuration
|
|
7
|
-
option :alchemy_attachments, :
|
|
8
|
-
option :alchemy_pictures, :
|
|
7
|
+
option :alchemy_attachments, :collection, item_type: :string, default: ["*"]
|
|
8
|
+
option :alchemy_pictures, :collection, item_type: :string, default: %w[jpg jpeg gif png svg webp]
|
|
9
9
|
|
|
10
10
|
def set(configuration_hash)
|
|
11
11
|
super(configuration_hash.transform_keys { transform_key(_1) })
|
data/lib/alchemy/deprecation.rb
CHANGED
data/lib/alchemy/engine.rb
CHANGED
|
@@ -26,7 +26,7 @@ module Alchemy
|
|
|
26
26
|
|
|
27
27
|
initializer "alchemy.admin_stylesheets" do |app|
|
|
28
28
|
if defined?(Sprockets)
|
|
29
|
-
Alchemy.admin_stylesheets.each do |stylesheet|
|
|
29
|
+
Alchemy.config.admin_stylesheets.each do |stylesheet|
|
|
30
30
|
app.config.assets.precompile << stylesheet
|
|
31
31
|
end
|
|
32
32
|
end
|
|
@@ -42,22 +42,35 @@ module Alchemy
|
|
|
42
42
|
end
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
+
initializer "alchemy.admin_importmap" do
|
|
46
|
+
Alchemy.config.admin_importmaps.add(
|
|
47
|
+
importmap_path: root.join("config/importmap.rb"),
|
|
48
|
+
source_paths: [
|
|
49
|
+
root.join("app/javascript"),
|
|
50
|
+
root.join("vendor/javascript")
|
|
51
|
+
],
|
|
52
|
+
name: "alchemy_admin"
|
|
53
|
+
)
|
|
54
|
+
end
|
|
55
|
+
|
|
45
56
|
initializer "alchemy.importmap" do |app|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
Alchemy.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
57
|
+
app.config.to_prepare do
|
|
58
|
+
watch_paths = []
|
|
59
|
+
|
|
60
|
+
Alchemy.config.admin_importmaps.each do |admin_import|
|
|
61
|
+
Alchemy.importmap.draw admin_import.importmap_path
|
|
62
|
+
watch_paths += admin_import.source_paths.to_a
|
|
63
|
+
app.config.assets.paths += admin_import.source_paths.to_a
|
|
64
|
+
if admin_import[:name] != "alchemy_admin"
|
|
65
|
+
Alchemy.config.admin_js_imports.add(admin_import.name)
|
|
66
|
+
end
|
|
54
67
|
end
|
|
55
|
-
end
|
|
56
68
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
69
|
+
if app.config.importmap.sweep_cache
|
|
70
|
+
Alchemy.importmap.cache_sweeper(watches: watch_paths)
|
|
71
|
+
ActiveSupport.on_load(:action_controller_base) do
|
|
72
|
+
before_action { Alchemy.importmap.cache_sweeper.execute_if_updated }
|
|
73
|
+
end
|
|
61
74
|
end
|
|
62
75
|
end
|
|
63
76
|
end
|
|
@@ -13,11 +13,20 @@ module Alchemy
|
|
|
13
13
|
module ConfigStubbing
|
|
14
14
|
# Stub a key from the Alchemy config
|
|
15
15
|
#
|
|
16
|
-
# @param
|
|
17
|
-
# @param value [Object] The value you want to return instead of the original one
|
|
16
|
+
# @param hash [Hash] The keys you would like to stub along with their values
|
|
18
17
|
#
|
|
19
|
-
def stub_alchemy_config(
|
|
20
|
-
|
|
18
|
+
def stub_alchemy_config(hash)
|
|
19
|
+
stub_config(Alchemy.config, hash)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def stub_config(config, hash)
|
|
23
|
+
hash.each do |key, value|
|
|
24
|
+
if value.is_a?(Hash)
|
|
25
|
+
stub_config(config.send(key), value)
|
|
26
|
+
else
|
|
27
|
+
allow(config).to receive(key).and_return(value)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
21
30
|
end
|
|
22
31
|
end
|
|
23
32
|
end
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
FactoryBot.define do
|
|
4
4
|
factory :alchemy_language, class: "Alchemy::Language" do
|
|
5
5
|
name { "Your Language" }
|
|
6
|
-
|
|
6
|
+
language_code { "en" }
|
|
7
|
+
locale { ::I18n.default_locale }
|
|
7
8
|
default { true }
|
|
8
9
|
frontpage_name { "Intro" }
|
|
9
10
|
page_layout { Alchemy.config.default_language.page_layout }
|
|
@@ -14,20 +15,23 @@ FactoryBot.define do
|
|
|
14
15
|
|
|
15
16
|
trait :klingon do
|
|
16
17
|
name { "Klingon" }
|
|
17
|
-
|
|
18
|
+
language_code { "kl" }
|
|
19
|
+
locale { :kl }
|
|
18
20
|
frontpage_name { "Tuq" }
|
|
19
21
|
default { false }
|
|
20
22
|
end
|
|
21
23
|
|
|
22
24
|
trait :english do
|
|
23
25
|
name { "English" }
|
|
24
|
-
|
|
26
|
+
language_code { "en" }
|
|
27
|
+
locale { :en }
|
|
25
28
|
default { false }
|
|
26
29
|
end
|
|
27
30
|
|
|
28
31
|
trait :german do
|
|
29
32
|
name { "Deutsch" }
|
|
30
|
-
|
|
33
|
+
language_code { "de" }
|
|
34
|
+
locale { :de }
|
|
31
35
|
default { false }
|
|
32
36
|
end
|
|
33
37
|
end
|