madmin 1.2.1 → 1.2.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1f3bd8e986e4859620b06401c531dc24ca84bb02e4e2284a34918b5a088c126c
4
- data.tar.gz: 9bf59b4f93849feda832005caa748e02b4227ea2552cd6e94264d3b7d170f5a9
3
+ metadata.gz: ea857d0e707bca79172d1bcbecb72cfb939724279ab3f2c08546ff279fd38d03
4
+ data.tar.gz: c886c8ad0c5d0a11c81f1aecf45463e29205e9bf29dfe00fae4fc94466988ee0
5
5
  SHA512:
6
- metadata.gz: 3181e8f05aad7af36b905a4a04ffb2ddd63419b347e699b0b9ea6d8d2fb9a880f12ebbd7b12d05770e02dc7508e4789a1cb8250b11b6eed26878b6ef71d7fc1b
7
- data.tar.gz: '0019a725b02cde9e007190917381da718a139662d1d9094a0e49ccc69b799437865a4170658b99492947ce1d6d2ae04f71dde97886212a8dd728c3a9aa2275f3'
6
+ metadata.gz: 65e7522be423638030455299a70bfdd21cc706e75a5b6624f7a41f869250517474b00dd514551914e86bb3b7e7dac31aa812826461a634649caba8456b73f5c8
7
+ data.tar.gz: faea74829b0c7e307960dcbe006986f51c064e147c00b17f1234bfc6b72246511c1d206d4891fd773f3f97ea05b96a87dbcdd3e9b709aac1141407a580529b26
@@ -0,0 +1,22 @@
1
+ module Madmin
2
+ class ApplicationController < Madmin::BaseController
3
+ before_action :authenticate_admin_user
4
+
5
+ def authenticate_admin_user
6
+ # TODO: Add your authentication logic here
7
+
8
+ # For example, we could redirect if the user isn't an admin
9
+ # redirect_to "/", alert: "Not authorized." unless user_signed_in? && current_user.admin?
10
+ end
11
+
12
+ # Authenticate with Clearance
13
+ # include Clearance::Controller
14
+ # before_action :require_login
15
+
16
+ # Authenticate with Devise
17
+ # before_action :authenticate_user!
18
+
19
+ # Authenticate with Basic Auth
20
+ # http_basic_authenticate_with(name: Rails.application.credentials.admin_username, password: Rails.application.credentials.admin_password)
21
+ end
22
+ end
@@ -1,5 +1,5 @@
1
1
  module Madmin
2
- class ResourceController < ApplicationController
2
+ class ResourceController < Madmin::ApplicationController
3
3
  include SortHelper
4
4
 
5
5
  before_action :set_record, except: [:index, :new, :create]
@@ -19,7 +19,7 @@
19
19
  <div id="sidebar" class="md:w-64 p-4 flex-shrink-0 border-r">
20
20
  <%= render "navigation" -%>
21
21
  </div>
22
- <main class="flex-grow p-4" role="main">
22
+ <main class="flex-grow p-4 overflow-x-scroll" role="main">
23
23
  <%#= render "flashes" -%>
24
24
  <%= yield %>
25
25
  </main>
@@ -3,7 +3,7 @@
3
3
  <%= stylesheet_link_tag "https://unpkg.com/tom-select/dist/css/tom-select.min.css", "data-turbo-track": "reload" %>
4
4
 
5
5
  <script type="module">
6
- import { Application, Controller } from 'https://cdn.skypack.dev/stimulus'
6
+ import { Application, Controller } from 'https://cdn.skypack.dev/@hotwired/stimulus'
7
7
  const application = Application.start()
8
8
 
9
9
  import { Dropdown } from "https://cdn.skypack.dev/tailwindcss-stimulus-components"
@@ -27,33 +27,36 @@
27
27
  <%= link_to scope.to_s.humanize, resource.index_path(scope: scope), class: class_names("p-2 rounded", {"bg-gray-100" => params[:scope] == scope.to_s}) %>
28
28
  <% end %>
29
29
  </div>
