alchemy_cms 4.6.1 → 5.0.0

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 +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 +30 -9
  8. data/CHANGELOG.md +102 -1
  9. data/Gemfile +24 -22
  10. data/README.md +32 -20
  11. data/Rakefile +11 -8
  12. data/alchemy_cms.gemspec +6 -5
  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/navigation.scss +1 -0
  25. data/app/assets/stylesheets/alchemy/node-select.scss +43 -0
  26. data/app/assets/stylesheets/alchemy/nodes.scss +1 -1
  27. data/app/assets/stylesheets/alchemy/sitemap.scss +5 -1
  28. data/app/assets/stylesheets/alchemy/tables.scss +1 -24
  29. data/app/assets/stylesheets/alchemy/tags.scss +2 -2
  30. data/app/controllers/alchemy/admin/attachments_controller.rb +8 -7
  31. data/app/controllers/alchemy/admin/base_controller.rb +13 -33
  32. data/app/controllers/alchemy/admin/clipboard_controller.rb +5 -4
  33. data/app/controllers/alchemy/admin/contents_controller.rb +1 -2
  34. data/app/controllers/alchemy/admin/dashboard_controller.rb +10 -9
  35. data/app/controllers/alchemy/admin/elements_controller.rb +20 -20
  36. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +12 -14
  37. data/app/controllers/alchemy/admin/languages_controller.rb +35 -2
  38. data/app/controllers/alchemy/admin/layoutpages_controller.rb +5 -2
  39. data/app/controllers/alchemy/admin/nodes_controller.rb +5 -4
  40. data/app/controllers/alchemy/admin/pages_controller.rb +51 -63
  41. data/app/controllers/alchemy/admin/pictures_controller.rb +16 -16
  42. data/app/controllers/alchemy/admin/resources_controller.rb +21 -13
  43. data/app/controllers/alchemy/admin/sites_controller.rb +18 -0
  44. data/app/controllers/alchemy/admin/styleguide_controller.rb +1 -0
  45. data/app/controllers/alchemy/admin/tags_controller.rb +5 -3
  46. data/app/controllers/alchemy/admin/trash_controller.rb +6 -6
  47. data/app/controllers/alchemy/api/base_controller.rb +2 -2
  48. data/app/controllers/alchemy/api/contents_controller.rb +4 -4
  49. data/app/controllers/alchemy/api/elements_controller.rb +8 -8
  50. data/app/controllers/alchemy/api/nodes_controller.rb +37 -1
  51. data/app/controllers/alchemy/api/pages_controller.rb +14 -23
  52. data/app/controllers/alchemy/attachments_controller.rb +5 -5
  53. data/app/controllers/alchemy/base_controller.rb +10 -9
  54. data/app/controllers/alchemy/messages_controller.rb +16 -23
  55. data/app/controllers/alchemy/pages_controller.rb +13 -11
  56. data/app/controllers/concerns/alchemy/admin/archive_overlay.rb +3 -2
  57. data/app/controllers/concerns/alchemy/admin/current_language.rb +23 -0
  58. data/app/controllers/concerns/alchemy/admin/uploader_responses.rb +5 -5
  59. data/app/controllers/concerns/alchemy/legacy_page_redirects.rb +4 -4
  60. data/app/controllers/concerns/alchemy/page_redirects.rb +2 -9
  61. data/app/controllers/concerns/alchemy/site_redirects.rb +2 -2
  62. data/app/decorators/alchemy/element_editor.rb +39 -0
  63. data/app/helpers/alchemy/admin/attachments_helper.rb +6 -6
  64. data/app/helpers/alchemy/admin/base_helper.rb +38 -35
  65. data/app/helpers/alchemy/admin/contents_helper.rb +3 -3
  66. data/app/helpers/alchemy/admin/elements_helper.rb +3 -88
  67. data/app/helpers/alchemy/admin/essences_helper.rb +8 -117
  68. data/app/helpers/alchemy/admin/form_helper.rb +1 -1
  69. data/app/helpers/alchemy/admin/navigation_helper.rb +24 -23
  70. data/app/helpers/alchemy/admin/pages_helper.rb +4 -4
  71. data/app/helpers/alchemy/admin/pictures_helper.rb +4 -6
  72. data/app/helpers/alchemy/admin/tags_helper.rb +8 -7
  73. data/app/helpers/alchemy/base_helper.rb +13 -8
  74. data/app/helpers/alchemy/elements_block_helper.rb +2 -31
  75. data/app/helpers/alchemy/elements_helper.rb +12 -58
  76. data/app/helpers/alchemy/pages_helper.rb +24 -174
  77. data/app/helpers/alchemy/url_helper.rb +4 -3
  78. data/app/mailers/alchemy/base_mailer.rb +1 -1
  79. data/app/mailers/alchemy/messages_mailer.rb +1 -1
  80. data/app/models/alchemy/attachment.rb +24 -19
  81. data/app/models/alchemy/base_record.rb +2 -5
  82. data/app/models/alchemy/content.rb +33 -38
  83. data/app/models/alchemy/content/factory.rb +24 -31
  84. data/app/models/alchemy/element.rb +45 -53
  85. data/app/models/alchemy/element/definitions.rb +4 -4
  86. data/app/models/alchemy/element/element_contents.rb +9 -6
  87. data/app/models/alchemy/element/element_essences.rb +4 -3
  88. data/app/models/alchemy/element/presenters.rb +3 -2
  89. data/app/models/alchemy/element_to_page.rb +1 -1
  90. data/app/models/alchemy/essence_boolean.rb +1 -3
  91. data/app/models/alchemy/essence_date.rb +2 -3
  92. data/app/models/alchemy/essence_file.rb +5 -5
  93. data/app/models/alchemy/essence_html.rb +1 -3
  94. data/app/models/alchemy/essence_link.rb +1 -3
  95. data/app/models/alchemy/essence_node.rb +18 -0
  96. data/app/models/alchemy/essence_page.rb +3 -16
  97. data/app/models/alchemy/essence_picture.rb +18 -17
  98. data/app/models/alchemy/essence_picture_view.rb +7 -6
  99. data/app/models/alchemy/essence_richtext.rb +1 -3
  100. data/app/models/alchemy/essence_select.rb +1 -3
  101. data/app/models/alchemy/essence_text.rb +0 -2
  102. data/app/models/alchemy/folded_page.rb +1 -0
  103. data/app/models/alchemy/language.rb +21 -35
  104. data/app/models/alchemy/language/code.rb +4 -4
  105. data/app/models/alchemy/legacy_page_url.rb +1 -1
  106. data/app/models/alchemy/message.rb +3 -3
  107. data/app/models/alchemy/node.rb +27 -4
  108. data/app/models/alchemy/page.rb +46 -127
  109. data/app/models/alchemy/page/fixed_attributes.rb +3 -2
  110. data/app/models/alchemy/page/page_elements.rb +35 -44
  111. data/app/models/alchemy/page/page_naming.rb +20 -70
  112. data/app/models/alchemy/page/page_natures.rb +7 -34
  113. data/app/models/alchemy/page/page_scopes.rb +23 -29
  114. data/app/models/alchemy/page/url_path.rb +0 -2
  115. data/app/models/alchemy/picture.rb +40 -30
  116. data/app/models/alchemy/picture/preprocessor.rb +26 -0
  117. data/app/models/alchemy/picture/transformations.rb +9 -7
  118. data/app/models/alchemy/picture/url.rb +9 -7
  119. data/app/models/alchemy/site.rb +6 -36
  120. data/app/models/alchemy/site/layout.rb +2 -2
  121. data/app/models/concerns/alchemy/touch_elements.rb +24 -0
  122. data/app/serializers/alchemy/content_serializer.rb +0 -3
  123. data/app/serializers/alchemy/essence_boolean_serializer.rb +3 -3
  124. data/app/serializers/alchemy/essence_date_serializer.rb +3 -3
  125. data/app/serializers/alchemy/essence_file_serializer.rb +4 -2
  126. data/app/serializers/alchemy/essence_html_serializer.rb +3 -3
  127. data/app/serializers/alchemy/essence_link_serializer.rb +3 -3
  128. data/app/serializers/alchemy/essence_picture_serializer.rb +5 -4
  129. data/app/serializers/alchemy/essence_richtext_serializer.rb +3 -3
  130. data/app/serializers/alchemy/essence_select_serializer.rb +3 -3
  131. data/app/serializers/alchemy/essence_text_serializer.rb +5 -4
  132. data/app/serializers/alchemy/node_serializer.rb +2 -0
  133. data/app/serializers/alchemy/page_tree_serializer.rb +9 -13
  134. data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +1 -2
  135. data/app/views/alchemy/admin/attachments/_file_to_assign.html.erb +1 -2
  136. data/app/views/alchemy/admin/attachments/_files_list.html.erb +4 -4
  137. data/app/views/alchemy/admin/contents/create.js.erb +1 -3
  138. data/app/views/alchemy/admin/elements/_element.html.erb +9 -18
  139. data/app/views/alchemy/admin/elements/create.js.erb +1 -1
  140. data/app/views/alchemy/admin/elements/fold.js.erb +1 -1
  141. data/app/views/alchemy/admin/elements/index.html.erb +3 -3
  142. data/app/views/alchemy/admin/essence_files/assign.js.erb +1 -6
  143. data/app/views/alchemy/admin/essence_files/edit.html.erb +1 -1
  144. data/app/views/alchemy/admin/essence_pictures/assign.js.erb +1 -7
  145. data/app/views/alchemy/admin/essence_pictures/crop.html.erb +1 -1
  146. data/app/views/alchemy/admin/essence_pictures/edit.html.erb +7 -7
  147. data/app/views/alchemy/admin/essence_pictures/update.js.erb +1 -1
  148. data/app/views/alchemy/admin/languages/_form.html.erb +5 -5
  149. data/app/views/alchemy/admin/languages/_table.html.erb +3 -3
  150. data/app/views/alchemy/admin/languages/edit.html.erb +1 -0
  151. data/app/views/alchemy/admin/languages/index.html.erb +23 -4
  152. data/app/views/alchemy/admin/languages/new.html.erb +1 -0
  153. data/app/views/alchemy/admin/layoutpages/index.html.erb +3 -3
  154. data/app/views/alchemy/admin/nodes/_form.html.erb +18 -15
  155. data/app/views/alchemy/admin/nodes/_node.html.erb +1 -5
  156. data/app/views/alchemy/admin/nodes/index.html.erb +3 -4
  157. data/app/views/alchemy/admin/pages/_create_language_form.html.erb +0 -8
  158. data/app/views/alchemy/admin/pages/_form.html.erb +0 -1
  159. data/app/views/alchemy/admin/pages/_new_page_form.html.erb +1 -0
  160. data/app/views/alchemy/admin/pages/_page.html.erb +11 -19
  161. data/app/views/alchemy/admin/pages/_page_infos.html.erb +0 -4
  162. data/app/views/alchemy/admin/pages/edit.html.erb +1 -1
  163. data/app/views/alchemy/admin/pages/info.html.erb +0 -9
  164. data/app/views/alchemy/admin/pages/unlock.js.erb +13 -6
  165. data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +0 -2
  166. data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +1 -5
  167. data/app/views/alchemy/admin/pictures/_overlay_picture_list.html.erb +1 -1
  168. data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +1 -2
  169. data/app/views/alchemy/admin/pictures/index.html.erb +18 -3
  170. data/app/views/alchemy/admin/pictures/show.html.erb +1 -1
  171. data/app/views/alchemy/admin/resources/_resource.html.erb +1 -1
  172. data/app/views/alchemy/admin/resources/_table.html.erb +2 -2
  173. data/app/views/alchemy/admin/resources/index.html.erb +21 -22
  174. data/app/views/alchemy/admin/sites/_form.html.erb +8 -0
  175. data/app/views/alchemy/admin/sites/edit.html.erb +1 -0
  176. data/app/views/alchemy/admin/sites/index.html.erb +21 -9
  177. data/app/views/alchemy/admin/sites/new.html.erb +1 -0
  178. data/app/views/alchemy/admin/tags/index.html.erb +2 -2
  179. data/app/views/alchemy/essences/_essence_boolean_editor.html.erb +10 -12
  180. data/app/views/alchemy/essences/_essence_date_editor.html.erb +11 -8
  181. data/app/views/alchemy/essences/_essence_file_editor.html.erb +16 -17
  182. data/app/views/alchemy/essences/_essence_file_view.html.erb +1 -1
  183. data/app/views/alchemy/essences/_essence_html_editor.html.erb +8 -5
  184. data/app/views/alchemy/essences/_essence_link_editor.html.erb +18 -15
  185. data/app/views/alchemy/essences/_essence_node_editor.html.erb +27 -0
  186. data/app/views/alchemy/essences/_essence_node_view.html.erb +1 -0
  187. data/app/views/alchemy/essences/_essence_page_editor.html.erb +14 -11
  188. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +22 -20
  189. data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +10 -7
  190. data/app/views/alchemy/essences/_essence_select_editor.html.erb +12 -16
  191. data/app/views/alchemy/essences/_essence_text_editor.html.erb +18 -17
  192. data/app/views/alchemy/essences/shared/_essence_picture_tools.html.erb +6 -11
  193. data/app/views/alchemy/pages/show.rss.builder +3 -2
  194. data/app/views/layouts/alchemy/admin.html.erb +1 -0
  195. data/babel.config.js +12 -0
  196. data/bin/rails +5 -4
  197. data/config/alchemy/config.yml +23 -16
  198. data/config/brakeman.ignore +1 -1
  199. data/config/initializers/assets.rb +2 -1
  200. data/config/initializers/dragonfly.rb +2 -1
  201. data/config/initializers/mime_types.rb +1 -0
  202. data/config/initializers/mini_profiler.rb +3 -2
  203. data/config/initializers/simple_form.rb +6 -6
  204. data/config/locales/alchemy.en.yml +23 -8
  205. data/config/routes.rb +25 -24
  206. data/config/spring.rb +3 -2
  207. data/db/migrate/20200226213334_alchemy_four_point_four.rb +313 -0
  208. data/db/migrate/20200423073425_create_alchemy_essence_nodes.rb +11 -0
  209. data/db/migrate/20200504210159_remove_site_id_from_nodes.rb +28 -0
  210. data/db/migrate/20200505215518_add_language_id_foreign_key_to_alchemy_pages.rb +8 -0
  211. data/db/migrate/20200511113603_add_menu_type_to_alchemy_nodes.rb +27 -0
  212. data/db/migrate/20200514091507_make_page_layoutpage_null_false.rb +6 -0
  213. data/db/migrate/20200519073500_remove_visible_from_alchemy_pages.rb +24 -0
  214. data/lib/alchemy/admin/locale.rb +3 -1
  215. data/lib/alchemy/admin/preview_url.rb +85 -0
  216. data/lib/alchemy/auth_accessors.rb +8 -7
  217. data/lib/alchemy/cache_digests/template_tracker.rb +5 -4
  218. data/lib/alchemy/config.rb +3 -5
  219. data/lib/alchemy/configuration_methods.rb +3 -1
  220. data/lib/alchemy/controller_actions.rb +6 -5
  221. data/lib/alchemy/deprecation.rb +2 -1
  222. data/lib/alchemy/elements_finder.rb +5 -5
  223. data/lib/alchemy/engine.rb +23 -8
  224. data/lib/alchemy/errors.rb +0 -7
  225. data/lib/alchemy/essence.rb +17 -16
  226. data/lib/alchemy/filetypes.rb +5 -5
  227. data/lib/alchemy/forms/builder.rb +4 -4
  228. data/lib/alchemy/hints.rb +1 -1
  229. data/lib/alchemy/i18n.rb +2 -1
  230. data/lib/alchemy/install/tasks.rb +41 -0
  231. data/lib/alchemy/modules.rb +12 -12
  232. data/lib/alchemy/name_conversions.rb +5 -5
  233. data/lib/alchemy/on_page_layout/callbacks_runner.rb +1 -0
  234. data/lib/alchemy/page_layout.rb +15 -12
  235. data/lib/alchemy/paths.rb +1 -1
  236. data/lib/alchemy/permissions.rb +7 -6
  237. data/lib/alchemy/resource.rb +25 -15
  238. data/lib/alchemy/resources_helper.rb +12 -18
  239. data/lib/alchemy/routing_constraints.rb +1 -1
  240. data/lib/alchemy/seeder.rb +42 -14
  241. data/lib/alchemy/shell.rb +13 -10
  242. data/lib/alchemy/taggable.rb +1 -0
  243. data/lib/alchemy/tasks/tidy.rb +4 -3
  244. data/lib/alchemy/test_support/config_stubbing.rb +1 -0
  245. data/lib/alchemy/test_support/essence_shared_examples.rb +72 -72
  246. data/lib/alchemy/test_support/factories.rb +1 -1
  247. data/lib/alchemy/test_support/factories/attachment_factory.rb +5 -5
  248. data/lib/alchemy/test_support/factories/content_factory.rb +6 -6
  249. data/lib/alchemy/test_support/factories/dummy_user_factory.rb +7 -7
  250. data/lib/alchemy/test_support/factories/element_factory.rb +9 -9
  251. data/lib/alchemy/test_support/factories/essence_file_factory.rb +3 -3
  252. data/lib/alchemy/test_support/factories/essence_page_factory.rb +3 -3
  253. data/lib/alchemy/test_support/factories/essence_picture_factory.rb +4 -4
  254. data/lib/alchemy/test_support/factories/essence_text_factory.rb +3 -3
  255. data/lib/alchemy/test_support/factories/language_factory.rb +21 -14
  256. data/lib/alchemy/test_support/factories/node_factory.rb +8 -8
  257. data/lib/alchemy/test_support/factories/page_factory.rb +15 -27
  258. data/lib/alchemy/test_support/factories/picture_factory.rb +5 -5
  259. data/lib/alchemy/test_support/factories/site_factory.rb +7 -6
  260. data/lib/alchemy/test_support/integration_helpers.rb +1 -0
  261. data/lib/alchemy/test_support/shared_contexts.rb +5 -4
  262. data/lib/alchemy/test_support/shared_uploader_examples.rb +4 -3
  263. data/lib/alchemy/tinymce.rb +15 -13
  264. data/lib/alchemy/upgrader.rb +8 -7
  265. data/lib/alchemy/upgrader/five_point_zero.rb +41 -0
  266. data/lib/alchemy/upgrader/tasks/element_views_updater.rb +4 -4
  267. data/lib/alchemy/upgrader/tasks/harden_gutentag_migrations.rb +29 -0
  268. data/lib/alchemy/version.rb +1 -1
  269. data/lib/alchemy_cms.rb +52 -50
  270. data/lib/{rails/generators → generators}/alchemy/base.rb +5 -4
  271. data/lib/{rails/generators → generators}/alchemy/elements/elements_generator.rb +13 -9
  272. data/lib/{rails/generators → generators}/alchemy/elements/templates/view.html.erb +0 -0
  273. data/lib/{rails/generators → generators}/alchemy/elements/templates/view.html.haml +0 -0
  274. data/lib/{rails/generators → generators}/alchemy/elements/templates/view.html.slim +0 -0
  275. data/lib/{rails/generators → generators}/alchemy/essence/essence_generator.rb +15 -13
  276. data/lib/generators/alchemy/essence/templates/editor.html.erb +17 -0
  277. data/lib/{rails/generators → generators}/alchemy/essence/templates/view.html.erb +0 -0
  278. data/lib/{rails/generators → generators}/alchemy/install/files/_article.html.erb +0 -0
  279. data/lib/{rails/generators → generators}/alchemy/install/files/_standard.html.erb +0 -0
  280. data/lib/{rails/generators → generators}/alchemy/install/files/alchemy.en.yml +0 -0
  281. data/lib/generators/alchemy/install/files/alchemy_admin.js +1 -0
  282. data/lib/{rails/generators → generators}/alchemy/install/files/all.css +0 -0
  283. data/lib/{rails/generators → generators}/alchemy/install/files/all.js +0 -0
  284. data/lib/{rails/generators → generators}/alchemy/install/files/application.html.erb +0 -0
  285. data/lib/{rails/generators → generators}/alchemy/install/files/article.scss +0 -0
  286. data/lib/generators/alchemy/install/install_generator.rb +169 -0
  287. data/lib/{rails/generators → generators}/alchemy/install/templates/dragonfly.rb.tt +0 -0
  288. data/lib/{rails/generators → generators}/alchemy/install/templates/elements.yml.tt +0 -0
  289. data/lib/{rails/generators → generators}/alchemy/install/templates/menus.yml.tt +0 -0
  290. data/lib/{rails/generators → generators}/alchemy/install/templates/page_layouts.yml.tt +0 -0
  291. data/lib/{rails/generators → generators}/alchemy/menus/menus_generator.rb +2 -2
  292. data/lib/{rails/generators → generators}/alchemy/menus/templates/node.html.erb +1 -4
  293. data/lib/{rails/generators → generators}/alchemy/menus/templates/node.html.haml +1 -4
  294. data/lib/{rails/generators → generators}/alchemy/menus/templates/node.html.slim +1 -4
  295. data/lib/{rails/generators → generators}/alchemy/menus/templates/wrapper.html.erb +1 -1
  296. data/lib/{rails/generators → generators}/alchemy/menus/templates/wrapper.html.haml +1 -1
  297. data/lib/{rails/generators → generators}/alchemy/menus/templates/wrapper.html.slim +1 -1
  298. data/lib/{rails/generators → generators}/alchemy/module/module_generator.rb +3 -2
  299. data/lib/{rails/generators → generators}/alchemy/module/templates/ability.rb.tt +0 -0
  300. data/lib/{rails/generators → generators}/alchemy/module/templates/controller.rb.tt +0 -0
  301. data/lib/{rails/generators → generators}/alchemy/module/templates/module_config.rb.tt +0 -0
  302. data/lib/{rails/generators → generators}/alchemy/page_layouts/page_layouts_generator.rb +5 -4
  303. data/lib/{rails/generators → generators}/alchemy/page_layouts/templates/layout.html.erb +0 -0
  304. data/lib/{rails/generators → generators}/alchemy/page_layouts/templates/layout.html.haml +0 -0
  305. data/lib/{rails/generators → generators}/alchemy/page_layouts/templates/layout.html.slim +0 -0
  306. data/lib/{rails/generators → generators}/alchemy/site_layouts/site_layouts_generator.rb +4 -2
  307. data/lib/{rails/generators → generators}/alchemy/site_layouts/templates/layout.html.erb +0 -0
  308. data/lib/{rails/generators → generators}/alchemy/site_layouts/templates/layout.html.haml +0 -0
  309. data/lib/{rails/generators → generators}/alchemy/site_layouts/templates/layout.html.slim +0 -0
  310. data/lib/{rails/generators → generators}/alchemy/views/views_generator.rb +7 -6
  311. data/lib/kaminari/scoped_pagination_url_helper.rb +1 -0
  312. data/lib/tasks/alchemy/db.rake +3 -19
  313. data/lib/tasks/alchemy/install.rake +5 -48
  314. data/lib/tasks/alchemy/tidy.rake +9 -8
  315. data/lib/tasks/alchemy/upgrade.rake +18 -116
  316. data/package.json +45 -0
  317. data/package/admin.js +14 -0
  318. data/package/src/__tests__/i18n.spec.js +70 -0
  319. data/package/src/i18n.js +48 -0
  320. data/package/src/node_tree.js +72 -0
  321. data/package/src/translations.js +32 -0
  322. data/package/src/utils/__tests__/ajax.spec.js +124 -0
  323. data/package/src/utils/__tests__/events.spec.js +38 -0
  324. data/package/src/utils/ajax.js +48 -0
  325. data/package/src/utils/events.js +16 -0
  326. data/vendor/assets/fonts/fa-regular-400.eot +0 -0
  327. data/vendor/assets/fonts/fa-regular-400.svg +798 -358
  328. data/vendor/assets/fonts/fa-regular-400.ttf +0 -0
  329. data/vendor/assets/fonts/fa-regular-400.woff +0 -0
  330. data/vendor/assets/fonts/fa-regular-400.woff2 +0 -0
  331. data/vendor/assets/fonts/fa-solid-900.eot +0 -0
  332. data/vendor/assets/fonts/fa-solid-900.svg +4933 -1408
  333. data/vendor/assets/fonts/fa-solid-900.ttf +0 -0
  334. data/vendor/assets/fonts/fa-solid-900.woff +0 -0
  335. data/vendor/assets/fonts/fa-solid-900.woff2 +0 -0
  336. data/vendor/assets/javascripts/jquery_plugins/jquery.ui.nestedSortable.js +1 -2
  337. data/vendor/assets/stylesheets/fontawesome/_core.scss +5 -0
  338. data/vendor/assets/stylesheets/fontawesome/_fixed-width.scss +1 -1
  339. data/vendor/assets/stylesheets/fontawesome/_icons.scss +651 -2
  340. data/vendor/assets/stylesheets/fontawesome/_mixins.scss +0 -1
  341. data/vendor/assets/stylesheets/fontawesome/_rotated-flipped.scss +3 -2
  342. data/vendor/assets/stylesheets/fontawesome/_stacked.scss +1 -1
  343. data/vendor/assets/stylesheets/fontawesome/_variables.scss +662 -9
  344. data/vendor/assets/stylesheets/fontawesome/fontawesome.scss +2 -2
  345. data/vendor/assets/stylesheets/fontawesome/regular.scss +23 -0
  346. data/vendor/assets/stylesheets/fontawesome/solid.scss +24 -0
  347. metadata +112 -88
  348. data/app/assets/javascripts/alchemy/alchemy.i18n.js.coffee +0 -32
  349. data/app/assets/javascripts/alchemy/alchemy.node_tree.js +0 -66
  350. data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +0 -29
  351. data/app/assets/javascripts/alchemy/alchemy.utils.js +0 -45
  352. data/app/helpers/alchemy/essences_helper.rb +0 -119
  353. data/app/models/concerns/alchemy/content_touching.rb +0 -23
  354. data/app/serializers/alchemy/legacy_element_serializer.rb +0 -15
  355. data/app/views/alchemy/admin/contents/_missing.html.erb +0 -17
  356. data/app/views/alchemy/admin/pages/_menu_fields.html.erb +0 -37
  357. data/app/views/alchemy/admin/pages/configure_external.html.erb +0 -32
  358. data/app/views/alchemy/elements/_editor_not_found.html.erb +0 -4
  359. data/app/views/alchemy/navigation/_image_link.html.erb +0 -14
  360. data/app/views/alchemy/navigation/_link.html.erb +0 -19
  361. data/app/views/alchemy/navigation/_renderer.html.erb +0 -29
  362. data/db/migrate/20180226123013_alchemy_four_point_zero.rb +0 -363
  363. data/db/migrate/20180227224537_migrate_tags_to_gutentag.rb +0 -41
  364. data/db/migrate/20180519204655_add_fixed_to_alchemy_elements.rb +0 -6
  365. data/db/migrate/20191016073858_create_alchemy_essence_pages.rb +0 -8
  366. data/db/migrate/20191029212236_create_alchemy_nodes.rb +0 -24
  367. data/db/migrate/20200226081535_add_site_id_to_alchemy_nodes.rb +0 -15
  368. data/lib/alchemy/ssl_protection.rb +0 -34
  369. data/lib/alchemy/tasks/helpers.rb +0 -81
  370. data/lib/alchemy/test_support/controller_requests.rb +0 -93
  371. data/lib/alchemy/upgrader/four_point_four.rb +0 -52
  372. data/lib/alchemy/upgrader/four_point_one.rb +0 -42
  373. data/lib/alchemy/upgrader/four_point_six.rb +0 -50
  374. data/lib/alchemy/upgrader/four_point_two.rb +0 -85
  375. data/lib/alchemy/upgrader/tasks/cells_migration.rb +0 -43
  376. data/lib/alchemy/upgrader/tasks/cells_upgrader.rb +0 -148
  377. data/lib/alchemy/upgrader/tasks/element_partial_name_variable_updater.rb +0 -28
  378. data/lib/alchemy/upgrader/tasks/harden_acts_as_taggable_on_migrations.rb +0 -27
  379. data/lib/alchemy/upgrader/tasks/picture_gallery_migration.rb +0 -65
  380. data/lib/alchemy/upgrader/tasks/picture_gallery_upgrader.rb +0 -210
  381. data/lib/rails/generators/alchemy/essence/templates/editor.html.erb +0 -15
  382. data/lib/rails/generators/alchemy/install/install_generator.rb +0 -60
  383. data/lib/tasks/alchemy/convert.rake +0 -97
  384. data/vendor/assets/javascripts/sortable/Sortable.min.js +0 -2
  385. data/vendor/assets/stylesheets/fontawesome/fa-regular.scss +0 -22
  386. data/vendor/assets/stylesheets/fontawesome/fa-solid.scss +0 -23
