alchemy_cms 2.6.0.rc5 → 2.6.0

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 (86) hide show
  1. data/.travis.yml +1 -1
  2. data/Gemfile +2 -1
  3. data/README.md +2 -4
  4. data/alchemy_cms.gemspec +1 -1
  5. data/app/assets/fonts/alchemy/icons.eot +0 -0
  6. data/app/assets/fonts/alchemy/icons.svg +71 -0
  7. data/app/assets/fonts/alchemy/icons.ttf +0 -0
  8. data/app/assets/fonts/alchemy/icons.woff +0 -0
  9. data/app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee +6 -8
  10. data/app/assets/javascripts/alchemy/alchemy.hotkeys.js.coffee +2 -3
  11. data/app/assets/javascripts/alchemy/alchemy.image_cropper.js.coffee +3 -8
  12. data/app/assets/javascripts/alchemy/alchemy.link_overlay.js.coffee +3 -3
  13. data/app/assets/javascripts/alchemy/alchemy.preview_window.js.coffee +19 -9
  14. data/app/assets/javascripts/tiny_mce/plugins/alchemy_link/editor_plugin.js +6 -7
  15. data/app/assets/stylesheets/alchemy/admin.css.scss +0 -1
  16. data/app/assets/stylesheets/alchemy/archive.scss +55 -7
  17. data/app/assets/stylesheets/alchemy/base.scss +8 -144
  18. data/app/assets/stylesheets/alchemy/defaults.scss +1 -1
  19. data/app/assets/stylesheets/alchemy/elements.scss +20 -16
  20. data/app/assets/stylesheets/alchemy/flash.scss +1 -1
  21. data/app/assets/stylesheets/alchemy/form_elements.scss +49 -42
  22. data/app/assets/stylesheets/alchemy/icon-font.css.scss +67 -0
  23. data/app/assets/stylesheets/alchemy/icons.scss +16 -4
  24. data/app/assets/stylesheets/alchemy/jquery-ui.scss +40 -26
  25. data/app/assets/stylesheets/alchemy/menubar.css.scss +1 -1
  26. data/app/assets/stylesheets/alchemy/notices.scss +6 -1
  27. data/app/assets/stylesheets/alchemy/search.scss +3 -2
  28. data/app/assets/stylesheets/alchemy/sitemap.scss +72 -13
  29. data/app/assets/stylesheets/alchemy/tables.scss +31 -24
  30. data/app/assets/stylesheets/alchemy/upload.scss +1 -1
  31. data/app/assets/stylesheets/alchemy/variables.scss +2 -1
  32. data/app/assets/stylesheets/tiny_mce/plugins/inlinepopups/skins/{alchemy → alchemy-tinymce-dialog}/window.css.scss +70 -65
  33. data/app/controllers/alchemy/admin/base_controller.rb +7 -4
  34. data/app/controllers/alchemy/admin/pictures_controller.rb +2 -0
  35. data/app/controllers/alchemy/admin/users_controller.rb +1 -1
  36. data/app/controllers/alchemy/user_sessions_controller.rb +1 -1
  37. data/app/helpers/alchemy/admin/base_helper.rb +161 -60
  38. data/app/helpers/alchemy/admin/pages_helper.rb +4 -1
  39. data/app/helpers/alchemy/elements_block_helper.rb +1 -1
  40. data/app/helpers/alchemy/elements_helper.rb +119 -31
  41. data/app/helpers/alchemy/pages_helper.rb +29 -72
  42. data/app/models/alchemy/attachment.rb +0 -2
  43. data/app/models/alchemy/content.rb +1 -1
  44. data/app/models/alchemy/language.rb +1 -0
  45. data/app/models/alchemy/page.rb +8 -8
  46. data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +3 -1
  47. data/app/views/alchemy/admin/attachments/_overlay_file_list.html.erb +1 -1
  48. data/app/views/alchemy/admin/attachments/_tag_list.html.erb +25 -27
  49. data/app/views/alchemy/admin/attachments/index.html.erb +4 -1
  50. data/app/views/alchemy/admin/elements/_elements_select.html.erb +6 -6
  51. data/app/views/alchemy/admin/elements/list.js.erb +1 -1
  52. data/app/views/alchemy/admin/pages/_page.html.erb +1 -1
  53. data/app/views/alchemy/admin/pages/_page_for_links.html.erb +1 -1
  54. data/app/views/alchemy/admin/pages/edit.html.erb +4 -2
  55. data/app/views/alchemy/admin/pictures/_archive.html.erb +0 -1
  56. data/app/views/alchemy/admin/pictures/_filter_bar.html.erb +2 -1
  57. data/app/views/alchemy/admin/pictures/_picture.html.erb +5 -0
  58. data/app/views/alchemy/admin/pictures/index.html.erb +1 -0
  59. data/app/views/alchemy/base/500.html.erb +26 -5
  60. data/app/views/alchemy/essences/_essence_picture_tools.html.erb +1 -1
  61. data/app/views/alchemy/essences/_linkable_essence_tools.html.erb +1 -1
  62. data/app/views/alchemy/language_links/_language.html.erb +12 -0
  63. data/app/views/alchemy/language_links/_spacer.html.erb +1 -0
  64. data/config/locales/alchemy.de.yml +7 -3
  65. data/config/locales/alchemy.en.yml +8 -3
  66. data/lib/alchemy/page_layout.rb +1 -1
  67. data/lib/alchemy/tinymce.rb +1 -1
  68. data/lib/alchemy/upgrader.rb +26 -0
  69. data/lib/alchemy/version.rb +1 -1
  70. data/lib/rails/generators/alchemy/scaffold/scaffold_generator.rb +4 -1
  71. data/lib/tasks/ferret.rake +1 -0
  72. data/spec/controllers/admin/users_controller_spec.rb +5 -5
  73. data/spec/features/admin/pages_controller_spec.rb +1 -1
  74. data/spec/helpers/admin/pages_helper_spec.rb +31 -0
  75. data/spec/helpers/pages_helper_spec.rb +60 -72
  76. data/spec/models/content_spec.rb +2 -1
  77. data/spec/models/page_layout_spec.rb +29 -0
  78. data/spec/models/page_spec.rb +33 -1
  79. data/spec/support/alchemy/test_tweaks.rb +2 -6
  80. metadata +34 -12
  81. data/app/assets/fonts/alchemy-icons.eot +0 -0
  82. data/app/assets/fonts/alchemy-icons.svg +0 -54
  83. data/app/assets/fonts/alchemy-icons.ttf +0 -0
  84. data/app/assets/fonts/alchemy-icons.woff +0 -0
  85. data/app/assets/images/alchemy/placeholder.png +0 -0
  86. 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
