SpringBoot 프로젝트

[프로젝트] 13. 커뮤니티 게시판 - 등록, 수정, 댓글 (Week 4)

더밸류(THEVALUE) 2022. 12. 19. 14:44

이번 프로젝트의 마지막 화면으로 

앞서 만든 게시판과 유사한 성격을 취하지만

아래의 기능이 더 포함되어 있음

1. 로그인한 일반 사용자가 글을 등록할 수 있다.
2. 답변 (댓글)을 등록하고 수정, 삭제할 수 있다.

 

[ CommunityController.java ]

경로 )
src\main\java\com\info\fastboard\community\controller\CommunityController.java
package com.info.fastboard.community.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;

import com.info.fastboard.community.persistence.CommunityMapper;
import com.info.fastboard.community.service.CommunityService;
import com.info.fastboard.main.util.SessionUtil;

@Controller
public class CommunityController {
	
	@Autowired
	private CommunityService communityService;
	
	@Autowired
	private CommunityMapper communityMapper;
	
	@GetMapping("/community")
	public String main() {
		return "community";
	}
	
	/**
     * 게시글 리스트 조회
     * @return
     */
	@ResponseBody
	@PostMapping("/community/findCommunityList")
	public List<String[]> findCommunityList(@RequestBody Map<String, Object> map) {
		
		List<Map<String, Object>> list = communityMapper.findCommunityList(map);
		
		List<String[]> newList = new ArrayList<String[]>();
		int idx = 1;
		for(Map<String, Object> inMap : list) {
			String[] output = new String[inMap.size()];
			output[0] = (idx++) + "";
			output[1] = (String) inMap.get("CODE_NAME");
			output[2] = (String) inMap.get("COMMUNITY_TITLE");
			output[3] = (String) inMap.get("USER_NM");
			output[4] = (String) inMap.get("INPUT_DATETIME");
			output[5] = (String) (inMap.get("COMMUNITY_IDX") + "");
			
			newList.add(output);
		}
		
		return newList;
	}
	
	/**
     * 게시글 상세 조회
     * @return
     */
	@ResponseBody
	@PostMapping("/community/findCommunityDetail")
	public List<Map<String, Object>> findCommunityDetail(@RequestBody Map<String, Object> map) {
		map.put("userId", SessionUtil.getSessionUserId());
		List<Map<String, Object>> list = communityMapper.findCommunityDetail(map);
		
		return list;
	}
	
	/**
     * 게시글 등록, 수정
     * @return
     */
	@ResponseBody
	@PostMapping("/community/saveCommunity")
	public Map<String, Object> saveCommunity(@RequestBody Map<String, Object> map) {
		map.put("userId", SessionUtil.getSessionUserId());
		Map<String, Object> result = new HashMap<String, Object>();
		communityService.saveCommunity(map);
		result.put("success", true);
		return result;
	}
	
	/**
     * 게시글 삭제
     * @return
     */
	@ResponseBody
	@PostMapping("/community/saveCommunityDelete")
	public Map<String, Object> saveCommunityDelete(@RequestBody Map<String, Object> map) {
		map.put("userId", SessionUtil.getSessionUserId());
		Map<String, Object> result = new HashMap<String, Object>();
		communityService.saveCommunityDelete(map);
		result.put("success", true);
		return result;
	}
	
	/**
     * 답변 조회
     * @return
     */
	@ResponseBody
	@PostMapping("/community/findReplyList")
	public List<Map<String, Object>> findReplyList(@RequestBody Map<String, Object> map) {
		map.put("userId", SessionUtil.getSessionUserId());
		List<Map<String, Object>> list = communityMapper.findReplyList(map);
		
		return list;
	}
	
	/**
     * 답변 등록
     * @return
     */
	@ResponseBody
	@PostMapping("/community/saveReply")
	public Map<String, Object> saveReply(@RequestBody Map<String, Object> map) {
		map.put("userId", SessionUtil.getSessionUserId());
		Map<String, Object> result = new HashMap<String, Object>();
		communityService.saveReply(map);
		result.put("success", true);
		return result;
	}
	
	/**
     * 답변 삭제
     * @return
     */
	@ResponseBody
	@PostMapping("/community/saveReplyDelete")
	public Map<String, Object> saveReplyDelete(@RequestBody Map<String, Object> map) {
		Map<String, Object> result = new HashMap<String, Object>();
		communityService.saveReplyDelete(map);
		result.put("success", true);
		return result;
	}
	
