admino 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.travis.yml +9 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +6 -0
- data/admino.gemspec +34 -0
- data/lib/admino.rb +9 -0
- data/lib/admino/query.rb +12 -0
- data/lib/admino/query/base.rb +94 -0
- data/lib/admino/query/base_presenter.rb +34 -0
- data/lib/admino/query/configuration.rb +54 -0
- data/lib/admino/query/dsl.rb +30 -0
- data/lib/admino/query/field.rb +52 -0
- data/lib/admino/query/group.rb +55 -0
- data/lib/admino/query/group_presenter.rb +67 -0
- data/lib/admino/table.rb +7 -0
- data/lib/admino/table/head_row.rb +59 -0
- data/lib/admino/table/presenter.rb +81 -0
- data/lib/admino/table/resource_row.rb +135 -0
- data/lib/admino/table/row.rb +65 -0
- data/lib/admino/version.rb +3 -0
- data/spec/admino/query/base_presenter_spec.rb +60 -0
- data/spec/admino/query/base_spec.rb +133 -0
- data/spec/admino/query/dsl_spec.rb +45 -0
- data/spec/admino/query/field_spec.rb +69 -0
- data/spec/admino/query/group_presenter_spec.rb +140 -0
- data/spec/admino/query/group_spec.rb +65 -0
- data/spec/admino/table/head_row_spec.rb +116 -0
- data/spec/admino/table/presenter_spec.rb +168 -0
- data/spec/admino/table/resource_row_spec.rb +206 -0
- data/spec/admino/table/row_spec.rb +71 -0
- data/spec/spec_helper.rb +82 -0
- metadata +244 -0
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'active_support/hash_with_indifferent_access'
|
2
|
+
require 'active_support/core_ext/hash'
|
3
|
+
|
4
|
+
module Admino
|
5
|
+
module Query
|
6
|
+
class Group
|
7
|
+
attr_reader :params
|
8
|
+
attr_reader :config
|
9
|
+
attr_reader :query_i18n_key
|
10
|
+
|
11
|
+
def initialize(config, params, query_i18n_key = nil)
|
12
|
+
@config = config
|
13
|
+
@params = ActiveSupport::HashWithIndifferentAccess.new(params)
|
14
|
+
@query_i18n_key = query_i18n_key
|
15
|
+
end
|
16
|
+
|
17
|
+
def augment_scope(scope)
|
18
|
+
if current_scope
|
19
|
+
scope.send(current_scope)
|
20
|
+
else
|
21
|
+
scope
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def current_scope
|
26
|
+
if param_value && available_scopes.include?(param_value.to_sym)
|
27
|
+
param_value.to_sym
|
28
|
+
else
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def is_scope_active?(scope)
|
34
|
+
current_scope == scope
|
35
|
+
end
|
36
|
+
|
37
|
+
def param_value
|
38
|
+
params.fetch(param_name, nil)
|
39
|
+
end
|
40
|
+
|
41
|
+
def param_name
|
42
|
+
config.name
|
43
|
+
end
|
44
|
+
|
45
|
+
def available_scopes
|
46
|
+
[nil] + config.scopes
|
47
|
+
end
|
48
|
+
|
49
|
+
def i18n_key
|
50
|
+
config.name
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'i18n'
|
2
|
+
require 'showcase'
|
3
|
+
require 'showcase/helpers/html_options'
|
4
|
+
require 'active_support/core_ext/array/extract_options'
|
5
|
+
require 'active_support/hash_with_indifferent_access'
|
6
|
+
require 'active_support/core_ext/hash'
|
7
|
+
|
8
|
+
module Admino
|
9
|
+
module Query
|
10
|
+
class GroupPresenter < Showcase::Presenter
|
11
|
+
def scope_link(scope, *args)
|
12
|
+
options = args.extract_options!
|
13
|
+
|
14
|
+
label = args.first || scope_name(scope)
|
15
|
+
|
16
|
+
active_class = options.delete(:active_class) { 'is-active' }
|
17
|
+
options = Showcase::Helpers::HtmlOptions.new(options)
|
18
|
+
|
19
|
+
if is_scope_active?(scope)
|
20
|
+
options.add_class!(active_class)
|
21
|
+
end
|
22
|
+
|
23
|
+
h.link_to label, scope_path(scope), options.to_h
|
24
|
+
end
|
25
|
+
|
26
|
+
def scope_path(scope)
|
27
|
+
h.request.path + "?" + scope_params(scope).to_query
|
28
|
+
end
|
29
|
+
|
30
|
+
def scope_params(scope)
|
31
|
+
params = ActiveSupport::HashWithIndifferentAccess.new(h.request.query_parameters)
|
32
|
+
|
33
|
+
if scope
|
34
|
+
params.merge!(param_name => scope.to_s)
|
35
|
+
else
|
36
|
+
params.delete(param_name)
|
37
|
+
end
|
38
|
+
|
39
|
+
params
|
40
|
+
end
|
41
|
+
|
42
|
+
def scope_name(scope)
|
43
|
+
scope ||= 'none'
|
44
|
+
I18n.t(
|
45
|
+
:"#{query_i18n_key}.#{i18n_key}.scopes.#{scope}",
|
46
|
+
scope: 'query.groups',
|
47
|
+
default: [
|
48
|
+
:"#{i18n_key}.scopes.#{scope}",
|
49
|
+
scope.to_s.titleize
|
50
|
+
]
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
def name
|
55
|
+
I18n.t(
|
56
|
+
:"#{query_i18n_key}.#{i18n_key}.name",
|
57
|
+
scope: 'query.groups',
|
58
|
+
default: [
|
59
|
+
:"#{i18n_key}.name",
|
60
|
+
i18n_key.to_s.titleize
|
61
|
+
]
|
62
|
+
)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
data/lib/admino/table.rb
ADDED
@@ -0,0 +1,59 @@
|
|
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
|
+
|
9
|
+
def initialize(resource_klass, view_context)
|
10
|
+
@resource_klass = resource_klass
|
11
|
+
@columns = ""
|
12
|
+
|
13
|
+
super(view_context)
|
14
|
+
end
|
15
|
+
|
16
|
+
def actions(*args, &block)
|
17
|
+
default_options = column_html_options(:actions)
|
18
|
+
label = I18n.t(
|
19
|
+
:"#{resource_klass.model_name.i18n_key}.title",
|
20
|
+
scope: 'table.actions',
|
21
|
+
default: [ :title, 'Actions' ]
|
22
|
+
)
|
23
|
+
|
24
|
+
@columns << h.content_tag(:th, label.to_s, default_options)
|
25
|
+
end
|
26
|
+
|
27
|
+
def column(*args, &block)
|
28
|
+
params = parse_column_args(args)
|
29
|
+
|
30
|
+
attribute_name = params[:attribute_name]
|
31
|
+
label = params[:label]
|
32
|
+
options = params[:html_options]
|
33
|
+
|
34
|
+
if label.nil? && attribute_name
|
35
|
+
label = resource_klass.human_attribute_name(attribute_name.to_s)
|
36
|
+
end
|
37
|
+
|
38
|
+
default_options = column_html_options(attribute_name)
|
39
|
+
html_options = Showcase::Helpers::HtmlOptions.new(default_options)
|
40
|
+
html_options.merge_attrs!(options)
|
41
|
+
|
42
|
+
@columns << h.content_tag(:th, label.to_s, html_options.to_h)
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_html
|
46
|
+
@columns.html_safe
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def column_html_options(attribute_name)
|
52
|
+
if attribute_name
|
53
|
+
{ role: attribute_name.to_s.gsub(/_/, '-') }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
@@ -0,0 +1,81 @@
|
|
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
|
+
|
10
|
+
def self.tag_helper(name, tag, options = {})
|
11
|
+
default_options_method = :"#{name}_html_options"
|
12
|
+
|
13
|
+
define_method :"#{name}_tag" do |*args, &block|
|
14
|
+
options = args.extract_options!
|
15
|
+
if respond_to?(default_options_method, true)
|
16
|
+
default_options = send(default_options_method, *args)
|
17
|
+
html_options = Showcase::Helpers::HtmlOptions.new(default_options)
|
18
|
+
html_options.merge_attrs!(options)
|
19
|
+
options = html_options.to_h
|
20
|
+
end
|
21
|
+
h.content_tag(tag, options, &block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
tag_helper :table, :table
|
26
|
+
tag_helper :thead, :thead
|
27
|
+
tag_helper :thead_tr, :tr
|
28
|
+
tag_helper :tbody, :tbody
|
29
|
+
tag_helper :tbody_tr, :tr, params: %w(resource index)
|
30
|
+
|
31
|
+
def initialize(collection, klass, context)
|
32
|
+
@collection_klass = klass
|
33
|
+
super(collection, context)
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_html(options = {}, &block)
|
37
|
+
table_tag(options) do
|
38
|
+
thead_tag do
|
39
|
+
thead_tr_tag do
|
40
|
+
row = head_row(collection_klass, view_context)
|
41
|
+
h.capture(row, nil, &block) if block_given?
|
42
|
+
row.to_html
|
43
|
+
end
|
44
|
+
end <<
|
45
|
+
tbody_tag do
|
46
|
+
collection.each_with_index.map do |resource, index|
|
47
|
+
tr_html_options = {
|
48
|
+
class: zebra_css_classes[index % zebra_css_classes.size],
|
49
|
+
id: resource.dom_id
|
50
|
+
}
|
51
|
+
tbody_tr_tag(resource, index, tr_html_options) do
|
52
|
+
row = resource_row(resource, view_context)
|
53
|
+
h.capture(row, resource, &block) if block_given?
|
54
|
+
row.to_html
|
55
|
+
end
|
56
|
+
end.join.html_safe
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def collection
|
64
|
+
@collection ||= present_collection(object)
|
65
|
+
end
|
66
|
+
|
67
|
+
def head_row(collection_klass, view_context)
|
68
|
+
HeadRow.new(collection_klass, view_context)
|
69
|
+
end
|
70
|
+
|
71
|
+
def resource_row(resource, view_context)
|
72
|
+
ResourceRow.new(resource, view_context)
|
73
|
+
end
|
74
|
+
|
75
|
+
def zebra_css_classes
|
76
|
+
%w(is-even is-odd)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
@@ -0,0 +1,135 @@
|
|
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
|
+
params = parse_column_args(args)
|
19
|
+
|
20
|
+
attribute_name = params[:attribute_name]
|
21
|
+
label = params[:label]
|
22
|
+
options = params[:html_options]
|
23
|
+
|
24
|
+
if block_given?
|
25
|
+
content = h.capture(resource, &block)
|
26
|
+
elsif attribute_name.present?
|
27
|
+
content = resource.send(attribute_name)
|
28
|
+
else
|
29
|
+
raise ArgumentError, 'attribute name or block required'
|
30
|
+
end
|
31
|
+
|
32
|
+
default_options = column_html_options(attribute_name)
|
33
|
+
html_options = Showcase::Helpers::HtmlOptions.new(default_options)
|
34
|
+
html_options.merge_attrs!(options)
|
35
|
+
|
36
|
+
@columns << h.content_tag(:td, content, html_options.to_h)
|
37
|
+
end
|
38
|
+
|
39
|
+
def actions(*actions, &block)
|
40
|
+
if block_given?
|
41
|
+
h.capture(&block)
|
42
|
+
else
|
43
|
+
actions.each do |action|
|
44
|
+
action(action)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def action(*args, &block)
|
50
|
+
params = parse_action_args(args)
|
51
|
+
|
52
|
+
action_name = params[:action_name]
|
53
|
+
label = params[:label]
|
54
|
+
url = params[:url]
|
55
|
+
options = params[:html_options]
|
56
|
+
|
57
|
+
if block_given?
|
58
|
+
@actions << h.capture(resource, &block)
|
59
|
+
return
|
60
|
+
end
|
61
|
+
|
62
|
+
if url.nil?
|
63
|
+
if action_name.nil?
|
64
|
+
raise ArgumentError, 'no URL provided, action name required'
|
65
|
+
end
|
66
|
+
|
67
|
+
action_url_method = "#{action_name}_action_url"
|
68
|
+
|
69
|
+
if !respond_to?(action_url_method, true)
|
70
|
+
raise ArgumentError,
|
71
|
+
"no URL provided, ##{action_url_method} method required"
|
72
|
+
end
|
73
|
+
|
74
|
+
url = send(action_url_method)
|
75
|
+
end
|
76
|
+
|
77
|
+
base_options = if action_name
|
78
|
+
action_html_options(action_name)
|
79
|
+
end
|
80
|
+
|
81
|
+
html_options = Showcase::Helpers::HtmlOptions.new(base_options)
|
82
|
+
|
83
|
+
action_html_options_method = "#{action_name}_action_html_options"
|
84
|
+
|
85
|
+
if respond_to?(action_html_options_method, true)
|
86
|
+
action_html_options = send(action_html_options_method)
|
87
|
+
html_options.merge_attrs!(action_html_options)
|
88
|
+
end
|
89
|
+
|
90
|
+
html_options.merge_attrs!(options)
|
91
|
+
|
92
|
+
if label.nil? && action_name
|
93
|
+
label = I18n.t(
|
94
|
+
:"#{resource.class.model_name.i18n_key}.#{action_name}",
|
95
|
+
scope: 'table.actions',
|
96
|
+
default: [
|
97
|
+
:"#{action_name}",
|
98
|
+
action_name.to_s.titleize
|
99
|
+
]
|
100
|
+
)
|
101
|
+
end
|
102
|
+
|
103
|
+
@actions << h.link_to(label, url, html_options.to_h)
|
104
|
+
end
|
105
|
+
|
106
|
+
def to_html
|
107
|
+
buffer = @columns
|
108
|
+
|
109
|
+
if @actions.any?
|
110
|
+
html_options = column_html_options(:actions)
|
111
|
+
buffer << h.content_tag(:td, html_options) do
|
112
|
+
@actions.join(" ").html_safe
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
buffer.html_safe
|
117
|
+
end
|
118
|
+
|
119
|
+
private
|
120
|
+
|
121
|
+
def action_html_options(action_name)
|
122
|
+
if action_name
|
123
|
+
{ role: action_name.to_s.gsub(/_/, '-') }
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def column_html_options(attribute_name)
|
128
|
+
if attribute_name
|
129
|
+
{ role: attribute_name.to_s.gsub(/_/, '-') }
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
@@ -0,0 +1,65 @@
|
|
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
|
+
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)
|
22
|
+
args.shift
|
23
|
+
else
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
|
27
|
+
{
|
28
|
+
attribute_name: attribute_name,
|
29
|
+
label: label,
|
30
|
+
html_options: options
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def parse_action_args(args)
|
35
|
+
options = args.extract_options!
|
36
|
+
|
37
|
+
action_name = if args.first.is_a?(Symbol)
|
38
|
+
args.shift
|
39
|
+
else
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
|
43
|
+
url = if args.first.is_a?(String)
|
44
|
+
args.shift
|
45
|
+
else
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
|
49
|
+
label = args.shift
|
50
|
+
|
51
|
+
{
|
52
|
+
action_name: action_name,
|
53
|
+
url: url,
|
54
|
+
label: label,
|
55
|
+
html_options: options
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_html
|
60
|
+
nil
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|