alchemy_cms 3.0.0.rc7 → 3.0.0.rc8

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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -1
  3. data/README.md +1 -1
  4. data/app/assets/javascripts/alchemy/alchemy.dragndrop.js.coffee +0 -2
  5. data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +1 -1
  6. data/app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee +26 -2
  7. data/app/assets/javascripts/alchemy/alchemy.preview_window.js.coffee +1 -1
  8. data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +22 -0
  9. data/app/assets/stylesheets/alchemy/base.scss +1 -5
  10. data/app/assets/stylesheets/alchemy/elements.scss +11 -61
  11. data/app/assets/stylesheets/alchemy/frame.scss +1 -1
  12. data/app/assets/stylesheets/tinymce/skins/alchemy/skin.min.css.scss +1 -1
  13. data/app/controllers/alchemy/admin/attachments_controller.rb +1 -1
  14. data/app/controllers/alchemy/admin/base_controller.rb +7 -13
  15. data/app/controllers/alchemy/admin/clipboard_controller.rb +15 -10
  16. data/app/controllers/alchemy/admin/elements_controller.rb +15 -11
  17. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +8 -1
  18. data/app/controllers/alchemy/admin/pages_controller.rb +95 -22
  19. data/app/controllers/alchemy/admin/tags_controller.rb +1 -1
  20. data/app/controllers/alchemy/pictures_controller.rb +33 -32
  21. data/app/helpers/alchemy/admin/base_helper.rb +3 -16
  22. data/app/models/alchemy/element.rb +1 -1
  23. data/app/models/alchemy/page/page_naming.rb +4 -2
  24. data/app/models/alchemy/page/page_natures.rb +1 -1
  25. data/app/models/alchemy/page.rb +20 -1
  26. data/app/models/alchemy/picture.rb +1 -0
  27. data/app/models/alchemy/tree_node.rb +4 -0
  28. data/app/views/alchemy/admin/contents/destroy.js.erb +4 -0
  29. data/app/views/alchemy/admin/dashboard/index.html.erb +1 -1
  30. data/app/views/alchemy/admin/elements/_element.html.erb +11 -12
  31. data/app/views/alchemy/admin/elements/_new_element_form.html.erb +0 -3
  32. data/app/views/alchemy/admin/elements/create.js.erb +3 -3
  33. data/app/views/alchemy/admin/elements/index.html.erb +4 -19
  34. data/app/views/alchemy/admin/elements/new.html.erb +0 -3
  35. data/app/views/alchemy/admin/elements/trash.js.erb +12 -16
  36. data/app/views/alchemy/admin/pages/_page.html.erb +1 -1
  37. data/app/views/alchemy/admin/pages/edit.html.erb +36 -30
  38. data/app/views/alchemy/admin/pictures/edit_multiple.html.erb +1 -1
  39. data/app/views/alchemy/admin/trash/clear.js.erb +4 -0
  40. data/config/locales/alchemy.de.yml +56 -84
  41. data/config/locales/alchemy.en.yml +326 -105
  42. data/config/locales/alchemy.fr.yml +942 -0
  43. data/config/locales/alchemy.nl.yml +111 -137
  44. data/config/locales/simple_form.fr.yml +26 -0
  45. data/lib/alchemy/engine.rb +7 -1
  46. data/lib/alchemy/i18n.rb +7 -1
  47. data/lib/alchemy/middleware/rescue_old_cookies.rb +27 -0
  48. data/lib/alchemy/permissions.rb +1 -1
  49. data/lib/alchemy/version.rb +1 -1
  50. data/spec/controllers/admin/clipboard_controller_spec.rb +16 -19
  51. data/spec/controllers/admin/elements_controller_spec.rb +20 -23
  52. data/spec/controllers/admin/essence_pictures_controller_spec.rb +22 -6
  53. data/spec/controllers/admin/pages_controller_spec.rb +94 -5
  54. data/spec/controllers/pictures_controller_spec.rb +44 -3
  55. data/spec/features/admin/link_overlay_spec.rb +1 -0
  56. data/spec/features/admin/locale_select_feature_spec.rb +22 -0
  57. data/spec/libraries/i18n_spec.rb +30 -0
  58. data/spec/libraries/permissions_spec.rb +1 -1
  59. data/spec/models/element_spec.rb +5 -4
  60. data/spec/models/page_spec.rb +137 -8
  61. data/spec/spec_helper.rb +23 -19
  62. data/vendor/assets/javascripts/jquery_plugins/jquery.ui.nestedSortable.js +9 -3
  63. metadata +12 -10
  64. data/app/models/alchemy/clipboard.rb +0 -74
  65. data/app/views/alchemy/admin/contents/destroy.js.coffee +0 -4
  66. data/app/views/alchemy/admin/elements/_add_element_button.html.erb +0 -18
  67. data/app/views/alchemy/admin/trash/clear.js.coffee +0 -4
  68. data/spec/models/clipboard_spec.rb +0 -111
  69. data/spec/support/phantomjs_mavericks_fix.rb +0 -32
