alchemy_cms 2.3.2 → 2.4.beta2

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 (164) hide show
  1. data/.gitignore +1 -2
  2. data/.travis.yml +1 -5
  3. data/Gemfile +4 -4
  4. data/README.md +22 -15
  5. data/alchemy_cms.gemspec +38 -38
  6. data/app/assets/javascripts/alchemy/alchemy.base.js +2 -2
  7. data/app/assets/javascripts/alchemy/alchemy.buttons.js.coffee +31 -0
  8. data/app/assets/javascripts/alchemy/alchemy.dragndrop.js +1 -1
  9. data/app/assets/javascripts/alchemy/alchemy.elements_window.js +24 -15
  10. data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +9 -3
  11. data/app/assets/javascripts/alchemy/alchemy.jquery_loader.js +2 -2
  12. data/app/assets/javascripts/alchemy/alchemy.js +1 -0
  13. data/app/assets/javascripts/alchemy/alchemy.menubar.js +4 -12
  14. data/app/assets/javascripts/alchemy/alchemy.onload.js.coffee +32 -0
  15. data/app/assets/javascripts/alchemy/alchemy.windows.js +4 -4
  16. data/app/assets/stylesheets/alchemy/_defaults.scss +0 -1
  17. data/app/assets/stylesheets/alchemy/alchemy.css +2 -1
  18. data/app/assets/stylesheets/alchemy/base.css.scss +2 -54
  19. data/app/assets/stylesheets/alchemy/elements.css.scss +8 -5
  20. data/app/assets/stylesheets/alchemy/errors.css.scss +51 -0
  21. data/app/assets/stylesheets/alchemy/flash.css.scss +0 -2
  22. data/app/assets/stylesheets/alchemy/form_elements.css.scss +31 -75
  23. data/app/assets/stylesheets/alchemy/icons.css.scss +5 -5
  24. data/app/assets/stylesheets/alchemy/menubar.css.scss +0 -2
  25. data/app/assets/stylesheets/alchemy/sitemap.css.scss +0 -1
  26. data/app/assets/stylesheets/alchemy/tables.css.scss +3 -1
  27. data/app/controllers/alchemy/admin/base_controller.rb +19 -12
  28. data/app/controllers/alchemy/admin/elements_controller.rb +52 -24
  29. data/app/controllers/alchemy/admin/pages_controller.rb +11 -5
  30. data/app/controllers/alchemy/admin/resources_controller.rb +3 -4
  31. data/app/controllers/alchemy/admin/users_controller.rb +1 -0
  32. data/app/controllers/alchemy/base_controller.rb +34 -8
  33. data/app/controllers/alchemy/pictures_controller.rb +16 -1
  34. data/app/controllers/alchemy/user_sessions_controller.rb +6 -1
  35. data/app/helpers/alchemy/base_helper.rb +14 -0
  36. data/app/helpers/alchemy/elements_helper.rb +10 -5
  37. data/app/helpers/alchemy/pages_helper.rb +1 -2
  38. data/app/helpers/alchemy/url_helper.rb +43 -24
  39. data/app/models/alchemy/element.rb +23 -16
  40. data/app/models/alchemy/page.rb +25 -14
  41. data/app/models/alchemy/picture.rb +24 -0
  42. data/app/views/alchemy/admin/contents/create.js.erb +1 -1
  43. data/app/views/alchemy/admin/elements/_new_element_form.html.erb +1 -1
  44. data/app/views/alchemy/admin/elements/create.js.erb +11 -3
  45. data/app/views/alchemy/admin/elements/fold.js.erb +1 -1
  46. data/app/views/alchemy/admin/elements/new.html.erb +1 -1
  47. data/app/views/alchemy/admin/elements/update.js.erb +1 -1
  48. data/app/views/alchemy/admin/essence_pictures/crop.html.erb +1 -1
  49. data/app/views/alchemy/admin/languages/_form.html.erb +1 -1
  50. data/app/views/alchemy/admin/pages/_new_page_form.html.erb +1 -1
  51. data/app/views/alchemy/admin/pages/_page.html.erb +1 -1
  52. data/app/views/alchemy/admin/pages/configure.html.erb +10 -6
  53. data/app/views/alchemy/admin/pages/configure_external.html.erb +1 -1
  54. data/app/views/alchemy/admin/pages/edit.html.erb +1 -2
  55. data/app/views/alchemy/admin/pages/new.html.erb +2 -2
  56. data/app/views/alchemy/admin/pages/update.js.erb +10 -2
  57. data/app/views/alchemy/admin/partials/_sub_navigation_tab.html.erb +5 -5
  58. data/app/views/alchemy/admin/pictures/_filter_bar.html.erb +2 -1
  59. data/app/views/alchemy/admin/pictures/_picture.html.erb +2 -2
  60. data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +2 -1
  61. data/app/views/alchemy/admin/pictures/show_in_window.html.erb +3 -2
  62. data/app/views/alchemy/admin/resources/_form.html.erb +1 -1
  63. data/app/views/alchemy/admin/users/_table.html.erb +4 -4
  64. data/app/views/alchemy/admin/users/edit.html.erb +1 -1
  65. data/app/views/alchemy/admin/users/new.html.erb +1 -1
  66. data/app/views/alchemy/base/error_notice.js.erb +1 -1
  67. data/app/views/alchemy/base/remote_errors.js.erb +2 -3
  68. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +10 -7
  69. data/app/views/alchemy/essences/_essence_picture_view.html.erb +24 -21
  70. data/app/views/layouts/alchemy/admin.html.erb +9 -31
  71. data/bin/alchemy +20 -24
  72. data/config/alchemy/config.yml +6 -0
  73. data/config/alchemy/page_layouts.yml +2 -0
  74. data/config/authorization_rules.rb +1 -1
  75. data/config/locales/alchemy.de.yml +3 -0
  76. data/config/locales/alchemy.en.yml +4 -1
  77. data/db/migrate/20121026100815_alchemy_two_point_three.rb +312 -0
  78. data/lib/alchemy/mount_point.rb +9 -3
  79. data/lib/alchemy/page_layout.rb +89 -73
  80. data/lib/alchemy/version.rb +1 -1
  81. data/lib/rails/generators/alchemy/deploy_script/deploy_script_generator.rb +45 -12
  82. data/lib/rails/generators/alchemy/deploy_script/templates/deploy.rb.tt +3 -1
  83. data/lib/rails/generators/alchemy/essence/essence_generator.rb +51 -0
  84. data/lib/rails/generators/alchemy/essence/templates/editor.html.erb +18 -0
  85. data/lib/rails/generators/alchemy/essence/templates/view.html.erb +2 -0
  86. data/lib/rails/templates/alchemy.rb +1 -1
  87. data/lib/tasks/install.rake +57 -2
  88. data/spec/controllers/admin/elements_controller_spec.rb +170 -22
  89. data/spec/controllers/admin/trash_controller_spec.rb +1 -1
  90. data/spec/controllers/admin/users_controller_spec.rb +36 -0
  91. data/spec/controllers/base_controller_spec.rb +12 -1
  92. data/spec/controllers/elements_controller_spec.rb +17 -13
  93. data/spec/controllers/pictures_controller_spec.rb +4 -4
  94. data/spec/dummy/config/application.rb +1 -1
  95. data/spec/dummy/db/migrate/20121026100815_alchemy_two_point_three.rb +312 -0
  96. data/spec/dummy/db/migrate/20121026104128_create_events.rb +19 -0
  97. data/spec/dummy/db/schema.rb +1 -1
  98. data/spec/factories.rb +0 -1
  99. data/spec/helpers/base_helper_spec.rb +48 -0
  100. data/spec/helpers/elements_helper_spec.rb +14 -3
  101. data/spec/helpers/url_helper_spec.rb +8 -3
  102. data/spec/integration/picture_security_spec.rb +35 -0
  103. data/spec/integration/translation_integration_spec.rb +6 -5
  104. data/spec/models/element_spec.rb +5 -5
  105. data/spec/models/page_layout_spec.rb +10 -16
  106. data/spec/models/page_spec.rb +25 -2
  107. data/spec/models/picture_spec.rb +24 -2
  108. data/spec/routing_spec.rb +115 -115
  109. data/spec/support/alchemy/specs_helpers.rb +4 -4
  110. data/{app/assets/images/alchemy → vendor/assets/images}/Jcrop.gif +0 -0
  111. data/vendor/assets/javascripts/jquery_plugins/jquery.Jcrop.min.js +19 -243
  112. data/vendor/assets/javascripts/jquery_plugins/jquery.selectboxit.min.js +1 -0
  113. data/vendor/assets/javascripts/jquery_plugins/jquery.ui.tabspaging.js +6 -6
  114. data/vendor/assets/stylesheets/jquery.Jcrop.min.css +28 -0
  115. metadata +48 -82
  116. data/app/assets/javascripts/alchemy/alchemy.buttons.js +0 -50
  117. data/app/assets/stylesheets/alchemy/jquery.Jcrop.css.scss +0 -54
  118. data/app/helpers/alchemy/pictures_helper.rb +0 -19
  119. data/db/migrate/20100607143125_create_pages.rb +0 -34
  120. data/db/migrate/20100607144254_create_elements.rb +0 -20
  121. data/db/migrate/20100607145256_create_contents.rb +0 -18
  122. data/db/migrate/20100607145719_create_users.rb +0 -32
  123. data/db/migrate/20100607150611_create_pictures.rb +0 -16
  124. data/db/migrate/20100607150812_create_attachments.rb +0 -16
  125. data/db/migrate/20100607153647_create_folded_pages.rb +0 -13
  126. data/db/migrate/20100607161345_create_essence_texts.rb +0 -19
  127. data/db/migrate/20100607162339_create_elements_pages.rb +0 -12
  128. data/db/migrate/20100607193638_create_essence_pictures.rb +0 -23
  129. data/db/migrate/20100607193646_create_essence_richtexts.rb +0 -16
  130. data/db/migrate/20100607193653_create_essence_htmls.rb +0 -13
  131. data/db/migrate/20100609111653_create_essence_dates.rb +0 -13
  132. data/db/migrate/20100609111809_create_essence_files.rb +0 -15
  133. data/db/migrate/20100609111821_create_essence_flashes.rb +0 -16
  134. data/db/migrate/20100609111837_create_essence_videos.rb +0 -18
  135. data/db/migrate/20100616150753_create_essence_audios.rb +0 -17
  136. data/db/migrate/20100812085225_add_crop_from_and_crop_size_to_essence_pictures.rb +0 -11
  137. data/db/migrate/20100909140701_change_essence_htmls_source_column_type.rb +0 -9
  138. data/db/migrate/20101109150312_alter_pages_visible_column_default.rb +0 -9
  139. data/db/migrate/20101109151812_create_languages.rb +0 -19
  140. data/db/migrate/20101216151419_add_language_id_to_pages.rb +0 -27
  141. data/db/migrate/20101216155216_add_index_to_languages.rb +0 -9
  142. data/db/migrate/20101216173323_add_default_to_languages.rb +0 -9
  143. data/db/migrate/20101218130049_add_urlname_index_to_pages.rb +0 -9
  144. data/db/migrate/20110115123343_remove_css_class_default_from_essence_pictures.rb +0 -11
  145. data/db/migrate/20110224105120_change_pages_visible_default.rb +0 -11
  146. data/db/migrate/20110228182659_remove_default_page_layout_from_pages.rb +0 -11
  147. data/db/migrate/20110414163140_remove_display_name_from_elements.rb +0 -11
  148. data/db/migrate/20110511100516_rename_essence_texts_title_to_link_title.rb +0 -9
  149. data/db/migrate/20110529130429_create_cells.rb +0 -14
  150. data/db/migrate/20110529130500_add_cell_id_to_elements.rb +0 -11
  151. data/db/migrate/20110530102804_change_pages_page_layout_column.rb +0 -11
  152. data/db/migrate/20110707190728_add_render_size_to_essence_pictures.rb +0 -9
  153. data/db/migrate/20110711142057_change_open_link_in_new_window_to_link_target.rb +0 -19
  154. data/db/migrate/20110919110451_add_default_role_to_users.rb +0 -9
  155. data/db/migrate/20111116125112_namespace_alchemy_models.rb +0 -23
  156. data/db/migrate/20120216135355_add_country_code_to_languages.rb +0 -9
  157. data/db/migrate/20120608085509_create_alchemy_essence_selects.rb +0 -11
  158. data/db/migrate/20120611221734_create_alchemy_essence_booleans.rb +0 -11
  159. data/db/migrate/20120704181529_add_upload_hash_to_alchemy_picture.rb +0 -5
  160. data/db/migrate/20120705214247_acts_as_taggable_on_migration.rb +0 -28
  161. data/db/migrate/20120728185830_add_cached_tag_list_to_alchemy_pictures.rb +0 -5
  162. data/db/migrate/20120831135441_set_alchemy_languages_country_code_default_to_empty_string.rb +0 -9
  163. data/spec/helpers/pictures_helper_spec.rb +0 -14
  164. data/vendor/assets/javascripts/jquery_plugins/jquery.selectBoxIt.js +0 -1909
