alchemy_cms 4.1.2 → 4.2.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/Bug_report.md +0 -5
  3. data/.rubocop.yml +4 -1
  4. data/.travis.yml +3 -3
  5. data/CHANGELOG.md +29 -10
  6. data/Gemfile +5 -7
  7. data/README.md +114 -62
  8. data/Rakefile +2 -2
  9. data/alchemy_cms.gemspec +5 -5
  10. data/app/assets/images/alchemy/icon.svg +1 -1
  11. data/app/assets/javascripts/alchemy/admin.js +2 -0
  12. data/app/assets/javascripts/alchemy/alchemy.base.js.coffee +0 -24
  13. data/app/assets/javascripts/alchemy/alchemy.datepicker.js.coffee +11 -9
  14. data/app/assets/javascripts/alchemy/alchemy.dragndrop.js.coffee +7 -24
  15. data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +9 -8
  16. data/app/assets/javascripts/alchemy/alchemy.fixed_elements.js +38 -0
  17. data/app/assets/javascripts/alchemy/alchemy.sitemap.js.coffee +2 -4
  18. data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +1 -1
  19. data/app/assets/stylesheets/alchemy/_mixins.scss +2 -1
  20. data/app/assets/stylesheets/alchemy/_variables.scss +7 -2
  21. data/app/assets/stylesheets/alchemy/admin.scss +2 -1
  22. data/app/assets/stylesheets/alchemy/archive.scss +18 -4
  23. data/app/assets/stylesheets/alchemy/buttons.scss +1 -1
  24. data/app/assets/stylesheets/alchemy/dialogs.scss +1 -1
  25. data/app/assets/stylesheets/alchemy/elements.scss +154 -90
  26. data/app/assets/stylesheets/alchemy/filter_field.scss +30 -0
  27. data/app/assets/stylesheets/alchemy/flatpickr.scss +839 -0
  28. data/app/assets/stylesheets/alchemy/forms.scss +5 -1
  29. data/app/assets/stylesheets/alchemy/frame.scss +6 -14
  30. data/app/assets/stylesheets/alchemy/navigation.scss +109 -98
  31. data/app/assets/stylesheets/alchemy/search.scss +11 -29
  32. data/app/assets/stylesheets/alchemy/tables.scss +0 -23
  33. data/app/assets/stylesheets/alchemy/tags.scss +4 -27
  34. data/app/assets/stylesheets/alchemy/toolbar.scss +12 -2
  35. data/app/assets/stylesheets/tinymce/skins/alchemy/skin.min.css.scss +4 -33
  36. data/app/controllers/alchemy/admin/attachments_controller.rb +1 -12
  37. data/app/controllers/alchemy/admin/contents_controller.rb +2 -24
  38. data/app/controllers/alchemy/admin/elements_controller.rb +11 -49
  39. data/app/controllers/alchemy/admin/pages_controller.rb +1 -1
  40. data/app/controllers/alchemy/admin/pictures_controller.rb +1 -14
  41. data/app/controllers/alchemy/api/contents_controller.rb +1 -1
  42. data/app/controllers/alchemy/api/elements_controller.rb +1 -1
  43. data/app/controllers/alchemy/api/pages_controller.rb +1 -1
  44. data/app/controllers/concerns/alchemy/admin/archive_overlay.rb +20 -0
  45. data/app/helpers/alchemy/admin/base_helper.rb +8 -18
  46. data/app/helpers/alchemy/admin/elements_helper.rb +55 -85
  47. data/app/helpers/alchemy/admin/pictures_helper.rb +0 -23
  48. data/app/helpers/alchemy/elements_helper.rb +80 -120
  49. data/app/helpers/alchemy/pages_helper.rb +5 -24
  50. data/app/models/alchemy/content.rb +0 -1
  51. data/app/models/alchemy/content/factory.rb +33 -57
  52. data/app/models/alchemy/element.rb +46 -66
  53. data/app/models/alchemy/element/element_contents.rb +2 -2
  54. data/app/models/alchemy/page.rb +34 -4
  55. data/app/models/alchemy/page/page_elements.rb +30 -122
  56. data/app/serializers/alchemy/attachment_serializer.rb +0 -2
  57. data/app/serializers/alchemy/content_serializer.rb +0 -2
  58. data/app/serializers/alchemy/element_serializer.rb +0 -3
  59. data/app/serializers/alchemy/essence_boolean_serializer.rb +0 -2
  60. data/app/serializers/alchemy/essence_date_serializer.rb +0 -2
  61. data/app/serializers/alchemy/essence_file_serializer.rb +0 -2
  62. data/app/serializers/alchemy/essence_html_serializer.rb +0 -2
  63. data/app/serializers/alchemy/essence_link_serializer.rb +0 -2
  64. data/app/serializers/alchemy/essence_picture_serializer.rb +0 -2
  65. data/app/serializers/alchemy/essence_richtext_serializer.rb +0 -2
  66. data/app/serializers/alchemy/essence_select_serializer.rb +0 -2
  67. data/app/serializers/alchemy/essence_text_serializer.rb +0 -2
  68. data/app/serializers/alchemy/legacy_element_serializer.rb +0 -3
  69. data/app/serializers/alchemy/page_serializer.rb +2 -8
  70. data/app/serializers/alchemy/page_tree_serializer.rb +1 -1
  71. data/app/serializers/alchemy/picture_serializer.rb +0 -2
  72. data/app/views/alchemy/admin/clipboard/index.html.erb +2 -2
  73. data/app/views/alchemy/admin/clipboard/insert.js.erb +9 -12
  74. data/app/views/alchemy/admin/contents/create.js.erb +4 -30
  75. data/app/views/alchemy/admin/elements/_element.html.erb +27 -12
  76. data/app/views/alchemy/admin/elements/_element_toolbar.html.erb +1 -1
  77. data/app/views/alchemy/admin/elements/_new_element_form.html.erb +0 -10
  78. data/app/views/alchemy/admin/elements/create.js.erb +12 -12
  79. data/app/views/alchemy/admin/elements/fold.js.erb +1 -1
  80. data/app/views/alchemy/admin/elements/index.html.erb +20 -19
  81. data/app/views/alchemy/admin/elements/publish.js.erb +5 -0
  82. data/app/views/alchemy/admin/elements/trash.js.erb +4 -1
  83. data/app/views/alchemy/admin/essence_pictures/assign.js.erb +0 -7
  84. data/app/views/alchemy/admin/essence_pictures/destroy.js.erb +0 -22
  85. data/app/views/alchemy/admin/pages/_publication_fields.html.erb +2 -4
  86. data/app/views/alchemy/admin/pages/edit.html.erb +1 -1
  87. data/app/views/alchemy/admin/pages/index.html.erb +14 -10
  88. data/app/views/alchemy/admin/partials/_language_tree_select.html.erb +1 -1
  89. data/app/views/alchemy/admin/partials/_main_navigation_entry.html.erb +1 -1
  90. data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +7 -5
  91. data/app/views/alchemy/admin/partials/_routes.html.erb +0 -1
  92. data/app/views/alchemy/admin/partials/_search_form.html.erb +6 -4
  93. data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +6 -3
  94. data/app/views/alchemy/admin/pictures/index.html.erb +1 -1
  95. data/app/views/alchemy/admin/trash/index.html.erb +8 -7
  96. data/app/views/alchemy/elements/_editor_not_found.html.erb +1 -1
  97. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +4 -19
  98. data/app/views/layouts/alchemy/admin.html.erb +1 -0
  99. data/bin/rspec +0 -5
  100. data/config/alchemy/config.yml +3 -0
  101. data/config/brakeman.ignore +1 -1
  102. data/config/locales/alchemy.en.yml +6 -12
  103. data/config/routes.rb +1 -5
  104. data/db/migrate/20180226123013_alchemy_four_point_zero.rb +0 -29
  105. data/db/migrate/20180519204655_add_fixed_to_alchemy_elements.rb +6 -0
  106. data/lib/alchemy/admin/locale.rb +1 -1
  107. data/lib/alchemy/cache_digests/template_tracker.rb +4 -27
  108. data/lib/alchemy/elements_finder.rb +111 -0
  109. data/lib/alchemy/errors.rb +0 -4
  110. data/lib/alchemy/modules.rb +49 -18
  111. data/lib/alchemy/tasks/tidy.rb +3 -40
  112. data/lib/alchemy/test_support/controller_requests.rb +1 -1
  113. data/lib/alchemy/test_support/essence_shared_examples.rb +1 -1
  114. data/lib/alchemy/test_support/factories/attachment_factory.rb +5 -3
  115. data/lib/alchemy/test_support/factories/content_factory.rb +4 -4
  116. data/lib/alchemy/test_support/factories/dummy_user_factory.rb +5 -5
  117. data/lib/alchemy/test_support/factories/element_factory.rb +12 -7
  118. data/lib/alchemy/test_support/factories/essence_text_factory.rb +1 -1
  119. data/lib/alchemy/test_support/factories/language_factory.rb +13 -13
  120. data/lib/alchemy/test_support/factories/page_factory.rb +18 -17
  121. data/lib/alchemy/test_support/factories/picture_factory.rb +6 -4
  122. data/lib/alchemy/test_support/factories/site_factory.rb +6 -6
  123. data/lib/alchemy/tinymce.rb +1 -1
  124. data/lib/alchemy/upgrader/four_point_two.rb +68 -0
  125. data/lib/alchemy/upgrader/tasks/cells_migration.rb +41 -0
  126. data/lib/alchemy/upgrader/tasks/cells_upgrader.rb +146 -0
  127. data/lib/alchemy/upgrader/tasks/picture_gallery_migration.rb +65 -0
  128. data/lib/alchemy/upgrader/tasks/picture_gallery_upgrader.rb +195 -0
  129. data/lib/alchemy/version.rb +1 -1
  130. data/lib/alchemy_cms.rb +1 -0
  131. data/lib/rails/generators/alchemy/elements/elements_generator.rb +1 -0
  132. data/lib/rails/generators/alchemy/elements/templates/editor.html.erb +0 -3
  133. data/lib/rails/generators/alchemy/elements/templates/editor.html.haml +0 -3
  134. data/lib/rails/generators/alchemy/elements/templates/editor.html.slim +0 -3
  135. data/lib/rails/generators/alchemy/elements/templates/view.html.erb +3 -14
  136. data/lib/rails/generators/alchemy/elements/templates/view.html.haml +3 -10
  137. data/lib/rails/generators/alchemy/elements/templates/view.html.slim +3 -10
  138. data/lib/tasks/alchemy/tidy.rake +1 -23
  139. data/lib/tasks/alchemy/upgrade.rake +44 -1
  140. data/vendor/assets/javascripts/flatpickr/flatpickr.min.js +2 -0
  141. data/vendor/assets/javascripts/tinymce/license.txt +0 -0
  142. data/vendor/assets/javascripts/tinymce/tinymce.min.js +2 -2
  143. metadata +25 -31
  144. data/app/assets/stylesheets/alchemy/jquery.datetimepicker.scss +0 -478
  145. data/app/models/alchemy/cell.rb +0 -95
  146. data/app/models/alchemy/page/page_cells.rb +0 -69
  147. data/app/serializers/alchemy/cell_serializer.rb +0 -19
  148. data/app/views/alchemy/admin/contents/new.html.erb +0 -11
  149. data/app/views/alchemy/admin/contents/order.js.erb +0 -3
  150. data/app/views/alchemy/admin/elements/_add_picture.html.erb +0 -14
  151. data/app/views/alchemy/admin/elements/_picture_gallery_editor.html.erb +0 -24
  152. data/bin/spring +0 -16
  153. data/lib/alchemy/test_support/factories/cell_factory.rb +0 -9
  154. data/vendor/assets/javascripts/date-formatter.js +0 -161
  155. data/vendor/assets/javascripts/jquery_plugins/jquery.datetimepicker.full.min.js +0 -2
