alchemy_cms 3.1.0.rc1 → 3.1.0.rc2

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -10
  3. data/.teatro.yml +7 -0
  4. data/Gemfile +13 -13
  5. data/README.md +20 -3
  6. data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +3 -3
  7. data/app/assets/javascripts/alchemy/alchemy.uploader.js.coffee +5 -0
  8. data/app/controllers/alchemy/admin/essence_files_controller.rb +23 -3
  9. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +7 -2
  10. data/app/controllers/alchemy/admin/pictures_controller.rb +1 -4
  11. data/app/controllers/alchemy/base_controller.rb +3 -1
  12. data/app/controllers/alchemy/pages_controller.rb +3 -1
  13. data/app/models/alchemy/content.rb +0 -3
  14. data/app/models/alchemy/element.rb +1 -2
  15. data/app/models/alchemy/page/page_scopes.rb +3 -1
  16. data/app/models/alchemy/page/page_users.rb +10 -3
  17. data/app/models/alchemy/picture.rb +29 -6
  18. data/app/models/alchemy/picture/transformations.rb +14 -7
  19. data/app/views/alchemy/_menubar.html.erb +1 -1
  20. data/app/views/alchemy/admin/leave.html.erb +1 -1
  21. data/app/views/alchemy/essences/_essence_boolean_editor.html.erb +2 -1
  22. data/config/initializers/dragonfly.rb +0 -2
  23. data/lib/alchemy/engine.rb +0 -1
  24. data/lib/alchemy/locale.rb +15 -13
  25. data/lib/alchemy/upgrader.rb +1 -0
  26. data/lib/alchemy/upgrader/three_point_zero.rb +27 -9
  27. data/lib/alchemy/version.rb +1 -1
  28. data/lib/tasks/alchemy/tidy.rake +34 -16
  29. data/spec/controllers/admin/essence_files_controller_spec.rb +13 -2
  30. data/spec/controllers/admin/essence_pictures_controller_spec.rb +8 -0
  31. data/spec/controllers/pages_controller_spec.rb +42 -0
  32. data/spec/dummy/app/controllers/application_controller.rb +5 -1
  33. data/spec/dummy/app/models/dummy_user.rb +4 -0
  34. data/spec/dummy/bin/bundle +0 -0
  35. data/spec/dummy/bin/rails +0 -0
  36. data/spec/dummy/bin/rake +0 -0
  37. data/spec/dummy/config/environments/production.rb +1 -1
  38. data/spec/dummy/db/seeds.rb +1 -0
  39. data/spec/features/translation_integration_spec.rb +14 -11
  40. data/spec/models/page_spec.rb +143 -52
  41. data/spec/spec_helper.rb +0 -3
  42. data/spec/support/transformation_examples.rb +7 -0
  43. data/spec/views/essences/essence_boolean_editor_spec.rb +1 -0
  44. data/vendor/assets/javascripts/fileupload/jquery.fileupload-process.js +6 -3
  45. data/vendor/assets/javascripts/fileupload/jquery.fileupload-validate.js +5 -3
  46. data/vendor/assets/javascripts/fileupload/jquery.fileupload.js +97 -46
  47. data/vendor/assets/javascripts/fileupload/jquery.iframe-transport.js +11 -4
  48. metadata +6 -4
  49. data/lib/extensions/action_view.rb +0 -17
@@ -5,7 +5,7 @@
5
5
  <li><%= link_to _t(:edit_page), alchemy.edit_admin_page_path(@page) %></li>
6
6
  <li>
7
7
  <%= form_tag Alchemy.logout_path, method: 'delete' do %>
8
- <%= button _t(:logout) %>
8
+ <%= button_tag _t(:logout) %>
9
9
  <% end %>
10
10
  </li>
11
11
  </ul>
@@ -7,5 +7,5 @@
7
7
  </p>
8
8
  <%= form_tag Alchemy.logout_path, method: 'delete', class: 'buttons' do %>
9
9
  <label><%= _t('or to completely') %></label>
10
- <%= button _t(:logout), autofocus: true %>
10
+ <%= button_tag _t(:logout), autofocus: true %>
11
11
  <% end %>
@@ -9,7 +9,8 @@
9
9
  style: local_assigns.fetch(:html_options, {})[:style] %>
10
10
  <label for="<%= content.form_field_id %>" style="display: inline">
11
11
  <%= render_content_name(content) %>
12
- <%= delete_content_link(content) %>
13
12
  </label>
