alchemy_cms 6.1.10 → 7.0.0.pre.a

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 (249) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +0 -3
  3. data/.gitignore +1 -6
  4. data/CHANGELOG.md +19 -44
  5. data/Gemfile +1 -1
  6. data/Rakefile +14 -9
  7. data/alchemy_cms.gemspec +2 -3
  8. data/app/assets/javascripts/alchemy/alchemy.dirty.js.coffee +1 -1
  9. data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +18 -32
  10. data/app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee +2 -2
  11. data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +2 -2
  12. data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +27 -29
  13. data/app/assets/stylesheets/alchemy/elements.scss +16 -35
  14. data/app/assets/stylesheets/alchemy/forms.scss +0 -4
  15. data/app/assets/stylesheets/alchemy/node-select.scss +2 -2
  16. data/app/controllers/alchemy/admin/attachments_controller.rb +0 -1
  17. data/app/controllers/alchemy/admin/elements_controller.rb +7 -32
  18. data/app/controllers/alchemy/admin/pages_controller.rb +1 -1
  19. data/app/controllers/alchemy/admin/pictures_controller.rb +1 -1
  20. data/app/controllers/alchemy/admin/resources_controller.rb +1 -18
  21. data/app/controllers/alchemy/api/elements_controller.rb +0 -2
  22. data/app/controllers/alchemy/api/pages_controller.rb +8 -4
  23. data/app/controllers/alchemy/messages_controller.rb +9 -9
  24. data/app/controllers/alchemy/pages_controller.rb +23 -18
  25. data/app/decorators/alchemy/element_editor.rb +10 -30
  26. data/app/helpers/alchemy/admin/elements_helper.rb +0 -2
  27. data/app/helpers/alchemy/elements_block_helper.rb +5 -42
  28. data/app/helpers/alchemy/elements_helper.rb +3 -11
  29. data/app/helpers/alchemy/pages_helper.rb +0 -4
  30. data/app/models/alchemy/attachment.rb +6 -3
  31. data/app/models/alchemy/base_record.rb +2 -0
  32. data/app/models/alchemy/eager_loading.rb +0 -1
  33. data/app/models/alchemy/element/element_ingredients.rb +1 -8
  34. data/app/models/alchemy/element/presenters.rb +9 -25
  35. data/app/models/alchemy/element.rb +2 -18
  36. data/app/models/alchemy/ingredient.rb +17 -6
  37. data/app/models/alchemy/ingredients/audio.rb +2 -0
  38. data/app/models/alchemy/ingredients/datetime.rb +3 -1
  39. data/app/models/alchemy/ingredients/file.rb +7 -0
  40. data/app/models/alchemy/ingredients/headline.rb +6 -0
  41. data/app/models/alchemy/ingredients/link.rb +2 -0
  42. data/app/models/alchemy/ingredients/node.rb +2 -0
  43. data/app/models/alchemy/ingredients/page.rb +2 -0
  44. data/app/models/alchemy/ingredients/picture.rb +11 -0
  45. data/app/models/alchemy/ingredients/richtext.rb +6 -0
  46. data/app/models/alchemy/ingredients/select.rb +1 -0
  47. data/app/models/alchemy/ingredients/text.rb +8 -0
  48. data/app/models/alchemy/ingredients/video.rb +2 -0
  49. data/app/models/alchemy/node.rb +9 -6
  50. data/app/models/alchemy/page/page_elements.rb +5 -26
  51. data/app/models/alchemy/page/page_layouts.rb +0 -14
  52. data/app/models/alchemy/page/page_natures.rb +0 -10
  53. data/app/models/alchemy/page.rb +0 -10
  54. data/app/models/alchemy/picture/transformations.rb +0 -30
  55. data/app/models/alchemy/picture/url.rb +1 -1
  56. data/app/models/alchemy/picture.rb +14 -13
  57. data/app/models/alchemy/picture_thumb/create.rb +7 -18
  58. data/app/models/alchemy/picture_thumb/file_store.rb +33 -0
  59. data/app/models/alchemy/picture_thumb.rb +10 -10
  60. data/app/models/concerns/alchemy/picture_thumbnails.rb +2 -6
  61. data/app/serializers/alchemy/element_serializer.rb +1 -6
  62. data/app/services/alchemy/delete_elements.rb +1 -7
  63. data/app/services/alchemy/duplicate_element.rb +1 -6
  64. data/app/views/alchemy/admin/elements/_element.html.erb +5 -22
  65. data/app/views/alchemy/admin/elements/create.js.erb +1 -1
  66. data/app/views/alchemy/admin/elements/fold.js.erb +2 -2
  67. data/app/views/alchemy/admin/elements/order.js.erb +1 -1
  68. data/app/views/alchemy/admin/elements/update.js.erb +1 -2
  69. data/app/views/alchemy/admin/pages/_external_link.html.erb +2 -2
  70. data/app/views/alchemy/admin/pages/_file_link.html.erb +2 -2
  71. data/app/views/alchemy/admin/pages/_internal_link.html.erb +2 -2
  72. data/app/views/alchemy/admin/pages/_table.html.erb +0 -6
  73. data/app/views/alchemy/admin/pages/_tinymce_custom_config.html.erb +3 -6
  74. data/app/views/alchemy/admin/pages/edit.html.erb +1 -1
  75. data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +1 -3
  76. data/app/views/alchemy/admin/pictures/_infos.html.erb +4 -6
  77. data/app/views/alchemy/admin/resources/_per_page_select.html.erb +1 -1
  78. data/app/views/alchemy/ingredients/_boolean_editor.html.erb +1 -1
  79. data/app/views/alchemy/ingredients/_headline_editor.html.erb +1 -1
  80. data/app/views/alchemy/ingredients/_html_editor.html.erb +1 -1
  81. data/app/views/alchemy/ingredients/_node_editor.html.erb +1 -1
  82. data/app/views/alchemy/ingredients/_picture_editor.html.erb +4 -4
  83. data/app/views/alchemy/ingredients/_select_editor.html.erb +2 -2
  84. data/app/views/alchemy/ingredients/_text_editor.html.erb +1 -1
  85. data/app/views/alchemy/ingredients/shared/_link_tools.html.erb +3 -3
  86. data/app/views/alchemy/pages/_meta_data.html.erb +0 -1
  87. data/app/views/layouts/alchemy/admin.html.erb +5 -1
  88. data/config/alchemy/config.yml +6 -6
  89. data/config/brakeman.ignore +56 -57
  90. data/config/locales/alchemy.en.yml +99 -113
  91. data/config/routes.rb +1 -16
  92. data/db/migrate/20230121212637_alchemy_six_point_one.rb +248 -0
  93. data/lib/alchemy/cache_digests/template_tracker.rb +6 -7
  94. data/lib/alchemy/config.rb +2 -2
  95. data/lib/alchemy/deprecation.rb +1 -1
  96. data/lib/alchemy/errors.rb +0 -11
  97. data/lib/alchemy/hints.rb +10 -10
  98. data/lib/alchemy/permissions.rb +4 -17
  99. data/lib/alchemy/routing_constraints.rb +3 -3
  100. data/lib/alchemy/searchable_resource.rb +38 -0
  101. data/lib/alchemy/seeder.rb +2 -8
  102. data/lib/alchemy/tasks/tidy.rb +0 -38
  103. data/lib/alchemy/test_support/capybara_helpers.rb +69 -0
  104. data/lib/alchemy/test_support/factories/element_factory.rb +0 -6
  105. data/lib/alchemy/test_support/factories/ingredient_factory.rb +1 -1
  106. data/lib/alchemy/test_support/factories/page_factory.rb +4 -2
  107. data/lib/alchemy/test_support/having_picture_thumbnails_examples.rb +0 -20
  108. data/lib/alchemy/test_support/shared_dom_ids_examples.rb +1 -1
  109. data/lib/alchemy/test_support/shared_ingredient_examples.rb +1 -1
  110. data/lib/alchemy/tinymce.rb +1 -18
  111. data/lib/alchemy/upgrader/seven_point_zero.rb +45 -0
  112. data/lib/alchemy/upgrader/tasks/.keep +0 -0
  113. data/lib/alchemy/upgrader.rb +8 -3
  114. data/lib/alchemy/version.rb +1 -1
  115. data/lib/alchemy.rb +0 -19
  116. data/lib/alchemy_cms.rb +1 -2
  117. data/lib/generators/alchemy/elements/elements_generator.rb +0 -1
  118. data/lib/generators/alchemy/elements/templates/view.html.erb +1 -10
  119. data/lib/generators/alchemy/elements/templates/view.html.haml +1 -9
  120. data/lib/generators/alchemy/elements/templates/view.html.slim +1 -9
  121. data/lib/generators/alchemy/install/files/alchemy.en.yml +7 -8
  122. data/lib/generators/alchemy/install/files/application.html.erb +1 -1
  123. data/lib/generators/alchemy/install/install_generator.rb +18 -34
  124. data/lib/generators/alchemy/install/templates/elements.yml.tt +12 -12
  125. data/lib/non_stupid_digest_assets.rb +1 -1
  126. data/lib/tasks/alchemy/thumbnails.rake +2 -21
  127. data/lib/tasks/alchemy/tidy.rake +1 -12
  128. data/lib/tasks/alchemy/upgrade.rake +10 -47
  129. data/package/dist/admin.js +16 -0
  130. data/package/dist/admin.js.map +7 -0
  131. data/package.json +5 -3
  132. metadata +18 -147
  133. data/app/controllers/alchemy/admin/contents_controller.rb +0 -21
  134. data/app/controllers/alchemy/admin/essence_audios_controller.rb +0 -30
  135. data/app/controllers/alchemy/admin/essence_files_controller.rb +0 -31
  136. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +0 -43
  137. data/app/controllers/alchemy/admin/essence_videos_controller.rb +0 -34
  138. data/app/controllers/alchemy/api/contents_controller.rb +0 -52
  139. data/app/decorators/alchemy/content_editor.rb +0 -119
  140. data/app/helpers/alchemy/admin/contents_helper.rb +0 -42
  141. data/app/helpers/alchemy/admin/essences_helper.rb +0 -31
  142. data/app/models/alchemy/content/factory.rb +0 -143
  143. data/app/models/alchemy/content.rb +0 -247
  144. data/app/models/alchemy/element/element_contents.rb +0 -200
  145. data/app/models/alchemy/element/element_essences.rb +0 -133
  146. data/app/models/alchemy/essence_audio.rb +0 -13
  147. data/app/models/alchemy/essence_boolean.rb +0 -20
  148. data/app/models/alchemy/essence_date.rb +0 -25
  149. data/app/models/alchemy/essence_file.rb +0 -49
  150. data/app/models/alchemy/essence_headline.rb +0 -41
  151. data/app/models/alchemy/essence_html.rb +0 -23
  152. data/app/models/alchemy/essence_link.rb +0 -21
  153. data/app/models/alchemy/essence_node.rb +0 -19
  154. data/app/models/alchemy/essence_page.rb +0 -17
  155. data/app/models/alchemy/essence_picture.rb +0 -67
  156. data/app/models/alchemy/essence_picture_view.rb +0 -90
  157. data/app/models/alchemy/essence_richtext.rb +0 -44
  158. data/app/models/alchemy/essence_select.rb +0 -19
  159. data/app/models/alchemy/essence_text.rb +0 -23
  160. data/app/models/alchemy/essence_video.rb +0 -13
  161. data/app/serializers/alchemy/content_serializer.rb +0 -17
  162. data/app/serializers/alchemy/essence_boolean_serializer.rb +0 -10
  163. data/app/serializers/alchemy/essence_date_serializer.rb +0 -10
  164. data/app/serializers/alchemy/essence_file_serializer.rb +0 -13
  165. data/app/serializers/alchemy/essence_html_serializer.rb +0 -10
  166. data/app/serializers/alchemy/essence_link_serializer.rb +0 -13
  167. data/app/serializers/alchemy/essence_picture_serializer.rb +0 -28
  168. data/app/serializers/alchemy/essence_richtext_serializer.rb +0 -11
  169. data/app/serializers/alchemy/essence_select_serializer.rb +0 -10
  170. data/app/serializers/alchemy/essence_text_serializer.rb +0 -22
  171. data/app/views/alchemy/admin/contents/create.js.erb +0 -21
  172. data/app/views/alchemy/admin/essence_audios/edit.html.erb +0 -7
  173. data/app/views/alchemy/admin/essence_files/edit.html.erb +0 -21
  174. data/app/views/alchemy/admin/essence_pictures/destroy.js.erb +0 -5
  175. data/app/views/alchemy/admin/essence_pictures/edit.html.erb +0 -30
  176. data/app/views/alchemy/admin/essence_pictures/save_link.js.erb +0 -3
  177. data/app/views/alchemy/admin/essence_pictures/update.js.erb +0 -8
  178. data/app/views/alchemy/admin/essence_videos/edit.html.erb +0 -12
  179. data/app/views/alchemy/essences/_essence_audio_editor.html.erb +0 -4
  180. data/app/views/alchemy/essences/_essence_audio_view.html.erb +0 -15
  181. data/app/views/alchemy/essences/_essence_boolean_editor.html.erb +0 -11
  182. data/app/views/alchemy/essences/_essence_boolean_view.html.erb +0 -2
  183. data/app/views/alchemy/essences/_essence_date_editor.html.erb +0 -16
  184. data/app/views/alchemy/essences/_essence_date_view.html.erb +0 -10
  185. data/app/views/alchemy/essences/_essence_file_editor.html.erb +0 -54
  186. data/app/views/alchemy/essences/_essence_file_view.html.erb +0 -18
  187. data/app/views/alchemy/essences/_essence_headline_editor.html.erb +0 -36
  188. data/app/views/alchemy/essences/_essence_headline_view.html.erb +0 -10
  189. data/app/views/alchemy/essences/_essence_html_editor.html.erb +0 -10
  190. data/app/views/alchemy/essences/_essence_html_view.html.erb +0 -2
  191. data/app/views/alchemy/essences/_essence_link_editor.html.erb +0 -30
  192. data/app/views/alchemy/essences/_essence_link_view.html.erb +0 -10
  193. data/app/views/alchemy/essences/_essence_node_editor.html.erb +0 -27
  194. data/app/views/alchemy/essences/_essence_node_view.html.erb +0 -1
  195. data/app/views/alchemy/essences/_essence_page_editor.html.erb +0 -26
  196. data/app/views/alchemy/essences/_essence_page_view.html.erb +0 -5
  197. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +0 -59
  198. data/app/views/alchemy/essences/_essence_picture_view.html.erb +0 -6
  199. data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +0 -14
  200. data/app/views/alchemy/essences/_essence_richtext_view.html.erb +0 -4
  201. data/app/views/alchemy/essences/_essence_select_editor.html.erb +0 -28
  202. data/app/views/alchemy/essences/_essence_select_view.html.erb +0 -2
  203. data/app/views/alchemy/essences/_essence_text_editor.html.erb +0 -29
  204. data/app/views/alchemy/essences/_essence_text_view.html.erb +0 -17
  205. data/app/views/alchemy/essences/_essence_video_editor.html.erb +0 -4
  206. data/app/views/alchemy/essences/_essence_video_view.html.erb +0 -19
  207. data/app/views/alchemy/essences/shared/_essence_picture_tools.html.erb +0 -59
  208. data/app/views/alchemy/essences/shared/_linkable_essence_tools.html.erb +0 -20
  209. data/app/views/alchemy/pages/show.rss.builder +0 -21
  210. data/db/migrate/20200226213334_alchemy_four_point_four.rb +0 -313
  211. data/db/migrate/20200423073425_create_alchemy_essence_nodes.rb +0 -11
  212. data/db/migrate/20200504210159_remove_site_id_from_nodes.rb +0 -28
  213. data/db/migrate/20200505215518_add_language_id_foreign_key_to_alchemy_pages.rb +0 -8
  214. data/db/migrate/20200511113603_add_menu_type_to_alchemy_nodes.rb +0 -27
  215. data/db/migrate/20200514091507_make_page_layoutpage_null_false.rb +0 -6
  216. data/db/migrate/20200519073500_remove_visible_from_alchemy_pages.rb +0 -24
  217. data/db/migrate/20200617110713_create_alchemy_picture_thumbs.rb +0 -22
  218. data/db/migrate/20200907111332_remove_tri_state_booleans.rb +0 -33
  219. data/db/migrate/20201207131309_create_page_versions.rb +0 -19
  220. data/db/migrate/20201207135820_add_page_version_id_to_alchemy_elements.rb +0 -76
  221. data/db/migrate/20210205143548_rename_public_on_and_public_until_on_alchemy_pages.rb +0 -10
  222. data/db/migrate/20210326105046_add_sanitized_body_to_alchemy_essence_richtexts.rb +0 -7
  223. data/db/migrate/20210406093436_add_alchemy_essence_headlines.rb +0 -12
  224. data/db/migrate/20210506135919_create_essence_audios.rb +0 -19
  225. data/db/migrate/20210506140258_create_essence_videos.rb +0 -23
  226. data/db/migrate/20210508091432_create_alchemy_ingredients.rb +0 -22
  227. data/db/migrate/20220514072456_restrict_on_delete_page_id_foreign_key_from_alchemy_nodes.rb +0 -13
  228. data/db/migrate/20220622130905_add_playsinline_to_alchemy_essence_videos.rb +0 -9
  229. data/lib/alchemy/essence.rb +0 -250
  230. data/lib/alchemy/tasks/usage.rb +0 -34
  231. data/lib/alchemy/test_support/essence_shared_examples.rb +0 -271
  232. data/lib/alchemy/test_support/factories/content_factory.rb +0 -20
  233. data/lib/alchemy/test_support/factories/essence_audio_factory.rb +0 -7
  234. data/lib/alchemy/test_support/factories/essence_file_factory.rb +0 -7
  235. data/lib/alchemy/test_support/factories/essence_page_factory.rb +0 -7
  236. data/lib/alchemy/test_support/factories/essence_picture_factory.rb +0 -11
  237. data/lib/alchemy/test_support/factories/essence_text_factory.rb +0 -7
  238. data/lib/alchemy/test_support/factories/essence_video_factory.rb +0 -7
  239. data/lib/alchemy/upgrader/five_point_zero.rb +0 -41
  240. data/lib/alchemy/upgrader/six_point_zero.rb +0 -21
  241. data/lib/alchemy/upgrader/tasks/add_page_versions.rb +0 -33
  242. data/lib/alchemy/upgrader/tasks/element_views_updater.rb +0 -34
  243. data/lib/alchemy/upgrader/tasks/harden_gutentag_migrations.rb +0 -29
  244. data/lib/alchemy/upgrader/tasks/ingredients_migrator.rb +0 -73
  245. data/lib/generators/alchemy/essence/essence_generator.rb +0 -49
  246. data/lib/generators/alchemy/essence/templates/editor.html.erb +0 -17
  247. data/lib/generators/alchemy/essence/templates/view.html.erb +0 -2
  248. data/lib/generators/alchemy/install/files/babel.config.js +0 -64
  249. data/lib/tasks/alchemy/usage.rake +0 -44
