alchemy_cms 6.1.10 → 7.0.0.pre.a

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 (249) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +0 -3
  3. data/.gitignore +1 -6
  4. data/CHANGELOG.md +19 -44
  5. data/Gemfile +1 -1
  6. data/Rakefile +14 -9
  7. data/alchemy_cms.gemspec +2 -3
  8. data/app/assets/javascripts/alchemy/alchemy.dirty.js.coffee +1 -1
  9. data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +18 -32
  10. data/app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee +2 -2
  11. data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +2 -2
  12. data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +27 -29
  13. data/app/assets/stylesheets/alchemy/elements.scss +16 -35
  14. data/app/assets/stylesheets/alchemy/forms.scss +0 -4
  15. data/app/assets/stylesheets/alchemy/node-select.scss +2 -2
  16. data/app/controllers/alchemy/admin/attachments_controller.rb +0 -1
  17. data/app/controllers/alchemy/admin/elements_controller.rb +7 -32
  18. data/app/controllers/alchemy/admin/pages_controller.rb +1 -1
  19. data/app/controllers/alchemy/admin/pictures_controller.rb +1 -1
  20. data/app/controllers/alchemy/admin/resources_controller.rb +1 -18
  21. data/app/controllers/alchemy/api/elements_controller.rb +0 -2
  22. data/app/controllers/alchemy/api/pages_controller.rb +8 -4
  23. data/app/controllers/alchemy/messages_controller.rb +9 -9
  24. data/app/controllers/alchemy/pages_controller.rb +23 -18
  25. data/app/decorators/alchemy/element_editor.rb +10 -30
  26. data/app/helpers/alchemy/admin/elements_helper.rb +0 -2
  27. data/app/helpers/alchemy/elements_block_helper.rb +5 -42
  28. data/app/helpers/alchemy/elements_helper.rb +3 -11
  29. data/app/helpers/alchemy/pages_helper.rb +0 -4
  30. data/app/models/alchemy/attachment.rb +6 -3
  31. data/app/models/alchemy/base_record.rb +2 -0
  32. data/app/models/alchemy/eager_loading.rb +0 -1
  33. data/app/models/alchemy/element/element_ingredients.rb +1 -8
  34. data/app/models/alchemy/element/presenters.rb +9 -25
  35. data/app/models/alchemy/element.rb +2 -18
  36. data/app/models/alchemy/ingredient.rb +17 -6
  37. data/app/models/alchemy/ingredients/audio.rb +2 -0
  38. data/app/models/alchemy/ingredients/datetime.rb +3 -1
  39. data/app/models/alchemy/ingredients/file.rb +7 -0
  40. data/app/models/alchemy/ingredients/headline.rb +6 -0
  41. data/app/models/alchemy/ingredients/link.rb +2 -0
  42. data/app/models/alchemy/ingredients/node.rb +2 -0
  43. data/app/models/alchemy/ingredients/page.rb +2 -0
  44. data/app/models/alchemy/ingredients/picture.rb +11 -0
  45. data/app/models/alchemy/ingredients/richtext.rb +6 -0
  46. data/app/models/alchemy/ingredients/select.rb +1 -0
  47. data/app/models/alchemy/ingredients/text.rb +8 -0
  48. data/app/models/alchemy/ingredients/video.rb +2 -0
  49. data/app/models/alchemy/node.rb +9 -6
  50. data/app/models/alchemy/page/page_elements.rb +5 -26
  51. data/app/models/alchemy/page/page_layouts.rb +0 -14
  52. data/app/models/alchemy/page/page_natures.rb +0 -10
  53. data/app/models/alchemy/page.rb +0 -10
  54. data/app/models/alchemy/picture/transformations.rb +0 -30
  55. data/app/models/alchemy/picture/url.rb +1 -1
  56. data/app/models/alchemy/picture.rb +14 -13
  57. data/app/models/alchemy/picture_thumb/create.rb +7 -18
  58. data/app/models/alchemy/picture_thumb/file_store.rb +33 -0
  59. data/app/models/alchemy/picture_thumb.rb +10 -10
  60. data/app/models/concerns/alchemy/picture_thumbnails.rb +2 -6
  61. data/app/serializers/alchemy/element_serializer.rb +1 -6
  62. data/app/services/alchemy/delete_elements.rb +1 -7
  63. data/app/services/alchemy/duplicate_element.rb +1 -6
  64. data/app/views/alchemy/admin/elements/_element.html.erb +5 -22
  65. data/app/views/alchemy/admin/elements/create.js.erb +1 -1
  66. data/app/views/alchemy/admin/elements/fold.js.erb +2 -2
  67. data/app/views/alchemy/admin/elements/order.js.erb +1 -1
  68. data/app/views/alchemy/admin/elements/update.js.erb +1 -2
  69. data/app/views/alchemy/admin/pages/_external_link.html.erb +2 -2
  70. data/app/views/alchemy/admin/pages/_file_link.html.erb +2 -2
  71. data/app/views/alchemy/admin/pages/_internal_link.html.erb +2 -2
  72. data/app/views/alchemy/admin/pages/_table.html.erb +0 -6
  73. data/app/views/alchemy/admin/pages/_tinymce_custom_config.html.erb +3 -6
  74. data/app/views/alchemy/admin/pages/edit.html.erb +1 -1
  75. data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +1 -3
  76. data/app/views/alchemy/admin/pictures/_infos.html.erb +4 -6
  77. data/app/views/alchemy/admin/resources/_per_page_select.html.erb +1 -1
  78. data/app/views/alchemy/ingredients/_boolean_editor.html.erb +1 -1
  79. data/app/views/alchemy/ingredients/_headline_editor.html.erb +1 -1
  80. data/app/views/alchemy/ingredients/_html_editor.html.erb +1 -1
  81. data/app/views/alchemy/ingredients/_node_editor.html.erb +1 -1
  82. data/app/views/alchemy/ingredients/_picture_editor.html.erb +4 -4
  83. data/app/views/alchemy/ingredients/_select_editor.html.erb +2 -2
  84. data/app/views/alchemy/ingredients/_text_editor.html.erb +1 -1
  85. data/app/views/alchemy/ingredients/shared/_link_tools.html.erb +3 -3
  86. data/app/views/alchemy/pages/_meta_data.html.erb +0 -1
  87. data/app/views/layouts/alchemy/admin.html.erb +5 -1
  88. data/config/alchemy/config.yml +6 -6
  89. data/config/brakeman.ignore +56 -57
  90. data/config/locales/alchemy.en.yml +99 -113
  91. data/config/routes.rb +1 -16
  92. data/db/migrate/20230121212637_alchemy_six_point_one.rb +248 -0
  93. data/lib/alchemy/cache_digests/template_tracker.rb +6 -7
  94. data/lib/alchemy/config.rb +2 -2
  95. data/lib/alchemy/deprecation.rb +1 -1
  96. data/lib/alchemy/errors.rb +0 -11
  97. data/lib/alchemy/hints.rb +10 -10
  98. data/lib/alchemy/permissions.rb +4 -17
  99. data/lib/alchemy/routing_constraints.rb +3 -3
  100. data/lib/alchemy/searchable_resource.rb +38 -0
  101. data/lib/alchemy/seeder.rb +2 -8
  102. data/lib/alchemy/tasks/tidy.rb +0 -38
  103. data/lib/alchemy/test_support/capybara_helpers.rb +69 -0
  104. data/lib/alchemy/test_support/factories/element_factory.rb +0 -6
  105. data/lib/alchemy/test_support/factories/ingredient_factory.rb +1 -1
  106. data/lib/alchemy/test_support/factories/page_factory.rb +4 -2
  107. data/lib/alchemy/test_support/having_picture_thumbnails_examples.rb +0 -20
  108. data/lib/alchemy/test_support/shared_dom_ids_examples.rb +1 -1
  109. data/lib/alchemy/test_support/shared_ingredient_examples.rb +1 -1
  110. data/lib/alchemy/tinymce.rb +1 -18
  111. data/lib/alchemy/upgrader/seven_point_zero.rb +45 -0
  112. data/lib/alchemy/upgrader/tasks/.keep +0 -0
  113. data/lib/alchemy/upgrader.rb +8 -3
  114. data/lib/alchemy/version.rb +1 -1
  115. data/lib/alchemy.rb +0 -19
  116. data/lib/alchemy_cms.rb +1 -2
  117. data/lib/generators/alchemy/elements/elements_generator.rb +0 -1
  118. data/lib/generators/alchemy/elements/templates/view.html.erb +1 -10
  119. data/lib/generators/alchemy/elements/templates/view.html.haml +1 -9
  120. data/lib/generators/alchemy/elements/templates/view.html.slim +1 -9
  121. data/lib/generators/alchemy/install/files/alchemy.en.yml +7 -8
  122. data/lib/generators/alchemy/install/files/application.html.erb +1 -1
  123. data/lib/generators/alchemy/install/install_generator.rb +18 -34
  124. data/lib/generators/alchemy/install/templates/elements.yml.tt +12 -12
  125. data/lib/non_stupid_digest_assets.rb +1 -1
  126. data/lib/tasks/alchemy/thumbnails.rake +2 -21
  127. data/lib/tasks/alchemy/tidy.rake +1 -12
  128. data/lib/tasks/alchemy/upgrade.rake +10 -47
  129. data/package/dist/admin.js +16 -0
  130. data/package/dist/admin.js.map +7 -0
  131. data/package.json +5 -3
  132. metadata +18 -147
  133. data/app/controllers/alchemy/admin/contents_controller.rb +0 -21
  134. data/app/controllers/alchemy/admin/essence_audios_controller.rb +0 -30
  135. data/app/controllers/alchemy/admin/essence_files_controller.rb +0 -31
  136. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +0 -43
  137. data/app/controllers/alchemy/admin/essence_videos_controller.rb +0 -34
  138. data/app/controllers/alchemy/api/contents_controller.rb +0 -52
  139. data/app/decorators/alchemy/content_editor.rb +0 -119
  140. data/app/helpers/alchemy/admin/contents_helper.rb +0 -42
  141. data/app/helpers/alchemy/admin/essences_helper.rb +0 -31
  142. data/app/models/alchemy/content/factory.rb +0 -143
  143. data/app/models/alchemy/content.rb +0 -247
  144. data/app/models/alchemy/element/element_contents.rb +0 -200
  145. data/app/models/alchemy/element/element_essences.rb +0 -133
  146. data/app/models/alchemy/essence_audio.rb +0 -13
  147. data/app/models/alchemy/essence_boolean.rb +0 -20
  148. data/app/models/alchemy/essence_date.rb +0 -25
  149. data/app/models/alchemy/essence_file.rb +0 -49
  150. data/app/models/alchemy/essence_headline.rb +0 -41
  151. data/app/models/alchemy/essence_html.rb +0 -23
  152. data/app/models/alchemy/essence_link.rb +0 -21
  153. data/app/models/alchemy/essence_node.rb +0 -19
  154. data/app/models/alchemy/essence_page.rb +0 -17
  155. data/app/models/alchemy/essence_picture.rb +0 -67
  156. data/app/models/alchemy/essence_picture_view.rb +0 -90
  157. data/app/models/alchemy/essence_richtext.rb +0 -44
  158. data/app/models/alchemy/essence_select.rb +0 -19
  159. data/app/models/alchemy/essence_text.rb +0 -23
  160. data/app/models/alchemy/essence_video.rb +0 -13
  161. data/app/serializers/alchemy/content_serializer.rb +0 -17
  162. data/app/serializers/alchemy/essence_boolean_serializer.rb +0 -10
  163. data/app/serializers/alchemy/essence_date_serializer.rb +0 -10
  164. data/app/serializers/alchemy/essence_file_serializer.rb +0 -13
  165. data/app/serializers/alchemy/essence_html_serializer.rb +0 -10
  166. data/app/serializers/alchemy/essence_link_serializer.rb +0 -13
  167. data/app/serializers/alchemy/essence_picture_serializer.rb +0 -28
  168. data/app/serializers/alchemy/essence_richtext_serializer.rb +0 -11
  169. data/app/serializers/alchemy/essence_select_serializer.rb +0 -10
  170. data/app/serializers/alchemy/essence_text_serializer.rb +0 -22
  171. data/app/views/alchemy/admin/contents/create.js.erb +0 -21
  172. data/app/views/alchemy/admin/essence_audios/edit.html.erb +0 -7
  173. data/app/views/alchemy/admin/essence_files/edit.html.erb +0 -21
  174. data/app/views/alchemy/admin/essence_pictures/destroy.js.erb +0 -5
  175. data/app/views/alchemy/admin/essence_pictures/edit.html.erb +0 -30
  176. data/app/views/alchemy/admin/essence_pictures/save_link.js.erb +0 -3
  177. data/app/views/alchemy/admin/essence_pictures/update.js.erb +0 -8
  178. data/app/views/alchemy/admin/essence_videos/edit.html.erb +0 -12
  179. data/app/views/alchemy/essences/_essence_audio_editor.html.erb +0 -4
  180. data/app/views/alchemy/essences/_essence_audio_view.html.erb +0 -15
  181. data/app/views/alchemy/essences/_essence_boolean_editor.html.erb +0 -11
  182. data/app/views/alchemy/essences/_essence_boolean_view.html.erb +0 -2
  183. data/app/views/alchemy/essences/_essence_date_editor.html.erb +0 -16
  184. data/app/views/alchemy/essences/_essence_date_view.html.erb +0 -10
  185. data/app/views/alchemy/essences/_essence_file_editor.html.erb +0 -54
  186. data/app/views/alchemy/essences/_essence_file_view.html.erb +0 -18
  187. data/app/views/alchemy/essences/_essence_headline_editor.html.erb +0 -36
  188. data/app/views/alchemy/essences/_essence_headline_view.html.erb +0 -10
  189. data/app/views/alchemy/essences/_essence_html_editor.html.erb +0 -10
  190. data/app/views/alchemy/essences/_essence_html_view.html.erb +0 -2
  191. data/app/views/alchemy/essences/_essence_link_editor.html.erb +0 -30
  192. data/app/views/alchemy/essences/_essence_link_view.html.erb +0 -10
  193. data/app/views/alchemy/essences/_essence_node_editor.html.erb +0 -27
  194. data/app/views/alchemy/essences/_essence_node_view.html.erb +0 -1
  195. data/app/views/alchemy/essences/_essence_page_editor.html.erb +0 -26
  196. data/app/views/alchemy/essences/_essence_page_view.html.erb +0 -5
  197. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +0 -59
  198. data/app/views/alchemy/essences/_essence_picture_view.html.erb +0 -6
  199. data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +0 -14
  200. data/app/views/alchemy/essences/_essence_richtext_view.html.erb +0 -4
  201. data/app/views/alchemy/essences/_essence_select_editor.html.erb +0 -28
  202. data/app/views/alchemy/essences/_essence_select_view.html.erb +0 -2
  203. data/app/views/alchemy/essences/_essence_text_editor.html.erb +0 -29
  204. data/app/views/alchemy/essences/_essence_text_view.html.erb +0 -17
  205. data/app/views/alchemy/essences/_essence_video_editor.html.erb +0 -4
  206. data/app/views/alchemy/essences/_essence_video_view.html.erb +0 -19
  207. data/app/views/alchemy/essences/shared/_essence_picture_tools.html.erb +0 -59
  208. data/app/views/alchemy/essences/shared/_linkable_essence_tools.html.erb +0 -20
  209. data/app/views/alchemy/pages/show.rss.builder +0 -21
  210. data/db/migrate/20200226213334_alchemy_four_point_four.rb +0 -313
  211. data/db/migrate/20200423073425_create_alchemy_essence_nodes.rb +0 -11
  212. data/db/migrate/20200504210159_remove_site_id_from_nodes.rb +0 -28
  213. data/db/migrate/20200505215518_add_language_id_foreign_key_to_alchemy_pages.rb +0 -8
  214. data/db/migrate/20200511113603_add_menu_type_to_alchemy_nodes.rb +0 -27
  215. data/db/migrate/20200514091507_make_page_layoutpage_null_false.rb +0 -6
  216. data/db/migrate/20200519073500_remove_visible_from_alchemy_pages.rb +0 -24
  217. data/db/migrate/20200617110713_create_alchemy_picture_thumbs.rb +0 -22
  218. data/db/migrate/20200907111332_remove_tri_state_booleans.rb +0 -33
  219. data/db/migrate/20201207131309_create_page_versions.rb +0 -19
  220. data/db/migrate/20201207135820_add_page_version_id_to_alchemy_elements.rb +0 -76
  221. data/db/migrate/20210205143548_rename_public_on_and_public_until_on_alchemy_pages.rb +0 -10
  222. data/db/migrate/20210326105046_add_sanitized_body_to_alchemy_essence_richtexts.rb +0 -7
  223. data/db/migrate/20210406093436_add_alchemy_essence_headlines.rb +0 -12
  224. data/db/migrate/20210506135919_create_essence_audios.rb +0 -19
  225. data/db/migrate/20210506140258_create_essence_videos.rb +0 -23
  226. data/db/migrate/20210508091432_create_alchemy_ingredients.rb +0 -22
  227. data/db/migrate/20220514072456_restrict_on_delete_page_id_foreign_key_from_alchemy_nodes.rb +0 -13
  228. data/db/migrate/20220622130905_add_playsinline_to_alchemy_essence_videos.rb +0 -9
  229. data/lib/alchemy/essence.rb +0 -250
  230. data/lib/alchemy/tasks/usage.rb +0 -34
  231. data/lib/alchemy/test_support/essence_shared_examples.rb +0 -271
  232. data/lib/alchemy/test_support/factories/content_factory.rb +0 -20
  233. data/lib/alchemy/test_support/factories/essence_audio_factory.rb +0 -7
  234. data/lib/alchemy/test_support/factories/essence_file_factory.rb +0 -7
  235. data/lib/alchemy/test_support/factories/essence_page_factory.rb +0 -7
  236. data/lib/alchemy/test_support/factories/essence_picture_factory.rb +0 -11
  237. data/lib/alchemy/test_support/factories/essence_text_factory.rb +0 -7
  238. data/lib/alchemy/test_support/factories/essence_video_factory.rb +0 -7
  239. data/lib/alchemy/upgrader/five_point_zero.rb +0 -41
  240. data/lib/alchemy/upgrader/six_point_zero.rb +0 -21
  241. data/lib/alchemy/upgrader/tasks/add_page_versions.rb +0 -33
  242. data/lib/alchemy/upgrader/tasks/element_views_updater.rb +0 -34
  243. data/lib/alchemy/upgrader/tasks/harden_gutentag_migrations.rb +0 -29
  244. data/lib/alchemy/upgrader/tasks/ingredients_migrator.rb +0 -73
  245. data/lib/generators/alchemy/essence/essence_generator.rb +0 -49
  246. data/lib/generators/alchemy/essence/templates/editor.html.erb +0 -17
  247. data/lib/generators/alchemy/essence/templates/view.html.erb +0 -2
  248. data/lib/generators/alchemy/install/files/babel.config.js +0 -64
  249. data/lib/tasks/alchemy/usage.rake +0 -44