30
-
31
- <table class="min-w-full divide-y divide-gray-200">
32
- <thead>
33
- <tr class="border-b border-gray-200">
34
- <% resource.attributes.values.each do |attribute| %>
35
- <% next if attribute.field.nil? %>
36
- <% next unless attribute.field.visible?(action_name) %>
37
-
38
- <th class="py-2 px-4 text-left text-xs text-gray-500 font-medium uppercase whitespace-nowrap"><%= sortable attribute.name, attribute.name.to_s.titleize %></th>
39
- <% end %>
40
- <th class="py-2 px-4 text-left text-xs text-gray-500 font-medium uppercase">Actions</th>
41
- </tr>
42
- </thead>
43
-
44
- <tbody class="text-sm divide-y">
45
- <% @records.each do |record| %>
46
- <tr>
30
+ <div class="min-w-full max-w-xl overflow-x-auto pb-4">
31
+ <table class="min-w-full divide-y divide-gray-200">
32
+ <thead>
33
+ <tr class="border-b border-gray-200">
47
34
  <% resource.attributes.values.each do |attribute| %>
48
35
  <% next if attribute.field.nil? %>
49
36
  <% next unless attribute.field.visible?(action_name) %>
50
- <td class="px-4 py-2"><%= render partial: attribute.field.to_partial_path("index"), locals: { field: attribute.field, record: record } %></td>
51
- <% end %>
52
37
 
53
- <td class="px-4 py-2 text-center"><%= link_to "View", resource.show_path(record), class: "text-indigo-500" %></td>
38
+ <th class="py-2 px-4 text-left text-xs text-gray-500 font-medium uppercase whitespace-nowrap"><%= sortable attribute.name, attribute.name.to_s.titleize %></th>
39
+ <% end %>
40
+ <th class="py-2 px-4 text-left text-xs text-gray-500 font-medium uppercase">Actions</th>
54
41
  </tr>
55
- <% end %>
56
- </tbody>
57
- </table>
58
-
42
+ </thead>
43
+
44
+ <tbody class="text-sm divide-y">
45
+ <% @records.each do |record| %>
46
+ <tr>
47
+ <% resource.attributes.values.each do |attribute| %>
48
+ <% next if attribute.field.nil? %>
49
+ <% next unless attribute.field.visible?(action_name) %>
50
+ <td class="px-4 py-2"><%= render partial: attribute.field.to_partial_path("index"), locals: { field: attribute.field, record: record, resource: resource } %></td>
51
+ <% end %>
52
+
53
+ <td class="px-4 py-2 text-center">
54
+ <%= link_to "View", resource.show_path(record), class: "text-indigo-500" %>
55
+ <%= link_to "Edit", resource.edit_path(record), class: "text-indigo-500" %>
56
+ </td>
57
+ </tr>
58
+ <% end %>
59
+ </tbody>
60
+ </table>
61
+ </div>
59
62
  <%== pagy_nav(@pagy) if @pagy.pages > 1 %>
@@ -24,7 +24,7 @@
24
24
  </div>
25
25
 
26
26
  <div class="md:col-span-3">
27
- <%= render partial: attribute.field.to_partial_path("show"), locals: { field: attribute.field, record: @record } %>
27
+ <%= render partial: attribute.field.to_partial_path("show"), locals: { field: attribute.field, record: @record, resource: resource } %>
28
28
  </div>
29
29
  </div>
30
30
  <% end %>
@@ -0,0 +1,4 @@
1
+ <div class="block md:inline-block md:w-32 flex-shrink-0 text-gray-700">
2
+ <%= render "madmin/shared/label", form: form, field: field %>
3
+ </div>
4
+ <%= form.file_field field.attribute_name, class: "form-input" %>
@@ -0,0 +1 @@
1
+ <%= field.value(record) %>
@@ -0,0 +1,6 @@
1
+ <% value = field.value(record) %>
2
+ <% if value.respond_to?(:url) %>
3
+ <%= link_to value.url, value.url, target: :_blank, class: "text-indigo-500 underline" %>
4
+ <% else %>
5
+ <%= value %>
6
+ <% end %>
@@ -1 +1,5 @@
1
- <%= field.value(record) %>
1
+ <% if field.attribute_name == :id %>
2
+ <%= link_to field.value(record), resource.show_path(record), class: "text-indigo-500 underline" %>
3
+ <% else %>
4
+ <%= field.value(record) %>
5
+ <% end %>
@@ -1,5 +1,5 @@
1
- <%= content_tag :div, class: "nested-fields bg-gray-100 rounded-t-xl p-5", data: { new_record: f.object.new_record? } do %>
2
- <% field.nested_attributes.each do |nested_attribute| %>
1
+ <%= content_tag :div, class: "nested-fields border border-gray-200 rounded-lg p-5", data: { new_record: f.object.new_record? } do %>
2
+ <% field.nested_attributes.each do |name, nested_attribute| %>
3
3
  <% next if nested_attribute[:field].nil? %>
