alchemy_cms 6.1.5 → 7.0.0.pre.b

Sign up to get free protection for your applications and to get access to all the features.
Files changed (363) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/brakeman-analysis.yml +2 -2
  3. data/.github/workflows/ci.yml +7 -10
  4. data/.github/workflows/lint.yml +17 -0
  5. data/.gitignore +1 -6
  6. data/.hound.yml +2 -3
  7. data/.rubocop.yml +4 -350
  8. data/.standard.yml +3 -0
  9. data/CHANGELOG.md +49 -19
  10. data/Gemfile +4 -2
  11. data/README.md +7 -9
  12. data/Rakefile +12 -7
  13. data/alchemy_cms.gemspec +3 -3
  14. data/app/assets/javascripts/alchemy/admin.js +0 -1
  15. data/app/assets/javascripts/alchemy/alchemy.dirty.js.coffee +1 -1
  16. data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +18 -32
  17. data/app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee +2 -2
  18. data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +2 -2
  19. data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +33 -30
  20. data/app/assets/stylesheets/alchemy/elements.scss +16 -35
  21. data/app/assets/stylesheets/alchemy/forms.scss +0 -4
  22. data/app/assets/stylesheets/alchemy/node-select.scss +2 -2
  23. data/app/components/alchemy/ingredients/audio_view.rb +37 -0
  24. data/app/components/alchemy/ingredients/base_view.rb +38 -0
  25. data/app/components/alchemy/ingredients/boolean_view.rb +13 -0
  26. data/app/components/alchemy/ingredients/datetime_view.rb +22 -0
  27. data/app/components/alchemy/ingredients/file_view.rb +40 -0
  28. data/app/components/alchemy/ingredients/headline_view.rb +20 -0
  29. data/app/components/alchemy/ingredients/html_view.rb +9 -0
  30. data/app/components/alchemy/ingredients/link_view.rb +25 -0
  31. data/app/components/alchemy/ingredients/node_view.rb +11 -0
  32. data/app/components/alchemy/ingredients/page_view.rb +15 -0
  33. data/app/components/alchemy/ingredients/picture_view.rb +108 -0
  34. data/app/components/alchemy/ingredients/richtext_view.rb +22 -0
  35. data/app/components/alchemy/ingredients/select_view.rb +6 -0
  36. data/app/components/alchemy/ingredients/text_view.rb +41 -0
  37. data/app/components/alchemy/ingredients/video_view.rb +39 -0
  38. data/app/controllers/alchemy/admin/attachments_controller.rb +3 -4
  39. data/app/controllers/alchemy/admin/base_controller.rb +7 -7
  40. data/app/controllers/alchemy/admin/clipboard_controller.rb +2 -2
  41. data/app/controllers/alchemy/admin/elements_controller.rb +33 -43
  42. data/app/controllers/alchemy/admin/languages_controller.rb +1 -1
  43. data/app/controllers/alchemy/admin/nodes_controller.rb +2 -2
  44. data/app/controllers/alchemy/admin/pages_controller.rb +11 -11
  45. data/app/controllers/alchemy/admin/pictures_controller.rb +15 -15
  46. data/app/controllers/alchemy/admin/resources_controller.rb +28 -46
  47. data/app/controllers/alchemy/admin/styleguide_controller.rb +1 -0
  48. data/app/controllers/alchemy/admin/tags_controller.rb +11 -11
  49. data/app/controllers/alchemy/api/base_controller.rb +2 -2
  50. data/app/controllers/alchemy/api/elements_controller.rb +11 -13
  51. data/app/controllers/alchemy/api/ingredients_controller.rb +1 -1
  52. data/app/controllers/alchemy/api/nodes_controller.rb +1 -1
  53. data/app/controllers/alchemy/api/pages_controller.rb +14 -12
  54. data/app/controllers/alchemy/attachments_controller.rb +3 -3
  55. data/app/controllers/alchemy/base_controller.rb +1 -1
  56. data/app/controllers/alchemy/messages_controller.rb +18 -18
  57. data/app/controllers/alchemy/pages_controller.rb +10 -16
  58. data/app/controllers/concerns/alchemy/admin/archive_overlay.rb +1 -0
  59. data/app/controllers/concerns/alchemy/admin/uploader_responses.rb +5 -7
  60. data/app/controllers/concerns/alchemy/legacy_page_redirects.rb +5 -5
  61. data/app/decorators/alchemy/element_editor.rb +13 -33
  62. data/app/decorators/alchemy/ingredient_editor.rb +6 -6
  63. data/app/helpers/alchemy/admin/attachments_helper.rb +1 -1
  64. data/app/helpers/alchemy/admin/base_helper.rb +21 -22
  65. data/app/helpers/alchemy/admin/elements_helper.rb +1 -3
  66. data/app/helpers/alchemy/admin/form_helper.rb +1 -1
  67. data/app/helpers/alchemy/admin/navigation_helper.rb +7 -7
  68. data/app/helpers/alchemy/admin/pages_helper.rb +2 -2
  69. data/app/helpers/alchemy/admin/tags_helper.rb +3 -3
  70. data/app/helpers/alchemy/base_helper.rb +2 -2
  71. data/app/helpers/alchemy/elements_block_helper.rb +13 -48
  72. data/app/helpers/alchemy/elements_helper.rb +15 -23
  73. data/app/helpers/alchemy/pages_helper.rb +11 -15
  74. data/app/helpers/alchemy/url_helper.rb +1 -1
  75. data/app/mailers/alchemy/messages_mailer.rb +1 -1
  76. data/app/models/alchemy/attachment.rb +12 -9
  77. data/app/models/alchemy/base_record.rb +3 -0
  78. data/app/models/alchemy/eager_loading.rb +6 -7
  79. data/app/models/alchemy/element/definitions.rb +1 -1
  80. data/app/models/alchemy/element/element_ingredients.rb +4 -11
  81. data/app/models/alchemy/element/presenters.rb +9 -25
  82. data/app/models/alchemy/element.rb +4 -19
  83. data/app/models/alchemy/elements_repository.rb +1 -1
  84. data/app/models/alchemy/image_cropper_settings.rb +2 -2
  85. data/app/models/alchemy/ingredient.rb +29 -16
  86. data/app/models/alchemy/ingredient_validator.rb +1 -1
  87. data/app/models/alchemy/ingredients/audio.rb +2 -0
  88. data/app/models/alchemy/ingredients/datetime.rb +3 -1
  89. data/app/models/alchemy/ingredients/file.rb +7 -0
  90. data/app/models/alchemy/ingredients/headline.rb +6 -0
  91. data/app/models/alchemy/ingredients/link.rb +2 -0
  92. data/app/models/alchemy/ingredients/node.rb +2 -0
  93. data/app/models/alchemy/ingredients/page.rb +2 -0
  94. data/app/models/alchemy/ingredients/picture.rb +29 -0
  95. data/app/models/alchemy/ingredients/richtext.rb +17 -8
  96. data/app/models/alchemy/ingredients/select.rb +1 -0
  97. data/app/models/alchemy/ingredients/text.rb +8 -0
  98. data/app/models/alchemy/ingredients/video.rb +2 -0
  99. data/app/models/alchemy/language/code.rb +1 -1
  100. data/app/models/alchemy/language.rb +4 -4
  101. data/app/models/alchemy/legacy_page_url.rb +1 -1
  102. data/app/models/alchemy/node.rb +11 -8
  103. data/app/models/alchemy/page/page_elements.rb +19 -40
  104. data/app/models/alchemy/page/page_layouts.rb +0 -14
  105. data/app/models/alchemy/page/page_naming.rb +4 -4
  106. data/app/models/alchemy/page/page_natures.rb +1 -11
  107. data/app/models/alchemy/page/page_scopes.rb +5 -5
  108. data/app/models/alchemy/page.rb +11 -19
  109. data/app/models/alchemy/picture/calculations.rb +2 -2
  110. data/app/models/alchemy/picture/transformations.rb +2 -32
  111. data/app/models/alchemy/picture/url.rb +5 -5
  112. data/app/models/alchemy/picture.rb +22 -20
  113. data/app/models/alchemy/picture_thumb/create.rb +7 -18
  114. data/app/models/alchemy/picture_thumb/file_store.rb +33 -0
  115. data/app/models/alchemy/picture_thumb.rb +11 -11
  116. data/app/models/alchemy/picture_variant.rb +2 -3
  117. data/app/models/alchemy/tag.rb +8 -0
  118. data/app/models/concerns/alchemy/picture_thumbnails.rb +8 -8
  119. data/app/serializers/alchemy/base_serializer.rb +1 -1
  120. data/app/serializers/alchemy/element_serializer.rb +1 -6
  121. data/app/serializers/alchemy/page_tree_serializer.rb +7 -7
  122. data/app/services/alchemy/delete_elements.rb +1 -7
  123. data/app/services/alchemy/duplicate_element.rb +2 -7
  124. data/app/services/alchemy/tag_validations.rb +1 -1
  125. data/app/views/alchemy/admin/elements/_element.html.erb +8 -22
  126. data/app/views/alchemy/admin/elements/create.js.erb +1 -1
  127. data/app/views/alchemy/admin/elements/fold.js.erb +2 -2
  128. data/app/views/alchemy/admin/elements/order.js.erb +1 -1
  129. data/app/views/alchemy/admin/elements/update.js.erb +1 -2
  130. data/app/views/alchemy/admin/pages/_external_link.html.erb +2 -2
  131. data/app/views/alchemy/admin/pages/_file_link.html.erb +2 -2
  132. data/app/views/alchemy/admin/pages/_internal_link.html.erb +2 -2
  133. data/app/views/alchemy/admin/pages/edit.html.erb +1 -4
  134. data/app/views/alchemy/admin/pages/update.js.erb +10 -4
  135. data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +1 -3
  136. data/app/views/alchemy/admin/pictures/_infos.html.erb +4 -6
  137. data/app/views/alchemy/ingredients/_audio_view.html.erb +1 -14
  138. data/app/views/alchemy/ingredients/_boolean_editor.html.erb +1 -1
  139. data/app/views/alchemy/ingredients/_boolean_view.html.erb +1 -1
  140. data/app/views/alchemy/ingredients/_datetime_view.html.erb +3 -9
  141. data/app/views/alchemy/ingredients/_file_view.html.erb +3 -16
  142. data/app/views/alchemy/ingredients/_headline_editor.html.erb +1 -1
  143. data/app/views/alchemy/ingredients/_headline_view.html.erb +4 -10
  144. data/app/views/alchemy/ingredients/_html_editor.html.erb +1 -1
  145. data/app/views/alchemy/ingredients/_html_view.html.erb +1 -1
  146. data/app/views/alchemy/ingredients/_link_view.html.erb +4 -9
  147. data/app/views/alchemy/ingredients/_node_editor.html.erb +1 -1
  148. data/app/views/alchemy/ingredients/_node_view.html.erb +1 -1
  149. data/app/views/alchemy/ingredients/_page_view.html.erb +1 -4
  150. data/app/views/alchemy/ingredients/_picture_editor.html.erb +4 -4
  151. data/app/views/alchemy/ingredients/_picture_view.html.erb +4 -5
  152. data/app/views/alchemy/ingredients/_richtext_editor.html.erb +11 -2
  153. data/app/views/alchemy/ingredients/_richtext_view.html.erb +3 -3
  154. data/app/views/alchemy/ingredients/_select_editor.html.erb +2 -2
  155. data/app/views/alchemy/ingredients/_select_view.html.erb +1 -1
  156. data/app/views/alchemy/ingredients/_text_editor.html.erb +1 -1
  157. data/app/views/alchemy/ingredients/_text_view.html.erb +3 -19
  158. data/app/views/alchemy/ingredients/_video_view.html.erb +3 -18
  159. data/app/views/alchemy/ingredients/shared/_link_tools.html.erb +4 -3
  160. data/app/views/alchemy/ingredients/shared/_picture_tools.html.erb +1 -0
  161. data/app/views/alchemy/pages/_meta_data.html.erb +0 -1
  162. data/app/views/layouts/alchemy/admin.html.erb +10 -8
  163. data/bin/setup +37 -0
  164. data/bin/start +17 -0
  165. data/config/alchemy/config.yml +6 -6
  166. data/config/brakeman.ignore +56 -57
  167. data/config/initializers/assets.rb +1 -0
  168. data/config/initializers/dragonfly.rb +1 -0
  169. data/config/initializers/mime_types.rb +1 -0
  170. data/config/initializers/mini_profiler.rb +1 -0
  171. data/config/initializers/simple_form.rb +3 -2
  172. data/config/locales/alchemy.en.yml +98 -112
  173. data/config/routes.rb +22 -36
  174. data/config/spring.rb +1 -0
  175. data/db/migrate/20230121212637_alchemy_six_point_one.rb +248 -0
  176. data/db/migrate/20230505132743_add_indexes_to_alchemy_pictures.rb +6 -0
  177. data/lib/alchemy/admin/locale.rb +3 -3
  178. data/lib/alchemy/admin/preview_url.rb +2 -2
  179. data/lib/alchemy/auth_accessors.rb +1 -1
  180. data/lib/alchemy/cache_digests/template_tracker.rb +6 -7
  181. data/lib/alchemy/config.rb +3 -3
  182. data/lib/alchemy/controller_actions.rb +4 -4
  183. data/lib/alchemy/deprecation.rb +2 -1
  184. data/lib/alchemy/dragonfly/processors/thumbnail.rb +1 -1
  185. data/lib/alchemy/element_definition.rb +2 -2
  186. data/lib/alchemy/engine.rb +2 -1
  187. data/lib/alchemy/errors.rb +0 -11
  188. data/lib/alchemy/filetypes.rb +7 -7
  189. data/lib/alchemy/forms/builder.rb +4 -4
  190. data/lib/alchemy/hints.rb +10 -10
  191. data/lib/alchemy/i18n.rb +6 -4
  192. data/lib/alchemy/install/tasks.rb +2 -1
  193. data/lib/alchemy/name_conversions.rb +1 -1
  194. data/lib/alchemy/page_layout.rb +1 -1
  195. data/lib/alchemy/permissions.rb +5 -17
  196. data/lib/alchemy/resource.rb +10 -10
  197. data/lib/alchemy/resources_helper.rb +7 -7
  198. data/lib/alchemy/routing_constraints.rb +5 -5
  199. data/lib/alchemy/searchable_resource.rb +38 -0
  200. data/lib/alchemy/seeder.rb +4 -3
  201. data/lib/alchemy/shell.rb +2 -1
  202. data/lib/alchemy/taggable.rb +3 -2
  203. data/lib/alchemy/tasks/tidy.rb +1 -38
  204. data/lib/alchemy/test_support/capybara_helpers.rb +69 -0
  205. data/lib/alchemy/test_support/config_stubbing.rb +1 -0
  206. data/lib/alchemy/test_support/factories/element_factory.rb +2 -4
  207. data/lib/alchemy/test_support/factories/ingredient_factory.rb +1 -1
  208. data/lib/alchemy/test_support/factories/page_factory.rb +5 -3
  209. data/lib/alchemy/test_support/having_crop_action_examples.rb +9 -9
  210. data/lib/alchemy/test_support/having_picture_thumbnails_examples.rb +33 -33
  211. data/lib/alchemy/test_support/integration_helpers.rb +4 -3
  212. data/lib/alchemy/test_support/shared_contexts.rb +2 -1
  213. data/lib/alchemy/test_support/shared_dom_ids_examples.rb +10 -10
  214. data/lib/alchemy/test_support/shared_ingredient_examples.rb +13 -7
  215. data/lib/alchemy/test_support/shared_uploader_examples.rb +1 -0
  216. data/lib/alchemy/tinymce.rb +3 -43
  217. data/lib/alchemy/upgrader/seven_point_zero.rb +45 -0
  218. data/lib/alchemy/upgrader/tasks/.keep +0 -0
  219. data/lib/alchemy/upgrader.rb +9 -3
  220. data/lib/alchemy/version.rb +1 -1
  221. data/lib/alchemy.rb +0 -19
  222. data/lib/alchemy_cms.rb +2 -2
  223. data/lib/generators/alchemy/base.rb +3 -2
  224. data/lib/generators/alchemy/elements/elements_generator.rb +2 -2
  225. data/lib/generators/alchemy/elements/templates/view.html.erb +1 -10
  226. data/lib/generators/alchemy/elements/templates/view.html.haml +1 -9
  227. data/lib/generators/alchemy/elements/templates/view.html.slim +1 -9
  228. data/lib/generators/alchemy/ingredient/ingredient_generator.rb +1 -0
  229. data/lib/generators/alchemy/install/files/alchemy.en.yml +7 -8
  230. data/lib/generators/alchemy/install/files/application.html.erb +1 -1
  231. data/lib/generators/alchemy/install/install_generator.rb +20 -23
  232. data/lib/generators/alchemy/install/templates/elements.yml.tt +12 -12
  233. data/lib/generators/alchemy/module/module_generator.rb +1 -0
  234. data/lib/generators/alchemy/page_layouts/page_layouts_generator.rb +1 -0
  235. data/lib/generators/alchemy/site_layouts/site_layouts_generator.rb +1 -0
  236. data/lib/generators/alchemy/views/views_generator.rb +2 -1
  237. data/lib/tasks/alchemy/thumbnails.rake +6 -25
  238. data/lib/tasks/alchemy/tidy.rake +2 -12
  239. data/lib/tasks/alchemy/upgrade.rake +13 -49
  240. data/package/admin.js +2 -0
  241. data/package/dist/admin.js +16 -0
  242. data/package/dist/admin.js.map +7 -0
  243. data/package/src/datepicker.js +1 -0
  244. data/package/src/tinymce.js +142 -0
  245. data/package.json +5 -3
  246. metadata +41 -135
  247. data/app/assets/javascripts/alchemy/alchemy.tinymce.js.coffee +0 -93
  248. data/app/controllers/alchemy/admin/contents_controller.rb +0 -21
  249. data/app/controllers/alchemy/admin/essence_audios_controller.rb +0 -30
  250. data/app/controllers/alchemy/admin/essence_files_controller.rb +0 -31
  251. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +0 -43
  252. data/app/controllers/alchemy/admin/essence_videos_controller.rb +0 -34
  253. data/app/controllers/alchemy/api/contents_controller.rb +0 -52
  254. data/app/decorators/alchemy/content_editor.rb +0 -119
  255. data/app/helpers/alchemy/admin/contents_helper.rb +0 -42
  256. data/app/helpers/alchemy/admin/essences_helper.rb +0 -31
  257. data/app/models/alchemy/content/factory.rb +0 -143
  258. data/app/models/alchemy/content.rb +0 -247
  259. data/app/models/alchemy/element/element_contents.rb +0 -200
  260. data/app/models/alchemy/element/element_essences.rb +0 -133
  261. data/app/models/alchemy/essence_audio.rb +0 -13
  262. data/app/models/alchemy/essence_boolean.rb +0 -20
  263. data/app/models/alchemy/essence_date.rb +0 -25
  264. data/app/models/alchemy/essence_file.rb +0 -49
  265. data/app/models/alchemy/essence_headline.rb +0 -41
  266. data/app/models/alchemy/essence_html.rb +0 -23
  267. data/app/models/alchemy/essence_link.rb +0 -21
  268. data/app/models/alchemy/essence_node.rb +0 -19
  269. data/app/models/alchemy/essence_page.rb +0 -17
  270. data/app/models/alchemy/essence_picture.rb +0 -67
  271. data/app/models/alchemy/essence_picture_view.rb +0 -90
  272. data/app/models/alchemy/essence_richtext.rb +0 -44
  273. data/app/models/alchemy/essence_select.rb +0 -19
  274. data/app/models/alchemy/essence_text.rb +0 -23
  275. data/app/models/alchemy/essence_video.rb +0 -13
  276. data/app/presenters/alchemy/picture_view.rb +0 -88
  277. data/app/serializers/alchemy/content_serializer.rb +0 -17
  278. data/app/serializers/alchemy/essence_boolean_serializer.rb +0 -10
  279. data/app/serializers/alchemy/essence_date_serializer.rb +0 -10
  280. data/app/serializers/alchemy/essence_file_serializer.rb +0 -13
  281. data/app/serializers/alchemy/essence_html_serializer.rb +0 -10
  282. data/app/serializers/alchemy/essence_link_serializer.rb +0 -13
  283. data/app/serializers/alchemy/essence_picture_serializer.rb +0 -28
  284. data/app/serializers/alchemy/essence_richtext_serializer.rb +0 -11
  285. data/app/serializers/alchemy/essence_select_serializer.rb +0 -10
  286. data/app/serializers/alchemy/essence_text_serializer.rb +0 -22
  287. data/app/views/alchemy/admin/contents/create.js.erb +0 -21
  288. data/app/views/alchemy/admin/essence_audios/edit.html.erb +0 -7
  289. data/app/views/alchemy/admin/essence_files/edit.html.erb +0 -21
  290. data/app/views/alchemy/admin/essence_pictures/destroy.js.erb +0 -5
  291. data/app/views/alchemy/admin/essence_pictures/edit.html.erb +0 -30
  292. data/app/views/alchemy/admin/essence_pictures/save_link.js.erb +0 -3
  293. data/app/views/alchemy/admin/essence_pictures/update.js.erb +0 -8
  294. data/app/views/alchemy/admin/essence_videos/edit.html.erb +0 -12
  295. data/app/views/alchemy/admin/pages/_tinymce_custom_config.html.erb +0 -13
  296. data/app/views/alchemy/essences/_essence_audio_editor.html.erb +0 -4
  297. data/app/views/alchemy/essences/_essence_audio_view.html.erb +0 -15
  298. data/app/views/alchemy/essences/_essence_boolean_editor.html.erb +0 -11
  299. data/app/views/alchemy/essences/_essence_boolean_view.html.erb +0 -2
  300. data/app/views/alchemy/essences/_essence_date_editor.html.erb +0 -16
  301. data/app/views/alchemy/essences/_essence_date_view.html.erb +0 -10
  302. data/app/views/alchemy/essences/_essence_file_editor.html.erb +0 -54
  303. data/app/views/alchemy/essences/_essence_file_view.html.erb +0 -18
  304. data/app/views/alchemy/essences/_essence_headline_editor.html.erb +0 -36
  305. data/app/views/alchemy/essences/_essence_headline_view.html.erb +0 -10
  306. data/app/views/alchemy/essences/_essence_html_editor.html.erb +0 -10
  307. data/app/views/alchemy/essences/_essence_html_view.html.erb +0 -2
  308. data/app/views/alchemy/essences/_essence_link_editor.html.erb +0 -30
  309. data/app/views/alchemy/essences/_essence_link_view.html.erb +0 -10
  310. data/app/views/alchemy/essences/_essence_node_editor.html.erb +0 -27
  311. data/app/views/alchemy/essences/_essence_node_view.html.erb +0 -1
  312. data/app/views/alchemy/essences/_essence_page_editor.html.erb +0 -26
  313. data/app/views/alchemy/essences/_essence_page_view.html.erb +0 -5
  314. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +0 -59
  315. data/app/views/alchemy/essences/_essence_picture_view.html.erb +0 -6
  316. data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +0 -14
  317. data/app/views/alchemy/essences/_essence_richtext_view.html.erb +0 -4
  318. data/app/views/alchemy/essences/_essence_select_editor.html.erb +0 -28
  319. data/app/views/alchemy/essences/_essence_select_view.html.erb +0 -2
  320. data/app/views/alchemy/essences/_essence_text_editor.html.erb +0 -29
  321. data/app/views/alchemy/essences/_essence_text_view.html.erb +0 -17
  322. data/app/views/alchemy/essences/_essence_video_editor.html.erb +0 -4
  323. data/app/views/alchemy/essences/_essence_video_view.html.erb +0 -19
  324. data/app/views/alchemy/essences/shared/_essence_picture_tools.html.erb +0 -59
  325. data/app/views/alchemy/essences/shared/_linkable_essence_tools.html.erb +0 -20
  326. data/app/views/alchemy/pages/show.rss.builder +0 -21
  327. data/db/migrate/20200226213334_alchemy_four_point_four.rb +0 -313
  328. data/db/migrate/20200423073425_create_alchemy_essence_nodes.rb +0 -11
  329. data/db/migrate/20200504210159_remove_site_id_from_nodes.rb +0 -28
  330. data/db/migrate/20200505215518_add_language_id_foreign_key_to_alchemy_pages.rb +0 -8
  331. data/db/migrate/20200511113603_add_menu_type_to_alchemy_nodes.rb +0 -27
  332. data/db/migrate/20200514091507_make_page_layoutpage_null_false.rb +0 -6
  333. data/db/migrate/20200519073500_remove_visible_from_alchemy_pages.rb +0 -24
  334. data/db/migrate/20200617110713_create_alchemy_picture_thumbs.rb +0 -22
  335. data/db/migrate/20200907111332_remove_tri_state_booleans.rb +0 -33
  336. data/db/migrate/20201207131309_create_page_versions.rb +0 -19
  337. data/db/migrate/20201207135820_add_page_version_id_to_alchemy_elements.rb +0 -76
  338. data/db/migrate/20210205143548_rename_public_on_and_public_until_on_alchemy_pages.rb +0 -10
  339. data/db/migrate/20210326105046_add_sanitized_body_to_alchemy_essence_richtexts.rb +0 -7
  340. data/db/migrate/20210406093436_add_alchemy_essence_headlines.rb +0 -12
  341. data/db/migrate/20210506135919_create_essence_audios.rb +0 -19
  342. data/db/migrate/20210506140258_create_essence_videos.rb +0 -23
  343. data/db/migrate/20210508091432_create_alchemy_ingredients.rb +0 -22
  344. data/db/migrate/20220514072456_restrict_on_delete_page_id_foreign_key_from_alchemy_nodes.rb +0 -13
  345. data/db/migrate/20220622130905_add_playsinline_to_alchemy_essence_videos.rb +0 -9
  346. data/lib/alchemy/essence.rb +0 -250
  347. data/lib/alchemy/test_support/essence_shared_examples.rb +0 -271
  348. data/lib/alchemy/test_support/factories/content_factory.rb +0 -20
  349. data/lib/alchemy/test_support/factories/essence_audio_factory.rb +0 -7
  350. data/lib/alchemy/test_support/factories/essence_file_factory.rb +0 -7
  351. data/lib/alchemy/test_support/factories/essence_page_factory.rb +0 -7
  352. data/lib/alchemy/test_support/factories/essence_picture_factory.rb +0 -11
  353. data/lib/alchemy/test_support/factories/essence_text_factory.rb +0 -7
  354. data/lib/alchemy/test_support/factories/essence_video_factory.rb +0 -7
  355. data/lib/alchemy/upgrader/five_point_zero.rb +0 -41
  356. data/lib/alchemy/upgrader/six_point_zero.rb +0 -21
  357. data/lib/alchemy/upgrader/tasks/add_page_versions.rb +0 -33
  358. data/lib/alchemy/upgrader/tasks/element_views_updater.rb +0 -34
  359. data/lib/alchemy/upgrader/tasks/harden_gutentag_migrations.rb +0 -29
  360. data/lib/alchemy/upgrader/tasks/ingredients_migrator.rb +0 -74
  361. data/lib/generators/alchemy/essence/essence_generator.rb +0 -49
  362. data/lib/generators/alchemy/essence/templates/editor.html.erb +0 -17
  363. data/lib/generators/alchemy/essence/templates/view.html.erb +0 -2
