gestart-admino 1.0.0
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 +7 -0
- data/.github/workflows/ci.yml +29 -0
- data/.gitignore +20 -0
- data/.tool-versions +1 -0
- data/CHANGELOG.md +91 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +716 -0
- data/Rakefile +6 -0
- data/gestart-admino.gemspec +36 -0
- data/lib/admino/action_view_extension.rb +35 -0
- data/lib/admino/query/base.rb +124 -0
- data/lib/admino/query/base_presenter.rb +27 -0
- data/lib/admino/query/builder.rb +24 -0
- data/lib/admino/query/configuration.rb +100 -0
- data/lib/admino/query/dsl.rb +38 -0
- data/lib/admino/query/filter_group.rb +73 -0
- data/lib/admino/query/filter_group_presenter.rb +85 -0
- data/lib/admino/query/scope_presenter.rb +17 -0
- data/lib/admino/query/search_field.rb +43 -0
- data/lib/admino/query/sorting.rb +74 -0
- data/lib/admino/query/sorting_presenter.rb +60 -0
- data/lib/admino/query.rb +15 -0
- data/lib/admino/table/head_row.rb +86 -0
- data/lib/admino/table/presenter.rb +122 -0
- data/lib/admino/table/resource_row.rb +145 -0
- data/lib/admino/table/row.rb +56 -0
- data/lib/admino/table.rb +7 -0
- data/lib/admino/version.rb +3 -0
- data/lib/admino.rb +14 -0
- data/lib/gestart-admino.rb +1 -0
- data/spec/admino/integration_spec.rb +63 -0
- data/spec/admino/query/base_presenter_spec.rb +59 -0
- data/spec/admino/query/base_spec.rb +192 -0
- data/spec/admino/query/dsl_spec.rb +52 -0
- data/spec/admino/query/filter_group_presenter_spec.rb +182 -0
- data/spec/admino/query/filter_group_spec.rb +133 -0
- data/spec/admino/query/search_field_spec.rb +66 -0
- data/spec/admino/query/sorting_presenter_spec.rb +206 -0
- data/spec/admino/query/sorting_spec.rb +137 -0
- data/spec/admino/table/head_row_spec.rb +158 -0
- data/spec/admino/table/presenter_spec.rb +180 -0
- data/spec/admino/table/resource_row_spec.rb +225 -0
- data/spec/admino/table/row_spec.rb +76 -0
- data/spec/spec_helper.rb +93 -0
- metadata +267 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
require 'showcase'
|
|
2
|
+
require 'active_support/core_ext/object/deep_dup'
|
|
3
|
+
|
|
4
|
+
module Admino
|
|
5
|
+
module Query
|
|
6
|
+
class SortingPresenter < Showcase::Presenter
|
|
7
|
+
def scope_link(scope, *args)
|
|
8
|
+
options = args.extract_options!
|
|
9
|
+
|
|
10
|
+
label = args.first || scope_name(scope)
|
|
11
|
+
|
|
12
|
+
desc_class = options.delete(:desc_class) { 'is-desc' }
|
|
13
|
+
asc_class = options.delete(:asc_class) { 'is-asc' }
|
|
14
|
+
|
|
15
|
+
options = Showcase::Helpers::HtmlOptions.new(options)
|
|
16
|
+
|
|
17
|
+
if is_scope_active?(scope)
|
|
18
|
+
options.add_class!(ascending? ? asc_class : desc_class)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
h.link_to label, scope_path(scope), options.to_h
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def scope_path(scope)
|
|
25
|
+
h.request.path + "?" + scope_params(scope).to_query
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def scopes
|
|
29
|
+
@scopes ||= super.map do |scope|
|
|
30
|
+
ScopePresenter.new(scope, self, view_context)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def scope_params(scope)
|
|
35
|
+
params = ActiveSupport::HashWithIndifferentAccess.new(
|
|
36
|
+
h.request.query_parameters.deep_dup
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
if is_scope_active?(scope)
|
|
40
|
+
params.merge!(sorting: scope.to_s, sort_order: ascending? ? 'desc' : 'asc')
|
|
41
|
+
elsif default_scope == scope
|
|
42
|
+
params.merge!(sorting: scope.to_s, sort_order: default_direction.to_s)
|
|
43
|
+
else
|
|
44
|
+
params.merge!(sorting: scope.to_s, sort_order: 'asc')
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
params
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def scope_name(scope)
|
|
51
|
+
I18n.t(
|
|
52
|
+
:"#{query_i18n_key}.#{scope}",
|
|
53
|
+
scope: 'query.sorting_scopes',
|
|
54
|
+
default: scope.to_s.titleize.capitalize
|
|
55
|
+
)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
data/lib/admino/query.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'admino/query/base'
|
|
2
|
+
require 'admino/query/base_presenter'
|
|
3
|
+
require 'admino/query/configuration'
|
|
4
|
+
require 'admino/query/search_field'
|
|
5
|
+
require 'admino/query/filter_group'
|
|
6
|
+
require 'admino/query/filter_group_presenter'
|
|
7
|
+
require 'admino/query/sorting'
|
|
8
|
+
require 'admino/query/sorting_presenter'
|
|
9
|
+
require 'admino/query/scope_presenter'
|
|
10
|
+
|
|
11
|
+
module Admino
|
|
12
|
+
module Query
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
require 'admino/table/row'
|
|
2
|
+
require 'showcase/helpers/html_options'
|
|
3
|
+
|
|
4
|
+
module Admino
|
|
5
|
+
module Table
|
|
6
|
+
class HeadRow < Row
|
|
7
|
+
attr_reader :resource_klass
|
|
8
|
+
attr_reader :query
|
|
9
|
+
|
|
10
|
+
def initialize(resource_klass, query, view_context)
|
|
11
|
+
@resource_klass = resource_klass
|
|
12
|
+
@query = query
|
|
13
|
+
@columns = +""
|
|
14
|
+
|
|
15
|
+
super(view_context)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def actions(*args, &block)
|
|
19
|
+
default_options = column_html_options(:actions)
|
|
20
|
+
label = I18n.t(
|
|
21
|
+
:"#{resource_klass.model_name.i18n_key}.title",
|
|
22
|
+
scope: 'table.actions',
|
|
23
|
+
default: [
|
|
24
|
+
:title,
|
|
25
|
+
'Actions'
|
|
26
|
+
]
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
@columns << h.content_tag(:th, label.to_s, default_options)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def column(*args, &block)
|
|
33
|
+
attribute_name, label, html_options = parse_column_args(args)
|
|
34
|
+
|
|
35
|
+
if label.nil?
|
|
36
|
+
label = column_label(attribute_name)
|
|
37
|
+
elsif label.is_a? Symbol
|
|
38
|
+
label = column_label(label)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
html_options = complete_column_html_options(
|
|
42
|
+
attribute_name,
|
|
43
|
+
html_options
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
sorting_scope = html_options.delete(:sorting)
|
|
47
|
+
sorting_html_options = html_options.delete(:sorting_html_options) { {} }
|
|
48
|
+
|
|
49
|
+
if sorting_scope
|
|
50
|
+
raise ArgumentError, 'query object is required' unless query
|
|
51
|
+
label = query.sorting.scope_link(sorting_scope, label, sorting_html_options)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
@columns << h.content_tag(:th, label.to_s, html_options)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def to_html
|
|
58
|
+
@columns.html_safe
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def column_label(attribute_name)
|
|
64
|
+
if attribute_name
|
|
65
|
+
resource_klass.human_attribute_name(attribute_name.to_s)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def complete_column_html_options(attribute_name, final_html_options)
|
|
70
|
+
if attribute_name.nil?
|
|
71
|
+
return final_html_options
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
default_options = column_html_options(attribute_name)
|
|
75
|
+
html_options = Showcase::Helpers::HtmlOptions.new(default_options)
|
|
76
|
+
html_options.merge_attrs!(final_html_options)
|
|
77
|
+
html_options = html_options.to_h
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def column_html_options(attribute_name)
|
|
81
|
+
{ role: attribute_name.to_s.gsub(/_/, '-') }
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
require 'showcase'
|
|
2
|
+
require 'admino/table/head_row'
|
|
3
|
+
require 'admino/table/resource_row'
|
|
4
|
+
|
|
5
|
+
module Admino
|
|
6
|
+
module Table
|
|
7
|
+
class Presenter < Showcase::Presenter
|
|
8
|
+
attr_reader :collection_klass
|
|
9
|
+
attr_reader :query
|
|
10
|
+
|
|
11
|
+
def self.tag_helper(name, tag, options = {})
|
|
12
|
+
options_method = :"#{name}_html_options"
|
|
13
|
+
|
|
14
|
+
define_method :"#{name}_tag" do |*args, &block|
|
|
15
|
+
options = args.extract_options!
|
|
16
|
+
if respond_to?(options_method, true)
|
|
17
|
+
default_options = send(options_method, *args)
|
|
18
|
+
html_options = Showcase::Helpers::HtmlOptions.new(default_options)
|
|
19
|
+
html_options.merge_attrs!(options)
|
|
20
|
+
options = html_options.to_h
|
|
21
|
+
end
|
|
22
|
+
h.content_tag(tag, options, &block)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
tag_helper :table, :table
|
|
27
|
+
tag_helper :thead, :thead
|
|
28
|
+
tag_helper :thead_tr, :tr
|
|
29
|
+
tag_helper :tbody, :tbody
|
|
30
|
+
tag_helper :tbody_tr, :tr, params: %w(resource index)
|
|
31
|
+
|
|
32
|
+
def initialize(*args)
|
|
33
|
+
context = args.pop
|
|
34
|
+
collection = args.shift
|
|
35
|
+
|
|
36
|
+
@collection_klass = args.shift
|
|
37
|
+
|
|
38
|
+
if !@collection_klass && !collection.empty?
|
|
39
|
+
@collection_klass = collection.first.class
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
@query = args.shift
|
|
43
|
+
|
|
44
|
+
super(collection, context)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def to_html(options = {}, &block)
|
|
48
|
+
|
|
49
|
+
if @collection_klass.nil?
|
|
50
|
+
raise ArgumentError, 'collection is empty and no explicit class is specified'
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
table_tag(options) do
|
|
54
|
+
thead_tag do
|
|
55
|
+
thead_tr_tag do
|
|
56
|
+
th_tags(&block)
|
|
57
|
+
end
|
|
58
|
+
end <<
|
|
59
|
+
tbody_tag do
|
|
60
|
+
tbody_tr_tags(&block)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
def tbody_tr_tags(&block)
|
|
68
|
+
collection.each_with_index.map do |resource, index|
|
|
69
|
+
html_options = base_tbody_tr_html_options(resource, index)
|
|
70
|
+
tbody_tr_tag(resource, index, html_options) do
|
|
71
|
+
td_tags(resource, &block)
|
|
72
|
+
end
|
|
73
|
+
end.join.html_safe
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def th_tags(&block)
|
|
77
|
+
row = head_row(collection_klass, query, view_context)
|
|
78
|
+
if block_given?
|
|
79
|
+
h.capture(row, nil, &block)
|
|
80
|
+
end
|
|
81
|
+
row.to_html
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def td_tags(resource, &block)
|
|
85
|
+
row = resource_row(resource, view_context)
|
|
86
|
+
if block_given?
|
|
87
|
+
h.capture(row, resource, &block)
|
|
88
|
+
end
|
|
89
|
+
row.to_html
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def collection
|
|
93
|
+
object
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def head_row(collection_klass, query, view_context)
|
|
97
|
+
HeadRow.new(collection_klass, query, view_context)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def resource_row(resource, view_context)
|
|
101
|
+
ResourceRow.new(resource, view_context)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def base_tbody_tr_html_options(resource, index)
|
|
105
|
+
options = {
|
|
106
|
+
class: zebra_css_classes[index % zebra_css_classes.size]
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if resource.respond_to?(:dom_id)
|
|
110
|
+
options[:id] = resource.dom_id
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
options
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def zebra_css_classes
|
|
117
|
+
%w(is-even is-odd)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
require 'admino/table/row'
|
|
2
|
+
require 'showcase/helpers/html_options'
|
|
3
|
+
|
|
4
|
+
module Admino
|
|
5
|
+
module Table
|
|
6
|
+
class ResourceRow < Row
|
|
7
|
+
attr_reader :resource
|
|
8
|
+
|
|
9
|
+
def initialize(resource, view_context)
|
|
10
|
+
@resource = resource
|
|
11
|
+
@columns = +""
|
|
12
|
+
@actions = []
|
|
13
|
+
|
|
14
|
+
super(view_context)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def column(*args, &block)
|
|
18
|
+
attribute_name, label, html_options = parse_column_args(args)
|
|
19
|
+
|
|
20
|
+
html_options = complete_column_html_options(
|
|
21
|
+
attribute_name,
|
|
22
|
+
html_options
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
if block_given?
|
|
26
|
+
content = h.capture(resource, &block)
|
|
27
|
+
elsif attribute_name.present?
|
|
28
|
+
content = resource.send(attribute_name)
|
|
29
|
+
else
|
|
30
|
+
raise ArgumentError, 'attribute name or block required'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
@columns << h.content_tag(:td, content, html_options)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def actions(*actions, &block)
|
|
37
|
+
if block_given?
|
|
38
|
+
h.capture(&block)
|
|
39
|
+
else
|
|
40
|
+
actions.each do |action|
|
|
41
|
+
action(action)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def action(*args, &block)
|
|
47
|
+
if block_given?
|
|
48
|
+
@actions << h.capture(resource, &block)
|
|
49
|
+
else
|
|
50
|
+
action_name, url, label, html_options = parse_action_args(args)
|
|
51
|
+
|
|
52
|
+
label ||= action_label(action_name)
|
|
53
|
+
url ||= action_url(action_name)
|
|
54
|
+
html_options = complete_action_html_options(
|
|
55
|
+
action_name,
|
|
56
|
+
html_options
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
@actions << h.link_to(label, url, html_options)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def to_html
|
|
64
|
+
buffer = @columns
|
|
65
|
+
|
|
66
|
+
if @actions.any?
|
|
67
|
+
html_options = column_html_options(:actions)
|
|
68
|
+
buffer << h.content_tag(:td, html_options) do
|
|
69
|
+
@actions.join(" ").html_safe
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
buffer.html_safe
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
def action_url(action_name)
|
|
79
|
+
if action_name.nil?
|
|
80
|
+
raise ArgumentError,
|
|
81
|
+
'no URL provided, action name required'
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
action_url_method = "#{action_name}_action_url"
|
|
85
|
+
|
|
86
|
+
if !respond_to?(action_url_method, true)
|
|
87
|
+
raise ArgumentError,
|
|
88
|
+
"no URL provided, ##{action_url_method} method required"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
url = send(action_url_method)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def complete_action_html_options(action_name, final_html_options)
|
|
95
|
+
if action_name
|
|
96
|
+
default_options = action_html_options(action_name)
|
|
97
|
+
html_options = Showcase::Helpers::HtmlOptions.new(default_options)
|
|
98
|
+
|
|
99
|
+
action_html_options_method = "#{action_name}_action_html_options"
|
|
100
|
+
if respond_to?(action_html_options_method, true)
|
|
101
|
+
html_options.merge_attrs!(send(action_html_options_method))
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
html_options.merge_attrs!(final_html_options)
|
|
105
|
+
html_options.to_h
|
|
106
|
+
else
|
|
107
|
+
final_html_options
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def complete_column_html_options(attribute_name, final_html_options)
|
|
112
|
+
if attribute_name
|
|
113
|
+
default_options = column_html_options(attribute_name)
|
|
114
|
+
html_options = Showcase::Helpers::HtmlOptions.new(default_options)
|
|
115
|
+
html_options.merge_attrs!(final_html_options)
|
|
116
|
+
html_options.to_h
|
|
117
|
+
else
|
|
118
|
+
final_html_options
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def action_label(action_name)
|
|
123
|
+
return nil unless action_name
|
|
124
|
+
|
|
125
|
+
I18n.t(
|
|
126
|
+
:"#{resource.class.model_name.i18n_key}.#{action_name}",
|
|
127
|
+
scope: 'table.actions',
|
|
128
|
+
default: [
|
|
129
|
+
:"#{action_name}",
|
|
130
|
+
action_name.to_s.titleize
|
|
131
|
+
]
|
|
132
|
+
)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def action_html_options(action_name)
|
|
136
|
+
{ role: action_name.to_s.gsub(/_/, '-') }
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def column_html_options(attribute_name)
|
|
140
|
+
{ role: attribute_name.to_s.gsub(/_/, '-') }
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
module Admino
|
|
2
|
+
module Table
|
|
3
|
+
class Row
|
|
4
|
+
attr_reader :view_context
|
|
5
|
+
|
|
6
|
+
alias_method :h, :view_context
|
|
7
|
+
|
|
8
|
+
def initialize(view_context)
|
|
9
|
+
@view_context = view_context
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def parse_column_args(args)
|
|
13
|
+
html_options = args.extract_options!
|
|
14
|
+
|
|
15
|
+
attribute_name = if args.first.is_a?(Symbol)
|
|
16
|
+
args.shift
|
|
17
|
+
else
|
|
18
|
+
nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
label = if args.first.is_a?(String) || args.first.is_a?(Symbol)
|
|
22
|
+
args.shift
|
|
23
|
+
else
|
|
24
|
+
nil
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
[attribute_name, label, html_options]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def parse_action_args(args)
|
|
31
|
+
html_options = args.extract_options!
|
|
32
|
+
|
|
33
|
+
action_name = if args.first.is_a?(Symbol)
|
|
34
|
+
args.shift
|
|
35
|
+
else
|
|
36
|
+
nil
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
url = if args.first.is_a?(String)
|
|
40
|
+
args.shift
|
|
41
|
+
else
|
|
42
|
+
nil
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
label = args.shift
|
|
46
|
+
|
|
47
|
+
[action_name, url, label, html_options]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def to_html
|
|
51
|
+
nil
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
data/lib/admino/table.rb
ADDED
data/lib/admino.rb
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require 'active_support/core_ext/module/delegation'
|
|
2
|
+
|
|
3
|
+
require "admino/version"
|
|
4
|
+
require "admino/query"
|
|
5
|
+
require "admino/table"
|
|
6
|
+
require "admino/action_view_extension"
|
|
7
|
+
|
|
8
|
+
module Admino
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
ActiveSupport.on_load(:action_view) do
|
|
12
|
+
include Admino::ActionViewExtension
|
|
13
|
+
end
|
|
14
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'admino'
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe 'Action View integration' do
|
|
4
|
+
let(:context) { RailsViewContext.new }
|
|
5
|
+
|
|
6
|
+
describe '#simple_table_for' do
|
|
7
|
+
let(:collection) { [ first_post, second_post ] }
|
|
8
|
+
let(:first_post) { Post.new('1') }
|
|
9
|
+
let(:second_post) { Post.new('2') }
|
|
10
|
+
let(:params) {
|
|
11
|
+
{
|
|
12
|
+
sorting: 'by_title',
|
|
13
|
+
sort_order: 'desc'
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
let(:query) { TestQuery.new(params) }
|
|
17
|
+
|
|
18
|
+
it 'produces HTML' do
|
|
19
|
+
result = context.table_for(collection, query: query) do |table, record|
|
|
20
|
+
table.column :title, sorting: :by_title
|
|
21
|
+
table.actions do
|
|
22
|
+
table.action :show, '/foo', 'Show'
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
expect(result).to have_tag(:table) do
|
|
27
|
+
with_tag 'thead th:first-child', with: { role: 'title' }
|
|
28
|
+
with_tag 'thead th:last-child', with: { role: 'actions' }
|
|
29
|
+
|
|
30
|
+
with_tag 'th:first-child a', with: { class: 'is-desc', href: '/?sort_order=asc&sorting=by_title' }, text: 'Title'
|
|
31
|
+
with_tag 'th:last-child', text: 'Actions'
|
|
32
|
+
|
|
33
|
+
with_tag 'tbody tr:first-child', with: { class: 'is-even' }
|
|
34
|
+
with_tag 'tbody tr:last-child', with: { class: 'is-odd' }
|
|
35
|
+
|
|
36
|
+
with_tag 'tbody tr:first-child td:first-child', with: { role: 'title' }, text: 'Post 1'
|
|
37
|
+
with_tag 'tbody tr:first-child td:last-child', with: { role: 'actions' }
|
|
38
|
+
|
|
39
|
+
with_tag 'tbody tr:first-child td:last-child a', with: { role: 'show', href: '/foo' }
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe '#simple_search_form_for' do
|
|
45
|
+
let(:params) {
|
|
46
|
+
{
|
|
47
|
+
query: { foo: 'test' }
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
let(:query) { TestQuery.new(params) }
|
|
51
|
+
|
|
52
|
+
it 'produces HTML' do
|
|
53
|
+
result = context.simple_search_form_for(query) do |f|
|
|
54
|
+
f.input :foo
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
expect(result).to have_tag(:form, with: { action: '/?p=1', method: 'get' }) do
|
|
58
|
+
with_tag 'input', with: { type: 'text', value: 'test', name: 'query[foo]' }
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Admino
|
|
4
|
+
module Query
|
|
5
|
+
describe BasePresenter do
|
|
6
|
+
subject(:presenter) { BasePresenter.new(query, view) }
|
|
7
|
+
let(:view) { RailsViewContext.new }
|
|
8
|
+
let(:query) do
|
|
9
|
+
TestQuery.new(query: { foo: 'value' })
|
|
10
|
+
end
|
|
11
|
+
let(:request_object) do
|
|
12
|
+
double(
|
|
13
|
+
'ActionDispatch::Request',
|
|
14
|
+
fullpath: '/?foo=bar'
|
|
15
|
+
)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
before do
|
|
19
|
+
allow(view).to receive(:request).and_return(request_object)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe '#simple_form' do
|
|
23
|
+
let(:result) do
|
|
24
|
+
presenter.simple_form do |form|
|
|
25
|
+
form.input(:foo)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
before do
|
|
30
|
+
I18n.backend.store_translations(
|
|
31
|
+
:en,
|
|
32
|
+
query: { attributes: { test_query: { foo: 'NAME' } } }
|
|
33
|
+
)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'renders a form pointing to the current URL' do
|
|
37
|
+
expect(result).to have_tag(:form, with: { action: '/?foo=bar' })
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'renders a form with method GET' do
|
|
41
|
+
expect(result).to have_tag(:form, with: { method: 'get' })
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'renders inputs with a query[] name prefix' do
|
|
45
|
+
expect(result).to have_tag(:input, with: { type: 'text', name: 'query[foo]' })
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'prefills inputs with query value' do
|
|
49
|
+
expect(result).to have_tag(:input, with: { type: 'text', value: 'value' })
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'it generates labels in the :query I18n space' do
|
|
53
|
+
expect(result).to have_tag(:label, content: 'NAME')
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|