13
+ <%= delete_content_link(content) %>
14
+ <%= render_hint_for(content) %>
14
15
  </div>
15
16
  <% end %>
@@ -6,8 +6,6 @@ Dragonfly.app(:alchemy_pictures).configure do
6
6
  datastore :file,
7
7
  root_path: Rails.root.join('uploads/pictures').to_s,
8
8
  store_meta: false
9
- url_format '/pictures/:job/:basename.:format'
10
- url_path_prefix Alchemy::MountPoint.get
11
9
  end
12
10
 
13
11
  # Attachments
@@ -45,7 +45,6 @@ require_relative './touching'
45
45
 
46
46
  # Require hacks
47
47
  require_relative './kaminari/scoped_pagination_url_helper'
48
- require_relative '../extensions/action_view'
49
48
 
50
49
  # Middleware
51
50
  require_relative './middleware/rescue_old_cookies'
@@ -10,20 +10,17 @@ module Alchemy
10
10
 
11
11
  # Sets Alchemy's GUI translation.
12
12
  #
13
- # * If one passed a locale via +params[:locale]+ it uses this.
14
- # * Or it tries to get users preffered language.
15
- # * If not found it guesses the language from the browser locale.
16
- # * If that also fails it takes the default.
13
+ # Uses the most preferred locale or falls back to the default locale if none of the preferred is available.
17
14
  #
18
15
  # It respects the default translation from your +config/application.rb+ +default_locale+ config option.
19
16
  #
20
17
  def set_translation
21
18
  if locale_change_needed?
22
- ::I18n.locale = session[:alchemy_locale] = locale_from_params ||
23
- locale_from_user || locale_from_browser || ::I18n.default_locale
19
+ locale = available_locale || ::I18n.default_locale
24
20
  else
25
- ::I18n.locale = session[:alchemy_locale]
21
+ locale = session[:alchemy_locale]
26
22
  end
23
+ ::I18n.locale = session[:alchemy_locale] = locale
27
24
  end
28
25
 
29
26
  # Checks if we need to change to locale or not.
@@ -31,12 +28,17 @@ module Alchemy
31
28
  params[:locale].present? || session[:alchemy_locale].blank?
32
29
  end
33
30
 
34
- # Try to get the locale from +params[:locale]+.
35
- def locale_from_params
36
- return if params[:locale].blank?
37
- if ::I18n.available_locales.include?(params[:locale].to_sym)
38
- params[:locale]
39
- end
31
+ # Returns either the most preferred locale that is within the list of available locales or nil
32
+ #
33
+ # The availability of the locales is checked in the exact order of either
34
+ #
35
+ # * the passed parameter: +params[:locale]+
36
+ # * the user's locale
37
+ # * the locale of the browser
38
+ #
39
+ def available_locale
40
+ locales = [params[:locale], locale_from_user, locale_from_browser].compact
41
+ locales.detect { |locale| ::I18n.available_locales.include?(locale.to_sym) }
40
42
  end
41
43
 
42
44
  # Try to get the locale from user settings.
@@ -5,6 +5,7 @@ module Alchemy
5
5
 
6
6
  Dir["#{File.dirname(__FILE__)}/upgrader/*.rb"].each { |f| require f }
7
7
 
8
+ extend Alchemy::Upgrader::ThreePointOne
8
9
  extend Alchemy::Upgrader::ThreePointZero
9
10
 
10
11
  class << self
@@ -3,16 +3,20 @@ module Alchemy
3
3
  private
4
4
 
5
5
  def rename_registered_role_ro_member
6
- desc 'Rename the `registered` user role to `member`'
7
- registered_users = Alchemy.user_class.where("alchemy_roles LIKE '%registered%'")
8
- if registered_users.any?
9
- registered_users.each do |user|
10
- roles = user.read_attribute(:alchemy_roles).sub(/registered/, 'member')
11
- user.update_column(:alchemy_roles, roles)
12
- log "Renamed #{user.inspect} role to `member`"
6
+ if Alchemy.user_class.column_names.include?('alchemy_roles')
7
+ desc 'Rename the `registered` user role to `member`'
8
+ registered_users = Alchemy.user_class.where("alchemy_roles LIKE '%registered%'")
9
+ if registered_users.any?
10
+ registered_users.each do |user|
11
+ roles = user.read_attribute(:alchemy_roles).sub(/registered/, 'member')
12
+ user.update_column(:alchemy_roles, roles)
13
+ log "Renamed #{user.inspect} role to `member`"
14
+ end
15
+ else
16
+ log 'No users with `registered` role found.', :skip
13
17
  end
