alchemy_cms 4.1.2 → 4.2.0.rc1
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/ISSUE_TEMPLATE/Bug_report.md +0 -5
- data/.rubocop.yml +4 -1
- data/.travis.yml +3 -3
- data/CHANGELOG.md +29 -10
- data/Gemfile +5 -7
- data/README.md +114 -62
- data/Rakefile +2 -2
- data/alchemy_cms.gemspec +5 -5
- data/app/assets/images/alchemy/icon.svg +1 -1
- data/app/assets/javascripts/alchemy/admin.js +2 -0
- data/app/assets/javascripts/alchemy/alchemy.base.js.coffee +0 -24
- data/app/assets/javascripts/alchemy/alchemy.datepicker.js.coffee +11 -9
- data/app/assets/javascripts/alchemy/alchemy.dragndrop.js.coffee +7 -24
- data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +9 -8
- data/app/assets/javascripts/alchemy/alchemy.fixed_elements.js +38 -0
- data/app/assets/javascripts/alchemy/alchemy.sitemap.js.coffee +2 -4
- data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +1 -1
- data/app/assets/stylesheets/alchemy/_mixins.scss +2 -1
- data/app/assets/stylesheets/alchemy/_variables.scss +7 -2
- data/app/assets/stylesheets/alchemy/admin.scss +2 -1
- data/app/assets/stylesheets/alchemy/archive.scss +18 -4
- data/app/assets/stylesheets/alchemy/buttons.scss +1 -1
- data/app/assets/stylesheets/alchemy/dialogs.scss +1 -1
- data/app/assets/stylesheets/alchemy/elements.scss +154 -90
- data/app/assets/stylesheets/alchemy/filter_field.scss +30 -0
- data/app/assets/stylesheets/alchemy/flatpickr.scss +839 -0
- data/app/assets/stylesheets/alchemy/forms.scss +5 -1
- data/app/assets/stylesheets/alchemy/frame.scss +6 -14
- data/app/assets/stylesheets/alchemy/navigation.scss +109 -98
- data/app/assets/stylesheets/alchemy/search.scss +11 -29
- data/app/assets/stylesheets/alchemy/tables.scss +0 -23
- data/app/assets/stylesheets/alchemy/tags.scss +4 -27
- data/app/assets/stylesheets/alchemy/toolbar.scss +12 -2
- data/app/assets/stylesheets/tinymce/skins/alchemy/skin.min.css.scss +4 -33
- data/app/controllers/alchemy/admin/attachments_controller.rb +1 -12
- data/app/controllers/alchemy/admin/contents_controller.rb +2 -24
- data/app/controllers/alchemy/admin/elements_controller.rb +11 -49
- data/app/controllers/alchemy/admin/pages_controller.rb +1 -1
- data/app/controllers/alchemy/admin/pictures_controller.rb +1 -14
- data/app/controllers/alchemy/api/contents_controller.rb +1 -1
- data/app/controllers/alchemy/api/elements_controller.rb +1 -1
- data/app/controllers/alchemy/api/pages_controller.rb +1 -1
- data/app/controllers/concerns/alchemy/admin/archive_overlay.rb +20 -0
- data/app/helpers/alchemy/admin/base_helper.rb +8 -18
- data/app/helpers/alchemy/admin/elements_helper.rb +55 -85
- data/app/helpers/alchemy/admin/pictures_helper.rb +0 -23
- data/app/helpers/alchemy/elements_helper.rb +80 -120
- data/app/helpers/alchemy/pages_helper.rb +5 -24
- data/app/models/alchemy/content.rb +0 -1
- data/app/models/alchemy/content/factory.rb +33 -57
- data/app/models/alchemy/element.rb +46 -66
- data/app/models/alchemy/element/element_contents.rb +2 -2
- data/app/models/alchemy/page.rb +34 -4
- data/app/models/alchemy/page/page_elements.rb +30 -122
- data/app/serializers/alchemy/attachment_serializer.rb +0 -2
- data/app/serializers/alchemy/content_serializer.rb +0 -2
- data/app/serializers/alchemy/element_serializer.rb +0 -3
- data/app/serializers/alchemy/essence_boolean_serializer.rb +0 -2
- data/app/serializers/alchemy/essence_date_serializer.rb +0 -2
- data/app/serializers/alchemy/essence_file_serializer.rb +0 -2
- data/app/serializers/alchemy/essence_html_serializer.rb +0 -2
- data/app/serializers/alchemy/essence_link_serializer.rb +0 -2
- data/app/serializers/alchemy/essence_picture_serializer.rb +0 -2
- data/app/serializers/alchemy/essence_richtext_serializer.rb +0 -2
- data/app/serializers/alchemy/essence_select_serializer.rb +0 -2
- data/app/serializers/alchemy/essence_text_serializer.rb +0 -2
- data/app/serializers/alchemy/legacy_element_serializer.rb +0 -3
- data/app/serializers/alchemy/page_serializer.rb +2 -8
- data/app/serializers/alchemy/page_tree_serializer.rb +1 -1
- data/app/serializers/alchemy/picture_serializer.rb +0 -2
- data/app/views/alchemy/admin/clipboard/index.html.erb +2 -2
- data/app/views/alchemy/admin/clipboard/insert.js.erb +9 -12
- data/app/views/alchemy/admin/contents/create.js.erb +4 -30
- data/app/views/alchemy/admin/elements/_element.html.erb +27 -12
- data/app/views/alchemy/admin/elements/_element_toolbar.html.erb +1 -1
- data/app/views/alchemy/admin/elements/_new_element_form.html.erb +0 -10
- data/app/views/alchemy/admin/elements/create.js.erb +12 -12
- data/app/views/alchemy/admin/elements/fold.js.erb +1 -1
- data/app/views/alchemy/admin/elements/index.html.erb +20 -19
- data/app/views/alchemy/admin/elements/publish.js.erb +5 -0
- data/app/views/alchemy/admin/elements/trash.js.erb +4 -1
- data/app/views/alchemy/admin/essence_pictures/assign.js.erb +0 -7
- data/app/views/alchemy/admin/essence_pictures/destroy.js.erb +0 -22
- data/app/views/alchemy/admin/pages/_publication_fields.html.erb +2 -4
- data/app/views/alchemy/admin/pages/edit.html.erb +1 -1
- data/app/views/alchemy/admin/pages/index.html.erb +14 -10
- data/app/views/alchemy/admin/partials/_language_tree_select.html.erb +1 -1
- data/app/views/alchemy/admin/partials/_main_navigation_entry.html.erb +1 -1
- data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +7 -5
- data/app/views/alchemy/admin/partials/_routes.html.erb +0 -1
- data/app/views/alchemy/admin/partials/_search_form.html.erb +6 -4
- data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +6 -3
- data/app/views/alchemy/admin/pictures/index.html.erb +1 -1
- data/app/views/alchemy/admin/trash/index.html.erb +8 -7
- data/app/views/alchemy/elements/_editor_not_found.html.erb +1 -1
- data/app/views/alchemy/essences/_essence_picture_editor.html.erb +4 -19
- data/app/views/layouts/alchemy/admin.html.erb +1 -0
- data/bin/rspec +0 -5
- data/config/alchemy/config.yml +3 -0
- data/config/brakeman.ignore +1 -1
- data/config/locales/alchemy.en.yml +6 -12
- data/config/routes.rb +1 -5
- data/db/migrate/20180226123013_alchemy_four_point_zero.rb +0 -29
- data/db/migrate/20180519204655_add_fixed_to_alchemy_elements.rb +6 -0
- data/lib/alchemy/admin/locale.rb +1 -1
- data/lib/alchemy/cache_digests/template_tracker.rb +4 -27
- data/lib/alchemy/elements_finder.rb +111 -0
- data/lib/alchemy/errors.rb +0 -4
- data/lib/alchemy/modules.rb +49 -18
- data/lib/alchemy/tasks/tidy.rb +3 -40
- data/lib/alchemy/test_support/controller_requests.rb +1 -1
- data/lib/alchemy/test_support/essence_shared_examples.rb +1 -1
- data/lib/alchemy/test_support/factories/attachment_factory.rb +5 -3
- data/lib/alchemy/test_support/factories/content_factory.rb +4 -4
- data/lib/alchemy/test_support/factories/dummy_user_factory.rb +5 -5
- data/lib/alchemy/test_support/factories/element_factory.rb +12 -7
- data/lib/alchemy/test_support/factories/essence_text_factory.rb +1 -1
- data/lib/alchemy/test_support/factories/language_factory.rb +13 -13
- data/lib/alchemy/test_support/factories/page_factory.rb +18 -17
- data/lib/alchemy/test_support/factories/picture_factory.rb +6 -4
- data/lib/alchemy/test_support/factories/site_factory.rb +6 -6
- data/lib/alchemy/tinymce.rb +1 -1
- data/lib/alchemy/upgrader/four_point_two.rb +68 -0
- data/lib/alchemy/upgrader/tasks/cells_migration.rb +41 -0
- data/lib/alchemy/upgrader/tasks/cells_upgrader.rb +146 -0
- data/lib/alchemy/upgrader/tasks/picture_gallery_migration.rb +65 -0
- data/lib/alchemy/upgrader/tasks/picture_gallery_upgrader.rb +195 -0
- data/lib/alchemy/version.rb +1 -1
- data/lib/alchemy_cms.rb +1 -0
- data/lib/rails/generators/alchemy/elements/elements_generator.rb +1 -0
- data/lib/rails/generators/alchemy/elements/templates/editor.html.erb +0 -3
- data/lib/rails/generators/alchemy/elements/templates/editor.html.haml +0 -3
- data/lib/rails/generators/alchemy/elements/templates/editor.html.slim +0 -3
- data/lib/rails/generators/alchemy/elements/templates/view.html.erb +3 -14
- data/lib/rails/generators/alchemy/elements/templates/view.html.haml +3 -10
- data/lib/rails/generators/alchemy/elements/templates/view.html.slim +3 -10
- data/lib/tasks/alchemy/tidy.rake +1 -23
- data/lib/tasks/alchemy/upgrade.rake +44 -1
- data/vendor/assets/javascripts/flatpickr/flatpickr.min.js +2 -0
- data/vendor/assets/javascripts/tinymce/license.txt +0 -0
- data/vendor/assets/javascripts/tinymce/tinymce.min.js +2 -2
- metadata +25 -31
- data/app/assets/stylesheets/alchemy/jquery.datetimepicker.scss +0 -478
- data/app/models/alchemy/cell.rb +0 -95
- data/app/models/alchemy/page/page_cells.rb +0 -69
- data/app/serializers/alchemy/cell_serializer.rb +0 -19
- data/app/views/alchemy/admin/contents/new.html.erb +0 -11
- data/app/views/alchemy/admin/contents/order.js.erb +0 -3
- data/app/views/alchemy/admin/elements/_add_picture.html.erb +0 -14
- data/app/views/alchemy/admin/elements/_picture_gallery_editor.html.erb +0 -24
- data/bin/spring +0 -16
- data/lib/alchemy/test_support/factories/cell_factory.rb +0 -9
- data/vendor/assets/javascripts/date-formatter.js +0 -161
- data/vendor/assets/javascripts/jquery_plugins/jquery.datetimepicker.full.min.js +0 -2
data/lib/alchemy/admin/locale.rb
CHANGED
|
@@ -28,7 +28,7 @@ module Alchemy
|
|
|
28
28
|
|
|
29
29
|
# Checks if we need to change to locale or not.
|
|
30
30
|
def locale_change_needed?
|
|
31
|
-
params[:admin_locale].present? || session[:alchemy_locale].blank?
|
|
31
|
+
params[:admin_locale].present? || session[:alchemy_locale].blank?
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
# Returns either the most preferred locale that is within the list of available locales or nil
|
|
@@ -14,19 +14,12 @@ module Alchemy
|
|
|
14
14
|
def dependencies
|
|
15
15
|
case @name.to_s
|
|
16
16
|
when /^alchemy\/pages\/show/
|
|
17
|
-
PageLayout.all.
|
|
17
|
+
PageLayout.all.map { |p| "alchemy/page_layouts/_#{p['name']}" }
|
|
18
18
|
when /^alchemy\/page_layouts\/_(.+)/
|
|
19
|
-
page_layout =
|
|
20
|
-
|
|
21
|
-
page_layout.fetch('cells', []).map { |name| "alchemy/cells/_#{name}" }
|
|
22
|
-
when /^alchemy\/cells\/_(.+)/
|
|
23
|
-
element_templates cell_definition($1)
|
|
19
|
+
page_layout = PageLayout.get($1)
|
|
20
|
+
page_layout.fetch('elements', []).map { |name| "alchemy/elements/_#{name}_view" }
|
|
24
21
|
when /alchemy\/elements\/_(.+)_view/
|
|
25
22
|
essences = essence_types($1)
|
|
26
|
-
element = element_definition($1)
|
|
27
|
-
if element && element['picture_gallery']
|
|
28
|
-
essences += ['EssencePicture']
|
|
29
|
-
end
|
|
30
23
|
essences.map { |name| "alchemy/essences/_#{name.underscore}_view" }.uniq
|
|
31
24
|
else
|
|
32
25
|
ActionView::DependencyTracker::ERBTracker.call(@name, @template)
|
|
@@ -35,24 +28,8 @@ module Alchemy
|
|
|
35
28
|
|
|
36
29
|
private
|
|
37
30
|
|
|
38
|
-
def element_templates(collection)
|
|
39
|
-
collection.fetch('elements', []).map { |name| "alchemy/elements/_#{name}_view" }
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def page_layout(name)
|
|
43
|
-
PageLayout.get(name)
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def cell_definition(name)
|
|
47
|
-
Cell.definition_for(name)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def element_definition(name)
|
|
51
|
-
Element.definitions.detect { |e| e['name'] == name }
|
|
52
|
-
end
|
|
53
|
-
|
|
54
31
|
def essence_types(name)
|
|
55
|
-
element =
|
|
32
|
+
element = Element.definitions.detect { |e| e['name'] == name }
|
|
56
33
|
return [] unless element
|
|
57
34
|
element.fetch('contents', []).collect { |c| c['type'] }
|
|
58
35
|
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'alchemy/logger'
|
|
4
|
+
|
|
5
|
+
module Alchemy
|
|
6
|
+
# Loads elements from given page
|
|
7
|
+
#
|
|
8
|
+
# Used by {Alchemy::Page#find_elements} and {Alchemy::ElementsHelper#render_elements} helper.
|
|
9
|
+
#
|
|
10
|
+
# If you need custom element loading logic in your views you can create your own finder class and
|
|
11
|
+
# tell the {Alchemy::ElementsHelper#render_elements} helper or {Alchemy::Page#find_elements}
|
|
12
|
+
# to use that finder instead of this one.
|
|
13
|
+
#
|
|
14
|
+
class ElementsFinder
|
|
15
|
+
# @option options [Array<String>|String] :only
|
|
16
|
+
# A list of element names to load only.
|
|
17
|
+
# @option options [Array<String>|String] :except
|
|
18
|
+
# A list of element names not to load.
|
|
19
|
+
# @option options [Boolean] :fixed (false)
|
|
20
|
+
# Return only fixed elements
|
|
21
|
+
# @option options [Integer] :count
|
|
22
|
+
# The amount of elements to load
|
|
23
|
+
# @option options [Integer] :offset
|
|
24
|
+
# The offset to begin loading elements from
|
|
25
|
+
# @option options [Boolean] :random (false)
|
|
26
|
+
# Randomize the output of elements
|
|
27
|
+
# @option options [Boolean] :reverse (false)
|
|
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
|
+
def initialize(options = {})
|
|
32
|
+
@options = options
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# @param page [Alchemy::Page|String]
|
|
36
|
+
# The page the elements are loaded from. You can pass a page_layout String or a {Alchemy::Page} object.
|
|
37
|
+
# @return [ActiveRecord::Relation]
|
|
38
|
+
def elements(page:)
|
|
39
|
+
elements = find_elements(page)
|
|
40
|
+
|
|
41
|
+
if fallback_required?(elements)
|
|
42
|
+
elements = elements.merge(fallback_elements)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
if options[:reverse]
|
|
46
|
+
elements = elements.reverse_order
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
if options[:random]
|
|
50
|
+
elements = elements.reorder(Arel.sql(random_function))
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
elements.offset(options[:offset]).limit(options[:count])
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
attr_reader :page, :options
|
|
59
|
+
|
|
60
|
+
def find_elements(page)
|
|
61
|
+
elements = Alchemy::Element
|
|
62
|
+
.where(page_id: page_ids(page))
|
|
63
|
+
.merge(Alchemy::Element.not_nested)
|
|
64
|
+
.where(fixed: !!options[:fixed])
|
|
65
|
+
.order(position: :asc)
|
|
66
|
+
.available
|
|
67
|
+
|
|
68
|
+
if options[:only]
|
|
69
|
+
elements = elements.named(options[:only])
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
if options[:except]
|
|
73
|
+
elements = elements.excluded(options[:except])
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
elements
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def page_ids(page)
|
|
80
|
+
case page
|
|
81
|
+
when String
|
|
82
|
+
Alchemy::Language.current.pages.where(
|
|
83
|
+
page_layout: page,
|
|
84
|
+
restricted: false
|
|
85
|
+
).pluck("#{Alchemy::Page.table_name}.id")
|
|
86
|
+
when Alchemy::Page
|
|
87
|
+
page.id
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def fallback_required?(elements)
|
|
92
|
+
options[:fallback] && elements
|
|
93
|
+
.where(Alchemy::Element.table_name => {name: options[:fallback][:for]})
|
|
94
|
+
.none?
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def fallback_elements
|
|
98
|
+
find_elements(options[:fallback][:from])
|
|
99
|
+
.named(options[:fallback][:with] || options[:fallback][:for])
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def random_function
|
|
103
|
+
case ActiveRecord::Base.connection_config[:adapter]
|
|
104
|
+
when 'postgresql', 'sqlite3'
|
|
105
|
+
then 'RANDOM()'
|
|
106
|
+
else
|
|
107
|
+
'RAND()'
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
data/lib/alchemy/errors.rb
CHANGED
data/lib/alchemy/modules.rb
CHANGED
|
@@ -6,25 +6,56 @@ module Alchemy
|
|
|
6
6
|
|
|
7
7
|
@@alchemy_modules = YAML.load_file(File.expand_path('../../config/alchemy/modules.yml', __dir__))
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
base
|
|
11
|
-
|
|
9
|
+
class << self
|
|
10
|
+
def included(base)
|
|
11
|
+
base.send :helper_method, :alchemy_modules, :module_definition_for
|
|
12
|
+
end
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
14
|
+
# Register a Alchemy module.
|
|
15
|
+
#
|
|
16
|
+
# A module is a Hash that must have at least a name and a navigation key
|
|
17
|
+
# that has a controller and action name.
|
|
18
|
+
#
|
|
19
|
+
# == Example:
|
|
20
|
+
#
|
|
21
|
+
# name: 'module',
|
|
22
|
+
# navigation: {
|
|
23
|
+
# controller: 'admin/controller_name',
|
|
24
|
+
# action: 'index'
|
|
25
|
+
# }
|
|
26
|
+
#
|
|
27
|
+
def register_module(module_definition)
|
|
28
|
+
definition_hash = module_definition.deep_stringify_keys
|
|
29
|
+
|
|
30
|
+
### Validate controller(s) existence
|
|
31
|
+
if definition_hash['navigation'].is_a?(Hash)
|
|
32
|
+
defined_controllers = [definition_hash['navigation']['controller']]
|
|
33
|
+
|
|
34
|
+
if definition_hash['navigation']['sub_navigation'].is_a?(Array)
|
|
35
|
+
defined_controllers.concat(definition_hash['navigation']['sub_navigation'].map{ |x| x['controller'] })
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
validate_controllers_existence(defined_controllers)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
@@alchemy_modules << definition_hash
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def validate_controllers_existence(controllers)
|
|
47
|
+
controllers.each do |controller_val|
|
|
48
|
+
next if controller_val.blank?
|
|
49
|
+
|
|
50
|
+
controller_name = "#{controller_val.camelize}Controller"
|
|
51
|
+
|
|
52
|
+
begin
|
|
53
|
+
controller_name.constantize
|
|
54
|
+
rescue NameError
|
|
55
|
+
raise "Error in AlchemyCMS module definition: '#{definition_hash['name']}'. Could not find the matching controller class #{controller_name.sub(/^::/, '')} for the specified controller: '#{controller_val}'"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
28
59
|
end
|
|
29
60
|
|
|
30
61
|
# Get the module definition for given module name
|
data/lib/alchemy/tasks/tidy.rb
CHANGED
|
@@ -5,29 +5,12 @@ module Alchemy
|
|
|
5
5
|
extend Shell
|
|
6
6
|
|
|
7
7
|
class << self
|
|
8
|
-
def create_missing_cells(page_layouts, cells)
|
|
9
|
-
page_layouts.each do |layout|
|
|
10
|
-
next if layout['cells'].blank?
|
|
11
|
-
cells_for_layout = cells.select { |cell| layout['cells'].include? cell['name'] }
|
|
12
|
-
Alchemy::Page.where(page_layout: layout['name']).each do |page|
|
|
13
|
-
cells_for_layout.each do |cell_for_layout|
|
|
14
|
-
cell = Alchemy::Cell.find_or_initialize_by(name: cell_for_layout['name'], page_id: page.id)
|
|
15
|
-
if cell.new_record?
|
|
16
|
-
log "Creating cell #{cell.name} for page #{page.name}"
|
|
17
|
-
else
|
|
18
|
-
log "Cell #{cell.name} for page #{page.name} already present", :skip
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
8
|
def update_element_positions
|
|
26
9
|
Alchemy::Page.all.each do |page|
|
|
27
10
|
if page.elements.any?
|
|
28
11
|
puts "\n## Updating element positions of page `#{page.name}`"
|
|
29
12
|
end
|
|
30
|
-
page.elements.group_by(&:
|
|
13
|
+
page.elements.group_by(&:parent_element_id).each do |_, elements|
|
|
31
14
|
elements.each_with_index do |element, idx|
|
|
32
15
|
position = idx + 1
|
|
33
16
|
if element.position != position
|
|
@@ -46,8 +29,7 @@ module Alchemy
|
|
|
46
29
|
if element.contents.any?
|
|
47
30
|
puts "\n## Updating content positions of element `#{element.name}`"
|
|
48
31
|
end
|
|
49
|
-
element.contents.group_by(&:
|
|
50
|
-
puts "-> Contents of type `#{essence_type}`"
|
|
32
|
+
element.contents.group_by(&:element_id).each do |_, contents|
|
|
51
33
|
contents.each_with_index do |content, idx|
|
|
52
34
|
position = idx + 1
|
|
53
35
|
if content.position != position
|
|
@@ -61,31 +43,12 @@ module Alchemy
|
|
|
61
43
|
end
|
|
62
44
|
end
|
|
63
45
|
|
|
64
|
-
def remove_orphaned_cells
|
|
65
|
-
puts "\n## Removing orphaned cells"
|
|
66
|
-
cells = Alchemy::Cell.unscoped.all
|
|
67
|
-
if cells.any?
|
|
68
|
-
orphaned_cells = cells.select do |cell|
|
|
69
|
-
cell.page.nil? && cell.page_id.present?
|
|
70
|
-
end
|
|
71
|
-
if orphaned_cells.any?
|
|
72
|
-
log "Found #{orphaned_cells.size} orphaned cells"
|
|
73
|
-
destroy_orphaned_records(orphaned_cells, 'cell')
|
|
74
|
-
else
|
|
75
|
-
log "No orphaned cells found", :skip
|
|
76
|
-
end
|
|
77
|
-
else
|
|
78
|
-
log "No cells found", :skip
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
|
|
82
46
|
def remove_orphaned_elements
|
|
83
47
|
puts "\n## Removing orphaned elements"
|
|
84
48
|
elements = Alchemy::Element.unscoped.all
|
|
85
49
|
if elements.any?
|
|
86
50
|
orphaned_elements = elements.select do |element|
|
|
87
|
-
element.page.nil? && element.page_id.present?
|
|
88
|
-
element.cell.nil? && element.cell_id.present?
|
|
51
|
+
element.page.nil? && element.page_id.present?
|
|
89
52
|
end
|
|
90
53
|
if orphaned_elements.any?
|
|
91
54
|
log "Found #{orphaned_elements.size} orphaned elements"
|
|
@@ -2,8 +2,10 @@ require 'factory_bot'
|
|
|
2
2
|
|
|
3
3
|
FactoryBot.define do
|
|
4
4
|
factory :alchemy_attachment, class: 'Alchemy::Attachment' do
|
|
5
|
-
file
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
file do
|
|
6
|
+
File.new(Alchemy::Engine.root.join('lib', 'alchemy', 'test_support', 'fixtures', 'image.png'))
|
|
7
|
+
end
|
|
8
|
+
name { 'image' }
|
|
9
|
+
file_name { 'image.png' }
|
|
8
10
|
end
|
|
9
11
|
end
|
|
@@ -3,18 +3,18 @@ require 'alchemy/test_support/factories/essence_text_factory'
|
|
|
3
3
|
|
|
4
4
|
FactoryBot.define do
|
|
5
5
|
factory :alchemy_content, class: 'Alchemy::Content' do
|
|
6
|
-
name "text"
|
|
7
|
-
essence_type "Alchemy::EssenceText"
|
|
6
|
+
name { "text" }
|
|
7
|
+
essence_type { "Alchemy::EssenceText" }
|
|
8
8
|
association :essence, factory: :alchemy_essence_text
|
|
9
9
|
association :element, factory: :alchemy_element
|
|
10
10
|
|
|
11
11
|
trait :essence_file do
|
|
12
|
-
essence_type "Alchemy::EssenceFile"
|
|
12
|
+
essence_type { "Alchemy::EssenceFile" }
|
|
13
13
|
association :essence, factory: :alchemy_essence_file
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
trait :essence_picture do
|
|
17
|
-
essence_type "Alchemy::EssencePicture"
|
|
17
|
+
essence_type { "Alchemy::EssencePicture" }
|
|
18
18
|
association :essence, factory: :alchemy_essence_picture
|
|
19
19
|
end
|
|
20
20
|
end
|
|
@@ -3,19 +3,19 @@ require 'factory_bot'
|
|
|
3
3
|
FactoryBot.define do
|
|
4
4
|
factory :alchemy_dummy_user, class: 'DummyUser' do
|
|
5
5
|
sequence(:email) { |n| "john.#{n}@doe.com" }
|
|
6
|
-
password 's3cr3t'
|
|
7
|
-
alchemy_roles ['member']
|
|
6
|
+
password { 's3cr3t' }
|
|
7
|
+
alchemy_roles { ['member'] }
|
|
8
8
|
|
|
9
9
|
trait :as_admin do
|
|
10
|
-
alchemy_roles ['admin']
|
|
10
|
+
alchemy_roles { ['admin'] }
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
trait :as_author do
|
|
14
|
-
alchemy_roles ['author']
|
|
14
|
+
alchemy_roles { ['author'] }
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
trait :as_editor do
|
|
18
|
-
alchemy_roles ['editor']
|
|
18
|
+
alchemy_roles { ['editor'] }
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
end
|
|
@@ -2,26 +2,31 @@ require 'factory_bot'
|
|
|
2
2
|
|
|
3
3
|
FactoryBot.define do
|
|
4
4
|
factory :alchemy_element, class: 'Alchemy::Element' do
|
|
5
|
-
name 'article'
|
|
6
|
-
|
|
5
|
+
name { 'article' }
|
|
6
|
+
autogenerate_contents { false }
|
|
7
7
|
association :page, factory: :alchemy_page
|
|
8
8
|
|
|
9
|
+
trait :fixed do
|
|
10
|
+
fixed { true }
|
|
11
|
+
name { 'right_column' }
|
|
12
|
+
end
|
|
13
|
+
|
|
9
14
|
trait :unique do
|
|
10
|
-
unique true
|
|
11
|
-
name 'header'
|
|
15
|
+
unique { true }
|
|
16
|
+
name { 'header' }
|
|
12
17
|
end
|
|
13
18
|
|
|
14
19
|
trait :with_nestable_elements do
|
|
15
|
-
name 'slider'
|
|
20
|
+
name { 'slider' }
|
|
16
21
|
end
|
|
17
22
|
|
|
18
23
|
trait :nested do
|
|
19
24
|
association :parent_element, factory: :alchemy_element, name: 'slider'
|
|
20
|
-
name 'slide'
|
|
25
|
+
name { 'slide' }
|
|
21
26
|
end
|
|
22
27
|
|
|
23
28
|
trait :with_contents do
|
|
24
|
-
|
|
29
|
+
autogenerate_contents { true }
|
|
25
30
|
end
|
|
26
31
|
end
|
|
27
32
|
end
|