alchemy_cms 4.4.4 → 5.0.0.beta2

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 (386) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +56 -18
  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 +33 -20
  8. data/CHANGELOG.md +121 -0
  9. data/Gemfile +24 -22
  10. data/README.md +31 -19
  11. data/Rakefile +10 -8
  12. data/alchemy_cms.gemspec +7 -5
  13. data/app/assets/javascripts/alchemy/admin.js +1 -2
  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.link_dialog.js.coffee +5 -5
  17. data/app/assets/javascripts/alchemy/alchemy.page_sorter.js +17 -17
  18. data/app/assets/javascripts/alchemy/node_select.js +39 -0
  19. data/app/assets/javascripts/alchemy/templates/index.js +2 -0
  20. data/app/assets/javascripts/alchemy/templates/node.hbs +16 -0
  21. data/app/assets/javascripts/alchemy/templates/node_folder.hbs +3 -0
  22. data/app/assets/javascripts/alchemy/templates/page.hbs +1 -1
  23. data/app/assets/stylesheets/alchemy/_mixins.scss +2 -3
  24. data/app/assets/stylesheets/alchemy/_variables.scss +2 -2
  25. data/app/assets/stylesheets/alchemy/admin.scss +3 -2
  26. data/app/assets/stylesheets/alchemy/base.scss +0 -1
  27. data/app/assets/stylesheets/alchemy/elements.scss +1 -1
  28. data/app/assets/stylesheets/alchemy/forms.scss +5 -0
  29. data/app/assets/stylesheets/alchemy/lists.scss +0 -8
  30. data/app/assets/stylesheets/alchemy/node-select.scss +43 -0
  31. data/app/assets/stylesheets/alchemy/nodes.scss +6 -1
  32. data/app/assets/stylesheets/alchemy/sitemap.scss +63 -21
  33. data/app/assets/stylesheets/alchemy/tables.scss +1 -24
  34. data/app/controllers/alchemy/admin/attachments_controller.rb +8 -7
  35. data/app/controllers/alchemy/admin/base_controller.rb +13 -33
  36. data/app/controllers/alchemy/admin/clipboard_controller.rb +5 -4
  37. data/app/controllers/alchemy/admin/contents_controller.rb +1 -2
  38. data/app/controllers/alchemy/admin/dashboard_controller.rb +10 -9
  39. data/app/controllers/alchemy/admin/elements_controller.rb +20 -20
  40. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +12 -14
  41. data/app/controllers/alchemy/admin/languages_controller.rb +35 -2
  42. data/app/controllers/alchemy/admin/layoutpages_controller.rb +5 -2
  43. data/app/controllers/alchemy/admin/nodes_controller.rb +5 -14
  44. data/app/controllers/alchemy/admin/pages_controller.rb +50 -63
  45. data/app/controllers/alchemy/admin/pictures_controller.rb +16 -16
  46. data/app/controllers/alchemy/admin/resources_controller.rb +21 -13
  47. data/app/controllers/alchemy/admin/sites_controller.rb +18 -0
  48. data/app/controllers/alchemy/admin/styleguide_controller.rb +1 -0
  49. data/app/controllers/alchemy/admin/tags_controller.rb +5 -3
  50. data/app/controllers/alchemy/admin/trash_controller.rb +6 -6
  51. data/app/controllers/alchemy/api/base_controller.rb +2 -2
  52. data/app/controllers/alchemy/api/contents_controller.rb +4 -4
  53. data/app/controllers/alchemy/api/elements_controller.rb +8 -8
  54. data/app/controllers/alchemy/api/nodes_controller.rb +65 -0
  55. data/app/controllers/alchemy/api/pages_controller.rb +15 -22
  56. data/app/controllers/alchemy/attachments_controller.rb +5 -5
  57. data/app/controllers/alchemy/base_controller.rb +10 -9
  58. data/app/controllers/alchemy/messages_controller.rb +16 -23
  59. data/app/controllers/alchemy/pages_controller.rb +13 -11
  60. data/app/controllers/concerns/alchemy/admin/archive_overlay.rb +3 -2
  61. data/app/controllers/concerns/alchemy/admin/current_language.rb +23 -0
  62. data/app/controllers/concerns/alchemy/admin/uploader_responses.rb +5 -5
  63. data/app/controllers/concerns/alchemy/legacy_page_redirects.rb +4 -4
  64. data/app/controllers/concerns/alchemy/page_redirects.rb +2 -9
  65. data/app/controllers/concerns/alchemy/site_redirects.rb +2 -2
  66. data/app/decorators/alchemy/content_editor.rb +55 -0
  67. data/app/decorators/alchemy/element_editor.rb +39 -0
  68. data/app/helpers/alchemy/admin/attachments_helper.rb +6 -6
  69. data/app/helpers/alchemy/admin/base_helper.rb +36 -35
  70. data/app/helpers/alchemy/admin/contents_helper.rb +3 -3
  71. data/app/helpers/alchemy/admin/elements_helper.rb +3 -88
  72. data/app/helpers/alchemy/admin/essences_helper.rb +8 -117
  73. data/app/helpers/alchemy/admin/form_helper.rb +1 -1
  74. data/app/helpers/alchemy/admin/navigation_helper.rb +24 -23
  75. data/app/helpers/alchemy/admin/pages_helper.rb +12 -12
  76. data/app/helpers/alchemy/admin/pictures_helper.rb +4 -6
  77. data/app/helpers/alchemy/admin/tags_helper.rb +8 -7
  78. data/app/helpers/alchemy/base_helper.rb +13 -8
  79. data/app/helpers/alchemy/elements_block_helper.rb +2 -31
  80. data/app/helpers/alchemy/elements_helper.rb +12 -58
  81. data/app/helpers/alchemy/pages_helper.rb +24 -174
  82. data/app/helpers/alchemy/url_helper.rb +2 -1
  83. data/app/mailers/alchemy/base_mailer.rb +1 -1
  84. data/app/mailers/alchemy/messages_mailer.rb +1 -1
  85. data/app/models/alchemy/attachment.rb +20 -18
  86. data/app/models/alchemy/base_record.rb +2 -5
  87. data/app/models/alchemy/content.rb +33 -52
  88. data/app/models/alchemy/content/factory.rb +24 -31
  89. data/app/models/alchemy/element.rb +45 -53
  90. data/app/models/alchemy/element/definitions.rb +4 -4
  91. data/app/models/alchemy/element/element_contents.rb +9 -6
  92. data/app/models/alchemy/element/element_essences.rb +4 -3
  93. data/app/models/alchemy/element/presenters.rb +3 -2
  94. data/app/models/alchemy/element_to_page.rb +1 -1
  95. data/app/models/alchemy/essence_boolean.rb +1 -3
  96. data/app/models/alchemy/essence_date.rb +2 -3
  97. data/app/models/alchemy/essence_file.rb +4 -4
  98. data/app/models/alchemy/essence_html.rb +1 -3
  99. data/app/models/alchemy/essence_link.rb +1 -3
  100. data/app/models/alchemy/essence_node.rb +18 -0
  101. data/app/models/alchemy/essence_page.rb +3 -16
  102. data/app/models/alchemy/essence_picture.rb +17 -16
  103. data/app/models/alchemy/essence_picture_view.rb +7 -6
  104. data/app/models/alchemy/essence_richtext.rb +1 -3
  105. data/app/models/alchemy/essence_select.rb +1 -3
  106. data/app/models/alchemy/essence_text.rb +0 -2
  107. data/app/models/alchemy/folded_page.rb +1 -0
  108. data/app/models/alchemy/language.rb +21 -35
  109. data/app/models/alchemy/language/code.rb +4 -4
  110. data/app/models/alchemy/legacy_page_url.rb +1 -1
  111. data/app/models/alchemy/message.rb +3 -3
  112. data/app/models/alchemy/node.rb +55 -9
  113. data/app/models/alchemy/page.rb +53 -123
  114. data/app/models/alchemy/page/fixed_attributes.rb +3 -2
  115. data/app/models/alchemy/page/page_elements.rb +35 -44
  116. data/app/models/alchemy/page/page_naming.rb +20 -70
  117. data/app/models/alchemy/page/page_natures.rb +7 -34
  118. data/app/models/alchemy/page/page_scopes.rb +23 -29
  119. data/app/models/alchemy/page/url_path.rb +64 -0
  120. data/app/models/alchemy/picture.rb +40 -30
  121. data/app/models/alchemy/picture/preprocessor.rb +26 -0
  122. data/app/models/alchemy/picture/transformations.rb +9 -7
  123. data/app/models/alchemy/picture/url.rb +5 -5
  124. data/app/models/alchemy/site.rb +6 -36
  125. data/app/models/alchemy/site/layout.rb +2 -2
  126. data/app/models/concerns/alchemy/touch_elements.rb +24 -0
  127. data/app/serializers/alchemy/content_serializer.rb +0 -3
  128. data/app/serializers/alchemy/essence_boolean_serializer.rb +3 -3
  129. data/app/serializers/alchemy/essence_date_serializer.rb +3 -3
  130. data/app/serializers/alchemy/essence_file_serializer.rb +4 -2
  131. data/app/serializers/alchemy/essence_html_serializer.rb +3 -3
  132. data/app/serializers/alchemy/essence_link_serializer.rb +3 -3
  133. data/app/serializers/alchemy/essence_picture_serializer.rb +5 -4
  134. data/app/serializers/alchemy/essence_richtext_serializer.rb +3 -3
  135. data/app/serializers/alchemy/essence_select_serializer.rb +3 -3
  136. data/app/serializers/alchemy/essence_text_serializer.rb +5 -4
  137. data/app/serializers/alchemy/node_serializer.rb +14 -0
  138. data/app/serializers/alchemy/page_serializer.rb +2 -1
  139. data/app/serializers/alchemy/page_tree_serializer.rb +11 -14
  140. data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +1 -2
  141. data/app/views/alchemy/admin/attachments/_file_to_assign.html.erb +1 -2
  142. data/app/views/alchemy/admin/attachments/_files_list.html.erb +4 -4
  143. data/app/views/alchemy/admin/contents/create.js.erb +1 -3
  144. data/app/views/alchemy/admin/elements/_element.html.erb +9 -18
  145. data/app/views/alchemy/admin/elements/create.js.erb +1 -1
  146. data/app/views/alchemy/admin/elements/fold.js.erb +1 -1
  147. data/app/views/alchemy/admin/elements/index.html.erb +3 -3
  148. data/app/views/alchemy/admin/essence_files/assign.js.erb +1 -6
  149. data/app/views/alchemy/admin/essence_files/edit.html.erb +1 -1
  150. data/app/views/alchemy/admin/essence_pictures/assign.js.erb +1 -7
  151. data/app/views/alchemy/admin/essence_pictures/crop.html.erb +1 -1
  152. data/app/views/alchemy/admin/essence_pictures/edit.html.erb +7 -7
  153. data/app/views/alchemy/admin/essence_pictures/update.js.erb +1 -1
  154. data/app/views/alchemy/admin/languages/_form.html.erb +5 -5
  155. data/app/views/alchemy/admin/languages/_table.html.erb +3 -3
  156. data/app/views/alchemy/admin/languages/edit.html.erb +1 -0
  157. data/app/views/alchemy/admin/languages/index.html.erb +23 -4
  158. data/app/views/alchemy/admin/languages/new.html.erb +1 -0
  159. data/app/views/alchemy/admin/layoutpages/index.html.erb +6 -2
  160. data/app/views/alchemy/admin/nodes/_form.html.erb +23 -15
  161. data/app/views/alchemy/admin/nodes/_node.html.erb +5 -19
  162. data/app/views/alchemy/admin/nodes/index.html.erb +3 -18
  163. data/app/views/alchemy/admin/pages/_create_language_form.html.erb +0 -8
  164. data/app/views/alchemy/admin/pages/_form.html.erb +1 -2
  165. data/app/views/alchemy/admin/pages/_new_page_form.html.erb +1 -0
  166. data/app/views/alchemy/admin/pages/_page.html.erb +14 -25
  167. data/app/views/alchemy/admin/pages/_page_infos.html.erb +0 -4
  168. data/app/views/alchemy/admin/pages/_sitemap.html.erb +6 -0
  169. data/app/views/alchemy/admin/pages/edit.html.erb +1 -1
  170. data/app/views/alchemy/admin/pages/info.html.erb +0 -9
  171. data/app/views/alchemy/admin/pages/unlock.js.erb +13 -6
  172. data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +0 -2
  173. data/app/views/alchemy/admin/partials/_routes.html.erb +8 -0
  174. data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +1 -5
  175. data/app/views/alchemy/admin/pictures/_overlay_picture_list.html.erb +1 -1
  176. data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +1 -2
  177. data/app/views/alchemy/admin/pictures/index.html.erb +18 -3
  178. data/app/views/alchemy/admin/resources/_resource.html.erb +1 -1
  179. data/app/views/alchemy/admin/resources/_table.html.erb +2 -2
  180. data/app/views/alchemy/admin/sites/_form.html.erb +8 -0
  181. data/app/views/alchemy/admin/sites/edit.html.erb +1 -0
  182. data/app/views/alchemy/admin/sites/index.html.erb +21 -9
  183. data/app/views/alchemy/admin/sites/new.html.erb +1 -0
  184. data/app/views/alchemy/admin/tags/index.html.erb +2 -2
  185. data/app/views/alchemy/essences/_essence_boolean_editor.html.erb +10 -12
  186. data/app/views/alchemy/essences/_essence_date_editor.html.erb +11 -8
  187. data/app/views/alchemy/essences/_essence_file_editor.html.erb +16 -17
  188. data/app/views/alchemy/essences/_essence_html_editor.html.erb +8 -5
  189. data/app/views/alchemy/essences/_essence_link_editor.html.erb +18 -15
  190. data/app/views/alchemy/essences/_essence_node_editor.html.erb +27 -0
  191. data/app/views/alchemy/essences/_essence_node_view.html.erb +1 -0
  192. data/app/views/alchemy/essences/_essence_page_editor.html.erb +14 -11
  193. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +22 -20
  194. data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +10 -7
  195. data/app/views/alchemy/essences/_essence_select_editor.html.erb +12 -16
  196. data/app/views/alchemy/essences/_essence_text_editor.html.erb +18 -17
  197. data/app/views/alchemy/essences/shared/_essence_picture_tools.html.erb +6 -11
  198. data/app/views/alchemy/pages/show.rss.builder +3 -2
  199. data/app/views/layouts/alchemy/admin.html.erb +1 -0
  200. data/babel.config.js +12 -0
  201. data/bin/rails +5 -4
  202. data/config/alchemy/config.yml +23 -22
  203. data/config/brakeman.ignore +1 -1
  204. data/config/initializers/assets.rb +2 -1
  205. data/config/initializers/dragonfly.rb +2 -1
  206. data/config/initializers/mime_types.rb +1 -0
  207. data/config/initializers/mini_profiler.rb +3 -2
  208. data/config/initializers/simple_form.rb +6 -6
  209. data/config/locales/alchemy.en.yml +37 -14
  210. data/config/routes.rb +32 -28
  211. data/config/spring.rb +3 -2
  212. data/db/migrate/20200226213334_alchemy_four_point_four.rb +313 -0
  213. data/db/migrate/20200423073425_create_alchemy_essence_nodes.rb +11 -0
  214. data/db/migrate/20200504210159_remove_site_id_from_nodes.rb +28 -0
  215. data/db/migrate/20200505215518_add_language_id_foreign_key_to_alchemy_pages.rb +8 -0
  216. data/db/migrate/20200511113603_add_menu_type_to_alchemy_nodes.rb +27 -0
  217. data/db/migrate/20200514091507_make_page_layoutpage_null_false.rb +6 -0
  218. data/db/migrate/20200519073500_remove_visible_from_alchemy_pages.rb +24 -0
  219. data/lib/alchemy/admin/locale.rb +3 -1
  220. data/lib/alchemy/admin/preview_url.rb +85 -0
  221. data/lib/alchemy/auth_accessors.rb +8 -7
  222. data/lib/alchemy/cache_digests/template_tracker.rb +5 -4
  223. data/lib/alchemy/config.rb +26 -2
  224. data/lib/alchemy/configuration_methods.rb +3 -1
  225. data/lib/alchemy/controller_actions.rb +6 -5
  226. data/lib/alchemy/deprecation.rb +2 -1
  227. data/lib/alchemy/elements_finder.rb +5 -5
  228. data/lib/alchemy/engine.rb +23 -8
  229. data/lib/alchemy/errors.rb +0 -7
  230. data/lib/alchemy/essence.rb +17 -16
  231. data/lib/alchemy/filetypes.rb +5 -5
  232. data/lib/alchemy/forms/builder.rb +4 -4
  233. data/lib/alchemy/hints.rb +1 -1
  234. data/lib/alchemy/i18n.rb +2 -1
  235. data/lib/alchemy/modules.rb +12 -12
  236. data/lib/alchemy/name_conversions.rb +5 -5
  237. data/lib/alchemy/on_page_layout/callbacks_runner.rb +1 -0
  238. data/lib/alchemy/page_layout.rb +15 -12
  239. data/lib/alchemy/paths.rb +1 -1
  240. data/lib/alchemy/permissions.rb +7 -6
  241. data/lib/alchemy/resource.rb +23 -13
  242. data/lib/alchemy/resources_helper.rb +12 -18
  243. data/lib/alchemy/routing_constraints.rb +1 -1
  244. data/lib/alchemy/seeder.rb +42 -14
  245. data/lib/alchemy/shell.rb +13 -10
  246. data/lib/alchemy/taggable.rb +1 -0
  247. data/lib/alchemy/tasks/tidy.rb +4 -3
  248. data/lib/alchemy/test_support/config_stubbing.rb +1 -0
  249. data/lib/alchemy/test_support/essence_shared_examples.rb +72 -72
  250. data/lib/alchemy/test_support/factories.rb +1 -1
  251. data/lib/alchemy/test_support/factories/attachment_factory.rb +5 -5
  252. data/lib/alchemy/test_support/factories/content_factory.rb +6 -6
  253. data/lib/alchemy/test_support/factories/dummy_user_factory.rb +7 -7
  254. data/lib/alchemy/test_support/factories/element_factory.rb +9 -9
  255. data/lib/alchemy/test_support/factories/essence_file_factory.rb +3 -3
  256. data/lib/alchemy/test_support/factories/essence_page_factory.rb +3 -3
  257. data/lib/alchemy/test_support/factories/essence_picture_factory.rb +4 -4
  258. data/lib/alchemy/test_support/factories/essence_text_factory.rb +3 -3
  259. data/lib/alchemy/test_support/factories/language_factory.rb +21 -14
  260. data/lib/alchemy/test_support/factories/node_factory.rb +8 -8
  261. data/lib/alchemy/test_support/factories/page_factory.rb +15 -27
  262. data/lib/alchemy/test_support/factories/picture_factory.rb +5 -5
  263. data/lib/alchemy/test_support/factories/site_factory.rb +7 -6
  264. data/lib/alchemy/test_support/integration_helpers.rb +1 -0
  265. data/lib/alchemy/test_support/shared_contexts.rb +5 -4
  266. data/lib/alchemy/test_support/shared_uploader_examples.rb +4 -3
  267. data/lib/alchemy/tinymce.rb +15 -13
  268. data/lib/alchemy/upgrader.rb +8 -7
  269. data/lib/alchemy/upgrader/five_point_zero.rb +41 -0
  270. data/lib/alchemy/upgrader/tasks/element_views_updater.rb +4 -4
  271. data/lib/alchemy/upgrader/tasks/harden_gutentag_migrations.rb +29 -0
  272. data/lib/alchemy/version.rb +1 -1
  273. data/lib/alchemy_cms.rb +52 -50
  274. data/lib/{rails/generators → generators}/alchemy/base.rb +5 -4
  275. data/lib/{rails/generators → generators}/alchemy/elements/elements_generator.rb +13 -9
  276. data/lib/{rails/generators → generators}/alchemy/elements/templates/view.html.erb +0 -0
  277. data/lib/{rails/generators → generators}/alchemy/elements/templates/view.html.haml +0 -0
  278. data/lib/{rails/generators → generators}/alchemy/elements/templates/view.html.slim +0 -0
  279. data/lib/{rails/generators → generators}/alchemy/essence/essence_generator.rb +15 -13
  280. data/lib/generators/alchemy/essence/templates/editor.html.erb +17 -0
  281. data/lib/{rails/generators → generators}/alchemy/essence/templates/view.html.erb +0 -0
  282. data/lib/{rails/generators → generators}/alchemy/install/files/_article.html.erb +0 -0
  283. data/lib/{rails/generators → generators}/alchemy/install/files/_standard.html.erb +0 -0
  284. data/lib/{rails/generators → generators}/alchemy/install/files/alchemy.en.yml +0 -0
  285. data/lib/generators/alchemy/install/files/alchemy_admin.js +1 -0
  286. data/lib/{rails/generators → generators}/alchemy/install/files/all.css +0 -0
  287. data/lib/{rails/generators → generators}/alchemy/install/files/all.js +0 -0
  288. data/lib/{rails/generators → generators}/alchemy/install/files/application.html.erb +0 -0
  289. data/lib/{rails/generators → generators}/alchemy/install/files/article.scss +0 -0
  290. data/lib/generators/alchemy/install/install_generator.rb +110 -0
  291. data/lib/{rails/generators → generators}/alchemy/install/templates/dragonfly.rb.tt +0 -0
  292. data/lib/{rails/generators → generators}/alchemy/install/templates/elements.yml.tt +0 -0
  293. data/lib/generators/alchemy/install/templates/menus.yml.tt +8 -0
  294. data/lib/{rails/generators → generators}/alchemy/install/templates/page_layouts.yml.tt +0 -0
  295. data/lib/{rails/generators → generators}/alchemy/menus/menus_generator.rb +5 -5
  296. data/lib/{rails/generators → generators}/alchemy/menus/templates/node.html.erb +1 -4
  297. data/lib/{rails/generators → generators}/alchemy/menus/templates/node.html.haml +1 -4
  298. data/lib/{rails/generators → generators}/alchemy/menus/templates/node.html.slim +1 -4
  299. data/lib/{rails/generators → generators}/alchemy/menus/templates/wrapper.html.erb +1 -1
  300. data/lib/{rails/generators → generators}/alchemy/menus/templates/wrapper.html.haml +2 -2
  301. data/lib/{rails/generators → generators}/alchemy/menus/templates/wrapper.html.slim +2 -2
  302. data/lib/{rails/generators → generators}/alchemy/module/module_generator.rb +3 -2
  303. data/lib/{rails/generators → generators}/alchemy/module/templates/ability.rb.tt +0 -0
  304. data/lib/{rails/generators → generators}/alchemy/module/templates/controller.rb.tt +0 -0
  305. data/lib/{rails/generators → generators}/alchemy/module/templates/module_config.rb.tt +0 -0
  306. data/lib/{rails/generators → generators}/alchemy/page_layouts/page_layouts_generator.rb +5 -4
  307. data/lib/{rails/generators → generators}/alchemy/page_layouts/templates/layout.html.erb +0 -0
  308. data/lib/{rails/generators → generators}/alchemy/page_layouts/templates/layout.html.haml +0 -0
  309. data/lib/{rails/generators → generators}/alchemy/page_layouts/templates/layout.html.slim +0 -0
  310. data/lib/{rails/generators → generators}/alchemy/site_layouts/site_layouts_generator.rb +4 -2
  311. data/lib/{rails/generators → generators}/alchemy/site_layouts/templates/layout.html.erb +0 -0
  312. data/lib/{rails/generators → generators}/alchemy/site_layouts/templates/layout.html.haml +0 -0
  313. data/lib/{rails/generators → generators}/alchemy/site_layouts/templates/layout.html.slim +0 -0
  314. data/lib/{rails/generators → generators}/alchemy/views/views_generator.rb +7 -6
  315. data/lib/kaminari/scoped_pagination_url_helper.rb +1 -0
  316. data/lib/tasks/alchemy/db.rake +3 -19
  317. data/lib/tasks/alchemy/install.rake +3 -2
  318. data/lib/tasks/alchemy/tidy.rake +9 -8
  319. data/lib/tasks/alchemy/upgrade.rake +28 -105
  320. data/package.json +45 -0
  321. data/package/admin.js +14 -0
  322. data/package/src/__tests__/i18n.spec.js +70 -0
  323. data/package/src/i18n.js +48 -0
  324. data/package/src/node_tree.js +72 -0
  325. data/package/src/translations.js +32 -0
  326. data/package/src/utils/__tests__/ajax.spec.js +124 -0
  327. data/package/src/utils/__tests__/events.spec.js +38 -0
  328. data/package/src/utils/ajax.js +48 -0
  329. data/package/src/utils/events.js +16 -0
  330. data/vendor/assets/fonts/fa-regular-400.eot +0 -0
  331. data/vendor/assets/fonts/fa-regular-400.svg +798 -358
  332. data/vendor/assets/fonts/fa-regular-400.ttf +0 -0
  333. data/vendor/assets/fonts/fa-regular-400.woff +0 -0
  334. data/vendor/assets/fonts/fa-regular-400.woff2 +0 -0
  335. data/vendor/assets/fonts/fa-solid-900.eot +0 -0
  336. data/vendor/assets/fonts/fa-solid-900.svg +4933 -1408
  337. data/vendor/assets/fonts/fa-solid-900.ttf +0 -0
  338. data/vendor/assets/fonts/fa-solid-900.woff +0 -0
  339. data/vendor/assets/fonts/fa-solid-900.woff2 +0 -0
  340. data/vendor/assets/javascripts/jquery_plugins/jquery.ui.nestedSortable.js +1 -2
  341. data/vendor/assets/stylesheets/fontawesome/_core.scss +5 -0
  342. data/vendor/assets/stylesheets/fontawesome/_fixed-width.scss +1 -1
  343. data/vendor/assets/stylesheets/fontawesome/_icons.scss +651 -2
  344. data/vendor/assets/stylesheets/fontawesome/_mixins.scss +0 -1
  345. data/vendor/assets/stylesheets/fontawesome/_rotated-flipped.scss +3 -2
  346. data/vendor/assets/stylesheets/fontawesome/_stacked.scss +1 -1
  347. data/vendor/assets/stylesheets/fontawesome/_variables.scss +662 -9
  348. data/vendor/assets/stylesheets/fontawesome/fontawesome.scss +2 -2
  349. data/vendor/assets/stylesheets/fontawesome/regular.scss +23 -0
  350. data/vendor/assets/stylesheets/fontawesome/solid.scss +24 -0
  351. metadata +131 -83
  352. data/app/assets/javascripts/alchemy/alchemy.i18n.js.coffee +0 -32
  353. data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +0 -29
  354. data/app/helpers/alchemy/essences_helper.rb +0 -119
  355. data/app/models/concerns/alchemy/content_touching.rb +0 -23
  356. data/app/serializers/alchemy/legacy_element_serializer.rb +0 -15
  357. data/app/views/alchemy/admin/contents/_missing.html.erb +0 -17
  358. data/app/views/alchemy/admin/pages/_menu_fields.html.erb +0 -33
  359. data/app/views/alchemy/admin/pages/configure_external.html.erb +0 -32
  360. data/app/views/alchemy/elements/_editor_not_found.html.erb +0 -4
  361. data/app/views/alchemy/navigation/_image_link.html.erb +0 -14
  362. data/app/views/alchemy/navigation/_link.html.erb +0 -19
  363. data/app/views/alchemy/navigation/_renderer.html.erb +0 -29
  364. data/db/migrate/20180226123013_alchemy_four_point_zero.rb +0 -363
  365. data/db/migrate/20180227224537_migrate_tags_to_gutentag.rb +0 -41
  366. data/db/migrate/20180519204655_add_fixed_to_alchemy_elements.rb +0 -6
  367. data/db/migrate/20191016073858_create_alchemy_essence_pages.rb +0 -8
  368. data/db/migrate/20191029212236_create_alchemy_nodes.rb +0 -24
  369. data/db/migrate/20200226081535_add_site_id_to_alchemy_nodes.rb +0 -15
  370. data/lib/alchemy/ssl_protection.rb +0 -32
  371. data/lib/alchemy/tasks/helpers.rb +0 -81
  372. data/lib/alchemy/test_support/controller_requests.rb +0 -93
  373. data/lib/alchemy/upgrader/four_point_four.rb +0 -52
  374. data/lib/alchemy/upgrader/four_point_one.rb +0 -42
  375. data/lib/alchemy/upgrader/four_point_two.rb +0 -85
  376. data/lib/alchemy/upgrader/tasks/cells_migration.rb +0 -43
  377. data/lib/alchemy/upgrader/tasks/cells_upgrader.rb +0 -148
  378. data/lib/alchemy/upgrader/tasks/element_partial_name_variable_updater.rb +0 -28
  379. data/lib/alchemy/upgrader/tasks/harden_acts_as_taggable_on_migrations.rb +0 -27
  380. data/lib/alchemy/upgrader/tasks/picture_gallery_migration.rb +0 -65
  381. data/lib/alchemy/upgrader/tasks/picture_gallery_upgrader.rb +0 -210
  382. data/lib/rails/generators/alchemy/essence/templates/editor.html.erb +0 -15
  383. data/lib/rails/generators/alchemy/install/install_generator.rb +0 -60
  384. data/lib/tasks/alchemy/convert.rake +0 -95
  385. data/vendor/assets/stylesheets/fontawesome/fa-regular.scss +0 -22
  386. data/vendor/assets/stylesheets/fontawesome/fa-solid.scss +0 -23