4
4
  <% next unless nested_attribute[:field].visible?(action_name) %>
5
5
  <% next unless nested_attribute[:field].visible?(:form) %>
@@ -14,5 +14,4 @@
14
14
  <small><%= link_to "Remove", "#", data: { action: "click->nested-form#remove_association" } %></small>
15
15
 
16
16
  <%= f.hidden_field :_destroy %>
17
-
18
17
  <% end %>
@@ -1 +1 @@
1
- <%= field.value(record) %>
1
+ <%= truncate field.value(record) %>
@@ -28,69 +28,19 @@ module Madmin
28
28
 
29
29
  private
30
30
 
31
- def associations
32
- model.reflections.reject { |name, association|
33
- # Hide these special associations
34
- name.starts_with?("rich_text") ||
35
- name.ends_with?("_attachment") ||
36
- name.ends_with?("_attachments") ||
37
- name.ends_with?("_blob") ||
38
- name.ends_with?("_blobs")
39
- }.keys
31
+ def model
32
+ @model ||= class_name.constantize
40
33
  end
41
34
 
42
- def attributes
43
- model.attribute_names + virtual_attributes - redundant_attributes
35
+ def resource_builder
36
+ @resource_builder ||= ResourceBuilder.new(model)
44
37
  end
45
38
 
46
- def virtual_attributes
47
- virtual = []
48
-
49
- # has_secure_password columns
50
- password_attributes = model.attribute_types.keys.select { |k| k.ends_with?("_digest") }.map { |k| k.delete_suffix("_digest") }
51
- virtual += password_attributes.map { |attr| [attr, "#{attr}_confirmation"] }.flatten
52
-
53
- # Add virtual attributes for ActionText and ActiveStorage
54
- model.reflections.each do |name, association|
55
- if name.starts_with?("rich_text")
56
- virtual << name.split("rich_text_").last
57
- elsif name.ends_with?("_attachment")
58
- virtual << name.split("_attachment").first
59
- elsif name.ends_with?("_attachments")
60
- virtual << name.split("_attachments").first
61
- end
62
- end
63
-
64
- virtual
39
+ def model_attributes
40
+ resource_builder.attributes
65
41
  end
66
42
 
67
- def redundant_attributes
68
- redundant = []
69
-
70
- # has_secure_password columns
71
- redundant += model.attribute_types.keys.select { |k| k.ends_with?("_digest") }
72
-
73
- model.reflections.each do |name, association|
74
- if association.has_one?
75
- next
76
- elsif association.collection?
77
- next
78
- elsif association.polymorphic?
79
- redundant << "#{name}_id"
80
- redundant << "#{name}_type"
81
- elsif name.starts_with?("rich_text")
82
- redundant << name
83
- else # belongs to
84
- redundant << "#{name}_id"
85
- end
86
- end
87
-
88
- redundant
89
- end
90
-
91
- def model
92
- @model ||= class_name.constantize
93
- end
43
+ delegate :associations, :virtual_attributes, :store_accessors, to: :resource_builder
94
44
 
95
45
  def formatted_options_for_attribute(name)
96
46
  options = options_for_attribute(name)
@@ -114,7 +64,7 @@ module Madmin
114
64
  {form: false}
115
65
 
116
66
  # Attributes without a database column
117
- elsif !model.column_names.include?(name)
67
+ elsif !model.column_names.include?(name) && !store_accessors.map(&:to_s).include?(name)
118
68
  {index: false}
119
69
  end
120
70
  end
@@ -1,6 +1,6 @@
1
1
  class <%= class_name %>Resource < Madmin::Resource
2
2
  # Attributes
3
- <% attributes.each do |attribute_name| -%>
3
+ <% model_attributes.each do |attribute_name| -%>
4
4
  attribute :<%= attribute_name %><%= formatted_options_for_attribute(attribute_name) %>
