alchemy_cms 4.6.2 → 5.0.0.beta1

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 (378) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +33 -1
  3. data/.github/workflows/stale.yml +1 -1
  4. data/.gitignore +20 -2
  5. data/.hound.yml +2 -1
  6. data/.prettierrc +6 -0
  7. data/.rubocop.yml +31 -10
  8. data/CHANGELOG.md +89 -3
  9. data/Gemfile +24 -22
  10. data/README.md +31 -19
  11. data/Rakefile +10 -8
  12. data/alchemy_cms.gemspec +5 -4
  13. data/app/assets/javascripts/alchemy/admin.js +1 -5
  14. data/app/assets/javascripts/alchemy/alchemy.base.js.coffee +2 -1
  15. data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +0 -2
  16. data/app/assets/javascripts/alchemy/alchemy.page_sorter.js +17 -17
  17. data/app/assets/javascripts/alchemy/node_select.js +39 -0
  18. data/app/assets/javascripts/alchemy/templates/index.js +1 -0
  19. data/app/assets/javascripts/alchemy/templates/node.hbs +16 -0
  20. data/app/assets/stylesheets/alchemy/admin.scss +3 -2
  21. data/app/assets/stylesheets/alchemy/base.scss +0 -1
  22. data/app/assets/stylesheets/alchemy/elements.scss +1 -1
  23. data/app/assets/stylesheets/alchemy/forms.scss +5 -0
  24. data/app/assets/stylesheets/alchemy/node-select.scss +43 -0
  25. data/app/assets/stylesheets/alchemy/nodes.scss +1 -1
  26. data/app/assets/stylesheets/alchemy/sitemap.scss +5 -1
  27. data/app/assets/stylesheets/alchemy/tables.scss +1 -24
  28. data/app/controllers/alchemy/admin/attachments_controller.rb +8 -7
  29. data/app/controllers/alchemy/admin/base_controller.rb +13 -33
  30. data/app/controllers/alchemy/admin/clipboard_controller.rb +5 -4
  31. data/app/controllers/alchemy/admin/contents_controller.rb +1 -2
  32. data/app/controllers/alchemy/admin/dashboard_controller.rb +10 -9
  33. data/app/controllers/alchemy/admin/elements_controller.rb +20 -20
  34. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +12 -14
  35. data/app/controllers/alchemy/admin/languages_controller.rb +35 -2
  36. data/app/controllers/alchemy/admin/layoutpages_controller.rb +5 -2
  37. data/app/controllers/alchemy/admin/nodes_controller.rb +5 -4
  38. data/app/controllers/alchemy/admin/pages_controller.rb +50 -62
  39. data/app/controllers/alchemy/admin/pictures_controller.rb +16 -16
  40. data/app/controllers/alchemy/admin/resources_controller.rb +21 -13
  41. data/app/controllers/alchemy/admin/sites_controller.rb +18 -0
  42. data/app/controllers/alchemy/admin/styleguide_controller.rb +1 -0
  43. data/app/controllers/alchemy/admin/tags_controller.rb +5 -3
  44. data/app/controllers/alchemy/admin/trash_controller.rb +6 -6
  45. data/app/controllers/alchemy/api/base_controller.rb +2 -2
  46. data/app/controllers/alchemy/api/contents_controller.rb +4 -4
  47. data/app/controllers/alchemy/api/elements_controller.rb +8 -8
  48. data/app/controllers/alchemy/api/nodes_controller.rb +37 -1
  49. data/app/controllers/alchemy/api/pages_controller.rb +14 -23
  50. data/app/controllers/alchemy/attachments_controller.rb +5 -5
  51. data/app/controllers/alchemy/base_controller.rb +10 -9
  52. data/app/controllers/alchemy/messages_controller.rb +16 -23
  53. data/app/controllers/alchemy/pages_controller.rb +13 -11
  54. data/app/controllers/concerns/alchemy/admin/archive_overlay.rb +3 -2
  55. data/app/controllers/concerns/alchemy/admin/current_language.rb +23 -0
  56. data/app/controllers/concerns/alchemy/admin/uploader_responses.rb +5 -5
  57. data/app/controllers/concerns/alchemy/legacy_page_redirects.rb +4 -4
  58. data/app/controllers/concerns/alchemy/page_redirects.rb +2 -9
  59. data/app/controllers/concerns/alchemy/site_redirects.rb +2 -2
  60. data/app/decorators/alchemy/element_editor.rb +39 -0
  61. data/app/helpers/alchemy/admin/attachments_helper.rb +6 -6
  62. data/app/helpers/alchemy/admin/base_helper.rb +36 -35
  63. data/app/helpers/alchemy/admin/contents_helper.rb +3 -3
  64. data/app/helpers/alchemy/admin/elements_helper.rb +3 -88
  65. data/app/helpers/alchemy/admin/essences_helper.rb +8 -117
  66. data/app/helpers/alchemy/admin/form_helper.rb +1 -1
  67. data/app/helpers/alchemy/admin/navigation_helper.rb +24 -23
  68. data/app/helpers/alchemy/admin/pages_helper.rb +4 -4
  69. data/app/helpers/alchemy/admin/pictures_helper.rb +3 -3
  70. data/app/helpers/alchemy/admin/tags_helper.rb +8 -7
  71. data/app/helpers/alchemy/base_helper.rb +13 -8
  72. data/app/helpers/alchemy/elements_block_helper.rb +2 -31
  73. data/app/helpers/alchemy/elements_helper.rb +12 -58
  74. data/app/helpers/alchemy/pages_helper.rb +24 -174
  75. data/app/helpers/alchemy/url_helper.rb +2 -1
  76. data/app/mailers/alchemy/base_mailer.rb +1 -1
  77. data/app/mailers/alchemy/messages_mailer.rb +1 -1
  78. data/app/models/alchemy/attachment.rb +20 -18
  79. data/app/models/alchemy/base_record.rb +2 -5
  80. data/app/models/alchemy/content.rb +33 -38
  81. data/app/models/alchemy/content/factory.rb +24 -31
  82. data/app/models/alchemy/element.rb +45 -53
  83. data/app/models/alchemy/element/definitions.rb +4 -4
  84. data/app/models/alchemy/element/element_contents.rb +9 -6
  85. data/app/models/alchemy/element/element_essences.rb +4 -3
  86. data/app/models/alchemy/element/presenters.rb +3 -2
  87. data/app/models/alchemy/element_to_page.rb +1 -1
  88. data/app/models/alchemy/essence_boolean.rb +1 -3
  89. data/app/models/alchemy/essence_date.rb +2 -3
  90. data/app/models/alchemy/essence_file.rb +4 -4
  91. data/app/models/alchemy/essence_html.rb +1 -3
  92. data/app/models/alchemy/essence_link.rb +1 -3
  93. data/app/models/alchemy/essence_node.rb +18 -0
  94. data/app/models/alchemy/essence_page.rb +3 -16
  95. data/app/models/alchemy/essence_picture.rb +17 -16
  96. data/app/models/alchemy/essence_picture_view.rb +7 -6
  97. data/app/models/alchemy/essence_richtext.rb +1 -3
  98. data/app/models/alchemy/essence_select.rb +1 -3
  99. data/app/models/alchemy/essence_text.rb +0 -2
  100. data/app/models/alchemy/folded_page.rb +1 -0
  101. data/app/models/alchemy/language.rb +21 -35
  102. data/app/models/alchemy/language/code.rb +4 -4
  103. data/app/models/alchemy/legacy_page_url.rb +1 -1
  104. data/app/models/alchemy/message.rb +3 -3
  105. data/app/models/alchemy/node.rb +27 -4
  106. data/app/models/alchemy/page.rb +46 -127
  107. data/app/models/alchemy/page/fixed_attributes.rb +3 -2
  108. data/app/models/alchemy/page/page_elements.rb +35 -44
  109. data/app/models/alchemy/page/page_naming.rb +20 -70
  110. data/app/models/alchemy/page/page_natures.rb +7 -34
  111. data/app/models/alchemy/page/page_scopes.rb +23 -29
  112. data/app/models/alchemy/page/url_path.rb +0 -2
  113. data/app/models/alchemy/picture.rb +18 -27
  114. data/app/models/alchemy/picture/transformations.rb +9 -7
  115. data/app/models/alchemy/picture/url.rb +5 -5
  116. data/app/models/alchemy/site.rb +6 -36
  117. data/app/models/alchemy/site/layout.rb +2 -2
  118. data/app/models/concerns/alchemy/touch_elements.rb +24 -0
  119. data/app/serializers/alchemy/content_serializer.rb +0 -3
  120. data/app/serializers/alchemy/essence_boolean_serializer.rb +3 -3
  121. data/app/serializers/alchemy/essence_date_serializer.rb +3 -3
  122. data/app/serializers/alchemy/essence_file_serializer.rb +4 -2
  123. data/app/serializers/alchemy/essence_html_serializer.rb +3 -3
  124. data/app/serializers/alchemy/essence_link_serializer.rb +3 -3
  125. data/app/serializers/alchemy/essence_picture_serializer.rb +5 -4
  126. data/app/serializers/alchemy/essence_richtext_serializer.rb +3 -3
  127. data/app/serializers/alchemy/essence_select_serializer.rb +3 -3
  128. data/app/serializers/alchemy/essence_text_serializer.rb +5 -4
  129. data/app/serializers/alchemy/node_serializer.rb +2 -0
  130. data/app/serializers/alchemy/page_tree_serializer.rb +9 -13
  131. data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +1 -2
  132. data/app/views/alchemy/admin/attachments/_file_to_assign.html.erb +1 -2
  133. data/app/views/alchemy/admin/attachments/_files_list.html.erb +4 -4
  134. data/app/views/alchemy/admin/contents/create.js.erb +1 -3
  135. data/app/views/alchemy/admin/elements/_element.html.erb +9 -18
  136. data/app/views/alchemy/admin/elements/create.js.erb +1 -1
  137. data/app/views/alchemy/admin/elements/fold.js.erb +1 -1
  138. data/app/views/alchemy/admin/elements/index.html.erb +3 -3
  139. data/app/views/alchemy/admin/essence_files/assign.js.erb +1 -6
  140. data/app/views/alchemy/admin/essence_files/edit.html.erb +1 -1
  141. data/app/views/alchemy/admin/essence_pictures/assign.js.erb +1 -7
  142. data/app/views/alchemy/admin/essence_pictures/crop.html.erb +1 -1
  143. data/app/views/alchemy/admin/essence_pictures/edit.html.erb +7 -7
  144. data/app/views/alchemy/admin/essence_pictures/update.js.erb +1 -1
  145. data/app/views/alchemy/admin/languages/_form.html.erb +5 -5
  146. data/app/views/alchemy/admin/languages/_table.html.erb +3 -3
  147. data/app/views/alchemy/admin/languages/edit.html.erb +1 -0
  148. data/app/views/alchemy/admin/languages/index.html.erb +23 -4
  149. data/app/views/alchemy/admin/languages/new.html.erb +1 -0
  150. data/app/views/alchemy/admin/layoutpages/index.html.erb +3 -3
  151. data/app/views/alchemy/admin/nodes/_form.html.erb +18 -15
  152. data/app/views/alchemy/admin/nodes/_node.html.erb +1 -5
  153. data/app/views/alchemy/admin/nodes/index.html.erb +3 -4
  154. data/app/views/alchemy/admin/pages/_create_language_form.html.erb +0 -8
  155. data/app/views/alchemy/admin/pages/_form.html.erb +0 -1
  156. data/app/views/alchemy/admin/pages/_new_page_form.html.erb +1 -0
  157. data/app/views/alchemy/admin/pages/_page.html.erb +11 -19
  158. data/app/views/alchemy/admin/pages/_page_infos.html.erb +0 -4
  159. data/app/views/alchemy/admin/pages/edit.html.erb +1 -1
  160. data/app/views/alchemy/admin/pages/info.html.erb +0 -9
  161. data/app/views/alchemy/admin/pages/unlock.js.erb +13 -6
  162. data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +0 -2
  163. data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +1 -5
  164. data/app/views/alchemy/admin/pictures/_overlay_picture_list.html.erb +1 -1
  165. data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +1 -2
  166. data/app/views/alchemy/admin/resources/_resource.html.erb +1 -1
  167. data/app/views/alchemy/admin/resources/_table.html.erb +2 -2
  168. data/app/views/alchemy/admin/sites/_form.html.erb +8 -0
  169. data/app/views/alchemy/admin/sites/edit.html.erb +1 -0
  170. data/app/views/alchemy/admin/sites/index.html.erb +21 -9
  171. data/app/views/alchemy/admin/sites/new.html.erb +1 -0
  172. data/app/views/alchemy/admin/tags/index.html.erb +2 -2
  173. data/app/views/alchemy/essences/_essence_boolean_editor.html.erb +10 -12
  174. data/app/views/alchemy/essences/_essence_date_editor.html.erb +11 -8
  175. data/app/views/alchemy/essences/_essence_file_editor.html.erb +16 -17
  176. data/app/views/alchemy/essences/_essence_html_editor.html.erb +8 -5
  177. data/app/views/alchemy/essences/_essence_link_editor.html.erb +18 -15
  178. data/app/views/alchemy/essences/_essence_node_editor.html.erb +27 -0
  179. data/app/views/alchemy/essences/_essence_node_view.html.erb +1 -0
  180. data/app/views/alchemy/essences/_essence_page_editor.html.erb +14 -11
  181. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +22 -20
  182. data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +10 -7
  183. data/app/views/alchemy/essences/_essence_select_editor.html.erb +12 -16
  184. data/app/views/alchemy/essences/_essence_text_editor.html.erb +18 -17
  185. data/app/views/alchemy/essences/shared/_essence_picture_tools.html.erb +6 -11
  186. data/app/views/alchemy/pages/show.rss.builder +3 -2
  187. data/app/views/layouts/alchemy/admin.html.erb +1 -0
  188. data/babel.config.js +12 -0
  189. data/bin/rails +5 -4
  190. data/config/alchemy/config.yml +15 -18
  191. data/config/brakeman.ignore +1 -1
  192. data/config/initializers/assets.rb +2 -1
  193. data/config/initializers/dragonfly.rb +2 -1
  194. data/config/initializers/mime_types.rb +1 -0
  195. data/config/initializers/mini_profiler.rb +3 -2
  196. data/config/initializers/simple_form.rb +6 -6
  197. data/config/locales/alchemy.en.yml +23 -8
  198. data/config/routes.rb +25 -24
  199. data/config/spring.rb +3 -2
  200. data/db/migrate/20200226213334_alchemy_four_point_four.rb +313 -0
  201. data/db/migrate/20200423073425_create_alchemy_essence_nodes.rb +11 -0
  202. data/db/migrate/20200504210159_remove_site_id_from_nodes.rb +28 -0
  203. data/db/migrate/20200505215518_add_language_id_foreign_key_to_alchemy_pages.rb +8 -0
  204. data/db/migrate/20200511113603_add_menu_type_to_alchemy_nodes.rb +27 -0
  205. data/db/migrate/20200514091507_make_page_layoutpage_null_false.rb +6 -0
  206. data/db/migrate/20200519073500_remove_visible_from_alchemy_pages.rb +24 -0
  207. data/lib/alchemy/admin/locale.rb +3 -1
  208. data/lib/alchemy/admin/preview_url.rb +64 -0
  209. data/lib/alchemy/auth_accessors.rb +8 -7
  210. data/lib/alchemy/cache_digests/template_tracker.rb +5 -4
  211. data/lib/alchemy/config.rb +1 -5
  212. data/lib/alchemy/configuration_methods.rb +3 -1
  213. data/lib/alchemy/controller_actions.rb +6 -5
  214. data/lib/alchemy/deprecation.rb +2 -1
  215. data/lib/alchemy/elements_finder.rb +5 -5
  216. data/lib/alchemy/engine.rb +23 -8
  217. data/lib/alchemy/errors.rb +0 -7
  218. data/lib/alchemy/essence.rb +17 -16
  219. data/lib/alchemy/filetypes.rb +5 -5
  220. data/lib/alchemy/forms/builder.rb +4 -4
  221. data/lib/alchemy/hints.rb +1 -1
  222. data/lib/alchemy/i18n.rb +2 -1
  223. data/lib/alchemy/modules.rb +12 -12
  224. data/lib/alchemy/name_conversions.rb +5 -5
  225. data/lib/alchemy/on_page_layout/callbacks_runner.rb +1 -0
  226. data/lib/alchemy/page_layout.rb +15 -12
  227. data/lib/alchemy/paths.rb +1 -1
  228. data/lib/alchemy/permissions.rb +7 -6
  229. data/lib/alchemy/resource.rb +23 -13
  230. data/lib/alchemy/resources_helper.rb +12 -18
  231. data/lib/alchemy/routing_constraints.rb +1 -1
  232. data/lib/alchemy/seeder.rb +42 -14
  233. data/lib/alchemy/shell.rb +13 -10
  234. data/lib/alchemy/taggable.rb +1 -0
  235. data/lib/alchemy/tasks/tidy.rb +4 -3
  236. data/lib/alchemy/test_support/config_stubbing.rb +1 -0
  237. data/lib/alchemy/test_support/essence_shared_examples.rb +72 -72
  238. data/lib/alchemy/test_support/factories.rb +1 -1
  239. data/lib/alchemy/test_support/factories/attachment_factory.rb +5 -5
  240. data/lib/alchemy/test_support/factories/content_factory.rb +6 -6
  241. data/lib/alchemy/test_support/factories/dummy_user_factory.rb +7 -7
  242. data/lib/alchemy/test_support/factories/element_factory.rb +9 -9
  243. data/lib/alchemy/test_support/factories/essence_file_factory.rb +3 -3
  244. data/lib/alchemy/test_support/factories/essence_page_factory.rb +3 -3
  245. data/lib/alchemy/test_support/factories/essence_picture_factory.rb +4 -4
  246. data/lib/alchemy/test_support/factories/essence_text_factory.rb +3 -3
  247. data/lib/alchemy/test_support/factories/language_factory.rb +16 -14
  248. data/lib/alchemy/test_support/factories/node_factory.rb +8 -8
  249. data/lib/alchemy/test_support/factories/page_factory.rb +15 -27
  250. data/lib/alchemy/test_support/factories/picture_factory.rb +5 -5
  251. data/lib/alchemy/test_support/factories/site_factory.rb +7 -6
  252. data/lib/alchemy/test_support/integration_helpers.rb +1 -0
  253. data/lib/alchemy/test_support/shared_contexts.rb +5 -4
  254. data/lib/alchemy/test_support/shared_uploader_examples.rb +4 -3
  255. data/lib/alchemy/tinymce.rb +15 -13
  256. data/lib/alchemy/upgrader.rb +8 -7
  257. data/lib/alchemy/upgrader/five_point_zero.rb +41 -0
  258. data/lib/alchemy/upgrader/tasks/element_views_updater.rb +4 -4
  259. data/lib/alchemy/upgrader/tasks/harden_gutentag_migrations.rb +29 -0
  260. data/lib/alchemy/version.rb +1 -1
  261. data/lib/alchemy_cms.rb +52 -50
  262. data/lib/{rails/generators → generators}/alchemy/base.rb +5 -4
  263. data/lib/{rails/generators → generators}/alchemy/elements/elements_generator.rb +13 -9
  264. data/lib/{rails/generators → generators}/alchemy/elements/templates/view.html.erb +0 -0
  265. data/lib/{rails/generators → generators}/alchemy/elements/templates/view.html.haml +0 -0
  266. data/lib/{rails/generators → generators}/alchemy/elements/templates/view.html.slim +0 -0
  267. data/lib/{rails/generators → generators}/alchemy/essence/essence_generator.rb +15 -13
  268. data/lib/generators/alchemy/essence/templates/editor.html.erb +17 -0
  269. data/lib/{rails/generators → generators}/alchemy/essence/templates/view.html.erb +0 -0
  270. data/lib/{rails/generators → generators}/alchemy/install/files/_article.html.erb +0 -0
  271. data/lib/{rails/generators → generators}/alchemy/install/files/_standard.html.erb +0 -0
  272. data/lib/{rails/generators → generators}/alchemy/install/files/alchemy.en.yml +0 -0
  273. data/lib/generators/alchemy/install/files/alchemy_admin.js +1 -0
  274. data/lib/{rails/generators → generators}/alchemy/install/files/all.css +0 -0
  275. data/lib/{rails/generators → generators}/alchemy/install/files/all.js +0 -0
  276. data/lib/{rails/generators → generators}/alchemy/install/files/application.html.erb +0 -0
  277. data/lib/{rails/generators → generators}/alchemy/install/files/article.scss +0 -0
  278. data/lib/generators/alchemy/install/install_generator.rb +110 -0
  279. data/lib/{rails/generators → generators}/alchemy/install/templates/dragonfly.rb.tt +0 -0
  280. data/lib/{rails/generators → generators}/alchemy/install/templates/elements.yml.tt +0 -0
  281. data/lib/{rails/generators → generators}/alchemy/install/templates/menus.yml.tt +0 -0
  282. data/lib/{rails/generators → generators}/alchemy/install/templates/page_layouts.yml.tt +0 -0
  283. data/lib/{rails/generators → generators}/alchemy/menus/menus_generator.rb +2 -2
  284. data/lib/{rails/generators → generators}/alchemy/menus/templates/node.html.erb +1 -4
  285. data/lib/{rails/generators → generators}/alchemy/menus/templates/node.html.haml +1 -4
  286. data/lib/{rails/generators → generators}/alchemy/menus/templates/node.html.slim +1 -4
  287. data/lib/{rails/generators → generators}/alchemy/menus/templates/wrapper.html.erb +1 -1
  288. data/lib/{rails/generators → generators}/alchemy/menus/templates/wrapper.html.haml +1 -1
  289. data/lib/{rails/generators → generators}/alchemy/menus/templates/wrapper.html.slim +1 -1
  290. data/lib/{rails/generators → generators}/alchemy/module/module_generator.rb +3 -2
  291. data/lib/{rails/generators → generators}/alchemy/module/templates/ability.rb.tt +0 -0
  292. data/lib/{rails/generators → generators}/alchemy/module/templates/controller.rb.tt +0 -0
  293. data/lib/{rails/generators → generators}/alchemy/module/templates/module_config.rb.tt +0 -0
  294. data/lib/{rails/generators → generators}/alchemy/page_layouts/page_layouts_generator.rb +5 -4
  295. data/lib/{rails/generators → generators}/alchemy/page_layouts/templates/layout.html.erb +0 -0
  296. data/lib/{rails/generators → generators}/alchemy/page_layouts/templates/layout.html.haml +0 -0
  297. data/lib/{rails/generators → generators}/alchemy/page_layouts/templates/layout.html.slim +0 -0
  298. data/lib/{rails/generators → generators}/alchemy/site_layouts/site_layouts_generator.rb +4 -2
  299. data/lib/{rails/generators → generators}/alchemy/site_layouts/templates/layout.html.erb +0 -0
  300. data/lib/{rails/generators → generators}/alchemy/site_layouts/templates/layout.html.haml +0 -0
  301. data/lib/{rails/generators → generators}/alchemy/site_layouts/templates/layout.html.slim +0 -0
  302. data/lib/{rails/generators → generators}/alchemy/views/views_generator.rb +7 -6
  303. data/lib/kaminari/scoped_pagination_url_helper.rb +1 -0
  304. data/lib/tasks/alchemy/db.rake +3 -19
  305. data/lib/tasks/alchemy/install.rake +3 -2
  306. data/lib/tasks/alchemy/tidy.rake +9 -8
  307. data/lib/tasks/alchemy/upgrade.rake +18 -116
  308. data/package.json +45 -0
  309. data/package/admin.js +14 -0
  310. data/package/src/__tests__/i18n.spec.js +70 -0
  311. data/package/src/i18n.js +48 -0
  312. data/package/src/node_tree.js +72 -0
  313. data/package/src/translations.js +32 -0
  314. data/package/src/utils/__tests__/ajax.spec.js +124 -0
  315. data/package/src/utils/__tests__/events.spec.js +38 -0
  316. data/package/src/utils/ajax.js +48 -0
  317. data/package/src/utils/events.js +16 -0
  318. data/vendor/assets/fonts/fa-regular-400.eot +0 -0
  319. data/vendor/assets/fonts/fa-regular-400.svg +798 -358
  320. data/vendor/assets/fonts/fa-regular-400.ttf +0 -0
  321. data/vendor/assets/fonts/fa-regular-400.woff +0 -0
  322. data/vendor/assets/fonts/fa-regular-400.woff2 +0 -0
  323. data/vendor/assets/fonts/fa-solid-900.eot +0 -0
  324. data/vendor/assets/fonts/fa-solid-900.svg +4933 -1408
  325. data/vendor/assets/fonts/fa-solid-900.ttf +0 -0
  326. data/vendor/assets/fonts/fa-solid-900.woff +0 -0
  327. data/vendor/assets/fonts/fa-solid-900.woff2 +0 -0
  328. data/vendor/assets/javascripts/jquery_plugins/jquery.ui.nestedSortable.js +1 -2
  329. data/vendor/assets/stylesheets/fontawesome/_core.scss +5 -0
  330. data/vendor/assets/stylesheets/fontawesome/_fixed-width.scss +1 -1
  331. data/vendor/assets/stylesheets/fontawesome/_icons.scss +651 -2
  332. data/vendor/assets/stylesheets/fontawesome/_mixins.scss +0 -1
  333. data/vendor/assets/stylesheets/fontawesome/_rotated-flipped.scss +3 -2
  334. data/vendor/assets/stylesheets/fontawesome/_stacked.scss +1 -1
  335. data/vendor/assets/stylesheets/fontawesome/_variables.scss +662 -9
  336. data/vendor/assets/stylesheets/fontawesome/fontawesome.scss +2 -2
  337. data/vendor/assets/stylesheets/fontawesome/regular.scss +23 -0
  338. data/vendor/assets/stylesheets/fontawesome/solid.scss +24 -0
  339. metadata +110 -88
  340. data/app/assets/javascripts/alchemy/alchemy.i18n.js.coffee +0 -32
  341. data/app/assets/javascripts/alchemy/alchemy.node_tree.js +0 -66
  342. data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +0 -29
  343. data/app/assets/javascripts/alchemy/alchemy.utils.js +0 -45
  344. data/app/helpers/alchemy/essences_helper.rb +0 -119
  345. data/app/models/concerns/alchemy/content_touching.rb +0 -23
  346. data/app/serializers/alchemy/legacy_element_serializer.rb +0 -15
  347. data/app/views/alchemy/admin/contents/_missing.html.erb +0 -17
  348. data/app/views/alchemy/admin/pages/_menu_fields.html.erb +0 -37
  349. data/app/views/alchemy/admin/pages/configure_external.html.erb +0 -32
  350. data/app/views/alchemy/elements/_editor_not_found.html.erb +0 -4
  351. data/app/views/alchemy/navigation/_image_link.html.erb +0 -14
  352. data/app/views/alchemy/navigation/_link.html.erb +0 -19
  353. data/app/views/alchemy/navigation/_renderer.html.erb +0 -29
  354. data/db/migrate/20180226123013_alchemy_four_point_zero.rb +0 -363
  355. data/db/migrate/20180227224537_migrate_tags_to_gutentag.rb +0 -41
  356. data/db/migrate/20180519204655_add_fixed_to_alchemy_elements.rb +0 -6
  357. data/db/migrate/20191016073858_create_alchemy_essence_pages.rb +0 -8
  358. data/db/migrate/20191029212236_create_alchemy_nodes.rb +0 -24
  359. data/db/migrate/20200226081535_add_site_id_to_alchemy_nodes.rb +0 -15
  360. data/lib/alchemy/ssl_protection.rb +0 -34
  361. data/lib/alchemy/tasks/helpers.rb +0 -81
  362. data/lib/alchemy/test_support/controller_requests.rb +0 -93
  363. data/lib/alchemy/upgrader/four_point_four.rb +0 -52
  364. data/lib/alchemy/upgrader/four_point_one.rb +0 -42
  365. data/lib/alchemy/upgrader/four_point_six.rb +0 -50
  366. data/lib/alchemy/upgrader/four_point_two.rb +0 -85
  367. data/lib/alchemy/upgrader/tasks/cells_migration.rb +0 -43
  368. data/lib/alchemy/upgrader/tasks/cells_upgrader.rb +0 -148
  369. data/lib/alchemy/upgrader/tasks/element_partial_name_variable_updater.rb +0 -28
  370. data/lib/alchemy/upgrader/tasks/harden_acts_as_taggable_on_migrations.rb +0 -27
  371. data/lib/alchemy/upgrader/tasks/picture_gallery_migration.rb +0 -65
  372. data/lib/alchemy/upgrader/tasks/picture_gallery_upgrader.rb +0 -210
  373. data/lib/rails/generators/alchemy/essence/templates/editor.html.erb +0 -15
  374. data/lib/rails/generators/alchemy/install/install_generator.rb +0 -60
  375. data/lib/tasks/alchemy/convert.rake +0 -97
  376. data/vendor/assets/javascripts/sortable/Sortable.min.js +0 -2
  377. data/vendor/assets/stylesheets/fontawesome/fa-regular.scss +0 -22
  378. data/vendor/assets/stylesheets/fontawesome/fa-solid.scss +0 -23