@@ -7,24 +7,24 @@ module Alchemy
7
7
 
8
8
  # sends file inline. i.e. for viewing pdfs/movies in browser
9
9
  def show
10
- response.headers['Content-Length'] = @attachment.file.size.to_s
10
+ response.headers["Content-Length"] = @attachment.file.size.to_s
11
11
  send_file(
12
12
  @attachment.file.path,
13
13
  {
14
14
  filename: @attachment.file_name,
15
15
  type: @attachment.file_mime_type,
16
- disposition: 'inline'
17
- }
16
+ disposition: "inline",
17
+ },
18
18
  )
19
19
  end
20
20
 
21
21
  # sends file as attachment. aka download
22
22
  def download
23
- response.headers['Content-Length'] = @attachment.file.size.to_s
23
+ response.headers["Content-Length"] = @attachment.file.size.to_s
24
24
  send_file(
25
25
  @attachment.file.path, {
26
26
  filename: @attachment.file_name,
27
- type: @attachment.file_mime_type
27
+ type: @attachment.file_mime_type,
28
28
  }
29
29
  )
30
30
  end
@@ -8,14 +8,13 @@ module Alchemy
8
8
  include Alchemy::AbilityHelper
9
9
  include Alchemy::ControllerActions
10
10
  include Alchemy::Modules
