alchemy_cms 5.1.0 → 5.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +2 -1
- data/CHANGELOG.md +51 -0
- data/Gemfile +2 -1
- data/alchemy_cms.gemspec +2 -2
- data/app/assets/stylesheets/alchemy/_variables.scss +2 -0
- data/app/assets/stylesheets/alchemy/elements.scss +38 -5
- data/app/controllers/alchemy/admin/base_controller.rb +1 -0
- data/app/controllers/alchemy/admin/trash_controller.rb +2 -0
- data/app/decorators/alchemy/content_editor.rb +64 -0
- data/app/decorators/alchemy/element_editor.rb +67 -0
- data/app/helpers/alchemy/admin/contents_helper.rb +3 -8
- data/app/helpers/alchemy/elements_helper.rb +0 -18
- data/app/helpers/alchemy/pages_helper.rb +3 -1
- data/app/models/alchemy/attachment.rb +4 -0
- data/app/models/alchemy/content.rb +7 -0
- data/app/models/alchemy/element.rb +38 -0
- data/app/models/alchemy/element/definitions.rb +5 -22
- data/app/models/alchemy/page/page_elements.rb +9 -2
- data/app/models/alchemy/picture_variant.rb +1 -1
- data/app/views/alchemy/admin/elements/_element.html.erb +1 -1
- data/app/views/alchemy/admin/elements/_element_footer.html.erb +1 -1
- data/app/views/alchemy/admin/elements/_element_header.html.erb +2 -0
- data/app/views/alchemy/admin/elements/_element_toolbar.html.erb +1 -1
- data/config/brakeman.ignore +305 -17
- data/config/locales/alchemy.en.yml +40 -24
- data/lib/alchemy/deprecation.rb +1 -1
- data/lib/alchemy/element_definition.rb +70 -0
- data/lib/alchemy/elements_finder.rb +6 -2
- data/lib/alchemy/essence.rb +4 -4
- data/lib/alchemy/filetypes.rb +13 -0
- data/lib/alchemy/forms/builder.rb +1 -1
- data/lib/alchemy/i18n.rb +4 -5
- data/lib/alchemy/page_layout.rb +1 -0
- data/lib/alchemy/resource.rb +5 -3
- data/lib/alchemy/test_support.rb +18 -0
- data/lib/alchemy/test_support/essence_shared_examples.rb +0 -3
- data/lib/alchemy/test_support/factories.rb +11 -0
- data/lib/alchemy/test_support/factories/attachment_factory.rb +0 -2
- data/lib/alchemy/test_support/factories/content_factory.rb +0 -6
- data/lib/alchemy/test_support/factories/dummy_user_factory.rb +0 -2
- data/lib/alchemy/test_support/factories/element_factory.rb +0 -3
- data/lib/alchemy/test_support/factories/essence_file_factory.rb +0 -3
- data/lib/alchemy/test_support/factories/essence_page_factory.rb +0 -3
- data/lib/alchemy/test_support/factories/essence_picture_factory.rb +0 -4
- data/lib/alchemy/test_support/factories/essence_text_factory.rb +0 -2
- data/lib/alchemy/test_support/factories/language_factory.rb +0 -3
- data/lib/alchemy/test_support/factories/node_factory.rb +0 -4
- data/lib/alchemy/test_support/factories/page_factory.rb +0 -3
- data/lib/alchemy/test_support/factories/picture_factory.rb +0 -2
- data/lib/alchemy/test_support/factories/picture_thumb_factory.rb +0 -3
- data/lib/alchemy/test_support/factories/site_factory.rb +0 -2
- data/lib/alchemy/test_support/integration_helpers.rb +5 -5
- data/lib/alchemy/version.rb +1 -1
- data/lib/alchemy_cms.rb +1 -0
- metadata +8 -6
@@ -130,31 +130,45 @@ en:
|
|
130
130
|
# == Mime Types translations
|
131
131
|
# These are human readable mime types used for the document-type row in archive files.
|
132
132
|
mime_types:
|
133
|
-
|
134
|
-
application/
|
135
|
-
application/
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
video/mpeg: 'MPEG-Video'
|
140
|
-
application/pdf: 'PDF-Document'
|
141
|
-
application/x-flash-video: 'Flash-Video'
|
142
|
-
video/x-flv: 'Flash-Video'
|
143
|
-
application/x-shockwave-flash: 'Flash-Movie'
|
144
|
-
application/zip: 'ZIP-Archive'
|
145
|
-
application/x-rar: 'RAR-Archive'
|
133
|
+
application/msexcel: Excel Spreadsheet
|
134
|
+
application/mspowerpoint: PowerPoint Presentation
|
135
|
+
application/msword: Word Document
|
136
|
+
application/pdf: PDF Document
|
137
|
+
application/rtf: RTF Document
|
138
|
+
application/vcard: vCard
|
146
139
|
application/vnd:
|
147
|
-
ms-excel:
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
application/
|
140
|
+
ms-excel: Excel Spreadsheet
|
141
|
+
ms-powerpoint: PowerPoint Presentation
|
142
|
+
ms-word: Word Document
|
143
|
+
openxmlformats-officedocument:
|
144
|
+
presentationml:
|
145
|
+
presentation: PowerPoint 2007 Presentation
|
146
|
+
spreadsheetml:
|
147
|
+
sheet: Excel 2007 Spreadsheet
|
148
|
+
wordprocessingml:
|
149
|
+
document: Word 2007 Document
|
150
|
+
application/x-flash-video: Flash Video
|
151
|
+
application/x-rar: RAR Archive
|
152
|
+
application/x-shockwave-flash: Flash Movie
|
153
|
+
application/zip: ZIP Archive
|
154
|
+
audio/mp4: MPEG-4 Audio
|
155
|
+
audio/mpeg: MP3 Audio
|
156
|
+
audio/wav: WAV Audio
|
157
|
+
audio/x-wav: WAV Audio
|
158
|
+
image/gif: GIF Image
|
159
|
+
image/jpeg: JPG Image
|
160
|
+
image/png: PNG Image
|
161
|
+
image/tiff: TIFF Image
|
162
|
+
image/x-psd: Photoshop File
|
163
|
+
image/svg+xml: SVG Image
|
164
|
+
text/plain: Plain Text Document
|
165
|
+
text/x-vcard: vCard
|
166
|
+
video/mp4: MPEG-4 Video
|
167
|
+
video/mpeg: MPEG Video
|
168
|
+
video/quicktime: Quicktime Video
|
169
|
+
video/x-flv: Flash Video
|
170
|
+
video/x-ms-wmv: Windows Media Video
|
171
|
+
video/x-msvideo: AVI Video
|
158
172
|
|
159
173
|
link_target_options:
|
160
174
|
default: Same Window
|
@@ -295,7 +309,9 @@ en:
|
|
295
309
|
"Visit page": "Visit page"
|
296
310
|
"Warning!": "Warning!"
|
297
311
|
content_definition_missing: "Warning: Content is missing its definition. Please check the elements.yml"
|
312
|
+
content_deprecated: "WARNING! This content is deprecated and will be removed soon. Please do not use it anymore."
|
298
313
|
element_definition_missing: "WARNING! Missing element definition. Please check your elements.yml file."
|
314
|
+
element_deprecated: "WARNING! This element is deprecated and will be removed soon. Please do not use it anymore."
|
299
315
|
page_definition_missing: "WARNING! Missing page layout definition. Please check your page_layouts.yml file."
|
300
316
|
"Welcome to Alchemy": "Welcome to Alchemy"
|
301
317
|
"Who else is online": "Who else is online"
|
data/lib/alchemy/deprecation.rb
CHANGED
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Alchemy
|
4
|
+
class ElementDefinition
|
5
|
+
class << self
|
6
|
+
# Returns the definitions from elements.yml file.
|
7
|
+
#
|
8
|
+
# Place a +elements.yml+ file inside your apps +config/alchemy+ folder to define
|
9
|
+
# your own set of elements
|
10
|
+
#
|
11
|
+
def all
|
12
|
+
@definitions ||= read_definitions_file.map(&:with_indifferent_access)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Add additional page definitions to collection.
|
16
|
+
#
|
17
|
+
# Useful for extending the elements from an Alchemy module.
|
18
|
+
#
|
19
|
+
# === Usage Example
|
20
|
+
#
|
21
|
+
# Call +Alchemy::ElementDefinition.add(your_definition)+ in your engine.rb file.
|
22
|
+
#
|
23
|
+
# @param [Array || Hash]
|
24
|
+
# You can pass a single element definition as Hash, or a collection of elements as Array.
|
25
|
+
#
|
26
|
+
def add(element)
|
27
|
+
all
|
28
|
+
if element.is_a?(Array)
|
29
|
+
@definitions += element
|
30
|
+
elsif element.is_a?(Hash)
|
31
|
+
@definitions << element
|
32
|
+
else
|
33
|
+
raise TypeError
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns one element definition by given name.
|
38
|
+
#
|
39
|
+
def get(name)
|
40
|
+
return {} if name.blank?
|
41
|
+
|
42
|
+
all.detect { |a| a["name"] == name }
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
# Reads the element definitions from +config/alchemy/elements.yml+.
|
48
|
+
#
|
49
|
+
def read_definitions_file
|
50
|
+
if File.exist?(definitions_file_path)
|
51
|
+
YAML.safe_load(
|
52
|
+
ERB.new(File.read(definitions_file_path)).result,
|
53
|
+
YAML_WHITELIST_CLASSES,
|
54
|
+
[],
|
55
|
+
true
|
56
|
+
) || []
|
57
|
+
else
|
58
|
+
raise LoadError,
|
59
|
+
"Could not find elements.yml file! Please run `rails generate alchemy:install`"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns the elements.yml file path
|
64
|
+
#
|
65
|
+
def definitions_file_path
|
66
|
+
Rails.root.join "config/alchemy/elements.yml"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -26,8 +26,6 @@ module Alchemy
|
|
26
26
|
# Randomize the output of elements
|
27
27
|
# @option options [Boolean] :reverse (false)
|
28
28
|
# Reverse the load order
|
29
|
-
# @option options [Hash] :fallback
|
30
|
-
# Define elements that are loaded from another page if no element was found on given page.
|
31
29
|
def initialize(options = {})
|
32
30
|
@options = options
|
33
31
|
end
|
@@ -83,6 +81,9 @@ module Alchemy
|
|
83
81
|
when Alchemy::Page
|
84
82
|
page_or_layout
|
85
83
|
when String
|
84
|
+
Alchemy::Deprecation.warn "Passing a String as `from_page` option to " \
|
85
|
+
"`render_elements` is deprecated and will be removed with Alchemy 6.0. " \
|
86
|
+
"Please load the page beforehand and pass it as an object instead."
|
86
87
|
Alchemy::Page.find_by(
|
87
88
|
language: Alchemy::Language.current,
|
88
89
|
page_layout: page_or_layout,
|
@@ -92,6 +93,9 @@ module Alchemy
|
|
92
93
|
end
|
93
94
|
|
94
95
|
def fallback_required?(elements)
|
96
|
+
if options[:fallback]
|
97
|
+
Alchemy::Deprecation.warn "Passing `fallback` options to `render_elements` is deprecated an will be removed with Alchemy 6.0."
|
98
|
+
end
|
95
99
|
options[:fallback] && elements
|
96
100
|
.where(Alchemy::Element.table_name => {name: options[:fallback][:for]})
|
97
101
|
.none?
|
data/lib/alchemy/essence.rb
CHANGED
@@ -83,7 +83,7 @@ module Alchemy #:nodoc:
|
|
83
83
|
|
84
84
|
if configuration[:belongs_to]
|
85
85
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
86
|
-
belongs_to :ingredient_association,
|
86
|
+
belongs_to :ingredient_association, **#{configuration[:belongs_to]}
|
87
87
|
|
88
88
|
alias_method :#{configuration[:ingredient_column]}, :ingredient_association
|
89
89
|
alias_method :#{configuration[:ingredient_column]}=, :ingredient_association=
|
@@ -108,9 +108,9 @@ module Alchemy #:nodoc:
|
|
108
108
|
# Register the current class as has_many association on +Alchemy::Page+ and +Alchemy::Element+ models
|
109
109
|
def register_as_essence_association!
|
110
110
|
klass_name = model_name.to_s
|
111
|
-
arguments = [:has_many, klass_name.demodulize.tableize.to_sym
|
112
|
-
|
113
|
-
%w(Page Element).each { |k| "Alchemy::#{k}".constantize.send(*arguments) }
|
111
|
+
arguments = [:has_many, klass_name.demodulize.tableize.to_sym]
|
112
|
+
kwargs = { through: :contents, source: :essence, source_type: klass_name }
|
113
|
+
%w(Page Element).each { |k| "Alchemy::#{k}".constantize.send(*arguments, **kwargs) }
|
114
114
|
end
|
115
115
|
end
|
116
116
|
|
data/lib/alchemy/filetypes.rb
CHANGED
@@ -40,7 +40,20 @@ module Alchemy
|
|
40
40
|
EXCEL_FILE_TYPES = [
|
41
41
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
42
42
|
"application/vnd.ms-excel",
|
43
|
+
"application/msexcel",
|
43
44
|
"text/csv",
|
44
45
|
]
|
46
|
+
|
47
|
+
WORD_FILE_TYPES = [
|
48
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
49
|
+
"application/vnd.ms-word",
|
50
|
+
"application/msword",
|
51
|
+
]
|
52
|
+
|
53
|
+
POWERPOINT_FILE_TYPES = [
|
54
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
55
|
+
"application/vnd.ms-powerpoint",
|
56
|
+
"application/mspowerpoint",
|
57
|
+
]
|
45
58
|
end
|
46
59
|
end
|
@@ -11,7 +11,7 @@ module Alchemy
|
|
11
11
|
if object.respond_to?(:attribute_fixed?) && object.attribute_fixed?(attribute_name)
|
12
12
|
options[:disabled] = true
|
13
13
|
options[:input_html] = options.fetch(:input_html, {}).merge(
|
14
|
-
"data-alchemy-tooltip" => Alchemy.t(:attribute_fixed, attribute_name),
|
14
|
+
"data-alchemy-tooltip" => Alchemy.t(:attribute_fixed, attribute: attribute_name),
|
15
15
|
)
|
16
16
|
end
|
17
17
|
|
data/lib/alchemy/i18n.rb
CHANGED
@@ -12,8 +12,8 @@ module Alchemy
|
|
12
12
|
#
|
13
13
|
# Alchemy.t(:hello)
|
14
14
|
#
|
15
|
-
def t(msg,
|
16
|
-
Alchemy::I18n.translate(msg,
|
15
|
+
def t(msg, **kwargs)
|
16
|
+
Alchemy::I18n.translate(msg, **kwargs)
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
@@ -47,11 +47,10 @@ module Alchemy
|
|
47
47
|
# world:
|
48
48
|
# hello: Hallo
|
49
49
|
#
|
50
|
-
def translate(msg,
|
51
|
-
options = args.extract_options!
|
50
|
+
def translate(msg, **options)
|
52
51
|
humanize_default_string!(msg, options)
|
53
52
|
scope = alchemy_scoped_scope(options)
|
54
|
-
::I18n.t(msg, options.merge(scope: scope))
|
53
|
+
::I18n.t(msg, **options.merge(scope: scope))
|
55
54
|
end
|
56
55
|
|
57
56
|
def available_locales
|
data/lib/alchemy/page_layout.rb
CHANGED
data/lib/alchemy/resource.rb
CHANGED
@@ -132,7 +132,9 @@ module Alchemy
|
|
132
132
|
end
|
133
133
|
|
134
134
|
def namespaced_resource_name
|
135
|
-
@_namespaced_resource_name ||=
|
135
|
+
@_namespaced_resource_name ||= begin
|
136
|
+
namespaced_resources_name.to_s.singularize
|
137
|
+
end.to_sym # Rails >= 6.0.3.7 needs symbols in polymorphic routes
|
136
138
|
end
|
137
139
|
|
138
140
|
def namespaced_resources_name
|
@@ -140,13 +142,13 @@ module Alchemy
|
|
140
142
|
resource_name_array = resource_array.dup
|
141
143
|
resource_name_array.delete(engine_name) if in_engine?
|
142
144
|
resource_name_array.join("_")
|
143
|
-
end
|
145
|
+
end.to_sym # Rails >= 6.0.3.7 needs symbols in polymorphic routes
|
144
146
|
end
|
145
147
|
|
146
148
|
def namespace_for_scope
|
147
149
|
namespace_array = namespace_diff
|
148
150
|
namespace_array.delete(engine_name) if in_engine?
|
149
|
-
namespace_array
|
151
|
+
namespace_array.map(&:to_sym) # Rails >= 6.0.3.7 needs symbols in polymorphic routes
|
150
152
|
end
|
151
153
|
|
152
154
|
# Returns an array of underscored association names
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Alchemy
|
4
|
+
module TestSupport
|
5
|
+
class << self
|
6
|
+
def factory_paths
|
7
|
+
Dir[
|
8
|
+
::Alchemy::Engine.root.join("lib", "alchemy", "test_support", "factories", "*_factory.rb")
|
9
|
+
].map { |path| path.sub(/.rb\z/, "") }
|
10
|
+
end
|
11
|
+
deprecate factory_paths: :factories_path, deprecator: Alchemy::Deprecation
|
12
|
+
|
13
|
+
def factories_path
|
14
|
+
::Alchemy::Engine.root.join("lib", "alchemy", "test_support", "factories")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -1,9 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "shoulda-matchers"
|
4
|
-
require "alchemy/test_support/factories/page_factory"
|
5
|
-
require "alchemy/test_support/factories/element_factory"
|
6
|
-
require "alchemy/test_support/factories/content_factory"
|
7
4
|
|
8
5
|
RSpec.shared_examples_for "an essence" do
|
9
6
|
let(:element) { Alchemy::Element.new }
|
@@ -1,5 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
Alchemy::Deprecation.warn <<~MSG
|
4
|
+
Please require factories using FactoryBots preferred approach:
|
5
|
+
|
6
|
+
# spec/rails_helper.rb
|
7
|
+
|
8
|
+
require 'alchemy/test_support'
|
9
|
+
|
10
|
+
FactoryBot.definition_file_paths.append(Alchemy::TestSupport.factories_path)
|
11
|
+
FactoryBot.find_definitions
|
12
|
+
MSG
|
13
|
+
|
3
14
|
Dir["#{File.dirname(__FILE__)}/factories/*.rb"].sort.each do |file|
|
4
15
|
require file
|
5
16
|
end
|
@@ -1,11 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "factory_bot"
|
4
|
-
require "alchemy/test_support/factories/element_factory"
|
5
|
-
require "alchemy/test_support/factories/essence_file_factory"
|
6
|
-
require "alchemy/test_support/factories/essence_picture_factory"
|
7
|
-
require "alchemy/test_support/factories/essence_text_factory"
|
8
|
-
|
9
3
|
FactoryBot.define do
|
10
4
|
factory :alchemy_content, class: "Alchemy::Content" do
|
11
5
|
name { "text" }
|
@@ -1,9 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "factory_bot"
|
4
|
-
require "alchemy/test_support/factories/content_factory"
|
5
|
-
require "alchemy/test_support/factories/picture_factory"
|
6
|
-
|
7
3
|
FactoryBot.define do
|
8
4
|
factory :alchemy_essence_picture, class: "Alchemy::EssencePicture" do
|
9
5
|
picture factory: :alchemy_picture
|