@@ -4,7 +4,7 @@ module Alchemy::Language::Code
4
4
  extend ActiveSupport::Concern
5
5
 
6
6
  def code
7
- [language_code, country_code].select(&:present?).join('-')
7
+ [language_code, country_code].select(&:present?).join("-")
8
8
  end
9
9
 
10
10
  def code=(code)
@@ -13,11 +13,11 @@ module Alchemy::Language::Code
13
13
 
14
14
  module ClassMethods
15
15
  def find_by_code(code)
16
- codes = code.split('-')
17
- codes << '' if codes.length == 1
16
+ codes = code.split("-")
17
+ codes << "" if codes.length == 1
18
18
  on_current_site.find_by(
19
19
  language_code: codes[0],
20
- country_code: codes[1]
20
+ country_code: codes[1],
21
21
  )
22
22
  end
23
23
  end
@@ -13,7 +13,7 @@
13
13
 
14
14
  class Alchemy::LegacyPageUrl < ActiveRecord::Base
15
15
  belongs_to :page,
16
- class_name: 'Alchemy::Page',
16
+ class_name: "Alchemy::Page",
17
17
  required: true
18
18
 
19
19
  validates :urlname,
@@ -22,17 +22,17 @@ module Alchemy
22
22
 
23
23
  attr_accessor :contact_form_id, :ip
