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.
- checksums.yaml +4 -4
- data/Gemfile +2 -1
- data/README.md +1 -1
- data/app/assets/javascripts/alchemy/alchemy.dragndrop.js.coffee +0 -2
- data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +1 -1
- data/app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee +26 -2
- data/app/assets/javascripts/alchemy/alchemy.preview_window.js.coffee +1 -1
- data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +22 -0
- data/app/assets/stylesheets/alchemy/base.scss +1 -5
- data/app/assets/stylesheets/alchemy/elements.scss +11 -61
- data/app/assets/stylesheets/alchemy/frame.scss +1 -1
- data/app/assets/stylesheets/tinymce/skins/alchemy/skin.min.css.scss +1 -1
- data/app/controllers/alchemy/admin/attachments_controller.rb +1 -1
- data/app/controllers/alchemy/admin/base_controller.rb +7 -13
- data/app/controllers/alchemy/admin/clipboard_controller.rb +15 -10
- data/app/controllers/alchemy/admin/elements_controller.rb +15 -11
- data/app/controllers/alchemy/admin/essence_pictures_controller.rb +8 -1
- data/app/controllers/alchemy/admin/pages_controller.rb +95 -22
- data/app/controllers/alchemy/admin/tags_controller.rb +1 -1
- data/app/controllers/alchemy/pictures_controller.rb +33 -32
- data/app/helpers/alchemy/admin/base_helper.rb +3 -16
- data/app/models/alchemy/element.rb +1 -1
- data/app/models/alchemy/page/page_naming.rb +4 -2
- data/app/models/alchemy/page/page_natures.rb +1 -1
- data/app/models/alchemy/page.rb +20 -1
- data/app/models/alchemy/picture.rb +1 -0
- data/app/models/alchemy/tree_node.rb +4 -0
- data/app/views/alchemy/admin/contents/destroy.js.erb +4 -0
- data/app/views/alchemy/admin/dashboard/index.html.erb +1 -1
- data/app/views/alchemy/admin/elements/_element.html.erb +11 -12
- data/app/views/alchemy/admin/elements/_new_element_form.html.erb +0 -3
- data/app/views/alchemy/admin/elements/create.js.erb +3 -3
- data/app/views/alchemy/admin/elements/index.html.erb +4 -19
- data/app/views/alchemy/admin/elements/new.html.erb +0 -3
- data/app/views/alchemy/admin/elements/trash.js.erb +12 -16
- data/app/views/alchemy/admin/pages/_page.html.erb +1 -1
- data/app/views/alchemy/admin/pages/edit.html.erb +36 -30
- data/app/views/alchemy/admin/pictures/edit_multiple.html.erb +1 -1
- data/app/views/alchemy/admin/trash/clear.js.erb +4 -0
- data/config/locales/alchemy.de.yml +56 -84
- data/config/locales/alchemy.en.yml +326 -105
- data/config/locales/alchemy.fr.yml +942 -0
- data/config/locales/alchemy.nl.yml +111 -137
- data/config/locales/simple_form.fr.yml +26 -0
- data/lib/alchemy/engine.rb +7 -1
- data/lib/alchemy/i18n.rb +7 -1
- data/lib/alchemy/middleware/rescue_old_cookies.rb +27 -0
- data/lib/alchemy/permissions.rb +1 -1
- data/lib/alchemy/version.rb +1 -1
- data/spec/controllers/admin/clipboard_controller_spec.rb +16 -19
- data/spec/controllers/admin/elements_controller_spec.rb +20 -23
- data/spec/controllers/admin/essence_pictures_controller_spec.rb +22 -6
- data/spec/controllers/admin/pages_controller_spec.rb +94 -5
- data/spec/controllers/pictures_controller_spec.rb +44 -3
- data/spec/features/admin/link_overlay_spec.rb +1 -0
- data/spec/features/admin/locale_select_feature_spec.rb +22 -0
- data/spec/libraries/i18n_spec.rb +30 -0
- data/spec/libraries/permissions_spec.rb +1 -1
- data/spec/models/element_spec.rb +5 -4
- data/spec/models/page_spec.rb +137 -8
- data/spec/spec_helper.rb +23 -19
- data/vendor/assets/javascripts/jquery_plugins/jquery.ui.nestedSortable.js +9 -3
- metadata +12 -10
- data/app/models/alchemy/clipboard.rb +0 -74
- data/app/views/alchemy/admin/contents/destroy.js.coffee +0 -4
- data/app/views/alchemy/admin/elements/_add_element_button.html.erb +0 -18
- data/app/views/alchemy/admin/trash/clear.js.coffee +0 -4
- data/spec/models/clipboard_spec.rb +0 -111
- 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
|
-
@
|
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
|
-
@
|
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(
|
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
|
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
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
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
|
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(
|
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
|
-
|
53
|
+
image = image.encode(type, "-quality #{quality}")
|
54
54
|
else
|
55
|
-
|
55
|
+
image = image.encode(type)
|
56
56
|
end
|
57
|
-
render text:
|
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
|
-
|
65
|
-
if
|
64
|
+
@image = @picture.image_file
|
65
|
+
if @image.nil?
|
66
66
|
raise MissingImageFileError, "Missing image file for #{@picture.inspect}"
|
67
67
|
end
|
68
|
-
if
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
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
|
-
|
78
|
+
@image
|
78
79
|
end
|
79
80
|
end
|
80
81
|
|
81
82
|
# Returns the Imagemagick geometry string for cropping the image.
|
82
|
-
def
|
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
|
-
@
|
90
|
-
params[:upsample] == 'true' ? @size.to_s : "#{@size}>"
|
91
|
-
end
|
92
|
+
params[:upsample] == 'true' ? @size : "#{@size}>"
|
92
93
|
end
|
93
94
|
|
94
|
-
# Returns
|
95
|
+
# Returns the Imagemagick geometry string used to crop the image.
|
95
96
|
#
|
96
|
-
# Prevents upscaling unless :upsample param is true
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
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 >
|
106
|
-
height =
|
107
|
+
if height.to_i > @image.height
|
108
|
+
height = @image.height
|
107
109
|
end
|
108
|
-
|
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
|
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
|
-
|
64
|
-
|
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[
|
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
|
-
|
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?
|
data/app/models/alchemy/page.rb
CHANGED
@@ -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[
|
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.
|
@@ -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
|
-
<%=
|
3
|
-
|
4
|
-
|
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
|
-
|
11
|
-
|
12
|
-
|
10
|
+
<p class="validation_notice">
|
11
|
+
<span class="validation_indicator">*</span> <%= _t('Mandatory') %>
|
12
|
+
</p>
|
13
13
|
<% end %>
|
14
14
|
<% if element.taggable? %>
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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',
|
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>
|