admino 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 95d1dd4a6bc98fcad84bb9d2269ac8104bdc4beb
4
- data.tar.gz: c5a3bf57e8c8c22abb5f3f26a45e324c8204415a
3
+ metadata.gz: e3846d45b87e8e04505a972b8deabf753e7518ed
4
+ data.tar.gz: f5a5177a520c3e14ce1828f0158e983ae230f93e
5
5
  SHA512:
6
- metadata.gz: 222f144346d9e0c3666f7eb682c716599bd883376265d7ad10bb257805d39e8d0cdcade04fd7ac3cf73d2ca9f5bedb888ac4b534db6df5c0e03aff2c535f9ca5
7
- data.tar.gz: 8a1117eb95c79108304c0d27e02578843f9a3bb985718202d1401d5b44cd8c44c263d83bfa5a1cc67dbb1a15d90cbc66a45e30921b1487d0619ebea5bb557bc2
6
+ metadata.gz: c063c612bd312def34cccd381533613f7c13aa2ad27470065ebe1ec90671ad3abf71a49893a7986e9c1dae0aa757c5dc0f2b59285f863d610a331173a4f25fb7
7
+ data.tar.gz: dc64e3c91e279a3c631bdd1cdd7503d17b6945e8b6b3ccbc39566d9246b3007108ec09e3ba5e0588d01d4b2b2004e6ad5d1e578b340906b1812b7ee902d38707
@@ -1,3 +1,7 @@
1
+ # v0.0.2
2
+
3
+ * Support to sortings
4
+
1
5
  # v0.0.1
2
6
 
3
7
  * First release
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Admino
2
2
 
3
+ [![Build Status](https://travis-ci.org/cantierecreativo/admino.png?branch=v0.0.1)](https://travis-ci.org/cantierecreativo/admino)
4
+ [![Coverage Status](https://coveralls.io/repos/cantierecreativo/admino/badge.png?branch=master)](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
+
@@ -4,6 +4,8 @@ require 'admino/query/configuration'
4
4
  require 'admino/query/field'
5
5
  require 'admino/query/group'
6
6
  require 'admino/query/group_presenter'
7
+ require 'admino/query/sorting'
8
+ require 'admino/query/sorting_presenter'
7
9
 
8
10
  module Admino
9
11
  module Query
@@ -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
- (fields + groups).each do |field|
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
@@ -4,6 +4,7 @@ module Admino
4
4
  module Query
5
5
  class BasePresenter < Showcase::Presenter
6
6
  presents_collection :groups
7
+ presents :sorting
7
8
 
8
9
  def form(options = {}, &block)
9
10
  h.form_for(
@@ -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
@@ -17,6 +17,11 @@ module Admino
17
17
  config.add_group(name, scopes)
18
18
  end
19
19
 
20
+ def sorting(*args)
21
+ options = args.extract_options!
22
+ config.add_sorting_scopes(args, options)
23
+ end
24
+
20
25
  def starting_scope(&block)
21
26
  config.starting_scope_callable = block
22
27
  end
@@ -15,14 +15,14 @@ module Admino
15
15
  end
16
16
 
17
17
  def augment_scope(scope)
18
- if current_scope
19
- scope.send(current_scope)
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 current_scope
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
- current_scope == scope
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(collection, klass, context)
32
- @collection_klass = klass
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)
@@ -1,3 +1,4 @@
1
1
  module Admino
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
4
+
@@ -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(true)
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
- expect(presenter.scope_link(:foo)).to have_tag(:a, with: { class: 'is-active' })
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
- expect(presenter.scope_link(:foo, active_class: 'active')).to have_tag(:a, with: { class: 'active' })
48
+ should have_tag(:a, with: { class: 'active' })
41
49
  end
42
50
  end
51
+ end
43
52
 
44
- context 'else' do
45
- before do
46
- group.stub(:is_scope_active?).with(:foo).and_return(false)
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
- expect(presenter.scope_link(:foo)).to have_tag(:a, text: 'scope_name')
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
- expect(presenter.scope_link(:foo, 'test')).to have_tag(:a, text: 'test')
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
- expect(presenter.scope_link(:foo)).to have_tag(:a, href: 'URL')
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 '#current_scope' do
10
+ describe '#active_scope' do
11
11
  context 'with no param' do
12
12
  let(:params) { {} }
13
13
 
14
- it 'returns the param value for the field' do
15
- expect(group.current_scope).to be_nil
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 the param value for the field' do
23
- expect(group.current_scope).to be_nil
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 nil' do
31
- expect(group.current_scope).to eq :bar
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
@@ -37,6 +37,10 @@ class TestQuery < Admino::Query::Base
37
37
 
38
38
  group :bar, [:one, :two]
39
39
 
40
+ sorting :by_title, :by_date,
41
+ default_scope: :by_title,
42
+ default_direction: :desc
43
+
40
44
  starting_scope { 'start' }
41
45
  ending_scope { 'end' }
42
46
  end
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.1
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-16 00:00:00.000000000 Z
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