alchemy_cms 3.0.0 → 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/README.md +3 -6
- data/alchemy_cms.gemspec +1 -1
- data/app/assets/stylesheets/alchemy/buttons.scss +4 -4
- data/app/assets/stylesheets/alchemy/sitemap.scss +1 -1
- data/app/controllers/alchemy/pages_controller.rb +5 -5
- data/app/helpers/alchemy/admin/elements_helper.rb +3 -3
- data/app/helpers/alchemy/admin/navigation_helper.rb +2 -1
- data/app/models/alchemy/cell.rb +1 -1
- data/app/models/alchemy/element.rb +10 -0
- data/app/models/alchemy/page/page_naming.rb +10 -3
- data/app/models/alchemy/picture.rb +6 -2
- data/app/views/alchemy/admin/pages/_page.html.erb +1 -1
- data/app/views/alchemy/admin/pages/edit.html.erb +1 -1
- data/app/views/alchemy/admin/pages/info.html.erb +10 -1
- data/app/views/alchemy/base/leave.html.erb +1 -1
- data/config/locales/alchemy.de.yml +1 -1
- data/config/locales/alchemy.en.yml +3 -3
- data/config/locales/alchemy.fr.yml +1 -1
- data/config/locales/alchemy.nl.yml +1 -1
- data/lib/alchemy/test_support/factories.rb +4 -4
- data/lib/alchemy/version.rb +1 -1
- data/lib/rails/generators/alchemy/essence/essence_generator.rb +1 -1
- data/lib/rails/generators/alchemy/essence/templates/editor.html.erb +1 -1
- data/spec/features/page_feature_spec.rb +20 -0
- data/spec/helpers/admin/elements_helper_spec.rb +11 -2
- data/spec/helpers/admin/navigation_helper_spec.rb +30 -0
- data/spec/models/element_spec.rb +27 -4
- data/spec/models/page_spec.rb +10 -7
- data/spec/models/picture_spec.rb +19 -0
- data/vendor/assets/javascripts/tinymce/langs/fr.js +184 -0
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 22899ddac5bccee25b1e3438bcec28374381edc6
|
4
|
+
data.tar.gz: 92792959062f3873ff293a491a7c981e83ed2797
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ec3084ada69925e12a6458ed3768d4f63e23c3b20def9ebe63543946b05ad3d4288fd040ef20c88fa2857a0c123daa8462ef2f87d2facaa8b78ff7dd4926eea7
|
7
|
+
data.tar.gz: 8f0f74f54d0b903c5d02c445107ea8358927c5faa2ff4ab30ac37f0b1612f92ef63ed00d9b4bdbe6cb856200d43664e82754e4d197200a044fe84e797b8dc2c3
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
![Alchemy CMS](http://alchemy-cms.com/assets/alchemy_logo.svg)
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/alchemy_cms.png)](http://badge.fury.io/rb/alchemy_cms)
|
4
|
-
[![Build Status](https://travis-ci.org/magiclabs/alchemy_cms.svg?branch=
|
4
|
+
[![Build Status](https://travis-ci.org/magiclabs/alchemy_cms.svg?branch=3.0-stable)](https://travis-ci.org/magiclabs/alchemy_cms) [![Code Climate](https://codeclimate.com/github/magiclabs/alchemy_cms.png)](https://codeclimate.com/github/magiclabs/alchemy_cms) [![Coverage Status](https://coveralls.io/repos/magiclabs/alchemy_cms/badge.png?branch=3.0-stable)](https://coveralls.io/r/magiclabs/alchemy_cms?branch=3.0-stable)
|
5
5
|
|
6
6
|
About
|
7
7
|
-----
|
@@ -10,9 +10,6 @@ Alchemy is the most powerful, userfriendly and flexible Rails CMS.
|
|
10
10
|
|
11
11
|
Read more on the [website](http://alchemy-cms.com) and in the [guidelines](http://guides.alchemy-cms.com).
|
12
12
|
|
13
|
-
**This master branch is a development branch that can contain bugs. For productive environments you should use the [current Ruby gem version](http://rubygems.org/gems/alchemy_cms/versions/3.0.0),
|
14
|
-
or the [latest stable branch (3.0-stable)](https://github.com/magiclabs/alchemy_cms/tree/3.0-stable).**
|
15
|
-
|
16
13
|
Features
|
17
14
|
--------
|
18
15
|
|
@@ -60,7 +57,7 @@ Installation
|
|
60
57
|
|
61
58
|
#### 1. Use the installer:
|
62
59
|
|
63
|
-
gem install alchemy_cms
|
60
|
+
gem install alchemy_cms
|
64
61
|
alchemy new my_magicpage
|
65
62
|
cd my_magicpage
|
66
63
|
|
@@ -84,7 +81,7 @@ Open `http://localhost:3000` and follow the on screen instructions.
|
|
84
81
|
|
85
82
|
In your App's Gemfile:
|
86
83
|
|
87
|
-
gem 'alchemy_cms', github: 'magiclabs/alchemy_cms', branch: '
|
84
|
+
gem 'alchemy_cms', github: 'magiclabs/alchemy_cms', branch: '3.0-stable'
|
88
85
|
|
89
86
|
#### 2. Install Alchemy into your app:
|
90
87
|
|
data/alchemy_cms.gemspec
CHANGED
@@ -25,7 +25,7 @@ Gem::Specification.new do |gem|
|
|
25
25
|
gem.add_runtime_dependency 'acts-as-taggable-on', '~> 3.1'
|
26
26
|
gem.add_runtime_dependency 'cancan', '~> 1.6.10'
|
27
27
|
gem.add_runtime_dependency 'dragonfly', '~> 1.0.1'
|
28
|
-
gem.add_runtime_dependency 'kaminari', '~> 0.15
|
28
|
+
gem.add_runtime_dependency 'kaminari', '~> 0.15'
|
29
29
|
gem.add_runtime_dependency 'acts_as_list', '~> 0.3.0'
|
30
30
|
gem.add_runtime_dependency 'magiclabs-userstamp', '~> 2.1.0'
|
31
31
|
gem.add_runtime_dependency 'simple_form', '~> 3.0.1'
|
@@ -117,12 +117,12 @@ button, input[type="submit"], a.button, input.button {
|
|
117
117
|
border: $default-border-width $default-border-style $button-hover-border-color;
|
118
118
|
@include border-radius($default-border-radius);
|
119
119
|
background: $button-hover-bg-color;
|
120
|
-
top:
|
121
|
-
right:
|
120
|
+
top: -1px;
|
121
|
+
right: -1px;
|
122
122
|
|
123
123
|
.icon {
|
124
|
-
left:
|
125
|
-
top:
|
124
|
+
left: 1px;
|
125
|
+
top: 3px;
|
126
126
|
}
|
127
127
|
}
|
128
128
|
}
|
@@ -8,20 +8,20 @@ module Alchemy
|
|
8
8
|
|
9
9
|
rescue_from ActionController::RoutingError, :with => :render_404
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
before_filter :load_page
|
14
|
-
authorize_resource only: 'show'
|
11
|
+
before_action :enforce_primary_host_for_site
|
12
|
+
before_action :render_page_or_redirect, only: [:show]
|
15
13
|
|
16
14
|
# Showing page from params[:urlname]
|
17
15
|
#
|
18
16
|
def show
|
17
|
+
authorize! :show, @page
|
18
|
+
|
19
19
|
if render_fresh_page?
|
20
20
|
respond_to do |format|
|
21
21
|
format.html { render layout: !request.xhr? }
|
22
22
|
format.rss do
|
23
23
|
if @page.contains_feed?
|
24
|
-
render
|
24
|
+
render layout: false, handlers: [:builder]
|
25
25
|
else
|
26
26
|
render xml: {error: 'Not found'}, status: 404
|
27
27
|
end
|
@@ -72,12 +72,12 @@ module Alchemy
|
|
72
72
|
end
|
73
73
|
other_elements = elements - celled_elements
|
74
74
|
unless other_elements.blank?
|
75
|
-
|
76
|
-
options[optgroup_label] = other_elements.map do |e|
|
75
|
+
options[_t(:main_content)] = other_elements.map do |e|
|
77
76
|
element_array_for_options(e, object_method)
|
78
77
|
end
|
79
78
|
end
|
80
|
-
|
79
|
+
# We don't want to show empty cells
|
80
|
+
options.delete_if { |cell, elements| elements.blank? }
|
81
81
|
end
|
82
82
|
|
83
83
|
def element_array_for_options(e, object_method, cell = nil)
|
data/app/models/alchemy/cell.rb
CHANGED
@@ -19,7 +19,7 @@
|
|
19
19
|
#
|
20
20
|
# Render cells with the +render_cell+ helper
|
21
21
|
#
|
22
|
-
# Views for cells are inside the +app/views/cells+ folder in
|
22
|
+
# Views for cells are inside the +app/views/cells+ folder in your project.
|
23
23
|
#
|
24
24
|
module Alchemy
|
25
25
|
class Cell < ActiveRecord::Base
|
@@ -47,6 +47,7 @@ module Alchemy
|
|
47
47
|
|
48
48
|
after_create :create_contents, :unless => proc { |e| e.create_contents_after_create == false }
|
49
49
|
after_update :touch_pages
|
50
|
+
after_update :touch_cell, unless: -> { self.cell.nil? }
|
50
51
|
|
51
52
|
scope :trashed, -> { where(position: nil).order('updated_at DESC') }
|
52
53
|
scope :not_trashed, -> { where(Element.arel_table[:position].not_eq(nil)) }
|
@@ -461,5 +462,14 @@ module Alchemy
|
|
461
462
|
available_page_cells(page).collect(&:name).uniq
|
462
463
|
end
|
463
464
|
|
465
|
+
# If element has a +cell+ associated,
|
466
|
+
# it updates it's timestamp.
|
467
|
+
#
|
468
|
+
# Called after_update
|
469
|
+
#
|
470
|
+
def touch_cell
|
471
|
+
self.cell.touch
|
472
|
+
end
|
473
|
+
|
464
474
|
end
|
465
475
|
end
|
@@ -72,11 +72,11 @@ module Alchemy
|
|
72
72
|
def set_urlname
|
73
73
|
if Config.get(:url_nesting)
|
74
74
|
url_name = [
|
75
|
-
|
76
|
-
convert_url_name(
|
75
|
+
parent_urlname,
|
76
|
+
convert_url_name(urlname.blank? ? name : slug)
|
77
77
|
].compact.join('/')
|
78
78
|
else
|
79
|
-
url_name = convert_url_name(
|
79
|
+
url_name = convert_url_name(urlname.blank? ? name : urlname)
|
80
80
|
end
|
81
81
|
write_attribute :urlname, url_name
|
82
82
|
end
|
@@ -98,5 +98,12 @@ module Alchemy
|
|
98
98
|
url_name
|
99
99
|
end
|
100
100
|
end
|
101
|
+
|
102
|
+
# Urlname of parent page.
|
103
|
+
# Returns nil, if the parent is either a language root page or the root page itself
|
104
|
+
def parent_urlname
|
105
|
+
return if parent.nil? || parent.language_root? || parent.root?
|
106
|
+
parent.urlname
|
107
|
+
end
|
101
108
|
end
|
102
109
|
end
|
@@ -39,9 +39,13 @@ module Alchemy
|
|
39
39
|
raise PictureInUseError, I18n.t(:cannot_delete_picture_notice) % { name: name }
|
40
40
|
end
|
41
41
|
|
42
|
+
# Enables Dragonfly image processing
|
42
43
|
dragonfly_accessor :image_file, app: :alchemy_pictures do
|
43
|
-
|
44
|
-
|
44
|
+
# Preprocess after uploading the picture
|
45
|
+
after_assign do |p|
|
46
|
+
if Config.get(:preprocess_image_resize).present?
|
47
|
+
p.thumb!("#{Config.get(:preprocess_image_resize)}>")
|
48
|
+
end
|
45
49
|
end
|
46
50
|
end
|
47
51
|
|
@@ -5,9 +5,18 @@
|
|
5
5
|
<% end %>
|
6
6
|
<% end %>
|
7
7
|
<div class="value">
|
8
|
-
<label><%=
|
8
|
+
<label><%= Alchemy::Page.human_attribute_name(:page_layout) %></label>
|
9
9
|
<p><%= @page.layout_display_name %></p>
|
10
10
|
</div>
|
11
|
+
<div class="value">
|
12
|
+
<% if @page.redirects_to_external? %>
|
13
|
+
<label><%= Alchemy::Page.human_attribute_name(:urlname) %></label>
|
14
|
+
<p><%= @page.urlname %></p>
|
15
|
+
<% else %>
|
16
|
+
<label><%= Alchemy::LegacyPageUrl.human_attribute_name(:urlname) %></label>
|
17
|
+
<p><%= "/#{@page.urlname}" %></p>
|
18
|
+
<% end %>
|
19
|
+
</div>
|
11
20
|
<div class="value">
|
12
21
|
<label><%= _t(:page_status) %></label>
|
13
22
|
<p><%= combined_page_status(@page) %></p>
|
@@ -6,6 +6,6 @@
|
|
6
6
|
<%= link_to _t('stay logged in'), alchemy.root_path, class: 'button' %>
|
7
7
|
</p>
|
8
8
|
<%= form_tag Alchemy.logout_path, method: 'delete', class: 'buttons' do %>
|
9
|
-
<label><%= _t('or to
|
9
|
+
<label><%= _t('or to completely') %></label>
|
10
10
|
<%= button _t(:logout), autofocus: true %>
|
11
11
|
<% end %>
|
@@ -579,7 +579,7 @@ de:
|
|
579
579
|
"You are about to leave Alchemy": "Sie sind dabei Alchemy zu verlassen"
|
580
580
|
"Do you want to": "Wollen Sie dabei"
|
581
581
|
"stay logged in": "angemeldet bleiben"
|
582
|
-
"or to
|
582
|
+
"or to completely": "oder Sich komplett"
|
583
583
|
"Are you sure?": "Sind Sie sicher?"
|
584
584
|
"Create": "Hinzufügen"
|
585
585
|
"Edit": "Bearbeiten"
|
@@ -201,7 +201,7 @@ en:
|
|
201
201
|
"Hide Elements": "Hide Elements"
|
202
202
|
"If you have any problems using the Flash uploader you can switch to": "If you have any problems using the Flash uploader you can switch to %{link}"
|
203
203
|
"Image missing": "Image missing"
|
204
|
-
"Image size": "
|
204
|
+
"Image size": "Image size"
|
205
205
|
"Language successfully created": "Language successfully created."
|
206
206
|
"Language successfully removed": "Language successfully removed."
|
207
207
|
"Language successfully updated": "Language successfully updated."
|
@@ -244,7 +244,7 @@ en:
|
|
244
244
|
"Please enter a new password": "Please enter a new password."
|
245
245
|
"Please enter your email address": "Please enter your email address."
|
246
246
|
"Please log in": "Please log in."
|
247
|
-
"Please seperate the tags with commata": "* Please seperate the tags with
|
247
|
+
"Please seperate the tags with commata": "* Please seperate the tags with commas."
|
248
248
|
"Properties": "Properties"
|
249
249
|
"Publish page": "Publish page"
|
250
250
|
"Read the License": "Read the License"
|
@@ -579,7 +579,7 @@ en:
|
|
579
579
|
"You are about to leave Alchemy": "You are about to leave Alchemy"
|
580
580
|
"Do you want to": "Do you want to"
|
581
581
|
"stay logged in": "stay logged in"
|
582
|
-
"or to
|
582
|
+
"or to completely": "or to completely"
|
583
583
|
"Are you sure?": "Are you sure?"
|
584
584
|
"Create": "Create"
|
585
585
|
"Edit": "Edit"
|
@@ -605,7 +605,7 @@ fr:
|
|
605
605
|
"You are about to leave Alchemy": "Vous êtes sur le point de quitter l'Alchimie"
|
606
606
|
"Do you want to": "Voulez-vous "
|
607
607
|
"stay logged in": "rester connecté"
|
608
|
-
"or to
|
608
|
+
"or to completely": "ou vous-même complètement"
|
609
609
|
"Please wait. Flash® is loading...": "S'il vous plaît attendre. Uploader Flash ® est en cours de chargement..."
|
610
610
|
"Are you sure?": "Etes-vous sûr?"
|
611
611
|
"Create": "ajouter"
|
@@ -579,7 +579,7 @@ nl:
|
|
579
579
|
"You are about to leave Alchemy": "U staat op het punt de NVM Regiosite te verlaten"
|
580
580
|
"Do you want to": "Wilt u"
|
581
581
|
"stay logged in": "ingelogd blijven"
|
582
|
-
"or to
|
582
|
+
"or to completely": "of compleet"
|
583
583
|
"Are you sure?": "Weet u het zeker?"
|
584
584
|
"Create": "Aanmaken"
|
585
585
|
"Edit": "Aanpassen"
|
@@ -5,19 +5,19 @@ FactoryGirl.define do
|
|
5
5
|
password 's3cr3t'
|
6
6
|
|
7
7
|
factory :admin_user do
|
8
|
-
alchemy_roles 'admin'
|
8
|
+
alchemy_roles ['admin']
|
9
9
|
end
|
10
10
|
|
11
11
|
factory :member_user do
|
12
|
-
alchemy_roles 'member'
|
12
|
+
alchemy_roles ['member']
|
13
13
|
end
|
14
14
|
|
15
15
|
factory :author_user do
|
16
|
-
alchemy_roles 'author'
|
16
|
+
alchemy_roles ['author']
|
17
17
|
end
|
18
18
|
|
19
19
|
factory :editor_user do
|
20
|
-
alchemy_roles 'editor'
|
20
|
+
alchemy_roles ['editor']
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
data/lib/alchemy/version.rb
CHANGED
@@ -36,7 +36,7 @@ CLASSMETHOD
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def copy_templates
|
39
|
-
essence_name = @essence_name.classify.demodulize
|
39
|
+
essence_name = @essence_name.classify.demodulize.underscore
|
40
40
|
template "view.html.erb", "#{@essence_view_path}/_#{essence_name}_view.html.erb"
|
41
41
|
template "editor.html.erb", "#{@essence_view_path}/_#{essence_name}_editor.html.erb"
|
42
42
|
end
|
@@ -6,7 +6,7 @@
|
|
6
6
|
Please consult Alchemy::Content.rb docs for further methods on the content object
|
7
7
|
%>
|
8
8
|
<%% cache(content) do %>
|
9
|
-
<div class="content_editor <%= @essence_name.classify.demodulize %>" id="<%%= content.dom_id %>">
|
9
|
+
<div class="content_editor <%= @essence_name.classify.demodulize.underscore %>" id="<%%= content.dom_id %>" data-content-id="<%%= content.id %>">
|
10
10
|
<%%= label_and_remove_link(content) %>
|
11
11
|
<%%= text_field_tag(
|
12
12
|
content.form_field_name,
|
@@ -234,5 +234,25 @@ module Alchemy
|
|
234
234
|
end
|
235
235
|
end
|
236
236
|
|
237
|
+
describe 'accessing restricted pages' do
|
238
|
+
let!(:restricted_page) { create(:restricted_page, public: true) }
|
239
|
+
|
240
|
+
context 'as a guest user' do
|
241
|
+
it "I am not able to visit the page" do
|
242
|
+
visit restricted_page.urlname
|
243
|
+
current_path.should == Alchemy.login_path
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
context 'as a member user' do
|
248
|
+
before { authorize_as_admin(create(:member_user)) }
|
249
|
+
|
250
|
+
it "I am able to visit the page" do
|
251
|
+
visit restricted_page.urlname
|
252
|
+
current_path.should == "/#{restricted_page.urlname}"
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
237
257
|
end
|
238
258
|
end
|
@@ -26,8 +26,11 @@ module Alchemy
|
|
26
26
|
}
|
27
27
|
|
28
28
|
before do
|
29
|
-
page.stub(layout_description: {'name' => "foo", 'cells' => ["foo_cell"]})
|
30
|
-
cell_descriptions = [
|
29
|
+
page.stub(layout_description: {'name' => "foo", 'cells' => ["foo_cell", "empty_cell"]})
|
30
|
+
cell_descriptions = [
|
31
|
+
{'name' => "foo_cell", 'elements' => ["1", "2"]},
|
32
|
+
{'name' => 'empty_cell', 'elements' => []}
|
33
|
+
]
|
31
34
|
Cell.stub(:definitions).and_return(cell_descriptions)
|
32
35
|
helper.instance_variable_set('@page', page)
|
33
36
|
end
|
@@ -48,6 +51,12 @@ module Alchemy
|
|
48
51
|
helper.grouped_elements_for_select(elements).should == ""
|
49
52
|
end
|
50
53
|
end
|
54
|
+
|
55
|
+
context "with cell having no elements" do
|
56
|
+
it "should remove that cell from hash" do
|
57
|
+
expect(helper.grouped_elements_for_select(elements)['Empty cell']).to be_nil
|
58
|
+
end
|
59
|
+
end
|
51
60
|
end
|
52
61
|
|
53
62
|
describe "#elements_for_select" do
|
@@ -27,6 +27,24 @@ describe Alchemy::Admin::NavigationHelper do
|
|
27
27
|
}
|
28
28
|
} }
|
29
29
|
|
30
|
+
let(:event_module_with_params) { {
|
31
|
+
'navigation' => {
|
32
|
+
'controller' => '/admin/events',
|
33
|
+
'action' => 'index',
|
34
|
+
'params' => {
|
35
|
+
'key' => 'value'
|
36
|
+
},
|
37
|
+
'sub_navigation' => [{
|
38
|
+
'controller' => '/admin/events',
|
39
|
+
'action' => 'index',
|
40
|
+
'params' => {
|
41
|
+
'key' => 'value',
|
42
|
+
'key2' => 'value2'
|
43
|
+
}
|
44
|
+
}]
|
45
|
+
}
|
46
|
+
} }
|
47
|
+
|
30
48
|
let(:navigation) { alchemy_module['navigation'] }
|
31
49
|
|
32
50
|
describe '#alchemy_main_navigation_entry' do
|
@@ -180,6 +198,10 @@ describe Alchemy::Admin::NavigationHelper do
|
|
180
198
|
it "returns correct url string" do
|
181
199
|
helper.url_for_module(event_module).should == '/admin/events'
|
182
200
|
end
|
201
|
+
|
202
|
+
it "returns correct url string with params" do
|
203
|
+
helper.url_for_module(event_module_with_params).should == '/admin/events?key=value'
|
204
|
+
end
|
183
205
|
end
|
184
206
|
end
|
185
207
|
|
@@ -209,6 +231,14 @@ describe Alchemy::Admin::NavigationHelper do
|
|
209
231
|
end
|
210
232
|
end
|
211
233
|
|
234
|
+
context "with module within host app with params" do
|
235
|
+
let(:current_module) { event_module_with_params }
|
236
|
+
|
237
|
+
it "returns correct url string with params" do
|
238
|
+
should == '/admin/events?key2=value2&key=value'
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
212
242
|
context 'without module found' do
|
213
243
|
before do
|
214
244
|
helper.stub(module_definition_for: nil)
|
data/spec/models/element_spec.rb
CHANGED
@@ -422,16 +422,20 @@ module Alchemy
|
|
422
422
|
end
|
423
423
|
|
424
424
|
describe '.after_update' do
|
425
|
+
let(:page) { create(:page) }
|
426
|
+
let(:element) { create(:element, page: page) }
|
427
|
+
let(:now) { Time.now }
|
428
|
+
|
429
|
+
before do
|
430
|
+
Time.stub(now: now)
|
431
|
+
end
|
432
|
+
|
425
433
|
context 'with touchable pages' do
|
426
434
|
let(:locker) { mock_model('DummyUser') }
|
427
|
-
let(:page) { create(:page) }
|
428
|
-
let(:element) { create(:element, page: page) }
|
429
|
-
let(:now) { Time.now }
|
430
435
|
let(:pages) { [page] }
|
431
436
|
|
432
437
|
before do
|
433
438
|
Alchemy.user_class.stub(:stamper).and_return(locker.id)
|
434
|
-
Time.stub(now: now)
|
435
439
|
end
|
436
440
|
|
437
441
|
it "updates page timestamps" do
|
@@ -446,6 +450,25 @@ module Alchemy
|
|
446
450
|
page.updater_id.should eq(locker.id)
|
447
451
|
end
|
448
452
|
end
|
453
|
+
|
454
|
+
context 'with cell associated' do
|
455
|
+
let(:cell) { mock_model('Cell') }
|
456
|
+
|
457
|
+
before do
|
458
|
+
element.stub(cell: cell)
|
459
|
+
end
|
460
|
+
|
461
|
+
it "updates timestamp of cell" do
|
462
|
+
element.cell.should_receive(:touch)
|
463
|
+
element.save
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
467
|
+
context 'without cell associated' do
|
468
|
+
it "does not update timestamp of cell" do
|
469
|
+
expect { element.save }.to_not raise_error
|
470
|
+
end
|
471
|
+
end
|
449
472
|
end
|
450
473
|
|
451
474
|
describe '#taggable?' do
|
data/spec/models/page_spec.rb
CHANGED
@@ -1203,12 +1203,13 @@ module Alchemy
|
|
1203
1203
|
end
|
1204
1204
|
|
1205
1205
|
context 'urlname updating' do
|
1206
|
-
let(:parentparent)
|
1207
|
-
let(:parent)
|
1208
|
-
let(:page)
|
1209
|
-
let(:invisible)
|
1210
|
-
let(:contact)
|
1211
|
-
let(:external)
|
1206
|
+
let(:parentparent) { FactoryGirl.create(:page, name: 'parentparent', visible: true) }
|
1207
|
+
let(:parent) { FactoryGirl.create(:page, parent_id: parentparent.id, name: 'parent', visible: true) }
|
1208
|
+
let(:page) { FactoryGirl.create(:page, parent_id: parent.id, name: 'page', visible: true) }
|
1209
|
+
let(:invisible) { FactoryGirl.create(:page, parent_id: page.id, name: 'invisible', visible: false) }
|
1210
|
+
let(:contact) { FactoryGirl.create(:page, parent_id: invisible.id, name: 'contact', visible: true) }
|
1211
|
+
let(:external) { FactoryGirl.create(:page, parent_id: parent.id, name: 'external', page_layout: 'external', urlname: 'http://google.com') }
|
1212
|
+
let(:language_root) { parentparent.parent }
|
1212
1213
|
|
1213
1214
|
context "with activated url_nesting" do
|
1214
1215
|
before { Config.stub(:get).and_return(true) }
|
@@ -1218,7 +1219,9 @@ module Alchemy
|
|
1218
1219
|
end
|
1219
1220
|
|
1220
1221
|
it "should not include the root page" do
|
1221
|
-
|
1222
|
+
Page.root.update_column(:urlname, 'root')
|
1223
|
+
language_root.update(urlname: 'new-urlname')
|
1224
|
+
language_root.urlname.should_not =~ /root/
|
1222
1225
|
end
|
1223
1226
|
|
1224
1227
|
it "should not include the language root page" do
|
data/spec/models/picture_spec.rb
CHANGED
@@ -32,6 +32,25 @@ module Alchemy
|
|
32
32
|
picture.should be_valid
|
33
33
|
end
|
34
34
|
|
35
|
+
context 'with enabled preprocess_image_resize config option' do
|
36
|
+
let(:image_file) do
|
37
|
+
File.new(File.expand_path('../../fixtures/80x60.png', __FILE__))
|
38
|
+
end
|
39
|
+
|
40
|
+
before do
|
41
|
+
Config.stub(:get) do |arg|
|
42
|
+
if arg == :preprocess_image_resize
|
43
|
+
'10x10'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it "it resizes the image after upload" do
|
49
|
+
picture = Picture.new(image_file: image_file)
|
50
|
+
expect(picture.image_file.data[0x10..0x18].unpack('NN')).to eq([10, 8])
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
35
54
|
describe '#suffix' do
|
36
55
|
it "should return the suffix of original filename" do
|
37
56
|
pic = stub_model(Picture, image_file_name: 'kitten.JPG')
|
@@ -0,0 +1,184 @@
|
|
1
|
+
tinymce.addI18n('fr',{
|
2
|
+
"Cut": "Couper",
|
3
|
+
"Header 2": "Titre 2",
|
4
|
+
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "Votre navigateur ne supporte pas la copie directe. Merci d'utiliser les touches Ctrl+X\/C\/V.",
|
5
|
+
"Div": "Div",
|
6
|
+
"Paste": "Coller",
|
7
|
+
"Close": "Fermer",
|
8
|
+
"Font Family": "Polices de caract\u00e8res",
|
9
|
+
"Pre": "Pre",
|
10
|
+
"Align right": "Aligner \u00e0 droite",
|
11
|
+
"New document": "Nouveau document",
|
12
|
+
"Blockquote": "Citation",
|
13
|
+
"Numbered list": "Num\u00e9rotation",
|
14
|
+
"Increase indent": "Augmenter le retrait",
|
15
|
+
"Formats": "Formats",
|
16
|
+
"Headers": "Titres",
|
17
|
+
"Select all": "Tout s\u00e9lectionner",
|
18
|
+
"Header 3": "Titre 3",
|
19
|
+
"Blocks": "Blocs",
|
20
|
+
"Undo": "Annuler",
|
21
|
+
"Strikethrough": "Barr\u00e9",
|
22
|
+
"Bullet list": "Puces",
|
23
|
+
"Header 1": "Titre 1",
|
24
|
+
"Superscript": "Exposant",
|
25
|
+
"Clear formatting": "Effacer la mise en forme",
|
26
|
+
"Font Sizes": "Tailles de la police",
|
27
|
+
"Subscript": "Indice",
|
28
|
+
"Header 6": "Titre 6",
|
29
|
+
"Redo": "R\u00e9tablir",
|
30
|
+
"Paragraph": "Paragraphe",
|
31
|
+
"Ok": "Ok",
|
32
|
+
"Bold": "Gras",
|
33
|
+
"Code": "Code",
|
34
|
+
"Italic": "Italique",
|
35
|
+
"Align center": "Aligner au centre",
|
36
|
+
"Header 5": "Titre 5",
|
37
|
+
"Decrease indent": "Diminuer le retrait",
|
38
|
+
"Header 4": "Titre 4",
|
39
|
+
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "Le presse-papiers est maintenant en mode \"texte plein\". Les contenus seront coll\u00e9s sans retenir les formatages jusqu'\u00e0 ce que vous d\u00e9sactiviez cette option.",
|
40
|
+
"Underline": "Soulign\u00e9",
|
41
|
+
"Cancel": "Annuler",
|
42
|
+
"Justify": "Justifi\u00e9",
|
43
|
+
"Inline": "En ligne",
|
44
|
+
"Copy": "Copier",
|
45
|
+
"Align left": "Aligner \u00e0 gauche",
|
46
|
+
"Visual aids": "Aides visuelle",
|
47
|
+
"Lower Greek": "Grec minuscule",
|
48
|
+
"Square": "Carr\u00e9",
|
49
|
+
"Default": "Par d\u00e9faut",
|
50
|
+
"Lower Alpha": "Alpha minuscule",
|
51
|
+
"Circle": "Cercle",
|
52
|
+
"Disc": "Disque",
|
53
|
+
"Upper Alpha": "Alpha majuscule",
|
54
|
+
"Upper Roman": "Romain majuscule",
|
55
|
+
"Lower Roman": "Romain minuscule",
|
56
|
+
"Name": "Nom",
|
57
|
+
"Anchor": "Ancre",
|
58
|
+
"You have unsaved changes are you sure you want to navigate away?": "Vous avez des modifications non enregistr\u00e9es, \u00eates-vous s\u00fbr de quitter la page?",
|
59
|
+
"Restore last draft": "Restaurer le dernier brouillon",
|
60
|
+
"Special character": "Caract\u00e8res sp\u00e9ciaux",
|
61
|
+
"Source code": "Code source",
|
62
|
+
"Right to left": "Droite \u00e0 gauche",
|
63
|
+
"Left to right": "Gauche \u00e0 droite",
|
64
|
+
"Emoticons": "Emotic\u00f4nes",
|
65
|
+
"Robots": "Robots",
|
66
|
+
"Document properties": "Propri\u00e9t\u00e9 du document",
|
67
|
+
"Title": "Titre",
|
68
|
+
"Keywords": "Mots-cl\u00e9s",
|
69
|
+
"Encoding": "Encodage",
|
70
|
+
"Description": "Description",
|
71
|
+
"Author": "Auteur",
|
72
|
+
"Fullscreen": "Plein \u00e9cran",
|
73
|
+
"Horizontal line": "Ligne horizontale",
|
74
|
+
"Horizontal space": "Espacement horizontal",
|
75
|
+
"Insert\/edit image": "Ins\u00e9rer\/\u00e9diter une image",
|
76
|
+
"General": "G\u00e9n\u00e9ral",
|
77
|
+
"Advanced": "Avanc\u00e9",
|
78
|
+
"Source": "Source",
|
79
|
+
"Border": "Bordure",
|
80
|
+
"Constrain proportions": "Contraindre les proportions",
|
81
|
+
"Vertical space": "Espacement vertical",
|
82
|
+
"Image description": "Description de l'image",
|
83
|
+
"Style": "Style",
|
84
|
+
"Dimensions": "Dimensions",
|
85
|
+
"Insert image": "Ins\u00e9rer une image",
|
86
|
+
"Insert date\/time": "Ins\u00e9rer date\/heure",
|
87
|
+
"Remove link": "Enlever le lien",
|
88
|
+
"Url": "Url",
|
89
|
+
"Text to display": "Texte \u00e0 afficher",
|
90
|
+
"Anchors": "Ancres",
|
91
|
+
"Insert link": "Ins\u00e9rer un lien",
|
92
|
+
"New window": "Nouvelle fen\u00eatre",
|
93
|
+
"None": "n\/a",
|
94
|
+
"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "L'URL que vous avez entr\u00e9e semble \u00eatre un lien externe. Voulez-vous ajouter le pr\u00e9fixe http:\/\/ n\u00e9cessaire?",
|
95
|
+
"Target": "Cible",
|
96
|
+
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "L'URL que vous avez entr\u00e9e semble \u00eatre une adresse e-mail. Voulez-vous ajouter le pr\u00e9fixe mailto: n\u00e9cessaire?",
|
97
|
+
"Insert\/edit link": "Ins\u00e9rer\/\u00e9diter un lien",
|
98
|
+
"Insert\/edit video": "Ins\u00e9rer\/\u00e9diter une vid\u00e9o",
|
99
|
+
"Poster": "Publier",
|
100
|
+
"Alternative source": "Source alternative",
|
101
|
+
"Paste your embed code below:": "Collez votre code d'int\u00e9gration ci-dessous :",
|
102
|
+
"Insert video": "Ins\u00e9rer une vid\u00e9o",
|
103
|
+
"Embed": "Ins\u00e9rer",
|
104
|
+
"Nonbreaking space": "Espace ins\u00e9cable",
|
105
|
+
"Page break": "Saut de page",
|
106
|
+
"Paste as text": "Coller comme texte",
|
107
|
+
"Preview": "Pr\u00e9visualiser",
|
108
|
+
"Print": "Imprimer",
|
109
|
+
"Save": "Enregistrer",
|
110
|
+
"Could not find the specified string.": "Impossible de trouver la cha\u00eene sp\u00e9cifi\u00e9e.",
|
111
|
+
"Replace": "Remplacer",
|
112
|
+
"Next": "Suiv",
|
113
|
+
"Whole words": "Mots entiers",
|
114
|
+
"Find and replace": "Trouver et remplacer",
|
115
|
+
"Replace with": "Remplacer par",
|
116
|
+
"Find": "Chercher",
|
117
|
+
"Replace all": "Tout remplacer",
|
118
|
+
"Match case": "Respecter la casse",
|
119
|
+
"Prev": "Pr\u00e9c ",
|
120
|
+
"Spellcheck": "V\u00e9rification orthographique",
|
121
|
+
"Finish": "Finie",
|
122
|
+
"Ignore all": "Tout ignorer",
|
123
|
+
"Ignore": "Ignorer",
|
124
|
+
"Insert row before": "Ins\u00e9rer une ligne avant",
|
125
|
+
"Rows": "Lignes",
|
126
|
+
"Height": "Hauteur",
|
127
|
+
"Paste row after": "Coller la ligne apr\u00e8s",
|
128
|
+
"Alignment": "Alignement",
|
129
|
+
"Column group": "Groupe de colonnes",
|
130
|
+
"Row": "Ligne",
|
131
|
+
"Insert column before": "Ins\u00e9rer une colonne avant",
|
132
|
+
"Split cell": "Diviser la cellule",
|
133
|
+
"Cell padding": "Espacement interne cellule",
|
134
|
+
"Cell spacing": "Espacement inter-cellulles",
|
135
|
+
"Row type": "Type de ligne",
|
136
|
+
"Insert table": "Ins\u00e9rer un tableau",
|
137
|
+
"Body": "Corps",
|
138
|
+
"Caption": "Titre",
|
139
|
+
"Footer": "Pied",
|
140
|
+
"Delete row": "Effacer la ligne",
|
141
|
+
"Paste row before": "Coller la ligne avant",
|
142
|
+
"Scope": "Etendue",
|
143
|
+
"Delete table": "Supprimer le tableau",
|
144
|
+
"H Align": "Alignement H",
|
145
|
+
"Top": "Haut",
|
146
|
+
"Header cell": "Cellule d'en-t\u00eate",
|
147
|
+
"Column": "Colonne",
|
148
|
+
"Row group": "Groupe de lignes",
|
149
|
+
"Cell": "Cellule",
|
150
|
+
"Middle": "Milieu",
|
151
|
+
"Cell type": "Type de cellule",
|
152
|
+
"Copy row": "Copier la ligne",
|
153
|
+
"Row properties": "Propri\u00e9t\u00e9s de la ligne",
|
154
|
+
"Table properties": "Propri\u00e9t\u00e9s du tableau",
|
155
|
+
"Bottom": "Bas",
|
156
|
+
"V Align": "Alignement V",
|
157
|
+
"Header": "En-t\u00eate",
|
158
|
+
"Right": "Droite",
|
159
|
+
"Insert column after": "Ins\u00e9rer une colonne apr\u00e8s",
|
160
|
+
"Cols": "Colonnes",
|
161
|
+
"Insert row after": "Ins\u00e9rer une ligne apr\u00e8s",
|
162
|
+
"Width": "Largeur",
|
163
|
+
"Cell properties": "Propri\u00e9t\u00e9s de la cellule",
|
164
|
+
"Left": "Gauche",
|
165
|
+
"Cut row": "Couper la ligne",
|
166
|
+
"Delete column": "Effacer la colonne",
|
167
|
+
"Center": "Centr\u00e9",
|
168
|
+
"Merge cells": "Fusionner les cellules",
|
169
|
+
"Insert template": "Ajouter un th\u00e8me",
|
170
|
+
"Templates": "Th\u00e8mes",
|
171
|
+
"Background color": "Couleur d'arri\u00e8re-plan",
|
172
|
+
"Text color": "Couleur du texte",
|
173
|
+
"Show blocks": "Afficher les blocs",
|
174
|
+
"Show invisible characters": "Afficher les caract\u00e8res invisibles",
|
175
|
+
"Words: {0}": "Mots : {0}",
|
176
|
+
"Insert": "Ins\u00e9rer",
|
177
|
+
"File": "Fichier",
|
178
|
+
"Edit": "Editer",
|
179
|
+
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "Zone Texte Riche. Appuyer sur ALT-F9 pour le menu. Appuyer sur ALT-F10 pour la barre d'outils. Appuyer sur ALT-0 pour de l'aide.",
|
180
|
+
"Tools": "Outils",
|
181
|
+
"View": "Voir",
|
182
|
+
"Table": "Tableau",
|
183
|
+
"Format": "Format"
|
184
|
+
});
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alchemy_cms
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas von Deyen
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2014-
|
15
|
+
date: 2014-09-11 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: rails
|
@@ -110,14 +110,14 @@ dependencies:
|
|
110
110
|
requirements:
|
111
111
|
- - "~>"
|
112
112
|
- !ruby/object:Gem::Version
|
113
|
-
version: 0.15
|
113
|
+
version: '0.15'
|
114
114
|
type: :runtime
|
115
115
|
prerelease: false
|
116
116
|
version_requirements: !ruby/object:Gem::Requirement
|
117
117
|
requirements:
|
118
118
|
- - "~>"
|
119
119
|
- !ruby/object:Gem::Version
|
120
|
-
version: 0.15
|
120
|
+
version: '0.15'
|
121
121
|
- !ruby/object:Gem::Dependency
|
122
122
|
name: acts_as_list
|
123
123
|
requirement: !ruby/object:Gem::Requirement
|
@@ -1075,6 +1075,7 @@ files:
|
|
1075
1075
|
- vendor/assets/javascripts/requestAnimationFrame.js
|
1076
1076
|
- vendor/assets/javascripts/spin.min.js
|
1077
1077
|
- vendor/assets/javascripts/tinymce/langs/de.js
|
1078
|
+
- vendor/assets/javascripts/tinymce/langs/fr.js
|
1078
1079
|
- vendor/assets/javascripts/tinymce/langs/nl.js
|
1079
1080
|
- vendor/assets/javascripts/tinymce/license.txt
|
1080
1081
|
- vendor/assets/javascripts/tinymce/plugins/anchor/plugin.min.js
|