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 &copy; 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(管理画面)'になります。

完成した画面

・管理画面へのログイン画面 f:id:study-output:20210427222942p:plain

・管理画面のトップページ f:id:study-output:20210427222956p:plain