11
- include Alchemy::SSLProtection
12
11
 
13
12
  protect_from_forgery
14
13
 
15
14
  before_action :mailer_set_url_options
16
15
  before_action :set_locale
17
16
 
18
- helper 'alchemy/admin/form'
17
+ helper "alchemy/admin/form"
19
18
 
20
19
  rescue_from CanCan::AccessDenied do |exception|
21
20
  permission_denied(exception)
@@ -26,7 +25,9 @@ module Alchemy
26
25
  # Sets +I18n.locale+ to current Alchemy language.
27
26
  #
28
27
  def set_locale
29
- ::I18n.locale = Language.current.locale
28
+ return unless Language.current
29
+
30
+ ::I18n.locale = Language.current&.locale
30
31
  end
31
32
 
32
33
  def not_found_error!(msg = "Not found \"#{request.fullpath}\"")
@@ -60,11 +61,11 @@ module Alchemy
60
61
  end
61
62
 
62
63
  def handle_redirect_for_user
63
- flash[:warning] = Alchemy.t('You are not authorized')
64
+ flash[:warning] = Alchemy.t("You are not authorized")
64
65
  if can?(:index, :alchemy_admin_dashboard)
65
66
  redirect_or_render_notice
66
67
  else
67
- redirect_to('/')
68
+ redirect_to("/")
68
69
  end
