かんがるーさんの日記

最近自分が興味をもったものを調べた時の手順等を書いています。今は Spring Boot をいじっています。

Spring Boot で書籍の貸出状況確認・貸出申請する Web アプリケーションを作る ( その41 )( 貸出承認画面の作成 )

概要

Spring Boot で書籍の貸出状況確認・貸出申請する Web アプリケーションを作る ( その40 )( 貸出申請画面の作成11 ) の続きです。

  • 貸出承認画面を作成します。5~6回に分けて書きます。
  • 今回の手順で確認できるのは以下の内容です。
    • 貸出承認画面の作成
      • Thymeleaf テンプレートファイルと Controller クラスの雛形の作成

参照したサイト・書籍

  1. Bootstrap3移行ガイド
    http://cccabinet.jpn.org/bootstrap3/

    • 「承認/却下」をボタンで選択できるようにする実装方法を調査した時に参照しました。

目次

  1. はじめに
  2. feature/53-issue ブランチの作成
  3. 貸出申請画面の HTML ファイルの作成
  4. Thymeleaf テンプレートファイルの作成
  5. LendingApprovalController クラスの作成
  6. 動作確認
  7. 次回は。。。

手順

はじめに

承認権限 ( ROLE_APPROVER ) を持つユーザのみが使用できる貸出承認画面を作成します。以下の仕様の想定です。

  • 貸出申請画面から送信されたメールに表示されている URL にアクセスして、パラメータで指定されている貸出申請 ID のデータを表示します。
  • 貸出申請ID、ステータス、貸出申請したユーザ名、及び「申請する」が選択された書籍と申請理由の一覧を表示します。
  • 各書籍毎に「承認」「却下」ボタンを表示します。
  • 却下理由の入力フィールドを表示し、却下する場合には必須入力とします。
  • 画面の下に「確定」ボタンを表示し、表示されている全ての書籍で「承認」「却下」のいずれかを選択した後「確定」ボタンをクリックします。
  • 「確定」ボタンがクリックされたら申請したユーザへメールを送信します。

feature/53-issue ブランチの作成

  1. feature/53-issue ブランチを作成します。

貸出申請画面の HTML ファイルの作成

  1. src/main/resources/static/html の下に lendingapproval.html を作成します。作成後、リンク先の内容 に変更します。

    html には記述していませんが、確定後は修正できないようにします。

    ■確定前 f:id:ksby:20160109011355p:plain

    ■確定後 f:id:ksby:20160109114635p:plain

  2. 一旦 commit します。

Thymeleaf テンプレートファイルの作成

  1. src/main/resources/templates の下に lendingapproval ディレクトリを作成します。

  2. src/main/resources/static/html/lendingapproval.html を src/main/resources/templates/lendingapproval の下にコピーします。

  3. src/main/resources/templates/lendingapproval の下の templates/lendingapp/lendingapproval.html を リンク先の内容 に変更します。

LendingApprovalController クラスの作成

  1. src/main/java/ksbysample/webapp/lending/web の下に lendingapproval パッケージを作成します。

  2. src/main/java/ksbysample/webapp/lending/web/lendingapproval の下に LendingapprovalController.java を作成します。作成後、リンク先の内容 に変更します。

動作確認

  1. Gradle projects View から bootRun タスクを実行して Tomcat を起動します。

  2. ブラウザを起動し http://localhost:8080/lendingapproval へアクセスします。最初はログイン画面が表示されますので ID に "tanaka.taro@sample.com"、Password に "taro" を入力して、「次回から自動的にログインする」をチェックせずに「ログイン」ボタンをクリックします。

    以下の画面が表示されることを確認します。

    f:id:ksby:20160109132111p:plain

  3. 「確定」ボタンをクリックしても同じ画面が表示されることを確認します。

  4. Ctrl+F2 を押して Tomcat を停止します。

  5. 一旦 commit します。

次回は。。。

パラメータで指定されている貸出申請 ID の「申請する」が選択された書籍と申請理由の一覧を DB から取得して表示する処理を実装します。

ソースコード