@@ -75,7 +75,14 @@ module Alchemy
75
75
 
76
76
  def sizes_from_essence
77
77
  return if @essence_picture.render_size.blank?
78
- @essence_picture.render_size.split('x')
78
+ size_x, size_y = @essence_picture.render_size.split('x').map(&:to_i)
79
+ if size_x.zero? || size_y.nil? || size_y.zero?
80
+ size_x_of_original = @essence_picture.picture.image_file_width
81
+ size_y_of_original = @essence_picture.picture.image_file_height
82
+ size_x = size_x_of_original * size_y / size_y_of_original if size_x.zero?
83
+ size_y = size_y_of_original * size_x / size_x_of_original if size_y.nil? || size_y.zero?
84
+ end
85
+ [size_x, size_y]
79
86
  end
80
87
 
81
88
  def sizes_string
@@ -40,7 +40,8 @@ module Alchemy
40
40
  def new
41
41
  @page = Page.new(layoutpage: params[:layoutpage] == 'true', parent_id: params[:parent_id])
42
42
  @page_layouts = PageLayout.layouts_for_select(Language.current.id, @page.layoutpage?)
43
- @clipboard_items = Page.all_from_clipboard_for_select(get_clipboard[:pages], Language.current.id, @page.layoutpage?)
43
+ @clipboard = get_clipboard('pages')
44
+ @clipboard_items = Page.all_from_clipboard_for_select(@clipboard, Language.current.id, @page.layoutpage?)
44
45
  end
45
46
 
46
47
  def create
@@ -50,7 +51,8 @@ module Alchemy
50
51
  do_redirect_to(redirect_path_after_create_page)
51
52
  else
52
53
  @page_layouts = PageLayout.layouts_for_select(Language.current.id, @page.layoutpage?)
53
- @clipboard_items = Page.all_from_clipboard_for_select(get_clipboard[:pages], Language.current.id, @page.layoutpage?)
54
+ @clipboard = get_clipboard('pages')
55
+ @clipboard_items = Page.all_from_clipboard_for_select(@clipboard, Language.current.id, @page.layoutpage?)
54
56
  render :new
55
57
  end
56
58
  end
@@ -59,7 +61,7 @@ module Alchemy
59
61
  def edit
60
62
  # fetching page via before filter
61
63
  if page_is_locked?
62
- flash[:notice] = _t("This page is locked by %{name}", name: @page.locker_name)
64
+ flash[:notice] = _t('This page is locked', name: @page.locker_name)
63
65
  redirect_to admin_pages_path
64
66
  else
65
67
  @page.lock_to!(current_alchemy_user)
@@ -102,7 +104,8 @@ module Alchemy
102
104
  format.js
103
105
  end
104
106
  # remove from clipboard
105
- get_clipboard.remove(:pages, @page_id)
107
+ @clipboard = get_clipboard('pages')
108
+ @clipboard.delete_if { |item| item['id'] == @page_id.to_s }
106
109
  end
107
110
  end
108
111
 
@@ -170,15 +173,17 @@ module Alchemy
170
173
  @sorting = true
171
174
  end
172
175
 
176
+ # Receives a JSON object representing a language tree to be ordered
177
+ # and updates all pages in that language structure to their correct indexes
173
178
  def order
174
- # Taken from https://github.com/matenia/jQuery-Awesome-Nested-Set-Drag-and-Drop
175
179
  neworder = JSON.parse(params[:set])
176
- prev_item = nil
177
- neworder.each do |item|
178
- dbitem = Page.find(item['id'])
179
- prev_item.nil? ? dbitem.move_to_child_of(@page_root) : dbitem.move_to_right_of(prev_item)
180
- sort_children(item, dbitem) unless item['children'].nil?
181
- prev_item = dbitem.reload
180
+ tree = create_tree(neworder, @page_root)
181
+
182
+ Alchemy::Page.transaction do
183
+ tree.each do |key, node|
184
+ dbitem = Page.find(key)
185
+ dbitem.update_node!(node)
186
+ end
182
187
  end
