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
@@ -3,6 +3,24 @@
3
3
  module Alchemy
4
4
  module Admin
5
5
  class SitesController < ResourcesController
6
+ def create
7
+ @site = Alchemy::Site.new(resource_params)
8
+ if @site.save
9
+ flash[:notice] = Alchemy.t("Please create a default language for this site.")
10
+ redirect_to alchemy.admin_languages_path(site_id: @site)
11
+ else
12
+ render :new
13
+ end
14
+ end
15
+
16
+ def destroy
17
+ if @site.destroy
18
+ flash[:notice] = Alchemy.t("Site successfully removed")
19
+ else
20
+ flash[:warning] = @site.errors.full_messages.to_sentence
21
+ end
22
+ do_redirect_to alchemy.admin_sites_path
23
+ end
6
24
  end
7
25
  end
8
26
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Alchemy
2
3
  module Admin
3
4
  class StyleguideController < BaseController
@@ -7,6 +7,7 @@ module Alchemy
7
7
 
8
8
  def index
9
9
  @query = Gutentag::Tag.ransack(search_filter_params[:q])
10
+ @query.sorts = default_sort_order if @query.sorts.empty?
10
11
  @tags = @query
11
12
  .result
12
13
  .page(params[:page] || 1)
@@ -20,7 +21,7 @@ module Alchemy
20
21
 
21
22
  def create
22
23
  @tag = Gutentag::Tag.create(tag_params)
23
- render_errors_or_redirect @tag, admin_tags_path, Alchemy.t('New Tag Created')
24
+ render_errors_or_redirect @tag, admin_tags_path, Alchemy.t("New Tag Created")
24
25
  end
25
26
 
26
27
  def edit
@@ -31,7 +32,7 @@ module Alchemy
31
32
  if tag_params[:merge_to]
32
33
  @new_tag = Gutentag::Tag.find(tag_params[:merge_to])
33
34
  Tag.replace(@tag, @new_tag)
34
- operation_text = Alchemy.t('Replaced Tag') % {old_tag: @tag.name, new_tag: @new_tag.name}
35
+ operation_text = Alchemy.t("Replaced Tag") % {old_tag: @tag.name, new_tag: @new_tag.name}
35
36
  @tag.destroy
36
37
  else
37
38
  @tag.update(tag_params)
@@ -65,7 +66,8 @@ module Alchemy
65
66
 
66
67
  def tags_from_term(term)
67
68
  return [] if term.blank?
68
- Gutentag::Tag.where(['LOWER(name) LIKE ?', "#{term.downcase}%"])
69
+
70
+ Gutentag::Tag.where(["LOWER(name) LIKE ?", "#{term.downcase}%"])
69
71
  end
70
72
 
71
73
  def json_for_autocomplete(items, attribute)
@@ -25,16 +25,16 @@ module Alchemy
25
25
  [
26
26
  {
27
27
  contents: {
28
- essence: :ingredient_association
28
+ essence: :ingredient_association,
29
29
  },
30
30
  all_nested_elements: [
31
31
  {
32
32
  contents: {
33
- essence: :ingredient_association
34
- }
35
- }
36
- ]
37
- }
33
+ essence: :ingredient_association,
34
+ },
35
+ },
36
+ ],
37
+ },
38
38
  ]
39
39
  end
40
40
  end
@@ -11,11 +11,11 @@ module Alchemy
11
11
  private
12
12
 
13
13
  def render_not_authorized
14
- render json: {error: 'Not authorized'}, status: 403
14
+ render json: {error: "Not authorized"}, status: 403
15
15
  end
16
16
 
17
17
  def render_not_found
18
- render json: {error: 'Record not found'}, status: 404
18
+ render json: {error: "Record not found"}, status: 404
19
19
  end
20
20
  end
21
21
  end
@@ -18,7 +18,7 @@ module Alchemy
18
18
  end
19
19
  @contents = @contents.includes(*content_includes)
20
20
 
21
- render json: @contents, adapter: :json, root: 'contents'
21
+ render json: @contents, adapter: :json, root: "contents"
22
22
  end
23
23
 
24
24
  # Returns a json object for content
@@ -36,7 +36,7 @@ module Alchemy
36
36
  elsif params[:element_id] && params[:name]
37
37
  @content = Content.where(
38
38
  element_id: params[:element_id],
39
- name: params[:name]
39
+ name: params[:name],
40
40
  ).includes(*content_includes).first || raise(ActiveRecord::RecordNotFound)
41
41
  end
42
42
  authorize! :show, @content
@@ -48,8 +48,8 @@ module Alchemy
48
48
  def content_includes
49
49
  [
50
50
  {
51
- essence: :ingredient_association
52
- }
51
+ essence: :ingredient_association,
52
+ },
53
53
  ]
54
54
  end
55
55
  end
@@ -22,7 +22,7 @@ module Alchemy
22
22
  end
23
23
  @elements = @elements.includes(*element_includes)
24
24
 