24
24
 
25
- config['fields'].each do |field|
25
+ config["fields"].each do |field|
26
26
  attr_accessor field.to_sym
27
27
  end
28
28
 
29
- config['validate_fields'].each do |field|
29
+ config["validate_fields"].each do |field|
30
30
  validates_presence_of field
31
31
 
32
32
  case field.to_sym
33
33
  when /email/
34
34
  validates_format_of field,
35
- with: Alchemy::Config.get('format_matchers')['email'],
35
+ with: Alchemy::Config.get("format_matchers")["email"],
36
36
  if: -> { send(field).present? }
37
37
  when :email_confirmation
38
38
  validates_confirmation_of :email
@@ -4,13 +4,22 @@ module Alchemy
4
4
  class Node < BaseRecord
5
5
  VALID_URL_REGEX = /\A(\/|\D[a-z\+\d\.\-]+:)/
6
6
 
7
+ before_destroy :check_if_related_essence_nodes_present
8
+
7
9
  acts_as_nested_set scope: "language_id", touch: true
8
10
  stampable stamper_class_name: Alchemy.user_class_name
9
11
 
10
- belongs_to :site, class_name: "Alchemy::Site"
11
12
  belongs_to :language, class_name: "Alchemy::Language"
12
13
  belongs_to :page, class_name: "Alchemy::Page", optional: true, inverse_of: :nodes