@@ -15,7 +15,7 @@ module Alchemy
15
15
  # :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.
16
16
  # :for => 'ELEMENT_NAME', # The name of the element the fallback is for
17
17
  # :with => 'ELEMENT_NAME', # (OPTIONAL) the name of element to fallback with
18
- # :from => 'PAGE_LAYOUT' # The page_layout name from the global page the fallback elements lie on. I.E 'left_column'
18
+ # :from => String || Page # Pass a page_layout name from a page the fallback elements lie on or pass the page object.
19
19
  # } #
20
20
  # :sort_by => Content#name # A Content name to sort the elements by
21
21
  # :reverse => boolean # Reverse the rendering order
@@ -55,13 +55,18 @@ module Alchemy
55
55
  else
56
56
  all_elements = page.find_elements(options)
57
57
  end
58
- unless options[:sort_by].blank?
58
+ if options[:sort_by].present?
59
59
  all_elements = all_elements.sort_by { |e| e.contents.detect { |c| c.name == options[:sort_by] }.ingredient }
60
60
  end
61
61
  element_string = ""
62
62
  if options[:fallback]
63
- unless all_elements.detect { |e| e.name == options[:fallback][:for] }
64
- if from = Page.where(:page_layout => options[:fallback][:from]).with_language(session[:language_id]).first
63
+ if all_elements.detect { |e| e.name == options[:fallback][:for] }.blank?
64
+ if options[:fallback][:from].class.name == 'Alchemy::Page'
65
+ from = options[:fallback][:from]
66
+ else
67
+ from = Page.not_restricted.where(:page_layout => options[:fallback][:from]).with_language(session[:language_id]).first
68
+ end
69
+ if from
65
70
  all_elements += from.elements.named(options[:fallback][:with].blank? ? options[:fallback][:for] : options[:fallback][:with])
