madmin 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +102 -0
  4. data/Rakefile +32 -0
  5. data/app/assets/config/madmin_manifest.js +2 -0
  6. data/app/assets/javascripts/madmin/application.js +15 -0
  7. data/app/assets/javascripts/madmin/dashboard.js +2 -0
  8. data/app/assets/javascripts/madmin/resources.js +36 -0
  9. data/app/assets/stylesheets/madmin/application.css +22 -0
  10. data/app/assets/stylesheets/madmin/dashboard.css +4 -0
  11. data/app/assets/stylesheets/madmin/resources.css +4 -0
  12. data/app/controllers/madmin/application_controller.rb +16 -0
  13. data/app/controllers/madmin/base_controller.rb +16 -0
  14. data/app/controllers/madmin/dashboard_controller.rb +8 -0
  15. data/app/controllers/madmin/resources_controller.rb +97 -0
  16. data/app/decorators/madmin/resource_decorator.rb +16 -0
  17. data/app/helpers/madmin/application_helper.rb +15 -0
  18. data/app/helpers/madmin/fields/polymorphic_helper.rb +25 -0
  19. data/app/jobs/madmin/application_job.rb +4 -0
  20. data/app/mailers/madmin/application_mailer.rb +6 -0
  21. data/app/models/madmin/application_record.rb +5 -0
  22. data/app/views/application/_navigation.html.erb +17 -0
  23. data/app/views/layouts/madmin/application.html.erb +30 -0
  24. data/app/views/madmin/dashboard/index.html.erb +6 -0
  25. data/app/views/madmin/fields/belongs_to/_form.html.erb +14 -0
  26. data/app/views/madmin/fields/belongs_to/_index.html.erb +7 -0
  27. data/app/views/madmin/fields/belongs_to/_show.html.erb +8 -0
  28. data/app/views/madmin/fields/check_box/_form.html.erb +4 -0
  29. data/app/views/madmin/fields/check_box/_index.html.erb +1 -0
  30. data/app/views/madmin/fields/check_box/_show.html.erb +8 -0
  31. data/app/views/madmin/fields/email/_form.html.erb +4 -0
  32. data/app/views/madmin/fields/email/_index.html.erb +1 -0
  33. data/app/views/madmin/fields/email/_show.html.erb +8 -0
  34. data/app/views/madmin/fields/has_many/_form.html.erb +0 -0
  35. data/app/views/madmin/fields/has_many/_show.html.erb +15 -0
  36. data/app/views/madmin/fields/has_one/_form.html.erb +0 -0
  37. data/app/views/madmin/fields/has_one/_show.html.erb +12 -0
  38. data/app/views/madmin/fields/number/_form.html.erb +4 -0
  39. data/app/views/madmin/fields/number/_index.html.erb +1 -0
  40. data/app/views/madmin/fields/number/_show.html.erb +8 -0
  41. data/app/views/madmin/fields/password/_form.html.erb +4 -0
  42. data/app/views/madmin/fields/password/_index.html.erb +1 -0
  43. data/app/views/madmin/fields/password/_show.html.erb +8 -0
  44. data/app/views/madmin/fields/polymorphic/_form.html.erb +32 -0
  45. data/app/views/madmin/fields/polymorphic/_index.html.erb +1 -0
  46. data/app/views/madmin/fields/polymorphic/_show.html.erb +14 -0
  47. data/app/views/madmin/fields/select/_form.html.erb +4 -0
  48. data/app/views/madmin/fields/select/_index.html.erb +1 -0
  49. data/app/views/madmin/fields/select/_show.html.erb +8 -0
  50. data/app/views/madmin/fields/text/_form.html.erb +4 -0
  51. data/app/views/madmin/fields/text/_index.html.erb +1 -0
  52. data/app/views/madmin/fields/text/_show.html.erb +8 -0
  53. data/app/views/madmin/fields/text_area/_form.html.erb +4 -0
  54. data/app/views/madmin/fields/text_area/_index.html.erb +1 -0
  55. data/app/views/madmin/fields/text_area/_show.html.erb +8 -0
  56. data/app/views/madmin/resources/_form.html.erb +15 -0
  57. data/app/views/madmin/resources/_scopes.html.erb +10 -0
  58. data/app/views/madmin/resources/edit.html.erb +2 -0
  59. data/app/views/madmin/resources/index.html.erb +13 -0
  60. data/app/views/madmin/resources/index/_content.html.erb +33 -0
  61. data/app/views/madmin/resources/new.html.erb +2 -0
  62. data/app/views/madmin/resources/show.html.erb +10 -0
  63. data/config/routes.rb +11 -0
  64. data/lib/generators/madmin/controller/USAGE +8 -0
  65. data/lib/generators/madmin/controller/controller_generator.rb +10 -0
  66. data/lib/generators/madmin/install/install_generator.rb +31 -0
  67. data/lib/generators/madmin/page/USAGE +8 -0
  68. data/lib/generators/madmin/page/page_generator.rb +20 -0
  69. data/lib/generators/madmin/page/templates/template.html.erb +2 -0
  70. data/lib/generators/madmin/page/templates/template.rb.erb +10 -0
  71. data/lib/generators/madmin/resource/resource_generator.rb +76 -0
  72. data/lib/generators/madmin/resource/templates/resource.rb.erb +11 -0
  73. data/lib/generators/madmin/views/views_generator.rb +15 -0
  74. data/lib/madmin.rb +30 -0
  75. data/lib/madmin/engine.rb +9 -0
  76. data/lib/madmin/field.rb +64 -0
  77. data/lib/madmin/field/associatable.rb +58 -0
  78. data/lib/madmin/field/belongs_to.rb +9 -0
  79. data/lib/madmin/field/check_box.rb +8 -0
  80. data/lib/madmin/field/date_time.rb +8 -0
  81. data/lib/madmin/field/email.rb +8 -0
  82. data/lib/madmin/field/has_many.rb +9 -0
  83. data/lib/madmin/field/has_one.rb +9 -0
  84. data/lib/madmin/field/number.rb +8 -0
  85. data/lib/madmin/field/password.rb +8 -0
  86. data/lib/madmin/field/polymorphic.rb +57 -0
  87. data/lib/madmin/field/select.rb +13 -0
  88. data/lib/madmin/field/text.rb +8 -0
  89. data/lib/madmin/field/text_area.rb +8 -0
  90. data/lib/madmin/generator_helpers.rb +13 -0
  91. data/lib/madmin/resourceable.rb +72 -0
  92. data/lib/madmin/resourceable/class_methods.rb +152 -0
  93. data/lib/madmin/resources.rb +13 -0
  94. data/lib/madmin/version.rb +3 -0
  95. data/lib/tasks/madmin_tasks.rake +4 -0
  96. metadata +197 -0