13
14
 
15
+ has_one :site, through: :language
16
+
17
+ has_many :essence_nodes, class_name: "Alchemy::EssenceNode", foreign_key: :node_id, inverse_of: :ingredient_association
18
+
19
+ before_validation :translate_root_menu_name, if: -> { root? }
20
+ before_validation :set_menu_type_from_root, unless: -> { root? }
21
+
22
+ validates :menu_type, presence: true
14
23
  validates :name, presence: true, if: -> { page.nil? }
15
24
  validates :url, format: { with: VALID_URL_REGEX }, unless: -> { url.nil? }
16
25
 
@@ -62,11 +71,25 @@ module Alchemy
62
71
  end
63
72
 
64
73
  def to_partial_path
65
- "#{view_folder_name}/wrapper"
74
+ "alchemy/menus/#{menu_type}/node"
75
+ end
76
+
77
+ private
78
+
79
+ def check_if_related_essence_nodes_present
80
+ dependent_essence_nodes = self_and_descendants.flat_map(&:essence_nodes)
81
+ if dependent_essence_nodes.any?
82
+ errors.add(:base, :essence_nodes_present, page_names: dependent_essence_nodes.map(&:page).map(&:name).to_sentence)
83
+ throw(:abort)
84
+ end
85
+ end
86
+
87
+ def translate_root_menu_name
88
+ self.name ||= Alchemy.t(menu_type, scope: :menu_names)
66
89
  end
