alchemy_cms 2.6.3 → 2.7.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 (246) hide show
  1. checksums.yaml +4 -4
  2. data/.simplecov +14 -0
  3. data/.travis.yml +1 -1
  4. data/Gemfile +7 -6
  5. data/README.md +15 -5
  6. data/alchemy_cms.gemspec +3 -2
  7. data/app/assets/javascripts/alchemy/alchemy.base.js.coffee +9 -17
  8. data/app/assets/javascripts/alchemy/alchemy.dirty.js.coffee +70 -0
  9. data/app/assets/javascripts/alchemy/alchemy.dragndrop.js.coffee +80 -0
  10. data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +43 -19
  11. data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +3 -1
  12. data/app/assets/javascripts/alchemy/alchemy.js +4 -2
  13. data/app/assets/javascripts/alchemy/alchemy.onload.js.coffee +1 -1
  14. data/app/assets/javascripts/alchemy/alchemy.spinner.js.coffee +14 -0
  15. data/app/assets/javascripts/alchemy/alchemy.tinymce.js.coffee.erb +96 -0
  16. data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +22 -0
  17. data/app/assets/javascripts/alchemy/alchemy.windows.js.coffee +28 -17
  18. data/app/assets/stylesheets/alchemy/base.scss +6 -0
  19. data/app/assets/stylesheets/alchemy/elements.scss +2 -28
  20. data/app/assets/stylesheets/alchemy/errors.scss +1 -1
  21. data/app/assets/stylesheets/alchemy/menubar.css.scss +2 -0
  22. data/app/assets/stylesheets/alchemy/sitemap.scss +21 -34
  23. data/app/assets/stylesheets/alchemy/tables.scss +13 -3
  24. data/app/controllers/alchemy/admin/attachments_controller.rb +10 -5
  25. data/app/controllers/alchemy/admin/base_controller.rb +19 -0
  26. data/app/controllers/alchemy/admin/contents_controller.rb +1 -4
  27. data/app/controllers/alchemy/admin/dashboard_controller.rb +2 -1
  28. data/app/controllers/alchemy/admin/elements_controller.rb +1 -1
  29. data/app/controllers/alchemy/admin/essence_files_controller.rb +1 -1
  30. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +70 -56
  31. data/app/controllers/alchemy/admin/pages_controller.rb +37 -114
  32. data/app/controllers/alchemy/admin/pictures_controller.rb +5 -12
  33. data/app/controllers/alchemy/admin/resources_controller.rb +3 -1
  34. data/app/controllers/alchemy/admin/trash_controller.rb +1 -1
  35. data/app/controllers/alchemy/attachments_controller.rb +1 -1
  36. data/app/controllers/alchemy/base_controller.rb +3 -15
  37. data/app/controllers/alchemy/messages_controller.rb +4 -10
  38. data/app/controllers/alchemy/pages_controller.rb +6 -6
  39. data/app/controllers/alchemy/passwords_controller.rb +1 -1
  40. data/app/controllers/alchemy/user_sessions_controller.rb +1 -1
  41. data/app/helpers/alchemy/admin/base_helper.rb +49 -230
  42. data/app/helpers/alchemy/admin/contents_helper.rb +5 -1
  43. data/app/helpers/alchemy/admin/elements_helper.rb +19 -47
  44. data/app/helpers/alchemy/admin/essences_helper.rb +59 -17
  45. data/app/helpers/alchemy/admin/navigation_helper.rb +204 -0
  46. data/app/helpers/alchemy/admin/pages_helper.rb +22 -79
  47. data/app/helpers/alchemy/admin/pictures_helper.rb +1 -1
  48. data/app/helpers/alchemy/admin/tags_helper.rb +42 -0
  49. data/app/helpers/alchemy/base_helper.rb +0 -11
  50. data/app/helpers/alchemy/elements_helper.rb +48 -25
  51. data/app/helpers/alchemy/essences_helper.rb +0 -20
  52. data/app/helpers/alchemy/pages_helper.rb +18 -14
  53. data/app/helpers/alchemy/url_helper.rb +1 -0
  54. data/app/mailers/alchemy/messages.rb +4 -6
  55. data/app/models/alchemy/attachment.rb +3 -0
  56. data/app/models/alchemy/cell.rb +33 -35
  57. data/app/models/alchemy/content.rb +20 -111
  58. data/app/models/alchemy/content/factory.rb +188 -0
  59. data/app/models/alchemy/element.rb +51 -200
  60. data/app/models/alchemy/element/definitions.rb +52 -0
  61. data/app/models/alchemy/element/presenters.rb +87 -0
  62. data/app/models/alchemy/essence_date.rb +1 -1
  63. data/app/models/alchemy/essence_file.rb +6 -7
  64. data/app/models/alchemy/essence_picture.rb +19 -4
  65. data/app/models/alchemy/message.rb +18 -14
  66. data/app/models/alchemy/page.rb +120 -214
  67. data/app/models/alchemy/page/elements.rb +145 -36
  68. data/app/models/alchemy/page/natures.rb +90 -0
  69. data/app/models/alchemy/page/scopes.rb +93 -0
  70. data/app/models/alchemy/page/users.rb +25 -0
  71. data/app/models/alchemy/picture.rb +15 -0
  72. data/app/models/alchemy/site.rb +15 -1
  73. data/app/models/alchemy/site/layout.rb +38 -0
  74. data/app/models/alchemy/user.rb +13 -3
  75. data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +7 -7
  76. data/app/views/alchemy/admin/attachments/_file_to_assign.html.erb +8 -8
  77. data/app/views/alchemy/admin/attachments/_tag_list.html.erb +1 -16
  78. data/app/views/alchemy/admin/attachments/destroy.js.erb +1 -4
  79. data/app/views/alchemy/admin/contents/create.js.erb +1 -1
  80. data/app/views/alchemy/admin/dashboard/index.html.erb +14 -13
  81. data/app/views/alchemy/admin/elements/_element_head.html.erb +7 -7
  82. data/app/views/alchemy/admin/elements/_refresh_editor.js.erb +10 -0
  83. data/app/views/alchemy/admin/elements/create.js.erb +44 -44
  84. data/app/views/alchemy/admin/elements/fold.js.erb +22 -26
  85. data/app/views/alchemy/admin/elements/trash.js.erb +1 -1
  86. data/app/views/alchemy/admin/elements/update.js.erb +22 -25
  87. data/app/views/alchemy/admin/essence_files/assign.js.erb +8 -3
  88. data/app/views/alchemy/admin/essence_pictures/crop.html.erb +14 -12
  89. data/app/views/alchemy/admin/essence_pictures/edit.html.erb +22 -39
  90. data/app/views/alchemy/admin/pages/_page.html.erb +73 -80
  91. data/app/views/alchemy/admin/pages/destroy.js.erb +2 -2
  92. data/app/views/alchemy/admin/pages/edit.html.erb +21 -18
  93. data/app/views/alchemy/admin/pages/fold.js.erb +1 -0
  94. data/app/views/alchemy/admin/pages/info.html.erb +32 -0
  95. data/app/views/alchemy/admin/partials/_main_navigation_entry.html.erb +11 -13
  96. data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +20 -20
  97. data/app/views/alchemy/admin/partials/_sub_navigation.html.erb +8 -0
  98. data/app/views/alchemy/admin/partials/_toolbar_button.html.erb +25 -0
  99. data/app/views/alchemy/admin/partials/_upload_form.html.erb +15 -15
  100. data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +39 -39
  101. data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +10 -10
  102. data/app/views/alchemy/admin/pictures/_tag_list.html.erb +1 -16
  103. data/app/views/alchemy/admin/resources/destroy.js.erb +1 -1
  104. data/app/views/alchemy/base/500.html.erb +1 -1
  105. data/app/views/alchemy/base/permission_denied.js.erb +1 -1
  106. data/app/views/alchemy/base/redirect.js.erb +1 -1
  107. data/app/views/alchemy/essences/_essence_link_editor.html.erb +1 -1
  108. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +1 -1
  109. data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +1 -1
  110. data/app/views/alchemy/essences/_essence_text_editor.html.erb +1 -1
  111. data/app/views/alchemy/essences/{_essence_picture_tools.html.erb → shared/_essence_picture_tools.html.erb} +5 -5
  112. data/app/views/alchemy/essences/{_linkable_essence_tools.html.erb → shared/_linkable_essence_tools.html.erb} +0 -0
  113. data/app/views/alchemy/messages/contact_form_mail.de.text.erb +12 -0
  114. data/app/views/alchemy/messages/contact_form_mail.en.text.erb +12 -0
  115. data/app/views/alchemy/notifications/reset_password_instructions.de.text.erb +1 -1
  116. data/app/views/alchemy/notifications/reset_password_instructions.en.text.erb +2 -2
  117. data/app/views/alchemy/pages/sitemap.xml.erb +3 -5
  118. data/app/views/alchemy/user_sessions/leave.html.erb +1 -1
  119. data/app/views/layouts/alchemy/admin.html.erb +4 -2
  120. data/app/views/layouts/alchemy/sitemap.xml.erb +1 -1
  121. data/bin/alchemy +7 -13
  122. data/config/alchemy/config.yml +1 -0
  123. data/config/authorization_rules.rb +2 -3
  124. data/config/initializers/dragonfly.rb +2 -0
  125. data/config/locales/alchemy.de.yml +8 -9
  126. data/config/locales/alchemy.en.yml +7 -4
  127. data/config/routes.rb +3 -0
  128. data/db/migrate/{20130214233001_alchemy_two_point_five.rb → 20130827094554_alchemy_two_point_six.rb} +29 -6
  129. data/lib/alchemy/auth/engine.rb +9 -0
  130. data/lib/alchemy/capistrano.rb +37 -12
  131. data/lib/alchemy/config.rb +48 -35
  132. data/lib/alchemy/engine.rb +35 -6
  133. data/lib/alchemy/essence.rb +25 -29
  134. data/lib/alchemy/ferret/search.rb +86 -0
  135. data/lib/alchemy/{scoped_pagination_url_helper.rb → kaminari/scoped_pagination_url_helper.rb} +0 -0
  136. data/lib/alchemy/logger.rb +3 -4
  137. data/lib/alchemy/page_layout.rb +124 -55
  138. data/lib/alchemy/resource.rb +0 -10
  139. data/lib/alchemy/resources_helper.rb +0 -5
  140. data/lib/alchemy/seeder.rb +1 -32
  141. data/lib/alchemy/shell.rb +6 -1
  142. data/lib/alchemy/tinymce.rb +41 -32
  143. data/lib/alchemy/upgrader.rb +3 -1
  144. data/lib/alchemy/upgrader/two_point_five.rb +15 -8
  145. data/lib/alchemy/upgrader/two_point_one.rb +10 -10
  146. data/lib/alchemy/upgrader/two_point_two.rb +96 -51
  147. data/lib/alchemy/version.rb +1 -1
  148. data/lib/alchemy_cms.rb +5 -46
  149. data/lib/rails/generators/alchemy/deploy_script/templates/deploy.rb.tt +1 -1
  150. data/lib/rails/generators/alchemy/devise/devise_generator.rb +9 -4
  151. data/lib/rails/generators/alchemy/essence/essence_generator.rb +7 -6
  152. data/lib/rails/generators/alchemy/essence/templates/editor.html.erb +1 -1
  153. data/lib/rails/generators/alchemy/scaffold/files/_standard.html.erb +1 -0
  154. data/lib/rails/generators/alchemy/scaffold/scaffold_generator.rb +1 -0
  155. data/lib/rails/generators/alchemy/site_layouts/site_layouts_generator.rb +23 -0
  156. data/lib/rails/generators/alchemy/site_layouts/templates/layout.html.erb +1 -0
  157. data/lib/rails/generators/alchemy/site_layouts/templates/layout.html.haml +1 -0
  158. data/lib/rails/generators/alchemy/site_layouts/templates/layout.html.slim +1 -0
  159. data/lib/rails/templates/alchemy.rb +2 -2
  160. data/lib/tasks/alchemy/db.rake +3 -1
  161. data/lib/tasks/alchemy/tidy.rake +82 -0
  162. data/lib/tasks/alchemy/upgrade.rake +2 -1
  163. data/spec/controllers/admin/attachments_controller_spec.rb +124 -0
  164. data/spec/controllers/admin/base_controller_spec.rb +35 -0
  165. data/spec/controllers/admin/clipboard_controller_spec.rb +1 -1
  166. data/spec/controllers/admin/contents_controller_spec.rb +17 -26
  167. data/spec/controllers/admin/dashboard_controller_spec.rb +121 -0
  168. data/spec/controllers/admin/elements_controller_spec.rb +1 -1
  169. data/spec/controllers/admin/essence_files_controller_spec.rb +67 -0
  170. data/spec/controllers/admin/essence_pictures_controller_spec.rb +161 -0
  171. data/spec/controllers/admin/languages_controller_spec.rb +1 -1
  172. data/spec/controllers/admin/layoutpages_controller_spec.rb +28 -0
  173. data/spec/controllers/admin/pages_controller_spec.rb +164 -118
  174. data/spec/controllers/admin/pictures_controller_spec.rb +89 -0
  175. data/spec/controllers/admin/trash_controller_spec.rb +21 -31
  176. data/spec/controllers/admin/users_controller_spec.rb +114 -85
  177. data/spec/controllers/attachments_controller_spec.rb +6 -2
  178. data/spec/controllers/base_controller_spec.rb +22 -0
  179. data/spec/controllers/elements_controller_spec.rb +1 -1
  180. data/spec/controllers/messages_controller_spec.rb +200 -0
  181. data/spec/controllers/pictures_controller_spec.rb +1 -1
  182. data/spec/controllers/user_sessions_controller_spec.rb +7 -6
  183. data/spec/controllers/users_controller_spec.rb +2 -2
  184. data/spec/dummy/config/alchemy/cells.yml +2 -0
  185. data/spec/dummy/config/application.rb +19 -8
  186. data/spec/dummy/db/migrate/{20130214233001_alchemy_two_point_five.rb → 20130827094554_alchemy_two_point_six.rb} +29 -6
  187. data/spec/dummy/db/schema.rb +1 -1
  188. data/spec/fast_specs.rb +15 -0
  189. data/spec/helpers/admin/base_helper_spec.rb +53 -34
  190. data/spec/helpers/admin/contents_helper_spec.rb +15 -7
  191. data/spec/helpers/admin/elements_helper_spec.rb +79 -34
  192. data/spec/helpers/admin/essences_helper_spec.rb +45 -31
  193. data/spec/helpers/admin/navigation_helper_spec.rb +204 -0
  194. data/spec/helpers/admin/pages_helper_spec.rb +25 -15
  195. data/spec/helpers/admin/tags_helper_spec.rb +62 -2
  196. data/spec/helpers/elements_helper_spec.rb +202 -138
  197. data/spec/helpers/pages_helper_spec.rb +48 -0
  198. data/spec/helpers/url_helper_spec.rb +7 -0
  199. data/spec/libraries/config_spec.rb +110 -3
  200. data/spec/libraries/essence_spec.rb +29 -9
  201. data/spec/libraries/page_layout_spec.rb +134 -0
  202. data/spec/libraries/resource_spec.rb +3 -16
  203. data/spec/libraries/resources_helper_spec.rb +4 -8
  204. data/spec/libraries/shell_spec.rb +1 -0
  205. data/spec/libraries/tinymce_spec.rb +61 -0
  206. data/spec/mailers/messages_spec.rb +23 -0
  207. data/spec/models/attachment_spec.rb +45 -0
  208. data/spec/models/cell_spec.rb +62 -9
  209. data/spec/models/content_spec.rb +110 -28
  210. data/spec/models/element_spec.rb +275 -253
  211. data/spec/models/essence_date_spec.rb +25 -0
  212. data/spec/models/essence_file_spec.rb +23 -0
  213. data/spec/models/essence_html_spec.rb +13 -0
  214. data/spec/models/essence_picture_spec.rb +16 -0
  215. data/spec/models/essence_text_spec.rb +29 -0
  216. data/spec/models/language_spec.rb +34 -0
  217. data/spec/models/message_spec.rb +43 -0
  218. data/spec/models/page_spec.rb +726 -567
  219. data/spec/models/picture_spec.rb +98 -0
  220. data/spec/models/site_spec.rb +60 -2
  221. data/spec/models/tag_spec.rb +31 -0
  222. data/spec/models/user_spec.rb +4 -4
  223. data/spec/spec_helper.rb +49 -58
  224. data/spec/support/alchemy/controller_helpers.rb +35 -0
  225. data/spec/support/alchemy/{specs_helpers.rb → integration_helpers.rb} +4 -8
  226. data/spec/{factories.rb → support/factories.rb} +11 -1
  227. data/vendor/assets/javascripts/jquery_plugins/jquery.ui.nestedSortable.js +2 -8
  228. metadata +166 -106
  229. data/Guardfile +0 -16
  230. data/app/assets/javascripts/alchemy/alchemy.dirty.js +0 -93
  231. data/app/assets/javascripts/alchemy/alchemy.dragndrop.js +0 -122
  232. data/app/models/alchemy/tree_node.rb +0 -4
  233. data/app/views/alchemy/admin/pages/_page_infos.html.erb +0 -3
  234. data/app/views/alchemy/admin/partials/_sub_navigation_tab.html.erb +0 -8
  235. data/app/views/alchemy/messages/contact_form_mail.text.erb +0 -12
  236. data/config/initializers/kaminari_config.rb +0 -9
  237. data/db/migrate/20130221200514_migrate_attachments_to_dragonfly.rb +0 -21
  238. data/db/migrate/20130312205327_change_alchemy_users_role_to_roles.rb +0 -11
  239. data/lib/alchemy/auth_engine.rb +0 -7
  240. data/lib/alchemy/authentication_helpers.rb +0 -9
  241. data/lib/alchemy/ferret_search.rb +0 -84
  242. data/lib/extensions/array.rb +0 -25
  243. data/lib/extensions/hash.rb +0 -34
  244. data/spec/dummy/db/migrate/20130221200514_migrate_attachments_to_dragonfly.rb +0 -21
  245. data/spec/dummy/db/migrate/20130312205327_change_alchemy_users_role_to_roles.rb +0 -11
  246. data/spec/models/page_layout_spec.rb +0 -60