183
188
 
184
189
  flash[:notice] = _t("Pages order saved")
@@ -215,6 +220,85 @@ module Alchemy
215
220
  Page.language_root_for(params[:languages][:old_lang_id])
216
221
  end
217
222
 
223
+ # Returns the current left index and the aggregated hash of tree nodes indexed by page id visited so far
224
+ #
225
+ # Visits a batch of children nodes, assigns them the correct ordering indexes and spuns recursively the same
226
+ # procedure on their children, if any
227
+ #
228
+ # @param [Array]
229
+ # An array of children nodes to be visited
230
+ # @param [Integer]
231
+ # The lft attribute that should be given to the first node in the array
232
+ # @param [Integer]
233
+ # The page id of the parent of this batch of children nodes
234
+ # @param [Integer]
235
+ # The depth at which these children reside
236
+ # @param [Hash]
237
+ # A Hash of TreeNode's indexed by their page ids
238
+ # @param [String]
239
+ # The url for the parent node of these children
240
+ # @param [Boolean]
241
+ # Whether these children reside in a restricted branch according to their ancestors
242
+ #
243
+ def visit_nodes(nodes, my_left, parent, depth, tree, url, restricted)
244
+ nodes.each do |item|
245
+ my_right = my_left + 1
246
+ my_restricted = item['restricted'] || restricted
247
+ urls = process_url(url, item)
248
+
249
+ if item['children']
250
+ my_right, tree = visit_nodes(item['children'], my_left + 1, item['id'], depth + 1, tree, urls[:children_path], my_restricted)
251
+ end
252
+
253
+ tree[item['id']] = TreeNode.new(my_left, my_right, parent, depth, urls[:my_urlname], my_restricted)
254
+ my_left = my_right + 1
255
+ end
256
+
257
+ [my_left, tree]
258
+ end
259
+
260
+ # Returns a Hash of TreeNode's indexed by their page ids
261
+ #
262
+ # Grabs the array representing a tree structure of pages passed as a parameter,
263
+ # visits it and creates a map of TreeNodes indexed by page id featuring Nested Set
264
+ # ordering information consisting of the left, right, depth and parent_id indexes as
265
+ # well as a node's url and restricted status
266
+ #
267
+ # @param [Array]
268
+ # An Array representing a tree of Alchemy::Page's
269
+ # @param [Alchemy::Page]
270
+ # The root page for the language being ordered
271
+ #
272
+ def create_tree(items, rootpage)
273
+ _, tree = visit_nodes(items, rootpage.lft + 1, rootpage.id, rootpage.depth + 1, {}, "", rootpage.restricted)
274
+ tree
275
+ end
276
+
277
+ # Returns a pair, the path that a given tree node should take, and the path its children should take
278
+ #
279
+ # This function will add a node's own slug into their ancestor's path
280
+ # in order to create the full URL of a node
281
+ #
282
+ # NOTE: external and invisible pages are not part of the full path of their children
283
+ #
284
+ # @param [String]
285
+ # The node's ancestors path
286
+ # @param [Hash]
287
+ # A children node
288
+ #
289
+ def process_url(ancestors_path, item)
290
+ default_urlname = (ancestors_path.blank? ? "" : "#{ancestors_path}/") + item['slug']
291
+
292
+ pair = {my_urlname: default_urlname, children_path: default_urlname}
293
+
294
+ if item['external'] == true || item['visible'] == false
295
+ # children ignore an ancestor in their path if external or invisible
296
+ pair[:children_path] = ancestors_path
297
+ end
298
+
299
+ pair
300
+ end
301
+
218
302
  def load_page
219
303
  @page = Page.find(params[:id])
220
304
  end
@@ -223,17 +307,6 @@ module Alchemy
223
307
  request.raw_post.split('&').map { |i| i = {i.split('=')[0].gsub(/[^0-9]/, '') => i.split('=')[1]} }
224
308
  end
225
309
 
226
- # Taken from https://github.com/matenia/jQuery-Awesome-Nested-Set-Drag-and-Drop
227
- def sort_children(element, dbitem)
228
- prevchild = nil
229
- element['children'].each do |child|
230
- childitem = Page.find(child['id'])
231
- prevchild.nil? ? childitem.move_to_child_of(dbitem) : childitem.move_to_right_of(prevchild)
232
- sort_children(child, childitem) unless child['children'].nil?
233
- prevchild = childitem
234
- end
235
- end
236
-
237
310
  def redirect_path_for_switch_language
