alchemy_cms 7.0.16 → 7.1.0.pre.b1

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 (359) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/backport.yml +36 -0
  3. data/.github/workflows/brakeman-analysis.yml +5 -13
  4. data/.github/workflows/lint.yml +2 -9
  5. data/.github/workflows/stale.yml +2 -5
  6. data/.github/workflows/test.yml +7 -15
  7. data/.gitignore +0 -1
  8. data/.standard.yml +1 -1
  9. data/CHANGELOG.md +144 -51
  10. data/Gemfile +7 -18
  11. data/README.md +10 -8
  12. data/alchemy_cms.gemspec +4 -3
  13. data/app/assets/config/alchemy_manifest.js +0 -1
  14. data/app/assets/javascripts/alchemy/admin.js +1 -19
  15. data/app/assets/javascripts/alchemy/alchemy.confirm_dialog.js.coffee +2 -3
  16. data/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee +19 -34
  17. data/app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee +38 -13
  18. data/app/assets/javascripts/alchemy/alchemy.file_progress.js.coffee +1 -1
  19. data/app/assets/javascripts/alchemy/alchemy.fixed_elements.js +32 -25
  20. data/app/assets/javascripts/alchemy/alchemy.growler.js.coffee +1 -1
  21. data/app/assets/javascripts/alchemy/alchemy.image_overlay.coffee +3 -5
  22. data/app/assets/javascripts/alchemy/alchemy.initializer.js.coffee +0 -57
  23. data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +22 -63
  24. data/app/assets/javascripts/alchemy/alchemy.list_filter.js.coffee +2 -2
  25. data/app/assets/javascripts/alchemy/alchemy.preview.js.coffee +5 -4
  26. data/app/assets/javascripts/alchemy/alchemy.preview_window.js.coffee +5 -5
  27. data/app/assets/javascripts/alchemy/templates/index.js +0 -2
  28. data/app/assets/javascripts/alchemy/templates/node_folder.hbs +1 -1
  29. data/app/assets/javascripts/alchemy/templates/page.hbs +1 -1
  30. data/app/assets/javascripts/alchemy/templates/page_folder.hbs +2 -2
  31. data/app/assets/stylesheets/alchemy/_custom-properties.scss +82 -0
  32. data/app/assets/stylesheets/alchemy/_mixins.scss +38 -30
  33. data/app/assets/stylesheets/alchemy/_variables.scss +12 -5
  34. data/app/assets/stylesheets/alchemy/admin.scss +3 -4
  35. data/app/assets/stylesheets/alchemy/archive.scss +107 -50
  36. data/app/assets/stylesheets/alchemy/attachments.scss +5 -4
  37. data/app/assets/stylesheets/alchemy/buttons.scss +38 -164
  38. data/app/assets/stylesheets/alchemy/dashboard.scss +31 -6
  39. data/app/assets/stylesheets/alchemy/dialogs.scss +12 -28
  40. data/app/assets/stylesheets/alchemy/elements.scss +273 -282
  41. data/app/assets/stylesheets/alchemy/flash.scss +20 -12
  42. data/app/assets/stylesheets/alchemy/forms.scss +21 -34
  43. data/app/assets/stylesheets/alchemy/frame.scss +11 -32
  44. data/app/assets/stylesheets/alchemy/hints.scss +4 -62
  45. data/app/assets/stylesheets/alchemy/image_library.scss +36 -33
  46. data/app/assets/stylesheets/alchemy/labels.scss +4 -1
  47. data/app/assets/stylesheets/alchemy/menubar.scss +7 -6
  48. data/app/assets/stylesheets/alchemy/navigation.scss +27 -15
  49. data/app/assets/stylesheets/alchemy/nodes.scss +11 -7
  50. data/app/assets/stylesheets/alchemy/notices.scss +16 -4
  51. data/app/assets/stylesheets/alchemy/page-select.scss +10 -2
  52. data/app/assets/stylesheets/alchemy/pagination.scss +22 -13
  53. data/app/assets/stylesheets/alchemy/preview_window.scss +4 -8
  54. data/app/assets/stylesheets/alchemy/resource_info.scss +7 -5
  55. data/app/assets/stylesheets/alchemy/selects.scss +49 -42
  56. data/app/assets/stylesheets/alchemy/shoelace.scss +345 -0
  57. data/app/assets/stylesheets/alchemy/sitemap.scss +24 -14
  58. data/app/assets/stylesheets/alchemy/spinner.scss +9 -19
  59. data/app/assets/stylesheets/alchemy/tables.scss +16 -24
  60. data/app/assets/stylesheets/alchemy/tags.scss +4 -0
  61. data/app/assets/stylesheets/alchemy/toolbar.scss +29 -25
  62. data/app/assets/stylesheets/alchemy/upload.scss +140 -89
  63. data/app/assets/stylesheets/tinymce/skins/alchemy/skin.min.css.scss +80 -108
  64. data/app/components/alchemy/admin/node_select.rb +39 -0
  65. data/app/components/alchemy/admin/page_select.rb +42 -0
  66. data/app/components/alchemy/ingredients/audio_view.rb +1 -1
  67. data/app/components/alchemy/ingredients/base_view.rb +1 -1
  68. data/app/components/alchemy/ingredients/boolean_view.rb +1 -1
  69. data/app/components/alchemy/ingredients/datetime_view.rb +3 -4
  70. data/app/components/alchemy/ingredients/file_view.rb +1 -1
  71. data/app/components/alchemy/ingredients/headline_view.rb +7 -16
  72. data/app/components/alchemy/ingredients/link_view.rb +1 -1
  73. data/app/components/alchemy/ingredients/page_view.rb +1 -1
  74. data/app/components/alchemy/ingredients/picture_view.rb +1 -1
  75. data/app/components/alchemy/ingredients/richtext_view.rb +1 -1
  76. data/app/components/alchemy/ingredients/text_view.rb +1 -1
  77. data/app/components/alchemy/ingredients/video_view.rb +1 -1
  78. data/app/controllers/alchemy/admin/base_controller.rb +7 -32
  79. data/app/controllers/alchemy/admin/elements_controller.rb +63 -35
  80. data/app/controllers/alchemy/admin/languages_controller.rb +2 -3
  81. data/app/controllers/alchemy/admin/layoutpages_controller.rb +0 -19
  82. data/app/controllers/alchemy/admin/pages_controller.rb +4 -5
  83. data/app/controllers/alchemy/admin/resources_controller.rb +1 -1
  84. data/app/controllers/alchemy/base_controller.rb +4 -2
  85. data/app/controllers/alchemy/messages_controller.rb +1 -1
  86. data/app/controllers/concerns/alchemy/admin/current_language.rb +1 -5
  87. data/app/controllers/concerns/alchemy/admin/uploader_responses.rb +1 -1
  88. data/app/decorators/alchemy/element_editor.rb +0 -2
  89. data/app/helpers/alchemy/admin/attachments_helper.rb +6 -5
  90. data/app/helpers/alchemy/admin/base_helper.rb +17 -12
  91. data/app/helpers/alchemy/admin/ingredients_helper.rb +4 -1
  92. data/app/helpers/alchemy/admin/pages_helper.rb +5 -11
  93. data/app/helpers/alchemy/base_helper.rb +47 -13
  94. data/app/javascript/alchemy_admin/components/alchemy_html_element.js +129 -0
  95. data/app/javascript/alchemy_admin/components/button.js +59 -0
  96. data/app/javascript/alchemy_admin/components/char_counter.js +40 -0
  97. data/app/javascript/alchemy_admin/components/datepicker.js +39 -0
  98. data/app/javascript/alchemy_admin/components/dialog_link.js +45 -0
  99. data/app/javascript/alchemy_admin/components/element_editor/publish_element_button.js +36 -0
  100. data/app/javascript/alchemy_admin/components/element_editor.js +553 -0
  101. data/app/javascript/alchemy_admin/components/ingredient_group.js +54 -0
  102. data/app/javascript/alchemy_admin/components/link_buttons/link_button.js +48 -0
  103. data/app/javascript/alchemy_admin/components/link_buttons/unlink_button.js +38 -0
  104. data/app/javascript/alchemy_admin/components/link_buttons.js +79 -0
  105. data/app/javascript/alchemy_admin/components/node_select.js +45 -0
  106. data/app/javascript/alchemy_admin/components/overlay.js +18 -0
  107. data/app/javascript/alchemy_admin/components/page_select.js +63 -0
  108. data/app/javascript/alchemy_admin/components/remote_select.js +134 -0
  109. data/app/javascript/alchemy_admin/components/select.js +12 -0
  110. data/app/javascript/alchemy_admin/components/spinner.js +31 -0
  111. data/app/javascript/alchemy_admin/components/tinymce.js +146 -0
  112. data/app/javascript/alchemy_admin/components/uploader/file_upload.js +266 -0
  113. data/app/javascript/alchemy_admin/components/uploader/progress.js +258 -0
  114. data/app/javascript/alchemy_admin/components/uploader.js +132 -0
  115. data/app/javascript/alchemy_admin/dirty.js +49 -0
  116. data/app/javascript/alchemy_admin/file_editors.js +1 -1
  117. data/app/javascript/alchemy_admin/gui.js +14 -0
  118. data/app/javascript/alchemy_admin/i18n.js +12 -8
  119. data/app/javascript/alchemy_admin/image_cropper.js +6 -3
  120. data/app/javascript/alchemy_admin/image_loader.js +7 -15
  121. data/app/javascript/alchemy_admin/ingredient_anchor_link.js +2 -5
  122. data/app/javascript/alchemy_admin/initializer.js +65 -0
  123. data/app/javascript/alchemy_admin/locales/en.js +31 -0
  124. data/app/javascript/alchemy_admin/picture_editors.js +2 -2
  125. data/app/javascript/alchemy_admin/picture_selector.js +38 -0
  126. data/app/javascript/alchemy_admin/please_wait_overlay.js +8 -0
  127. data/app/javascript/alchemy_admin/sortable_elements.js +78 -0
  128. data/app/javascript/alchemy_admin/spinner.js +36 -0
  129. data/app/javascript/alchemy_admin/tags_autocomplete.js +46 -0
  130. data/app/javascript/alchemy_admin/utils/ajax.js +6 -5
  131. data/app/javascript/alchemy_admin/utils/dom_helpers.js +20 -0
  132. data/app/javascript/alchemy_admin/utils/format.js +11 -0
  133. data/app/javascript/alchemy_admin/utils/string_conversions.js +10 -0
  134. data/app/javascript/alchemy_admin.js +70 -13
  135. data/app/javascript/menubar.js +10 -0
  136. data/app/models/alchemy/attachment.rb +9 -11
  137. data/app/models/alchemy/element.rb +11 -0
  138. data/app/models/alchemy/ingredients/audio.rb +0 -11
  139. data/app/models/alchemy/ingredients/datetime.rb +1 -1
  140. data/app/models/alchemy/ingredients/richtext.rb +1 -10
  141. data/app/models/alchemy/ingredients/video.rb +0 -12
  142. data/app/models/alchemy/node.rb +4 -0
  143. data/app/models/alchemy/page/page_elements.rb +2 -11
  144. data/app/models/alchemy/page/page_natures.rb +10 -2
  145. data/app/models/alchemy/page.rb +12 -54
  146. data/app/models/alchemy/picture/url.rb +1 -9
  147. data/app/models/concerns/alchemy/picture_thumbnails.rb +5 -4
  148. data/app/serializers/alchemy/page_tree_serializer.rb +2 -1
  149. data/app/services/alchemy/copy_page.rb +98 -0
  150. data/app/views/alchemy/_menubar.html.erb +17 -13
  151. data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +14 -10
  152. data/app/views/alchemy/admin/attachments/_attachment.html.erb +44 -36
  153. data/app/views/alchemy/admin/attachments/_replace_button.html.erb +15 -21
  154. data/app/views/alchemy/admin/attachments/archive_overlay.js.erb +0 -1
  155. data/app/views/alchemy/admin/attachments/assign.js.erb +1 -1
  156. data/app/views/alchemy/admin/attachments/index.html.erb +6 -4
  157. data/app/views/alchemy/admin/attachments/show.html.erb +8 -8
  158. data/app/views/alchemy/admin/clipboard/clear.js.erb +1 -1
  159. data/app/views/alchemy/admin/clipboard/index.html.erb +3 -7
  160. data/app/views/alchemy/admin/clipboard/insert.js.erb +1 -1
  161. data/app/views/alchemy/admin/crop.html.erb +1 -1
  162. data/app/views/alchemy/admin/dashboard/_locked_pages.html.erb +1 -1
  163. data/app/views/alchemy/admin/dashboard/index.html.erb +13 -11
  164. data/app/views/alchemy/admin/dashboard/info.html.erb +7 -7
  165. data/app/views/alchemy/admin/elements/_add_nested_element_form.html.erb +21 -23
  166. data/app/views/alchemy/admin/elements/_element.html.erb +52 -44
  167. data/app/views/alchemy/admin/elements/_footer.html.erb +1 -1
  168. data/app/views/alchemy/admin/elements/_form.html.erb +1 -1
  169. data/app/views/alchemy/admin/elements/_header.html.erb +11 -12
  170. data/app/views/alchemy/admin/elements/_toolbar.html.erb +33 -45
  171. data/app/views/alchemy/admin/elements/create.js.erb +7 -15
  172. data/app/views/alchemy/admin/elements/destroy.js.erb +0 -2
  173. data/app/views/alchemy/admin/elements/index.html.erb +27 -24
  174. data/app/views/alchemy/admin/elements/new.html.erb +9 -11
  175. data/app/views/alchemy/admin/ingredients/_file_fields.html.erb +2 -2
  176. data/app/views/alchemy/admin/ingredients/_picture_fields.html.erb +3 -3
  177. data/app/views/alchemy/admin/ingredients/_video_fields.html.erb +1 -2
  178. data/app/views/alchemy/admin/languages/_form.html.erb +2 -3
  179. data/app/views/alchemy/admin/languages/_language.html.erb +15 -8
  180. data/app/views/alchemy/admin/languages/_table.html.erb +1 -0
  181. data/app/views/alchemy/admin/layoutpages/_layoutpage.html.erb +28 -16
  182. data/app/views/alchemy/admin/layoutpages/edit.html.erb +1 -1
  183. data/app/views/alchemy/admin/layoutpages/index.html.erb +2 -2
  184. data/app/views/alchemy/admin/legacy_page_urls/_legacy_page_url.html.erb +12 -8
  185. data/app/views/alchemy/admin/legacy_page_urls/_new.html.erb +1 -1
  186. data/app/views/alchemy/admin/nodes/_form.html.erb +20 -21
  187. data/app/views/alchemy/admin/nodes/_node.html.erb +39 -34
  188. data/app/views/alchemy/admin/nodes/index.html.erb +1 -1
  189. data/app/views/alchemy/admin/pages/_anchor_link.html.erb +4 -4
  190. data/app/views/alchemy/admin/pages/_create_language_form.html.erb +2 -2
  191. data/app/views/alchemy/admin/pages/_current_page.html.erb +1 -1
  192. data/app/views/alchemy/admin/pages/_external_link.html.erb +4 -4
  193. data/app/views/alchemy/admin/pages/_file_link.html.erb +5 -5
  194. data/app/views/alchemy/admin/pages/_form.html.erb +10 -21
  195. data/app/views/alchemy/admin/pages/_internal_link.html.erb +4 -4
  196. data/app/views/alchemy/admin/pages/_locked_page.html.erb +2 -2
  197. data/app/views/alchemy/admin/pages/_new_page_form.html.erb +4 -17
  198. data/app/views/alchemy/admin/pages/_page.html.erb +76 -72
  199. data/app/views/alchemy/admin/pages/_page_infos.html.erb +23 -7
  200. data/app/views/alchemy/admin/pages/_page_layout_filter.html.erb +2 -1
  201. data/app/views/alchemy/admin/pages/_page_status.html.erb +11 -21
  202. data/app/views/alchemy/admin/pages/_publication_fields.html.erb +2 -5
  203. data/app/views/alchemy/admin/pages/_table.html.erb +1 -1
  204. data/app/views/alchemy/admin/pages/_table_row.html.erb +43 -39
  205. data/app/views/alchemy/admin/pages/_toolbar.html.erb +43 -38
  206. data/app/views/alchemy/admin/pages/configure.html.erb +12 -14
  207. data/app/views/alchemy/admin/pages/edit.html.erb +80 -103
  208. data/app/views/alchemy/admin/pages/info.html.erb +20 -11
  209. data/app/views/alchemy/admin/pages/link.html.erb +22 -16
  210. data/app/views/alchemy/admin/pages/new.html.erb +9 -11
  211. data/app/views/alchemy/admin/pages/unlock.js.erb +10 -3
  212. data/app/views/alchemy/admin/partials/_language_tree_select.html.erb +15 -13
  213. data/app/views/alchemy/admin/partials/_main_navigation_entry.html.erb +3 -5
  214. data/app/views/alchemy/admin/partials/_routes.html.erb +10 -2
  215. data/app/views/alchemy/admin/partials/_site_select.html.erb +6 -5
  216. data/app/views/alchemy/admin/partials/_toolbar_button.html.erb +28 -23
  217. data/app/views/alchemy/admin/pictures/_archive.html.erb +5 -5
  218. data/app/views/alchemy/admin/pictures/_archive_overlay.html.erb +1 -1
  219. data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +21 -23
  220. data/app/views/alchemy/admin/pictures/_infos.html.erb +2 -6
  221. data/app/views/alchemy/admin/pictures/_picture.html.erb +15 -17
  222. data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +17 -16
  223. data/app/views/alchemy/admin/pictures/_tag_list.html.erb +1 -1
  224. data/app/views/alchemy/admin/pictures/archive_overlay.js.erb +1 -1
  225. data/app/views/alchemy/admin/pictures/assign.js.erb +1 -1
  226. data/app/views/alchemy/admin/pictures/index.html.erb +34 -30
  227. data/app/views/alchemy/admin/pictures/show.html.erb +3 -3
  228. data/app/views/alchemy/admin/resources/_filter.html.erb +2 -2
  229. data/app/views/alchemy/admin/resources/_form.html.erb +2 -2
  230. data/app/views/alchemy/admin/resources/_per_page_select.html.erb +1 -1
  231. data/app/views/alchemy/admin/resources/_resource.html.erb +16 -9
  232. data/app/views/alchemy/admin/resources/_table.html.erb +4 -1
  233. data/app/views/alchemy/admin/resources/index.html.erb +22 -19
  234. data/app/views/alchemy/admin/sites/index.html.erb +2 -1
  235. data/app/views/alchemy/admin/styleguide/index.html.erb +54 -28
  236. data/app/views/alchemy/admin/tags/_tag.html.erb +16 -18
  237. data/app/views/alchemy/admin/tags/index.html.erb +15 -12
  238. data/app/views/alchemy/admin/tinymce/_setup.html.erb +29 -0
  239. data/app/views/alchemy/admin/uploader/_button.html.erb +23 -29
  240. data/app/views/alchemy/admin/uploader/_setup.html.erb +3 -8
  241. data/app/views/alchemy/base/500.html.erb +1 -1
  242. data/app/views/alchemy/base/error_notice.js.erb +0 -1
  243. data/app/views/alchemy/ingredients/_boolean_editor.html.erb +1 -1
  244. data/app/views/alchemy/ingredients/_datetime_editor.html.erb +2 -3
  245. data/app/views/alchemy/ingredients/_file_editor.html.erb +5 -5
  246. data/app/views/alchemy/ingredients/_link_editor.html.erb +1 -1
  247. data/app/views/alchemy/ingredients/_node_editor.html.erb +6 -19
  248. data/app/views/alchemy/ingredients/_page_editor.html.erb +7 -19
  249. data/app/views/alchemy/ingredients/_picture_editor.html.erb +2 -2
  250. data/app/views/alchemy/ingredients/_richtext_editor.html.erb +6 -15
  251. data/app/views/alchemy/ingredients/_select_editor.html.erb +2 -1
  252. data/app/views/alchemy/ingredients/_text_editor.html.erb +1 -1
  253. data/app/views/alchemy/ingredients/shared/_anchor.html.erb +1 -1
  254. data/app/views/alchemy/ingredients/shared/_link_tools.html.erb +10 -20
  255. data/app/views/alchemy/ingredients/shared/_picture_tools.html.erb +42 -49
  256. data/app/views/kaminari/alchemy/_first_page.html.erb +4 -2
  257. data/app/views/kaminari/alchemy/_gap.html.erb +1 -1
  258. data/app/views/kaminari/alchemy/_last_page.html.erb +4 -2
  259. data/app/views/kaminari/alchemy/_next_page.html.erb +4 -2
  260. data/app/views/kaminari/alchemy/_prev_page.html.erb +4 -2
  261. data/app/views/layouts/alchemy/admin.html.erb +10 -29
  262. data/config/alchemy/modules.yml +30 -30
  263. data/config/importmap.rb +10 -1
  264. data/config/initializers/rails_live_reload.rb +13 -0
  265. data/config/locales/alchemy.en.yml +23 -9
  266. data/config/routes.rb +3 -2
  267. data/lib/alchemy/auth_accessors.rb +6 -1
  268. data/lib/alchemy/controller_actions.rb +17 -4
  269. data/lib/alchemy/dev_support/live_reload_watcher.rb +5 -0
  270. data/lib/alchemy/engine.rb +8 -2
  271. data/lib/alchemy/forms/builder.rb +18 -12
  272. data/lib/alchemy/modules.rb +2 -2
  273. data/lib/alchemy/permissions.rb +1 -1
  274. data/lib/alchemy/resources_helper.rb +3 -3
  275. data/lib/alchemy/routing_constraints.rb +1 -1
  276. data/lib/alchemy/test_support/capybara_helpers.rb +8 -5
  277. data/lib/alchemy/test_support/rspec_matchers.rb +14 -0
  278. data/lib/alchemy/test_support/shared_uploader_examples.rb +1 -1
  279. data/lib/alchemy/tinymce.rb +8 -3
  280. data/lib/alchemy/version.rb +1 -1
  281. data/lib/tasks/alchemy/tidy.rake +1 -0
  282. data/package.json +14 -5
  283. data/vendor/assets/fonts/remixicon.eot +0 -0
  284. data/vendor/assets/fonts/remixicon.svg +7816 -0
  285. data/vendor/assets/fonts/remixicon.ttf +0 -0
  286. data/vendor/assets/fonts/remixicon.woff +0 -0
  287. data/vendor/assets/fonts/remixicon.woff2 +0 -0
  288. data/vendor/assets/stylesheets/remixicon.scss +10480 -0
  289. metadata +87 -97
  290. data/.gem_release.yml +0 -8
  291. data/app/assets/javascripts/alchemy/alchemy.autocomplete.js.coffee +0 -30
  292. data/app/assets/javascripts/alchemy/alchemy.base.js.coffee +0 -53
  293. data/app/assets/javascripts/alchemy/alchemy.buttons.js.coffee +0 -45
  294. data/app/assets/javascripts/alchemy/alchemy.char_counter.js.coffee +0 -19
  295. data/app/assets/javascripts/alchemy/alchemy.dirty.js.coffee +0 -59
  296. data/app/assets/javascripts/alchemy/alchemy.dragndrop.js.coffee +0 -79
  297. data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +0 -267
  298. data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +0 -27
  299. data/app/assets/javascripts/alchemy/alchemy.spinner.js +0 -32
  300. data/app/assets/javascripts/alchemy/alchemy.tooltips.coffee +0 -10
  301. data/app/assets/javascripts/alchemy/alchemy.uploader.js.coffee +0 -131
  302. data/app/assets/javascripts/alchemy/menubar.js.coffee +0 -8
  303. data/app/assets/javascripts/alchemy/node_select.js +0 -39
  304. data/app/assets/javascripts/alchemy/page_select.js +0 -46
  305. data/app/assets/javascripts/alchemy/templates/node.hbs +0 -16
  306. data/app/assets/javascripts/alchemy/templates/spinner.hbs +0 -7
  307. data/app/assets/stylesheets/alchemy/jquery-ui.scss +0 -435
  308. data/app/javascript/alchemy_admin/datepicker.js +0 -40
  309. data/app/javascript/alchemy_admin/tinymce.js +0 -146
  310. data/app/javascript/alchemy_admin/translations.js +0 -32
  311. data/app/views/alchemy/admin/elements/fold.js.erb +0 -33
  312. data/app/views/alchemy/admin/elements/order.js.erb +0 -11
  313. data/app/views/alchemy/admin/elements/publish.js.erb +0 -21
  314. data/app/views/alchemy/admin/elements/update.js.erb +0 -27
  315. data/vendor/assets/fonts/fa-regular-400.eot +0 -0
  316. data/vendor/assets/fonts/fa-regular-400.svg +0 -803
  317. data/vendor/assets/fonts/fa-regular-400.ttf +0 -0
  318. data/vendor/assets/fonts/fa-regular-400.woff +0 -0
  319. data/vendor/assets/fonts/fa-regular-400.woff2 +0 -0
  320. data/vendor/assets/fonts/fa-solid-900.eot +0 -0
  321. data/vendor/assets/fonts/fa-solid-900.svg +0 -4938
  322. data/vendor/assets/fonts/fa-solid-900.ttf +0 -0
  323. data/vendor/assets/fonts/fa-solid-900.woff +0 -0
  324. data/vendor/assets/fonts/fa-solid-900.woff2 +0 -0
  325. data/vendor/assets/javascripts/fileupload/jquery.fileupload-process.js +0 -178
  326. data/vendor/assets/javascripts/fileupload/jquery.fileupload-validate.js +0 -125
  327. data/vendor/assets/javascripts/fileupload/jquery.fileupload.js +0 -1502
  328. data/vendor/assets/javascripts/fileupload/jquery.iframe-transport.js +0 -224
  329. data/vendor/assets/javascripts/jquery-ui/data.js +0 -45
  330. data/vendor/assets/javascripts/jquery-ui/ie.js +0 -20
  331. data/vendor/assets/javascripts/jquery-ui/keycode.js +0 -51
  332. data/vendor/assets/javascripts/jquery-ui/plugin.js +0 -49
  333. data/vendor/assets/javascripts/jquery-ui/safe-active-element.js +0 -46
  334. data/vendor/assets/javascripts/jquery-ui/safe-blur.js +0 -27
  335. data/vendor/assets/javascripts/jquery-ui/scroll-parent.js +0 -50
  336. data/vendor/assets/javascripts/jquery-ui/unique-id.js +0 -54
  337. data/vendor/assets/javascripts/jquery-ui/version.js +0 -20
  338. data/vendor/assets/javascripts/jquery-ui/widget.js +0 -754
  339. data/vendor/assets/javascripts/jquery-ui/widgets/draggable.js +0 -1268
  340. data/vendor/assets/javascripts/jquery-ui/widgets/mouse.js +0 -241
  341. data/vendor/assets/javascripts/jquery-ui/widgets/sortable.js +0 -1623
  342. data/vendor/assets/javascripts/jquery-ui/widgets/tabs.js +0 -931
  343. data/vendor/assets/javascripts/jquery_plugins/jquery.scrollTo.min.js +0 -7
  344. data/vendor/assets/javascripts/jquery_plugins/jquery.ui.tabspaging.js +0 -296
  345. data/vendor/assets/stylesheets/fontawesome/_animated.scss +0 -20
  346. data/vendor/assets/stylesheets/fontawesome/_bordered-pulled.scss +0 -20
  347. data/vendor/assets/stylesheets/fontawesome/_core.scss +0 -21
  348. data/vendor/assets/stylesheets/fontawesome/_fixed-width.scss +0 -6
  349. data/vendor/assets/stylesheets/fontawesome/_icons.scss +0 -1441
  350. data/vendor/assets/stylesheets/fontawesome/_larger.scss +0 -23
  351. data/vendor/assets/stylesheets/fontawesome/_list.scss +0 -18
  352. data/vendor/assets/stylesheets/fontawesome/_mixins.scss +0 -56
  353. data/vendor/assets/stylesheets/fontawesome/_rotated-flipped.scss +0 -24
  354. data/vendor/assets/stylesheets/fontawesome/_screen-reader.scss +0 -5
  355. data/vendor/assets/stylesheets/fontawesome/_stacked.scss +0 -31
  356. data/vendor/assets/stylesheets/fontawesome/_variables.scss +0 -1458
  357. data/vendor/assets/stylesheets/fontawesome/fontawesome.scss +0 -16
  358. data/vendor/assets/stylesheets/fontawesome/regular.scss +0 -23
  359. data/vendor/assets/stylesheets/fontawesome/solid.scss +0 -24
