Compare commits

...

8 Commits

Author SHA1 Message Date
thkim 020739c98a feat: 관리자 화면 상단 우측 location 부분 수정 건
K) 관리자 - 컨텐츠관리 - 팝업관리
    K) 관리자 - 컨텐츠관리 - 건설기준연구 관리
    K) 관리자 - 환경설정 - 위원회 코드관리
    K) 관리자 - 위원회관리 - 진행현황 관리
    K) 관리자 - 위원회관리 - 위원회 일정관리
    K) 관리자 - 컨텐츠관리 - 설문관리
2024-01-08 09:23:45 +09:00
thkim abbbbddcb0 Merge branch 'thkim' 2024-01-05 18:01:46 +09:00
강석 최 56a71cb934 Merge branch 'master' of http://118.219.150.34:50501/DBNT/kcscDev 2024-01-05 18:00:04 +09:00
강석 최 a839bd5708 페이지네이션 주석 삭제.
관리자 좌측 메뉴 자동화.
2024-01-05 18:00:00 +09:00
Lim\jun 9b5e5f51b0 개인정보 front-end 수정 2024-01-05 17:56:07 +09:00
thkim 29690fdf38 Merge branch 'thkim' 2024-01-05 17:49:49 +09:00
유민형 d05a5864c4 대시보드 사용자 접속현황 그래프 월별차트보기 추가 2024-01-05 17:39:51 +09:00
강석 최 5cd1c3148d 개인정보 로그현황 페이지네이션 관련 소스 수정 2024-01-05 17:38:31 +09:00
22 changed files with 169 additions and 166 deletions

View File

@ -36,7 +36,7 @@ function EgovPaging({pagination, moveToPage}) {
}
if(pagination.endNum!=pagination.maxNum){
//
const nextPageIndex = pagination.pageIndex+10 < pagination.maxNum?pagination.maxNum:(pagination.pageIndex-10)
const nextPageIndex = pagination.pageIndex+10 > pagination.maxNum?pagination.maxNum:(pagination.pageIndex+10)
paginationTag.push(<li key="np" className="btn">
<button onClick={e => {moveToPage(nextPageIndex)}} className="next">다음</button>
</li>);
@ -46,59 +46,6 @@ function EgovPaging({pagination, moveToPage}) {
<button onClick={e => {moveToPage(pagination.maxNum)}} className="last"></button>
</li>);
}
/*const currentPageNo = pagination.currentPageNo;
const pageSize = pagination.pageSize;
const totalRecordCount = pagination.contentCnt;
const recordCountPerPage = pagination.rowCnt;
const totalPageCount = Math.ceil(totalRecordCount / recordCountPerPage);
const currentFirstPage = Math.floor((currentPageNo - 1) / pageSize) * pageSize + 1;
let currentLastPage = currentFirstPage + pageSize - 1;
currentLastPage = (currentLastPage > totalPageCount) ? totalPageCount : currentLastPage;
if (totalPageCount > pageSize) {
//
const firstPageTag = <li key="fp" className="btn">
<button onClick={e => {moveToPage(1)}} className="first">처음</button></li>;
paginationTag.push(firstPageTag);
//
const prevPageIndex = (currentPageNo - 1 > 0) ? currentPageNo - 1 : 1;
const previousPageTag = <li key="pp" className="btn">
<button onClick={e => {moveToPage(prevPageIndex)}} className="prev">이전</button></li>;
paginationTag.push(previousPageTag);
}
for (let i = currentFirstPage; i <= currentLastPage; i++) {
if (i === currentPageNo) {
//
const currentPage = <li key={i}>
<button className="cur">{i}</button>
</li>;
paginationTag.push(currentPage);
} else {
//
const otherPage = <li key={i}>
<button onClick={e => {moveToPage(i)}}>{i}</button>
</li>;
console.log("@@@ otherpage : " + otherPage);
paginationTag.push(otherPage);
}
}
if (totalPageCount > pageSize) {
//
const nextPageIndex = (currentLastPage + 1 < totalPageCount) ? currentLastPage + 1 : totalPageCount;
const nextPageTag = <li key="np" className="btn">
<button onClick={e => {moveToPage(nextPageIndex)}} className="next">다음</button>
</li>;
paginationTag.push(nextPageTag);
//
const lastPageTag = <li key="lp" className="btn">
<button onClick={e => {moveToPage(totalPageCount)}} className="last"></button></li>;
paginationTag.push(lastPageTag);
}*/
}
console.log("paginationTag", paginationTag);
console.groupEnd("EgovPaging");

View File