- # truncate the message, because very long error messages (i.e from mysql2) causes cookie oveflow errors
28
- @notice = "Error: #{e.message[0..255]}"
29
- @trace = e.backtrace
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(:role) unless permitted_to?(:update_role)
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 for an overlay window.
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
- # === Options:
20
+ # == Example
21
21
  #
22
- # :size [String] # String with format of "WidthxHeight". I.E. ("420x280")
23
- # :title [String] # Text for the overlay title bar.
24
- # :overflow [Boolean] # Should the dialog have overlapping content. If not, it shows scrollbars. Good for select boxes. Default false.
25
- # :resizable [Boolean] # Is the dialog window resizable? Default false.
26
- # :modal [Boolean] # Show as modal window. Default true.
27
- # :overflow [Boolean] # Should the window show overflowing content? Default true.
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
- # Used by Alchemy to display a javascript driven filter for lists.
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
- # @param [String] a jquery compatible selector string that represents the items to filter
85
- # @param [Hash] html options passed to the input field
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
- # == Options:
207
+ # Useful for the <tt>select_values</tt> options from the {Alchemy::Admin::EssencesHelper#render_essence_editor} helpers.
159
208
  #
160
- # :from_page [String, Page] # Return only elements from this page. You can either pass a Page instance, or a page_layout name
161
- # :elements_with_name [Array, String] # Return only elements with this name(s).
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
- # === Parameters
188
- #
189
- # 1. A collection of pages so it only returns these pages and does not query the database.
190
- # 2. Pass a +Page#name+ or +Page#id+ as second parameter to be passed as selected item to the +options_for_select+ helper.
191
- # 3. The third parameter is used as prompt message in the select tag
192
- # 4. The fourth parameter is the method that is called on the page object to get the value that is passed with the params of the form.
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
- # == Options:
355
- #
356
- # :icon [String] # Icon class. See base.css.sccs for available icons, or make your own.
357
- # :label [String] # Text for button label.
358
- # :url [String] # Url for link.
359
- # :title [String] # Text for title tag.
360
- # :hotkey [String] # Keyboard shortcut for this button. I.E 'alt-n'
361
- # :overlay [Boolean] # Pass true to open the link in a modal overlay window.
362
- # :overlay_options [Hash] # Overlay options. See link_to_overlay_window helper.
363
- # :if_permitted_to [Array] # Check permission for button. [:action, :controller]. Exactly how you defined the permission in your +authorization_rules.rb+. Defaults to controller and action from button url.
364
- # :skip_permission_check [Boolean] # Skip the permission check. Default false. NOT RECOMMENDED!
365
- # :loading_indicator [Boolean] # Shows the please wait overlay while loading. Only for buttons not opening an overlay window. Default true.
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 Alchemy backend toolbar
483
+ # Renders the toolbar shown on top of the records.
413
484
  #