	/**
     * 답변 수정
     * @return
     */
	@ResponseBody
	@PostMapping("/community/saveReplyModify")
	public Map<String, Object> saveReplyModify(@RequestBody Map<String, Object> map) {
		Map<String, Object> result = new HashMap<String, Object>();
		communityService.saveReplyModify(map);
		result.put("success", true);
		return result;
	}
	
}

 

[ CommunityMapper.java ]

경로 )
src\main\java\com\info\fastboard\community\persistence\CommunityMapper.java
package com.info.fastboard.community.persistence;

import java.util.List;
import java.util.Map;

import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface CommunityMapper {
	// 커뮤니티 리스트 조회
    int findCommunityLastNo();
    
	// 커뮤니티 리스트 조회
    List<Map<String, Object>> findCommunityList(Map<String, Object> map);
    
    // 커뮤니티 상세 데이터 조회 
    List<Map<String, Object>> findCommunityDetail(Map<String, Object> map);
    
    // 게시글 저장 
    void saveCommunityInsert(Map<String, Object> map);
    
    // 게시글 수정 
    void saveCommunityUpdate(Map<String, Object> map);
    
    // 게시글 삭제 
    void saveCommunityDelete(Map<String, Object> map);
    
    // 게시글 하위 모든 답변 삭제 
    void saveReplyDeleteAll(Map<String, Object> map);
    
    // 답변 조회 
    List<Map<String, Object>> findReplyList(Map<String, Object> map);
    
    // 답변 등록 
    void saveReply(Map<String, Object> map);
    
    // 답변 삭제 
    void saveReplyDelete(Map<String, Object> map);
    
    // 답변 수정 
    void saveReplyModify(Map<String, Object> map);
}

 

[ CommunityService.java ]

경로 )
src\main\java\com\info\fastboard\community\service\CommunityService.java
package com.info.fastboard.community.service;

import java.util.Map;

public interface CommunityService {
	// 게시글 추가, 수정 
	void saveCommunity(Map<String, Object> map);
	
	// 게시글 삭제 
	void saveCommunityDelete(Map<String, Object> map);
	
	// 답변 등록 
	void saveReply(Map<String, Object> map);
	
	// 답변 삭제
	void saveReplyDelete(Map<String, Object> map);
	
	// 답변 수정
	void saveReplyModify(Map<String, Object> map);
}

 

[ CommunityServiceImpl.java ]

경로 )
src\main\java\com\info\fastboard\community\service\CommunityServiceImpl.java
package com.info.fastboard.community.service;

import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.info.fastboard.community.persistence.CommunityMapper;


@Service
@Transactional
public class CommunityServiceImpl implements CommunityService {

	@Autowired
	private CommunityMapper communityMapper;
	
	@Override
	public void saveCommunity(Map<String, Object> map) {
		
		if("Y".equals(map.get("modifyYn"))) {
			communityMapper.saveCommunityUpdate(map);
		} else {
			int lastNo = communityMapper.findCommunityLastNo();
			map.put("communityIdx", lastNo);
			communityMapper.saveCommunityInsert(map);
		}
	}
	
	@Override
	public void saveCommunityDelete(Map<String, Object> map) {
		// 게시글 삭제 
		communityMapper.saveCommunityDelete(map);
		// 게시글 하위 모든 답변 삭제
		communityMapper.saveReplyDeleteAll(map);
	}
	
	@Override
	public void saveReply(Map<String, Object> map) {
		communityMapper.saveReply(map);
	}
	
	@Override
	public void saveReplyDelete(Map<String, Object> map) {
		communityMapper.saveReplyDelete(map);
	}
	
	@Override
	public void saveReplyModify(Map<String, Object> map) {
		communityMapper.saveReplyModify(map);
	}
}

 

[ CommunityMapper.xml ]

