alchemy_cms 2.3.2 → 2.4.beta2

Sign up to get free protection for your applications and to get access to all the features.
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 %>