@@ -6,11 +6,9 @@ module Alchemy
6
6
  include Userstamp
7
7
  include Locale
8
8
 
9
- before_action { enforce_ssl if ssl_required? && !request.ssl? }
10
9
  before_action :load_locked_pages
11
10
 
12
- helper_method :clipboard_empty?, :trash_empty?, :get_clipboard, :is_admin?,
13
- :options_from_params
11
+ helper_method :clipboard_empty?, :trash_empty?, :get_clipboard, :is_admin?
14
12
 
15
13
  check_authorization
16
14
 
@@ -28,14 +26,14 @@ module Alchemy
28
26
 
29
27
  def leave
30
28
  authorize! :leave, :alchemy_admin
31
- render template: '/alchemy/admin/leave', layout: !request.xhr?
29
+ render template: "/alchemy/admin/leave", layout: !request.xhr?
32
30
  end
33
31
 
34
32
  private
35
33
 
36
34
  # Disable layout rendering for xhr requests.
37
35
  def set_layout
38
- request.xhr? ? false : 'alchemy/admin'
36
+ request.xhr? ? false : "alchemy/admin"
39
37
  end
40
38
 
41
39
  # Handles exceptions
@@ -56,7 +54,7 @@ module Alchemy
56
54
  if request.xhr?
57
55
  render action: "error_notice"