@@ -1,7 +1,6 @@
1
1
  module Alchemy
2
2
  module Admin
3
3
  module ContentsHelper
4
-
5
4
  include Alchemy::Admin::BaseHelper
6
5
 
7
6
  # Returns a string for the id attribute of a html element for the given content
@@ -16,6 +15,11 @@ module Alchemy
16
15
  "#{c.essence_type.demodulize.underscore}_#{c.id}"
17
16
  end
18
17
 
18
+ # Returns a jquery selector string of form field ids from given contents
19
+ def contents_form_field_ids_string(contents)
20
+ contents.collect { |c| "##{c.form_field_id}" }.join(', ')
21
+ end
22
+
19
23
  # Renders the name of elements content or the default name defined in elements.yml
20
24
  def render_content_name(content)
21
25
  if content.blank?
@@ -8,31 +8,6 @@ module Alchemy
8
8
  include Alchemy::Admin::ContentsHelper
9
9
  include Alchemy::Admin::EssencesHelper
10
10
 
11
- # Returns an Array for essence_text_editor select options_for_select.
12
- def elements_by_name_for_select(name, options={})
13
- defaults = {
14
- :grouped_by_page => true,
15
- :from_page => :all
16
- }
17
- options = defaults.merge(options)
18
- elements = all_elements_by_name(
19
- name,
20
- :from_page => options[:from_page]
21
- )
22
- if options[:grouped_by_page] && options[:from_page] == :all
23
- elements_for_options = {}
24
- pages = elements.collect(&:page).compact.uniq
25
- pages.sort { |x, y| x.name <=> y.name }.each do |page|
26
- page_elements = page.elements.select { |e| e.name == name }
27
- elements_for_options[page.name] = page_elements.map { |pe| [pe.preview_text, pe.id.to_s] }
28
- end
29
- else
30
- elements_for_options = elements.map { |e| [e.preview_text, e.id.to_s] }
31
- elements_for_options = [''] + elements_for_options
32
- end
33
- return elements_for_options
34
- end
35
-
36
11
  # Renders the element editor partial