414
- # == Options
485
+ # == Example
415
486
  #
416
- # :buttons [Array] # Pass an Array with button options. They will be passed to toolbar_button helper. For options see toolbar_button
417
- # :search [Boolean] # Show searchfield. Default true.
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 +input type="date"+ field.
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
- _t(page.status.to_a.map{ |k, v| "#{k}.#{v}" }.flatten, :scope => "page_states").delete_if(&:blank?).join("<br>").html_safe
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 ID)
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
- # === Options are:
11
- #
12
- # :only => [] # A list of element names to be rendered only. Very useful if you want to render a specific element type in a special html part (e.g.. <div>) of your page and all other elements in another part.
13
- # :except => [] # A list of element names to be rendered. The opposite of the only option.
14
- # :from_page => @page # The Alchemy::Page.page_layout string from which the elements are rendered from, or you even pass a Page object.
15
- # :from_cell => nil # The Cell object from which the elements are rendered from.
16
- # :count => nil # The amount of elements to be rendered (begins with first element found)
17
- # :fallback => { # You can use the fallback option as an override. So you can take elements from a glo´bal laout page and only if the user adds an element on current page the local one gets rendered.
18
- # :for => 'ELEMENT_NAME', # The name of the element the fallback is for
19
- # :with => 'ELEMENT_NAME', # (OPTIONAL) the name of element to fallback with
20
- # :from => String || Page # Pass a page_layout name from a page the fallback elements lie on or pass the page object.
21
- # } #
22
- # :sort_by => Content#name # A Content name to sort the elements by
23
- # :reverse => boolean # Reverse the rendering order
24
- # :random => boolean # Randomize the output of elements
25
- #
26
- # === Note:
27
- # This helper also stores all pages where elements gets rendered on, so we can sweep them later if caching expires!
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 the Element partial for either the view or the editor part.
80
- # Generate element partials with rails generate alchemy:elements
81
- def render_element(element, part = :view, options = {}, i = 1)
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
- :options => options,
98
- :counter => i
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 element.
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(' ') }')