14
18
  else
15
- log 'No users with `registered` role found.', :skip
19
+ log 'No users with `alchemy_roles` database column found.', :skip
16
20
  end
17
21
  end
18
22
 
@@ -29,7 +33,7 @@ module Alchemy
29
33
  end
30
34
  end
31
35
 
32
- def alchemy_3_todos
36
+ def alchemy_3_0_todos
33
37
  notice = <<-NOTE
34
38
 
35
39
  Alchemy User Class Removed
@@ -67,6 +71,20 @@ also read the official TinyMCE documentation in how to upgrade.
67
71
  Alchemy default TinyMCE config: https://github.com/magiclabs/alchemy_cms/blob/master/lib/alchemy/tinymce.rb#L5-L19
68
72
  Offical TinyMCE documentation: http://www.tinymce.com/wiki.php/Configuration
69
73
 
74
+
75
+ Essence Validation Syntax changed
76
+ ---------------------------------
77
+
78
+ The API of the format validations for essences has changed.
79
+ You can now define individual format matchers in the config.yml.
80
+
81
+ * `format_as` and `format_with` options has been removed and renamed to simply `format`
82
+
83
+ Pleae have a look at this commit:
84
+ https://github.com/AlchemyCMS/alchemy_cms/commit/44866dbebaed00ffa3b77201f93a04616001b955
85
+
86
+ for a detailed explanation.
87
+
70
88
  NOTE
71
89
  todo notice, 'Alchemy v3.0 changes'
72
90
  end
@@ -1,5 +1,5 @@
1
1
  module Alchemy
2
- VERSION = "3.1.0.rc1"
2
+ VERSION = "3.1.0.rc2"
3
3
 
4
4
  def self.version
5
5
  VERSION
@@ -5,16 +5,21 @@ namespace :alchemy do
5
5
  task :up do
6
6
  Rake::Task['alchemy:tidy:cells'].invoke
7
7
  Rake::Task['alchemy:tidy:element_positions'].invoke
8
+ Rake::Task['alchemy:tidy:content_positions'].invoke
8
9
  end
9
10
 
10
11
  desc "Creates missing cells for pages."
11
12
  task :cells => :environment do
12
- cells = Alchemy::Cell.definitions
13
- page_layouts = Alchemy::PageLayout.all
14
- if cells && page_layouts
15
- Alchemy::Tidy.create_missing_cells(page_layouts, cells)
13
+ if !File.exist? Rails.root.join('config/alchemy/cells.yml')
14
+ puts "No page cell definitions found."
16
15
  else
17
- puts "No page layouts or cell definitions found."
16
+ cells = Alchemy::Cell.definitions
17
+ page_layouts = Alchemy::PageLayout.all
18
+ if cells && page_layouts
19
+ Alchemy::Tidy.create_missing_cells(page_layouts, cells)
20
+ else
21
+ puts "No page layouts or cell definitions found."
22
+ end
18
23
  end
19
24
  end
20
25
 
@@ -23,6 +28,10 @@ namespace :alchemy do
23
28
  Alchemy::Tidy.update_element_positions
24
29
  end
25
30
 
31
+ desc "Fixes content positions."
32
+ task :content_positions => [:environment] do
33
+ Alchemy::Tidy.update_content_positions
34
+ end
26
35
  end
27
36
  end
28
37
 
@@ -31,7 +40,6 @@ module Alchemy
31
40
  extend Shell
32
41
 
33
42
  def self.create_missing_cells(page_layouts, cells)
34
- desc "Create missing cells"
35
43
  page_layouts.each do |layout|
36
44
  next if layout['cells'].blank?
37
45
  cells_for_layout = cells.select { |cell| layout['cells'].include? cell['name'] }
@@ -51,8 +59,10 @@ module Alchemy
51
59
  end
52
60
 
53
61
  def self.update_element_positions
54
- desc "Update element positions"
55
62
  Alchemy::Page.all.each do |page|
63
+ if page.elements.any?
64
+ puts "\n## Updating element positions of page `#{page.name}`"
65
+ end
56
66
  page.elements.group_by(&:cell_id).each do |cell_id, elements|
57
67
  elements.each_with_index do |element, idx|
58
68
  position = idx + 1
@@ -60,23 +70,31 @@ module Alchemy
60
70
  log "Updating position for element ##{element.id} to #{position}"