37
12
  def render_editor(element)
38
13
  render_element(element, :editor)
@@ -73,7 +48,7 @@ module Alchemy
73
48
  return [] if elements.nil?
74
49
  options = elements.collect do |e|
75
50
  [
76
- _t(e['name'], scope: 'element_names', default: e['name'].to_s.humanize),
51
+ Element.display_name_for(e['name']),
77
52
  e['name']
78
53
  ]
79
54
  end
@@ -114,32 +89,29 @@ module Alchemy
114
89
  ]
115
90
  else
116
91
  [
117
- _t(e['name'], scope: :element_names, default: e['name'].to_s.humanize),
92
+ Element.display_name_for(e['name']),
118
93
  e[object_method] + (cell ? "##{cell['name']}" : "")
119
94
  ]
120
95
  end
121
96
  end
122
97
 
123
- def update_elements_with_essence_selects(page, element)
124
- elements = page.contents.essence_selects.collect(&:element).uniq.delete_if { |e| e == element }
125
- if elements.any?
126
- js = "var $ess_sel_el;"
127
- elements.each do |element|
128
- rtfs = element.contents.essence_richtexts
129
- js += "\n$ess_sel_el = $('#element_#{element.id}');"
130
- rtfs.each do |content|
131
- js += "\ntinymce.get('contents_content_#{content.id}_body').remove();"
132
- end
133
- js += "\n$('div.element_content', $ess_sel_el).html('#{escape_javascript render_editor(element)}');"
134
- js += "\nAlchemy.GUI.initElement($ess_sel_el);"
135
- rtfs.each do |content|
136
- js += "\nAlchemy.Tinymce.addEditor('#{content.form_field_id}');"
137
- end
138
- end
139
- js
140
- else
141
- nil
142
- end
98
+ # This helper loads all elements from page that have EssenceSelects in them.
99
+ #
100
+ # It returns a javascript function that replaces all editor partials of this elements.
101
+ #
102
+ # We need this while updating, creating or trashing an element,
103
+ # because another element on the same page could have a element selector in it.
104
+ #
105
+ # In cases like this one wants Ember.js databinding!
106
+ #
107
+ def update_essence_select_elements(page, element)
108
+ elements = page.elements.not_trashed.joins(:contents)
109
+ .where("alchemy_contents.element_id != #{element.id}")
110
+ .where("alchemy_contents.essence_type" => "Alchemy::EssenceSelect")
111
+ return if elements.blank?
112
+ elements.collect do |element|
113
+ render 'alchemy/admin/elements/refresh_editor', element: element
114
+ end.join.html_safe
143
115
  end