67
90
 
68
- def view_folder_name
69
- "alchemy/menus/#{name.parameterize.underscore}"
91
+ def set_menu_type_from_root
92
+ self.menu_type = root.menu_type
70
93
  end
71
94
  end
72
95
  end
@@ -17,7 +17,6 @@
17
17
  # rgt :integer
18
18
  # parent_id :integer
19
19
  # depth :integer
20
- # visible :boolean default(FALSE)
21
20
  # locked_by :integer
22
21
  # restricted :boolean default(FALSE)
23
22
  # robot_index :boolean default(TRUE)
@@ -44,11 +43,10 @@ module Alchemy
44
43
 
45
44
  DEFAULT_ATTRIBUTES_FOR_COPY = {
46
45
  autogenerate_elements: false,
47
- visible: false,
48
46
  public_on: nil,
49
47
  public_until: nil,
50
48
  locked_at: nil,
51
- locked_by: nil
49
+ locked_by: nil,
52
50
  }
53
51
 
54
52
  SKIPPED_ATTRIBUTES_ON_COPY = %w(
@@ -78,16 +76,15 @@ module Alchemy
78
76
  :tag_list,
79
77
  :title,
80
78
  :urlname,
81
- :visible,
82
79
  :layoutpage,
83
- :menu_id
80
+ :menu_id,
84
81
  ]