58
56
  else
59
- render '500', status: 500
57
+ render "500", status: 500
60
58
  end
61
59
  end
62
60
 
@@ -90,6 +88,7 @@ module Alchemy
90
88
  # Returns true if the current_alchemy_user (The logged-in Alchemy User) has the admin role.
91
89
  def is_admin?
92
90
  return false if !current_alchemy_user
91
+
93
92
  current_alchemy_user.admin?
94
93
  end
95
94
 
@@ -105,22 +104,15 @@ module Alchemy
105
104
  flash[:notice] = Alchemy.t(flash_notice)
106
105
  do_redirect_to redirect_url
107
106
  else
108
- render action: (params[:action] == 'update' ? 'edit' : 'new')
107
+ render action: (params[:action] == "update" ? "edit" : "new")
109
108
  end
110
109
  end
111
110
 
112
- def per_page_value_for_screen_size
113
- Alchemy::Deprecation.warn("#per_page_value_for_screen_size is deprecated, please use #items_per_page instead")
114
- return items_per_page if session[:screen_size].blank?
115
- screen_height = session[:screen_size].split('x').last.to_i
116
- (screen_height / 50) - 12
117
- end
118
-
119
111
  # Does redirects for html and js requests
120
112
  #
121
113
  def do_redirect_to(url_or_path)
