💭 기존 코멘트는 관리자, 마이페이지, 콘텐츠 영역에 모두 들어가기 때문에
폴더 구조상 review 패키지를 따로 빼는 게 낫지 않나 생각했는데
관리자 기능의 review, 마이페이지 기능의 review... 와 같이 진행되기 때문에
각각의 패키지(admin, member 등) 안에 넣기로 함!
💻 adminCommentView는 변화 없음
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>관리자 코멘트 관리</title>
<link href="resources/css/adminCommentView.css" rel="stylesheet">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
<!--
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://bootswatch.com/5/lux/bootstrap.css">
-->
</head>
<body>
<!-- 전체 영역 -->
<div class="wrap">
<!-- 플로팅 버튼 영역 -->
<jsp:include page="../common/floatingButton.jsp" />
<!-- 헤더 영역 -->
<jsp:include page="../common/header.jsp" />
<!-- 컨텐츠 영역 (개별 구현 구역) -->
<div id="content_container">
<table id="admin_profile">
<tr>
<td width="220"><img src="resources/image/user/profile/admin.png" width="170" height="170"></td>
<td width="380" style="font-size:50px; font-weight:900; color:white;">관리자</td>
</tr>
</table>
<!-- !!! 본인이 맡은 탭 div에 id="selected_tab" 붙어녛기 !!!-->
<div id="admin_mypage_navi">
<div><a href="admin_list.me">회원 관리</a></div>
<div><a href="">콘텐츠 관리</a></div>
<div id="selected_tab"><a href="commentList.ad">코멘트 관리</a></div>
<div><a href="">이용권 관리</a></div>
<div><a href="">신고 관리</a></div>
<div><a href="admin_stat.st">통계 관리</a></div>
</div>
<!-- 이곳부터 본인 화면 구현 -->
<div id="commentManagementArea">
<br><br>
<div id="selectCommentInfo">
<form action="searchComment.ad" method="get">
<select id="selectCommentMenu" name="condition">
<option value="userId" name="userId">이메일</option>
<option value="userNickname" name="userNickname">닉네임</option>
<option value="contentsTitle" name="contentsTitle">콘텐츠명</option>
</select>
<input type="text" id="inputUserMail" name="keyword" value="${ keyword }" placeholder="검색할 유저의 정보를 입력하세요">
<button type="submit" id="selectButton">검색</button>
</form>
</div>
<!-- 검색어 유지를 위해 추가 -->
<c:if test="${ not empty condition }">
<script>
$(function() {
$("#selectCommentInfo option[value=${ condition }]").attr("selected", true);
});
</script>
</c:if>
<br><br>
<div id="commentListAll">
<br>
<c:choose>
<c:when test="${ not empty list }">
<table id="commentTable">
<thead>
<tr id="comment_head" class="line">
<th class="comment_head1" width="5%">선택</th>
<th class="comment_head1" width="15%;">유저 이메일</th>
<th class="comment_head1" width="10%;">유저 닉네임</th>
<th class="comment_head1" width="20%;">콘텐츠명</th>
<th class="comment_head1" width="10%;">별점</th>
<th class="comment_head1" width="40%">코멘트 내용</th>
</tr>
</thead>
<tbody>
<c:forEach var="r" items="${ list }">
<tr class="personalComment">
<td><input type="checkbox" name="selectContent" id="selectContent"><label for="selectContent"></label></td>
<td id="userMail">${ r.userId }</td>
<td id="userNickname">${ r.userNickname }</td>
<td id="ContentName">
<c:choose>
<c:when test="${ not empty r.movieTitle }">
${ r.movieTitle }
</c:when>
<c:otherwise>
${ r.tvName }
</c:otherwise>
</c:choose>
</td>
<td id="reviewStar">★ ${ r.reviewStar }</td>
<td id="review_content">${ r.reviewContent }</td>
</tr>
</c:forEach>
<tr><th colspan="6" style="text-align: right;"><button type="button" class="btn btn-danger">삭제</button></th></tr>
</tbody>
</table>
<br><br>
<div id="pagingArea">
<c:choose>
<c:when test="${ pi.currentPage eq 1 }">
<button type="button" onclick="location.href='#';" disabled>«</button>
</c:when>
<c:otherwise>
<button type="button" onclick="location.href='commentList.ad?cpage=${ pi.currentPage - 1}';">«</button>
</c:otherwise>
</c:choose>
<c:forEach var="p" begin="${ pi.startPage }" end="${ pi.endPage }" step="1">
<button type="button" onclick="location.href='commentList.ad?cpage=${ p }';">${ p }</button>
</c:forEach>
<c:choose>
<c:when test="${ pi.currentPage eq pi.maxPage }">
<button type="button" onclick="location.href='#';" disabled>»</button>
</c:when>
<c:otherwise>
<button type="button" onclick="location.href='commentList.ad?cpage=${ pi.currentPage + 1}';">${ p }</button>
</c:otherwise>
</c:choose>
</div>
</c:when>
<c:when test="${ not empty searchList }">
<table id="commentTable">
<thead>
<tr id="comment_head" class="line">
<th class="comment_head1" width="5%">선택</th>
<th class="comment_head1" width="15%;">유저 이메일</th>
<th class="comment_head1" width="10%;">유저 닉네임</th>
<th class="comment_head1" width="20%;">콘텐츠명</th>
<th class="comment_head1" width="10%;">별점</th>
<th class="comment_head1" width="40%">코멘트 내용</th>
</tr>
</thead>
<tbody>
<c:forEach var="r" items="${ searchList }">
<tr class="personalComment">
<td><input type="checkbox" name="selectContent" id="selectContent"><label for="selectContent"></label></td>
<td id="userMail">${ r.userId }</td>
<td id="userNickname">${ r.userNickname }</td>
<td id="ContentName">
<c:choose>
<c:when test="${ not empty r.movieTitle }">
${ r.movieTitle }
</c:when>
<c:otherwise>
${ r.tvName }
</c:otherwise>
</c:choose>
</td>
<td id="reviewStar">★ ${ r.reviewStar }</td>
<td id="review_content">${ r.reviewContent }</td>
</tr>
</c:forEach>
<tr><th colspan="6" style="text-align: right;"><button type="button" class="btn btn-danger">삭제</button></th></tr>
</tbody>
</table>
<br><br>
<div id="pagingArea">
<c:choose>
<c:when test="${ pi.currentPage eq 1 }">
<button type="button" onclick="location.href='#';" disabled>«</button>
</c:when>
<c:otherwise>
<button type="button" onclick="location.href='commentList.ad?cpage=${ pi.currentPage - 1}';">«</button>
</c:otherwise>
</c:choose>
<c:forEach var="p" begin="${ pi.startPage }" end="${ pi.endPage }" step="1">
<button type="button" onclick="location.href='commentList.ad?cpage=${ p }';">${ p }</button>
</c:forEach>
<c:choose>
<c:when test="${ pi.currentPage eq pi.maxPage }">
<button type="button" onclick="location.href='#';" disabled>»</button>
</c:when>
<c:otherwise>
<button type="button" onclick="location.href='commentList.ad?cpage=${ pi.currentPage + 1}';">${ p }</button>
</c:otherwise>
</c:choose>
</div>
</c:when>
<c:otherwise>
조회된 코멘트가 없습니다.
</c:otherwise>
</c:choose>
</div> <!-- commentListAll 영역 끝 -->
</div> <!-- 본인 구현 영역 끝 -->
</div> <!-- 컨텐츠 영역 끝 -->
<!-- 푸터 영역 -->
<jsp:include page="../common/footer.jsp" />
</div> <!-- 전체 영역 끝 -->
</body>
</html>
❌ ReviewController
👉🏻 ⭕️ AdminController
package com.urfavoriteott.ufo.admin.controller;
import java.util.ArrayList;
import java.util.HashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.urfavoriteott.ufo.admin.model.service.AdminService;
import com.urfavoriteott.ufo.common.model.vo.PageInfo;
import com.urfavoriteott.ufo.common.template.Pagination;
import com.urfavoriteott.ufo.contents.model.vo.Review;
@Controller
public class AdminController {
@Autowired
private AdminService adminService;
/**
* 관리자 페이지 코멘트 관리에서 사용할 페이징 바, 기본 접속 시 전체 코멘트 조회 - 작성자 : 수빈
* @param currentPage
* @param model
* @return
*/
@RequestMapping(value="commentList.ad")
public String selectAdminCommentList(@RequestParam(value="cpage", defaultValue="1") int currentPage, Model model) {
int listCount = adminService.selectAdminCommentListCount();
int pageLimit = 10;
int boardLimit = 10;
PageInfo pi = Pagination.getPageInfo(listCount, currentPage, pageLimit, boardLimit);
ArrayList<Review> list = adminService.selectAdminCommentList(pi);
model.addAttribute("pi", pi);
model.addAttribute("list", list);
return "admin/adminCommentView";
}
/**
* 관리자 페이지 코멘트 관리에서 검색 시 사용할 페이징 바, 검색 시 키워드에 해당하는 코멘트를 조회 - 작성자 : 수빈
* @param currentPage
* @param condition
* @param keyword
* @param model
* @return
*/
@RequestMapping(value="searchComment.ad")
public String searchAdminCommentList(@RequestParam(value="cpage", defaultValue="1") int currentPage, String condition, String keyword, Model model) {
// System.out.println("condition: " + condition);
// System.out.println("keyword: " + keyword);
HashMap<String, String> map = new HashMap<>();
map.put("condition", condition);
map.put("keyword", keyword);
int searchCount = adminService.searchAdminCommentListCount(map);
int pageLimit = 10;
int boardLimit = 10;
PageInfo pi = Pagination.getPageInfo(searchCount, currentPage, pageLimit, boardLimit);
ArrayList<Review> searchList = adminService.searchAdminCommentList(map, pi);
model.addAttribute("pi", pi);
model.addAttribute("searchList", searchList);
// 검색한 조건과 검색어 유지를 위해 다시 jsp로 보내 줌
model.addAttribute("condition", condition);
model.addAttribute("keyword", keyword);
return "admin/adminCommentView";
}
}
❌ ReviewService
👉🏻 ⭕️ AdminService
package com.urfavoriteott.ufo.admin.model.service;
import java.util.ArrayList;
import java.util.HashMap;
import com.urfavoriteott.ufo.common.model.vo.PageInfo;
import com.urfavoriteott.ufo.contents.model.vo.Review;
public interface AdminService {
/**
* 관리자 페이지 코멘트 관리를 위한 페이징바 - 작성자: 수빈
* @param reviewNo : 코멘트 번호
* @return
*/
int selectAdminCommentListCount();
/**
* 관리자 페이지에서 코멘트 관리를 위해 모든 코멘트 조회 (select) - 작성자: 수빈
* @param reviewNo : 코멘트 번호
* @return
*/
ArrayList<Review> selectAdminCommentList(PageInfo pi);
/**
* 관리자 페이지 코멘트 관리에서 검색을 위한 페이징바(select) - 작성자: 수빈
* @return
*/
int searchAdminCommentListCount(HashMap map);
/**
* 관리자 페이지 코멘트 관리에서 검색된 코멘트 조회 (select) - 작성자: 수빈
* @return
*/
ArrayList<Review> searchAdminCommentList(HashMap map, PageInfo pi);
}
❌ ReviewServiceImpl
👉🏻 ⭕️ AdminServiceImpl
package com.urfavoriteott.ufo.admin.model.service;
import java.util.ArrayList;
import java.util.HashMap;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.urfavoriteott.ufo.admin.model.dao.AdminDao;
import com.urfavoriteott.ufo.common.model.vo.PageInfo;
import com.urfavoriteott.ufo.contents.model.vo.Review;
@Service
public class AdminServiceImpl implements AdminService {
@Autowired
private SqlSessionTemplate sqlSession;
@Autowired
private AdminDao adminDao;
/**
* 관리자 페이지 코멘트 관리를 위한 페이징바 - 작성자: 수빈
* @param reviewNo : 코멘트 번호
* @return
*/
@Override
public int selectAdminCommentListCount() {
return adminDao.selectAdminCommentListCount(sqlSession);
}
/**
* 관리자 페이지에서 코멘트 관리를 위해 모든 코멘트 조회 (select) - 작성자: 수빈
* @param reviewNo : 코멘트 번호
* @return
*/
@Override
public ArrayList<Review> selectAdminCommentList(PageInfo pi) {
return adminDao.selectAdminCommentList(sqlSession, pi);
}
/**
* 관리자 페이지 코멘트 관리에서 검색을 위한 페이징바(select) - 작성자: 수빈
* @return
*/
@Override
public int searchAdminCommentListCount(HashMap map) {
return adminDao.searchAdminCommentListCount(sqlSession, map);
}
/**
* 관리자 페이지 코멘트 관리에서 검색된 코멘트 조회 (select) - 작성자: 수빈
* @return
*/
@Override
public ArrayList<Review> searchAdminCommentList(HashMap map, PageInfo pi) {
return adminDao.searchAdminCommentList(sqlSession, map, pi);
}
}
❌ ReviewDao
👉🏻 ⭕️ AdminDao
package com.urfavoriteott.ufo.admin.model.dao;
import java.util.ArrayList;
import java.util.HashMap;
import org.apache.ibatis.session.RowBounds;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.stereotype.Repository;
import com.urfavoriteott.ufo.common.model.vo.PageInfo;
import com.urfavoriteott.ufo.contents.model.vo.Review;
@Repository
public class AdminDao {
/**
* 관리자 페이지 코멘트 관리를 위한 페이징바 - 작성자: 수빈
* @param sqlSession
* @return
*/
public int selectAdminCommentListCount(SqlSessionTemplate sqlSession) {
return sqlSession.selectOne("adminMapper.selectAdminCommentListCount");
}
/**
* 관리자 페이지에서 코멘트 관리를 위해 모든 코멘트 조회 (select) - 작성자: 수빈
* @param sqlSession
* @param pi
* @return
*/
public ArrayList<Review> selectAdminCommentList(SqlSessionTemplate sqlSession, PageInfo pi) {
int limit = pi.getBoardLimit();
int offset = (pi.getCurrentPage() -1) * limit;
RowBounds rowBounds = new RowBounds(offset, limit);
return (ArrayList)sqlSession.selectList("adminMapper.selectAdminCommentList", null, rowBounds);
}
/**
* 관리자 페이지 코멘트 관리에서 검색을 위한 페이징바(select) - 작성자: 수빈
* @param sqlSession
* @param map
* @return
*/
public int searchAdminCommentListCount(SqlSessionTemplate sqlSession, HashMap map) {
return sqlSession.selectOne("adminMapper.searchAdminCommentListCount", map);
}
/**
* 관리자 페이지 코멘트 관리에서 검색된 코멘트 조회 (select) - 작성자: 수빈
* @param sqlSession
* @param map
* @param pi
* @return
*/
public ArrayList<Review> searchAdminCommentList(SqlSessionTemplate sqlSession, HashMap map, PageInfo pi) {
int limit = pi.getBoardLimit();
int offset = (pi.getCurrentPage() -1) * limit;
RowBounds rowBounds = new RowBounds(offset, limit);
return (ArrayList)sqlSession.selectList("adminMapper.searchAdminCommentList", map, rowBounds);
}
}
❌ review-mapper.xml
👉🏻 ⭕️ admin-mapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd" >
<mapper namespace="adminMapper">
<!-- 리뷰 관련 resultSet, 작성자: 수빈 -->
<resultMap id="reviewResultSet" type="review">
<result column="REVIEW_NO" property="reviewNo" />
<result column="USER_NO" property="userNo" />
<result column="MOVIE_ID" property="movieId" />
<result column="MOVIE_TITLE" property="movieTitle" />
<result column="TV_ID" property="tvId" />
<result column="TV_NAME" property="tvName" />
<result column="REVIEW_STAR" property="reviewStar" />
<result column="REVIEW_CONTENT" property="reviewContent" />
<result column="REVIEW_REGISTER_DATE" property="reviewDate" />
<result column="REVIEW_STATUS" property="reviewStatus" />
<result column="USER_ID" property="userId" />
<result column="USER_NICKNAME" property="userNickname" />
</resultMap>
<!-- 관리자 페이지 코멘트 관리를 위한 페이징바 , 작성자: 수빈 -->
<select id="selectAdminCommentListCount" resultType="_int">
SELECT COUNT(*)
FROM REVIEW
WHERE REVIEW_STATUS = 'Y'
</select>
<!-- 관리자 페이지에서 코멘트 관리를 위해 모든 코멘트 조회 (select) -->
<select id="selectAdminCommentList" resultMap="reviewResultSet">
SELECT REVIEW_NO
, MB.USER_ID
, MB.USER_NICKNAME
, MV.TITLE AS "MOVIE_TITLE"
, TV.NAME AS "TV_NAME"
, TO_CHAR(REVIEW_STAR, 'FM0.0') AS "REVIEW_STAR"
, REVIEW_CONTENT
FROM REVIEW R
LEFT JOIN MEMBER MB USING(USER_NO)
LEFT JOIN MOVIE MV ON(R.MOVIE_ID = MV.MOVIE_ID)
LEFT JOIN TV ON (R.MOVIE_ID = TV.TV_ID)
WHERE REVIEW_STATUS = 'Y'
ORDER BY REVIEW_REGISTER_DATE DESC
</select>
<!-- 관리자 페이지 코멘트 관리에서 검색을 위한 페이징바(select) - 작성자: 수빈 -->
<select id="searchAdminCommentListCount" resultType="_int">
SELECT COUNT(*)
FROM REVIEW R
LEFT JOIN MEMBER MB USING(USER_NO)
LEFT JOIN MOVIE MV ON(R.MOVIE_ID = MV.MOVIE_ID)
LEFT JOIN TV ON (R.MOVIE_ID = TV.TV_ID)
WHERE REVIEW_STATUS = 'Y'
<if test="condition == 'contentsTitle'">
AND TV.NAME LIKE '%' || #{keyword} || '%'
OR MV.TITLE LIKE '%' || #{keyword} || '%'
</if>
<if test="condition == 'userId'">
AND MB.USER_ID LIKE '%' || #{keyword} || '%'
</if>
<if test="condition == 'userNickname'">
AND MB.USER_NICKNAME LIKE '%' || #{keyword} || '%'
</if>
</select>
<!-- 관리자 페이지 코멘트 관리에서 검색된 코멘트 조회 (select) - 작성자: 수빈 -->
<select id="searchAdminCommentList" resultMap="reviewResultSet">
SELECT REVIEW_NO
, MB.USER_ID
, MB.USER_NICKNAME
, MV.TITLE AS "MOVIE_TITLE"
, TV.NAME AS "TV_NAME"
, TO_CHAR(REVIEW_STAR, 'FM0.0') AS "REVIEW_STAR"
, REVIEW_CONTENT
FROM REVIEW R
LEFT JOIN MEMBER MB USING(USER_NO)
LEFT JOIN MOVIE MV ON(R.MOVIE_ID = MV.MOVIE_ID)
LEFT JOIN TV ON (R.MOVIE_ID = TV.TV_ID)
WHERE REVIEW_STATUS = 'Y'
<if test="condition == 'contentsTitle'">
AND TV.NAME LIKE '%' || #{keyword} || '%'
OR MV.TITLE LIKE '%' || #{keyword} || '%'
</if>
<if test="condition == 'userId'">
AND MB.USER_ID LIKE '%' || #{keyword} || '%'
</if>
<if test="condition == 'userNickname'">
AND MB.USER_NICKNAME LIKE '%' || #{keyword} || '%'
</if>
ORDER BY REVIEW_REGISTER_DATE DESC
</select>
</mapper>
💻 Review는 변화 없음
package com.urfavoriteott.ufo.contents.model.vo;
import java.sql.Date;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@NoArgsConstructor
@AllArgsConstructor
@Setter
@Getter
@ToString
public class Review {
private int reviewNo; // REVIEW_NO NUMBER
private String reviewStatus; // REVIEW_STATUS CHAR(1 BYTE)
private String reviewStar; // REVIEW_STAR NUMBER
private String reviewContent; // REVIEW_CONTENT LONG
private Date reviewDate; // REVIEW_DATE DATE
private int userNo; // USER_NO NUMBER
private String userId; // 코멘트에 대한 리스트를 보여줄때 가지고 올 이메일
private String userNickname; // 코멘트에 대한 리스트를 보여줄때 가지고 올 닉네임
private int movieId; // MOVIE_ID
private String movieTitle; // movie 테이블에서 가지고 올 한글 제목
private int tvId; // TV_ID
private String tvName; // tv 테이블에서 가지고 올 한글 제목
}
💻 mybatis-config.xml는 변화 없음
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "mybatis-3-config.dtd" >
<configuration>
<!-- 런타임 시 MyBatis 설정 -->
<settings>
<!-- DB에 전달할 값이 없을 때 NULL 전달 -->
<setting name="jdbcTypeForNull" value="NULL" />
</settings>
<!-- 작성할 코드 줄이기 위한 자바 타입의 별칭 설정 -->
<typeAliases>
<typeAlias type="com.urfavoriteott.ufo.contents.model.vo.Review" alias="review" />
</typeAliases>
<!-- SQL 매핑 파일 등록 -->
<mappers>
<mapper resource="/mappers/admin-mapper.xml" />
</mappers>
</configuration>