static/html/lendingapproval.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <title>貸出承認</title>
    <!-- Tell the browser to be responsive to screen width -->
    <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"/>
    <!-- Bootstrap 3.3.4 -->
    <link href="/css/bootstrap.min.css" rel="stylesheet" type="text/css"/>
    <!-- Font Awesome Icons -->
    <link href="/css/font-awesome.min.css" rel="stylesheet" type="text/css"/>
    <!-- Ionicons -->
    <link href="/css/ionicons.min.css" rel="stylesheet" type="text/css"/>
    <!-- Theme style -->
    <link href="/css/AdminLTE.min.css" rel="stylesheet" type="text/css"/>
    <!-- AdminLTE Skins. Choose a skin from the css/skins
         folder instead of downloading all of them to reduce the load. -->
    <link href="/css/skins/_all-skins.min.css" rel="stylesheet" type="text/css"/>

    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
    <script src="/js/html5shiv.min.js"></script>
    <script src="/js/respond.min.js"></script>
    <![endif]-->

    <style>
        .content-wrapper {
            background-color: #fffafa;
        }
        .selected-library {
            color: #ffffff !important;
            font-size: 100%;
            font-weight: 700;
        }
        .box-body.no-padding {
            padding-bottom: 10px !important;
        }
        .table>tbody>tr>td
        , .table>tbody>tr>th
        , .table>tfoot>tr>td
        , .table>tfoot>tr>th
        , .table>thead>tr>td
        , .table>thead>tr>th {
            padding: 5px;
            font-size: 90%;
        }
        .jp-gothic {
            font-family: Verdana, "游ゴシック", YuGothic, "Hiragino Kaku Gothic ProN", Meiryo, sans-serif;
        }
        .btn-approval.active {
            background-color: #00a65a;
        }
        .btn-reject.active {
            background-color: #dd4b39;
        }
    </style>
</head>

<!-- ADD THE CLASS layout-top-nav TO REMOVE THE SIDEBAR. -->
<body class="skin-blue layout-top-nav">
<div class="wrapper">

    <header class="main-header">
        <nav class="navbar navbar-static-top">
            <div class="container">
                <div class="navbar-header">
                    <a href="#" class="navbar-brand"><b>ksbysample-lending</b></a>
                    <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse">
                        <i class="fa fa-bars"></i>
                    </button>
                </div>

                <!-- Collect the nav links, forms, and other content for toggling -->
                <div class="collapse navbar-collapse pull-left" id="navbar-collapse">
                    <ul class="nav navbar-nav">
                        <li class="dropdown">
                            <a href="#" class="dropdown-toggle" data-toggle="dropdown">メニュー <span class="caret"></span></a>
                            <ul class="dropdown-menu" role="menu">
                                <li><a href="#">Action</a></li>
                                <li><a href="#">Another action</a></li>
                                <li><a href="#">Something else here</a></li>
                                <li class="divider"></li>
                                <li><a href="#">Separated link</a></li>
                                <li class="divider"></li>
                                <li><a href="#">One more separated link</a></li>
                            </ul>
                        </li>
                    </ul>
                </div>
                <!-- /.navbar-collapse -->

                <!-- Navbar Right Menu -->
                <div class="navbar-custom-menu">
                    <p class="navbar-text selected-library">選択中:テスト図書館</p>
                    <ul class="nav navbar-nav">
                        <li><a href="#">ログアウト</a></li>
                    </ul>
                </div>
                <!-- /.navbar-custom-menu -->
            </div>
            <!-- /.container-fluid -->
        </nav>
    </header>

    <!-- Full Width Column -->
    <div class="content-wrapper">
        <div class="container">
            <!-- Content Header (Page header) -->
            <section class="content-header">
                <h1>貸出承認</h1>
            </section>

            <!-- Main content -->
            <section class="content">
                <div class="row">
                    <div class="col-xs-12">
                        <div class="box">
                            <div class="box-body no-padding">
                                <div class="col-xs-6 no-padding">
                                    <table class="table table-bordered">
                                        <colgroup>
                                            <col width="30%"/>
                                            <col width="70%"/>
                                        </colgroup>
                                        <tr>
                                            <th class="bg-purple">貸出申請ID</th>
                                            <th>1</th>
                                        </tr>
                                        <tr>
                                            <th class="bg-purple">ステータス</th>
                                            <th>申請中</th>
                                        </tr>
                                        <tr>
                                            <th class="bg-purple">申請者</th>
                                            <th>田中 太郎</th>
                                        </tr>
                                    </table>
                                </div>
                                <br/>

                                <form id="lendingappForm" method="post" action="">
                                    <table class="table">
                                        <colgroup>
                                            <col width="5%"/>
                                            <col width="15%"/>
                                            <col width="15%"/>
                                            <col width="20%"/>
                                            <col width="20%"/>
                                            <col width="25%"/>
                                        </colgroup>
                                        <thead class="bg-purple">
                                        <tr>
                                            <th>No.</th>
                                            <th>ISBN</th>
                                            <th>書名</th>
                                            <th>申請理由</th>
                                            <th>承認/却下</th>
                                            <th>却下理由</th>
                                        </tr>
                                        </thead>
                                        <tbody class="jp-gothic">
                                        <tr>
                                            <th>1</th>
                                            <th>978-4-7741-6366-6</th>
                                            <th>GitHub実践入門</th>
                                            <th>開発で使用する為</th>
                                            <th>
                                                <div class="btn-group-sm" data-toggle="buttons">
                                                    <label class="btn btn-default btn-approval"><input type="radio" name="approval" value="1" /> 承認</label>
                                                    <label class="btn btn-default btn-reject"><input type="radio" name="approval" value="2" /> 却下</label>
                                                </div>
                                            </th>
                                            <th>
                                                <input type="text" name="reason" class="form-control input-sm" value=""/>
                                            </th>
                                        </tr>
                                        <tr>
                                            <th>2</th>
                                            <th>978-4-7741-5380-3</th>
                                            <th>Spring3入門</th>
                                            <th>開発で使用する為</th>
                                            <th>
                                                <div class="btn-group-sm" data-toggle="buttons">
                                                    <label class="btn btn-default btn-approval"><input type="radio" name="approval" value="1" /> 承認</label>
                                                    <label class="btn btn-default btn-reject"><input type="radio" name="approval" value="2" /> 却下</label>
                                                </div>
                                            </th>
                                            <th>
                                                <input type="text" name="reason" class="form-control input-sm" value=""/>
                                            </th>
                                        </tr>
                                        <tr>
                                            <th>3</th>
                                            <th>978-4-87311-718-8</th>
                                            <th>Javaパフォーマンス</th>
                                            <th>勉強会の為</th>
                                            <th>
                                                <div class="btn-group-sm" data-toggle="buttons">
                                                    <label class="btn btn-default btn-approval"><input type="radio" name="approval" value="1" /> 承認</label>
                                                    <label class="btn btn-default btn-reject"><input type="radio" name="approval" value="2" /> 却下</label>
                                                </div>
                                            </th>
                                            <th>
                                                <input type="text" name="reason" class="form-control input-sm" value=""/>
                                            </th>
                                        </tr>
                                        </tbody>
                                    </table>
                                    <div class="text-center">
                                        <button class="btn bg-blue"><i class="fa fa-check-square-o"></i> 確定</button>
                                    </div>
                                </form>
                            </div>
                        </div>
                    </div>
                </div>
            </section>
            <!-- /.content -->
        </div>
        <!-- /.container -->
    </div>