144
116
 
145
117
  end
@@ -43,22 +43,6 @@ module Alchemy
43
43
  return_string
44
44
  end
45
45
 
46
- # Renders the Content editor partial from the given Element by position (e.g. 1).
47
- # For options see -> render_essence
48
- def render_essence_editor_by_position(element, position, options = {})
49
- ActiveSupport::Deprecation.warn 'Alchemy CMS: render_essence_editor_by_position is not supported anymore and will be removed.'
50
- if element.blank?
51
- warning('Element is nil')
52
- return ""
53
- end
54
- content = element.contents.find_by_position(position)
55
- if content.nil?
56
- render_missing_content(element, position, options)
57
- else
58
- render_essence_editor(content, options)
59
- end
60
- end
61
-
62
46
  # Renders the Content editor partial found in views/contents/ for the content with name inside the passed Element.
63
47
  # For options see -> render_essence
64
48
  #
@@ -121,8 +105,31 @@ module Alchemy
121
105
  end
122
106
  end
123
107
 
108
+ # Returns all public pages from current language as an option tags string suitable or the Rails +select_tag+ helper.
109
+ #
110
+ # @param [Array]
111
+ # A collection of pages so it only returns these pages and does not query the database.
112
+ # @param [String]
113
+ # Pass a +Page#name+ or +Page#id+ as selected item to the +options_for_select+ helper.
114
+ # @param [String]
115
+ # Used as prompt message in the select tag
116
+ # @param [Symbol]
117
+ # Method that is called on the page object to get the value that is passed with the params of the form.
118
+ #
119
+ def pages_for_select(pages = nil, selected = nil, prompt = "Choose page", page_attribute = :id)
120
+ values = [[_t(prompt), ""]]
121
+ pages ||= begin
122
+ nested = true
123
+ Page.with_language(session[:language_id]).published.order(:lft)
124
+ end
125
+ values += pages_attributes_for_select(pages, page_attribute, nested)
126
+ options_for_select(values, selected.to_s)
127
+ end
128
+
129
+ # Renders the missing content partial
130
+ #
124
131
  def render_missing_content(element, name, options)