85
82
 
86
- acts_as_nested_set(dependent: :destroy)
83
+ acts_as_nested_set(dependent: :destroy, scope: [:layoutpage, :language_id])
87
84
 
88
85
  stampable stamper_class_name: Alchemy.user_class_name
89
86
 
90
- belongs_to :language, optional: true
87
+ belongs_to :language
91
88
 
92
89
  belongs_to :creator,
93
90
  primary_key: Alchemy.user_class_primary_key,
@@ -110,43 +107,33 @@ module Alchemy
110
107
  has_one :site, through: :language
111
108
  has_many :site_languages, through: :site, source: :languages
112
109
  has_many :folded_pages
113
- has_many :legacy_urls, class_name: 'Alchemy::LegacyPageUrl'
114
- has_many :nodes, class_name: 'Alchemy::Node', inverse_of: :page
110
+ has_many :legacy_urls, class_name: "Alchemy::LegacyPageUrl"
111
+ has_many :nodes, class_name: "Alchemy::Node", inverse_of: :page
115
112
 
116
- validates_presence_of :language, on: :create, unless: :root
117
- validates_presence_of :page_layout, unless: :systempage?
118
- validates_format_of :page_layout, with: /\A[a-z0-9_-]+\z/, unless: -> { systempage? || page_layout.blank? }
119
- validates_presence_of :parent_id, if: proc { Page.count > 1 }
113
+ before_validation :set_language,
114
+ if: -> { language.nil? }
115
+
116
+ validates_presence_of :page_layout
117
+ validates_format_of :page_layout, with: /\A[a-z0-9_-]+\z/, unless: -> { page_layout.blank? }
118
+ validates_presence_of :parent, unless: -> { layoutpage? || language_root? }
120
119
 
121
120
  before_save :set_language_code,
122
- if: -> { language.present? },
123
- unless: :systempage?
121
+ if: -> { language.present? }
124
122
 
125
123
  before_save :set_restrictions_to_child_pages,
126
- if: :restricted_changed?,
127
- unless: :systempage?
124
+ if: :restricted_changed?
128
125
 
129
126
  before_save :inherit_restricted_status,