69
70
  end
70
71
 
@@ -75,8 +76,8 @@ module Alchemy
75
76
  render plain: flash.discard(:warning), status: 403
76
77
  end
77
78
  format.html do
78
- render partial: 'alchemy/admin/partials/flash',
79
- locals: {message: flash[:warning], flash_type: 'warning'}
79
+ render partial: "alchemy/admin/partials/flash",
80
+ locals: { message: flash[:warning], flash_type: "warning" }
80
81
  end
81
82
  end
82
83
  else
@@ -85,7 +86,7 @@ module Alchemy
85
86
  end
86
87
 
87
88
  def handle_redirect_for_guest
88
- flash[:info] = Alchemy.t('Please log in')
89
+ flash[:info] = Alchemy.t("Please log in")
89
90
  if request.xhr?
90
91
  render :permission_denied
91
92
  else
@@ -98,7 +99,7 @@ module Alchemy
98
99
  def exception_logger(error)
99
100
  Rails.logger.error("\n#{error.class} #{error.message} in #{error.backtrace.first}")
100
101
  Rails.logger.error(error.backtrace[1..50].each { |line|
101
- line.gsub(/#{Rails.root.to_s}/, '')
102
+ line.gsub(/#{Rails.root}/, "")
102
103
  }.join("\n"))
103
104
  end
104
105
  end
@@ -34,32 +34,23 @@ module Alchemy
34
34
  #
35
35
  # Disabling the page caching is strongly recommended!
36
36
  #
37
- # The editor view for your element should have this layout:
38
- #
39
- # <%= element_editor_for(element) do |el| %>
40
- # <%= el.edit :mail_from %>
41
- # <%= el.edit :mail_to %>
42
- # <%= el.edit :subject %>
43
- # <%= el.edit :success_page %>
44
- # <% end %>
45
- #
46
37
  # Please have a look at the +alchemy/config/config.yml+ file for further Message settings.
47
38
  #
48
39
  class MessagesController < Alchemy::BaseController
49
40
  before_action :get_page, except: :create
50
41
 
51
- helper 'alchemy/pages'
42
+ helper "alchemy/pages"
52
43
 
53
44
  def index #:nodoc:
54
45
  redirect_to show_page_path(
55
46
  urlname: @page.urlname,
56
- locale: prefix_locale? ? @page.language_code : nil
47
+ locale: prefix_locale? ? @page.language_code : nil,
57
48
  )
58
49
  end
59
50
 
60
51
  def new #:nodoc:
61
52
  @message = Message.new
62
- render template: 'alchemy/pages/show'
53
+ render template: "alchemy/pages/show"
63
54
  end
64
55
 
65
56
  def create #:nodoc:
@@ -69,13 +60,14 @@ module Alchemy
69
60
  if @element.nil?
70
61
  raise ActiveRecord::RecordNotFound, "Contact form id not found. Please pass the :contact_form_id in a hidden field. Example: <%= f.hidden_field :contact_form_id, value: element.id %>"
71
62
  end
63
+
72
64
  @page = @element.page
73
65
  @root_page = @page.get_language_root
74
66
  if @message.valid?
75
67
  MessagesMailer.contact_form_mail(@message, mail_to, mail_from, subject).deliver
76
68
  redirect_to_success_page
77
69
  else
78
- render template: 'alchemy/pages/show'
70
+ render template: "alchemy/pages/show"
79
71
  end
80
72
  end
81
73
 
@@ -86,29 +78,29 @@ module Alchemy
86
78
  end
87
79
 
88
80
  def mail_to
89
- @element.ingredient(:mail_to) || mailer_config['mail_to']
81
+ @element.ingredient(:mail_to) || mailer_config["mail_to"]
90
82
  end
91
83
 
92
84
  def mail_from
93
- @element.ingredient(:mail_from) || mailer_config['mail_from']
85
+ @element.ingredient(:mail_from) || mailer_config["mail_from"]
94
86
  end
95
87
 
96
88
  def subject
97
- @element.ingredient(:subject) || mailer_config['subject']
89
+ @element.ingredient(:subject) || mailer_config["subject"]
98
90
  end
99
91
 
100
92
  def redirect_to_success_page
101
- flash[:notice] = Alchemy.t(:success, scope: 'contactform.messages')
93
+ flash[:notice] = Alchemy.t(:success, scope: "contactform.messages")
102
94
  if success_page
103
95
  urlname = success_page_urlname
104
- elsif mailer_config['forward_to_page'] && mailer_config['mail_success_page']
105
- urlname = Page.find_by(urlname: mailer_config['mail_success_page']).urlname
96
+ elsif mailer_config["forward_to_page"] && mailer_config["mail_success_page"]
97
+ urlname = Page.find_by(urlname: mailer_config["mail_success_page"]).urlname
106
98
  else
107
99
  urlname = Language.current_root_page.urlname
108
100
  end
109
101
  redirect_to show_page_path(
110
102
  urlname: urlname,
111
- locale: prefix_locale? ? Language.current.code : nil
103
+ locale: prefix_locale? ? Language.current.code : nil,
112
104
  )
113
105
  end
114
106
 
@@ -126,15 +118,16 @@ module Alchemy
126
118
  end
127
119
 
128
120
  def get_page
129
- @page = Language.current.pages.find_by(page_layout: mailer_config['page_layout_name'])
121
+ @page = Language.current.pages.find_by(page_layout: mailer_config["page_layout_name"])
130
122
  if @page.blank?
131
- raise "Page for page_layout #{mailer_config['page_layout_name']} not found"
123
+ raise "Page for page_layout #{mailer_config["page_layout_name"]} not found"
132
124
  end
125
+
133
126
  @root_page = @page.get_language_root
134
127
  end
135
128
 
136
129
  def message_params
137
- params.require(:message).permit(*mailer_config['fields'])
130
+ params.require(:message).permit(*mailer_config["fields"])
138
131
  end
139
132
  end
140
133
  end
@@ -3,10 +3,10 @@
3
3
  module Alchemy
4
4
  class PagesController < Alchemy::BaseController
5
5
  SHOW_PAGE_PARAMS_KEYS = [
6
- 'action',
7
- 'controller',
8
- 'urlname',
9
- 'locale'
6
+ "action",
7
+ "controller",
8
+ "urlname",
9
+ "locale",
10
10
  ]
11
11
 
12
12
  include OnPageLayout::CallbacksRunner
@@ -78,7 +78,7 @@ module Alchemy
78
78
  def sitemap
79
79
  @pages = Page.sitemap
80
80
  respond_to do |format|
81
- format.xml { render layout: 'alchemy/sitemap' }
81
+ format.xml { render layout: "alchemy/sitemap" }
82
82
  end
83
83
  end
84
84
 
@@ -95,7 +95,7 @@ module Alchemy
95
95
  #
96
96
  def load_index_page
97
97
  @page ||= Language.current_root_page
98
- render template: 'alchemy/welcome', layout: false if signup_required?
98
+ render template: "alchemy/welcome", layout: false if signup_required?
99
99
  end
100
100
 
101
101
  # == Loads page by urlname
@@ -108,9 +108,11 @@ module Alchemy
108
108
  # @return NilClass
109
109
  #
110
110
  def load_page
111
+ page_not_found! unless Language.current
112
+
111
113
  @page ||= Language.current.pages.contentpages.find_by(
112
114
  urlname: params[:urlname],
113
- language_code: params[:locale] || Language.current.code
115
+ language_code: params[:locale] || Language.current.code,
114
116
  )
115
117
  end
116
118
 
@@ -148,7 +150,7 @@ module Alchemy
148
150
  if @page.contains_feed?
149
151
  render action: :show, layout: false, handlers: [:builder]
150
152
  else
151
- render xml: {error: 'Not found'}, status: 404
153
+ render xml: { error: "Not found" }, status: 404
152
154
  end
153
155
  end
154
156
  end
@@ -191,9 +193,9 @@ module Alchemy
191
193
  #
192
194
  def render_fresh_page?
193
195
  must_not_cache? || stale?(etag: page_etag,
194
- last_modified: @page.published_at,
195
- public: !@page.restricted,
196
- template: 'pages/show')
196
+ last_modified: @page.published_at,
197
+ public: !@page.restricted,
198
+ template: "pages/show")
197
199
  end
198
200
 
199
201
  # don't cache pages if we have flash message to display or the page has caching disabled
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Alchemy
2
3
  module Admin
3
4
  module ArchiveOverlay
@@ -11,8 +12,8 @@ module Alchemy
11
12
  @content = Content.find_by(id: params[:content_id])
12
13
 
13
14
  respond_to do |format|
14
- format.html { render partial: 'archive_overlay' }
15
- format.js { render action: 'archive_overlay' }
15
+ format.html { render partial: "archive_overlay" }
16
+ format.js { render action: "archive_overlay" }
16
17
  end
17
18
  end
18
19
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Alchemy
4
+ module Admin
5
+ module CurrentLanguage
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ before_action :load_current_language
10
+ end
11
+
12
+ private
13
+
14
+ def load_current_language
15
+ @current_language = Alchemy::Language.current
16
+ if @current_language.nil?
17
+ flash[:warning] = Alchemy.t("Please create a language first.")
18
+ redirect_to admin_languages_path
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -8,12 +8,12 @@ module Alchemy
8
8
  def successful_uploader_response(file:, status: :created)
9
9
  message = Alchemy.t(:upload_success,
10
10
  scope: [:uploader, file.class.model_name.i18n_key],
11
- name: file.name
11
+ name: file.name,
12
12
  )
13
13
 
14
14
  {
15
15
  json: uploader_response(file: file, message: message),
16
- status: status
16
+ status: status,
17
17
  }
18
18
  end
19
19
 
@@ -21,12 +21,12 @@ module Alchemy
21
21
  message = Alchemy.t(:upload_failure,
22
22
  scope: [:uploader, file.class.model_name.i18n_key],
23
23
  error: file.errors[:file].join,
24
- name: file.name
24
+ name: file.name,
25
25
  )
26
26
 
27
27
  {
28
28
  json: uploader_response(file: file, message: message),
29
- status: :unprocessable_entity
29
+ status: :unprocessable_entity,
30
30
  }
31
31
  end
32
32
 
@@ -35,7 +35,7 @@ module Alchemy
35
35
  def uploader_response(file:, message:)
36
36
  {
37
37
  files: [file.to_jq_upload],
38
- growl_message: message
38
+ growl_message: message,
39
39
  }
40
40
  end
41
41
  end
@@ -36,18 +36,18 @@ module Alchemy
36
36
 
37
37
  alchemy.show_page_path(
38
38
  locale: prefix_locale? ? page.language_code : nil,
39
- urlname: page.urlname
39
+ urlname: page.urlname,
40
40
  )
41
41
  end
42
42
 
43
43
  def legacy_urls
44
44
  # /slug/tree => slug/tree
45
- urlname = (request.fullpath[1..-1] if request.fullpath[0] == '/') || request.fullpath
45
+ urlname = (request.fullpath[1..-1] if request.fullpath[0] == "/") || request.fullpath
46
46
  LegacyPageUrl.joins(:page).where(
47
47
  urlname: urlname,
48
48
  Page.table_name => {
49
- language_id: Language.current.id
50
- }
49
+ language_id: Language.current.id,
50
+ },
51
51
  )
