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
@@ -145,11 +145,11 @@ td.value {
145
145
  overflow: hidden;
146
146
 
147
147
  p {
148
- @include inline-block;
149
- width: 214px;
148
+ background: white;
150
149
  text-align: left;
151
- margin: $default-form-field-margin;
150
+ padding: $default-padding 2*$default-padding;
152
151
  line-height: 25px;
152
+ @extend .rounded-border;
153
153
  }
154
154
 
155
155
  &.long {
@@ -182,6 +182,7 @@ td.heading {
182
182
  @extend .disable-user-select;
183
183
  background-repeat: no-repeat;
184
184
  margin: 0 $default-margin;
185
+ text-indent: -100px;
185
186
  }
186
187
 
187
188
  .list td.icon .icon {
@@ -196,6 +197,15 @@ td, th {
196
197
 
197
198
  &.center, &.boolean {
198
199
  text-align: center;
200
+
201
+ .icon {
202
+ @extend .false;
203
+ }
204
+
205
+ .icon.true {
206
+ @extend .icon;
207
+ @extend .true;
208
+ }
199
209
  }
200
210
 
201
211
  &.right {
@@ -20,9 +20,9 @@ module Alchemy
20
20
  @attachment = Attachment.new
21
21
  if in_overlay?
22
22
  @while_assigning = true
23
- @content = Content.find(params[:content_id], :select => 'id') if !params[:content_id].blank?
23
+ @content = Content.find(params[:content_id], :select => 'id')
24
24
  @swap = params[:swap]
25
- @options = hashified_options
25
+ @options = options_from_params
26
26
  end
27
27
  render :layout => !request.xhr?
28
28
  end
@@ -33,7 +33,7 @@ module Alchemy
33
33
  @while_assigning = true
34
34
  @content = Content.find(params[:content_id], :select => 'id') if !params[:content_id].blank?
35
35
  @swap = params[:swap]
36
- @options = hashified_options
36
+ @options = options_from_params
37
37
  end
38
38
  @attachments = Attachment.find_paginated(params, per_page_value_for_screen_size, sort_order)
39
39
  @message = _t('File %{name} uploaded succesfully', :name => @attachment.name)
@@ -64,7 +64,12 @@ module Alchemy
64
64
  @attachment = Attachment.find(params[:id])
65
65
  name = @attachment.name
66
66
  @attachment.destroy
67
- flash[:notice] = _t("File: '%{name}' deleted successfully", :name => name)
67
+ @url = admin_attachments_url(
68
+ per_page: params[:per_page],
69
+ page: params[:page],
70
+ query: params[:query]
71
+ )
72
+ flash[:notice] = _t("File: '%{name}' deleted successfully", name: name)
68
73
  end
69
74
 
70
75
  def show
@@ -90,7 +95,7 @@ module Alchemy
90
95
 
91
96
  def archive_overlay
92
97
  @content = Content.find(params[:content_id], select: 'id')
93
- @options = hashified_options
98
+ @options = options_from_params
94
99
  respond_to do |format|
95
100
  format.html {
96
101
  render partial: 'archive_overlay'
@@ -128,6 +128,25 @@ module Alchemy
128
128
  (screen_height / 30) - 10
129
129
  end
130
130
 
131
+ # Extracts options from params.
132
+ #
133
+ # Helps to parse JSONified options into Hash or Array
134
+ #
135
+ def options_from_params
136
+ case params[:options]
137
+ when ''
138
+ {}
139
+ when String
140
+ JSON.parse(params[:options])
141
+ when Hash
142
+ params[:options]
143
+ when Array
144
+ params[:options]
145
+ else
146
+ {}
147
+ end.symbolize_keys
148
+ end
149
+
131
150
  end
132
151
  end
133
152
  end
@@ -14,11 +14,8 @@ module Alchemy
14
14
  def create
15
15
  @element = Element.find(params[:content][:element_id])
16
16
  @content = Content.create_from_scratch(@element, params[:content])
17
- @options = params[:options] || {}
17
+ @options = options_from_params
18
18
  @html_options = params[:html_options] || {}
19
- if @options.is_a?(String)
20
- @options = @options.present? ? JSON.parse(@options) : {}
21
- end
22
19
  if @content.essence_type == "Alchemy::EssencePicture"
23
20
  @content_dom_id = "#add_picture_#{@element.id}"
24
21
  @content.essence.picture_id = params[:picture_id]
@@ -1,11 +1,12 @@
1
1
  require 'net/http'
2
+ require 'alchemy/version'
2
3
 
3
4
  module Alchemy
4
5
  module Admin
5
6
  class DashboardController < Alchemy::Admin::BaseController
6
7
 
7
8
  def index
8
- @last_edited_pages = Page.all_last_edited_from(current_user)
9
+ @last_edited_pages = Page.from_current_site.all_last_edited_from(current_user)
9
10
  @locked_pages = Page.from_current_site.all_locked
10
11
  @online_users = User.logged_in.to_a - [current_user]
11
12
  @first_time = current_user.sign_in_count == 1 && current_user.last_sign_in_at.nil?
@@ -26,7 +26,7 @@ module Alchemy
26
26
  def new
27
27
  @page = Page.find_by_id(params[:page_id])
28
28
  @element = @page.elements.build
29
- @elements = Element.all_for_page(@page)
29
+ @elements = @page.available_element_definitions
30
30
  clipboard_elements = get_clipboard[:elements]
31
31
  unless clipboard_elements.blank?
32
32
  @clipboard_items = Element.all_from_clipboard_for_page(clipboard_elements, @page)
@@ -19,7 +19,7 @@ module Alchemy
19
19
  @content = Content.find_by_id(params[:id])
20
20
  @attachment = Attachment.find_by_id(params[:attachment_id])
21
21
  @content.essence.attachment = @attachment
22
- @options = params[:options] || {}
22
+ @options = options_from_params
23
23
  end
24
24
 
25
25
  end
@@ -1,92 +1,106 @@
1
1
  module Alchemy
2
2
  module Admin
3
3
  class EssencePicturesController < Alchemy::Admin::BaseController
4
+ before_filter :load_essence_picture, only: [:edit, :crop, :update]
5
+ before_filter :load_content, only: [:edit, :update, :assign]
6
+ before_filter :load_options
4
7
 
5
8
  helper "alchemy/admin/contents"
6
9
  helper "alchemy/admin/essences"
7
10
  helper "alchemy/url"
8
11
 
9
12
  def edit
10
- @essence_picture = EssencePicture.find(params[:id])
11
- @content = Content.find(params[:content_id])
12
- @options = params[:options] || {}
13
13
  render layout: !request.xhr?
14
14
  end
15
15
 
16
16
  def crop
17
- @essence_picture = EssencePicture.find(params[:id])
18
- if @essence_picture.picture
17
+ if @picture = @essence_picture.picture
19
18
  @content = @essence_picture.content
20
- @options = params[:options] || {}
21
19
  @options[:format] ||= (configuration(:image_store_format) or 'png')
22
- if @essence_picture.render_size.blank?
23
- if @options[:image_size].blank?
24
- @size_x, @size_y = 0, 0
25
- else
26
- @size_x, @size_y = @options[:image_size].split('x')[0], @options[:image_size].split('x')[1]
27
- end
28
- else
29
- @size_x, @size_y = @essence_picture.render_size.split('x')[0], @essence_picture.render_size.split('x')[1]
30
- end
31
- if @essence_picture.crop_from.blank? && @essence_picture.crop_size.blank?
32
- @initial_box = @essence_picture.picture.default_mask("#{@size_x}x#{@size_y}")
33
- @default_box = @initial_box
34
- else
35
- @initial_box = {
36
- :x1 => @essence_picture.crop_from.split('x')[0].to_i,
37
- :y1 => @essence_picture.crop_from.split('x')[1].to_i,
38
- :x2 => @essence_picture.crop_from.split('x')[0].to_i + @essence_picture.crop_size.split('x')[0].to_i,
39
- :y2 => @essence_picture.crop_from.split('x')[1].to_i + @essence_picture.crop_size.split('x')[1].to_i
40
- }
41
- @default_box = @essence_picture.picture.default_mask("#{@size_x}x#{@size_y}")
42
- end
43
- @ratio = @options[:fixed_ratio] == 'false' ? false : (@size_x.to_f / @size_y.to_f)
20
+ @size_x, @size_y = sizes_from_essence_or_params
21
+ @initial_box, @default_box = cropping_boxes
22
+ @ratio = ratio_from_size_or_params
44
23
  else
45
- @no_image_notice = _t('No image found. Did you saved the element?')
24
+ @no_image_notice = _t(:no_image_for_cropper_found)
46
25
  end
47
26
  render layout: !request.xhr?
48
27
  end
49
28
 
50
29
  def update
51
- @essence_picture = EssencePicture.find(params[:id])
52
30
  @essence_picture.update_attributes(params[:essence_picture])
53
- @content = Content.find(params[:content_id])
54
- @options = params[:options] || {}
55
31
  end
56
32
 
33
+ # Assigns picture, but does not saves it.
34
+ #
35
+ # When the user press save on the element, it gets saved.
36
+ #
57
37
  def assign
58
- @content = Content.find_by_id(params[:id])
59
38
  @picture = Picture.find_by_id(params[:picture_id])
60
39
  @content.essence.picture = @picture
61
- @options = params[:options] || {}
62
40
  @element = @content.element
63
41
  @dragable = @options[:grouped]
64
- # If options params come from Flash uploader then we have to parse them as hash.
65
- if @options.is_a?(String)
66
- @options = Rack::Utils.parse_query(@options)
67
- end
68
- @options = @options.merge(
69
- :dragable => @dragable
70
- )
71
- end
72
-
73
- def save_link
74
- @content = Content.find(params[:id])
75
- @picture_essence = @content.essence
76
- @picture_essence.link = params[:link]
77
- @picture_essence.link_title = params[:title]
78
- @picture_essence.open_link_in_new_window = params[:blank]
79
- @notice = _t(:saved_link)
80
- @picture_essence.save
42
+ @options = @options.merge(dragable: @dragable)
81
43
  end
82
44
 
83
45
  def destroy
84
- content = Content.find_by_id(params[:id])
85
- @element = content.element
86
- @content_id = content.id
87
- content.destroy
46
+ @content = Content.find_by_id(params[:id])
47
+ @element = @content.element
48
+ @content_id = @content.id
49
+ @content.destroy
88
50
  @essence_pictures = @element.contents.find_all_by_essence_type('Alchemy::EssencePicture')
89
- @options = params[:options]
51
+ end
52
+
53
+ private
54
+
55
+ def load_options
56
+ @options = options_from_params
57
+ end
58
+
59
+ def load_essence_picture
60
+ @essence_picture = EssencePicture.find(params[:id])
61
+ end
62
+
63
+ def load_content
64
+ @content = Content.find(params[:content_id])
65
+ end
66
+
67
+ def sizes_from_essence_or_params
68
+ sizes_from_essence || sizes_from_params
69
+ end
70
+
71
+ def sizes_from_params
72
+ return [0, 0] if @options[:image_size].blank?
73
+ @options[:image_size].split('x')
74
+ end
75
+
76
+ def sizes_from_essence
77
+ return if @essence_picture.render_size.blank?
78
+ @essence_picture.render_size.split('x')
79
+ end
80
+
81
+ def sizes_string
82
+ @sizes_string ||= "#{@size_x}x#{@size_y}"
83
+ end
84
+
85
+ def cropping_boxes
86
+ if @essence_picture.crop_from.blank? || @essence_picture.crop_size.blank?
87
+ initial_box = @picture.default_mask(sizes_string)
88
+ default_box = initial_box
89
+ else
90
+ initial_box = @essence_picture.cropping_mask
91
+ default_box = @picture.default_mask(sizes_string)
92
+ end
93
+ [initial_box, default_box]
94
+ end
95
+
96
+ def ratio_from_size_or_params
97
+ if @options[:fixed_ratio] == false
98
+ false
99
+ elsif @size_y == 0
100
+ 1
101
+ else
102
+ @size_x.to_f / @size_y.to_f
103
+ end
90
104
  end
91
105
 
92
106
  end
@@ -1,13 +1,13 @@
1
1
  module Alchemy
2
2
  module Admin
3
3
  class PagesController < Alchemy::Admin::BaseController
4
- include Alchemy::FerretSearch
4
+ include Ferret::Search
5
5
 
6
6
  helper "alchemy/pages"
7
7
 
8
8
  before_filter :set_translation, :except => [:show]
9
9
 
10
- filter_access_to [:show, :unlock, :visit, :publish, :configure, :edit, :update, :destroy, :fold], :attribute_check => true, :load_method => :load_page, :model => Alchemy::Page
10
+ filter_access_to [:show, :info, :unlock, :visit, :publish, :configure, :edit, :update, :destroy, :fold], :attribute_check => true, :load_method => :load_page, :model => Alchemy::Page
11
11
  filter_access_to [:index, :link, :layoutpages, :new, :switch_language, :create, :move, :flush], :attribute_check => false
12
12
 
13
13
  cache_sweeper Alchemy::PagesSweeper, :only => [:publish], :if => proc { Alchemy::Config.get(:cache_pages) }
@@ -41,6 +41,10 @@ module Alchemy
41
41
  render :file => Rails.root.join('public', '500.html'), :status => 500, :layout => false
42
42
  end
43
43
 
44
+ def info
45
+ render layout: !request.xhr?
46
+ end
47
+
44
48
  def new
45
49
  @page = Page.new(:layoutpage => params[:layoutpage] == 'true', :parent_id => params[:parent_id])
46
50
  @page_layouts = PageLayout.layouts_for_select(session[:language_id], @page.layoutpage?)
@@ -49,24 +53,13 @@ module Alchemy
49
53
  end
50
54
 
51
55
  def create
52
- parent = Page.find_by_id(params[:page][:parent_id]) || Page.root
53
- params[:page][:language_id] ||= parent.language ? parent.language.id : Language.get_default.id
54
- params[:page][:language_code] ||= parent.language ? parent.language.code : Language.get_default.code
55
- # Copy the page
56
- if params[:paste_from_clipboard].present?
57
- source_page = Page.find(params[:paste_from_clipboard])
58
- @page = Page.copy(source_page, {
59
- :parent_id => params[:page][:parent_id],
60
- :language => parent.language,
61
- :name => params[:page][:name],
62
- :title => params[:page][:name]
63
- })
64
- if source_page.children.any?
65
- source_page.copy_children_to(@page)
66
- end
56
+ if params[:paste_from_clipboard]
57
+ source = Page.find(params[:paste_from_clipboard])
58
+ parent = Page.find_by_id(params[:page][:parent_id]) || Page.root
59
+ @page = Page.paste_from_clipboard(source, parent, params[:page][:name])
67
60
  else
68
- # Create new page
69
61
  @page = Page.new(params[:page])
62
+ @page.set_language_from_parent_or_default_language
70
63
  end
71
64
  if @page.save
72
65
  redirect_path = params[:redirect_to] || edit_admin_page_path(@page)
@@ -81,10 +74,10 @@ module Alchemy
81
74
  def edit
82
75
  # fetching page via before filter
83
76
  if @page.locked? && @page.locker && @page.locker.logged_in? && @page.locker != current_user
84
- flash[:notice] = _t("This page is locked by %{name}", :name => (@page.locker.name rescue _t(:unknown)))
77
+ flash[:notice] = _t("This page is locked by %{name}", name: @page.locker_name)
85
78
  redirect_to admin_pages_path
86
79
  else
87
- @page.lock(current_user)
80
+ @page.lock!(current_user)
88
81
  @locked_pages = Page.from_current_site.all_locked_by(current_user)
89
82
  end
90
83
  @layoutpage = @page.layoutpage?
@@ -151,8 +144,7 @@ module Alchemy
151
144
 
152
145
  def fold
153
146
  # @page is fetched via before filter
154
- @page.fold(current_user.id, !@page.folded?(current_user.id))
155
- @page.save
147
+ @page.fold!(current_user.id, !@page.folded?(current_user.id))
156
148
  respond_to do |format|
157
149
  format.js
158
150
  end
@@ -161,7 +153,7 @@ module Alchemy
161
153
  # Leaves the page editing mode and unlocks the page for other users
162
154
  def unlock
163
155
  # fetching page via before filter
164
- @page.unlock
156
+ @page.unlock!
165
157
  flash[:notice] = _t(:unlocked_page, :name => @page.name)
166
158
  @pages_locked_by_user = Page.from_current_site.all_locked_by(current_user)
167
159
  respond_to do |format|
@@ -173,7 +165,7 @@ module Alchemy
173
165
  end
174
166
 
175
167
  def visit
176
- @page.unlock
168
+ @page.unlock!
177
169
  redirect_to show_page_path(:urlname => @page.urlname, :lang => multi_language? ? @page.language_code : nil)
178
170
  end
179
171
 
@@ -208,19 +200,17 @@ module Alchemy
208
200
  @sorting = true
209
201
  end
210
202
 
211
- # Receives a JSON object representing a language tree to be ordered
212
- # and updates all pages in that language structure to their correct indexes
213
203
  def order
214
- neworder = JSON.parse(params[:set])
215
- rootpage = Page.language_root_for(session[:language_id])
216
-
217
- tree = create_tree(neworder, rootpage)
204
+ @page_root = Page.language_root_for(session[:language_id])
218
205
 
219
- Alchemy::Page.transaction do
220
- tree.each do |key, node|
221
- dbitem = Page.find(key)
222
- dbitem.update_node!(node)
223
- end
206
+ # Taken from https://github.com/matenia/jQuery-Awesome-Nested-Set-Drag-and-Drop
207
+ neworder = JSON.parse(params[:set])
208
+ prev_item = nil
209
+ neworder.each do |item|
210
+ dbitem = Page.find(item['id'])
211
+ prev_item.nil? ? dbitem.move_to_child_of(@page_root) : dbitem.move_to_right_of(prev_item)
212
+ sort_children(item, dbitem) unless item['children'].nil?
213
+ prev_item = dbitem.reload
224
214
  end
225
215
 
226
216
  flash[:notice] = _t("Pages order saved")
@@ -250,85 +240,6 @@ module Alchemy
250
240
 
251
241
  private
252
242
 
253
- # Returns the current left index and the aggregated hash of tree nodes indexed by page id visited so far
254
- #
255
- # Visits a batch of children nodes, assigns them the correct ordering indexes and spuns recursively the same
256
- # procedure on their children, if any
257
- #
258
- # @param [Array]
259
- # An array of children nodes to be visited
260
- # @param [Integer]
261
- # The lft attribute that should be given to the first node in the array
262
- # @param [Integer]
263
- # The page id of the parent of this batch of children nodes
264
- # @param [Integer]
265
- # The depth at which these children reside
266
- # @param [Hash]
267
- # A Hash of TreeNode's indexed by their page ids
268
- # @param [String]
269
- # The url for the parent node of these children
270
- # @param [Boolean]
271
- # Whether these children reside in a restricted branch according to their ancestors
272
- #
273
- def visit_nodes(nodes, my_left, parent, depth, tree, url, restricted)
274
- nodes.each do |item|
275
- my_right = my_left + 1
276
- my_restricted = item['restricted'] || restricted
277
- urls = process_url(url, item)
278
-
279
- if item['children']
280
- my_right, tree = visit_nodes(item['children'], my_left + 1, item['id'], depth + 1, tree, urls[:children_path], my_restricted)
281
- end
282
-
283
- tree[item['id']] = TreeNode.new(my_left, my_right, parent, depth, urls[:my_urlname], my_restricted)
284
- my_left = my_right + 1
285
- end
286
-
287
- [my_left, tree]
288
- end
289
-
290
- # Returns a Hash of TreeNode's indexed by their page ids
291
- #
292
- # Grabs the array representing a tree structure of pages passed as a parameter,
293
- # visits it and creates a map of TreeNodes indexed by page id featuring Nested Set
294
- # ordering information consisting of the left, right, depth and parent_id indexes as
295
- # well as a node's url and restricted status
296
- #
297
- # @param [Array]
298
- # An Array representing a tree of Alchemy::Page's
299
- # @param [Alchemy::Page]
300
- # The root page for the language being ordered
301
- #
302
- def create_tree(items, rootpage)
303
- _, tree = visit_nodes(items, rootpage.lft + 1, rootpage.id, rootpage.depth + 1, {}, "", rootpage.restricted)
304
- tree
305
- end
306
-
307
- # Returns a pair, the path that a given tree node should take, and the path its children should take
308
- #
309
- # This function will add a node's own slug into their ancestor's path
310
- # in order to create the full URL of a node
311
- #
312
- # NOTE: external and invisible pages are not part of the full path of their children
313
- #
314
- # @param [String]
315
- # The node's ancestors path
316
- # @param [Hash]
317
- # A children node
318
- #
319
- def process_url(ancestors_path, item)
320
- default_urlname = (ancestors_path.blank? ? "" : "#{ancestors_path}/") + item['slug']
321
-
322
- pair = {my_urlname: default_urlname, children_path: default_urlname}
323
-
324
- if item['external'] == true || item['visible'] == false
325
- # children ignore an ancestor in their path if external or invisible
326
- pair[:children_path] = ancestors_path
327
- end
328
-
329
- pair
330
- end
331
-
332
243
  def load_page
333
244
  @page = Page.find(params[:id])
334
245
  end
@@ -336,6 +247,18 @@ module Alchemy
336
247
  def pages_from_raw_request
337
248
  request.raw_post.split('&').map { |i| i = {i.split('=')[0].gsub(/[^0-9]/, '') => i.split('=')[1]} }
338
249
  end
250
+
251
+ # Taken from https://github.com/matenia/jQuery-Awesome-Nested-Set-Drag-and-Drop
252
+ def sort_children(element, dbitem)
253
+ prevchild = nil
254
+ element['children'].each do |child|
255
+ childitem = Page.find(child['id'])
256
+ prevchild.nil? ? childitem.move_to_child_of(dbitem) : childitem.move_to_right_of(prevchild)
257
+ sort_children(child, childitem) unless child['children'].nil?
258
+ prevchild = childitem
259
+ end
260
+ end
261
+
339
262
  end
340
263
  end
341
264
  end