@ -1,10 +1,40 @@
import React from 'react';
import { useLocation } from 'react-router-dom';
import { NavLink } from 'react-router-dom';
import URL from 'constants/url';
import {Accordion} from "react-bootstrap";
function EgovLeftNavAdmin({activeKey}) {
function EgovLeftNavAdmin(props) {
const location = useLocation();
const getMiddleFolder = (url) => { //
const parts = url.split('/').filter(Boolean); // '/'
if (parts.length >= 2) {
return parts[1]; //
}
return null;
};
const activeFolder = getMiddleFolder(location.pathname);
let activeKey;
if (activeFolder === "config") {
activeKey = "0";
} else if (activeFolder === "users") {
activeKey = "1";
} else if (activeFolder === "boards") {
activeKey = "2";
} else if (activeFolder === "standards") {
activeKey = "3";
} else if (activeFolder === "contents") {
activeKey = "4";
} else if (activeFolder === "committee") {
activeKey = "5";
} else if (activeFolder === "logs") {
activeKey = "6";
} else {
activeKey = "7";
}
return (
<div className="nav">
<div className="inner">
@ -62,7 +92,7 @@ function EgovLeftNavAdmin({activeKey}) {
<ul className="menu4">
<li><NavLink to={URL.ADMIN__CONTENTS__SURVEY} className={({ isActive }) => (isActive ? "cur" : "")}>설문 관리</NavLink></li>
<li><NavLink to={URL.ADMIN__CONTENTS__POP_UP} className={({ isActive }) => (isActive ? "cur" : "")}>팝업 관리</NavLink></li>
<li><NavLink to={URL.ADMIN__CONTENTS__STANDARD_RESEARCH} className={({ isActive }) => (isActive ? "cur" : "")}>건설기준연구 관리</NavLink></li>
<li><NavLink to={URL.ADMIN__CONTENTS__STANDARDS_RESEARCH} className={({ isActive }) => (isActive ? "cur" : "")}>건설기준연구 관리</NavLink></li>
<li><NavLink to={URL.ADMIN__CONTENTS__TEXT_MESSAGES} className={({ isActive }) => (isActive ? "cur" : "")}>문자 발송</NavLink></li>
</ul>
</Accordion.Body>

View File

@ -15,6 +15,7 @@ function ProgressStatus(props) {
<li><Link to={URL.MAIN} className="home">Home</Link></li>
<li><Link to={URL.ADMIN}>사이트 관리</Link></li>
<li>위원회 관리</li>
<li>진행현황 관리</li>
</ul>
</div>
)

View File

@ -187,6 +187,7 @@ function Schedules(props) {
<li><Link to={URL.MAIN} className="home">Home</Link></li>
<li><Link to={URL.ADMIN}>사이트 관리</Link></li>
<li>위원회 관리</li>
<li>위원회 일정 관리</li>
</ul>
</div>
)

View File

@ -212,6 +212,7 @@ function SchedulesEdit(props) {
<li><Link to={URL.MAIN} className="home">Home</Link></li>
<li><Link to={URL.ADMIN}>사이트 관리</Link></li>
<li>위원회 관리</li>
<li>위원회 일정 관리</li>
</ul>
</div>
{/* <!--// Location --> */}

View File

@ -30,7 +30,7 @@ function BaseCodeMgt(props) {
</div>
<div className="layout">
{/* <!-- Navigation --> */}
<EgovLeftNav activeKey={"0"}></EgovLeftNav>
<EgovLeftNav />
<div className="contents NOTICE_LIST" id="contents">
{/* <!-- 본문 --> */}

View File

@ -15,6 +15,7 @@ function CommitteeCodeMgt(props) {
<li><Link to={URL.MAIN} className="home">Home</Link></li>
<li><Link to={URL.ADMIN}>사이트 관리</Link></li>
<li>환경 설정</li>
<li>위원회 코드 관리</li>
</ul>
</div>
)

View File

@ -16,6 +16,7 @@ function PopUp(props) {
<li><Link to={URL.MAIN} className="home">Home</Link></li>
<li><Link to={URL.ADMIN}>사이트 관리</Link></li>
<li>컨텐츠 관리</li>
<li>팝업 관리</li>
</ul>
</div>
)

View File

@ -15,6 +15,7 @@ function StandardResearch(props) {
<li><Link to={URL.MAIN} className="home">Home</Link></li>
<li><Link to={URL.ADMIN}>사이트 관리</Link></li>
<li>컨텐츠 관리</li>
<li>건설기준연구 관리</li>
</ul>
</div>
)

View File

@ -15,6 +15,7 @@ function Survey(props) {
<li><Link to={URL.MAIN} className="home">Home</Link></li>
<li><Link to={URL.ADMIN}>사이트 관리</Link></li>
<li>컨텐츠 관리</li>
<li>설문 관리</li>
</ul>
</div>
)

View File

@ -48,8 +48,8 @@ function PrivacyConnections(props) {
listTag.push(<p className="no_data" key="0">데이터가 없습니다.</p>); //
const resultCnt = parseInt(resp.result.resultCnt);
const currentPageNo = resp.result.paginationInfo.currentPageNo;
const pageSize = resp.result.paginationInfo.pageSize;
const currentPageNo = resp.result.paginationInfo.pageIndex;
const pageSize = resp.result.paginationInfo.rowCnt;
const startIndex = (currentPageNo - 1) * pageSize;
const endIndex = Math.min(startIndex + pageSize, resultCnt);

View File

@ -216,10 +216,14 @@ function EgovAdminScheduleList(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [scheduleList]);
const [isDailyChart, setChart] = useState(true);
const getDailyUserLogList = useCallback(() => {
console.groupCollapsed("EgovAdminScheduleList.getDailyUserLogList()");
const dailyUserLogListURL = '/admin/dashboard/daily-user-log-list';
console.log("@@@ isDailyChart : " + isDailyChart);
const dailyUserLogListURL = isDailyChart ? '/admin/dashboard/daily-user-log-list' : '/admin/dashboard/monthly-user-log-list';
const requestOptions = {
method: "GET",
@ -239,12 +243,29 @@ function EgovAdminScheduleList(props) {
}
);
console.groupEnd("EgovAdminScheduleList.getDailyUserLogList()");
}, []);
}, [isDailyChart]);
useEffect(() => {
getDailyUserLogList();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
}, [isDailyChart]);
const handleChartToggle = () => {
setChart(!isDailyChart);
};
const ChartToggle = ({onToggle}) => {
const handleToggle = () => {
onToggle(!isDailyChart);
};
return (
<button onClick={handleToggle}>
{isDailyChart ? '월별차트보기' : '일별차트보기'}
</button>
)
}
const data = dailyUserLogList.map(item => ({
logDt: item.logDt,
@ -253,35 +274,12 @@ function EgovAdminScheduleList(props) {
amt: item.pcCnt,
}));
const getIntroOfPage = (label) => {
if (label === 'Page A') {
return "Page A is about men's clothing";
}
if (label === 'Page B') {
return "Page B is about women's dress";
}
if (label === 'Page C') {
return "Page C is about women's bag";
}
if (label === 'Page D') {
return 'Page D is about household goods';
}
if (label === 'Page E') {
return 'Page E is about food';
}
if (label === 'Page F') {
return 'Page F is about baby food';
}
return '';
};
const CustomTooltip = ({active, payload, label}) => {
if (active && payload && payload.length) {
return (
<div className="custom-tooltip">
<p className="desc">사용자 접속 현황</p>
<p className="label">{`${label} : ${payload[0].value}`}</p>
<p className="intro">{getIntroOfPage(label)}</p>
</div>
);
}
@ -289,7 +287,7 @@ function EgovAdminScheduleList(props) {
return null;
};
class Example extends PureComponent {
class UserLogChart extends PureComponent {
static demoUrl = 'https://codesandbox.io/s/tooltip-with-customized-content-lyxvs';
render() {
@ -341,8 +339,10 @@ function EgovAdminScheduleList(props) {
<h2 className="tit_2">일정관리</h2>
<ChartToggle isDailyChart={isDailyChart} onToggle={handleChartToggle}/>
<div style={{width: 1000, height: 300}}>
<Example/>
<UserLogChart/>
</div>
{/* <!-- 검색조건 --> */}

View File

@ -99,7 +99,7 @@ function List(props) {
</div>
<div className="layout">
{/* <!-- Navigation --> */}
<EgovLeftNav activeKey={"1"}></EgovLeftNav>
<EgovLeftNav/>
<div className="contents NOTICE_LIST" id="contents">
{/* <!-- 본문 --> */}

View File

@ -293,7 +293,7 @@ const SecondRoutes = () => {
{/* 관리자 - 컨텐츠 관리 */}
<Route path={URL.ADMIN__CONTENTS__SURVEY} element={<AdminContentsSurvey />} />
<Route path={URL.ADMIN__CONTENTS__POP_UP} element={<AdminContentsPopUp />} />
<Route path={URL.ADMIN__CONTENTS__STANDARD_RESEARCH} element={<AdminContentsStandardResearch />} />
<Route path={URL.ADMIN__CONTENTS__STANDARDS_RESEARCH} element={<AdminContentsStandardResearch />} />
<Route path={URL.ADMIN__CONTENTS__TEXT_MESSAGES} element={<AdminContentsTextMessages />} />
{/* 관리자 - 위원회 관리 */}

View File

@ -1,5 +1,6 @@
package com.dbnt.kcscbackend.admin.dashboard;
import com.dbnt.kcscbackend.admin.dashboard.dto.MonthlyUserLogDTO;
import com.dbnt.kcscbackend.admin.dashboard.service.AdminDashboardService;
import com.dbnt.kcscbackend.config.common.BaseController;
import com.dbnt.kcscbackend.config.common.ResultVO;
@ -13,9 +14,12 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigInteger;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@RestController
@RequiredArgsConstructor
@ -26,9 +30,9 @@ public class AdminDashboardController extends BaseController {
private final AdminDashboardService adminDashboardService;
@Operation(
summary = "기본코드 그룹 조회",
description = "기본코드 그룹 조회",
tags = {"AdminConfigController"}
summary = "일별 사용자 현황 차트 조회",
description = "일별 사용자 현황 차트 조회",
tags = {"AdminDashboardController"}
)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "조회 성공"),
@ -42,9 +46,6 @@ public class AdminDashboardController extends BaseController {
// 현재 날짜
// todo endDate 뒤에 .minus 지워야함
LocalDate endDate = LocalDate.now().minusMonths(6);
System.out.println("@@@ localdate : " + endDate);
// 3개월 전 날짜 계산
LocalDate startDate = endDate.minusMonths(3);
@ -52,4 +53,34 @@ public class AdminDashboardController extends BaseController {
resultVO.setResult(resultMap);
return resultVO;
}
@Operation(
summary = "월별 사용자 현황 차트 조회",
description = "월별 사용자 현황 차트 조회",
tags = {"AdminDashboardController"}
)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "조회 성공"),
@ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
})
@RequestMapping(method = RequestMethod.GET, value = "/monthly-user-log-list", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResultVO getMonthlyUserLogList() throws Exception {
ResultVO resultVO = new ResultVO();
Map<String, Object> resultMap = new HashMap<>();
// 현재 날짜
// todo endDate 뒤에 .minus 지워야함
LocalDate endDate = LocalDate.now().minusMonths(6);
// 3개월 전 날짜 계산
LocalDate startDate = endDate.minusMonths(3);
List<Object[]> result = adminDashboardService.selectMonthlyUserLogList(startDate, endDate);
List<MonthlyUserLogDTO> monthlyUserLogDTOList = result.stream()
.map(row -> new MonthlyUserLogDTO((String) row[0], (BigInteger) row[1]))
.collect(Collectors.toList());
resultMap.put("dailyUserLogList", monthlyUserLogDTOList);
resultVO.setResult(resultMap);
return resultVO;
}
}

View File

@ -0,0 +1,22 @@
package com.dbnt.kcscbackend.admin.dashboard.dto;
import com.dbnt.kcscbackend.admin.dashboard.entity.TnDailyUserLog;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.ToString;
import java.math.BigInteger;
import java.time.LocalDate;
@Data
@AllArgsConstructor
@ToString
public class MonthlyUserLogDTO {
private String logDt;
private BigInteger logCnt;
public MonthlyUserLogDTO(Object[] row) {
this.logDt = (String) row[0];
this.logCnt = (BigInteger) row[1];
}
}

View File

@ -7,6 +7,7 @@ import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.*;
import java.math.BigInteger;
import java.time.LocalDate;
@Getter
@ -33,4 +34,6 @@ public class TnDailyUserLog {
@Column(name = "pc_cnt")
private Integer pcCnt;
}

View File

@ -2,10 +2,21 @@ package com.dbnt.kcscbackend.admin.dashboard.repository;
import com.dbnt.kcscbackend.admin.dashboard.entity.TnDailyUserLog;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.time.LocalDate;
import java.util.List;
public interface TnDailyUserLogRepository extends JpaRepository<TnDailyUserLog, Long> {
List<TnDailyUserLog> findByLogDtBetweenOrderByLogDt(LocalDate startDate, LocalDate endDate);
@Query(value = "SELECT TO_CHAR(log_dt, 'YYYYMM') as log_dt, "
+ "SUM(log_cnt) as log_cnt "
+ "FROM tn_daily_user_log "
+ "WHERE log_dt BETWEEN :startDate AND :endDate "
+ "GROUP BY TO_CHAR(log_dt, 'YYYYMM') "
+ "ORDER BY log_dt", nativeQuery = true)
List<Object[]> selectMonthlyUserLogStatistics(@Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate);
}

View File

@ -17,4 +17,8 @@ public class AdminDashboardService extends EgovAbstractServiceImpl {
public List<TnDailyUserLog> selectDailyUserLogList(LocalDate startDate, LocalDate endDate) {
return tnDailyUserLogRepository.findByLogDtBetweenOrderByLogDt(startDate, endDate);
}
public List<Object[]> selectMonthlyUserLogList(LocalDate startDate, LocalDate endDate) {
return tnDailyUserLogRepository.selectMonthlyUserLogStatistics(startDate, endDate);
}
}

View File

@ -49,25 +49,12 @@ public class AdminLogsController extends BaseController {
throws Exception {
ResultVO resultVO = new ResultVO();
thPrivacyLog.setQueryInfo();
Map<String, Object> resultMap = adminLogsService.selectPrivacyList();
PaginationInfo paginationInfo = new PaginationInfo();
paginationInfo.setCurrentPageNo(thPrivacyLog.getPageIndex());
paginationInfo.setRecordCountPerPage(propertyService.getInt("Globals.pageUnit"));
paginationInfo.setPageSize(propertyService.getInt("Globals.pageSize"));
thPrivacyLog.setFirstIndex(paginationInfo.getFirstRecordIndex());
thPrivacyLog.setLastIndex(paginationInfo.getLastRecordIndex());
thPrivacyLog.setRecordCountPerPage(paginationInfo.getRecordCountPerPage());
int totCnt = Integer.parseInt((String)resultMap.get("resultCnt"));
paginationInfo.setTotalRecordCount(totCnt);
// resultMap.put("resultList", adminLogsService.selectPrivacyList());
// resultMap.put("resultList", resultMap.get("resultList"));
// resultMap.put("resultCnt", totCnt);
resultMap.put("paginationInfo", paginationInfo);
thPrivacyLog.setContentCnt(totCnt);
thPrivacyLog.setPaginationInfo();
resultMap.put("paginationInfo", thPrivacyLog);
resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
resultVO.setResultMessage(ResponseCode.SUCCESS.getMessage());

View File

@ -1,6 +1,8 @@
package com.dbnt.kcscbackend.admin.logs.entity;
import java.io.Serializable;
import com.dbnt.kcscbackend.config.common.BoardParams;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.NoArgsConstructor;
@ -22,61 +24,9 @@ import java.time.LocalDateTime;
@DynamicInsert
@DynamicUpdate
@Table(name = "th_user_privacy_log")
public class ThPrivacyLog implements Serializable {
public class ThPrivacyLog extends BoardParams implements Serializable {
private static final long serialVersionUID = -3779821913760046011L;
@Transient
@Schema(description = "검색시작일")
private String searchBgnDe = "";
@Transient
@Schema(description = "검색조건")
private String searchCnd = "";
@Transient
@Schema(description = "검색종료일")
private String searchEndDe = "";
@Transient
@Schema(description = "검색단어")
private String searchWrd = "";
@Transient
@Schema(description = "정렬순서(DESC,ASC)")
private long sortOrdr = 0L;
@Transient
@Schema(description = "검색사용여부")
private String searchUseYn = "";
@Transient
@Schema(description = "현재페이지")
private int pageIndex = 1;
@Transient
@Schema(description = "페이지갯수")
private int pageUnit = 10;
@Transient
@Schema(description = "페이지사이즈")
private int pageSize = 10;
@Transient
@Schema(description = "첫페이지 인덱스")
private int firstIndex = 1;
@Transient
@Schema(description = "마지막페이지 인덱스")
private int lastIndex = 1;
@Transient
@Schema(description = "페이지당 레코드 개수")
private int recordCountPerPage = 10;
@Transient
@Schema(description = "레코드 번호")
private int rowNo = 0;
@Id
@Column(name = "upl_seq")
private Long uplSeq;

View File

@ -1,5 +1,6 @@
package com.dbnt.kcscbackend.config.common;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@ -28,6 +29,16 @@ public class BoardParams implements Serializable {
@Transient
private Integer contentCnt=0;
@Transient
@Schema(description = "검색시작일")
private String searchBgnDe = "";
@Transient
@Schema(description = "검색종료일")
private String searchEndDe = "";
@Transient
@Schema(description = "정렬순서(DESC,ASC)")
private long sortOrdr = 0L;
public void setQueryInfo(){
setFirstIndex((getPageIndex()-1)*getRowCnt());
}