130
- if: -> { parent && parent.restricted? },
131
- unless: :systempage?
127
+ if: -> { parent && parent.restricted? }
132
128
 
133
129
  before_save :set_published_at,
134
- if: -> { public_on.present? && published_at.nil? },
135
- unless: :systempage?
130
+ if: -> { public_on.present? && published_at.nil? }
136
131
 
137
132
  before_save :set_fixed_attributes,
138
133
  if: -> { fixed_attributes.any? }
139
134
 
140
- before_create :set_language_from_parent_or_default,
141
- if: -> { language_id.blank? },
142
- unless: :systempage?
143
-
144
135
  after_update :create_legacy_url,
145
- if: :should_create_legacy_url?,
146
- unless: -> { definition['redirects_to_external'] }
147
-
148
- after_update :attach_to_menu!,
149
- if: :should_attach_to_menu?
136
+ if: :saved_change_to_urlname?
150
137
 
151
138
  after_update -> { nodes.update_all(updated_at: Time.current) }
152
139
 
@@ -159,26 +146,9 @@ module Alchemy
159
146
  # site_name accessor
160
147
  delegate :name, to: :site, prefix: true, allow_nil: true
161
148
 
162
- attr_accessor :menu_id
163
-
164
- deprecate visible: "Page slugs will be visible in URLs of child pages all the time. " \
165
- "Please use Menus and Tags instead to re-organize your pages if your page tree does not reflect the URL hierarchy.",
166
- deprecator: Alchemy::Deprecation
167
-
168
149
  # Class methods
169
150
  #
170
151
  class << self
171
- # The root page of the page tree
172
- #
173
- # Internal use only. You wouldn't use this page ever.
174
- #
175
- # Automatically created when accessed the first time.
176
- #
177
- def root
178
- super || create!(name: 'Root')
179
- end
180
- alias_method :rootpage, :root
181
-
182
152
  # Used to store the current page previewed in the edit page template.
183
153
  #
184
154
  def current_preview=(page)
@@ -222,29 +192,12 @@ module Alchemy
222
192
  end
223
193
  end
224
194
 
225
- def layout_root_for(language_id)
226
- where({parent_id: Page.root.id, layoutpage: true, language_id: language_id}).limit(1).first
227
- end
228
-
229
- def find_or_create_layout_root_for(language_id)
230
- layoutroot = layout_root_for(language_id)
231
- return layoutroot if layoutroot
232
- language = Language.find(language_id)
233
- Page.create!(
234
- name: "Layoutroot for #{language.name}",
235
- layoutpage: true,
236
- language: language,
237
- autogenerate_elements: false,
238
- parent_id: Page.root.id
239
- )
240
- end
241
-
242
195
  def copy_and_paste(source, new_parent, new_name)
243
196
  page = copy(source, {
244
197
  parent_id: new_parent.id,
245
198
  language: new_parent.language,
246
199
  name: new_name,
247
- title: new_name
200
+ title: new_name,
248
201
  })
249
202
  if source.children.any?
250
203
  source.copy_children_to(page)
@@ -254,34 +207,29 @@ module Alchemy
254
207
 
255
208
  def all_from_clipboard(clipboard)
256
209
  return [] if clipboard.blank?
257
- where(id: clipboard.collect { |p| p['id'] })
210
+
211
+ where(id: clipboard.collect { |p| p["id"] })
258
212
  end
259
213
 
260
214
  def all_from_clipboard_for_select(clipboard, language_id, layoutpage = false)
261
215
  return [] if clipboard.blank?
216
+
262
217
  clipboard_pages = all_from_clipboard(clipboard)
263
218
  allowed_page_layouts = Alchemy::PageLayout.selectable_layouts(language_id, layoutpage)
264
- allowed_page_layout_names = allowed_page_layouts.collect { |p| p['name'] }
219
+ allowed_page_layout_names = allowed_page_layouts.collect { |p| p["name"] }
265
220
  clipboard_pages.select { |cp| allowed_page_layout_names.include?(cp.page_layout) }
266
221
  end
267
222
 
268
223
  def link_target_options
269
- options = [[Alchemy.t(:default, scope: 'link_target_options'), '']]
224
+ options = [[Alchemy.t(:default, scope: "link_target_options"), ""]]
270
225
  link_target_options = Config.get(:link_target_options)
271
226
  link_target_options.each do |option|
272
- options << [Alchemy.t(option, scope: 'link_target_options',
273
- default: option.to_s.humanize), option]
227
+ options << [Alchemy.t(option, scope: "link_target_options",
228
+ default: option.to_s.humanize), option]
274
229
  end
275
230
  options
276
231
  end
277
232
 
278
- # Returns an array of all pages in the same branch from current.
279
- # I.e. used to find the active page in navigation.
280
- def ancestors_for(current)
281
- return [] if current.nil?
282
- current.self_and_ancestors.contentpages
283
- end
284
-
285
233
  private
286
234
 
287
235
  # Aggregates the attributes from given source for copy of page.
@@ -296,7 +244,7 @@ module Alchemy
296
244
  differences.stringify_keys!
297
245
  attributes = source.attributes.merge(differences)
298
246
  attributes.merge!(DEFAULT_ATTRIBUTES_FOR_COPY)
299
- attributes['name'] = new_name_for_copy(differences['name'], source.name)
247
+ attributes["name"] = new_name_for_copy(differences["name"], source.name)
300
248
  attributes.except(*SKIPPED_ATTRIBUTES_ON_COPY)
301
249
  end
302
250
 
@@ -312,7 +260,8 @@ module Alchemy
312
260
  #
313
261
  def new_name_for_copy(custom_name, source_name)
314
262
  return custom_name if custom_name.present?
315
- "#{source_name} (#{Alchemy.t('Copy')})"
263
+
264
+ "#{source_name} (#{Alchemy.t("Copy")})"
316
265
  end
317
266
  end
318
267
 
@@ -340,13 +289,7 @@ module Alchemy
340
289
  # Use this for your custom element loading logic.
341
290
  #
342
291
  # @return [ActiveRecord::Relation]