@@ -138,29 +138,27 @@ module Alchemy
138
138
  def icon_css_class
139
139
  case file_mime_type
140
140
  when "application/pdf"
141
- "file-pdf"
142
- when "application/msword"
143
- "file-word"
141
+ "file-pdf-2"
144
142
  when *TEXT_FILE_TYPES
145
- "file-alt"
143
+ "file-text"
146
144
  when *EXCEL_FILE_TYPES
147
- "file-excel"
145
+ "file-excel-2"
148
146
  when *POWERPOINT_FILE_TYPES
149
- "file-powerpoint"
147
+ "file-ppt-2"
150
148
  when *WORD_FILE_TYPES
151
- "file-word"
149
+ "file-word-2"
152
150
  when *VCARD_FILE_TYPES
153
- "address-card"
151
+ "profile"
154
152
  when *ARCHIVE_FILE_TYPES
155
- "file-archive"
153
+ "file-zip"
156
154
  when *AUDIO_FILE_TYPES
157
- "file-audio"
155
+ "file-music"
158
156
  when *IMAGE_FILE_TYPES
159
157
  "file-image"
160
158
  when *VIDEO_FILE_TYPES
161
159
  "file-video"
162
160
  else
163
- "file"
161
+ "file-3"
164
162
  end
165
163
  end