5
5
  <% end -%>
6
6
 
data/lib/madmin/engine.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  module Madmin
2
2
  class Engine < ::Rails::Engine
3
- initializer "madmin.autoload", before: :set_autoload_paths do |app|
4
- app.config.paths.add "app/madmin/resources", eager_load: true
5
- app.config.paths.add "app/madmin/fields", eager_load: true
3
+ config.before_configuration do |app|
4
+ app.config.autoload_paths << File.expand_path("app/madmin/resources", Rails.root)
5
+ app.config.autoload_paths << File.expand_path("app/madmin/fields", Rails.root)
6
6
  end
7
7
 
8
8
  config.to_prepare do
data/lib/madmin/field.rb CHANGED
@@ -1,14 +1,15 @@
1
1
  module Madmin
2
2
  class Field
3
- attr_reader :attribute_name, :model, :options
3
+ attr_reader :attribute_name, :model, :options, :resource
4
4
 
5
5
  def self.field_type
6
6
  to_s.split("::").last.underscore
7
7
  end
8
8
 
9
- def initialize(attribute_name:, model:, **options)
9
+ def initialize(attribute_name:, model:, resource:, **options)
10
10
  @attribute_name = attribute_name
11
11
  @model = model
12
+ @resource = resource
12
13
  @options = options
13
14
  end
14
15
 
@@ -0,0 +1,9 @@
1
+ module Madmin
2
+ module Fields
3
+ class File < Field
4
+ def searchable?
5
+ false
6
+ end
7
+ end
8
+ end
9
+ end
@@ -3,7 +3,7 @@ module Madmin
3
3
  class NestedHasMany < Field
4
4
  DEFAULT_ATTRIBUTES = %w[_destroy id].freeze
5
5
  def nested_attributes
6
- resource.attributes.reject { |i| skipped_fields.include?(i[:name]) }
6
+ resource.attributes.reject { |name, attribute| skipped_fields.include?(name) }
7
7
  end
8
8
 
9
9
  def resource
@@ -11,7 +11,7 @@ module Madmin
11
11
  end
12
12
 
13
13
  def model
14
- model_name.constantize
14
+ @model ||= model_name.constantize
15
15
  end
16
16
 
17
17
  def model_find(id)
@@ -37,36 +37,51 @@ module Madmin
37
37
  attributes[name] = OpenStruct.new(
38
38
  name: name,
39
39
  type: type,
40
- field: field.new(**options.merge(attribute_name: name, model: model))
40
+ field: field.new(**options.merge(attribute_name: name, model: model, resource: self))
41
41
  )
42
+ rescue => e
43
+ builder = ResourceBuilder.new(model)
44
+ raise ArgumentError, <<~MESSAGE
45
+ Madmin couldn't find attribute or association '#{name}' on #{model} model.
46
+
47
+ We searched these attributes and associations:
48
+ #{(builder.attributes + builder.associations).join(", ")}
49
+
50
+ This attribute is defined in a Madmin resource at:
51
+ #{e.backtrace.find { |l| l =~ /_resource.rb/ }}
52
+
53
+ Either add the missing attribute or assocation, or remove this line from your Madmin resource.
54
+ MESSAGE
42
55
  end
43
56
 
44
57
  def friendly_name
45
58
  model_name.gsub("::", " / ")
46
59
  end
47
60
 
48
- def index_path(options = {})
49
- route_name = "madmin_#{model.model_name.plural}_path"
61
+ # Support for isolated namespaces
62
+ # Finds parent module class to include in polymorphic urls
63
+ def route_namespace
64
+ return @route_namespace if instance_variable_defined?(:@route_namespace)
65
+ namespace = model.module_parents.detect do |n|
66
+ n.respond_to?(:use_relative_model_naming?) && n.use_relative_model_naming?
67
+ end
68
+ @route_namespace = (namespace ? namespace.name.singularize.underscore.to_sym : nil)
69
+ end
50
70
 
51
- url_helpers.send(route_name, options)
71
+ def index_path(options = {})
72
+ url_helpers.polymorphic_path([:madmin, route_namespace, model], options)
52
73
  end
53
74
 
54
75
  def new_path
