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
@@ -6,7 +6,7 @@ module Alchemy
6
6
  include UploaderResponses
7
7
  include ArchiveOverlay
8
8
 
9
- helper 'alchemy/admin/tags'
9
+ helper "alchemy/admin/tags"
10
10
 
11
11
  before_action :load_resource,
12
12
  only: [:show, :edit, :update, :destroy, :info]
@@ -14,12 +14,12 @@ module Alchemy
14
14
  authorize_resource class: Alchemy::Picture
15
15
 
16
16
  def index
17
- @size = params[:size].present? ? params[:size] : 'medium'
17
+ @size = params[:size].present? ? params[:size] : "medium"
18
18
  @query = Picture.ransack(search_filter_params[:q])
19
19
  @pictures = Picture.search_by(
20
20
  search_filter_params,
21
21
  @query,
22
- items_per_page
22
+ items_per_page,
23
23
  )
24
24
 
25
25
  if in_overlay?
@@ -31,7 +31,7 @@ module Alchemy
31
31
  @previous = @picture.previous(params)
32
32
  @next = @picture.next(params)
33
33
  @assignments = @picture.essence_pictures.joins(content: {element: :page})
34
- render action: 'show'
34
+ render action: "show"
35
35
  end
36
36
 
37
37
  def create
@@ -46,19 +46,19 @@ module Alchemy
46
46
 
47
47
  def edit_multiple
48
48
  @pictures = Picture.where(id: params[:picture_ids])
49
- @tags = @pictures.collect(&:tag_list).flatten.uniq.join(', ')
49
+ @tags = @pictures.collect(&:tag_list).flatten.uniq.join(", ")
50
50
  end
51
51
 
52
52
  def update
53
53
  if @picture.update(picture_params)
54
54
  @message = {
55
55
  body: Alchemy.t(:picture_updated_successfully, name: @picture.name),
56
- type: 'notice'
56
+ type: "notice",
57
57
  }
58
58
  else
59
59
  @message = {
60
60
  body: Alchemy.t(:picture_update_failed),
61
- type: 'error'
61
+ type: "error",
62
62
  }
63
63
  end
64
64
  render :update
@@ -89,7 +89,7 @@ module Alchemy
89
89
  if not_deletable.any?
90
90
  flash[:warn] = Alchemy.t(
91
91
  "These pictures could not be deleted, because they were in use",
92
- names: not_deletable.to_sentence
92
+ names: not_deletable.to_sentence,
93
93
  )
94
94
  else
95
95
  flash[:notice] = Alchemy.t("Pictures deleted successfully", names: names.to_sentence)
@@ -116,15 +116,15 @@ module Alchemy
116
116
  def items_per_page
117
117
  if in_overlay?
118
118
  case params[:size]
119
- when 'small' then 25
120
- when 'large' then 4
119
+ when "small" then 25
120
+ when "large" then 4
121
121
  else
122
122
  9
123
123
  end
124
124
  else
125
125
  cookies[:alchemy_pictures_per_page] = params[:per_page] ||
126
- cookies[:alchemy_pictures_per_page] ||
127
- pictures_per_page_for_size(params[:size])
126
+ cookies[:alchemy_pictures_per_page] ||
127
+ pictures_per_page_for_size(params[:size])
128
128
  end
129
129
  end
130
130
 
@@ -137,8 +137,8 @@ module Alchemy
137
137
 
138
138
  def pictures_per_page_for_size(size)
139
139
  case size
140
- when 'small' then 60
141
- when 'large' then 12
140
+ when "small" then 60
141
+ when "large" then 12
142
142
  else
143
143
  20
144
144
  end
@@ -154,8 +154,8 @@ module Alchemy
154
154
  :size,
155
155
  :element_id,
156
156
  :swap,
157
- :content_id
158
- ]
157
+ :content_id,
158
+ ],
159
159
  )
160
160
  end
161
161
 
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'csv'
4
- require 'alchemy/resource'
5
- require 'alchemy/resources_helper'
3
+ require "csv"
4
+ require "alchemy/resource"
5
+ require "alchemy/resources_helper"
6
6
 
7
7
  module Alchemy
8
8
  module Admin
@@ -22,6 +22,7 @@ module Alchemy
22
22
 
23
23
  def index
24
24
  @query = resource_handler.model.ransack(search_filter_params[:q])
25
+ @query.sorts = default_sort_order if @query.sorts.empty?
25
26
  items = @query.result
26
27
 
27
28
  if contains_relations?
@@ -52,7 +53,7 @@ module Alchemy
52
53
  end
53
54
 
54
55
  def show
55
- render action: 'edit'
56
+ render action: "edit"
56
57
  end
57
58
 
58
59
  def edit; end
@@ -63,7 +64,7 @@ module Alchemy
63
64
  render_errors_or_redirect(
64
65
  resource_instance_variable,
65
66
  resources_path(resource_instance_variable.class, search_filter_params),
66
- flash_notice_for_resource_action
67
+ flash_notice_for_resource_action,
67
68
  )
68
69
  end
69
70
 
@@ -72,14 +73,17 @@ module Alchemy
72
73
  render_errors_or_redirect(
73
74
  resource_instance_variable,
74
75
  resources_path(resource_instance_variable.class, search_filter_params),
75
- flash_notice_for_resource_action
76
+ flash_notice_for_resource_action,
76
77
  )
77
78
  end
78
79
 
79
80
  def destroy
80
81
  resource_instance_variable.destroy
82
+ if resource_instance_variable.errors.any?
83
+ flash[:error] = resource_instance_variable.errors.full_messages.join(", ")
84
+ end
81
85
  flash_notice_for_resource_action