66
71
  end
67
72
  end
@@ -163,7 +168,7 @@ module Alchemy
163
168
 
164
169
  # Returns the full url containing host, page and anchor for the given element
165
170
  def full_url_for_element(element)
166
- "http://" + request.env["HTTP_HOST"] + "/" + element.page.urlname + "##{element.name}_#{element.id}"
171
+ "#{current_server}/#{element.page.urlname}##{element_dom_id(element)}"
167
172
  end
168
173
 
169
174
  end
@@ -3,7 +3,6 @@ module Alchemy
3
3
 
4
4
  include Alchemy::BaseHelper
5
5
  include Alchemy::ElementsHelper
6
- include Alchemy::PicturesHelper
7
6
  include Alchemy::UrlHelper
8
7
 
9
8
  def render_classes(classes=[])
@@ -479,7 +478,7 @@ module Alchemy
479
478
  Alchemy.loadAlchemyMenuBar({
480
479
  page_id: #{@page.id},
481
480
  route: '#{Alchemy.mount_point}',
482
- locale: '#{current_user.language || ::I18n.default_locale}'
481
+ locale: '#{current_user.language}'
483
482
  });
484
483
  } catch(e) {
485
484
  if(console){console.log(e)}
@@ -5,14 +5,6 @@
5
5
  module Alchemy
6
6
  module UrlHelper
7
7
 
8
- # Returns the correct params-hash for passing to show_page_path
9
- def show_page_path_params(page, optional_params={})
10
- url_params = {:level1 => nil, :level2 => nil, :level3 => nil, :urlname => page.urlname}
11
- url_params.update(optional_params)
12
- url_params.update(params_for_nested_url(page)) if configuration(:url_nesting)
13
- multi_language? ? url_params.update(:lang => page.language_code) : url_params
14
- end
15
-
16
8
  # Returns the path for rendering an alchemy page
17
9
  def show_alchemy_page_path(page, optional_params={})
18
10
  alchemy.show_page_path(show_page_path_params(page, optional_params))
@@ -23,22 +15,6 @@ module Alchemy
23
15
  alchemy.show_page_url(show_page_path_params(page, optional_params))
24
16
  end
25
17
 
26
- # Returns the correct params-hash for passing to show_picture_path
27
- def show_picture_path_params(picture, optional_params={})
28
- url_params = {:id => picture.id, :name => picture.urlname, :format => configuration(:image_output_format)}
29
- url_params.update(optional_params.update({:crop => optional_params[:crop] ? 'crop' : nil}))
30
- end
31
-
32
- # Returns the path for rendering an alchemy picture
33
- def show_alchemy_picture_path(picture, optional_params={})
34
- alchemy.show_picture_path(show_picture_path_params(picture, optional_params))
35
- end
36
-
37
- # Returns the url for rendering an alchemy picture
38
- def show_alchemy_picture_url(picture, optional_params={})
39
- alchemy.show_picture_url(show_picture_path_params(picture, optional_params))
40
- end
41
-
42
18
  # This helper returns a path for use inside a link_to helper.
43
19
  #
44
20
  # You may pass a page_layout or an urlname.
@@ -63,5 +39,48 @@ module Alchemy
63
39
  alchemy.show_page_path({:urlname => urlname, :lang => multi_language? ? session[:language_code] : nil}.merge(options.except(:page_layout, :urlname, :lang)))
64
40
  end
65
41
 
42
+ # This helper returns a path to picture for use inside a image_tag helper.
43
+ #
44
+ # Any additional options are passed to the url_helper, so you can add arguments to your url.
45
+ #
46
+ # Example:
47
+ #
48
+ # <%= image_tag show_alchemy_picture_path(picture, :size => '320x200', :format => :png) %>
49
+ #
50
+ def show_alchemy_picture_path(picture, optional_params={})
51
+ alchemy.show_picture_path(show_picture_path_params(picture, optional_params))
52
+ end
53
+
54
+ # This helper returns an url to picture for use inside a image_tag helper.
55
+ #
56
+ # Any additional options are passed to the url_helper, so you can add arguments to your url.
57
+ #
58
+ # Example:
59
+ #
60
+ # <%= image_tag show_alchemy_picture_url(picture, :size => '320x200', :format => :png) %>
61
+ #
62
+ def show_alchemy_picture_url(picture, optional_params={})
63
+ alchemy.show_picture_url(show_picture_path_params(picture, optional_params))
64
+ end
65
+
66
+ # Returns the correct params hash for passing to show_picture_path
67
+ def show_picture_path_params(picture, optional_params={})
68
+ url_params = {
69
+ :id => picture.id,
70
+ :name => picture.urlname,
71
+ :format => configuration(:image_output_format),
72
+ :sh => picture.security_token(optional_params)
73
+ }
74
+ url_params.update(optional_params.update({:crop => optional_params[:crop] ? 'crop' : nil}))
75
+ end
76
+
77
+ # Returns the correct params-hash for passing to show_page_path
78
+ def show_page_path_params(page, optional_params={})
79
+ url_params = {:level1 => nil, :level2 => nil, :level3 => nil, :urlname => page.urlname}
80
+ url_params.update(optional_params)
81
+ url_params.update(params_for_nested_url(page)) if configuration(:url_nesting)
82
+ multi_language? ? url_params.update(:lang => page.language_code) : url_params
83
+ end
84
+
66
85
  end
67
86
  end
@@ -28,7 +28,7 @@ module Alchemy
28
28
 
29
29
  attr_accessor :create_contents_after_create
30
30
 
31
- after_create :create_contents, :unless => Proc.new { |m| m.create_contents_after_create == false }
31
+ after_create :create_contents, :unless => proc { |e| e.create_contents_after_create == false }
32
32
 
33
33
  scope :trashed, where(:position => nil).order('updated_at DESC')
34
34
  scope :not_trashed, where(Element.arel_table[:position].not_eq(nil))
@@ -44,16 +44,16 @@ module Alchemy
44
44
 
45
45
  # Builds a new element as described in +/config/alchemy/elements.yml+
46
46
  def new_from_scratch(attributes)
47
- attributes.stringify_keys!
48
- return new if attributes['name'].blank?
47
+ attributes = attributes.dup.symbolize_keys
48
+ return new if attributes[:name].blank?
49
49
  return nil if descriptions.blank?
50
50
  # clean the name from cell name
51
- attributes['name'] = attributes['name'].split('#').first
52
- element_scratch = descriptions.detect { |m| m["name"] == attributes['name'] }
51
+ attributes[:name] = attributes[:name].split('#').first
52
+ element_scratch = descriptions.detect { |el| el['name'] == attributes[:name] }
53
53
  if element_scratch
54
- new(element_scratch.except(*FORBIDDEN_DEFINITION_ATTRIBUTES).merge(attributes))
54
+ new(element_scratch.merge(attributes).except(*FORBIDDEN_DEFINITION_ATTRIBUTES))
55
55
  else
56
- raise "Element description for #{attributes['name']} not found. Please check your elements.yml"
56
+ raise "Element description for #{attributes[:name]} not found. Please check your elements.yml"
57
57
  end
58
58
  end
59
59
 
@@ -81,6 +81,9 @@ module Alchemy
81
81
  raise LoadError, "Could not find elements.yml file! Please run: rails generate alchemy:scaffold"
82
82
  end
83
83
  element_definitions
84
+ rescue TypeError => e
85
+ Rails.logger.warn "\n++++ WARNING: Your elements.yml is empty.\n"
86
+ []
84
87
  end
85
88
  alias_method :definitions, :descriptions
86
89
 
@@ -153,8 +156,7 @@ module Alchemy
153
156
  "created_at",
154
157
  "updated_at",
155
158
  "creator_id",
156
- "updater_id",
157
- "cell_id"
159
+ "updater_id"
158
160
  ).merge(differences.stringify_keys)