@@ -0,0 +1,13 @@
1
+ module Alchemy
2
+ module Ingredients
3
+ class BooleanView < BaseView
4
+ def call
5
+ Alchemy.t(value, scope: "ingredient_values.boolean")
6
+ end
7
+
8
+ def render?
9
+ !value.nil?
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,22 @@
1
+ module Alchemy
2
+ module Ingredients
3
+ class DatetimeView < BaseView
4
+ attr_reader :date_format
5
+
6
+ # @param ingredient [Alchemy::Ingredient]
7
+ # @param date_format [String] The date format to use. Use either a strftime format string, a I18n format symbol or "rfc822".
8
+ def initialize(ingredient, date_format: nil, html_options: {})
9
+ super(ingredient)
10
+ @date_format = settings_value(:date_format, value: date_format)
11
+ end
12
+
13
+ def call
14
+ if date_format == "rfc822"
15
+ ingredient.value.to_s(:rfc822)
16
+ else
17
+ ::I18n.l(ingredient.value, format: date_format)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,40 @@
1
+ module Alchemy
2
+ module Ingredients
3
+ class FileView < BaseView
4
+ delegate :attachment, to: :ingredient
5
+
6
+ # @param ingredient [Alchemy::Ingredient]
7
+ # @param link_text [String] The link text. If not given, the ingredients link_text setting or the attachments name will be used.
8
+ # @param html_options [Hash] Options that will be passed to the a tag.
9
+ def initialize(ingredient, link_text: nil, html_options: {})
10
+ super(ingredient, html_options: html_options)
11
+ @link_text = settings_value(:link_text, value: link_text, default: attachment&.name)
12
+ end
13
+
14
+ def call
15
+ link_to(
16
+ link_text,
17
+ attachment.url(
18
+ download: true,
19
+ name: attachment.slug,
20
+ format: attachment.suffix
21
+ ),
22
+ {
23
+ class: ingredient.css_class.presence,
24
+ title: ingredient.title.presence
25
+ }.merge(html_options)
26
+ )
27
+ end
28
+
29
+ def render?
30
+ !attachment.nil?
31
+ end
32
+
33
+ private
34
+
35
+ def link_text
36
+ ingredient.link_text.presence || @link_text
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,20 @@
1
+ module Alchemy
2
+ module Ingredients
3
+ class HeadlineView < BaseView
4
+ def initialize(ingredient, level: nil, html_options: {})
5
+ super(ingredient, html_options: html_options)
6
+ @level = level
7
+ end
8
+
9
+ def call
10
+ content_tag "h#{@level || ingredient.level}",
11
+ ingredient.value,
12
+ id: ingredient.dom_id.presence,
13
+ class: [
14
+ ingredient.size ? "h#{ingredient.size}" : nil,
15
+ html_options[:class]
16
+ ]
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,9 @@
1
+ module Alchemy
2
+ module Ingredients
3
+ class HtmlView < BaseView
4
+ def call
5
+ value.to_s.html_safe
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,25 @@
1
+ module Alchemy
2
+ module Ingredients
3
+ class LinkView < BaseView
4
+ attr_reader :link_text
5
+
6
+ # @param ingredient [Alchemy::Ingredient]
7
+ # @param text [String] The link text. If not given, the ingredient's text setting or the value will be used.
8
+ # @param html_options [Hash] Options that will be passed to the a tag.
9
+ def initialize(ingredient, text: nil, html_options: {})
10
+ super(ingredient, html_options: html_options)
11
+ @link_text = settings_value(:text, value: text, default: value)
12
+ end
13
+
14
+ def call
15
+ link_to(link_text, value, {target: link_target}.merge(html_options))
16
+ end
17
+
18
+ private
19
+
20
+ def link_target
21
+ (ingredient.link_target == "blank") ? "_blank" : nil
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,11 @@
1
+ module Alchemy
2
+ module Ingredients
3
+ class NodeView < BaseView
4
+ delegate :node, to: :ingredient
5
+
6
+ def call
7
+ render(node)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module Alchemy
2
+ module Ingredients
3
+ class PageView < BaseView
4
+ delegate :page, to: :ingredient
5
+
6
+ def call
7
+ link_to page.name, alchemy.show_page_path(urlname: page.urlname)
8
+ end
9
+
10
+ def render?
11
+ !!page
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Alchemy
4
+ module Ingredients
5
+ # Renders a picture ingredient view
6
+ class PictureView < BaseView
7
+ attr_reader :ingredient,
8
+ :show_caption,
9
+ :disable_link,
10
+ :srcset,
11
+ :sizes,
12
+ :html_options,
13
+ :picture_options,
14
+ :picture
15
+
16
+ # @param ingredient [Alchemy::Ingredient]
17
+ # @param show_caption [Boolean] (true) Whether to show a caption or not, even if present on the picture.
18
+ # @param disable_link [Boolean] (false) Whether to disable the link even if the picture has a link.
19
+ # @param srcset [Array<String>] An array of srcset sizes that will generate variants of the picture.
20
+ # @param sizes [Array<String>] An array of sizes that will be passed to the img tag.
21
+ # @param picture_options [Hash] Options that will be passed to the picture url. See {Alchemy::PictureVariant} for options.
22
+ # @param html_options [Hash] Options that will be passed to the img tag.
23
+ # @see Alchemy::PictureVariant
24
+ def initialize(
25
+ ingredient,
26
+ show_caption: nil,
27
+ disable_link: nil,
28
+ srcset: nil,
29
+ sizes: nil,
30
+ picture_options: {},
31
+ html_options: {}
32
+ )
33
+ super(ingredient)
34
+ @show_caption = settings_value(:show_caption, value: show_caption, default: true)
35
+ @disable_link = settings_value(:disable_link, value: disable_link, default: false)
36
+ @srcset = settings_value(:srcset, value: srcset, default: [])
37
+ @sizes = settings_value(:sizes, value: sizes, default: [])
38
+ @picture_options = picture_options || {}
39
+ @html_options = html_options || {}
40
+ @picture = ingredient.picture
41
+ end
42
+
43
+ def call
44
+ return if picture.blank?
45
+
46
+ output = caption ? img_tag + caption : img_tag
47
+
48
+ if is_linked?
49
+ output = link_to(output, url_for(ingredient.link), {
50
+ title: ingredient.link_title.presence,
51
+ target: (ingredient.link_target == "blank") ? "_blank" : nil,
52
+ data: {link_target: ingredient.link_target.presence}
53
+ })
54
+ end
55
+
56
+ if caption
57
+ content_tag(:figure, output, {class: ingredient.css_class.presence}.merge(html_options))
58
+ else
59
+ output
60
+ end
61
+ end
62
+
63
+ private
64
+
65
+ def caption
66
+ return unless show_caption?
67
+
68
+ @_caption ||= content_tag(:figcaption, ingredient.caption)
69
+ end
70
+
71
+ def src
72
+ ingredient.picture_url(picture_options)
73
+ end
74
+
75
+ def img_tag
76
+ @_img_tag ||= image_tag(
77
+ src, {
78
+ alt: alt_text,
79
+ title: ingredient.title.presence,
80
+ class: caption ? nil : ingredient.css_class.presence,
81
+ srcset: srcset_options.join(", ").presence,
82
+ sizes: sizes.join(", ").presence
83
+ }.merge(caption ? {} : html_options)
84
+ )
85
+ end
86
+
87
+ def show_caption?
88
+ show_caption && ingredient.caption.present?
89
+ end
90
+
91
+ def is_linked?
92
+ !disable_link && ingredient.link.present?
93
+ end
94
+
95
+ def srcset_options
96
+ srcset.map do |size|
97
+ url = ingredient.picture_url(size: size)
98
+ width, height = size.split("x")
99
+ width.present? ? "#{url} #{width}w" : "#{url} #{height}h"
100
+ end
101
+ end
102
+
103
+ def alt_text
104
+ ingredient.alt_tag.presence || html_options.delete(:alt) || ingredient.picture.name&.humanize
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,22 @@
1
+ module Alchemy
2
+ module Ingredients
3
+ class RichtextView < BaseView
4
+ attr_reader :plain_text
5
+
6
+ # @param ingredient [Alchemy::Ingredient]
7
+ # @param plain_text [Boolean] (false) Whether to show as plain text or with markup
8
+ def initialize(ingredient, plain_text: nil, html_options: {})
9
+ super(ingredient)
10
+ @plain_text = settings_value(:plain_text, value: plain_text, default: false)
11
+ end
12
+
13
+ def call
14
+ if plain_text
15
+ ingredient.stripped_body
16
+ else
17
+ value.to_s.html_safe
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,6 @@
1
+ module Alchemy
2
+ module Ingredients
3
+ class SelectView < BaseView
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,41 @@
1
+ module Alchemy
2
+ module Ingredients
3
+ class TextView < BaseView
4
+ attr_reader :disable_link
5
+
6
+ delegate :dom_id, :link, :link_title, :link_target,
7
+ to: :ingredient
8
+
9
+ # @param ingredient [Alchemy::Ingredient]
10
+ # @param disable_link [Boolean] (false) Whether to disable the link even if the picture has a link.
11
+ # @param html_options [Hash] Options that will be passed to the a tag.
12
+ def initialize(ingredient, disable_link: nil, html_options: {})
13
+ super(ingredient, html_options: html_options)
14
+ @disable_link = settings_value(:disable_link, value: disable_link, default: false)
15
+ end
16
+
17
+ def call
18
+ if disable_link?
19
+ dom_id.present? ? anchor : value
20
+ else
21
+ link_to(value, url_for(link), {
22
+ id: dom_id.presence,
23
+ title: link_title,
24
+ target: ((link_target == "blank") ? "_blank" : nil),
25
+ data: {link_target: link_target}
26
+ }.merge(html_options))
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def anchor
33
+ content_tag(:a, value, {id: dom_id}.merge(html_options))
34
+ end
35
+
36
+ def disable_link?
37
+ link.blank? || disable_link
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,39 @@
1
+ module Alchemy
2
+ module Ingredients
3
+ class VideoView < BaseView
4
+ delegate :attachment, to: :ingredient
5
+
6
+ def call
7
+ content_tag(:video, html_options) do
8
+ tag(:source, src: src, type: attachment.file_mime_type)
9
+ end
10
+ end
11
+
12
+ def render?
13
+ !attachment.nil?
14
+ end
15
+
16
+ private
17
+
18
+ def src
19
+ alchemy.show_attachment_path(
20
+ attachment,
21
+ format: attachment.suffix
22
+ )
23
+ end
24
+
25
+ def html_options
26
+ {
27
+ controls: ingredient.controls,
28
+ autoplay: ingredient.autoplay,
29
+ loop: ingredient.loop,
30
+ muted: ingredient.muted,
31
+ playsinline: ingredient.playsinline,
32
+ preload: ingredient.preload.presence,
33
+ width: ingredient.width.presence,
34
+ height: ingredient.height.presence
35
+ }.merge(@html_options)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -52,7 +52,7 @@ module Alchemy
52
52
  render_errors_or_redirect(
53
53
  @attachment,
54
54
  admin_attachments_path(search_filter_params),
55
- Alchemy.t("File successfully updated"),
55
+ Alchemy.t("File successfully updated")
56
56
  )
