alchemy_cms 3.0.0.rc7 → 3.0.0.rc8

Sign up to get free protection for your applications and to get access to all the features.
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>