maglevcms 2.0.0 → 3.0.0.beta1

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 (677) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +53 -13
  3. data/Rakefile +0 -4
  4. data/app/assets/builds/maglev/tailwind.css +14393 -0
  5. data/app/assets/config/maglev_manifest.js +7 -0
  6. data/app/assets/javascripts/maglev/client/dom-operations.js +282 -0
  7. data/app/{frontend/live-preview-client → assets/javascripts/maglev/client}/iframe-decorator.js +81 -15
  8. data/app/{frontend/live-preview-client/message.js → assets/javascripts/maglev/client/incoming-messages.js} +14 -12
  9. data/app/assets/javascripts/maglev/client/index.js +26 -0
  10. data/app/{frontend/live-preview-client → assets/javascripts/maglev/client}/utils.js +4 -0
  11. data/app/assets/javascripts/maglev/editor/controllers/app/forms/section_form_controller.js +46 -0
  12. data/app/assets/javascripts/maglev/editor/controllers/app/forms/style_form_controller.js +19 -0
  13. data/app/assets/javascripts/maglev/editor/controllers/app/index.js +15 -0
  14. data/app/assets/javascripts/maglev/editor/controllers/app/page_preview_controller.js +163 -0
  15. data/app/assets/javascripts/maglev/editor/controllers/app/preview_notification_center_controller.js +151 -0
  16. data/app/assets/javascripts/maglev/editor/controllers/app/setting_controller.js +42 -0
  17. data/app/assets/javascripts/maglev/editor/controllers/application.js +9 -0
  18. data/app/assets/javascripts/maglev/editor/controllers/index.js +3 -0
  19. data/app/assets/javascripts/maglev/editor/controllers/shared/auto_save_controller.js +16 -0
  20. data/app/assets/javascripts/maglev/editor/controllers/shared/broken_image_controller.js +16 -0
  21. data/app/assets/javascripts/maglev/editor/controllers/shared/copy_to_clipboard_controller.js +36 -0
  22. data/app/assets/javascripts/maglev/editor/controllers/shared/disappearance_controller.js +21 -0
  23. data/app/assets/javascripts/maglev/editor/controllers/shared/dispatcher_controller.js +12 -0
  24. data/app/assets/javascripts/maglev/editor/controllers/shared/form_refresh_controller.js +15 -0
  25. data/app/assets/javascripts/maglev/editor/controllers/shared/index.js +27 -0
  26. data/app/assets/javascripts/maglev/editor/controllers/shared/max_length_controller.js +30 -0
  27. data/app/assets/javascripts/maglev/editor/controllers/shared/prevent_same_path.js +20 -0
  28. data/app/assets/javascripts/maglev/editor/controllers/shared/reload_page_controller.js +7 -0
  29. data/app/assets/javascripts/maglev/editor/controllers/shared/sortable_controller.js +64 -0
  30. data/app/assets/javascripts/maglev/editor/controllers/shared/submit_button_controller.js +45 -0
  31. data/app/assets/javascripts/maglev/editor/controllers/shared/transition_controller.js +14 -0
  32. data/app/assets/javascripts/maglev/editor/controllers/uikit.js +39 -0
  33. data/app/assets/javascripts/maglev/editor/controllers/utils.js +10 -0
  34. data/app/assets/javascripts/maglev/editor/index.js +66 -0
  35. data/app/assets/stylesheets/maglev/application.css +88 -0
  36. data/app/{frontend/editor/design/components/rich-text-editor.scss → assets/stylesheets/maglev/tailwind.css.erb} +30 -15
  37. data/app/components/maglev/editor/setting_registry.rb +59 -0
  38. data/app/components/maglev/editor/settings/base_component.rb +55 -0
  39. data/app/components/maglev/editor/settings/checkbox/checkbox_component.html.erb +16 -0
  40. data/app/components/maglev/editor/settings/checkbox/checkbox_component.rb +12 -0
  41. data/app/components/maglev/editor/settings/collection_item/collection_item_component.html.erb +25 -0
  42. data/app/components/maglev/editor/settings/collection_item/collection_item_component.rb +19 -0
  43. data/app/components/maglev/editor/settings/color/color_component.html.erb +17 -0
  44. data/app/components/maglev/editor/settings/color/color_component.rb +12 -0
  45. data/app/components/maglev/editor/settings/divider/divider_component.html.erb +12 -0
  46. data/app/components/maglev/editor/settings/divider/divider_component.rb +15 -0
  47. data/app/components/maglev/editor/settings/hint/hint_component.html.erb +3 -0
  48. data/app/components/maglev/editor/settings/hint/hint_component.rb +12 -0
  49. data/app/components/maglev/editor/settings/icon/icon_component.html.erb +21 -0
  50. data/app/components/maglev/editor/settings/icon/icon_component.rb +15 -0
  51. data/app/components/maglev/editor/settings/image/image_component.html.erb +26 -0
  52. data/app/components/maglev/editor/settings/image/image_component.rb +23 -0
  53. data/app/components/maglev/editor/settings/link/link_component.html.erb +22 -0
  54. data/app/components/maglev/editor/settings/link/link_component.rb +19 -0
  55. data/app/components/maglev/editor/settings/select/select_component.html.erb +20 -0
  56. data/app/components/maglev/editor/settings/select/select_component.rb +27 -0
  57. data/app/components/maglev/editor/settings/text/richtext_component.html.erb +22 -0
  58. data/app/components/maglev/editor/settings/text/richtext_component.rb +12 -0
  59. data/app/components/maglev/editor/settings/text/text_component.html.erb +18 -0
  60. data/app/components/maglev/editor/settings/text/text_component.rb +12 -0
  61. data/app/components/maglev/editor/settings/text/textarea_component.html.erb +21 -0
  62. data/app/components/maglev/editor/settings/text/textarea_component.rb +12 -0
  63. data/app/components/maglev/editor/settings_group_component.html.erb +5 -0
  64. data/app/components/maglev/editor/settings_group_component.rb +30 -0
  65. data/app/components/maglev/section_component.rb +10 -7
  66. data/app/components/maglev/uikit/app_layout/layout_component.html.erb +15 -0
  67. data/app/components/maglev/uikit/app_layout/layout_component.rb +19 -0
  68. data/app/components/maglev/uikit/app_layout/sidebar/link_component.html.erb +5 -0
  69. data/app/components/maglev/uikit/app_layout/sidebar/link_component.rb +40 -0
  70. data/app/components/maglev/uikit/app_layout/sidebar_component.html.erb +19 -0
  71. data/app/components/maglev/uikit/app_layout/sidebar_component.rb +11 -0
  72. data/app/components/maglev/uikit/app_layout/topbar/logo_component.html.erb +3 -0
  73. data/app/components/maglev/uikit/app_layout/topbar/logo_component.rb +18 -0
  74. data/app/components/maglev/uikit/app_layout/topbar/page_info_component.html.erb +26 -0
  75. data/app/components/maglev/uikit/app_layout/topbar/page_info_component.rb +28 -0
  76. data/app/components/maglev/uikit/app_layout/topbar_component.html.erb +15 -0
  77. data/app/components/maglev/uikit/app_layout/topbar_component.rb +21 -0
  78. data/app/components/maglev/uikit/badge_component.rb +40 -0
  79. data/app/components/maglev/uikit/base_component.rb +15 -0
  80. data/app/components/maglev/uikit/breadcrumbs/breadcrumbs_component.html.erb +10 -0
  81. data/app/components/maglev/uikit/breadcrumbs/breadcrumbs_component.rb +11 -0
  82. data/app/components/maglev/uikit/breadcrumbs/link_component.html.erb +12 -0
  83. data/app/components/maglev/uikit/breadcrumbs/link_component.rb +25 -0
  84. data/app/components/maglev/uikit/collapsible/collapsible_component.html.erb +5 -0
  85. data/app/components/maglev/uikit/collapsible/collapsible_component.rb +11 -0
  86. data/app/components/maglev/uikit/collapsible/collapsible_controller.js +9 -0
  87. data/app/components/maglev/uikit/collapsible/item_component.html.erb +17 -0
  88. data/app/components/maglev/uikit/collapsible/item_component.rb +11 -0
  89. data/app/components/maglev/uikit/device_toggler_component/device_toggler_component.html.erb +16 -0
  90. data/app/components/maglev/uikit/device_toggler_component/device_toggler_controller.js +25 -0
  91. data/app/components/maglev/uikit/device_toggler_component.rb +28 -0
  92. data/app/components/maglev/uikit/dropdown_component/dropdown_component.html.erb +18 -0
  93. data/app/components/maglev/uikit/dropdown_component/dropdown_controller.js +69 -0
  94. data/app/components/maglev/uikit/dropdown_component.rb +15 -0
  95. data/app/components/maglev/uikit/form/checkbox_component.html.erb +17 -0
  96. data/app/components/maglev/uikit/form/checkbox_component.rb +26 -0
  97. data/app/components/maglev/uikit/form/checkbox_controller.js +7 -0
  98. data/app/components/maglev/uikit/form/color_field_component.html.erb +76 -0
  99. data/app/components/maglev/uikit/form/color_field_component.rb +57 -0
  100. data/app/components/maglev/uikit/form/color_field_controller.js +25 -0
  101. data/app/components/maglev/uikit/form/combobox/list_component.html.erb +14 -0
  102. data/app/components/maglev/uikit/form/combobox/list_component.rb +13 -0
  103. data/app/components/maglev/uikit/form/combobox/option_component.html.erb +16 -0
  104. data/app/components/maglev/uikit/form/combobox/option_component.rb +22 -0
  105. data/app/components/maglev/uikit/form/combobox_component.html.erb +75 -0
  106. data/app/components/maglev/uikit/form/combobox_component.rb +64 -0
  107. data/app/components/maglev/uikit/form/combobox_controller.js +385 -0
  108. data/app/components/maglev/uikit/form/icon_field_component.html.erb +76 -0
  109. data/app/components/maglev/uikit/form/icon_field_component.rb +35 -0
  110. data/app/components/maglev/uikit/form/icon_field_controller.js +38 -0
  111. data/app/components/maglev/uikit/form/image_field_component.html.erb +101 -0
  112. data/app/components/maglev/uikit/form/image_field_component.rb +52 -0
  113. data/app/components/maglev/uikit/form/image_field_controller.js +74 -0
  114. data/app/components/maglev/uikit/form/link/base_component.rb +19 -0
  115. data/app/components/maglev/uikit/form/link/email_link_component.html.erb +16 -0
  116. data/app/components/maglev/uikit/form/link/email_link_component.rb +12 -0
  117. data/app/components/maglev/uikit/form/link/page_link_component.html.erb +17 -0
  118. data/app/components/maglev/uikit/form/link/page_link_component.rb +12 -0
  119. data/app/components/maglev/uikit/form/link/static_page_link_component.html.erb +16 -0
  120. data/app/components/maglev/uikit/form/link/static_page_link_component.rb +12 -0
  121. data/app/components/maglev/uikit/form/link/url_link_component.html.erb +16 -0
  122. data/app/components/maglev/uikit/form/link/url_link_component.rb +19 -0
  123. data/app/components/maglev/uikit/form/link_component.html.erb +55 -0
  124. data/app/components/maglev/uikit/form/link_component.rb +80 -0
  125. data/app/components/maglev/uikit/form/link_controller.js +36 -0
  126. data/app/components/maglev/uikit/form/richtext/block_button_component.html.erb +38 -0
  127. data/app/components/maglev/uikit/form/richtext/block_button_component.rb +22 -0
  128. data/app/components/maglev/uikit/form/richtext/button_component.html.erb +16 -0
  129. data/app/components/maglev/uikit/form/richtext/button_component.rb +19 -0
  130. data/app/components/maglev/uikit/form/richtext/button_group_component.html.erb +7 -0
  131. data/app/components/maglev/uikit/form/richtext/button_group_component.rb +13 -0
  132. data/app/components/maglev/uikit/form/richtext/toolbar_component.html.erb +23 -0
  133. data/app/components/maglev/uikit/form/richtext/toolbar_component.rb +19 -0
  134. data/app/components/maglev/uikit/form/richtext_component.html.erb +28 -0
  135. data/app/components/maglev/uikit/form/richtext_component.rb +54 -0
  136. data/app/components/maglev/uikit/form/richtext_controller.js +248 -0
  137. data/app/components/maglev/uikit/form/search_form_component.html.erb +24 -0
  138. data/app/components/maglev/uikit/form/search_form_component.rb +42 -0
  139. data/app/components/maglev/uikit/form/search_form_controller.js +31 -0
  140. data/app/components/maglev/uikit/form/select_component.html.erb +19 -0
  141. data/app/components/maglev/uikit/form/select_component.rb +52 -0
  142. data/app/components/maglev/uikit/form/select_controller.js +7 -0
  143. data/app/components/maglev/uikit/form/text_field_component.html.erb +26 -0
  144. data/app/components/maglev/uikit/form/text_field_component.rb +42 -0
  145. data/app/components/maglev/uikit/form/text_field_controller.js +18 -0
  146. data/app/components/maglev/uikit/form/textarea_component.html.erb +43 -0
  147. data/app/components/maglev/uikit/form/textarea_component.rb +53 -0
  148. data/app/components/maglev/uikit/icon_button_component/icon_button_component.html.erb +3 -0
  149. data/app/components/maglev/uikit/icon_button_component.rb +18 -0
  150. data/app/components/maglev/uikit/icon_component.rb +140 -0
  151. data/app/components/maglev/uikit/image_library/card_component.html.erb +41 -0
  152. data/app/components/maglev/uikit/image_library/card_component.rb +52 -0
  153. data/app/components/maglev/uikit/image_library/list_component.html.erb +7 -0
  154. data/app/components/maglev/uikit/image_library/list_component.rb +11 -0
  155. data/app/components/maglev/uikit/image_library/uploader_component.html.erb +30 -0
  156. data/app/components/maglev/uikit/image_library/uploader_component.rb +29 -0
  157. data/app/components/maglev/uikit/image_library/uploader_controller.js +74 -0
  158. data/app/components/maglev/uikit/list/insert_button_component.html.erb +7 -0
  159. data/app/components/maglev/uikit/list/insert_button_component.rb +40 -0
  160. data/app/components/maglev/uikit/list/list_component.html.erb +17 -0
  161. data/app/components/maglev/uikit/list/list_component.rb +34 -0
  162. data/app/components/maglev/uikit/list/list_item_component.html.erb +47 -0
  163. data/app/components/maglev/uikit/list/list_item_component.rb +85 -0
  164. data/app/components/maglev/uikit/locale_switcher_component/locale_switcher_component.html.erb +22 -0
  165. data/app/components/maglev/uikit/locale_switcher_component.rb +18 -0
  166. data/app/components/maglev/uikit/menu_dropdown_component/menu_dropdown_component.html.erb +15 -0
  167. data/app/components/maglev/uikit/menu_dropdown_component.rb +32 -0
  168. data/app/components/maglev/uikit/modal_component/modal_component.html.erb +63 -0
  169. data/app/components/maglev/uikit/modal_component/modal_controller.js +47 -0
  170. data/app/components/maglev/uikit/modal_component.rb +33 -0
  171. data/app/components/maglev/uikit/page_actions_dropdown_component/page_actions_dropdown_component.html.erb +56 -0
  172. data/app/components/maglev/uikit/page_actions_dropdown_component.rb +24 -0
  173. data/app/components/maglev/uikit/page_layout_component/back_link_component.html.erb +4 -0
  174. data/app/components/maglev/uikit/page_layout_component/page_layout_component.html.erb +58 -0
  175. data/app/components/maglev/uikit/page_layout_component/page_layout_controller.js +34 -0
  176. data/app/components/maglev/uikit/page_layout_component.rb +42 -0
  177. data/app/components/maglev/uikit/pagination_component/pagination_component.html.erb +70 -0
  178. data/app/components/maglev/uikit/pagination_component.rb +25 -0
  179. data/app/components/maglev/uikit/section_toolbar/bottom_component.html.erb +13 -0
  180. data/app/components/maglev/uikit/section_toolbar/bottom_component.rb +27 -0
  181. data/app/components/maglev/uikit/section_toolbar/section_toolbar_component.html.erb +17 -0
  182. data/app/components/maglev/uikit/section_toolbar/section_toolbar_component.rb +18 -0
  183. data/app/components/maglev/uikit/section_toolbar/section_toolbar_controller.js +90 -0
  184. data/app/components/maglev/uikit/section_toolbar/top_left_corner_component.html.erb +16 -0
  185. data/app/components/maglev/uikit/section_toolbar/top_left_corner_component.rb +15 -0
  186. data/app/components/maglev/uikit/section_toolbar/top_right_corner_component.html.erb +28 -0
  187. data/app/components/maglev/uikit/section_toolbar/top_right_corner_component.rb +28 -0
  188. data/app/components/maglev/uikit/tabs_component/tabs_component.html.erb +35 -0
  189. data/app/components/maglev/uikit/tabs_component/tabs_controller.js +57 -0
  190. data/app/components/maglev/uikit/tabs_component.rb +71 -0
  191. data/app/controllers/concerns/maglev/content_locale_concern.rb +5 -1
  192. data/app/controllers/concerns/maglev/editor/errors_concern.rb +45 -0
  193. data/app/controllers/concerns/maglev/fetchers_concern.rb +3 -6
  194. data/app/controllers/concerns/maglev/flash_i18n_concern.rb +11 -0
  195. data/app/controllers/maglev/application_controller.rb +1 -7
  196. data/app/controllers/maglev/editor/assets_controller.rb +59 -0
  197. data/app/controllers/maglev/editor/base_controller.rb +111 -0
  198. data/app/controllers/maglev/editor/combobox/collection_items_controller.rb +17 -0
  199. data/app/controllers/maglev/editor/combobox/pages_controller.rb +20 -0
  200. data/app/controllers/maglev/editor/home_controller.rb +25 -0
  201. data/app/controllers/maglev/editor/icons_controller.rb +24 -0
  202. data/app/controllers/maglev/editor/links_controller.rb +52 -0
  203. data/app/controllers/maglev/editor/page_clone_controller.rb +20 -0
  204. data/app/controllers/maglev/editor/pages_controller.rb +77 -0
  205. data/app/controllers/maglev/editor/publication_controller.rb +14 -0
  206. data/app/controllers/maglev/editor/section_blocks_controller.rb +101 -0
  207. data/app/controllers/maglev/editor/sections_controller.rb +96 -0
  208. data/app/controllers/maglev/editor/style_controller.rb +31 -0
  209. data/app/controllers/maglev/page_preview_controller.rb +1 -5
  210. data/app/controllers/maglev/published_page_preview_controller.rb +50 -0
  211. data/app/controllers/maglev/sitemap_controller.rb +1 -1
  212. data/app/helpers/maglev/application_helper.rb +148 -18
  213. data/app/helpers/maglev/editor/pages_helper.rb +23 -0
  214. data/app/helpers/maglev/editor/section_blocks_helper.rb +124 -0
  215. data/app/helpers/maglev/editor/settings_helper.rb +52 -0
  216. data/app/helpers/maglev/page_preview_helper.rb +1 -1
  217. data/app/lib/maglev/form/form_builder.rb +38 -0
  218. data/app/lib/maglev/form/inputs/check_box.rb +20 -0
  219. data/app/lib/maglev/form/inputs/combobox.rb +33 -0
  220. data/app/lib/maglev/form/inputs/image_field.rb +39 -0
  221. data/app/lib/maglev/form/inputs/richtext.rb +34 -0
  222. data/app/lib/maglev/form/inputs/select.rb +34 -0
  223. data/app/lib/maglev/form/inputs/text_field.rb +32 -0
  224. data/app/lib/maglev/form/inputs/textarea.rb +30 -0
  225. data/app/lib/maglev/turbo/streams/tag_builder.rb +17 -0
  226. data/app/models/concerns/maglev/content/enhanced_value_concern.rb +40 -0
  227. data/app/models/concerns/maglev/sections_concern.rb +30 -1
  228. data/app/models/concerns/maglev/translatable.rb +23 -4
  229. data/app/models/maglev/application_record.rb +10 -0
  230. data/app/models/maglev/asset.rb +1 -3
  231. data/app/models/maglev/content/block_content.rb +96 -0
  232. data/app/models/maglev/content/editor_link.rb +49 -0
  233. data/app/models/maglev/content/section_content.rb +85 -0
  234. data/app/models/maglev/content/setting_content.rb +33 -0
  235. data/app/models/maglev/page/path_concern.rb +7 -0
  236. data/app/models/maglev/page/search_concern.rb +24 -7
  237. data/app/models/maglev/page.rb +3 -0
  238. data/app/models/maglev/section/block.rb +43 -6
  239. data/app/models/maglev/section/content_concern.rb +15 -1
  240. data/app/models/maglev/section/setting.rb +12 -0
  241. data/app/models/maglev/section.rb +52 -4
  242. data/app/models/maglev/sections_content_store.rb +36 -0
  243. data/app/models/maglev/setting_types/base.rb +8 -0
  244. data/app/models/maglev/setting_types/collection_item.rb +5 -1
  245. data/app/models/maglev/setting_types/image.rb +4 -0
  246. data/app/models/maglev/setting_types/link.rb +4 -0
  247. data/app/models/maglev/setting_types/text.rb +5 -0
  248. data/app/models/maglev/site/locales_concern.rb +4 -14
  249. data/app/models/maglev/site/style_value.rb +19 -13
  250. data/app/models/maglev/site.rb +8 -0
  251. data/app/models/maglev/theme/section_category.rb +6 -1
  252. data/app/models/maglev/theme/style_setting.rb +1 -1
  253. data/app/models/maglev/theme.rb +13 -0
  254. data/app/services/concerns/maglev/content/helpers_concern.rb +100 -0
  255. data/app/services/concerns/maglev/get_page_sections/transform_section_concern.rb +97 -0
  256. data/app/services/maglev/app_container.rb +27 -2
  257. data/app/services/maglev/content/add_section_block_service.rb +53 -0
  258. data/app/services/maglev/content/add_section_service.rb +99 -0
  259. data/app/services/maglev/content/delete_section_block_service.rb +45 -0
  260. data/app/services/maglev/content/delete_section_service.rb +34 -0
  261. data/app/services/maglev/content/sort_section_blocks_service.rb +47 -0
  262. data/app/services/maglev/content/update_section_block_service.rb +52 -0
  263. data/app/services/maglev/content/update_section_service.rb +50 -0
  264. data/app/services/maglev/create_page_service.rb +39 -0
  265. data/app/services/maglev/fetch_section_screenshot_url.rb +12 -1
  266. data/app/services/maglev/fetch_style.rb +22 -12
  267. data/app/services/maglev/get_base_url.rb +3 -1
  268. data/app/services/maglev/get_page_section_names.rb +1 -1
  269. data/app/services/maglev/get_page_sections.rb +11 -82
  270. data/app/services/maglev/get_published_page_sections_service.rb +48 -0
  271. data/app/services/maglev/persist_section_screenshot.rb +1 -1
  272. data/app/services/maglev/persist_style_service.rb +36 -0
  273. data/app/services/maglev/publish_service.rb +30 -0
  274. data/app/services/maglev/reset_section_content.rb +64 -0
  275. data/app/services/maglev/search_pages.rb +6 -2
  276. data/app/services/maglev/setup_pages.rb +44 -33
  277. data/app/types/maglev/locales_type.rb +9 -0
  278. data/app/views/layouts/maglev/editor/_head.html.erb +0 -0
  279. data/app/views/layouts/maglev/editor/_sidebar.html.erb +39 -0
  280. data/app/views/layouts/maglev/editor/_topbar.html.erb +45 -0
  281. data/app/views/layouts/maglev/editor/application.html.erb +67 -0
  282. data/app/views/maglev/editor/assets/_list.html.erb +33 -0
  283. data/app/views/maglev/editor/assets/index.html.erb +29 -0
  284. data/app/views/maglev/editor/combobox/collection_items/index.turbo_stream.erb +18 -0
  285. data/app/views/maglev/editor/combobox/pages/index.turbo_stream.erb +7 -0
  286. data/app/views/maglev/editor/home/index.html.erb +1 -0
  287. data/app/views/maglev/editor/icons/_list.html.erb +27 -0
  288. data/app/views/maglev/editor/icons/index.html.erb +23 -0
  289. data/app/views/maglev/editor/links/edit/_email.html.erb +5 -0
  290. data/app/views/maglev/editor/links/edit/_page.html.erb +29 -0
  291. data/app/views/maglev/editor/links/edit/_tabs.html.erb +11 -0
  292. data/app/views/maglev/editor/links/edit/_url.html.erb +7 -0
  293. data/app/views/maglev/editor/links/edit.html.erb +31 -0
  294. data/app/views/maglev/editor/links/update.turbo_stream.erb +9 -0
  295. data/app/views/maglev/editor/pages/_list.html.erb +28 -0
  296. data/app/views/maglev/editor/pages/_preview.html.erb +35 -0
  297. data/app/views/maglev/editor/pages/_preview_empty_message.html.erb +14 -0
  298. data/app/views/maglev/editor/pages/edit.html.erb +32 -0
  299. data/app/views/maglev/editor/pages/form/_main.html.erb +7 -0
  300. data/app/views/maglev/editor/pages/form/_seo.html.erb +11 -0
  301. data/app/views/maglev/editor/pages/form/_tabs.html.erb +8 -0
  302. data/app/views/maglev/editor/pages/index.html.erb +23 -0
  303. data/app/views/maglev/editor/pages/new.html.erb +28 -0
  304. data/app/views/maglev/editor/publication/create.turbo_stream.erb +1 -0
  305. data/app/views/maglev/editor/section_blocks/_form.html.erb +15 -0
  306. data/app/views/maglev/editor/section_blocks/_new.html.erb +21 -0
  307. data/app/views/maglev/editor/section_blocks/edit.html.erb +28 -0
  308. data/app/views/maglev/editor/section_blocks/index/_list.html.erb +41 -0
  309. data/app/views/maglev/editor/section_blocks/index/_tree.html.erb +56 -0
  310. data/app/views/maglev/editor/section_blocks/index.html.erb +20 -0
  311. data/app/views/maglev/editor/section_blocks/update.turbo_stream.erb +5 -0
  312. data/app/views/maglev/editor/sections/_form.html.erb +21 -0
  313. data/app/views/maglev/editor/sections/_list.html.erb +50 -0
  314. data/app/views/maglev/editor/sections/_theme_list.html.erb +32 -0
  315. data/app/views/maglev/editor/sections/_toolbar_list.html.erb +17 -0
  316. data/app/views/maglev/editor/sections/edit.html.erb +24 -0
  317. data/app/views/maglev/editor/sections/index.html.erb +11 -0
  318. data/app/views/maglev/editor/sections/new.html.erb +20 -0
  319. data/app/views/maglev/editor/sections/update.turbo_stream.erb +5 -0
  320. data/app/views/maglev/editor/shared/_button_label.html.erb +18 -0
  321. data/app/views/maglev/editor/shared/errors/not_authorized_error.turbo_stream.erb +17 -0
  322. data/app/views/maglev/editor/shared/errors/stale_object_error.turbo_stream.erb +21 -0
  323. data/app/views/maglev/editor/shared/errors/standard_error.turbo_stream.erb +17 -0
  324. data/app/views/maglev/editor/style/edit.html.erb +24 -0
  325. data/app/views/maglev/sitemap/index.xml.builder +1 -1
  326. data/config/client_importmap.rb +4 -0
  327. data/config/editor_importmap.rb +26 -0
  328. data/config/initializers/active_record_types.rb +5 -0
  329. data/config/initializers/migration_patches.rb +9 -0
  330. data/config/initializers/pagy.rb +3 -0
  331. data/config/locales/activerecord.ar.yml +20 -2
  332. data/config/locales/activerecord.en.yml +20 -2
  333. data/config/locales/activerecord.es.yml +15 -14
  334. data/config/locales/activerecord.fr.yml +15 -14
  335. data/config/locales/activerecord.pt-BR.yml +22 -4
  336. data/config/locales/editor.ar.yml +268 -0
  337. data/config/locales/editor.en.yml +268 -0
  338. data/config/locales/editor.es.yml +268 -0
  339. data/config/locales/editor.fr.yml +268 -0
  340. data/config/locales/editor.pt-BR.yml +268 -0
  341. data/config/locales/uikit.ar.yml +14 -0
  342. data/config/locales/uikit.en.yml +14 -0
  343. data/config/locales/uikit.es.yml +14 -0
  344. data/config/locales/uikit.fr.yml +14 -0
  345. data/config/locales/uikit.pt-BR.yml +14 -0
  346. data/config/routes.rb +34 -35
  347. data/db/migrate/20200831101942_create_maglev_section_content.rb +4 -0
  348. data/db/migrate/20210819092740_switch_to_localized_page_fields.rb +8 -2
  349. data/db/migrate/20211008064437_add_locales_to_sites.rb +2 -0
  350. data/db/migrate/20211013210954_translate_section_content.rb +6 -2
  351. data/db/migrate/20211203224112_add_open_graph_tags_to_pages.rb +4 -0
  352. data/db/migrate/20220612092235_add_style_to_sites.rb +2 -0
  353. data/db/migrate/20250929203214_create_maglev_sections_content_stores.rb +21 -0
  354. data/exe/tailwind-cli +29 -0
  355. data/lib/commands/maglev/change_site_locales_command.rb +1 -1
  356. data/lib/commands/maglev/create_site_command.rb +1 -1
  357. data/lib/commands/maglev/publish_site_command.rb +46 -0
  358. data/lib/commands/maglev/sections/remove_command.rb +1 -1
  359. data/lib/commands/maglev/sections/rename_command.rb +6 -2
  360. data/lib/commands/maglev/sections/reset_command.rb +56 -0
  361. data/lib/generators/maglev/install_generator.rb +1 -6
  362. data/lib/generators/maglev/templates/install/config/initializers/maglev.rb +6 -2
  363. data/lib/generators/maglev/templates/theme/app/views/theme/layout.html.erb.tt +2 -2
  364. data/lib/maglev/config.rb +2 -1
  365. data/lib/maglev/engine.rb +34 -42
  366. data/lib/maglev/errors.rb +3 -0
  367. data/lib/maglev/version.rb +1 -1
  368. data/lib/maglev.rb +4 -2
  369. data/lib/tasks/maglev/tailwindcss.rake +38 -0
  370. data/lib/tasks/maglev_tasks.rake +4 -34
  371. metadata +355 -342
  372. data/.babelrc +0 -9
  373. data/.yarn/install-state.gz +0 -0
  374. data/.yarn/releases/yarn-4.4.0.cjs +0 -925
  375. data/.yarnrc.yml +0 -3
  376. data/app/controllers/maglev/admin/base_controller.rb +0 -20
  377. data/app/controllers/maglev/admin/dashboard_controller.rb +0 -11
  378. data/app/controllers/maglev/admin/sections/previews_controller.rb +0 -52
  379. data/app/controllers/maglev/admin/sections/screenshots_controller.rb +0 -17
  380. data/app/controllers/maglev/admin/themes_controller.rb +0 -19
  381. data/app/controllers/maglev/api/assets_controller.rb +0 -44
  382. data/app/controllers/maglev/api/collection_items_controller.rb +0 -21
  383. data/app/controllers/maglev/api/page_clones_controller.rb +0 -21
  384. data/app/controllers/maglev/api/pages_controller.rb +0 -65
  385. data/app/controllers/maglev/api/publications_controller.rb +0 -15
  386. data/app/controllers/maglev/api/sites_controller.rb +0 -21
  387. data/app/controllers/maglev/api_controller.rb +0 -61
  388. data/app/controllers/maglev/editor_controller.rb +0 -59
  389. data/app/frontend/admin/controllers/dropdown_controller.js +0 -9
  390. data/app/frontend/admin/controllers/iframe_controller.js +0 -16
  391. data/app/frontend/admin/controllers/screenshot_controller.js +0 -69
  392. data/app/frontend/admin/index.js +0 -10
  393. data/app/frontend/admin/utils/axios.js +0 -16
  394. data/app/frontend/editor/App.vue +0 -43
  395. data/app/frontend/editor/assets/remixicons/add-box-line.svg +0 -1
  396. data/app/frontend/editor/assets/remixicons/arrow-down-s-line.svg +0 -1
  397. data/app/frontend/editor/assets/remixicons/arrow-drop-left.svg +0 -1
  398. data/app/frontend/editor/assets/remixicons/arrow-drop-right.svg +0 -1
  399. data/app/frontend/editor/assets/remixicons/arrow-up-s-line.svg +0 -1
  400. data/app/frontend/editor/assets/remixicons/camera-line.svg +0 -1
  401. data/app/frontend/editor/assets/remixicons/clipboard-line.svg +0 -1
  402. data/app/frontend/editor/assets/remixicons/close-line.svg +0 -1
  403. data/app/frontend/editor/assets/remixicons/computer-line.svg +0 -1
  404. data/app/frontend/editor/assets/remixicons/delete-bin-line.svg +0 -1
  405. data/app/frontend/editor/assets/remixicons/file-line.svg +0 -1
  406. data/app/frontend/editor/assets/remixicons/format-blockquote.svg +0 -1
  407. data/app/frontend/editor/assets/remixicons/format-bold.svg +0 -1
  408. data/app/frontend/editor/assets/remixicons/format-code.svg +0 -1
  409. data/app/frontend/editor/assets/remixicons/format-heading-2.svg +0 -1
  410. data/app/frontend/editor/assets/remixicons/format-heading-3.svg +0 -1
  411. data/app/frontend/editor/assets/remixicons/format-heading-4.svg +0 -1
  412. data/app/frontend/editor/assets/remixicons/format-italic.svg +0 -1
  413. data/app/frontend/editor/assets/remixicons/format-link-unlink.svg +0 -1
  414. data/app/frontend/editor/assets/remixicons/format-link.svg +0 -1
  415. data/app/frontend/editor/assets/remixicons/format-list-ordered.svg +0 -1
  416. data/app/frontend/editor/assets/remixicons/format-list-unordered.svg +0 -1
  417. data/app/frontend/editor/assets/remixicons/format-paragraph.svg +0 -1
  418. data/app/frontend/editor/assets/remixicons/format-strikethrough.svg +0 -1
  419. data/app/frontend/editor/assets/remixicons/format-superscript.svg +0 -1
  420. data/app/frontend/editor/assets/remixicons/format-underline.svg +0 -1
  421. data/app/frontend/editor/assets/remixicons/home-4-line.svg +0 -1
  422. data/app/frontend/editor/assets/remixicons/image-line.svg +0 -1
  423. data/app/frontend/editor/assets/remixicons/logout-box-r-line.svg +0 -1
  424. data/app/frontend/editor/assets/remixicons/ri-add-line.svg +0 -1
  425. data/app/frontend/editor/assets/remixicons/ri-alert-line.svg +0 -1
  426. data/app/frontend/editor/assets/remixicons/ri-book-line.svg +0 -1
  427. data/app/frontend/editor/assets/remixicons/ri-bug-line.svg +0 -1
  428. data/app/frontend/editor/assets/remixicons/ri-check-line.svg +0 -1
  429. data/app/frontend/editor/assets/remixicons/ri-close-circle-line.svg +0 -1
  430. data/app/frontend/editor/assets/remixicons/ri-close-line.svg +0 -1
  431. data/app/frontend/editor/assets/remixicons/ri-delete-column.svg +0 -1
  432. data/app/frontend/editor/assets/remixicons/ri-delete-row.svg +0 -1
  433. data/app/frontend/editor/assets/remixicons/ri-draggable.svg +0 -1
  434. data/app/frontend/editor/assets/remixicons/ri-drop-line.svg +0 -1
  435. data/app/frontend/editor/assets/remixicons/ri-external-link-line.svg +0 -1
  436. data/app/frontend/editor/assets/remixicons/ri-eye-line.svg +0 -1
  437. data/app/frontend/editor/assets/remixicons/ri-eye-off-line.svg +0 -1
  438. data/app/frontend/editor/assets/remixicons/ri-file-copy-line.svg +0 -1
  439. data/app/frontend/editor/assets/remixicons/ri-file-line.svg +0 -1
  440. data/app/frontend/editor/assets/remixicons/ri-folders-line.svg +0 -1
  441. data/app/frontend/editor/assets/remixicons/ri-global-line.svg +0 -1
  442. data/app/frontend/editor/assets/remixicons/ri-insert-column-left.svg +0 -1
  443. data/app/frontend/editor/assets/remixicons/ri-insert-column-right.svg +0 -1
  444. data/app/frontend/editor/assets/remixicons/ri-insert-row-bottom.svg +0 -1
  445. data/app/frontend/editor/assets/remixicons/ri-insert-row-top.svg +0 -1
  446. data/app/frontend/editor/assets/remixicons/ri-loader-4-line.svg +0 -1
  447. data/app/frontend/editor/assets/remixicons/ri-mail-line.svg +0 -1
  448. data/app/frontend/editor/assets/remixicons/ri-more-2-fill.svg +0 -1
  449. data/app/frontend/editor/assets/remixicons/ri-more-fill.svg +0 -1
  450. data/app/frontend/editor/assets/remixicons/ri-palette-line.svg +0 -1
  451. data/app/frontend/editor/assets/remixicons/ri-pencil-line.svg +0 -1
  452. data/app/frontend/editor/assets/remixicons/ri-play-list-add-line.svg +0 -1
  453. data/app/frontend/editor/assets/remixicons/ri-settings-5-line.svg +0 -1
  454. data/app/frontend/editor/assets/remixicons/ri-shadow-line.svg +0 -1
  455. data/app/frontend/editor/assets/remixicons/ri-stack-line.svg +0 -1
  456. data/app/frontend/editor/assets/remixicons/ri-table-2.svg +0 -1
  457. data/app/frontend/editor/assets/remixicons/ri-table-line.svg +0 -1
  458. data/app/frontend/editor/assets/remixicons/search-line.svg +0 -1
  459. data/app/frontend/editor/assets/remixicons/settings-4-line.svg +0 -1
  460. data/app/frontend/editor/assets/remixicons/smartphone-line.svg +0 -1
  461. data/app/frontend/editor/assets/remixicons/tablet-line.svg +0 -1
  462. data/app/frontend/editor/components/dynamic-form/dynamic-input.vue +0 -141
  463. data/app/frontend/editor/components/dynamic-form/index.vue +0 -36
  464. data/app/frontend/editor/components/errors/forbidden.vue +0 -24
  465. data/app/frontend/editor/components/errors/stale-record.vue +0 -24
  466. data/app/frontend/editor/components/header-nav/device-toggler.vue +0 -40
  467. data/app/frontend/editor/components/header-nav/index.vue +0 -77
  468. data/app/frontend/editor/components/header-nav/locale-toggler/index.vue +0 -51
  469. data/app/frontend/editor/components/header-nav/locale-toggler/locale-link.vue +0 -32
  470. data/app/frontend/editor/components/header-nav/page-info.vue +0 -41
  471. data/app/frontend/editor/components/header-nav/preview-button.vue +0 -20
  472. data/app/frontend/editor/components/header-nav/preview-toggler.vue +0 -40
  473. data/app/frontend/editor/components/header-nav/publish-button.vue +0 -77
  474. data/app/frontend/editor/components/header-nav/save-button.vue +0 -33
  475. data/app/frontend/editor/components/header-nav/separator.vue +0 -11
  476. data/app/frontend/editor/components/icon-library/index.vue +0 -39
  477. data/app/frontend/editor/components/image-library/index.vue +0 -107
  478. data/app/frontend/editor/components/image-library/list-item.vue +0 -93
  479. data/app/frontend/editor/components/image-library/list.vue +0 -26
  480. data/app/frontend/editor/components/image-library/uploader.vue +0 -76
  481. data/app/frontend/editor/components/kit/accordion.vue +0 -68
  482. data/app/frontend/editor/components/kit/checkbox-input.vue +0 -59
  483. data/app/frontend/editor/components/kit/collection-item-input.vue +0 -79
  484. data/app/frontend/editor/components/kit/color-input/core-input.vue +0 -92
  485. data/app/frontend/editor/components/kit/color-input/preset-button.vue +0 -61
  486. data/app/frontend/editor/components/kit/color-input/preset-dropdown.vue +0 -47
  487. data/app/frontend/editor/components/kit/color-input.vue +0 -41
  488. data/app/frontend/editor/components/kit/confirmation-button.vue +0 -65
  489. data/app/frontend/editor/components/kit/copy-paste-button.vue +0 -26
  490. data/app/frontend/editor/components/kit/divider.vue +0 -22
  491. data/app/frontend/editor/components/kit/dropdown.vue +0 -66
  492. data/app/frontend/editor/components/kit/hint.vue +0 -12
  493. data/app/frontend/editor/components/kit/icon-button.vue +0 -24
  494. data/app/frontend/editor/components/kit/icon-input.vue +0 -96
  495. data/app/frontend/editor/components/kit/icon.vue +0 -36
  496. data/app/frontend/editor/components/kit/image-input.vue +0 -124
  497. data/app/frontend/editor/components/kit/index.js +0 -56
  498. data/app/frontend/editor/components/kit/link-input.vue +0 -121
  499. data/app/frontend/editor/components/kit/modal-root.vue +0 -85
  500. data/app/frontend/editor/components/kit/modal.vue +0 -39
  501. data/app/frontend/editor/components/kit/page-icon.vue +0 -21
  502. data/app/frontend/editor/components/kit/pagination/button.vue +0 -35
  503. data/app/frontend/editor/components/kit/pagination/index.vue +0 -116
  504. data/app/frontend/editor/components/kit/rich-text-input/block-button.vue +0 -75
  505. data/app/frontend/editor/components/kit/rich-text-input/extensions/Doc.js +0 -12
  506. data/app/frontend/editor/components/kit/rich-text-input/extensions/LineBreak.js +0 -38
  507. data/app/frontend/editor/components/kit/rich-text-input/extensions/marks/Link.js +0 -57
  508. data/app/frontend/editor/components/kit/rich-text-input/extensions/marks/Superscript.js +0 -43
  509. data/app/frontend/editor/components/kit/rich-text-input/format-buttons.vue +0 -47
  510. data/app/frontend/editor/components/kit/rich-text-input/link-buttons.vue +0 -91
  511. data/app/frontend/editor/components/kit/rich-text-input/list-buttons.vue +0 -29
  512. data/app/frontend/editor/components/kit/rich-text-input/menu-button.vue +0 -22
  513. data/app/frontend/editor/components/kit/rich-text-input/table-button.vue +0 -112
  514. data/app/frontend/editor/components/kit/rich-text-input.vue +0 -187
  515. data/app/frontend/editor/components/kit/search-input.vue +0 -54
  516. data/app/frontend/editor/components/kit/select-input.vue +0 -200
  517. data/app/frontend/editor/components/kit/simple-select.vue +0 -56
  518. data/app/frontend/editor/components/kit/submit-button.vue +0 -117
  519. data/app/frontend/editor/components/kit/tabs.vue +0 -99
  520. data/app/frontend/editor/components/kit/text-input.vue +0 -63
  521. data/app/frontend/editor/components/kit/textarea-input.vue +0 -61
  522. data/app/frontend/editor/components/link-picker/actions.vue +0 -32
  523. data/app/frontend/editor/components/link-picker/email.vue +0 -32
  524. data/app/frontend/editor/components/link-picker/index.vue +0 -97
  525. data/app/frontend/editor/components/link-picker/page.vue +0 -126
  526. data/app/frontend/editor/components/link-picker/url.vue +0 -43
  527. data/app/frontend/editor/components/page/edit.vue +0 -99
  528. data/app/frontend/editor/components/page/form/main.vue +0 -64
  529. data/app/frontend/editor/components/page/form/seo.vue +0 -94
  530. data/app/frontend/editor/components/page/list/actions-button.vue +0 -159
  531. data/app/frontend/editor/components/page/list/index.vue +0 -58
  532. data/app/frontend/editor/components/page/list/list-item.vue +0 -96
  533. data/app/frontend/editor/components/page/new.vue +0 -79
  534. data/app/frontend/editor/components/section-block-pane/index.vue +0 -69
  535. data/app/frontend/editor/components/section-block-pane/setting-list.vue +0 -53
  536. data/app/frontend/editor/components/section-highlighter/bottom-actions.vue +0 -60
  537. data/app/frontend/editor/components/section-highlighter/index.vue +0 -125
  538. data/app/frontend/editor/components/section-highlighter/top-left-actions.vue +0 -78
  539. data/app/frontend/editor/components/section-highlighter/top-right-actions.vue +0 -130
  540. data/app/frontend/editor/components/section-list/add-button.vue +0 -39
  541. data/app/frontend/editor/components/section-list/index.vue +0 -79
  542. data/app/frontend/editor/components/section-list/list-item.vue +0 -60
  543. data/app/frontend/editor/components/section-pane/block-list/index.vue +0 -68
  544. data/app/frontend/editor/components/section-pane/block-list/list-item.vue +0 -74
  545. data/app/frontend/editor/components/section-pane/block-list/new-block-button.vue +0 -74
  546. data/app/frontend/editor/components/section-pane/block-tree/index.vue +0 -63
  547. data/app/frontend/editor/components/section-pane/block-tree/new-nested-block-button.vue +0 -67
  548. data/app/frontend/editor/components/section-pane/block-tree/tree-node.vue +0 -109
  549. data/app/frontend/editor/components/section-pane/index.vue +0 -94
  550. data/app/frontend/editor/components/section-pane/setting-list.vue +0 -50
  551. data/app/frontend/editor/components/sidebar-nav/index.vue +0 -102
  552. data/app/frontend/editor/components/sidebar-nav/link.vue +0 -60
  553. data/app/frontend/editor/components/style-pane/index.vue +0 -48
  554. data/app/frontend/editor/components/theme-section-list/category.vue +0 -47
  555. data/app/frontend/editor/components/theme-section-list/index.vue +0 -27
  556. data/app/frontend/editor/components/theme-section-list/list-item.vue +0 -95
  557. data/app/frontend/editor/design/application.scss +0 -17
  558. data/app/frontend/editor/design/components/buttons.scss +0 -25
  559. data/app/frontend/editor/design/components/modal.scss +0 -49
  560. data/app/frontend/editor/design/components/tooltip.scss +0 -123
  561. data/app/frontend/editor/design/components/tree.scss +0 -6
  562. data/app/frontend/editor/design/helpers.scss +0 -9
  563. data/app/frontend/editor/design/transitions.scss +0 -121
  564. data/app/frontend/editor/layouts/app.vue +0 -42
  565. data/app/frontend/editor/layouts/default.vue +0 -57
  566. data/app/frontend/editor/layouts/slide-pane.vue +0 -87
  567. data/app/frontend/editor/locales/editor.ar.json +0 -265
  568. data/app/frontend/editor/locales/editor.en.json +0 -265
  569. data/app/frontend/editor/locales/editor.es.json +0 -265
  570. data/app/frontend/editor/locales/editor.fr.json +0 -265
  571. data/app/frontend/editor/locales/editor.pt-BR.json +0 -265
  572. data/app/frontend/editor/locales/index.js +0 -23
  573. data/app/frontend/editor/main.js +0 -21
  574. data/app/frontend/editor/misc/__tests__/utils.spec.js +0 -43
  575. data/app/frontend/editor/misc/utils.js +0 -177
  576. data/app/frontend/editor/mixins/error-modal.js +0 -28
  577. data/app/frontend/editor/mixins/focused-input.js +0 -20
  578. data/app/frontend/editor/mixins/global.js +0 -140
  579. data/app/frontend/editor/mixins/grouped-dropdowns.js +0 -17
  580. data/app/frontend/editor/mixins/index.js +0 -1
  581. data/app/frontend/editor/mixins/preview-transformation.js +0 -59
  582. data/app/frontend/editor/plugins/event-bus.js +0 -3
  583. data/app/frontend/editor/plugins/filters.js +0 -7
  584. data/app/frontend/editor/plugins/i18n.js +0 -13
  585. data/app/frontend/editor/plugins/index.js +0 -3
  586. data/app/frontend/editor/plugins/tooltip.js +0 -4
  587. data/app/frontend/editor/router/index.js +0 -41
  588. data/app/frontend/editor/router/routes/base.js +0 -59
  589. data/app/frontend/editor/router/routes/index.js +0 -3
  590. data/app/frontend/editor/router/routes/page.js +0 -30
  591. data/app/frontend/editor/router/routes/section-block.js +0 -29
  592. data/app/frontend/editor/router/routes/section.js +0 -67
  593. data/app/frontend/editor/router/routes/style.js +0 -17
  594. data/app/frontend/editor/services/__tests__/page.spec.js +0 -38
  595. data/app/frontend/editor/services/__tests__/section.spec.js +0 -39
  596. data/app/frontend/editor/services/api.js +0 -40
  597. data/app/frontend/editor/services/block.js +0 -26
  598. data/app/frontend/editor/services/collection-item.js +0 -20
  599. data/app/frontend/editor/services/image.js +0 -26
  600. data/app/frontend/editor/services/index.js +0 -21
  601. data/app/frontend/editor/services/live-preview.js +0 -131
  602. data/app/frontend/editor/services/page.js +0 -107
  603. data/app/frontend/editor/services/section.js +0 -214
  604. data/app/frontend/editor/services/site.js +0 -21
  605. data/app/frontend/editor/services/theme.js +0 -9
  606. data/app/frontend/editor/spec/__mocks__/page.js +0 -434
  607. data/app/frontend/editor/spec/__mocks__/section.js +0 -232
  608. data/app/frontend/editor/spec/__mocks__/services.js +0 -84
  609. data/app/frontend/editor/spec/__mocks__/site.js +0 -95
  610. data/app/frontend/editor/spec/__mocks__/theme.js +0 -518
  611. data/app/frontend/editor/store/__tests__/getters.spec.js +0 -158
  612. data/app/frontend/editor/store/actions/__tests__/page.spec.js +0 -97
  613. data/app/frontend/editor/store/actions/__tests__/section-block.spec.js +0 -105
  614. data/app/frontend/editor/store/actions/__tests__/section.spec.js +0 -62
  615. data/app/frontend/editor/store/actions/index.js +0 -35
  616. data/app/frontend/editor/store/actions/page.js +0 -66
  617. data/app/frontend/editor/store/actions/section-block.js +0 -57
  618. data/app/frontend/editor/store/actions/section.js +0 -75
  619. data/app/frontend/editor/store/actions/site.js +0 -32
  620. data/app/frontend/editor/store/default-state.js +0 -27
  621. data/app/frontend/editor/store/getters.js +0 -113
  622. data/app/frontend/editor/store/index.js +0 -29
  623. data/app/frontend/editor/store/mutations.js +0 -187
  624. data/app/frontend/editor/views/content-pane.vue +0 -109
  625. data/app/frontend/editor/views/page-preview.vue +0 -160
  626. data/app/frontend/editor/views/pages/edit.vue +0 -26
  627. data/app/frontend/editor/views/pages/index.vue +0 -65
  628. data/app/frontend/editor/views/sections/add-pane.vue +0 -23
  629. data/app/frontend/editor/views/sections/list-pane.vue +0 -20
  630. data/app/frontend/editor/views/slide-pane.vue +0 -14
  631. data/app/frontend/editor/views/slide-pane2.vue +0 -14
  632. data/app/frontend/editor/views/style/edit-pane.vue +0 -22
  633. data/app/frontend/entrypoints/admin.js +0 -3
  634. data/app/frontend/entrypoints/admin.scss +0 -5
  635. data/app/frontend/entrypoints/editor.js +0 -8
  636. data/app/frontend/entrypoints/live-preview-client.js +0 -6
  637. data/app/frontend/entrypoints/live-preview-rails-client.js +0 -9
  638. data/app/frontend/live-preview-client/index.js +0 -11
  639. data/app/frontend/live-preview-client/rails.js +0 -217
  640. data/app/helpers/maglev/editor_helper.rb +0 -95
  641. data/app/services/maglev/persist_page.rb +0 -97
  642. data/app/views/layouts/maglev/admin/_header_actions.html.erb +0 -5
  643. data/app/views/layouts/maglev/admin/application.html.erb +0 -26
  644. data/app/views/maglev/admin/sections/previews/show.html.erb +0 -47
  645. data/app/views/maglev/admin/themes/_empty.html.erb +0 -20
  646. data/app/views/maglev/admin/themes/_section_categories.html.erb +0 -9
  647. data/app/views/maglev/admin/themes/_sections.html.erb +0 -54
  648. data/app/views/maglev/admin/themes/show.html.erb +0 -21
  649. data/app/views/maglev/api/_pagination.json.jbuilder +0 -6
  650. data/app/views/maglev/api/assets/_show.json.jbuilder +0 -8
  651. data/app/views/maglev/api/assets/index.json.jbuilder +0 -9
  652. data/app/views/maglev/api/assets/show.json.jbuilder +0 -3
  653. data/app/views/maglev/api/collection_items/_show.json.jbuilder +0 -5
  654. data/app/views/maglev/api/collection_items/index.json.jbuilder +0 -5
  655. data/app/views/maglev/api/collection_items/show.json.jbuilder +0 -7
  656. data/app/views/maglev/api/page_clones/create.json.jbuilder +0 -3
  657. data/app/views/maglev/api/pages/_show.json.jbuilder +0 -23
  658. data/app/views/maglev/api/pages/index.json.jbuilder +0 -18
  659. data/app/views/maglev/api/pages/show.json.jbuilder +0 -3
  660. data/app/views/maglev/api/sites/_show.json.jbuilder +0 -15
  661. data/app/views/maglev/api/sites/show.json.jbuilder +0 -3
  662. data/app/views/maglev/api/themes/_show.json.jbuilder +0 -17
  663. data/app/views/maglev/editor/_header.html.erb +0 -1
  664. data/app/views/maglev/editor/show.html.erb +0 -41
  665. data/app/views/maglev/settings/index.html.erb +0 -11
  666. data/bin/vite +0 -29
  667. data/config/initializers/kaminari.rb +0 -16
  668. data/config/vite.json +0 -17
  669. data/lib/tasks/maglev/vite.rake +0 -62
  670. data/package.json +0 -58
  671. data/postcss.config.cjs +0 -6
  672. data/tailwind.config.js +0 -68
  673. data/vite.config.ts +0 -18
  674. data/yarn.lock +0 -4749
  675. /data/app/{frontend/images → assets/images/maglev}/favicon.svg +0 -0
  676. /data/app/{frontend/images → assets/images/maglev}/logo.svg +0 -0
  677. /data/app/{frontend/live-preview-client → assets/javascripts/maglev/client}/run-scripts.js +0 -0
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Maglev
4
+ module Content
5
+ class AddSectionService
6
+ include Injectable
7
+ include Maglev::Content::HelpersConcern
8
+
9
+ dependency :fetch_theme
10
+ dependency :fetch_site
11
+
12
+ argument :page
13
+ argument :section_type
14
+ argument :content, default: nil
15
+ argument :position, default: -1
16
+ argument :dry_run, default: false
17
+ argument :site, default: nil
18
+ argument :theme, default: nil
19
+
20
+ def call
21
+ raise Maglev::Errors::UnknownSection unless section_definition
22
+
23
+ section_content = build_section_content
24
+
25
+ ActiveRecord::Base.transaction do
26
+ add_to_site!(section_content) if can_add_to_site?
27
+ add_to_page!(section_content) if can_add_to_page?
28
+ end
29
+
30
+ # in case the instance of the service is reused, we need to reset the memoization
31
+ # this is the case for the setup_pages service
32
+ reset_memoization
33
+
34
+ section_content
35
+ end
36
+
37
+ private
38
+
39
+ def theme
40
+ @theme ||= fetch_theme.call
41
+ end
42
+
43
+ def site
44
+ @site ||= fetch_site.call
45
+ end
46
+
47
+ def add_to_site!(section_content)
48
+ # we don't care about the position for site scoped sections
49
+ site.sections_translations_will_change!
50
+
51
+ site.sections ||= []
52
+ site.sections.push(section_content)
53
+ site.prepare_sections(theme)
54
+
55
+ site.save! unless dry_run
56
+ end
57
+
58
+ def add_to_page!(section_content)
59
+ page.sections_translations_will_change!
60
+ page.sections ||= []
61
+ page.sections.insert(final_position, section_content)
62
+ page.prepare_sections(theme)
63
+
64
+ page.save! unless dry_run
65
+ end
66
+
67
+ def can_add_to_site?
68
+ # We don't want to add the section to the site if there is already a section with the same type
69
+ site_scoped? && site.find_sections_by_type(section_type).empty?
70
+ end
71
+
72
+ def can_add_to_page?
73
+ # we don't want to add the section if it's a singleton and there is already a section with the same type
74
+ !(section_definition.singleton? && page.find_sections_by_type(section_type).any?)
75
+ end
76
+
77
+ def build_section_content
78
+ if site_scoped? && site.find_sections_by_type(section_type).any?
79
+ site.find_sections_by_type(section_type).first.dup
80
+ else
81
+ content || section_definition.build_default_content
82
+ end.with_indifferent_access
83
+ end
84
+
85
+ def section_definition
86
+ @section_definition ||= theme.sections.find(section_type)
87
+ end
88
+
89
+ def final_position
90
+ case section_definition.insert_at
91
+ when 'top' then 0
92
+ when 'bottom' then page.sections.count
93
+ else
94
+ position
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Maglev
4
+ module Content
5
+ class DeleteSectionBlockService
6
+ include Injectable
7
+ include Maglev::Content::HelpersConcern
8
+
9
+ dependency :fetch_theme
10
+ dependency :fetch_site
11
+
12
+ argument :page
13
+ argument :section_id
14
+ argument :block_id
15
+ argument :lock_version, default: nil
16
+
17
+ def call
18
+ raise Maglev::Errors::UnknownSection unless section_definition
19
+ raise Maglev::Errors::UnknownBlock unless block_definition
20
+
21
+ ActiveRecord::Base.transaction do
22
+ if site_scoped?
23
+ delete_section_block!(site)
24
+ else
25
+ delete_section_block!(page)
26
+ end
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def delete_section_block!(source)
33
+ check_section_lock_version!(source)
34
+
35
+ source.sections_translations_will_change!
36
+ delete_section_block(source)
37
+ source.save!
38
+ end
39
+
40
+ def delete_section_block(source)
41
+ find_blocks(source).delete_if { |block| block['id'] == block_id }
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Maglev
4
+ module Content
5
+ class DeleteSectionService
6
+ include Injectable
7
+ include Maglev::Content::HelpersConcern
8
+
9
+ dependency :fetch_theme
10
+ dependency :fetch_site
11
+
12
+ argument :page
13
+ argument :section_id
14
+
15
+ def call
16
+ raise Maglev::Errors::UnknownSection unless section_definition
17
+
18
+ ActiveRecord::Base.transaction do
19
+ # we never delete site scoped sections:
20
+ # A page might not need it anymore but others might still need it.
21
+ delete_section!(page)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def delete_section!(source)
28
+ source.sections_translations_will_change!
29
+ source.delete_section(section_id)
30
+ source.save!
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Maglev
4
+ module Content
5
+ class SortSectionBlocksService
6
+ include Injectable
7
+ include Maglev::Content::HelpersConcern
8
+
9
+ dependency :fetch_theme
10
+ dependency :fetch_site
11
+
12
+ argument :page
13
+ argument :section_id
14
+ argument :block_ids
15
+ argument :parent_id, default: nil
16
+ argument :lock_version, default: nil
17
+
18
+ def call
19
+ raise Maglev::Errors::UnknownSection unless section_definition
20
+
21
+ ActiveRecord::Base.transaction do
22
+ if site_scoped?
23
+ sort_section_blocks!(site)
24
+ else
25
+ sort_section_blocks!(page)
26
+ end
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def sort_section_blocks!(source)
33
+ check_section_lock_version!(source)
34
+
35
+ source.sections_translations_will_change!
36
+ sort_section_blocks(source)
37
+ source.save!
38
+ end
39
+
40
+ def sort_section_blocks(source)
41
+ find_blocks(source)&.sort_by! do |block|
42
+ block['parent_id'] == parent_id ? block_ids.index(block['id']) || Float::INFINITY : -1
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Maglev
4
+ module Content
5
+ class UpdateSectionBlockService
6
+ include Injectable
7
+ include Maglev::Content::HelpersConcern
8
+
9
+ dependency :fetch_theme
10
+ dependency :fetch_site
11
+
12
+ argument :page
13
+ argument :section_id
14
+ argument :block_id
15
+ argument :content
16
+ argument :lock_version, default: nil
17
+
18
+ def call
19
+ raise Maglev::Errors::UnknownSection unless section_definition
20
+ raise Maglev::Errors::UnknownBlock unless block_definition
21
+
22
+ ActiveRecord::Base.transaction do
23
+ if site_scoped?
24
+ update_section_block_content!(site)
25
+ else
26
+ update_section_block_content!(page)
27
+ end
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def update_section_block_content!(source)
34
+ check_block_lock_version!(source)
35
+
36
+ source.sections_translations_will_change!
37
+ update_section_block_content(source)
38
+ source.save!
39
+ end
40
+
41
+ def update_section_block_content(source)
42
+ current_section_block_content = find_block_content(source)
43
+
44
+ block_definition.settings.each do |setting|
45
+ next unless content.key?(setting.id.to_sym)
46
+
47
+ update_setting_value(setting, current_section_block_content)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Maglev
4
+ module Content
5
+ class UpdateSectionService
6
+ include Injectable
7
+ include Maglev::Content::HelpersConcern
8
+
9
+ dependency :fetch_theme
10
+ dependency :fetch_site
11
+
12
+ argument :page
13
+ argument :section_id
14
+ argument :content
15
+ argument :lock_version, default: nil
16
+
17
+ def call
18
+ raise Maglev::Errors::UnknownSection unless section_definition
19
+
20
+ ActiveRecord::Base.transaction do
21
+ if site_scoped?
22
+ update_section_content!(site)
23
+ else
24
+ update_section_content!(page)
25
+ end
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def update_section_content!(source)
32
+ check_section_lock_version!(source)
33
+
34
+ source.sections_translations_will_change!
35
+ update_section_content(source)
36
+ source.save!
37
+ end
38
+
39
+ def update_section_content(source)
40
+ current_section_content = find_section_content(source)
41
+
42
+ section_definition.settings.each do |setting|
43
+ next unless content.key?(setting.id.to_sym)
44
+
45
+ update_setting_value(setting, current_section_content)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Maglev
4
+ class CreatePageService
5
+ include Injectable
6
+
7
+ dependency :fetch_site
8
+
9
+ argument :attributes
10
+ argument :site, default: nil
11
+
12
+ def call
13
+ page = translate(build_page)
14
+ page.save
15
+ page
16
+ end
17
+
18
+ private
19
+
20
+ def site
21
+ @site ||= fetch_site.call
22
+ end
23
+
24
+ def build_page
25
+ Maglev::Page.new(attributes)
26
+ end
27
+
28
+ def translate(page)
29
+ site.locale_prefixes.each do |locale|
30
+ Maglev::I18n.with_locale(locale) do
31
+ # the title mightn't be empty if we set the title_translations field in "attributes"
32
+ page.title ||= attributes[:title]
33
+ page.path ||= attributes[:path]
34
+ end
35
+ end
36
+ page
37
+ end
38
+ end
39
+ end
@@ -8,7 +8,18 @@ module Maglev
8
8
  argument :section