122
114
  respond_to do |format|
123
- format.js {
115
+ format.js {
124
116
  @redirect_url = url_or_path
125
117
  render :redirect
126
118
  }
@@ -128,18 +120,6 @@ module Alchemy
128
120
  end
129
121
  end
130
122
 
131
- # Extracts options from params and permits all keys
132
- #
133
- # If no options are present it returns an empty parameters hash.
134
- #
135
- # @returns [ActionController::Parameters]
136
- def options_from_params
137
- @_options_from_params ||= begin
138
- (params[:options] || ActionController::Parameters.new).permit!
139
- end
140
- end
141
- deprecate :options_from_params, deprecator: Alchemy::Deprecation
142
-
143
123
  # This method decides if we want to raise an exception or not.
144
124
  #
145
125
  # I.e. in test environment.
@@ -150,7 +130,7 @@ module Alchemy
150
130
 
151
131
  # Are we currently in the page edit mode page preview.
152
132
  def is_page_preview?
153
- controller_path == 'alchemy/admin/pages' && action_name == 'show'
133
+ controller_path == "alchemy/admin/pages" && action_name == "show"
154
134
  end
155
135
 
156
136
  def load_locked_pages
@@ -161,11 +141,11 @@ module Alchemy
161
141
  #
162
142
  def current_alchemy_site
163
143
  @current_alchemy_site ||= begin
164
- site_id = params[:site_id] || session[:alchemy_site_id]
165
- site = Site.find_by(id: site_id) || super
166
- session[:alchemy_site_id] = site.id
167
- site
168
- end
144
+ site_id = params[:site_id] || session[:alchemy_site_id]
145
+ site = Site.find_by(id: site_id) || super
146
+ session[:alchemy_site_id] = site&.id
147
+ site
148
+ end
169
149
  end
170
150
  end
171
151
  end
@@ -17,10 +17,10 @@ module Alchemy
17
17
 
18
18
  def insert
19
19
  @item = model_class.find(remarkable_params[:remarkable_id])
20
- unless @clipboard.detect { |item| item['id'] == remarkable_params[:remarkable_id] }
20
+ unless @clipboard.detect { |item| item["id"] == remarkable_params[:remarkable_id] }
21
21
  @clipboard << {
22
- 'id' => remarkable_params[:remarkable_id],
23
- 'action' => params[:remove] ? 'cut' : 'copy'
22
+ "id" => remarkable_params[:remarkable_id],
23
+ "action" => params[:remove] ? "cut" : "copy",
24
24
  }
25
25
  end
26
26
  respond_to do |format|
@@ -30,7 +30,7 @@ module Alchemy
30
30
 
31
31
  def remove
32
32
  @item = model_class.find(remarkable_params[:remarkable_id])
33
- @clipboard.delete_if { |item| item['id'] == remarkable_params[:remarkable_id] }
33
+ @clipboard.delete_if { |item| item["id"] == remarkable_params[:remarkable_id] }
34
34
  respond_to do |format|
35
35
  format.js
36
36
  end
@@ -48,6 +48,7 @@ module Alchemy
48
48
 
49
49
  def model_class
50
50
  raise ActionController::BadRequest unless remarkable_type
51
+
51
52
  "alchemy/#{remarkable_type}".classify.constantize
52
53
  end
53
54
 
@@ -3,13 +3,12 @@
3
3
  module Alchemy
4
4
  module Admin
5
5
  class ContentsController < Alchemy::Admin::BaseController
6
- helper 'alchemy/admin/essences'
6
+ helper "alchemy/admin/essences"
7
7
 
8
8
  authorize_resource class: Alchemy::Content
9
9
 
10
10
  def create
11
11
  @content = Content.create(content_params)
12
- @html_options = params[:html_options] || {}
13
12
  end
14
13
 
15
14
  private
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'net/http'
4
- require 'alchemy/version'
3
+ require "net/http"
4
+ require "alchemy/version"
5
5
 
6
6
  module Alchemy
7
7
  module Admin
@@ -28,9 +28,9 @@ module Alchemy
28
28
  def update_check
29
29
  @alchemy_version = Alchemy.version
30
30
  if @alchemy_version < latest_alchemy_version
31
- render plain: 'true'
31
+ render plain: "true"
32
32
  else
33
- render plain: 'false'
33
+ render plain: "false"
34
34
  end
35
35
  rescue UpdateServiceUnavailable => e
36
36
  render plain: e, status: 503
@@ -41,7 +41,8 @@ module Alchemy
41
41
  # Returns latest alchemy version.
42
42
  def latest_alchemy_version
43
43
  versions = get_alchemy_versions
44
- return '' if versions.blank?
44
+ return "" if versions.blank?
45
+
45
46
  # reject any non release version
46
47
  versions.reject! { |v| v =~ /[a-z]/ }
47
48
  versions.max
@@ -53,14 +54,14 @@ module Alchemy
53
54
  response = query_rubygems
54
55
  if response.code == "200"
55
56
  alchemy_versions = JSON.parse(response.body)
56
- alchemy_versions.collect { |h| h['number'] }.sort
57
+ alchemy_versions.collect { |h| h["number"] }.sort
57
58
  else
58
59
  # rubygems.org not available?
59
60
  # then we try github
60
61
  response = query_github
61
62
  if response.code == "200"
62
63
  alchemy_tags = JSON.parse(response.body)
63
- alchemy_tags.collect { |h| h['name'].tr('v', '') }.sort
64
+ alchemy_tags.collect { |h| h["name"].tr("v", "") }.sort
64
65
  else
65
66
  # no luck at all?
66
67
  raise UpdateServiceUnavailable
@@ -70,12 +71,12 @@ module Alchemy
70
71
 
71
72
  # Query the RubyGems API for Alchemy versions.
72
73
  def query_rubygems
73
- make_api_request('https://rubygems.org/api/v1/versions/alchemy_cms.json')
74
+ make_api_request("https://rubygems.org/api/v1/versions/alchemy_cms.json")
74
75
  end
75
76
 
76
77
  # Query the GitHub API for Alchemy tags.
77
78
  def query_github
78
- make_api_request('https://api.github.com/repos/AlchemyCMS/alchemy_cms/tags')
79
+ make_api_request("https://api.github.com/repos/AlchemyCMS/alchemy_cms/tags")
79
80
  end
80
81
 
81
82
  # Make a HTTP API request for given request url.
@@ -17,7 +17,7 @@ module Alchemy
17
17
  @parent_element = Element.find_by(id: params[:parent_element_id])
18
18
  @elements = @page.available_elements_within_current_scope(@parent_element)
19
19
  @element = @page.elements.build
20
- @clipboard = get_clipboard('elements')
20
+ @clipboard = get_clipboard("elements")
21
21
  @clipboard_items = Element.all_from_clipboard_for_page(@clipboard, @page)
22
22
  end
23
23
 
@@ -30,7 +30,7 @@ module Alchemy
30
30
  else
31
31
  @element = Element.create(create_element_params)
32
32
  end
33
- if @page.definition['insert_elements_at'] == 'top'
33
+ if @page.definition["insert_elements_at"] == "top"
34
34
  @insert_at_top = true
35
35
  @element.move_to_top
36
36
  end
@@ -40,7 +40,7 @@ module Alchemy
40
40
  else
41
41
  @element.page = @page
42
42
  @elements = @page.available_element_definitions
43
- @clipboard = get_clipboard('elements')
43
+ @clipboard = get_clipboard("elements")
44
44
  @clipboard_items = Element.all_from_clipboard_for_page(@clipboard, @page)
45
45
  render :new
46
46
  end
@@ -56,7 +56,7 @@ module Alchemy
56
56
  @element_validated = @element.update(element_params)
57
57
  else
58
58
  @element_validated = false
59
- @notice = Alchemy.t('Validation failed')
59
+ @notice = Alchemy.t("Validation failed")
60
60
  @error_message = "<h2>#{@notice}</h2><p>#{Alchemy.t(:content_validations_headline)}</p>".html_safe
61
61
  end
62
62
  end
@@ -81,7 +81,7 @@ module Alchemy
81
81
  Element.where(id: element_id).update_all(
82
82
  page_id: params[:page_id],
83
83
  parent_element_id: params[:parent_element_id],
84
- position: idx + 1
84
+ position: idx + 1,
85
85
  )
86
86
  end
87
87
  @parent_element.try!(:touch)
@@ -100,20 +100,20 @@ module Alchemy
100
100
  [
101
101
  {
102
102
  contents: {
103
- essence: :ingredient_association
104
- }
103
+ essence: :ingredient_association,
104
+ },
105
105
  },
106
106
  :tags,
107
107
  {
108
108
  all_nested_elements: [
109
109
  {
110
110
  contents: {
111
- essence: :ingredient_association
112
- }
111
+ essence: :ingredient_association,
112
+ },
113
113
  },
114
- :tags
115
- ]
116
- }
114
+ :tags,
115
+ ],
116
+ },
117
117
  ]
