madmin 1.2.10 → 2.0.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 +4 -4
- data/app/assets/config/madmin_manifest.js +3 -0
- data/app/assets/stylesheets/madmin/actiontext.css +31 -0
- data/app/assets/stylesheets/madmin/application.css +88 -0
- data/app/assets/stylesheets/madmin/buttons.css +46 -0
- data/app/assets/stylesheets/madmin/forms.css +82 -0
- data/app/assets/stylesheets/madmin/pagination.css +59 -0
- data/app/assets/stylesheets/madmin/reset.css +242 -0
- data/app/assets/stylesheets/madmin/sidebar.css +80 -0
- data/app/assets/stylesheets/madmin/tables.css +56 -0
- data/app/controllers/madmin/application_controller.rb +7 -12
- data/app/controllers/madmin/base_controller.rb +1 -0
- data/app/helpers/madmin/application_helper.rb +1 -12
- data/app/helpers/madmin/sort_helper.rb +17 -1
- data/app/javascript/madmin/application.js +4 -0
- data/app/javascript/madmin/controllers/application.js +12 -0
- data/app/javascript/madmin/controllers/index.js +5 -0
- data/app/javascript/madmin/controllers/nested_form_controller.js +34 -0
- data/app/javascript/madmin/controllers/select_controller.js +32 -0
- data/app/views/layouts/madmin/application.html.erb +11 -13
- data/app/views/madmin/application/_form.html.erb +13 -12
- data/app/views/madmin/application/_javascript.html.erb +3 -136
- data/app/views/madmin/application/_navigation.html.erb +22 -27
- data/app/views/madmin/application/edit.html.erb +9 -5
- data/app/views/madmin/application/index.html.erb +37 -31
- data/app/views/madmin/application/new.html.erb +9 -5
- data/app/views/madmin/application/show.html.erb +28 -22
- data/app/views/madmin/dashboard/show.html.erb +4 -1
- data/app/views/madmin/fields/attachment/_form.html.erb +11 -4
- data/app/views/madmin/fields/attachment/_index.html.erb +5 -1
- data/app/views/madmin/fields/attachment/_show.html.erb +4 -4
- data/app/views/madmin/fields/attachments/_form.html.erb +1 -4
- data/app/views/madmin/fields/belongs_to/_form.html.erb +1 -4
- data/app/views/madmin/fields/belongs_to/_index.html.erb +2 -1
- data/app/views/madmin/fields/boolean/_form.html.erb +3 -4
- data/app/views/madmin/fields/currency/_form.html.erb +1 -0
- data/app/views/madmin/fields/currency/_index.html.erb +1 -0
- data/app/views/madmin/fields/currency/_show.html.erb +1 -0
- data/app/views/madmin/fields/date/_form.html.erb +1 -4
- data/app/views/madmin/fields/date_time/_form.html.erb +1 -4
- data/app/views/madmin/fields/decimal/_form.html.erb +0 -3
- data/app/views/madmin/fields/enum/_form.html.erb +1 -4
- data/app/views/madmin/fields/file/_form.html.erb +0 -3
- data/app/views/madmin/fields/float/_form.html.erb +0 -3
- data/app/views/madmin/fields/has_many/_form.html.erb +1 -4
- data/app/views/madmin/fields/has_one/_form.html.erb +0 -3
- data/app/views/madmin/fields/integer/_form.html.erb +0 -3
- data/app/views/madmin/fields/integer/_index.html.erb +1 -5
- data/app/views/madmin/fields/json/_form.html.erb +0 -3
- data/app/views/madmin/fields/nested_has_many/_fields.html.erb +4 -5
- data/app/views/madmin/fields/nested_has_many/_form.html.erb +0 -4
- data/app/views/madmin/fields/password/_form.html.erb +0 -3
- data/app/views/madmin/fields/polymorphic/_form.html.erb +1 -4
- data/app/views/madmin/fields/rich_text/_form.html.erb +1 -6
- data/app/views/madmin/fields/select/_form.html.erb +1 -0
- data/app/views/madmin/fields/select/_index.html.erb +1 -0
- data/app/views/madmin/fields/select/_show.html.erb +1 -0
- data/app/views/madmin/fields/string/_form.html.erb +1 -4
- data/app/views/madmin/fields/text/_form.html.erb +0 -3
- data/app/views/madmin/shared/_label.html.erb +2 -2
- data/config/importmap.rb +10 -0
- data/lib/generators/madmin/field/templates/_form.html.erb +0 -3
- data/lib/generators/madmin/install/templates/controller.rb.tt +5 -12
- data/lib/generators/madmin/resource/templates/resource.rb.tt +12 -10
- data/lib/madmin/engine.rb +20 -0
- data/lib/madmin/field.rb +17 -5
- data/lib/madmin/fields/belongs_to.rb +10 -5
- data/lib/madmin/fields/currency.rb +15 -0
- data/lib/madmin/fields/polymorphic.rb +1 -1
- data/lib/madmin/fields/select.rb +9 -0
- data/lib/madmin/menu.rb +70 -0
- data/lib/madmin/resource.rb +56 -24
- data/lib/madmin/search.rb +1 -1
- data/lib/madmin/version.rb +1 -1
- data/lib/madmin.rb +22 -1
- metadata +61 -13
- data/app/assets/config/manifest.js +0 -2
- data/app/assets/stylesheets/actiontext.scss +0 -36
- data/app/assets/stylesheets/application.css +0 -15
- data/app/views/madmin/application/_menu_resources.html.erb +0 -7
@@ -1,32 +1,38 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
<%= content_for :title, resource.display_name(@record) %>
|
2
|
+
|
3
|
+
<header class="header">
|
4
|
+
<h1>
|
5
|
+
<%= link_to resource.friendly_name.pluralize, resource.index_path %>
|
4
6
|
/
|
5
|
-
<%=
|
7
|
+
<%= resource.display_name(@record) %>
|
6
8
|
</h1>
|
7
9
|
|
8
|
-
<div class="
|
10
|
+
<div class="actions">
|
9
11
|
<% resource.member_actions.each do |action| %>
|
10
|
-
<%=
|
12
|
+
<%= instance_exec(@record, &action) %>
|
11
13
|
<% end %>
|
12
|
-
<%= link_to "Edit", resource.edit_path(@record), class: "
|
13
|
-
<%= button_to "Delete", resource.show_path(@record), method: :delete, data: { turbo_confirm: "Are you sure?" }, class: "
|
14
|
+
<%= link_to "Edit", resource.edit_path(@record), class: "btn btn-secondary" %>
|
15
|
+
<%= button_to "Delete", resource.show_path(@record), method: :delete, data: { turbo_confirm: "Are you sure?" }, class: "btn btn-danger" %>
|
14
16
|
</div>
|
15
|
-
</
|
17
|
+
</header>
|
16
18
|
|
17
|
-
<div class="
|
18
|
-
|
19
|
-
|
20
|
-
<%
|
19
|
+
<div class="table-scroll">
|
20
|
+
<table>
|
21
|
+
<tbody>
|
22
|
+
<% resource.attributes.values.each do |attribute| %>
|
23
|
+
<% next if attribute.field.nil? %>
|
24
|
+
<% next unless attribute.field.visible?(action_name) %>
|
21
25
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
+
<tr>
|
27
|
+
<th class="label">
|
28
|
+
<%= attribute.field.options.label || attribute.name.to_s.titleize %>
|
29
|
+
</th>
|
26
30
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
31
|
+
<td>
|
32
|
+
<%= render partial: attribute.field.to_partial_path("show"), locals: { field: attribute.field, record: @record, resource: resource } %>
|
33
|
+
</td>
|
34
|
+
</tr>
|
35
|
+
<% end %>
|
36
|
+
</tbody>
|
37
|
+
</table>
|
32
38
|
</div>
|
@@ -1,4 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
<%= form.file_field field.to_param, class: "form-input"%>
|
2
|
+
|
3
|
+
<% if form.object.persisted? %>
|
4
|
+
<div class="mt-2">
|
5
|
+
<%= render partial: field.to_partial_path("show"), locals: {field: field, record: record} %>
|
6
|
+
|
7
|
+
<% if (value = field.value(record) && value&.attached?) %>
|
8
|
+
<%= link_to "Remove", Madmin.resource_for(value).show_path(value), data: { turbo_method: :delete, turbo_confirm: "Are you sure? You will lose any other changes."} %>
|
9
|
+
<% end %>
|
10
|
+
</div>
|
11
|
+
<% end %>
|
@@ -1,3 +1,7 @@
|
|
1
1
|
<% if (attachment = field.value(record)) && attachment.attached? %>
|
2
|
-
|
2
|
+
<% if attachment.variable? %>
|
3
|
+
<%= image_tag main_app.url_for(attachment), class: "max-h-8" %>
|
4
|
+
<% else %>
|
5
|
+
<%= attachment.filename %>
|
6
|
+
<% end %>
|
3
7
|
<% end %>
|
@@ -1,9 +1,9 @@
|
|
1
1
|
<% if (attachment = field.value(record)) && attachment.attached? %>
|
2
2
|
<% if attachment.variable? %>
|
3
|
-
<%=
|
4
|
-
<%= image_tag main_app.url_for(attachment), class: "max-h-32" %>
|
5
|
-
<% end %>
|
3
|
+
<%= image_tag main_app.url_for(attachment), class: "max-h-32" %>
|
6
4
|
<% else %>
|
7
5
|
<%= link_to attachment.filename, main_app.url_for(attachment), target: :_blank, class: "text-blue-500 underline" %>
|
8
6
|
<% end %>
|
9
|
-
|
7
|
+
|
8
|
+
<%= link_to "Remove", Madmin.resource_for(attachment).show_path(attachment), data: { turbo_method: :delete, turbo_confirm: "Are you sure? You will lose any other changes."} %>
|
9
|
+
<% end %>
|
@@ -1,4 +1 @@
|
|
1
|
-
|
2
|
-
<%= render "madmin/shared/label", form: form, field: field %>
|
3
|
-
</div>
|
4
|
-
<%= form.file_field field.attribute_name, multiple: true %>
|
1
|
+
<%= form.file_field field.attribute_name, multiple: true, class: "form-input" %>
|
@@ -1,4 +1 @@
|
|
1
|
-
|
2
|
-
<%= render "madmin/shared/label", form: form, field: field %>
|
3
|
-
</div>
|
4
|
-
<%= form.select field.to_param, field.options_for_select(record), { prompt: true }, { class: "form-select", data: { controller: "select", select_url_value: field.index_path } } %>
|
1
|
+
<%= form.select field.to_param, field.options_for_select(record), { prompt: true }, { data: { controller: "select", select_url_value: field.index_path } } %>
|
@@ -1,3 +1,4 @@
|
|
1
1
|
<% if (object = field.value(record)) %>
|
2
|
-
|
2
|
+
<% object_resource = Madmin.resource_for(object) %>
|
3
|
+
<%= link_to object_resource.display_name(object), object_resource.show_path(object) %>
|
3
4
|
<% end %>
|
@@ -1,4 +1,3 @@
|
|
1
|
-
<div class="
|
2
|
-
<%=
|
3
|
-
</div>
|
4
|
-
<%= form.check_box field.attribute_name, class: "form-input" %>
|
1
|
+
<div class="form-input">
|
2
|
+
<%= form.check_box field.attribute_name %>
|
3
|
+
</div>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= form.number_field field.attribute_name, class: "form-input" %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= number_to_currency field.value(record) if field.value(record) %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= number_to_currency field.value(record) if field.value(record) %>
|
@@ -1,4 +1 @@
|
|
1
|
-
|
2
|
-
<%= render "madmin/shared/label", form: form, field: field %>
|
3
|
-
</div>
|
4
|
-
<%= form.text_field field.attribute_name, { class: "form-select", data: { controller: "flatpickr" } } %>
|
1
|
+
<%= form.date_field field.attribute_name, class: "form-input" %>
|
@@ -1,4 +1 @@
|
|
1
|
-
|
2
|
-
<%= render "madmin/shared/label", form: form, field: field %>
|
3
|
-
</div>
|
4
|
-
<%= form.text_field field.attribute_name, data: { controller: "flatpickr", flatpickr_enable_time: true } %>
|
1
|
+
<%= form.datetime_field field.attribute_name, class: "form-input" %>
|
@@ -1,4 +1 @@
|
|
1
|
-
|
2
|
-
<%= render "madmin/shared/label", form: form, field: field %>
|
3
|
-
</div>
|
4
|
-
<%= form.select field.attribute_name, field.options_for_select(record), { prompt: true }, { class: "form-select", data: { controller: "select" } } %>
|
1
|
+
<%= form.select field.attribute_name, field.options_for_select(record), { prompt: true }, { data: { controller: "select" } } %>
|
@@ -1,4 +1 @@
|
|
1
|
-
|
2
|
-
<%= render "madmin/shared/label", form: form, field: field %>
|
3
|
-
</div>
|
4
|
-
<%= form.select "#{field.attribute_name.to_s.singularize}_ids", field.options_for_select(record), { prompt: true }, { multiple: true, class: "form-select", data: { controller: "select", select_url_value: field.index_path } } %>
|
1
|
+
<%= form.select "#{field.attribute_name.to_s.singularize}_ids", field.options_for_select(record), { prompt: true }, { multiple: true, data: { controller: "select", select_url_value: field.index_path } } %>
|
@@ -1,5 +1 @@
|
|
1
|
-
|
2
|
-
<%= link_to field.value(record), resource.show_path(record), class: "text-blue-500 underline" %>
|
3
|
-
<% else %>
|
4
|
-
<%= field.value(record) %>
|
5
|
-
<% end %>
|
1
|
+
<%= link_to_if field.attribute_name.to_s == resource.model.primary_key, field.value(record), resource.show_path(record) %>
|
@@ -1,10 +1,9 @@
|
|
1
1
|
<%= content_tag :div, class: "nested-fields border border-gray-200 rounded-lg p-5", data: { new_record: f.object.new_record? } do %>
|
2
2
|
<% field.nested_attributes.each do |name, nested_attribute| %>
|
3
|
-
<%
|
4
|
-
<% next
|
5
|
-
<% next unless
|
6
|
-
|
7
|
-
<% nested_field = nested_attribute[:field] %>
|
3
|
+
<% nested_field = nested_attribute.field %>
|
4
|
+
<% next if nested_field.nil? %>
|
5
|
+
<% next unless nested_field.visible?(action_name) %>
|
6
|
+
<% next unless nested_field.visible?(:form) %>
|
8
7
|
|
9
8
|
<div class="mb-4 flex">
|
10
9
|
<%= render partial: nested_field.to_partial_path("form"), locals: { field: nested_field, record: f.object, form: f, resource: field.resource } %>
|
@@ -1,7 +1,4 @@
|
|
1
1
|
<%= form.fields_for field.attribute_name do |pf| %>
|
2
|
-
|
3
|
-
<%= render "madmin/shared/label", form: pf, field: field %>
|
4
|
-
</div>
|
5
|
-
<%= pf.select :value, field.options_for_select(record).map(&:to_global_id), { selected: field.value(record)&.to_global_id, prompt: true }, { class: "form-select", data: { controller: "slimselect" } } %>
|
2
|
+
<%= pf.select :value, field.options_for_select(record).map(&:to_global_id), { selected: field.value(record)&.to_global_id, prompt: true }, { data: { controller: "select" } } %>
|
6
3
|
<%= pf.hidden_field :type, value: "polymorphic" %>
|
7
4
|
<% end %>
|
@@ -1,6 +1 @@
|
|
1
|
-
|
2
|
-
<%= render "madmin/shared/label", form: form, field: field %>
|
3
|
-
</div>
|
4
|
-
<div class="flex-1">
|
5
|
-
<%= form.rich_text_area field.attribute_name, class: "form-input block" %>
|
6
|
-
</div>
|
1
|
+
<%= form.rich_text_area field.attribute_name, class: "form-input" %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= form.select field.attribute_name, field.options_for_select(record), { prompt: true }, { data: { controller: "select" } } %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= field.value(record) %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= field.value(record) %>
|
@@ -1,4 +1 @@
|
|
1
|
-
|
2
|
-
<%= render "madmin/shared/label", form: form, field: field %>
|
3
|
-
</div>
|
4
|
-
<%= form.text_field field.attribute_name, class: "form-input" %>
|
1
|
+
<%= form.text_field field.attribute_name, class: "form-input", placeholder: field.options.placeholder %>
|
data/config/importmap.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
pin "application", to: "madmin/application.js", preload: true
|
2
|
+
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
|
3
|
+
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
|
4
|
+
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
|
5
|
+
pin "trix"
|
6
|
+
pin "@rails/actiontext", to: "actiontext.esm.js"
|
7
|
+
pin_all_from Madmin::Engine.root.join("app/javascript/madmin/controllers"), under: "controllers", to: "madmin/controllers"
|
8
|
+
|
9
|
+
pin "tom-select", to: "https://ga.jspm.io/npm:tom-select@2.4.1/dist/js/tom-select.complete.js"
|
10
|
+
pin "tailwindcss-stimulus-components", to: "https://ga.jspm.io/npm:tailwindcss-stimulus-components@6.1.2/dist/tailwindcss-stimulus-components.module.js"
|
@@ -5,18 +5,11 @@ module Madmin
|
|
5
5
|
def authenticate_admin_user
|
6
6
|
# TODO: Add your authentication logic here
|
7
7
|
|
8
|
-
# For example,
|
9
|
-
# redirect_to "/", alert: "Not authorized." unless
|
10
|
-
end
|
11
|
-
|
12
|
-
# Authenticate with Clearance
|
13
|
-
# include Clearance::Controller
|
14
|
-
# before_action :require_login
|
8
|
+
# For example, with Rails 8 authentication
|
9
|
+
# redirect_to "/", alert: "Not authorized." unless authenticated? && Current.user.admin?
|
15
10
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
# Authenticate with Basic Auth
|
20
|
-
# http_basic_authenticate_with(name: Rails.application.credentials.admin_username, password: Rails.application.credentials.admin_password)
|
11
|
+
# Or with Devise
|
12
|
+
# redirect_to "/", alert: "Not authorized." unless current_user&.admin?
|
13
|
+
end
|
21
14
|
end
|
22
15
|
end
|
@@ -9,17 +9,19 @@ class <%= class_name %>Resource < Madmin::Resource
|
|
9
9
|
attribute :<%= association_name %>
|
10
10
|
<% end -%>
|
11
11
|
|
12
|
-
#
|
13
|
-
#
|
14
|
-
# record.name
|
15
|
-
# end
|
12
|
+
# Add scopes to easily filter records
|
13
|
+
# scope :published
|
16
14
|
|
17
|
-
#
|
18
|
-
#
|
19
|
-
# "
|
15
|
+
# Add actions to the resource's show page
|
16
|
+
# member_action do |record|
|
17
|
+
# link_to "Do Something", some_path
|
20
18
|
# end
|
19
|
+
|
20
|
+
# Customize the display name of records in the admin area.
|
21
|
+
# def self.display_name(record) = record.name
|
22
|
+
|
23
|
+
# Customize the default sort column and direction.
|
24
|
+
# def self.default_sort_column = "created_at"
|
21
25
|
#
|
22
|
-
# def self.default_sort_direction
|
23
|
-
# "desc"
|
24
|
-
# end
|
26
|
+
# def self.default_sort_direction = "desc"
|
25
27
|
end
|
data/lib/madmin/engine.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require "importmap-rails"
|
2
|
+
|
1
3
|
module Madmin
|
2
4
|
class Engine < ::Rails::Engine
|
3
5
|
isolate_namespace Madmin
|
@@ -9,6 +11,24 @@ module Madmin
|
|
9
11
|
|
10
12
|
config.to_prepare do
|
11
13
|
Madmin.reset_resources!
|
14
|
+
Madmin.site_name ||= Rails.application.class.module_parent_name
|
15
|
+
end
|
16
|
+
|
17
|
+
initializer "madmin.assets" do |app|
|
18
|
+
if app.config.respond_to?(:assets)
|
19
|
+
app.config.assets.paths << root.join("app/assets/stylesheets")
|
20
|
+
app.config.assets.paths << root.join("app/javascript")
|
21
|
+
app.config.assets.precompile += %w[madmin_manifest]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
initializer "madmin.importmap", before: "importmap" do |app|
|
26
|
+
Madmin.importmap.draw root.join("config/importmap.rb")
|
27
|
+
Madmin.importmap.cache_sweeper watches: root.join("app/javascript")
|
28
|
+
|
29
|
+
ActiveSupport.on_load(:action_controller_base) do
|
30
|
+
before_action { Madmin.importmap.cache_sweeper.execute_if_updated }
|
31
|
+
end
|
12
32
|
end
|
13
33
|
end
|
14
34
|
end
|
data/lib/madmin/field.rb
CHANGED
@@ -6,8 +6,8 @@ module Madmin
|
|
6
6
|
to_s.split("::").last.underscore
|
7
7
|
end
|
8
8
|
|
9
|
-
def initialize(attribute_name:, model:, resource:,
|
10
|
-
@attribute_name = attribute_name
|
9
|
+
def initialize(attribute_name:, model:, resource:, options:)
|
10
|
+
@attribute_name = attribute_name.to_sym
|
11
11
|
@model = model
|
12
12
|
@resource = resource
|
13
13
|
@options = options
|
@@ -18,7 +18,7 @@ module Madmin
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def to_partial_path(name)
|
21
|
-
unless %w[index show form].include? name
|
21
|
+
unless %w[index show form].include? name.to_s
|
22
22
|
raise ArgumentError, "`partial` must be 'index', 'show', or 'form'"
|
23
23
|
end
|
24
24
|
|
@@ -30,8 +30,20 @@ module Madmin
|
|
30
30
|
end
|
31
31
|
|
32
32
|
# Used for checking visibility of attribute on an view
|
33
|
-
def visible?(action
|
34
|
-
|
33
|
+
def visible?(action)
|
34
|
+
action = action.to_sym
|
35
|
+
options.fetch(action) do
|
36
|
+
case action
|
37
|
+
when :index
|
38
|
+
default_index_attributes.include?(attribute_name)
|
39
|
+
else
|
40
|
+
true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def default_index_attributes
|
46
|
+
[model.primary_key.to_sym, :avatar, :title, :name, :user, :created_at]
|
35
47
|
end
|
36
48
|
|
37
49
|
def required?
|
@@ -2,12 +2,13 @@ module Madmin
|
|
2
2
|
module Fields
|
3
3
|
class BelongsTo < Field
|
4
4
|
def options_for_select(record)
|
5
|
-
if (record = record.send(attribute_name))
|
6
|
-
|
7
|
-
[[resource.display_name(record), record.id]]
|
5
|
+
records = if (record = record.send(attribute_name))
|
6
|
+
[record]
|
8
7
|
else
|
9
|
-
|
8
|
+
associated_resource.model.first(25)
|
10
9
|
end
|
10
|
+
|
11
|
+
records.map { [Madmin.resource_for(_1).display_name(_1), _1.id] }
|
11
12
|
end
|
12
13
|
|
13
14
|
def to_param
|
@@ -15,7 +16,11 @@ module Madmin
|
|
15
16
|
end
|
16
17
|
|
17
18
|
def index_path
|
18
|
-
|
19
|
+
associated_resource.index_path(format: :json)
|
20
|
+
end
|
21
|
+
|
22
|
+
def associated_resource
|
23
|
+
Madmin.resource_by_name(model.reflect_on_association(attribute_name).klass)
|
19
24
|
end
|
20
25
|
end
|
21
26
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Madmin
|
2
|
+
module Fields
|
3
|
+
class Currency < Field
|
4
|
+
def value(record)
|
5
|
+
value = record.public_send(attribute_name)
|
6
|
+
value /= 100.0 if value && options.minor_units
|
7
|
+
value
|
8
|
+
end
|
9
|
+
|
10
|
+
def searchable?
|
11
|
+
options.fetch(:searchable, model.column_names.include?(attribute_name.to_s))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/madmin/menu.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
module Madmin
|
2
|
+
class Menu
|
3
|
+
def initialize
|
4
|
+
@children = {}
|
5
|
+
end
|
6
|
+
|
7
|
+
def reset
|
8
|
+
@children = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def before_render(&block)
|
12
|
+
if block_given?
|
13
|
+
@before_render = block
|
14
|
+
else
|
15
|
+
@before_render
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def render(&block)
|
20
|
+
instance_eval(&@before_render) if @before_render
|
21
|
+
|
22
|
+
# Ensure all the resources have been added to the menu
|
23
|
+
Madmin.resources.each do |resource|
|
24
|
+
next if resource.menu_options == false
|
25
|
+
add resource.menu_options
|
26
|
+
end
|
27
|
+
|
28
|
+
items.each(&block)
|
29
|
+
end
|
30
|
+
|
31
|
+
module Node
|
32
|
+
def add(options)
|
33
|
+
options = options.dup
|
34
|
+
|
35
|
+
if (parent = options.delete(:parent))
|
36
|
+
@children[parent] ||= Item.new(label: parent)
|
37
|
+
@children[parent].add options
|
38
|
+
else
|
39
|
+
item = Item.new(**options)
|
40
|
+
@children[item.label] = item
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def items
|
45
|
+
@children.values.sort do |a, b|
|
46
|
+
result = a.position <=> b.position
|
47
|
+
result = a.label <=> b.label if result == 0 # sort alphabetically for the same position
|
48
|
+
result
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
include Node
|
54
|
+
|
55
|
+
class Item
|
56
|
+
include Node
|
57
|
+
|
58
|
+
attr_reader :label, :url, :position, :parent, :children
|
59
|
+
|
60
|
+
def initialize(label:, url: nil, position: 99, parent: nil, **options)
|
61
|
+
@label = label
|
62
|
+
@url = url
|
63
|
+
@position = position
|
64
|
+
@parent = parent
|
65
|
+
@if = options.delete(:if)
|
66
|
+
@children = {}
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|