57
57
  end
58
58
  end
@@ -68,7 +68,7 @@ module Alchemy
68
68
  @attachment = Attachment.find(params[:id])
69
69
  send_file @attachment.file.path, {
70
70
  filename: @attachment.file_name,
71
- type: @attachment.file_mime_type,
71
+ type: @attachment.file_mime_type
72
72
  }
73
73
  end
74
74
 
@@ -77,8 +77,7 @@ module Alchemy
77
77
  def search_filter_params
78
78
  @_search_filter_params ||= params.except(*COMMON_SEARCH_FILTER_EXCLUDES + [:attachment]).permit(
79
79
  *common_search_filter_includes + [
80
- :form_field_id,
81
- :content_id,
80
+ :form_field_id
82
81
  ]
83
82
  )
84
83
  end
@@ -54,7 +54,7 @@ module Alchemy
54
54
  else
55
55
  respond_to do |format|
56
56
  format.html { render "500", status: 500 }
57
- format.json { render json: { message: @notice }, status: 500 }
57
+ format.json { render json: {message: @notice}, status: 500 }
58
58
  end
59
59
  end
60
60
  end
@@ -101,7 +101,7 @@ module Alchemy
101
101
  flash[:notice] = Alchemy.t(flash_notice)
102
102
  do_redirect_to redirect_url