61
71
  element.update_column(:position, position)
62
72
  else
63
- log "Position for element ##{element.id} is already correct", :skip
73
+ log "Position for element ##{element.id} is already correct (#{position})", :skip
64
74
  end
65
75
  end
66
76
  end
67
77
  end
68
78
  end
69
79
 
70
- # TODO: implement remove_orphan_cells
71
- def self.remove_orphan_cells(page_layouts, cells)
72
- puts "== Remove cell orphans"
73
- Alchemy::Cell.all.each do |cell|
74
- if cells.detect { |cell| cell['name'] == cell.name }.nil?
75
- # move elements to page or into another cell of page
76
- # remove cell from database
80
+ def self.update_content_positions
81
+ Alchemy::Element.all.each do |element|
82
+ if element.contents.any?
83
+ puts "\n## Updating content positions of element `#{element.name}`"
84
+ end
85
+ element.contents.group_by(&:essence_type).each do |essence_type, contents|
86
+ puts "-> Contents of type `#{essence_type}`"
87
+ contents.each_with_index do |content, idx|
88
+ position = idx + 1
89
+ if content.position != position
90
+ log "Updating position for content ##{content.id} to #{position}"
91
+ content.update_column(:position, position)
92
+ else
93
+ log "Position for content ##{content.id} is already correct (#{position})", :skip
94
+ end
95
+ end
77
96
  end
78
97
  end
79
98
  end
80
-
81
99
  end
82
100
  end
@@ -29,17 +29,22 @@ module Alchemy
29
29
  end
30
30
 
31
31
  describe '#update' do
32
+ let(:essence_file) { FactoryGirl.create(:essence_file) }
33
+
32
34
  before do
33
35
  expect(EssenceFile).to receive(:find).and_return(essence_file)
34
36
  end
35
37
 
36
38
  it "should update the attributes of essence_file" do
37
- expect(essence_file).to receive(:update).and_return(true)
38
- xhr :put, :update, id: essence_file.id
39
+ xhr :put, :update, id: essence_file.id, essence_file: {title: 'new title', css_class: 'left'}
40
+ expect(essence_file.title).to eq 'new title'
41
+ expect(essence_file.css_class).to eq 'left'
39
42
  end
40
43
  end
41
44
 
42
45
  describe '#assign' do
46
+ let(:content) { create(:content) }
47
+
43
48
  before do
44
49
  expect(Content).to receive(:find_by).and_return(content)
45
50
  expect(Attachment).to receive(:find_by).and_return(attachment)
@@ -55,6 +60,12 @@ module Alchemy
55
60
  expect(content.essence).to receive(:attachment=).with(attachment)
56
61
  xhr :put, :assign, content_id: content.id, attachment_id: attachment.id
57
62
  end
63
+
64
+ it "updates the @content.updated_at column" do
65
+ expect {
66
+ xhr :put, :assign, content_id: content.id, attachment_id: attachment.id
67
+ }.to change(content, :updated_at)
68
+ end
58
69
  end
59
70
  end
60
71
  end
@@ -179,6 +179,8 @@ module Alchemy
179
179
  end
180
180
 
181
181
  describe '#assign' do
182
+ let(:content) { create(:content) }
183
+
182
184
  before do
183
185
  expect(Content).to receive(:find).and_return(content)
184
186
  expect(content).to receive(:essence).at_least(:once).and_return(essence)
@@ -189,6 +191,12 @@ module Alchemy
189
191
  xhr :put, :assign, content_id: '1', picture_id: '1'
190
192
  expect(assigns(:content).essence.picture).to eq(picture)
191
193
  end
194
+
195
+ it "updates the content timestamp" do
196
+ expect {
197
+ xhr :put, :assign, content_id: '1', picture_id: '1'
198
+ }.to change(content, :updated_at)
199
+ end
192
200
  end
193
201
  end
194
202
  end
@@ -229,5 +229,47 @@ module Alchemy
229
229
  end
230
230
  end
231
231
  end