@@ -1,119 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Alchemy
4
- class ContentEditor < SimpleDelegator
5
- alias_method :content, :__getobj__
6
-
7
- def to_partial_path
8
- "alchemy/essences/#{essence_partial_name}_editor"
9
- end
10
-
11
- def css_classes
12
- [
13
- "content_editor",
14
- essence_partial_name,
15
- deprecated? ? "deprecated" : nil,
16
- ].compact
17
- end
18
-
19
- def data_attributes
20
- {
21
- content_id: id,
22
- content_name: name,
23
- }
24
- end
25
-
26
- # Returns a string to be passed to Rails form field tags to ensure we have same params layout everywhere.
27
- #
28
- # === Example:
29
- #
30
- # <%= text_field_tag content_editor.form_field_name, content_editor.ingredient %>
31
- #
32
- # === Options:
33
- #
34
- # You can pass an Essence column_name. Default is 'ingredient'
35
- #
36
- # ==== Example:
37
- #
38
- # <%= text_field_tag content_editor.form_field_name(:link), content_editor.ingredient %>
39
- #
40
- def form_field_name(essence_column = "ingredient")
41
- "contents[#{id}][#{essence_column}]"
42
- end
43
-
44
- def form_field_id(essence_column = "ingredient")
45
- "contents_#{id}_#{essence_column}"
46
- end
47
-
48
- # Fixes Rails partial renderer calling to_model on the object
49
- # which reveals the delegated content instead of this decorator.
50
- def respond_to?(method_name)
51
- return false if method_name == :to_model
52
-
53
- super
54
- end
55
-
56
- def has_warnings?
57
- definition.blank? || deprecated?
58
- end
59
-
60
- def warnings
61
- return unless has_warnings?
62
-
63
- if definition.blank?
64
- Logger.warn("Content #{name} is missing its definition", caller(1..1))
65
- Alchemy.t(:content_definition_missing)
66
- else
67
- deprecation_notice
68
- end
69
- end
70
-
71
- # Returns a deprecation notice for contents marked deprecated
72
- #
73
- # You can either use localizations or pass a String as notice
74
- # in the content definition.
75
- #
76
- # == Custom deprecation notices
77
- #
78
- # Use general content deprecation notice
79
- #
80
- # - name: element_name
81
- # contents:
82
- # - name: old_content
83
- # type: EssenceText
84
- # deprecated: true
85
- #
86
- # Add a translation to your locale file for a per content notice.
87
- #
88
- # en:
89
- # alchemy:
90
- # content_deprecation_notices:
91
- # element_name:
92
- # old_content: Foo baz widget is deprecated
93
- #
94
- # or use the global translation that apply to all deprecated contents.
95
- #
96
- # en:
97
- # alchemy:
98
- # content_deprecation_notice: Foo baz widget is deprecated
99
- #
100
- # or pass string as deprecation notice.
101
- #
102
- # - name: element_name
103
- # contents:
104
- # - name: old_content
105
- # type: EssenceText
106
- # deprecated: This content will be removed soon.
107
- #
108
- def deprecation_notice
109
- case definition["deprecated"]
110
- when String
111
- definition["deprecated"]
112
- when TrueClass
113
- Alchemy.t(name,
114
- scope: [:content_deprecation_notices, element.name],
115
- default: Alchemy.t(:content_deprecated))
116
- end
117
- end
118
- end
119
- end
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Alchemy
4
- module Admin
5
- module ContentsHelper
6
- include Alchemy::Admin::BaseHelper
7
-
8
- # Renders the name of elements content.
9
- #
10
- # Displays a warning icon if content is missing its definition.
11
- #
12
- # Displays a mandatory field indicator, if the content has validations.
13
- #
14
- def render_content_name(content)
15
- if content.blank?
16
- warning("Content is nil")
17
- return
18
- end
19
-
20
- content_name = content.name_for_label
21
-
22
- if content.has_warnings?
23
- icon = hint_with_tooltip(content.warnings)
24
- content_name = "#{icon} #{content_name}".html_safe
25
- end
26
-
27
- if content.has_validations?
28
- "#{content_name}<span class='validation_indicator'>*</span>".html_safe
29
- else
30
- content_name
31
- end
32
- end
33
-
34
- # Renders the label and a remove link for a content.
35
- def content_label(content)
36
- content_tag :label, for: content.form_field_id do
37
- [render_content_name(content), render_hint_for(content)].compact.join("&nbsp;").html_safe
38
- end
39
- end
40
- end
41
- end
42
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Alchemy
4
- module Admin
5
- module EssencesHelper
6
- # Renders a thumbnail for given EssencePicture content with correct cropping and size
7
- def essence_picture_thumbnail(content)
8
- picture = content.ingredient
9
- essence = content.essence
10
-
11
- return if picture.nil?
12
-
13
- image_tag(
14
- essence.thumbnail_url,
15
- alt: picture.name,
16
- class: "img_paddingtop",
17
- title: Alchemy.t(:image_name, name: picture.name),
18
- )
19
- end
20
-
21
- # Size value for edit picture dialog
22
- def edit_picture_dialog_size(content)
23
- if content.settings[:caption_as_textarea]
24
- content.settings[:sizes] ? "380x320" : "380x300"
25
- else
26
- content.settings[:sizes] ? "380x290" : "380x255"
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,143 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Alchemy
4
- # Holds everything concerning the building and creating of contents and the related essence object.
5
- #
6
- class Content < BaseRecord
7
- module Factory
8
- extend ActiveSupport::Concern
9
-
10
- module ClassMethods
11
- SKIPPED_ATTRIBUTES_ON_COPY = %w(position created_at updated_at creator_id updater_id element_id id)
12
-
13
- # Builds a new content as descriped in the elements.yml file.
14
- #
15
- # @param [Hash]
16
- # The content definition used for finding the content in +elements.yml+ file
17
- #
18
- def new(attributes = {})
19
- element = attributes[:element] || Element.find_by(id: attributes[:element_id])
20
- return super if attributes.empty? || element.nil?
21
-
22
- definition = element.content_definition_for(attributes[:name])
23
- if definition.blank? && attributes[:essence_type].nil?
24
- raise ContentDefinitionError, "No definition found in elements.yml for #{attributes.inspect} and #{element.inspect}"
25
- end
26
-
27
- super(
28
- name: attributes[:name],
29
- essence_type: attributes[:essence_type] || normalize_essence_type(definition[:type]),
30
- element: element,
31
- ).tap(&:build_essence)
32
- end
33
-
34
- # Creates a new content from elements definition in the +elements.yml+ file.
35
- #
36
- # 1. It builds the content
37
- # 2. It creates the essence record (content object gets saved)
38
- #
39
- # @return [Alchemy::Content]
40
- #
41
- def create(attributes = {})
42
- new(attributes).tap do |content|
43
- content.essence.save && content.save
44
- end
45
- end
46
-
47
- # Creates a copy of source and also copies the associated essence.
48
- #
49
- # You can pass a differences hash to update the attributes of the copy.
50
- #
51
- # === Example
52
- #
53
- # @copy = Alchemy::Content.copy(@content, {element_id: 3})
54
- # @copy.element_id # => 3
55
- #
56
- def copy(source, differences = {})
57
- Content.new(
58
- source.attributes.with_indifferent_access.
59
- except(*SKIPPED_ATTRIBUTES_ON_COPY).
60
- merge(differences.with_indifferent_access)
61
- ).tap do |new_content|
62
- new_content.build_essence(
63
- source.essence.attributes.
64
- except(*SKIPPED_ATTRIBUTES_ON_COPY)
65
- )
66
- new_content.save
67
- end
68
- end
69
-
70
- # Returns all content definitions from elements.yml
71
- #
72
- def definitions
73
- definitions = Element.definitions.flat_map { |e| e["contents"] }
74
- definitions.compact!
75
- definitions
76
- end
77
-
78
- # Returns a normalized Essence type
79
- #
80
- # Adds Alchemy module name in front of given essence type
81
- # unless there is a Class with the specified name that is an essence.
82
- #
83
- # @param [String]
84
- # the essence type to normalize
85
- #
86
- def normalize_essence_type(essence_type)
87
- essence_type = essence_type.classify
88
- return essence_type if is_an_essence?(essence_type)
89
-
90
- "Alchemy::#{essence_type}"
91
- end
92
-
93
- private
94
-
95
- def is_an_essence?(essence_type)
96
- klass = Module.const_get(essence_type)
97
- klass.is_a?(Class) && klass.new.acts_as_essence?
98
- rescue NameError
99
- false
100
- end
101
- end
102
-
103
- # Instance Methods
104
-
105
- # Returns the definition hash from +elements.yml+ file.
106
- #
107
- def definition
108
- if element.blank?
109
- log_warning "Content with id #{id} is missing its Element."
110
- return {}
111
- end
112
- element.content_definition_for(name) || {}
113
- end
114
-
115
- # Build essence from definition.
116
- #
117
- # If an optional type is passed, this type of essence gets created.
118
- #
119
- def build_essence(attributes = {})
120
- self.essence = essence_class.new(
121
- { content: self, ingredient: default_value }.merge(attributes)
122
- )
123
- end
124
-
125
- # Creates essence from definition.
126
- #
127
- # If an optional type is passed, this type of essence gets created.
128
- #
129
- def create_essence!(attrs = {})
130
- build_essence(attrs).save!
131
- save!
132
- end
133
-
134
- private
135
-
136
- # Returns a class constant from definition's type field or the essence_type column
137
- #
138
- def essence_class
139
- (essence_type || Content.normalize_essence_type(definition["type"])).constantize
140
- end
141
- end
142
- end
143
- end
@@ -1,247 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # == Schema Information
4
- #
5
- # Table name: alchemy_contents
6
- #
7
- # id :integer not null, primary key
8
- # name :string
9
- # essence_type :string not null
10
- # essence_id :integer not null
11
- # element_id :integer not null
12
- # position :integer
13
- # created_at :datetime not null
14
- # updated_at :datetime not null
15
- # creator_id :integer
16
- # updater_id :integer
17
- #
18
-
19
- require_dependency "alchemy/content/factory"
20
-
21
- module Alchemy
22
- # @deprecated
23
- class Content < BaseRecord
24
- include Alchemy::Logger
25
- include Alchemy::Hints
26
-
27
- # Concerns
28
- include Factory
29
-
30
- belongs_to :essence, polymorphic: true, dependent: :destroy, inverse_of: :content
31
- belongs_to :element, touch: true, inverse_of: :contents
32
- has_one :page, through: :element
33
-
34
- # Essence scopes
35
- scope :essence_booleans, -> { where(essence_type: "Alchemy::EssenceBoolean") }
36
- scope :essence_dates, -> { where(essence_type: "Alchemy::EssenceDate") }
37
- scope :essence_files, -> { where(essence_type: "Alchemy::EssenceFile") }
38
- scope :essence_htmls, -> { where(essence_type: "Alchemy::EssenceHtml") }
39
- scope :essence_links, -> { where(essence_type: "Alchemy::EssenceLink") }
40
- scope :essence_pictures, -> { where(essence_type: "Alchemy::EssencePicture") }
41
- scope :essence_richtexts, -> { where(essence_type: "Alchemy::EssenceRichtext") }
42
- scope :essence_selects, -> { where(essence_type: "Alchemy::EssenceSelect") }
43
- scope :essence_texts, -> { where(essence_type: "Alchemy::EssenceText") }
44
- scope :named, ->(name) { where(name: name) }
45
- scope :available, -> { published }
46
- scope :published, -> { joins(:element).merge(Element.published) }
47
- scope :not_restricted, -> { joins(:element).merge(Element.not_restricted) }
48
-
49
- delegate :restricted?, to: :page, allow_nil: true
50
- delegate :public?, to: :element, allow_nil: true
51
-
52
- class << self
53
- # Returns the translated label for a content name.
54
- #
55
- # Translate it in your locale yml file:
56
- #
57
- # alchemy:
58
- # content_names:
59
- # foo: Bar
60
- #
61
- # Optionally you can scope your content name to an element:
62
- #
63
- # alchemy:
64
- # content_names:
65
- # article:
66
- # foo: Baz
67
- #
68
- def translated_label_for(content_name, element_name = nil)
69
- Alchemy.t(
70
- content_name,
71
- scope: "content_names.#{element_name}",
72
- default: Alchemy.t("content_names.#{content_name}", default: content_name.humanize),
73
- )
74
- end
75
- end
76
-
77
- # The content's view partial is dependent from its name
78
- #
79
- # == Define contents
80
- #
81
- # Contents are defined in the +config/alchemy/elements.yml+ file
82
- #
83
- # - name: article
84
- # contents:
85
- # - name: headline
86
- # type: EssenceText
87
- #
88
- # == Override the view
89
- #
90
- # Content partials live in +app/views/alchemy/essences+
91
- #
92
- def to_partial_path
93
- "alchemy/essences/#{essence_partial_name}_view"
94
- end
95
-
96
- # Settings from the elements.yml definition
97
- def settings
98
- return {} if definition.blank?
99
-
100
- @settings ||= definition.fetch(:settings, {})
101
- end
102
-
103
- # Fetches value from settings
104
- #
105
- # @param key [Symbol] - The hash key you want to fetch the value from
106
- # @param options [Hash] - An optional Hash that can override the settings.
107
- # Normally passed as options hash into the content
108
- # editor view.
109
- def settings_value(key, options = {})
110
- settings.update(options || {}).symbolize_keys[key.to_sym]
111
- end
112
-
113
- def siblings
114
- return [] if !element
115
-
116
- element.contents
117
- end
118
-
119
- # Gets the ingredient from essence
120
- def ingredient
121
- return nil if essence.nil?
122
-
123
- essence.ingredient
124
- end
125
-
126
- # Serialized object representation for json api
127
- #
128
- def serialize
129
- {
130
- name: name,
131
- value: serialized_ingredient,
132
- link: essence.try(:link),
133
- }.delete_if { |_k, v| v.blank? }
134
- end
135
-
136
- # Ingredient value from essence for json api
137
- #
138
- # If the essence responds to +serialized_ingredient+ method it takes this
139
- # otherwise it uses the ingredient column.
140
- #
141
- def serialized_ingredient
142
- essence.try(:serialized_ingredient) || ingredient
143
- end
144
-
145
- # Sets the ingredient from essence
146
- def ingredient=(value)
147
- raise EssenceMissingError if essence.nil?
148
-
149
- essence.ingredient = value
150
- end
151
-
152
- # Updates the essence.
153
- #
154
- # Called from +Alchemy::Element#update_contents+
155
- #
156
- # Adds errors to self.base if essence validation fails.
157
- #
158
- def update_essence(params = {})
159
- raise EssenceMissingError if essence.nil?
160
-
161
- if essence.update(params)
162
- true
163
- else
164
- errors.add(:essence, :validation_failed)
165
- false
166
- end
167
- end
168
-
169
- def essence_validation_failed?
170
- essence.errors.any?
171
- end
172
-
173
- def has_validations?
174
- definition["validate"].present?
175
- end
176
-
177
- # Returns a string used as dom id on html elements.
178
- def dom_id
179
- return "" if essence.nil?
180
-
181
- "#{essence_partial_name}_#{id}"
182
- end
183
-
184
- # Returns the translated name for displaying in labels, etc.
185
- def name_for_label
186
- self.class.translated_label_for(name, element.name)
187
- end
188
-
189
- def linked?
190
- essence && !essence.link.blank?
191
- end
192
-
193
- def deprecated?
194
- !!definition["deprecated"]
195
- end
196
-
197
- # Returns true if this content should be taken for element preview.
198
- def preview_content?
199
- !!definition["as_element_title"]
200
- end
201
-
202
- # Proxy method that returns the preview text from essence.
203
- #
204
- def preview_text(maxlength = 30)
205
- essence.preview_text(maxlength)
206
- end
207
-
208
- def essence_partial_name
209
- return "" if essence.nil?
210
-
211
- essence.partial_name
212
- end
213
-
214
- def normalized_essence_type
215
- self.class.normalize_essence_type(essence_type)
216
- end
217
-
218
- # Returns true if there is a tinymce setting defined on the content definiton
219
- # or if the +essence.has_tinymce?+ returns true.
220
- def has_tinymce?
221
- settings[:tinymce].present? || (essence.present? && essence.has_tinymce?)
222
- end
223
-
224
- # Returns true if there is a tinymce setting defined that contains settings.
225
- def has_custom_tinymce_config?
226
- settings[:tinymce].is_a?(Hash)
227
- end
228
-
229
- # Returns css class names for the content textarea.
230
- def tinymce_class_name
231
- "has_tinymce" + (has_custom_tinymce_config? ? " #{element.name}_#{name}" : "")
232
- end
233
-
234
- # Returns the default value from content definition
235
- #
236
- # If the value is a symbol it gets passed through i18n
237
- # inside the +alchemy.default_content_texts+ scope
238
- def default_value(default = definition[:default])
239
- case default
240
- when Symbol
241
- Alchemy.t(default, scope: :default_content_texts)
242
- else
243
- default
244
- end
245
- end
246
- end
247
- end