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
@@ -0,0 +1,14 @@
1
+ import TagsAutocomplete from "alchemy_admin/tags_autocomplete"
2
+
3
+ function init(scope) {
4
+ if (!scope) {
5
+ Alchemy.watchForDialogs()
6
+ }
7
+ Alchemy.Hotkeys(scope)
8
+ Alchemy.ListFilter(scope)
9
+ TagsAutocomplete(scope)
10
+ }
11
+
12
+ export default {
13
+ init
14
+ }
@@ -1,11 +1,8 @@
1
- const KEY_SEPARATOR = /\./
1
+ import { en } from "alchemy_admin/locales/en"
2
2
 
3
- function currentLocale() {
4
- if (Alchemy.locale == null) {
5
- throw "Alchemy.locale is not set! Please set Alchemy.locale to a locale string in order to translate something."
6
- }
7
- return Alchemy.locale
8
- }
3
+ Alchemy.translations = Object.assign(Alchemy.translations || {}, { en })
4
+
5
+ const KEY_SEPARATOR = /\./
9
6
 
10
7
  function getTranslations() {
11
8
  const locale = currentLocale()
@@ -36,7 +33,14 @@ function getTranslation(key) {
36
33
  return translations[key] || key
37
34
  }
38
35
 
39
- export default function translate(key, replacement) {
36
+ export function currentLocale() {
37
+ if (document.documentElement.lang) {
38
+ return document.documentElement.lang
39
+ }
40
+ return "en"
41
+ }
42
+
43
+ export function translate(key, replacement = undefined) {
40
44
  let translation = getTranslation(key)
41
45
 
42
46
  if (replacement) {
@@ -90,12 +90,15 @@ export default class ImageCropper {
90
90
  }
91
91
 
92
92
  bind() {
93
- this.dialog.dialog_body.find('button[type="submit"]').click(() => {
94
- Alchemy.setElementDirty(`[data-element-id='${this.elementId}']`)
93
+ this.dialog.dialog_body.find('button[type="submit"]').on("click", () => {
94
+ const elementEditor = document.querySelector(
95
+ `[data-element-id='${this.elementId}']`
96
+ )
97
+ elementEditor.setDirty()
95
98
  this.dialog.close()
96
99
  return false
97
100
  })
98
- this.dialog.dialog_body.find('button[type="reset"]').click(() => {
101
+ this.dialog.dialog_body.find('button[type="reset"]').on("click", () => {
99
102
  this.reset()
100
103
  return false
101
104
  })
@@ -1,23 +1,21 @@
1
1
  // Shows spinner while loading images and
2
2
  // fades the image after its been loaded
3
3
 
4
- const DEFAULT_SPINNER_OPTIONS = { fill: "#fff" }
5
-
6
4
  export default class ImageLoader {
7
- static init(scope = document, spinnerOptions = DEFAULT_SPINNER_OPTIONS) {
5
+ static init(scope = document) {
8
6
  if (typeof scope === "string") {
9
7
  scope = document.querySelector(scope)
10
8
  }
11
9
  scope.querySelectorAll("img").forEach((image) => {
12
- const loader = new ImageLoader(image, spinnerOptions)
10
+ const loader = new ImageLoader(image)
13
11
  loader.load()
14
12
  })
15
13
  }
16
14
 
17
- constructor(image, spinnerOptions = DEFAULT_SPINNER_OPTIONS) {
15
+ constructor(image) {
18
16
  this.image = image
19
17
  this.parent = image.parentNode
20
- this.spinner = new Alchemy.Spinner("small", spinnerOptions)
18
+ this.spinner = new Alchemy.Spinner("small")
21
19
  this.bind()
22
20
  }
23
21
 
@@ -34,15 +32,15 @@ export default class ImageLoader {
34
32
  }
35
33
 
36
34
  onLoaded() {
37
- this.removeSpinner()
35
+ this.spinner.stop()
38
36
  this.image.classList.remove("loading")
39
37
  this.unbind()
40
38
  }
41
39
 
42
40
  onError(evt) {
43
41
  const message = `Could not load "${this.image.src}"`
44
- this.removeSpinner()
45
- this.parent.innerHTML = `<span class="icon error fas fa-exclamation-triangle" title="${message}" />`
42
+ this.spinner.stop()
43
+ this.parent.innerHTML = `<span class="icon error ri-alert-line" title="${message}" />`
46
44
  console.error(message, evt)
47
45
  this.unbind()
48
46
  }
@@ -51,10 +49,4 @@ export default class ImageLoader {
51
49
  this.image.removeEventListener("load", this.onLoaded)
52
50
  this.image.removeEventListener("error", this.onError)
53
51
  }
54
-
55
- removeSpinner() {
56
- this.parent.querySelectorAll(".spinner").forEach((spinner) => {
57
- spinner.remove()
58
- })
59
- }
60
52
  }
@@ -7,11 +7,8 @@ export default class IngredientAnchorLink {
7
7
  const icon = ingredientEditor.querySelector(
8
8
  ".edit-ingredient-anchor-link > a > .icon"
9
9
  )
10
- if (icon) {
11
- active
12
- ? icon.classList.replace("far", "fas")
13
- : icon.classList.replace("fas", "far")
14
- }
10
+ icon?.classList.toggle("ri-bookmark-fill", active)
11
+ icon?.classList.toggle("ri-bookmark-line", !active)
15
12
  }
16
13
  }
17
14
  }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * add change listener to select to redirect the user after selecting another locale or site
3
+ * @param {string} selectId
4
+ * @param {string} parameterName
5
+ * @param {boolean} forcedReload
6
+ */
7
+ function selectHandler(selectId, parameterName, forcedReload = false) {
8
+ $(`select#${selectId}`).on("change", function (e) {
9
+ let url = window.location.pathname
10
+ let delimiter = url.match(/\?/) ? "&" : "?"
11
+ const location = `${url}${delimiter}${parameterName}=${$(this).val()}`
12
+
13
+ if (forcedReload) {
14
+ window.location.href = location
15
+ } else {
16
+ Turbo.visit(location, {})
17
+ }
18
+ })
19
+ }
20
+
21
+ function Initialize() {
22
+ // We obviously have javascript enabled.
23
+ $("html").removeClass("no-js")
24
+
25
+ // Initialize the GUI.
26
+ Alchemy.GUI.init()
27
+
28
+ // Fade all growl notifications.
29
+ if ($("#flash_notices").length > 0) {
30
+ Alchemy.Growler.fade()
31
+ }
32
+
33
+ // Add observer for please wait overlay.
34
+ $(".please_wait")
35
+ .not("*[data-alchemy-confirm]")
36
+ .on("click", Alchemy.pleaseWaitOverlay)
37
+
38
+ // Hack for enabling tab focus for <a>'s styled as button.
39
+ $("a.button").attr({ tabindex: 0 })
40
+
41
+ // Locale select handler
42
+ selectHandler("change_locale", "admin_locale", true)
43
+
44
+ // Site select handler
45
+ selectHandler("change_site", "site_id")
46
+
47
+ // Submit forms of selects with `data-autosubmit="true"`
48
+ $('select[data-auto-submit="true"]').on("change", function () {
49
+ $(this.form).submit()
50
+ })
51
+
52
+ // Attaches the image loader on all images
53
+ Alchemy.ImageLoader("#main_content")
54
+
55
+ // Override the filter of keymaster.js so we can blur the fields on esc key.
56
+ key.filter = function (event) {
57
+ let tagName = (event.target || event.srcElement).tagName
58
+ return (
59
+ key.isPressed("esc") ||
60
+ !(tagName === "INPUT" || tagName === "SELECT" || tagName === "TEXTAREA")
61
+ )
62
+ }
63
+ }
64
+
65
+ export default Initialize
@@ -0,0 +1,31 @@
1
+ export const en = {
2
+ allowed_chars: "of %{count} chars",
3
+ cancel: "Cancel",
4
+ cancelled: "Cancelled",
5
+ click_to_edit: "click to edit",
6
+ complete: "Complete",
7
+ element_dirty_notice:
8
+ "This element has unsaved changes. Do you really want to fold it?",
9
+ help: "Help",
10
+ ok: "Ok",
11
+ page_dirty_notice:
12
+ "You have unsaved changes on this page. They will be lost if you continue.",
13
+ page_found: "Page found",
14
+ pages_found: "Pages found",
15
+ url_validation_failed: "The url has no valid format.",
16
+ warning: "Warning!",
17
+ "File is too large": "File is too large",
18
+ "File is too small": "File is too small",
19
+ "File type not allowed": "File type not allowed",
20
+ "Maximum number of files exceeded": "Maximum number of files exceeded",
21
+ "Uploaded bytes exceed file size": "Uploaded bytes exceed file size",
22
+ "Abort upload": "Abort upload",
23
+ "Cancel all uploads": "Cancel all uploads",
24
+ Close: "Close",
25
+ formats: {
26
+ datetime: "Y-m-d H:i",
27
+ date: "Y-m-d",
28
+ time: "H:i",
29
+ time_24hr: false
30
+ }
31
+ }
@@ -4,7 +4,7 @@ import { get } from "alchemy_admin/utils/ajax"
4
4
  import ImageLoader from "alchemy_admin/image_loader"
5
5
 
6
6
  const UPDATE_DELAY = 125
7
- const IMAGE_PLACEHOLDER = '<i class="icon far fa-image fa-fw"></i>'
7
+ const IMAGE_PLACEHOLDER = '<i class="icon ri-image-line ri-fw"></i>'
8
8
  const THUMBNAIL_SIZE = "160x120"
9
9
 
10
10
  class PictureEditor {
@@ -93,7 +93,7 @@ class PictureEditor {
93
93
  this.pictureIdField.value = ""
94
94
  this.image = null
95
95
  this.cropLink.classList.add("disabled")
96
- Alchemy.setElementDirty(this.container.closest(".element-editor"))
96
+ this.container.closest(".element-editor").setDirty()
97
97
  }
98
98
 
99
99
  updateCropLink() {
@@ -0,0 +1,38 @@
1
+ import { on } from "alchemy_admin/utils/events"
2
+
3
+ /**
4
+ * Multiple picture select handler for the picture archive.
5
+ */
6
+ export default function PictureSelector() {
7
+ const selectedItemTools = document.querySelector(".selected_item_tools")
8
+ const checkedInputs = () =>
9
+ document.querySelectorAll("#picture_archive input:checked")
10
+
11
+ // make the item toolbar visible and show the checkbox also if it is not hovered anymore
12
+ on("change", ".picture_tool.select", "input", (event) => {
13
+ selectedItemTools.style.display =
14
+ checkedInputs().length > 0 ? "block" : "none"
15
+
16
+ const parentElementClassList = event.target.parentElement.classList
17
+ const checked = event.target.checked
18
+
19
+ parentElementClassList.toggle("visible", checked)
20
+ parentElementClassList.toggle("hidden", !checked)
21
+ })
22
+
23
+ // open the edit view in a dialog modal
24
+ on("click", ".selected_item_tools", "a#edit_multiple_pictures", (event) => {
25
+ event.preventDefault()
26
+
27
+ const searchParameters = new URLSearchParams()
28
+ checkedInputs().forEach((entry) =>
29
+ searchParameters.append(entry.name, entry.value)
30
+ )
31
+ const url = event.target.href + "?" + searchParameters.toString()
32
+
33
+ Alchemy.openDialog(url, {
34
+ title: event.target.title,
35
+ size: "400x295"
36
+ })
37
+ })
38
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * To show the "Please wait" overlay.
3
+ * Pass false to hide it.
4
+ * @param {boolean} show
5
+ */
6
+ export default function pleaseWaitOverlay(show = true) {
7
+ document.querySelector("alchemy-overlay").show = !!show
8
+ }
@@ -0,0 +1,78 @@
1
+ import Sortable from "sortablejs"
2
+ import { post } from "alchemy_admin/utils/ajax"
3
+
4
+ const SORTABLE_OPTIONS = {
5
+ draggable: ".element-editor",
6
+ handle: ".element-handle",
7
+ ghostClass: "dragged",
8
+ animation: 150,
9
+ swapThreshold: 0.65,
10
+ easing: "cubic-bezier(1, 0, 0, 1)"
11
+ }
12
+
13
+ function onStart(event) {
14
+ const name = event.item.dataset.elementName
15
+ document
16
+ .querySelectorAll(`[data-droppable-elements~="${name}"]`)
17
+ .forEach((dropzone) => dropzone.classList.add("droppable-elements"))
18
+ }
19
+
20
+ function onSort(event) {
21
+ const item = event.item
22
+ const parentElement = event.to.parentElement.closest(".element-editor")
23
+ const params = {
24
+ element_id: item.dataset.elementId,
25
+ position: event.newIndex + 1
26
+ }
27
+
28
+ if (parentElement) {
29
+ params.parent_element_id = parentElement.dataset.elementId
30
+ }
31
+
32
+ post(Alchemy.routes.order_admin_elements_path, params).then((response) => {
33
+ const data = response.data
34
+ Alchemy.growl(data.message)
35
+ Alchemy.PreviewWindow.refresh()
36
+ item.updateTitle(data.preview_text)
37
+ })
38
+ }
39
+
40
+ function onEnd() {
41
+ const dropzones = document.querySelectorAll("[data-droppable-elements]")
42
+ dropzones.forEach((dropzone) =>
43
+ dropzone.classList.remove("droppable-elements")
44
+ )
45
+ }
46
+
47
+ function createSortable(element, options = {}) {
48
+ const group = {
49
+ name: element.dataset.elementName,
50
+ put(to, _from, item) {
51
+ return to.el.dataset.droppableElements
52
+ .split(" ")
53
+ .includes(item.dataset.elementName)
54
+ }
55
+ }
56
+ new Sortable(element, {
57
+ ...SORTABLE_OPTIONS,
58
+ ...options,
59
+ onStart,
60
+ onSort,
61
+ onEnd,
62
+ group
63
+ })
64
+ }
65
+
66
+ export default function SortableElements(selector) {
67
+ if (selector == null) selector = ".sortable-elements"
68
+
69
+ const sortable_areas = document.querySelectorAll(selector, {
70
+ direction: "vertical"
71
+ })
72
+
73
+ sortable_areas.forEach((element) => createSortable(element))
74
+
75
+ document.querySelectorAll(".nested-elements").forEach((nestedElement) => {
76
+ createSortable(nestedElement)
77
+ })
78
+ }
@@ -0,0 +1,36 @@
1
+ import { createHtmlElement } from "alchemy_admin/utils/dom_helpers"
2
+
3
+ export default class Spinner {
4
+ constructor(size, color = "currentColor") {
5
+ this.size = size
6
+ this.color = color
7
+ this.spinner = undefined
8
+ }
9
+
10
+ /**
11
+ * @returns {HTMLElement|undefined}
12
+ */
13
+ get el() {
14
+ return this.spinner
15
+ }
16
+ /**
17
+ * @param {HTMLElement|undefined} parent
18
+ */
19
+ spin(parent) {
20
+ if (typeof parent === "undefined") {
21
+ parent = document.body
22
+ }
23
+ this.spinner = createHtmlElement(
24
+ `<alchemy-spinner size="${this.size}" color="${this.color}"></alchemy-spinner>`
25
+ )
26
+ parent.append(this.spinner)
27
+ return this
28
+ }
29
+
30
+ stop() {
31
+ if (this.spinner) {
32
+ this.spinner.remove()
33
+ this.spinner = undefined
34
+ }
35
+ }
36
+ }
@@ -0,0 +1,46 @@
1
+ function createSearchChoice(term, data) {
2
+ if (
3
+ $(data).filter(function () {
4
+ return this.text.localeCompare(term) === 0
5
+ }).length === 0
6
+ ) {
7
+ return {
8
+ id: term,
9
+ text: term
10
+ }
11
+ }
12
+ }
13
+
14
+ function initSelection(element, callback) {
15
+ const data = []
16
+ $(element.val().split(",")).each(function () {
17
+ data.push({
18
+ id: this.trim(),
19
+ text: this
20
+ })
21
+ })
22
+ callback(data)
23
+ }
24
+
25
+ export default function TagsAutocomplete(scope) {
26
+ const field = $("[data-autocomplete]", scope)
27
+ const url = field.data("autocomplete")
28
+ field.select2({
29
+ tags: true,
30
+ tokenSeparators: [","],
31
+ minimumInputLength: 1,
32
+ openOnEnter: false,
33
+ createSearchChoice,
34
+ ajax: {
35
+ url,
36
+ dataType: "json",
37
+ data: (term) => {
38
+ return { term }
39
+ },
40
+ results: (data) => {
41
+ return { results: data }
42
+ }
43
+ },
44
+ initSelection
45
+ })
46
+ }
@@ -24,7 +24,7 @@ function buildPromise(xhr) {
24
24
  })
25
25
  }
26
26
 
27
- function getToken() {
27
+ export function getToken() {
28
28
  const metaTag = document.querySelector('meta[name="csrf-token"]')
29
29
  return metaTag.attributes.content.textContent
30
30
  }
@@ -37,11 +37,11 @@ export function patch(url, data) {
37
37
  return ajax("PATCH", url, data)
38
38
  }
39
39
 
40
- export function post(url, data) {
41
- return ajax("POST", url, data)
40
+ export function post(url, data, accept = "application/json") {
41
+ return ajax("POST", url, data, accept)
42
42
  }
43
43
 
44
- export default function ajax(method, path, data) {
44
+ export default function ajax(method, path, data, accept = "application/json") {
45
45
  const xhr = new XMLHttpRequest()
46
46
  const promise = buildPromise(xhr)
47
47
  const url = new URL(window.location.origin + path)
@@ -52,7 +52,8 @@ export default function ajax(method, path, data) {
52
52
 
53
53
  xhr.open(method, url.toString())
54
54
  xhr.setRequestHeader("Content-type", "application/json; charset=utf-8")
55
- xhr.setRequestHeader("Accept", "application/json")
55
+ xhr.setRequestHeader("Accept", accept)
56
+ xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest")
56
57
  xhr.setRequestHeader("X-CSRF-Token", getToken())
57
58
 
58
59
  if (data && method.toLowerCase() !== "get") {
@@ -0,0 +1,20 @@
1
+ /**
2
+ * create a HTML element
3
+ * @param {string} text
4
+ * @returns {HTMLElement}
5
+ */
6
+ export function createHtmlElement(text) {
7
+ const element = document.createElement("template")
8
+ element.innerHTML = text
9
+ return element.content.children[0]
10
+ }
11
+
12
+ /**
13
+ * wrap element with wrappingElement
14
+ * @param {HTMLElement} element
15
+ * @param {HTMLElement} wrappingElement
16
+ */
17
+ export function wrap(element, wrappingElement) {
18
+ element.replaceWith(wrappingElement)
19
+ wrappingElement.appendChild(element)
20
+ }
@@ -0,0 +1,11 @@
1
+ export function formatFileSize(bytes) {
2
+ let exponent = bytes === 0 ? 0 : Math.floor(Math.log(bytes) / Math.log(1024))
3
+
4
+ // prevent format higher than GB
5
+ if (exponent > 3) {
6
+ exponent = 3
7
+ }
8
+
9
+ let value = (bytes / Math.pow(1024, exponent)).toFixed(2)
10
+ return value + " " + ["B", "kB", "MB", "GB"][exponent]
11
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * convert dashes and underscore strings into camelCase strings
3
+ * @param {string} str
4
+ * @returns {string}
5
+ */
6
+ export function toCamelCase(str) {
7
+ return str
8
+ .split(/-|_/)
9
+ .reduce((a, b) => a + b.charAt(0).toUpperCase() + b.slice(1))
10
+ }
@@ -1,17 +1,69 @@
1
+ import "@ungap/custom-elements"
1
2
  import "@hotwired/turbo-rails"
3
+ import Rails from "@rails/ujs"
2
4
 
3
- import translate from "alchemy_admin/i18n"
4
- import translationData from "alchemy_admin/translations"
5
- import fileEditors from "alchemy_admin/file_editors"
5
+ import GUI from "alchemy_admin/gui"
6
+ import { translate } from "alchemy_admin/i18n"
7
+ import Dirty from "alchemy_admin/dirty"
6
8
  import IngredientAnchorLink from "alchemy_admin/ingredient_anchor_link"
7
- import pictureEditors from "alchemy_admin/picture_editors"
8
9
  import ImageLoader from "alchemy_admin/image_loader"
9
10
  import ImageCropper from "alchemy_admin/image_cropper"
10
- import Datepicker from "alchemy_admin/datepicker"
11
+ import Initializer from "alchemy_admin/initializer"
12
+ import pictureSelector from "alchemy_admin/picture_selector"
13
+ import pleaseWaitOverlay from "alchemy_admin/please_wait_overlay"
11
14
  import Sitemap from "alchemy_admin/sitemap"
12
- import Tinymce from "alchemy_admin/tinymce"
15
+ import SortableElements from "alchemy_admin/sortable_elements"
16
+ import Spinner from "alchemy_admin/spinner"
13
17
  import PagePublicationFields from "alchemy_admin/page_publication_fields"
14
18
 
19
+ // Setting jQueryUIs global animation duration to something more snappy
20
+ $.fx.speeds._default = 400
21
+
22
+ // Web Components
23
+ import "alchemy_admin/components/button"
24
+ import "alchemy_admin/components/char_counter"
25
+ import "alchemy_admin/components/datepicker"
26
+ import "alchemy_admin/components/dialog_link"
27
+ import "alchemy_admin/components/element_editor"
28
+ import "alchemy_admin/components/ingredient_group"
29
+ import "alchemy_admin/components/link_buttons"
30
+ import "alchemy_admin/components/node_select"
31
+ import "alchemy_admin/components/uploader"
32
+ import "alchemy_admin/components/overlay"
33
+ import "alchemy_admin/components/page_select"
34
+ import "alchemy_admin/components/select"
35
+ import "alchemy_admin/components/spinner"
36
+ import "alchemy_admin/components/tinymce"
37
+ import "@shoelace/progress-bar"
38
+ import "@shoelace/switch"
39
+ import "@shoelace/tab"
40
+ import "@shoelace/tab-group"
41
+ import "@shoelace/tab-panel"
42
+ import "@shoelace/tooltip"
43
+
44
+ import { setDefaultAnimation } from "@shoelace/animation-registry"
45
+
46
+ // Change the default animation for all dialogs
47
+ setDefaultAnimation("tooltip.show", {
48
+ keyframes: [
49
+ { transform: "translateY(10px)", opacity: "0" },
50
+ { transform: "translateY(0)", opacity: "1" }
51
+ ],
52
+ options: {
53
+ duration: 100
54
+ }
55
+ })
56
+
57
+ setDefaultAnimation("tooltip.hide", {
58
+ keyframes: [
59
+ { transform: "translateY(0)", opacity: "1" },
60
+ { transform: "translateY(10px)", opacity: "0" }
61
+ ],
62
+ options: {
63
+ duration: 100
64
+ }
65
+ })
66
+
15
67
  // Global Alchemy object
16
68
  if (typeof window.Alchemy === "undefined") {
17
69
  window.Alchemy = {}
@@ -19,16 +71,21 @@ if (typeof window.Alchemy === "undefined") {
19
71
 
20
72
  // Enhance the global Alchemy object with imported features
21
73
  Object.assign(Alchemy, {
22
- // Global utility method for translating a given string
23
- t: translate,
24
- translations: Object.assign(Alchemy.translations || {}, translationData),
25
- fileEditors,
26
- pictureEditors,
74
+ ...Dirty,
75
+ GUI,
76
+ t: translate, // Global utility method for translating a given string
27
77
  ImageLoader: ImageLoader.init,
28
78
  ImageCropper,
79
+ Initializer,
29
80
  IngredientAnchorLink,
30
- Datepicker,
81
+ pictureSelector,
82
+ pleaseWaitOverlay,
31
83
  Sitemap,
32
- Tinymce,
84
+ SortableElements,
85
+ Spinner,
33
86
  PagePublicationFields
34
87
  })
88
+
89
+ Rails.start()
90
+
91
+ $(document).on("turbo:load", Initializer)
@@ -0,0 +1,10 @@
1
+ class Menubar extends HTMLElement {
2
+ constructor() {
3
+ super()
4
+ const template = this.querySelector("template")
5
+ const attachedShadowRoot = this.attachShadow({ mode: "open" })
6
+ attachedShadowRoot.appendChild(template.content.cloneNode(true))
7
+ }
8
+ }
9
+
10
+ customElements.define("alchemy-menubar", Menubar)