코드관리 페이지 기능 추가.

강석 최 2022-08-22 18:35:33 +09:00
parent 46fb96f291
commit 81f0d616a1
16 changed files with 284 additions and 176 deletions

View File

@ -38,8 +38,8 @@ public class SecurityConfig{
log.warn("accessDeniedHandler");
return (request, response, e) -> {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.setContentType("text/plain;charset=UTF-8");
response.getWriter().write("ACCESS DENIED");
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("<script>alert('접근이 거부되었습니다.'); location.href='/';</script>");
response.getWriter().flush();
response.getWriter().close();
};
@ -49,8 +49,8 @@ public class SecurityConfig{
public AuthenticationEntryPoint authenticationEntryPoint() {
return (request, response, e) -> {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType("text/plain;charset=UTF-8");
response.getWriter().write("UNAUTHORIZED");
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("<script>alert('로그인이 해제되었습니다.'); location.href='/';</script>");
response.getWriter().flush();
response.getWriter().close();
};
@ -59,7 +59,7 @@ public class SecurityConfig{
@Bean
protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeRequests() // 페이지 권한 설정
.antMatchers("/dashboard").hasRole(Role.USER.name()) // USER, ADMIN 접근 허용
.antMatchers("/dashboard", "/refreshSession").hasRole(Role.USER.name()) // USER, ADMIN 접근 허용
.antMatchers("/codeMgt/**", "/menuMgt/**").hasRole(Role.ADMIN.name()) // ADMIN만 접근 허용
.antMatchers("/login").permitAll() // 로그인 페이지는 권한 없이 접근 허용
.and() // 로그인 설정

View File

@ -1,11 +1,10 @@
package com.dbnt.faisp.controller;
import com.dbnt.faisp.model.UserInfo;
import com.dbnt.faisp.service.CommonCodeService;
import com.dbnt.faisp.service.CodeMgtService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
@ -15,7 +14,7 @@ import javax.servlet.http.HttpSession;
@RequiredArgsConstructor
public class BaseController {
private final CommonCodeService commonCodeService;
private final CodeMgtService codeMgtService;
@GetMapping("/")
public ModelAndView loginCheck(@AuthenticationPrincipal UserInfo loginUser, HttpSession session) {
@ -23,6 +22,7 @@ public class BaseController {
if(loginUser == null){
mav = new ModelAndView("redirect:/login");
}else{
session.setAttribute("commonCodeList", codeMgtService.selectCodeCatgAndChild());
mav = new ModelAndView("redirect:/dashboard");
}
return mav;
@ -30,8 +30,7 @@ public class BaseController {
@GetMapping("/refreshSession")
public void getSession(HttpSession session){
session.setAttribute("positionList", commonCodeService.selectCommonCodeValue("POSITION"));
session.setAttribute("departmentList", commonCodeService.selectCommonCodeValue("DEPARTMENT"));
session.setAttribute("commonCodeList", codeMgtService.selectCodeCatgAndChild());
}
@GetMapping("/login")

View File

@ -1,13 +1,13 @@
package com.dbnt.faisp.controller;
import com.dbnt.faisp.model.CodeCatg;
import com.dbnt.faisp.service.CodeMgtService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import java.util.List;
@RestController
@RequiredArgsConstructor
@RequestMapping("/codeMgt")
@ -21,4 +21,16 @@ public class CodeMgtController {
return mav;
}
@PostMapping("/saveCode")
@ResponseBody
public String saveCode(@RequestBody List<CodeCatg> codeCategoryList){
codeMgtService.saveCode(codeCategoryList);
return "";
}
@GetMapping("/selectCodeCatgList")
public List<CodeCatg> selectCodeCatgList(){
return codeMgtService.selectCodeCatgAndChild();
}
}

View File

@ -1,14 +1,11 @@
package com.dbnt.faisp.controller;
import com.dbnt.faisp.model.UserInfo;
import com.dbnt.faisp.service.CommonCodeService;
import com.dbnt.faisp.service.UserInfoService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
@RestController
@RequiredArgsConstructor

View File

@ -1,11 +0,0 @@
package com.dbnt.faisp.mapper;
import com.dbnt.faisp.model.CommonCode;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface CommonCodeMapper {
List<CommonCode> selectCommonCodeCategory(CommonCode commonCode);
}

View File

@ -7,6 +7,7 @@ import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.*;
import java.util.List;
@Getter
@Setter
@ -24,4 +25,9 @@ public class CodeCatg {
@Column(name = "description")
private String description;
@Transient
private String status;
@Transient
private List<CodeMgt> itemList;
}

View File

@ -22,11 +22,14 @@ public class CodeMgt {
@Id
@Column(name = "item_cd")
private String itemCd;
@Column(name = "VALUE", nullable = false)
private String value;
@Column(name = "item_value", nullable = false)
private String itemValue;
@Column(name = "use_chk")
private String useChk;
@Transient
private String status;
@Embeddable
@Data
@NoArgsConstructor

View File

@ -1,32 +0,0 @@
package com.dbnt.faisp.model;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.*;
@Getter
@Setter
@Entity
@NoArgsConstructor
@DynamicInsert
@DynamicUpdate
@Table(name = "COMMON_CODE")
public class CommonCode {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "CODE_SQ")
private Integer codeSq;
@Column(name = "CATEGORY", nullable = false)
private String category;
@Column(name = "VALUE", nullable = false)
private String value;
@Column(name = "DESCRIPTION")
private String description;
@Column(name = "IS_DELETED")
private String isDeleted;
}

View File

@ -3,9 +3,11 @@ package com.dbnt.faisp.repository;
import com.dbnt.faisp.model.CodeMgt;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
import java.util.Optional;
public interface CodeMgtRepository extends JpaRepository<CodeMgt, CodeMgt.CodeMgtId> {
List<CodeMgt> findByCategoryCdOrderByItemCdAsc(String categoryCd);
}

View File

@ -1,11 +0,0 @@
package com.dbnt.faisp.repository;
import com.dbnt.faisp.model.CommonCode;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface CommonCodeRepository extends JpaRepository<CommonCode, Integer> {
List<CommonCode> findByCategoryAndIsDeleted(String category, String isDeleted);
}

View File

@ -1,6 +1,8 @@
package com.dbnt.faisp.service;
import com.dbnt.faisp.mapper.CodeMgtMapper;
import com.dbnt.faisp.model.CodeCatg;
import com.dbnt.faisp.model.CodeMgt;
import com.dbnt.faisp.repository.CodeCatgRepository;
import com.dbnt.faisp.repository.CodeMgtRepository;
import lombok.RequiredArgsConstructor;
@ -17,4 +19,26 @@ public class CodeMgtService{
private final CodeCatgRepository codeCatgRepository;
private final CodeMgtMapper codeMgtMapper;
@Transactional
public String saveCode(List<CodeCatg> codeMgtList){
for(CodeCatg codeCatg: codeMgtList){
codeCatgRepository.save(codeCatg);
if (codeCatg.getItemList().size()>0){
codeItemSave(codeCatg.getItemList());
}
}
return "";
}
private void codeItemSave(List<CodeMgt> itemList){
codeMgtRepository.saveAll(itemList);
}
public List<CodeCatg> selectCodeCatgAndChild() {
List<CodeCatg> codeCatgList = codeCatgRepository.findAll();
for(CodeCatg codeCatg: codeCatgList){
codeCatg.setItemList(codeMgtRepository.findByCategoryCdOrderByItemCdAsc(codeCatg.getCategoryCd()));
}
return codeCatgList;
}
}

View File

@ -1,31 +0,0 @@
package com.dbnt.faisp.service;
import com.dbnt.faisp.mapper.CommonCodeMapper;
import com.dbnt.faisp.model.CommonCode;
import com.dbnt.faisp.repository.CommonCodeRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@RequiredArgsConstructor
public class CommonCodeService {
private final CommonCodeMapper commonCodeMapper;
private final CommonCodeRepository commonCodeRepository;
public List<CommonCode> selectCommonCodeCategory(CommonCode commonCode) {
return commonCodeMapper.selectCommonCodeCategory(commonCode);
}
public List<CommonCode> selectCommonCodeValue(String category) {
return commonCodeRepository.findByCategoryAndIsDeleted(category, "N");
}
public void insertCommonCode(CommonCode commonCode) {
commonCodeRepository.save(commonCode);
}
public void updateCommonCode(List<CommonCode> codeList) {
commonCodeRepository.saveAll(codeList);
}
}

View File

@ -1,17 +0,0 @@
<?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.dbnt.faisp.mapper.CommonCodeMapper">
<select id="selectCommonCodeCategory" resultType="CommonCode" parameterType="CommonCode">
SELECT DISTINCT
CATEGORY
FROM COMMON_CODE
<where>
<if test="isDeleted == null or isDeleted == ''">
AND IS_DELETED = 'N'
</if>
</where>
</select>
</mapper>

View File

@ -0,0 +1,149 @@
let codeCategoryList=[];
let selectedCategoryIdx=0;
let selectedItemIdx=0;
$(function(){
$.ajax({
url: '/codeMgt/selectCodeCatgList',
type: 'GET',
dataType:"json",
success: function(data){
codeCategoryList = data;
makeCategoryTr();
},
error:function(){
}
});
});
$(document).on('click', '#categoryAddBtn', function (){
$('#categoryTable').find('tbody').append(
'<tr class="categoryTr">' +
'<td><button class="btn btn-sm btn-outline-danger rowDeleteBtn"><i class="bi bi-x"></i></button></td>'+
'<td><input type="text" class="form-control form-control-sm categoryInput" name="categoryCd"></td>'+
'<td><input type="text" class="form-control form-control-sm categoryInput" name="categoryValue"></td>'+
'<td><input type="text" class="form-control form-control-sm categoryInput" name="description"></td>'+
'</tr>'
)
codeCategoryList.push({categoryCd:"", categoryValue: "", description: "", status:"new", itemList: []})
})
$(document).on('click', '#itemAddBtn', function (){
$('#itemTable').find('tbody').append(
'<tr class="itemTr">' +
'<td><button class="btn btn-sm btn-outline-danger rowDeleteBtn"><i class="bi bi-x"></i></button></td>'+
'<td><input type="text" class="form-control form-control-sm itemInput" name="itemCd"></td>'+
'<td><input type="text" class="form-control form-control-sm itemInput" name="itemValue"></td>'+
'<td></td>'+
'</tr>'
)
codeCategoryList[selectedCategoryIdx].itemList.push({categoryCd:codeCategoryList[selectedCategoryIdx].categoryCd, itemCd:"", itemValue: "", useChk: "", status:"new"})
})
$(document).on('click', '.rowDeleteBtn', function (){
switch ($(this).parents("table")[0].id){
case "categoryTable":
selectedCategoryIdx = $(this).parents('tr')[0].rowIndex-1;
codeCategoryList.splice(selectedItemIdx, 1);
break;
case "itemTable":
selectedItemIdx = $(this).parents('tr')[0].rowIndex-1;
codeCategoryList[selectedCategoryIdx].itemList.splice(selectedItemIdx, 1);
break;
}
$(this).parents('tr').remove();
})
$(document).on('click', '.categoryTr', function (){
selectedCategoryIdx = this.rowIndex-1;
$(".allChk").prop("checked", false);
$('#itemTable').find('tbody').find('tr').remove();
$("#itemBtnRow").show();
if(codeCategoryList[selectedCategoryIdx].itemList.length>0){
makeItemTr(codeCategoryList[selectedCategoryIdx].itemList);
}
})
$(document).on('click', '.itemTr', function (){
selectedItemIdx = this.rowIndex-1;
})
$(document).on('change', '.categoryInput', function (){
selectedCategoryIdx = $(this).parents('tr')[0].rowIndex-1;
const target = codeCategoryList[selectedCategoryIdx];
switch (this.name){
case "categoryCd":
target.categoryCd = this.value
break;
case "categoryValue":
target.categoryValue = this.value
break;
case "description":
target.description = this.value
break;
}
})
$(document).on('change', '.itemInput', function (){
selectedItemIdx = $(this).parents('tr')[0].rowIndex-1;
const target = codeCategoryList[selectedCategoryIdx].itemList[selectedItemIdx];
switch (this.name){
case "itemCd":
target.itemCd = this.value
break;
case "itemValue":
target.itemValue = this.value
break;
case "useChk":
target.useChk = this.checked?"T":"F"
break;
}
})
$(document).on('click', '#codeSaveBtn', function (){
contentFade("in");
$.ajax({
type : 'POST',
url : "/codeMgt/saveCode",
data : JSON.stringify(codeCategoryList),
contentType: 'application/json',
beforeSend: function (xhr){
xhr.setRequestHeader($("[name='_csrf_header']").val(), $("[name='_csrf']").val());
},
success : function(data) {
alert("저장되었습니다.");
contentFade("out");
location.reload();
},
error : function(xhr, status) {
alert("저장에 실패하였습니다.")
contentFade("out");
}
})
})
function makeCategoryTr(){
codeCategoryList.forEach(function (category, idx){
$("#categoryTable").find('tbody').append(
'<tr class="categoryTr" '+(category.status==="delete"?'style="display:none;"':'')+'>' +
'<td>'+(category.status==="new"?'<button class="btn btn-sm btn-outline-danger rowDeleteBtn"><i class="bi bi-x"></i></button>':'')+'</td>'+
'<td><input type="text" class="form-control form-control-sm categoryInput" name="categoryCd" value="'+category.categoryCd+'"></td>'+
'<td><input type="text" class="form-control form-control-sm categoryInput" name="categoryValue" value="'+category.categoryValue+'"></td>'+
'<td><input type="text" class="form-control form-control-sm categoryInput" name="description" value="'+category.description+'"></td>'+
'</tr>'
)
});
}
function makeItemTr(itemList){
itemList.forEach(function (item, idx){
$("#itemTable").find('tbody').append(
'<tr class="itemTr" '+(item.status==="delete"?'style="display:none;"':'')+'>' +
'<td>'+(item.status==="new"?'<button class="btn btn-sm btn-outline-danger rowDeleteBtn"><i class="bi bi-x"></i></button>':'<input type="checkbox" class="codeItemChk">')+'</td>'+
'<td><input type="text" class="form-control form-control-sm itemInput" name="itemCd" value="'+item.itemCd+'"></td>'+
'<td><input type="text" class="form-control form-control-sm itemInput" name="itemValue" value="'+item.itemValue+'"></td>'+
'<td><input type="checkbox" class="itemInput" name="useChk" '+(item.useChk==="T"?'checked':'')+'></td>'+
'</tr>'
)
});
}

View File

@ -5,3 +5,16 @@ function contentFade(action){
$("#fadeDiv").hide()
}
}
function sessionReload(){
$.ajax({
url: '/refreshSession',
type: 'GET',
success: function(){location.reload();},
error:function(){}
});
}
$(document).on('click', '.allChk', function (){
$(this).parents('table').find('[type="checkbox"]').prop("checked", this.checked);
})

View File

@ -3,19 +3,29 @@
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/layout}">
<th:block layout:fragment="script">
<script type="text/javascript" th:src="@{/js/admin/userMgt.js}"></script>
<script type="text/javascript" th:src="@{/js/codeMgt/codeMgt.js}"></script>
</th:block>
<div layout:fragment="content">
<main class="pt-3">
<h4>코드 관리</h4>
<input type="hidden" name="_csrf_header" th:value="${_csrf.headerName}"/>
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
<div class="row mx-0">
<div class="col-12 card text-center">
<div class="card-body">
<div class="row">
<div class="col-10">
<div class="row justify-content-end">
<button class="col-auto btn btn-success mx-3 my-2" id="codeSaveBtn">저장</button>
</div>
</div>
</div>
<div class="row justify-content-start">
<div class="col-6">
<div class="card">
<div class="card-body">
<table class="table table-striped">
<div class="row">
<table class="table table-striped" id="categoryTable">
<thead>
<tr>
<th></th>
@ -24,44 +34,39 @@
<th>설명</th>
</tr>
</thead>
<!--<tbody th:if="${categoryList.size()==0}">
<tr>
<td colspan="2">검색된 분류가 없습니다.</td>
</tr>
<tbody class="overflow-scroll">
</tbody>
<tbody th:if="${categoryList.size()>0}">
<tr class="categoryTr" th:each="commonCode:${categoryList}">
<td>
<input type="checkbox" class="categoryCheckBox" th:value="${commonCode.category}">
</td>
<td th:text="${commonCode.category}"></td>
</tr>
</tbody>-->
</table>
</div>
<div class="row justify-content-center">
<button class="btn btn-sm btn-outline-primary col-auto" id="categoryAddBtn"><i class="bi bi-plus-lg"></i></button>
</div>
</div>
</div>
</div>
<div class="col-4" id="valueDiv">
<div class="card">
<div class="card-body">
<table class="table table-striped">
<div class="row">
<table class="table table-striped" id="itemTable">
<thead>
<tr>
<th>
<input type="checkbox" class="valueCheckBox" id="allValueCheckBox">
</th>
<th></th>
<th>하위코드</th>
<th></th>
<th>사용여부</th>
<th>사용</th>
</tr>
</thead>
<!--<tbody>
<tr>
<td colspan="3">분류를 선택해주세요.</td>
</tr>
</tbody>-->
<tbody class="overflow-scroll">
<tr><td colspan="4">분류를 선택해주세요.</td></tr>
</tbody>
</table>
</div>
<div class="row justify-content-center" id="itemBtnRow" style="display: none">
<button class="btn btn-sm btn-outline-primary col-auto" id="itemAddBtn"><i class="bi bi-plus-lg"></i></button>
</div>
</div>
</div>
</div>
</div>