@@ -0,0 +1,4 @@
1
+ module Madmin
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module Madmin
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: "from@example.com"
4
+ layout "mailer"
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module Madmin
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ <nav class="nav bg-dark col-md-2 sidebar px-4 py-3 d-flex flex-column">
2
+ <h3><%= link_to 'Madmin', root_path %></h3>
3
+
4
+ <ul class="list-unstyled mt-3">
5
+ <% available_resources.each do |resource| %>
6
+ <% next unless resource.show_in_menu? %>
7
+ <li class="mb-1">
8
+ <%= link_to resource.friendly_name.pluralize, resources_path(resource.slug), class: "text-white" %>
9
+ </li>
10
+ <% end %>
11
+ <% pages.each do |page| %>
12
+ <li class="mb-1">
13
+ <%= link_to page, "#", class: "text-white"%>
14
+ </li>
15
+ <% end %>
16
+ </ul>
17
+ </nav>
@@ -0,0 +1,30 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Madmin</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
9
+
10
+ <%= stylesheet_link_tag "madmin/application", media: "all" %>
11
+ </head>
12
+ <body>
13
+ <div class="container-fluid">
14
+ <div class="row">
15
+ <%= render 'application/navigation' %>
16
+ <div class="col-10 ml-sm-auto mt-4">
17
+ <div class="container">
18
+ <%= yield %>
19
+ </div>
20
+ </div>
21
+ </div>
22
+ </div>
23
+
24
+ <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
25
+ <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
26
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
27
+ <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
28
+ <%= javascript_include_tag "madmin/application" %>
29
+ </body>
30
+ </html>
@@ -0,0 +1,6 @@
1
+ <h1>Administration</h1>
2
+ <% available_resources.each do |type| %>
3
+ <li>
4
+ <%= link_to type.friendly_name.pluralize, resources_path(type.slug) %>
5
+ </li>
6
+ <% end %>
@@ -0,0 +1,14 @@
1
+ <div class="form-group">
2
+ <%= form.label field.key %>
3
+ <%=
4
+ form.select field.association_foreign_key,
5
+ options_from_collection_for_select(
6
+ field.association_collection,
7
+ :id,
8
+ field.association_display_value,
9
+ field.association_id_or_blank_for(resource)
10
+ ),
11
+ { include_blank: true },
12
+ class: 'form-control'
13
+ %>
14
+ </div>
@@ -0,0 +1,7 @@
1
+ <%=
2
+ link_to field.association_value_for(resource),
3
+ resource_path(
4
+ field.association_slug,
5
+ field.association_id_for(resource)
6
+ )
7
+ %>
@@ -0,0 +1,8 @@
1
+ <div class="row">
2
+ <div class="col-3">
3
+ <%= field.label %>
4
+ </div>
5
+ <div class="col-9">
6
+ <%= field.association_value_for(resource) %>
7
+ </div>
8
+ </div>
@@ -0,0 +1,4 @@
1
+ <div class="form-group form-check">
2
+ <%= form.check_box field.key, class: "form-check-input" %>
3
+ <%= form.label field.key, field.label, class: "form-check-label" %>
4
+ </div>
@@ -0,0 +1 @@
1
+ <%= field.value_for(resource) %>
@@ -0,0 +1,8 @@
1
+ <div class="row">
2
+ <div class="col-3">
3
+ <%= field.label %>
4
+ </div>
5
+ <div class="col-9">
6
+ <%= field.value_for(resource) %>
7
+ </div>
8
+ </div>
@@ -0,0 +1,4 @@
1
+ <div class="form-group">
2
+ <%= form.label field.key, field.label %>
3
+ <%= form.email_field field.key, class: "form-control" %>
4
+ </div>
@@ -0,0 +1 @@
1
+ <%= field.value_for(resource) %>
@@ -0,0 +1,8 @@
1
+ <div class="row">
2
+ <div class="col-3">
3
+ <%= field.label %>
4
+ </div>
5
+ <div class="col-9">
6
+ <%= field.value_for(resource) %>
7
+ </div>
8
+ </div>
@@ -0,0 +1,15 @@
1
+ <div class="mt-3">
2
+ <div class="row">
3
+ <div class="col">
4
+ <h3><%= field.label %></h3>
5
+ <%= link_to "Add", new_resource_path(field.association_slug, field.association_param => { field.association_foreign_key => resource.id }) %>
6
+ <%=
7
+ render "madmin/resources/index/content",
8
+ headers: [],
9
+ collection: field.value_for(resource),
10
+ madmin_resource: madmin_resource_for(model: field.association_class),
11
+ show_new_button: false
12
+ %>
13
+ </div>
14
+ </div>
15
+ </div>
@@ -0,0 +1,12 @@
1
+ <div class="mt-3">
2
+ <div class="row">
3
+ <div class="col">
4
+ <h3><%= field.name %></h3>
5
+ <% if !field.value %>
6
+ <%= link_to "Add", new_resource_path(madmin_resource_for(model: field.foreign_class).slug, ActiveModel::Naming.param_key(field.foreign_class) => { field.foreign_key => field.resource.id }) %>
7
+ <% else %>
8
+ <%= render "madmin/resources/index/content", headers: [], collection: [Madmin::ResourceDecorator.new(field.value)], show_new_button: false %>
9
+ <% end %>
10
+ </div>
11
+ </div>
12
+ </div>
@@ -0,0 +1,4 @@
1
+ <div class="form-group">
2
+ <%= form.label field.key, field.label %>
3
+ <%= form.number_field field.key, class: "form-control" %>
4
+ </div>
@@ -0,0 +1 @@
1
+ <%= link_to field.value_for(resource), resource_path(madmin_resource.slug, id: resource.id) %>
@@ -0,0 +1,8 @@
1
+ <div class="row">
2
+ <div class="col-3">
3
+ <%= field.label %>
4
+ </div>
5
+ <div class="col-9">
6
+ <%= field.value_for(resource) %>
7
+ </div>
8
+ </div>
@@ -0,0 +1,4 @@
1
+ <div class="form-group">
2
+ <%= form.label field.key, field.label %>
3
+ <%= form.password_field field.key, class: "form-control", autocomplete: false %>
4
+ </div>
@@ -0,0 +1 @@
1
+ <%= 'Password Encrypted' if field.value %>
@@ -0,0 +1,8 @@
1
+ <div class="row">
2
+ <div class="col-3">
3
+ <%= field.label %>
4
+ </div>
5
+ <div class="col-9">
6
+ <%= 'Password Encrypted' if field.value_for(resource).present? %>
7
+ </div>
8
+ </div>
@@ -0,0 +1,32 @@
1
+ <div class="form-group">
2
+ <%= form.label field.key %>
3
+ <%=
4
+ form.select field.polymorphic_type_param,
5
+ polymorphic_models(field.key).map { |m| [m.name, m.name, { "data-slug" => madmin_resource_for(model: m).slug }] },
6
+ { include_blank: true },
7
+ id: field.polymorphic_type_param,
8
+ class: "form-control"
9
+ %>
10
+ <% if field.polymorphic_relationship_exists?(form.object) %>
11
+ <%=
12
+ form.select field.polymorphic_id_param,
13
+ polymorphic_options_for_selected_type(form: form, field: field),
14
+ {},
15
+ id: field.polymorphic_id_param,
16
+ class: "form-control"
17
+ %>
18
+ <% else %>
19
+ <%=
20
+ form.select field.polymorphic_id_param,
21
+ [],
22
+ {},
23
+ id: field.polymorphic_id_param,
24
+ class: "d-none form-control"
25
+ %>
26
+ <% end %>
27
+ </div>
28
+
29
+ <script>
30
+ window.polymorphicFields = window.polymorphicFields || [];
31
+ window.polymorphicFields.push('<%= field.key %>')
32
+ </script>
@@ -0,0 +1 @@
1
+ <%= link_to field.polymorphic_value_for(resource), resource_path(field.polymorphic_slug_for(resource), field.polymorphic_id_for(resource)) %>
@@ -0,0 +1,14 @@
1
+ <div class="row">
2
+ <div class="col-3">
3
+ <%= field.label %>
4
+ </div>
5
+ <div class="col-9">
6
+ <%=
7
+ link_to field.polymorphic_value_for(resource),
8
+ resource_path(
9
+ field.polymorphic_slug_for(resource),
10
+ field.polymorphic_id_for(resource)
11
+ )
12
+ %>
13
+ </div>
14
+ </div>
@@ -0,0 +1,4 @@
1
+ <div class="form-group">
2
+ <%= form.label field.key, field.label %>
3
+ <%= form.select field.key, field.select_options, {}, class: "form-control" %>
4
+ </div>
@@ -0,0 +1 @@
1
+ <%= field.value %>
@@ -0,0 +1,8 @@
1
+ <div class="row">
2
+ <div class="col-3">
3
+ <%= field.label %>
4
+ </div>
5
+ <div class="col-9">
6
+ <%= field.value_for(resource) %>
7
+ </div>
8
+ </div>
@@ -0,0 +1,4 @@
1
+ <div class="form-group">
2
+ <%= form.label field.key, field.label %>
3
+ <%= form.text_field field.key, class: "form-control" %>
4
+ </div>
@@ -0,0 +1 @@
1
+ <%= field.value_for(resource) %>
@@ -0,0 +1,8 @@
1
+ <div class="row">
2
+ <div class="col-3">
3
+ <%= field.label %>
4
+ </div>
5
+ <div class="col-9">
6
+ <%= field.value_for(resource) %>
7
+ </div>
8
+ </div>
@@ -0,0 +1,4 @@
1
+ <div class="form-group">
2
+ <%= form.label field.key, field.label %>
3
+ <%= form.text_area field.key, class: "form-control" %>
4
+ </div>
@@ -0,0 +1 @@
1
+ <%= field.value %>
@@ -0,0 +1,8 @@
1
+ <div class="row">
2
+ <div class="col-3">
3
+ <%= field.label %>
4
+ </div>
5
+ <div class="col-9">
6
+ <%= field.value_for(resource) %>
7
+ </div>
8
+ </div>
@@ -0,0 +1,15 @@
1
+ <%= form_for resource, url: url do |form| %>
2
+ <% if resource.errors.any? %>
3
+ <% resource.errors.full_messages.each do |message| %>
4
+ <li><%= message %></li>
5
+ <% end %>
6
+ <% end %>
7
+
8
+ <% madmin_resource.form_fields.each do |field| %>
9
+ <%= render "#{field.to_partial_path}/form", field: field, form: form, resource: resource %>
10
+ <% end %>
11
+
12
+ <div class="mt-4">
13
+ <%= form.submit class: "btn btn-primary" %>
14
+ </div>
15
+ <% end %>
@@ -0,0 +1,10 @@
1
+ <div class="list-group">
2
+ <%= link_to resources_path(madmin_resource.slug), class: "list-group-item py-2 list-group-item-action #{'active' if params[:scope].blank?}" do %>
3
+ All
4
+ <% end %>
5
+ <% scopes.each do |scope| %>
6
+ <%= link_to resources_path(madmin_resource.slug, scope: scope.to_s), class: "list-group-item py-2 list-group-item-action #{'active' if params[:scope] == scope.to_s}" do %>
7
+ <%= scope.to_s.titleize %>
8
+ <% end %>
9
+ <% end %>
10
+ </div>
@@ -0,0 +1,2 @@
1
+ <h1><%= @resource.name %> <%= @resource.id %></h1>
2
+ <%= render 'form', resource: @resource, url: resource_path %>
@@ -0,0 +1,13 @@
1
+ <div class="row">
2
+ <div class="col">
3
+ <h1><%= madmin_resource.friendly_name.pluralize %></h1>
4
+ </div>
5
+ </div>
6
+ <div class="row">
7
+ <%= content_tag :div, class: @scopes.any? ? 'col-3' : 'd-none' do %>
8
+ <%= render 'scopes', scopes: @scopes %>
9
+ <% end %>
10
+ <%= content_tag :div, class: @scopes.any? ? 'col-9' : 'col-12' do %>
11
+ <%= render 'madmin/resources/index/content', headers: @headers, collection: @collection, show_new_button: true %>
12
+ <% end %>
13
+ </div>
@@ -0,0 +1,33 @@
1
+ <table class="table">
2
+ <thead>
3
+ <% headers.each do |header| %>
4
+ <th><%= header %></th>
5
+ <% end %>
6
+ </thead>
7
+ <% if collection.any? %>
8
+ <% collection.each do |resource| %>
9
+ <tr>
10
+ <% madmin_resource.index_fields.each do |field| %>
11
+ <td>
12
+ <%=
13
+ render "#{field.to_partial_path}/index",
14
+ field: field,
15
+ madmin_resource: madmin_resource,
16
+ resource: resource
17
+ %>
18
+ </td>
19
+ <% end %>
20
+ </tr>
21
+ <% end %>
22
+ <% else %>
23
+ <tr>
24
+ <td>No records found</td>
25
+ </tr>
26
+ <% end %>
27
+ </table>
28
+
29
+ <% if show_new_button %>
30
+ <div class="mt-4">
31
+ <%= link_to 'New', new_resource_path, class: "btn btn-primary" %>
32
+ </div>
33
+ <% end %>
@@ -0,0 +1,2 @@
1
+ <h1>New <%= @resource.name %></h1>
2
+ <%= render 'form', resource: @resource, url: resources_path %>
@@ -0,0 +1,10 @@
1
+ <h1><%= @resource.name %> <%= @resource.id %></h1>
2
+
3
+ <% madmin_resource.show_fields.each do |field| %>
4
+ <%= render "#{field.to_partial_path}/show", field: field, resource: @resource %>
5
+ <% end %>
6
+
7
+ <div class="mt-4">
8
+ <%= link_to 'Edit', edit_resource_path(id: @resource.id), class: "btn btn-primary" %>
9
+ <%= link_to 'Delete', resource_path(id: @resource.id), method: :delete, class: "btn btn-danger" %>
10
+ </div>
@@ -0,0 +1,11 @@
1
+ Madmin::Engine.routes.draw do
2
+ root to: "dashboard#index"
3
+
4
+ get "/:resource", to: "resources#index", as: :resources
5
+ get "/:resource/new", to: "resources#new", as: :new_resource
6
+ post "/:resource", to: "resources#create"
7
+ get "/:resource/:id", to: "resources#show", as: :resource
8
+ get "/:resource/:id/edit", to: "resources#edit", as: :edit_resource
9
+ patch "/:resource/:id", to: "resources#update"
10
+ delete "/:resource/:id", to: "resources#destroy"
11
+ end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Override certain Madmin controllers for fine-tuning
3
+
4
+ Example:
5
+ rails generate madmin:controller Application
6
+
7
+ This will create:
8
+ app/controllers/madmin/application_controller.rb