55
- route_name = "new_madmin_#{model.model_name.singular}_path"
56
-
57
- url_helpers.send(route_name)
76
+ url_helpers.polymorphic_path([:madmin, route_namespace, model], action: :new)
58
77
  end
59
78
 
60
79
  def show_path(record)
61
- route_name = "madmin_#{model.model_name.singular}_path"
62
-
63
- url_helpers.send(route_name, record.to_param)
80
+ url_helpers.polymorphic_path([:madmin, route_namespace, record])
64
81
  end
65
82
 
66
83
  def edit_path(record)
67
- route_name = "edit_madmin_#{model.model_name.singular}_path"
68
-
69
- url_helpers.send(route_name, record.to_param)
84
+ url_helpers.polymorphic_path([:madmin, route_namespace, record], action: :edit)
70
85
  end
71
86
 
72
87
  def param_key
@@ -115,6 +130,7 @@ module Madmin
115
130
  time: Fields::Time,
116
131
  timestamp: Fields::Time,
117
132
  password: Fields::Password,
133
+ file: Fields::File,
118
134
 
119
135
  # Postgres specific types
120
136
  bit: Fields::String,
@@ -154,15 +170,6 @@ module Madmin
154
170
  rich_text: Fields::RichText,
155
171
  nested_has_many: Fields::NestedHasMany
156
172
  }.fetch(type)
157
- rescue
158
- raise ArgumentError, <<~MESSAGE
159
- Couldn't find attribute or association '#{name}' with type '#{type}' on #{model} model
160
-
161
- To fix this, either:
162
-
163
- 1. Remove 'attribute #{name}' from app/madmin/resources/#{model.to_s.underscore}_resource.rb
164
- 2. Or add the missing attribute or association to the #{model} model
165
- MESSAGE
166
173
  end
167
174
 
168
175
  def infer_type(name)
@@ -187,6 +194,10 @@ module Madmin
187
194
  # has_secure_password
188
195
  elsif model.attribute_types.include?("#{name_string}_digest") || name_string.ends_with?("_confirmation")
189
196
  :password
197
+
198
+ # ActiveRecord Store
199
+ elsif model_store_accessors.include?(name)
200
+ :string
190
201
  end
191
202
  end
192
203
 
@@ -205,6 +216,12 @@ module Madmin
205
216
  def url_helpers
206
217
  @url_helpers ||= Rails.application.routes.url_helpers
207
218
  end
219
+
220
+ def model_store_accessors
221
+ store_accessors = model.stored_attributes.values
222
+
223
+ store_accessors.flatten
224
+ end
208
225
  end
209
226
  end
210
227
  end
@@ -0,0 +1,80 @@
1
+ module Madmin
2
+ class ResourceBuilder
3
+ attr_reader :model
4
+
5
+ def initialize(model)
6
+ @model = model
7
+ end
8
+
9
+ def associations
10
+ model.reflections.reject { |name, association|
11
+ # Hide these special associations
12
+ name.starts_with?("rich_text") ||
13
+ name.ends_with?("_attachment") ||
14
+ name.ends_with?("_attachments") ||
15
+ name.ends_with?("_blob") ||
16
+ name.ends_with?("_blobs")
17
+ }.keys
18
+ end
19
+
20
+ def attributes
21
+ model.attribute_names + virtual_attributes - redundant_attributes
22
+ end
23
+
24
+ def store_accessors
25
+ model.stored_attributes.values.flatten
26
+ end
27
+
28
+ def virtual_attributes
29
+ virtual = []
30
+
31
+ # has_secure_password columns
32
+ password_attributes = model.attribute_types.keys.select { |k| k.ends_with?("_digest") }.map { |k| k.delete_suffix("_digest") }
33
+ virtual += password_attributes.map { |attr| [attr, "#{attr}_confirmation"] }.flatten
34
+
35
+ # ActiveRecord Store columns
36
+ virtual += store_accessors.map(&:to_s)
37
+
38
+ # Add virtual attributes for ActionText and ActiveStorage
39
+ model.reflections.each do |name, association|
40
+ if name.starts_with?("rich_text")
41
+ virtual << name.split("rich_text_").last
42
+ elsif name.ends_with?("_attachment")
43
+ virtual << name.split("_attachment").first
44
+ elsif name.ends_with?("_attachments")
45
+ virtual << name.split("_attachments").first
46
+ end
47
+ end
48
+
49
+ virtual
50
+ end
51
+
52
+ def redundant_attributes
53
+ redundant = []
54
+
55
+ # has_secure_password columns
56
+ redundant += model.attribute_types.keys.select { |k| k.ends_with?("_digest") }
57
+
58
+ # ActiveRecord Store columns
59
+ store_columns = model.stored_attributes.keys
60
+ redundant += store_columns.map(&:to_s)
61
+
62
+ model.reflections.each do |name, association|
63
+ if association.has_one?
64
+ next
65
+ elsif association.collection?
66
+ next
67
+ elsif association.polymorphic?
68
+ redundant << "#{name}_id"
69
+ redundant << "#{name}_type"
70
+ elsif name.starts_with?("rich_text")
71
+ redundant << name
72
+ else # belongs to
73
+ redundant << "#{name}_id"
74
+ end
75
+ end
76
+
77
+ redundant
78
+ end
79
+ end
80
+ end
@@ -1,3 +1,3 @@
1
1
  module Madmin
