alchemy_cms 2.1.beta5 → 2.1.beta6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/Gemfile +1 -1
  2. data/README.md +14 -0
  3. data/alchemy_cms.gemspec +1 -1
  4. data/app/assets/javascripts/alchemy/alchemy.base.js +8 -2
  5. data/app/assets/javascripts/alchemy/alchemy.dragndrop.js.erb +1 -1
  6. data/app/assets/javascripts/alchemy/alchemy.link_overlay.js +1 -10
  7. data/app/assets/javascripts/alchemy/alchemy.routes.js.erb +9 -9
  8. data/app/assets/stylesheets/alchemy/base.css.scss +68 -66
  9. data/app/assets/stylesheets/alchemy/elements.css.scss +3 -2
  10. data/app/assets/stylesheets/alchemy/jquery-ui.alchemy.css.scss +1 -1
  11. data/app/assets/stylesheets/alchemy/jquery.Jcrop.css.scss +1 -1
  12. data/app/assets/stylesheets/alchemy/jquery.sb.css.scss +1 -1
  13. data/app/assets/stylesheets/alchemy/tinymce_content.css.scss +1 -1
  14. data/app/assets/stylesheets/alchemy/tinymce_dialog.css.scss +1 -1
  15. data/app/controllers/alchemy/admin/base_controller.rb +1 -1
  16. data/app/controllers/alchemy/admin/contents_controller.rb +1 -1
  17. data/app/controllers/alchemy/admin/elements_controller.rb +2 -1
  18. data/app/controllers/alchemy/admin/pages_controller.rb +18 -8
  19. data/app/controllers/alchemy/admin/resources_controller.rb +1 -1
  20. data/app/controllers/alchemy/pages_controller.rb +14 -2
  21. data/app/helpers/alchemy/admin/base_helper.rb +2 -2
  22. data/app/helpers/alchemy/admin/elements_helper.rb +1 -1
  23. data/app/helpers/alchemy/admin/essences_helper.rb +1 -1
  24. data/app/helpers/alchemy/base_helper.rb +0 -8
  25. data/app/helpers/alchemy/essences_helper.rb +1 -2
  26. data/app/helpers/alchemy/pages_helper.rb +3 -3
  27. data/app/models/alchemy/content.rb +27 -3
  28. data/app/models/alchemy/element.rb +2 -2
  29. data/app/models/alchemy/page.rb +4 -4
  30. data/app/models/alchemy/user.rb +5 -1
  31. data/app/views/alchemy/admin/clipboard/insert.js.erb +9 -9
  32. data/app/views/alchemy/admin/dashboard/index.html.erb +1 -1
  33. data/app/views/alchemy/admin/elements/create.js.erb +26 -19
  34. data/app/views/alchemy/admin/essence_pictures/assign.js.erb +1 -1
  35. data/app/views/alchemy/admin/essence_pictures/edit.html.erb +4 -4
  36. data/app/views/alchemy/admin/essence_pictures/update.js.erb +1 -1
  37. data/app/views/alchemy/admin/layoutpages/index.html.erb +1 -14
  38. data/app/views/alchemy/admin/pages/_external_link.html.erb +3 -13
  39. data/app/views/alchemy/admin/pages/index.html.erb +1 -14
  40. data/app/views/alchemy/admin/partials/_language_tree_select.html.erb +22 -0
  41. data/app/views/alchemy/admin/partials/_pagination_links.html.erb +3 -1
  42. data/app/views/alchemy/admin/pictures/update.js.erb +2 -0
  43. data/app/views/alchemy/admin/trash/index.html.erb +1 -1
  44. data/app/views/alchemy/admin/users/_user.html.erb +1 -1
  45. data/config/locales/alchemy.de.yml +29 -17
  46. data/config/locales/alchemy.en.yml +5 -4
  47. data/lib/alchemy/capistrano.rb +5 -0
  48. data/lib/alchemy/i18n.rb +1 -1
  49. data/lib/alchemy/page_layout.rb +1 -1
  50. data/lib/alchemy/scoped_pagination_link_renderer.rb +27 -0
  51. data/lib/alchemy/version.rb +1 -1
  52. data/lib/alchemy_cms.rb +1 -1
  53. data/spec/controllers/admin/contents_controller_spec.rb +19 -0
  54. data/spec/controllers/admin/pages_controller_spec.rb +19 -0
  55. data/spec/controllers/base_controller_spec.rb +1 -1
  56. data/spec/controllers/pages_controller_spec.rb +62 -0
  57. data/spec/dummy/app/views/layouts/.gitkeep +0 -0
  58. data/spec/integration/admin/pages_controller_spec.rb +42 -13
  59. data/spec/integration/pages_controller_spec.rb +2 -2
  60. data/spec/models/content_spec.rb +40 -0
  61. data/spec/models/element_spec.rb +50 -0
  62. data/spec/models/page_spec.rb +45 -1
  63. data/spec/routing_spec.rb +27 -29
  64. data/spec/spec_helper.rb +2 -2
  65. metadata +40 -36
  66. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