166
164
 
@@ -183,6 +183,17 @@ module Alchemy
183
183
  end
184
184
  end
185
185
 
186
+ # Heavily unoptimized naive way to get all parent ids
187
+ def parent_element_ids
188
+ ids ||= []
189
+ parent = parent_element
190
+ while parent
191
+ ids.push parent.id
192
+ parent = parent.parent_element
193
+ end
194
+ ids
195
+ end
196
+
186
197
  # Returns next public element from same page.
187
198
  #
188
199
  # Pass an element name to get next of this kind.
@@ -26,17 +26,6 @@ module Alchemy
26
26
  def preview_text(max_length = 30)
27
27
  name.to_s[0..max_length - 1]
28
28
  end
29
-
30
- %i[
31
- autoplay
32
- controls
33
- loop
34
- muted
35
- ].each do |method|
36
- define_method(:"#{method}=") do |value|
37
- super(ActiveModel::Type::Boolean.new.cast(value))
38
- end
39
- end
40
29
  end
41
30
  end
42
31
  end
@@ -5,7 +5,7 @@ module Alchemy
5
5
  # A datetime value
6
6
  #
7
7
  class Datetime < Alchemy::Ingredient
8
- allow_settings %i[date_format input_type]
8
+ allow_settings %i[date_format]
9
9
 