2
- VERSION = "1.2.1"
2
+ VERSION = "1.2.5"
3
3
  end
data/lib/madmin.rb CHANGED
@@ -6,6 +6,7 @@ module Madmin
6
6
  autoload :Field, "madmin/field"
7
7
  autoload :GeneratorHelpers, "madmin/generator_helpers"
8
8
  autoload :Resource, "madmin/resource"
9
+ autoload :ResourceBuilder, "madmin/resource_builder"
9
10
  autoload :Search, "madmin/search"
10
11
 
11
12
  module Fields
@@ -17,6 +18,7 @@ module Madmin
17
18
  autoload :DateTime, "madmin/fields/date_time"
18
19
  autoload :Decimal, "madmin/fields/decimal"
19
20
  autoload :Enum, "madmin/fields/enum"
21
+ autoload :File, "madmin/fields/file"
20
22
  autoload :Float, "madmin/fields/float"
21
23
  autoload :HasMany, "madmin/fields/has_many"
22
24
  autoload :HasOne, "madmin/fields/has_one"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: madmin
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Oliver
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-09-09 00:00:00.000000000 Z
12
+ date: 2021-09-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -59,6 +59,7 @@ files:
59
59
  - app/assets/config/manifest.js
60
60
  - app/assets/stylesheets/actiontext.scss
61
61
  - app/assets/stylesheets/application.css
62
+ - app/controllers/madmin/application_controller.rb
62
63
  - app/controllers/madmin/base_controller.rb
63
64
  - app/controllers/madmin/dashboard_controller.rb
64
65
  - app/controllers/madmin/resource_controller.rb
@@ -98,6 +99,9 @@ files:
98
99
  - app/views/madmin/fields/enum/_form.html.erb
99
100
  - app/views/madmin/fields/enum/_index.html.erb
100
101
  - app/views/madmin/fields/enum/_show.html.erb
102
+ - app/views/madmin/fields/file/_form.html.erb
103
+ - app/views/madmin/fields/file/_index.html.erb
104
+ - app/views/madmin/fields/file/_show.html.erb
101
105
  - app/views/madmin/fields/float/_form.html.erb
102
106
  - app/views/madmin/fields/float/_index.html.erb
103
107
  - app/views/madmin/fields/float/_show.html.erb
@@ -167,6 +171,7 @@ files:
167
171
  - lib/madmin/fields/date_time.rb
168
172
  - lib/madmin/fields/decimal.rb
169
173
  - lib/madmin/fields/enum.rb
174
+ - lib/madmin/fields/file.rb
170
175
  - lib/madmin/fields/float.rb
171
176
  - lib/madmin/fields/has_many.rb
172
177
  - lib/madmin/fields/has_one.rb
@@ -182,6 +187,7 @@ files:
182
187
  - lib/madmin/generator_helpers.rb
183
188
  - lib/madmin/namespace.rb
184
189
  - lib/madmin/resource.rb
190
+ - lib/madmin/resource_builder.rb
185
191
  - lib/madmin/search.rb
186
192
  - lib/madmin/version.rb
187
193
  - lib/madmin/view_generator.rb