godmin 0.9.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/.gitignore +24 -0
- data/.hound.yml +2 -0
- data/.rubocop.yml +7 -0
- data/.travis.yml +7 -0
- data/Gemfile +11 -0
- data/MIT-LICENSE +20 -0
- data/README.md +523 -0
- data/Rakefile +34 -0
- data/app/assets/images/godmin/.keep +0 -0
- data/app/assets/javascripts/godmin/application.js +19 -0
- data/app/assets/javascripts/godmin/batch_actions.js +42 -0
- data/app/assets/javascripts/godmin/navigation.js +9 -0
- data/app/assets/javascripts/godmin/select_tags.js +8 -0
- data/app/assets/stylesheets/godmin/application.css.scss +62 -0
- data/app/views/godmin/application/welcome.html.erb +65 -0
- data/app/views/godmin/resource/_actions.html.erb +10 -0
- data/app/views/godmin/resource/_batch_actions.html.erb +12 -0
- data/app/views/godmin/resource/_breadcrumb.html.erb +21 -0
- data/app/views/godmin/resource/_errors.html.erb +9 -0
- data/app/views/godmin/resource/_filters.html.erb +23 -0
- data/app/views/godmin/resource/_form.html.erb +12 -0
- data/app/views/godmin/resource/_pagination.html.erb +6 -0
- data/app/views/godmin/resource/_scopes.html.erb +11 -0
- data/app/views/godmin/resource/_table.html.erb +36 -0
- data/app/views/godmin/resource/columns/_actions.html.erb +11 -0
- data/app/views/godmin/resource/edit.html.erb +5 -0
- data/app/views/godmin/resource/index.html.erb +17 -0
- data/app/views/godmin/resource/new.html.erb +5 -0
- data/app/views/godmin/resource/show.html.erb +1 -0
- data/app/views/godmin/sessions/new.html.erb +9 -0
- data/app/views/godmin/shared/_navigation.html.erb +29 -0
- data/app/views/kaminari/_first_page.html.erb +3 -0
- data/app/views/kaminari/_gap.html.erb +3 -0
- data/app/views/kaminari/_last_page.html.erb +3 -0
- data/app/views/kaminari/_next_page.html.erb +3 -0
- data/app/views/kaminari/_page.html.erb +3 -0
- data/app/views/kaminari/_paginator.html.erb +15 -0
- data/app/views/kaminari/_prev_page.html.erb +3 -0
- data/app/views/layouts/godmin/_content.html.erb +13 -0
- data/app/views/layouts/godmin/_layout.html.erb +13 -0
- data/app/views/layouts/godmin/application.html.erb +17 -0
- data/app/views/layouts/godmin/login.html.erb +18 -0
- data/bin/rails +8 -0
- data/config/locales/en.yml +41 -0
- data/config/locales/sv.yml +41 -0
- data/config/routes.rb +2 -0
- data/godmin.gemspec +32 -0
- data/lib/generators/godmin/authentication/authentication_generator.rb +61 -0
- data/lib/generators/godmin/install/install_generator.rb +34 -0
- data/lib/generators/godmin/policy/policy_generator.rb +29 -0
- data/lib/generators/godmin/resource/resource_generator.rb +56 -0
- data/lib/godmin.rb +24 -0
- data/lib/godmin/application.rb +37 -0
- data/lib/godmin/authentication.rb +35 -0
- data/lib/godmin/authentication/sessions.rb +45 -0
- data/lib/godmin/authentication/user.rb +27 -0
- data/lib/godmin/authorization.rb +30 -0
- data/lib/godmin/authorization/policy.rb +40 -0
- data/lib/godmin/authorization/policy_finder.rb +28 -0
- data/lib/godmin/engine.rb +4 -0
- data/lib/godmin/generators/base.rb +13 -0
- data/lib/godmin/helpers/application.rb +6 -0
- data/lib/godmin/helpers/batch_actions.rb +17 -0
- data/lib/godmin/helpers/filters.rb +108 -0
- data/lib/godmin/helpers/tables.rb +41 -0
- data/lib/godmin/helpers/translations.rb +19 -0
- data/lib/godmin/rails.rb +36 -0
- data/lib/godmin/resolver.rb +46 -0
- data/lib/godmin/resource.rb +126 -0
- data/lib/godmin/resource/batch_actions.rb +45 -0
- data/lib/godmin/resource/filters.rb +41 -0
- data/lib/godmin/resource/ordering.rb +25 -0
- data/lib/godmin/resource/pagination.rb +11 -0
- data/lib/godmin/resource/scopes.rb +49 -0
- data/lib/godmin/version.rb +3 -0
- data/lib/tasks/godmin_tasks.rake +4 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/mailers/.keep +0 -0
- data/test/dummy/app/models/.keep +0 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +23 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +29 -0
- data/test/dummy/config/environments/production.rb +80 -0
- data/test/dummy/config/environments/test.rb +36 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +12 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +4 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/public/404.html +58 -0
- data/test/dummy/public/422.html +58 -0
- data/test/dummy/public/500.html +57 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/godmin_test.rb +7 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/lib/godmin/policy_finder_test.rb +30 -0
- data/test/lib/godmin/resolver_test.rb +31 -0
- data/test/test_helper.rb +21 -0
- data/vendor/assets/images/godmin/chosen-sprite.png +0 -0
- data/vendor/assets/images/godmin/chosen-sprite@2x.png +0 -0
- data/vendor/assets/javascripts/.keep +0 -0
- data/vendor/assets/stylesheets/.keep +0 -0
- metadata +361 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Godmin
|
|
2
|
+
module Helpers
|
|
3
|
+
module Translations
|
|
4
|
+
def translate_scoped(translate, scope: nil, default: nil, **options)
|
|
5
|
+
if @resource_class
|
|
6
|
+
scope ||= @resource_class.to_s.underscore
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
defaults = [
|
|
10
|
+
["godmin", scope, translate].compact.join(".").to_sym,
|
|
11
|
+
["godmin", translate].compact.join(".").to_sym,
|
|
12
|
+
default
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
t(defaults.shift, default: defaults, **options)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
data/lib/godmin/rails.rb
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module ActionDispatch::Routing
|
|
2
|
+
class Mapper
|
|
3
|
+
def godmin
|
|
4
|
+
override_resources do
|
|
5
|
+
yield
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
unless has_named_route?(:root)
|
|
9
|
+
root to: "application#welcome"
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def override_resources
|
|
16
|
+
def resources(*resources)
|
|
17
|
+
unless Godmin.resources.include?(resources.first)
|
|
18
|
+
Godmin.resources << resources.first
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
super(*resources) do
|
|
22
|
+
if block_given?
|
|
23
|
+
yield
|
|
24
|
+
end
|
|
25
|
+
post "batch_action", on: :collection
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
yield
|
|
30
|
+
|
|
31
|
+
def resources(*resources, &block)
|
|
32
|
+
super(*resources, &block)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
module Godmin
|
|
2
|
+
class Resolver < ::ActionView::FileSystemResolver
|
|
3
|
+
attr_accessor :namespace, :controller_name
|
|
4
|
+
|
|
5
|
+
def find_templates(name, prefix, partial, details)
|
|
6
|
+
template = []
|
|
7
|
+
|
|
8
|
+
template_paths(prefix, partial).each do |path|
|
|
9
|
+
template = super(name, path, partial, details)
|
|
10
|
+
|
|
11
|
+
if template.present?
|
|
12
|
+
break
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
template
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def template_paths(prefix, _partial)
|
|
20
|
+
[
|
|
21
|
+
[namespace, controller_name, prefix],
|
|
22
|
+
[namespace, controller_name],
|
|
23
|
+
[namespace, prefix],
|
|
24
|
+
[namespace, "resource", prefix],
|
|
25
|
+
[namespace, "resource"],
|
|
26
|
+
[namespace]
|
|
27
|
+
].map { |path| path.compact.join("/") }.compact
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class EngineResolver < Resolver
|
|
32
|
+
def initialize(controller_name)
|
|
33
|
+
super [Godmin.namespace, "app/views"].compact.join("/")
|
|
34
|
+
self.namespace = Godmin.namespace
|
|
35
|
+
self.controller_name = controller_name
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class GodminResolver < Resolver
|
|
40
|
+
def initialize(controller_name)
|
|
41
|
+
super [Godmin::Engine.root, "app/views"].compact.join("/")
|
|
42
|
+
self.namespace = "godmin"
|
|
43
|
+
self.controller_name = controller_name
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
require "godmin/helpers/batch_actions"
|
|
2
|
+
require "godmin/helpers/filters"
|
|
3
|
+
require "godmin/helpers/tables"
|
|
4
|
+
require "godmin/resource/batch_actions"
|
|
5
|
+
require "godmin/resource/filters"
|
|
6
|
+
require "godmin/resource/ordering"
|
|
7
|
+
require "godmin/resource/pagination"
|
|
8
|
+
require "godmin/resource/scopes"
|
|
9
|
+
|
|
10
|
+
module Godmin
|
|
11
|
+
module Resource
|
|
12
|
+
extend ActiveSupport::Concern
|
|
13
|
+
|
|
14
|
+
included do
|
|
15
|
+
helper Godmin::Helpers::BatchActions
|
|
16
|
+
helper Godmin::Helpers::Filters
|
|
17
|
+
helper Godmin::Helpers::Tables
|
|
18
|
+
|
|
19
|
+
include Godmin::Resource::BatchActions
|
|
20
|
+
include Godmin::Resource::Filters
|
|
21
|
+
include Godmin::Resource::Scopes
|
|
22
|
+
include Godmin::Resource::Ordering
|
|
23
|
+
include Godmin::Resource::Pagination
|
|
24
|
+
|
|
25
|
+
respond_to :html, :json
|
|
26
|
+
|
|
27
|
+
before_action :set_resource_class
|
|
28
|
+
before_action :set_resources, only: :index
|
|
29
|
+
before_action :set_resource, only: [:show, :new, :edit, :update, :destroy]
|
|
30
|
+
|
|
31
|
+
helper_method :attrs_for_index
|
|
32
|
+
helper_method :attrs_for_form
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def resource_class
|
|
36
|
+
controller_name.classify.constantize
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def resources_relation
|
|
40
|
+
resource_class.all
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def resources
|
|
44
|
+
apply_pagination(
|
|
45
|
+
apply_order(
|
|
46
|
+
apply_filters(
|
|
47
|
+
apply_scope(
|
|
48
|
+
resources_relation
|
|
49
|
+
)
|
|
50
|
+
)
|
|
51
|
+
)
|
|
52
|
+
)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def resource
|
|
56
|
+
if params[:id]
|
|
57
|
+
resources_relation.find(params[:id])
|
|
58
|
+
else
|
|
59
|
+
resources_relation.new
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def index
|
|
64
|
+
respond_with(@resources)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def show
|
|
68
|
+
respond_with(@resource)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def new
|
|
72
|
+
respond_with(@resource)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def edit
|
|
76
|
+
respond_with(@resource)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def create
|
|
80
|
+
@resource = resource_class.create(resource_params)
|
|
81
|
+
respond_with(@resource)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def update
|
|
85
|
+
@resource.update(resource_params)
|
|
86
|
+
respond_with(@resource)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def destroy
|
|
90
|
+
@resource.destroy
|
|
91
|
+
respond_with(@resource)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Gives the view access to the list of column names
|
|
95
|
+
# to be printed in the index view
|
|
96
|
+
def attrs_for_index
|
|
97
|
+
[]
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Gives the view access to the list of attributes
|
|
101
|
+
# to be included in the default form
|
|
102
|
+
def attrs_for_form
|
|
103
|
+
[]
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
protected
|
|
107
|
+
|
|
108
|
+
def set_resource_class
|
|
109
|
+
@resource_class ||= resource_class
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def set_resources
|
|
113
|
+
@resources ||= resources
|
|
114
|
+
authorize(@resources) if authorization_enabled?
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def set_resource
|
|
118
|
+
@resource ||= resource
|
|
119
|
+
authorize(@resource) if authorization_enabled?
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def resource_params
|
|
123
|
+
params.require(resource_class.name.downcase.to_sym).permit(attrs_for_form)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module Godmin
|
|
2
|
+
module Resource
|
|
3
|
+
module BatchActions
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
included do
|
|
7
|
+
helper_method :batch_action_map
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def batch_action_map
|
|
11
|
+
self.class.batch_action_map
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def batch_action
|
|
15
|
+
action = params[:batch_action][:action]
|
|
16
|
+
item_ids = params[:batch_action][:items].keys.map(&:to_i)
|
|
17
|
+
|
|
18
|
+
if batch_action_map.key?(action.to_sym)
|
|
19
|
+
# Store the batched item ids so they can be highlighted later
|
|
20
|
+
flash[:batch_actioned_ids] = item_ids
|
|
21
|
+
|
|
22
|
+
# If the batch action returns false, it is because it has implemented
|
|
23
|
+
# its own redirect. Therefore we return wihout redirecting.
|
|
24
|
+
return unless send("batch_action_#{action}", resource_class.find(item_ids))
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
redirect_to :back
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
module ClassMethods
|
|
31
|
+
def batch_action_map
|
|
32
|
+
@batch_action_map ||= {}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def batch_action(attr, options = {})
|
|
36
|
+
batch_action_map[attr] = {
|
|
37
|
+
only: nil,
|
|
38
|
+
except: nil,
|
|
39
|
+
confirm: false
|
|
40
|
+
}.merge(options)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module Godmin
|
|
2
|
+
module Resource
|
|
3
|
+
module Filters
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
included do
|
|
7
|
+
helper_method :filter_map
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def filter_map
|
|
11
|
+
self.class.filter_map
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def apply_filters(resources)
|
|
15
|
+
if params[:filter].present?
|
|
16
|
+
params[:filter].each do |name, value|
|
|
17
|
+
if filter_map.key?(name.to_sym) && value.present?
|
|
18
|
+
resources = send("filter_#{name}", resources, value)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
resources
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
module ClassMethods
|
|
26
|
+
def filter_map
|
|
27
|
+
@filter_map ||= {}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def filter(attr, options = {})
|
|
31
|
+
filter_map[attr] = {
|
|
32
|
+
as: :string,
|
|
33
|
+
option_text: "to_s",
|
|
34
|
+
option_value: "id",
|
|
35
|
+
collection: nil
|
|
36
|
+
}.merge(options)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Godmin
|
|
2
|
+
module Resource
|
|
3
|
+
module Ordering
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
def apply_order(resources)
|
|
7
|
+
if params[:order].present?
|
|
8
|
+
resources.order("#{resource_class.table_name}.#{order_column} #{order_direction}")
|
|
9
|
+
else
|
|
10
|
+
resources
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
protected
|
|
15
|
+
|
|
16
|
+
def order_column
|
|
17
|
+
params[:order].rpartition("_").first
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def order_direction
|
|
21
|
+
params[:order].rpartition("_").last
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module Godmin
|
|
2
|
+
module Resource
|
|
3
|
+
module Scopes
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
included do
|
|
7
|
+
helper_method :scope_map
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def scope_map
|
|
11
|
+
self.class.scope_map
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def apply_scope(resources)
|
|
15
|
+
if params[:scope].blank?
|
|
16
|
+
params[:scope] = default_scope
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
if params[:scope] && scope_map.key?(params[:scope].to_sym)
|
|
20
|
+
send("scope_#{params[:scope]}", resources)
|
|
21
|
+
else
|
|
22
|
+
resources
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
protected
|
|
27
|
+
|
|
28
|
+
def default_scope
|
|
29
|
+
scope = scope_map.find -> { scope_map.first } do |_key, value|
|
|
30
|
+
value[:default] == true
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
scope ? scope[0].to_s : nil
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
module ClassMethods
|
|
37
|
+
def scope_map
|
|
38
|
+
@scope_map ||= {}
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def scope(attr, options = {})
|
|
42
|
+
scope_map[attr] = {
|
|
43
|
+
default: false
|
|
44
|
+
}.merge(options)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
== README
|
|
2
|
+
|
|
3
|
+
This README would normally document whatever steps are necessary to get the
|
|
4
|
+
application up and running.
|
|
5
|
+
|
|
6
|
+
Things you may want to cover:
|
|
7
|
+
|
|
8
|
+
* Ruby version
|
|
9
|
+
|
|
10
|
+
* System dependencies
|
|
11
|
+
|
|
12
|
+
* Configuration
|
|
13
|
+
|
|
14
|
+
* Database creation
|
|
15
|
+
|
|
16
|
+
* Database initialization
|
|
17
|
+
|
|
18
|
+
* How to run the test suite
|
|
19
|
+
|
|
20
|
+
* Services (job queues, cache servers, search engines, etc.)
|
|
21
|
+
|
|
22
|
+
* Deployment instructions
|
|
23
|
+
|
|
24
|
+
* ...
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
Please feel free to use a different markup language if you do not plan to run
|
|
28
|
+
<tt>rake doc:app</tt>.
|