10
10
  def value
11
11
  ActiveRecord::Type::DateTime.new.cast(self[:value])
@@ -28,21 +28,12 @@ module Alchemy
28
28
  stripped_body.to_s[0..max_length - 1]
29
29
  end
30
30
 
31
- def element_id
32
- "tinymce_#{id}"
33
- end
34
-
35
31
  def has_tinymce?
36
32
  true
37
33
  end
38
34
 
39
- # Returns true if there is a tinymce setting defined that contains settings.
40
- def has_custom_tinymce_config?
41
- custom_tinymce_config.is_a?(Hash)
42
- end
43
-
44
35
  def custom_tinymce_config
45
- settings[:tinymce]
36
+ settings[:tinymce] || {}
46
37
  end
47
38
 
48
39
  private
@@ -31,18 +31,6 @@ module Alchemy
31
31
  def preview_text(max_length = 30)
32
32
  name.to_s[0..max_length - 1]
33
33
  end
34
-
35
- %i[
36
- autoplay
37
- controls
38
- loop
39
- muted
40
- playsinline
41
- ].each do |method|
42
- define_method(:"#{method}=") do |value|
43
- super(ActiveModel::Type::Boolean.new.cast(value))
44
- end
45
- end
46
34
  end
47
35
  end
48
36
  end