103
103
  else
104
- render action: (params[:action] == "update" ? "edit" : "new")
104
+ render action: ((params[:action] == "update") ? "edit" : "new")
105
105
  end
106
106
  end
107
107
 
@@ -138,11 +138,11 @@ module Alchemy
138
138
  #
139
139
  def current_alchemy_site
140
140
  @current_alchemy_site ||= begin
141
- site_id = params[:site_id] || session[:alchemy_site_id]
142
- site = Site.find_by(id: site_id) || super
143
- session[:alchemy_site_id] = site&.id
144
- site
145
- end
141
+ site_id = params[:site_id] || session[:alchemy_site_id]
142
+ site = Site.find_by(id: site_id) || super
143
+ session[:alchemy_site_id] = site&.id
144
+ site
145
+ end
146
146
  end
147
147
 
148
148
  def notify_error_tracker(exception)
@@ -3,7 +3,7 @@
3
3
  module Alchemy
4
4
  module Admin
5
5
  class ClipboardController < Alchemy::Admin::BaseController
6
- REMARKABLE_TYPES = %w(elements pages)
6
+ REMARKABLE_TYPES = %w[elements pages]
7
7
 
8
8
  authorize_resource class: :alchemy_admin_clipboard
9
9
  before_action :set_clipboard
@@ -20,7 +20,7 @@ module Alchemy
20
20
  unless @clipboard.detect { |item| item["id"] == remarkable_params[:remarkable_id] }