</div>
<!-- ./wrapper -->

<!-- jQuery 2.1.4 -->
<script src="/js/jQuery-2.1.4.min.js" type="text/javascript"></script>
<!-- Bootstrap 3.3.2 JS -->
<script src="/js/bootstrap.min.js" type="text/javascript"></script>
<!-- AdminLTE App -->
<script src="/js/app.min.js" type="text/javascript"></script>
</body>
</html>

templates/lendingapp/lendingapproval.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <title>貸出承認</title>
    <!-- Tell the browser to be responsive to screen width -->
    <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"/>
    <link th:replace="common/head-cssjs"/>

    <style>
        .content-wrapper {
            background-color: #fffafa;
        }
        .selected-library {
            color: #ffffff !important;
            font-size: 100%;
            font-weight: 700;
        }
        .box-body.no-padding {
            padding-bottom: 10px !important;
        }
        .table>tbody>tr>td
        , .table>tbody>tr>th
        , .table>tfoot>tr>td
        , .table>tfoot>tr>th
        , .table>thead>tr>td
        , .table>thead>tr>th {
            padding: 5px;
            font-size: 90%;
        }
        .jp-gothic {
            font-family: Verdana, "游ゴシック", YuGothic, "Hiragino Kaku Gothic ProN", Meiryo, sans-serif;
        }
        .btn-approval.active {
            background-color: #00a65a;
        }
        .btn-reject.active {
            background-color: #dd4b39;
        }
    </style>
</head>