159
161
  element = self.create!(attributes.merge(:create_contents_after_create => false))
160
162
  source.contents.each do |content|
@@ -309,7 +311,12 @@ module Alchemy
309
311
 
310
312
  # returns the description of the element with my name in element.yml
311
313
  def description
312
- self.class.descriptions.detect { |d| d['name'] == self.name }
314
+ description = self.class.descriptions.detect { |d| d['name'] == self.name }
315
+ if description.blank?
316
+ raise "Could not find element definition for #{self.name}. Please check your elements.yml"
317
+ else
318
+ return description
319
+ end
313
320
  end
314
321
  alias_method :definition, :description
315
322
 
@@ -459,12 +466,12 @@ module Alchemy
459
466
  essence_errors.each do |content_name, errors|
460
467
  errors.each do |error|
461
468
  messages << I18n.t(error,
462
- :scope => [:content_validations, self.name, content_name],
463
- :default => [
464
- "alchemy.content_validations.fields.#{content_name}.#{error}".to_sym,
465
- "alchemy.content_validations.errors.#{error}".to_sym
466
- ],
467
- :field => Content.translated_label_for(content_name)
469
+ :scope => [:content_validations, self.name, content_name],
470
+ :default => [
471
+ "alchemy.content_validations.fields.#{content_name}.#{error}".to_sym,
472
+ "alchemy.content_validations.errors.#{error}".to_sym
473
+ ],
474
+ :field => Content.translated_label_for(content_name)
468
475
  )