@@ -0,0 +1,248 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AlchemySixPointOne < ActiveRecord::Migration[ActiveRecord::Migration.current_version]
4
+ def up
5
+ unless table_exists?("alchemy_attachments")
6
+ create_table "alchemy_attachments" do |t|
7
+ t.string "name"
8
+ t.string "file_name"
9
+ t.string "file_mime_type"
10
+ t.integer "file_size"
11
+ t.integer "creator_id"
12
+ t.integer "updater_id"
13
+ t.datetime "created_at", null: false
14
+ t.datetime "updated_at", null: false
15
+ t.string "file_uid"
16
+ t.index ["creator_id"], name: "index_alchemy_attachments_on_creator_id"
17
+ t.index ["file_uid"], name: "index_alchemy_attachments_on_file_uid"
18
+ t.index ["updater_id"], name: "index_alchemy_attachments_on_updater_id"
19
+ end
20
+ end
21
+
22
+ unless table_exists?("alchemy_elements_alchemy_pages")
23
+ create_table "alchemy_elements_alchemy_pages", id: false do |t|
24
+ t.integer "element_id"
25
+ t.integer "page_id"
26
+ t.index ["element_id"], name: "index_alchemy_elements_alchemy_pages_on_element_id"
27
+ t.index ["page_id"], name: "index_alchemy_elements_alchemy_pages_on_page_id"
28
+ end
29
+ end
30
+
31
+ unless table_exists?("alchemy_folded_pages")
32
+ create_table "alchemy_folded_pages" do |t|
33
+ t.integer "page_id", null: false
34
+ t.integer "user_id", null: false
35
+ t.boolean "folded", default: false, null: false
36
+ t.index ["page_id", "user_id"], name: "index_alchemy_folded_pages_on_page_id_and_user_id", unique: true
37
+ end
38
+ end
39
+
40
+ unless table_exists?("alchemy_sites")
41
+ create_table "alchemy_sites" do |t|
42
+ t.string "host"
43
+ t.string "name"
44
+ t.datetime "created_at", null: false
45
+ t.datetime "updated_at", null: false
46
+ t.boolean "public", default: false, null: false
47
+ t.text "aliases"
48
+ t.boolean "redirect_to_primary_host", default: false, null: false
49
+ t.index ["host", "public"], name: "alchemy_sites_public_hosts_idx"
50
+ t.index ["host"], name: "index_alchemy_sites_on_host"
51
+ end
52
+ end
53
+
54
+ unless table_exists?("alchemy_languages")
55
+ create_table "alchemy_languages" do |t|
56
+ t.string "name"
57
+ t.string "language_code"
58
+ t.string "frontpage_name"
59
+ t.string "page_layout", default: "intro"
60
+ t.boolean "public", default: false, null: false
61
+ t.datetime "created_at", null: false
62
+ t.datetime "updated_at", null: false
63
+ t.integer "creator_id"
64
+ t.integer "updater_id"
65
+ t.boolean "default", default: false, null: false
66
+ t.string "country_code", default: "", null: false
67
+ t.references "site", null: false, foreign_key: { to_table: :alchemy_sites }
68
+ t.string "locale"
69
+ t.index ["creator_id"], name: "index_alchemy_languages_on_creator_id"
70
+ t.index ["language_code", "country_code"], name: "index_alchemy_languages_on_language_code_and_country_code"
71
+ t.index ["language_code"], name: "index_alchemy_languages_on_language_code"
72
+ t.index ["updater_id"], name: "index_alchemy_languages_on_updater_id"
73
+ end
74
+ end
75
+
76
+ unless table_exists?("alchemy_legacy_page_urls")
77
+ create_table "alchemy_legacy_page_urls" do |t|
78
+ t.string "urlname", null: false
79
+ t.integer "page_id", null: false
80
+ t.datetime "created_at", null: false
81
+ t.datetime "updated_at", null: false
82
+ t.index ["page_id"], name: "index_alchemy_legacy_page_urls_on_page_id"
83
+ t.index ["urlname"], name: "index_alchemy_legacy_page_urls_on_urlname"
84
+ end
85
+ end
86
+
87
+ unless table_exists?("alchemy_pages")
88
+ create_table "alchemy_pages" do |t|
89
+ t.string "name"
90
+ t.string "urlname"
91
+ t.string "title"
92
+ t.string "language_code"
93
+ t.boolean "language_root", default: false, null: false
94
+ t.string "page_layout"
95
+ t.text "meta_keywords"
96
+ t.text "meta_description"
97
+ t.integer "lft"
98
+ t.integer "rgt"
99
+ t.integer "parent_id"
100
+ t.integer "depth"
101
+ t.integer "locked_by"
102
+ t.boolean "restricted", default: false, null: false
103
+ t.boolean "robot_index", default: true, null: false
104
+ t.boolean "robot_follow", default: true, null: false
105
+ t.boolean "sitemap", default: true, null: false
106
+ t.boolean "layoutpage", default: false, null: false
107
+ t.datetime "created_at", null: false
108
+ t.datetime "updated_at", null: false
109
+ t.integer "creator_id"
110
+ t.integer "updater_id"
111
+ t.references "language", null: false, foreign_key: { to_table: :alchemy_languages }
112
+ t.datetime "published_at", precision: nil
113
+ t.datetime "locked_at", precision: nil
114
+ t.index ["creator_id"], name: "index_alchemy_pages_on_creator_id"
115
+ t.index ["locked_at", "locked_by"], name: "index_alchemy_pages_on_locked_at_and_locked_by"
116
+ t.index ["parent_id", "lft"], name: "index_pages_on_parent_id_and_lft"
117
+ t.index ["rgt"], name: "index_alchemy_pages_on_rgt"
118
+ t.index ["updater_id"], name: "index_alchemy_pages_on_updater_id"
119
+ t.index ["urlname"], name: "index_pages_on_urlname"
120
+ end
121
+ end
122
+
123
+ unless table_exists?("alchemy_page_versions")
124
+ create_table "alchemy_page_versions" do |t|
125
+ t.references "page", null: false, foreign_key: { to_table: :alchemy_pages, on_delete: :cascade }
126
+ t.datetime "public_on", precision: nil
127
+ t.datetime "public_until", precision: nil
128
+ t.datetime "created_at", null: false
129
+ t.datetime "updated_at", null: false
130
+ t.index ["public_on", "public_until"], name: "index_alchemy_page_versions_on_public_on_and_public_until"
131
+ end
132
+ end
133
+
134
+ unless table_exists?("alchemy_elements")
135
+ create_table "alchemy_elements" do |t|
136
+ t.string "name"
137
+ t.integer "position"
138
+ t.boolean "public", default: true, null: false
139
+ t.boolean "folded", default: false, null: false
140
+ t.boolean "unique", default: false, null: false
141
+ t.datetime "created_at", null: false
142
+ t.datetime "updated_at", null: false
143
+ t.integer "creator_id"
144
+ t.integer "updater_id"
145
+ t.integer "parent_element_id"
146
+ t.boolean "fixed", default: false, null: false
147
+ t.references "page_version", null: false, foreign_key: { to_table: :alchemy_page_versions, on_delete: :cascade }
148
+ t.index ["creator_id"], name: "index_alchemy_elements_on_creator_id"
149
+ t.index ["fixed"], name: "index_alchemy_elements_on_fixed"
150
+ t.index ["page_version_id", "parent_element_id"], name: "idx_alchemy_elements_on_page_version_id_and_parent_element_id"
151
+ t.index ["page_version_id", "position"], name: "idx_alchemy_elements_on_page_version_id_and_position"
152
+ t.index ["updater_id"], name: "index_alchemy_elements_on_updater_id"
153
+ end
154
+ end
155
+
156
+ unless table_exists?("alchemy_ingredients")
157
+ create_table "alchemy_ingredients" do |t|
158
+ t.references "element", null: false, foreign_key: { to_table: :alchemy_elements, on_delete: :cascade }
159
+ t.string "type", null: false
160
+ t.string "role", null: false
161
+ t.text "value"
162
+ if ActiveRecord::Migration.connection.adapter_name.match?(/postgres/i)
163
+ t.jsonb :data, default: {}
164
+ else
165
+ t.json :data
166
+ end
167
+ t.string "related_object_type"
168
+ t.integer "related_object_id"
169
+ t.datetime "created_at", null: false
170
+ t.datetime "updated_at", null: false
171
+ t.index ["element_id", "role"], name: "index_alchemy_ingredients_on_element_id_and_role", unique: true
172
+ t.index ["related_object_id", "related_object_type"], name: "idx_alchemy_ingredient_relation"
173
+ t.index ["type"], name: "index_alchemy_ingredients_on_type"
174
+ end
175
+ end
176
+
177
+ unless table_exists?("alchemy_nodes")
178
+ create_table "alchemy_nodes" do |t|
179
+ t.string "name"
180
+ t.string "title"
181
+ t.string "url"
182
+ t.boolean "nofollow", default: false, null: false
183
+ t.boolean "external", default: false, null: false
184
+ t.boolean "folded", default: false, null: false
185
+ t.integer "parent_id"
186
+ t.integer "lft", null: false
187
+ t.integer "rgt", null: false
188
+ t.integer "depth", default: 0, null: false
189
+ t.references "page", foreign_key: { to_table: :alchemy_pages, on_delete: :restrict }
190
+ t.references "language", null: false, foreign_key: { to_table: :alchemy_languages }
191
+ t.integer "creator_id"
192
+ t.integer "updater_id"
193
+ t.datetime "created_at", null: false
194
+ t.datetime "updated_at", null: false
195
+ t.string "menu_type", null: false
196
+ t.index ["creator_id"], name: "index_alchemy_nodes_on_creator_id"
197
+ t.index ["lft"], name: "index_alchemy_nodes_on_lft"
198
+ t.index ["parent_id"], name: "index_alchemy_nodes_on_parent_id"
199
+ t.index ["rgt"], name: "index_alchemy_nodes_on_rgt"
200
+ t.index ["updater_id"], name: "index_alchemy_nodes_on_updater_id"
201
+ end
202
+ end
203
+
204
+ unless table_exists?("alchemy_pictures")
205
+ create_table "alchemy_pictures" do |t|
206
+ t.string "name"
207
+ t.string "image_file_name"
208
+ t.integer "image_file_width"
209
+ t.integer "image_file_height"
210
+ t.datetime "created_at", null: false
211
+ t.datetime "updated_at", null: false
212
+ t.integer "creator_id"
213
+ t.integer "updater_id"
214
+ t.string "upload_hash"
215
+ t.string "image_file_uid"
216
+ t.integer "image_file_size"
217
+ t.string "image_file_format"
218
+ t.index ["creator_id"], name: "index_alchemy_pictures_on_creator_id"
219
+ t.index ["updater_id"], name: "index_alchemy_pictures_on_updater_id"
220
+ end
221
+ end
222
+
223
+ unless table_exists?("alchemy_picture_thumbs")
224
+ create_table "alchemy_picture_thumbs" do |t|
225
+ t.references "picture", null: false, foreign_key: { to_table: :alchemy_pictures }
226
+ t.string "signature", null: false
227
+ t.text "uid", null: false
228
+ t.index ["signature"], name: "index_alchemy_picture_thumbs_on_signature", unique: true
229
+ end
230
+ end
231
+ end
232
+
233
+ def down
234
+ drop_table "alchemy_attachments" if table_exists?("alchemy_attachments")
235
+ drop_table "alchemy_elements" if table_exists?("alchemy_elements")
236
+ drop_table "alchemy_elements_alchemy_pages" if table_exists?("alchemy_elements_alchemy_pages")
237
+ drop_table "alchemy_folded_pages" if table_exists?("alchemy_folded_pages")
238
+ drop_table "alchemy_ingredients" if table_exists?("alchemy_ingredients")
239
+ drop_table "alchemy_languages" if table_exists?("alchemy_languages")
240
+ drop_table "alchemy_legacy_page_urls" if table_exists?("alchemy_legacy_page_urls")
241
+ drop_table "alchemy_nodes" if table_exists?("alchemy_nodes")
242
+ drop_table "alchemy_page_versions" if table_exists?("alchemy_page_versions")
243
+ drop_table "alchemy_pages" if table_exists?("alchemy_pages")
244
+ drop_table "alchemy_picture_thumbs" if table_exists?("alchemy_picture_thumbs")
245
+ drop_table "alchemy_pictures" if table_exists?("alchemy_pictures")
246
+ drop_table "alchemy_sites" if table_exists?("alchemy_sites")
247
+ end
248
+ end
@@ -18,11 +18,10 @@ module Alchemy
18
18
  when /^alchemy\/page_layouts\/_(\w+)/