@@ -2,6 +2,6 @@ require 'factory_bot'
2
2
 
3
3
  FactoryBot.define do
4
4
  factory :alchemy_essence_text, class: 'Alchemy::EssenceText' do
5
- body 'This is a headline'
5
+ body { 'This is a headline' }
6
6
  end
7
7
  end
@@ -3,26 +3,26 @@ require 'alchemy/test_support/factories/site_factory'
3
3
 
4
4
  FactoryBot.define do
5
5
  factory :alchemy_language, class: 'Alchemy::Language' do
6
- name 'Deutsch'
7
- code 'de'
8
- default true
9
- frontpage_name 'Intro'
6
+ name { 'Deutsch' }
7
+ code { 'de' }
8
+ default { true }
9
+ frontpage_name { 'Intro' }
10
10
  page_layout { Alchemy::Config.get(:default_language)['page_layout'] }
11
- public true
11
+ public { true }
12
12
  site { Alchemy::Site.default }
13
13
 
14
14
  trait :klingon do
15
- name 'Klingon'
16
- code 'kl'
17
- frontpage_name 'Tuq'
18
- default false
15
+ name { 'Klingon' }
16
+ code { 'kl' }
17
+ frontpage_name { 'Tuq' }
18
+ default { false }
19
19
  end
20
20
 