343
- def find_elements(options = {}, show_non_public = false)
344
- if show_non_public
345
- Alchemy::Deprecation.warn "Passing true as second argument to page#find_elements to include" \
346
- " invisible elements has been removed. Please implement your own ElementsFinder" \
347
- " and pass it with options[:finder]."
348
- end
349
-
292
+ def find_elements(options = {})
350
293
  finder = options[:finder] || Alchemy::ElementsFinder.new(options)
351
294
  finder.elements(page: self)
352
295
  end
@@ -384,9 +327,10 @@ module Alchemy
384
327
  # only public pages (true), skip public pages (false)
385
328
  #
386
329
  def previous(options = {})
387
- pages = self_and_siblings.where('lft < ?', lft)
330
+ pages = self_and_siblings.where("lft < ?", lft)
388
331
  select_page(pages, options.merge(order: :desc))
389
332
  end
333
+
390
334
  alias_method :previous_page, :previous
391
335
 
392
336
  # Returns the next page on the same level or nil.
@@ -397,9 +341,10 @@ module Alchemy
397
341
  # only public pages (true), skip public pages (false)
398
342
  #
399
343
  def next(options = {})
400
- pages = self_and_siblings.where('lft > ?', lft)
344
+ pages = self_and_siblings.where("lft > ?", lft)
401
345
  select_page(pages, options.merge(order: :asc))
402
346
  end
347
+
403
348
  alias_method :next_page, :next
404
349
 
405
350
  # Locks the page to given user
@@ -445,9 +390,10 @@ module Alchemy
445
390
  def copy_children_to(new_parent)
446
391
  children.each do |child|
447
392
  next if child == new_parent
393
+
448
394
  new_child = Page.copy(child, {
449
395
  language_id: new_parent.language_id,
450
- language_code: new_parent.language_code
396
+ language_code: new_parent.language_code,
451
397
  })
452
398
  new_child.move_to_child_of(new_parent)
453
399
  child.copy_children_to(new_child) unless child.children.blank?
@@ -466,22 +412,22 @@ module Alchemy
466
412
  update_columns(
467
413
  published_at: current_time,
468
414
  public_on: already_public_for?(current_time) ? public_on : current_time,
469
- public_until: still_public_for?(current_time) ? public_until : nil
415
+ public_until: still_public_for?(current_time) ? public_until : nil,
470
416
  )
471
417
  end
472
418
 
473
419
  # Updates an Alchemy::Page based on a new ordering to be applied to it
474
420
  #
475
421
  # Note: Page's urls should not be updated (and a legacy URL created) if nesting is OFF
476
- # or if a page is external or if the URL is the same
422
+ # or if the URL is the same
477
423
  #
478
424
  # @param [TreeNode]
479
425
  # A tree node with new lft, rgt, depth, url, parent_id and restricted indexes to be updated
480
426
  #
481
427
  def update_node!(node)
482
- hash = {lft: node.left, rgt: node.right, parent_id: node.parent, depth: node.depth, restricted: node.restricted}
428
+ hash = { lft: node.left, rgt: node.right, parent_id: node.parent, depth: node.depth, restricted: node.restricted }
483
429
 
484
- if Config.get(:url_nesting) && !definition['redirects_to_external'] && urlname != node.url
430
+ if urlname != node.url
485
431
  LegacyPageUrl.create(page_id: id, urlname: urlname)
486
432
  hash[:urlname] = node.url
487
433
  end
@@ -506,6 +452,7 @@ module Alchemy
506
452
  #
507
453
  def editable_by?(user)
508
454
  return true unless has_limited_editors?
455
+
509
456
  (editor_roles & user.alchemy_roles).any?
510
457
  end
511
458
 
@@ -531,7 +478,7 @@ module Alchemy
531
478
  # does not respond to +#name+ it returns +'unknown'+
532
479
  #
533
480
  def creator_name
534
- creator.try(:name) || Alchemy.t('unknown')
481
+ creator.try(:name) || Alchemy.t("unknown")
535
482
  end
536
483
 
537
484
  # Returns the name of the last updater of this page.
@@ -540,7 +487,7 @@ module Alchemy
540
487
  # does not respond to +#name+ it returns +'unknown'+
541
488
  #
542
489
  def updater_name
543
- updater.try(:name) || Alchemy.t('unknown')
490
+ updater.try(:name) || Alchemy.t("unknown")
544
491
  end
545
492
 
546
493
  # Returns the name of the user currently editing this page.
@@ -549,7 +496,7 @@ module Alchemy
549
496
  # does not respond to +#name+ it returns +'unknown'+
550
497
  #
551
498
  def locker_name
552
- locker.try(:name) || Alchemy.t('unknown')
499
+ locker.try(:name) || Alchemy.t("unknown")
553
500
  end
554
501
 
555
502
  # Menus (aka. root nodes) this page is attached to
@@ -573,8 +520,8 @@ module Alchemy
573
520
  .limit(1).first
574
521
  end
575
522
 
576
- def set_language_from_parent_or_default
577
- self.language = parent.language || Language.default
523
+ def set_language
524
+ self.language = parent&.language || Language.current
578
525
  set_language_code
579
526
  end
580
527
 
@@ -582,41 +529,13 @@ module Alchemy
582
529
  self.language_code = language.code
583
530
  end
584
531
 
585
- def should_create_legacy_url?
586
- if active_record_5_1?
587
- saved_change_to_urlname?
588
- else
589
- urlname_changed?
590
- end
591
- end
592
-
593
532
  # Stores the old urlname in a LegacyPageUrl
594
533
  def create_legacy_url
595
- if active_record_5_1?
596
- former_urlname = urlname_before_last_save
597
- else
598
- former_urlname = urlname_was
599
- end
600
- legacy_urls.find_or_create_by(urlname: former_urlname)
534
+ legacy_urls.find_or_create_by(urlname: urlname_before_last_save)
601
535
  end
602
536
 
603
537
  def set_published_at
604
538
  self.published_at = Time.current
605
539
  end
606
-
607
- def attach_to_menu!
608
- current_site_id = Alchemy::Site.current.id
609
- node = Alchemy::Node.find_by!(id: menu_id, site_id: current_site_id)
610
- node.children.create!(
611
- site_id: current_site_id,
612
- language_id: language_id,
613
- page_id: id,
614
- name: name
615
- )
616
- end
617
-
618
- def should_attach_to_menu?
619
- menu_id.present? && nodes.none?
620
- end
621
540
  end
622
541
  end