125
- render :partial => 'alchemy/admin/contents/missing', :locals => {:element => element, :name => name, :options => options}
132
+ render 'alchemy/admin/contents/missing', {element: element, name: name, options: options}
126
133
  end
127
134
 
128
135
  def essence_picture_thumbnail(content, options)
@@ -145,6 +152,41 @@ module Alchemy
145
152
  )
146
153
  end
147
154
 
155
+ private
156
+
157
+ # Returns an Array with page attributes for select options
158
+ #
159
+ # @param [Array]
160
+ # The pages
161
+ # @param [String || Symbol]
162
+ # The attribute that is used as value
163
+ # @param [Boolean] (false)
164
+ # Should the name be indented or not
165
+ #
166
+ def pages_attributes_for_select(pages, page_attribute, indent = false)
167
+ pages.map do |page|
168
+ [
169
+ page_name_attribute_for_select(page, indent),
170
+ page.send(page_attribute).to_s
171
+ ]
172
+ end
173
+ end
174
+
175
+ # Returns the page name for pages_for_select helper
176
+ #
177
+ # @param [Alchemy::Page]
178
+ # The page
179
+ # @param [Boolean] (false)
180
+ # Should the page be indented or not
181
+ #
182
+ def page_name_attribute_for_select(page, indent = false)
183
+ if indent
184
+ ("&nbsp;&nbsp;" * (page.level - 1) + page.name).html_safe
185
+ else
186
+ page.name
187
+ end
188
+ end
189
+
148
190
  end