9
9
 
10
10
  def call
11
- fetch_section_screenshot_path.call(section: section) + "?#{section.screenshot_timestamp}"
11
+ screenshot_path = fetch_section_screenshot_path.call(section: section) + query_string
12
+ asset_host ? URI.join(asset_host, screenshot_path).to_s : screenshot_path
13
+ end
14
+
15
+ private
16
+
17
+ def asset_host
18
+ Rails.application.config.asset_host
19
+ end
20
+
21
+ def query_string
22
+ "?#{section.screenshot_timestamp}"
12
23
  end
13
24
  end
14
25
  end
@@ -5,34 +5,44 @@ module Maglev
5
5
  class FetchStyle
6
6
  include Injectable
7
7
 
8
- argument :site
9
- argument :theme
8
+ dependency :fetch_site
9
+ dependency :fetch_theme
10
10
 
11
11
  def call
12
- Maglev::Site::StyleValue::Store.new(
12
+ Maglev::Site::StyleValue::AssociationProxy.new(
13
13
  build_style_value_list
14
14
  )
15
15
  end
16
16
 
17
17
  protected
18
18
 
19
+ def site
20
+ @site ||= fetch_site.call
21
+ end
22
+
23
+ def theme
24
+ @theme ||= fetch_theme.call
25
+ end
26
+
19
27
  def build_style_value_list
20
- theme.style_settings.map do |setting|
21
- build_style_value(setting)
28
+ theme.style_settings.map do |definition|
29
+ build_style_value(definition)
22
30
  end
23
31
  end
24
32
 
25
- def build_style_value(setting)
33
+ def build_style_value(definition)
26
34
  Maglev::Site::StyleValue.new(
27
- setting.id,
28
- setting.type,
29
- custom_value(setting)
35
+ definition.id,
36
+ definition.type,
37
+ custom_value(definition)
30
38
  )
31
39
  end
32
40
 
33
- def custom_value(setting)
34
- value = site.style.find { |local_value| local_value['id'] == setting.id }
35
- value && value['type'] == setting.type ? value['value'] : setting.default
41
+ def custom_value(definition)
42
+ value = (site.style || []).find do |local_value|
43
+ local_value['id'] == definition.id && local_value['type'] == definition.type
44
+ end
45
+ value ? value['value'] : definition.default
36
46
  end
37
47
  end
38
48
  end
@@ -26,7 +26,9 @@ module Maglev
26
26
  end
27
27
 
28
28
  def live_url
29
- nil
29
+ return nil if context.controller.request.nil?
30
+
31
+ context.controller.request.base_url
30
32
  end
31
33
  end
32
34
  end
@@ -12,7 +12,7 @@ module Maglev
12
12
  def call
13
13
  (page.sections || []).map do |section|
14
14
  definition = theme.sections.find(section['type'])
15
- { id: section['id'], name: definition.name }
15
+ { id: section['id'], name: definition.human_name }
16
16
  end
17
17
  end
18
18
 
@@ -6,9 +6,7 @@ module Maglev
6
6
  # Also replace the links by their real values based on the context (live editing or not).
7
7
  class GetPageSections
8
8
  include Injectable
9
- include Maglev::GetPageSections::TransformTextConcern
10
- include Maglev::GetPageSections::TransformLinkConcern
11
- include Maglev::GetPageSections::TransformCollectionItemConcern
9
+ include Maglev::GetPageSections::TransformSectionConcern
12
10
 
13
11
  dependency :fetch_site
14
12
  dependency :fetch_theme
@@ -17,11 +15,11 @@ module Maglev
17
15
  dependency :get_page_fullpath
18
16
 
19
17
  argument :page
20
- argument :page_sections, default: nil
18
+ argument :section_id, default: nil
21
19
  argument :locale, default: nil
22
20
 
23
21
  def call
24
- (page_sections || page.sections || []).map do |section|
22
+ sections.map do |section|
25
23
  transform_section(section.dup)
26
24
  end.compact
27
25
  end
@@ -36,85 +34,16 @@ module Maglev
36
34
  fetch_site.call
37
35
  end
38
36
 
39
- def transform_section(section)
40
- definition = theme.sections.find(section['type'])
41
-
42
- raise_unknown_section_error(section['type']) unless definition
43
-
44
- transform_if_site_scoped(section, definition)
45
- transform_section_blocks(section['blocks'], definition)
46
- transform_section_settings(section, definition)
47
-
48
- section
49
- end
50
-
51
- # rubocop:disable Style/StringHashKeys
52
- def transform_if_site_scoped(section, definition)
53
- return unless definition.site_scoped?
54
-
55
- site_section = site.find_section(section['type'])
56
-
57
- return unless !page_sections && site_section
58
-
59
- # keep the same section id all over the pages
60
- section.merge!(
61
- 'id' => site_section['id'],
62
- 'settings' => site_section['settings'],
63
- 'blocks' => site_section['blocks']
64
- )
65
- end
66
- # rubocop:enable Style/StringHashKeys
67
-
68
- def transform_section_blocks(blocks, definition)
69
- blocks.each do |block|
70
- block_definition = definition.blocks.find { |bd| bd.type == block['type'] }
71
-
72
- next unless block_definition
73
-
74
- transform_section_settings(block, block_definition)
75
- end
76
- end
77
-
78
- def transform_section_settings(section, definition)
79
- remove_unused_settings(section, definition)
80
-
81
- definition.settings.each do |setting|
82
- section_setting = find_section_setting(section, setting.id)
83
-
84
- next unless section_setting
85
-
86
- transform_content_setting(section_setting, setting)
87
- end
88
- end
89
-
90
- def transform_content_setting(content, setting)
91
- case setting.type
92
- when 'link'
93
- transform_link_content_setting(content, setting)
94
- when 'text'
95
- transform_text_content_setting(content, setting)
96
- when 'collection_item'
97
- transform_collection_item_content_setting(content, setting)
98
- end
99
- end
100
-
101
- def remove_unused_settings(section, definition)
102
- section['settings'].select! do |setting|
103
- definition.settings.any? do |definition_setting|
104
- definition_setting.id == setting['id']
105
- end
106
- end
107
- end
108
-
109
- def find_section_setting(section, setting_id)
110
- # NOTE: works for both sections and blocks
111
- section['settings'].find { |setting| setting['id'] == setting_id }
37
+ def sections
38
+ if section_id.present? # when refreshing the preview of a section in the editor
39
+ [page.find_section_by_id(section_id)]
40
+ else
41
+ page.sections || []
42
+ end.compact
112
43
  end
113
44
 
114
- def raise_unknown_section_error(type)
115
- raise ::Maglev::Errors::UnknownSection, "Unknown Maglev section type (#{type})" unless Rails.env.production?
116
-
117
- Rails.logger.warn "[#{theme.id}] unknown Maglev section type (#{type})"
45
+ def find_site_section(type)
46
+ site.find_section(type)
118
47
  end
119
48
  end
120
49
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Maglev
4
+ class GetPublishedPageSectionsService
5
+ include Injectable
6
+ include Maglev::GetPageSections::TransformSectionConcern
7
+
8
+ dependency :fetch_site
9
+ dependency :fetch_theme
10
+ dependency :fetch_collection_items
11
+ dependency :fetch_static_pages
12
+ dependency :get_page_fullpath
13
+
14
+ argument :page
15
+ argument :locale, default: nil
16
+
17
+ def call
18
+ fetch_container_store(page).sections.map do |section|
19
+ transform_section(section.dup)
20
+ end.compact
21
+ end
22
+
23
+ protected
24
+
25
+ def theme
26
+ fetch_theme.call
27
+ end
28
+
29
+ def site
30
+ fetch_site.call
31
+ end
32
+
33
+ def site_store
34
+ @site_store ||= fetch_container_store(site)
35
+ end
36
+
37
+ def find_site_section(type)
38
+ site_store.find_sections_by_type(type).first
39
+ end
40
+
41
+ def fetch_container_store(container)
42
+ store = container.sections_content_stores.published.first
43
+ raise Maglev::Errors::UnpublishedPage if store.blank?
44
+
45
+ store
46
+ end
47
+ end
48
+ end
@@ -34,7 +34,7 @@ module Maglev
34
34
  tmp_file.write(image_data)
35
35
  tmp_file.close
36
36
 
37
- # PNG -> JPG to lower the size of the image
37
+ # PNG -> JPG to decrease the size of the image
38
38
  ::ActiveStorage::Variation.new(format: 'jpg', saver: { quality: 90 }).transform(tmp_file) do |output|
39
39
  FileUtils.mkdir_p(screenshots_dir)
40
40
  File.open(screenshot_filepath, 'wb') do |f|
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Maglev
4
+ class PersistStyleService
5
+ include Injectable
6
+
7
+ dependency :fetch_theme
8
+ dependency :fetch_site
9
+
10
+ argument :new_style
11
+ argument :lock_version, default: nil
12
+
13
+ def call
14
+ site.lock_version = lock_version if lock_version.present?
15
+ site.style = compute_new_style
16
+ site.save!
17
+ end
18
+
19
+ private
20
+
21
+ def site
22
+ @site ||= fetch_site.call
23
+ end
24
+
25
+ def theme
26
+ @theme ||= fetch_theme.call
27
+ end
28
+
29
+ def compute_new_style
30
+ theme.style_settings.map do |definition|
31
+ value = new_style[definition.id.to_s]
32
+ { id: definition.id, value: value, type: definition.type }
33
+ end
34
+ end
35
+ end
36
+ end