232
+
233
+ describe '#cache_page?' do
234
+ subject { controller.send(:cache_page?) }
235
+
236
+ before do
237
+ Rails.application.config.action_controller.perform_caching = true
238
+ controller.instance_variable_set('@page', page)
239
+ end
240
+
241
+ it 'returns true when everthing is alright' do
242
+ expect(subject).to be true
243
+ end
244
+
245
+ it 'returns false when the Rails app does not perform caching' do
246
+ Rails.application.config.action_controller.perform_caching = false
247
+ expect(subject).to be false
248
+ end
249
+
250
+ it 'returns false when there is no page' do
251
+ controller.instance_variable_set('@page', nil)
252
+ expect(subject).to be false
253
+ end
254
+
255
+ it 'returns false when caching is deactivated in the Alchemy config' do
256
+ allow(Alchemy::Config).to receive(:get).with(:cache_pages).and_return(false)
257
+ expect(subject).to be false
258
+ end
259
+
260
+ it 'returns false when the page layout is set to cache = false' do
261
+ page_layout = PageLayout.get('news')
262
+ page_layout['cache'] = false
263
+ allow(PageLayout).to receive(:get).with('news').and_return(page_layout)
264
+ expect(subject).to be false
265
+ end
266
+
267
+ it 'returns false when the page layout is set to searchresults = true' do
268
+ page_layout = PageLayout.get('news')
269
+ page_layout['searchresults'] = true
270
+ allow(PageLayout).to receive(:get).with('news').and_return(page_layout)
271
+ expect(subject).to be false
272
+ end
273
+ end
232
274
  end
233
275
  end
@@ -6,6 +6,10 @@ class ApplicationController < ActionController::Base
6
6
  private
7
7
 
8
8
  def current_user
9
- nil
9
+ if Rails.env.test?
10
+ nil
11
+ else
12
+ DummyUser.new(email: "dummy@alchemy.com")
13
+ end
10
14
  end
11
15
  end
@@ -4,4 +4,8 @@ class DummyUser < ActiveRecord::Base
4
4
  def self.logged_in
5
5
  []
6
6
  end
7
+
8
+ def alchemy_roles
9
+ %w(admin)
10
+ end
7
11
  end
File without changes
File without changes
File without changes
@@ -27,7 +27,7 @@ Dummy::Application.configure do
27
27
  # config.assets.css_compressor = :sass
28
28
 
29
29
  # Do not fallback to assets pipeline if a precompiled asset is missed.
30
- config.assets.compile = false
30
+ config.assets.compile = true
31
31
 
32
32
  # Generate digests for assets URLs.
33
33
  config.assets.digest = true
@@ -0,0 +1 @@
1
+ Alchemy::Seeder.seed!
@@ -2,17 +2,19 @@ require 'spec_helper'
2
2
 
3
3
  describe "Translation integration" do
4
4
  context "in admin backend" do
5
- before { authorize_as_admin(mock_model('DummyUser', alchemy_roles: %w(admin), language: 'de')) }
5
+ let(:dummy_user) { mock_model('DummyUser', alchemy_roles: %w(admin), language: 'de') }
6
+
7
+ before { authorize_as_admin(dummy_user) }
6
8
 
7
9
  it "should be possible to set the locale of the admin backend via params" do
8
- visit admin_dashboard_path(locale: 'de')
9
- expect(page).to have_content('Willkommen')
10
+ visit admin_dashboard_path(locale: 'nl')
11
+ expect(page).to have_content('Welkom')
10
12
  end
11
13
 
12
14
  it "should store the current locale in the session" do
13
- visit admin_dashboard_path(locale: 'de')
15
+ visit admin_dashboard_path(locale: 'nl')
14
16
  visit admin_dashboard_path
15
- expect(page).to have_content('Willkommen')
17
+ expect(page).to have_content('Welkom')
16
18
  end
17
19
 
18
20
  it "should be possible to change the current locale in the session" do
@@ -34,14 +36,15 @@ describe "Translation integration" do
34
36
  visit admin_dashboard_path
35
37
  expect(page).to have_content('Willkommen')
36
38
  end
37
- end
38
39
 
39
- context "with translated header" do
40
- before { Capybara.current_driver = :rack_test_translated_header }
40
+ context "if user has no preferred locale" do
41
+ let(:dummy_user) { mock_model('DummyUser', alchemy_roles: %w(admin), language: nil) }
41
42
 
42
- it "should use the browsers language setting if no other parameter is given" do
43
- visit admin_dashboard_path
44
- expect(page).to have_content('Willkommen')
43
+ it "should use the browsers language setting" do
44
+ page.driver.header 'ACCEPT-LANGUAGE', 'es-ES'
45
+ visit admin_dashboard_path
46
+ expect(page).to have_content('Bienvenido')
47
+ end
45
48
  end
46
49
  end
47
50
  end