Files
eapim-admin/WebContent/jsp/onl/apim/apigroup/apiGroupManDetail.jsp
T
Rinjae b7c8e7f41c API 그룹 팝업 JSP 추가 - Swagger Validator JS 등록 - Summernote CSS 추가
- API 그룹 팝업(djbApiGroupPopup.jsp) 화면 파일 추가
- Swagger Validator (djb-swagger-validator.js) 및 관련 리팩토링
- Summernote 콘텐츠 스타일 정의 (editor-content.css) 추가
2026-07-03 16:54:47 +09:00

493 lines
21 KiB
Plaintext

<%@ page language="java" contentType="text/html; charset=utf-8"%>
<%@ page import="java.io.*"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ include file="/jsp/common/include/localemessage.jsp" %>
<%
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Expires", "0");
%>
<%!
public String getRequiredLabel(String label) {
return label + " <span class=\"required-mark\">*</span>";
}
%>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<jsp:include page="/jsp/common/include/css.jsp"/>
<jsp:include page="/jsp/common/include/script.jsp"/>
<jsp:include page="/jsp/common/include/portal.jsp"/>
<script language="javascript" >
var url = '<c:url value="/onl/apim/apigroup/apiGroupMan.json"/>';
var url_view = '<c:url value="/onl/apim/apigroup/apiGroupMan.view"/>';
var url_popup_view = '<c:url value="/onl/transaction/apim/apiSpecMan.view"/>';
var isDetail = false;
let dialog;
let selectedOrgs = {};
function componentRenderingInit() {
$('#apiGrid').jqGrid({
datatype: "json",
colNames: ['업무구분',
'<%= localeMessage.getString("eaiMessage.eaiSvcName")%>',
'<%= localeMessage.getString("eaiMessage.eaiSvcDesc")%>',
'표시순서'
],
colModel: [ { name : 'bizCode', align : 'center', width:'40', sortable:false},
{ name : 'apiId', align : 'left', width:'100'},
{ name : 'apiDesc', align : 'left' },
{ name : 'displayOrder', align : 'center', width: '60', editable: true,
edittype: 'text', editrules: { number: true, required: true }, formatter: 'integer' }
],
sortable: true,
rowNum: 10000,
autoheight: true,
height: "510",
autowidth: true,
multiselect: true,
viewrecords: true,
sortname: 'displayOrder',
sortorder: 'asc',
gridComplete: function() {
if (!this.sortableInitialized) {
$("#apiGrid tbody").sortable({
items: 'tr.jqgrow',
cursor: 'move',
axis: 'y',
helper: function (e, ui) {
ui.children().each(function () {
$(this).width($(this).width());
});
return ui;
},
update: function (event, ui) {
// 드래그 앤 드롭 완료 후 displayOrder 재계산
const rows = $("#apiGrid").jqGrid('getRowData');
rows.forEach((row, index) => {
const rowId = $("#apiGrid").getDataIDs()[index];
$("#apiGrid").jqGrid('setCell', rowId, 'displayOrder', index + 1);
});
}
}).disableSelection();
this.sortableInitialized = true;
}
}
});
/*$('#contentDetail').summernote({
height: 300,
toolbar: [
['style', ['style']],
['font', ['bold', 'underline', 'clear']],
['color', ['color']],
['para', ['ul', 'ol', 'paragraph']],
['table', ['table']],
['insert', ['link', 'picture', 'video']],
['view', ['codeview', 'help']]
],
callbacks: {
onInit: function() {
$('.note-editable').on('keydown', function(e) {
if (e.keyCode === 8) {
e.stopPropagation();
}
});
}
}
});*/
}
function selectOrg(selectedOrgs) {
// 기관 ID와 이름을 각각의 필드에 설정
const orgIds = selectedOrgs.map(org => org.id).join(',');
$('#displayOrg').val(orgIds);
const orgNames = selectedOrgs.map(org => org.orgName).join(', ');
$('#displayOrgName').val(orgNames);
}
function detail(key){
if (!isDetail)return;
$.ajax({
type : "POST",
url:url,
dataType:"json",
data:{cmd: 'DETAIL', apiGroupId : key},
success:function(json){
json.apiGroupApiList.sort((a, b) => {
return (a.displayOrder || 0) - (b.displayOrder || 0);
});
$("#apiGrid")[0].addJSONData(json.apiGroupApiList);
var data = json;
$('input[name=groupName]');
$("#ajaxForm input[type!=checkbox]:not([type=file]),#ajaxForm select,#ajaxForm textarea").each(function(){
var name = $(this).attr("name");
var tag = $(this).prop("tagName");
$(tag+"[name="+name+"]").val(data[name]);
});
// $('#contentDetail').summernote('code', data.contentDetail);
const files = $("input[type='file']");
for (let i = 0; i < files.length; i++) {
const fileInput = files[i];
if (data[fileInput.name]) {
const previewSelector = "#"+fileInput.name+"Preview";
$(previewSelector).attr('src', data[fileInput.name]).show();
$(previewSelector).attr('tooltip', 'true'); // 툴팁 설정
}
}
if(json.displayYn === "1") {
$("input[name=displayYn]").prop('checked', true);
} else {
$("input[name=displayYn]").prop('checked', false);
}
if(json.displayRoleCode) {
const roles = json.displayRoleCode.split(',');
roles.forEach(role => {
$('input[name="roleCode"][value="' + role + '"]').prop('checked', true);
});
}
if(json.displayOrg) {
$("#displayOrg").val(json.displayOrg); // ID 값
$("#displayOrgName").val(json.displayOrgName);
}
},
error:function(e){
alert(e.responseText);
}
});
}
function init(key){
componentRenderingInit();
detail(key);
}
function toBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
});
}
function readURL(input, previewSelector) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$(previewSelector).attr('src', e.target.result);
$(previewSelector).show();
$(previewSelector).attr('tooltip', 'true'); // 툴팁 설정
}
reader.readAsDataURL(input.files[0]);
} else {
$(previewSelector).hide();
}
}
$(document).ready(function() {
var returnUrl = getReturnUrlForReturn();
var key ="${param.apiGroupId}";
if (key != "" && key !="null"){
isDetail = true;
}
init(key);
$(document).tooltip({
items: "img[tooltip]",
content: function () {
var element = $(this);
var imgSrc = element.attr("src");
return "<img src='" + imgSrc + "' style='max-width:300px; max-height:300px;'/>";
},
track: true
});
$("#btn_select_org").click(function(){
var popupUrl = url_popup_view + "?cmd=POPUP_LIST";
var selectedOrgIds = $('#displayOrg').val() || '';
if (selectedOrgIds) {
popupUrl += "&selectedOrgIds=" + encodeURIComponent(selectedOrgIds);
}
var args = { title:'공개 법인 리스트', selectedOrgIds: selectedOrgIds };
showModal(popupUrl, args, 450, 550);
});
$("#btn_modify").click(async function(){
if (!checkRequired("ajaxForm")) return;
const roleValues = $('input[name="roleCode"]:checked')
.map(function() { return $(this).val(); })
.get()
.join(',');
$('#displayRoleCode').val(roleValues);
let postData = $('#ajaxForm').serializeArray();
if(!postData.some(item => item.name === 'displayYn')) {
postData.push({ name: "displayYn", value: "0" });
}
if (isDetail){
postData.push({ name: "cmd" , value:"UPDATE"});
}else{
postData.push({ name: "cmd" , value:"INSERT"});
}
postData = postData.filter(item => !(item.name === "id" && item.value === ''));
const files = $("input[type='file']");
for (let i = 0; i < files.length; i++) {
const fileInput = files[i];
if (fileInput.files.length > 0) {
const file = fileInput.files[0];
const base64 = await toBase64(file);
postData.push({ name: fileInput.name , value: base64});
}
}
const data = $("#apiGrid").getRowData();
const apiGroupApiList = new Array();
const apiGroupId = $("input[name=id]").val();
for ( let i = 0; i < data.length; i++) {
const apiGroupApi = {
apiId: data[i]["apiId"],
displayOrder: data[i]["displayOrder"],
}
if(apiGroupId != ''){
apiGroupApi.apiGroupId = apiGroupId;
}
apiGroupApiList.push(apiGroupApi);
}
postData.push({
name : "apiGroupApiList",
value : JSON.stringify(apiGroupApiList)
});
$.ajax({
type : "POST",
url:url,
data:postData,
success:function(args){
alert("저장 되었습니다.");
goNav(returnUrl);//LIST로 이동
},
error:function(e){
alert(e.responseText);
}
});
});
$("#btn_delete").click(function(){
if(confirm("삭제하시겠습니까?")){
var postData = $('#ajaxForm').serializeArray();
postData.push({ name: "cmd" , value:"DELETE"});
$.ajax({
type : "POST",
url:url,
data:postData,
success:function(args){
if(args.status=="error"){
alert("동기화중 오류입니다.\n확인하여 주십시요.\n" + args.message);
}else{
alert("삭제 되었습니다.");
goNav(returnUrl);//LIST로 이동
}
},
error:function(e){
alert(e.responseText);
}
});
}
});
$("#btn_previous").click(function(){
goNav(returnUrl);//LIST로 이동
});
$("#btn_popup_api").click(function(){
const args = { title: 'API 선택' };
let url2 = url_view + "?cmd=POPUP";
const currentApis = $("#apiGrid").getRowData().map(row => row.apiId);
if(currentApis.length > 0) {
url2 += "&selectedApiIds=" + encodeURIComponent(currentApis.join(','));
}
showModal(url2,args,1280,860,function (){
const popupFrame = args.self.frames[0];
const returnValue = popupFrame.returnValue;
if (!returnValue) {
return;
}
// 단일 객체인 경우도 배열로 처리하기 위해 배열로 변환
const itemsToAdd = Array.isArray(returnValue) ? returnValue : [returnValue];
itemsToAdd.forEach(item => {
// 중복 체크를 위해 현재 그리드의 데이터를 다시 가져옴
const currentGridData = $("#apiGrid").getRowData();
const isDuplicate = currentGridData.some(row => row.apiId === item.apiId);
// 중복되지 않은 경우에만 추가
if (!isDuplicate) {
const newRowId = $("#apiGrid").getGridParam("reccount") + 1;
const currentRowCount = $("#apiGrid").jqGrid('getRowData').length;
$("#apiGrid").jqGrid('addRowData', newRowId, {
bizCode: item.bizCode,
apiId: item.apiId,
apiDesc: item.apiDesc,
displayOrder: currentRowCount + 1
});
}
});
});
});
$("#btn_delete_api").click(function(){
var grid = $("#apiGrid");
var selectedRowIds = grid.jqGrid('getGridParam', 'selarrrow'); // 선택된 행의 ID 배열을 가져옴
if (selectedRowIds.length > 0) {
// 선택된 행의 ID를 복사한 배열을 사용
var idsToDelete = selectedRowIds.slice();
for (var i = 0; i < idsToDelete.length; i++) {
grid.jqGrid('delRowData', idsToDelete[i]); // 선택된 각 행을 삭제
}
} else {
alert("Please select at least one row to delete.");
}
});
$("input[type='file'][name='mainIcon']").change(function() {
readURL(this, "#mainIconPreview");
});
// $("input[type='file'][name='contentIcon']").change(function() {
// readURL(this, "#contentIconPreview");
// });
$('input[name="displayOrder"]').on('input', function() {
this.value = this.value.replace(/[^0-9]/g, '');
});
buttonControl(isDetail);
titleControl(isDetail);
});
</script>
</head>
<body>
<div class="right_box">
<div class="content_top">
<ul class="path">
<li><a href="#">${rmsMenuPath}</a></li>
</ul>
</div><!-- end content_top -->
<div class="content_middle">
<div class="search_wrap">
<button type="button" class="cssbtn" id="btn_delete" level="W" status="DETAIL"><i class="material-icons">delete</i> <%= localeMessage.getString("button.delete") %></button>
<button type="button" class="cssbtn" id="btn_modify" level="W" status="DETAIL,NEW"><i class="material-icons">save</i> <%= localeMessage.getString("button.modify") %></button>
<button type="button" class="cssbtn" id="btn_previous" level="R" status="DETAIL,NEW"><i class="material-icons">arrow_back</i> <%= localeMessage.getString("button.previous") %></button>
</div>
<div class="title">API 그룹 상세</div>
<form id="ajaxForm">
<input type="hidden" name="id">
<div id="titleRow" class="table_row_title">API 그룹</div>
<table class="table_row" cellspacing="0">
<tr>
<th style="width:150px;"><%= getRequiredLabel("API 그룹 명") %></th>
<td colspan="7">
<input type="text" name="groupName" data-required data-warning="API 그룹 명을 입력하여 주십시오.">
</td>
</tr>
<tr>
<th style="width:150px;">공개 여부</th>
<td style="width:100px;">
<label class="checkbox-inline">
<input type="checkbox" name="displayYn" value="1" onclick="this.value = this.checked ? '1' : '0'"> 공개
</label>
</td>
<th style="width:150px;"><%= getRequiredLabel("표시 순서") %></th>
<td style="width:100px;">
<input type="number" name="displayOrder" min="1" step="1" data-required data-warning="표시 순서를 입력하여 주십시오.">
</td>
<th style="width:150px;">공개 권한</th>
<td colspan="3">
<div class="checkbox-group">
<label class="checkbox-inline">
<input type="checkbox" name="roleCode" value="ROLE_USER"> 개인사용자
</label>
<label class="checkbox-inline">
<input type="checkbox" name="roleCode" value="ROLE_CORP_USER" style="margin-left: 5px;"> 법인사용자
</label>
<label class="checkbox-inline">
<input type="checkbox" name="roleCode" value="ROLE_CORP_MANAGER" style="margin-left: 5px;"> 법인관리자
</label>
<input type="hidden" name="displayRoleCode" id="displayRoleCode">
</div>
</td>
</tr>
<tr>
<th style="width:150px;">공개 법인</th>
<td colspan="7" >
<div style="display: flex;">
<input type="text" id="displayOrgName" readonly>
<input type="hidden" name="displayOrg" id="displayOrg">
<button type="button" class="cssbtn smallBtn" id="btn_select_org" style="margin-left: 10px; vertical-align: middle;" >
<i class="material-icons">search</i> 법인 선택
</button>
</div>
</td>
</tr>
<tr>
<th style="width:150px;">메인 아이콘</th>
<td colspan="7">
<input type="file" name="mainIcon" accept="image/*" />
<img id="mainIconPreview" src="#" alt="Main Icon Preview" style="display:none;height:20px">
</td>
</tr>
<%--<tr>
<th>컨텐츠 내용</th>
<td colspan="5">
<textarea name="contentDetail" id="contentDetail" rows="10" cols="50"></textarea>
</td>
</tr>--%>
</table>
<div style="margin-top:15px;">
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 5px ">
<div class="table_row_title" style="margin-bottom: 0px">그룹 대상 API</div>
<div style="text-align: end;">
<button type="button" class="cssbtn" id="btn_delete_api" level="W" status="DETAIL,NEW">
<i class="material-icons">delete</i> <%= localeMessage.getString("button.delete") %>
</button>
<button type="button" class="cssbtn" id="btn_popup_api" level="W" status="DETAIL,NEW">
<i class="material-icons">add</i> <%= localeMessage.getString("button.add") %>
</button>
</div>
</div>
<div id = "gridDiv">
<table id="apiGrid"></table>
</div>
</div>
</form>
</div><!-- end content_middle -->
</div><!-- end right_box -->
</body>
</html>