@@ -0,0 +1,22 @@
1
+ <div class="button_with_label">
2
+ <%= select_tag(
3
+ 'language',
4
+ options_for_select(@languages.map { |l| [l.name, l.id] }, session[:language_id]),
5
+ :id => 'language_tree_select',
6
+ :class => 'short'
7
+ ) %>
8
+ <label><%= t("Language tree") %></label>
9
+ </div>
10
+
11
+ <% content_for :javascripts do %>
12
+ <script type="text/javascript" charset="utf-8">
13
+ (function($) {
14
+ $('#language_tree_select').on('change', function() {
15
+ Alchemy.pleaseWaitOverlay();
16
+ $.get('<%= switch_language_admin_pages_path %>', {
17
+ language_id: this.value
18
+ });
19
+ });
20
+ })(jQuery);
21
+ </script>
22
+ <% end %>
@@ -1,5 +1,7 @@
1
1
  <%= will_paginate(
2
2
  items,
3
3
  :previous_label => '&laquo; ' + t('pagination.previous_page'),
4
- :next_label => t('pagination.next_page') + ' &raquo;'
4
+ :next_label => t('pagination.next_page') + ' &raquo;',
5
+ :renderer => 'Alchemy::ScopedPaginationLinkRenderer',
6
+ :params => defined?(scope) ? {:scope => scope} : nil
5
7
  ) %>
@@ -1 +1,3 @@
1
1
  Alchemy.growl('<%= @message %>');
2
+ $('.inplace-edit').remove();
3
+ $("#picture_#{@picture.id}").replaceWith('<%= escape_javascript(render("picture", :picture => @picture)) %>');
@@ -6,7 +6,7 @@
6
6
  <%- else -%>
7
7
  <div class="info">
8
8
  <%= render_icon('info') %>
9
- <%= t('Drag an element over to the element window to restore it.') %>
9
+ <%= t('Drag an element over to the element window to restore it') %>
10
10
  </div>
11
11
  <div id="trash_items">
12
12
  <%- @elements.each do |element| -%>
@@ -8,7 +8,7 @@
8
8
  <td><%= user.lastname -%></td>
9
9
  <td class="email"><%= user.email %></td>
10
10
  <td><%= t(user.language, :scope => 'translations') %></td>
11
- <td class="role"><%= t("user_roles.#{user.role}") %></td>
11
+ <td class="role"><%= user.human_role_name %></td>
12
12
  <td class="tools">
13
13
  <%- permitted_to?(:destroy, :alchemy_admin_users) do -%>