469
476
  end
470
477
  end
@@ -58,6 +58,8 @@ module Alchemy
58
58
  before_save :inherit_restricted_status, :if => proc { |page| !page.systempage? && page.parent && page.parent.restricted? }
59
59
  after_create :create_cells, :unless => :systempage?
60
60
  after_create :autogenerate_elements, :unless => proc { |page| page.systempage? || page.do_not_autogenerate }
61
+ after_update :trash_not_allowed_elements, :if => :page_layout_changed?
62
+ after_update :autogenerate_elements, :if => :page_layout_changed?
61
63
 
62
64
  scope :language_roots, where(:language_root => true)
63
65
  scope :layoutpages, where(:layoutpage => true)
@@ -66,9 +68,8 @@ module Alchemy
66
68
  scope :not_locked, where(:locked => false)
67
69
  scope :visible, where(:visible => true)
68
70
  scope :published, where(:public => true)
69
- scope :accessible, where(:restricted => false)
70
- scope :restricted, where(:restricted => true)
71
71
  scope :not_restricted, where(:restricted => false)
72
+ scope :restricted, where(:restricted => true)
72
73
  scope :public_language_roots, lambda {
73
74
  where(:language_root => true, :language_code => Language.all_codes_for_published, :public => true)
74
75
  }
@@ -339,7 +340,6 @@ module Alchemy
339
340
  description
