alchemy_cms 6.1.6 → 7.0.0.pre.a

Sign up to get free protection for your applications and to get access to all the features.
Files changed (243) 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 -25
  5. data/Gemfile +1 -1
  6. data/Rakefile +14 -9
  7. data/alchemy_cms.gemspec +1 -2
  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 -8
  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 -2
  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/_tinymce_custom_config.html.erb +3 -6
  73. data/app/views/alchemy/admin/pages/edit.html.erb +1 -1
  74. data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +1 -3
  75. data/app/views/alchemy/admin/pictures/_infos.html.erb +4 -6
  76. data/app/views/alchemy/ingredients/_boolean_editor.html.erb +1 -1
  77. data/app/views/alchemy/ingredients/_headline_editor.html.erb +1 -1
  78. data/app/views/alchemy/ingredients/_html_editor.html.erb +1 -1
  79. data/app/views/alchemy/ingredients/_node_editor.html.erb +1 -1
  80. data/app/views/alchemy/ingredients/_picture_editor.html.erb +4 -4
  81. data/app/views/alchemy/ingredients/_select_editor.html.erb +2 -2
  82. data/app/views/alchemy/ingredients/_text_editor.html.erb +1 -1
  83. data/app/views/alchemy/ingredients/shared/_link_tools.html.erb +3 -3
  84. data/app/views/alchemy/pages/_meta_data.html.erb +0 -1
  85. data/app/views/layouts/alchemy/admin.html.erb +5 -1
  86. data/config/alchemy/config.yml +6 -6
  87. data/config/brakeman.ignore +56 -57
  88. data/config/locales/alchemy.en.yml +99 -113
  89. data/config/routes.rb +1 -16
  90. data/db/migrate/20230121212637_alchemy_six_point_one.rb +248 -0
  91. data/lib/alchemy/cache_digests/template_tracker.rb +6 -7
  92. data/lib/alchemy/config.rb +2 -2
  93. data/lib/alchemy/deprecation.rb +1 -1
  94. data/lib/alchemy/errors.rb +0 -11
  95. data/lib/alchemy/hints.rb +10 -10
  96. data/lib/alchemy/permissions.rb +4 -17
  97. data/lib/alchemy/routing_constraints.rb +3 -3
  98. data/lib/alchemy/searchable_resource.rb +38 -0
  99. data/lib/alchemy/seeder.rb +2 -8
  100. data/lib/alchemy/tasks/tidy.rb +0 -38
  101. data/lib/alchemy/test_support/capybara_helpers.rb +69 -0
  102. data/lib/alchemy/test_support/factories/element_factory.rb +0 -6
  103. data/lib/alchemy/test_support/factories/ingredient_factory.rb +1 -1
  104. data/lib/alchemy/test_support/factories/page_factory.rb +4 -2
  105. data/lib/alchemy/test_support/shared_dom_ids_examples.rb +1 -1
  106. data/lib/alchemy/test_support/shared_ingredient_examples.rb +1 -1
  107. data/lib/alchemy/tinymce.rb +1 -18
  108. data/lib/alchemy/upgrader/seven_point_zero.rb +45 -0
  109. data/lib/alchemy/upgrader/tasks/.keep +0 -0
  110. data/lib/alchemy/upgrader.rb +8 -3
  111. data/lib/alchemy/version.rb +1 -1
  112. data/lib/alchemy.rb +0 -19
  113. data/lib/alchemy_cms.rb +1 -2
  114. data/lib/generators/alchemy/elements/elements_generator.rb +0 -1
  115. data/lib/generators/alchemy/elements/templates/view.html.erb +1 -10
  116. data/lib/generators/alchemy/elements/templates/view.html.haml +1 -9
  117. data/lib/generators/alchemy/elements/templates/view.html.slim +1 -9
  118. data/lib/generators/alchemy/install/files/alchemy.en.yml +7 -8
  119. data/lib/generators/alchemy/install/files/application.html.erb +1 -1
  120. data/lib/generators/alchemy/install/install_generator.rb +18 -34
  121. data/lib/generators/alchemy/install/templates/elements.yml.tt +12 -12
  122. data/lib/tasks/alchemy/thumbnails.rake +2 -21
  123. data/lib/tasks/alchemy/tidy.rake +1 -12
  124. data/lib/tasks/alchemy/upgrade.rake +10 -47
  125. data/package/dist/admin.js +16 -0
  126. data/package/dist/admin.js.map +7 -0
  127. data/package.json +5 -3
  128. metadata +15 -142
  129. data/app/controllers/alchemy/admin/contents_controller.rb +0 -21
  130. data/app/controllers/alchemy/admin/essence_audios_controller.rb +0 -30
  131. data/app/controllers/alchemy/admin/essence_files_controller.rb +0 -31
  132. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +0 -43
  133. data/app/controllers/alchemy/admin/essence_videos_controller.rb +0 -34
  134. data/app/controllers/alchemy/api/contents_controller.rb +0 -52
  135. data/app/decorators/alchemy/content_editor.rb +0 -119
  136. data/app/helpers/alchemy/admin/contents_helper.rb +0 -42
  137. data/app/helpers/alchemy/admin/essences_helper.rb +0 -31
  138. data/app/models/alchemy/content/factory.rb +0 -143
  139. data/app/models/alchemy/content.rb +0 -247
  140. data/app/models/alchemy/element/element_contents.rb +0 -200
  141. data/app/models/alchemy/element/element_essences.rb +0 -133
  142. data/app/models/alchemy/essence_audio.rb +0 -13
  143. data/app/models/alchemy/essence_boolean.rb +0 -20
  144. data/app/models/alchemy/essence_date.rb +0 -25
  145. data/app/models/alchemy/essence_file.rb +0 -49
  146. data/app/models/alchemy/essence_headline.rb +0 -41
  147. data/app/models/alchemy/essence_html.rb +0 -23
  148. data/app/models/alchemy/essence_link.rb +0 -21
  149. data/app/models/alchemy/essence_node.rb +0 -19
  150. data/app/models/alchemy/essence_page.rb +0 -17
  151. data/app/models/alchemy/essence_picture.rb +0 -67
  152. data/app/models/alchemy/essence_picture_view.rb +0 -90
  153. data/app/models/alchemy/essence_richtext.rb +0 -44
  154. data/app/models/alchemy/essence_select.rb +0 -19
  155. data/app/models/alchemy/essence_text.rb +0 -23
  156. data/app/models/alchemy/essence_video.rb +0 -13
  157. data/app/serializers/alchemy/content_serializer.rb +0 -17
  158. data/app/serializers/alchemy/essence_boolean_serializer.rb +0 -10
  159. data/app/serializers/alchemy/essence_date_serializer.rb +0 -10
  160. data/app/serializers/alchemy/essence_file_serializer.rb +0 -13
  161. data/app/serializers/alchemy/essence_html_serializer.rb +0 -10
  162. data/app/serializers/alchemy/essence_link_serializer.rb +0 -13
  163. data/app/serializers/alchemy/essence_picture_serializer.rb +0 -28
  164. data/app/serializers/alchemy/essence_richtext_serializer.rb +0 -11
  165. data/app/serializers/alchemy/essence_select_serializer.rb +0 -10
  166. data/app/serializers/alchemy/essence_text_serializer.rb +0 -22
  167. data/app/views/alchemy/admin/contents/create.js.erb +0 -21
  168. data/app/views/alchemy/admin/essence_audios/edit.html.erb +0 -7
  169. data/app/views/alchemy/admin/essence_files/edit.html.erb +0 -21
  170. data/app/views/alchemy/admin/essence_pictures/destroy.js.erb +0 -5
  171. data/app/views/alchemy/admin/essence_pictures/edit.html.erb +0 -30
  172. data/app/views/alchemy/admin/essence_pictures/save_link.js.erb +0 -3
  173. data/app/views/alchemy/admin/essence_pictures/update.js.erb +0 -8
  174. data/app/views/alchemy/admin/essence_videos/edit.html.erb +0 -12
  175. data/app/views/alchemy/essences/_essence_audio_editor.html.erb +0 -4
  176. data/app/views/alchemy/essences/_essence_audio_view.html.erb +0 -15
  177. data/app/views/alchemy/essences/_essence_boolean_editor.html.erb +0 -11
  178. data/app/views/alchemy/essences/_essence_boolean_view.html.erb +0 -2
  179. data/app/views/alchemy/essences/_essence_date_editor.html.erb +0 -16
  180. data/app/views/alchemy/essences/_essence_date_view.html.erb +0 -10
  181. data/app/views/alchemy/essences/_essence_file_editor.html.erb +0 -54
  182. data/app/views/alchemy/essences/_essence_file_view.html.erb +0 -18
  183. data/app/views/alchemy/essences/_essence_headline_editor.html.erb +0 -36
  184. data/app/views/alchemy/essences/_essence_headline_view.html.erb +0 -10
  185. data/app/views/alchemy/essences/_essence_html_editor.html.erb +0 -10
  186. data/app/views/alchemy/essences/_essence_html_view.html.erb +0 -2
  187. data/app/views/alchemy/essences/_essence_link_editor.html.erb +0 -30
  188. data/app/views/alchemy/essences/_essence_link_view.html.erb +0 -10
  189. data/app/views/alchemy/essences/_essence_node_editor.html.erb +0 -27
  190. data/app/views/alchemy/essences/_essence_node_view.html.erb +0 -1
  191. data/app/views/alchemy/essences/_essence_page_editor.html.erb +0 -26
  192. data/app/views/alchemy/essences/_essence_page_view.html.erb +0 -5
  193. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +0 -59
  194. data/app/views/alchemy/essences/_essence_picture_view.html.erb +0 -6
  195. data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +0 -14
  196. data/app/views/alchemy/essences/_essence_richtext_view.html.erb +0 -4
  197. data/app/views/alchemy/essences/_essence_select_editor.html.erb +0 -28
  198. data/app/views/alchemy/essences/_essence_select_view.html.erb +0 -2
  199. data/app/views/alchemy/essences/_essence_text_editor.html.erb +0 -29
  200. data/app/views/alchemy/essences/_essence_text_view.html.erb +0 -17
  201. data/app/views/alchemy/essences/_essence_video_editor.html.erb +0 -4
  202. data/app/views/alchemy/essences/_essence_video_view.html.erb +0 -19
  203. data/app/views/alchemy/essences/shared/_essence_picture_tools.html.erb +0 -59
  204. data/app/views/alchemy/essences/shared/_linkable_essence_tools.html.erb +0 -20
  205. data/app/views/alchemy/pages/show.rss.builder +0 -21
  206. data/db/migrate/20200226213334_alchemy_four_point_four.rb +0 -313
  207. data/db/migrate/20200423073425_create_alchemy_essence_nodes.rb +0 -11
  208. data/db/migrate/20200504210159_remove_site_id_from_nodes.rb +0 -28
  209. data/db/migrate/20200505215518_add_language_id_foreign_key_to_alchemy_pages.rb +0 -8
  210. data/db/migrate/20200511113603_add_menu_type_to_alchemy_nodes.rb +0 -27
  211. data/db/migrate/20200514091507_make_page_layoutpage_null_false.rb +0 -6
  212. data/db/migrate/20200519073500_remove_visible_from_alchemy_pages.rb +0 -24
  213. data/db/migrate/20200617110713_create_alchemy_picture_thumbs.rb +0 -22
  214. data/db/migrate/20200907111332_remove_tri_state_booleans.rb +0 -33
  215. data/db/migrate/20201207131309_create_page_versions.rb +0 -19
  216. data/db/migrate/20201207135820_add_page_version_id_to_alchemy_elements.rb +0 -76
  217. data/db/migrate/20210205143548_rename_public_on_and_public_until_on_alchemy_pages.rb +0 -10
  218. data/db/migrate/20210326105046_add_sanitized_body_to_alchemy_essence_richtexts.rb +0 -7
  219. data/db/migrate/20210406093436_add_alchemy_essence_headlines.rb +0 -12
  220. data/db/migrate/20210506135919_create_essence_audios.rb +0 -19
  221. data/db/migrate/20210506140258_create_essence_videos.rb +0 -23
  222. data/db/migrate/20210508091432_create_alchemy_ingredients.rb +0 -22
  223. data/db/migrate/20220514072456_restrict_on_delete_page_id_foreign_key_from_alchemy_nodes.rb +0 -13
  224. data/db/migrate/20220622130905_add_playsinline_to_alchemy_essence_videos.rb +0 -9
  225. data/lib/alchemy/essence.rb +0 -250
  226. data/lib/alchemy/test_support/essence_shared_examples.rb +0 -271
  227. data/lib/alchemy/test_support/factories/content_factory.rb +0 -20
  228. data/lib/alchemy/test_support/factories/essence_audio_factory.rb +0 -7
  229. data/lib/alchemy/test_support/factories/essence_file_factory.rb +0 -7
  230. data/lib/alchemy/test_support/factories/essence_page_factory.rb +0 -7
  231. data/lib/alchemy/test_support/factories/essence_picture_factory.rb +0 -11
  232. data/lib/alchemy/test_support/factories/essence_text_factory.rb +0 -7
  233. data/lib/alchemy/test_support/factories/essence_video_factory.rb +0 -7
  234. data/lib/alchemy/upgrader/five_point_zero.rb +0 -41
  235. data/lib/alchemy/upgrader/six_point_zero.rb +0 -21
  236. data/lib/alchemy/upgrader/tasks/add_page_versions.rb +0 -33
  237. data/lib/alchemy/upgrader/tasks/element_views_updater.rb +0 -34
  238. data/lib/alchemy/upgrader/tasks/harden_gutentag_migrations.rb +0 -29
  239. data/lib/alchemy/upgrader/tasks/ingredients_migrator.rb +0 -73
  240. data/lib/generators/alchemy/essence/essence_generator.rb +0 -49
  241. data/lib/generators/alchemy/essence/templates/editor.html.erb +0 -17
  242. data/lib/generators/alchemy/essence/templates/view.html.erb +0 -2
  243. data/lib/generators/alchemy/install/files/babel.config.js +0 -64