118
118
  end
119
119
 
@@ -123,20 +123,20 @@ module Alchemy
123
123
 
124
124
  def element_from_clipboard
125
125
  @element_from_clipboard ||= begin
126
- @clipboard = get_clipboard('elements')
127
- @clipboard.detect { |item| item['id'].to_i == params[:paste_from_clipboard].to_i }
128
- end
126
+ @clipboard = get_clipboard("elements")
127
+ @clipboard.detect { |item| item["id"].to_i == params[:paste_from_clipboard].to_i }
128
+ end
129
129
  end
130
130
 
131
131
  def paste_element_from_clipboard
132
- @source_element = Element.find(element_from_clipboard['id'])
132
+ @source_element = Element.find(element_from_clipboard["id"])
133
133
  element = Element.copy(@source_element, {
134
134
  parent_element_id: create_element_params[:parent_element_id],
135
- page_id: @page.id}
136
- )
137
- if element_from_clipboard['action'] == 'cut'
135
+ page_id: @page.id,
136
+ })
137
+ if element_from_clipboard["action"] == "cut"
138
138
  @cut_element_id = @source_element.id
139
- @clipboard.delete_if { |item| item['id'] == @source_element.id.to_s }
139
+ @clipboard.delete_if { |item| item["id"] == @source_element.id.to_s }
140
140
  @source_element.destroy