340
341
  end
341
342
  end
342
-
343
343
  alias_method :definition, :layout_description
344
344
 
345
345
  def cell_definitions
@@ -562,21 +562,27 @@ module Alchemy
562
562
  # If the page has cells, it looks if there are elements to generate.
563
563
  #
564
564
  def autogenerate_elements
565
+ elements_already_on_page = self.elements.available.collect(&:name)
565
566
  elements = self.layout_description["autogenerate"]
566
567
  if elements.present?
567
568
  elements.each do |element|
568
- if self.has_cells? && (cell_definition = cell_definitions.detect { |c| c['elements'].include?(element) })
569
- cell = self.cells.find_by_name(cell_definition['name'])
570
- if cell
571
- attributes = {'page_id' => self.id, 'cell_id' => cell.id, 'name' => element}
572
- else
573
- raise "Cell not found for page #{self.inspect}"
574
- end
575
- else
576
- attributes = {'page_id' => self.id, 'name' => element}
577
- end
578
- Element.create_from_scratch(attributes)
569
+ next if elements_already_on_page.include?(element)
570
+ Element.create_from_scratch(attributes_for_element_name(element))
571
+ end
572
+ end
573
+ end
574
+
575
+ # Returns a hash of attributes for given element name
576
+ def attributes_for_element_name(element)
577
+ if self.has_cells? && (cell_definition = cell_definitions.detect { |c| c['elements'].include?(element) })
578
+ cell = self.cells.find_by_name(cell_definition['name'])
579
+ if cell
580
+ return {:page_id => self.id, :cell_id => cell.id, :name => element}
581
+ else
582
+ raise "Cell not found for page #{self.inspect}"
579
583
  end