@@ -35,9 +35,9 @@
35
35
  }
36
36
 
37
37
  // The container of the rendered node is slightly larger than other a line of
38
- // text, as it would be for the Alchemy::EssencePage. Reducing the padding here from 0.6em
38
+ // text, as it would be for the Alchemy::Ingredients::Page. Reducing the padding here from 0.6em
39
39
  // to 0.4em centers the content nicely.
40
- .essence_node {
40
+ .ingredient-editor.node {
41
41
  .select2-container.alchemy_selectbox .select2-choice {
42
42
  padding: 0.4em 0.75em;
43
43
  }
@@ -78,7 +78,6 @@ module Alchemy
78
78
  @_search_filter_params ||= params.except(*COMMON_SEARCH_FILTER_EXCLUDES + [:attachment]).permit(
79
79
  *common_search_filter_includes + [
80
80
  :form_field_id,
81
- :content_id,
82
81
  ]
83
82
  )
84
83
  end
@@ -49,22 +49,21 @@ module Alchemy
49
49
  end
50
50
  end
51
51
 
52
- # Updates the element.
53
- #
54
- # And update all contents in the elements by calling update_contents.
52
+ # Updates the element and all ingredients in the element.
55
53
  #
56
54
  def update
57
55
  @page = @element.page
58
56
 
59
- if element_params.key?(:ingredients_attributes)
60
- update_element_with_ingredients
57
+ if @element.update(element_params)
58
+ @element_validated = true
61
59
  else
62
- update_element_with_contents
60
+ element_update_error
61
+ @error_messages = @element.ingredient_error_messages
63
62
  end
64
63
  end
65
64
 
66
65
  def destroy
67
- @richtext_ids = @element.richtext_contents_ids + @element.richtext_ingredients_ids
66
+ @richtext_ids = @element.richtext_ingredients_ids
68
67
  @element.destroy
69
68
  @notice = Alchemy.t("Successfully deleted element") % { element: @element.display_name }
70
69
  end
@@ -103,14 +102,12 @@ module Alchemy
103
102
  def element_includes
104
103
  [
105
104
  {
106
- contents: :essence,
107
105
  ingredients: :related_object,
108
106
  },
109
107
  :tags,
110
108
  {
111
109
  all_nested_elements: [
112
110
  {
113
- contents: :essence,
114
111
  ingredients: :related_object,
115
112
  },
116
113
  :tags,
@@ -152,10 +149,6 @@ module Alchemy
152
149
  element
153
150
  end
154
151
 
155
- def contents_params
156
- params.fetch(:contents, {}).permit!
157
- end
158
-
159
152
  def element_params
160
153
  params.fetch(:element, {}).permit(:tag_list, ingredients_attributes: {})
161
154
  end
@@ -164,28 +157,10 @@ module Alchemy
164
157
  params.require(:element).permit(:name, :page_version_id, :parent_element_id)
165
158
  end
166
159
 
167
- def update_element_with_ingredients
168
- if @element.update(element_params)
169
- @element_validated = true
170
- else
171
- element_update_error
172
- @error_messages = @element.ingredient_error_messages
173
- end
174
- end
175
-
176
- def update_element_with_contents
177
- if @element.update_contents(contents_params)
178
- @element_validated = @element.update(element_params)
179
- else
180
- element_update_error
181
- @error_messages = @element.essence_error_messages
182
- end
183
- end
184
-
185
160
  def element_update_error
186
161
  @element_validated = false
187
162
  @notice = Alchemy.t("Validation failed")
188
- @error_message = "<h2>#{@notice}</h2><p>#{Alchemy.t(:content_validations_headline)}</p>".html_safe
163
+ @error_message = "<h2>#{@notice}</h2><p>#{Alchemy.t(:ingredient_validations_headline)}</p>".html_safe
189
164
  end
190
165
  end
191
166
  end
@@ -94,7 +94,7 @@ module Alchemy
94
94
  end
95
95
  end
96
96
 
97
- # Edit the content of the page and all its elements and contents.
97
+ # Edit the content of the page and all its elements and ingredients.
98
98
  #
99
99
  # Locks the page to current user to prevent other users from editing it meanwhile.
100
100
  #
@@ -32,7 +32,7 @@ module Alchemy
32
32
  @query = Picture.ransack(params[:q])
33
33
  @previous = filtered_pictures.where("name < ?", @picture.name).last
34
34
  @next = filtered_pictures.where("name > ?", @picture.name).first
35
- @assignments = @picture.essence_pictures.joins(content: { element: :page })
35
+ @assignments = @picture.picture_ingredients.joins(element: :page)
36
36
 
37
37
  render action: "show"
38
38
  end
@@ -103,7 +103,7 @@ module Alchemy
103
103
  def resource_filters
104
104
  return unless resource_has_filters
105
105
 
106
- @_resource_filters ||= deprecated_resource_filters || resource_model.alchemy_resource_filters
106
+ @_resource_filters ||= resource_model.alchemy_resource_filters
107
107
  end
108
108
 
109
109
  def resource_filters_for_select
@@ -114,23 +114,6 @@ module Alchemy
114
114
 
115
115
  protected
116
116
 
117
- def deprecated_resource_filters
118
- if resource_has_deprecated_filters
119
- Alchemy::Deprecation.warn(
120
- "#{resource_model}.alchemy_resource_filters is using a legacy data structure. " \
121
- "Please use an Array of Hashes instead. i.e. [{ name: 'foo', values: ['bar', 'baz'] }, ...] " \
122
- "where values are scopes. With Alchemy 6.1 only the new structure will be supported."
123
- )
124
-
125
- @_resource_filters ||= [
126
- {
127
- name: :misc,
128
- values: resource_model.alchemy_resource_filters,
129
- },
130
- ]
131
- end
132
- end
133
-
134
117
  def apply_filters(items)
135
118
  sanitize_filter_params!
136
119
 
@@ -47,14 +47,12 @@ module Alchemy
47
47
  {
48
48
  nested_elements: [
49
49
  {
50
- contents: :essence,
51
50
  ingredients: :related_object,
52
51
  },
53
52
  :tags,
54
53
  ],
55
54
  },
56
55
  {
57
- contents: :essence,
58
56
  ingredients: :related_object,
59
57
  },
60
58
  :tags,
@@ -8,7 +8,9 @@ module Alchemy
8
8
  # Returns all pages as json object
9
9
  #
10
10
  def index
11
+ language = Alchemy::Language.find_by(id: params[:language_id]) || Alchemy::Language.current
11
12
  @pages = Alchemy::Page.accessible_by(current_ability, :index)
13
+ @pages = @pages.where(language: language)
12
14
  @pages = @pages.includes(*page_includes)
13
15
  @pages = @pages.ransack(params[:q]).result
14
16
 
@@ -28,11 +30,13 @@ module Alchemy
28
30
  def nested
29
31
  @page = Page.find_by(id: params[:page_id]) || Language.current_root_page
30
32
 
31
- render json: PageTreeSerializer.new(@page,
33
+ render json: PageTreeSerializer.new(
34
+ @page,
32
35
  ability: current_ability,
33
36
  user: current_alchemy_user,
34
37
  elements: params[:elements],
35
- full: true)
38
+ full: true,
39
+ )
36
40
  end
37
41
 
38
42
  # Returns a json object for page
@@ -105,13 +109,13 @@ module Alchemy
105
109
  {
106
110
  nested_elements: [
107
111
  {
108
- contents: :essence,
112
+ ingredients: :related_object,
109
113
  },
110
114
  :tags,
111
115
  ],
112
116
  },
113
117
  {
114
- contents: :essence,
118
+ ingredients: :related_object,
115
119
  },
116
120
  :tags,
117
121
  ],
@@ -11,15 +11,15 @@ module Alchemy
11
11
  # Make an Element with this options inside your @elements.yml file:
12
12
  #
13
13
  # - name: contactform
14
- # contents:
15
- # - name: mail_to
16
- # type: EssenceText
17
- # - name: subject
18
- # type: EssenceText
19
- # - name: mail_from
20
- # type: EssenceText
21
- # - name: success_page
22
- # type: EssencePage
14
+ # ingredients:
15
+ # - role: mail_to
16
+ # type: Text
17
+ # - role: subject
18
+ # type: Text
19
+ # - role: mail_from
20
+ # type: Text
21
+ # - role: success_page
22
+ # type: Page
23
23
  #
24
24
  # The fields +mail_to+, +mail_from+, +subject+ and +success_page+ are recommended.
25
25
  # The +Alchemy::MessagesController+ uses them to send your mails. So your customer has full controll of these values inside his contactform element.
@@ -104,7 +104,13 @@ module Alchemy
104
104
  # If no index page and no admin users are present we show the "Welcome to Alchemy" page.
105
105
  #
106
106
  def load_index_page
107
- @page ||= Language.current_root_page
107
+ @page ||= Alchemy::Page
108
+ .contentpages
109
+ .language_roots
110
+ .where(language: Language.current)
111
+ .includes(page_includes)
112
+ .first
113
+
108
114
  render template: "alchemy/welcome", layout: false if signup_required?
109
115
  end
110
116
 
@@ -120,10 +126,11 @@ module Alchemy
120
126
  def load_page
121
127
  page_not_found! unless Language.current
122
128
 
123
- @page ||= Language.current.pages.contentpages.find_by(
124
- urlname: params[:urlname],
125
- language_code: params[:locale] || Language.current.code,
126
- )
129
+ @page ||= Alchemy::Page
130
+ .contentpages
131
+ .where(language: Language.current)
132
+ .includes(page_includes)
133
+ .find_by(urlname: params[:urlname])
127
134
  end
128
135
 
129
136
  def enforce_locale
@@ -168,7 +175,7 @@ module Alchemy
168
175
 
169
176
  # == Renders the page :show template
170
177
  #
171
- # Handles html and rss requests (for pages containing a feed)
178
+ # Handles html requests
172
179
  #
173
180
  # Omits the layout, if the request is a XHR request.
174
181
  #
@@ -177,14 +184,6 @@ module Alchemy
177
184
  format.html do
178
185
  render action: :show, layout: !request.xhr?
179
186
  end
180
-
181
- format.rss do
182
- if @page.contains_feed?
183
- render action: :show, layout: false, handlers: [:builder]
184
- else
185
- render xml: { error: "Not found" }, status: 404
186
- end
187
- end
188
187
  end
189
188
  end
190
189
 
@@ -220,10 +219,12 @@ module Alchemy
220
219
  # or the cache is stale, because it's been republished by the user.
221
220
  #
222
221
  def render_fresh_page?
223
- must_not_cache? || stale?(etag: page_etag,
224
- last_modified: @page.published_at,
225
- public: !@page.restricted,
226
- template: "pages/show")
222
+ must_not_cache? || stale?(
223
+ etag: page_etag,
224
+ last_modified: @page.published_at,
225
+ public: !@page.restricted,
226
+ template: "pages/show",
227
+ )
227
228
  end
228
229
 
229
230
  # don't cache pages if we have flash message to display or the page has caching disabled
@@ -234,5 +235,9 @@ module Alchemy
234
235
  def page_not_found!
235
236
  not_found_error!("Alchemy::Page not found \"#{request.fullpath}\"")
236
237
  end
238
+
239
+ def page_includes
240
+ Alchemy::EagerLoading.page_includes(version: :public_version)
241
+ end
237
242
  end
238
243
  end
@@ -8,17 +8,6 @@ module Alchemy
8
8
  "alchemy/admin/elements/element"
9
9
  end
10
10
 
11
- # Returns content editor instances for defined contents
12
- #
13
- # Creates contents on demand if the content is not yet present on the element
14
- #
15
- # @return Array<Alchemy::ContentEditor>
16
- def contents
17
- element.definition.fetch(:contents, []).map do |content|
18
- Alchemy::ContentEditor.new(find_or_create_content(content[:name]))
19
- end
20
- end
21
-
22
11
  # Returns ingredient editor instances for defined ingredients
23
12
  #
24
13
  # Creates ingredient on demand if the ingredient is not yet present on the element
@@ -36,7 +25,7 @@ module Alchemy
36
25
  element.definition.fetch(:ingredients, []).any?
37
26
  end
38
27
 
39
- # Returns the translated content/ingredient group for displaying in admin editor group headings
28
+ # Returns the translated ingredient group for displaying in admin editor group headings
40
29
  #
41
30
  # Translate it in your locale yml file:
42
31
  #
@@ -63,7 +52,7 @@ module Alchemy
63
52
  def css_classes
64
53
  [
65
54
  "element-editor",
66
- content_definitions.present? ? "with-contents" : "without-contents",
55
+ ingredient_definitions.present? ? "with-ingredients" : "without-ingredients",
67
56
  nestable_elements.any? ? "nestable" : "not-nestable",
68
57
  taggable? ? "taggable" : "not-taggable",
69
58
  folded ? "folded" : "expanded",
@@ -78,12 +67,13 @@ module Alchemy
78
67
  def editable?
79
68
  return false if folded?
80
69
 
81
- content_definitions.present? || ingredient_definitions.any? || taggable?
70
+ ingredient_definitions.any? || taggable?
82
71
  end
83
72
 
84
73
  # Fixes Rails partial renderer calling to_model on the object
85
74
  # which reveals the delegated element instead of this decorator.
86
- def respond_to?(method_name)
75
+ def respond_to?(*args, **kwargs)
76
+ method_name = args.first
87
77
  return false if method_name == :to_model
88
78
 
89
79
  super
@@ -124,26 +114,16 @@ module Alchemy
124
114
  when String
125
115
  definition["deprecated"]
126
116
  when TrueClass
127
- Alchemy.t(name,
128
- scope: :element_deprecation_notices,
129
- default: Alchemy.t(:element_deprecated))
117
+ Alchemy.t(
118
+ name,
119
+ scope: :element_deprecation_notices,
120
+ default: Alchemy.t(:element_deprecated),
121
+ )
130
122
  end
131
123
  end
132
124
 
133
125
  private
134
126
 
135
- def find_or_create_content(name)
136
- find_content(name) || create_content(name)
137
- end
138
-
139
- def find_content(name)
140
- element.contents.find { |content| content.name == name }
141
- end
142
-
143
- def create_content(name)
144
- Alchemy::Content.create(element: element, name: name)
145
- end
146
-
147
127
  def find_or_create_ingredient(definition)
148
128
  element.ingredients.detect { |i| i.role == definition[:role] } ||
149
129
  element.ingredients.create!(
@@ -4,8 +4,6 @@ module Alchemy
4
4
  module Admin
5
5
  module ElementsHelper
6
6
  include Alchemy::Admin::IngredientsHelper
7
- include Alchemy::Admin::ContentsHelper
8
- include Alchemy::Admin::EssencesHelper
9
7
 
10
8
  # Returns an elements array for select helper.
11
9
  #
@@ -24,69 +24,32 @@ module Alchemy
24
24
  # Block-level helper class for element views.
25
25
  #
26
26
  class ElementViewHelper < BlockHelper
27
- # Renders one of the element's contents.
27
+ # Renders one of the element's ingredients.
28
28
  #
29
29
  # If the element uses +ingredients+ it renders the ingredient record.
30
30
  #
31
31
  def render(name, options = {}, html_options = {})
32
- renderable = element.ingredient_by_role(name) || Alchemy::Deprecation.silence { content(name) }
32
+ renderable = element.ingredient_by_role(name)
33
33
  return if renderable.nil?
34
34
 
35
- if Alchemy::DEPRECATED_ESSENCE_CLASSES.include?(renderable.try(:essence)&.class&.name)
36
- Alchemy::Deprecation.warn(
37
- "Using a '#{renderable.essence.class.name.demodulize}' content is deprecated. " \
38
- "Please use a '#{Alchemy::DEPRECATED_ESSENCE_CLASS_MAPPING[renderable.essence.class.name].demodulize}' ingredient instead."
39
- )
40
- end
41
-
42
35
  helpers.render(renderable, {
43
36
  options: options,
44
37
  html_options: html_options,
45
38
  })
46
39
  end
47
40
 
48
- # Returns one of the element's contents (ie. essence instances).
49
- #
50
- def content(name)
51
- element.content_by_name(name)
52
- end
53
-
54
- deprecate content: "Use `ingredient_by_role` instead", deprecator: Alchemy::Deprecation
55
-
56
- # Returns the ingredient of one of the element's contents.
57
- #
58
- # If the element uses +ingredients+ it returns the +value+ of the ingredient record.
59
- #
60
- def ingredient(name)
61
- element.ingredient(name)
62
- end
63
-
64
41
  # Returns the value of one of the element's ingredients.
65
42
  #
66
43
  def value(name)
67
44
  element.value_for(name)
68
45
  end
69
46
 
70
- # Returns true if the given content or ingredient has a value.
47
+ # Returns true if the given ingredient has a value.
71
48
  #
72
49
  def has?(name)
73
- if element.ingredient_definitions.any?
74
- element.has_value_for?(name)
75
- else
76
- Alchemy::Deprecation.silence do
77
- element.has_ingredient?(name)
78
- end
79
- end
50
+ element.has_value_for?(name)
80
51
  end
81
52
 
82
- # Return's the given content's essence.
83
- #
84
- def essence(name)
85
- content(name).try(:essence)
86
- end
87
-
88
- deprecate essence: "Use `ingredient_by_role` instead", deprecator: Alchemy::Deprecation
89
-
90
53
  # Return's the ingredient record by given role.
91
54
  #
92
55
  def ingredient_by_role(role)
@@ -129,7 +92,7 @@ module Alchemy
129
92
  # The HTML tag to be used for the wrapping element.
130
93
  # @option options :id (the element's dom_id)
131
94
  # The wrapper tag's DOM ID.
132
- # @option options :class (the element's essence name)
95
+ # @option options :class (the element's name)
133
96
  # The wrapper tag's DOM class.
134
97
  # @option options :tags_formatter
135
98
  # A lambda used for formatting the element's tags (see Alchemy::ElementsHelper::element_tags_attributes). Set to +false+ to not include tags in the wrapper element.
@@ -112,9 +112,9 @@ module Alchemy
112
112
  #
113
113
  # # elements.yml
114
114
  # - name: headline
115
- # contents:
116
- # - name: text
117
- # type: EssenceText
115
+ # ingredients:
116
+ # - role: text
117
+ # type: Text
118
118
  #
119
119
  # Then your element view partial has to be named like:
120
120
  #
@@ -166,14 +166,6 @@ module Alchemy
166
166
  render "alchemy/elements/view_not_found", name: element.name
167
167
  end
168
168
 
169
- # Returns a string for the id attribute of a html element for the given element
170
- # @deprecated
171
- def element_dom_id(element)
172
- element&.dom_id
173
- end
174
-
175
- deprecate element_dom_id: "element.dom_id", deprecator: Alchemy::Deprecation
176
-
177
169
  # Renders the HTML tag attributes required for preview mode.
178
170
  def element_preview_code(element)
179
171
  tag_builder.tag_options(element_preview_code_attributes(element))
@@ -5,10 +5,6 @@ module Alchemy
5
5
  include Alchemy::BaseHelper
6
6
  include Alchemy::ElementsHelper
7
7
 
8
- def picture_essence_caption(content)
9
- content.try(:essence).try(:caption)
10
- end
11
-
12
8
  # Renders links to language root pages of all published languages.
13
9
  #
14
10
  # @option options linkname [String] ('name')
@@ -30,9 +30,12 @@ module Alchemy
30
30
 
31
31
  stampable stamper_class_name: Alchemy.user_class.name
32
32
 
33
- has_many :essence_files, class_name: "Alchemy::EssenceFile", foreign_key: "attachment_id"
34
- has_many :contents, through: :essence_files
35
- has_many :elements, through: :contents
33
+ has_many :file_ingredients,
34
+ class_name: "Alchemy::Ingredients::File",
35
+ foreign_key: "related_object_id",
36
+ inverse_of: :related_object
37
+
38
+ has_many :elements, through: :file_ingredients
36
39
  has_many :pages, through: :elements
37
40
 
38
41
  scope :by_file_type, ->(file_type) { where(file_mime_type: file_type) }
@@ -5,6 +5,8 @@ module Alchemy
5
5
  end
6
6
 
7
7
  class BaseRecord < ActiveRecord::Base
8
+ extend Alchemy::SearchableResource
9
+
8
10
  self.abstract_class = true
9
11
  end
10
12
  end
@@ -28,7 +28,6 @@ module Alchemy
28
28
  :tags,
29
29
  {
30
30
  ingredients: :related_object,
31
- contents: :essence,
32
31
  },
33
32
  ],
34
33
  },
@@ -37,13 +37,6 @@ module Alchemy
37
37
  ingredients_by_type(type).first
38
38
  end
39
39
 
40
- # All ingredients from element by given role.
41
- def ingredients_by_role(role)
42
- ingredients.select do |ingredient|
43
- ingredient.role == Ingredient.normalize_type(role)
44
- end
45
- end
46
-
47
40
  # All ingredients from element by given type.
48
41
  def ingredients_by_type(type)
49
42
  ingredients.select do |ingredient|
@@ -133,7 +126,7 @@ module Alchemy
133
126
  # == Error message translation fallbacks
134
127
  #
135
128
  # In order to not translate every single ingredient for every element
136
- # you can provide default error messages per content name:
129
+ # you can provide default error messages per ingredient role:
137
130
  #
138
131
  # === Example
139
132
  #
@@ -38,16 +38,15 @@ module Alchemy
38
38
 
39
39
  # Returns a preview text for element.
40
40
  #
41
- # It's taken from the first Content found in the +elements.yml+ definition file.
41
+ # It's taken from the first Ingredient found in the +elements.yml+ definition file.
42
42
  #
43
- # You can flag a Content as +as_element_title+ to take this as preview.
43
+ # You can flag a Ingredient as +as_element_title+ to take this as preview.
44
44
  #
45
45
  # @param maxlength [Fixnum] (60)
46
46
  # Length of characters after the text will be cut off.
47
47
  #
48
48
  def preview_text(maxlength = 60)
49
49
  preview_text_from_preview_ingredient(maxlength) ||
50
- preview_text_from_preview_content(maxlength) ||
51
50
  preview_text_from_nested_elements(maxlength)
52
51
  end
53
52
 
@@ -61,14 +60,14 @@ module Alchemy
61
60
  #
62
61
  # - name: funky_element
63
62
  # display_name: Funky Element
64
- # contents:
65
- # - name: headline
66
- # type: EssenceText
67
- # - name: text
68
- # type EssenceRichtext
69
- # as_element_title: true
63
+ # ingredients:
64
+ # - role: headline
65
+ # type: Text
66
+ # - role: text
67
+ # type: Richtext
68
+ # as_element_title: true
70
69
  #
71
- # With "I want to tell you a funky story" as stripped_body for the EssenceRichtext Content produces:
70
+ # With "I want to tell you a funky story" as stripped_body for the Richtext ingredient produces:
72
71
  #
73
72
  # Funky Element: I want to tell ...
74
73
  #
@@ -85,17 +84,6 @@ module Alchemy
85
84
  self.class.dom_id_class.new(self).call
86
85
  end
87
86
 
88
- # The content that's used for element's preview text.
89
- #
90
- # It tries to find one of element's contents that is defined +as_element_title+.
91
- # Takes element's first content if no content is defined +as_element_title+.
92
- #
93
- # @return (Alchemy::Content)
94
- #
95
- def preview_content
96
- @_preview_content ||= contents.detect(&:preview_content?) || contents.first
97
- end
98
-
99
87
  # The ingredient that's used for element's preview text.
100
88
  #
101
89
  # It tries to find one of element's ingredients that is defined +as_element_title+.
@@ -115,10 +103,6 @@ module Alchemy
115
103
  all_nested_elements.first.preview_text(maxlength)
116
104
  end
117
105
 
118
- def preview_text_from_preview_content(maxlength)
119
- preview_content.try!(:preview_text, maxlength)
120
- end
121
-
122
106
  def preview_text_from_preview_ingredient(maxlength)
123
107
  preview_ingredient&.preview_text(maxlength)
124
108
  end