52
52
  end
53
53
 
@@ -27,8 +27,7 @@ module Alchemy
27
27
  # @return NilClass
28
28
  #
29
29
  def redirect_url
30
- @_redirect_url ||= public_child_redirect_url || controller_and_action_url ||
31
- locale_prefixed_url || nil
30
+ @_redirect_url ||= public_child_redirect_url || locale_prefixed_url || nil
32
31
  end
33
32
 
34
33
  def locale_prefixed_url
@@ -48,17 +47,11 @@ module Alchemy
48
47
  end
49
48
  end
50
49
 
51
- def controller_and_action_url
52
- return unless @page.definition['controller']
53
-
54
- main_app.url_for(@page.controller_and_action)
55
- end
56
-
57
50
  # Page url with or without locale while keeping all additional params
58
51
  def page_redirect_url(options = {})
59
52
  options = {
60
53
  locale: prefix_locale? ? @page.language_code : nil,
61
- urlname: @page.urlname
54
+ urlname: @page.urlname,
62
55
  }.merge(options)
63
56
 
64
57
  alchemy.show_page_path additional_params.merge(options)
@@ -16,8 +16,8 @@ module Alchemy
16
16
  end
17
17
 
18
18
  def needs_redirect_to_primary_host?
19
- current_alchemy_site.redirect_to_primary_host? &&
20
- current_alchemy_site.host != '*' &&
19
+ current_alchemy_site&.redirect_to_primary_host? &&
20
+ current_alchemy_site.host != "*" &&
21
21
  current_alchemy_site.host != request.host