584
+ else
585
+ return {:page_id => self.id, :name => element}
580
586
  end
581
587
  end
582
588
 
@@ -592,5 +598,10 @@ module Alchemy
592
598
  end
593
599
  end
594
600
 
601
+ # Trashes all elements that are not allowed for this page_layout.
602
+ def trash_not_allowed_elements
603
+ elements.select { |e| !definition['elements'].include?(e.name) }.map(&:trash)
604
+ end
605
+
595
606
  end
596
607
  end
@@ -141,5 +141,29 @@ module Alchemy
141
141
  pages.any? && pages.not_restricted.blank?
142
142
  end
143
143
 
144
+ # Returns a security token for signed picture rendering requests.
145
+ #
146
+ # Pass a params hash containing:
147
+ #
148
+ # size [String] (Optional)
149
+ # crop [Boolean] (Optional)
150
+ # crop_from [String] (Optional)
151
+ # crop_size [String] (Optional)
152
+ #
153
+ # to sign them.
154
+ #
155
+ def security_token(params = {})
156
+ @params = params.stringify_keys
157
+ @params.update({'crop' => @params['crop'] ? 'crop' : nil})
158
+ Digest::SHA1.hexdigest(secured_params)[0..15]
159
+ end
160
+
161
+ private
162
+
163
+ def secured_params
164
+ secret = Rails.configuration.secret_token
165
+ [id, @params['size'], @params['crop'], @params['crop_from'], @params['crop_size'], secret].join('-')
166
+ end
167
+
144
168
  end
145
169
  end
@@ -17,7 +17,7 @@
17
17
  :locals => @locals
18
18
  )
19
19
  ) %>');
20
- Alchemy.enableButton('.disabled.button');
20
+ Alchemy.Buttons.enable();
21
21
  Alchemy.growl('<%= t("Successfully added content") % {:content => @content.name_for_label} %>')
22
22
 
23
23
  <% end %>
@@ -6,7 +6,7 @@
6
6
  </div>
7
7
  <%- else -%>
8
8
  <%= form_for [:admin, @element], :remote => true, :class => "add_element_content" do |form| %>
9
- <div id="errors" style="display: none"></div>
9
+ <div id="errors"></div>
10
10
  <table>
11
11
  <tr>
12
12
  <td class="label">
@@ -1,14 +1,22 @@
1
1
  var $el;
2
+ var $element_area = $('#cell_<%= @cell_name -%>');
3
+ var element_html = '<%= escape_javascript render(:partial => "element", :object => @element, :locals => {:draggable => true}) -%>';
4
+
2
5
  <% if @cutted_element_id %>
3
6
  $('.element_editor[data-element-id="<%= @cutted_element_id %>"]').remove();
4
7
  <% end %>
5
8
 
6
9
  <% if @page.can_have_cells? %>
7
- Alchemy.selectOrCreateCellTab('<%= @cell.nil? ? "for_other_elements" : @cell.name -%>', '<%= @cell.nil? ? t("other Elements") : @cell.name_for_label -%>');
10
+ Alchemy.selectOrCreateCellTab('<%= @cell_name -%>', '<%= @cell.nil? ? t("other Elements") : @cell.name_for_label -%>');
11
+ <% end %>
12
+
13
+ <% if @insert_at_top %>
14
+ $element_area.prepend(element_html);
15
+ <% else %>
16
+ $element_area.append(element_html);
8
17
  <% end %>
9
18
 
10
- $('#cell_<%= @cell.nil? ? "for_other_elements" : @cell.name -%>').append('<%= escape_javascript render(:partial => "element", :object => @element, :locals => {:draggable => true}) -%>');
11
- $('#cell_<%= @cell.nil? ? "for_other_elements" : @cell.name -%>').sortable('refresh');
19
+ $element_area.sortable('refresh');
12
20
  Alchemy.growl('<%= t("successfully_added_element") -%>');
13
21
  Alchemy.closeCurrentWindow();
14
22
 
@@ -36,7 +36,7 @@
36
36
 
37
37
  Alchemy.ElementDirtyObserver($el);
38
38
  Alchemy.Datepicker('input[type="date"]', $el);
