alchemy_cms 2.6.0.rc5 → 2.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +1 -1
- data/Gemfile +2 -1
- data/README.md +2 -4
- data/alchemy_cms.gemspec +1 -1
- data/app/assets/fonts/alchemy/icons.eot +0 -0
- data/app/assets/fonts/alchemy/icons.svg +71 -0
- data/app/assets/fonts/alchemy/icons.ttf +0 -0
- data/app/assets/fonts/alchemy/icons.woff +0 -0
- data/app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee +6 -8
- data/app/assets/javascripts/alchemy/alchemy.hotkeys.js.coffee +2 -3
- data/app/assets/javascripts/alchemy/alchemy.image_cropper.js.coffee +3 -8
- data/app/assets/javascripts/alchemy/alchemy.link_overlay.js.coffee +3 -3
- data/app/assets/javascripts/alchemy/alchemy.preview_window.js.coffee +19 -9
- data/app/assets/javascripts/tiny_mce/plugins/alchemy_link/editor_plugin.js +6 -7
- data/app/assets/stylesheets/alchemy/admin.css.scss +0 -1
- data/app/assets/stylesheets/alchemy/archive.scss +55 -7
- data/app/assets/stylesheets/alchemy/base.scss +8 -144
- data/app/assets/stylesheets/alchemy/defaults.scss +1 -1
- data/app/assets/stylesheets/alchemy/elements.scss +20 -16
- data/app/assets/stylesheets/alchemy/flash.scss +1 -1
- data/app/assets/stylesheets/alchemy/form_elements.scss +49 -42
- data/app/assets/stylesheets/alchemy/icon-font.css.scss +67 -0
- data/app/assets/stylesheets/alchemy/icons.scss +16 -4
- data/app/assets/stylesheets/alchemy/jquery-ui.scss +40 -26
- data/app/assets/stylesheets/alchemy/menubar.css.scss +1 -1
- data/app/assets/stylesheets/alchemy/notices.scss +6 -1
- data/app/assets/stylesheets/alchemy/search.scss +3 -2
- data/app/assets/stylesheets/alchemy/sitemap.scss +72 -13
- data/app/assets/stylesheets/alchemy/tables.scss +31 -24
- data/app/assets/stylesheets/alchemy/upload.scss +1 -1
- data/app/assets/stylesheets/alchemy/variables.scss +2 -1
- data/app/assets/stylesheets/tiny_mce/plugins/inlinepopups/skins/{alchemy → alchemy-tinymce-dialog}/window.css.scss +70 -65
- data/app/controllers/alchemy/admin/base_controller.rb +7 -4
- data/app/controllers/alchemy/admin/pictures_controller.rb +2 -0
- data/app/controllers/alchemy/admin/users_controller.rb +1 -1
- data/app/controllers/alchemy/user_sessions_controller.rb +1 -1
- data/app/helpers/alchemy/admin/base_helper.rb +161 -60
- data/app/helpers/alchemy/admin/pages_helper.rb +4 -1
- data/app/helpers/alchemy/elements_block_helper.rb +1 -1
- data/app/helpers/alchemy/elements_helper.rb +119 -31
- data/app/helpers/alchemy/pages_helper.rb +29 -72
- data/app/models/alchemy/attachment.rb +0 -2
- data/app/models/alchemy/content.rb +1 -1
- data/app/models/alchemy/language.rb +1 -0
- data/app/models/alchemy/page.rb +8 -8
- data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +3 -1
- data/app/views/alchemy/admin/attachments/_overlay_file_list.html.erb +1 -1
- data/app/views/alchemy/admin/attachments/_tag_list.html.erb +25 -27
- data/app/views/alchemy/admin/attachments/index.html.erb +4 -1
- data/app/views/alchemy/admin/elements/_elements_select.html.erb +6 -6
- data/app/views/alchemy/admin/elements/list.js.erb +1 -1
- data/app/views/alchemy/admin/pages/_page.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_page_for_links.html.erb +1 -1
- data/app/views/alchemy/admin/pages/edit.html.erb +4 -2
- data/app/views/alchemy/admin/pictures/_archive.html.erb +0 -1
- data/app/views/alchemy/admin/pictures/_filter_bar.html.erb +2 -1
- data/app/views/alchemy/admin/pictures/_picture.html.erb +5 -0
- data/app/views/alchemy/admin/pictures/index.html.erb +1 -0
- data/app/views/alchemy/base/500.html.erb +26 -5
- data/app/views/alchemy/essences/_essence_picture_tools.html.erb +1 -1
- data/app/views/alchemy/essences/_linkable_essence_tools.html.erb +1 -1
- data/app/views/alchemy/language_links/_language.html.erb +12 -0
- data/app/views/alchemy/language_links/_spacer.html.erb +1 -0
- data/config/locales/alchemy.de.yml +7 -3
- data/config/locales/alchemy.en.yml +8 -3
- data/lib/alchemy/page_layout.rb +1 -1
- data/lib/alchemy/tinymce.rb +1 -1
- data/lib/alchemy/upgrader.rb +26 -0
- data/lib/alchemy/version.rb +1 -1
- data/lib/rails/generators/alchemy/scaffold/scaffold_generator.rb +4 -1
- data/lib/tasks/ferret.rake +1 -0
- data/spec/controllers/admin/users_controller_spec.rb +5 -5
- data/spec/features/admin/pages_controller_spec.rb +1 -1
- data/spec/helpers/admin/pages_helper_spec.rb +31 -0
- data/spec/helpers/pages_helper_spec.rb +60 -72
- data/spec/models/content_spec.rb +2 -1
- data/spec/models/page_layout_spec.rb +29 -0
- data/spec/models/page_spec.rb +33 -1
- data/spec/support/alchemy/test_tweaks.rb +2 -6
- metadata +34 -12
- data/app/assets/fonts/alchemy-icons.eot +0 -0
- data/app/assets/fonts/alchemy-icons.svg +0 -54
- data/app/assets/fonts/alchemy-icons.ttf +0 -0
- data/app/assets/fonts/alchemy-icons.woff +0 -0
- data/app/assets/images/alchemy/placeholder.png +0 -0
- data/app/assets/stylesheets/alchemy/fonts.scss +0 -46
@@ -20,17 +20,20 @@ module Alchemy
|
|
20
20
|
def exception_handler(e)
|
21
21
|
exception_logger(e)
|
22
22
|
show_error_notice(e)
|
23
|
+
if defined?(Airbrake)
|
24
|
+
notify_airbrake(e) unless Rails.env.development? || Rails.env.test?
|
25
|
+
end
|
23
26
|
end
|
24
27
|
|
25
28
|
# Displays an error notice in the Alchemy backend.
|
26
29
|
def show_error_notice(e)
|
27
|
-
|
28
|
-
|
29
|
-
@
|
30
|
+
@error = e
|
31
|
+
# truncate the message, because very long error messages (i.e from mysql2) causes cookie overflow errors
|
32
|
+
@notice = e.message[0..255]
|
33
|
+
@trace = e.backtrace[0..35]
|
30
34
|
if request.xhr?
|
31
35
|
render :action => "error_notice", :layout => false
|
32
36
|
else
|
33
|
-
flash.now[:error] = @notice
|
34
37
|
render '500', :status => 500
|
35
38
|
end
|
36
39
|
end
|
@@ -17,6 +17,8 @@ module Alchemy
|
|
17
17
|
@pictures = @pictures.recent
|
18
18
|
when 'last_upload'
|
19
19
|
@pictures = @pictures.last_upload
|
20
|
+
when 'without_tag'
|
21
|
+
@pictures = @pictures.where("cached_tag_list IS NULL OR cached_tag_list = ''")
|
20
22
|
end
|
21
23
|
@pictures = @pictures.find_paginated(params, pictures_per_page_for_size(@size))
|
22
24
|
if in_overlay?
|
@@ -44,7 +44,7 @@ module Alchemy
|
|
44
44
|
|
45
45
|
def update
|
46
46
|
# User is fetched via before filter
|
47
|
-
params[:user].delete(:
|
47
|
+
params[:user].delete(:roles) unless permitted_to?(:update_roles)
|
48
48
|
if params[:user][:password].present?
|
49
49
|
@user.update_attributes(params[:user])
|
50
50
|
else
|
@@ -4,7 +4,7 @@ module Alchemy
|
|
4
4
|
include Alchemy::FerretSearch
|
5
5
|
helper 'Alchemy::Admin::Base', 'Alchemy::Pages'
|
6
6
|
|
7
|
-
before_filter { enforce_ssl if ssl_required? && !request.ssl? }
|
7
|
+
before_filter(except: 'destroy') { enforce_ssl if ssl_required? && !request.ssl? }
|
8
8
|
before_filter :set_translation
|
9
9
|
before_filter :check_user_count, :only => :new
|
10
10
|
|
@@ -5,26 +5,43 @@ module Alchemy
|
|
5
5
|
#
|
6
6
|
# The most important helpers for module developers are:
|
7
7
|
#
|
8
|
-
# * toolbar
|
9
|
-
# * toolbar_button
|
10
|
-
# * link_to_overlay_window
|
11
|
-
# * link_to_confirmation_window
|
8
|
+
# * {#toolbar}
|
9
|
+
# * {#toolbar_button}
|
10
|
+
# * {#link_to_overlay_window}
|
11
|
+
# * {#link_to_confirmation_window}
|
12
12
|
#
|
13
13
|
module BaseHelper
|
14
14
|
include Alchemy::BaseHelper
|
15
15
|
|
16
|
-
# This helper renders the link
|
16
|
+
# This helper renders the link to an overlay window.
|
17
17
|
#
|
18
18
|
# We use this for our fancy modal overlay windows in the Alchemy cockpit.
|
19
19
|
#
|
20
|
-
#
|
20
|
+
# == Example
|
21
21
|
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
22
|
+
# <%= link_to_overlay_window('Edit', edit_product_path, {size: '200x300'}, {class: 'icon_button'}) %>
|
23
|
+
#
|
24
|
+
# @param [String] content
|
25
|
+
# The string inside the link tag
|
26
|
+
# @param [String or Hash] url
|
27
|
+
# The url of the action displayed inside the overlay window.
|
28
|
+
# @param [Hash] options
|
29
|
+
# options for the overlay window.
|
30
|
+
# @param [Hash] html_options
|
31
|
+
# HTML options passed to the <tt>link_to</tt> helper
|
32
|
+
#
|
33
|
+
# @option options [String] :size
|
34
|
+
# String with format of "WidthxHeight". I.E. ("420x280")
|
35
|
+
# @option options [String] :title
|
36
|
+
# Text for the overlay title bar.
|
37
|
+
# @option options [Boolean] :overflow (false)
|
38
|
+
# Should the dialog have overlapping content. If not, it shows scrollbars. Good for select boxes.
|
39
|
+
# @option options [Boolean] :resizable (false)
|
40
|
+
# Is the dialog window resizable?
|
41
|
+
# @option options [Boolean] :modal (true)
|
42
|
+
# Show as modal window.
|
43
|
+
# @option options [Boolean] :overflow (true)
|
44
|
+
# Should the window show overflowing content?
|
28
45
|
#
|
29
46
|
def link_to_overlay_window(content, url, options={}, html_options={})
|
30
47
|
default_options = {
|
@@ -79,10 +96,30 @@ module Alchemy
|
|
79
96
|
end
|
80
97
|
end
|
81
98
|
|
82
|
-
#
|
99
|
+
# Returns a javascript driven live filter for lists.
|
100
|
+
#
|
101
|
+
# The items must have a html +name+ attribute that holds the filterable value.
|
102
|
+
#
|
103
|
+
# == Example
|
104
|
+
#
|
105
|
+
# Given a list of items:
|
106
|
+
#
|
107
|
+
# <%= js_filter_field('#products .product') %>
|
83
108
|
#
|
84
|
-
#
|
85
|
-
#
|
109
|
+
# <ul id="products">
|
110
|
+
# <li class="product" name="kat litter">Kat Litter</li>
|
111
|
+
# <li class="product" name="milk">Milk</li>
|
112
|
+
# </ul>
|
113
|
+
#
|
114
|
+
# @param [String] items
|
115
|
+
# A jquery compatible selector string that represents the items to filter
|
116
|
+
# @param [Hash] options
|
117
|
+
# HTML options passed to the input field
|
118
|
+
#
|
119
|
+
# @option options [String] :class ('js_filter_field')
|
120
|
+
# The css class of the <input> tag
|
121
|
+
# @option options [String or Hash] :data ({'alchemy-list-filter' => items})
|
122
|
+
# A HTML data attribute that holds the jQuery selector that represents the list to be filtered
|
86
123
|
#
|
87
124
|
def js_filter_field(items, options = {})
|
88
125
|
options = {
|
@@ -99,17 +136,28 @@ module Alchemy
|
|
99
136
|
|
100
137
|
# Returns a link that opens a modal confirmation to delete window.
|
101
138
|
#
|
102
|
-
# === Parameters:
|
103
|
-
#
|
104
|
-
# 1. The content inside the <a> tag
|
105
|
-
# 2. The message that is displayed in the overlay window
|
106
|
-
# 3. The url that gets opened after confirmation (Note: This is an Ajax request with a method of DELETE!)
|
107
|
-
# 4. html options get passed to the link
|
108
|
-
#
|
109
139
|
# === Example:
|
110
140
|
#
|
111
141
|
# <%= link_to_confirmation_window('delete', 'Do you really want to delete this comment?', '/admin/comments/1') %>
|
112
142
|
#
|
143
|
+
# @param [String] link_string
|
144
|
+
# The content inside the <a> tag
|
145
|
+
# @param [String] message
|
146
|
+
# The message that is displayed in the overlay window
|
147
|
+
# @param [String] url
|
148
|
+
# The url that gets opened after confirmation (Note: This is an Ajax request with a method of DELETE!)
|
149
|
+
# @param [Hash] html_options
|
150
|
+
# HTML options get passed to the link
|
151
|
+
#
|
152
|
+
# @option html_options [String] :title (_t(:please_confirm))
|
153
|
+
# The overlay title
|
154
|
+
# @option html_options [String] :message (message)
|
155
|
+
# The message displayed in the overlay
|
156
|
+
# @option html_options [String] :ok_label (_t("Yes"))
|
157
|
+
# The label for the ok button
|
158
|
+
# @option html_options [String] :cancel_label (_t("No"))
|
159
|
+
# The label for the cancel button
|
160
|
+
#
|
113
161
|
def link_to_confirmation_window(link_string = "", message = "", url = "", html_options = {})
|
114
162
|
link_to(link_string, url,
|
115
163
|
html_options.merge(
|
@@ -127,19 +175,21 @@ module Alchemy
|
|
127
175
|
#
|
128
176
|
# After confirmation it proceeds to send the form's action.
|
129
177
|
#
|
130
|
-
# === Parameters:
|
131
|
-
#
|
132
|
-
# 1. The content inside the <a> tag
|
133
|
-
# 2. The url that gets opened after confirmation
|
134
|
-
# 3. Options for the Alchemy confirm overlay (See: app/assets/javascripts/alchemy/alchemy.window.js#openConfirmWindow)
|
135
|
-
# 4. HTML options that get passed to the button_tag helper.
|
136
|
-
#
|
137
|
-
# NOTE: The method option in the html_options hash gets passed to the form_tag helper!
|
138
|
-
#
|
139
178
|
# === Example:
|
140
179
|
#
|
141
180
|
# <%= button_with_confirm('pay', '/admin/orders/1/pay', message: 'Do you really want to mark this order as payed?') %>
|
142
181
|
#
|
182
|
+
# @param [String] value
|
183
|
+
# The content inside the <tt><a></tt> tag
|
184
|
+
# @param [String] url
|
185
|
+
# The url that gets opened after confirmation
|
186
|
+
# @param [Hash] options
|
187
|
+
# Options for the Alchemy confirm overlay (see also +app/assets/javascripts/alchemy/alchemy.window.js#openConfirmWindow+)
|
188
|
+
# @param [Hash] html_options
|
189
|
+
# HTML options that get passed to the +button_tag+ helper.
|
190
|
+
#
|
191
|
+
# @note The method option in the <tt>html_options</tt> hash gets passed to the <tt>form_tag</tt> helper!
|
192
|
+
#
|
143
193
|
def button_with_confirm(value = "", url = "", options = {}, html_options = {})
|
144
194
|
options = {
|
145
195
|
message: _t(:confirm_to_proceed),
|
@@ -153,12 +203,15 @@ module Alchemy
|
|
153
203
|
end
|
154
204
|
|
155
205
|
# Returns an Array build for passing it to the options_for_select helper inside an essence editor partial.
|
156
|
-
# Usefull for the select_values options from the render_essence_editor helpers.
|
157
206
|
#
|
158
|
-
#
|
207
|
+
# Useful for the <tt>select_values</tt> options from the {Alchemy::Admin::EssencesHelper#render_essence_editor} helpers.
|
159
208
|
#
|
160
|
-
#
|
161
|
-
#
|
209
|
+
# @option options [String or Page] :from_page (nil)
|
210
|
+
# Return only elements from this page. You can either pass a Page instance, or a page_layout name
|
211
|
+
# @option options [Array or String] :elements_with_name (nil)
|
212
|
+
# Return only elements with this name(s).
|
213
|
+
# @option options [String] :prompt (_t('Please choose'))
|
214
|
+
# Prompt inside the select tag.
|
162
215
|
#
|
163
216
|
def elements_for_essence_editor_select(options={})
|
164
217
|
defaults = {
|
@@ -184,12 +237,14 @@ module Alchemy
|
|
184
237
|
|
185
238
|
# Returns all public pages from current language as an option tags string suitable or the Rails +select_tag+ helper.
|
186
239
|
#
|
187
|
-
#
|
188
|
-
#
|
189
|
-
#
|
190
|
-
#
|
191
|
-
#
|
192
|
-
#
|
240
|
+
# @param [Array]
|
241
|
+
# A collection of pages so it only returns these pages and does not query the database.
|
242
|
+
# @param [String]
|
243
|
+
# Pass a +Page#name+ or +Page#id+ as selected item to the +options_for_select+ helper.
|
244
|
+
# @param [String]
|
245
|
+
# Used as prompt message in the select tag
|
246
|
+
# @param [Symbol]
|
247
|
+
# Method that is called on the page object to get the value that is passed with the params of the form.
|
193
248
|
#
|
194
249
|
def pages_for_select(pages = nil, selected = nil, prompt = "", page_attribute = :id)
|
195
250
|
result = [[prompt.blank? ? _t('Choose page') : prompt, ""]]
|
@@ -223,6 +278,7 @@ module Alchemy
|
|
223
278
|
)
|
224
279
|
end
|
225
280
|
|
281
|
+
# Renders the admin main navigation
|
226
282
|
def admin_main_navigation
|
227
283
|
entries = ""
|
228
284
|
alchemy_modules.each do |alchemy_module|
|
@@ -231,10 +287,16 @@ module Alchemy
|
|
231
287
|
entries.html_safe
|
232
288
|
end
|
233
289
|
|
290
|
+
# Renders one admin main navigation entry
|
291
|
+
#
|
292
|
+
# @param [Hash] alchemy_module
|
293
|
+
# The Hash representing a Alchemy module
|
294
|
+
#
|
234
295
|
def alchemy_main_navigation_entry(alchemy_module)
|
235
296
|
render 'alchemy/admin/partials/main_navigation_entry', :alchemy_module => alchemy_module.stringify_keys, :navigation => alchemy_module['navigation'].stringify_keys
|
236
297
|
end
|
237
298
|
|
299
|
+
# Renders the subnavigation in the admin areas
|
238
300
|
def admin_subnavigation
|
239
301
|
alchemy_module = module_definition_for(:controller => params[:controller], :action => 'index')
|
240
302
|
unless alchemy_module.nil?
|
@@ -268,6 +330,7 @@ module Alchemy
|
|
268
330
|
end
|
269
331
|
end
|
270
332
|
|
333
|
+
# Returns true if the subnavigation entry is in the current params
|
271
334
|
def admin_sub_navigation_entry_active?(entry)
|
272
335
|
params[:controller] == entry["controller"].gsub(/^\//, '') && (params[:action] == entry["action"] || entry["nested_actions"] && entry["nested_actions"].include?(params[:action]))
|
273
336
|
end
|
@@ -351,18 +414,26 @@ module Alchemy
|
|
351
414
|
|
352
415
|
# Renders a toolbar button for the Alchemy toolbar
|
353
416
|
#
|
354
|
-
#
|
355
|
-
#
|
356
|
-
#
|
357
|
-
#
|
358
|
-
#
|
359
|
-
#
|
360
|
-
#
|
361
|
-
#
|
362
|
-
#
|
363
|
-
#
|
364
|
-
#
|
365
|
-
#
|
417
|
+
# @option options [String] :icon
|
418
|
+
# Icon class. See +app/assets/stylesheets/alchemy/icons.css.sccs+ for available icons, or make your own.
|
419
|
+
# @option options [String] :label
|
420
|
+
# Text for button label.
|
421
|
+
# @option options [String] :url
|
422
|
+
# Url for link.
|
423
|
+
# @option options [String] :title
|
424
|
+
# Text for title tag.
|
425
|
+
# @option options [String] :hotkey
|
426
|
+
# Keyboard shortcut for this button. I.E +alt-n+
|
427
|
+
# @option options [Boolean] :overlay (true)
|
428
|
+
# Open the link in a modal overlay window.
|
429
|
+
# @option options [Hash] :overlay_options
|
430
|
+
# Overlay options. See link_to_overlay_window helper.
|
431
|
+
# @option options [Array] :if_permitted_to ([:action, :controller])
|
432
|
+
# Check permission for button. Exactly how you defined the permission in your +authorization_rules.rb+. Defaults to controller and action from button url.
|
433
|
+
# @option options [Boolean] :skip_permission_check (false)
|
434
|
+
# Skip the permission check. NOT RECOMMENDED!
|
435
|
+
# @option options [Boolean] :loading_indicator (true)
|
436
|
+
# Shows the please wait overlay while loading. Only for buttons not opening an overlay window.
|
366
437
|
#
|
367
438
|
def toolbar_button(options = {})
|
368
439
|
options.symbolize_keys!
|
@@ -409,12 +480,32 @@ module Alchemy
|
|
409
480
|
end
|
410
481
|
end
|
411
482
|
|
412
|
-
# Renders the
|
483
|
+
# Renders the toolbar shown on top of the records.
|
413
484
|
#
|
414
|
-
# ==
|
485
|
+
# == Example
|
415
486
|
#
|
416
|
-
#
|
417
|
-
#
|
487
|
+
# <% label_title = _t("Create #{resource_name}", default: _t('Create')) %>
|
488
|
+
# <% toolbar(
|
489
|
+
# buttons: [
|
490
|
+
# {
|
491
|
+
# icon: 'create',
|
492
|
+
# label: label_title,
|
493
|
+
# url: new_resource_path,
|
494
|
+
# title: label_title,
|
495
|
+
# hotkey: 'alt-n',
|
496
|
+
# overlay_options: {
|
497
|
+
# title: label_title,
|
498
|
+
# size: "430x400"
|
499
|
+
# },
|
500
|
+
# if_permitted_to: [:new, resource_permission_scope]
|
501
|
+
# }
|
502
|
+
# ]
|
503
|
+
# ) %>
|
504
|
+
#
|
505
|
+
# @option options [Array] :buttons ([])
|
506
|
+
# Pass an Array with button options. They will be passed to {#toolbar_button} helper.
|
507
|
+
# @option options [Boolean] :search (true)
|
508
|
+
# Show searchfield.
|
418
509
|
#
|
419
510
|
def toolbar(options = {})
|
420
511
|
defaults = {
|
@@ -467,14 +558,24 @@ module Alchemy
|
|
467
558
|
|
468
559
|
# Renders a textfield ready to display a datepicker
|
469
560
|
#
|
470
|
-
# Uses a HTML5
|
471
|
-
#
|
472
|
-
# Pass a type as third option to override that. But old browsers hand this as text field anyway. So there is no need to override that.
|
561
|
+
# Uses a HTML5 <tt><input type="date"></tt> field.
|
473
562
|
#
|
474
563
|
# === Example
|
475
564
|
#
|
476
565
|
# <%= alchemy_datepicker(@person, :birthday) %>
|
477
566
|
#
|
567
|
+
# @param [ActiveModel::Base] object
|
568
|
+
# An instance of a model
|
569
|
+
# @param [String or Symbol] method
|
570
|
+
# The attribute method to be called for the date value
|
571
|
+
#
|
572
|
+
# @option html_options [String] :type ('date')
|
573
|
+
# The type of text field
|
574
|
+
# @option html_options [String] :class ('thin_border date')
|
575
|
+
# CSS classes of the input field
|
576
|
+
# @option html_options [String] :value (object.send(method.to_sym).nil? ? nil : l(object.send(method.to_sym), :format => :datepicker))
|
577
|
+
# The value the input displays
|
578
|
+
#
|
478
579
|
def alchemy_datepicker(object, method, html_options={})
|
479
580
|
text_field(object.class.name.underscore.to_sym, method.to_sym, {
|
480
581
|
:type => 'date',
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module Alchemy
|
2
2
|
module Admin
|
3
3
|
module PagesHelper
|
4
|
+
include Alchemy::BaseHelper
|
4
5
|
|
5
6
|
def tinymce_javascript_tags
|
6
7
|
init = Alchemy::Tinymce.init
|
@@ -99,7 +100,9 @@ module Alchemy
|
|
99
100
|
# Returns the translated explanation of the page´s status.
|
100
101
|
#
|
101
102
|
def combined_page_status(page)
|
102
|
-
|
103
|
+
page.status.map do |state, value|
|
104
|
+
page.status_title(state)
|
105
|
+
end.delete_if(&:blank?).join("<br>").html_safe
|
103
106
|
end
|
104
107
|
|
105
108
|
end
|
@@ -99,7 +99,7 @@ module Alchemy
|
|
99
99
|
#
|
100
100
|
# @option options :tag (:div)
|
101
101
|
# The HTML tag to be used for the wrapping element.
|
102
|
-
# @option options :id (the element's
|
102
|
+
# @option options :id (the element's dom_id)
|
103
103
|
# The wrapper tag's DOM ID.
|
104
104
|
# @option options :class (the element's essence name)
|
105
105
|
# The wrapper tag's DOM class.
|
@@ -1,30 +1,75 @@
|
|
1
1
|
module Alchemy
|
2
|
+
# This helpers are useful to render elements from pages.
|
3
|
+
#
|
4
|
+
# The most important helper for frontend developers is the {#render_elements} helper.
|
5
|
+
#
|
2
6
|
module ElementsHelper
|
3
|
-
|
4
7
|
include Alchemy::EssencesHelper
|
5
8
|
include Alchemy::UrlHelper
|
6
9
|
include Alchemy::ElementsBlockHelper
|
7
10
|
|
8
|
-
# Renders all elements from current page
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
# :
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
11
|
+
# Renders all elements from current page
|
12
|
+
#
|
13
|
+
# == Examples:
|
14
|
+
#
|
15
|
+
# === Render only certain elements:
|
16
|
+
#
|
17
|
+
# <header>
|
18
|
+
# <%= render_elements only: ['header', 'claim'] %>
|
19
|
+
# </header>
|
20
|
+
# <section id="content">
|
21
|
+
# <%= render_elements except: ['header', 'claim'] %>
|
22
|
+
# </section>
|
23
|
+
#
|
24
|
+
# === Render elements from global page:
|
25
|
+
#
|
26
|
+
# <footer>
|
27
|
+
# <%= render_elements from_page: 'footer' %>
|
28
|
+
# </footer>
|
29
|
+
#
|
30
|
+
# === Render elements from cell:
|
31
|
+
#
|
32
|
+
# <aside>
|
33
|
+
# <%= render_elements from_cell: 'sidebar' %>
|
34
|
+
# </aside>
|
35
|
+
#
|
36
|
+
# === Fallback to elements from global page:
|
37
|
+
#
|
38
|
+
# You can use the fallback option as an override for elements that are stored on another page.
|
39
|
+
# So you can take elements from a global page and only if the user adds an element on current page the
|
40
|
+
# local one gets rendered.
|
41
|
+
#
|
42
|
+
# 1. You have to pass the the name of the element the fallback is for as <tt>for</tt> key.
|
43
|
+
# 2. You have to pass a <tt>page_layout</tt> name or {Alchemy::Page} from where the fallback elements is taken from as <tt>from</tt> key.
|
44
|
+
# 3. You can pass the name of element to fallback with as <tt>with</tt> key. This is optional (the element name from the <tt>for</tt> key is taken as default).
|
45
|
+
#
|
46
|
+
# <%= render_elements(fallback: {
|
47
|
+
# for: 'contact_teaser',
|
48
|
+
# from: 'sidebar',
|
49
|
+
# with: 'contact_teaser'
|
50
|
+
# }) %>
|
51
|
+
#
|
52
|
+
# @param [Hash] options
|
53
|
+
# Additional options.
|
54
|
+
#
|
55
|
+
# @option options [Number] :count
|
56
|
+
# The amount of elements to be rendered (begins with first element found)
|
57
|
+
# @option options [Array or String] :except ([])
|
58
|
+
# A list of element names not to be rendered.
|
59
|
+
# @option options [Hash] :fallback
|
60
|
+
# Define elements that are rendered from another page.
|
61
|
+
# @option options [Alchemy::Cell or String] :from_cell
|
62
|
+
# The cell the elements are rendered from. You can pass a {Alchemy::Cell} name String or a {Alchemy::Cell} object.
|
63
|
+
# @option options [Alchemy::Page or String] :from_page (@page)
|
64
|
+
# The page the elements are rendered from. You can pass a page_layout String or a {Alchemy::Page} object.
|
65
|
+
# @option options [Array or String] :only ([])
|
66
|
+
# A list of element names only to be rendered.
|
67
|
+
# @option options [Boolean] :random
|
68
|
+
# Randomize the output of elements
|
69
|
+
# @option options [Boolean] :reverse
|
70
|
+
# Reverse the rendering order
|
71
|
+
# @option options [String] :sort_by
|
72
|
+
# The name of a {Alchemy::Content} to sort the elements by
|
28
73
|
#
|
29
74
|
def render_elements(options = {})
|
30
75
|
default_options = {
|
@@ -76,26 +121,69 @@ module Alchemy
|
|
76
121
|
end
|
77
122
|
end
|
78
123
|
|
79
|
-
# This helper renders
|
80
|
-
#
|
81
|
-
|
124
|
+
# This helper renders a {Alchemy::Element} partial.
|
125
|
+
#
|
126
|
+
# A element has always two partials:
|
127
|
+
#
|
128
|
+
# 1. A view partial (This is the view presented to the website visitor)
|
129
|
+
# 2. A editor partial (This is the form presented to the website editor while in page edit mode)
|
130
|
+
#
|
131
|
+
# The partials are located in <tt>app/views/alchemy/elements</tt>.
|
132
|
+
#
|
133
|
+
# == View partial naming
|
134
|
+
#
|
135
|
+
# The partials have to be named after the name of the element as defined in the <tt>elements.yml</tt> file and has to be suffixed with the partial part.
|
136
|
+
#
|
137
|
+
# === Example
|
138
|
+
#
|
139
|
+
# Given a headline element
|
140
|
+
#
|
141
|
+
# # elements.yml
|
142
|
+
# - name: headline
|
143
|
+
# contents:
|
144
|
+
# - name: text
|
145
|
+
# type: EssenceText
|
146
|
+
#
|
147
|
+
# Then your element view partials has to be named like:
|
148
|
+
#
|
149
|
+
# app/views/alchemy/elements/_headline_editor.html.erb
|
150
|
+
# app/views/alchemy/elements/_headline_view.html.erb
|
151
|
+
#
|
152
|
+
# === Element partials generator
|
153
|
+
#
|
154
|
+
# You can use this handy generator to let Alchemy generate the partials for you:
|
155
|
+
#
|
156
|
+
# $ rails generate alchemy:elements --skip
|
157
|
+
#
|
158
|
+
# == Usage
|
159
|
+
#
|
160
|
+
# <%= render_element(Alchemy::Element.published.named(:headline).first) %>
|
161
|
+
#
|
162
|
+
# @param [Alchemy::Element] element
|
163
|
+
# The element you want to render the view for
|
164
|
+
# @param [Symbol] part
|
165
|
+
# The type of element partial (<tt>:editor</tt> or <tt>:view</tt>) you want to render
|
166
|
+
# @param [Hash] options
|
167
|
+
# Additional options
|
168
|
+
# @param [Number] counter
|
169
|
+
# a counter
|
170
|
+
#
|
171
|
+
# @note If the view partial is not found <tt>alchemy/elements/_view_not_found.html.erb</tt> or <tt>alchemy/elements/_editor_not_found.html.erb</tt> gets rendered.
|
172
|
+
#
|
173
|
+
def render_element(element, part = :view, options = {}, counter = 1)
|
82
174
|
begin
|
83
175
|
if element.blank?
|
84
176
|
warning('Element is nil')
|
85
177
|
render :partial => "alchemy/elements/#{part}_not_found", :locals => {:name => 'nil'}
|
86
178
|
else
|
87
|
-
default_options = {
|
88
|
-
:shorten_to => nil
|
89
|
-
}
|
90
|
-
options = default_options.merge(options)
|
91
179
|
element.store_page(@page) if part == :view
|
92
180
|
locals = options.delete(:locals)
|
93
181
|
render(
|
94
182
|
:partial => "alchemy/elements/#{element.name.underscore}_#{part}",
|
95
183
|
:locals => {
|
96
184
|
:element => element,
|
97
|
-
:
|
98
|
-
:
|
185
|
+
:counter => counter,
|
186
|
+
:options => options
|
99
187
|
}.merge(locals || {})
|
100
188
|
)
|
101
189
|
end
|
@@ -189,7 +277,7 @@ module Alchemy
|
|
189
277
|
|
190
278
|
# Returns the element's tags information as an attribute hash.
|
191
279
|
#
|
192
|
-
# @param [Alchemy::Element] element The
|
280
|
+
# @param [Alchemy::Element] element The {Alchemy::Element} you want to render the tags from.
|
193
281
|
#
|
194
282
|
# @option options [Proc] :formatter
|
195
283
|
# ('lambda { |tags| tags.join(' ') }')
|