From d42accff75a11bc174ae3e4a762a94868df31d38 Mon Sep 17 00:00:00 2001 From: "Lim\\jun" Date: Fri, 26 Jan 2024 13:50:34 +0900 Subject: [PATCH 1/2] =?UTF-8?q?API=20Key=20=EA=B4=80=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/pages/admin/standards/ApiKeys.jsx | 224 ++++++++++++++++-- .../standards/AdminStandardsController.java | 108 +++++++++ .../admin/standards/entity/TnApiKey.java | 41 ++++ .../repository/ApiKeyRepository.java | 19 ++ .../standards/service/AdminApiService.java | 47 ++++ 5 files changed, 421 insertions(+), 18 deletions(-) create mode 100644 kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/standards/AdminStandardsController.java create mode 100644 kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/standards/entity/TnApiKey.java create mode 100644 kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/standards/repository/ApiKeyRepository.java create mode 100644 kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/standards/service/AdminApiService.java diff --git a/egovframe-template-simple-react-contribution/src/pages/admin/standards/ApiKeys.jsx b/egovframe-template-simple-react-contribution/src/pages/admin/standards/ApiKeys.jsx index 7088968..3475d31 100644 --- a/egovframe-template-simple-react-contribution/src/pages/admin/standards/ApiKeys.jsx +++ b/egovframe-template-simple-react-contribution/src/pages/admin/standards/ApiKeys.jsx @@ -1,30 +1,180 @@ -import React from 'react'; -import { Link } from 'react-router-dom'; +import React, {useState, useEffect, useCallback, useRef, PureComponent} from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import {BarChart, Bar, Rectangle, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer} from 'recharts'; + +import Switch from '@mui/material/Switch'; + +import * as EgovNet from 'api/egovFetch'; import URL from 'constants/url'; import { default as EgovLeftNav } from 'components/leftmenu/EgovLeftNavAdmin'; +import { itemIdxByPage } from 'utils/calc'; +import EgovPaging from 'components/EgovPaging'; + function ApiKeys(props) { + // console.group("EgovAdminPrivacyList"); + // console.log("[Start] EgovAdminPrivacyList ------------------------------"); + // console.log("EgovAdminPrivacyList [props] : ", props); + const location = useLocation(); + // console.log("EgovAdminPrivacyList [location] : ", location); + + // eslint-disable-next-line no-unused-vars + const [searchCondition, setSearchCondition] = useState(location.state?.searchCondition || { pageIndex: 1, searchCnd: '0', searchWrd: '' }); + const [paginationInfo, setPaginationInfo] = useState({}); + const [chartData, setChartData] = useState([]); + const [user_id, setuser_id] = useState([]); + + const [listTag, setListTag] = useState([]); + // const label = { inputProps: { 'aria-label': '사용여부' } }; + + const retrieveList = useCallback((srchCnd) => { + // console.groupCollapsed("EgovAdminUsageList.retrieveList()"); + const retrieveListURL = '/admin/standards/apikey'; + + const requestOptions = { + method: "POST", + headers: { + 'Content-type': 'application/json', + }, + body: JSON.stringify(srchCnd) + } + + EgovNet.requestFetch( + retrieveListURL, + requestOptions, + (resp) => { + setPaginationInfo(resp.result.paginationInfo); + + let mutListTag = []; + listTag.push(

데이터가 없습니다.

); // 게시판 목록 초기값 + + const resultCnt = parseInt(resp.result.resultCnt); + const currentPageNo = resp.result.paginationInfo.pageIndex; + const pageSize = resp.result.paginationInfo.rowCnt; + + const startIndex = (currentPageNo - 1) * pageSize; + const endIndex = Math.min(startIndex + pageSize, resultCnt); + + // 리스트 항목 구성 + for (let index = startIndex; index < endIndex; index++) { + const listIdx = itemIdxByPage(resultCnt, currentPageNo, 0, index); // pageSize 로 넣으면 listIdx값이 2배씩 줄어서 0으로 수정 + const item = resp.result.resultList[index]; + + mutListTag.push( +
+
{item.userId}
+
handleApiKeyChart(item)}>{item.apiKey}
+
{item.startDt} ~ {item.endDt}
+
{item.idntyYn === 'Y' ? handleSwitchToggle(item)} /> : handleSwitchToggle(item)} />}
+
+ ); + } + setListTag(mutListTag); + }, + function (resp) { + console.log("err response : ", resp); + } + ); + // console.groupEnd("EgovAdminPrivacyList.retrieveList()"); + },[listTag]); + + const CustomTooltip = ({ active, payload, label }) => { + if (active && payload && payload.length) { + return ( +
+