39
- Alchemy.ButtonObserver('button.button', $el);
39
+ Alchemy.Buttons.observe($el);
40
40
  Alchemy.overlayObserver("#element_<%= @element.id -%>");
41
41
 
42
42
  <% end %>
@@ -11,7 +11,7 @@
11
11
  </div>
12
12
  <div id="paste_element_tab">
13
13
  <%= form_for([:admin, @element], :remote => true, :id => 'paste_element_form') do |f| %>
14
- <div id="errors" style="display: none"></div>
14
+ <div id="paste_element_errors" class="errors"></div>
15
15
  <table>
16
16
  <tr>
17
17
  <td class="label">
@@ -19,6 +19,6 @@ $('#element_<%= @element.id %>_errors').html('<%= @error_message %><ul><li><%= @
19
19
  $("#element_<%= @element.id %>_errors").show();
20
20
  $('div.content_editor').removeClass('validation_failed');
21
21
  $('<%= @element.contents_with_errors.map { |content| "#" + content_dom_id(content) }.join(", ") %>').addClass('validation_failed');
22
- Alchemy.enableButton('button.button', $el);
22
+ Alchemy.Buttons.enable($el);
23
23
 
24
24
  <% end %>
@@ -30,7 +30,7 @@
30
30
 
31
31
  <div id="jscropper">
32
32
  <%= image_tag(
33
- alchemy.zoom_picture_path(:id => @essence_picture.picture.id, :name => @essence_picture.picture.urlname, :format => @options[:format] ),
33
+ alchemy.zoom_picture_path(:id => @essence_picture.picture.id, :name => @essence_picture.picture.urlname, :format => @options[:format], :sh => @essence_picture.picture.security_token),
34
34
  :id => 'imageToCrop',
35
35
  :onload => "Alchemy.ImageCropper.init(
36
36
  [#{@initial_box[:x1]}, #{@initial_box[:y1]}, #{@initial_box[:x2]}, #{@initial_box[:y2]}],
@@ -1,5 +1,5 @@
1
1
  <%= form_for [alchemy, :admin, @language], :remote => true, :html => {:style => 'width: 403px'} do |f| %>
2
- <div id="errors" style="display: none"></div>
2
+ <div id="errors"></div>
3
3
  <table>
4
4
  <tr>
5
5
  <td class="label"><%= f.label :name %></td>
@@ -1,7 +1,7 @@
1
1
  <%= form_for([:admin, @page], :remote => true, :html => {:id => 'new_page_form'}) do |f| %>
2
2
  <%= f.hidden_field(:parent_id) %>
3
3
  <%= f.hidden_field(:layoutpage) %>
4
- <div id="errors" style="display:none"></div>
4
+ <div id="errors"></div>
5
5
  <table id="new_page_form">
6
6
  <tr>
7
7
  <td class="label">
@@ -31,7 +31,7 @@
31
31
  alchemy.configure_admin_page_path(page),
32
32
  {
33
33
  :title => t('edit_page_properties'),
34
- :size => page.redirects_to_external? ? '410x270' : '410x660'
34
+ :size => page.redirects_to_external? ? '410x270' : '410x655'
35
35
  },
36
36
  :class => '',
37
37
  :title => t('edit_page_properties')
@@ -1,9 +1,11 @@
1
1
  <%= form_for([:admin, @page], :remote => true) do |f| %>
2
- <div id="errors" style="display: none"></div>
2
+ <div id="errors"></div>
3
3
  <table id="page_names">
4
4
  <tr>
5
5
  <td class="label"><%= t("page_type") %>: </td>
6
- <td class="value long"><p><%= @page.layout_display_name %></p></td>
6
+ <td class="select">
7
+ <%= f.select('page_layout', @page_layouts, {}, {:class => 'alchemy_selectbox long'}) %>
8
+ </td>
7
9
  </tr>
8
10
  <%- unless @page.layoutpage -%>
9
11
  <tr>
@@ -64,10 +66,12 @@
64
66
  </tr>
65
67
  <%- end -%>
66
68
  <tr>
67
- <td colspan="2" class="right"><%= f.button t("save"), :class => 'button' %></td>
69
+ <td colspan="2" class="submit">
70
+ <p class="foot_note">
71
+ *<%= t('pages.update.comma_seperated') %>
72
+ </p>
73
+ <%= f.button t("save"), :class => 'button' %>
74
+ </td>
68
75
  </tr>
69
76
  </table>
70
- <p class="foot_note">
71
- *<%= t('pages.update.comma_seperated') %>
72
- </p>
73
77
  <% end %>