21
21
  trait :english do
22
- name 'English'
23
- code 'en'
24
- frontpage_name 'Intro'
25
- default false
22
+ name { 'English' }
23
+ code { 'en' }
24
+ frontpage_name { 'Intro' }
25
+ default { false }
26
26
  end
27
27
  end
28
28
  end
@@ -5,7 +5,7 @@ FactoryBot.define do
5
5
  factory :alchemy_page, class: 'Alchemy::Page' do
6
6
  language { Alchemy::Language.default || FactoryBot.create(:alchemy_language) }
7
7
  sequence(:name) { |n| "A Page #{n}" }
8
- page_layout "standard"
8
+ page_layout { "standard" }
9
9
 
10
10
  parent_id do
11
11
  (Alchemy::Page.find_by(language_root: true) ||
@@ -13,20 +13,20 @@ FactoryBot.define do
13
13
  end
14
14
 
15
15
  # This speeds up creating of pages dramatically.
16
- # Pass do_not_autogenerate: false to generate elements
17
- do_not_autogenerate true
16
+ # Pass autogenerate_elements: true to generate elements
17
+ autogenerate_elements { false }
18
18
 
19
19
  trait :root do
20
- name 'Root'
21
- language nil
22
- parent_id nil
23
- page_layout nil
20
+ name { 'Root' }
21
+ language { nil }
22
+ parent_id { nil }
23
+ page_layout { nil }
24
24
  end
25
25
 
26
26
  trait :language_root do
27
- name 'Startseite'
27
+ name { 'Startseite' }
28
28
  page_layout { language.page_layout }
29
- language_root true
29
+ language_root { true }
30
30
  public_on { Time.current }
31
31
  parent_id { Alchemy::Page.root.id }
32
32
  end
@@ -37,22 +37,23 @@ FactoryBot.define do
37
37
  end
38
38
 
39
39
  trait :system do
40
- name "Systempage"
40
+ name { "Systempage" }
41
41
  parent_id { Alchemy::Page.root.id }
42
- language_root false
43
- page_layout nil
44
- language nil
42
+ language_root { false }
43
+ page_layout { nil }
44
+ language { nil }
45
45
  end
46
46
 
47
47
  trait :layoutpage do
48
- name "Footer"
48
+ name { "Footer" }
49
49
  parent_id { Alchemy::Page.find_or_create_layout_root_for(Alchemy::Language.current.id).id }
50
- page_layout "footer"
50
+ layoutpage { true }
51
+ page_layout { "footer" }
51
52
  end
52
53
 
53
54
  trait :restricted do
54
- name "Restricted page"
55
- restricted true
55
+ name { "Restricted page" }
56
+ restricted { true }
56
57
  end
57
58
 
58
59
  trait :locked do
@@ -2,9 +2,11 @@ require 'factory_bot'
2
2
 
3
3
  FactoryBot.define do
4
4
  factory :alchemy_picture, class: 'Alchemy::Picture' do
5
- image_file File.new(Alchemy::Engine.root.join('lib', 'alchemy', 'test_support', 'fixtures', 'image.png'))
6
- name 'image'
7
- image_file_name 'image.png'
8
- upload_hash Time.current.hash
5
+ image_file do
6
+ File.new(Alchemy::Engine.root.join('lib', 'alchemy', 'test_support', 'fixtures', 'image.png'))
7
+ end
8
+ name { 'image' }
9
+ image_file_name { 'image.png' }
10
+ upload_hash { Time.current.hash }
9
11
  end
10
12
  end
@@ -2,17 +2,17 @@ require 'factory_bot'
2
2
 
3
3
  FactoryBot.define do
4
4
  factory :alchemy_site, class: 'Alchemy::Site' do
5
- name 'A Site'
6
- host 'domain.com'
5
+ name { 'A Site' }
6
+ host { 'domain.com' }
7
7
 
8
8
  trait :default do
9
- public true
10
- name Alchemy::Config.get(:default_site)['name']
11
- host Alchemy::Config.get(:default_site)['host']
9
+ public { true }
10
+ name { Alchemy::Config.get(:default_site)['name'] }
11
+ host { Alchemy::Config.get(:default_site)['host'] }
12
12
  end
13
13
 
14
14
  trait :public do
15
- public true
15
+ public { true }
16
16
  end
17
17
  end
18
18
  end
@@ -4,7 +4,7 @@ module Alchemy
4
4
  module Tinymce
5
5
  mattr_accessor :languages, :plugins
6
6
 
7
- @@plugins = %w(alchemy_link anchor autoresize charmap code directionality fullscreen hr link paste tabfocus table)
7
+ @@plugins = %w(alchemy_link anchor autoresize charmap code directionality fullscreen hr link lists paste tabfocus table)
8
8
  @@init = {
9
9
  skin: 'alchemy',
10
10
  width: 'auto',
@@ -0,0 +1,68 @@
1
+ require_relative 'tasks/picture_gallery_upgrader'
2
+ require_relative 'tasks/picture_gallery_migration'
3
+ require_relative 'tasks/cells_upgrader'
4
+ require_relative 'tasks/cells_migration'
5
+
6
+ module Alchemy
7
+ class Upgrader::FourPointTwo < Upgrader
8
+ class << self
9
+ def convert_picture_galleries
10
+ desc 'Convert `picture_gallery` element definitions to `nestable_elements`.'
11
+ Alchemy::Upgrader::Tasks::PictureGalleryUpgrader.new.convert_picture_galleries
12
+ end
13
+
14
+ def migrate_picture_galleries
15
+ desc 'Migrate existing gallery elements to `nestable_elements`.'
16
+ Alchemy::Upgrader::Tasks::PictureGalleryMigration.new.migrate_picture_galleries
17
+ end
18
+
19
+ def convert_cells
20
+ desc 'Convert cells config to fixed nestable elements.'
21
+ Alchemy::Upgrader::Tasks::CellsUpgrader.new.convert_cells
22
+ end
23
+
24
+ def migrate_cells
25
+ desc 'Migrate existing cells to fixed nestable elements.'
26
+ Alchemy::Upgrader::Tasks::CellsMigration.new.migrate_cells
27
+ end
28
+
29
+ def alchemy_4_2_todos
30
+ notice = <<-NOTE
31
+
32
+ Element's "picture_gallery" feature removed
33
+ ----------------------------------------------
34
+
35
+ The `picture_gallery` feature of elements was removed and has been replaced by nestable elements.
36
+
37
+ The automatic updater that just ran updated your `config/alchemy/elements.yml`. A backup was made.
38
+ Nevertheless, you should have a look into it and double check the changes.
39
+
40
+ We created nested elements for each gallery picture we found in your database.
41
+
42
+ We also updated your element view partials so they have hints about how to render the child elements.
43
+
44
+ Cells replaced by fixed nestable elements
45
+ -----------------------------------------
46
+
47
+ The Cells feature has been replaced by fixed nestable elements.
48
+
49
+ The automatic updater that just ran updated your `config/alchemy/elements.yml`.
50
+ Nevertheless, you should have a look into it and double check the changes.
51
+
52
+ We defined new fixed elements for each cell former defined in `cells.yml`
53
+ and put its `elements` into the `nestable_elements` collection of the new elements definition.
54
+
55
+ We also updated your element view partials so they render the child elements.
56
+
57
+ Please review and fix markup, if necessary.
58
+
59
+ PLEASE DOUBLE CHECK YOUR ELEMENT PARTIALS AND ADJUST ACCORDINGLY!
60
+
61
+ As always `git diff` is your friend.
62
+
63
+ NOTE
64
+ todo notice, 'Alchemy v4.2 changes'
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,41 @@
1
+ module Alchemy::Upgrader::Tasks
2
+ class CellsMigration
3
+ class Cell < ActiveRecord::Base
4
+ self.table_name = 'alchemy_cells'
5
+ belongs_to :page, class_name: 'Alchemy::Page'
6
+ end
7
+
8
+ def migrate_cells
9
+ if ActiveRecord::Base.connection.data_source_exists?('alchemy_cells')
10
+ cells = Cell.all
11
+
12
+ if cells.any?
13
+ cells.each do |cell|
14
+ migrate_cell!(cell)
15
+ end
16
+ else
17
+ puts "No cells found. Skip"
18
+ end
19
+ else
20
+ puts "Cells table does not exist. Skip"
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def migrate_cell!(cell)
27
+ # bust element definitions insta cache
28
+ Alchemy::Element.instance_variable_set('@definitions', nil)
29
+ fixed_element = Alchemy::Element.find_or_initialize_by(fixed: true, name: cell.name, page: cell.page)
30
+ elements = Alchemy::Element.where(cell_id: cell.id)
31
+
32
+ if fixed_element.new_record?
33
+ fixed_element.nested_elements = elements
34
+ fixed_element.save!
35
+ puts "Created new fixed element '#{fixed_element.name}' for cell '#{cell.name}'."
36
+ else
37
+ puts "Element for cell '#{cell.name}' already present. Skip"
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,146 @@
1
+ require 'alchemy/upgrader'
2
+ require 'rails/generators'
3
+
4
+ module Alchemy::Upgrader::Tasks
5
+ class CellsUpgrader < Thor
6
+ include Thor::Actions
7
+
8
+ no_tasks do
9
+ def convert_cells
10
+ if File.exist?(page_layouts_config_file)
11
+ backup_config
12
+ convert_page_layouts_config
13
+ else
14
+ puts "\nNo page layouts config found. Skipping."
15
+ end
16
+ if File.exist?(cells_config_file)
17
+ convert_cell_config
18
+ delete_cells_config
19
+ else
20
+ puts "\nNo cells config found. Skipping."
21
+ end
22
+ update_cell_views
23
+ update_render_cell_calls
24
+ move_cell_views
25
+ generate_editor_partials
26
+ puts 'Done ✔'
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def backup_config
33
+ print "-- Copy existing config file to `config/alchemy/page_layouts.yml.old` ... "
34
+
35
+ FileUtils.copy Rails.root.join('config', 'alchemy', 'page_layouts.yml'),
36
+ Rails.root.join('config', 'alchemy', 'page_layouts.yml.old')
37
+
38
+ puts "done ✔\n"
39
+ end
40
+
41
+ def write_config(config)
42
+ print '-- Writing new `config/alchemy/page_layouts.yml` ... '
43
+
44
+ File.open(Rails.root.join('config', 'alchemy', 'page_layouts.yml'), "w") do |f|
45
+ f.write config.to_yaml.sub("---\n", "").gsub("\n-", "\n\n-")
46
+ end
47
+
48
+ puts "done ✔\n"
49
+ end
50
+
51
+ def convert_page_layouts_config
52
+ print '-- Moving `cells` from page layouts definition into autogenerated `elements` ... '
53
+ page_layouts = YAML.load_file(page_layouts_config_file)
54
+ page_layouts.select { |p| p['cells'].present? }.map do |page_layout|
55
+ elements = page_layout['elements'] || []
56
+ autogenerate_elements = page_layout['autogenerate'] || []
57
+ cell_elements = page_layout.delete('cells')
58
+ page_layout['elements'] = (elements + cell_elements).uniq
59
+ page_layout['autogenerate'] = (autogenerate_elements + cell_elements).uniq
60
+ end
61
+ puts "done ✔\n"
62
+ write_config(page_layouts)
63
+ end
64
+
65
+ def page_layouts_config_file
66
+ Rails.root.join('config', 'alchemy', 'page_layouts.yml')
67
+ end
68
+
69
+ def cells_config_file
70
+ Rails.root.join('config', 'alchemy', 'cells.yml')
71
+ end
72
+
73
+ def convert_cell_config
74
+ puts '-- Converting cells into unique fixed nestable elements.'
75
+
76
+ YAML.load_file(cells_config_file).each do |cell|
77
+ append_to_file Rails.root.join('config', 'alchemy', 'elements.yml') do
78
+ <<-CELL.strip_heredoc
79
+
80
+ - name: #{cell['name']}
81
+ fixed: true
82
+ unique: true
83
+ nestable_elements: [#{cell['elements'].join(', ')}]
84
+ CELL
85
+ end
86
+ end
87
+ end
88
+
89
+ def delete_cells_config
90
+ puts '-- Deleting cells config file.'
91
+ FileUtils.rm(cells_config_file)
92
+ end
93
+
94
+ def move_cell_views
95
+ if Dir.exist? cells_view_folder
96
+ puts "-- Move cell views into elements view folder"
97
+ Dir.glob("#{cells_view_folder}/*").each do |view|
98
+ filename = File.basename(view).gsub(/(_\w+)\.(\w*\.)?(erb|haml|slim)/, '\1_view.\2\3')
99
+ FileUtils.mv(view, "#{elements_view_folder}/#{filename}")
100
+ puts " Moved #{File.basename(view)} into `app/views/alchemy/elements/` folder"
101
+ end
102
+ FileUtils.rm_rf(cells_view_folder)
103
+ else
104
+ puts "No cell views found. Skip"
105
+ end
106
+ end
107
+
108
+ def generate_editor_partials
109
+ puts "-- Generate editor partials"
110
+ Rails::Generators.invoke('alchemy:elements', ['--skip'])
111
+ end
112
+
113
+ def update_cell_views
114
+ if Dir.exist? cells_view_folder
115
+ puts "-- Update cell views"
116
+ Dir.glob("#{cells_view_folder}/*").each do |view|
117
+ gsub_file(view, /cell\.elements/, 'element.nested_elements.published')
118
+ gsub_file(view, /render_elements\(?from_cell:\scell\)?/, 'render element.nested_elements.published')
119
+ gsub_file(view, /cell/, 'element')
120
+ end
121
+ else
122
+ puts "No cell views found. Skip"
123
+ end
124
+ end
125
+
126
+ def update_render_cell_calls
127
+ puts "-- Update render_cell calls"
128
+ Dir.glob("#{alchemy_views_folder}/**/*").each do |view|
129
+ next if File.directory?(view)
130
+ gsub_file(view, /render_cell[\(\s]?([:'"]?[a-z_]+['"]?)\)?/, 'render_elements(only: \1, fixed: true)')
131
+ end
132
+ end
133
+
134
+ def elements_view_folder
135
+ Rails.root.join('app', 'views', 'alchemy', 'elements')
136
+ end
137
+
138
+ def cells_view_folder
139
+ Rails.root.join('app', 'views', 'alchemy', 'cells')
140
+ end
141
+
142
+ def alchemy_views_folder
143
+ Rails.root.join('app', 'views', 'alchemy')
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,65 @@
1
+ module Alchemy
2
+ class Upgrader::Tasks::PictureGalleryMigration
3
+ def migrate_picture_galleries
4
+ if picture_gallery_elements.present?
5
+ picture_gallery_elements.each do |el|
6
+ migrate_element(el)
7
+ end
8
+ else
9
+ puts "No `picture_gallery` elements found. Skip"
10
+ end
11
+ end
12
+
13
+ private
14
+
15
+ def picture_gallery_elements
16
+ Element.distinct.joins(:contents).where("#{Content.table_name}.name LIKE 'essence_picture_%'")
17
+ end
18
+
19
+ def migrate_element(element)
20
+ gallery_contents = element.contents.where("#{Content.table_name}.name LIKE 'essence_picture_%'").order("#{Content.table_name}.position ASC")
21
+
22
+ if gallery_contents.any?
23
+ if element.nestable_elements.any? { |el| el != "#{element.name}_picture" }
24
+ parent = create_gallery_element(element)
25
+ else
26
+ parent = element
27
+ end
28
+ gallery_contents.each do |content|
29
+ create_element_for_content(content, parent)
30
+ end
31
+ else
32
+ puts "No gallery contents found for #{element.dom_id}. Skip"
33
+ end
34
+ end
35
+
36
+ def create_gallery_element(parent)
37
+ new_element = parent.nested_elements.create!(
38
+ name: "#{parent.name}_picture_gallery",
39
+ public: parent.public,
40
+ folded: parent.folded,
41
+ creator: parent.creator,
42
+ updater: parent.updater,
43
+ page: parent.page,
44
+ autogenerate_contents: false
45
+ )
46
+ puts "Created new `#{new_element.name}` for `#{parent.name}`"
47
+ new_element
48
+ end
49
+
50
+ def create_element_for_content(content, parent)
51
+ new_element = parent.nested_elements.create!(
52
+ name: "#{parent.name}_picture",
53
+ public: parent.public,
54
+ folded: parent.folded,
55
+ creator: parent.creator,
56
+ updater: parent.updater,
57
+ page: parent.page,
58
+ autogenerate_contents: false
59
+ )
60
+
61
+ content.update_columns(element_id: new_element.id, name: 'picture')
62
+ puts "Created new `#{new_element.name}` for `#{parent.name}`"
63
+ end
64
+ end
65
+ end