21
21
  @clipboard << {
22
22
  "id" => remarkable_params[:remarkable_id],
23
- "action" => params[:remove] ? "cut" : "copy",
23
+ "action" => params[:remove] ? "cut" : "copy"
24
24
  }
25
25
  end
26
26
  respond_to do |format|
@@ -29,10 +29,11 @@ module Alchemy
29
29
  @page_version = PageVersion.find(params[:element][:page_version_id])
30
30
  @page = @page_version.page
31
31
  Element.transaction do
32
- if @paste_from_clipboard = params[:paste_from_clipboard].present?
33
- @element = paste_element_from_clipboard
32
+ @paste_from_clipboard = params[:paste_from_clipboard].present?
33
+ @element = if @paste_from_clipboard
34
+ paste_element_from_clipboard
34
35
  else
35
- @element = Element.new(create_element_params)
36
+ Element.new(create_element_params)
36
37
  end
37
38
  if @page.definition["insert_elements_at"] == "top"
38
39
  @insert_at_top = true
@@ -49,24 +50,23 @@ module Alchemy
49
50
  end
50
51
  end
51
52
 
52
- # Updates the element.
53
- #
54
- # And update all contents in the elements by calling update_contents.
53
+ # Updates the element and all ingredients in the element.
55
54
  #
