admino 0.0.1 → 0.0.2
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/CHANGELOG.md +4 -0
- data/README.md +4 -0
- data/lib/admino/query.rb +2 -0
- data/lib/admino/query/base.rb +12 -1
- data/lib/admino/query/base_presenter.rb +1 -0
- data/lib/admino/query/configuration.rb +25 -0
- data/lib/admino/query/dsl.rb +5 -0
- data/lib/admino/query/group.rb +4 -4
- data/lib/admino/query/sorting.rb +74 -0
- data/lib/admino/query/sorting_presenter.rb +41 -0
- data/lib/admino/table/head_row.rb +11 -1
- data/lib/admino/table/presenter.rb +11 -5
- data/lib/admino/version.rb +2 -1
- data/spec/admino/query/base_spec.rb +17 -0
- data/spec/admino/query/dsl_spec.rb +7 -0
- data/spec/admino/query/group_presenter_spec.rb +20 -14
- data/spec/admino/query/group_spec.rb +7 -7
- data/spec/admino/query/sorting_presenter_spec.rb +167 -0
- data/spec/admino/query/sorting_spec.rb +129 -0
- data/spec/admino/table/head_row_spec.rb +27 -2
- data/spec/admino/table/presenter_spec.rb +3 -2
- data/spec/spec_helper.rb +4 -0
- metadata +8 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e3846d45b87e8e04505a972b8deabf753e7518ed
|
|
4
|
+
data.tar.gz: f5a5177a520c3e14ce1828f0158e983ae230f93e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c063c612bd312def34cccd381533613f7c13aa2ad27470065ebe1ec90671ad3abf71a49893a7986e9c1dae0aa757c5dc0f2b59285f863d610a331173a4f25fb7
|
|
7
|
+
data.tar.gz: dc64e3c91e279a3c631bdd1cdd7503d17b6945e8b6b3ccbc39566d9246b3007108ec09e3ba5e0588d01d4b2b2004e6ad5d1e578b340906b1812b7ee902d38707
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# Admino
|
|
2
2
|
|
|
3
|
+
[](https://travis-ci.org/cantierecreativo/admino)
|
|
4
|
+
[](https://coveralls.io/r/cantierecreativo/admino?branch=master)
|
|
5
|
+
|
|
3
6
|
TODO: Write a gem description
|
|
4
7
|
|
|
5
8
|
## Installation
|
|
@@ -27,3 +30,4 @@ TODO: Write usage instructions here
|
|
|
27
30
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
28
31
|
4. Push to the branch (`git push origin my-new-feature`)
|
|
29
32
|
5. Create new Pull Request
|
|
33
|
+
|
data/lib/admino/query.rb
CHANGED
data/lib/admino/query/base.rb
CHANGED
|
@@ -15,6 +15,7 @@ module Admino
|
|
|
15
15
|
attr_reader :params
|
|
16
16
|
attr_reader :groups
|
|
17
17
|
attr_reader :fields
|
|
18
|
+
attr_reader :sorting
|
|
18
19
|
|
|
19
20
|
def self.i18n_scope
|
|
20
21
|
:query
|
|
@@ -26,6 +27,7 @@ module Admino
|
|
|
26
27
|
|
|
27
28
|
init_groups
|
|
28
29
|
init_fields
|
|
30
|
+
init_sorting
|
|
29
31
|
end
|
|
30
32
|
|
|
31
33
|
def scope(starting_scope = nil)
|
|
@@ -37,7 +39,10 @@ module Admino
|
|
|
37
39
|
|
|
38
40
|
scope_builder = starting_scope
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
scope_augmenters = fields + groups
|
|
43
|
+
scope_augmenters << sorting if sorting
|
|
44
|
+
|
|
45
|
+
scope_augmenters.each do |field|
|
|
41
46
|
scope_builder = field.augment_scope(scope_builder)
|
|
42
47
|
end
|
|
43
48
|
|
|
@@ -88,6 +93,12 @@ module Admino
|
|
|
88
93
|
@fields[config.name] = Field.new(config, params)
|
|
89
94
|
end
|
|
90
95
|
end
|
|
96
|
+
|
|
97
|
+
def init_sorting
|
|
98
|
+
if config.sorting
|
|
99
|
+
@sorting = Sorting.new(config.sorting, params)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
91
102
|
end
|
|
92
103
|
end
|
|
93
104
|
end
|
|
@@ -27,8 +27,29 @@ module Admino
|
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
class Sorting
|
|
31
|
+
attr_reader :scopes
|
|
32
|
+
attr_reader :default_scope
|
|
33
|
+
attr_reader :default_direction
|
|
34
|
+
|
|
35
|
+
def initialize(scopes, options = {})
|
|
36
|
+
options.symbolize_keys!
|
|
37
|
+
options.assert_valid_keys(:default_scope, :default_direction)
|
|
38
|
+
|
|
39
|
+
@scopes = scopes.map(&:to_sym)
|
|
40
|
+
@default_scope = if options[:default_scope]
|
|
41
|
+
options[:default_scope].to_sym
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
@default_direction = if options[:default_direction]
|
|
45
|
+
options[:default_direction].to_sym
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
30
50
|
attr_reader :fields
|
|
31
51
|
attr_reader :groups
|
|
52
|
+
attr_reader :sorting
|
|
32
53
|
attr_accessor :starting_scope_callable
|
|
33
54
|
attr_accessor :ending_scope_callable
|
|
34
55
|
|
|
@@ -48,6 +69,10 @@ module Admino
|
|
|
48
69
|
self.groups << group
|
|
49
70
|
end
|
|
50
71
|
end
|
|
72
|
+
|
|
73
|
+
def add_sorting_scopes(scopes, options = {})
|
|
74
|
+
@sorting = Sorting.new(scopes, options)
|
|
75
|
+
end
|
|
51
76
|
end
|
|
52
77
|
end
|
|
53
78
|
end
|
data/lib/admino/query/dsl.rb
CHANGED
data/lib/admino/query/group.rb
CHANGED
|
@@ -15,14 +15,14 @@ module Admino
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def augment_scope(scope)
|
|
18
|
-
if
|
|
19
|
-
scope.send(
|
|
18
|
+
if active_scope
|
|
19
|
+
scope.send(active_scope)
|
|
20
20
|
else
|
|
21
21
|
scope
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
def
|
|
25
|
+
def active_scope
|
|
26
26
|
if param_value && available_scopes.include?(param_value.to_sym)
|
|
27
27
|
param_value.to_sym
|
|
28
28
|
else
|
|
@@ -31,7 +31,7 @@ module Admino
|
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def is_scope_active?(scope)
|
|
34
|
-
|
|
34
|
+
active_scope == scope
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
def param_value
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
require 'coercible'
|
|
2
|
+
require 'active_support/hash_with_indifferent_access'
|
|
3
|
+
require 'active_support/core_ext/hash'
|
|
4
|
+
|
|
5
|
+
module Admino
|
|
6
|
+
module Query
|
|
7
|
+
class Sorting
|
|
8
|
+
attr_reader :params
|
|
9
|
+
attr_reader :config
|
|
10
|
+
|
|
11
|
+
def initialize(config, params)
|
|
12
|
+
@config = config
|
|
13
|
+
@params = ActiveSupport::HashWithIndifferentAccess.new(params)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def augment_scope(scope)
|
|
17
|
+
if active_scope
|
|
18
|
+
scope.send(active_scope, ascending? ? :asc : :desc)
|
|
19
|
+
else
|
|
20
|
+
scope
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def is_scope_active?(scope)
|
|
25
|
+
active_scope == scope
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def ascending?
|
|
29
|
+
if params[:sort_order] == 'desc'
|
|
30
|
+
false
|
|
31
|
+
elsif params[:sort_order].blank? && active_scope == default_scope
|
|
32
|
+
default_direction_is_ascending?
|
|
33
|
+
else
|
|
34
|
+
true
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def active_scope
|
|
39
|
+
if param_value && available_scopes.include?(param_value.to_sym)
|
|
40
|
+
param_value.to_sym
|
|
41
|
+
elsif default_scope
|
|
42
|
+
default_scope
|
|
43
|
+
else
|
|
44
|
+
nil
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def default_scope
|
|
49
|
+
config.default_scope
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def default_direction_is_ascending?
|
|
53
|
+
config.default_direction != :desc
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def param_value
|
|
57
|
+
params.fetch(param_name, nil)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def param_name
|
|
61
|
+
:sorting
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def available_scopes
|
|
65
|
+
config.scopes
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def scope_name
|
|
69
|
+
config.name
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require 'showcase'
|
|
2
|
+
|
|
3
|
+
module Admino
|
|
4
|
+
module Query
|
|
5
|
+
class SortingPresenter < Showcase::Presenter
|
|
6
|
+
def scope_link(scope, label, *args)
|
|
7
|
+
options = args.extract_options!
|
|
8
|
+
|
|
9
|
+
desc_class = options.delete(:desc_class) { 'is-desc' }
|
|
10
|
+
asc_class = options.delete(:asc_class) { 'is-asc' }
|
|
11
|
+
|
|
12
|
+
options = Showcase::Helpers::HtmlOptions.new(options)
|
|
13
|
+
|
|
14
|
+
if is_scope_active?(scope)
|
|
15
|
+
options.add_class!(ascending? ? asc_class : desc_class)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
h.link_to label, scope_path(scope), options.to_h
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def scope_path(scope)
|
|
22
|
+
h.request.path + "?" + scope_params(scope).to_query
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def scope_params(scope)
|
|
26
|
+
params = ActiveSupport::HashWithIndifferentAccess.new(h.request.query_parameters)
|
|
27
|
+
|
|
28
|
+
if is_scope_active?(scope)
|
|
29
|
+
params.merge!(sorting: scope.to_s, sort_order: ascending? ? 'desc' : 'asc')
|
|
30
|
+
elsif default_scope == scope
|
|
31
|
+
params.merge!(sorting: scope.to_s, sort_order: default_direction.to_s)
|
|
32
|
+
else
|
|
33
|
+
params.merge!(sorting: scope.to_s, sort_order: 'asc')
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
params
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
@@ -5,9 +5,11 @@ module Admino
|
|
|
5
5
|
module Table
|
|
6
6
|
class HeadRow < Row
|
|
7
7
|
attr_reader :resource_klass
|
|
8
|
+
attr_reader :query
|
|
8
9
|
|
|
9
|
-
def initialize(resource_klass, view_context)
|
|
10
|
+
def initialize(resource_klass, query, view_context)
|
|
10
11
|
@resource_klass = resource_klass
|
|
12
|
+
@query = query
|
|
11
13
|
@columns = ""
|
|
12
14
|
|
|
13
15
|
super(view_context)
|
|
@@ -38,6 +40,14 @@ module Admino
|
|
|
38
40
|
default_options = column_html_options(attribute_name)
|
|
39
41
|
html_options = Showcase::Helpers::HtmlOptions.new(default_options)
|
|
40
42
|
html_options.merge_attrs!(options)
|
|
43
|
+
html_options = html_options.to_h
|
|
44
|
+
|
|
45
|
+
sorting_scope = html_options.delete(:sorting)
|
|
46
|
+
if sorting_scope
|
|
47
|
+
raise ArgumentError, 'query object is required' unless query
|
|
48
|
+
sorting_html_options = html_options.delete(:sorting_html_options) { {} }
|
|
49
|
+
label = query.sorting.scope_link(sorting_scope, label, sorting_html_options)
|
|
50
|
+
end
|
|
41
51
|
|
|
42
52
|
@columns << h.content_tag(:th, label.to_s, html_options.to_h)
|
|
43
53
|
end
|
|
@@ -6,6 +6,7 @@ module Admino
|
|
|
6
6
|
module Table
|
|
7
7
|
class Presenter < Showcase::Presenter
|
|
8
8
|
attr_reader :collection_klass
|
|
9
|
+
attr_reader :query
|
|
9
10
|
|
|
10
11
|
def self.tag_helper(name, tag, options = {})
|
|
11
12
|
default_options_method = :"#{name}_html_options"
|
|
@@ -28,8 +29,13 @@ module Admino
|
|
|
28
29
|
tag_helper :tbody, :tbody
|
|
29
30
|
tag_helper :tbody_tr, :tr, params: %w(resource index)
|
|
30
31
|
|
|
31
|
-
def initialize(
|
|
32
|
-
|
|
32
|
+
def initialize(*args)
|
|
33
|
+
context = args.pop
|
|
34
|
+
collection = args.shift
|
|
35
|
+
|
|
36
|
+
@collection_klass = args.shift
|
|
37
|
+
@query = args.shift
|
|
38
|
+
|
|
33
39
|
super(collection, context)
|
|
34
40
|
end
|
|
35
41
|
|
|
@@ -37,7 +43,7 @@ module Admino
|
|
|
37
43
|
table_tag(options) do
|
|
38
44
|
thead_tag do
|
|
39
45
|
thead_tr_tag do
|
|
40
|
-
row = head_row(collection_klass, view_context)
|
|
46
|
+
row = head_row(collection_klass, query, view_context)
|
|
41
47
|
h.capture(row, nil, &block) if block_given?
|
|
42
48
|
row.to_html
|
|
43
49
|
end
|
|
@@ -64,8 +70,8 @@ module Admino
|
|
|
64
70
|
@collection ||= present_collection(object)
|
|
65
71
|
end
|
|
66
72
|
|
|
67
|
-
def head_row(collection_klass, view_context)
|
|
68
|
-
HeadRow.new(collection_klass, view_context)
|
|
73
|
+
def head_row(collection_klass, query, view_context)
|
|
74
|
+
HeadRow.new(collection_klass, query, view_context)
|
|
69
75
|
end
|
|
70
76
|
|
|
71
77
|
def resource_row(resource, view_context)
|
data/lib/admino/version.rb
CHANGED
|
@@ -50,6 +50,23 @@ module Admino
|
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
+
context 'with a declared sorting' do
|
|
54
|
+
let(:config) { Configuration.new }
|
|
55
|
+
let(:sorting_config) do
|
|
56
|
+
config.add_sorting_scopes([:by_title, :by_date])
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
before do
|
|
60
|
+
sorting_config
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'returns a configured Sorting' do
|
|
64
|
+
sorting = query.sorting
|
|
65
|
+
expect(sorting.config).to eq sorting_config
|
|
66
|
+
expect(sorting.params).to eq params
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
53
70
|
describe '#scope' do
|
|
54
71
|
let(:config) { Configuration.new }
|
|
55
72
|
let(:result) { query.scope(starting_scope) }
|
|
@@ -18,6 +18,13 @@ module Admino
|
|
|
18
18
|
expect(group.scopes).to eq [:one, :two]
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
+
it 'allows #sortings declaration' do
|
|
22
|
+
sorting = config.sorting
|
|
23
|
+
expect(sorting.scopes).to eq [:by_title, :by_date]
|
|
24
|
+
expect(sorting.default_scope).to eq :by_title
|
|
25
|
+
expect(sorting.default_direction).to eq :desc
|
|
26
|
+
end
|
|
27
|
+
|
|
21
28
|
it 'allows #starting_scope block declaration' do
|
|
22
29
|
expect(config.starting_scope_callable.call).to eq 'start'
|
|
23
30
|
end
|
|
@@ -26,29 +26,33 @@ module Admino
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
describe '#scope_link' do
|
|
29
|
+
subject { presenter.scope_link(:foo) }
|
|
30
|
+
|
|
29
31
|
before do
|
|
30
|
-
group.stub(:is_scope_active?).with(:foo).and_return(
|
|
32
|
+
group.stub(:is_scope_active?).with(:foo).and_return(false)
|
|
31
33
|
end
|
|
32
34
|
|
|
33
35
|
context 'active CSS class' do
|
|
36
|
+
before do
|
|
37
|
+
group.stub(:is_scope_active?).with(:foo).and_return(true)
|
|
38
|
+
end
|
|
39
|
+
|
|
34
40
|
it 'adds an is-active class' do
|
|
35
|
-
|
|
41
|
+
should have_tag(:a, with: { class: 'is-active' })
|
|
36
42
|
end
|
|
37
43
|
|
|
38
44
|
context 'if an :active_class option is specified' do
|
|
45
|
+
subject { presenter.scope_link(:foo, active_class: 'active') }
|
|
46
|
+
|
|
39
47
|
it 'adds it' do
|
|
40
|
-
|
|
48
|
+
should have_tag(:a, with: { class: 'active' })
|
|
41
49
|
end
|
|
42
50
|
end
|
|
51
|
+
end
|
|
43
52
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
it 'does not add it' do
|
|
50
|
-
expect(presenter.scope_link(:foo)).not_to have_tag(:a, with: { class: 'is-active' })
|
|
51
|
-
end
|
|
53
|
+
context 'else' do
|
|
54
|
+
it 'does not add it' do
|
|
55
|
+
should_not have_tag(:a, with: { class: 'is-active' })
|
|
52
56
|
end
|
|
53
57
|
end
|
|
54
58
|
|
|
@@ -58,12 +62,14 @@ module Admino
|
|
|
58
62
|
end
|
|
59
63
|
|
|
60
64
|
it 'uses #scope_name method' do
|
|
61
|
-
|
|
65
|
+
should have_tag(:a, text: 'scope_name')
|
|
62
66
|
end
|
|
63
67
|
|
|
64
68
|
context 'if a second parameter is supplied' do
|
|
69
|
+
subject { presenter.scope_link(:foo, 'test', active_class: 'active') }
|
|
70
|
+
|
|
65
71
|
it 'uses it' do
|
|
66
|
-
|
|
72
|
+
should have_tag(:a, text: 'test')
|
|
67
73
|
end
|
|
68
74
|
end
|
|
69
75
|
end
|
|
@@ -74,7 +80,7 @@ module Admino
|
|
|
74
80
|
end
|
|
75
81
|
|
|
76
82
|
it 'uses #scope_path method' do
|
|
77
|
-
|
|
83
|
+
should have_tag(:a, href: 'URL')
|
|
78
84
|
end
|
|
79
85
|
end
|
|
80
86
|
end
|
|
@@ -7,28 +7,28 @@ module Admino
|
|
|
7
7
|
let(:config) { Configuration::Group.new(:foo, [:bar]) }
|
|
8
8
|
let(:params) { {} }
|
|
9
9
|
|
|
10
|
-
describe '#
|
|
10
|
+
describe '#active_scope' do
|
|
11
11
|
context 'with no param' do
|
|
12
12
|
let(:params) { {} }
|
|
13
13
|
|
|
14
|
-
it 'returns
|
|
15
|
-
expect(group.
|
|
14
|
+
it 'returns nil' do
|
|
15
|
+
expect(group.active_scope).to be_nil
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
context 'with an invalid value' do
|
|
20
20
|
let(:params) { { 'foo' => 'qux' } }
|
|
21
21
|
|
|
22
|
-
it 'returns
|
|
23
|
-
expect(group.
|
|
22
|
+
it 'returns nil' do
|
|
23
|
+
expect(group.active_scope).to be_nil
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
context 'with a valid value' do
|
|
28
28
|
let(:params) { { 'foo' => 'bar' } }
|
|
29
29
|
|
|
30
|
-
it 'returns
|
|
31
|
-
expect(group.
|
|
30
|
+
it 'returns the scope name' do
|
|
31
|
+
expect(group.active_scope).to eq :bar
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
34
|
end
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Admino
|
|
4
|
+
module Query
|
|
5
|
+
describe SortingPresenter do
|
|
6
|
+
subject(:presenter) { SortingPresenter.new(sorting, view) }
|
|
7
|
+
let(:view) { RailsViewContext.new }
|
|
8
|
+
let(:sorting) { double('Sorting', default_scope: 'by_name') }
|
|
9
|
+
let(:request_object) do
|
|
10
|
+
double(
|
|
11
|
+
'ActionDispatch::Request',
|
|
12
|
+
query_parameters: { 'sorting' => 'by_date' },
|
|
13
|
+
path: '/'
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
before do
|
|
18
|
+
view.stub(:request).and_return(request_object)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe '#scope_link' do
|
|
22
|
+
subject { presenter.scope_link(:by_title, 'Titolo') }
|
|
23
|
+
|
|
24
|
+
before do
|
|
25
|
+
sorting.stub(:is_scope_active?).with(:by_title).and_return(false)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context 'scope is active' do
|
|
29
|
+
before do
|
|
30
|
+
sorting.stub(:is_scope_active?).with(:by_title).and_return(true)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
context 'ascending' do
|
|
34
|
+
before do
|
|
35
|
+
sorting.stub(:ascending?).and_return(true)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'adds an is-asc class' do
|
|
39
|
+
should have_tag(:a, with: { class: 'is-asc' })
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
context 'if an :asc_class option is specified' do
|
|
43
|
+
subject { presenter.scope_link(:by_title, 'Titolo', asc_class: 'asc') }
|
|
44
|
+
|
|
45
|
+
it 'adds it' do
|
|
46
|
+
should have_tag(:a, with: { class: 'asc' })
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
context 'descendent' do
|
|
52
|
+
before do
|
|
53
|
+
sorting.stub(:ascending?).and_return(false)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'adds an is-desc class' do
|
|
57
|
+
should have_tag(:a, with: { class: 'is-desc' })
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
context 'if a :desc_class option is specified' do
|
|
61
|
+
subject { presenter.scope_link(:by_title, 'Titolo', desc_class: 'desc') }
|
|
62
|
+
|
|
63
|
+
it 'adds it' do
|
|
64
|
+
should have_tag(:a, with: { class: 'desc' })
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context 'else' do
|
|
71
|
+
it 'does not add it' do
|
|
72
|
+
should_not have_tag(:a, with: { class: 'is-asc' })
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
context 'label' do
|
|
77
|
+
it 'uses the provided argument' do
|
|
78
|
+
should have_tag(:a, text: 'Titolo')
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
context 'URL' do
|
|
83
|
+
before do
|
|
84
|
+
presenter.stub(:scope_path).with(:by_title).and_return('URL')
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it 'uses #scope_path method' do
|
|
88
|
+
should have_tag(:a, href: 'URL')
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
describe '#scope_params' do
|
|
94
|
+
subject { presenter.scope_params(:by_title) }
|
|
95
|
+
|
|
96
|
+
before do
|
|
97
|
+
sorting.stub(:is_scope_active?).with(:by_title).and_return(false)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it 'sets the sorting param as the scope' do
|
|
101
|
+
subject[:sorting] == 'by_title'
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
context 'scope is active' do
|
|
105
|
+
before do
|
|
106
|
+
sorting.stub(:is_scope_active?).with(:by_title).and_return(true)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
context 'is currently ascending' do
|
|
110
|
+
before do
|
|
111
|
+
sorting.stub(:ascending?).and_return(true)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it 'sets the sorting order to descending' do
|
|
115
|
+
subject[:sort_order] == 'desc'
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
context 'is currently descending' do
|
|
120
|
+
before do
|
|
121
|
+
sorting.stub(:ascending?).and_return(false)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it 'sets the sorting order to ascending' do
|
|
125
|
+
subject[:sort_order] == 'asc'
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
context 'scope is the default one' do
|
|
131
|
+
let(:sorting) { double('Sorting', default_scope: 'by_title') }
|
|
132
|
+
|
|
133
|
+
context 'default scope is ascending' do
|
|
134
|
+
before do
|
|
135
|
+
sorting.stub(:default_direction).and_return(:asc)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it 'sets the sorting order to ascending' do
|
|
139
|
+
subject[:sort_order] == 'asc'
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
context 'default scope is descending' do
|
|
144
|
+
before do
|
|
145
|
+
sorting.stub(:default_direction).and_return(:desc)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it 'sets the sorting order to descending' do
|
|
149
|
+
subject[:sort_order] == 'desc'
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
context 'else' do
|
|
155
|
+
before do
|
|
156
|
+
sorting.stub(:is_scope_active?).with(:by_title).and_return(false)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it 'sets the sorting order to ascending' do
|
|
160
|
+
subject[:sort_order] == 'asc'
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Admino
|
|
4
|
+
module Query
|
|
5
|
+
describe Sorting do
|
|
6
|
+
subject(:sorting) { Sorting.new(config, params) }
|
|
7
|
+
let(:config) do
|
|
8
|
+
Configuration::Sorting.new(sorting_scopes, options)
|
|
9
|
+
end
|
|
10
|
+
let(:sorting_scopes) { [:by_title, :by_date] }
|
|
11
|
+
let(:options) { {} }
|
|
12
|
+
let(:params) { {} }
|
|
13
|
+
|
|
14
|
+
describe '#active_scope' do
|
|
15
|
+
context 'with no param' do
|
|
16
|
+
let(:params) { {} }
|
|
17
|
+
|
|
18
|
+
it 'returns false' do
|
|
19
|
+
expect(sorting.active_scope).to be_nil
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context 'if a default scope is configured' do
|
|
23
|
+
let(:options) { { default_scope: :by_date } }
|
|
24
|
+
|
|
25
|
+
it 'returns it' do
|
|
26
|
+
expect(sorting.active_scope).to eq :by_date
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
context 'with an invalid value' do
|
|
32
|
+
let(:params) { { 'sorting' => 'foo' } }
|
|
33
|
+
|
|
34
|
+
it 'returns false' do
|
|
35
|
+
expect(sorting.active_scope).to be_nil
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context 'with a valid value' do
|
|
40
|
+
let(:params) { { 'sorting' => 'by_title' } }
|
|
41
|
+
|
|
42
|
+
it 'returns the scope name' do
|
|
43
|
+
expect(sorting.active_scope).to eq :by_title
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
describe '#ascending?' do
|
|
49
|
+
context 'with no param' do
|
|
50
|
+
let(:params) { {} }
|
|
51
|
+
|
|
52
|
+
it 'returns true' do
|
|
53
|
+
expect(sorting).to be_ascending
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
context 'with invalid value' do
|
|
58
|
+
let(:params) { { 'sort_order' => 'foo' } }
|
|
59
|
+
|
|
60
|
+
it 'returns true' do
|
|
61
|
+
expect(sorting).to be_ascending
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
context 'with "asc" value' do
|
|
66
|
+
let(:params) { { 'sort_order' => 'asc' } }
|
|
67
|
+
|
|
68
|
+
it 'returns nil' do
|
|
69
|
+
expect(sorting).to be_ascending
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context 'with "desc" value' do
|
|
74
|
+
let(:params) { { 'sort_order' => 'desc' } }
|
|
75
|
+
|
|
76
|
+
it 'returns the param value for the field' do
|
|
77
|
+
expect(sorting).not_to be_ascending
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
context 'if a default scope and direction are set and default scope is current' do
|
|
82
|
+
let(:options) { { default_scope: :by_date, default_direction: :desc } }
|
|
83
|
+
let(:params) { { 'sorting' => 'by_date', 'sort_order' => 'desc' } }
|
|
84
|
+
|
|
85
|
+
it 'returns it' do
|
|
86
|
+
expect(sorting).not_to be_ascending
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
describe '#augment_scope' do
|
|
92
|
+
let(:result) { sorting.augment_scope(scope) }
|
|
93
|
+
let(:scope) { ScopeMock.new('original') }
|
|
94
|
+
|
|
95
|
+
context 'if the field has a value' do
|
|
96
|
+
let(:params) { { 'sorting' => 'by_title', 'sort_order' => 'desc' } }
|
|
97
|
+
|
|
98
|
+
it 'returns the original scope chained with the current scope' do
|
|
99
|
+
expect(result.chain).to eq [:by_title, [:desc]]
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
context 'else' do
|
|
104
|
+
it 'returns the original scope' do
|
|
105
|
+
expect(result).to eq scope
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
context 'if a default scope is configured' do
|
|
110
|
+
let(:options) { { default_scope: :by_date } }
|
|
111
|
+
let(:params) { {} }
|
|
112
|
+
|
|
113
|
+
it 'returns the original scope chained with the default scope' do
|
|
114
|
+
expect(result.chain).to eq [:by_date, [:asc]]
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
context 'if a default direction is configured' do
|
|
118
|
+
let(:options) { { default_scope: :by_date, default_direction: :desc } }
|
|
119
|
+
|
|
120
|
+
it 'returns the original scope chained with the default scope and default direction' do
|
|
121
|
+
expect(result.chain).to eq [:by_date, [:desc]]
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
@@ -3,9 +3,10 @@ require 'spec_helper'
|
|
|
3
3
|
module Admino
|
|
4
4
|
module Table
|
|
5
5
|
describe HeadRow do
|
|
6
|
-
subject(:row) { HeadRow.new(klass, view) }
|
|
7
|
-
let(:view) { RailsViewContext.new }
|
|
6
|
+
subject(:row) { HeadRow.new(klass, query, view) }
|
|
8
7
|
let(:klass) { Post }
|
|
8
|
+
let(:query) { nil }
|
|
9
|
+
let(:view) { RailsViewContext.new }
|
|
9
10
|
|
|
10
11
|
it 'takes a class and a view context' do
|
|
11
12
|
expect(row.resource_klass).to eq klass
|
|
@@ -50,6 +51,30 @@ module Admino
|
|
|
50
51
|
end
|
|
51
52
|
end
|
|
52
53
|
|
|
54
|
+
context 'sorting' do
|
|
55
|
+
context 'if no query object is present' do
|
|
56
|
+
it 'raises an ArgumentError' do
|
|
57
|
+
expect { row.column(:title, sorting: :by_title) }.to raise_error ArgumentError
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
context 'else' do
|
|
62
|
+
let(:query) { double('Query', sorting: sorting) }
|
|
63
|
+
let(:sorting) { double('Sorting') }
|
|
64
|
+
|
|
65
|
+
before do
|
|
66
|
+
sorting.stub(:scope_link).with(:by_title, 'Title', {}).
|
|
67
|
+
and_return('Link')
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
before { row.column(:title, sorting: :by_title) }
|
|
71
|
+
|
|
72
|
+
it 'generates a sorting scope link' do
|
|
73
|
+
should have_tag(:th, text: 'Link')
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
53
78
|
context 'role' do
|
|
54
79
|
before { row.column(:author_name) }
|
|
55
80
|
|
|
@@ -4,8 +4,9 @@ require 'ostruct'
|
|
|
4
4
|
module Admino
|
|
5
5
|
module Table
|
|
6
6
|
describe Presenter do
|
|
7
|
-
subject(:presenter) { presenter_klass.new(collection, Post, view) }
|
|
7
|
+
subject(:presenter) { presenter_klass.new(collection, Post, query, view) }
|
|
8
8
|
let(:presenter_klass) { Presenter }
|
|
9
|
+
let(:query) { double('Query') }
|
|
9
10
|
let(:view) { RailsViewContext.new }
|
|
10
11
|
|
|
11
12
|
let(:collection) { [ first_post, second_post ] }
|
|
@@ -21,7 +22,7 @@ module Admino
|
|
|
21
22
|
PostPresenter.stub(:new).with(first_post, view).and_return(first_post_presenter)
|
|
22
23
|
PostPresenter.stub(:new).with(second_post, view).and_return(second_post_presenter)
|
|
23
24
|
|
|
24
|
-
HeadRow.stub(:new).with(Post, view).and_return(head_row)
|
|
25
|
+
HeadRow.stub(:new).with(Post, query, view).and_return(head_row)
|
|
25
26
|
ResourceRow.stub(:new).with(first_post_presenter, view).and_return(resource_row)
|
|
26
27
|
ResourceRow.stub(:new).with(second_post_presenter, view).and_return(resource_row)
|
|
27
28
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: admino
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stefano Verna
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2014-03-
|
|
11
|
+
date: 2014-03-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: showcase
|
|
@@ -188,6 +188,8 @@ files:
|
|
|
188
188
|
- lib/admino/query/field.rb
|
|
189
189
|
- lib/admino/query/group.rb
|
|
190
190
|
- lib/admino/query/group_presenter.rb
|
|
191
|
+
- lib/admino/query/sorting.rb
|
|
192
|
+
- lib/admino/query/sorting_presenter.rb
|
|
191
193
|
- lib/admino/table.rb
|
|
192
194
|
- lib/admino/table/head_row.rb
|
|
193
195
|
- lib/admino/table/presenter.rb
|
|
@@ -200,6 +202,8 @@ files:
|
|
|
200
202
|
- spec/admino/query/field_spec.rb
|
|
201
203
|
- spec/admino/query/group_presenter_spec.rb
|
|
202
204
|
- spec/admino/query/group_spec.rb
|
|
205
|
+
- spec/admino/query/sorting_presenter_spec.rb
|
|
206
|
+
- spec/admino/query/sorting_spec.rb
|
|
203
207
|
- spec/admino/table/head_row_spec.rb
|
|
204
208
|
- spec/admino/table/presenter_spec.rb
|
|
205
209
|
- spec/admino/table/resource_row_spec.rb
|
|
@@ -236,6 +240,8 @@ test_files:
|
|
|
236
240
|
- spec/admino/query/field_spec.rb
|
|
237
241
|
- spec/admino/query/group_presenter_spec.rb
|
|
238
242
|
- spec/admino/query/group_spec.rb
|
|
243
|
+
- spec/admino/query/sorting_presenter_spec.rb
|
|
244
|
+
- spec/admino/query/sorting_spec.rb
|
|
239
245
|
- spec/admino/table/head_row_spec.rb
|
|
240
246
|
- spec/admino/table/presenter_spec.rb
|
|
241
247
|
- spec/admino/table/resource_row_spec.rb
|