141
141
  end
142
142
  element
@@ -9,9 +9,9 @@ module Alchemy
9
9
  before_action :load_essence_picture, only: [:edit, :crop, :update]
10
10
  before_action :load_content, only: [:edit, :update, :assign]
11
11
 
12
- helper 'alchemy/admin/contents'
13
- helper 'alchemy/admin/essences'
14
- helper 'alchemy/url'
12
+ helper "alchemy/admin/contents"
13
+ helper "alchemy/admin/essences"
14
+ helper "alchemy/url"
15
15
 
16
16
  def edit
17
17
  end
@@ -19,10 +19,8 @@ module Alchemy
19
19
  def crop
20
20
  if @picture = @essence_picture.picture
21
21
  @content = @essence_picture.content
22
- options_from_params[:format] ||= (configuration(:image_store_format) || 'png')
23
-
24
22
  @min_size = sizes_from_essence_or_params
25
- @ratio = ratio_from_size_or_params
23
+ @ratio = ratio_from_size_or_settings
26
24
  infer_width_or_height_from_ratio
27
25
 
28
26
  @default_box = @essence_picture.default_mask(@min_size)
@@ -70,26 +68,26 @@ module Alchemy
70
68
 
71
69
  # Gets the minimum size of the image to be rendered.
72
70
  #