56
55
  def update
57
56
  @page = @element.page
58
57
 
59
- if element_params.key?(:ingredients_attributes)
60
- update_element_with_ingredients
58
+ if @element.update(element_params)
59
+ @element_validated = true
61
60
  else
62
- update_element_with_contents
61
+ element_update_error
62
+ @error_messages = @element.ingredient_error_messages
63
63
  end
64
64
  end
65
65
 
66
66
  def destroy
67
- @richtext_ids = @element.richtext_contents_ids + @element.richtext_ingredients_ids
67
+ @richtext_ids = @element.richtext_ingredients_ids
68
68
  @element.destroy
69
- @notice = Alchemy.t("Successfully deleted element") % { element: @element.display_name }
69
+ @notice = Alchemy.t("Successfully deleted element") % {element: @element.display_name}
70
70
  end
71
71
 
72
72
  def publish
@@ -81,7 +81,7 @@ module Alchemy
81
81
  # element over from another nestable element
82
82
  Element.find_by(id: element_id).update_columns(
83
83
  parent_element_id: params[:parent_element_id],
84
- position: position,
84
+ position: position
85
85
  )
86
86
  end
87
87
  # Need to manually touch the parent because Rails does not do it
@@ -96,26 +96,38 @@ module Alchemy
96
96
  @page = @element.page