<!-- ADD THE CLASS layout-top-nav TO REMOVE THE SIDEBAR. -->
<body class="skin-blue layout-top-nav">
<div class="wrapper">

    <!-- Main Header -->
    <div th:replace="common/mainparts :: main-header"></div>

    <!-- Full Width Column -->
    <div class="content-wrapper">
        <div class="container">
            <!-- Content Header (Page header) -->
            <section class="content-header">
                <h1>貸出承認</h1>
            </section>

            <!-- Main content -->
            <section class="content">
                <div class="row">
                    <div class="col-xs-12">
                        <div class="box">
                            <div class="box-body no-padding">
                                <div class="col-xs-6 no-padding">
                                    <table class="table table-bordered">
                                        <colgroup>
                                            <col width="30%"/>
                                            <col width="70%"/>
                                        </colgroup>
                                        <tr>
                                            <th class="bg-purple">貸出申請ID</th>
                                            <th>1</th>
                                        </tr>
                                        <tr>
                                            <th class="bg-purple">ステータス</th>
                                            <th>申請中</th>
                                        </tr>
                                        <tr>
                                            <th class="bg-purple">申請者</th>
                                            <th>田中 太郎</th>
                                        </tr>
                                    </table>
                                </div>
                                <br/>

                                <form id="lendingapprovalForm" method="post" action="/lendingapproval/complete"
                                      th:action="@{/lendingapproval/complete}" th:object="${lendingapprovalForm}">
                                    <table class="table">
                                        <colgroup>
                                            <col width="5%"/>
                                            <col width="15%"/>
                                            <col width="15%"/>
                                            <col width="20%"/>
                                            <col width="20%"/>
                                            <col width="25%"/>
                                        </colgroup>
                                        <thead class="bg-purple">
                                        <tr>
                                            <th>No.</th>
                                            <th>ISBN</th>
                                            <th>書名</th>
                                            <th>申請理由</th>
                                            <th>承認/却下</th>
                                            <th>却下理由</th>
                                        </tr>
                                        </thead>
                                        <tbody class="jp-gothic">
                                        <tr>
                                            <th>1</th>
                                            <th>978-4-7741-6366-6</th>
                                            <th>GitHub実践入門</th>
                                            <th>開発で使用する為</th>
                                            <th>
                                                <div class="btn-group-sm" data-toggle="buttons">
                                                    <label class="btn btn-default btn-approval"><input type="radio" name="approval" value="1" /> 承認</label>
                                                    <label class="btn btn-default btn-reject"><input type="radio" name="approval" value="2" /> 却下</label>
                                                </div>
                                            </th>
                                            <th>
                                                <input type="text" name="reason" class="form-control input-sm" value=""/>
                                            </th>
                                        </tr>
                                        <tr>
                                            <th>2</th>
                                            <th>978-4-7741-5380-3</th>
                                            <th>Spring3入門</th>
                                            <th>開発で使用する為</th>
                                            <th>
                                                <div class="btn-group-sm" data-toggle="buttons">
                                                    <label class="btn btn-default btn-approval"><input type="radio" name="approval" value="1" /> 承認</label>
                                                    <label class="btn btn-default btn-reject"><input type="radio" name="approval" value="2" /> 却下</label>
                                                </div>
                                            </th>
                                            <th>
                                                <input type="text" name="reason" class="form-control input-sm" value=""/>
                                            </th>
                                        </tr>
                                        <tr>
                                            <th>3</th>
                                            <th>978-4-87311-718-8</th>
                                            <th>Javaパフォーマンス</th>
                                            <th>勉強会の為</th>
                                            <th>
                                                <div class="btn-group-sm" data-toggle="buttons">
                                                    <label class="btn btn-default btn-approval"><input type="radio" name="approval" value="1" /> 承認</label>
                                                    <label class="btn btn-default btn-reject"><input type="radio" name="approval" value="2" /> 却下</label>
                                                </div>
                                            </th>
                                            <th>
                                                <input type="text" name="reason" class="form-control input-sm" value=""/>
                                            </th>
                                        </tr>
                                        </tbody>
                                    </table>
                                    <div class="text-center">
                                        <button class="btn bg-blue js-btn-complete"><i class="fa fa-check-square-o"></i> 確定</button>
                                    </div>
                                </form>
                            </div>
                        </div>
                    </div>
                </div>
            </section>
            <!-- /.content -->
        </div>
        <!-- /.container -->
    </div>

</div>
<!-- ./wrapper -->

<script th:replace="common/bottom-js"></script>
<script type="text/javascript">
    <!--
    $(document).ready(function() {
        $(".js-btn-complete").click(function(){
            $("#lendingapprovalForm").submit();
            return false;
        });
    });
    -->
</script>
</body>
</html>
  • <html><html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> へ変更します。
  • <!-- Bootstrap 3.3.4 --> ... <script src="/js/respond.min.js"></script><![endif]--><link th:replace="common/head-cssjs"/> へ変更します。
  • <header class="main-header"> ... </header><div th:replace="common/mainparts :: main-header"></div> へ変更します。
  • <form id="lendingappForm" method="post" action=""><form id="lendingapprovalForm" method="post" action="/lendingapproval/complete" th:action="@{/lendingapproval/complete}" th:object="${lendingapprovalForm}"> へ変更します。
  • <button class="btn bg-blue">... 確定</button><button class="btn bg-blue js-btn-complete">... 確定</button> へ変更します。
  • <!-- jQuery 2.1.4 --> ... <script src="/js/app.min.js" type="text/javascript"></script><script th:replace="common/bottom-js"></script> へ変更します。
  • </body> の前に <script type="text/javascript"> ... </script> を追加します。

LendingapprovalController.java

package ksbysample.webapp.lending.web.lendingapproval;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/lendingapproval")
public class LendingapprovalController {

    @RequestMapping
    public String index() {
        return "lendingapproval/lendingapproval";        
    }

    @RequestMapping(value = "/complete", method = RequestMethod.POST)
    public String complete() {
        return "lendingapproval/lendingapproval";
    }                        

}

履歴

2016/01/09
初版発行。