@@ -48,6 +48,10 @@ module Alchemy
48
48
 
49
49
  private
50
50
 
51
+ def searchable_alchemy_resource_associations
52
+ %w[page]
53
+ end
54
+
51
55
  # Reads the element definitions file named +menus.yml+ from +config/alchemy/+ folder.
52
56
  #
53
57
  def read_definitions_file
@@ -37,20 +37,11 @@ module Alchemy
37
37
  #
38
38
  def copy_elements(source, target)
39
39
  repository = source.draft_version.element_repository
40
- elements = repository.not_nested
41
- page_version = target.draft_version
42
- duplicate_elements(elements.unfixed, repository, page_version) +
43
- duplicate_elements(elements.fixed, repository, page_version)
44
- end
45
-
46
- private
47
-
48
- def duplicate_elements(elements, repository, page_version)
49
40
  transaction do
50
41
  Element.acts_as_list_no_update do
51
- elements.each.with_index(1) do |element, position|
42
+ repository.not_nested.each.with_index(1) do |element, position|
52
43
  Alchemy::DuplicateElement.new(element, repository: repository).call(
53
- page_version_id: page_version.id,
44
+ page_version_id: target.draft_version.id,
54
45
  position: position
55
46
  )
56
47
  end
@@ -62,14 +62,22 @@ module Alchemy
62
62
  }