97
97
  # We do not want to trigger the touch callback or any validations
98
98
  @element.update_columns(folded: !@element.folded)
99
+ # Fold all nested elements if folded
100
+ if @element.folded?
101
+ ids = collapse_nested_elements_ids(@element)
102
+ Alchemy::Element.where(id: ids).update_all(folded: true)
103
+ end
99
104
  end
100
105
 
101
106
  private
102
107
 
108
+ def collapse_nested_elements_ids(element)
109
+ ids = []
110
+ element.all_nested_elements.includes(:all_nested_elements).reject(&:compact?).each do |nested_element|
111
+ ids.push nested_element.id if nested_element.expanded?
112
+ ids.concat collapse_nested_elements_ids(nested_element) if nested_element.all_nested_elements.reject(&:compact?).any?
113
+ end
114
+ ids
115
+ end
116
+
103
117
  def element_includes
104
118
  [
105
119
  {
106
- contents: :essence,
107
- ingredients: :related_object,
120
+ ingredients: :related_object
108
121
  },
109
122
  :tags,
110
123
  {
111
124
  all_nested_elements: [
112
125
  {
113
- contents: :essence,
114
- ingredients: :related_object,
126
+ ingredients: :related_object
115
127
  },
116
- :tags,
117
- ],
118
- },
128
+ :tags
129
+ ]
130
+ }
119
131
  ]