22
22
  end
23
23
  end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Alchemy
4
+ class ContentEditor < SimpleDelegator
5
+ alias_method :content, :__getobj__
6
+
7
+ def to_partial_path
8
+ "alchemy/essences/#{essence_partial_name}_editor"
9
+ end
10
+
11
+ def css_classes
12
+ [
13
+ "content_editor",
14
+ essence_partial_name,
15
+ ].compact
16
+ end
17
+
18
+ def data_attributes
19
+ {
20
+ content_id: id,
21
+ content_name: name,
22
+ }
23
+ end
24
+
25
+ # Returns a string to be passed to Rails form field tags to ensure we have same params layout everywhere.
26
+ #
27
+ # === Example:
28
+ #
29
+ # <%= text_field_tag content_editor.form_field_name, content_editor.ingredient %>
30
+ #
31
+ # === Options:
32
+ #
33
+ # You can pass an Essence column_name. Default is 'ingredient'
34
+ #
35
+ # ==== Example:
36
+ #
37
+ # <%= text_field_tag content_editor.form_field_name(:link), content_editor.ingredient %>
38
+ #
39
+ def form_field_name(essence_column = "ingredient")
40
+ "contents[#{id}][#{essence_column}]"
41
+ end
42
+
43
+ def form_field_id(essence_column = "ingredient")
44
+ "contents_#{id}_#{essence_column}"
45
+ end
46
+
47
+ # Fixes Rails partial renderer calling to_model on the object
48
+ # which reveals the delegated content instead of this decorator.
49
+ def respond_to?(method_name)
50
+ return false if method_name == :to_model
51
+
52
+ super
53
+ end
54
+ end
55
+ end