73
- # The +render_size+ attribute has preference over the +size+ parameter.
71
+ # The +render_size+ attribute has preference over the contents +size+ setting.
74
72
  #
75
73
  def sizes_from_essence_or_params
76
74
  if @essence_picture.render_size?
77
75
  @essence_picture.sizes_from_string(@essence_picture.render_size)
78
- elsif options_from_params[:size]
79
- @essence_picture.sizes_from_string(options_from_params[:size])
76
+ elsif @essence_picture.content.settings[:size]
77
+ @essence_picture.sizes_from_string(@essence_picture.content.settings[:size])
80
78
  else
81
79
  { width: 0, height: 0 }
82
80
  end
83
81
  end
84
82
 
85
- # Infers the aspect ratio from size or parameters. If you don't want a fixed
83
+ # Infers the aspect ratio from size or contents settings. If you don't want a fixed
86
84
  # aspect ratio, don't specify a size or only width or height.
87
85
  #
88
- def ratio_from_size_or_params
89
- if @min_size.value?(0) && options_from_params[:fixed_ratio].to_s =~ FLOAT_REGEX
90
- options_from_params[:fixed_ratio].to_f
86
+ def ratio_from_size_or_settings
87
+ if @min_size.value?(0) && @essence_picture.content.settings[:fixed_ratio].to_s =~ FLOAT_REGEX
88
+ @essence_picture.content.settings[:fixed_ratio].to_f
91
89
  elsif !@min_size[:width].zero? && !@min_size[:height].zero?