238
311
  if request.referer && request.referer.include?('admin/layoutpages')
239
312
  admin_layoutpages_path
@@ -26,7 +26,7 @@ module Alchemy
26
26
  if tag_params[:merge_to]
27
27
  @new_tag = ActsAsTaggableOn::Tag.find(tag_params[:merge_to])
28
28
  Tag.replace(@tag, @new_tag)
29
- operation_text = _t('Replaced Tag %{old_tag} with %{new_tag}') % {:old_tag => @tag.name, :new_tag => @new_tag.name}
29
+ operation_text = _t('Replaced Tag') % {old_tag: @tag.name, new_tag: @new_tag.name}
30
30
  @tag.destroy
31
31
  else
32
32
  @tag.update_attributes(tag_params)
@@ -45,68 +45,69 @@ module Alchemy
45
45
  return false
46
46
  end
47
47
 
48
- def send_image(image_file, format)
48
+ def send_image(image, format)
49
49
  ALLOWED_IMAGE_TYPES.each do |type|
50
50
  format.send(type) do
51
51
  if type == 'jpeg'
52
52
  quality = params[:quality] || Config.get(:output_image_jpg_quality)
53
- image_file = image_file.encode(type, "-quality #{quality}")
53
+ image = image.encode(type, "-quality #{quality}")
54
54
  else
55
- image_file = image_file.encode(type)
55
+ image = image.encode(type)
56
56
  end
57
- render text: image_file.data
57
+ render text: image.data
58
58
  end
59
59
  end
60
60
  end
61
61
 
62
62
  # Return the processed image dependent of size and cropping parameters
63
63
  def processed_image
64
- image_file = @picture.image_file
65
- if image_file.nil?
64
+ @image = @picture.image_file
65
+ if @image.nil?
66
66
  raise MissingImageFileError, "Missing image file for #{@picture.inspect}"
67
67
  end
68
- if params[:crop_size].present? && params[:crop_from].present?
69
- image_file = image_file.thumb crop_geometry_string(params)
70
- image_file.thumb(resize_geometry_string)
71
- elsif params[:crop] == 'crop' && @size.present?
72
- width, height = normalize_sizes(image_file)
73
- image_file.thumb("#{width}x#{height}#")
74
- elsif @size.present?
75
- image_file.thumb(resize_geometry_string)
68
+ if @size.present?
69
+ if params[:crop_size].present? && params[:crop_from].present?
70
+ @image = @image.thumb xy_crop_geometry_string(params)
71
+ @image.thumb(resize_geometry_string)
72
+ elsif params[:crop]
73
+ @image.thumb(center_crop_geometry_string)
74
+ else
75
+ @image.thumb(resize_geometry_string)
76
+ end
76
77
  else
77
- image_file
78
+ @image
78
79
  end
79
80
  end
80
81
 
81
82
  # Returns the Imagemagick geometry string for cropping the image.
82
- def crop_geometry_string(params)
83
+ def xy_crop_geometry_string(params)
83
84
  crop_from_x, crop_from_y = params[:crop_from].split('x')
84
85
  "#{params[:crop_size]}+#{crop_from_x}+#{crop_from_y}"
85
86
  end
86
87
 
87
88
  # Returns the Imagemagick geometry string used to resize the image.
89
+ #
90
+ # Prevents upscaling unless :upsample param is true.
88
91
  def resize_geometry_string
89
- @resize_geometry_string ||= begin
90
- params[:upsample] == 'true' ? @size.to_s : "#{@size}>"
91
- end
92
+ params[:upsample] == 'true' ? @size : "#{@size}>"
92
93
  end
93
94
 
94
- # Returns normalized width and height values
95
+ # Returns the Imagemagick geometry string used to crop the image.
95
96
  #