경로 )
src\main\resources\mapper\CommunityMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.info.fastboard.community.persistence.CommunityMapper">

	<select id="findCommunityLastNo" resultType="int">
		SELECT NVL(MAX(COMMUNITY_IDX) + 1, 1) AS COMMUNITY_IDX
   		  FROM INFO.CRT_COMMUNITY_INFO 
	</select>
	
	<select id="findCommunityList" parameterType="hashmap" resultType="hashmap">
		SELECT A.COMMUNITY_IDX
		     , B.CODE_NAME
		     , A.COMMUNITY_TITLE
		     , C.USER_NM
		     , A.COMMUNITY_DESC
		     , A.INPUT_USER_ID
		     , TO_CHAR(A.INPUT_DATETIME, 'yyyy-mm-dd hh24:mi:ss') AS INPUT_DATETIME
		     , A.MODIFY_USER_ID
		     , TO_CHAR(A.MODIFY_DATETIME, 'yyyy-mm-dd hh24:mi:ss') AS MODIFY_DATETIME
		  FROM INFO.CRT_COMMUNITY_INFO A
		  LEFT OUTER JOIN INFO.CRT_CODE_DETAIL B
		    ON A.COMMUNITY_TYPE = B.DETAIL_ID
		   AND B.CODE_ID = 'COMMUNITY_TYPE'
		  LEFT OUTER JOIN INFO.CRT_USER_INFO C
		    ON A.INPUT_USER_ID = C.USER_ID
		 WHERE 1=1
		 	<if test="!''.equals(searchType)">
		 	AND A.COMMUNITY_TYPE = #{searchType}
		 	</if>
            <if test="!''.equals(searchText)">
            AND A.COMMUNITY_TITLE LIKE '%' || #{searchText} || '%'
            </if>
         ORDER BY A.INPUT_DATETIME DESC
	</select>
	
	<select id="findCommunityDetail" parameterType="hashmap" resultType="hashmap">
		SELECT A.COMMUNITY_IDX
		     , B.CODE_NAME
		     , A.COMMUNITY_TITLE
		     , C.USER_NM
		     , A.COMMUNITY_DESC
		     , A.INPUT_USER_ID
		     , TO_CHAR(A.INPUT_DATETIME, 'yyyy-mm-dd hh24:mi:ss') AS INPUT_DATETIME
		     , A.MODIFY_USER_ID
		     , TO_CHAR(A.MODIFY_DATETIME, 'yyyy-mm-dd hh24:mi:ss') AS MODIFY_DATETIME
		     , #{userId} AS CUR_USER_ID
		  FROM INFO.CRT_COMMUNITY_INFO A
		  LEFT OUTER JOIN INFO.CRT_CODE_DETAIL B
		    ON A.COMMUNITY_TYPE = B.DETAIL_ID
		   AND B.CODE_ID = 'COMMUNITY_TYPE'
		  LEFT OUTER JOIN INFO.CRT_USER_INFO C
		    ON A.INPUT_USER_ID = C.USER_ID
		 WHERE 1=1
		   AND A.COMMUNITY_IDX = #{communityIdx}
	</select>
	
	<insert id="saveCommunityInsert" parameterType="hashmap">
		INSERT INTO INFO.CRT_COMMUNITY_INFO (COMMUNITY_IDX, COMMUNITY_TYPE, COMMUNITY_TITLE, COMMUNITY_DESC, INPUT_USER_ID, INPUT_DATETIME)
    	 VALUES (
    	 	  #{communityIdx}
    	 	, #{communityType}
    	 	, #{communityTitle}
    	 	, #{communityDesc}
    	 	, #{userId}
    	 	, SYSDATE
    	 )
	</insert>
	
	<update id="saveCommunityUpdate" parameterType="hashmap">
		UPDATE INFO.CRT_COMMUNITY_INFO
		   SET COMMUNITY_TITLE = #{communityTitle}
		     , COMMUNITY_DESC = #{communityDesc}
		     , COMMUNITY_TYPE = #{communityType}
		 WHERE INPUT_USER_ID = #{userId}
		   AND COMMUNITY_IDX = #{communityIdx}
	</update>
	
	<delete id="saveCommunityDelete" parameterType="hashmap">
		DELETE 
		  FROM INFO.CRT_COMMUNITY_INFO
		 WHERE COMMUNITY_IDX = #{communityIdx}
	</delete>
	
	<delete id="saveReplyDeleteAll" parameterType="hashmap">
		DELETE 
		  FROM INFO.CRT_COMMUNITY_REPLY
		 WHERE COMMUNITY_IDX = #{communityIdx}
	</delete>
	
	<select id="findReplyList" parameterType="hashmap" resultType="hashmap">
		SELECT A.REPLY_IDX
		     , A.REPLY_DESC
		     , TO_CHAR(A.INPUT_DATETIME, 'yyyy-mm-dd hh24:mi:ss') AS INPUT_DATETIME
		     , C.USER_NM
		     , A.INPUT_USER_ID
		     , #{userId} AS CUR_USER_ID
		  FROM INFO.CRT_COMMUNITY_REPLY A
		  LEFT OUTER JOIN INFO.CRT_USER_INFO C
		    ON A.INPUT_USER_ID = C.USER_ID
		 WHERE 1=1
		   AND COMMUNITY_IDX = #{communityIdx}
		 ORDER BY INPUT_DATETIME DESC
	</select>
	
	<insert id="saveReply" parameterType="hashmap">
		INSERT INTO INFO.CRT_COMMUNITY_REPLY (COMMUNITY_IDX, REPLY_IDX, REPLY_DESC, INPUT_USER_ID, INPUT_DATETIME)
    	 VALUES (
    	 	  #{communityIdx}
    	 	, (SELECT NVL(MAX(REPLY_IDX) + 1, 1) FROM INFO.CRT_COMMUNITY_REPLY)
    	 	, #{replyDesc}
    	 	, #{userId}
    	 	, SYSDATE
    	 )
	</insert>
	
	<delete id="saveReplyDelete" parameterType="hashmap">
		DELETE 
		  FROM INFO.CRT_COMMUNITY_REPLY
		 WHERE REPLY_IDX = #{replyIdx}
	</delete>
	
	<update id="saveReplyModify" parameterType="hashmap">
		UPDATE INFO.CRT_COMMUNITY_REPLY
		   SET REPLY_DESC = #{replyDesc}
		 WHERE REPLY_IDX = #{replyIdx}
	</update>