92
- @min_size[:width].to_f / @min_size[:height].to_f
90
+ @min_size[:width].to_f / @min_size[:height]
93
91
  else
94
92
  false
95
93
  end
@@ -3,21 +3,54 @@
3
3
  module Alchemy
4
4
  module Admin
5
5
  class LanguagesController < ResourcesController
6
+ before_action :load_current_site, only: %i[index new]
7
+
6
8
  def index
7
- @query = Language.on_current_site.ransack(search_filter_params[:q])
9
+ @query = Language.on_site(@current_site).ransack(search_filter_params[:q])
10
+ @query.sorts = default_sort_order if @query.sorts.empty?
8
11
  @languages = @query.result.page(params[:page] || 1).per(items_per_page)
9
12
  end
10
13
 
11
14
  def new
12
15
  @language = Language.new(
13
- page_layout: Config.get(:default_language)['page_layout']
16
+ site: @current_site,
17
+ page_layout: Config.get(:default_language)["page_layout"],
14
18
  )
15
19
  end
16
20
 
21
+ def create
22
+ @language = Alchemy::Language.new(resource_params)
23
+ if @language.save
24
+ flash[:notice] = Alchemy.t("Language successfully created")
25
+ redirect_to alchemy.admin_pages_path(language_id: @language)
26
+ else
27
+ render :new
28
+ end
29
+ end
30
+
31
+ def destroy
32
+ if @language.destroy
33
+ flash[:notice] = Alchemy.t("Language successfully removed")
34
+ else
35
+ flash[:warning] = @language.errors.full_messages.to_sentence
36
+ end
37
+ do_redirect_to alchemy.admin_languages_path
38
+ end
39
+
17
40
  def switch
18
41
  set_alchemy_language(params[:language_id])
19
42
  do_redirect_to request.referer || alchemy.admin_dashboard_path
20
43
  end
44
+
45
+ private
46
+
47
+ def load_current_site
48
+ @current_site = Alchemy::Site.current
49
+ if @current_site.nil?
50
+ flash[:warning] = Alchemy.t("Please create a site first.")
51
+ redirect_to admin_sites_path
52
+ end
53
+ end
21
54
  end
22
55
  end
23
56
  end
@@ -4,16 +4,19 @@ module Alchemy
4
4
  module Admin
5
5
  class LayoutpagesController < Alchemy::Admin::BaseController
6
6
  authorize_resource class: :alchemy_admin_layoutpages
7
+
8
+ include Alchemy::Admin::CurrentLanguage
9
+
7
10
  helper Alchemy::Admin::PagesHelper
8
11
 
9
12
  def index
10
- @layout_root = Page.find_or_create_layout_root_for(Language.current.id)
13
+ @layout_pages = Page.layoutpages.where(language: @current_language)
11
14
  @languages = Language.on_current_site
12
15
  end
13
16
 
14
17
  def edit
15
18
  @page = Page.find(params[:id])
16
- @page_layouts = PageLayout.layouts_with_own_for_select(@page.page_layout, Language.current.id, true)
19
+ @page_layouts = PageLayout.layouts_with_own_for_select(@page.page_layout, @current_language.id, true)
17
20
  end
18
21
  end
19
22
  end