25
- render json: @elements, adapter: :json, root: 'elements'
25
+ render json: @elements, adapter: :json, root: "elements"
26
26
  end
27
27
 
28
28
  # Returns a json object for element
@@ -41,18 +41,18 @@ module Alchemy
41
41
  nested_elements: [
42
42
  {
43
43
  contents: {
44
- essence: :ingredient_association
45
- }
44
+ essence: :ingredient_association,
45
+ },
46
46
  },
47
- :tags
48
- ]
47
+ :tags,
48
+ ],
49
49
  },
50
50
  {
51
51
  contents: {
52
- essence: :ingredient_association
53
- }
52
+ essence: :ingredient_association,
53
+ },
54
54
  },
55
- :tags
55
+ :tags,
56
56
  ]
57
57
  end
58
58
  end
@@ -2,9 +2,21 @@
2
2
 
3
3
  module Alchemy
4
4
  class Api::NodesController < Api::BaseController
5
- before_action :load_node
5
+ before_action :load_node, except: :index
6
6
  before_action :authorize_access, only: [:move, :toggle_folded]
7
7
 
8
+ def index
9
+ @nodes = Node.all
10
+ @nodes = @nodes.includes(:parent)
11
+ @nodes = @nodes.ransack(params[:filter]).result
12
+
13
+ if params[:page]
14
+ @nodes = @nodes.page(params[:page]).per(params[:per_page])
15
+ end
16
+
17
+ render json: @nodes, adapter: :json, root: "data", meta: meta_data, include: params[:include]
18
+ end
19
+
8
20
  def move
9
21
  target_parent_node = Node.find(params[:target_parent_id])
10
22
  @node.move_to_child_with_index(target_parent_node, params[:new_position])
@@ -25,5 +37,29 @@ module Alchemy
25
37
  def authorize_access
26
38
  authorize! :update, @node
27
39
  end
40
+
41
+ def meta_data
42
+ {
43
+ total_count: total_count_value,
44
+ per_page: per_page_value,
45
+ page: page_value,
46
+ }
47
+ end
48
+
49
+ def total_count_value
50
+ params[:page] ? @nodes.total_count : @nodes.size
51
+ end
52
+
53
+ def per_page_value
54
+ if params[:page]
55
+ (params[:per_page] || Kaminari.config.default_per_page).to_i
56
+ else
57
+ @nodes.size
58
+ end
59
+ end
60
+
61
+ def page_value
62
+ params[:page] ? params[:page].to_i : 1
63
+ end
28
64
  end
29
65
  end
@@ -13,25 +13,14 @@ module Alchemy
13
13
  else
14
14
  @pages = Page.accessible_by(current_ability, :index)
15
15
  end
16
- @pages = @pages.where.not(parent_id: nil)
17
16
  @pages = @pages.includes(*page_includes)
18
- if params[:page_layout].present?
19
- Alchemy::Deprecation.warn <<~WARN
20
- Passing page_layout parameter to Alchemy::Api::PagesController#index is deprecated.
21
- Please pass a Ransack search query instead:
22
- q: {
23
- page_layout_eq: '#{params[:page_layout]}'
24
- }
25
- WARN
26
- @pages = @pages.where(page_layout: params[:page_layout])
27
- end
28
17
  @pages = @pages.ransack(params[:q]).result
29
18
 
30
19
  if params[:page]
31
20
  @pages = @pages.page(params[:page]).per(params[:per_page])
32
21
  end
33
22
 
34
- render json: @pages, adapter: :json, root: 'pages', meta: meta_data
23
+ render json: @pages, adapter: :json, root: "pages", meta: meta_data
35
24
  end
36
25
 
37
26
  # Returns all pages as nested json object for tree views
@@ -71,9 +60,11 @@ module Alchemy
71
60
  end
72
61
 
73
62
  def load_page_by_urlname
63
+ return unless Language.current
64
+
74
65
  Language.current.pages.where(
75
66
  urlname: params[:urlname],
76
- language_code: params[:locale] || Language.current.code
67
+ language_code: params[:locale] || Language.current.code,
77
68
  ).includes(page_includes).first
78
69
  end
79
70
 
@@ -81,7 +72,7 @@ module Alchemy
81
72
  {
82
73
  total_count: total_count_value,
83
74
  per_page: per_page_value,
84
- page: page_value
75
+ page: page_value,
85
76
  }
86
77
  end
87
78
 
@@ -111,20 +102,20 @@ module Alchemy
111
102
  nested_elements: [
112
103
  {
113
104
  contents: {
114
- essence: :ingredient_association
115
- }
105
+ essence: :ingredient_association,
106
+ },
116
107
  },
117
- :tags
118
- ]
108
+ :tags,
109
+ ],
119
110
  },
120
111
  {
121
112
  contents: {
122
- essence: :ingredient_association
123
- }
113
+ essence: :ingredient_association,
114
+ },
124
115
  },
125
- :tags
126
- ]
127
- }
116
+ :tags,
117
+ ],
118
+ },
128
119
  ]
129
120
  end
130
121
  end
@@ -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