Skip to content

Commit

Permalink
Add menu configuration to resources
Browse files Browse the repository at this point in the history
  • Loading branch information
excid3 committed Oct 30, 2024
1 parent 26df7b2 commit a590bc4
Show file tree
Hide file tree
Showing 11 changed files with 170 additions and 50 deletions.
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,32 @@
- Remove Tailwind CDN
- Add styles through asset pipeline
- Refactor JavaScript into an Import map (separate from the Rails app)
- Include Rails route helpers in Madmin controllers and views for better integration with the main app
- Add `menu` to resources to allow customizing navigation sort order and add headers for grouping

```ruby
# config/initializers/madmin.rb

# Add a Payments header at the first position in the menu
Madmin.menu.add label: "Payments", position: 0
```

```ruby
class SubscriptionResource < Madmin::Resource
# Add Subscriptions under the Payments header
menu parent: "Payments"
end
```

- `member_action` now yields the record to the block

```ruby
class UserResource < Madmin::Resource
member_action do |user|
button_to "Impersonate", impersonate_user_path(user)
end
end
```

### 1.2.10

Expand Down
21 changes: 21 additions & 0 deletions app/assets/stylesheets/madmin/sidebar.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,25 @@ main {
position: fixed;
width: var(--sidebar-width);

h1 {
margin-top: 0;

a {
color: var(--text-color);
text-decoration: none;

&:hover {
text-decoration: underline;
}
}
}

nav {
h4 {
margin-top: 0.5rem;
margin-bottom: 0.25rem;
}

a {
border-radius: .375rem;
color: var(--text-color);
Expand All @@ -23,6 +41,9 @@ main {
padding: 0.5rem;
text-decoration: none;

margin-top: 0.1rem;
margin-bottom: 0.1rem;

&:hover {
background-color: rgb(243 244 246);
}
Expand Down
17 changes: 5 additions & 12 deletions app/controllers/madmin/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,11 @@ class ApplicationController < Madmin::BaseController
def authenticate_admin_user
# TODO: Add your authentication logic here

# For example, we could redirect if the user isn't an admin
# redirect_to "/", alert: "Not authorized." unless user_signed_in? && current_user.admin?
end

# Authenticate with Clearance
# include Clearance::Controller
# before_action :require_login
# For example, with Rails 8 authentication
# redirect_to "/", alert: "Not authorized." unless authenticated? && Current.user.admin?

# Authenticate with Devise
# before_action :authenticate_user!

# Authenticate with Basic Auth
# http_basic_authenticate_with(name: Rails.application.credentials.admin_username, password: Rails.application.credentials.admin_password)
# Or with Devise
# redirect_to "/", alert: "Not authorized." unless current_user&.admin?
end
end
end
5 changes: 0 additions & 5 deletions app/views/madmin/application/_menu_resources.html.erb

This file was deleted.

17 changes: 14 additions & 3 deletions app/views/madmin/application/_navigation.html.erb
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
<h1><%= Madmin.site_name %></h1>
<h1><%= link_to_if respond_to?(:root_url), Madmin.site_name, root_url, data: {turbo: false} %></h1>

<nav>
<%= link_to "← Back to App", main_app.root_url, data: { turbo: false } if main_app.respond_to?(:root_url) %>
<%= render "menu_resources" %>
<%= nav_link_to "Dashboard", madmin_root_path %>

<% Madmin.menu.render do |item| %>
<% if item.url %>
<%= nav_link_to item.label, item.url, starts_with: item.url %>
<% else %>
<h4><%= item.label %></h4>
<% end %>

<% item.items.each do |item| %>
<%= nav_link_to item.label, item.url, starts_with: item.url %>
<% end %>
<% end %>
</nav>

<footer>
Expand Down
5 changes: 1 addition & 4 deletions lib/generators/madmin/field/templates/_form.html.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
<div class="block md:inline-block md:w-32 flex-shrink-0 text-gray-700">
<%= render "madmin/shared/label", form: form, field: field %>
</div>
<%= form.text_field field.attribute_name, class: "flex-grow form-input" %>
<%= form.text_field field.attribute_name, class: "form-input" %>
17 changes: 5 additions & 12 deletions lib/generators/madmin/install/templates/controller.rb.tt
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,11 @@ module Madmin
def authenticate_admin_user
# TODO: Add your authentication logic here

# For example, we could redirect if the user isn't an admin
# redirect_to "/", alert: "Not authorized." unless user_signed_in? && current_user.admin?
end

# Authenticate with Clearance
# include Clearance::Controller
# before_action :require_login
# For example, with Rails 8 authentication
# redirect_to "/", alert: "Not authorized." unless authenticated? && Current.user.admin?

# Authenticate with Devise
# before_action :authenticate_user!

# Authenticate with Basic Auth
# http_basic_authenticate_with(name: Rails.application.credentials.admin_username, password: Rails.application.credentials.admin_password)
# Or with Devise
# redirect_to "/", alert: "Not authorized." unless current_user&.admin?
end
end
end
22 changes: 12 additions & 10 deletions lib/generators/madmin/resource/templates/resource.rb.tt
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,19 @@ class <%= class_name %>Resource < Madmin::Resource
attribute :<%= association_name %>
<% end -%>

# Uncomment this to customize the display name of records in the admin area.
# def self.display_name(record)
# record.name
# end
# Add scopes to easily filter records
# scope :published

# Uncomment this to customize the default sort column and direction.
# def self.default_sort_column
# "created_at"
# Add actions to the resource's show page
# member_action do |record|
# link_to "Do Something", some_path
# end

# Customize the display name of records in the admin area.
# def self.display_name(record) = record.name

# Customize the default sort column and direction.
# def self.default_sort_column = "created_at"
#
# def self.default_sort_direction
# "desc"
# end
# def self.default_sort_direction = "desc"
end
7 changes: 5 additions & 2 deletions lib/madmin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
module Madmin
autoload :Field, "madmin/field"
autoload :GeneratorHelpers, "madmin/generator_helpers"
autoload :Menu, "madmin/menu"
autoload :Resource, "madmin/resource"
autoload :ResourceBuilder, "madmin/resource_builder"
autoload :Search, "madmin/search"
Expand Down Expand Up @@ -35,8 +36,9 @@ module Fields
autoload :Time, "madmin/fields/time"
end

mattr_accessor :site_name
mattr_accessor :importmap, default: Importmap::Map.new
mattr_accessor :menu, default: Menu.new
mattr_accessor :site_name

class << self
def resource_for(object)
Expand All @@ -61,11 +63,12 @@ def resource_by_name(name)
end

def resources
@resources ||= resource_names.map(&:constantize).sort_by(&:nav_position)
@resources ||= resource_names.map(&:constantize)
end

def reset_resources!
@resources = nil
menu.reset
end

def resource_names
Expand Down
70 changes: 70 additions & 0 deletions lib/madmin/menu.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
module Madmin
class Menu
def initialize
@children = {}
end

def reset
@children = {}
end

def before_render(&block)
if block_given?
@before_render = block
else
@before_render
end
end

def render(&block)
instance_eval(&@before_render) if @before_render

# Ensure all the resources have been added to the menu
Madmin.resources.each do |resource|
next if resource.menu_options == false
add resource.menu_options
end

items.each(&block)
end

module Node
def add(options)
options = options.dup

if (parent = options.delete(:parent))
@children[parent] ||= Item.new(label: parent)
@children[parent].add options
else
item = Item.new(**options)
@children[item.label] = item
end
end

def items
@children.values.sort do |a, b|
result = a.position <=> b.position
result = a.label <=> b.label if result == 0 # sort alphabetically for the same position
result
end
end
end

include Node

class Item
include Node

attr_reader :label, :url, :position, :parent, :children

def initialize(label:, url: nil, position: 99, parent: nil, **options)
@label = label
@url = url
@position = position
@parent = parent
@if = options.delete(:if)
@children = {}
end
end
end
end
13 changes: 11 additions & 2 deletions lib/madmin/resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ class Resource
class_attribute :attributes, default: ActiveSupport::OrderedHash.new
class_attribute :member_actions, default: []
class_attribute :scopes, default: []
class_attribute :nav_position, default: 999
class_attribute :show_in_nav, default: true
class_attribute :menu_options, instance_reader: false

class << self
def inherited(base)
Expand Down Expand Up @@ -257,6 +256,16 @@ def model_store_accessors
store_accessors = model.stored_attributes.values
store_accessors.flatten
end

def menu(options)
@menu_options = options
end

def menu_options
return false if @menu_options == false
@menu_options ||= {}
@menu_options.with_defaults(label: friendly_name.pluralize, url: index_path)
end
end
end
end

0 comments on commit a590bc4

Please sign in to comment.