API 요청 [{user_id}]

+

{`${label} : ${payload[0].value}`}회

+
+ ); + } + return null; + }; + + const handleSwitchToggle = async (item) => { + try { + const updateApiEndpoint = '/admin/standards/apiupdate'; + const requestOptions = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(item), + }; + + const response = await EgovNet.requestFetch(updateApiEndpoint, requestOptions); + const data = await response.json(); + + if (response.ok) { + console.log('Data updated successfully:', data); + return { success: true, data }; + } else { + console.error('Failed to update data:', data); + return { success: false, error: data }; + } + } catch (error) { + console.error('Error during data update:', error); + return { success: false, error }; + } + }; + + const handleApiKeyChart = (item) => { + try { + const updateApiEndpoint = '/admin/standards/apiDailyChart'; + const requestOptions = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(item), + }; + + EgovNet.requestFetch( + updateApiEndpoint, + requestOptions, + (resp) => { + let chartDataArray = resp.result.resultList.map((item, index) => ({ + logdt: item[0], // Assuming logCnt is the x-axis data + "API 요청수": item[1], // Assuming menuTitle is the y-axis data + })); + setChartData(chartDataArray); + // item.userId 값 넣기 + console.log(`User ID: ${item.userId}`); + setuser_id(item.userId); + }, + function (resp) { + console.log("err response : ", resp); + } + ); + } catch (error) { + console.error('Error during data update:', error); + return { success: false, error }; + } + }; + + useEffect(() => { + retrieveList(searchCondition); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + // console.log("------------------------------EgovAdminPrivacyList [End]"); + // console.groupEnd("EgovAdminPrivacyList"); - const Location = React.memo(function Location() { - return ( -
- -
- ) - }); return (
{/* */} - +
+
    +
  • Home
  • +
  • 사이트관리
  • +
  • 건설기준 관리
  • +
  • API KEY 관리
  • +
+
{/* */}
@@ -35,13 +185,51 @@ function ApiKeys(props) {
{/* */}
-

건설기준 관리

+

API KEY 관리

-

API KEY 관리

+ {/* */} +
+
+ 사용자 + 발급키 + 승인기간 + 승인여부 +
+
+ {listTag} +
+
+ {/* */} - 여기에 구현해주세요. - {/* */} +
+ {/* */} + { + retrieveList({ ...searchCondition, pageIndex: passedPage }) //, searchCnd: cndRef.current.value, searchWrd: wrdRef.current.value + }} /> + {/* */} +
+
+ + + + + + } /> + + } /> + + +
+ {/* */}
diff --git a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/standards/AdminStandardsController.java b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/standards/AdminStandardsController.java new file mode 100644 index 0000000..d0dc80c --- /dev/null +++ b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/standards/AdminStandardsController.java @@ -0,0 +1,108 @@ +package com.dbnt.kcscbackend.admin.standards; + +import com.dbnt.kcscbackend.admin.standards.entity.TnApiKey; +import com.dbnt.kcscbackend.admin.standards.service.AdminApiService; +import com.dbnt.kcscbackend.auth.entity.LoginVO; +import com.dbnt.kcscbackend.config.common.BaseController; +import com.dbnt.kcscbackend.config.common.ResponseCode; +import com.dbnt.kcscbackend.config.common.ResultVO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.http.MediaType; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; +import java.util.Map; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/admin/standards") +@Tag(name="AdminStandardsController", description = "사이트관리 건설기준관리 메뉴 컨트롤러") +public class AdminStandardsController extends BaseController { + + private final AdminApiService adminApiService; + + @Operation( + summary = "건설기준관리 - API 관리", + description = "API 관리", + tags = {"AdminStandardsController"} + ) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "조회 성공"), + @ApiResponse(responseCode = "403", description = "인가된 사용자가 아님") + }) + @RequestMapping(method = RequestMethod.POST, value = "/apikey", consumes = MediaType.APPLICATION_JSON_VALUE) + public ResultVO selectApiList(@RequestBody TnApiKey tnApiKey, @AuthenticationPrincipal LoginVO user) + throws Exception { + + ResultVO resultVO = new ResultVO(); + tnApiKey.setQueryInfo(); + Map resultMap = adminApiService.selectApiList(); + int totCnt = Integer.parseInt((String)resultMap.get("resultCnt")); + tnApiKey.setContentCnt(totCnt); + tnApiKey.setPaginationInfo(); + resultMap.put("paginationInfo", tnApiKey); + + resultVO.setResultCode(ResponseCode.SUCCESS.getCode()); + resultVO.setResultMessage(ResponseCode.SUCCESS.getMessage()); + resultVO.setResult(resultMap); + return resultVO; + } + + @Operation( + summary = "API key 관리", + description = "API key 승인여부 수정", + tags = {"AdminStandardsController"} + ) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "수정 성공"), + @ApiResponse(responseCode = "303", description = "만료된 토큰"), + @ApiResponse(responseCode = "403", description = "인가된 사용자가 아님") + }) + @RequestMapping(method = RequestMethod.POST, value = "/apiupdate", consumes = MediaType.APPLICATION_JSON_VALUE) + public ResultVO modifyApi(@RequestBody TnApiKey tnApiKey, @AuthenticationPrincipal LoginVO user) throws Exception{ + ResultVO resultVO = new ResultVO(); + + TnApiKey existingApiKey = adminApiService.getApiKeyById(tnApiKey.getUserId()); + if (existingApiKey != null) { + existingApiKey.setIdntyYn(existingApiKey.getIdntyYn().equals("Y") ? "N" : "Y"); + adminApiService.modifyApi(existingApiKey); + + resultVO.setResultCode(ResponseCode.SUCCESS.getCode()); + } else { + resultVO.setResultCode(ResponseCode.SAVE_ERROR.getCode()); // 존재하지 않는 user_id에 대한 처리 + } + return resultVO; + } + + @Operation( + summary = "API key Chart", + description = "API key 클릭시 차트", + tags = {"AdminStandardsController"} + ) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "수정 성공"), + @ApiResponse(responseCode = "303", description = "만료된 토큰"), + @ApiResponse(responseCode = "403", description = "인가된 사용자가 아님") + }) + @RequestMapping(method = RequestMethod.POST, value = "/apiDailyChart", consumes = MediaType.APPLICATION_JSON_VALUE) + public ResultVO ApiChart(@RequestBody Map dateRange, @AuthenticationPrincipal LoginVO user) throws Exception{ + ResultVO resultVO = new ResultVO(); + Map resultMap = new HashMap<>(); + + String UserId = dateRange.get("userId"); + + resultMap.put("resultList", adminApiService.selectApiDailyCount(UserId)); + resultVO.setResultCode(ResponseCode.SUCCESS.getCode()); + resultVO.setResultMessage(ResponseCode.SUCCESS.getMessage()); + resultVO.setResult(resultMap); + return resultVO; + } +} diff --git a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/standards/entity/TnApiKey.java b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/standards/entity/TnApiKey.java new file mode 100644 index 0000000..f565c6f --- /dev/null +++ b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/standards/entity/TnApiKey.java @@ -0,0 +1,41 @@ +package com.dbnt.kcscbackend.admin.standards.entity; + +import com.dbnt.kcscbackend.config.common.BoardParams; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.experimental.Accessors; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.persistence.*; +import java.time.LocalDate; + +@Getter +@Setter +@Accessors(chain = true) +@Entity +@NoArgsConstructor +@DynamicInsert +@DynamicUpdate +@Table(name = "tn_api_key") +public class TnApiKey extends BoardParams { + @Id + @Column(name = "user_id") + private String userId; + + @Column(name = "api_key") + private String apiKey; + + @Column(name = "idnty_yn") + private String idntyYn; + + @Column(name = "start_dt") + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDate startDt; + + @Column(name = "end_dt") + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDate endDt; +} diff --git a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/standards/repository/ApiKeyRepository.java b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/standards/repository/ApiKeyRepository.java new file mode 100644 index 0000000..cbfcb18 --- /dev/null +++ b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/standards/repository/ApiKeyRepository.java @@ -0,0 +1,19 @@ +package com.dbnt.kcscbackend.admin.standards.repository; + +import com.dbnt.kcscbackend.admin.standards.entity.TnApiKey; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +public interface ApiKeyRepository extends JpaRepository { + List findAllByOrderByEndDtDesc(); + + @Query(value = "SELECT TO_CHAR(access_dt, 'YYYY-MM-DD') as log_dt, count(1) as log_cnt " + + "FROM th_api_log " + + "WHERE access_id = :UserId " + + "GROUP BY TO_CHAR(access_dt, 'YYYY-MM-DD') " + + "ORDER BY log_dt asc", nativeQuery = true) + List selectCountApiDaily(@Param("UserId") String UserId); +} diff --git a/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/standards/service/AdminApiService.java b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/standards/service/AdminApiService.java new file mode 100644 index 0000000..e736724 --- /dev/null +++ b/kcsc-back-end/src/main/java/com/dbnt/kcscbackend/admin/standards/service/AdminApiService.java @@ -0,0 +1,47 @@ +package com.dbnt.kcscbackend.admin.standards.service; + +import com.dbnt.kcscbackend.admin.standards.entity.TnApiKey; +import com.dbnt.kcscbackend.admin.standards.repository.ApiKeyRepository; +import lombok.RequiredArgsConstructor; +import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +@RequiredArgsConstructor +public class AdminApiService extends EgovAbstractServiceImpl { + private final ApiKeyRepository apiKeyRepository; + + public Map selectApiList() { + Map resultMap = new HashMap<>(); + + long totalRecordCount = apiKeyRepository.count(); // 전체 레코드 수 가져오기 + List apiList = apiKeyRepository.findAllByOrderByEndDtDesc(); // 개인 정보 로그 리스트 가져오기 + + resultMap.put("resultCnt", String.valueOf(totalRecordCount)); // 개수를 resultMap에 추가 + resultMap.put("resultList", apiList); // 결과를 resultMap에 추가 + + return resultMap; + } + + public TnApiKey getApiKeyById(String userId) { return apiKeyRepository.findById(userId).orElse(null); } + + @Transactional + public String modifyApi(TnApiKey tnApiKey) { + try { + apiKeyRepository.save(tnApiKey); + return "API key updated successfully"; + } catch (Exception e) { + return "Failed to update API key"; + } + } + + public List selectApiDailyCount(String UserId) { + return apiKeyRepository.selectCountApiDaily(UserId); + } // 일자별 API 요청횟수 + +} From 903ef68f86948ca589cb499c2da41458a1f50611 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EC=84=9D=20=EC=B5=9C?= Date: Fri, 26 Jan 2024 17:53:28 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=EA=B1=B4=EC=84=A4=EA=B8=B0=EC=A4=80?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EA=B2=80=EC=83=89=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=9E=91=EC=97=85=EC=A4=91.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/EgovHeader.jsx | 26 ++- .../src/constants/url.js | 4 +- .../src/css/component.css | 4 +- .../{ => list}/StandardCodeList.jsx | 154 ++++++++---------- .../{ => list}/StandardCodeListModal.js | 0 .../{ => viewer}/BookmarkModal.js | 2 +- .../standardCode/{ => viewer}/Sb.style.js | 0 .../pages/standardCode/{ => viewer}/SbItem.js | 0 .../standardCode/{ => viewer}/Vw.style.js | 0 .../pages/standardCode/{ => viewer}/viewer.js | 8 +- .../{ => viewer}/viwerComponents.js | 2 +- .../src/routes/index.jsx | 5 +- 12 files changed, 100 insertions(+), 105 deletions(-) rename egovframe-template-simple-react-contribution/src/pages/standardCode/{ => list}/StandardCodeList.jsx (85%) rename egovframe-template-simple-react-contribution/src/pages/standardCode/{ => list}/StandardCodeListModal.js (100%) rename egovframe-template-simple-react-contribution/src/pages/standardCode/{ => viewer}/BookmarkModal.js (98%) rename egovframe-template-simple-react-contribution/src/pages/standardCode/{ => viewer}/Sb.style.js (100%) rename egovframe-template-simple-react-contribution/src/pages/standardCode/{ => viewer}/SbItem.js (100%) rename egovframe-template-simple-react-contribution/src/pages/standardCode/{ => viewer}/Vw.style.js (100%) rename egovframe-template-simple-react-contribution/src/pages/standardCode/{ => viewer}/viewer.js (99%) rename egovframe-template-simple-react-contribution/src/pages/standardCode/{ => viewer}/viwerComponents.js (99%) diff --git a/egovframe-template-simple-react-contribution/src/components/EgovHeader.jsx b/egovframe-template-simple-react-contribution/src/components/EgovHeader.jsx index 41f7132..a1b898f 100644 --- a/egovframe-template-simple-react-contribution/src/components/EgovHeader.jsx +++ b/egovframe-template-simple-react-contribution/src/components/EgovHeader.jsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useState} from 'react'; import { Link, NavLink, useNavigate } from 'react-router-dom'; import * as EgovNet from 'api/egovFetch'; @@ -13,6 +13,7 @@ function EgovHeader({ loginUser, onChangeLogin }) { console.group("EgovHeader"); console.log("[Start] EgovHeader ------------------------------"); + const [menuDiv, setMenuDiv] = useState(false); const accessToken = getLocalItem('accessToken'); const userInfo = parseJwt(accessToken); const sessionUserId = userInfo?.id; @@ -56,9 +57,15 @@ function EgovHeader({ loginUser, onChangeLogin }) { ); } + function allMenuControl(){ + setMenuDiv(!menuDiv); + } + console.log("------------------------------EgovHeader [End]"); console.groupEnd("EgovHeader"); + + return ( //
@@ -71,7 +78,8 @@ function EgovHeader({ loginUser, onChangeLogin }) {

주메뉴

    -
  • (isActive ? "cur" : "")}>사이트소개
  • +
  • (isActive ? "cur" : "")}>건설기준코드
  • + {/*
  • (isActive ? "cur" : "")}>사이트소개
  • */}
  • (isActive ? "cur" : "")}>정보마당
  • (isActive ? "cur" : "")}>고객지원
  • (isActive ? "cur" : "")}>알림마당
  • @@ -98,17 +106,24 @@ function EgovHeader({ loginUser, onChangeLogin }) { {/* */} {/* */} -
    +
    {/* */} -
    +

    전체메뉴

    +

    건설기준코드

    +
      +
    • (isActive ? "cur" : "")}>건설기준코드 안내
    • +
    • (isActive ? "cur" : "")}>건설기준코드 검색
    • +
    +
    + {/*

    사이트소개

    • (isActive ? "cur" : "")}>소개
    • @@ -116,7 +131,8 @@ function EgovHeader({ loginUser, onChangeLogin }) {
    • (isActive ? "cur" : "")}>조직소개
    • (isActive ? "cur" : "")}>찾아오시는 길
    -
    +
    */} +

    정보마당

      diff --git a/egovframe-template-simple-react-contribution/src/constants/url.js b/egovframe-template-simple-react-contribution/src/constants/url.js index d36fd9e..8597ffd 100644 --- a/egovframe-template-simple-react-contribution/src/constants/url.js +++ b/egovframe-template-simple-react-contribution/src/constants/url.js @@ -119,7 +119,9 @@ const URL = { ADMIN__LOGS__FILE_DOWNLOAD_STATUS : "/admin/logs/file-download-status", // 위원회 관리/파일 다운현황 //기준코드 - STANDARD_CODE_LIST : "/standardCode/list/:listCode", //건설기준코드/리스트 + STANDARD_CODE_INFO : "/standardCode/info", + STANDARD_CODE_LIST : "/standardCode/list", //건설기준코드/리스트 + STANDARD_CODE_LIST_LINK : "/standardCode/list/:listCode", //건설기준코드/리스트 STANDARD_CODE_DETAIL : "/standardCode/detail", //건설기준코드/리스트 STANDARD_CODE_VIEWER : "/standardCode/viewer", //건설기준코드/뷰어 STANDARD_CODE_VIEWER_LINK : "/standardCode/viewer/:linkedDocCode", //건설기준코드/뷰어/새 창 링크 diff --git a/egovframe-template-simple-react-contribution/src/css/component.css b/egovframe-template-simple-react-contribution/src/css/component.css index dd27ca4..1dc342c 100644 --- a/egovframe-template-simple-react-contribution/src/css/component.css +++ b/egovframe-template-simple-react-contribution/src/css/component.css @@ -187,7 +187,7 @@ /* Condition */ -.condition {padding: 10px; border: 1px solid #dde2e5; border-radius: 10px; font-size: 0; text-align: center;} /* changed by lim padding: 26px;*/ +.condition {padding: 10px; border: 1px solid #dde2e5; border-radius: 10px; text-align: center;} /* changed by lim padding: 26px;*/ .condition > ul, .condition > ul li {display: inline-block; vertical-align: top;} .condition > ul li + li {margin-left: 20px;} @@ -246,7 +246,7 @@ select::-ms-expand {display:none;} /* 건설기준코드list 설계기준 표준시방서 전문시방서 통합 다운로드 탭 */ .right_col {display: flex; justify-content: space-between; align-items: center;} .mini_board ul {display: flex; list-style: none; padding: 0; margin: 0;} -.tab {padding: 10px; margin-right: 10px; cursor: pointer; border: 1px solid #ccc; border-radius: 5px; transition: background-color 0.3s;} +.tab {padding: 5px 10px; margin-right: 10px; cursor: pointer; border: 1px solid #ccc; border-radius: 5px; transition: background-color 0.3s;} .tab:hover {background-color: #f0f0f0;} .active {background-color: #007bff; color: #fff;} diff --git a/egovframe-template-simple-react-contribution/src/pages/standardCode/StandardCodeList.jsx b/egovframe-template-simple-react-contribution/src/pages/standardCode/list/StandardCodeList.jsx similarity index 85% rename from egovframe-template-simple-react-contribution/src/pages/standardCode/StandardCodeList.jsx rename to egovframe-template-simple-react-contribution/src/pages/standardCode/list/StandardCodeList.jsx index b80f276..d742d88 100644 --- a/egovframe-template-simple-react-contribution/src/pages/standardCode/StandardCodeList.jsx +++ b/egovframe-template-simple-react-contribution/src/pages/standardCode/list/StandardCodeList.jsx @@ -8,13 +8,52 @@ import {AiFillFileMarkdown, AiFillStar} from "react-icons/ai"; function StandardCodeList(props) { const {listCode} = useParams(); - const [show, setshow] = useState(false); - const [groupseq, setgroupseq] = useState(); + const [show, setShow] = useState(false); + const [groupSeq, setgroupSeq] = useState(); - function showhandling(e) { + console.group("StandardCodeList"); + console.log("[Start] StandardCodeList ------------------------------"); + console.log("StandardCodeList [props] : ", props); + console.log("listcode----------------------------" + listCode); + + const location = useLocation(); + console.log("StandardCodeList [location] : ", location); + + const category1Ref = useRef(); + const category2Ref = useRef(); + const category3Ref = useRef(); + const wrdRef = useRef(); + + // eslint-disable-next-line no-unused-vars + const [searchCondition, setSearchCondition] = useState(location.state?.searchCondition || { + pageIndex: 1, + tab: listCode?.substring(0, 2), + category1: listCode?.substring(2, 4), + category2: listCode?.substring(4, 6), + searchWrd: '' + });// 기존 조회에서 접근 했을 시 || 신규로 접근 했을 시 + const [masterBoard, setMasterBoard] = useState({}); + + /* 검색기능 추가 변수*/ + const [listData, setlistData] = useState([]); + const [filterData, setFilterData] = useState(''); + const [category1List, setCategory1List] = useState([]); + const [category2List, setCategory2List] = useState([]); + const [category3List, setCategory3List] = useState([]); + const [resultCnt, setResultCnt] = useState(0); + + /* 탭 */ + const [activeTab, setActiveTab] = useState(10); + const [subTabsVisible, setSubTabsVisible] = useState(false); + + function close() { + setShow(false); + } + + function showHandling(e) { const param = e.currentTarget.dataset; - const groupseq = param.groupseq; - console.log(groupseq); + const groupSeq = param.groupSeq; + console.log(groupSeq); EgovNet.requestFetch( '/standardCode/codeListModal.do', { @@ -23,7 +62,7 @@ function StandardCodeList(props) { 'Content-type': 'application/json' }, body: JSON.stringify( - groupseq + groupSeq ) }, (resp) => { console.log(resp + "------------------------resp") @@ -50,52 +89,14 @@ function StandardCodeList(props) { ) } - setgroupseq(); + setgroupSeq(); } ) - setshow(true); + setShow(true); } - function close() { - setshow(false); - } - - console.group("StandardCodeList"); - console.log("[Start] StandardCodeList ------------------------------"); - console.log("StandardCodeList [props] : ", props); - console.log("listcode----------------------------" + listCode); - - const location = useLocation(); - console.log("StandardCodeList [location] : ", location); - - const category1Ref = useRef(); - const category2Ref = useRef(); - const category3Ref = useRef(); - const wrdRef = useRef(); - - // eslint-disable-next-line no-unused-vars - const [searchCondition, setSearchCondition] = useState(location.state?.searchCondition || { - pageIndex: 1, - tab: listCode.substring(0, 2), - category1: listCode.substring(2, 4), - category2: listCode.substring(4, 6), - searchWrd: '' - });// 기존 조회에서 접근 했을 시 || 신규로 접근 했을 시 - const [masterBoard, setMasterBoard] = useState({}); - - /* 검색기능 추가 변수*/ - const [listdata, setlistdata] = useState([]); - const [filterData, setfilterData] = useState(''); - const [category1List, setCategory1List] = useState([]); - const [category2List, setCategory2List] = useState([]); - const [category3List, setCategory3List] = useState([]); - const [resultCnt, setResultCnt] = useState(0); - - /* 탭 */ - const [activeTab, setActiveTab] = useState(10); - const [subTabsVisible, setSubTabsVisible] = useState(false); - + const handleTabClick = (tabName) => { setActiveTab(tabName); @@ -135,7 +136,7 @@ function StandardCodeList(props) { (resp) => { setMasterBoard(resp.result.tnDocumentInfo); /*검색을 위한 리스트 state에 저장*/ - setlistdata(resp.result.resultList); + setlistData(resp.result.resultList); setCategory1List(resp.result.category1List); setCategory2List(resp.result.category2List); setCategory3List(resp.result.category3List); @@ -159,49 +160,31 @@ function StandardCodeList(props) { return (
      - {/* */}
      • Home
      • 건설기준코드
      • -
      • {masterBoard && masterBoard.bbsNm}
      • +
      • 건설기준코드 검색
      - {/* */} -
      - {/* */} - - {/* */} -
      - {/* */} -
      -

      건설기준코드

      +

      건설기준코드 검색

      - -

      설계기준, 표준시방서 내용을 열람할 수 있습니다.

      - - {/* */}
        -
      • - - { - setfilterData(e.target.value); - }} - /> - - +
      • +
        handleTabClick(10)}>설계기준
        +
      • +
      • +
        handleTabClick(20)}>표준시방서
        +
      • +
      • +
        handleTabClick(40)}>전문시방서
      • +
      • +
        통합 다운로드
        +
      {/* */} -
      -
      -
        -
        handleTabClick(10)}>설계기준
        -
        handleTabClick(20)}>표준시방서
        -
        handleTabClick(40)}>전문시방서
        -
        통합 다운로드
        -
      -
      -
      {subTabsVisible && (
      @@ -315,7 +291,7 @@ function StandardCodeList(props) {
      {/*검색기능 filterData가 없는경우 모든 데이터 출력*/} - {listdata.filter(item => { + {listData.filter(item => { if (item.groupNm.includes(filterData)) { return item } @@ -327,7 +303,7 @@ function StandardCodeList(props) {
      {item.middleCategory}
      {item.kcscCd}
      {item.groupNm}
      - +
      {item.contentcount > 0 ? 내용보기 : null}
      {item.docFileGrpId == null ? null : }
      @@ -343,7 +319,7 @@ function StandardCodeList(props) { {/* */} {/* */} - + {/* */} diff --git a/egovframe-template-simple-react-contribution/src/pages/standardCode/StandardCodeListModal.js b/egovframe-template-simple-react-contribution/src/pages/standardCode/list/StandardCodeListModal.js similarity index 100% rename from egovframe-template-simple-react-contribution/src/pages/standardCode/StandardCodeListModal.js rename to egovframe-template-simple-react-contribution/src/pages/standardCode/list/StandardCodeListModal.js diff --git a/egovframe-template-simple-react-contribution/src/pages/standardCode/BookmarkModal.js b/egovframe-template-simple-react-contribution/src/pages/standardCode/viewer/BookmarkModal.js similarity index 98% rename from egovframe-template-simple-react-contribution/src/pages/standardCode/BookmarkModal.js rename to egovframe-template-simple-react-contribution/src/pages/standardCode/viewer/BookmarkModal.js index cb66c8c..38b8add 100644 --- a/egovframe-template-simple-react-contribution/src/pages/standardCode/BookmarkModal.js +++ b/egovframe-template-simple-react-contribution/src/pages/standardCode/viewer/BookmarkModal.js @@ -1,6 +1,6 @@ import {React, useCallback, useEffect, useState} from "react"; import Modal from "react-bootstrap/Modal"; -import * as EgovNet from "../../api/egovFetch"; +import * as EgovNet from "../../../api/egovFetch"; import {VwDiv} from "./Vw.style"; import Col from "react-bootstrap/Col"; import Row from "react-bootstrap/Row"; diff --git a/egovframe-template-simple-react-contribution/src/pages/standardCode/Sb.style.js b/egovframe-template-simple-react-contribution/src/pages/standardCode/viewer/Sb.style.js similarity index 100% rename from egovframe-template-simple-react-contribution/src/pages/standardCode/Sb.style.js rename to egovframe-template-simple-react-contribution/src/pages/standardCode/viewer/Sb.style.js diff --git a/egovframe-template-simple-react-contribution/src/pages/standardCode/SbItem.js b/egovframe-template-simple-react-contribution/src/pages/standardCode/viewer/SbItem.js similarity index 100% rename from egovframe-template-simple-react-contribution/src/pages/standardCode/SbItem.js rename to egovframe-template-simple-react-contribution/src/pages/standardCode/viewer/SbItem.js diff --git a/egovframe-template-simple-react-contribution/src/pages/standardCode/Vw.style.js b/egovframe-template-simple-react-contribution/src/pages/standardCode/viewer/Vw.style.js similarity index 100% rename from egovframe-template-simple-react-contribution/src/pages/standardCode/Vw.style.js rename to egovframe-template-simple-react-contribution/src/pages/standardCode/viewer/Vw.style.js diff --git a/egovframe-template-simple-react-contribution/src/pages/standardCode/viewer.js b/egovframe-template-simple-react-contribution/src/pages/standardCode/viewer/viewer.js similarity index 99% rename from egovframe-template-simple-react-contribution/src/pages/standardCode/viewer.js rename to egovframe-template-simple-react-contribution/src/pages/standardCode/viewer/viewer.js index 312283c..7645660 100644 --- a/egovframe-template-simple-react-contribution/src/pages/standardCode/viewer.js +++ b/egovframe-template-simple-react-contribution/src/pages/standardCode/viewer/viewer.js @@ -1,7 +1,7 @@ import React, { useState, useEffect, useCallback } from 'react'; import { useLocation, useParams } from 'react-router-dom'; import SbItem from './SbItem' -import Loading from '../../components/Loading' +import Loading from '../../../components/Loading' import BookmarkModal from './BookmarkModal'; import {SbContainer} from './Sb.style' import {VwDiv, VwPtag} from './Vw.style' @@ -10,9 +10,9 @@ import Row from 'react-bootstrap/Row'; import Col from 'react-bootstrap/Col'; import Modal from 'react-bootstrap/Modal'; import * as EgovNet from 'api/egovFetch'; -import {getLocalItem} from "../../utils/storage"; -import CODE from "../../constants/code"; -import {parseJwt} from "../../utils/parseJwt"; +import {getLocalItem} from "../../../utils/storage"; +import CODE from "../../../constants/code"; +import {parseJwt} from "../../../utils/parseJwt"; function CodeViewer(props) { const [treeLoading, setTreeLoading] = useState(true); diff --git a/egovframe-template-simple-react-contribution/src/pages/standardCode/viwerComponents.js b/egovframe-template-simple-react-contribution/src/pages/standardCode/viewer/viwerComponents.js similarity index 99% rename from egovframe-template-simple-react-contribution/src/pages/standardCode/viwerComponents.js rename to egovframe-template-simple-react-contribution/src/pages/standardCode/viewer/viwerComponents.js index df95218..1f986fb 100644 --- a/egovframe-template-simple-react-contribution/src/pages/standardCode/viwerComponents.js +++ b/egovframe-template-simple-react-contribution/src/pages/standardCode/viewer/viwerComponents.js @@ -1,4 +1,4 @@ -import * as EgovNet from "../../api/egovFetch"; +import * as EgovNet from "../../../api/egovFetch"; import React, {useEffect, useState} from "react"; import SbItem from "./SbItem"; import {Col, Row} from "react-bootstrap"; diff --git a/egovframe-template-simple-react-contribution/src/routes/index.jsx b/egovframe-template-simple-react-contribution/src/routes/index.jsx index 27837f7..f5cb5a0 100644 --- a/egovframe-template-simple-react-contribution/src/routes/index.jsx +++ b/egovframe-template-simple-react-contribution/src/routes/index.jsx @@ -109,11 +109,11 @@ import AdminLogsFileDownloadStatus from 'pages/admin/logs/FileDownloadStatus'; //건설기준코드 -import CodeViewer from 'pages/standardCode/viewer'; +import CodeViewer from 'pages/standardCode/viewer/viewer'; import * as EgovNet from 'api/egovFetch'; // jwt토큰 위조 검사 때문에 추가 import initPage from 'js/ui'; -import StandardCodeList from "../pages/standardCode/StandardCodeList"; +import StandardCodeList from "../pages/standardCode/list/StandardCodeList"; const RootRoutes = () => { //useLocation객체를 이용하여 정규표현식을 사용한 /admin/~ 으로 시작하는 경로와 비교에 사용(아래 1줄) */} @@ -326,6 +326,7 @@ const SecondRoutes = () => { {/*기준코드리스트*/} } /> + } />