96
- # Prevents upscaling unless :upsample param is true,
97
- # because unfurtunally Dragonfly does not handle this correctly while cropping
98
- #
99
- def normalize_sizes(image_file)
100
- width, height = @size.split('x').collect(&:to_i)
101
- return width, height if params[:upsample] == 'true'
102
- if width > image_file.width
103
- width = image_file.width
97
+ # Prevents upscaling unless :upsample param is true
98
+ def center_crop_geometry_string
99
+ params[:upsample] == 'true' ? "#{@size}#" : "#{normalized_sizes(*@size.split('x'))}#"
100
+ end
101
+
102
+ # Ensure we're not trying to scale the image up. Used only for cropping.
103
+ def normalized_sizes(width, height)
104
+ if width.to_i > @image.width
105
+ width = @image.width
104
106
  end
105
- if height > image_file.height
106
- height = image_file.height
107
+ if height.to_i > @image.height
108
+ height = @image.height
107
109
  end
108
- return width, height
110
+ "#{width}x#{height}"
109
111
  end
110
-
111
112
  end
112
113
  end
@@ -34,12 +34,6 @@ module Alchemy
34
34
  #
35
35
  # <%= link_to_dialog('Edit', edit_product_path, {size: '200x300'}, {class: 'icon_button'}) %>
36
36
  #
37
- # Or you call it with a block
38
- #
39
- # <%= link_to_dialog edit_product_path, {size: 200x300} do %>
40
- # <%= render_icon(:edit) %>
41
- # <% end %>
42
- #
43
37
  # @param [String] content
44
38
  # The string inside the link tag
45
39
  # @param [String or Hash] url
@@ -56,18 +50,11 @@ module Alchemy
56
50
  # @option options [Boolean] :modal (true)
57
51
  # Show as modal window.
58
52
  #
59
- def link_to_dialog(content = nil, url = nil, options = {}, html_options = {}, &block)
60
- html_options, options, url, content = options, url, content, block if block_given?
53
+ def link_to_dialog(content, url, options={}, html_options={})
61
54
  default_options = {modal: true}
62
55
  options = default_options.merge(options)
63
- if block_given?
64
- link_to url,
65
- html_options.merge('data-alchemy-dialog' => options.to_json),
66
- &block
67
- else
68
- link_to content, url,
69
- html_options.merge('data-alchemy-dialog' => options.to_json)
70
- end
56
+ link_to content, url,
57
+ html_options.merge('data-alchemy-dialog' => options.to_json)
71
58
  end
72
59
 
73
60
  # Used for translations selector in Alchemy cockpit user settings.
@@ -115,7 +115,7 @@ module Alchemy
115
115
 
116
116
  def all_from_clipboard(clipboard)
117
117
  return [] if clipboard.nil?
118
- where(id: clipboard.collect { |e| e[:id] })
118
+ where(id: clipboard.collect { |e| e['id'] })
119
119
  end
120
120
 
121
121
  # All elements in clipboard that could be placed on page
@@ -16,8 +16,10 @@ module Alchemy
16
16
  uniqueness: {scope: [:language_id, :layoutpage], if: 'urlname.present?'},
17
17
  exclusion: {in: RESERVED_URLNAMES},
18
18
  length: {minimum: 3, if: 'urlname.present?'},
19
- format: {with: /\A[:\.\w\-+_\/\?&%;=]*\z/, if: :redirects_to_external?},
20
- presence: {if: :redirects_to_external?}
19
+ format: {with: /\A[:\.\w\-+_\/\?&%;=]*\z/, if: :redirects_to_external?}
20
+ validates :urlname,
21
+ on: :update,
22
+ presence: {if: :redirects_to_external?}
21
23
 
22
24
  before_save :set_title, :if => 'title.blank?', :unless => proc { systempage? || redirects_to_external? }
23
25
  after_update :update_descendants_urlnames,
@@ -27,7 +27,7 @@ module Alchemy
27
27
 
28
28
  # Returns true or false if the pages layout_description for config/alchemy/page_layouts.yml contains redirects_to_external: true
29
29
  def redirects_to_external?
30
- definition["redirects_to_external"]
30
+ !!definition["redirects_to_external"]
31
31
  end
32
32
 
33
33
  def has_controller?
@@ -177,7 +177,7 @@ module Alchemy
177
177
 
178
178
  def all_from_clipboard(clipboard)
179
179
  return [] if clipboard.blank?
180
- where(id: clipboard.collect { |p| p[:id] })
180
+ where(id: clipboard.collect { |p| p['id'] })
181
181
  end
182
182
 
183
183
  def all_from_clipboard_for_select(clipboard, language_id, layoutpage = false)
@@ -333,6 +333,25 @@ module Alchemy
333
333
  update_columns(published_at: Time.now, public: true)
334
334
  end
335
335
 
