Skip to content

Commit

Permalink
Make sidebar navigation collapsible
Browse files Browse the repository at this point in the history
Closes #3198
  • Loading branch information
mshibuya committed Aug 12, 2022
1 parent 33e9214 commit e8cb8ed
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 23 deletions.
25 changes: 20 additions & 5 deletions app/helpers/rails_admin/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def main_navigation

label = navigation_label || t('admin.misc.navigation')

%(<li class='dropdown-header'>#{label}</li>#{li_stack}) if li_stack.present?
collapsible_stack(label, 'main', li_stack)
end.join.html_safe
end

Expand All @@ -101,18 +101,17 @@ def root_navigation
end.join.html_safe
label ||= t('admin.misc.root_navigation')

%(<li class='dropdown-header'>#{label}</li>#{li_stack}) if li_stack.present?
collapsible_stack(label, 'action', li_stack)
end.join.html_safe
end

def static_navigation
li_stack = RailsAdmin::Config.navigation_static_links.collect do |title, url|
content_tag(:li, link_to(title.to_s, url, target: '_blank', rel: 'noopener noreferrer', class: 'nav-link'))
end.join
end.join.html_safe

label = RailsAdmin::Config.navigation_static_label || t('admin.misc.navigation_static_label')
li_stack = %(<li class='dropdown-header'>#{label}</li>#{li_stack}).html_safe if li_stack.present?
li_stack
collapsible_stack(label, 'static', li_stack) || ''
end

def navigation(parent_groups, nodes, level = 0)
Expand Down Expand Up @@ -232,5 +231,21 @@ def edit_user_link_label
def gravatar_url(email)
"https://secure.gravatar.com/avatar/#{Digest::MD5.hexdigest email}?s=30"
end

def collapsible_stack(label, class_prefix, li_stack)
return nil unless li_stack.present?

collapse_classname = "#{class_prefix}-#{Digest::MD5.hexdigest(label)[0..7]}"
content_tag(:li, class: 'mb-1') do
content_tag(:button, 'aria-expanded': true, class: 'btn btn-toggle align-items-center rounded', data: {bs_toggle: "collapse", bs_target: ".sidebar .#{collapse_classname}"}) do
content_tag(:i, '', class: 'fas fa-chevron-down') + html_escape(' ' + label)
end +
content_tag(:div, class: "collapse show #{collapse_classname}") do
content_tag(:ul, class: 'btn-toggle-nav list-unstyled fw-normal pb-1') do
li_stack
end
end
end
end
end
end
2 changes: 1 addition & 1 deletion app/views/layouts/rails_admin/_sidebar_navigation.html.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<ul class="col-sm-3 col-md-2 btn-toggle-nav list-unstyled bg-light">
<ul class="sidebar col-sm-3 col-md-2 btn-toggle-nav list-unstyled bg-light">
<%= main_navigation %>
<%= root_navigation %>
<%= static_navigation %>
Expand Down
14 changes: 7 additions & 7 deletions spec/helpers/rails_admin/application_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@
RailsAdmin.config do |config|
config.included_models = [Ball, Comment]
end
expect(helper.main_navigation).to match(/(dropdown-header).*(Navigation).*(Balls).*(Comments)/m)
expect(helper.main_navigation).to match(/(btn-toggle).*(Navigation).*(Balls).*(Comments)/m)
end

it 'does not draw empty navigation labels' do
Expand All @@ -263,8 +263,8 @@
label_plural 'Confirmed'
end
end
expect(helper.main_navigation).to match(/(dropdown-header).*(Navigation).*(Balls).*(Commentz).*(Confirmed)/m)
expect(helper.main_navigation).not_to match(/(dropdown-header).*(Navigation).*(Balls).*(Commentz).*(Confirmed).*(Comment)/m)
expect(helper.main_navigation).to match(/(btn-toggle).*(Navigation).*(Balls).*(Commentz).*(Confirmed)/m)
expect(helper.main_navigation).not_to match(/(btn-toggle).*(Navigation).*(Balls).*(Commentz).*(Confirmed).*(Comment)/m)
end

it 'does not show unvisible models' do
Expand All @@ -275,7 +275,7 @@
end
end
result = helper.main_navigation
expect(result).to match(/(dropdown-header).*(Navigation).*(Balls)/m)
expect(result).to match(/(btn-toggle).*(Navigation).*(Balls)/m)
expect(result).not_to match('Comments')
end

Expand All @@ -286,14 +286,14 @@
hide
end
end
expect(helper.main_navigation).to match(/(dropdown-header).*(Navigation).*(Hardballs)/m)
expect(helper.main_navigation).to match(/(btn-toggle).*(Navigation).*(Hardballs)/m)
end

it 'shows children of excluded models' do
RailsAdmin.config do |config|
config.included_models = [Hardball]
end
expect(helper.main_navigation).to match(/(dropdown-header).*(Navigation).*(Hardballs)/m)
expect(helper.main_navigation).to match(/(btn-toggle).*(Navigation).*(Hardballs)/m)
end

it 'nests in navigation label' do
Expand All @@ -303,7 +303,7 @@
navigation_label 'commentable'
end
end
expect(helper.main_navigation).to match(/(dropdown-header).*(commentable).*(Comments)/m)
expect(helper.main_navigation).to match(/(btn-toggle).*(commentable).*(Comments)/m)
end

it 'nests in parent model' do
Expand Down
21 changes: 21 additions & 0 deletions spec/integration/rails_admin_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,27 @@
end
end

describe 'sidebar navigation', js: true do
it 'is collapsible' do
visit dashboard_path
is_expected.to have_css('.sidebar .nav-link', text: 'Players')
click_button 'Navigation'
is_expected.to have_css('.sidebar .btn-toggle.collapsed')
is_expected.not_to have_css('.sidebar #navigation.show')
is_expected.not_to have_css('.sidebar .nav-link', text: 'Players')
end

it 'persists over a page transition' do
visit dashboard_path
click_button 'Navigation'
is_expected.to have_css('.sidebar .btn-toggle.collapsed')
is_expected.not_to have_css('.sidebar #navigation.show')
find('.player_links .show a').trigger('click')
is_expected.to have_content 'List of Players'
is_expected.not_to have_css('.sidebar .nav-link', text: 'Players')
end
end

describe '_current_user' do # https://github.com/railsadminteam/rails_admin/issues/549
it 'is accessible from the list view' do
RailsAdmin.config Player do
Expand Down
18 changes: 11 additions & 7 deletions src/rails_admin/styles/base/theming.scss
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,22 @@ body.rails_admin {
}

/* Sidebar navigation */
.btn-toggle-nav {
.sidebar.btn-toggle-nav {
padding: 0;

.dropdown-header {
padding: calc($grid-gutter-width / 2) calc($grid-gutter-width / 2) 3px;
.btn-toggle {
margin-top: calc(#{$grid-gutter-width} / 2);
padding: 3px calc(#{$grid-gutter-width} / 2);
font-weight: bold;
color: $gray-600;
}

.btn-toggle[aria-expanded="true"] {
color: $gray-700;
text-transform: uppercase;
}

> li > a {
padding: calc($navbar-padding-y / 2) calc($grid-gutter-width / 2);
.btn-toggle-nav > li > a {
padding: calc(#{$navbar-padding-y} / 2) calc(#{$grid-gutter-width} / 2);

&.active {
background-color: map-get($theme-colors, primary);
Expand Down Expand Up @@ -320,7 +324,7 @@ body.rails_admin {

@media screen and (min-width: map-get($grid-breakpoints, "sm")) {
body.rails_admin {
.btn-toggle-nav {
.sidebar.btn-toggle-nav {
position: fixed;
top: $nav-link-height + $navbar-padding-y * 2;
bottom: 0;
Expand Down
26 changes: 23 additions & 3 deletions src/rails_admin/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,30 @@ import I18n from "./i18n";

$(document)
.on("turbo:click", function () {
return $("#loading").show();
$("#loading").show();
})
.on("turbo:before-render", function () {
return $("#loading").hide();
.on("turbo:before-render", function (event) {
document
.querySelectorAll('.sidebar .btn-toggle[aria-expanded="false"]')
.forEach((element) => {
const newButton = event.detail.newBody.querySelector(
`.sidebar [data-bs-target="${element.dataset.bsTarget}"]`
);
const newMenu = event.detail.newBody.querySelector(
element.dataset.bsTarget
);
if (newButton) {
newButton.parentNode.replaceChild(
element.cloneNode(true),
newButton
);
}
if (newMenu) {
newMenu.classList.remove("show");
}
});

$("#loading").hide();
});

$(document).on("click", "[data-bs-target]", function () {
Expand Down

0 comments on commit e8cb8ed

Please sign in to comment.