63
63
  end
64
64
 
65
- # Returns the translated status for given status type.
65
+ # Returns the long translated status message for given status type.
66
66
  #
67
67
  # @param [Symbol] status_type
68
68
  #
69
- def status_title(status_type)
69
+ def status_message(status_type)
70
70
  Alchemy.t(status[status_type].to_s, scope: "page_states.#{status_type}")
71
71
  end
72
72
 
73
+ # Returns the sort translated status title for given status type.
74
+ #
75
+ # @param [Symbol] status_type
76
+ #
77
+ def status_title(status_type)
78
+ Alchemy.t(status[status_type].to_s, scope: "page_status_titles.#{status_type}")
79
+ end
80
+
73
81
  # Returns the self#page_layout definition from config/alchemy/page_layouts.yml file.
74
82
  def definition
75
83
  definition = PageLayout.get(page_layout)
@@ -121,8 +121,6 @@ module Alchemy
121
121
  has_one :draft_version, -> { drafts }, class_name: "Alchemy::PageVersion"
122
122
  has_one :public_version, -> { published }, class_name: "Alchemy::PageVersion", autosave: -> { persisted? }
123
123
 
124
- has_many :page_ingredients, class_name: "Alchemy::Ingredients::Page", foreign_key: :related_object_id, dependent: :nullify
125
-
126
124
  before_validation :set_language,
127
125
  if: -> { language.nil? }
128
126
 
@@ -235,23 +233,17 @@ module Alchemy
235
233
  # @return [Alchemy::Page]
236
234
  #
237
235
  def copy(source, differences = {})
238
- transaction do
239
- page = Alchemy::Page.new(attributes_from_source_for_copy(source, differences))
240
- page.tag_list = source.tag_list
241
- if page.save!
242
- copy_elements(source, page)
243
- page
244
- end
245
- end
236
+ Alchemy::CopyPage.new(page: source).call(changed_attributes: differences)
246
237
  end
247
238
 
248
239
  def copy_and_paste(source, new_parent, new_name)
249
- page = copy(source, {
250
- parent: new_parent,
251
- language: new_parent&.language,
252
- name: new_name,
253
- title: new_name
254
- })
240
+ page = Alchemy::CopyPage.new(page: source)
241
+ .call(changed_attributes: {
242
+ parent: new_parent,
243
+ language: new_parent&.language,
244
+ name: new_name,
245
+ title: new_name
246
+ })
255
247
  if source.children.any?
256
248
  source.copy_children_to(page)
257
249
  end
@@ -282,40 +274,6 @@ module Alchemy
282
274
  end
283
275
  options
284
276
  end
285
-
286
- private
287
-
288
- # Aggregates the attributes from given source for copy of page.
289
- #
290
- # @param [Alchemy::Page]
291
- # The source page
292
- # @param [Hash]
293
- # A optional hash with attributes that take precedence over the source attributes
294
- #
295
- def attributes_from_source_for_copy(source, differences = {})
296
- source.attributes.stringify_keys!
297
- differences.stringify_keys!
298
- attributes = source.attributes.merge(differences)
299
- attributes.merge!(DEFAULT_ATTRIBUTES_FOR_COPY)
300
- attributes["name"] = new_name_for_copy(differences["name"], source.name)
301
- attributes.except(*SKIPPED_ATTRIBUTES_ON_COPY)
302
- end
303
-
304
- # Returns a new name for copy of page.
305
- #
306
- # If the differences hash includes a new name this is taken.
307
- # Otherwise +source.name+
308
- #
309
- # @param [String]
310
- # The differences hash that contains a new name
311
- # @param [String]
312
- # The name of the source
313
- #
314
- def new_name_for_copy(custom_name, source_name)
315
- return custom_name if custom_name.present?
316
-
317
- "#{source_name} (#{Alchemy.t("Copy")})"
318
- end
319
277
  end
320
278
 
321
279
  # Instance methods
@@ -449,7 +407,7 @@ module Alchemy
449
407
  children.each do |child|
450
408
  next if child == new_parent
451
409
 
