goodmin 0.0.1
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/MIT-LICENSE +20 -0
- data/README.md +1359 -0
- data/Rakefile +56 -0
- data/app/assets/stylesheets/goodmin/application.css +75 -0
- data/app/controllers/goodmin/application_controller.rb +43 -0
- data/app/controllers/goodmin/resource_controller.rb +235 -0
- data/app/helpers/goodmin/application_helper.rb +45 -0
- data/app/javascript/goodmin/application.js +8 -0
- data/app/javascript/goodmin/controllers/batch_actions_controller.js +101 -0
- data/app/javascript/goodmin/controllers/datetimepicker_controller.js +24 -0
- data/app/javascript/goodmin/controllers/navigation_controller.js +30 -0
- data/app/jobs/goodmin/application_job.rb +4 -0
- data/app/mailers/goodmin/application_mailer.rb +6 -0
- data/app/models/goodmin/application_record.rb +5 -0
- data/app/views/goodmin/application/welcome.html.erb +17 -0
- data/app/views/goodmin/fields/association/_form.html.erb +19 -0
- data/app/views/goodmin/fields/association/_index.html.erb +6 -0
- data/app/views/goodmin/fields/association/_show.html.erb +6 -0
- data/app/views/goodmin/fields/boolean/_form.html.erb +7 -0
- data/app/views/goodmin/fields/boolean/_index.html.erb +1 -0
- data/app/views/goodmin/fields/boolean/_show.html.erb +1 -0
- data/app/views/goodmin/fields/date/_form.html.erb +6 -0
- data/app/views/goodmin/fields/date/_index.html.erb +1 -0
- data/app/views/goodmin/fields/date/_show.html.erb +1 -0
- data/app/views/goodmin/fields/date_time/_form.html.erb +6 -0
- data/app/views/goodmin/fields/date_time/_index.html.erb +1 -0
- data/app/views/goodmin/fields/date_time/_show.html.erb +1 -0
- data/app/views/goodmin/fields/enum/_index.html.erb +1 -0
- data/app/views/goodmin/fields/enum/_show.html.erb +1 -0
- data/app/views/goodmin/fields/nested_has_one/_form.html.erb +6 -0
- data/app/views/goodmin/fields/nested_has_one/_index.html.erb +1 -0
- data/app/views/goodmin/fields/nested_has_one/_show.html.erb +1 -0
- data/app/views/goodmin/fields/number/_form.html.erb +5 -0
- data/app/views/goodmin/fields/number/_index.html.erb +1 -0
- data/app/views/goodmin/fields/number/_show.html.erb +1 -0
- data/app/views/goodmin/fields/password/_form.html.erb +5 -0
- data/app/views/goodmin/fields/password/_index.html.erb +1 -0
- data/app/views/goodmin/fields/password/_show.html.erb +1 -0
- data/app/views/goodmin/fields/select/_form.html.erb +5 -0
- data/app/views/goodmin/fields/select/_index.html.erb +1 -0
- data/app/views/goodmin/fields/select/_show.html.erb +1 -0
- data/app/views/goodmin/fields/string/_form.html.erb +5 -0
- data/app/views/goodmin/fields/string/_index.html.erb +1 -0
- data/app/views/goodmin/fields/string/_show.html.erb +1 -0
- data/app/views/goodmin/fields/text/_form.html.erb +5 -0
- data/app/views/goodmin/fields/text/_index.html.erb +1 -0
- data/app/views/goodmin/fields/text/_show.html.erb +1 -0
- data/app/views/goodmin/resource/_actions.html.erb +9 -0
- data/app/views/goodmin/resource/_batch_actions.html.erb +12 -0
- data/app/views/goodmin/resource/_breadcrumb.html.erb +33 -0
- data/app/views/goodmin/resource/_breadcrumb_actions.html.erb +41 -0
- data/app/views/goodmin/resource/_button_actions.html.erb +3 -0
- data/app/views/goodmin/resource/_errors.html.erb +9 -0
- data/app/views/goodmin/resource/_export_actions.html.erb +15 -0
- data/app/views/goodmin/resource/_filters.html.erb +22 -0
- data/app/views/goodmin/resource/_form.html.erb +26 -0
- data/app/views/goodmin/resource/_pagination.html.erb +40 -0
- data/app/views/goodmin/resource/_scopes.html.erb +14 -0
- data/app/views/goodmin/resource/_table.html.erb +45 -0
- data/app/views/goodmin/resource/columns/_actions.html.erb +28 -0
- data/app/views/goodmin/resource/edit.html.erb +5 -0
- data/app/views/goodmin/resource/index.csv.csvbuilder +5 -0
- data/app/views/goodmin/resource/index.html.erb +10 -0
- data/app/views/goodmin/resource/index.json.jbuilder +3 -0
- data/app/views/goodmin/resource/new.html.erb +5 -0
- data/app/views/goodmin/resource/show.html.erb +11 -0
- data/app/views/goodmin/resource/show.json.jbuilder +1 -0
- data/app/views/goodmin/sessions/new.html.erb +11 -0
- data/app/views/goodmin/shared/_navigation.html.erb +0 -0
- data/app/views/goodmin/shared/_navigation_aside.html.erb +7 -0
- data/app/views/layouts/goodmin/_content.html.erb +13 -0
- data/app/views/layouts/goodmin/_layout.html.erb +22 -0
- data/app/views/layouts/goodmin/application.html.erb +28 -0
- data/app/views/layouts/goodmin/login.html.erb +18 -0
- data/config/importmap.rb +5 -0
- data/config/locales/en.yml +49 -0
- data/config/locales/pl-BR.yml +49 -0
- data/config/locales/pt-BR.yml +49 -0
- data/config/locales/sv.yml +49 -0
- data/config/routes.rb +3 -0
- data/lib/generators/goodmin/authentication/authentication_generator.rb +41 -0
- data/lib/generators/goodmin/authentication/templates/sessions_controller.rb +9 -0
- data/lib/generators/goodmin/install/install_generator.rb +41 -0
- data/lib/generators/goodmin/policy/policy_generator.rb +7 -0
- data/lib/generators/goodmin/policy/templates/policy.rb +23 -0
- data/lib/generators/goodmin/resource/resource_generator.rb +31 -0
- data/lib/generators/goodmin/resource/templates/resource.rb +25 -0
- data/lib/generators/goodmin/resource/templates/resource_controller.rb +9 -0
- data/lib/generators/goodmin/resource/templates/resource_model.rb +4 -0
- data/lib/generators/goodmin/resource/templates/resource_service.rb +23 -0
- data/lib/goodmin/authentication/sessions_controller.rb +46 -0
- data/lib/goodmin/authentication/user.rb +27 -0
- data/lib/goodmin/authentication.rb +35 -0
- data/lib/goodmin/authorization/policy.rb +41 -0
- data/lib/goodmin/authorization.rb +69 -0
- data/lib/goodmin/engine.rb +30 -0
- data/lib/goodmin/fields/association.rb +62 -0
- data/lib/goodmin/fields/base.rb +57 -0
- data/lib/goodmin/fields/boolean.rb +6 -0
- data/lib/goodmin/fields/date.rb +6 -0
- data/lib/goodmin/fields/date_time.rb +6 -0
- data/lib/goodmin/fields/enum.rb +15 -0
- data/lib/goodmin/fields/nested_has_one.rb +41 -0
- data/lib/goodmin/fields/number.rb +6 -0
- data/lib/goodmin/fields/password.rb +6 -0
- data/lib/goodmin/fields/select.rb +19 -0
- data/lib/goodmin/fields/string.rb +6 -0
- data/lib/goodmin/fields/text.rb +6 -0
- data/lib/goodmin/generators/base.rb +49 -0
- data/lib/goodmin/generators/named_base.rb +31 -0
- data/lib/goodmin/helpers/application.rb +47 -0
- data/lib/goodmin/helpers/batch_actions.rb +21 -0
- data/lib/goodmin/helpers/filters.rb +123 -0
- data/lib/goodmin/helpers/forms.rb +42 -0
- data/lib/goodmin/helpers/navigation.rb +52 -0
- data/lib/goodmin/helpers/tables.rb +25 -0
- data/lib/goodmin/helpers/translations.rb +19 -0
- data/lib/goodmin/paginator.rb +55 -0
- data/lib/goodmin/resolver.rb +141 -0
- data/lib/goodmin/resources/attribute.rb +46 -0
- data/lib/goodmin/resources/form_builder.rb +96 -0
- data/lib/goodmin/resources/form_component.rb +65 -0
- data/lib/goodmin/resources/form_components/col.rb +33 -0
- data/lib/goodmin/resources/form_components/row.rb +25 -0
- data/lib/goodmin/resources/form_components/section.rb +51 -0
- data/lib/goodmin/resources/form_components/tab.rb +49 -0
- data/lib/goodmin/resources/resource/associations.rb +23 -0
- data/lib/goodmin/resources/resource/batch_actions.rb +56 -0
- data/lib/goodmin/resources/resource/filters.rb +44 -0
- data/lib/goodmin/resources/resource/ordering.rb +41 -0
- data/lib/goodmin/resources/resource/pagination.rb +22 -0
- data/lib/goodmin/resources/resource/scopes.rb +61 -0
- data/lib/goodmin/resources/resource.rb +199 -0
- data/lib/goodmin/resources/resource_controller/batch_actions.rb +49 -0
- data/lib/goodmin/resources/resource_service/associations.rb +23 -0
- data/lib/goodmin/resources/resource_service/batch_actions.rb +52 -0
- data/lib/goodmin/resources/resource_service/filters.rb +44 -0
- data/lib/goodmin/resources/resource_service/ordering.rb +41 -0
- data/lib/goodmin/resources/resource_service/pagination.rb +22 -0
- data/lib/goodmin/resources/resource_service/scopes.rb +61 -0
- data/lib/goodmin/resources/resource_service.rb +199 -0
- data/lib/goodmin/service_locator.rb +25 -0
- data/lib/goodmin/version.rb +3 -0
- data/lib/goodmin.rb +44 -0
- data/lib/tasks/goodmin_tasks.rake +4 -0
- metadata +461 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module Goodmin
|
|
2
|
+
module Resources
|
|
3
|
+
module Resource
|
|
4
|
+
module Ordering
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
def apply_order(order_param, resources)
|
|
8
|
+
if order_param.present? && order_column_method?(order_column(order_param))
|
|
9
|
+
send("order_by_#{order_column(order_param)}", resources, order_direction(order_param))
|
|
10
|
+
elsif order_param.present? && order_column_column?(order_column(order_param))
|
|
11
|
+
resources.order("#{resource_class.table_name}.#{order_column(order_param)} #{order_direction(order_param)}")
|
|
12
|
+
else
|
|
13
|
+
resources
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def orderable_column?(column)
|
|
18
|
+
order_column_method?(column) || order_column_column?(column)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
protected
|
|
22
|
+
|
|
23
|
+
def order_column_method?(column)
|
|
24
|
+
respond_to?("order_by_#{column}")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def order_column_column?(column)
|
|
28
|
+
resource_class.column_names.include?(column)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def order_column(order_param)
|
|
32
|
+
order_param.rpartition("_").first
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def order_direction(order_param)
|
|
36
|
+
order_param.rpartition("_").last == "asc" ? "asc" : "desc"
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Goodmin
|
|
2
|
+
module Resources
|
|
3
|
+
module Resource
|
|
4
|
+
module Pagination
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
def apply_pagination(page_param, resources)
|
|
8
|
+
@paginator = Paginator.new(resources, per_page: per_page, current_page: page_param)
|
|
9
|
+
@paginator.paginate
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def paginator
|
|
13
|
+
@paginator
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def per_page
|
|
17
|
+
25
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
module Goodmin
|
|
2
|
+
module Resources
|
|
3
|
+
module Resource
|
|
4
|
+
module Scopes
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
delegate :scope_map, to: "self.class"
|
|
8
|
+
|
|
9
|
+
def apply_scope(scope_param, resources)
|
|
10
|
+
return resources if scope_map.empty?
|
|
11
|
+
|
|
12
|
+
self.scope = scope_param
|
|
13
|
+
|
|
14
|
+
if scope && scope_map.key?(scope.to_sym)
|
|
15
|
+
send("scope_#{@scope}", resources)
|
|
16
|
+
else
|
|
17
|
+
fail NotImplementedError, "Scope #{@scope} not implemented"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def scope=(scope)
|
|
22
|
+
@scope = scope.blank? ? default_scope : scope
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def scope
|
|
26
|
+
@scope
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def scoped_by?(name)
|
|
30
|
+
@scope == name.to_s
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def scope_count(scope)
|
|
34
|
+
send("scope_#{scope}", resources_relation).count
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
protected
|
|
38
|
+
|
|
39
|
+
def default_scope
|
|
40
|
+
scope = scope_map.find -> { scope_map.first } do |_key, value|
|
|
41
|
+
value[:default] == true
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
scope ? scope[0].to_s : nil
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
module ClassMethods
|
|
48
|
+
def scope_map
|
|
49
|
+
@scope_map ||= {}
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def scope(attr, options = {})
|
|
53
|
+
scope_map[attr] = {
|
|
54
|
+
default: false
|
|
55
|
+
}.merge(options)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
require "goodmin/resources/attribute"
|
|
2
|
+
require "goodmin/resources/form_builder"
|
|
3
|
+
require "goodmin/resources/resource/associations"
|
|
4
|
+
require "goodmin/resources/resource/batch_actions"
|
|
5
|
+
require "goodmin/resources/resource/filters"
|
|
6
|
+
require "goodmin/resources/resource/ordering"
|
|
7
|
+
require "goodmin/resources/resource/pagination"
|
|
8
|
+
require "goodmin/resources/resource/scopes"
|
|
9
|
+
|
|
10
|
+
module Goodmin
|
|
11
|
+
module Resources
|
|
12
|
+
module Resource
|
|
13
|
+
extend ActiveSupport::Concern
|
|
14
|
+
|
|
15
|
+
class AttributeBuilder
|
|
16
|
+
attr_reader :attributes
|
|
17
|
+
|
|
18
|
+
def initialize
|
|
19
|
+
@attributes = []
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def attribute(name, field: nil, **options)
|
|
23
|
+
@attributes << Attribute.new(name, field_class: field, **options)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
include Associations
|
|
28
|
+
include BatchActions
|
|
29
|
+
include Filters
|
|
30
|
+
include Ordering
|
|
31
|
+
include Pagination
|
|
32
|
+
include Scopes
|
|
33
|
+
|
|
34
|
+
attr_reader :options
|
|
35
|
+
|
|
36
|
+
def initialize(options = {})
|
|
37
|
+
@options = options
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def resource_class
|
|
41
|
+
self.class.name.delete_prefix("Goodmin::Resources::").chomp("Resource").constantize
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def resources_relation
|
|
45
|
+
if options[:resource_parent].present?
|
|
46
|
+
parent = options[:resource_parent]
|
|
47
|
+
association_name = resource_class.name.underscore.pluralize.to_sym
|
|
48
|
+
reflection = parent.class.reflect_on_association(association_name)
|
|
49
|
+
|
|
50
|
+
if reflection && (reflection.macro == :has_and_belongs_to_many ||
|
|
51
|
+
(reflection.macro == :has_many && reflection.options[:through].present?))
|
|
52
|
+
parent.send(association_name)
|
|
53
|
+
else
|
|
54
|
+
resource_class.where(parent.class.name.underscore => parent)
|
|
55
|
+
end
|
|
56
|
+
else
|
|
57
|
+
resource_class.all
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def resources(params)
|
|
62
|
+
apply_pagination(
|
|
63
|
+
params[:page], apply_order(
|
|
64
|
+
params[:order], apply_filters(
|
|
65
|
+
params[:filter], apply_scope(
|
|
66
|
+
params[:scope], resources_relation
|
|
67
|
+
)
|
|
68
|
+
)
|
|
69
|
+
)
|
|
70
|
+
)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def find_resource(id)
|
|
74
|
+
resources_relation.find(id)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def build_resource(params)
|
|
78
|
+
resources_relation.new(params)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def create_resource(resource)
|
|
82
|
+
resource.save
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def update_resource(resource, params)
|
|
86
|
+
resource.update(params)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def destroy_resource(resource)
|
|
90
|
+
resource.destroy
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def attrs_for_index
|
|
94
|
+
self.class.attrs_for_index
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def attrs_for_show
|
|
98
|
+
self.class.attrs_for_show
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def attrs_for_form
|
|
102
|
+
self.class.attrs_for_form
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def form_nodes
|
|
106
|
+
self.class.form_nodes
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def form_tabs
|
|
110
|
+
self.class.form_tabs
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def attrs_for_export
|
|
114
|
+
self.class.attrs_for_export
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def display_name(record)
|
|
118
|
+
record.to_s
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def option_text_for_association(attribute)
|
|
122
|
+
self.class.association_option_texts[attribute] || :to_s
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
module ClassMethods
|
|
126
|
+
def index(&block)
|
|
127
|
+
if block_given?
|
|
128
|
+
builder = AttributeBuilder.new
|
|
129
|
+
builder.instance_eval(&block)
|
|
130
|
+
@attrs_for_index = builder.attributes
|
|
131
|
+
end
|
|
132
|
+
@attrs_for_index || []
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def show(&block)
|
|
136
|
+
if block_given?
|
|
137
|
+
builder = AttributeBuilder.new
|
|
138
|
+
builder.instance_eval(&block)
|
|
139
|
+
@attrs_for_show = builder.attributes
|
|
140
|
+
end
|
|
141
|
+
@attrs_for_show || []
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def form(&block)
|
|
145
|
+
if block_given?
|
|
146
|
+
builder = FormBuilder.new
|
|
147
|
+
builder.instance_eval(&block)
|
|
148
|
+
@form_nodes = builder.nodes
|
|
149
|
+
@attrs_for_form = builder.attributes
|
|
150
|
+
@form_tabs = builder.tabs
|
|
151
|
+
end
|
|
152
|
+
@attrs_for_form || []
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def export(&block)
|
|
156
|
+
if block_given?
|
|
157
|
+
builder = AttributeBuilder.new
|
|
158
|
+
builder.instance_eval(&block)
|
|
159
|
+
@attrs_for_export = builder.attributes
|
|
160
|
+
end
|
|
161
|
+
@attrs_for_export || []
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def attrs_for_index
|
|
165
|
+
@attrs_for_index || []
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def attrs_for_show
|
|
169
|
+
@attrs_for_show || []
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def attrs_for_form
|
|
173
|
+
@attrs_for_form || []
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def form_nodes
|
|
177
|
+
@form_nodes || attrs_for_form.map { |attr| AttributeNode.new(attr) }
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def form_tabs
|
|
181
|
+
@form_tabs || []
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def attrs_for_export
|
|
185
|
+
@attrs_for_export || []
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def association_option_text(attribute, method_name)
|
|
189
|
+
@association_option_texts ||= {}
|
|
190
|
+
@association_option_texts[attribute] = method_name
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def association_option_texts
|
|
194
|
+
@association_option_texts || {}
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module Goodmin
|
|
2
|
+
module Resources
|
|
3
|
+
module ResourceController
|
|
4
|
+
module BatchActions
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
prepend_before_action :perform_batch_action, only: :update
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
protected
|
|
12
|
+
|
|
13
|
+
def perform_batch_action
|
|
14
|
+
return unless params[:batch_action].present?
|
|
15
|
+
|
|
16
|
+
set_resource_service
|
|
17
|
+
set_resource_class
|
|
18
|
+
|
|
19
|
+
if authorization_enabled?
|
|
20
|
+
authorize(batch_action_records, "batch_action_#{params[:batch_action]}?")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
if @resource_service.batch_action(params[:batch_action], batch_action_records)
|
|
24
|
+
flash[:notice] = translate_scoped(
|
|
25
|
+
"flash.batch_action", number_of_records: batch_action_ids.length,
|
|
26
|
+
resource: @resource_class.model_name.human(count: batch_action_ids.length)
|
|
27
|
+
)
|
|
28
|
+
flash[:updated_ids] = batch_action_ids
|
|
29
|
+
|
|
30
|
+
if respond_to?("redirect_after_batch_action_#{params[:batch_action]}", true)
|
|
31
|
+
redirect_to send("redirect_after_batch_action_#{params[:batch_action]}")
|
|
32
|
+
return
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
redirect_back(fallback_location: root_path)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def batch_action_ids
|
|
40
|
+
@_batch_action_ids ||= params[:id].split(",").map(&:to_i)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def batch_action_records
|
|
44
|
+
@_batch_action_records ||= @resource_class.where(id: batch_action_ids)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Goodmin
|
|
2
|
+
module Resources
|
|
3
|
+
module ResourceService
|
|
4
|
+
module Associations
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
delegate :has_many_map, to: "self.class"
|
|
8
|
+
|
|
9
|
+
module ClassMethods
|
|
10
|
+
def has_many_map
|
|
11
|
+
@has_many_map ||= {}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def has_many(attr, options = {})
|
|
15
|
+
has_many_map[attr] = {
|
|
16
|
+
class_name: attr.to_s.singularize.classify
|
|
17
|
+
}.merge(options)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module Goodmin
|
|
2
|
+
module Resources
|
|
3
|
+
module ResourceService
|
|
4
|
+
module BatchActions
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
delegate :batch_action_map, to: "self.class"
|
|
8
|
+
|
|
9
|
+
def batch_action(action, records)
|
|
10
|
+
if batch_action?(action)
|
|
11
|
+
send("batch_action_#{action}", records)
|
|
12
|
+
true
|
|
13
|
+
else
|
|
14
|
+
false
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def batch_action?(action)
|
|
19
|
+
batch_action_map.key?(action.to_sym)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def include_batch_action?(action)
|
|
23
|
+
options = batch_action_map[action.to_sym]
|
|
24
|
+
|
|
25
|
+
(options[:only].nil? && options[:except].nil?) ||
|
|
26
|
+
(options[:only] && options[:only].include?(scope.to_sym)) ||
|
|
27
|
+
(options[:except] && !options[:except].include?(scope.to_sym))
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def include_batch_actions?
|
|
31
|
+
batch_action_map.keys.any? do |action|
|
|
32
|
+
include_batch_action?(action)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
module ClassMethods
|
|
37
|
+
def batch_action_map
|
|
38
|
+
@batch_action_map ||= {}
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def batch_action(attr, options = {})
|
|
42
|
+
batch_action_map[attr] = {
|
|
43
|
+
only: nil,
|
|
44
|
+
except: nil,
|
|
45
|
+
confirm: false
|
|
46
|
+
}.merge(options)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Goodmin
|
|
2
|
+
module Resources
|
|
3
|
+
module ResourceService
|
|
4
|
+
module Filters
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
delegate :filter_map, to: "self.class"
|
|
8
|
+
|
|
9
|
+
def apply_filters(filter_params, resources)
|
|
10
|
+
if filter_params.present?
|
|
11
|
+
filter_params.each do |name, value|
|
|
12
|
+
if apply_filter?(name, value)
|
|
13
|
+
resources = send("filter_#{name}", resources, value)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
resources
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def apply_filter?(name, value)
|
|
23
|
+
return false if value == [""]
|
|
24
|
+
filter_map.key?(name.to_sym) && value.present?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
module ClassMethods
|
|
28
|
+
def filter_map
|
|
29
|
+
@filter_map ||= {}
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def filter(attr, options = {})
|
|
33
|
+
filter_map[attr] = {
|
|
34
|
+
as: :string,
|
|
35
|
+
option_text: "to_s",
|
|
36
|
+
option_value: "id",
|
|
37
|
+
collection: nil
|
|
38
|
+
}.merge(options)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module Goodmin
|
|
2
|
+
module Resources
|
|
3
|
+
module ResourceService
|
|
4
|
+
module Ordering
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
def apply_order(order_param, resources)
|
|
8
|
+
if order_param.present? && order_column_method?(order_column(order_param))
|
|
9
|
+
send("order_by_#{order_column(order_param)}", resources, order_direction(order_param))
|
|
10
|
+
elsif order_param.present? && order_column_column?(order_column(order_param))
|
|
11
|
+
resources.order("#{resource_class.table_name}.#{order_column(order_param)} #{order_direction(order_param)}")
|
|
12
|
+
else
|
|
13
|
+
resources
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def orderable_column?(column)
|
|
18
|
+
order_column_method?(column) || order_column_column?(column)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
protected
|
|
22
|
+
|
|
23
|
+
def order_column_method?(column)
|
|
24
|
+
respond_to?("order_by_#{column}")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def order_column_column?(column)
|
|
28
|
+
resource_class.column_names.include?(column)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def order_column(order_param)
|
|
32
|
+
order_param.rpartition("_").first
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def order_direction(order_param)
|
|
36
|
+
order_param.rpartition("_").last == "asc" ? "asc" : "desc"
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Goodmin
|
|
2
|
+
module Resources
|
|
3
|
+
module ResourceService
|
|
4
|
+
module Pagination
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
def apply_pagination(page_param, resources)
|
|
8
|
+
@paginator = Paginator.new(resources, per_page: per_page, current_page: page_param)
|
|
9
|
+
@paginator.paginate
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def paginator
|
|
13
|
+
@paginator
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def per_page
|
|
17
|
+
25
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
module Goodmin
|
|
2
|
+
module Resources
|
|
3
|
+
module ResourceService
|
|
4
|
+
module Scopes
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
delegate :scope_map, to: "self.class"
|
|
8
|
+
|
|
9
|
+
def apply_scope(scope_param, resources)
|
|
10
|
+
return resources if scope_map.empty?
|
|
11
|
+
|
|
12
|
+
self.scope = scope_param
|
|
13
|
+
|
|
14
|
+
if scope && scope_map.key?(scope.to_sym)
|
|
15
|
+
send("scope_#{@scope}", resources)
|
|
16
|
+
else
|
|
17
|
+
fail NotImplementedError, "Scope #{@scope} not implemented"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def scope=(scope)
|
|
22
|
+
@scope = scope.blank? ? default_scope : scope
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def scope
|
|
26
|
+
@scope
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def scoped_by?(name)
|
|
30
|
+
@scope == name.to_s
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def scope_count(scope)
|
|
34
|
+
send("scope_#{scope}", resources_relation).count
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
protected
|
|
38
|
+
|
|
39
|
+
def default_scope
|
|
40
|
+
scope = scope_map.find -> { scope_map.first } do |_key, value|
|
|
41
|
+
value[:default] == true
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
scope ? scope[0].to_s : nil
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
module ClassMethods
|
|
48
|
+
def scope_map
|
|
49
|
+
@scope_map ||= {}
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def scope(attr, options = {})
|
|
53
|
+
scope_map[attr] = {
|
|
54
|
+
default: false
|
|
55
|
+
}.merge(options)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|