madmin 1.2.11 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 +1 -4
- data/app/views/madmin/fields/enum/_form.html.erb +1 -4
- data/app/views/madmin/fields/file/_form.html.erb +1 -4
- data/app/views/madmin/fields/float/_form.html.erb +1 -4
- 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 +1 -4
- data/app/views/madmin/fields/integer/_index.html.erb +1 -5
- data/app/views/madmin/fields/json/_form.html.erb +1 -4
- 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 +1 -4
- 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 +1 -4
- 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 +1 -4
- 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.number_field field.attribute_name, step: :any, class: "flex-grow form-input" %>
|
1
|
+
<%= form.number_field field.attribute_name, step: :any, 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.file_field field.attribute_name, class: "flex-grow form-input" %>
|
1
|
+
<%= form.file_field field.attribute_name, class: "form-input" %>
|
@@ -1,4 +1 @@
|
|
1
|
-
|
2
|
-
<%= render "madmin/shared/label", form: form, field: field %>
|
3
|
-
</div>
|
4
|
-
<%= form.number_field field.attribute_name, step: :any, class: "flex-grow form-input" %>
|
1
|
+
<%= form.number_field field.attribute_name, step: :any, class: "form-input" %>
|
@@ -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,4 +1 @@
|
|
1
|
-
|
2
|
-
<%= render "madmin/shared/label", form: form, field: field %>
|
3
|
-
</div>
|
4
|
-
<%= form.number_field field.attribute_name, class: "flex-grow form-input" %>
|
1
|
+
<%= form.number_field field.attribute_name, class: "form-input" %>
|
@@ -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,4 +1 @@
|
|
1
|
-
|
2
|
-
<%= render "madmin/shared/label", form: form, field: field %>
|
3
|
-
</div>
|
4
|
-
<%= form.text_area field.attribute_name, class: "flex-grow form-input" %>
|
1
|
+
<%= form.text_area field.attribute_name, class: "form-input" %>
|
@@ -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,4 +1 @@
|
|
1
|
-
|
2
|
-
<%= render "madmin/shared/label", form: form, field: field %>
|
3
|
-
</div>
|
4
|
-
<%= form.password_field field.attribute_name, class: "flex-grow form-input" %>
|
1
|
+
<%= form.password_field field.attribute_name, class: "form-input" %>
|
@@ -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: "flex-grow 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: "flex-grow form-input" %>
|
1
|
+
<%= form.text_field field.attribute_name, class: "form-input", placeholder: field.options.placeholder %>
|
@@ -1,4 +1 @@
|
|
1
|
-
|
2
|
-
<%= render "madmin/shared/label", form: form, field: field %>
|
3
|
-
</div>
|
4
|
-
<%= form.text_area field.attribute_name, class: "flex-grow form-input" %>
|
1
|
+
<%= form.text_area field.attribute_name, class: "form-input" %>
|
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"
|
@@ -1,4 +1 @@
|
|
1
|
-
|
2
|
-
<%= render "madmin/shared/label", form: form, field: field %>
|
3
|
-
</div>
|
4
|
-
<%= form.text_field field.attribute_name, class: "flex-grow form-input" %>
|
1
|
+
<%= form.text_field field.attribute_name, class: "form-input" %>
|
@@ -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
|