82
- do_redirect_to resource_url_proxy.url_for(search_filter_params.merge(action: 'index'))
86
+ do_redirect_to resource_url_proxy.url_for(search_filter_params.merge(action: "index"))
83
87
  end
84
88
 
85
89
  def resource_handler
@@ -92,6 +96,7 @@ module Alchemy
92
96
  # The key should look like "Modelname successfully created|updated|destroyed."
93
97
  def flash_notice_for_resource_action(action = params[:action])
94
98
  return if resource_instance_variable.errors.any?
99
+
95
100
  case action.to_sym
96
101
  when :create
97
102
  verb = "created"
@@ -104,11 +109,11 @@ module Alchemy
104
109
  end
105
110
 
106
111
  def is_alchemy_module?
107
- !alchemy_module.nil? && !alchemy_module['engine_name'].nil?
112
+ !alchemy_module.nil? && !alchemy_module["engine_name"].nil?
108
113
  end
109
114
 
110
115
  def alchemy_module
111
- @alchemy_module ||= module_definition_for(controller: params[:controller], action: 'index')
116
+ @alchemy_module ||= module_definition_for(controller: params[:controller], action: "index")
112
117
  end
113
118
 
114
119
  def load_resource
@@ -143,16 +148,14 @@ module Alchemy
143
148
 
144
149
  def common_search_filter_includes
145
150
  [
146
- # contrary to Rails' documentation passing an empty hash to permit all keys does not work
147
- {options: options_from_params.keys},
148
151
  {q: [
149
152
  resource_handler.search_field_name,
150
- :s
153
+ :s,
151
154
  ]},
152
155
  :tagged_with,
153
156
  :filter,
154
157
  :page,
155
- :per_page
158
+ :per_page,
156
159
  ].freeze
157
160
  end
158
161
 
@@ -164,6 +167,11 @@ module Alchemy
164
167
  per_page = Alchemy::Config.get(:items_per_page)
165
168
  [per_page, per_page * 2, per_page * 4]
166
169
  end
170
+
171
+ def default_sort_order
172
+ name = resource_handler.attributes.detect { |attr| attr[:name] == "name" }
173
+ name ? "name asc" : "#{resource_handler.attributes.first[:name]} asc"
174
+ end
167
175
  end
168
176
  end
169
177
  end
@@ -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
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Alchemy
4
+ class Api::NodesController < Api::BaseController
5
+ before_action :load_node, except: :index
6
+ before_action :authorize_access, only: [:move, :toggle_folded]
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
+
20
+ def move
21
+ target_parent_node = Node.find(params[:target_parent_id])
22
+ @node.move_to_child_with_index(target_parent_node, params[:new_position])
23
+ render json: @node, serializer: NodeSerializer
24
+ end
25
+
26
+ def toggle_folded
27
+ @node.update(folded: !@node.folded)
28
+ render json: @node, serializer: NodeSerializer
29
+ end
30
+
31
+ private
32
+
33
+ def load_node
34
+ @node = Node.find(params[:id])
35
+ end
36
+
37
+ def authorize_access
38
+ authorize! :update, @node
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
64
+ end
65
+ end
@@ -14,23 +14,13 @@ module Alchemy
14
14
  @pages = Page.accessible_by(current_ability, :index)
15
15
  end
16
16
  @pages = @pages.includes(*page_includes)
17
- if params[:page_layout].present?
18
- Alchemy::Deprecation.warn <<~WARN
19
- Passing page_layout parameter to Alchemy::Api::PagesController#index is deprecated.
20
- Please pass a Ransack search query instead:
21
- q: {
22
- page_layout_eq: '#{params[:page_layout]}'
23
- }
24
- WARN
25
- @pages = @pages.where(page_layout: params[:page_layout])
26
- end
27
17
  @pages = @pages.ransack(params[:q]).result
28
18
 
29
19
  if params[:page]
30
20
  @pages = @pages.page(params[:page]).per(params[:per_page])
31
21
  end
32
22
 
33
- render json: @pages, adapter: :json, root: 'pages', meta: meta_data
23
+ render json: @pages, adapter: :json, root: "pages", meta: meta_data
34
24
  end
35
25
 
36
26
  # Returns all pages as nested json object for tree views
@@ -70,9 +60,11 @@ module Alchemy
70
60
  end
71
61
 
72
62
  def load_page_by_urlname
63
+ return unless Language.current
64
+
73
65
  Language.current.pages.where(
74
66
  urlname: params[:urlname],
75
- language_code: params[:locale] || Language.current.code
67
+ language_code: params[:locale] || Language.current.code,
76
68
  ).includes(page_includes).first
77
69
  end
78
70
 
@@ -80,7 +72,7 @@ module Alchemy
80
72
  {
81
73
  total_count: total_count_value,
82
74
  per_page: per_page_value,
83
- page: page_value
75
+ page: page_value,
84
76
  }
85
77
  end
86
78
 
@@ -104,25 +96,26 @@ module Alchemy
104
96
  [
105
97
  :tags,
106
98
  {
99
+ language: :site,
107
100
  elements: [
108
101
  {
109
102
  nested_elements: [
110
103
  {
111
104
  contents: {
112
- essence: :ingredient_association
113
- }
105
+ essence: :ingredient_association,
106
+ },
114
107
  },
115
- :tags
116
- ]
108
+ :tags,
109
+ ],
117
110
  },
118
111
  {
119
112
  contents: {
120
- essence: :ingredient_association
121
- }
113
+ essence: :ingredient_association,
114
+ },
122
115
  },
123
- :tags
124
- ]
125
- }
116
+ :tags,
117
+ ],
118
+ },
126
119
  ]
127
120
  end
128
121
  end