336
+ # Updates an Alchemy::Page based on a new ordering to be applied to it
337
+ #
338
+ # Note: Page's urls should not be updated (and a legacy URL created) if nesting is OFF
339
+ # or if a page is external or if the URL is the same
340
+ #
341
+ # @param [TreeNode]
342
+ # A tree node with new lft, rgt, depth, url, parent_id and restricted indexes to be updated
343
+ #
344
+ def update_node!(node)
345
+ hash = {lft: node.left, rgt: node.right, parent_id: node.parent, depth: node.depth, restricted: node.restricted}
346
+
347
+ if Config.get(:url_nesting) && !self.redirects_to_external? && self.urlname != node.url
348
+ LegacyPageUrl.create(page_id: self.id, urlname: self.urlname)
349
+ hash.merge!(urlname: node.url)
350
+ end
351
+
352
+ update_columns(hash)
353
+ end
354
+
336
355
  private
337
356
 
338
357
  # Returns the next or previous page on the same level or nil.
@@ -200,6 +200,7 @@ module Alchemy
200
200
  return "111x93" if size == "111x93" || size.blank?
201
201
  x = size.split('x')[0].to_i
202
202
  y = size.split('x')[1].to_i
203
+ return "111x93" if x.zero? || y.zero?
203
204
  if (x > y)
204
205
  zoom_factor = 111.0 / x
205
206
  new_x = 111
@@ -0,0 +1,4 @@
1
+ module Alchemy
2
+ class TreeNode < Struct.new(:left, :right, :parent, :depth, :url, :restricted)
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ $('#<%= @content_dom_id %>').remove();
2
+ Alchemy.growl('<%= j @notice %>');
3
+ Alchemy.reloadPreview();
4
+ Alchemy.pleaseWaitOverlay(false);
@@ -26,7 +26,7 @@
26
26
  </h1>
27
27
  <% if @last_sign_at %>
28
28
  <p>
29
- <small><%= _t('Your last login was on %{time}', time: l(@last_sign_at)) %></small>
29
+ <small><%= _t('Your last login was on', time: l(@last_sign_at)) %></small>
30
30
  </p>
31
31
  <% end %>
32
32
  <div class="column left">
@@ -1,24 +1,23 @@
1
1
  <div class="element_editor<%= element.folded ? ' folded' : '' %> <%= defined?(draggable) && !draggable ? 'not-draggable' : 'draggable' %>" id="element_<%= element.id %>" data-element-id="<%= element.id %>">
2
- <%= form_for [:admin, element], remote: true, html: {id: "element_#{element.id}_form"} do |f| %>
3
- <%= render 'alchemy/admin/elements/element_head', element: element %>
4
- <% unless element.folded? %>
2
+ <%= render :partial => "alchemy/admin/elements/element_head", :locals => {:element => element} %>
3
+ <% if !element.folded? %>
4
+ <%= form_for [:admin, element], :remote => true, :html => {:id => "element_#{element.id}_form"} do |f| %>
5
5
  <div id="element_<%= element.id %>_errors" class="element_errors" style="display: none"></div>
6
6
  <div id="element_<%= element.id %>_content" class="element_content">
7
7
  <%= render_editor(element) %>
8
8
  </div>
9
9
  <% if element.has_validations? %>
10
- <p class="validation_notice">
11
- <span class="validation_indicator">*</span> <%= _t('Mandatory') %>
12
- </p>
10
+ <p class="validation_notice">
11
+ <span class="validation_indicator">*</span> <%= _t('Mandatory') %>
12
+ </p>
13
13
  <% end %>
14
14
  <% if element.taggable? %>
15
- <div class="autocomplete_tag_list">
16
- <%= f.label :tag_list %>
17
- <%= render 'alchemy/admin/partials/autocomplete_tag_list', f: f %>
18
- </div>
15
+ <div class="autocomplete_tag_list">
16
+ <%= f.label :tag_list %>
17
+ <%= render 'alchemy/admin/partials/autocomplete_tag_list', f: f %>
18
+ </div>
19
19
  <% end %>
20
- <%= render 'alchemy/admin/elements/element_foot', element: element, f: f %>
20
+ <%= render :partial => 'alchemy/admin/elements/element_foot', :locals => {:element => element, :f => f} %>
21
21
  <% end %>
22
22
  <% end %>
23
- <%= render 'alchemy/admin/elements/add_element_button', element_before: element %>
24
23
  </div>