alchemy_cms 3.1.0.rc1 → 3.1.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -10
- data/.teatro.yml +7 -0
- data/Gemfile +13 -13
- data/README.md +20 -3
- data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +3 -3
- data/app/assets/javascripts/alchemy/alchemy.uploader.js.coffee +5 -0
- data/app/controllers/alchemy/admin/essence_files_controller.rb +23 -3
- data/app/controllers/alchemy/admin/essence_pictures_controller.rb +7 -2
- data/app/controllers/alchemy/admin/pictures_controller.rb +1 -4
- data/app/controllers/alchemy/base_controller.rb +3 -1
- data/app/controllers/alchemy/pages_controller.rb +3 -1
- data/app/models/alchemy/content.rb +0 -3
- data/app/models/alchemy/element.rb +1 -2
- data/app/models/alchemy/page/page_scopes.rb +3 -1
- data/app/models/alchemy/page/page_users.rb +10 -3
- data/app/models/alchemy/picture.rb +29 -6
- data/app/models/alchemy/picture/transformations.rb +14 -7
- data/app/views/alchemy/_menubar.html.erb +1 -1
- data/app/views/alchemy/admin/leave.html.erb +1 -1
- data/app/views/alchemy/essences/_essence_boolean_editor.html.erb +2 -1
- data/config/initializers/dragonfly.rb +0 -2
- data/lib/alchemy/engine.rb +0 -1
- data/lib/alchemy/locale.rb +15 -13
- data/lib/alchemy/upgrader.rb +1 -0
- data/lib/alchemy/upgrader/three_point_zero.rb +27 -9
- data/lib/alchemy/version.rb +1 -1
- data/lib/tasks/alchemy/tidy.rake +34 -16
- data/spec/controllers/admin/essence_files_controller_spec.rb +13 -2
- data/spec/controllers/admin/essence_pictures_controller_spec.rb +8 -0
- data/spec/controllers/pages_controller_spec.rb +42 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -1
- data/spec/dummy/app/models/dummy_user.rb +4 -0
- data/spec/dummy/bin/bundle +0 -0
- data/spec/dummy/bin/rails +0 -0
- data/spec/dummy/bin/rake +0 -0
- data/spec/dummy/config/environments/production.rb +1 -1
- data/spec/dummy/db/seeds.rb +1 -0
- data/spec/features/translation_integration_spec.rb +14 -11
- data/spec/models/page_spec.rb +143 -52
- data/spec/spec_helper.rb +0 -3
- data/spec/support/transformation_examples.rb +7 -0
- data/spec/views/essences/essence_boolean_editor_spec.rb +1 -0
- data/vendor/assets/javascripts/fileupload/jquery.fileupload-process.js +6 -3
- data/vendor/assets/javascripts/fileupload/jquery.fileupload-validate.js +5 -3
- data/vendor/assets/javascripts/fileupload/jquery.fileupload.js +97 -46
- data/vendor/assets/javascripts/fileupload/jquery.iframe-transport.js +11 -4
- metadata +6 -4
- data/lib/extensions/action_view.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 64b4c80e471321ff237ae2fa6232841e2769f1fc
|
4
|
+
data.tar.gz: c66e6fbc68e16aa584ac6801d32821a3e04267f1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3e43c4db264c179ebc193d8ace01227b9e94570b82c8c6f4c572e4cb1e5cfcd66995fa99a7326d57ac65f144da95f47c8aa28b2c2358dcf79afc4ea844672464
|
7
|
+
data.tar.gz: 326af8d144fdab241db4c6e41c8f981364b4ab5552c86132ba05f61aafe25ac06f635742c9f1f610e0c2f0d2f6ff026b833e69aaf32c1268b0f2a2860cf7f9ae
|
data/.gitignore
CHANGED
@@ -6,22 +6,16 @@ doc/
|
|
6
6
|
rdoc/
|
7
7
|
Gemfile.lock
|
8
8
|
pkg
|
9
|
-
/spec/dummy/log/development.log
|
10
|
-
/spec/dummy/log/test.log
|
11
|
-
/spec/dummy/db/test.sqlite3
|
12
|
-
/spec/dummy/db/development.sqlite3
|
13
9
|
tmp
|
14
|
-
spec/dummy/index/
|
15
10
|
log
|
16
|
-
spec/dummy/uploads/
|
17
11
|
.sass-cache
|
18
|
-
spec/dummy/
|
19
|
-
spec/dummy/db
|
20
|
-
|
12
|
+
spec/dummy/uploads/
|
13
|
+
spec/dummy/db/*.sqlite3*
|
14
|
+
spec/dummy/public/assets
|
21
15
|
spec/dummy/config/locales/**/*
|
16
|
+
.rvmrc
|
22
17
|
/coverage/
|
23
18
|
*.gem
|
24
|
-
/.ruby-version
|
25
19
|
/index/
|
26
20
|
/.bundle/
|
27
21
|
.rbenv-version
|
data/.teatro.yml
ADDED
data/Gemfile
CHANGED
@@ -6,20 +6,16 @@ if ENV['RAILS_VERSION']
|
|
6
6
|
gem 'rails', "~> #{ENV['RAILS_VERSION']}"
|
7
7
|
end
|
8
8
|
|
9
|
-
|
10
|
-
gem '
|
11
|
-
|
12
|
-
group :test do
|
13
|
-
gem 'sqlite3' if ENV['DB'].nil? || ENV['DB'] == 'sqlite'
|
14
|
-
gem 'mysql2' if ENV['DB'] == 'mysql'
|
15
|
-
gem 'pg' if ENV['DB'] == 'postgresql'
|
16
|
-
unless ENV['CI']
|
17
|
-
gem 'launchy'
|
18
|
-
end
|
19
|
-
end
|
9
|
+
gem 'sqlite3' if ENV['DB'].nil? || ENV['DB'] == 'sqlite'
|
10
|
+
gem 'mysql2' if ENV['DB'] == 'mysql'
|
11
|
+
gem 'pg' if ENV['DB'] == 'postgresql'
|
20
12
|
|
21
13
|
group :development, :test do
|
14
|
+
gem 'jasmine-rails', github: 'searls/jasmine-rails'
|
15
|
+
gem 'jasmine-jquery-rails', github: 'travisjeffery/jasmine-jquery-rails'
|
16
|
+
gem 'coveralls', require: false
|
22
17
|
unless ENV['CI']
|
18
|
+
gem 'launchy'
|
23
19
|
gem 'annotate'
|
24
20
|
gem 'bumpy'
|
25
21
|
gem 'yard'
|
@@ -28,6 +24,10 @@ group :development, :test do
|
|
28
24
|
gem 'spring'
|
29
25
|
gem 'spring-commands-rspec'
|
30
26
|
end
|
31
|
-
|
32
|
-
|
27
|
+
end
|
28
|
+
|
29
|
+
# We need this if we want to start the dummy app in production, ie on Teatro.io
|
30
|
+
group :production do
|
31
|
+
gem 'uglifier', '>= 1.0.3'
|
32
|
+
gem 'therubyracer'
|
33
33
|
end
|
data/README.md
CHANGED
@@ -261,11 +261,18 @@ Please take a look into Alchemys [Capistrano receipt](https://github.com/Alchemy
|
|
261
261
|
|
262
262
|
If you want to contribute to Alchemy ([and we encourage you to do so](https://github.com/AlchemyCMS/alchemy_cms/blob/master/CONTRIBUTING.md)) we have a strong test suite that helps you to not break anything.
|
263
263
|
|
264
|
+
### Preparation
|
265
|
+
|
266
|
+
First of all you need to clone your fork to your local development machine. Then you need to install the dependencies with bundler.
|
267
|
+
|
268
|
+
```shell
|
269
|
+
$ bundle install
|
270
|
+
```
|
271
|
+
|
264
272
|
To prepare the tests of your Alchemy fork please make sure to run the preparation task:
|
265
273
|
|
266
274
|
```shell
|
267
|
-
|
268
|
-
$ bin/rake alchemy:spec:prepare
|
275
|
+
$ bundle exec rake alchemy:spec:prepare
|
269
276
|
```
|
270
277
|
|
271
278
|
to set up the database for testing.
|
@@ -276,7 +283,7 @@ to set up the database for testing.
|
|
276
283
|
$ bundle exec rspec
|
277
284
|
```
|
278
285
|
|
279
|
-
**Alternatively** you can just run
|
286
|
+
**Alternatively** you can just run*:
|
280
287
|
|
281
288
|
```shell
|
282
289
|
$ bundle exec rake
|
@@ -284,6 +291,16 @@ $ bundle exec rake
|
|
284
291
|
|
285
292
|
*) This default task executes the database preparations and runs all defined test cases.
|
286
293
|
|
294
|
+
### Start the dummy app
|
295
|
+
|
296
|
+
You can even start the dummy app and use it to manually test your changes with:
|
297
|
+
|
298
|
+
```shell
|
299
|
+
$ cd spec/dummy
|
300
|
+
$ bin/rake db:setup
|
301
|
+
$ bin/rails s
|
302
|
+
```
|
303
|
+
|
287
304
|
**A note about RSpec version:**
|
288
305
|
|
289
306
|
Alchemy specs are written **in RSpec 3**. Please **do not use deprecated RSpec 2.x syntax**. Thanks
|
@@ -22,8 +22,8 @@ Alchemy.translations =
|
|
22
22
|
'File is too large': 'Datei ist zu groß.'
|
23
23
|
'File is too small': 'Datei ist zu klein.'
|
24
24
|
'File type not allowed': 'Dateityp nicht erlaubt.'
|
25
|
-
'Maximum number of files exceeded': 'Maximale Anzahl
|
26
|
-
'Uploaded bytes exceed file size': '
|
25
|
+
'Maximum number of files exceeded': 'Maximale Anzahl gleichzeitig erlaubter Datei-Uploads erreicht.'
|
26
|
+
'Uploaded bytes exceed file size': 'Maximale Größe der erlaubten Dateigröße erreicht.'
|
27
27
|
|
28
28
|
# English
|
29
29
|
en:
|
@@ -109,7 +109,7 @@ Alchemy.translations =
|
|
109
109
|
'File type not allowed': 'Этот тип файла не разрешен'
|
110
110
|
'Maximum number of files exceeded': 'Исчерпано максимальное количество файлов.'
|
111
111
|
'Uploaded bytes exceed file size': 'Превышен максимальный размер файла'
|
112
|
-
|
112
|
+
|
113
113
|
# Spanish
|
114
114
|
es:
|
115
115
|
allowed_chars: 'de %{count} caracteres'
|
@@ -25,6 +25,7 @@ Alchemy.Uploader = (settings) ->
|
|
25
25
|
$("#fileupload").fileupload
|
26
26
|
dropZone: '#dropbox'
|
27
27
|
dataType: 'json'
|
28
|
+
filesContainer: $('#uploadProgressContainer')
|
28
29
|
acceptFileTypes: new RegExp("(.|/)(#{file_types})", "i")
|
29
30
|
maxNumberOfFiles: settings.file_upload_limit
|
30
31
|
maxFileSize: settings.file_size_limit * 1000000
|
@@ -32,6 +33,10 @@ Alchemy.Uploader = (settings) ->
|
|
32
33
|
form_data = form.serializeArray()
|
33
34
|
$.merge(form_data, settings.post_params)
|
34
35
|
form_data
|
36
|
+
getNumberOfFiles: ->
|
37
|
+
@filesContainer
|
38
|
+
.children()
|
39
|
+
.not('.progressBarInProgress').length - 1
|
35
40
|
add: (e, data) ->
|
36
41
|
$this = $(this)
|
37
42
|
data.context = new Alchemy.FileProgress(data.files[0])
|
@@ -3,24 +3,44 @@ module Alchemy
|
|
3
3
|
class EssenceFilesController < Alchemy::Admin::BaseController
|
4
4
|
authorize_resource class: Alchemy::EssenceFile
|
5
5
|
|
6
|
+
before_filter :load_essence_file, only: [:edit, :update]
|
7
|
+
|
6
8
|
helper "Alchemy::Admin::Contents"
|
7
9
|
|
8
10
|
def edit
|
9
|
-
@essence_file = EssenceFile.find(params[:id])
|
10
11
|
@content = @essence_file.content
|
11
12
|
@options = options_from_params
|
12
13
|
end
|
13
14
|
|
14
15
|
def update
|
15
|
-
@essence_file
|
16
|
-
@essence_file.update(params[:essence_file])
|
16
|
+
@essence_file.update(essence_file_params)
|
17
17
|
end
|
18
18
|
|
19
|
+
# Assigns file, but does not saves it.
|
20
|
+
#
|
21
|
+
# When the user saves the element the content gets updated as well.
|
22
|
+
#
|
19
23
|
def assign
|
20
24
|
@content = Content.find_by(id: params[:content_id])
|
21
25
|
@attachment = Attachment.find_by(id: params[:attachment_id])
|
22
26
|
@content.essence.attachment = @attachment
|
23
27
|
@options = options_from_params
|
28
|
+
|
29
|
+
# We need to update timestamp here because we don't save yet,
|
30
|
+
# but the cache needs to be get invalid.
|
31
|
+
# And we don't user @content.touch here, because that updates
|
32
|
+
# also the element and page timestamps what we don't want yet.
|
33
|
+
@content.update_column(:updated_at, Time.now)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def essence_file_params
|
39
|
+
params.require(:essence_file).permit(:title, :css_class)
|
40
|
+
end
|
41
|
+
|
42
|
+
def load_essence_file
|
43
|
+
@essence_file = EssenceFile.find(params[:id])
|
24
44
|
end
|
25
45
|
end
|
26
46
|
end
|
@@ -36,15 +36,20 @@ module Alchemy
|
|
36
36
|
|
37
37
|
# Assigns picture, but does not saves it.
|
38
38
|
#
|
39
|
-
# When the user
|
39
|
+
# When the user saves the element the content gets updated as well.
|
40
40
|
#
|
41
41
|
def assign
|
42
42
|
@picture = Picture.find_by(id: params[:picture_id])
|
43
43
|
@content.essence.picture = @picture
|
44
|
-
@content.touch # We need to touch manually because its not saved yet.
|
45
44
|
@element = @content.element
|
46
45
|
@dragable = @options[:grouped]
|
47
46
|
@options = @options.merge(dragable: @dragable)
|
47
|
+
|
48
|
+
# We need to update timestamp here because we don't save yet,
|
49
|
+
# but the cache needs to be get invalid.
|
50
|
+
# And we don't user @content.touch here, because that updates
|
51
|
+
# also the element and page timestamps what we don't want yet.
|
52
|
+
@content.update_column(:updated_at, Time.now)
|
48
53
|
end
|
49
54
|
|
50
55
|
def destroy
|
@@ -12,10 +12,7 @@ module Alchemy
|
|
12
12
|
|
13
13
|
def index
|
14
14
|
@size = params[:size].present? ? params[:size] : 'medium'
|
15
|
-
@pictures = Picture.
|
16
|
-
@pictures = @pictures.tagged_with(params[:tagged_with]) if params[:tagged_with].present?
|
17
|
-
@pictures = @pictures.filtered_by(params[:filter]) if params[:filter]
|
18
|
-
@pictures = @pictures.find_paginated(params, pictures_per_page_for_size(@size))
|
15
|
+
@pictures = Picture.find_paginated(params, pictures_per_page_for_size(@size))
|
19
16
|
if in_overlay?
|
20
17
|
archive_overlay
|
21
18
|
end
|
@@ -96,11 +96,13 @@ module Alchemy
|
|
96
96
|
protected
|
97
97
|
|
98
98
|
def permission_denied(exception = nil)
|
99
|
-
|
99
|
+
if exception
|
100
|
+
Rails.logger.debug <<-WARN
|
100
101
|
|
101
102
|
/!\\ Failed to permit #{exception.action} on #{exception.subject.inspect} for:
|
102
103
|
#{current_alchemy_user.inspect}
|
103
104
|
WARN
|
105
|
+
end
|
104
106
|
if current_alchemy_user
|
105
107
|
handle_redirect_for_user
|
106
108
|
else
|
@@ -184,7 +184,9 @@ module Alchemy
|
|
184
184
|
# @returns Boolean
|
185
185
|
#
|
186
186
|
def cache_page?
|
187
|
-
return false
|
187
|
+
return false if @page.nil? ||
|
188
|
+
!Rails.application.config.action_controller.perform_caching ||
|
189
|
+
!Alchemy::Config.get(:cache_pages)
|
188
190
|
page_layout = PageLayout.get(@page.page_layout)
|
189
191
|
page_layout['cache'] != false && page_layout['searchresults'] != true
|
190
192
|
end
|
@@ -37,9 +37,6 @@ module Alchemy
|
|
37
37
|
"element_id = #{element_id || 'null'} AND essence_type = '#{essence_type}'"
|
38
38
|
end
|
39
39
|
|
40
|
-
# Validations
|
41
|
-
validates :position, uniqueness: {scope: [:element_id, :essence_type]}
|
42
|
-
|
43
40
|
# Essence scopes
|
44
41
|
scope :essence_booleans, -> { where(essence_type: "Alchemy::EssenceBoolean") }
|
45
42
|
scope :essence_dates, -> { where(essence_type: "Alchemy::EssenceDate") }
|
@@ -29,7 +29,7 @@ module Alchemy
|
|
29
29
|
acts_as_taggable
|
30
30
|
|
31
31
|
# All Elements inside a cell are a list. All Elements not in cell are in the cell_id.nil list.
|
32
|
-
acts_as_list :
|
32
|
+
acts_as_list scope: [:page_id, :cell_id]
|
33
33
|
stampable stamper_class_name: Alchemy.user_class_name
|
34
34
|
|
35
35
|
has_many :contents, -> { order(:position) }, dependent: :destroy
|
@@ -39,7 +39,6 @@ module Alchemy
|
|
39
39
|
class_name: 'Alchemy::Page',
|
40
40
|
join_table: 'alchemy_elements_alchemy_pages'
|
41
41
|
|
42
|
-
validates_uniqueness_of :position, :scope => [:page_id, :cell_id], :if => lambda { |e| e.position != nil }
|
43
42
|
validates_presence_of :name, :on => :create
|
44
43
|
validates_format_of :name, :on => :create, :with => /\A[a-z0-9_-]+\z/
|
45
44
|
|
@@ -21,7 +21,9 @@ module Alchemy
|
|
21
21
|
# All pages locked by given user
|
22
22
|
#
|
23
23
|
scope :all_locked_by, ->(user) {
|
24
|
-
|
24
|
+
if user.class.respond_to? :primary_key
|
25
|
+
all_locked.where(locked_by: user.send(user.class.primary_key))
|
26
|
+
end
|
25
27
|
}
|
26
28
|
|
27
29
|
# All not locked pages
|
@@ -5,19 +5,19 @@ module Alchemy
|
|
5
5
|
# Returns the creator of this page.
|
6
6
|
#
|
7
7
|
def creator
|
8
|
-
|
8
|
+
get_page_user(creator_id)
|
9
9
|
end
|
10
10
|
|
11
11
|
# Returns the last updater of this page.
|
12
12
|
#
|
13
13
|
def updater
|
14
|
-
|
14
|
+
get_page_user(updater_id)
|
15
15
|
end
|
16
16
|
|
17
17
|
# Returns the user currently editing this page.
|
18
18
|
#
|
19
19
|
def locker
|
20
|
-
|
20
|
+
get_page_user(locked_by)
|
21
21
|
end
|
22
22
|
|
23
23
|
# Returns the name of the creator of this page.
|
@@ -47,5 +47,12 @@ module Alchemy
|
|
47
47
|
(locker && locker.try(:name)) || I18n.t('unknown')
|
48
48
|
end
|
49
49
|
|
50
|
+
private
|
51
|
+
|
52
|
+
def get_page_user(id)
|
53
|
+
if Alchemy.user_class.respond_to? :primary_key
|
54
|
+
Alchemy.user_class.try(:find_by, {Alchemy.user_class.primary_key => id})
|
55
|
+
end
|
56
|
+
end
|
50
57
|
end
|
51
58
|
end
|
@@ -62,10 +62,21 @@ module Alchemy
|
|
62
62
|
|
63
63
|
stampable stamper_class_name: Alchemy.user_class_name
|
64
64
|
|
65
|
-
scope :named,
|
66
|
-
|
67
|
-
|
68
|
-
|
65
|
+
scope :named, ->(name) {
|
66
|
+
where("#{self.table_name}.name LIKE ?", "%#{name}%")
|
67
|
+
}
|
68
|
+
|
69
|
+
scope :recent, -> {
|
70
|
+
where("#{self.table_name}.created_at > ?", Time.now - 24.hours).order(:created_at)
|
71
|
+
}
|
72
|
+
|
73
|
+
scope :deletable, -> {
|
74
|
+
where("#{self.table_name}.id NOT IN (SELECT picture_id FROM alchemy_essence_pictures)")
|
75
|
+
}
|
76
|
+
|
77
|
+
scope :without_tag, -> {
|
78
|
+
where("#{self.table_name}.cached_tag_list IS NULL OR #{self.table_name}.cached_tag_list = ''")
|
79
|
+
}
|
69
80
|
|
70
81
|
after_update :touch_contents
|
71
82
|
|
@@ -73,8 +84,21 @@ module Alchemy
|
|
73
84
|
|
74
85
|
class << self
|
75
86
|
|
87
|
+
# Returns filtered, paginated and ordered picture collection.
|
76
88
|
def find_paginated(params, per_page)
|
77
|
-
|
89
|
+
@pictures = Picture.all
|
90
|
+
|
91
|
+
if params[:tagged_with].present?
|
92
|
+
@pictures = @pictures.tagged_with(params[:tagged_with])
|
93
|
+
end
|
94
|
+
if params[:filter].present?
|
95
|
+
@pictures = @pictures.filtered_by(params[:filter])
|
96
|
+
end
|
97
|
+
if params[:query].present?
|
98
|
+
@pictures = @pictures.named(params[:query])
|
99
|
+
end
|
100
|
+
|
101
|
+
@pictures.page(params[:page] || 1).per(per_page).order(:name)
|
78
102
|
end
|
79
103
|
|
80
104
|
def last_upload
|
@@ -92,7 +116,6 @@ module Alchemy
|
|
92
116
|
all
|
93
117
|
end
|
94
118
|
end
|
95
|
-
|
96
119
|
end
|
97
120
|
|
98
121
|
# Instance methods
|
@@ -173,17 +173,24 @@ module Alchemy
|
|
173
173
|
# This function takes a target and a base dimensions hash and returns
|
174
174
|
# the dimensions of the image when the base dimensions hash fills
|
175
175
|
# the target.
|
176
|
+
#
|
176
177
|
# Aspect ratio will be preserved.
|
177
178
|
#
|
178
179
|
def size_when_fitting(target, dimensions = get_base_dimensions)
|
179
|
-
|
180
|
-
|
180
|
+
zoom = [
|
181
|
+
dimensions[:width].to_f / target[:width],
|
182
|
+
dimensions[:height].to_f / target[:height]
|
183
|
+
].max
|
184
|
+
|
185
|
+
if zoom == 0.0
|
186
|
+
width = target[:width]
|
187
|
+
height = target[:height]
|
188
|
+
else
|
189
|
+
width = (dimensions[:width] / zoom).round
|
190
|
+
height = (dimensions[:height] / zoom).round
|
191
|
+
end
|
181
192
|
|
182
|
-
|
183
|
-
{
|
184
|
-
width: (dimensions[:width] / zoom).round.to_i,
|
185
|
-
height: (dimensions[:height] / zoom).round.to_i
|
186
|
-
}
|
193
|
+
{width: width.to_i, height: height.to_i}
|
187
194
|
end
|
188
195
|
|
189
196
|
# Given a point as a Hash with :x and :y, and a mask with
|