madmin 0.1.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/MIT-LICENSE +20 -0
- data/README.md +102 -0
- data/Rakefile +32 -0
- data/app/assets/config/madmin_manifest.js +2 -0
- data/app/assets/javascripts/madmin/application.js +15 -0
- data/app/assets/javascripts/madmin/dashboard.js +2 -0
- data/app/assets/javascripts/madmin/resources.js +36 -0
- data/app/assets/stylesheets/madmin/application.css +22 -0
- data/app/assets/stylesheets/madmin/dashboard.css +4 -0
- data/app/assets/stylesheets/madmin/resources.css +4 -0
- data/app/controllers/madmin/application_controller.rb +16 -0
- data/app/controllers/madmin/base_controller.rb +16 -0
- data/app/controllers/madmin/dashboard_controller.rb +8 -0
- data/app/controllers/madmin/resources_controller.rb +97 -0
- data/app/decorators/madmin/resource_decorator.rb +16 -0
- data/app/helpers/madmin/application_helper.rb +15 -0
- data/app/helpers/madmin/fields/polymorphic_helper.rb +25 -0
- data/app/jobs/madmin/application_job.rb +4 -0
- data/app/mailers/madmin/application_mailer.rb +6 -0
- data/app/models/madmin/application_record.rb +5 -0
- data/app/views/application/_navigation.html.erb +17 -0
- data/app/views/layouts/madmin/application.html.erb +30 -0
- data/app/views/madmin/dashboard/index.html.erb +6 -0
- data/app/views/madmin/fields/belongs_to/_form.html.erb +14 -0
- data/app/views/madmin/fields/belongs_to/_index.html.erb +7 -0
- data/app/views/madmin/fields/belongs_to/_show.html.erb +8 -0
- data/app/views/madmin/fields/check_box/_form.html.erb +4 -0
- data/app/views/madmin/fields/check_box/_index.html.erb +1 -0
- data/app/views/madmin/fields/check_box/_show.html.erb +8 -0
- data/app/views/madmin/fields/email/_form.html.erb +4 -0
- data/app/views/madmin/fields/email/_index.html.erb +1 -0
- data/app/views/madmin/fields/email/_show.html.erb +8 -0
- data/app/views/madmin/fields/has_many/_form.html.erb +0 -0
- data/app/views/madmin/fields/has_many/_show.html.erb +15 -0
- data/app/views/madmin/fields/has_one/_form.html.erb +0 -0
- data/app/views/madmin/fields/has_one/_show.html.erb +12 -0
- data/app/views/madmin/fields/number/_form.html.erb +4 -0
- data/app/views/madmin/fields/number/_index.html.erb +1 -0
- data/app/views/madmin/fields/number/_show.html.erb +8 -0
- data/app/views/madmin/fields/password/_form.html.erb +4 -0
- data/app/views/madmin/fields/password/_index.html.erb +1 -0
- data/app/views/madmin/fields/password/_show.html.erb +8 -0
- data/app/views/madmin/fields/polymorphic/_form.html.erb +32 -0
- data/app/views/madmin/fields/polymorphic/_index.html.erb +1 -0
- data/app/views/madmin/fields/polymorphic/_show.html.erb +14 -0
- data/app/views/madmin/fields/select/_form.html.erb +4 -0
- data/app/views/madmin/fields/select/_index.html.erb +1 -0
- data/app/views/madmin/fields/select/_show.html.erb +8 -0
- data/app/views/madmin/fields/text/_form.html.erb +4 -0
- data/app/views/madmin/fields/text/_index.html.erb +1 -0
- data/app/views/madmin/fields/text/_show.html.erb +8 -0
- data/app/views/madmin/fields/text_area/_form.html.erb +4 -0
- data/app/views/madmin/fields/text_area/_index.html.erb +1 -0
- data/app/views/madmin/fields/text_area/_show.html.erb +8 -0
- data/app/views/madmin/resources/_form.html.erb +15 -0
- data/app/views/madmin/resources/_scopes.html.erb +10 -0
- data/app/views/madmin/resources/edit.html.erb +2 -0
- data/app/views/madmin/resources/index.html.erb +13 -0
- data/app/views/madmin/resources/index/_content.html.erb +33 -0
- data/app/views/madmin/resources/new.html.erb +2 -0
- data/app/views/madmin/resources/show.html.erb +10 -0
- data/config/routes.rb +11 -0
- data/lib/generators/madmin/controller/USAGE +8 -0
- data/lib/generators/madmin/controller/controller_generator.rb +10 -0
- data/lib/generators/madmin/install/install_generator.rb +31 -0
- data/lib/generators/madmin/page/USAGE +8 -0
- data/lib/generators/madmin/page/page_generator.rb +20 -0
- data/lib/generators/madmin/page/templates/template.html.erb +2 -0
- data/lib/generators/madmin/page/templates/template.rb.erb +10 -0
- data/lib/generators/madmin/resource/resource_generator.rb +76 -0
- data/lib/generators/madmin/resource/templates/resource.rb.erb +11 -0
- data/lib/generators/madmin/views/views_generator.rb +15 -0
- data/lib/madmin.rb +30 -0
- data/lib/madmin/engine.rb +9 -0
- data/lib/madmin/field.rb +64 -0
- data/lib/madmin/field/associatable.rb +58 -0
- data/lib/madmin/field/belongs_to.rb +9 -0
- data/lib/madmin/field/check_box.rb +8 -0
- data/lib/madmin/field/date_time.rb +8 -0
- data/lib/madmin/field/email.rb +8 -0
- data/lib/madmin/field/has_many.rb +9 -0
- data/lib/madmin/field/has_one.rb +9 -0
- data/lib/madmin/field/number.rb +8 -0
- data/lib/madmin/field/password.rb +8 -0
- data/lib/madmin/field/polymorphic.rb +57 -0
- data/lib/madmin/field/select.rb +13 -0
- data/lib/madmin/field/text.rb +8 -0
- data/lib/madmin/field/text_area.rb +8 -0
- data/lib/madmin/generator_helpers.rb +13 -0
- data/lib/madmin/resourceable.rb +72 -0
- data/lib/madmin/resourceable/class_methods.rb +152 -0
- data/lib/madmin/resources.rb +13 -0
- data/lib/madmin/version.rb +3 -0
- data/lib/tasks/madmin_tasks.rake +4 -0
- metadata +197 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
class Madmin::ControllerGenerator < Rails::Generators::NamedBase
|
|
2
|
+
source_root File.expand_path("../../../../../", __FILE__)
|
|
3
|
+
|
|
4
|
+
def copy_controller
|
|
5
|
+
copy_file(
|
|
6
|
+
"app/controllers/madmin/#{file_name}_controller.rb",
|
|
7
|
+
"app/controllers/madmin/#{file_name}_controller.rb"
|
|
8
|
+
)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require "rails/generators/base"
|
|
2
|
+
require "madmin/generator_helpers"
|
|
3
|
+
|
|
4
|
+
module Madmin
|
|
5
|
+
module Generators
|
|
6
|
+
class InstallGenerator < Rails::Generators::Base
|
|
7
|
+
include Madmin::GeneratorHelpers
|
|
8
|
+
|
|
9
|
+
def generate_resources
|
|
10
|
+
resources.each do |model|
|
|
11
|
+
call_generator "madmin:resource", model.to_s
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def install_route
|
|
16
|
+
inject_into_file(
|
|
17
|
+
Rails.root.join("config/routes.rb"),
|
|
18
|
+
after: "Rails.application.routes.draw do\n"
|
|
19
|
+
) { " namespace :madmin do\n end\n mount Madmin::Engine => \"/madmin\"\n" }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def resources
|
|
25
|
+
Rails.application.eager_load! unless Rails.application.config.cache_classes
|
|
26
|
+
|
|
27
|
+
ActiveRecord::Base.descendants.reject(&:abstract_class?)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
class Madmin::PageGenerator < Rails::Generators::NamedBase
|
|
2
|
+
source_root File.expand_path("templates", __dir__)
|
|
3
|
+
|
|
4
|
+
def copy_template
|
|
5
|
+
template(
|
|
6
|
+
"template.rb.erb",
|
|
7
|
+
Rails.root.join("app/controllers/madmin/#{file_name}_controller.rb"),
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
template(
|
|
11
|
+
"template.html.erb",
|
|
12
|
+
Rails.root.join("app/views/madmin/#{file_name}/index.html.erb"),
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
inject_into_file(
|
|
16
|
+
Rails.root.join("config/routes.rb"),
|
|
17
|
+
after: "namespace :madmin do\n"
|
|
18
|
+
) { " get \"#{file_name}\", to: \"#{file_name}#index\"\n" }
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
require "rails/generators/named_base"
|
|
2
|
+
require "madmin/generator_helpers"
|
|
3
|
+
|
|
4
|
+
module Madmin
|
|
5
|
+
module Generators
|
|
6
|
+
class ResourceGenerator < Rails::Generators::NamedBase
|
|
7
|
+
ATTRIBUTE_TYPE_MAPPING = {
|
|
8
|
+
boolean: "Field::CheckBox",
|
|
9
|
+
date: "Field::DateTime",
|
|
10
|
+
datetime: "Field::DateTime",
|
|
11
|
+
enum: "Field::Text",
|
|
12
|
+
float: "Field::Number",
|
|
13
|
+
integer: "Field::Number",
|
|
14
|
+
time: "Field::DateTime",
|
|
15
|
+
text: "Field::TextArea",
|
|
16
|
+
string: "Field::Text",
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
source_root File.expand_path("../templates", __FILE__)
|
|
20
|
+
|
|
21
|
+
def create_resource_file
|
|
22
|
+
template(
|
|
23
|
+
"resource.rb.erb",
|
|
24
|
+
Rails.root.join("app/madmin/resources/#{file_name}.rb"),
|
|
25
|
+
)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def attributes
|
|
31
|
+
klass.attribute_types.map { |name, attr|
|
|
32
|
+
# Skip attributes related to associations
|
|
33
|
+
next if ignored_attributes.include?(name)
|
|
34
|
+
|
|
35
|
+
[name, madmin_type_for_column(attr.type)]
|
|
36
|
+
}.compact
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def associations
|
|
40
|
+
klass.reflections.map do |name, association|
|
|
41
|
+
if association.polymorphic?
|
|
42
|
+
[name, "Field::Polymorphic"]
|
|
43
|
+
elsif association.belongs_to?
|
|
44
|
+
[name, "Field::BelongsTo"]
|
|
45
|
+
elsif association.has_one?
|
|
46
|
+
[name, "Field::HasOne"]
|
|
47
|
+
else
|
|
48
|
+
[name, "Field::HasMany"]
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def ignored_attributes
|
|
54
|
+
attrs = []
|
|
55
|
+
|
|
56
|
+
klass.reflections.map do |name, association|
|
|
57
|
+
if association.polymorphic?
|
|
58
|
+
attrs += [association.foreign_key, association.foreign_type]
|
|
59
|
+
elsif association.belongs_to?
|
|
60
|
+
attrs += [association.foreign_key]
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
attrs
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def klass
|
|
68
|
+
@klass ||= Object.const_get(class_name)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def madmin_type_for_column(column_type)
|
|
72
|
+
ATTRIBUTE_TYPE_MAPPING[column_type]
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require "rails/generators/base"
|
|
2
|
+
|
|
3
|
+
module Madmin
|
|
4
|
+
module Generators
|
|
5
|
+
class ViewsGenerator < Rails::Generators::Base
|
|
6
|
+
desc("Copies views for customizing Madmin's views")
|
|
7
|
+
|
|
8
|
+
source_root File.expand_path("../../../../..", __FILE__)
|
|
9
|
+
|
|
10
|
+
def copy_views
|
|
11
|
+
directory "app/views/madmin", "app/views/madmin"
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
data/lib/madmin.rb
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require "madmin/engine"
|
|
2
|
+
require "madmin/resourceable"
|
|
3
|
+
require "madmin/resources"
|
|
4
|
+
|
|
5
|
+
module Madmin
|
|
6
|
+
class NoResourcesError < StandardError; end
|
|
7
|
+
class ResourceNotFoundError < StandardError; end
|
|
8
|
+
class WrongArgumentError < StandardError; end
|
|
9
|
+
class UndefinedScopeError < StandardError; end
|
|
10
|
+
class ScopeWithArgumentsError < StandardError; end
|
|
11
|
+
|
|
12
|
+
autoload :Field, "madmin/field"
|
|
13
|
+
autoload :Resourceable, "madmin/resourceable"
|
|
14
|
+
|
|
15
|
+
class Field
|
|
16
|
+
autoload :Associatable, "madmin/field/associatable"
|
|
17
|
+
autoload :BelongsTo, "madmin/field/belongs_to"
|
|
18
|
+
autoload :CheckBox, "madmin/field/check_box"
|
|
19
|
+
autoload :DateTime, "madmin/field/date_time"
|
|
20
|
+
autoload :Email, "madmin/field/email"
|
|
21
|
+
autoload :HasMany, "madmin/field/has_many"
|
|
22
|
+
autoload :HasOne, "madmin/field/has_one"
|
|
23
|
+
autoload :Number, "madmin/field/number"
|
|
24
|
+
autoload :Password, "madmin/field/password"
|
|
25
|
+
autoload :Polymorphic, "madmin/field/polymorphic"
|
|
26
|
+
autoload :Select, "madmin/field/select"
|
|
27
|
+
autoload :TextArea, "madmin/field/text_area"
|
|
28
|
+
autoload :Text, "madmin/field/text"
|
|
29
|
+
end
|
|
30
|
+
end
|
data/lib/madmin/field.rb
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
module Madmin
|
|
2
|
+
class Field
|
|
3
|
+
attr_reader :form
|
|
4
|
+
attr_reader :index
|
|
5
|
+
attr_reader :key
|
|
6
|
+
attr_reader :label
|
|
7
|
+
attr_reader :model
|
|
8
|
+
attr_reader :options
|
|
9
|
+
attr_reader :show
|
|
10
|
+
attr_reader :type
|
|
11
|
+
|
|
12
|
+
def initialize(args)
|
|
13
|
+
@key = args[:key]
|
|
14
|
+
@options = args
|
|
15
|
+
@model = args[:model]
|
|
16
|
+
@label = option_or_default(:label, label_from_attribute(key))
|
|
17
|
+
@form = option_or_default(:form, false)
|
|
18
|
+
@index = option_or_default(:index, false)
|
|
19
|
+
@show = option_or_default(:show, true)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
##
|
|
23
|
+
# Returns an array of key(s) to use in strong
|
|
24
|
+
# params for the resources controller.
|
|
25
|
+
def strong_params_keys
|
|
26
|
+
[key]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
##
|
|
30
|
+
# Returns the partial path for the field type
|
|
31
|
+
def to_partial_path
|
|
32
|
+
"madmin/fields/#{self.class.to_s.split("Madmin::Field::").last.underscore}"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
##
|
|
36
|
+
# Returns the value for a given resource
|
|
37
|
+
def value_for(resource)
|
|
38
|
+
resource.send(key)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
##
|
|
44
|
+
# This method takes an attribute and converts it
|
|
45
|
+
# into a human readable format for form labels.
|
|
46
|
+
def label_from_attribute(attribute)
|
|
47
|
+
attribute.to_s.humanize
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
##
|
|
51
|
+
# This method verifies options are present
|
|
52
|
+
# (as a hash).
|
|
53
|
+
def options?
|
|
54
|
+
options.is_a?(Hash)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
##
|
|
58
|
+
# This method extracts the many option checks
|
|
59
|
+
# performed when assigning field options.
|
|
60
|
+
def option_or_default(key, default)
|
|
61
|
+
options? ? options.fetch(key, default) : default
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
module Madmin
|
|
2
|
+
class Field
|
|
3
|
+
module Associatable
|
|
4
|
+
class << self
|
|
5
|
+
def included(_base)
|
|
6
|
+
attr_reader :association_class
|
|
7
|
+
attr_reader :association_display_value
|
|
8
|
+
attr_reader :association_foreign_key
|
|
9
|
+
attr_reader :association_scope
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def initialize(args)
|
|
14
|
+
super(args)
|
|
15
|
+
implement_association!
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def association_collection
|
|
19
|
+
association_class.send(association_scope)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def association_id_for(resource)
|
|
23
|
+
value_for(resource).id
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def association_id_or_blank_for(resource)
|
|
27
|
+
value_for(resource).try(:id)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def association_param
|
|
31
|
+
ActiveModel::Naming.param_key(association_class)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def association_slug
|
|
35
|
+
Object.const_get("::Madmin::Resources::#{association_class}").new.slug
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def association_value_for(resource)
|
|
39
|
+
value_for(resource).send(association_display_value)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def strong_params_keys
|
|
43
|
+
[association_foreign_key]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def implement_association!
|
|
49
|
+
association = model.reflect_on_all_associations.find { |assc| assc.name == key }
|
|
50
|
+
|
|
51
|
+
@association_class = association.klass
|
|
52
|
+
@association_display_value = option_or_default(:display_value, :name)
|
|
53
|
+
@association_foreign_key = association.foreign_key
|
|
54
|
+
@association_scope = :all
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|