</mapper>

 

[ community.html ]

경로 )
src\main\resources\templates\community.html
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org" lang="ko" class="h-100"
	xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
	xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
<meta charset="utf-8">
<!-- 반응형 -->
<meta name="viewport" content="width=device-width, initial-scale=1">

<th:bloc th:replace="../static/common/header::header"></th:bloc>
</head>
<body class="d-flex flex-column h-100">
 
	<!-- 상단 메뉴바 -->
	<th:bloc th:replace="../static/common/menu::menu"></th:bloc>

	<!-- Begin page content -->
	<main class="flex-shrink-0">
		<div class="container">
			<h1 class="mt-5">FAST BOARD 커뮤니티 게시판</h1>
			<p class="lead">
				커뮤니티 게시글 등록 및 커뮤니티 게시글 조회를 위한 화면입니다.
			</p>
			
			<!-- 조회조건 영역 -->
			<div id="panel1" class="row p-5 bg-light border rounded-3 mb-5 panel">
				<div class="col-sm-4 row">
					<label for="txtTitle" class="col-sm-6 col-form-label">제목</label>
					<div class="col-sm-6">
						<input type="text" class="form-control" id="txtTitle" placeholder="제목으로 검색">
					</div>
				</div>
				<div class="col-sm-4 row">
					<label for="txtTitle" class="col-sm-6 col-form-label">카테고리</label>
					<div class="col-sm-6">
						<select id="cmbCommunityType1" class="form-control"></select>
					</div>
				</div>
				<div class="col-sm-4 text-end">
					<button type="button" class="btn btn-primary" id="btnSearch">조회</button>
					<button type="button" class="btn btn-primary" id="btnWrite" sec:authorize="isAuthenticated()">글 쓰기</button>
				</div>
				
				<div style="clear: both;"></div>
				<br/>
				
				<div class="com-sm-12">
					<table id="tblMain" class="table table-bordered" summary="게시물 목록">
						<thead>
							<tr>
								<th width="8%">NO</th>
								<th width="18%">카테고리</th>
								<th>제목</th>
								<th width="18%">작성자</th>
								<th width="18%">등록일자</th>
							</tr>
						</thead>
					</table>
				</div>
			</div>
			
			<!-- 데이터 영역 -->
			<div id="panel2"  class="row p-5 bg-light border rounded-3 mb-5 panel" style="display: none;">
				<div class="com-sm-12">
					<table id="tblSub" class="table table-bordered">
						<tbody>
							<tr>
								<th width="18%">카테고리</th>
								<td id="tdCommunityType"></td>
								<th width="18%">작성자</th>
								<td id="tdInputUser"></td>
								<th width="18%">등록일자</th>
								<td id="tdInputDate"></td>
							</tr>
							<tr>
								<th width="18%">제목</th>
								<td id="tdCommunityTitle" colspan="5"></td>
							</tr>
							<tr>
								<th width="18%">내용</th>
								<td colspan="5" style="height: 640px;">
									<pre id="tdCommunityDesc" style="height: 100%; overflow-y: auto;"></pre>
								</td>
							</tr>
						</tbody>
					</table>
					
					<br/>
					<!-- 답변 -->
					<h5 class="road_tit">글 답변</h5>
					<p sec:authorize="isAnonymous()">* 로그인 후 답변 등록이 가능합니다.</p>
					<div style="max-height: 300px; overflow-y: auto;">
						<table id="tblReply" class="bbs_con_v2">
						</table>
					</div>
					
					<br/>
					<div class="btn-group">
						<button type="button" id="btnReply" value="답변등록" title="답변등록" class="btn btn-primary" sec:authorize="isAuthenticated()">답변등록</button>
						<button type="button" id="btnDelete" value="삭제" title="삭제" class="btn btn-primary" style="display: none;">삭제</button>
						<button type="button" id="btnModify" value="수정" title="수정" class="btn btn-primary" style="display: none;">수정</button>
						<button type="button" id="btnBack" value="목록" title="목록" class="btn btn-primary">목록</button>
					</div>
				</div>
			</div>
			
			<!-- 글 등록 패널 -->
			<div id="panel3" class="contents_in panel" style="display: none;">
				<h5 id="txtModifyYn" class="road_tit">글 등록</h5>
            	<fieldset class="board_search">
					<label for="SearchCriteria">제목</label>
					<input id="txtCommunityTitle" name="searchkey" type="text" class="form-control" value="" title="게시글 제목 입력" placeholder="게시글 제목 입력">
					<label for="SearchCriteria">카테고리</label>
					<select id="cmbCommunityType2" class="form-control"></select>
				</fieldset>
				
				<div id="summernote"></div>
				
				<br/>
				<div class="btn-group">
					<button type="button" id="btnCancel" value="취소" title="취소" class="btn btn-primary">취소</button>
					<button type="button" id="btnSave" value="저장" title="저장" class="btn btn-primary">저장</button>
				</div>
			</div>
		</div>
	</main>
	
	<div id="modal" class="modal">
		<h3>답변 등록</h3>
	    <fieldset class="board_search">
			<textarea id="txtReply" class="textarea"></textarea>
	    </fieldset>
	    <a id="btnApplyReply" class="btn_d">등록</a>
	    <a href="#" rel="modal:close" class="btn btn-primary">닫기</a>
	</div>
	
	<div id="modalModify" class="modal">
		<h3>답변 수정</h3>
	    <fieldset class="board_search">
	    	<input type="hidden" id="txtReplyIdx">
			<textarea id="txtReplyModify" class="textarea"></textarea>
	    </fieldset>
	    <a id="btnModifyReply" class="btn_d">수정</a>
	    <a href="#" rel="modal:close" class="btn btn-primary">닫기</a>
	</div>
	
	<!-- 하단 푸터 영역 -->
	<th:bloc th:replace="../static/common/footer::footer"></th:bloc>

	<!-- Page Script -->
	<script src="static/views/community.js"></script>