14
14
  <%= link_to_confirmation_window(
@@ -2,9 +2,6 @@
2
2
 
3
3
  de:
4
4
 
5
- yes: "Ja"
6
- no: "Nein"
7
-
8
5
  # = Alchemy Translations
9
6
  # All translations used in Alchemy CMS are inside this alchemy namespace.
10
7
  alchemy:
@@ -193,7 +190,7 @@ de:
193
190
  "Do you really want to clear the clipboard?": "Wollen Sie die Zwischenablage wirklich leeren?"
194
191
  "Do you really want to clear the trash?": "Wollen Sie den Papierkorb wirklich leeren?"
195
192
  "Do you really want to delete this content?": "Wollen Sie diesen Inhalt wirklich löschen?"
196
- "Drag an element over to the element window to restore it.": "Ziehen Sie ein Element mit der Maus in das Elemente Fenster, um es wieder herzustellen."
193
+ "Drag an element over to the element window to restore it": "Ziehen Sie ein Element mit der Maus in das Elemente Fenster, um es wieder herzustellen."
197
194
  "Edit Picturemask": "Bildmaske bearbeiten"
198
195
  "Element trashed": "Das Element wurde in den Papierkorb gelegt"
199
196
  "Error with the Flash® Uploader!": "Fehler mit dem Flash® Uploader!"
@@ -210,6 +207,7 @@ de:
210
207
  "If you have any problems using the Flash uploader you can switch to": "Sollten Sie Probleme mit dem Flash® Uploader haben, wechseln Sie einfach zur %{link}"
211
208
  "Image missing": "Bild fehlt"
212
209
  "Image size": "Bildgröße"
210
+ "Image updated successfully": "Bild wurde gespeichert"
213
211
  "Index Error after saving Element. Please try again!": "Indizierungsfehler beim Speichern des Elements. Bitte erneut versuchen!"
214
212
  "Language successfully created.": "Sprache wurde erfolgreich erstellt."
215
213
  "Language successfully destroyed.": "Sprache wurde erfolgreich gelöscht."
@@ -231,12 +229,12 @@ de:
231
229
  "Page saved": "%{name} wurde gespeichert"
232
230
  "Page Preview": "Seitenvorschau"
233
231
  "Page cache flushed": "Seitencache wurde geleert"
234
- "Page not public": "Seite nicht öffentlich"
235
- "Page not restricted": "Seite nicht geschützt"
236
- "Page not visible": "Seite nicht in der Navigation sichtbar"
237
- "Page public": "Seite öffentlich"
238
- "Page restricted": "Seite geschützt"
239
- "Page visible": "Seite in der Navigation sichtbar"
232
+ "Page not public": "Seite ist nicht veröffentlicht"
233
+ "Page not restricted": "Seite ist nicht Passwort geschützt"
234
+ "Page not visible": "Seite ist nicht in der Navigation sichtbar"
235
+ "Page public": "Seite ist veröffentlicht"
236
+ "Page restricted": "Seite ist Passwort geschützt"
237
+ "Page visible": "Seite ist in der Navigation sichtbar"
240
238
  "Pages order saved": "Seitensortierung wurde gespeichert"
241
239
  "Password": "Passwort"
242
240
  "Paste from clipboard": "Aus Zwischenablage"
@@ -434,7 +432,7 @@ de:
434
432
  no_search_results: "Keine Suchergebnisse."
435
433
  "not a valid image": "Keine valide Bilddatei."
436
434
  "other Elements": "sonst. Elemente"
437
- "Page created.": "Seite '%{name}' wurde erstellt."
435
+ "Page created": "Seite '%{name}' wurde erstellt."
438
436
  page_for_links:
439
437
  choose_page: "%{name} wählen"
440
438
  page_locked: "Die Seite ist gesperrt"
@@ -682,6 +680,20 @@ de:
682
680
  name: "Name"
683
681
  public: "sichtbar"
684
682
 
683
+ alchemy/essence_picture:
684
+ caption: "Untertitel"
685
+ title: "Titel"
686
+ alt_tag: "Alternativ-Text"
687
+ link: Link
688
+ link_class_name: "Link CSS-Klasse"
689
+ link_title: Link-Titel
690
+ css_class: CSS-Klasse
691
+ link_target: Link-Ziel
692
+ render_size: Darstellungsgröße
693
+ crop_from: Bildmaskenursprung
694
+ crop_size: Bildmaskenausmaß
695
+ picture_id: Bild
696
+
685
697
  alchemy/language:
686
698
  code: "Sprachkürzel"
687
699
  default: "Standardsprache"
@@ -695,19 +707,19 @@ de:
695
707
  language: "Sprache"
696
708
  locked: "Die Seite ist gesperrt"
697
709
  locked_by: "Gesperrt durch"
698
- meta_description: "Meta Beschreibung"
699
- meta_keywords: "Meta Schlagwörter"
710
+ meta_description: "Seitenbeschreibung"
711
+ meta_keywords: "Suchbegriffe"
700
712
  name: "Name"
701
713
  page_layout: "Seitentyp"
702
- public: "Seite veröffentlichen"
703
- resctricted: "Seite schützen"
714
+ public: "veröffentlicht"
715
+ restricted: "Passwort geschützt"
704
716
  robot_follow: "den Robot Links folgen lassen"
705
717
  robot_index: "durch Robot indizieren"
706
- sitemap: "in der Seitemap anzeigen"
718
+ sitemap: "in der Seitenübersicht sichtbar"
707
719
  title: "Seitentitel"
708
720
  updated_at: "Aktualisiert am"
709
721
  urlname: "URL-Name"
710
- visible: "in der Navigation anzeigen"
722
+ visible: "in der Navigation sichtbar"
711
723
 
712
724
  alchemy/picture:
713
725
  image_filename: "Dateiname"
@@ -208,6 +208,7 @@ en:
208
208
  document: "File"
209
209
  documents: "Files"
210
210
  download_file: "Download file '%{filename}'"
211
+ "Drag an element over to the element window to restore it": "Drag an element over to the element window to restore it."
211
212
  drag_to_sort: "Drag'n'Drop to sort images"
212
213
  edit_file_properties: "Edit Fileproperties"
213
214
  edit_image_properties: "Edit image properties."
@@ -278,7 +279,7 @@ en:
278
279
  no_more_elements_to_add: "No more elements available."
279
280
  no_search_results: "Your search did not return any results."
280
281
  "not a valid image": "This is not an valid image."
281
- "Page created.": "Page: '%{name}' created."
282
+ "Page created": "Page: '%{name}' created."
282
283
  page_for_links.choose_page: "Choose %{name}"
283
284
  page_locked: "This page is locked by another user."
284
285
  page_properties: "page properties"
@@ -503,14 +504,14 @@ en:
503
504
  name: "Name"
504
505
  page_layout: "Pagetype"
505
506
  public: "public"
506
- resctricted: "restricted"
507
+ restricted: "restricted"
507
508
  robot_follow: "robot may follow links"
508
509
  robot_index: "allow robot to index"
509
- sitemap: "show in sitemap"
510
+ sitemap: "visible in sitemap"
510
511
  title: "Title"
511
512
  updated_at: "Updated at"
512
513
  urlname: "Urlname"
513
- visible: "show in navigation"
514
+ visible: "visible in navigation"
514
515
 
515
516
  alchemy/picture:
516
517
  image_filename: "Filename"
@@ -49,6 +49,11 @@ Capistrano::Configuration.instance(:must_exist).load do
49
49
 
50
50
  end
51
51
 
52
+ desc "Upgrades production database to current Alchemy CMS version"
53
+ task :upgrade do
54
+ run "cd #{current_path} && RAILS_ENV=production #{rake} alchemy:upgrade"
55
+ end
56
+
52
57
  namespace :database_yml do
53
58
 
54
59
  desc "Creates the database.yml file"
@@ -22,7 +22,7 @@ module Alchemy
22
22
  #
23
23
  def self.t(msg, *args)
24
24
  options = args.extract_options!
25
- options[:default] = options[:default] ? options[:default] : msg.humanize
25
+ options[:default] = options[:default] ? options[:default] : msg.to_s.humanize
26
26
  scope = ['alchemy']
27
27
  case options[:scope].class.name
28
28
  when "Array"
@@ -61,7 +61,7 @@ module Alchemy
61
61
  def self.get_layouts_for_select(language_id, layoutpage = false)
62
62
  layouts_for_select = [ [ Alchemy::I18n.t("Please choose"), "" ] ]
63
63
  selectable_layouts(language_id, layoutpage).each do |layout|
64
- display_name = Alchemy::I18n.t("alchemy.page_layout_names.#{layout['name']}", :default => layout['name'].camelize)
64
+ display_name = Alchemy::I18n.t("page_layout_names.#{layout['name']}", :default => layout['name'].camelize)
65
65
  layouts_for_select << [display_name, layout["name"]]
66
66
  end
67
67
  layouts_for_select
@@ -0,0 +1,27 @@
1
+ # A custom WillPaginate LinkRenderer Class for scoping the urls.
2
+ require 'will_paginate/view_helpers/action_view'
3
+
4
+ module Alchemy
5
+ class ScopedPaginationLinkRenderer < WillPaginate::ActionView::LinkRenderer
6
+
7
+ def url(page)
8
+ @base_url_params ||= begin
9
+ url_params = merge_get_params(default_url_params)
10
+ merge_optional_params(url_params)
11
+ end
12
+
13
+ url_params = @base_url_params.dup
14
+ add_current_page_param(url_params, page)
15
+
16
+ if url_params[:scope]
17
+ scope = url_params[:scope]
18
+ url_params.delete(:scope)
19
+ url_params.delete(:controller)
20
+ scope.url_for(url_params)
21
+ else
22
+ @template.url_for(url_params)
23
+ end
24
+ end
25
+
26
+ end
27
+ end
@@ -1,5 +1,5 @@
1
1
  module Alchemy
2
2
 
3
- VERSION = "2.1.beta5"
3
+ VERSION = "2.1.beta6"
4
4
 
5
5
  end
@@ -17,7 +17,7 @@ if defined?(Rails) && Rails::VERSION::MAJOR == 3
17
17
  require 'alchemy/version'
18
18
  require 'alchemy/auth_engine'
19
19
  require 'alchemy/engine'
20
- %w(config essence page_layout modules remote_pagination_link_renderer tinymce i18n).each do |class_name|
20
+ %w(config essence page_layout modules scoped_pagination_link_renderer remote_pagination_link_renderer tinymce i18n).each do |class_name|
21
21
  require File.join(File.dirname(__FILE__), "alchemy", class_name)
22
22
  end
23
23
  require File.join(File.dirname(__FILE__), "alchemy", "seeder")
@@ -13,4 +13,23 @@ describe Alchemy::Admin::ContentsController do
13
13
  @element.ingredient('intro').should == "Peters Petshop"
14
14
  end
15
15
 
16
+ describe "#order" do
17
+
18
+ context "with content_ids in params" do
19
+
20
+ before(:each) do
21
+ @element = Factory(:element)
22
+ end
23
+
24
+ it "should reorder the contents" do
25
+ content_ids = @element.contents.essence_texts.collect(&:id)
26
+ post :order, {:content_ids => content_ids.reverse, :format => :js}
27
+ response.status.should == 200
28
+ @element.contents.essence_texts.collect(&:id).should == content_ids.reverse
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+
16
35
  end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Alchemy::Admin::PagesController do
4
+
5
+ before(:each) do
6
+ activate_authlogic
7
+ Alchemy::UserSession.create Factory(:admin_user)
8
+ end
9
+
10
+ describe "#flush", :focus => true do
11
+
12
+ it "should remove the cache of all pages" do
13
+ post :flush, {:format => :js}
14
+ response.status.should == 200
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -17,7 +17,7 @@ describe Alchemy::BaseController do
17
17
  controller.session[:language_code].should == @language.code
18
18
  end
19
19
 
20
- it "should set the language from id as string", :focus => true do
20
+ it "should set the language from id as string" do
21
21
  @language = Factory(:language)
22
22
  controller.send :set_language_from, @language.id.to_s
23
23
  controller.session[:language_id].should == @language.id
@@ -37,4 +37,66 @@ describe Alchemy::PagesController do
37
37
 
38
38
  end
39
39
 
40
+ describe "Layout rendering" do
41
+
42
+ context "with param layout set to none" do
43
+
44
+ it "should not render a layout" do
45
+ get :show, :urlname => :home, :layout => false
46
+ response.body.should_not have_content('<head>')
47
+ end
48
+
49
+ end
50
+
51
+ context "with param layout set to a custom layout" do
52
+
53
+ before do
54
+ @custom_layout = Rails.root.join('app/views/layouts', 'custom.html.erb')
55
+ File.open(@custom_layout, 'w') do |custom_layout|
56
+ custom_layout.puts "<html>I am a custom layout</html>"
57
+ end
58
+ end
59
+
60
+ it "should render the custom layout" do
61
+ get :show, :urlname => :home, :layout => 'custom'
62
+ response.body.should have_content('I am a custom layout')
63
+ end
64
+
65
+ after do
66
+ FileUtils.rm(@custom_layout)
67
+ end
68
+
69
+ end
70
+
71
+ context "with application layout absent" do
72
+
73
+ it "should render pages layout" do
74
+ get :show, :urlname => :home
75
+ response.body.should_not have_content('I am the application layout')
76
+ end
77
+
78
+ end
79
+
80
+ context "with application layout present" do
81
+
82
+ before do
83
+ @app_layout = Rails.root.join('app/views/layouts', 'application.html.erb')
84
+ File.open(@app_layout, 'w') do |app_layout|
85
+ app_layout.puts "<html>I am the application layout</html>"
86
+ end
87
+ end
88
+
89
+ it "should render application layout" do
90
+ get :show, :urlname => :home
91
+ response.body.should have_content('I am the application layout')
92
+ end
93
+
94
+ after do
95
+ FileUtils.rm(@app_layout)
96
+ end
97
+
98
+ end
99
+
100
+ end
101
+
40
102
  end
File without changes
@@ -1,46 +1,73 @@
1
+ # Skipping on Travis-CI, because capybara-webkit does not install on travis.
2
+ unless ENV["CI"]
3
+
1
4
  require 'spec_helper'
2
5
 
3
- describe Alchemy::Admin::PagesController do
6
+ describe Alchemy::Admin::PagesController, :js => true do
4
7
 
5
- describe "language tree switching", :js => true do
8
+ describe "language tree switching" do
6
9
 
7
10
  context "in a multilangual environment" do
8
11
 
9
- before(:each) do
12
+ before(:all) do
10
13
  Factory.build(:admin_user).save_without_session_maintenance
11
- Factory(:language)
12
- Factory(:language_root_page, :language => Alchemy::Language.get_default, :name => 'Deutsch')
13
- Factory(:language_root_page, :name => 'Klingonian')
14
+ @language = Factory(:language)
15
+ @german_root = Factory(:language_root_page, :language => Alchemy::Language.get_default, :name => 'Deutsch')
16
+ @klingonian_root = Factory(:language_root_page, :name => 'Klingonian')
14
17
  end
15
18
 
16
19
  it "one should be able to switch the language tree" do
17
- pending "This driver does not execute javascript as it should"
18
20
  login_to_alchemy
19
21
  visit('/alchemy/admin/pages')
20
22
  page.select 'Klingonian', :from => 'language'
21
23
  within('#sitemap') { page.should have_content('Klingonian') }
22
24
  end
23
25
 
26
+ after(:all) {
27
+ @language.destroy
28
+ @klingonian_root.destroy
29
+ @german_root.destroy
30
+ }
31
+
24
32
  end
25
33
 
26
34
  context "with no language root page" do
27
35
 
28
- before(:each) do
36
+ before(:all) do
29
37
  Factory.build(:admin_user).save_without_session_maintenance
38
+ @language = Factory(:language)
30
39
  end
31
40
 
32
- it "it should display the form for creating or copy language root" do
33
- pending "This driver does not work."
41
+ it "it should display the form for creating language root" do
34
42
  login_to_alchemy
35
43
  visit('/alchemy/admin/pages')
36
- save_and_open_page
44
+ page.select 'Klingonian', :from => 'language'
37
45
  within('#archive_all') do
38
46
  page.should have_content('This language tree does not exist')
39
- page.should have_content('Do you want to copy')
40
- page.should have_content('do you want to create a new empty language tree')
41
47
  end
42
48
  end
43
49
 
50
+ after(:all) {
51
+ @language.destroy
52
+ }
53
+
54
+ end
55
+
56
+ end
57
+
58
+ describe "flush complete page cache" do
59
+
60
+ before(:all) do
61
+ Factory.build(:admin_user).save_without_session_maintenance
62
+ end
63
+
64
+ it "should remove the cache of all pages" do
65
+ login_to_alchemy
66
+ visit '/alchemy/admin/pages'
67
+ click_link 'Flush page cache'
68
+ within('#flash_notices') do
69
+ page.should have_content('Page cache flushed')
70
+ end
44
71
  end
45
72
 
46
73
  end
@@ -54,3 +81,5 @@ def login_to_alchemy
54
81
  fill_in('alchemy_user_session_password', :with => 's3cr3t')
55
82
  click_on('Login')
56
83
  end
84
+
85
+ end