AdminLTEを導入して管理画面を作る
はじめに
AdminLTEを導入して管理画面を作る方法について
AdminLTEの導入方法
まずはyarnを使ってAdminLTEをインストールします。
$ yarn add admin-lte
バージョンを指定する場合
$ yarn add admin-lte@^3.0
これでadminlteの3系がインストールされます。
インストールされると、railsアプリ直下に'node_moduls'と'package_json'が作成されます。
'package_json'ではadminlteのバージョンが確認できます。
また、node_moduls/admin-lte配下には、ビューで使うデフォルトのテンプレートが作成されます。
管理画面用のマニフェストファイルを作成
一般のページと管理画面のページで見た目が大きく異なるため、管理画面用の'js'と'css'のマニフェストファイルを作成します。
//= require jquery3 //= require jquery_ujs //= require admin-lte/plugins/jquery/jquery.min.js //= require admin-lte/plugins/bootstrap/js/bootstrap.bundle.min.js //= require admin-lte/dist/js/adminlte.min.js
@import 'admin-lte/plugins/fontawesome-free/css/all.min.css'; @import 'admin-lte/plugins/icheck-bootstrap/icheck-bootstrap.min.css'; @import 'admin-lte/dist/css/adminlte.min.css'; @import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700&display=fallback);
この時、'require = tree .'で一括読み込みしていた場合は、一般ページと管理画面で'js'や'scss'が異なるので、この記載を削除して個別に読み込むようにします。
管理画面用のマニフェストファイルの読み込み
application以外のマニフェストファイルを個別にインストールする場合、パスとプリコンパイルの設定をしないと読み込めません。
Rails.application.config.assets.paths << Rails.root.join('node_modules') #この記述がなかったら追加 Rails.application.config.assets.precompile += %w[admin.js admin.css] #コメントアウトされているので外す
管理画面のコントローラを作成
コントローラは、管理がしやすいように'admin'ディレクトリ配下にまとめて作成していきます。
まずはベースとなるコントローラを作成します。
$ rails g controller admin::base
これで、controllers配下にadminディレクトリが作成され、その下にbase_controller.rbが作成されます。
このファイルは一般ページのapplicationコントローラと同じ役割で使用します。
このファイルにベースとなる処理を書いていきます。
class Admin::BaseController < ApplicationController before_action :check_admin layout 'admin/layouts/admin' private def check_admin redirect_to root_path, danger: t('権限がありません') unless current_user.admin? end def not_authenticated flash[:warning] = t('ログインしてください') redirect_to admin_login_path end end
ここで'layout'メソッドを使って、レイアウトを指定しています。
指定している'admin/layouts/admin'は、一般ページのapplication.html.erbと同じ役割です。
続いて、トップページと管理画面へのログインページの部分のコントローラを作成します。
$ rails g controller admin::dashboards $ rails g controller admin::user_sessions
class Admin::DashboardsController < Admin::BaseController def index; end end
class Admin::UserSessionsController < Admin::BaseController skip_before_action :check_admin, only: %i[new create] skip_before_action :require_login, only: %i[new create] layout 'admin/layouts/admin_login' def new; end def create @user = login(params[:email], params[:password]) if @user redirect_to admin_root_path, success: 'ログインしました。' else flash.now[:danger] = 'ログインできませんでした。' render :new end end def destroy logout redirect_to admin_login_path, success: 'ログアウトしました。' end end
2つとも先程作成したadmin/base_controller.rbを継承するように修正します。
また、ログイン画面でもレイアウトを分けたいので明示的にレイアウトを指定します。
ルーティングを作成
管理画面に関するルーティングは、adminというnamespaceを使って作成します。
namespace :admin do root 'dashboards#index' get 'login', to: 'user_sessions#new' post 'login', to: 'user_sessions#create' delete 'logout', to: 'user_sessions#destroy' # resources :users, only: %i[index show edit update destroy] # resources :boards, onyl: %i[index show edit update destroy] end
これでURLの前に'admin'がつくようになります。
root_path → /admin
login_path → /admin/login
こんな感じです。
ビューを作成
ログイン画面のビューとログインした後の管理画面のビューを作ります。
コードについては、node_modules/admin-lteディレクトリ配下にデフォルトのテンプレートがあるので、それをコピーし少し修正して使います。
ログイン画面のビューは、node_modules/admin-lte/pages/example/login.html、
ログイン後の管理画面のビューは、node_modules/admin-lte/starter.htmlを使います。
・ログイン画面のビュー
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title><%= page_title(yield(:title), admin=true) %></title> <%= csrf_meta_tags %> <%= stylesheet_link_tag 'admin', media: 'all' %> <%= javascript_include_tag 'admin' %> </head> <body class="hold-transition login-page"> <div class="login-box"> <%= render 'shared/flash_message' %> <%= yield %> </div> <!-- /.login-box --> </body> </html>
<%= content_for(:title, t('.title')) %> <div class="login-logo"> <h1><%= t('.title') %></h1> </div> <!-- /.login-logo --> <div class="card"> <div class="card-body login-card-body"> <%= form_with url: admin_login_path, local: true do |f| %> <div class="form-group" %> <%= f.label :email, User.human_attribute_name(:email)%> <%= f.email_field :email, class: 'form-control' %> </div> <div class="form-group" %> <%= f.label :password, User.human_attribute_name(:password) %> <%= f.password_field :password, class: 'form-control' %> </div> <div class='actions'> <%= f.submit t('.title'), class: 'btn btn-primary' %> </div> <% end %> </div> <!-- /.login-card-body --> </div>
・ログイン後の管理画面のビュー
<!DOCTYPE html> <!-- This is a starter template page. Use this page to start your new project from scratch. This page gets rid of all links and provides the needed markup only. --> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title><%= page_title(yield(:title), admin= true) %></title> <%= csrf_meta_tags %> <%= stylesheet_link_tag 'admin', media: 'all' %> <%= javascript_include_tag 'admin' %> </head> <body class="hold-transition sidebar-mini"> <div class="wrapper"> <%= render 'admin/shared/header' %> <%= render 'admin/shared/sidebar' %> <!-- Content Wrapper. Contains page content --> <div class="content-wrapper"> <%= render 'shared/flash_message' %> <%= yield %> </div> <!-- /.content-wrapper --> <!-- Main Footer --> <%= render 'admin/shared/footer' %> </div> <!-- ./wrapper --> </body> </html>
<!-- Navbar --> <nav class="main-header navbar navbar-expand navbar-white navbar-light"> <!-- Left navbar links --> <ul class="navbar-nav"> <li class="nav-item"> <a class="nav-link" data-widget="pushmenu" href="#"><i class="fas fa-bars"></i></a> </li> </ul> <!-- Right navbar links --> <ul class="navbar-nav ml-auto"> <li class="nav-item"> <%= link_to t('defaults.logout'), admin_logout_path, class: 'nav-link', method: :delete %> </li> </ul> </nav> <!-- /.navbar -->
<!-- Main Sidebar Container --> <aside class="main-sidebar sidebar-dark-primary elevation-4"> <!-- Brand Logo --> <a href="index3.html" class="brand-link"> <%= image_tag 'AdminLTELogo.png', class: 'brand-image img-circle elevation-3' %> <span class="brand-text font-weight-light">AdminLTE 3</span> </a> <!-- Sidebar --> <div class="sidebar"> <!-- Sidebar user panel (optional) --> <div class="user-panel mt-3 pb-3 mb-3 d-flex"> <div class="image"> <%= image_tag current_user.avator_url, class: 'img-circle elevation-2' %> </div> <div class="info"> <a href="#" class="d-block"><%= current_user.decorate.full_name %></a> </div> </div> <!-- Sidebar Menu --> <nav class="mt-2"> <ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false"> <li class="nav-item"> <%= link_to admin_boards_path, class:"nav-link #{active?("admin/boards")}" do %> <i class="nav-icon far fa-file"></i> <p> 掲示板一覧 </p> <% end %> </li> <li class="nav-item"> <%= link_to admin_users_path, class:"nav-link #{active?("admin/users")}" do %> <i class="nav-icon far fa-user"></i> <p> ユーザー一覧 </p> <% end %> </li> </ul> </nav> <!-- /.sidebar-menu --> </div> <!-- /.sidebar --> </aside>
<footer class="main-footer"> <strong>Copyright © 2021</strong> All rights reserved. </footer>
<%= content_for(:title, t('.title'))%> <div class="container"> <div class="row"> ダッシュボードです </div> </div>
タイトルの設定
module ApplicationHelper def page_title(page_title = '', admin = false) base_title = if admin 'BOARD APP(管理画面)' else 'BOARD APP' end page_title.empty? ? base_title : page_title + ' | ' + base_title end end
このヘルパーは一般ページでも利用しているヘルパーです。
なので、第2引数にはデフォルトで'admin = false'を指定し、一般ページから呼び出す時は第2引数は指定しません。
管理画面ページから呼び出す時は、第2引数を'true'にして呼び出します。
こうすることで、一般ページから呼び出す時はタイトルが'BOARD APP'になり、管理画面ページから呼び出す時は'BOARD APP(管理画面)'になります。
完成した画面
・管理画面へのログイン画面
・管理画面のトップページ