</body>
</html>

 

[ community.js ]

경로 )
src\main\resources\static\views\community.js
/*******************************************************************************
 * 
 * community.js
 * 
 * @author THKIM
 * @since 2022
 * @DESC 커뮤니티 게시판 화면 스크립트
 * 
 ******************************************************************************/
(function() {
	
	function Community() {
		
		/* 
		 * private variables
		 */
		var MODIFY_YN = 'N';
		var SELECTED_COMMUNITY_IDX = '';
		
		 // Korean
		var dataTables = null;
	    var lang_kor = {
	        "decimal" : "",
	        "emptyTable" : "데이터가 없습니다.",
	        "info" : "_START_ - _END_ (총 _TOTAL_ 건)",
	        "infoEmpty" : "0건",
	        "infoFiltered" : "(전체 _MAX_ 건 중 검색결과)",
	        "infoPostFix" : "",
	        "thousands" : ",",
	        "lengthMenu" : "_MENU_ 개씩 보기",
	        "loadingRecords" : "로딩중...",
	        "processing" : "처리중...",
	        "search" : "검색 : ",
	        "zeroRecords" : "검색된 데이터가 없습니다.",
	        "paginate" : {
	            "first" : "첫 페이지",
	            "last" : "마지막 페이지",
	            "next" : "다음",
	            "previous" : "이전"
	        },
	        "aria" : {
	            "sortAscending" : " :  오름차순 정렬",
	            "sortDescending" : " :  내림차순 정렬"
	        }
	    };
		
		/* 
		 * 초기화 메소드
		 */
		
		function _init() {
			// 이벤트 
			bindEvent();
			
			// 카테고리 조회 
			findCodeList();
			
			// 커뮤니티 리스트 조회 
			findCommunityList();
			
			// 에디터 설정
			setEditor();
		}
		
		function bindEvent() {
			// 조회 버튼 클릭 이벤트
			$("#btnSearch").on("click", function() {
				toastr.success('데이터 조회중입니다.', '커뮤니티게시판');
				findCommunityList();
			});
			
			// 게시글 저장 버튼 클릭 이벤트
			$("#btnSave").on("click", function() {
				saveCommunity();
			});
			
			// 글 쓰기 버튼 클릭 이벤트 
			$("#btnWrite").on("click", function() {
				$("#txtModifyYn").html("글 등록");
				// form 초기화
				$('#summernote').summernote('code', "");
				$("#txtCommunityTitle").val(""); // 제목 초기화 
				$(".panel").hide();
				$("#panel3").show();
			});
			
			// 취소 버튼 클릭 이벤트 
			$("#btnCancel").on("click", function() {
				MODIFY_YN = 'N';
				$(".panel").hide();
				$("#panel1").show();
			});
			
			// 목록 버튼 클릭 이벤트 
			$("#btnBack").on("click", function() {
				SELECTED_COMMUNITY_IDX = '';
				$(".panel").hide();
				$("#panel1").show();
			});
			
			// 글 삭제 버튼 클릭 이벤트 
			$("#btnDelete").on("click", function() {
				saveCommunityDelete();
			});
			
			// 글 수정 버튼 클릭 이벤트 
			$("#btnModify").on("click", function() {
				$("#txtModifyYn").html("글 수정");
				MODIFY_YN = 'Y';
				$(".panel").hide();
				$("#panel3").show();
			});
			
			// 답글달기 버튼 클릭 이벤트 
			$("#btnReply").on("click", function() {
				console.log("??");
				$("#modal").modal();
			});
			
			// 답글등록 버튼 클릭 이벤트 
			$("#btnApplyReply").on("click", function() {
				saveReply();
			});
			
			// 답변수정 버튼 클릭 이벤트 
			$("#btnModifyReply").on("click", function() {
				saveReplyModify();
			});
		}
		
		/*
		 * 코드 정보 리스트 조회 
		 */
		function findCodeList() {
			var obj = {
				codeId: 'COMMUNITY_TYPE'
			}
			
			var html = "";
			cfFind("/findCodeList", obj, function(data) {
				$.each(data, function(idx, node) {
					html += "<option id='" + node.DETAIL_ID + "'>" + node.CODE_NAME + "</option>";
				});
				
				$("#cmbCommunityType1").html("<option id=''>전체</option>" + html);
				$("#cmbCommunityType2").html(html);
				
			}, true, "POST");
		}
		
		/*
		 * 커뮤니티 리스트 조회 
		 */
		function findCommunityList() {
			var obj = {
				searchText: $("#txtTitle").val(),
				searchType: $("#cmbCommunityType1 option:selected")[0].id
			}
			
			cfFind("/community/findCommunityList", obj, function(data) {
				if(dataTables != null) {
					$("#tblMain").DataTable().destroy();
				}
				
				dataTables = $("#tblMain").DataTable({
					data: data,
					columns: [
						{ title: "NO", width: "8%" },
						{ title: "카테고리", width: "18%" },
			            { title: "제목" },
			            { title: "작성자", width: "18%" },
			            { title: "등록일자", width: "18%" }
			        ],
			        language: lang_kor,
			        filter: false,
			        ordering: false,
			        lengthChange: false
				});
				
				// row 클릭 이벤트 
				$("#tblMain tbody").on('click', 'td', function () {
					var rowIdx = $(this)[0].parentNode.childNodes[0].innerText;
					var rowNode = dataTables.row(Number(rowIdx)-1).data();
					SELECTED_COMMUNITY_IDX = rowNode[5];
					findCommunityDetail();
				});
				
			}, true, "POST");
		}
		
		/*
		 * 커뮤니티 상세 조회
		 */
		function findCommunityDetail() {
			var obj = {
				communityIdx: SELECTED_COMMUNITY_IDX
			}
			
			cfFind("/community/findCommunityDetail", obj, function(data) {
				if(data.length > 0) {
					$.each(data, function(idx, node) {
						if(idx == 0) {
							$("#tdCommunityType").html(node.CODE_NAME); // 카테고리 
							$("#tdInputUser").html(node.USER_NM); // 작성자 
							$("#tdInputDate").html(node.INPUT_DATETIME); // 등록일자 
							$("#tdCommunityTitle").html(node.COMMUNITY_TITLE); // 제목 
							$("#tdCommunityDesc").html(node.COMMUNITY_DESC); // 내용 
							
							$('#summernote').summernote('code', node.COMMUNITY_DESC);
							$("#txtCommunityTitle").val(node.COMMUNITY_TITLE); // 제목 
							$("#cmbCommunityType2").val(node.CODE_NAME); // 카테고리 
							
							// 글 쓴 사용자가 로그인 사용자와 일치하는 경우에만 버튼 출력 (삭제, 수정 버튼)
							if(node.CUR_USER_ID == node.INPUT_USER_ID) {
								$("#btnDelete").show();
								$("#btnModify").show();
							} else {
								$("#btnDelete").hide();
								$("#btnModify").hide();
							}
							
							// admin 관리자는 삭제 가능하도록 
							if(node.CUR_USER_ID == 'admin') {
								$("#btnDelete").show();
							}
						}
					});
					
					$(".panel").hide();
					$("#panel2").show();
					
					// 답변 조회
					findReplyList();
				} 
				
			}, true, "POST");
		}
		
		/*
		 * 에디터 설정
		 */
		function setEditor() {
			$('#summernote').summernote({
		    	height:500,
				lang: 'ko-KR',
				toolbar: [
				    ['fontname', ['fontname']],
				    ['fontsize', ['fontsize']],
				    ['style', ['bold', 'italic', 'underline','strikethrough', 'clear']],
				    ['color', ['forecolor','color']],
				    ['table', ['table']],
				    ['para', ['paragraph']],
				    ['height', ['height']],
				    ['insert',['picture','link']],
				    ['view', ['help']]
				  ],
				fontNames: ['Arial', 'Arial Black', 'Comic Sans MS', 'Courier New','맑은 고딕','궁서','굴림체','굴림','돋움체','바탕체'],
				fontSizes: ['8','9','10','11','12','14','16','18','20','22','24','28','30','36','50','72']
		    });
		}
		
		/*
		 * 게시글 저장
		 */
		function saveCommunity() {
			var title = $("#txtCommunityTitle").val(); // 게시글 제목 
			if(title == "") { 
				alert("게시글 제목을 입력하시기 바랍니다."); 
				$("#txtCommunityTitle").focus();
				return false; 
			}
			
			var code = $('#summernote').summernote('code'); // 게시글 내용 
			var result = confirm("게시글을 저장하시겠습니까?");
			if(result) {
				var obj = {
					communityIdx: SELECTED_COMMUNITY_IDX,
					communityTitle: title,
					communityDesc: code,
					modifyYn: MODIFY_YN,
					communityType: $("#cmbCommunityType2 option:selected")[0].id
				}
				cfSave("/community/saveCommunity", obj, function(data) {
					if (data.success) {
						toastr.success('데이터 저장이 완료되었습니다.', '글 저장');
						
						// form 초기화
						$('#summernote').summernote('code', "");
						$("#txtCommunityTitle").val(""); // 제목 초기화 
						
						$(".panel").hide();
						$("#panel1").show();
						
						// 리스트 재조회
						findCommunityList();
						
						MODIFY_YN = 'N';
						
					} else {
						toastr.error('데이터 저장 오류', '글 저장');
					}
				});
			}
		}
		
		/*
		 * 게시글 삭제
		 */
		function saveCommunityDelete() {
			var result = confirm("게시글을 삭제하시겠습니까?");
			if(result) {
				var obj = {
					communityIdx: SELECTED_COMMUNITY_IDX
				}
				cfSave("/community/saveCommunityDelete", obj, function(data) {
					if (data.success) {
						toastr.success('데이터 삭제가 완료되었습니다.', '글 삭제');
						
						SELECTED_COMMUNITY_IDX = '';
						$(".panel").hide();
						$("#panel1").show();
						
						// 리스트 재조회
						findCommunityList();
						
					} else {
						toastr.error('데이터 삭제 오류', '글 삭제');
					}
				});
			}
		}
		
		/*
		 * 답변 조회
		 */
		function findReplyList() {
			var obj = {
				communityIdx: SELECTED_COMMUNITY_IDX
			}
			
			var html = "";
			cfFind("/community/findReplyList", obj, function(data) {
				if(data.length > 0) {
					$.each(data, function(idx, node) {
						if(node.CUR_USER_ID == node.INPUT_USER_ID) {
							html += "<tr><td style='text-overflow: ellipsis; white-space: pre;'>" + node.REPLY_DESC;
							html += "<a id='" + idx + "' class='btn btn-primary btnDelete'>삭제</a>";
							html += "<a id='" + idx + "' class='btn btn-primary btnModify'>수정</a>";
							html += "</td>";
						} else {
							html += "<tr><td style='text-overflow: ellipsis; white-space: pre;'>" + node.REPLY_DESC + "</td>";
						}
						html += "<td style='width: 10%;'>" + node.USER_NM + "</td>";
						html += "<td style='width: 15%;'>" + node.INPUT_DATETIME + "</td>";
						html += "</tr>";
					});
				} 
				
				$("#tblReply").html(html);
				
				// 답변수정 버튼 클릭 이벤트 
				$(".btnModify").on("click", function() {
					var idx = $(this)[0].id;
					$("#txtReplyModify").val(data[idx]["REPLY_DESC"]);
					$("#txtReplyIdx").val(data[idx]["REPLY_IDX"]);
					
					$("#modalModify").modal();
				});
				// 답변삭제 버튼 클릭 이벤트 
				$(".btnDelete").on("click", function() {
					var idx = $(this)[0].id;
					var result = confirm("답변을 삭제하시겠습니까?");
					if(result) {
						var obj = {
							replyIdx: data[idx]["REPLY_IDX"]
						}
						cfSave("/community/saveReplyDelete", obj, function(data) {
							if (data.success) {
								toastr.success('데이터 삭제가 완료되었습니다.', '답변 삭제');
								
								// 답변 리스트 재조회
								findReplyList();
								
							} else {
								toastr.error('데이터 삭제 오류', '답변 삭제');
							}
						});
					}
				});
			}, true, "POST");
		}
		
		/*
		 * 답변 등록
		 */
		function saveReply() {
			var txtReply = $("#txtReply").val();
			if(txtReply == "" || txtReply == null) {
				alert("답변 내용을 입력학시기 바랍니다.");
				return false;
			}
			var result = confirm("답변을 등록하시겠습니까?");
			if(result) {
				var obj = {
					communityIdx: SELECTED_COMMUNITY_IDX,
					replyDesc: txtReply
				}
				cfSave("/community/saveReply", obj, function(data) {
					if (data.success) {
						toastr.success('데이터 저장이 완료되었습니다.', '답변 등록');
						
						// 답변 리스트 재조회
						findReplyList();
						
						$("#txtReply").val("");
						$.modal.close();
						
					} else {
						toastr.error('데이터 저장 오류', '답변 등록');
					}
				});
			}
		}
		
		/*
		 * 답변 수정
		 */
		function saveReplyModify() {
			var txtReplyIdx = $("#txtReplyIdx").val();
			var txtReply = $("#txtReplyModify").val();
			if(txtReply == "" || txtReply == null) {
				alert("답변 내용을 입력학시기 바랍니다.");
				return false;
			}
			var result = confirm("답변을 수정하시겠습니까?");
			if(result) {
				var obj = {
					communityIdx: SELECTED_COMMUNITY_IDX,
					replyDesc: txtReply,
					replyIdx: txtReplyIdx
				}
				cfSave("/community/saveReplyModify", obj, function(data) {
					if (data.success) {
						toastr.success('데이터 저장이 완료되었습니다.', '답변 수정');
						
						// 답변 리스트 재조회
						findReplyList();
						
						$("#txtReplyIdx").val("");
						$("#txtReplyModify").val("");
						$.modal.close();
						
					} else {
						toastr.error('데이터 저장 오류', '답변 수정');
					}
				});
			}
		}
		
		
		function _finalize() {
		}
		
		return {
            init : _init,
            finalize : _finalize
        };
    };
    
    var community = new Community();
    community.init();
    
})();

//# sourceURL=community.js