19
19
  page_layout = PageLayout.get($1)
20
20
  layout_elements = page_layout.fetch("elements", [])
21
- layout_elements.map { |name| "alchemy/elements/_#{name}_view" } +
22
- layout_elements.map { |name| "alchemy/elements/_#{name}" }
23
- when /^alchemy\/elements\/_(\w+)_view/, /^alchemy\/elements\/_(\w+)/
24
- essence_types($1).map { |name|
25
- "alchemy/essences/_#{name.underscore}_view"
21
+ layout_elements.map { |name| "alchemy/elements/_#{name}" }
22
+ when /^alchemy\/elements\/_(\w+)/
23
+ ingredient_types($1).map { |type|
24
+ "alchemy/ingredients/_#{type.underscore}_view"
26
25
  }.uniq
27
26
  else
28
27
  ActionView::DependencyTracker::ERBTracker.call(@name, @template)
@@ -31,11 +30,11 @@ module Alchemy
31
30
 
32
31
  private
33
32
 
34
- def essence_types(name)
33
+ def ingredient_types(name)
35
34
  element = Element.definitions.detect { |e| e["name"] == name }
36
35
  return [] unless element
37
36
 
38
- element.fetch("contents", []).collect { |c| c["type"] }
37
+ element.fetch("ingredients", []).collect { |c| c["type"] }
39
38
  end
40
39
  end
41
40
  end
@@ -78,11 +78,11 @@ module Alchemy
78
78
  if deprecated_configs.key?(name.to_sym)
79
79
  config = deprecated_configs[name.to_sym]
80
80
  if config.nil?
81
- Alchemy::Deprecation.warn("#{name} configuration is deprecated and will be removed from Alchemy 5.1")
81
+ Alchemy::Deprecation.warn("#{name} configuration is deprecated and will be removed from Alchemy #{Alchemy::Deprecation.deprecation_horizon}")
82
82
  else
83
83
  value = show[name.to_s]
84
84
  if value != config
85
- Alchemy::Deprecation.warn("Setting #{name} configuration to #{value} is deprecated and will be always #{config} in Alchemy 5.1")
85
+ Alchemy::Deprecation.warn("Setting #{name} configuration to #{value} is deprecated and will be always #{config} in Alchemy #{Alchemy::Deprecation.deprecation_horizon}")
86
86
  end
87
87
  end
88
88
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Alchemy
3
- Deprecation = ActiveSupport::Deprecation.new("7.0", "Alchemy")
3
+ Deprecation = ActiveSupport::Deprecation.new("8.0", "Alchemy")
4
4
  end
@@ -3,10 +3,6 @@
3
3
  # Custom error classes.
4
4
  #
5
5
  module Alchemy
6
- class ContentDefinitionError < StandardError
7
- # Raised if no content definition can be found.
8
- end
9
-
10
6
  class DefaultLanguageNotFoundError < StandardError
11
7
  # Raised if no default language configuration can be found.
12
8
  def message
@@ -34,13 +30,6 @@ module Alchemy
34
30
  end
35
31
  end
36
32
 
37
- class EssenceMissingError < StandardError
38
- # Raised if a content misses its essence.
39
- def message
40
- "Essence not found"
41
- end
42
- end
43
-
44
33
  # Raised if calling +image_file+ on a Picture object returns nil.
45
34
  class MissingImageFileError < StandardError; end
46
35
 
data/lib/alchemy/hints.rb CHANGED
@@ -4,7 +4,7 @@ module Alchemy
4
4
  module Hints
5
5
  # Returns a hint
6
6
  #
7
- # To add a hint to a content pass +hint: true+ to the element definition in its element.yml
7
+ # To add a hint to a ingredient pass +hint: true+ to the element definition in its element.yml
8
8
  #
9
9
  # Then the hint itself is placed in the locale yml files.
10
10
  #
@@ -14,23 +14,23 @@ module Alchemy
14
14
  #
15
15
  # # elements.yml
16
16
  # - name: headline
17
- # contents:
18
- # - name: headline
19
- # type: EssenceText
20
- # hint: true
17
+ # ingredients:
18
+ # - role: headline
19
+ # type: Text
20
+ # hint: true
21
21
  #
22
22
  # # config/locales/de.yml
23
23
  # de:
24
- # content_hints:
24
+ # ingredient_hints:
25
25
  # headline: Lorem ipsum
26
26
  #
27
27
  # == Hint Key Example:
28
28
  #
29
29
  # - name: headline
30
- # contents:
31
- # - name: headline
32
- # type: EssenceText
33
- # hint: Lorem ipsum
30
+ # ingredients:
31
+ # - role: headline
32
+ # type: Text
33
+ # hint: Lorem ipsum
34
34
  #
35
35
  # @return String
36
36
  #
@@ -37,16 +37,12 @@ module Alchemy
37
37
  def alchemy_guest_user_rules
38
38
  can([:show, :download], Alchemy::Attachment) { |a| !a.restricted? }
39
39
 
40
- can :read, Alchemy::Content, Alchemy::Content.available.not_restricted do |c|
41
- c.public? && !c.restricted?
42
- end
43
-
44
40
  can :read, Alchemy::Element, Alchemy::Element.published.not_restricted do |e|
45
41
  e.public? && !e.restricted?
46
42
  end
47
43
 
48
- can :read, Alchemy::Page, Alchemy::Page.published.not_restricted.from_current_site do |p|
49
- p.public? && !p.restricted? && p.site == Alchemy::Site.current
44
+ can :read, Alchemy::Page, Alchemy::Page.published.not_restricted do |p|
45
+ p.public? && !p.restricted?
50
46
  end
51
47
  end
52
48
  end
@@ -64,16 +60,12 @@ module Alchemy
64
60
  # Resources
65
61
  can [:show, :download], Alchemy::Attachment
66
62
 
67
- can :read, Alchemy::Content, Alchemy::Content.available do |c|
68
- c.public?
69
- end
70
-
71
63
  can :read, Alchemy::Element, Alchemy::Element.published do |e|
72
64
  e.public?
73
65
  end
74
66
 
75
- can :read, Alchemy::Page, Alchemy::Page.published.from_current_site do |p|
76
- p.public? && p.site == Alchemy::Site.current
67
+ can :read, Alchemy::Page, Alchemy::Page.published do |p|
68
+ p.public?
77
69
  end
78
70
  end
79
71
  end
@@ -109,12 +101,7 @@ module Alchemy
109
101
 
110
102
  # Resources
111
103
  can [:read, :download], Alchemy::Attachment
112
- can :manage, Alchemy::Content
113
104
  can :manage, Alchemy::Element
114
- can :manage, Alchemy::EssenceAudio
115
- can :manage, Alchemy::EssenceFile
116
- can :manage, Alchemy::EssencePicture
117
- can :manage, Alchemy::EssenceVideo
118
105
  can :manage, Alchemy::Ingredient
119
106
  can [:crop], Alchemy::Ingredients::Picture
120
107
  can :manage, Alchemy::LegacyPageUrl
@@ -6,7 +6,7 @@ module Alchemy
6
6
  # Alchemy has a very strong catch all route.
7
7
  # But we don't want to handle all requests.
8
8
  #
9
- # For instance we only want to handle html and rss requests and
9
+ # For instance we only want to handle html requests and
10
10
  # don't want to swallow the rails/info routes in development mode.
11
11
  #
12
12
  class RoutingConstraints
@@ -21,13 +21,13 @@ module Alchemy
21
21
 
22
22
  private
23
23
 
24
- # We only want html and rss requests to be handled by us.
24
+ # We only want html requests to be handled by us.
25
25
  #
26
26
  # If an unknown format is requested we want to handle this,
27
27
  # because it could be a legacy route that needs to be redirected.
28
28
  #
29
29
  def handable_format?
30
- @request.format.symbol.nil? || (@request.format.symbol == :html) || (@request.format.symbol == :rss)
30
+ @request.format.symbol.nil? || (@request.format.symbol == :html)
31
31
  end
32
32
 
33
33
  # We don't want to handle the Rails info routes.
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Alchemy
4
+ # Defines the methods that are needed to
5
+ # make a model searchable in Alchemy's admin search by Ransack.
6
+ module SearchableResource
7
+ SEARCHABLE_COLUMN_TYPES = %i[string text]
8
+
9
+ # Allow all string and text attributes to be searchable by Ransack.
10
+ def ransackable_attributes(_auth_object = nil)
11
+ searchable_alchemy_resource_attributes
12
+ end
13
+
14
+ # Allow all attributes to be sortable by Ransack.
15
+ def ransortable_attributes(_auth_object = nil)
16
+ columns.map(&:name)
17
+ end
18
+
19
+ # Allow all associations defined in +alchemy_resource_relations+ to be searchable by Ransack.
20
+ def ransackable_associations(_auth_object = nil)
21
+ searchable_alchemy_resource_associations
22
+ end
23
+
24
+ protected
25
+
26
+ def searchable_alchemy_resource_attributes
27
+ columns.select { |c| c.type.in?(SEARCHABLE_COLUMN_TYPES) }.map(&:name)
28
+ end
29
+
30
+ def searchable_alchemy_resource_associations
31
+ if respond_to?(:alchemy_resource_relations)
32
+ alchemy_resource_relations.keys.map!(&:to_s)
33
+ else
34
+ []
35
+ end
36
+ end
37
+ end
38
+ end
@@ -82,11 +82,7 @@ module Alchemy
82
82
  end
83
83
 
84
84
  def page_yml
85
- @_page_yml ||= YAML.safe_load(
86
- page_seeds_file.read,
87
- permitted_classes: [Date],
88
- aliases: true
89
- )
85
+ @_page_yml ||= YAML.load_file(page_seeds_file)
90
86
  end
91
87
 
92
88
  def contentpages
@@ -103,9 +99,7 @@ module Alchemy
103
99
 
104
100
  def create_page(draft, attributes = {})
105
101
  children = draft.delete("children") || []
106
- page = Alchemy::Page.new(draft.merge(attributes))
107
- page.versions.build
108
- page.save!
102
+ page = Alchemy::Page.create!(draft.merge(attributes))
109
103
  log "Created page: #{page.name}"
110
104
  children.each do |child|
111
105
  create_page(child, parent: page, language: page.language)
@@ -25,25 +25,6 @@ module Alchemy
25
25
  end
26
26
  end
27
27
 
28
- def update_content_positions
29
- Alchemy::Element.all.each do |element|
30
- if element.contents.any?
31
- puts "\n## Updating content positions of element `#{element.name}`"
32
- end
33
- element.contents.group_by(&:element_id).each do |_, contents|
34
- contents.each_with_index do |content, idx|
35
- position = idx + 1
36
- if content.position != position
37
- log "Updating position for content ##{content.id} to #{position}"
38
- content.update_column(:position, position)
39
- else
40
- log "Position for content ##{content.id} is already correct (#{position})", :skip
41
- end
42
- end
43
- end
44
- end
45
- end
46
-
47
28
  def remove_orphaned_elements
48
29
  puts "\n## Removing orphaned elements"
49
30
  elements = Alchemy::Element.unscoped.not_nested
@@ -79,25 +60,6 @@ module Alchemy
79
60
  end
80
61
  end
81
62
 
82
- def remove_orphaned_contents
83
- puts "\n## Removing orphaned contents"
84
- contents = Alchemy::Content.unscoped.all
85
- if contents.any?
86
- orphaned_contents = contents.select do |content|
87
- content.essence.nil? && content.essence_id.present? ||
88
- content.element.nil? && content.element_id.present?
89
- end
90
- if orphaned_contents.any?
91
- log "Found #{orphaned_contents.size} orphaned contents"
92
- destroy_orphaned_records(orphaned_contents, "content")
93
- else
94
- log "No orphaned contents found", :skip
95
- end
96
- else
97
- log "No contents found", :skip
98
- end
99
- end
100
-
101
63
  def remove_duplicate_legacy_urls
102
64
  puts "\n## Removing duplicate legacy URLs"
103
65
  sql = <<~SQL
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Alchemy
4
+ module TestSupport
5
+ module CapybaraHelpers
6
+ # Select2 capybara helper
7
+ def select2(value, options)
8
+ label = find_label_by_text(options[:from])
9
+
10
+ select2_anchor_selector = ".select2-container a"
11
+
12
+ if label.has_css?(select2_anchor_selector)
13
+ label.find(select2_anchor_selector).click
14
+ else
15
+ within label.find(:xpath, "..") do
16
+ find(select2_anchor_selector).click
17
+ end
18
+ end
19
+
20
+ within_entire_page do
21
+ page.find(
22
+ "div.select2-result-label",
23
+ text: /#{Regexp.escape(value)}/i, match: :prefer_exact,
24
+ ).click
25
+ end
26
+ end
27
+
28
+ def select2_search(value, options)
29
+ if options[:from]
30
+ label = find_label_by_text(options[:from])
31
+ within label.first(:xpath, ".//..") do
32
+ options[:from] = "##{find(".select2-container")["id"]}"
33
+ end
34
+ elsif options[:element_id] && options[:ingredient_role]
35
+ container_id = find("#element_#{options[:element_id]} [data-ingredient-role='#{options[:ingredient_role]}'] .select2-container")["id"]
36
+ options[:from] = "##{container_id}"
37
+ end
38
+
39
+ find("#{options[:from]}:not(.select2-container-disabled):not(.select2-offscreen)").click
40
+
41
+ within_entire_page do
42
+ find("input.select2-input.select2-focused").set(value)
43
+ expect(page).to have_selector(".select2-result-label", visible: true)
44
+ find("div.select2-result-label", text: /#{Regexp.escape(value)}/i, match: :prefer_exact).click
45
+ expect(page).not_to have_selector(".select2-result-label")
46
+ end
47
+ end
48
+
49
+ def click_button_with_label(label)
50
+ label = find("label", text: label)
51
+ within label.first(:xpath, ".//..") do
52
+ first("button").click
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def within_entire_page(&block)
59
+ within(:xpath, "//body", &block)
60
+ end
61
+
62
+ def find_label_by_text(text)
63
+ find "label:not(.select2-offscreen)",
64
+ text: /#{Regexp.escape(text)}/i,
65
+ match: :one
66
+ end
67
+ end
68
+ end
69
+ end
@@ -3,7 +3,6 @@
3
3
  FactoryBot.define do
4
4
  factory :alchemy_element, class: "Alchemy::Element" do
5
5
  name { "article" }
6
- autogenerate_contents { false }
7
6
  autogenerate_ingredients { false }
8
7
  association :page_version, factory: :alchemy_page_version
9
8
 
@@ -26,12 +25,7 @@ FactoryBot.define do
26
25
  name { "slide" }
27
26
  end
28
27
 
29
- trait :with_contents do
30
- autogenerate_contents { true }
31
- end
32
-
33
28
  trait :with_ingredients do
34
- name { "element_with_ingredients" }
35
29
  autogenerate_ingredients { true }
36
30
  end
37
31
  end
@@ -19,7 +19,7 @@ FactoryBot.define do
19
19
  factory :"alchemy_ingredient_#{ingredient}", class: "Alchemy::Ingredients::#{ingredient.classify}" do
20
20
  role { ingredient }
21
21
  type { "Alchemy::Ingredients::#{ingredient.classify}" }
22
- association :element, name: "all_you_can_eat_ingredients", factory: :alchemy_element
22
+ association :element, name: "all_you_can_eat", factory: :alchemy_element
23
23
  end
24
24
  end
25
25
  end