452
- new_child = Page.copy(child, {
410
+ new_child = Alchemy::CopyPage.new(page: child).call(changed_attributes: {
453
411
  parent_id: new_parent.id,
454
412
  language_id: new_parent.language_id,
455
413
  language_code: new_parent.language_code
@@ -546,7 +504,7 @@ module Alchemy
546
504
  # does not respond to +#name+ it returns +'unknown'+
547
505
  #
548
506
  def creator_name
549
- creator.try(:alchemy_display_name) || Alchemy.t("unknown")
507
+ creator.try(:name) || Alchemy.t("unknown")
550
508
  end
551
509
 
552
510
  # Returns the name of the last updater of this page.
@@ -555,7 +513,7 @@ module Alchemy
555
513
  # does not respond to +#name+ it returns +'unknown'+
556
514
  #
557
515
  def updater_name
558
- updater.try(:alchemy_display_name) || Alchemy.t("unknown")
516
+ updater.try(:name) || Alchemy.t("unknown")
559
517
  end
560
518
 
561
519
  # Returns the name of the user currently editing this page.
@@ -564,7 +522,7 @@ module Alchemy
564
522
  # does not respond to +#name+ it returns +'unknown'+
565
523
  #
566
524
  def locker_name
567
- locker.try(:alchemy_display_name) || Alchemy.t("unknown")
525
+ locker.try(:name) || Alchemy.t("unknown")
568
526
  end
569
527
 
570
528
  # Key hint translations by page layout, rather than the default name.
@@ -35,7 +35,7 @@ module Alchemy
35
35
  thumb.uid
36
36
  else
37
37
  uid = PictureThumb::Uid.call(signature, variant)
38
- ActiveRecord::Base.connected_to(role: db_writing_role) do
38
+ ActiveRecord::Base.connected_to(role: ActiveRecord.writing_role) do
39
39
  PictureThumb::Create.call(variant, signature, uid)
40
40
  end
41
41
  uid
@@ -49,14 +49,6 @@ module Alchemy
49
49
  variant.picture.thumbs.find_by(signature: signature)
50
50
  end
51
51
  end
52
-
53
- def db_writing_role
54
- if ActiveRecord::Base.respond_to?(:writing_role)
55
- ActiveRecord::Base.writing_role
56
- else
57
- ActiveRecord.writing_role
58
- end
59
- end
60
52
  end
61
53
  end
62
54
  end
@@ -102,10 +102,11 @@ module Alchemy
102
102
 
103
103
  # Show image cropping link for ingredient
104
104
  def allow_image_cropping?
105
- settings[:crop] && picture&.can_be_cropped_to?(
106
- settings[:size],
107
- settings[:upsample]
108
- ) && !!picture.image_file
105
+ settings[:crop] && picture &&
106
+ picture.can_be_cropped_to?(
107
+ settings[:size],
108
+ settings[:upsample]
109
+ ) && !!picture.image_file
109
110
  end
110
111
 
111
112
  private
@@ -105,7 +105,8 @@ module Alchemy
105
105
  def page_status_titles(page)
106
106
  {
107
107
  public: page.status_title(:public),
108
- restricted: page.status_title(:restricted)
108
+ restricted: page.status_title(:restricted),
109
+ locked: page.status_title(:locked)
109
110
  }
110
111
  end
111
112
  end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Alchemy
4
+ # Creates a copy of given source page.
5
+ #
6
+ # Also copies all elements included in source page.
7
+ #
8
+ # === Note:
9
+ #
10
+ # It prevents the element auto generator from running.
11
+ class CopyPage
12
+ DEFAULT_ATTRIBUTES_FOR_COPY = {
13
+ autogenerate_elements: false,
14
+ public_on: nil,
15
+ public_until: nil,
16
+ locked_at: nil,
17
+ locked_by: nil
18
+ }
19
+
20
+ SKIPPED_ATTRIBUTES_ON_COPY = %w[
21
+ id
22
+ updated_at
23
+ created_at
24
+ creator_id
25
+ updater_id
26
+ lft
27
+ rgt
28
+ depth
29
+ urlname
30
+ cached_tag_list
31
+ ]
32
+
33
+ attr_reader :page
34
+
35
+ # @param page [Alchemy::Page]
36
+ # The source page the copy is taken from
37
+ def initialize(page:)
38
+ @page = page
39
+ end
40
+
41
+ # @param changed_attributes [Hash]
42
+ # A optional hash with attributes that take precedence over the source attributes
43
+ #
44
+ # @return [Alchemy::Page]
45
+ #
46
+ def call(changed_attributes:)
47
+ Alchemy::Page.transaction do
48
+ new_page = Alchemy::Page.new(attributes_from_source_for_copy(changed_attributes))
49
+ new_page.tag_list = page.tag_list
50
+ if new_page.save!
51
+ Alchemy::Page.copy_elements(page, new_page)
52
+ end
53
+ new_page
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ # Aggregates the attributes from given source for copy of page.
60
+ #
61
+ # @param [Alchemy::Page]
62
+ # The source page
63
+ # @param [Hash]
64
+ # A optional hash with attributes that take precedence over the source attributes
65
+ #
66
+ def attributes_from_source_for_copy(differences = {})
67
+ source_attributes = page.attributes.stringify_keys
68
+ differences.stringify_keys!
69
+ desired_attributes = source_attributes
70
+ .merge(DEFAULT_ATTRIBUTES_FOR_COPY)
71
+ .merge(differences)
72
+ desired_attributes["name"] = best_name_for_copy(source_attributes, desired_attributes)
73
+ desired_attributes.except(*SKIPPED_ATTRIBUTES_ON_COPY)
74
+ end
75
+
76
+ # Returns a new name for copy of page.
77
+ #
78
+ # If the differences hash includes a new name this is taken.
79
+ # Otherwise +source.name+
80
+ #
81
+ # @param [Hash]
82
+ # The differences hash that contains a new name
83
+ # @param [Hash]
84
+ # The name of the source
85
+ #
86
+ def best_name_for_copy(source_attributes, desired_attributes)
87
+ desired_name = desired_attributes["name"].presence || source_attributes["name"]
88
+
89
+ new_parent_id = desired_attributes["parent"]&.id || desired_attributes["parent_id"]
90
+
91
+ if Alchemy::Page.where(parent_id: new_parent_id, name: desired_name).exists?
92
+ "#{desired_name} (#{Alchemy.t("Copy")})"
93
+ else
94
+ desired_name
95
+ end
96
+ end
97
+ end
98
+ end
@@ -1,16 +1,20 @@
1
1
  <% if !@preview_mode && @page && can?(:edit_content, @page) %>
2
- <div id="alchemy_menubar" style="display: none" data-turbo="false" data-turbolinks="false">
3
- <ul>
4
- <li><%= link_to Alchemy.t(:to_alchemy), alchemy.admin_dashboard_url %></li>
5
- <li><%= link_to Alchemy.t(:edit_page), alchemy.edit_admin_page_url(@page) %></li>
6
- <li>
7
- <%= form_tag Alchemy.logout_path, method: Alchemy.logout_method do %>
8
- <%= button_tag Alchemy.t(:logout) %>
9
- <% end %>
10
- </li>
11
- </ul>
12
- </div>
2
+ <alchemy-menubar>
3
+ <template>
4
+ <%= stylesheet_link_tag("alchemy/menubar") %>
5
+ <div id="alchemy_menubar" data-turbo="false">
6
+ <ul>
7
+ <li><%= link_to Alchemy.t(:to_alchemy), alchemy.admin_dashboard_url %></li>
8
+ <li><%= link_to Alchemy.t(:edit_page), alchemy.edit_admin_page_url(@page) %></li>
9
+ <li>
10
+ <%= form_tag Alchemy.logout_path, method: Alchemy.logout_method do %>
11
+ <%= button_tag Alchemy.t(:logout) %>
12
+ <% end %>
13
+ </li>
14
+ </ul>
15
+ </div>
16
+ </template>
17
+ </alchemy-menubar>
13
18
 
14
- <%= stylesheet_link_tag("alchemy/menubar") %>
15
- <%= javascript_include_tag('alchemy/menubar') %>
19
+ <%= javascript_include_tag('menubar', type: "module") %>
16
20
  <% end %>
@@ -1,14 +1,18 @@
1
1
  <div id="overlay_toolbar">
2
- <% if can? :create, Alchemy::Attachment %>
3
- <%= render 'alchemy/admin/uploader/button',
4
- object: Alchemy::Attachment.new,
5
- dropzone: '#assign_file_list',
6
- file_attribute: 'file',
7
- in_dialog: true,
8
- redirect_url: admin_attachments_path(
9
- form_field_id: @form_field_id
10
- ) %>
11
- <% end %>
2
+ <div class="toolbar_buttons">
3
+ <% if can? :create, Alchemy::Attachment %>
4
+ <div class="toolbar_button">
5
+ <%= render 'alchemy/admin/uploader/button',
6
+ object: Alchemy::Attachment.new,
7
+ dropzone: '#assign_file_list',
8
+ file_attribute: 'file',
9
+ in_dialog: true,
10
+ redirect_url: admin_attachments_path(
11
+ form_field_id: @form_field_id
12
+ ) %>
13
+ </div>
14
+ <% end %>
15
+ </div>
12
16
  <%= render 'alchemy/admin/partials/remote_search_form' %>
13
17
  </div>
14
18
 
@@ -1,6 +1,6 @@
1
1
  <tr class="<%= cycle('even', 'odd') %>">
2
2
  <td class="icon">
3
- <%= render_icon attachment.icon_css_class, style: 'regular', size: 'lg' %>
3
+ <%= render_icon attachment.icon_css_class, size: "xl" %>
4
4
  </td>
5
5
  <td class="name">
6
6
  <% if can?(:show, attachment) %>
@@ -25,49 +25,57 @@
25
25
  <td class="date"><%= l(attachment.created_at, format: :'alchemy.default') %></td>
26
26
  <td class="tools long">
27
27
  <% if can?(:show, attachment) %>
28
- <%= link_to_dialog(
29
- render_icon('info-circle'),
30
- alchemy.admin_attachment_path(attachment),
31
- {
32
- title: attachment.name,
33
- size: attachment_preview_size(attachment)
34
- },
35
- {
36
- title: Alchemy.t('Attachment Preview')
37
- }
38
- ) %>
28
+ <sl-tooltip content="<%= Alchemy.t('Attachment Preview') %>">
29
+ <%= link_to_dialog(
30
+ render_icon(:information),
31
+ alchemy.admin_attachment_path(attachment),
32
+ {
33
+ title: attachment.name,
34
+ size: attachment_preview_size(attachment)
35
+ },
36
+ class: "icon_button"
37
+ ) %>
38
+ </sl-tooltip>
39
39
  <% end %>
40
40
  <% if can?(:download, attachment) %>
41
- <%= link_to render_icon(:download),
42
- alchemy.download_admin_attachment_path(attachment),
43
- title: Alchemy.t("download_file", filename: attachment.file_name),
44
- target: "_blank" %>
41
+ <sl-tooltip content="<%= Alchemy.t("download_file", filename: attachment.file_name) %>">
42
+ <%= link_to render_icon(:download),
43
+ alchemy.download_admin_attachment_path(attachment),
44
+ target: "_blank",
45
+ class: "icon_button" %>
46
+ </sl-tooltip>
45
47
  <% end %>
46
48
  <% if can?(:edit, attachment) %>
47
- <%= render 'alchemy/admin/attachments/replace_button',
48
- redirect_url: alchemy.admin_attachments_path,
49
- object: attachment,
50
- file_attribute: 'file' %>
49
+ <sl-tooltip content="<%= Alchemy.t(:replace_file) %>">
50
+ <%= render 'alchemy/admin/attachments/replace_button',
51
+ redirect_url: alchemy.admin_attachments_path,
52
+ object: attachment,
53
+ file_attribute: 'file' %>
54
+ </sl-tooltip>
51
55
  <% end %>
52
56
  <% if can?(:destroy, attachment) %>
53
- <%= link_to_confirm_dialog render_icon(:minus),
54
- Alchemy.t(:confirm_to_delete_file),
55
- alchemy.admin_attachment_path(
56
- id: attachment,
57
- q: search_filter_params[:q],
58
- page: params[:page],
59
- per_page: params[:per_page]
60
- ),
61
- title: Alchemy.t(:delete_file) %>
57
+ <sl-tooltip content="<%= Alchemy.t(:delete_file) %>">
58
+ <%= link_to_confirm_dialog render_icon(:minus),
59
+ Alchemy.t(:confirm_to_delete_file),
60
+ alchemy.admin_attachment_path(
61
+ id: attachment,
62
+ q: search_filter_params[:q],
63
+ page: params[:page],
64
+ per_page: params[:per_page]
65
+ ),
66
+ class: "icon_button" %>
67
+ </sl-tooltip>
62
68
  <% end %>
63
69
  <% if can?(:edit, attachment) %>
64
- <%= link_to_dialog render_icon(:edit),
65
- alchemy.edit_admin_attachment_path(attachment, q: search_filter_params[:q], page: params[:page]),
66
- {
67
- title: Alchemy.t(:rename_file),
68
- size: '500x250'
69
- },
70
- title: Alchemy.t(:rename_file) %>
70
+ <sl-tooltip content="<%= Alchemy.t(:rename_file) %>">
71
+ <%= link_to_dialog render_icon(:edit),
72
+ alchemy.edit_admin_attachment_path(attachment, q: search_filter_params[:q], page: params[:page]),
73
+ {
74
+ title: Alchemy.t(:rename_file),
75
+ size: '500x250'
76
+ },
77
+ class: "icon_button" %>
78
+ </sl-tooltip>
71
79
  <% end %>
72
80
  </td>
73
81
  </tr>
@@ -1,25 +1,19 @@
1
- <%= form_for [:admin, object], html: {multipart: true, class: 'upload-button'} do |f| %>
2
- <%= f.file_field file_attribute,
3
- class: 'fileupload--field',
4
- name: "#{f.object_name}[#{file_attribute}]",
5
- id: "replace_#{dom_id(object)}" %>
6
- <%= label_tag "replace_#{dom_id(object)}", title: Alchemy.t(:replace_file) do %>
7
- <%= render_icon :sync %>
8
- <% end %>
9
- <% end %>
1
+ <% file_upload_id = "file_upload_#{dom_id(object)}" %>
10
2
 
11
- <% file_types = local_assigns[:file_types].presence ||
12
- configuration(:uploader)['allowed_filetypes'][object.class.model_name.collection] || ['*'] %>
3
+ <alchemy-uploader id="<%= file_upload_id %>">
4
+ <%= form_for [:admin, object], html: {multipart: true, class: 'upload-button'} do |f| %>
5
+ <%= f.file_field file_attribute,
6
+ class: 'fileupload--field',
7
+ name: "#{f.object_name}[#{file_attribute}]",
8
+ id: "replace_#{dom_id(object)}" %>
9
+ <%= label_tag "replace_#{dom_id(object)}", class: "icon_button" do %>
10
+ <%= render_icon "file-upload" %>
11
+ <% end %>
12
+ <% end %>
13
+ </alchemy-uploader>
13
14
 
14
15
  <script type='text/javascript'>
15
- $(function() {
16
- var options = {
17
- selector: '#replace_<%= dom_id(object) %>',
18
- file_types: '<%= file_types.join("|") %>',
19
- complete: function() {
20
- Turbo.visit('<%= redirect_url.html_safe %>');
21
- }
22
- };
23
- Alchemy.Uploader(options);
24
- });
16
+ document.getElementById("<%= file_upload_id %>").addEventListener("Alchemy.upload.successful", (event) => {
17
+ Turbo.visit('<%= redirect_url.html_safe %>');
18
+ })
25
19
  </script>