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.
- 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
|