149
191
  end
150
192
  end
@@ -0,0 +1,204 @@
1
+ module Alchemy
2
+ module Admin
3
+
4
+ # This module contains helper methods for rendering the admin navigation.
5
+ #
6
+ module NavigationHelper
7
+
8
+ # Renders one admin main navigation entry
9
+ #
10
+ # @param [Hash] alchemy_module
11
+ # The Hash representing a Alchemy module
12
+ #
13
+ def alchemy_main_navigation_entry(alchemy_module)
14
+ render(
15
+ 'alchemy/admin/partials/main_navigation_entry',
16
+ alchemy_module: alchemy_module.stringify_keys,
17
+ navigation: module_main_navigation(alchemy_module)
18
+ )
19
+ end
20
+
21
+ # Renders the subnavigation from current module
22
+ #
23
+ # We find the module from current controller and index action.
24
+ #
25
+ def admin_subnavigation
26
+ if current_alchemy_module.present?
27
+ render(
28
+ 'alchemy/admin/partials/sub_navigation',
29
+ entries: current_sub_navigation
30
+ )
31
+ end
32
+ end
33
+
34
+ # Used for checking the main navi permissions
35
+ #
36
+ def navigate_module(navigation)
37
+ [
38
+ navigation['action'].to_sym,
39
+ navigation['controller'].gsub(/^\//, '').gsub(/\//, '_').to_sym
40
+ ]
41
+ end
42
+
43
+ # CSS classes for main navigation entry.
44
+ #
45
+ def main_navigation_css_classes(navigation)
46
+ [
47
+ 'main_navi_entry',
48
+ admin_mainnavi_active?(navigation) ? 'active' : nil
49
+ ].compact.join(' ')
50
+ end
51
+
52
+ # Returns true if given navi entry is in params controller and action
53
+ #
54
+ # == Example
55
+ # <%= entry_active?({controller: 'admin/users', action: 'index'}) %>
56
+ #
57
+ # @param [Hash]
58
+ # A Alchemy module definition navigation entry
59
+ #
60
+ def entry_active?(entry)
61
+ is_entry_controller_active?(entry) && is_entry_action_active?(entry)
62
+ end
63
+
64
+ # Returns url for given Alchemy module.
65
+ #
66
+ # If the module is inside an engine it calls the +url_for+ helper on the engines routing proxy.
67
+ #
68
+ # If the module is inside the host rails app it calls the +url_for+ helper on the main_app routing proxy.
69
+ #
70
+ # @param [Hash]
71
+ # A Alchemy module definition
72
+ #
73
+ def url_for_module(alchemy_module)
74
+ route_from_engine_or_main_app(
75
+ alchemy_module['engine_name'],
76
+ url_options_for_module(alchemy_module)
77
+ )
78
+ end
79
+
80
+ # Returns url for given Alchemy module sub navigation entry.
81
+ #
82
+ # If the module is inside an engine it calls the +url_for+ helper on the engines routing proxy.
83
+ #
84
+ # If the module is inside the host rails app it calls the +url_for+ helper on the main_app routing proxy.
85
+ #
86
+ # @param [Hash]
87
+ # A Alchemy module sub navigation definition
88
+ #
89
+ def url_for_module_sub_navigation(navigation)
90
+ alchemy_module = module_definition_for(navigation)
91
+ route_from_engine_or_main_app(
92
+ alchemy_module['engine_name'],
93
+ url_options_for_navigation_entry(navigation)
94
+ )
95
+ end
96
+
97
+ private
98
+
99
+ # Calls +url_for+ helper on engine if present or on host app.
100
+ #
101
+ # @param [String]
102
+ # A name of an engine
103
+ # @param [Hash]
104
+ # url options hash passed to +url_for+ helper
105
+ #
106
+ def route_from_engine_or_main_app(engine_name, url_options)
107
+ if engine_name.present?
108
+ eval(engine_name).url_for(url_options)
109
+ else
110
+ main_app.url_for(url_options)
111
+ end
112
+ end
113
+
114
+ # Returns a url options hash for given Alchemy module.
115
+ #
116
+ # @param [Hash]
117
+ # A Alchemy module definition
118
+ #
119
+ def url_options_for_module(alchemy_module)
120
+ url_options_for_navigation_entry(module_main_navigation(alchemy_module))
121
+ end
122
+
123
+ # Returns a url options hash for given navigation entry.
124
+ #
125
+ # @param [Hash]
126
+ # A Alchemy module navigation entry
127
+ #
128
+ def url_options_for_navigation_entry(entry)
129
+ entry.stringify_keys!
130
+ {
131
+ controller: entry['controller'],
132
+ action: entry['action'],
133
+ only_path: true
134
+ }
135
+ end
136
+
137
+ # Retrieves the current Alchemy module from controller and index action.
138
+ #
139
+ def current_alchemy_module
140
+ module_definition_for(controller: params[:controller], action: 'index')
141
+ end
142
+
143
+ # Returns the sub navigation for current Alchemy module.
144
+ #
145
+ def current_sub_navigation
146
+ module_sub_navigation(module_main_navigation(current_alchemy_module))
147
+ end
148
+
149
+ # Returns navigation entries from given module.
150
+ #
151
+ def module_main_navigation(alchemy_module)
152
+ alchemy_module.fetch('navigation', {}).stringify_keys
153
+ end
154
+
155
+ # Returns sub navigation entries from given module.
156
+ #
157
+ def module_sub_navigation(alchemy_module)
158
+ alchemy_module.fetch('sub_navigation', []).map(&:stringify_keys)
159
+ end
160
+
161
+ # Returns nested navigation entries for given module.
162
+ #
163
+ def module_nested_navigation(alchemy_module)
164
+ alchemy_module.fetch('nested', []).map(&:stringify_keys)
165
+ end
166
+
167
+ # Returns true if the current controller and action is in a modules navigation definition.
168
+ #
169
+ def admin_mainnavi_active?(main_navigation)
170
+ main_navigation.stringify_keys!
171
+ # Has the given navigation entry a active sub navigation?
172
+ has_active_entry?(module_sub_navigation(main_navigation)) or
173
+ # Has the given navigation entry a active nested navigation?
174
+ has_active_entry?(module_nested_navigation(main_navigation)) or
175
+ # Is the navigation entry active?
176
+ entry_active?(main_navigation)
177
+ end
178
+
179
+ # Returns true if the given entry's controller is current controller
180
+ #
181
+ def is_entry_controller_active?(entry)
182
+ entry['controller'].gsub(/^\//, '') == params[:controller]
183
+ end
184
+
185
+ # Returns true if the given entry's action is current controllers action
186
+ #
187
+ # Also checks if given entry has a +nested_actions+ key, if so it checks if one of them is current controller's action
188
+ #
189
+ def is_entry_action_active?(entry)
190
+ entry['action'] == params[:action] || entry['nested_actions'].to_a.include?(params[:action])
191
+ end
192
+
193
+ # Returns true if an entry of given entries is active.
194
+ #
195
+ # @param [Array]
196
+ # Alchemy module navigation entries.
197
+ #
198
+ def has_active_entry?(entries)
199
+ !entries.detect { |entry| entry_active?(entry) }.nil?
200
+ end
201
+
202
+ end
203
+ end
204
+ end
@@ -3,88 +3,29 @@ module Alchemy
3
3
  module PagesHelper
4
4
  include Alchemy::BaseHelper
5
5
 
6
- def tinymce_javascript_tags
7
- init = Alchemy::Tinymce.init
8
- if init.is_a?(Hash)
9
- init = HashWithIndifferentAccess.new(init)
10
- init = init.keys.sort.collect(&:to_s).sort.collect do |key|
11
- [key, init[key]]
12
- end
13
- end
14
- init = init.collect { |key, value| "#{key} : #{value.to_json}" }.join(', ')
15
- setup = "init.setup = #{Alchemy::Tinymce.setup};" if Alchemy::Tinymce.setup
16
- tinymce_javascript_string = "
17
- <script type='text/javascript'>
18
- jQuery(function($) {
19
- if (typeof(Alchemy) !== 'object') { Alchemy = {}; };
20
- Alchemy.Tinymce = {
21
- init : function(callback) {
22
- var init = { #{init} };
23
- var spinner = Alchemy.Spinner.small();
24
- $('.tinymce_container').prepend(spinner.spin().el);
25
- init.mode = 'specific_textareas';
26
- init.editor_selector = 'default_tinymce';
27
- init.plugins = '#{Alchemy::Tinymce.plugins.join(',')}';
28
- init.language = '#{::I18n.locale.to_s.split('-')[0].downcase }';
29
- init.init_instance_callback = function(inst) {
30
- $('#' + inst.editorId).prev('.spinner').remove();
31
- }
32
- if (callback)
33
- init.oninit = callback;
34
- #{setup}
35
- tinymce.init(init);
36
- },
37
- addEditor : function(dom_id) {
38
- tinymce.execCommand('mceAddControl', true, dom_id);
39
- }
40
- };
41
- });
42
- </script>"
43
- if Alchemy::Tinymce.custom_config_contents.any?
44
- (tinymce_javascript_string + custom_tinymce_javascript_tags).html_safe
6
+ # Used for rendering the folder link in +Admin::Pages#index+ sitemap.
7
+ #
8
+ def sitemap_folder_link(page)
9
+ if page.folded?(current_user.id)
10
+ css_class = 'folded'
11
+ title = _t('Show childpages')
45
12
  else
46
- tinymce_javascript_string.html_safe
13
+ css_class = 'collapsed'
14
+ title = _t('Hide childpages')
47
15
  end
16
+ link_to(
17
+ '',
18
+ alchemy.fold_admin_page_path(page),
19
+ remote: true,
20
+ method: :post,
21
+ class: "page_folder #{css_class} spinner",
22
+ title: title,
23
+ id: "fold_button_#{page.id}"
24
+ )
48
25
  end
49
26
 
50
- def custom_tinymce_javascript_tags
51
- custom_config_string = "
52
- <script type='text/javascript'>
53
- jQuery(function($) {
54
- Alchemy.Tinymce.customInits = [];"
55
- custom_config_contents = Alchemy::Tinymce.custom_config_contents
56
- content_names = custom_config_contents.collect{ |c| c['name'] }
57
- if content_names.uniq.length != content_names.length
58
- raise TinymceError, "Duplicated content names with tinymce setting in elements.yml found. Please rename these contents."
59
- end
60
- custom_config_contents.each do |content|
61
- next unless content['settings']['tinymce']
62
- config = Alchemy::Tinymce.init.merge(content['settings']['tinymce'].symbolize_keys)
63
- config = config.collect { |key, value| "#{key} : #{value.to_json}" }.join(', ')
64
- custom_config_string += "
65
- Alchemy.Tinymce.customInits.push(function(callback) {
66
- var init = { #{config} };
67
- init.mode = 'specific_textareas';
68
- init.editor_selector = /custom_tinymce #{Regexp.escape(content['name'])}/;
69
- init.plugins = '#{Alchemy::Tinymce.plugins.join(',')}';
70
- init.language = '#{::I18n.locale.to_s.split('-')[0].downcase }';
71
- init.init_instance_callback = function(inst) {
72
- var $this = $('#' + inst.editorId);
73
- var parent = $this.parents('.element_editor');
74
- parent.find('.spinner').remove();
75
- inst.onChange.add(function (ed, l) {
76
- Alchemy.setElementDirty(parent);
77
- });
78
- }
79
- tinymce.init(init);
80
- });"
81
- end
82
- custom_config_string += "
83
- });
84
- </script>"
85
- custom_config_string.html_safe
86
- end
87
-
27
+ # Returns options tags for the screen sizes select in page edit view.
28
+ #
88
29
  def preview_sizes_for_select
89
30
  options_for_select([
90
31
  'auto',
@@ -101,7 +42,9 @@ module Alchemy
101
42
  #
102
43
  def combined_page_status(page)
103
44
  page.status.map do |state, value|
104
- page.status_title(state)
45
+ next if state == :locked
46
+ val = content_tag(:span, '', class: page.send(state) ? "page_status #{state}" : "page_status not_#{state}")
47
+ val += page.status_title(state)
105
48
  end.delete_if(&:blank?).join("<br>").html_safe
106
49
  end
107
50