120
132
  end
121
133
 
@@ -141,7 +153,7 @@ module Alchemy
141
153
  @source_element,
142
154
  {
143
155
  parent_element_id: create_element_params[:parent_element_id],
144
- page_version_id: @page_version.id,
156
+ page_version_id: @page_version.id
145
157
  }
146
158
  )
147
159
  if element_from_clipboard["action"] == "cut"
@@ -152,10 +164,6 @@ module Alchemy
152
164
  element
153
165
  end
154
166
 
155
- def contents_params
156
- params.fetch(:contents, {}).permit!
157
- end
158
-
159
167
  def element_params
160
168
  params.fetch(:element, {}).permit(:tag_list, ingredients_attributes: {})
161
169
  end
@@ -164,28 +172,10 @@ module Alchemy
164
172
  params.require(:element).permit(:name, :page_version_id, :parent_element_id)
165
173
  end
166
174
 
167
- def update_element_with_ingredients
168
- if @element.update(element_params)
169
- @element_validated = true
170
- else
171
- element_update_error
172
- @error_messages = @element.ingredient_error_messages
173
- end
174
- end
175
-
176
- def update_element_with_contents
177
- if @element.update_contents(contents_params)
178
- @element_validated = @element.update(element_params)
179
- else
180
- element_update_error
181
- @error_messages = @element.essence_error_messages
182
- end
183
- end
184
-
185
175
  def element_update_error
186
176
  @element_validated = false
187
177
  @notice = Alchemy.t("Validation failed")
188
- @error_message = "<h2>#{@notice}</h2><p>#{Alchemy.t(:content_validations_headline)}</p>".html_safe
178
+ @error_message = "<h2>#{@notice}</h2><p>#{Alchemy.t(:ingredient_validations_headline)}</p>".html_safe
189
179
  end
190
180
  end
191
181
  end
@@ -14,7 +14,7 @@ module Alchemy
14
14
  def new
15
15
  @language = Language.new(
16
16
  site: @current_site,
17
- page_layout: Config.get(:default_language)["page_layout"],
17
+ page_layout: Config.get(:default_language)["page_layout"]
18
18
  )
19
19
  end
20
20
 
@@ -12,7 +12,7 @@ module Alchemy
12
12
  def new
13
13
  @node = Node.new(
14
14
  parent_id: params[:parent_id],
15
- language: @current_language,
15
+ language: @current_language
16
16
  )
17
17
  end
18
18
 
@@ -28,7 +28,7 @@ module Alchemy
28
28
  :url,
29
29
  :title,
30
30
  :nofollow,
31
- :external,
31
+ :external
32
32
  )
33
33
  end
34
34
  end