Compare commits
47 Commits
98d2da2e21
...
432cad27ab
| Author | SHA1 | Date |
|---|---|---|
|
|
432cad27ab | |
|
|
a357df161d | |
|
|
ff036473d7 | |
|
|
694f0ef918 | |
|
|
bf3a460610 | |
|
|
f210629907 | |
|
|
1fd7ba0fb1 | |
|
|
cbfb9b2ca3 | |
|
|
6ca96a65ad | |
|
|
a2fcdfe569 | |
|
|
60521e4995 | |
|
|
e825207231 | |
|
|
a63a47a7b8 | |
|
|
b84bb9a7a9 | |
|
|
8e22399ec4 | |
|
|
f14ee3b03d | |
|
|
701e813fbb | |
|
|
2ec64ceac0 | |
|
|
9e3a856d23 | |
|
|
b5003f30d2 | |
|
|
7c5a94ed38 | |
|
|
3bf8cb065a | |
|
|
7a141fff89 | |
|
|
a476f3e00c | |
|
|
1f5485249b | |
|
|
1cd9cf8202 | |
|
|
94963507c4 | |
|
|
76ce7a9a36 | |
|
|
64e4b07953 | |
|
|
cdd6f726c2 | |
|
|
a7bdd5093f | |
|
|
720033ece6 | |
|
|
52e6aed96e | |
|
|
dc0046a3c1 | |
|
|
7936704abd | |
|
|
2bbd80d40b | |
|
|
ebe40f2f3e | |
|
|
33f3654222 | |
|
|
c7440cbc0d | |
|
|
f0fdfbfcbb | |
|
|
67852a87d0 | |
|
|
2ac1241ef1 | |
|
|
7136da0529 | |
|
|
d413c605cd | |
|
|
c308ec3691 | |
|
|
3657c16a15 | |
|
|
47e4fda988 |
File diff suppressed because it is too large
Load Diff
|
|
@ -3,6 +3,8 @@
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@ant-design/colors": "^6.0.0",
|
||||||
|
"@ant-design/icons": "^4.7.0",
|
||||||
"@emotion/react": "^11.11.3",
|
"@emotion/react": "^11.11.3",
|
||||||
"@emotion/styled": "^11.11.0",
|
"@emotion/styled": "^11.11.0",
|
||||||
"@material-ui/core": "^4.12.4",
|
"@material-ui/core": "^4.12.4",
|
||||||
|
|
@ -10,19 +12,25 @@
|
||||||
"@mui/icons-material": "^5.15.6",
|
"@mui/icons-material": "^5.15.6",
|
||||||
"@mui/material": "^5.14.19",
|
"@mui/material": "^5.14.19",
|
||||||
"@mui/styles": "^5.15.3",
|
"@mui/styles": "^5.15.3",
|
||||||
|
"apexcharts": "^3.45.2",
|
||||||
"bootstrap": "^5.3.2",
|
"bootstrap": "^5.3.2",
|
||||||
"date-fns": "^3.2.0",
|
"date-fns": "^3.2.0",
|
||||||
|
"prop-types": "^15.8.1",
|
||||||
"qs": "^6.11.0",
|
"qs": "^6.11.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
|
"react-apexcharts": "^1.4.0",
|
||||||
"react-bootstrap": "^2.9.0",
|
"react-bootstrap": "^2.9.0",
|
||||||
|
"react-copy-to-clipboard": "^5.1.0",
|
||||||
"react-csv": "^2.2.2",
|
"react-csv": "^2.2.2",
|
||||||
"react-datepicker": "^4.8.0",
|
"react-datepicker": "^4.8.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
"react-element-to-jsx-string": "^15.0.0",
|
||||||
"react-icons": "^4.11.0",
|
"react-icons": "^4.11.0",
|
||||||
"react-loader-spinner": "^5.4.5",
|
"react-loader-spinner": "^5.4.5",
|
||||||
"react-quill": "^2.0.0",
|
"react-quill": "^2.0.0",
|
||||||
"react-router-dom": "^6.4.0",
|
"react-router-dom": "^6.4.0",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
|
"react-syntax-highlighter": "^15.5.0",
|
||||||
"recharts": "^2.10.3",
|
"recharts": "^2.10.3",
|
||||||
"styled-components": "^6.0.9",
|
"styled-components": "^6.0.9",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
import RootRoutes from './routes';
|
import RootRoutes from './routes';
|
||||||
|
import ThemeCustomization from 'themes';
|
||||||
|
import ScrollTop from 'components/ScrollTop';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||||
|
|
@ -12,9 +14,11 @@ import './css/Custom/customMain.css'
|
||||||
function App() {
|
function App() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="wrap">
|
<ThemeCustomization>
|
||||||
<RootRoutes />
|
<ScrollTop>
|
||||||
</div>
|
<RootRoutes />
|
||||||
|
</ScrollTop>
|
||||||
|
</ThemeCustomization>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,65 +29,67 @@ export function requestFetch(url, requestOptions, handler, errorHandler) {
|
||||||
const accessToken = getLocalItem('accessToken');
|
const accessToken = getLocalItem('accessToken');
|
||||||
const sessionUser = parseJwt(accessToken);
|
const sessionUser = parseJwt(accessToken);
|
||||||
const sessionUserId = sessionUser?.id || null;
|
const sessionUserId = sessionUser?.id || null;
|
||||||
const refreshToken = getLocalItem('refreshToken');
|
|
||||||
if(sessionUserId != null){
|
if(accessToken && new Date(sessionUser.exp*1000) < new Date()){
|
||||||
if( !requestOptions['headers'] ) requestOptions['headers']={}
|
//만료된 토큰 재발급 절차 진행.
|
||||||
if( !requestOptions['headers']['Authorization'] ) requestOptions['headers']['Authorization']=null;
|
accessTokenRefresh(url, requestOptions, handler, errorHandler);
|
||||||
requestOptions['headers']['Authorization'] = accessToken;
|
}else{
|
||||||
|
if(sessionUserId != null){
|
||||||
|
if( !requestOptions['headers'] ) requestOptions['headers']={}
|
||||||
|
if( !requestOptions['headers']['Authorization'] ) requestOptions['headers']['Authorization']=null;
|
||||||
|
requestOptions['headers']['Authorization'] = accessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
//CORS ISSUE 로 인한 조치 - origin 및 credentials 추가
|
||||||
|
// origin 추가
|
||||||
|
if (!requestOptions['origin']) {
|
||||||
|
requestOptions = { ...requestOptions, origin: SERVER_URL };
|
||||||
|
}
|
||||||
|
// credentials 추가
|
||||||
|
if (!requestOptions['credentials']) {
|
||||||
|
requestOptions = { ...requestOptions, credentials: 'include' };
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch(SERVER_URL + url, requestOptions)
|
||||||
|
.then(response => {// response Stream. Not completion object
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then((resp) => {
|
||||||
|
if (Number(resp.resultCode) === Number(CODE.RCV_ERROR_AUTH)) {
|
||||||
|
alert("로그인이 해제되었습니다.")
|
||||||
|
window.location.href = "/login"
|
||||||
|
}else{
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((resp) => {
|
||||||
|
console.groupCollapsed("requestFetch.then()");
|
||||||
|
console.log("requestFetch [response] ", resp);
|
||||||
|
if (typeof handler === 'function') {
|
||||||
|
handler(resp);
|
||||||
|
} else {
|
||||||
|
console.log('egov fetch handler not assigned!');
|
||||||
|
}
|
||||||
|
console.groupEnd("requestFetch.then()");
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('There was an error!', error);
|
||||||
|
if (error === 'TypeError: Failed to fetch') {
|
||||||
|
alert("서버와의 연결이 원활하지 않습니다. 서버를 확인하세요.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof errorHandler === 'function') {
|
||||||
|
errorHandler(error);
|
||||||
|
} else {
|
||||||
|
console.error('egov error handler not assigned!');
|
||||||
|
alert("ERR : " + error.message);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
console.log("requestFetch finally end");
|
||||||
|
console.groupEnd("requestFetch");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//CORS ISSUE 로 인한 조치 - origin 및 credentials 추가
|
|
||||||
// origin 추가
|
|
||||||
if (!requestOptions['origin']) {
|
|
||||||
requestOptions = { ...requestOptions, origin: SERVER_URL };
|
|
||||||
}
|
|
||||||
// credentials 추가
|
|
||||||
if (!requestOptions['credentials']) {
|
|
||||||
requestOptions = { ...requestOptions, credentials: 'include' };
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch(SERVER_URL + url, requestOptions)
|
|
||||||
.then(response => {// response Stream. Not completion object
|
|
||||||
//console.log("requestFetch [Response Stream] ", response);
|
|
||||||
return response.json();
|
|
||||||
})
|
|
||||||
.then((resp) => {
|
|
||||||
if (Number(resp.resultCode) === Number(CODE.RCV_ERROR_AUTH)) {
|
|
||||||
//accessToken 갱신 요청
|
|
||||||
accessTokenRefresh(url, requestOptions, handler, errorHandler);
|
|
||||||
return resp;
|
|
||||||
} else {
|
|
||||||
return resp;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((resp) => {
|
|
||||||
console.groupCollapsed("requestFetch.then()");
|
|
||||||
console.log("requestFetch [response] ", resp);
|
|
||||||
if (typeof handler === 'function') {
|
|
||||||
handler(resp);
|
|
||||||
} else {
|
|
||||||
console.log('egov fetch handler not assigned!');
|
|
||||||
}
|
|
||||||
console.groupEnd("requestFetch.then()");
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('There was an error!', error);
|
|
||||||
if (error === 'TypeError: Failed to fetch') {
|
|
||||||
alert("서버와의 연결이 원활하지 않습니다. 서버를 확인하세요.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof errorHandler === 'function') {
|
|
||||||
errorHandler(error);
|
|
||||||
} else {
|
|
||||||
console.error('egov error handler not assigned!');
|
|
||||||
alert("ERR : " + error.message);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
console.log("requestFetch finally end");
|
|
||||||
console.groupEnd("requestFetch");
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function accessTokenRefresh(url, requestOptions, handler, errorHandler){
|
function accessTokenRefresh(url, requestOptions, handler, errorHandler){
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ function EgovHeader({ loginUser, onChangeLogin }) {
|
||||||
{/* <!-- All menu : web --> */}
|
{/* <!-- All menu : web --> */}
|
||||||
<div className={`all_menu WEB ${menuDiv?"open":"closed"}`}>
|
<div className={`all_menu WEB ${menuDiv?"open":"closed"}`}>
|
||||||
<h2 className="blind">전체메뉴</h2>
|
<h2 className="blind">전체메뉴</h2>
|
||||||
<div className="inner">
|
<div className="inner row">
|
||||||
<div className="col">
|
<div className="col">
|
||||||
<h3>건설기준코드</h3>
|
<h3>건설기준코드</h3>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,16 @@
|
||||||
import React from 'react';
|
import React, {useEffect, useState} from 'react';
|
||||||
import {Blocks} from "react-loader-spinner";
|
import {Blocks} from "react-loader-spinner";
|
||||||
import {LoadingDiv} from "./Loading.style";
|
import {LoadingDiv} from "./Loading.style";
|
||||||
|
|
||||||
function Loading () {
|
function Loading ({loadingState}) {
|
||||||
|
const [visible, setVisible] = useState(loadingState);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setVisible(loadingState)
|
||||||
|
}, [loadingState]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LoadingDiv>
|
<LoadingDiv $visible={visible}>
|
||||||
<Blocks
|
<Blocks
|
||||||
height="150"
|
height="150"
|
||||||
width="150"
|
width="150"
|
||||||
|
|
|
||||||
|
|
@ -4,4 +4,5 @@ export const LoadingDiv = styled.div`
|
||||||
min-height: 83vh;
|
min-height: 83vh;
|
||||||
padding-top: calc(40vh - 150px);
|
padding-top: calc(40vh - 150px);
|
||||||
padding-left: calc(54vw - 150px);
|
padding-left: calc(54vw - 150px);
|
||||||
|
display: ${props=>props.$visible?"block":"none"};
|
||||||
`
|
`
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import { useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
|
// ==============================|| NAVIGATION - SCROLL TO TOP ||============================== //
|
||||||
|
|
||||||
|
const ScrollTop = ({ children }) => {
|
||||||
|
const location = useLocation();
|
||||||
|
const { pathname } = location;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
window.scrollTo({
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
behavior: 'smooth'
|
||||||
|
});
|
||||||
|
}, [pathname]);
|
||||||
|
|
||||||
|
return children || null;
|
||||||
|
};
|
||||||
|
|
||||||
|
ScrollTop.propTypes = {
|
||||||
|
children: PropTypes.node
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ScrollTop;
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
// material-ui
|
||||||
|
import { Box, Chip, Grid, Stack, Typography } from '@mui/material';
|
||||||
|
|
||||||
|
// project import
|
||||||
|
import MainCard from 'components/cards/MainCard';
|
||||||
|
|
||||||
|
// assets
|
||||||
|
import { RiseOutlined, FallOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
|
// ==============================|| STATISTICS - ECOMMERCE CARD ||============================== //
|
||||||
|
|
||||||
|
const AnalyticEcommerce = ({ color, title, count, percentage, isLoss, extra }) => (
|
||||||
|
<MainCard contentSX={{ p: 2.25 }}>
|
||||||
|
<Stack spacing={0.5}>
|
||||||
|
<Typography variant="h6" color="textSecondary">
|
||||||
|
{title}
|
||||||
|
</Typography>
|
||||||
|
<Grid container alignItems="center">
|
||||||
|
<Grid item>
|
||||||
|
<Typography variant="h4" color="inherit">
|
||||||
|
{count}
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
{percentage && (
|
||||||
|
<Grid item>
|
||||||
|
<Chip
|
||||||
|
variant="combined"
|
||||||
|
color={color}
|
||||||
|
icon={
|
||||||
|
<>
|
||||||
|
{!isLoss && <RiseOutlined style={{ fontSize: '0.75rem', color: 'inherit' }} />}
|
||||||
|
{isLoss && <FallOutlined style={{ fontSize: '0.75rem', color: 'inherit' }} />}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
label={`${percentage}%`}
|
||||||
|
sx={{ ml: 1.25, pl: 1 }}
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
|
</Stack>
|
||||||
|
<Box sx={{ pt: 2.25 }}>
|
||||||
|
<Typography variant="caption" color="textSecondary">
|
||||||
|
지난달{' '}
|
||||||
|
<Typography component="span" variant="caption" sx={{ color: `${color || 'primary'}.main` }}>
|
||||||
|
{extra}
|
||||||
|
</Typography>{' '}
|
||||||
|
건이 기록되었습니다.
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
</MainCard>
|
||||||
|
);
|
||||||
|
|
||||||
|
AnalyticEcommerce.propTypes = {
|
||||||
|
color: PropTypes.string,
|
||||||
|
title: PropTypes.string,
|
||||||
|
count: PropTypes.string,
|
||||||
|
percentage: PropTypes.number,
|
||||||
|
isLoss: PropTypes.bool,
|
||||||
|
extra: PropTypes.oneOfType([PropTypes.node, PropTypes.string])
|
||||||
|
};
|
||||||
|
|
||||||
|
AnalyticEcommerce.defaultProps = {
|
||||||
|
color: 'primary'
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AnalyticEcommerce;
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { forwardRef } from 'react';
|
||||||
|
|
||||||
|
// material-ui
|
||||||
|
import { useTheme } from '@mui/material/styles';
|
||||||
|
import { Card, CardContent, CardHeader, Divider, Typography } from '@mui/material';
|
||||||
|
|
||||||
|
// project import
|
||||||
|
import Highlighter from '../third-party/Highlighter';
|
||||||
|
|
||||||
|
// header style
|
||||||
|
const headerSX = {
|
||||||
|
p: 2.5,
|
||||||
|
'& .MuiCardHeader-action': { m: '0px auto', alignSelf: 'center' }
|
||||||
|
};
|
||||||
|
|
||||||
|
// ==============================|| CUSTOM - MAIN CARD ||============================== //
|
||||||
|
|
||||||
|
const MainCard = forwardRef(
|
||||||
|
(
|
||||||
|
{
|
||||||
|
border = true,
|
||||||
|
boxShadow,
|
||||||
|
children,
|
||||||
|
content = true,
|
||||||
|
contentSX = {},
|
||||||
|
darkTitle,
|
||||||
|
elevation,
|
||||||
|
secondary,
|
||||||
|
shadow,
|
||||||
|
sx = {},
|
||||||
|
title,
|
||||||
|
codeHighlight,
|
||||||
|
...others
|
||||||
|
},
|
||||||
|
ref
|
||||||
|
) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
boxShadow = theme.palette.mode === 'dark' ? boxShadow || true : boxShadow;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
elevation={elevation || 0}
|
||||||
|
ref={ref}
|
||||||
|
{...others}
|
||||||
|
sx={{
|
||||||
|
border: border ? '1px solid' : 'none',
|
||||||
|
borderRadius: 2,
|
||||||
|
borderColor: theme.palette.mode === 'dark' ? theme.palette.divider : theme.palette.grey.A800,
|
||||||
|
boxShadow: boxShadow && (!border || theme.palette.mode === 'dark') ? shadow || theme.customShadows.z1 : 'inherit',
|
||||||
|
':hover': {
|
||||||
|
boxShadow: boxShadow ? shadow || theme.customShadows.z1 : 'inherit'
|
||||||
|
},
|
||||||
|
'& pre': {
|
||||||
|
m: 0,
|
||||||
|
p: '16px !important',
|
||||||
|
fontFamily: theme.typography.fontFamily,
|
||||||
|
fontSize: '0.75rem'
|
||||||
|
},
|
||||||
|
...sx
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* card header and action */}
|
||||||
|
{!darkTitle && title && (
|
||||||
|
<CardHeader sx={headerSX} titleTypographyProps={{ variant: 'subtitle1' }} title={title} action={secondary} />
|
||||||
|
)}
|
||||||
|
{darkTitle && title && <CardHeader sx={headerSX} title={<Typography variant="h3">{title}</Typography>} action={secondary} />}
|
||||||
|
|
||||||
|
{/* card content */}
|
||||||
|
{content && <CardContent sx={contentSX}>{children}</CardContent>}
|
||||||
|
{!content && children}
|
||||||
|
|
||||||
|
{/* card footer - clipboard & highlighter */}
|
||||||
|
{codeHighlight && (
|
||||||
|
<>
|
||||||
|
<Divider sx={{ borderStyle: 'dashed' }} />
|
||||||
|
<Highlighter codeHighlight={codeHighlight} main>
|
||||||
|
{children}
|
||||||
|
</Highlighter>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
MainCard.propTypes = {
|
||||||
|
border: PropTypes.bool,
|
||||||
|
boxShadow: PropTypes.bool,
|
||||||
|
contentSX: PropTypes.object,
|
||||||
|
darkTitle: PropTypes.bool,
|
||||||
|
divider: PropTypes.bool,
|
||||||
|
elevation: PropTypes.number,
|
||||||
|
secondary: PropTypes.node,
|
||||||
|
shadow: PropTypes.string,
|
||||||
|
sx: PropTypes.object,
|
||||||
|
title: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
||||||
|
codeHighlight: PropTypes.bool,
|
||||||
|
content: PropTypes.bool,
|
||||||
|
children: PropTypes.node
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MainCard;
|
||||||
|
|
@ -18,15 +18,16 @@ import FormDialog from '../../components/alert/FormDialog';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function generate(items, element, onClickListner) {
|
function generate(items, element, onClickListner,nameKey,
|
||||||
|
idKey) {
|
||||||
return items.map((value, index) =>
|
return items.map((value, index) =>
|
||||||
React.cloneElement(element, {
|
React.cloneElement(element, {
|
||||||
key: value,
|
key: value[nameKey],
|
||||||
},
|
},
|
||||||
<Card fullWidth sx={{ '&': { boxShadow: 'none' } }}>
|
<Card fullWidth sx={{ '&': { boxShadow: 'none' } }}>
|
||||||
<CardActionArea fullWidth sx={{ px: 1 }}>
|
<CardActionArea fullWidth sx={{ px: 1 }}>
|
||||||
<ListItemText
|
<ListItemText
|
||||||
primary={value}
|
primary={value[nameKey]}
|
||||||
key={index}
|
key={index}
|
||||||
data-index={index}
|
data-index={index}
|
||||||
onClick={(e) => {onClickListner(e, index);}}
|
onClick={(e) => {onClickListner(e, index);}}
|
||||||
|
|
@ -99,7 +100,9 @@ function ListCreateUpdateDelete(props) {
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
</ListItem>,
|
</ListItem>,
|
||||||
onClickItem
|
onClickItem,
|
||||||
|
props.nameKey,
|
||||||
|
props.idKey
|
||||||
)}
|
)}
|
||||||
</List>
|
</List>
|
||||||
</Demo>
|
</Demo>
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,10 @@ function ListLabelInputs(props) {
|
||||||
|
|
||||||
useEffect(function () {
|
useEffect(function () {
|
||||||
setItems(props.items);
|
setItems(props.items);
|
||||||
console.log( props.items );
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [props]);
|
}, [props]);
|
||||||
|
|
||||||
useEffect(function () {
|
useEffect(function () {
|
||||||
console.log( items );
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
|
||||||
}, [items]);
|
}, [items]);
|
||||||
|
|
|
||||||
65
egovframe-template-simple-react-contribution/src/components/third-party/Highlighter.js
vendored
Normal file
65
egovframe-template-simple-react-contribution/src/components/third-party/Highlighter.js
vendored
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
// material-ui
|
||||||
|
import { Box, CardActions, Collapse, Divider, IconButton, Tooltip } from '@mui/material';
|
||||||
|
|
||||||
|
// third-party
|
||||||
|
import { CopyToClipboard } from 'react-copy-to-clipboard';
|
||||||
|
import reactElementToJSXString from 'react-element-to-jsx-string';
|
||||||
|
|
||||||
|
// project import
|
||||||
|
import SyntaxHighlight from 'utils/SyntaxHighlight';
|
||||||
|
|
||||||
|
// assets
|
||||||
|
import { CodeOutlined, CopyOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
|
// ==============================|| CLIPBOARD & HIGHLIGHTER ||============================== //
|
||||||
|
|
||||||
|
const Highlighter = ({ children }) => {
|
||||||
|
const [highlight, setHighlight] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box sx={{ position: 'relative' }}>
|
||||||
|
<CardActions sx={{ justifyContent: 'flex-end', p: 1, mb: highlight ? 1 : 0 }}>
|
||||||
|
<Box sx={{ display: 'flex', position: 'inherit', right: 0, top: 6 }}>
|
||||||
|
<CopyToClipboard text={reactElementToJSXString(children, { showFunctions: true, maxInlineAttributesLineLength: 100 })}>
|
||||||
|
<Tooltip title="Copy the source" placement="top-end">
|
||||||
|
<IconButton color="secondary" size="small" sx={{ fontSize: '0.875rem' }}>
|
||||||
|
<CopyOutlined />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</CopyToClipboard>
|
||||||
|
<Divider orientation="vertical" variant="middle" flexItem sx={{ mx: 1 }} />
|
||||||
|
<Tooltip title="Show the source" placement="top-end">
|
||||||
|
<IconButton
|
||||||
|
sx={{ fontSize: '0.875rem' }}
|
||||||
|
size="small"
|
||||||
|
color={highlight ? 'primary' : 'secondary'}
|
||||||
|
onClick={() => setHighlight(!highlight)}
|
||||||
|
>
|
||||||
|
<CodeOutlined />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</Box>
|
||||||
|
</CardActions>
|
||||||
|
<Collapse in={highlight}>
|
||||||
|
{highlight && (
|
||||||
|
<SyntaxHighlight>
|
||||||
|
{reactElementToJSXString(children, {
|
||||||
|
showFunctions: true,
|
||||||
|
showDefaultProps: false,
|
||||||
|
maxInlineAttributesLineLength: 100
|
||||||
|
})}
|
||||||
|
</SyntaxHighlight>
|
||||||
|
)}
|
||||||
|
</Collapse>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Highlighter.propTypes = {
|
||||||
|
children: PropTypes.node
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Highlighter;
|
||||||
|
|
@ -46,14 +46,27 @@
|
||||||
.code_list .result .List_Codes >div:nth-child(7){
|
.code_list .result .List_Codes >div:nth-child(7){
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
.codelistcontent{
|
|
||||||
padding: 0 0;
|
.standard_code_modal .head >span:nth-child(1),.standard_code_modal .result .list_item >div:nth-child(1){width: 12%;}
|
||||||
width: 80%;
|
.standard_code_modal .head >span:nth-child(2),.standard_code_modal .result .list_item >div:nth-child(2){width: 15%;}
|
||||||
|
.standard_code_modal .head >span:nth-child(3),.standard_code_modal .result .list_item >div:nth-child(3){width: 10%;}
|
||||||
|
|
||||||
|
.standard_code_result{
|
||||||
|
max-height: 520px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
.download_list{
|
||||||
|
max-height: 550px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
.codeListContent{
|
||||||
|
padding: 10px 0;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
.StandardCodeList{
|
.StandardCodeList{
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
.listtablediv{
|
.listTableDiv{
|
||||||
padding: 0 !important;
|
padding: 0 !important;
|
||||||
}
|
}
|
||||||
.vieweratag{
|
.vieweratag{
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ body {min-width: 1400px;}
|
||||||
.c_wrap .layout {display: table; width: 100%; table-layout: fixed; padding-bottom: 20px;} /* added by lim padding-bottom: 20px; */
|
.c_wrap .layout {display: table; width: 100%; table-layout: fixed; padding-bottom: 20px;} /* added by lim padding-bottom: 20px; */
|
||||||
|
|
||||||
/* sub navigation */
|
/* sub navigation */
|
||||||
.c_wrap .layout .nav {display: table-cell; width: 220px; vertical-align: top;} /* changed by lim width: 260px; */
|
.c_wrap .layout .nav:not(.tabs) {display: table-cell; width: 220px; vertical-align: top;} /* changed by lim width: 260px; */
|
||||||
.c_wrap .layout .nav .inner {border: 1px solid #dde2e5; border-radius: 10px;}
|
.c_wrap .layout .nav .inner {border: 1px solid #dde2e5; border-radius: 10px;}
|
||||||
.nav_title{padding: 35px 30px 26px 30px;} /* changed by lim border-bottom: 4px solid #dde2e5; */
|
.nav_title{padding: 35px 30px 26px 30px;} /* changed by lim border-bottom: 4px solid #dde2e5; */
|
||||||
.c_wrap .layout .nav h2 {color: #222; font-size: 24px;}
|
.c_wrap .layout .nav h2 {color: #222; font-size: 24px;}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,199 @@
|
||||||
|
import React, { useState, useEffect, useCallback, useRef } from 'react';
|
||||||
|
import { Link, useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
|
import * as EgovNet from 'api/egovFetch';
|
||||||
|
import URL from 'constants/url';
|
||||||
|
|
||||||
|
import { default as EgovLeftNav } from 'components/leftmenu/EgovLeftNavAdmin';
|
||||||
|
import EgovPaging from 'components/EgovPaging';
|
||||||
|
|
||||||
|
import { itemIdxByPage } from 'utils/calc';
|
||||||
|
|
||||||
|
function EgovAdminBoardList(props) {
|
||||||
|
console.group("EgovAdminBoardList");
|
||||||
|
console.log("[Start] EgovAdminBoardList ------------------------------");
|
||||||
|
console.log("EgovAdminBoardList [props] : ", props);
|
||||||
|
|
||||||
|
const location = useLocation();
|
||||||
|
console.log("EgovAdminBoardList [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 cndRef = useRef();
|
||||||
|
const wrdRef = useRef();
|
||||||
|
|
||||||
|
const [listTag, setListTag] = useState([]);
|
||||||
|
|
||||||
|
const retrieveList = useCallback((srchCnd) => {
|
||||||
|
console.groupCollapsed("EgovAdminBoardList.retrieveList()");
|
||||||
|
|
||||||
|
const retrieveListURL = '/cop/bbs/selectBBSMasterInfsAPI.do';
|
||||||
|
|
||||||
|
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(<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;
|
||||||
|
|
||||||
|
// 리스트 항목 구성
|
||||||
|
resp.result.resultList.forEach(function (item, index) {
|
||||||
|
if (index === 0) mutListTag = []; // 목록 초기화
|
||||||
|
const listIdx = itemIdxByPage(resultCnt , currentPageNo, pageSize, index);
|
||||||
|
|
||||||
|
mutListTag.push(
|
||||||
|
<Link
|
||||||
|
to={{pathname: URL.ADMIN_BOARD_MODIFY}}
|
||||||
|
state={{
|
||||||
|
bbsId: item.bbsId,
|
||||||
|
searchCondition: searchCondition
|
||||||
|
}}
|
||||||
|
key={listIdx}
|
||||||
|
className="list_item">
|
||||||
|
<div>{listIdx}</div>
|
||||||
|
<div>{item.bbsNm}</div>
|
||||||
|
<div>{item.bbsTyCodeNm}</div>
|
||||||
|
<div>{item.bbsAttrbCodeNm}</div>
|
||||||
|
<div>{item.frstRegisterPnttm}</div>
|
||||||
|
<div>{item.useAt === "Y" ? "사용" : "사용안함"}</div>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
setListTag(mutListTag);
|
||||||
|
},
|
||||||
|
function (resp) {
|
||||||
|
console.log("err response : ", resp);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
console.groupEnd("EgovAdminBoardList.retrieveList()");
|
||||||
|
},[listTag, searchCondition]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
retrieveList(searchCondition);
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
console.log("------------------------------EgovAdminBoardList [End]");
|
||||||
|
console.groupEnd("EgovAdminBoardList");
|
||||||
|
return (
|
||||||
|
<div className="container">
|
||||||
|
<div className="c_wrap">
|
||||||
|
{/* <!-- Location --> */}
|
||||||
|
<div className="location">
|
||||||
|
<ul>
|
||||||
|
<li><Link to={URL.MAIN} className="home">Home</Link></li>
|
||||||
|
<li><Link to={URL.ADMIN}>사이트관리</Link></li>
|
||||||
|
<li>게시판생성 관리</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{/* <!--// Location --> */}
|
||||||
|
|
||||||
|
<div className="layout">
|
||||||
|
{/* <!-- Navigation --> */}
|
||||||
|
<EgovLeftNav></EgovLeftNav>
|
||||||
|
{/* <!--// Navigation --> */}
|
||||||
|
|
||||||
|
<div className="contents BOARD_CREATE_LIST" id="contents">
|
||||||
|
{/* <!-- 본문 --> */}
|
||||||
|
|
||||||
|
<div className="top_tit">
|
||||||
|
<h1 className="tit_1">사이트관리</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 className="tit_2">게시판생성 관리</h2>
|
||||||
|
|
||||||
|
{/* <!-- 검색조건 --> */}
|
||||||
|
<div className="condition">
|
||||||
|
<ul>
|
||||||
|
<li className="third_1 L">
|
||||||
|
<span className="lb">검색유형선택</span>
|
||||||
|
<label className="f_select" htmlFor="searchCnd">
|
||||||
|
<select id="searchCnd" name="searchCnd" title="검색유형선택" ref={cndRef}
|
||||||
|
onChange={e => {
|
||||||
|
cndRef.current.value = e.target.value;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<option value="0">게시판명</option>
|
||||||
|
<option value="1">게시판유형</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li className="third_2 R">
|
||||||
|
<span className="lb">검색어</span>
|
||||||
|
<span className="f_search w_400">
|
||||||
|
<input type="text" name="" defaultValue={searchCondition && searchCondition.searchWrd} placeholder="" ref={wrdRef}
|
||||||
|
onChange={e => {
|
||||||
|
wrdRef.current.value = e.target.value;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<button type="button"
|
||||||
|
onClick={() => {
|
||||||
|
retrieveList({ ...searchCondition, pageIndex: 1, searchCnd: cndRef.current.value, searchWrd: wrdRef.current.value });
|
||||||
|
}}>조회</button>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Link to={URL.ADMIN_BOARD_CREATE} className="btn btn_blue_h46 pd35">등록</Link>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{/* <!--// 검색조건 --> */}
|
||||||
|
|
||||||
|
{/* <!-- 게시판목록 --> */}
|
||||||
|
<div className="board_list BRD006">
|
||||||
|
<div className="head">
|
||||||
|
<span>번호</span>
|
||||||
|
<span>게시판명</span>
|
||||||
|
<span>게시판유형</span>
|
||||||
|
<span>게시판속성</span>
|
||||||
|
<span>생성일</span>
|
||||||
|
<span>사용여부</span>
|
||||||
|
</div>
|
||||||
|
<div className="result">
|
||||||
|
{listTag}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* <!--// 게시판목록 --> */}
|
||||||
|
|
||||||
|
<div className="board_bot">
|
||||||
|
{/* <!-- Paging --> */}
|
||||||
|
<EgovPaging pagination={paginationInfo} moveToPage={passedPage => {
|
||||||
|
retrieveList({ ...searchCondition, pageIndex: passedPage, searchCnd: cndRef.current.value, searchWrd: wrdRef.current.value })
|
||||||
|
}} />
|
||||||
|
{/* <!--/ Paging --> */}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <!--// 본문 --> */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EgovAdminBoardList;
|
||||||
|
|
@ -1,430 +1,162 @@
|
||||||
import React, { useState, useEffect, useRef } from 'react';
|
import React, {useState, useEffect, useRef} from 'react';
|
||||||
import { Link, useNavigate, useLocation } from 'react-router-dom';
|
import {Link, useNavigate, useLocation, useParams} from 'react-router-dom';
|
||||||
|
import Modal from "react-bootstrap/Modal";
|
||||||
|
|
||||||
import * as EgovNet from 'api/egovFetch';
|
import * as EgovNet from 'api/egovFetch';
|
||||||
import URL from 'constants/url';
|
import URL from 'constants/url';
|
||||||
import CODE from 'constants/code';
|
import CODE from 'constants/code';
|
||||||
|
|
||||||
import { default as EgovLeftNav } from 'components/leftmenu/EgovLeftNavAdmin';
|
import {default as EgovLeftNav} from 'components/leftmenu/EgovLeftNavAdmin';
|
||||||
import EgovRadioButtonGroup from 'components/EgovRadioButtonGroup';
|
import EgovRadioButtonGroup from 'components/EgovRadioButtonGroup';
|
||||||
|
import {Form} from "react-bootstrap";
|
||||||
|
|
||||||
|
|
||||||
function EgovAdminBoardEdit(props) {
|
function EgovAdminBoardEdit({props, reloadFunction}) {
|
||||||
console.group("EgovAdminBoardEdit");
|
console.group("EgovAdminBoardEdit");
|
||||||
console.log("[Start] EgovAdminBoardEdit ------------------------------");
|
console.log("[Start] EgovAdminBoardEdit ------------------------------");
|
||||||
console.log("EgovAdminBoardEdit [props] : ", props);
|
console.log("EgovAdminBoardEdit [props] : ", props);
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const checkRef = useRef([]);
|
const checkRef = useRef([]);
|
||||||
|
|
||||||
console.log("EgovAdminBoardEdit [location] : ", location);
|
console.log("EgovAdminBoardEdit [location] : ", location);
|
||||||
|
|
||||||
const replyPosblAtRadioGroup = [{ value: "Y", label: "가능" }, { value: "N", label: "불가능" }];
|
let item = null;
|
||||||
const fileAtchPosblAtRadioGroup = [{ value: "Y", label: "가능" }, { value: "N", label: "불가능" }];
|
item = props;
|
||||||
const bbsTyCodeOptions = [{ value: "", label: "선택" }, { value: "BBST01", label: "일반게시판" }, { value: "BBST03", label: "공지게시판" }];
|
console.log("@@@ item : " + JSON.stringify(item));
|
||||||
const bbsAttrbCodeOptions = [{ value: "", label: "선택" }, { value: "BBSA02", label: "갤러리" }, { value: "BBSA03", label: "일반게시판" }];
|
|
||||||
const posblAtchFileNumberOptions = [{ value: 0, label: "선택하세요" }, { value: 1, label: "1개" }, { value: 2, label: "2개" }, { value: 3, label: "3개" }];
|
|
||||||
const bbsId = location.state?.bbsId || "";
|
|
||||||
|
|
||||||
const [modeInfo, setModeInfo] = useState({ mode: props.mode });
|
const [modeInfo, setModeInfo] = useState(item != null ? {mode: props.mode} : {mode: CODE.MODE_CREATE});
|
||||||
const [boardDetail, setBoardDetail] = useState({});
|
const [boardDetail, setBoardDetail] = useState({});
|
||||||
|
console.log("@@@ mode : " + modeInfo.mode);
|
||||||
const initMode = () => {
|
|
||||||
switch (props.mode) {
|
|
||||||
case CODE.MODE_CREATE:
|
|
||||||
setModeInfo({
|
|
||||||
...modeInfo,
|
|
||||||
modeTitle: "등록",
|
|
||||||
editURL: '/cop/bbs/insertBBSMasterInfAPI.do'
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CODE.MODE_MODIFY:
|
|
||||||
setModeInfo({
|
|
||||||
...modeInfo,
|
|
||||||
modeTitle: "수정",
|
|
||||||
editURL: `/cop/bbs/updateBBSMasterInfAPI/${bbsId}.do`
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
navigate({pathname: URL.ERROR}, {state: {msg : ""}});
|
|
||||||
}
|
|
||||||
retrieveDetail();
|
|
||||||
}
|
|
||||||
|
|
||||||
const retrieveDetail = () => {
|
|
||||||
if (modeInfo.mode === CODE.MODE_CREATE) {// 조회/등록이면 조회 안함
|
|
||||||
setBoardDetail({
|
|
||||||
tmplatId: "TMPLAT_BOARD_DEFAULT", //Template 고정
|
|
||||||
replyPosblAt: "Y", //답장가능여부 초기값
|
|
||||||
fileAtchPosblAt: "Y" //파일첨부가능여부 초기값
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const retrieveDetailURL = '/cop/bbs/selectBBSMasterInfAPI.do';
|
|
||||||
|
|
||||||
const requestOptions = {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
'Content-type': 'application/json',
|
|
||||||
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
bbsId: bbsId
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
EgovNet.requestFetch(retrieveDetailURL,
|
|
||||||
requestOptions,
|
|
||||||
function (resp) {
|
|
||||||
// 수정모드일 경우 조회값 세팅
|
|
||||||
if (modeInfo.mode === CODE.MODE_MODIFY) {
|
|
||||||
setBoardDetail(resp.result.boardMasterVO);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const formValidator = (formData) => {
|
|
||||||
if (formData.get('bbsNm') === null || formData.get('bbsNm') === "") {
|
|
||||||
alert("게시판명은 필수 값입니다.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (formData.get('bbsIntrcn') === null || formData.get('bbsIntrcn') === "") {
|
|
||||||
alert("게시판 소개는 필수 값입니다.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (formData.get('bbsTyCode') === null || formData.get('bbsTyCode') === "") {
|
|
||||||
alert("게시판 유형은 필수 값입니다.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (formData.get('bbsAttrbCode') === null || formData.get('bbsAttrbCode') === "") {
|
|
||||||
alert("게시판 속성은 필수 값입니다.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (formData.get('posblAtchFileNumber') === null || formData.get('posblAtchFileNumber') === "") {
|
|
||||||
alert("첨부파일 가능 숫자는 필수 값입니다.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const formObjValidator = (checkRef) => {
|
|
||||||
if(checkRef.current[0].value === ""){
|
|
||||||
alert("게시판명은 필수 값입니다.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(checkRef.current[1].value === ""){
|
|
||||||
alert("게시판 소개는 필수 값입니다.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(checkRef.current[2].value === "0"){
|
|
||||||
alert("첨부파일 가능 숫자는 필수 값입니다.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateBoard = () => {
|
|
||||||
|
|
||||||
let modeStr = modeInfo.mode === CODE.MODE_CREATE ? "POST" : "PUT";
|
|
||||||
|
|
||||||
let requestOptions ={};
|
|
||||||
|
|
||||||
if (modeStr === "POST") {
|
|
||||||
|
|
||||||
const formData = new FormData();
|
|
||||||
|
|
||||||
for (let key in boardDetail) {
|
|
||||||
formData.append(key, boardDetail[key]);
|
|
||||||
//console.log("boardDetail [%s] ", key, boardDetail[key]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (formValidator(formData)) {
|
|
||||||
|
|
||||||
requestOptions = {
|
|
||||||
method: modeStr,
|
|
||||||
headers: {
|
|
||||||
|
|
||||||
},
|
|
||||||
body: formData
|
|
||||||
}
|
|
||||||
|
|
||||||
EgovNet.requestFetch(modeInfo.editURL,
|
|
||||||
requestOptions,
|
|
||||||
(resp) => {
|
|
||||||
if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
|
|
||||||
navigate({ pathname: URL.ADMIN_BOARD });
|
|
||||||
} else {
|
|
||||||
navigate({pathname: URL.ERROR}, {state: {msg : resp.resultMessage}});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (formObjValidator(checkRef)) {
|
|
||||||
|
|
||||||
requestOptions = {
|
|
||||||
method: modeStr,
|
|
||||||
headers: {
|
|
||||||
'Content-type': 'application/json',
|
|
||||||
|
|
||||||
},
|
|
||||||
body: JSON.stringify({...boardDetail})
|
|
||||||
}
|
|
||||||
|
|
||||||
EgovNet.requestFetch(modeInfo.editURL,
|
|
||||||
requestOptions,
|
|
||||||
(resp) => {
|
|
||||||
if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
|
|
||||||
navigate({ pathname: URL.ADMIN_BOARD });
|
|
||||||
} else {
|
|
||||||
navigate({pathname: URL.ERROR}, {state: {msg : resp.resultMessage}});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteBoardArticle = (bbsId) => {
|
|
||||||
const deleteBoardURL = `/cop/bbs/deleteBBSMasterInfAPI/${bbsId}.do`;
|
|
||||||
|
|
||||||
const requestOptions = {
|
|
||||||
method: "PUT",
|
|
||||||
headers: {
|
|
||||||
'Content-type': 'application/json',
|
|
||||||
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
bbsId: bbsId
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
EgovNet.requestFetch(deleteBoardURL,
|
|
||||||
requestOptions,
|
|
||||||
(resp) => {
|
|
||||||
console.log("====>>> board delete= ", resp);
|
|
||||||
if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
|
|
||||||
alert("게시글이 삭제되었습니다.")
|
|
||||||
navigate(URL.ADMIN_BOARD, { replace: true });
|
|
||||||
} else {
|
|
||||||
alert("ERR : " + resp.resultMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const getSelectedLabel = (objArray, findLabel = "") => {
|
|
||||||
let foundValueLabelObj = objArray.find(o => o['value'] === findLabel);
|
|
||||||
return foundValueLabelObj['label'];
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
initMode();
|
initMode();
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const initMode = () => {
|
||||||
|
if (modeInfo.mode === CODE.MODE_MODIFY) {
|
||||||
|
setBoardDetail(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function editBoard(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
const form = e.target;
|
||||||
|
const info = {
|
||||||
|
bbsId: form.bbsId.value,
|
||||||
|
bbsTitle: form.bbsTitle.value,
|
||||||
|
bbsDesc: form.bbsDesc.value
|
||||||
|
}
|
||||||
|
if (modeInfo.mode === CODE.MODE_MODIFY) {
|
||||||
|
info.bbsSeq = props.bbsSeq;
|
||||||
|
}
|
||||||
|
EgovNet.requestFetch(
|
||||||
|
'/admin/boards/board-mgt',
|
||||||
|
{
|
||||||
|
method: "PUT",
|
||||||
|
headers: {
|
||||||
|
'Content-type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(info)
|
||||||
|
},
|
||||||
|
(resp) => {
|
||||||
|
if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
|
||||||
|
alert("저장되었습니다.");
|
||||||
|
reloadFunction();
|
||||||
|
} else if (Number(resp.resultCode) === Number(CODE.RCV_ERROR_AUTH)) {
|
||||||
|
console.log("토큰 갱신중.")
|
||||||
|
} else {
|
||||||
|
alert(resp.result.resultMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteBoard(bbs){
|
||||||
|
if(window.confirm("삭제하시겠습니까?")) {
|
||||||
|
EgovNet.requestFetch(
|
||||||
|
'/admin/boards/board-mgt',
|
||||||
|
{
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
'Content-type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(bbs)
|
||||||
|
},
|
||||||
|
(resp) => {
|
||||||
|
if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
|
||||||
|
alert("삭제되었습니다.")
|
||||||
|
reloadFunction();
|
||||||
|
} else if (Number(resp.resultCode) === Number(CODE.RCV_ERROR_AUTH)) {
|
||||||
|
console.log("토큰 갱신중.")
|
||||||
|
} else {
|
||||||
|
alert(resp.result.resultMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
console.log("------------------------------EgovAdminBoardEdit [End]");
|
console.log("------------------------------EgovAdminBoardEdit [End]");
|
||||||
console.groupEnd("EgovAdminBoardEdit");
|
console.groupEnd("EgovAdminBoardEdit");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container">
|
<>
|
||||||
<div className="c_wrap">
|
{/* <!-- 본문 --> */}
|
||||||
{/* <!-- Location --> */}
|
<Modal.Header closeButton>
|
||||||
<div className="location">
|
<Modal.Title>
|
||||||
<ul>
|
{modeInfo.mode === CODE.MODE_CREATE && '게시판 생성'}
|
||||||
<li><Link to={URL.MAIN} className="home">Home</Link></li>
|
{modeInfo.mode === CODE.MODE_MODIFY && '게시판 수정'}
|
||||||
<li><Link to={URL.ADMIN}>사이트관리</Link></li>
|
</Modal.Title>
|
||||||
<li>게시판생성 관리</li>
|
</Modal.Header>
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{/* <!--// Location --> */}
|
|
||||||
|
|
||||||
<div className="layout">
|
<Modal.Body>
|
||||||
{/* <!-- Navigation --> */}
|
<div className="board_view2">
|
||||||
<EgovLeftNav></EgovLeftNav>
|
<Form onSubmit={(e) => {editBoard(e)}} noValidate>
|
||||||
{/* <!--// Navigation --> */}
|
<dl>
|
||||||
|
<dt><label htmlFor="bbsId">게시판 ID</label><span className="req">필수</span></dt>
|
||||||
|
<dd>
|
||||||
|
<Form.Control className="f_input2 w_full" type="text" name="bbsId" placeholder="게시판 ID" required
|
||||||
|
defaultValue={props?.bbsId} readOnly={props!==undefined}/>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
<dl>
|
||||||
|
<dt><label htmlFor="bbsTitle">게시판명</label><span className="req">필수</span></dt>
|
||||||
|
<dd>
|
||||||
|
<Form.Control className="f_input2 w_full" type="text" name="bbsTitle" placeholder="게시판명" required
|
||||||
|
defaultValue={props?.bbsTitle}/>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
<dl>
|
||||||
|
<dt><label htmlFor="bbsDesc">게시판 소개</label><span className="req">필수</span></dt>
|
||||||
|
<dd>
|
||||||
|
<Form.Control className="f_txtar w_full h_100" as="textarea" name="bbsDesc" placeholder="게시판 소개" required
|
||||||
|
defaultValue={props?.bbsDesc}/>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
<div className="contents BOARD_CREATE_REG" id="contents">
|
{/* <!-- 버튼영역 --> */}
|
||||||
{/* <!-- 본문 --> */}
|
<div className="board_btn_area">
|
||||||
|
<div className="left_col btn1">
|
||||||
<div className="top_tit">
|
<button type="submit" className="btn btn_skyblue_h46 w_100">저장
|
||||||
<h1 className="tit_1">사이트관리</h1>
|
</button>
|
||||||
</div>
|
{modeInfo.mode === CODE.MODE_MODIFY &&
|
||||||
|
<button type={"button"} className="btn btn_skyblue_h46 w_100" onClick={()=>{deleteBoard(props)}}>삭제</button>
|
||||||
{modeInfo.mode === CODE.MODE_CREATE &&
|
}
|
||||||
<h2 className="tit_2">게시판 생성</h2>
|
|
||||||
}
|
|
||||||
|
|
||||||
{modeInfo.mode === CODE.MODE_MODIFY &&
|
|
||||||
<h2 className="tit_2">게시판 수정</h2>
|
|
||||||
}
|
|
||||||
|
|
||||||
<div className="board_view2">
|
|
||||||
<dl>
|
|
||||||
<dt><label htmlFor="bbsNm">게시판명</label><span className="req">필수</span></dt>
|
|
||||||
<dd>
|
|
||||||
<input className="f_input2 w_full" type="text" name="bbsNm" title="" id="bbsNm" placeholder=""
|
|
||||||
defaultValue={boardDetail.bbsNm}
|
|
||||||
onChange={e => setBoardDetail({ ...boardDetail, bbsNm: e.target.value })}
|
|
||||||
ref={el => (checkRef.current[0] = el)}
|
|
||||||
/>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<dl>
|
|
||||||
<dt><label htmlFor="bbsIntrcn">게시판 소개</label><span className="req">필수</span></dt>
|
|
||||||
<dd>
|
|
||||||
<textarea className="f_txtar w_full h_100" name="bbsIntrcn" id="bbsIntrcn" cols="30" rows="10" placeholder=""
|
|
||||||
defaultValue={boardDetail.bbsIntrcn}
|
|
||||||
onChange={e => setBoardDetail({ ...boardDetail, bbsIntrcn: e.target.value })}
|
|
||||||
ref={el => (checkRef.current[1] = el)}
|
|
||||||
></textarea>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<dl>
|
|
||||||
<dt>게시판 유형<span className="req">필수</span></dt>
|
|
||||||
<dd>
|
|
||||||
{/* 수정/조회 일때 변경 불가 */}
|
|
||||||
{modeInfo.mode === CODE.MODE_CREATE &&
|
|
||||||
<label className="f_select w_130" htmlFor="bbsTyCode">
|
|
||||||
<select
|
|
||||||
id="bbsTyCode"
|
|
||||||
name="bbsTyCode"
|
|
||||||
title="게시판유형선택"
|
|
||||||
onChange={(e) => setBoardDetail({ ...boardDetail, bbsTyCode: e.target.value })}
|
|
||||||
value={boardDetail.bbsTyCode}
|
|
||||||
>
|
|
||||||
{bbsTyCodeOptions.map((option, i) => {
|
|
||||||
return (
|
|
||||||
<option value={option.value} key={option.value}>
|
|
||||||
{option.label}
|
|
||||||
</option>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
}
|
|
||||||
{modeInfo.mode === CODE.MODE_MODIFY &&
|
|
||||||
<span>
|
|
||||||
{boardDetail.bbsTyCode && getSelectedLabel(bbsTyCodeOptions, boardDetail.bbsTyCode)}
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<dl>
|
|
||||||
<dt>게시판 속성<span className="req">필수</span></dt>
|
|
||||||
<dd>
|
|
||||||
{/* 등록 일때 변경 가능 */}
|
|
||||||
{modeInfo.mode === CODE.MODE_CREATE &&
|
|
||||||
<label className="f_select w_130" htmlFor="bbsAttrbCode">
|
|
||||||
<select
|
|
||||||
id="bbsAttrbCode"
|
|
||||||
name="bbsAttrbCode"
|
|
||||||
title="게시판속성선택"
|
|
||||||
onChange={(e) => setBoardDetail({ ...boardDetail, bbsAttrbCode: e.target.value })}
|
|
||||||
value={boardDetail.bbsAttrbCode}
|
|
||||||
>
|
|
||||||
{bbsAttrbCodeOptions.map((option, i) => {
|
|
||||||
return (
|
|
||||||
<option value={option.value} key={option.value}>
|
|
||||||
{option.label}
|
|
||||||
</option>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
}
|
|
||||||
{/* 수정/조회 일때 변경 불가 */}
|
|
||||||
{modeInfo.mode === CODE.MODE_MODIFY &&
|
|
||||||
<span>
|
|
||||||
{boardDetail.bbsAttrbCode && getSelectedLabel(bbsAttrbCodeOptions, boardDetail.bbsAttrbCode)}
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<dl>
|
|
||||||
<dt>답장가능여부<span className="req">필수</span></dt>
|
|
||||||
<dd>
|
|
||||||
{/* 등록 일때 변경 가능 */}
|
|
||||||
{modeInfo.mode === CODE.MODE_CREATE &&
|
|
||||||
<EgovRadioButtonGroup
|
|
||||||
name="replyPosblAt"
|
|
||||||
radioGroup={replyPosblAtRadioGroup}
|
|
||||||
setValue={boardDetail.replyPosblAt}
|
|
||||||
setter={(v) => setBoardDetail({ ...boardDetail, replyPosblAt: v })} />
|
|
||||||
}
|
|
||||||
{/* 수정/조회 일때 변경 불가 */}
|
|
||||||
{modeInfo.mode === CODE.MODE_MODIFY &&
|
|
||||||
<span>
|
|
||||||
{boardDetail.replyPosblAt && getSelectedLabel(replyPosblAtRadioGroup, boardDetail.replyPosblAt)}
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<dl>
|
|
||||||
<dt>파일첨부가능여부<span className="req">필수</span></dt>
|
|
||||||
<dd>
|
|
||||||
<EgovRadioButtonGroup
|
|
||||||
name="fileAtchPosblAt"
|
|
||||||
radioGroup={fileAtchPosblAtRadioGroup}
|
|
||||||
setValue={boardDetail.fileAtchPosblAt}
|
|
||||||
setter={(v) => setBoardDetail({ ...boardDetail, fileAtchPosblAt: v })} />
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<dl>
|
|
||||||
<dt><label htmlFor="schdulDeptName">첨부파일가능파일 숫자</label><span className="req">필수</span></dt>
|
|
||||||
<dd>
|
|
||||||
<label className="f_select " htmlFor="posblAtchFileNumber">
|
|
||||||
<select
|
|
||||||
id="posblAtchFileNumber"
|
|
||||||
name="posblAtchFileNumber"
|
|
||||||
title="첨부가능파일 숫자선택"
|
|
||||||
onChange={(e) => setBoardDetail({ ...boardDetail, posblAtchFileNumber: e.target.value })}
|
|
||||||
value={boardDetail.posblAtchFileNumber}
|
|
||||||
ref={el => (checkRef.current[2] = el)}
|
|
||||||
>
|
|
||||||
{posblAtchFileNumberOptions.map((option, i) => {
|
|
||||||
return (
|
|
||||||
<option value={option.value} key={option.value}>
|
|
||||||
{option.label}
|
|
||||||
</option>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
</label>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
{/* <!-- 버튼영역 --> */}
|
|
||||||
<div className="board_btn_area">
|
|
||||||
<div className="left_col btn1">
|
|
||||||
<button className="btn btn_skyblue_h46 w_100"
|
|
||||||
onClick={() => updateBoard()}>저장</button>
|
|
||||||
{modeInfo.mode === CODE.MODE_MODIFY &&
|
|
||||||
<button className="btn btn_skyblue_h46 w_100" onClick={() => {
|
|
||||||
deleteBoardArticle(boardDetail.bbsId);
|
|
||||||
}}>삭제</button>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="right_col btn1">
|
|
||||||
<Link to={URL.ADMIN_BOARD} className="btn btn_blue_h46 w_100">목록</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{/* <!--// 버튼영역 --> */}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* <!--// 본문 --> */}
|
<div className="right_col btn1">
|
||||||
</div>
|
<button type={"button"} className="btn btn_blue_h46 w_100" onClick={()=>{reloadFunction()}}>목록</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* <!--// 버튼영역 --> */}
|
||||||
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Modal.Body>
|
||||||
</div>
|
</>
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,41 @@
|
||||||
import React from 'react';
|
import React, { useState, useEffect, useCallback } from 'react';
|
||||||
|
import { Link, useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
|
import * as EgovNet from 'api/egovFetch';
|
||||||
|
import URL from 'constants/url';
|
||||||
|
|
||||||
function Keywords(props) {
|
import { default as EgovLeftNav } from 'components/leftmenu/EgovLeftNavAdmin';
|
||||||
|
|
||||||
|
function StandardCodeMgt(props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container">
|
<div className="container">
|
||||||
Keywords
|
<div className="c_wrap">
|
||||||
|
{/* <!-- Location --> */}
|
||||||
|
<div className="location">
|
||||||
|
<ul>
|
||||||
|
<li><Link to={URL.MAIN} className="home">Home</Link></li>
|
||||||
|
<li><Link to={URL.ADMIN} >사이트관리</Link></li>
|
||||||
|
<li>게시판현황</li>
|
||||||
|
<li>키워드 관리</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{/* <!--// Location --> */}
|
||||||
|
|
||||||
|
<div className="layout">
|
||||||
|
{/* <!-- Navigation --> */}
|
||||||
|
<EgovLeftNav></EgovLeftNav>
|
||||||
|
{/* <!--// Navigation --> */}
|
||||||
|
|
||||||
|
<div className="contents NOTICE_LIST" id="contents">
|
||||||
|
<div className="top_tit">
|
||||||
|
<h1 className="tit_1">키워드 관리</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Keywords;
|
export default StandardCodeMgt;
|
||||||
|
|
@ -3,11 +3,12 @@ import { Link, useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
import * as EgovNet from 'api/egovFetch';
|
import * as EgovNet from 'api/egovFetch';
|
||||||
import URL from 'constants/url';
|
import URL from 'constants/url';
|
||||||
|
import CODE from 'constants/code';
|
||||||
|
|
||||||
import { default as EgovLeftNav } from 'components/leftmenu/EgovLeftNavAdmin';
|
import { default as EgovLeftNav } from 'components/leftmenu/EgovLeftNavAdmin';
|
||||||
import EgovPaging from 'components/EgovPaging';
|
import Modal from "react-bootstrap/Modal";
|
||||||
|
import EgovAdminBoardEdit from "../board/EgovAdminBoardEdit";
|
||||||
import { itemIdxByPage } from 'utils/calc';
|
import {format} from "date-fns";
|
||||||
|
|
||||||
function EgovAdminBoardList(props) {
|
function EgovAdminBoardList(props) {
|
||||||
console.group("EgovAdminBoardList");
|
console.group("EgovAdminBoardList");
|
||||||
|
|
@ -20,10 +21,15 @@ function EgovAdminBoardList(props) {
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
const [searchCondition, setSearchCondition] = useState(location.state?.searchCondition || { pageIndex: 1, searchCnd: '0', searchWrd: '' });// 기존 조회에서 접근 했을 시 || 신규로 접근 했을 시
|
const [searchCondition, setSearchCondition] = useState(location.state?.searchCondition || { pageIndex: 1, searchCnd: '0', searchWrd: '' });// 기존 조회에서 접근 했을 시 || 신규로 접근 했을 시
|
||||||
const [paginationInfo, setPaginationInfo] = useState({});
|
const [paginationInfo, setPaginationInfo] = useState({});
|
||||||
|
|
||||||
const [listTag, setListTag] = useState([]);
|
const [listTag, setListTag] = useState([]);
|
||||||
|
|
||||||
|
const [show, setShow] = useState(false);
|
||||||
|
const [modalBody, setModalBody] = useState();
|
||||||
|
const handleClose = () => setShow(false);
|
||||||
|
const handleShow = () => setShow(true);
|
||||||
|
|
||||||
const retrieveList = useCallback(() => {
|
const retrieveList = useCallback(() => {
|
||||||
|
handleClose();
|
||||||
console.groupCollapsed("AdminBoardList.retrieveList()");
|
console.groupCollapsed("AdminBoardList.retrieveList()");
|
||||||
|
|
||||||
const retrieveListURL = '/admin/boards/board-list';
|
const retrieveListURL = '/admin/boards/board-list';
|
||||||
|
|
@ -49,14 +55,15 @@ function EgovAdminBoardList(props) {
|
||||||
if (index === 0) mutListTag = []; // 목록 초기화
|
if (index === 0) mutListTag = []; // 목록 초기화
|
||||||
|
|
||||||
mutListTag.push(
|
mutListTag.push(
|
||||||
<Link className="list_item">
|
<div className="list_item">
|
||||||
<div>{item.bbsSeq}</div>
|
<div>{item.bbsSeq}</div>
|
||||||
<div>{item.bbsId}</div>
|
<div>{item.bbsId}</div>
|
||||||
<div>{item.bbsTitle}</div>
|
<div>{item.bbsTitle}</div>
|
||||||
<div>{item.frstCrtId}</div>
|
<div>{item.frstCrtId}</div>
|
||||||
<div>{item.frstCrtDt}</div>
|
<div>{item.frstCrtDt ? format(item.frstCrtDt, "yyyy-MM-dd HH:mm") : ""}</div>
|
||||||
<div>{item.lastChgDt}</div>
|
<div>{item.lastChgDt ? format(item.lastChgDt, "yyyy-MM-dd HH:mm") : ""}</div>
|
||||||
</Link>
|
<div><button className={"btn btn_blue_h31 px-1"} onClick={()=>{editBoard(item)}}>수정</button></div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -75,6 +82,14 @@ function EgovAdminBoardList(props) {
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
function editBoard(item){
|
||||||
|
handleShow();
|
||||||
|
if(item != undefined) {
|
||||||
|
item.mode = CODE.MODE_MODIFY;
|
||||||
|
}
|
||||||
|
setModalBody(<EgovAdminBoardEdit props={item} reloadFunction={retrieveList}/>)
|
||||||
|
}
|
||||||
|
|
||||||
console.log("------------------------------EgovAdminBoardList [End]");
|
console.log("------------------------------EgovAdminBoardList [End]");
|
||||||
console.groupEnd("EgovAdminBoardList");
|
console.groupEnd("EgovAdminBoardList");
|
||||||
return (
|
return (
|
||||||
|
|
@ -150,6 +165,7 @@ function EgovAdminBoardList(props) {
|
||||||
<span>작성자</span>
|
<span>작성자</span>
|
||||||
<span>작성일</span>
|
<span>작성일</span>
|
||||||
<span>수정일</span>
|
<span>수정일</span>
|
||||||
|
<span><button className={"btn btn_blue_h31 px-1"} onClick={()=>{editBoard(undefined)}}>추가</button></span>
|
||||||
</div>
|
</div>
|
||||||
<div className="result">
|
<div className="result">
|
||||||
{listTag}
|
{listTag}
|
||||||
|
|
@ -169,6 +185,9 @@ function EgovAdminBoardList(props) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<Modal show={show} onHide={handleClose} keyboard={false}>
|
||||||
|
{modalBody}
|
||||||
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,41 @@
|
||||||
import React from 'react';
|
import React, { useState, useEffect, useCallback } from 'react';
|
||||||
|
import { Link, useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
|
import * as EgovNet from 'api/egovFetch';
|
||||||
|
import URL from 'constants/url';
|
||||||
|
|
||||||
function Posts(props) {
|
import { default as EgovLeftNav } from 'components/leftmenu/EgovLeftNavAdmin';
|
||||||
|
|
||||||
|
function StandardCodeMgt(props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container">
|
<div className="container">
|
||||||
Posts
|
<div className="c_wrap">
|
||||||
|
{/* <!-- Location --> */}
|
||||||
|
<div className="location">
|
||||||
|
<ul>
|
||||||
|
<li><Link to={URL.MAIN} className="home">Home</Link></li>
|
||||||
|
<li><Link to={URL.ADMIN} >사이트관리</Link></li>
|
||||||
|
<li>게시판현황</li>
|
||||||
|
<li>게시물 관리</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{/* <!--// Location --> */}
|
||||||
|
|
||||||
|
<div className="layout">
|
||||||
|
{/* <!-- Navigation --> */}
|
||||||
|
<EgovLeftNav></EgovLeftNav>
|
||||||
|
{/* <!--// Navigation --> */}
|
||||||
|
|
||||||
|
<div className="contents NOTICE_LIST" id="contents">
|
||||||
|
<div className="top_tit">
|
||||||
|
<h1 className="tit_1">게시물 관리</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Posts;
|
export default StandardCodeMgt;
|
||||||
|
|
@ -1,13 +1,41 @@
|
||||||
import React from 'react';
|
import React, { useState, useEffect, useCallback } from 'react';
|
||||||
|
import { Link, useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
|
import * as EgovNet from 'api/egovFetch';
|
||||||
|
import URL from 'constants/url';
|
||||||
|
|
||||||
function AboutSiteMgt(props) {
|
import { default as EgovLeftNav } from 'components/leftmenu/EgovLeftNavAdmin';
|
||||||
|
|
||||||
|
function StandardCodeMgt(props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container">
|
<div className="container">
|
||||||
AboutSiteMgt
|
<div className="c_wrap">
|
||||||
|
{/* <!-- Location --> */}
|
||||||
|
<div className="location">
|
||||||
|
<ul>
|
||||||
|
<li><Link to={URL.MAIN} className="home">Home</Link></li>
|
||||||
|
<li><Link to={URL.ADMIN} >사이트관리</Link></li>
|
||||||
|
<li>환경설정</li>
|
||||||
|
<li>관련사이트 관리</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{/* <!--// Location --> */}
|
||||||
|
|
||||||
|
<div className="layout">
|
||||||
|
{/* <!-- Navigation --> */}
|
||||||
|
<EgovLeftNav></EgovLeftNav>
|
||||||
|
{/* <!--// Navigation --> */}
|
||||||
|
|
||||||
|
<div className="contents NOTICE_LIST" id="contents">
|
||||||
|
<div className="top_tit">
|
||||||
|
<h1 className="tit_1">관련사이트 관리</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AboutSiteMgt;
|
export default StandardCodeMgt;
|
||||||
|
|
@ -1,25 +1,8 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { styled } from '@mui/material/styles';
|
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import Paper from '@mui/material/Paper';
|
|
||||||
import List from '@mui/material/List';
|
import * as EgovNet from 'api/egovFetch';
|
||||||
import ListItem from '@mui/material/ListItem';
|
|
||||||
import EditIcon from '@mui/icons-material/Edit';
|
|
||||||
import ListItemAvatar from '@mui/material/ListItemAvatar';
|
|
||||||
import ListItemIcon from '@mui/material/ListItemIcon';
|
|
||||||
import ListItemText from '@mui/material/ListItemText';
|
|
||||||
import Avatar from '@mui/material/Avatar';
|
|
||||||
import IconButton from '@mui/material/IconButton';
|
|
||||||
import FormGroup from '@mui/material/FormGroup';
|
|
||||||
import FormControlLabel from '@mui/material/FormControlLabel';
|
|
||||||
import Checkbox from '@mui/material/Checkbox';
|
|
||||||
import Grid from '@mui/material/Grid';
|
|
||||||
import Typography from '@mui/material/Typography';
|
|
||||||
import FolderIcon from '@mui/icons-material/Folder';
|
|
||||||
import DeleteIcon from '@mui/icons-material/Delete';
|
|
||||||
import AddIcon from '@mui/icons-material/Add';
|
|
||||||
import AddBoxOutlinedIcon from '@mui/icons-material/AddBoxOutlined';
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -35,13 +18,12 @@ import { default as EgovLeftNav } from 'components/leftmenu/EgovLeftNavAdmin';
|
||||||
|
|
||||||
function CommitteeCodeMgt(props) {
|
function CommitteeCodeMgt(props) {
|
||||||
|
|
||||||
const [dense, setDense] = useState(false);
|
const [searchCondition, setSearchCondition] = useState({ paramCodeGroup: null, paramCodeLevel: 'LV_01' });
|
||||||
const [secondary, setSecondary] = useState(false);
|
|
||||||
|
|
||||||
const [depth01List, setDepth01List] = useState(["중앙건설기술심의", "테스트2"]);
|
const [depth01List, setDepth01List] = useState([]);
|
||||||
const [depth02List, setDepth02List] = useState(["123", "테스트2"]);
|
const [depth02List, setDepth02List] = useState([]);
|
||||||
const [depth03List, setDepth03List] = useState(["다람쥐", "쳇바퀴"]);
|
const [depth03List, setDepth03List] = useState([]);
|
||||||
const [depth04List, setDepth04List] = useState(["임시 텍스트", "text"]);
|
const [depth04List, setDepth04List] = useState([]);
|
||||||
const [summaryArray, setSummaryArray] = useState({});
|
const [summaryArray, setSummaryArray] = useState({});
|
||||||
|
|
||||||
const [depth01SelectedIndex, setDepth01SelectedIndex] = React.useState();
|
const [depth01SelectedIndex, setDepth01SelectedIndex] = React.useState();
|
||||||
|
|
@ -49,13 +31,70 @@ function CommitteeCodeMgt(props) {
|
||||||
const [depth03SelectedIndex, setDepth03SelectedIndex] = React.useState();
|
const [depth03SelectedIndex, setDepth03SelectedIndex] = React.useState();
|
||||||
const [depth04SelectedIndex, setDepth04SelectedIndex] = React.useState();
|
const [depth04SelectedIndex, setDepth04SelectedIndex] = React.useState();
|
||||||
|
|
||||||
|
|
||||||
|
// '중앙건설기술심의'에서 특정 item선택 시, 하위 '총괄위원회'목록을 불러온다.
|
||||||
|
useEffect(function () {
|
||||||
|
// 여기에서 레벨2를 지정했다는 명확한 분기가 이루어지도록 수정해야 함.
|
||||||
|
if( typeof depth01SelectedIndex !== 'undefined' ) {
|
||||||
|
setSearchCondition({ paramCodeGroup: depth01List[depth01SelectedIndex].orgId, paramCodeLevel: 'LV_02' });
|
||||||
|
//setDepth02List([]);
|
||||||
|
}
|
||||||
|
if( typeof depth02SelectedIndex !== 'undefined' ) {
|
||||||
|
setSearchCondition({ paramCodeGroup: depth02List[depth02SelectedIndex].orgId, paramCodeLevel: 'LV_03' });
|
||||||
|
//setDepth03List([]);
|
||||||
|
}
|
||||||
|
if( typeof depth03SelectedIndex !== 'undefined' ) {
|
||||||
|
setSearchCondition({ paramCodeGroup: depth03List[depth03SelectedIndex].orgId, paramCodeLevel: 'LV_04' });
|
||||||
|
//setDepth04List([]);
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [depth01SelectedIndex, depth02SelectedIndex, depth03SelectedIndex]);
|
||||||
|
|
||||||
|
|
||||||
|
// 검색 조건이 변경되면 데이터를 불러온다.
|
||||||
|
useEffect(function () {
|
||||||
|
if( typeof searchCondition !== 'undefined' ) {
|
||||||
|
getList(searchCondition);
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [searchCondition]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const requestOptions = {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
'Content-type': 'application/json'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getList = (searchCondition) => {
|
||||||
|
|
||||||
|
EgovNet.requestFetch(`/admin/config/committee-code-management?paramCodeGroup=${searchCondition.paramCodeGroup}¶mCodeLevel=${searchCondition.paramCodeLevel}`,
|
||||||
|
requestOptions,
|
||||||
|
function (resp) {
|
||||||
|
if( searchCondition.paramCodeLevel === 'LV_01' ) {
|
||||||
|
setDepth01List(resp.result.list);
|
||||||
|
} else if( searchCondition.paramCodeLevel === 'LV_02' ) {
|
||||||
|
setDepth02List(resp.result.list);
|
||||||
|
} else if( searchCondition.paramCodeLevel === 'LV_03' ) {
|
||||||
|
setDepth03List(resp.result.list);
|
||||||
|
} else if( searchCondition.paramCodeLevel === 'LV_04' ) {
|
||||||
|
setDepth04List(resp.result.list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(function () {
|
useEffect(function () {
|
||||||
setSummaryArray(
|
setSummaryArray(
|
||||||
{
|
{
|
||||||
"중앙건설기술심의" : depth01List[depth01SelectedIndex],
|
"중앙건설기술심의" : depth01List[depth01SelectedIndex] && depth01List[depth01SelectedIndex].orgNm ? depth01List[depth01SelectedIndex].orgNm : "",
|
||||||
"총괄위원회" : depth02List[depth02SelectedIndex],
|
"총괄위원회" : depth02List[depth02SelectedIndex] && depth02List[depth02SelectedIndex].orgNm ? depth02List[depth02SelectedIndex].orgNm : "",
|
||||||
"건설기준위원회" : depth03List[depth03SelectedIndex],
|
"건설기준위원회" : depth03List[depth03SelectedIndex] && depth03List[depth03SelectedIndex].orgNm ? depth03List[depth03SelectedIndex].orgNm : "",
|
||||||
"실무위원회" : depth04List[depth04SelectedIndex],
|
"실무위원회" : depth04List[depth04SelectedIndex] && depth04List[depth04SelectedIndex].orgNm ? depth04List[depth04SelectedIndex].orgNm : "",
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
console.log(`${depth01List[depth01SelectedIndex]}[${depth01SelectedIndex}]`);
|
console.log(`${depth01List[depth01SelectedIndex]}[${depth01SelectedIndex}]`);
|
||||||
|
|
@ -68,13 +107,7 @@ function CommitteeCodeMgt(props) {
|
||||||
depth01SelectedIndex,
|
depth01SelectedIndex,
|
||||||
depth02SelectedIndex,
|
depth02SelectedIndex,
|
||||||
depth03SelectedIndex,
|
depth03SelectedIndex,
|
||||||
depth04SelectedIndex]);
|
depth04SelectedIndex]);
|
||||||
|
|
||||||
useEffect(function () {
|
|
||||||
console.log( summaryArray );
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [summaryArray]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Location = React.memo(function Location() {
|
const Location = React.memo(function Location() {
|
||||||
|
|
@ -90,6 +123,8 @@ function CommitteeCodeMgt(props) {
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<div className="c_wrap">
|
<div className="c_wrap">
|
||||||
|
|
@ -107,7 +142,6 @@ function CommitteeCodeMgt(props) {
|
||||||
<div className="top_tit">
|
<div className="top_tit">
|
||||||
<h1 className="tit_1">위원회 코드 관리</h1>
|
<h1 className="tit_1">위원회 코드 관리</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
|
@ -119,23 +153,27 @@ function CommitteeCodeMgt(props) {
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ListCreateUpdateDelete title="중앙건설기술심의" items={depth01List} setItemIndex={setDepth01SelectedIndex}/>
|
<ListCreateUpdateDelete title="중앙건설기술심의" items={depth01List} setItemIndex={setDepth01SelectedIndex} nameKey="orgNm" idKey="orgId" />
|
||||||
<ListCreateUpdateDelete title="총괄위원회" items={depth02List} setItemIndex={setDepth02SelectedIndex}/>
|
<ListCreateUpdateDelete title="총괄위원회" items={depth02List} setItemIndex={setDepth02SelectedIndex} nameKey="orgNm" idKey="orgId" />
|
||||||
<ListCreateUpdateDelete title="건설기준위원회" items={depth03List} setItemIndex={setDepth03SelectedIndex}/>
|
<ListCreateUpdateDelete title="건설기준위원회" items={depth03List} setItemIndex={setDepth03SelectedIndex} nameKey="orgNm" idKey="orgId" />
|
||||||
<ListCreateUpdateDelete title="실무위원회" items={depth04List} setItemIndex={setDepth04SelectedIndex}/>
|
<ListCreateUpdateDelete title="실무위원회" items={depth04List} setItemIndex={setDepth04SelectedIndex} nameKey="orgNm" idKey="orgId" />
|
||||||
</Box>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
'& > :not(style)': {
|
|
||||||
mt: 4,
|
|
||||||
width: 245,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ListLabelInputs title="위원회 코드정보" items={summaryArray} />
|
|
||||||
</Box>
|
</Box>
|
||||||
|
{ true &&
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
'& > :not(style)': {
|
||||||
|
mt: 4,
|
||||||
|
width: 245,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ListLabelInputs title="위원회 코드정보" items={summaryArray} />
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
{/* <!--// 본문 --> */}
|
{/* <!--// 본문 --> */}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,39 @@
|
||||||
import React from 'react';
|
import React, { useState, useEffect, useCallback } from 'react';
|
||||||
|
import { Link, useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
|
import * as EgovNet from 'api/egovFetch';
|
||||||
|
import URL from 'constants/url';
|
||||||
|
|
||||||
|
import { default as EgovLeftNav } from 'components/leftmenu/EgovLeftNavAdmin';
|
||||||
|
|
||||||
function StandardCodeMgt(props) {
|
function StandardCodeMgt(props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container">
|
<div className="container">
|
||||||
StandardCodeMgt
|
<div className="c_wrap">
|
||||||
|
{/* <!-- Location --> */}
|
||||||
|
<div className="location">
|
||||||
|
<ul>
|
||||||
|
<li><Link to={URL.MAIN} className="home">Home</Link></li>
|
||||||
|
<li><Link to={URL.ADMIN} >사이트관리</Link></li>
|
||||||
|
<li>환경설정</li>
|
||||||
|
<li>건설기준코드 관리</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{/* <!--// Location --> */}
|
||||||
|
|
||||||
|
<div className="layout">
|
||||||
|
{/* <!-- Navigation --> */}
|
||||||
|
<EgovLeftNav></EgovLeftNav>
|
||||||
|
{/* <!--// Navigation --> */}
|
||||||
|
|
||||||
|
<div className="contents NOTICE_LIST" id="contents">
|
||||||
|
<div className="top_tit">
|
||||||
|
<h1 className="tit_1">건설기준코드 관리</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, {useState, useEffect, useCallback, useRef, PureComponent} from 'react';
|
import React, {useState, useEffect, useCallback} from 'react';
|
||||||
import { Link, useLocation } from 'react-router-dom';
|
import { Link, useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
import {LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer} from 'recharts';
|
import {LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer} from 'recharts';
|
||||||
|
|
@ -145,6 +145,7 @@ function FileConnections(props) {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
// console.groupEnd("EgovAdminPrivacyList.retrieveList()");
|
// console.groupEnd("EgovAdminPrivacyList.retrieveList()");
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
},[listTag]);
|
},[listTag]);
|
||||||
|
|
||||||
const CustomTooltip = ({ active, payload, label }) => {
|
const CustomTooltip = ({ active, payload, label }) => {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, {useState, useEffect, useCallback, useRef, PureComponent} from 'react';
|
import React, {useState, useEffect, useCallback} from 'react';
|
||||||
import { Link, useLocation } from 'react-router-dom';
|
import { Link, useLocation } from 'react-router-dom';
|
||||||
import {BarChart, Bar, Rectangle, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer} from 'recharts';
|
import {BarChart, Bar, Rectangle, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer} from 'recharts';
|
||||||
|
|
||||||
|
|
@ -85,6 +85,7 @@ function MenuConnections(props) {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
// console.groupEnd("EgovAdminPrivacyList.retrieveList()");
|
// console.groupEnd("EgovAdminPrivacyList.retrieveList()");
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
},[listTag]);
|
},[listTag]);
|
||||||
|
|
||||||
const CustomTooltip = ({ active, payload, label }) => {
|
const CustomTooltip = ({ active, payload, label }) => {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useState, useEffect, useCallback, useRef } from 'react';
|
import React, { useState, useEffect, useCallback } from 'react';
|
||||||
import { Link, useLocation } from 'react-router-dom';
|
import { Link, useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
import * as EgovNet from 'api/egovFetch';
|
import * as EgovNet from 'api/egovFetch';
|
||||||
|
|
@ -77,6 +77,7 @@ function PrivacyConnections(props) {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
// console.groupEnd("EgovAdminPrivacyList.retrieveList()");
|
// console.groupEnd("EgovAdminPrivacyList.retrieveList()");
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
},[listTag]);
|
},[listTag]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, {useState, useEffect, useCallback, useRef, PureComponent} from 'react';
|
import React, {useState, useEffect, useCallback} from 'react';
|
||||||
import { Link, useLocation } from 'react-router-dom';
|
import { Link, useLocation } from 'react-router-dom';
|
||||||
import {BarChart, Bar, Rectangle, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer} from 'recharts';
|
import {BarChart, Bar, Rectangle, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer} from 'recharts';
|
||||||
|
|
||||||
|
|
@ -84,6 +84,7 @@ function UserConnections(props) {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
// console.groupEnd("EgovAdminPrivacyList.retrieveList()");
|
// console.groupEnd("EgovAdminPrivacyList.retrieveList()");
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
},[listTag]);
|
},[listTag]);
|
||||||
|
|
||||||
const CustomTooltip = ({ active, payload, label }) => {
|
const CustomTooltip = ({ active, payload, label }) => {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,166 @@
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { Link as RouterLink } from 'react-router-dom';
|
||||||
|
|
||||||
|
// material-ui
|
||||||
|
import { Box, Link, Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from '@mui/material';
|
||||||
|
|
||||||
|
function createData(trackingNo, title, dt, name) {
|
||||||
|
return { trackingNo, title, dt, name };
|
||||||
|
}
|
||||||
|
|
||||||
|
const rows = [
|
||||||
|
createData(1, '흙막이 가시설 띠장 전단 설계시 플래지 ...', '2024-02-04 13:22', '홍길동'),
|
||||||
|
createData(2, '콘크리트 벽체 설계기준 적용 유무 확인 ...', '2024-02-04 13:22', '홍길동'),
|
||||||
|
createData(3, '한중콘크리트 초기양생 관련', '2024-02-04 13:22', '홍길동'),
|
||||||
|
createData(4, 'KDS 21 30 00 : 2022가설흙...', '2024-02-04 13:22', '홍길동'),
|
||||||
|
createData(5, '인테리어필름 시방서 관련', '2024-02-04 13:22', '홍길동'),
|
||||||
|
createData(6, '고온고압증기양생기포콘크리트(ALC) 구조', '2024-02-04 13:22', '홍길동'),
|
||||||
|
createData(7, '지반을 최저등급으로 가정한 경우란', '2024-02-04 13:22', '홍길동')
|
||||||
|
];
|
||||||
|
|
||||||
|
function descendingComparator(a, b, orderBy) {
|
||||||
|
if (b[orderBy] < a[orderBy]) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (b[orderBy] > a[orderBy]) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getComparator(order, orderBy) {
|
||||||
|
return order === 'desc' ? (a, b) => descendingComparator(a, b, orderBy) : (a, b) => -descendingComparator(a, b, orderBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
function stableSort(array, comparator) {
|
||||||
|
const stabilizedThis = array.map((el, index) => [el, index]);
|
||||||
|
stabilizedThis.sort((a, b) => {
|
||||||
|
const order = comparator(a[0], b[0]);
|
||||||
|
if (order !== 0) {
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
return a[1] - b[1];
|
||||||
|
});
|
||||||
|
return stabilizedThis.map((el) => el[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==============================|| ORDER TABLE - HEADER CELL ||============================== //
|
||||||
|
|
||||||
|
const headCells = [
|
||||||
|
{
|
||||||
|
id: 'trackingNo',
|
||||||
|
align: 'left',
|
||||||
|
disablePadding: false,
|
||||||
|
label: 'No.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'title',
|
||||||
|
align: 'center',
|
||||||
|
disablePadding: true,
|
||||||
|
label: '제목'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'dt',
|
||||||
|
align: 'center',
|
||||||
|
disablePadding: false,
|
||||||
|
label: '작성일자'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'name',
|
||||||
|
align: 'center',
|
||||||
|
disablePadding: false,
|
||||||
|
label: '작성자'
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// ==============================|| ORDER TABLE - HEADER ||============================== //
|
||||||
|
|
||||||
|
function OrderTableHead({ order, orderBy }) {
|
||||||
|
return (
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
{headCells.map((headCell) => (
|
||||||
|
<TableCell
|
||||||
|
key={headCell.id}
|
||||||
|
align={headCell.align}
|
||||||
|
padding={headCell.disablePadding ? 'none' : 'normal'}
|
||||||
|
sortDirection={orderBy === headCell.id ? order : false}
|
||||||
|
sx={{ width:headCell.id === 'trackingNo' ? '10%' :
|
||||||
|
headCell.id === 'title' ? '50%' :
|
||||||
|
headCell.id === 'dt' ? '25%' : '15%', }}
|
||||||
|
>
|
||||||
|
{headCell.label}
|
||||||
|
</TableCell>
|
||||||
|
))}
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
OrderTableHead.propTypes = {
|
||||||
|
order: PropTypes.string,
|
||||||
|
orderBy: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
// ==============================|| ORDER TABLE ||============================== //
|
||||||
|
|
||||||
|
export default function OrderTable() {
|
||||||
|
const [order] = useState('asc');
|
||||||
|
const [orderBy] = useState('trackingNo');
|
||||||
|
const [selected] = useState([]);
|
||||||
|
|
||||||
|
const isSelected = (trackingNo) => selected.indexOf(trackingNo) !== -1;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<TableContainer
|
||||||
|
sx={{
|
||||||
|
width: '100%',
|
||||||
|
overflowX: 'auto',
|
||||||
|
position: 'relative',
|
||||||
|
display: 'block',
|
||||||
|
maxWidth: '100%',
|
||||||
|
'& td, & th': { whiteSpace: 'nowrap' }
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Table
|
||||||
|
aria-labelledby="tableTitle"
|
||||||
|
sx={{
|
||||||
|
'& .MuiTableCell-root:first-of-type': {
|
||||||
|
pl: 2
|
||||||
|
},
|
||||||
|
'& .MuiTableCell-root:last-of-type': {
|
||||||
|
pr: 0
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<OrderTableHead order={order} orderBy={orderBy} />
|
||||||
|
<TableBody>
|
||||||
|
{stableSort(rows, getComparator(order, orderBy)).map((row, index) => {
|
||||||
|
const isItemSelected = isSelected(row.trackingNo);
|
||||||
|
const labelId = `enhanced-table-checkbox-${index}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableRow
|
||||||
|
hover
|
||||||
|
role="checkbox"
|
||||||
|
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
|
||||||
|
aria-checked={isItemSelected}
|
||||||
|
tabIndex={-1}
|
||||||
|
key={row.trackingNo}
|
||||||
|
selected={isItemSelected}
|
||||||
|
>
|
||||||
|
<TableCell width="10%" align="left" component="th" id={labelId} scope="row">{row.trackingNo}</TableCell>
|
||||||
|
<TableCell width="50%" align="left"><Link color="secondary" component={RouterLink} to="" sx={{ overflow: 'hidden', textOverflow: 'ellipsis', display: 'block'}}>{row.title}</Link></TableCell>
|
||||||
|
<TableCell width="25%" align="center">{row.dt}</TableCell>
|
||||||
|
<TableCell width="15%" align="center">{row.name}</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</TableContainer>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,202 +0,0 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
|
||||||
import { Link, useLocation, useNavigate } from 'react-router-dom';
|
|
||||||
|
|
||||||
import * as EgovNet from 'api/egovFetch';
|
|
||||||
import URL from 'constants/url';
|
|
||||||
import CODE from 'constants/code';
|
|
||||||
|
|
||||||
import { default as EgovLeftNav } from 'components/leftmenu/EgovLeftNavAdmin';
|
|
||||||
import EgovAttachFile from 'components/EgovAttachFile';
|
|
||||||
|
|
||||||
function EgovAdminScheduleDetail(props) {
|
|
||||||
console.group("EgovAdminScheduleDetail");
|
|
||||||
console.log("[Start] EgovAdminScheduleDetail ------------------------------");
|
|
||||||
console.log("EgovAdminScheduleDetail [props] : ", props);
|
|
||||||
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const location = useLocation();
|
|
||||||
console.log("EgovAdminScheduleDetail [location] : ", location);
|
|
||||||
|
|
||||||
const [scheduleDetail, setScheduleDetail] = useState({});
|
|
||||||
const [boardAttachFiles, setBoardAttachFiles] = useState();
|
|
||||||
const [user, setUser] = useState({});
|
|
||||||
|
|
||||||
const retrieveDetail = () => {
|
|
||||||
|
|
||||||
const retrieveDetailURL = `/schedule/${location.state?.schdulId}`;
|
|
||||||
const requestOptions = {
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
'Content-type': 'application/json',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EgovNet.requestFetch(retrieveDetailURL,
|
|
||||||
requestOptions,
|
|
||||||
function (resp) {
|
|
||||||
let rawScheduleDetail = resp.result.scheduleDetail;
|
|
||||||
rawScheduleDetail.startDateTime = convertDate(rawScheduleDetail.schdulBgnde);
|
|
||||||
rawScheduleDetail.endDateTime = convertDate(rawScheduleDetail.schdulEndde);
|
|
||||||
rawScheduleDetail.reptitSeCodeNm = getCodeName(resp.result.reptitSeCode, resp.result.scheduleDetail.reptitSeCode);
|
|
||||||
rawScheduleDetail.schdulIpcrCodeNm = getCodeName(resp.result.schdulIpcrCode, resp.result.scheduleDetail.schdulIpcrCode);
|
|
||||||
rawScheduleDetail.schdulSeNm = getCodeName(resp.result.schdulSe, resp.result.scheduleDetail.schdulSe);
|
|
||||||
setScheduleDetail(rawScheduleDetail);
|
|
||||||
setUser(resp.result.user);
|
|
||||||
setBoardAttachFiles(resp.result.resultFiles);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const convertDate = (str) => {
|
|
||||||
let year = str.substring(0, 4);
|
|
||||||
let month = str.substring(4, 6);
|
|
||||||
let date = str.substring(6, 8);
|
|
||||||
let hour = str.substring(8, 10);
|
|
||||||
let minute = str.substring(10, 12);
|
|
||||||
return {
|
|
||||||
year: year,
|
|
||||||
month: month,
|
|
||||||
date: date,
|
|
||||||
hour: hour,
|
|
||||||
minute: minute,
|
|
||||||
dateForm: year + "년 " + month + "월 " + date + "일 " + hour + "시 " + minute + "분 "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getCodeName = (codeArr, code) => {
|
|
||||||
return (
|
|
||||||
codeArr.map((codeObj) => {
|
|
||||||
if (codeObj.code === code.trim()) return codeObj.codeNm
|
|
||||||
else return "";
|
|
||||||
})
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onClickDeleteSchedule = (schdulId) => {
|
|
||||||
const deleteBoardURL = `/schedule/${schdulId}`;
|
|
||||||
|
|
||||||
const requestOptions = {
|
|
||||||
method: "DELETE",
|
|
||||||
headers: {
|
|
||||||
'Content-type': 'application/json',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EgovNet.requestFetch(deleteBoardURL,
|
|
||||||
requestOptions,
|
|
||||||
(resp) => {
|
|
||||||
console.log("====>>> Schdule delete= ", resp);
|
|
||||||
if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
|
|
||||||
alert("게시글이 삭제되었습니다.")
|
|
||||||
navigate(URL.ADMIN_SCHEDULE ,{ replace: true });
|
|
||||||
} else {
|
|
||||||
// alert("ERR : " + resp.message);
|
|
||||||
navigate({pathname: URL.ERROR}, {state: {msg : resp.resultMessage}});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(function () {
|
|
||||||
retrieveDetail();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
console.log("------------------------------EgovAdminScheduleDetail [End]");
|
|
||||||
console.groupEnd("EgovAdminScheduleDetail");
|
|
||||||
return (
|
|
||||||
<div className="container">
|
|
||||||
<div className="c_wrap">
|
|
||||||
{/* <!-- Location --> */}
|
|
||||||
<div className="location">
|
|
||||||
<ul>
|
|
||||||
<li><Link to={URL.MAIN} className="home">Home</Link></li>
|
|
||||||
<li><Link to={URL.ADMIN}>사이트관리</Link></li>
|
|
||||||
<li>일정관리</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{/* <!--// Location --> */}
|
|
||||||
|
|
||||||
<div className="layout">
|
|
||||||
{/* <!-- Navigation --> */}
|
|
||||||
<EgovLeftNav></EgovLeftNav>
|
|
||||||
{/* <!--// Navigation --> */}
|
|
||||||
|
|
||||||
<div className="contents SITE_GALLARY_VIEW" id="contents">
|
|
||||||
{/* <!-- 본문 --> */}
|
|
||||||
|
|
||||||
<div className="top_tit">
|
|
||||||
<h1 className="tit_1">사이트관리</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2 className="tit_2">일정관리 상세보기</h2>
|
|
||||||
|
|
||||||
{/* <!-- 게시판 상세보기 --> */}
|
|
||||||
<div className="board_view2">
|
|
||||||
<dl>
|
|
||||||
<dt>일정구분</dt>
|
|
||||||
<dd>{scheduleDetail.schdulSeNm}</dd>
|
|
||||||
</dl>
|
|
||||||
<dl>
|
|
||||||
<dt>중요도</dt>
|
|
||||||
<dd>{scheduleDetail.schdulIpcrCodeNm}</dd>
|
|
||||||
</dl>
|
|
||||||
<dl>
|
|
||||||
<dt>부서</dt>
|
|
||||||
<dd>{scheduleDetail.schdulDeptName}</dd>
|
|
||||||
</dl>
|
|
||||||
<dl>
|
|
||||||
<dt>일정명</dt>
|
|
||||||
<dd>{scheduleDetail.schdulNm}</dd>
|
|
||||||
</dl>
|
|
||||||
<dl>
|
|
||||||
<dt>일정내용</dt>
|
|
||||||
<dd>{scheduleDetail.schdulCn}</dd>
|
|
||||||
</dl>
|
|
||||||
<dl>
|
|
||||||
<dt>반복구분</dt>
|
|
||||||
<dd>{scheduleDetail.reptitSeCodeNm}</dd>
|
|
||||||
</dl>
|
|
||||||
<dl>
|
|
||||||
<dt>날짜/시간</dt>
|
|
||||||
<dd> {scheduleDetail.startDateTime?.dateForm} ~ {scheduleDetail.endDateTime?.dateForm}</dd>
|
|
||||||
</dl>
|
|
||||||
<dl>
|
|
||||||
<dt>담당자</dt>
|
|
||||||
<dd>{scheduleDetail.schdulChargerName}</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<EgovAttachFile boardFiles={boardAttachFiles} />
|
|
||||||
|
|
||||||
{/* <!-- 버튼영역 --> */}
|
|
||||||
<div className="board_btn_area">
|
|
||||||
{user.id &&
|
|
||||||
<div className="left_col btn1">
|
|
||||||
<Link to={{pathname: URL.ADMIN_SCHEDULE_MODIFY}}
|
|
||||||
state={{
|
|
||||||
schdulId: location.state?.schdulId
|
|
||||||
}}
|
|
||||||
className="btn btn_skyblue_h46 w_100">수정</Link>
|
|
||||||
<button className="btn btn_skyblue_h46 w_100"
|
|
||||||
onClick={(e) => {
|
|
||||||
onClickDeleteSchedule(location.state?.schdulId);
|
|
||||||
}}>삭제</button>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<div className="right_col btn1">
|
|
||||||
<Link to={URL.ADMIN_SCHEDULE} className="btn btn_blue_h46 w_100">목록</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/* <!--// 버튼영역 --> */}
|
|
||||||
</div>
|
|
||||||
{/* <!-- 게시판 상세보기 --> */}
|
|
||||||
|
|
||||||
{/* <!--// 본문 --> */}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default EgovAdminScheduleDetail;
|
|
||||||
|
|
@ -1,364 +0,0 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
|
||||||
import { Link, useLocation, useNavigate } from 'react-router-dom';
|
|
||||||
import DatePicker from "react-datepicker";
|
|
||||||
|
|
||||||
import * as EgovNet from 'api/egovFetch';
|
|
||||||
import URL from 'constants/url';
|
|
||||||
import CODE from 'constants/code';
|
|
||||||
|
|
||||||
import { default as EgovLeftNav } from 'components/leftmenu/EgovLeftNavAdmin';
|
|
||||||
import EgovAttachFile from 'components/EgovAttachFile';
|
|
||||||
import EgovRadioButtonGroup from 'components/EgovRadioButtonGroup';
|
|
||||||
|
|
||||||
import 'react-datepicker/dist/react-datepicker.css';
|
|
||||||
|
|
||||||
function EgovAdminScheduleEdit(props) {
|
|
||||||
console.group("EgovAdminScheduleEdit");
|
|
||||||
console.log("[Start] EgovAdminScheduleEdit ------------------------------");
|
|
||||||
console.log("EgovAdminScheduleEdit [props] : ", props);
|
|
||||||
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const location = useLocation();
|
|
||||||
console.log("EgovAdminScheduleEdit [location] : ", location);
|
|
||||||
|
|
||||||
const reptitSeCodeRadioGroup = [{ value: "1", label: "당일" }, { value: "2", label: "반복" }, { value: "3", label: "연속" }];
|
|
||||||
|
|
||||||
const [modeInfo, setModeInfo] = useState({ mode: props.mode });
|
|
||||||
const [scheduleDetail, setScheduleDetail] = useState({ schdulDeptName: "관리자부서", schdulChargerName: "관리자", schdulKindCode: 2, reptitSeCode: "1", startDate: new Date(), endDate: new Date() });
|
|
||||||
const [boardAttachFiles, setBoardAttachFiles] = useState();
|
|
||||||
|
|
||||||
const [schdulBgndeHH, setSchdulBgndeHH] = useState();
|
|
||||||
const [schdulBgndeMM, setSchdulBgndeMM] = useState();
|
|
||||||
const [schdulEnddeHH, setSchdulEnddeHH] = useState();
|
|
||||||
const [schdulEnddeMM, setSchdulEnddeMM] = useState();
|
|
||||||
|
|
||||||
|
|
||||||
const initMode = () => {
|
|
||||||
switch (props.mode) {
|
|
||||||
case CODE.MODE_CREATE:
|
|
||||||
setModeInfo({
|
|
||||||
...modeInfo,
|
|
||||||
modeTitle: "등록",
|
|
||||||
method : "POST",
|
|
||||||
editURL: '/schedule'
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case CODE.MODE_MODIFY:
|
|
||||||
setModeInfo({
|
|
||||||
...modeInfo,
|
|
||||||
modeTitle: "수정",
|
|
||||||
method : "PUT",
|
|
||||||
editURL: '/schedule'
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
navigate({pathname: URL.ERROR}, {state: {msg : ""}});
|
|
||||||
}
|
|
||||||
retrieveDetail();
|
|
||||||
}
|
|
||||||
|
|
||||||
const convertDate = (str) => {
|
|
||||||
let year = str.substring(0, 4);
|
|
||||||
let month = str.substring(4, 6);
|
|
||||||
let date = str.substring(6, 8);
|
|
||||||
let hour = str.substring(8, 10);
|
|
||||||
let minute = str.substring(10, 12);
|
|
||||||
return new Date(year, month - 1, date, hour, minute)
|
|
||||||
}
|
|
||||||
|
|
||||||
const retrieveDetail = () => {
|
|
||||||
if (modeInfo.mode === CODE.MODE_CREATE) {// 조회/등록이면 조회 안함
|
|
||||||
setScheduleDetail({
|
|
||||||
...scheduleDetail,
|
|
||||||
schdulBgnde: location.state.iUseDate,
|
|
||||||
schdulEndde: location.state.iUseDate,
|
|
||||||
startDate: convertDate(location.state.iUseDate),
|
|
||||||
endDate: convertDate(location.state.iUseDate),
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const retrieveDetailURL = `/schedule/${location.state?.schdulId}`;
|
|
||||||
const requestOptions = {
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
'Content-type': 'application/json'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EgovNet.requestFetch(retrieveDetailURL,
|
|
||||||
requestOptions,
|
|
||||||
function (resp) {
|
|
||||||
let rawScheduleDetail = resp.result.scheduleDetail;
|
|
||||||
//기본값 설정
|
|
||||||
setScheduleDetail({
|
|
||||||
...scheduleDetail,
|
|
||||||
...rawScheduleDetail,
|
|
||||||
startDate: convertDate(rawScheduleDetail.schdulBgnde),
|
|
||||||
endDate: convertDate(rawScheduleDetail.schdulEndde),
|
|
||||||
atchFileId : rawScheduleDetail.atchFileId.trim(),
|
|
||||||
});
|
|
||||||
setBoardAttachFiles(resp.result.resultFiles);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const updateSchedule = () => {
|
|
||||||
const formData = new FormData();
|
|
||||||
|
|
||||||
for (let key in scheduleDetail) {
|
|
||||||
formData.append(key, scheduleDetail[key]);
|
|
||||||
console.log("scheduleDetail [%s] ", key, scheduleDetail[key]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (formValidator(formData)) {
|
|
||||||
const requestOptions = {
|
|
||||||
method: modeInfo.method,
|
|
||||||
body: formData
|
|
||||||
}
|
|
||||||
|
|
||||||
if (modeInfo.mode === CODE.MODE_MODIFY) {
|
|
||||||
modeInfo.editURL = `${modeInfo.editURL}/${location.state?.schdulId}`;
|
|
||||||
}
|
|
||||||
EgovNet.requestFetch(modeInfo.editURL,
|
|
||||||
requestOptions,
|
|
||||||
(resp) => {
|
|
||||||
if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
|
|
||||||
navigate({ pathname: URL.ADMIN_SCHEDULE });
|
|
||||||
} else {
|
|
||||||
navigate({pathname: URL.ERROR}, {state: {msg : resp.resultMessage}});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const formValidator = (formData) => {
|
|
||||||
if (formData.get('schdulNm') === null || formData.get('schdulNm') === "") {
|
|
||||||
alert("일정명은 필수 값입니다.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (formData.get('schdulCn') === null || formData.get('schdulCn') === "") {
|
|
||||||
alert("일정내용은 필수 값입니다.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (formData.get('schdulSe') === null || formData.get('schdulSe') === "") {
|
|
||||||
alert("일정구분은 필수 값입니다.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (formData.get('schdulIpcrCode') === null || formData.get('schdulIpcrCode') === "") {
|
|
||||||
alert("중요도는 필수 값입니다.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (formData.get('reptitSeCode') === null ||formData.get('reptitSeCode') === "") {
|
|
||||||
alert("반복구분은 필수 값입니다.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (formData.get('schdulBgnde') > formData.get('schdulEndde')) {
|
|
||||||
alert("종료일시는 시작일시보다 앞 설 수 없습니다.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const getDateFourteenDigit = (date) => {
|
|
||||||
return getYYYYMMDD(date).toString() + makeTwoDigit(date.getHours()) + makeTwoDigit(date.getMinutes()) + makeTwoDigit(date.getSeconds());
|
|
||||||
}
|
|
||||||
const getYYYYMMDD = (date) => {
|
|
||||||
return date.getFullYear().toString() + makeTwoDigit(Number(date.getMonth() + 1)) + makeTwoDigit(date.getDate());
|
|
||||||
}
|
|
||||||
const makeTwoDigit = (number) => {
|
|
||||||
return number < 10 ? "0" + number : number.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(function () {
|
|
||||||
initMode();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
console.log("------------------------------EgovAdminScheduleEdit [End]");
|
|
||||||
console.groupEnd("EgovAdminScheduleEdit");
|
|
||||||
return (
|
|
||||||
<div className="container">
|
|
||||||
<div className="c_wrap">
|
|
||||||
{/* <!-- Location --> */}
|
|
||||||
<div className="location">
|
|
||||||
<ul>
|
|
||||||
<li><Link to={URL.MAIN} className="home">Home</Link></li>
|
|
||||||
<li><Link to={URL.ADMIN}>사이트관리</Link></li>
|
|
||||||
<li>일정관리</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{/* <!--// Location --> */}
|
|
||||||
|
|
||||||
<div className="layout">
|
|
||||||
{/* <!-- Navigation --> */}
|
|
||||||
<EgovLeftNav></EgovLeftNav>
|
|
||||||
{/* <!--// Navigation --> */}
|
|
||||||
|
|
||||||
<div className="contents SITE_SCHDULE_REG" id="contents">
|
|
||||||
{/* <!-- 본문 --> */}
|
|
||||||
|
|
||||||
<div className="top_tit">
|
|
||||||
<h1 className="tit_1">사이트관리</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2 className="tit_2">일정관리 상세보기</h2>
|
|
||||||
|
|
||||||
{/* <!-- 게시판 상세보기 --> */}
|
|
||||||
<div className="board_view2">
|
|
||||||
<dl>
|
|
||||||
<dt>일정구분<span className="req">필수</span></dt>
|
|
||||||
<dd>
|
|
||||||
<label className="f_select w_130" htmlFor="schdulSe">
|
|
||||||
<select id="schdulSe" name="schdulSe" title="일정구분"
|
|
||||||
value={scheduleDetail.schdulSe}
|
|
||||||
onChange={(e) => setScheduleDetail({ ...scheduleDetail, schdulSe: e.target.value })}>
|
|
||||||
<option value="">선택</option>
|
|
||||||
<option value="1">회의</option>
|
|
||||||
<option value="2">세미나</option>
|
|
||||||
<option value="3">강의</option>
|
|
||||||
<option value="4">교육</option>
|
|
||||||
<option value="5">기타</option>
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<dl>
|
|
||||||
<dt>중요도<span className="req">필수</span></dt>
|
|
||||||
<dd>
|
|
||||||
<label className="f_select w_130" htmlFor="schdulIpcrCode">
|
|
||||||
<select id="schdulIpcrCode" name="schdulIpcrCode" title="중요도"
|
|
||||||
value={scheduleDetail.schdulIpcrCode}
|
|
||||||
onChange={(e) => setScheduleDetail({ ...scheduleDetail, schdulIpcrCode: e.target.value })}>
|
|
||||||
<option value="">선택</option>
|
|
||||||
<option value="A">높음</option>
|
|
||||||
<option value="B">보통</option>
|
|
||||||
<option value="C">낮음</option>
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<dl>
|
|
||||||
<dt><label htmlFor="schdulDeptName">부서</label><span className="req">필수</span></dt>
|
|
||||||
<dd>
|
|
||||||
<input className="f_input2 w_full" type="text" name="schdulDeptName" title="부서" id="schdulDeptName"
|
|
||||||
value={scheduleDetail.schdulDeptName} readOnly
|
|
||||||
/>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<dl>
|
|
||||||
<dt><label htmlFor="schdulNm">일정명</label><span className="req">필수</span></dt>
|
|
||||||
<dd>
|
|
||||||
<input className="f_input2 w_full" type="text" name="schdulNm" title="부서" id="schdulNm" placeholder="일정 테스트"
|
|
||||||
defaultValue={scheduleDetail.schdulNm}
|
|
||||||
onChange={(e) => setScheduleDetail({ ...scheduleDetail, schdulNm: e.target.value })} />
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<dl>
|
|
||||||
<dt><label htmlFor="schdulCn">일정내용</label><span className="req">필수</span></dt>
|
|
||||||
<dd>
|
|
||||||
<textarea className="f_txtar w_full h_100" name="schdulCn" id="schdulCn" cols="30" rows="10" placeholder="일정내용"
|
|
||||||
defaultValue={scheduleDetail.schdulCn}
|
|
||||||
onChange={(e) => setScheduleDetail({ ...scheduleDetail, schdulCn: e.target.value })}
|
|
||||||
></textarea>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<dl>
|
|
||||||
<dt>반복구분<span className="req">필수</span></dt>
|
|
||||||
<dd>
|
|
||||||
<EgovRadioButtonGroup
|
|
||||||
name="reptitSeCode"
|
|
||||||
radioGroup={reptitSeCodeRadioGroup}
|
|
||||||
setValue={scheduleDetail.reptitSeCode.trim()}
|
|
||||||
setter={(v) => setScheduleDetail({ ...scheduleDetail, reptitSeCode: v })} />
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<dl>
|
|
||||||
<dt>날짜/시간<span className="req">필수</span></dt>
|
|
||||||
<dd className="datetime">
|
|
||||||
<span className="line_break">
|
|
||||||
<DatePicker
|
|
||||||
selected={scheduleDetail.startDate}
|
|
||||||
name="schdulBgnde"
|
|
||||||
className="f_input"
|
|
||||||
dateFormat="yyyy-MM-dd HH:mm"
|
|
||||||
showTimeInput
|
|
||||||
onChange={(date) => {
|
|
||||||
console.log("setStartDate : ", date);
|
|
||||||
setScheduleDetail({ ...scheduleDetail, schdulBgnde: getDateFourteenDigit(date), schdulBgndeYYYMMDD: getYYYYMMDD(date), schdulBgndeHH: date.getHours(), schdulBgndeMM: date.getMinutes(), startDate: date });
|
|
||||||
setSchdulBgndeHH(date.getHours());
|
|
||||||
setSchdulBgndeMM(date.getMinutes());
|
|
||||||
}} />
|
|
||||||
<input type="hidden" name="schdulBgndeHH" defaultValue={schdulBgndeHH} readOnly />
|
|
||||||
<input type="hidden" name="schdulBgndeMM" defaultValue={schdulBgndeMM} readOnly />
|
|
||||||
<span className="f_inn_txt">~</span>
|
|
||||||
</span>
|
|
||||||
<span className="line_break">
|
|
||||||
<DatePicker
|
|
||||||
selected={scheduleDetail.endDate}
|
|
||||||
name="schdulEndde"
|
|
||||||
className="f_input"
|
|
||||||
dateFormat="yyyy-MM-dd HH:mm"
|
|
||||||
showTimeInput
|
|
||||||
minDate={scheduleDetail.startDate}
|
|
||||||
onChange={(date) => {
|
|
||||||
console.log("setEndDate: ", date);
|
|
||||||
setScheduleDetail({ ...scheduleDetail, schdulEndde: getDateFourteenDigit(date), schdulEnddeYYYMMDD: getYYYYMMDD(date), schdulEnddeHH: date.getHours(), schdulEnddeMM: date.getMinutes(), endDate: date });
|
|
||||||
setSchdulEnddeHH(date.getHours());
|
|
||||||
setSchdulEnddeMM(date.getMinutes());
|
|
||||||
}
|
|
||||||
} />
|
|
||||||
<input type="hidden" name="schdulEnddeHH" defaultValue={schdulEnddeHH} readOnly />
|
|
||||||
<input type="hidden" name="schdulEnddeMM" defaultValue={schdulEnddeMM} readOnly />
|
|
||||||
</span>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<dl>
|
|
||||||
<dt><label htmlFor="schdulChargerName">담당자</label><span className="req">필수</span></dt>
|
|
||||||
<dd>
|
|
||||||
<input className="f_input2 w_full" type="text" name="schdulChargerName" id="schdulChargerName" defaultValue="관리자" readOnly
|
|
||||||
/>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<EgovAttachFile
|
|
||||||
fnChangeFile={(attachfile) => {
|
|
||||||
console.log("====>>> Changed attachfile file = ", attachfile);
|
|
||||||
const arrayConcat = { ...scheduleDetail}; // 기존 단일 파일 업로드에서 다중파일 객체 추가로 변환(아래 for문으로)
|
|
||||||
for ( let i = 0; i < attachfile.length; i++) {
|
|
||||||
arrayConcat[`file_${i}`] = attachfile[i];
|
|
||||||
}
|
|
||||||
setScheduleDetail(arrayConcat);
|
|
||||||
}}
|
|
||||||
fnDeleteFile={(deletedFile) => {
|
|
||||||
console.log("====>>> Delete deletedFile = ", deletedFile);
|
|
||||||
setBoardAttachFiles(deletedFile);
|
|
||||||
}}
|
|
||||||
boardFiles={boardAttachFiles}
|
|
||||||
mode={props.mode} />
|
|
||||||
|
|
||||||
{/* <!-- 버튼영역 --> */}
|
|
||||||
<div className="board_btn_area">
|
|
||||||
<div className="left_col btn1">
|
|
||||||
<button className="btn btn_skyblue_h46 w_100"
|
|
||||||
onClick={() => updateSchedule()}
|
|
||||||
> 저장</button>
|
|
||||||
<a href="#!" className="btn btn_skyblue_h46 w_100">삭제</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="right_col btn1">
|
|
||||||
<Link to={URL.ADMIN_SCHEDULE} className="btn btn_blue_h46 w_100">목록</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/* <!--// 버튼영역 --> */}
|
|
||||||
</div>
|
|
||||||
{/* <!-- 게시판 상세보기 --> */}
|
|
||||||
|
|
||||||
{/* <!--// 본문 --> */}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div >
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default EgovAdminScheduleEdit;
|
|
||||||
|
|
@ -1,328 +1,221 @@
|
||||||
import React, {useState, useEffect, useCallback, PureComponent} from 'react';
|
import React, {useState, useEffect, useCallback} from 'react'; // PureComponent
|
||||||
import {Link, useLocation} from 'react-router-dom';
|
import {Link} from 'react-router-dom'; //useLocation
|
||||||
import {BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer} from 'recharts';
|
|
||||||
|
// import {BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer} from 'recharts';
|
||||||
|
|
||||||
import * as EgovNet from 'api/egovFetch';
|
import * as EgovNet from 'api/egovFetch';
|
||||||
import URL from 'constants/url';
|
import URL from 'constants/url';
|
||||||
import CODE from 'constants/code';
|
// import CODE from 'constants/code';
|
||||||
|
|
||||||
|
// material-ui
|
||||||
|
import { Box, Button, Grid, Stack, Typography } from '@mui/material';
|
||||||
|
import MainCard from 'components/cards/MainCard';
|
||||||
|
import BbsTable from './BbsTable';
|
||||||
|
import IncomeAreaChart from './IncomeAreaChart';
|
||||||
|
import MonthlyBarChart from './MonthlyBarChart';
|
||||||
|
import ReportAreaChart from './ReportAreaChart';
|
||||||
|
import AnalyticEcommerce from 'components/cards/AnalyticEcommerce';
|
||||||
|
|
||||||
import {default as EgovLeftNav} from 'components/leftmenu/EgovLeftNavAdmin';
|
import {default as EgovLeftNav} from 'components/leftmenu/EgovLeftNavAdmin';
|
||||||
|
|
||||||
function EgovAdminScheduleList(props) {
|
function EgovAdminDashboard(props) {
|
||||||
console.group("EgovAdminScheduleList");
|
// console.group("EgovAdminScheduleList");
|
||||||
console.log("[Start] EgovAdminScheduleList ------------------------------");
|
// console.log("[Start] EgovAdminScheduleList ------------------------------");
|
||||||
console.log("EgovAdminScheduleList [props] : ", props);
|
// console.log("EgovAdminScheduleList [props] : ", props);
|
||||||
|
|
||||||
const location = useLocation();
|
// const location = useLocation();
|
||||||
console.log("EgovAdminScheduleList [location] : ", location);
|
// console.log("EgovAdminScheduleList [location] : ", location);
|
||||||
|
|
||||||
const DATE = new Date();
|
const DATE = new Date();
|
||||||
const TODAY = new Date(DATE.getFullYear(), DATE.getMonth(), DATE.getDate());
|
// const TODAY = new Date(DATE.getFullYear(), DATE.getMonth(), DATE.getDate());
|
||||||
|
//
|
||||||
|
// const [searchCondition, setSearchCondition] = useState(location.state?.searchCondition || {schdulSe: '', year: TODAY.getFullYear(), month: TODAY.getMonth(), date: TODAY.getDate()});
|
||||||
|
// const [calendarTag, setCalendarTag] = useState([]);
|
||||||
|
//
|
||||||
|
// const [scheduleList, setScheduleList] = useState([]);
|
||||||
|
|
||||||
const [searchCondition, setSearchCondition] = useState(location.state?.searchCondition || {schdulSe: '', year: TODAY.getFullYear(), month: TODAY.getMonth(), date: TODAY.getDate()});
|
// const innerConsole = (...args) => {
|
||||||
const [calendarTag, setCalendarTag] = useState([]);
|
// console.log(...args);
|
||||||
|
// }
|
||||||
|
|
||||||
const [scheduleList, setScheduleList] = useState([]);
|
// const changeDate = (target, amount) => {
|
||||||
const [dailyUserLogList, setDailyUserLogList] = useState([]);
|
// let changedDate;
|
||||||
|
//
|
||||||
|
// if (target === CODE.DATE_YEAR) {
|
||||||
|
// changedDate = new Date(searchCondition.year + amount, searchCondition.month, searchCondition.date);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (target === CODE.DATE_MONTH) {
|
||||||
|
// changedDate = new Date(searchCondition.year, searchCondition.month + amount, searchCondition.date);
|
||||||
|
// }
|
||||||
|
// setSearchCondition({...searchCondition, year: changedDate.getFullYear(), month: changedDate.getMonth(), date: changedDate.getDate()});
|
||||||
|
// }
|
||||||
|
|
||||||
const innerConsole = (...args) => {
|
// const retrieveList = useCallback((srchcnd) => {
|
||||||
console.log(...args);
|
// console.groupCollapsed("EgovAdminScheduleList.retrieveList()");
|
||||||
}
|
//
|
||||||
|
// const retrieveListURL = '/schedule/month' + EgovNet.getQueryString(srchcnd);
|
||||||
|
//
|
||||||
|
// const requestOptions = {
|
||||||
|
// method: "GET",
|
||||||
|
// headers: {
|
||||||
|
// 'Content-type': 'application/json',
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// EgovNet.requestFetch(retrieveListURL,
|
||||||
|
// requestOptions,
|
||||||
|
// (resp) => {
|
||||||
|
// setScheduleList(resp.result.resultList);
|
||||||
|
// },
|
||||||
|
// function (resp) {
|
||||||
|
// console.log("err response : ", resp);
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
// console.groupEnd("EgovAdminScheduleList.retrieveList()");
|
||||||
|
// }, []);
|
||||||
|
|
||||||
const getLastDateOfMonth = (year, month) => {
|
|
||||||
const LAST_DATE_SUPPLMENT = 1;
|
|
||||||
return new Date(year, month + LAST_DATE_SUPPLMENT, 0);
|
|
||||||
}
|
|
||||||
const getFirstDateOfMonth = (year, month) => {
|
|
||||||
return new Date(year, month, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const changeDate = (target, amount) => {
|
// const Location = React.memo(function Location() {
|
||||||
let changedDate;
|
// return (
|
||||||
|
// <div className="location">
|
||||||
|
// <ul>
|
||||||
|
// <li><Link to={URL.MAIN} className="home">Home</Link></li>
|
||||||
|
// <li><Link to={URL.ADMIN}>사이트관리</Link></li>
|
||||||
|
// <li>Dashboard</li>
|
||||||
|
// </ul>
|
||||||
|
// </div>
|
||||||
|
// )
|
||||||
|
// });
|
||||||
|
|
||||||
if (target === CODE.DATE_YEAR) {
|
// useEffect(() => {
|
||||||
changedDate = new Date(searchCondition.year + amount, searchCondition.month, searchCondition.date);
|
// //retrieveList(searchCondition); disabled by thkim
|
||||||
}
|
// // eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
// }, [searchCondition]);
|
||||||
|
|
||||||
if (target === CODE.DATE_MONTH) {
|
// const [dailyUserLogList, setDailyUserLogList] = useState([]);
|
||||||
changedDate = new Date(searchCondition.year, searchCondition.month + amount, searchCondition.date);
|
// const [isDailyChart, setIsDailyChart] = useState(true);
|
||||||
}
|
//
|
||||||
setSearchCondition({...searchCondition, year: changedDate.getFullYear(), month: changedDate.getMonth(), date: changedDate.getDate()});
|
// const getDailyUserLogList = useCallback(() => {
|
||||||
}
|
// // console.groupCollapsed("EgovAdminScheduleList.getDailyUserLogList()");
|
||||||
|
// //
|
||||||
|
// // console.log("@@@ isDailyChart : " + isDailyChart);
|
||||||
|
//
|
||||||
|
// const dailyUserLogListURL = isDailyChart ? '/admin/dashboard/daily-user-log-list' : '/admin/dashboard/monthly-user-log-list';
|
||||||
|
//
|
||||||
|
// const requestOptions = {
|
||||||
|
// method: "GET",
|
||||||
|
// headers: {
|
||||||
|
// 'Content-type': 'application/json',
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// EgovNet.requestFetch(dailyUserLogListURL,
|
||||||
|
// requestOptions,
|
||||||
|
// (resp) => {
|
||||||
|
// setDailyUserLogList(resp.result.dailyUserLogList);
|
||||||
|
// // console.log("@@@ : " + dailyUserLogList);
|
||||||
|
// },
|
||||||
|
// function (resp) {
|
||||||
|
// // console.log("err response : ", resp);
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
// // console.groupEnd("EgovAdminScheduleList.getDailyUserLogList()");
|
||||||
|
// // eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
// }, [isDailyChart]);
|
||||||
|
//
|
||||||
|
// useEffect(() => {
|
||||||
|
// getDailyUserLogList();
|
||||||
|
// // eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
// }, [isDailyChart]);
|
||||||
|
//
|
||||||
|
// const handleChartToggle = () => {
|
||||||
|
// setIsDailyChart(!isDailyChart);
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// const ChartToggle = ({onToggle}) => {
|
||||||
|
//
|
||||||
|
// const handleToggle = () => {
|
||||||
|
// onToggle(!isDailyChart);
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// return (
|
||||||
|
// <button onClick={handleToggle}>
|
||||||
|
// {isDailyChart ? '월별차트보기' : '일별차트보기'}
|
||||||
|
// </button>
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// const data = dailyUserLogList.map(item => ({
|
||||||
|
// logDt: item.logDt,
|
||||||
|
// uv: item.mobileCnt,
|
||||||
|
// "사용자 접속현황": item.logCnt,
|
||||||
|
// amt: item.pcCnt,
|
||||||
|
// }));
|
||||||
|
//
|
||||||
|
// 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>
|
||||||
|
// </div>
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return null;
|
||||||
|
// };
|
||||||
|
|
||||||
const retrieveList = useCallback((srchcnd) => {
|
// class UserLogChart extends PureComponent {
|
||||||
console.groupCollapsed("EgovAdminScheduleList.retrieveList()");
|
// render() {
|
||||||
|
// return (
|
||||||
|
// <ResponsiveContainer width="100%" height="100%">
|
||||||
|
// <BarChart
|
||||||
|
// width={500}
|
||||||
|
// height={300}
|
||||||
|
// data={data}
|
||||||
|
// margin={{
|
||||||
|
// top: 5,
|
||||||
|
// right: 30,
|
||||||
|
// left: 20,
|
||||||
|
// bottom: 5,
|
||||||
|
// }}
|
||||||
|
// >
|
||||||
|
// <CartesianGrid strokeDasharray="3 3"/>
|
||||||
|
// <XAxis dataKey="logDt"/>
|
||||||
|
// <YAxis/>
|
||||||
|
// <Tooltip content={<CustomTooltip/>}/>
|
||||||
|
// <Legend/>
|
||||||
|
// <Bar dataKey="사용자 접속현황" barSize={20} fill="#87CEFA"/>
|
||||||
|
// </BarChart>
|
||||||
|
// </ResponsiveContainer>
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
const retrieveListURL = '/schedule/month' + EgovNet.getQueryString(srchcnd);
|
// console.log("------------------------------EgovAdminScheduleList [End]");
|
||||||
|
// console.groupEnd("EgovAdminScheduleList");
|
||||||
|
|
||||||
const requestOptions = {
|
// const [value, setValue] = useState('today');
|
||||||
method: "GET",
|
const [slot, setSlot] = useState('week');
|
||||||
headers: {
|
const [totalDownloads, setTotalDownloads] = useState(0);
|
||||||
'Content-type': 'application/json',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EgovNet.requestFetch(retrieveListURL,
|
// 총 다운로드 수를 받아온 후 state 업데이트
|
||||||
requestOptions,
|
const handleTotalDownloads = (sum) => {
|
||||||
(resp) => {
|
setTotalDownloads(sum);
|
||||||
setScheduleList(resp.result.resultList);
|
|
||||||
},
|
|
||||||
function (resp) {
|
|
||||||
console.log("err response : ", resp);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
console.groupEnd("EgovAdminScheduleList.retrieveList()");
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const drawCalendar = () => {
|
|
||||||
console.groupCollapsed("EgovAdminScheduleList.drawCalendar()");
|
|
||||||
const PREV_MONTH_ADDITION = -1;
|
|
||||||
|
|
||||||
let lastOfLastMonth = getLastDateOfMonth(searchCondition.year, searchCondition.month + PREV_MONTH_ADDITION);
|
|
||||||
let firstOfThisMonth = getFirstDateOfMonth(searchCondition.year, searchCondition.month);
|
|
||||||
let lastOfThisMonth = getLastDateOfMonth(searchCondition.year, searchCondition.month);
|
|
||||||
|
|
||||||
console.log("lastOfLastMonth : ", lastOfLastMonth, lastOfLastMonth.getDay());
|
|
||||||
console.log("firstOfThisMonth :", firstOfThisMonth, firstOfThisMonth.getDay());
|
|
||||||
console.log("lastOfThisMonth :", lastOfThisMonth, lastOfThisMonth.getDay());
|
|
||||||
console.log("scheduleList : ", scheduleList);
|
|
||||||
|
|
||||||
let firstDayOfThisMonth = firstOfThisMonth.getDay();
|
|
||||||
let lastDateOfThisMonth = lastOfThisMonth.getDate();
|
|
||||||
console.log("firstDayOfThisMonth", firstDayOfThisMonth, "lastDateOfThisMonth", lastDateOfThisMonth)
|
|
||||||
|
|
||||||
let monthArr = [];
|
|
||||||
let weekArr = [];
|
|
||||||
|
|
||||||
// firstWeek Date Set START
|
|
||||||
let firstWeekDateCount = 0;
|
|
||||||
for (let day = 0; day < 7; day++) {
|
|
||||||
if (day < firstDayOfThisMonth) { //
|
|
||||||
weekArr.push(0);
|
|
||||||
firstWeekDateCount = 0;
|
|
||||||
} else {
|
|
||||||
weekArr.push(++firstWeekDateCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
monthArr.push(weekArr);
|
|
||||||
console.log("FirstWeek monthArr : ", monthArr);
|
|
||||||
// firstWeek Date Set END
|
|
||||||
|
|
||||||
// otherWeek Date Set START
|
|
||||||
let dayCount = 0;
|
|
||||||
weekArr = [];//초기화
|
|
||||||
for (let day = firstWeekDateCount + 1; day <= lastDateOfThisMonth; day++) {
|
|
||||||
|
|
||||||
if (dayCount % 7 !== 6) {
|
|
||||||
weekArr.push(day);
|
|
||||||
} else {
|
|
||||||
weekArr.push(day);
|
|
||||||
monthArr.push(weekArr);
|
|
||||||
weekArr = [];
|
|
||||||
dayCount = -1;
|
|
||||||
}
|
|
||||||
dayCount++;
|
|
||||||
}
|
|
||||||
// otherWeek Date Set END
|
|
||||||
|
|
||||||
// lastWeek Date Set START
|
|
||||||
if (weekArr.length > 0) {//남은 부분
|
|
||||||
for (let day = weekArr.length; day < 7; day++) {
|
|
||||||
weekArr.push(0);
|
|
||||||
}
|
|
||||||
monthArr.push(weekArr);
|
|
||||||
}
|
|
||||||
// lastWeek Date Set END
|
|
||||||
console.log("OtherWeek monthArr : ", monthArr);
|
|
||||||
|
|
||||||
let mutsUseYearMonth = searchCondition.year.toString() + ((searchCondition.month + 1).toString().length === 1 ? "0" + (searchCondition.month + 1).toString() : (searchCondition.month + 1).toString());
|
|
||||||
console.log("mutsUseYearMonth : ", mutsUseYearMonth);
|
|
||||||
|
|
||||||
let mutCalendarTagList = [];
|
|
||||||
let keyIdx = 0;
|
|
||||||
|
|
||||||
//draw Calendar
|
|
||||||
monthArr.forEach((week, weekIdx) => {
|
|
||||||
console.log();
|
|
||||||
mutCalendarTagList.push(
|
|
||||||
<tr key={keyIdx++}>{
|
|
||||||
week.map((day, dayIdx) => {
|
|
||||||
if (day !== 0) {//당월 일별 구현
|
|
||||||
let sDate = day.toString().length === 1 ? "0" + day.toString() : day.toString();
|
|
||||||
let iUseDate = Number(mutsUseYearMonth + sDate);
|
|
||||||
if (scheduleList.length > 0) {//일정 있는 경우
|
|
||||||
return (
|
|
||||||
<td key={keyIdx++}>
|
|
||||||
<Link to={{pathname: URL.ADMIN_SCHEDULE_CREATE}} state={{iUseDate: mutsUseYearMonth + sDate + "000000"}} className="day"
|
|
||||||
key={keyIdx++}>{day}</Link><br/>
|
|
||||||
{
|
|
||||||
scheduleList.map((schedule, scheduleIdx) => {
|
|
||||||
let iBeginDate = Number(schedule.schdulBgnde.substring(0, 8));
|
|
||||||
let iEndDate = Number(schedule.schdulEndde.substring(0, 8));
|
|
||||||
innerConsole("scheduleList ", day, scheduleIdx, iBeginDate, iUseDate, iEndDate, iUseDate >= iBeginDate && iUseDate <= iEndDate);
|
|
||||||
innerConsole("schedule.schdulId ", schedule.schdulId);
|
|
||||||
if (iUseDate >= iBeginDate && iUseDate <= iEndDate) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Link to={{pathname: URL.ADMIN_SCHEDULE_DETAIL}}
|
|
||||||
state={{schdulId: schedule.schdulId}}
|
|
||||||
key={keyIdx++}>{schedule.schdulNm}
|
|
||||||
</Link>
|
|
||||||
<br/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
} else return <></>
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</td>
|
|
||||||
);
|
|
||||||
} else {//일정 없는 경우
|
|
||||||
return (
|
|
||||||
<td key={keyIdx++}>
|
|
||||||
<Link to={{pathname: URL.ADMIN_SCHEDULE_CREATE}} state={{iUseDate: mutsUseYearMonth + sDate + "000000"}} className="day"
|
|
||||||
key={keyIdx++}>{day}</Link><br/>
|
|
||||||
</td>);
|
|
||||||
}
|
|
||||||
} else if (day === 0) {// 이전달/다음달 구현
|
|
||||||
return (<td key={keyIdx++}></td>);
|
|
||||||
} else return <></>
|
|
||||||
})
|
|
||||||
}</tr>);
|
|
||||||
})
|
|
||||||
console.log("mutCalendarTagList : ", mutCalendarTagList);
|
|
||||||
setCalendarTag(mutCalendarTagList);
|
|
||||||
console.groupEnd("EgovAdminScheduleList.drawCalendar()");
|
|
||||||
}
|
|
||||||
|
|
||||||
const Location = React.memo(function Location() {
|
|
||||||
return (
|
|
||||||
<div className="location">
|
|
||||||
<ul>
|
|
||||||
<li><Link to={URL.MAIN} className="home">Home</Link></li>
|
|
||||||
<li><Link to={URL.ADMIN}>사이트관리</Link></li>
|
|
||||||
<li>일정관리</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
//retrieveList(searchCondition); disabled by thkim
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [searchCondition]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
drawCalendar();
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [scheduleList]);
|
|
||||||
|
|
||||||
const [isDailyChart, setChart] = useState(true);
|
|
||||||
|
|
||||||
const getDailyUserLogList = useCallback(() => {
|
|
||||||
console.groupCollapsed("EgovAdminScheduleList.getDailyUserLogList()");
|
|
||||||
|
|
||||||
console.log("@@@ isDailyChart : " + isDailyChart);
|
|
||||||
|
|
||||||
const dailyUserLogListURL = isDailyChart ? '/admin/dashboard/daily-user-log-list' : '/admin/dashboard/monthly-user-log-list';
|
|
||||||
|
|
||||||
const requestOptions = {
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
'Content-type': 'application/json',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EgovNet.requestFetch(dailyUserLogListURL,
|
|
||||||
requestOptions,
|
|
||||||
(resp) => {
|
|
||||||
setDailyUserLogList(resp.result.dailyUserLogList);
|
|
||||||
console.log("@@@ : " + dailyUserLogList);
|
|
||||||
},
|
|
||||||
function (resp) {
|
|
||||||
console.log("err response : ", resp);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
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,
|
|
||||||
uv: item.mobileCnt,
|
|
||||||
"사용자 접속현황": item.logCnt,
|
|
||||||
amt: item.pcCnt,
|
|
||||||
}));
|
|
||||||
|
|
||||||
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>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
class UserLogChart extends PureComponent {
|
|
||||||
static demoUrl = 'https://codesandbox.io/s/tooltip-with-customized-content-lyxvs';
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<ResponsiveContainer width="100%" height="100%">
|
|
||||||
<BarChart
|
|
||||||
width={500}
|
|
||||||
height={300}
|
|
||||||
data={data}
|
|
||||||
margin={{
|
|
||||||
top: 5,
|
|
||||||
right: 30,
|
|
||||||
left: 20,
|
|
||||||
bottom: 5,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<CartesianGrid strokeDasharray="3 3"/>
|
|
||||||
<XAxis dataKey="logDt"/>
|
|
||||||
<YAxis/>
|
|
||||||
<Tooltip content={<CustomTooltip/>}/>
|
|
||||||
<Legend/>
|
|
||||||
<Bar dataKey="사용자 접속현황" barSize={20} fill="#87CEFA"/>
|
|
||||||
</BarChart>
|
|
||||||
</ResponsiveContainer>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("------------------------------EgovAdminScheduleList [End]");
|
|
||||||
console.groupEnd("EgovAdminScheduleList");
|
|
||||||
return (
|
return (
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<div className="c_wrap">
|
<div className="c_wrap">
|
||||||
{/* <!-- Location --> */}
|
{/* <!-- Location --> */}
|
||||||
<Location/>
|
<div className="location">
|
||||||
|
<ul>
|
||||||
|
<li><Link to={URL.MAIN} className="home">Home</Link></li>
|
||||||
|
<li><Link to={URL.ADMIN} >사이트관리</Link></li>
|
||||||
|
<li>Dashboard</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
{/* <!--// Location --> */}
|
{/* <!--// Location --> */}
|
||||||
|
|
||||||
<div className="layout">
|
<div className="layout">
|
||||||
|
|
@ -334,16 +227,132 @@ function EgovAdminScheduleList(props) {
|
||||||
{/* <!-- 본문 --> */}
|
{/* <!-- 본문 --> */}
|
||||||
|
|
||||||
<div className="top_tit">
|
<div className="top_tit">
|
||||||
<h1 className="tit_1">사이트관리</h1>
|
<h1 className="tit_1">Dashboard</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 className="tit_2"></h2>
|
<Grid container rowSpacing={4.5} columnSpacing={2.75}>
|
||||||
|
{/* row 1 */}
|
||||||
|
{/*<Grid item xs={12} sx={{ mb: -2.25 }}>*/}
|
||||||
|
{/* <Typography variant="h5">Dashboard</Typography>*/}
|
||||||
|
{/*</Grid>*/}
|
||||||
|
<Grid item xs={12} sm={6} md={4} lg={3}>
|
||||||
|
<AnalyticEcommerce title={`총접속자수 (${DATE.getMonth() + 1}월)`} count="442,236" percentage={59.3} extra="35,000" />
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} sm={6} md={4} lg={3}>
|
||||||
|
<AnalyticEcommerce title={`건설기준 오류건수 (${DATE.getMonth() + 1}월)`} count="78,250" percentage={70.5} extra="8,900" />
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} sm={6} md={4} lg={3}>
|
||||||
|
<AnalyticEcommerce title={`기준코드 등록건수 (${DATE.getMonth() + 1}월)`} count="18,800" percentage={27.4} isLoss color="warning" extra="1,943" />
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} sm={6} md={4} lg={3}>
|
||||||
|
<AnalyticEcommerce title={`민원건수 (${DATE.getMonth() + 1}월)`} count="5" percentage={80} isLoss color="warning" extra="1" />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<ChartToggle isDailyChart={isDailyChart} onToggle={handleChartToggle}/>
|
<Grid item md={8} sx={{ display: { sm: 'none', md: 'block', lg: 'none' } }} />
|
||||||
|
|
||||||
<div style={{width: 1000, height: 300}}>
|
{/* row 2 */}
|
||||||
<UserLogChart/>
|
<Grid item xs={12} md={7} lg={8}>
|
||||||
</div>
|
<Grid container alignItems="center" justifyContent="space-between">
|
||||||
|
<Grid item>
|
||||||
|
<Typography variant="h5">{ DATE.getFullYear() }년 메뉴접속 / 방문수 </Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<Stack direction="row" alignItems="center" spacing={0}>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
onClick={() => setSlot('month')}
|
||||||
|
color={slot === 'month' ? 'primary' : 'secondary'}
|
||||||
|
variant={slot === 'month' ? 'outlined' : 'text'}
|
||||||
|
>
|
||||||
|
Month
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
onClick={() => setSlot('week')}
|
||||||
|
color={slot === 'week' ? 'primary' : 'secondary'}
|
||||||
|
variant={slot === 'week' ? 'outlined' : 'text'}
|
||||||
|
>
|
||||||
|
Week
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
<MainCard content={false} sx={{ mt: 1.5 }}>
|
||||||
|
<Box sx={{ pt: 1, pr: 2 }}>
|
||||||
|
<IncomeAreaChart slot={slot} />
|
||||||
|
</Box>
|
||||||
|
</MainCard>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={5} lg={4}>
|
||||||
|
<Grid container alignItems="center" justifyContent="space-between">
|
||||||
|
<Grid item>
|
||||||
|
<Typography variant="h5">다운로드수</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item />
|
||||||
|
</Grid>
|
||||||
|
<MainCard sx={{ mt: 2 }} content={false}>
|
||||||
|
<Box sx={{ p: 3, pb: 0 }}>
|
||||||
|
<Stack spacing={2}>
|
||||||
|
<Typography variant="h3" color="textSecondary">
|
||||||
|
주간 현황
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="h6">총 {totalDownloads}건</Typography>
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
<MonthlyBarChart onDataFetched={handleTotalDownloads} />
|
||||||
|
</MainCard>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* row 3 */}
|
||||||
|
<Grid item xs={12} md={7} lg={8}>
|
||||||
|
<Grid container alignItems="center" justifyContent="space-between">
|
||||||
|
<Grid item>
|
||||||
|
<Typography variant="h5">최근 문의사항</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item />
|
||||||
|
</Grid>
|
||||||
|
<MainCard sx={{ mt: 2 }} content={false}>
|
||||||
|
<BbsTable />
|
||||||
|
</MainCard>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={5} lg={4}>
|
||||||
|
<Grid container alignItems="center" justifyContent="space-between">
|
||||||
|
<Grid item>
|
||||||
|
<Typography variant="h5">접속 방법</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item />
|
||||||
|
</Grid>
|
||||||
|
<MainCard sx={{ mt: 2 }} content={false}>
|
||||||
|
<ReportAreaChart />
|
||||||
|
</MainCard>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
|
||||||
|
{/*<ChartToggle isDailyChart={isDailyChart} onToggle={handleChartToggle}/>*/}
|
||||||
|
|
||||||
|
{/*<div style={{width: 1000, height: 300}}>*/}
|
||||||
|
{/* <ResponsiveContainer width="100%" height="100%">*/}
|
||||||
|
{/* <BarChart*/}
|
||||||
|
{/* width={500}*/}
|
||||||
|
{/* height={300}*/}
|
||||||
|
{/* data={data}*/}
|
||||||
|
{/* margin={{*/}
|
||||||
|
{/* top: 5,*/}
|
||||||
|
{/* right: 30,*/}
|
||||||
|
{/* left: 20,*/}
|
||||||
|
{/* bottom: 5,*/}
|
||||||
|
{/* }}*/}
|
||||||
|
{/* >*/}
|
||||||
|
{/* <CartesianGrid strokeDasharray="3 3"/>*/}
|
||||||
|
{/* <XAxis dataKey="logDt"/>*/}
|
||||||
|
{/* <YAxis/>*/}
|
||||||
|
{/* <Tooltip content={<CustomTooltip/>}/>*/}
|
||||||
|
{/* <Legend/>*/}
|
||||||
|
{/* <Bar dataKey="사용자 접속현황" barSize={20} fill="#87CEFA"/>*/}
|
||||||
|
{/* </BarChart>*/}
|
||||||
|
{/* </ResponsiveContainer>*/}
|
||||||
|
{/*</div>*/}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -351,4 +360,4 @@ function EgovAdminScheduleList(props) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default EgovAdminScheduleList;
|
export default EgovAdminDashboard;
|
||||||
|
|
@ -0,0 +1,156 @@
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useState, useEffect, useCallback } from 'react';
|
||||||
|
|
||||||
|
// material-ui
|
||||||
|
import { useTheme } from '@mui/material/styles';
|
||||||
|
|
||||||
|
// third-party
|
||||||
|
import ReactApexChart from 'react-apexcharts';
|
||||||
|
|
||||||
|
import * as EgovNet from 'api/egovFetch';
|
||||||
|
|
||||||
|
// chart options
|
||||||
|
const areaChartOptions = {
|
||||||
|
chart: {
|
||||||
|
height: 450,
|
||||||
|
type: 'area',
|
||||||
|
toolbar: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dataLabels: {
|
||||||
|
enabled: false
|
||||||
|
},
|
||||||
|
stroke: {
|
||||||
|
curve: 'smooth',
|
||||||
|
width: 2
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
strokeDashArray: 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ==============================|| INCOME AREA CHART ||============================== //
|
||||||
|
|
||||||
|
const IncomeAreaChart = ({ slot }) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
|
const { primary, secondary } = theme.palette.text;
|
||||||
|
const line = theme.palette.divider;
|
||||||
|
|
||||||
|
const [options, setOptions] = useState(areaChartOptions);
|
||||||
|
const [menuMonthlyList, setMenuMonthlyList] = useState([]);
|
||||||
|
const [menuDailyList, setMenuDailyList] = useState([]);
|
||||||
|
const [loginMonthlyList, setLoginMonthlyList] = useState([]);
|
||||||
|
const [loginDailyList, setLoginDailyList] = useState([]);
|
||||||
|
|
||||||
|
// 메뉴 접속 및 방문자 수
|
||||||
|
const retrieveList = useCallback(() => {
|
||||||
|
const retrieveListURL = '/admin/dashboard/menu-login'
|
||||||
|
|
||||||
|
const requestOptions = {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
'Content-type': 'application/json',
|
||||||
|
},
|
||||||
|
// body: JSON.stringify()
|
||||||
|
}
|
||||||
|
|
||||||
|
EgovNet.requestFetch(retrieveListURL,
|
||||||
|
requestOptions,
|
||||||
|
(resp) => {
|
||||||
|
setMenuMonthlyList(resp.result.menuMonthlyList);
|
||||||
|
setMenuDailyList(resp.result.menuDailyList);
|
||||||
|
setLoginMonthlyList(resp.result.loginMonthlyList);
|
||||||
|
setLoginDailyList(resp.result.loginDailyList);
|
||||||
|
},
|
||||||
|
function (resp) {
|
||||||
|
console.log("err response : ", resp);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
// eslint-disable-next-lie react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
retrieveList();
|
||||||
|
|
||||||
|
setOptions((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
colors: [theme.palette.primary.main, theme.palette.primary[700]],
|
||||||
|
xaxis: {
|
||||||
|
categories:
|
||||||
|
slot === 'month'
|
||||||
|
? ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
|
||||||
|
: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
|
||||||
|
labels: {
|
||||||
|
style: {
|
||||||
|
colors: [
|
||||||
|
secondary,
|
||||||
|
secondary,
|
||||||
|
secondary,
|
||||||
|
secondary,
|
||||||
|
secondary,
|
||||||
|
secondary,
|
||||||
|
secondary,
|
||||||
|
secondary,
|
||||||
|
secondary,
|
||||||
|
secondary,
|
||||||
|
secondary,
|
||||||
|
secondary
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisBorder: {
|
||||||
|
show: true,
|
||||||
|
color: line
|
||||||
|
},
|
||||||
|
tickAmount: slot === 'month' ? 11 : 7
|
||||||
|
},
|
||||||
|
yaxis: {
|
||||||
|
labels: {
|
||||||
|
style: {
|
||||||
|
colors: [secondary]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
borderColor: line
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
theme: 'light'
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}, [primary, secondary, line, theme, slot, retrieveList]);
|
||||||
|
|
||||||
|
const [series, setSeries] = useState([
|
||||||
|
{
|
||||||
|
name: 'Menu Views',
|
||||||
|
data: menuDailyList
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Login Count',
|
||||||
|
data: loginDailyList
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setSeries([
|
||||||
|
{
|
||||||
|
name: 'Menu Views',
|
||||||
|
data: slot === 'month' ? menuMonthlyList : menuDailyList
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Login Count',
|
||||||
|
data: slot === 'month' ? loginMonthlyList : loginDailyList
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
}, [slot, menuMonthlyList, menuDailyList, loginMonthlyList, loginDailyList]);
|
||||||
|
|
||||||
|
return <ReactApexChart options={options} series={series} type="area" height={450} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
IncomeAreaChart.propTypes = {
|
||||||
|
slot: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
export default IncomeAreaChart;
|
||||||
|
|
@ -0,0 +1,125 @@
|
||||||
|
import {useCallback, useEffect, useState} from 'react';
|
||||||
|
|
||||||
|
// material-ui
|
||||||
|
import { useTheme } from '@mui/material/styles';
|
||||||
|
|
||||||
|
// third-party
|
||||||
|
import ReactApexChart from 'react-apexcharts';
|
||||||
|
|
||||||
|
import * as EgovNet from 'api/egovFetch';
|
||||||
|
|
||||||
|
// chart options
|
||||||
|
const barChartOptions = {
|
||||||
|
chart: {
|
||||||
|
type: 'bar',
|
||||||
|
height: 365,
|
||||||
|
toolbar: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
plotOptions: {
|
||||||
|
bar: {
|
||||||
|
columnWidth: '45%',
|
||||||
|
borderRadius: 4
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dataLabels: {
|
||||||
|
enabled: true
|
||||||
|
},
|
||||||
|
xaxis: {
|
||||||
|
categories: ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'],
|
||||||
|
axisBorder: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisTicks: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
yaxis: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ==============================|| MONTHLY BAR CHART ||============================== //
|
||||||
|
|
||||||
|
const MonthlyBarChart = ({ onDataFetched }) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
|
const { primary, secondary } = theme.palette.text;
|
||||||
|
const info = theme.palette.info.light;
|
||||||
|
|
||||||
|
const [options, setOptions] = useState(barChartOptions);
|
||||||
|
const [fileDailyList, setFileDailyList] = useState([]);
|
||||||
|
|
||||||
|
// 메뉴 접속 및 방문자 수
|
||||||
|
const retrieveList = useCallback(() => {
|
||||||
|
const retrieveListURL = '/admin/dashboard/file'
|
||||||
|
|
||||||
|
const requestOptions = {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
'Content-type': 'application/json',
|
||||||
|
},
|
||||||
|
// body: JSON.stringify()
|
||||||
|
}
|
||||||
|
|
||||||
|
EgovNet.requestFetch(retrieveListURL,
|
||||||
|
requestOptions,
|
||||||
|
(resp) => {
|
||||||
|
setFileDailyList(resp.result.fileDailyList);
|
||||||
|
const sum = resp.result.fileDailyList.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
|
||||||
|
onDataFetched(sum);
|
||||||
|
},
|
||||||
|
function (resp) {
|
||||||
|
console.log("err response : ", resp);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
// eslint-disable-next-lie react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const [series, setSeries] = useState([
|
||||||
|
{
|
||||||
|
name: '다운로드수',
|
||||||
|
data: fileDailyList
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
retrieveList();
|
||||||
|
}, [onDataFetched]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setSeries([
|
||||||
|
{
|
||||||
|
data: fileDailyList
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
setOptions((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
colors: [info],
|
||||||
|
xaxis: {
|
||||||
|
labels: {
|
||||||
|
style: {
|
||||||
|
colors: [secondary, secondary, secondary, secondary, secondary, secondary, secondary]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
theme: 'light'
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [primary, info, secondary, fileDailyList]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div id="chart">
|
||||||
|
<ReactApexChart options={options} series={series} type="bar" height={365} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MonthlyBarChart;
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
// material-ui
|
||||||
|
import { useTheme } from '@mui/material/styles';
|
||||||
|
|
||||||
|
// third-party
|
||||||
|
import ReactApexChart from 'react-apexcharts';
|
||||||
|
|
||||||
|
// chart options
|
||||||
|
const areaChartOptions = {
|
||||||
|
chart: {
|
||||||
|
type: 'donut',
|
||||||
|
},
|
||||||
|
plotOptions: {
|
||||||
|
pie: {
|
||||||
|
startAngle: -90,
|
||||||
|
endAngle: 90,
|
||||||
|
offsetY: 10,
|
||||||
|
expandOnClick:false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dataLabels: {
|
||||||
|
enabled: true
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
text: '2024년 2월',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
responsive: [{
|
||||||
|
breakpoint: 480,
|
||||||
|
options: {
|
||||||
|
chart: {
|
||||||
|
width: 200
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
position: 'bottom'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
grid: {
|
||||||
|
padding: {
|
||||||
|
bottom: -150
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// ==============================|| REPORT AREA CHART ||============================== //
|
||||||
|
|
||||||
|
const ReportAreaChart = () => {
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
|
const { primary, secondary } = theme.palette.text;
|
||||||
|
const line = theme.palette.divider;
|
||||||
|
|
||||||
|
const [options, setOptions] = useState(areaChartOptions);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setOptions((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
labels: ['PC', 'Mobile'],
|
||||||
|
colors: ['#448EF7', '#FFC107'],
|
||||||
|
// colors: [theme.palette.warning.main],
|
||||||
|
grid: {
|
||||||
|
borderColor: line
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
theme: 'light'
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
position: 'bottom',
|
||||||
|
labels: {
|
||||||
|
colors: 'grey.500'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}, [primary, secondary, line, theme]);
|
||||||
|
|
||||||
|
const [series] = useState([90, 10]);
|
||||||
|
|
||||||
|
return <ReactApexChart options={options} series={series} type="donut" />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ReportAreaChart;
|
||||||
|
|
@ -35,11 +35,9 @@ function InfoDisclosure(props) {
|
||||||
<div className="contents " id="contents">
|
<div className="contents " id="contents">
|
||||||
{/* <!-- 본문 --> */}
|
{/* <!-- 본문 --> */}
|
||||||
<div className="top_tit">
|
<div className="top_tit">
|
||||||
<h1 className="tit_1">건설기준 관리</h1>
|
<h1 className="tit_1">건설기준 내용 관리</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 className="tit_2">건설기준 내용 관리</h2>
|
|
||||||
|
|
||||||
여기에 구현해주세요.
|
여기에 구현해주세요.
|
||||||
{/* <!--// 본문 --> */}
|
{/* <!--// 본문 --> */}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -35,11 +35,9 @@ function ReferenceCodes(props) {
|
||||||
<div className="contents " id="contents">
|
<div className="contents " id="contents">
|
||||||
{/* <!-- 본문 --> */}
|
{/* <!-- 본문 --> */}
|
||||||
<div className="top_tit">
|
<div className="top_tit">
|
||||||
<h1 className="tit_1">건설기준 관리</h1>
|
<h1 className="tit_1">참조코드 관리</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 className="tit_2">참조코드 관리</h2>
|
|
||||||
|
|
||||||
여기에 구현해주세요.
|
여기에 구현해주세요.
|
||||||
{/* <!--// 본문 --> */}
|
{/* <!--// 본문 --> */}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -35,10 +35,9 @@ function SimilarityCheck(props) {
|
||||||
<div className="contents " id="contents">
|
<div className="contents " id="contents">
|
||||||
{/* <!-- 본문 --> */}
|
{/* <!-- 본문 --> */}
|
||||||
<div className="top_tit">
|
<div className="top_tit">
|
||||||
<h1 className="tit_1">건설기준 관리</h1>
|
<h1 className="tit_1">유사성 검사</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 className="tit_2">유사성 검사</h2>
|
|
||||||
|
|
||||||
여기에 구현해주세요.
|
여기에 구현해주세요.
|
||||||
{/* <!--// 본문 --> */}
|
{/* <!--// 본문 --> */}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useState, useEffect, useRef } from 'react';
|
import React, { useState } from 'react';
|
||||||
import {Link, useLocation, useNavigate} from 'react-router-dom';
|
import {Link, useLocation, useNavigate} from 'react-router-dom';
|
||||||
import * as EgovNet from 'api/egovFetch';
|
import * as EgovNet from 'api/egovFetch';
|
||||||
|
|
||||||
|
|
@ -7,7 +7,7 @@ import CODE from "constants/code";
|
||||||
import Row from 'react-bootstrap/Row';
|
import Row from 'react-bootstrap/Row';
|
||||||
import Col from 'react-bootstrap/Col';
|
import Col from 'react-bootstrap/Col';
|
||||||
|
|
||||||
import { getLocalItem, setLocalItem, setSessionItem } from 'utils/storage';
|
import { setLocalItem } from 'utils/storage';
|
||||||
import InfoShareChk from "./InfoShareChk";
|
import InfoShareChk from "./InfoShareChk";
|
||||||
|
|
||||||
function Join(props) {
|
function Join(props) {
|
||||||
|
|
@ -21,7 +21,6 @@ function Join(props) {
|
||||||
|
|
||||||
const [userInfo, setUserInfo] = useState({ id: '', password: '', passwordChk: '', userNm: '', email: '', phoneNum: ''});
|
const [userInfo, setUserInfo] = useState({ id: '', password: '', passwordChk: '', userNm: '', email: '', phoneNum: ''});
|
||||||
const [infoShareChk, setInfoShareChk] = useState(false);
|
const [infoShareChk, setInfoShareChk] = useState(false);
|
||||||
const [submitFlag, setSubmitFlag] = useState(true);
|
|
||||||
|
|
||||||
const submitFormHandler = (e) => {
|
const submitFormHandler = (e) => {
|
||||||
console.log("JoinContent submitFormHandler()");
|
console.log("JoinContent submitFormHandler()");
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,88 @@
|
||||||
|
import React, {useEffect, useState} from "react";
|
||||||
|
import {Button, Modal, Nav} from "react-bootstrap";
|
||||||
|
import Col from "react-bootstrap/Col";
|
||||||
|
import Row from "react-bootstrap/Row";
|
||||||
|
import * as EgovNet from "api/egovFetch";
|
||||||
|
|
||||||
|
|
||||||
|
function DownloadModal({closeFn}){
|
||||||
|
const [tab, setTab] = useState(10);
|
||||||
|
const [subTabsVisible, setSubTabsVisible] = useState(false);
|
||||||
|
const [listData, setListData] = useState([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
EgovNet.requestFetch('/standardCode/standard-code-download-list?listCode='+tab,
|
||||||
|
{
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
'Content-type': 'application/json',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(resp) => {
|
||||||
|
setListData(resp.result.resultList);
|
||||||
|
},
|
||||||
|
function (resp) {
|
||||||
|
console.log("err response : ", resp);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}, [tab]);
|
||||||
|
|
||||||
|
return(
|
||||||
|
<>
|
||||||
|
<Modal.Header closeButton>
|
||||||
|
<Modal.Title id="example-modal-sizes-title-lg">통합다운로드</Modal.Title>
|
||||||
|
</Modal.Header>
|
||||||
|
<Modal.Body>
|
||||||
|
<Row className={"justify-content-start py-1 mx-1"}>
|
||||||
|
<Col xs={"auto px-1"}>
|
||||||
|
<div className={`tab ${tab === 10 ? 'active' : ''}`}
|
||||||
|
onClick={() => {setTab(10); setSubTabsVisible(false)}}>설계기준</div>
|
||||||
|
</Col>
|
||||||
|
<Col xs={"auto px-1"}>
|
||||||
|
<div className={`tab ${tab === 20 ? 'active' : ''}`}
|
||||||
|
onClick={() => {setTab(20); setSubTabsVisible(false)}}>표준시방서</div>
|
||||||
|
</Col>
|
||||||
|
<Col xs={"auto px-1"}>
|
||||||
|
<div className={`tab ${[40, 50, 60, 70, 80, 90].includes(tab) ? 'active' : ''}`}
|
||||||
|
onClick={() => {setTab(40); setSubTabsVisible(true)}}>전문시방서</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
{subTabsVisible && (
|
||||||
|
<Nav className={"tabs"} variant={"tabs"} >
|
||||||
|
<Nav.Item><Nav.Link className={`${tab === 40 ? 'active' : ''}`} onClick={() => {setTab(40)}}>서울특별시</Nav.Link></Nav.Item>
|
||||||
|
<Nav.Item><Nav.Link className={`${tab === 50 ? 'active' : ''}`} onClick={() => {setTab(50)}}>고속도로공사</Nav.Link></Nav.Item>
|
||||||
|
<Nav.Item><Nav.Link className={`${tab === 60 ? 'active' : ''}`} onClick={() => {setTab(60)}}>한국농어촌공사</Nav.Link></Nav.Item>
|
||||||
|
<Nav.Item><Nav.Link className={`${tab === 70 ? 'active' : ''}`} onClick={() => {setTab(70)}}>철도건설공사</Nav.Link></Nav.Item>
|
||||||
|
<Nav.Item><Nav.Link className={`${tab === 80 ? 'active' : ''}`} onClick={() => {setTab(80)}}>LH한국토지주택공사</Nav.Link></Nav.Item>
|
||||||
|
<Nav.Item><Nav.Link className={`${tab === 90 ? 'active' : ''}`} onClick={() => {setTab(90)}}>K-Water</Nav.Link></Nav.Item>
|
||||||
|
</Nav>
|
||||||
|
)}
|
||||||
|
<div className="board_list standard_code_modal download_list">
|
||||||
|
<div className="head">
|
||||||
|
<span>구분</span>
|
||||||
|
<span>코드</span>
|
||||||
|
<span>다운로드</span>
|
||||||
|
</div>
|
||||||
|
<div className={"result"}>
|
||||||
|
{listData.filter(item => {
|
||||||
|
return item;
|
||||||
|
}).map(item => {
|
||||||
|
return (
|
||||||
|
<div className="list_item">
|
||||||
|
<div className="mainCategory">{item.groupNm}</div>
|
||||||
|
<div className="middleCategory">{item.groupCurCd}</div>
|
||||||
|
<div className="kcscCd">
|
||||||
|
<Button size={"sm"} variant={"outline-secondary"}>다운로드</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Modal.Body>
|
||||||
|
<Modal.Footer><Button onClick={closeFn}>닫기</Button></Modal.Footer>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DownloadModal;
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
|
||||||
|
import React, {useState} from "react";
|
||||||
|
import {AiFillStar} from "react-icons/ai";
|
||||||
|
import {getLocalItem} from "utils/storage";
|
||||||
|
import * as EgovNet from "../../../api/egovFetch";
|
||||||
|
|
||||||
|
function FavoriteIcon({item}){
|
||||||
|
|
||||||
|
const [favoriteChk, setFavoriteChk] = useState(item.favoriteChk);
|
||||||
|
|
||||||
|
function favoriteStateChange(groupSeq, checked){
|
||||||
|
EgovNet.requestFetch(
|
||||||
|
'/standardCode/document-favorite',
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
'Content-type': 'application/json',
|
||||||
|
},
|
||||||
|
body:JSON.stringify({groupSeq: groupSeq, active: checked})
|
||||||
|
},
|
||||||
|
(resp) => {
|
||||||
|
|
||||||
|
},
|
||||||
|
function (resp) {
|
||||||
|
console.log("err response : ", resp);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="star clickable"
|
||||||
|
onClick={()=>{
|
||||||
|
const accessToken = getLocalItem('accessToken')
|
||||||
|
if(accessToken) {
|
||||||
|
favoriteStateChange(item.groupSeq, !favoriteChk)
|
||||||
|
setFavoriteChk(!favoriteChk)
|
||||||
|
}else{
|
||||||
|
alert("로그인 후 이용 가능한 서비스 입니다.")
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
<AiFillStar color={favoriteChk?'#FFC000':''}/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FavoriteIcon;
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
import React, {useEffect, useState} from "react";
|
||||||
|
import {Button, Modal, Nav} from "react-bootstrap";
|
||||||
|
import Col from "react-bootstrap/Col";
|
||||||
|
import Row from "react-bootstrap/Row";
|
||||||
|
import * as EgovNet from "api/egovFetch";
|
||||||
|
|
||||||
|
|
||||||
|
function HistoryModal({closeFn, standardCode}){
|
||||||
|
|
||||||
|
return(
|
||||||
|
<>
|
||||||
|
<Modal.Header closeButton>
|
||||||
|
<Modal.Title id="example-modal-sizes-title-lg">개정이력</Modal.Title>
|
||||||
|
</Modal.Header>
|
||||||
|
<Modal.Body>
|
||||||
|
<div>코드 : {standardCode.kcscCd}</div>
|
||||||
|
<div className="board_list standard_code_modal">
|
||||||
|
<div className="head">
|
||||||
|
<span>고시일</span>
|
||||||
|
<span>기준코드</span>
|
||||||
|
<span>신구건설기준비교</span>
|
||||||
|
</div>
|
||||||
|
<div className={"result"}>
|
||||||
|
{standardCode.historyList.filter(history => {
|
||||||
|
return history;
|
||||||
|
}).map(history => {
|
||||||
|
return (
|
||||||
|
<div className="list_item">
|
||||||
|
<div className="mainCategory">{history.rvsnYmd.split('T')[0]}</div>
|
||||||
|
<div className="middleCategory">
|
||||||
|
<Button size={"sm"} variant={"outline-secondary"}>다운로드</Button>
|
||||||
|
</div>
|
||||||
|
<div className="kcscCd">
|
||||||
|
<Button size={"sm"} variant={"outline-secondary"}>다운로드</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Modal.Body>
|
||||||
|
<Modal.Footer><Button onClick={closeFn}>닫기</Button></Modal.Footer>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HistoryModal;
|
||||||
|
|
@ -1,143 +1,66 @@
|
||||||
import React, {useState, useEffect, useCallback, useRef} from 'react';
|
import React from 'react';
|
||||||
import {Link, useLocation, useParams} from 'react-router-dom';
|
import Col from "react-bootstrap/Col";
|
||||||
|
import Row from "react-bootstrap/Row";
|
||||||
|
import FavoriteIcon from "./FavoriteIcon";
|
||||||
|
import Button from "react-bootstrap/Button";
|
||||||
|
|
||||||
import * as EgovNet from 'api/egovFetch';
|
function StandardCodeList({listData, filterData, getHistoryModal}) {
|
||||||
import URL from 'constants/url';
|
|
||||||
import {StandardCodeListModal, StandardCodeListModalTable} from './StandardCodeListModal'
|
|
||||||
import {AiFillFileMarkdown, AiFillStar} from "react-icons/ai";
|
|
||||||
import StandardCodeSearchForm from "./StandardCodeSearchForm";
|
|
||||||
|
|
||||||
function StandardCodeList({}) {
|
function historyBtn(item){
|
||||||
const {listCode} = useParams();
|
getHistoryModal(item);
|
||||||
const [listData, setListData] = useState([])
|
|
||||||
const [filterData, setFilterData] = useState('');
|
|
||||||
const [resultCnt, setResultCnt] = useState(0);
|
|
||||||
const [groupSeq, setGroupSeq] = useState();
|
|
||||||
|
|
||||||
const [show, setShow] = useState(false);
|
|
||||||
function close() {
|
|
||||||
setShow(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function showHandling(e) {
|
|
||||||
const param = e.currentTarget.dataset;
|
|
||||||
const groupSeq = param.groupSeq;
|
|
||||||
console.log(groupSeq);
|
|
||||||
EgovNet.requestFetch(
|
|
||||||
'/standardCode/codeListModal.do',
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
'Content-type': 'application/json'
|
|
||||||
},
|
|
||||||
body: JSON.stringify(
|
|
||||||
groupSeq
|
|
||||||
)
|
|
||||||
}, (resp) => {
|
|
||||||
console.log(resp + "------------------------resp")
|
|
||||||
const body = [];
|
|
||||||
const head = [];
|
|
||||||
if (resp.length > 0) {
|
|
||||||
|
|
||||||
resp.forEach(function (item, index) {
|
|
||||||
const formattedDate = item.aplcnBgngYmd.match(/\d{4}-\d{2}-\d{2}/)[0];
|
|
||||||
const url = "https://www.kcsc.re.kr/file/DownloadGrp/" + item.docFileGrpId;
|
|
||||||
body.push(
|
|
||||||
<tr>
|
|
||||||
<td>{formattedDate}</td>
|
|
||||||
<td><a href={url}><AiFillFileMarkdown/></a></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>)
|
|
||||||
})
|
|
||||||
head.push(
|
|
||||||
<tr>
|
|
||||||
<td>년도</td>
|
|
||||||
<td>기준코드</td>
|
|
||||||
<td>신구건설기준비교</td>
|
|
||||||
</tr>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
setGroupSeq(<StandardCodeListModalTable head={head} content={body}/>);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
setShow(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
const retrieveList = useCallback((searchCondition) => {
|
|
||||||
if(searchCondition?.tab){
|
|
||||||
EgovNet.requestFetch('/standardCode/standard-code-list'+EgovNet.convParams(searchCondition),
|
|
||||||
{
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
'Content-type': 'application/json',
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(resp) => {
|
|
||||||
setListData(resp.result.resultList);
|
|
||||||
setResultCnt(resp.result.resultCnt);
|
|
||||||
},
|
|
||||||
function (resp) {
|
|
||||||
console.log("err response : ", resp);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="StandardCodeList container">
|
<div className={"result standard_code_result"}>
|
||||||
<div className="c_wrap codelistcontent">
|
{listData.filter(item => {
|
||||||
<div className="location">
|
if (item.groupNm.includes(filterData)) {
|
||||||
<ul>
|
return item
|
||||||
<li><Link to={URL.MAIN} className="home">Home</Link></li>
|
}
|
||||||
<li><Link to='#'>건설기준코드</Link></li>
|
return null
|
||||||
<li><Link to={URL.STANDARD_CODE_LIST}>건설기준코드 검색</Link></li>
|
}).map(item => {
|
||||||
</ul>
|
return (
|
||||||
</div>
|
<div className="list_item List_Codes">
|
||||||
<div className="layout">
|
<div className="mainCategory">{item.mainCategory}</div>
|
||||||
<div className="contents NOTICE_LIST listtablediv">
|
<div className="middleCategory">{item.middleCategory}</div>
|
||||||
<div className="top_tit">
|
<div className="kcscCd">{item.kcscCd}</div>
|
||||||
<h2 className="tit_1">건설기준코드 검색</h2>
|
<div className="groupNm">{item.groupNm}<br/><span className={"text-danger"}>{item.rvsnRemark}</span></div>
|
||||||
|
<div className="Revisionhistory">
|
||||||
|
<Button size={"sm"} variant={"outline-secondary"} onClick={()=>{historyBtn(item)}}>개정 이력</Button>
|
||||||
</div>
|
</div>
|
||||||
<StandardCodeSearchForm param={listCode} reloadFunction={retrieveList}/>
|
<div className="fille">
|
||||||
<div><span>전체 {resultCnt} 건</span></div>
|
<Row className={"justify-content-start"}>
|
||||||
{/* <!-- 게시판목록 --> */}
|
{item.historyList.filter(history => {
|
||||||
<div className="board_list code_list">
|
return history;
|
||||||
<div className="head">
|
}).map(history => {
|
||||||
<span>대분류</span>
|
let buttonClass = "btn btn-sm docInfoBtn docInfoActive "
|
||||||
<span>중분류</span>
|
let pClass = "yearInfo yearInfoActive";
|
||||||
<span>코드번호</span>
|
if(history.docEr === 'E'){
|
||||||
<span>코드명</span>
|
buttonClass += "btn-success "
|
||||||
<span>개정이력</span>
|
}else{
|
||||||
<span>보기</span>
|
buttonClass += "btn-primary "
|
||||||
<span>즐겨찾기</span>
|
|
||||||
</div>
|
|
||||||
<div className="result">
|
|
||||||
{listData.filter(item => {
|
|
||||||
if (item.groupNm.includes(filterData)) {
|
|
||||||
return item
|
|
||||||
}
|
}
|
||||||
return null
|
|
||||||
}).map(item => {
|
|
||||||
return (
|
return (
|
||||||
<div className="list_item List_Codes">
|
<Col xs={"auto"} className={"px-1"}>
|
||||||
<div className="mainCategory">{item.mainCategory}</div>
|
<input type="button"
|
||||||
<div className="middleCategory">{item.middleCategory}</div>
|
className={buttonClass}
|
||||||
<div className="kcscCd">{item.kcscCd}</div>
|
value={history.docEr==='E'?'제':'개'}
|
||||||
<div className="groupNm">{item.groupNm}</div>
|
onClick={()=>{
|
||||||
<div className="Revisionhistory"><a className="vieweratag" onClick={showHandling} data-groupSeq={item.groupSeq}>개정이력</a></div>
|
const rvsnYmd = new Date(history.rvsnYmd)
|
||||||
<div className="fille">{item.contentcount > 0 ? <a className="vieweratag" href={"/standardCode/viewer/" + item.kcscCd}>내용보기</a> : null}</div>
|
rvsnYmd.setHours(rvsnYmd.getHours()+9)
|
||||||
<div className="star"><AiFillStar/></div>
|
window.open("/standardCode/viewer/"+history.kcscCd+":"+rvsnYmd.toISOString().split('T')[0]);
|
||||||
</div>
|
}}
|
||||||
|
/>
|
||||||
|
<br/>
|
||||||
|
<p className={pClass}>{history.docYr}</p>
|
||||||
|
</Col>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
<StandardCodeListModal size={"lg"} show={show} content={groupSeq} onClose={close} title={"개정이력"}/>
|
<FavoriteIcon item={item}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)
|
||||||
</div>
|
})}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
import {Button, Modal, ModalBody, ModalFooter, ModalHeader, ModalTitle} from "react-bootstrap";
|
|
||||||
|
|
||||||
|
|
||||||
function StandardCodeListModal({show,content,onClose,title,size}){
|
|
||||||
return(
|
|
||||||
<Modal size={size} show={show} aria-labelledby="example-modal-sizes-title-lg">
|
|
||||||
<ModalHeader>
|
|
||||||
<ModalTitle id="example-modal-sizes-title-lg">{title}</ModalTitle>
|
|
||||||
</ModalHeader>
|
|
||||||
<ModalBody>
|
|
||||||
{content}
|
|
||||||
</ModalBody>
|
|
||||||
<ModalFooter><Button onClick={onClose}>닫기</Button></ModalFooter>
|
|
||||||
</Modal>)
|
|
||||||
}
|
|
||||||
|
|
||||||
function StandardCodeListModalTable({head,content}){
|
|
||||||
return(
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
{head}
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{content}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export {StandardCodeListModal,StandardCodeListModalTable};
|
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
import React, {useState, useCallback} from 'react';
|
||||||
|
import {useParams} from 'react-router-dom';
|
||||||
|
|
||||||
|
import * as EgovNet from 'api/egovFetch';
|
||||||
|
import DownloadModal from './DownloadModal'
|
||||||
|
import StandardCodeSearchForm from "./StandardCodeSearchForm";
|
||||||
|
import Loading from "components/Loading";
|
||||||
|
import StandardCodeList from "./StandardCodeList";
|
||||||
|
|
||||||
|
import Modal from "react-bootstrap/Modal";
|
||||||
|
import HistoryModal from "./HistoryModal";
|
||||||
|
|
||||||
|
function StandardCodePage({}) {
|
||||||
|
const {listCode} = useParams();
|
||||||
|
const [listData, setListData] = useState([])
|
||||||
|
const [listLoading, setListLoading] = useState(true);
|
||||||
|
const [filterData, setFilterData] = useState('');
|
||||||
|
const [resultCnt, setResultCnt] = useState(0);
|
||||||
|
const [remarkCnt, setRemarkCnt] = useState(0);
|
||||||
|
const [modalContent, setModalContent] = useState([]);
|
||||||
|
|
||||||
|
const [show, setShow] = useState(false);
|
||||||
|
function close() {
|
||||||
|
setShow(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const retrieveList = useCallback((searchCondition) => {
|
||||||
|
setListLoading(true)
|
||||||
|
EgovNet.requestFetch('/standardCode/standard-code-list'+EgovNet.convParams(searchCondition),
|
||||||
|
{
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
'Content-type': 'application/json',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(resp) => {
|
||||||
|
setListData(resp.result.resultList);
|
||||||
|
setResultCnt(resp.result.resultCnt.allCnt);
|
||||||
|
setRemarkCnt(resp.result.resultCnt.remarkCnt);
|
||||||
|
setListLoading(false)
|
||||||
|
},
|
||||||
|
function (resp) {
|
||||||
|
console.log("err response : ", resp);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
function downloadModal(){
|
||||||
|
setShow(true);
|
||||||
|
setModalContent(<DownloadModal closeFn={close}/>)
|
||||||
|
}
|
||||||
|
|
||||||
|
function historyModal(item){
|
||||||
|
setShow(true);
|
||||||
|
setModalContent(<HistoryModal closeFn={close} standardCode={item}/>)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<div className="c_wrap">
|
||||||
|
{/*<div className="location">
|
||||||
|
<ul>
|
||||||
|
<li><Link to={URL.MAIN} className="home">Home</Link></li>
|
||||||
|
<li>건설기준코드</li>
|
||||||
|
<li><Link to={URL.STANDARD_CODE_LIST} >건설기준코드 검색</Link></li>
|
||||||
|
</ul>
|
||||||
|
</div>*/}
|
||||||
|
<div className="layout">
|
||||||
|
<div className="contents NOTICE_LIST" id="contents">
|
||||||
|
{/*<div className="top_tit">
|
||||||
|
<h1 className="tit_1">건설기준코드 검색</h1>
|
||||||
|
</div>*/}
|
||||||
|
<div className="StandardCodeList container">
|
||||||
|
<div className="c_wrap codeListContent">
|
||||||
|
<div className="layout">
|
||||||
|
<div className="contents NOTICE_LIST listTableDiv">
|
||||||
|
<StandardCodeSearchForm param={listCode?listCode:'10'} reloadFunction={retrieveList} resultCnt={resultCnt} remarkCnt={remarkCnt} downloadModal={downloadModal}/>
|
||||||
|
<div className="board_list code_list">
|
||||||
|
<div className="head">
|
||||||
|
<span>대분류</span>
|
||||||
|
<span>중분류</span>
|
||||||
|
<span>코드번호</span>
|
||||||
|
<span>코드명</span>
|
||||||
|
<span>개정이력</span>
|
||||||
|
<span className={"text-start"}>보기</span>
|
||||||
|
<span>즐겨찾기</span>
|
||||||
|
</div>
|
||||||
|
{
|
||||||
|
listLoading?(<Loading loadingState={true}/>):(
|
||||||
|
<StandardCodeList listData={listData} filterData={filterData} getHistoryModal={historyModal}/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<Modal size={"lg"} show={show} onHide={close}>
|
||||||
|
{modalContent}
|
||||||
|
</Modal>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default StandardCodePage;
|
||||||
|
|
||||||
|
|
@ -1,16 +1,41 @@
|
||||||
import React, {useEffect, useState} from "react";
|
import React, {useEffect, useState} from "react";
|
||||||
|
import {Nav} from "react-bootstrap";
|
||||||
|
import Row from "react-bootstrap/Row";
|
||||||
|
import Col from "react-bootstrap/Col";
|
||||||
|
import {Link} from "react-router-dom";
|
||||||
|
import Button from "react-bootstrap/Button";
|
||||||
|
import * as EgovNet from "../../../api/egovFetch";
|
||||||
|
|
||||||
function StandardCodeSearchForm({param, reloadFunction}){
|
function StandardCodeSearchForm({param, reloadFunction, resultCnt, remarkCnt, downloadModal}){
|
||||||
|
|
||||||
const [searchCondition, setSearchCondition] = useState({
|
const [searchCondition, setSearchCondition] = useState({
|
||||||
pageIndex: 1,
|
|
||||||
tab: Number(param?.substring(0, 2)),
|
tab: Number(param?.substring(0, 2)),
|
||||||
category1: param?.substring(2, 4),
|
category1: param?.substring(2, 4),
|
||||||
category2: param?.substring(4, 6),
|
category2: param?.substring(4, 6),
|
||||||
searchWrd: ''
|
category3: param?.substring(6, 8),
|
||||||
});
|
});
|
||||||
const [subTabsVisible, setSubTabsVisible] = useState(false);
|
const [subTabsVisible, setSubTabsVisible] = useState(false);
|
||||||
|
|
||||||
|
const [cat1SelectOption, setCat1SelectOption] = useState([])
|
||||||
|
const [cat2SelectOption, setCat2SelectOption] = useState([])
|
||||||
|
const [cat3SelectOption, setCat3SelectOption] = useState([])
|
||||||
|
|
||||||
|
function getSelectBoxOption(groupCd, handler){
|
||||||
|
EgovNet.requestFetch(
|
||||||
|
'/standardCode/category-option?listCode='+groupCd,
|
||||||
|
{
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
'Content-type': 'application/json',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handler,
|
||||||
|
function (resp) {
|
||||||
|
console.log("err response : ", resp);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if(searchCondition.tab){
|
if(searchCondition.tab){
|
||||||
if(searchCondition.tab !== 10 && searchCondition.tab !== 20){
|
if(searchCondition.tab !== 10 && searchCondition.tab !== 20){
|
||||||
|
|
@ -22,6 +47,43 @@ function StandardCodeSearchForm({param, reloadFunction}){
|
||||||
reloadFunction(searchCondition)
|
reloadFunction(searchCondition)
|
||||||
}, [searchCondition]);
|
}, [searchCondition]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setSearchCondition({...searchCondition, category1: '', category2: '', category3: ''})
|
||||||
|
const groupCd = searchCondition.tab;
|
||||||
|
getSelectBoxOption(groupCd, (resp)=>{
|
||||||
|
const options = [];
|
||||||
|
resp.result.groupList.forEach(function (item, index){
|
||||||
|
options.push(<option value={item.groupCurCd}>{item.groupNm}</option>)
|
||||||
|
})
|
||||||
|
setCat1SelectOption(options)
|
||||||
|
})
|
||||||
|
}, [searchCondition.tab]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setSearchCondition({...searchCondition, category2: '', category3: ''})
|
||||||
|
const groupCd = searchCondition.tab+searchCondition.category1;
|
||||||
|
getSelectBoxOption(groupCd, (resp)=>{
|
||||||
|
const options = [];
|
||||||
|
resp.result.groupList.forEach(function (item, index){
|
||||||
|
options.push(<option value={item.groupCurCd}>{item.groupNm}</option>)
|
||||||
|
})
|
||||||
|
setCat2SelectOption(options)
|
||||||
|
})
|
||||||
|
}, [searchCondition.category1]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setSearchCondition({...searchCondition, category3: ''})
|
||||||
|
const groupCd = searchCondition.tab+searchCondition.category1+searchCondition.category2;
|
||||||
|
getSelectBoxOption(groupCd, (resp)=>{
|
||||||
|
const options = [];
|
||||||
|
resp.result.groupList.forEach(function (item, index){
|
||||||
|
options.push(<option value={item.groupCurCd}>{item.groupNm}</option>)
|
||||||
|
})
|
||||||
|
setCat3SelectOption(options)
|
||||||
|
})
|
||||||
|
}, [searchCondition.category2]);
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="condition">
|
<div className="condition">
|
||||||
|
|
@ -40,45 +102,61 @@ function StandardCodeSearchForm({param, reloadFunction}){
|
||||||
</li>
|
</li>
|
||||||
<li className="third_1 L">
|
<li className="third_1 L">
|
||||||
<label className="f_select" htmlFor="sel1">
|
<label className="f_select" htmlFor="sel1">
|
||||||
<select id="sel1" title="조건" value={searchCondition.category1}>
|
<select id="sel1" title="조건" value={searchCondition.category1}
|
||||||
|
onChange={(e)=>{setSearchCondition({...searchCondition, category1: e.target.value})}}>
|
||||||
<option value="">전체</option>
|
<option value="">전체</option>
|
||||||
|
{cat1SelectOption}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li className="third_1 L">
|
||||||
|
<label className="f_select w_306" htmlFor="sel1">
|
||||||
|
<select id="sel2" title="조건" value={searchCondition.category2}
|
||||||
|
onChange={(e)=>{setSearchCondition({...searchCondition, category2: e.target.value})}}>
|
||||||
|
<option value="">전체</option>
|
||||||
|
{cat2SelectOption}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li className="third_1 L">
|
||||||
|
<label className="f_select w_306" htmlFor="sel1">
|
||||||
|
<select id="sel3" title="조건" value={searchCondition.category3}
|
||||||
|
onChange={(e)=>{setSearchCondition({...searchCondition, category3: e.target.value})}}>
|
||||||
|
<option value="">전체</option>
|
||||||
|
{cat3SelectOption}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
<li className="third_1 L">
|
||||||
|
{remarkCnt?(
|
||||||
|
<span>전체 {resultCnt} / <span className={"text-danger"}>{remarkCnt}</span> 건</span>
|
||||||
|
):(
|
||||||
|
<span>전체 {resultCnt} 건</span>
|
||||||
|
)}
|
||||||
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
</li>
|
</li>
|
||||||
<li className="third_1 L">
|
<li className="third_1 L">
|
||||||
<label className="f_select w_306" htmlFor="sel1">
|
<div className={`tab`} onClick={downloadModal}>통합 다운로드</div>
|
||||||
<select id="sel2" title="조건" value={searchCondition.category2}>
|
|
||||||
<option value="">전체</option>
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
<li className="third_1 L">
|
|
||||||
<label className="f_select w_306" htmlFor="sel1">
|
|
||||||
<select id="sel3" title="조건" value={searchCondition.category3} >
|
|
||||||
<option value="">전체</option>
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
<li className="third_1 L">
|
|
||||||
<div className={`tab`}>통합 다운로드</div>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{subTabsVisible && (
|
<Row className={"justify-content-between"}>
|
||||||
<div className="right_col">
|
<Col>
|
||||||
<div className="mini_board">
|
{subTabsVisible && (
|
||||||
<ul>
|
<Nav className={"tabs"} variant={"tabs"} >
|
||||||
<div className={`tab ${searchCondition.tab === 40 ? 'active' : ''}`} onClick={() => {setSearchCondition({...searchCondition, tab: 40})}}>서울특별시</div>
|
<Nav.Item><Nav.Link className={`${searchCondition.tab === 40 ? 'active' : ''}`} onClick={() => {setSearchCondition({...searchCondition, tab: 40})}}>서울특별시</Nav.Link></Nav.Item>
|
||||||
<div className={`tab ${searchCondition.tab === 50 ? 'active' : ''}`} onClick={() => {setSearchCondition({...searchCondition, tab: 50})}}>고속도로공사</div>
|
<Nav.Item><Nav.Link className={`${searchCondition.tab === 50 ? 'active' : ''}`} onClick={() => {setSearchCondition({...searchCondition, tab: 50})}}>고속도로공사</Nav.Link></Nav.Item>
|
||||||
<div className={`tab ${searchCondition.tab === 60 ? 'active' : ''}`} onClick={() => {setSearchCondition({...searchCondition, tab: 60})}}>한국농어촌공사</div>
|
<Nav.Item><Nav.Link className={`${searchCondition.tab === 60 ? 'active' : ''}`} onClick={() => {setSearchCondition({...searchCondition, tab: 60})}}>한국농어촌공사</Nav.Link></Nav.Item>
|
||||||
<div className={`tab ${searchCondition.tab === 70 ? 'active' : ''}`} onClick={() => {setSearchCondition({...searchCondition, tab: 70})}}>철도건설공사</div>
|
<Nav.Item><Nav.Link className={`${searchCondition.tab === 70 ? 'active' : ''}`} onClick={() => {setSearchCondition({...searchCondition, tab: 70})}}>철도건설공사</Nav.Link></Nav.Item>
|
||||||
<div className={`tab ${searchCondition.tab === 80 ? 'active' : ''}`} onClick={() => {setSearchCondition({...searchCondition, tab: 80})}}>LH한국토지주택공사</div>
|
<Nav.Item><Nav.Link className={`${searchCondition.tab === 80 ? 'active' : ''}`} onClick={() => {setSearchCondition({...searchCondition, tab: 80})}}>LH한국토지주택공사</Nav.Link></Nav.Item>
|
||||||
<div className={`tab ${searchCondition.tab === 90 ? 'active' : ''}`} onClick={() => {setSearchCondition({...searchCondition, tab: 90})}}>K-Water</div>
|
<Nav.Item><Nav.Link className={`${searchCondition.tab === 90 ? 'active' : ''}`} onClick={() => {setSearchCondition({...searchCondition, tab: 90})}}>K-Water</Nav.Link></Nav.Item>
|
||||||
</ul>
|
</Nav>
|
||||||
</div>
|
)}
|
||||||
</div>
|
</Col>
|
||||||
)}
|
<Col xs={"auto"}>
|
||||||
|
<Button href={"/standardCode/info"} size={"sm"} variant={"secondary"}>건설기준코드 안내</Button>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,17 +49,13 @@ const BookmarkModal = ({docCode, docPart, ymd}) => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const getCodeInfo = useCallback(() => {
|
const getCodeInfo = useCallback(() => {
|
||||||
console.groupCollapsed("EgovMain.getCodeInfo()");
|
|
||||||
EgovNet.requestFetch(
|
EgovNet.requestFetch(
|
||||||
'/standardCode/getCodeInfo.do',
|
'/standardCode/code-info?docCode='+docCode,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
'Content-type': 'application/json'
|
'Content-type': 'application/json'
|
||||||
},
|
}
|
||||||
body: JSON.stringify({
|
|
||||||
docCode: docCode
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
(resp) => {
|
(resp) => {
|
||||||
const docInfo = resp.result.docInfo;
|
const docInfo = resp.result.docInfo;
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { useState, useEffect, useCallback } from 'react';
|
import React, { useState, useEffect, useCallback } from 'react';
|
||||||
import { useLocation, useParams } from 'react-router-dom';
|
import { useLocation, useParams } from 'react-router-dom';
|
||||||
import SbItem from './SbItem'
|
import SbItem from './SbItem'
|
||||||
import Loading from '../../../components/Loading'
|
import Loading from 'components/Loading'
|
||||||
import BookmarkModal from './BookmarkModal';
|
import BookmarkModal from './BookmarkModal';
|
||||||
import {SbContainer} from './Sb.style'
|
import {SbContainer} from './Sb.style'
|
||||||
import {VwDiv, VwPtag} from './Vw.style'
|
import {VwDiv, VwPtag} from './Vw.style'
|
||||||
|
|
@ -10,18 +10,21 @@ import Row from 'react-bootstrap/Row';
|
||||||
import Col from 'react-bootstrap/Col';
|
import Col from 'react-bootstrap/Col';
|
||||||
import Modal from 'react-bootstrap/Modal';
|
import Modal from 'react-bootstrap/Modal';
|
||||||
import * as EgovNet from 'api/egovFetch';
|
import * as EgovNet from 'api/egovFetch';
|
||||||
import {getLocalItem} from "../../../utils/storage";
|
import {getLocalItem} from "utils/storage";
|
||||||
import CODE from "../../../constants/code";
|
import CODE from "constants/code";
|
||||||
import {parseJwt} from "../../../utils/parseJwt";
|
import {parseJwt} from "utils/parseJwt";
|
||||||
|
import Button from "react-bootstrap/Button";
|
||||||
|
import {InputGroup} from "react-bootstrap";
|
||||||
|
import ViewerTree from "./ViewerTree";
|
||||||
|
|
||||||
function CodeViewer(props) {
|
function CodeViewer(props) {
|
||||||
const [treeLoading, setTreeLoading] = useState(true);
|
const [treeLoading, setTreeLoading] = useState(true);
|
||||||
const [docLoading, setDocLoading] = useState(true);
|
const [docLoading, setDocLoading] = useState(true);
|
||||||
|
|
||||||
const {linkedDocCode} = useParams();
|
const {linkedDocCode} = useParams();
|
||||||
const [docCode, setDocCode] = useState(linkedDocCode !== undefined?linkedDocCode.split(':')[0]:props.docCode);
|
const [docCode, setDocCode] = useState(linkedDocCode !== undefined?linkedDocCode.split(':')[0]:props.docCode);
|
||||||
const [ymd, setYmd] = useState(linkedDocCode !== undefined?linkedDocCode.split(':')[1]:props.ymd);
|
const [ymd, setYmd] = useState(linkedDocCode !== undefined?linkedDocCode.split(':')[1]:props.ymd);
|
||||||
const [docInfo, setDocInfo] = useState();
|
const [docInfo, setDocInfo] = useState();
|
||||||
const [codeTree, setCodeTree] = useState();
|
|
||||||
const [docSummary, setDocSummary] = useState();
|
const [docSummary, setDocSummary] = useState();
|
||||||
const [docDetail, setDocDetail] = useState();
|
const [docDetail, setDocDetail] = useState();
|
||||||
const [errorSelector, setErrorSelector] = useState();
|
const [errorSelector, setErrorSelector] = useState();
|
||||||
|
|
@ -29,6 +32,8 @@ function CodeViewer(props) {
|
||||||
const [show, setShow] = useState(false);
|
const [show, setShow] = useState(false);
|
||||||
const [bookMarkModal, setBookMarkModal] = useState();
|
const [bookMarkModal, setBookMarkModal] = useState();
|
||||||
|
|
||||||
|
const [colList, setColList] = useState([3,2,7]);
|
||||||
|
|
||||||
|
|
||||||
const sessionUser = parseJwt(getLocalItem('accessToken'));
|
const sessionUser = parseJwt(getLocalItem('accessToken'));
|
||||||
const sessionUserSe = sessionUser?.userSe;
|
const sessionUserSe = sessionUser?.userSe;
|
||||||
|
|
@ -44,65 +49,21 @@ function CodeViewer(props) {
|
||||||
console.log("viewer [docCode] : ", docCode);
|
console.log("viewer [docCode] : ", docCode);
|
||||||
|
|
||||||
const updateDocCode = (docCode)=>{
|
const updateDocCode = (docCode)=>{
|
||||||
setDocSummary([<div></div>])
|
setDocLoading(true);
|
||||||
setDocDetail([<div>불러오는중</div>])
|
|
||||||
setDocInfo([])
|
|
||||||
setDocCode(docCode);
|
setDocCode(docCode);
|
||||||
getCodeInfo(docCode);
|
getCodeInfo(docCode);
|
||||||
getCodeDetailInfo(docCode);
|
getCodeDetailInfo(docCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
const getCodeTree = ()=>{
|
|
||||||
EgovNet.requestFetch(
|
|
||||||
'/standardCode/getCodeTree.do',
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
'Content-type': 'application/json'
|
|
||||||
},
|
|
||||||
body: JSON.stringify({})
|
|
||||||
},
|
|
||||||
(resp) => {
|
|
||||||
const menuData = resp.result.codeTree;
|
|
||||||
// 코드 목록 트리 구성
|
|
||||||
// https://garve32.tistory.com/52 참고
|
|
||||||
const nest = (menuData, parent_seq = null, link = 'parent_seq') =>
|
|
||||||
menuData.filter(item => item[link] === parent_seq)
|
|
||||||
.map(item => ({ ...item, childrens: nest(menuData, item.seq) }));
|
|
||||||
const tree = nest(menuData);
|
|
||||||
let treeTag = [];
|
|
||||||
if(tree.length>0){
|
|
||||||
treeTag.push(
|
|
||||||
<SbContainer>
|
|
||||||
{tree.map((subItem) =>
|
|
||||||
<SbItem item={subItem} openDocCode={docCode} updateDocCode={updateDocCode} />
|
|
||||||
)}
|
|
||||||
</SbContainer>
|
|
||||||
)
|
|
||||||
}else{
|
|
||||||
treeTag.push(<div>검색된 결과가 없습니다.</div>); // 코드 목록 초기값
|
|
||||||
}
|
|
||||||
setCodeTree(treeTag);
|
|
||||||
setTreeLoading(false);
|
|
||||||
},
|
|
||||||
function (resp) {
|
|
||||||
console.log("err response : ", resp);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const getCodeInfo = useCallback((docCode) => {
|
const getCodeInfo = useCallback((docCode) => {
|
||||||
console.groupCollapsed("EgovMain.getCodeInfo()");
|
console.groupCollapsed("EgovMain.getCodeInfo()");
|
||||||
EgovNet.requestFetch(
|
EgovNet.requestFetch(
|
||||||
'/standardCode/getCodeInfo.do',
|
'/standardCode/code-info?docCode='+docCode,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
'Content-type': 'application/json'
|
'Content-type': 'application/json'
|
||||||
},
|
}
|
||||||
body: JSON.stringify({
|
|
||||||
docCode: docCode
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
(resp) => {
|
(resp) => {
|
||||||
const docInfo = resp.result.docInfo;
|
const docInfo = resp.result.docInfo;
|
||||||
|
|
@ -307,6 +268,7 @@ function CodeViewer(props) {
|
||||||
clickBtn.parentElement.querySelector("p").className += " yearInfoActive"
|
clickBtn.parentElement.querySelector("p").className += " yearInfoActive"
|
||||||
getCodeDetailInfo(clickBtn.dataset.doccode, clickBtn.dataset.ymd);
|
getCodeDetailInfo(clickBtn.dataset.doccode, clickBtn.dataset.ymd);
|
||||||
})
|
})
|
||||||
|
|
||||||
const actionAppend = (el) => {
|
const actionAppend = (el) => {
|
||||||
if(!el) return;
|
if(!el) return;
|
||||||
if(el.childNodes.length===0){
|
if(el.childNodes.length===0){
|
||||||
|
|
@ -420,9 +382,15 @@ function CodeViewer(props) {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
function treeControl(){
|
||||||
|
if(colList[0]===3){
|
||||||
|
setColList([0,3,9]);
|
||||||
|
}else{
|
||||||
|
setColList([3,2,7]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getCodeTree();
|
|
||||||
getCodeInfo(docCode);
|
getCodeInfo(docCode);
|
||||||
getCodeDetailInfo(docCode);
|
getCodeDetailInfo(docCode);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
@ -431,38 +399,49 @@ function CodeViewer(props) {
|
||||||
console.groupEnd("viewer");
|
console.groupEnd("viewer");
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{treeLoading || docLoading? (<Loading/>):(
|
{/*{treeLoading || docLoading? ():()}*/}
|
||||||
<Row className="mx-0">
|
<Loading loadingState={treeLoading || docLoading}/>
|
||||||
<Col xs={12} className="border-bottom">
|
<Row className={`mx-0 ${treeLoading || docLoading?'d-none':''}`}>
|
||||||
<Row>
|
<Col xs={12} className="border-bottom">
|
||||||
<Col xs={3}></Col>
|
<Row>
|
||||||
<Col xs={9}>
|
<Col xs={3}></Col>
|
||||||
<Row className="justify-content-between">
|
<Col xs={9}>
|
||||||
<Col xs={"auto"}>
|
<Row className="justify-content-between">
|
||||||
<Row>
|
<Col xs={"auto"}>
|
||||||
<Col xs={"auto"}>{docInfo}</Col>
|
<Row>
|
||||||
<Col>
|
<Col xs={"auto"}>{docInfo}</Col>
|
||||||
<input type="button" className="btn btn-sm btn-primary optionBtn" value="연혁"/>
|
<Col>
|
||||||
<input type="button" className="btn btn-sm btn-primary optionBtn" value="비교"/>
|
<input type="button" className="btn btn-sm btn-primary optionBtn" value="연혁"/>
|
||||||
</Col>
|
<input type="button" className="btn btn-sm btn-primary optionBtn" value="2단비교"/>
|
||||||
</Row>
|
<input type="button" className="btn btn-sm btn-primary optionBtn" value="신구조문"/>
|
||||||
</Col>
|
<input type="button" className="btn btn-sm btn-primary optionBtn" value="첨부파일"/>
|
||||||
<Col xs={"auto"}>{errorSelector}</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
<Col xs={"auto"}>
|
||||||
</Col>
|
<InputGroup>
|
||||||
<Col xs={3} className="border-end viewerDiv">
|
<Form.Control type="text" size={"sm"} placeholder={"문서 내 검색"}/>
|
||||||
{codeTree}
|
{errorSelector}
|
||||||
</Col>
|
</InputGroup>
|
||||||
<Col xs={2} className="border-end viewerDiv">
|
</Col>
|
||||||
{docSummary}
|
</Row>
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs={7} className="viewerDiv detailInfoDiv" ref={actionAppend}>
|
</Row>
|
||||||
{docDetail}
|
</Col>
|
||||||
</Col>
|
<Col xs={colList[0]} className={`border-end viewerDiv ${colList[0]===3?'':'d-none'}`}>
|
||||||
</Row>
|
{/*{codeTree}*/}
|
||||||
)}
|
<ViewerTree docCode={docCode} updateDocCode={updateDocCode} setTreeLoading={setTreeLoading}/>
|
||||||
|
</Col>
|
||||||
|
<Col xs={colList[1]} className="border-end viewerDiv">
|
||||||
|
<div>
|
||||||
|
<Button size={"sm"} variant={"outline-secondary"} onClick={treeControl}>{colList[0]===3?'트리 접기':'트리 펼치기'}</Button>
|
||||||
|
</div>
|
||||||
|
{docSummary}
|
||||||
|
</Col>
|
||||||
|
<Col xs={colList[2]} className="viewerDiv detailInfoDiv" ref={actionAppend}>
|
||||||
|
{docDetail}
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
<Modal show={show} onHide={handleClose} size="xl" keyboard={false} scrollable>
|
<Modal show={show} onHide={handleClose} size="xl" keyboard={false} scrollable>
|
||||||
{bookMarkModal}
|
{bookMarkModal}
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
@ -471,8 +450,8 @@ function CodeViewer(props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeViewer.defaultProps = {
|
CodeViewer.defaultProps = {
|
||||||
docCode: 'KCS 24 31 10',
|
docCode: 'KDS 11 10 15',
|
||||||
docName: '용접(한계상태설계법)'
|
docName: '지반계측'
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CodeViewer;
|
export default CodeViewer;
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
import React, {useEffect, useState} from "react";
|
||||||
|
import {SbContainer} from "./Sb.style";
|
||||||
|
import SbItem from "./SbItem";
|
||||||
|
import * as EgovNet from "api/egovFetch";
|
||||||
|
|
||||||
|
|
||||||
|
function ViewerTree({docCode, updateDocCode, setTreeLoading}){
|
||||||
|
const [tree, setTree] = useState([]);
|
||||||
|
function getCodeTree(){
|
||||||
|
EgovNet.requestFetch(
|
||||||
|
'/standardCode/code-tree',
|
||||||
|
{
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
'Content-type': 'application/json'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(resp) => {
|
||||||
|
const menuData = resp.result.codeTree;
|
||||||
|
// 코드 목록 트리 구성
|
||||||
|
// https://garve32.tistory.com/52 참고
|
||||||
|
const nest = (menuData, parent_seq = null, link = 'parent_seq') =>
|
||||||
|
menuData.filter(item => item[link] === parent_seq)
|
||||||
|
.map(item => ({ ...item, childrens: nest(menuData, item.seq) }));
|
||||||
|
setTree(nest(menuData));
|
||||||
|
setTreeLoading(false);
|
||||||
|
},
|
||||||
|
function (resp) {
|
||||||
|
console.log("err response : ", resp);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getCodeTree()
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SbContainer>
|
||||||
|
{tree.map((subItem) =>
|
||||||
|
<SbItem item={subItem} openDocCode={docCode} updateDocCode={updateDocCode} />
|
||||||
|
)}
|
||||||
|
</SbContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ViewerTree;
|
||||||
|
|
@ -47,8 +47,8 @@ import EgovGalleryEdit from 'pages/inform/gallery/EgovGalleryEdit';
|
||||||
|
|
||||||
//ADMIN
|
//ADMIN
|
||||||
import EgovAdminScheduleList from 'pages/admin/schedule/EgovAdminScheduleList';
|
import EgovAdminScheduleList from 'pages/admin/schedule/EgovAdminScheduleList';
|
||||||
import EgovAdminScheduleDetail from 'pages/admin/schedule/EgovAdminScheduleDetail';
|
// import EgovAdminScheduleDetail from 'pages/admin/schedule/EgovAdminScheduleDetail';
|
||||||
import EgovAdminScheduleEdit from 'pages/admin/schedule/EgovAdminScheduleEdit';
|
// import EgovAdminScheduleEdit from 'pages/admin/schedule/EgovAdminScheduleEdit';
|
||||||
|
|
||||||
import EgovAdminBoardList from 'pages/admin/board/EgovAdminBoardList';
|
import EgovAdminBoardList from 'pages/admin/board/EgovAdminBoardList';
|
||||||
import EgovAdminBoardEdit from 'pages/admin/board/EgovAdminBoardEdit';
|
import EgovAdminBoardEdit from 'pages/admin/board/EgovAdminBoardEdit';
|
||||||
|
|
@ -94,7 +94,7 @@ import AdminContentsPopUp from 'pages/admin/contents/PopUp';
|
||||||
import AdminContentsPopUpEditor from 'pages/admin/contents/PopUp/PopupEditor'; // 관리자 - 컨텐츠 관리/팝업 관리/팝업 추가 또는 수정
|
import AdminContentsPopUpEditor from 'pages/admin/contents/PopUp/PopupEditor'; // 관리자 - 컨텐츠 관리/팝업 관리/팝업 추가 또는 수정
|
||||||
import AdminContentsStandardResearch from 'pages/admin/contents/StandardResearch'; // 관리자 - 컨텐츠 관리/건설기준연구 관리
|
import AdminContentsStandardResearch from 'pages/admin/contents/StandardResearch'; // 관리자 - 컨텐츠 관리/건설기준연구 관리
|
||||||
import AdminContentsStandardResearchEditor from 'pages/admin/contents/StandardResearch/StandardResearchEditor'; // 컨텐츠 관리/건설기준연구 관리/추가 또는 수정
|
import AdminContentsStandardResearchEditor from 'pages/admin/contents/StandardResearch/StandardResearchEditor'; // 컨텐츠 관리/건설기준연구 관리/추가 또는 수정
|
||||||
import AdminContentsTextMessages from 'pages/admin/contents/TextMessages'; // 관리자 - 컨텐츠 관리/문자 발송
|
// import AdminContentsTextMessages from 'pages/admin/contents/TextMessages'; // 관리자 - 컨텐츠 관리/문자 발송
|
||||||
|
|
||||||
// 관리자 - 위원회 관리
|
// 관리자 - 위원회 관리
|
||||||
import AdminCommitteeProgressStatus from 'pages/admin/committee/ProgressStatus'; // 관리자 - 위원회 관리/진행현황 관리
|
import AdminCommitteeProgressStatus from 'pages/admin/committee/ProgressStatus'; // 관리자 - 위원회 관리/진행현황 관리
|
||||||
|
|
@ -110,11 +110,13 @@ import AdminLogsFileDownloadStatus from 'pages/admin/logs/FileDownloadStatus';
|
||||||
|
|
||||||
|
|
||||||
//건설기준코드
|
//건설기준코드
|
||||||
import CodeViewer from 'pages/standardCode/viewer/viewer';
|
import CodeViewer from 'pages/standardCode/viewer/CodeViewer';
|
||||||
|
import StandardCodePage from "../pages/standardCode/list/StandardCodePage";
|
||||||
|
import StandardCodeInfo from "../pages/standardCode/info/StandardCodeInfo";
|
||||||
|
|
||||||
|
|
||||||
import * as EgovNet from 'api/egovFetch'; // jwt토큰 위조 검사 때문에 추가
|
import * as EgovNet from 'api/egovFetch'; // jwt토큰 위조 검사 때문에 추가
|
||||||
import initPage from 'js/ui';
|
import initPage from 'js/ui';
|
||||||
import StandardCodeList from "../pages/standardCode/list/StandardCodeList";
|
|
||||||
|
|
||||||
const RootRoutes = () => {
|
const RootRoutes = () => {
|
||||||
//useLocation객체를 이용하여 정규표현식을 사용한 /admin/~ 으로 시작하는 경로와 비교에 사용(아래 1줄) */}
|
//useLocation객체를 이용하여 정규표현식을 사용한 /admin/~ 으로 시작하는 경로와 비교에 사용(아래 1줄) */}
|
||||||
|
|
@ -136,6 +138,8 @@ const RootRoutes = () => {
|
||||||
(resp) => {
|
(resp) => {
|
||||||
if (resp === false) {
|
if (resp === false) {
|
||||||
setMounted(false);
|
setMounted(false);
|
||||||
|
alert("관리자 전용 페이지입니다.")
|
||||||
|
window.location.href="/";
|
||||||
} else {
|
} else {
|
||||||
setMounted(true); // 이 값으로 true 일 때만 페이지를 렌더링이 되는 변수 사용.
|
setMounted(true); // 이 값으로 true 일 때만 페이지를 렌더링이 되는 변수 사용.
|
||||||
}
|
}
|
||||||
|
|
@ -248,9 +252,9 @@ const SecondRoutes = () => {
|
||||||
{/* ADMIN */}
|
{/* ADMIN */}
|
||||||
<Route path={URL.ADMIN} element={<Navigate to={URL.ADMIN_SCHEDULE} />} />
|
<Route path={URL.ADMIN} element={<Navigate to={URL.ADMIN_SCHEDULE} />} />
|
||||||
<Route path={URL.ADMIN_SCHEDULE} element={<EgovAdminScheduleList />} />
|
<Route path={URL.ADMIN_SCHEDULE} element={<EgovAdminScheduleList />} />
|
||||||
<Route path={URL.ADMIN_SCHEDULE_DETAIL} element={<EgovAdminScheduleDetail />} />
|
{/*<Route path={URL.ADMIN_SCHEDULE_DETAIL} element={<EgovAdminScheduleDetail />} />*/}
|
||||||
<Route path={URL.ADMIN_SCHEDULE_CREATE} element={<EgovAdminScheduleEdit mode={CODE.MODE_CREATE} />} />
|
{/*<Route path={URL.ADMIN_SCHEDULE_CREATE} element={<EgovAdminScheduleEdit mode={CODE.MODE_CREATE} />} />*/}
|
||||||
<Route path={URL.ADMIN_SCHEDULE_MODIFY} element={<EgovAdminScheduleEdit mode={CODE.MODE_MODIFY} />} />
|
{/*<Route path={URL.ADMIN_SCHEDULE_MODIFY} element={<EgovAdminScheduleEdit mode={CODE.MODE_MODIFY} />} />*/}
|
||||||
|
|
||||||
<Route path={URL.ADMIN_BOARD} element={<EgovAdminBoardList />} />
|
<Route path={URL.ADMIN_BOARD} element={<EgovAdminBoardList />} />
|
||||||
<Route path={URL.ADMIN_BOARD_CREATE} element={<EgovAdminBoardEdit mode={CODE.MODE_CREATE} />} />
|
<Route path={URL.ADMIN_BOARD_CREATE} element={<EgovAdminBoardEdit mode={CODE.MODE_CREATE} />} />
|
||||||
|
|
@ -304,7 +308,7 @@ const SecondRoutes = () => {
|
||||||
<Route path={URL.ADMIN__CONTENTS__STANDARDS_RESEARCH} element={<AdminContentsStandardResearch />} />
|
<Route path={URL.ADMIN__CONTENTS__STANDARDS_RESEARCH} element={<AdminContentsStandardResearch />} />
|
||||||
<Route path={URL.ADMIN__CONTENTS__STANDARDS_RESEARCH__CREATE} element={<AdminContentsStandardResearchEditor mode={CODE.MODE_CREATE} />} />
|
<Route path={URL.ADMIN__CONTENTS__STANDARDS_RESEARCH__CREATE} element={<AdminContentsStandardResearchEditor mode={CODE.MODE_CREATE} />} />
|
||||||
<Route path={URL.ADMIN__CONTENTS__STANDARDS_RESEARCH__MODIFY} element={<AdminContentsStandardResearchEditor mode={CODE.MODE_MODIFY} />} />
|
<Route path={URL.ADMIN__CONTENTS__STANDARDS_RESEARCH__MODIFY} element={<AdminContentsStandardResearchEditor mode={CODE.MODE_MODIFY} />} />
|
||||||
<Route path={URL.ADMIN__CONTENTS__TEXT_MESSAGES} element={<AdminContentsTextMessages />} />
|
{/*<Route path={URL.ADMIN__CONTENTS__TEXT_MESSAGES} element={<AdminContentsTextMessages />} />*/}
|
||||||
|
|
||||||
{/* 관리자 - 위원회 관리 */}
|
{/* 관리자 - 위원회 관리 */}
|
||||||
<Route path={URL.ADMIN__COMMITTEE__PROGRESS_STATUS} element={<AdminCommitteeProgressStatus />} />
|
<Route path={URL.ADMIN__COMMITTEE__PROGRESS_STATUS} element={<AdminCommitteeProgressStatus />} />
|
||||||
|
|
@ -327,9 +331,10 @@ const SecondRoutes = () => {
|
||||||
<Route path={URL.STANDARD_CODE_VIEWER} element={<CodeViewer mode={CODE.MODE_READ} />} />
|
<Route path={URL.STANDARD_CODE_VIEWER} element={<CodeViewer mode={CODE.MODE_READ} />} />
|
||||||
<Route path={URL.STANDARD_CODE_VIEWER_LINK} element={<CodeViewer mode={CODE.MODE_READ} />} />
|
<Route path={URL.STANDARD_CODE_VIEWER_LINK} element={<CodeViewer mode={CODE.MODE_READ} />} />
|
||||||
|
|
||||||
|
<Route path={URL.STANDARD_CODE_INFO} element={<StandardCodeInfo />} />
|
||||||
{/*기준코드리스트*/}
|
{/*기준코드리스트*/}
|
||||||
<Route path={URL.STANDARD_CODE_LIST} element={<StandardCodeList />} />
|
<Route path={URL.STANDARD_CODE_LIST} element={<StandardCodePage />} />
|
||||||
<Route path={URL.STANDARD_CODE_LIST_LINK} element={<StandardCodeList />} />
|
<Route path={URL.STANDARD_CODE_LIST_LINK} element={<StandardCodePage />} />
|
||||||
|
|
||||||
</Routes>
|
</Routes>
|
||||||
<EgovFooter />
|
<EgovFooter />
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
|
// material-ui
|
||||||
|
import { CssBaseline, StyledEngineProvider } from '@mui/material';
|
||||||
|
import { createTheme, ThemeProvider } from '@mui/material/styles';
|
||||||
|
|
||||||
|
// project import
|
||||||
|
import Palette from './palette';
|
||||||
|
import Typography from './typography';
|
||||||
|
import CustomShadows from './shadows';
|
||||||
|
import componentsOverride from './overrides';
|
||||||
|
|
||||||
|
// ==============================|| DEFAULT THEME - MAIN ||============================== //
|
||||||
|
|
||||||
|
export default function ThemeCustomization({ children }) {
|
||||||
|
const theme = Palette('light', 'default');
|
||||||
|
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
const themeTypography = Typography(`'Public Sans', sans-serif`);
|
||||||
|
const themeCustomShadows = useMemo(() => CustomShadows(theme), [theme]);
|
||||||
|
|
||||||
|
const themeOptions = useMemo(
|
||||||
|
() => ({
|
||||||
|
breakpoints: {
|
||||||
|
values: {
|
||||||
|
xs: 0,
|
||||||
|
sm: 768,
|
||||||
|
md: 1024,
|
||||||
|
lg: 1266,
|
||||||
|
xl: 1536
|
||||||
|
}
|
||||||
|
},
|
||||||
|
direction: 'ltr',
|
||||||
|
mixins: {
|
||||||
|
toolbar: {
|
||||||
|
minHeight: 60,
|
||||||
|
paddingTop: 8,
|
||||||
|
paddingBottom: 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
palette: theme.palette,
|
||||||
|
customShadows: themeCustomShadows,
|
||||||
|
typography: themeTypography
|
||||||
|
}),
|
||||||
|
[theme, themeTypography, themeCustomShadows]
|
||||||
|
);
|
||||||
|
|
||||||
|
const themes = createTheme(themeOptions);
|
||||||
|
themes.components = componentsOverride(themes);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledEngineProvider injectFirst>
|
||||||
|
<ThemeProvider theme={themes}>
|
||||||
|
<CssBaseline />
|
||||||
|
{children}
|
||||||
|
</ThemeProvider>
|
||||||
|
</StyledEngineProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ThemeCustomization.propTypes = {
|
||||||
|
children: PropTypes.node
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
// ==============================|| OVERRIDES - BADGE ||============================== //
|
||||||
|
|
||||||
|
export default function Badge(theme) {
|
||||||
|
return {
|
||||||
|
MuiBadge: {
|
||||||
|
styleOverrides: {
|
||||||
|
standard: {
|
||||||
|
minWidth: theme.spacing(2),
|
||||||
|
height: theme.spacing(2),
|
||||||
|
padding: theme.spacing(0.5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
// ==============================|| OVERRIDES - BUTTON ||============================== //
|
||||||
|
|
||||||
|
export default function Button(theme) {
|
||||||
|
const disabledStyle = {
|
||||||
|
'&.Mui-disabled': {
|
||||||
|
backgroundColor: theme.palette.grey[200]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
MuiButton: {
|
||||||
|
defaultProps: {
|
||||||
|
disableElevation: true
|
||||||
|
},
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
fontWeight: 400
|
||||||
|
},
|
||||||
|
contained: {
|
||||||
|
...disabledStyle
|
||||||
|
},
|
||||||
|
outlined: {
|
||||||
|
...disabledStyle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
// ==============================|| OVERRIDES - CARD CONTENT ||============================== //
|
||||||
|
|
||||||
|
export default function CardContent() {
|
||||||
|
return {
|
||||||
|
MuiCardContent: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
padding: 20,
|
||||||
|
'&:last-child': {
|
||||||
|
paddingBottom: 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
// ==============================|| OVERRIDES - CHECKBOX ||============================== //
|
||||||
|
|
||||||
|
export default function Checkbox(theme) {
|
||||||
|
return {
|
||||||
|
MuiCheckbox: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
color: theme.palette.secondary[300]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
// ==============================|| OVERRIDES - CHIP ||============================== //
|
||||||
|
|
||||||
|
export default function Chip(theme) {
|
||||||
|
return {
|
||||||
|
MuiChip: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
borderRadius: 4,
|
||||||
|
'&:active': {
|
||||||
|
boxShadow: 'none'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sizeLarge: {
|
||||||
|
fontSize: '1rem',
|
||||||
|
height: 40
|
||||||
|
},
|
||||||
|
light: {
|
||||||
|
color: theme.palette.primary.main,
|
||||||
|
backgroundColor: theme.palette.primary.lighter,
|
||||||
|
borderColor: theme.palette.primary.light,
|
||||||
|
'&.MuiChip-lightError': {
|
||||||
|
color: theme.palette.error.main,
|
||||||
|
backgroundColor: theme.palette.error.lighter,
|
||||||
|
borderColor: theme.palette.error.light
|
||||||
|
},
|
||||||
|
'&.MuiChip-lightSuccess': {
|
||||||
|
color: theme.palette.success.main,
|
||||||
|
backgroundColor: theme.palette.success.lighter,
|
||||||
|
borderColor: theme.palette.success.light
|
||||||
|
},
|
||||||
|
'&.MuiChip-lightWarning': {
|
||||||
|
color: theme.palette.warning.main,
|
||||||
|
backgroundColor: theme.palette.warning.lighter,
|
||||||
|
borderColor: theme.palette.warning.light
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
// ==============================|| OVERRIDES - ICON BUTTON ||============================== //
|
||||||
|
|
||||||
|
export default function IconButton(theme) {
|
||||||
|
return {
|
||||||
|
MuiIconButton: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
borderRadius: 4
|
||||||
|
},
|
||||||
|
sizeLarge: {
|
||||||
|
width: theme.spacing(5.5),
|
||||||
|
height: theme.spacing(5.5),
|
||||||
|
fontSize: '1.25rem'
|
||||||
|
},
|
||||||
|
sizeMedium: {
|
||||||
|
width: theme.spacing(4.5),
|
||||||
|
height: theme.spacing(4.5),
|
||||||
|
fontSize: '1rem'
|
||||||
|
},
|
||||||
|
sizeSmall: {
|
||||||
|
width: theme.spacing(3.75),
|
||||||
|
height: theme.spacing(3.75),
|
||||||
|
fontSize: '0.75rem'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
// ==============================|| OVERRIDES - INPUT LABEL ||============================== //
|
||||||
|
|
||||||
|
export default function InputLabel(theme) {
|
||||||
|
return {
|
||||||
|
MuiInputLabel: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
color: theme.palette.grey[600]
|
||||||
|
},
|
||||||
|
outlined: {
|
||||||
|
lineHeight: '0.8em',
|
||||||
|
'&.MuiInputLabel-sizeSmall': {
|
||||||
|
lineHeight: '1em'
|
||||||
|
},
|
||||||
|
'&.MuiInputLabel-shrink': {
|
||||||
|
background: theme.palette.background.paper,
|
||||||
|
padding: '0 8px',
|
||||||
|
marginLeft: -6,
|
||||||
|
lineHeight: '1.4375em'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
// ==============================|| OVERRIDES - LINER PROGRESS ||============================== //
|
||||||
|
|
||||||
|
export default function LinearProgress() {
|
||||||
|
return {
|
||||||
|
MuiLinearProgress: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
height: 6,
|
||||||
|
borderRadius: 100
|
||||||
|
},
|
||||||
|
bar: {
|
||||||
|
borderRadius: 100
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
// ==============================|| OVERRIDES - LINK ||============================== //
|
||||||
|
|
||||||
|
export default function Link() {
|
||||||
|
return {
|
||||||
|
MuiLink: {
|
||||||
|
defaultProps: {
|
||||||
|
underline: 'hover'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
// ==============================|| OVERRIDES - LIST ITEM ICON ||============================== //
|
||||||
|
|
||||||
|
export default function ListItemIcon() {
|
||||||
|
return {
|
||||||
|
MuiListItemIcon: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
minWidth: 24
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
// material-ui
|
||||||
|
import { alpha } from '@mui/material/styles';
|
||||||
|
|
||||||
|
// ==============================|| OVERRIDES - OUTLINED INPUT ||============================== //
|
||||||
|
|
||||||
|
export default function OutlinedInput(theme) {
|
||||||
|
return {
|
||||||
|
MuiOutlinedInput: {
|
||||||
|
styleOverrides: {
|
||||||
|
input: {
|
||||||
|
padding: '10.5px 14px 10.5px 12px'
|
||||||
|
},
|
||||||
|
notchedOutline: {
|
||||||
|
borderColor: theme.palette.grey[300]
|
||||||
|
},
|
||||||
|
root: {
|
||||||
|
'&:hover .MuiOutlinedInput-notchedOutline': {
|
||||||
|
borderColor: theme.palette.primary.light
|
||||||
|
},
|
||||||
|
'&.Mui-focused': {
|
||||||
|
boxShadow: `0 0 0 2px ${alpha(theme.palette.primary.main, 0.2)}`,
|
||||||
|
'& .MuiOutlinedInput-notchedOutline': {
|
||||||
|
border: `1px solid ${theme.palette.primary.light}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'&.Mui-error': {
|
||||||
|
'&:hover .MuiOutlinedInput-notchedOutline': {
|
||||||
|
borderColor: theme.palette.error.light
|
||||||
|
},
|
||||||
|
'&.Mui-focused': {
|
||||||
|
boxShadow: `0 0 0 2px ${alpha(theme.palette.error.main, 0.2)}`,
|
||||||
|
'& .MuiOutlinedInput-notchedOutline': {
|
||||||
|
border: `1px solid ${theme.palette.error.light}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
inputSizeSmall: {
|
||||||
|
padding: '7.5px 8px 7.5px 12px'
|
||||||
|
},
|
||||||
|
inputMultiline: {
|
||||||
|
padding: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
// ==============================|| OVERRIDES - TAB ||============================== //
|
||||||
|
|
||||||
|
export default function Tab(theme) {
|
||||||
|
return {
|
||||||
|
MuiTab: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
minHeight: 46,
|
||||||
|
color: theme.palette.text.primary
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
// ==============================|| OVERRIDES - TABLE CELL ||============================== //
|
||||||
|
|
||||||
|
export default function TableCell(theme) {
|
||||||
|
return {
|
||||||
|
MuiTableCell: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
fontSize: '0.875rem',
|
||||||
|
padding: 12,
|
||||||
|
borderColor: theme.palette.divider
|
||||||
|
},
|
||||||
|
head: {
|
||||||
|
fontWeight: 600,
|
||||||
|
paddingTop: 20,
|
||||||
|
paddingBottom: 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
// ==============================|| OVERRIDES - TABS ||============================== //
|
||||||
|
|
||||||
|
export default function Tabs() {
|
||||||
|
return {
|
||||||
|
MuiTabs: {
|
||||||
|
styleOverrides: {
|
||||||
|
vertical: {
|
||||||
|
overflow: 'visible'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
// ==============================|| OVERRIDES - TYPOGRAPHY ||============================== //
|
||||||
|
|
||||||
|
export default function Typography() {
|
||||||
|
return {
|
||||||
|
MuiTypography: {
|
||||||
|
styleOverrides: {
|
||||||
|
gutterBottom: {
|
||||||
|
marginBottom: 12
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
// third-party
|
||||||
|
import { merge } from 'lodash';
|
||||||
|
|
||||||
|
// project import
|
||||||
|
import Badge from './Badge';
|
||||||
|
import Button from './Button';
|
||||||
|
import CardContent from './CardContent';
|
||||||
|
import Checkbox from './Checkbox';
|
||||||
|
import Chip from './Chip';
|
||||||
|
import IconButton from './IconButton';
|
||||||
|
import InputLabel from './InputLabel';
|
||||||
|
import LinearProgress from './LinearProgress';
|
||||||
|
import Link from './Link';
|
||||||
|
import ListItemIcon from './ListItemIcon';
|
||||||
|
import OutlinedInput from './OutlinedInput';
|
||||||
|
import Tab from './Tab';
|
||||||
|
import TableCell from './TableCell';
|
||||||
|
import Tabs from './Tabs';
|
||||||
|
import Typography from './Typography';
|
||||||
|
|
||||||
|
// ==============================|| OVERRIDES - MAIN ||============================== //
|
||||||
|
|
||||||
|
export default function ComponentsOverrides(theme) {
|
||||||
|
return merge(
|
||||||
|
Button(theme),
|
||||||
|
Badge(theme),
|
||||||
|
CardContent(),
|
||||||
|
Checkbox(theme),
|
||||||
|
Chip(theme),
|
||||||
|
IconButton(theme),
|
||||||
|
InputLabel(theme),
|
||||||
|
LinearProgress(),
|
||||||
|
Link(),
|
||||||
|
ListItemIcon(),
|
||||||
|
OutlinedInput(theme),
|
||||||
|
Tab(theme),
|
||||||
|
TableCell(theme),
|
||||||
|
Tabs(),
|
||||||
|
Typography()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
// material-ui
|
||||||
|
import { createTheme } from '@mui/material/styles';
|
||||||
|
|
||||||
|
// third-party
|
||||||
|
import { presetPalettes } from '@ant-design/colors';
|
||||||
|
|
||||||
|
// project import
|
||||||
|
import ThemeOption from './theme';
|
||||||
|
|
||||||
|
// ==============================|| DEFAULT THEME - PALETTE ||============================== //
|
||||||
|
|
||||||
|
const Palette = (mode) => {
|
||||||
|
const colors = presetPalettes;
|
||||||
|
|
||||||
|
const greyPrimary = [
|
||||||
|
'#ffffff',
|
||||||
|
'#fafafa',
|
||||||
|
'#f5f5f5',
|
||||||
|
'#f0f0f0',
|
||||||
|
'#d9d9d9',
|
||||||
|
'#bfbfbf',
|
||||||
|
'#8c8c8c',
|
||||||
|
'#595959',
|
||||||
|
'#262626',
|
||||||
|
'#141414',
|
||||||
|
'#000000'
|
||||||
|
];
|
||||||
|
const greyAscent = ['#fafafa', '#bfbfbf', '#434343', '#1f1f1f'];
|
||||||
|
const greyConstant = ['#fafafb', '#e6ebf1'];
|
||||||
|
|
||||||
|
colors.grey = [...greyPrimary, ...greyAscent, ...greyConstant];
|
||||||
|
|
||||||
|
const paletteColor = ThemeOption(colors);
|
||||||
|
|
||||||
|
return createTheme({
|
||||||
|
palette: {
|
||||||
|
mode,
|
||||||
|
common: {
|
||||||
|
black: '#000',
|
||||||
|
white: '#fff'
|
||||||
|
},
|
||||||
|
...paletteColor,
|
||||||
|
text: {
|
||||||
|
primary: paletteColor.grey[700],
|
||||||
|
secondary: paletteColor.grey[500],
|
||||||
|
disabled: paletteColor.grey[400]
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
disabled: paletteColor.grey[300]
|
||||||
|
},
|
||||||
|
divider: paletteColor.grey[200],
|
||||||
|
background: {
|
||||||
|
paper: paletteColor.grey[0],
|
||||||
|
// default: paletteColor.grey.A50 // 뒷배경 색이 깔려서 주석처리함
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Palette;
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
// material-ui
|
||||||
|
import { alpha } from '@mui/material/styles';
|
||||||
|
|
||||||
|
// ==============================|| DEFAULT THEME - CUSTOM SHADOWS ||============================== //
|
||||||
|
|
||||||
|
const CustomShadows = (theme) => ({
|
||||||
|
button: `0 2px #0000000b`,
|
||||||
|
text: `0 -1px 0 rgb(0 0 0 / 12%)`,
|
||||||
|
z1: `0px 2px 8px ${alpha(theme.palette.grey[900], 0.15)}`
|
||||||
|
// only available in paid version
|
||||||
|
});
|
||||||
|
|
||||||
|
export default CustomShadows;
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
// ==============================|| PRESET THEME - THEME SELECTOR ||============================== //
|
||||||
|
|
||||||
|
const Theme = (colors) => {
|
||||||
|
const { blue, red, gold, cyan, green, grey } = colors;
|
||||||
|
const greyColors = {
|
||||||
|
0: grey[0],
|
||||||
|
50: grey[1],
|
||||||
|
100: grey[2],
|
||||||
|
200: grey[3],
|
||||||
|
300: grey[4],
|
||||||
|
400: grey[5],
|
||||||
|
500: grey[6],
|
||||||
|
600: grey[7],
|
||||||
|
700: grey[8],
|
||||||
|
800: grey[9],
|
||||||
|
900: grey[10],
|
||||||
|
A50: grey[15],
|
||||||
|
A100: grey[11],
|
||||||
|
A200: grey[12],
|
||||||
|
A400: grey[13],
|
||||||
|
A700: grey[14],
|
||||||
|
A800: grey[16]
|
||||||
|
};
|
||||||
|
const contrastText = '#fff';
|
||||||
|
|
||||||
|
return {
|
||||||
|
primary: {
|
||||||
|
lighter: blue[0],
|
||||||
|
100: blue[1],
|
||||||
|
200: blue[2],
|
||||||
|
light: blue[3],
|
||||||
|
400: blue[4],
|
||||||
|
main: blue[5],
|
||||||
|
dark: blue[6],
|
||||||
|
700: blue[7],
|
||||||
|
darker: blue[8],
|
||||||
|
900: blue[9],
|
||||||
|
contrastText
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
lighter: greyColors[100],
|
||||||
|
100: greyColors[100],
|
||||||
|
200: greyColors[200],
|
||||||
|
light: greyColors[300],
|
||||||
|
400: greyColors[400],
|
||||||
|
main: greyColors[500],
|
||||||
|
600: greyColors[600],
|
||||||
|
dark: greyColors[700],
|
||||||
|
800: greyColors[800],
|
||||||
|
darker: greyColors[900],
|
||||||
|
A100: greyColors[0],
|
||||||
|
A200: greyColors.A400,
|
||||||
|
A300: greyColors.A700,
|
||||||
|
contrastText: greyColors[0]
|
||||||
|
},
|
||||||
|
error: {
|
||||||
|
lighter: red[0],
|
||||||
|
light: red[2],
|
||||||
|
main: red[4],
|
||||||
|
dark: red[7],
|
||||||
|
darker: red[9],
|
||||||
|
contrastText
|
||||||
|
},
|
||||||
|
warning: {
|
||||||
|
lighter: gold[0],
|
||||||
|
light: gold[3],
|
||||||
|
main: gold[5],
|
||||||
|
dark: gold[7],
|
||||||
|
darker: gold[9],
|
||||||
|
contrastText: greyColors[100]
|
||||||
|
},
|
||||||
|
info: {
|
||||||
|
lighter: cyan[0],
|
||||||
|
light: cyan[3],
|
||||||
|
main: cyan[5],
|
||||||
|
dark: cyan[7],
|
||||||
|
darker: cyan[9],
|
||||||
|
contrastText
|
||||||
|
},
|
||||||
|
success: {
|
||||||
|
lighter: green[0],
|
||||||
|
light: green[3],
|
||||||
|
main: green[5],
|
||||||
|
dark: green[7],
|
||||||
|
darker: green[9],
|
||||||
|
contrastText
|
||||||
|
},
|
||||||
|
grey: greyColors
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Theme;
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
// ==============================|| DEFAULT THEME - TYPOGRAPHY ||============================== //
|
||||||
|
|
||||||
|
const Typography = (fontFamily) => ({
|
||||||
|
htmlFontSize: 16,
|
||||||
|
fontFamily,
|
||||||
|
fontWeightLight: 300,
|
||||||
|
fontWeightRegular: 400,
|
||||||
|
fontWeightMedium: 500,
|
||||||
|
fontWeightBold: 600,
|
||||||
|
h1: {
|
||||||
|
fontWeight: 600,
|
||||||
|
fontSize: '2.375rem',
|
||||||
|
lineHeight: 1.21
|
||||||
|
},
|
||||||
|
h2: {
|
||||||
|
fontWeight: 600,
|
||||||
|
fontSize: '1.875rem',
|
||||||
|
lineHeight: 1.27
|
||||||
|
},
|
||||||
|
h3: {
|
||||||
|
fontWeight: 600,
|
||||||
|
fontSize: '1.5rem',
|
||||||
|
lineHeight: 1.33
|
||||||
|
},
|
||||||
|
h4: {
|
||||||
|
fontWeight: 600,
|
||||||
|
fontSize: '1.25rem',
|
||||||
|
lineHeight: 1.4
|
||||||
|
},
|
||||||
|
h5: {
|
||||||
|
fontWeight: 600,
|
||||||
|
fontSize: '1rem',
|
||||||
|
lineHeight: 1.5
|
||||||
|
},
|
||||||
|
h6: {
|
||||||
|
fontWeight: 400,
|
||||||
|
fontSize: '0.875rem',
|
||||||
|
lineHeight: 1.57
|
||||||
|
},
|
||||||
|
caption: {
|
||||||
|
fontWeight: 400,
|
||||||
|
fontSize: '0.75rem',
|
||||||
|
lineHeight: 1.66
|
||||||
|
},
|
||||||
|
body1: {
|
||||||
|
fontSize: '0.875rem',
|
||||||
|
lineHeight: 1.57
|
||||||
|
},
|
||||||
|
body2: {
|
||||||
|
fontSize: '0.75rem',
|
||||||
|
lineHeight: 1.66
|
||||||
|
},
|
||||||
|
subtitle1: {
|
||||||
|
fontSize: '0.875rem',
|
||||||
|
fontWeight: 600,
|
||||||
|
lineHeight: 1.57
|
||||||
|
},
|
||||||
|
subtitle2: {
|
||||||
|
fontSize: '0.75rem',
|
||||||
|
fontWeight: 500,
|
||||||
|
lineHeight: 1.66
|
||||||
|
},
|
||||||
|
overline: {
|
||||||
|
lineHeight: 1.66
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
textTransform: 'capitalize'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Typography;
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
// third-party
|
||||||
|
import SyntaxHighlighter from 'react-syntax-highlighter';
|
||||||
|
import { a11yDark } from 'react-syntax-highlighter/dist/esm/styles/hljs';
|
||||||
|
|
||||||
|
// ==============================|| CODE HIGHLIGHTER ||============================== //
|
||||||
|
|
||||||
|
export default function SyntaxHighlight({ children, ...others }) {
|
||||||
|
return (
|
||||||
|
<SyntaxHighlighter language="javacript" showLineNumbers style={a11yDark} {...others}>
|
||||||
|
{children}
|
||||||
|
</SyntaxHighlighter>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
SyntaxHighlight.propTypes = {
|
||||||
|
children: PropTypes.node
|
||||||
|
};
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,7 +1,11 @@
|
||||||
package com.dbnt.kcscbackend.admin.boards;
|
package com.dbnt.kcscbackend.admin.boards;
|
||||||
|
|
||||||
|
import com.dbnt.kcscbackend.admin.boards.entity.TnBbs;
|
||||||
import com.dbnt.kcscbackend.admin.boards.service.AdminBoardsService;
|
import com.dbnt.kcscbackend.admin.boards.service.AdminBoardsService;
|
||||||
|
import com.dbnt.kcscbackend.admin.config.entity.TcMenu;
|
||||||
|
import com.dbnt.kcscbackend.auth.entity.LoginVO;
|
||||||
import com.dbnt.kcscbackend.config.common.BaseController;
|
import com.dbnt.kcscbackend.config.common.BaseController;
|
||||||
|
import com.dbnt.kcscbackend.config.common.ResponseCode;
|
||||||
import com.dbnt.kcscbackend.config.common.ResultVO;
|
import com.dbnt.kcscbackend.config.common.ResultVO;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
|
|
@ -9,21 +13,27 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||||
|
import org.springframework.validation.Errors;
|
||||||
|
import org.springframework.validation.FieldError;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@RequestMapping("/admin/boards")
|
@RequestMapping("/admin/boards")
|
||||||
@Tag(name="AdminBoardsController", description = "사이트관리 게시판현황")
|
@Tag(name = "AdminBoardsController", description = "사이트관리 게시판현황")
|
||||||
public class AdminBoardsController extends BaseController {
|
public class AdminBoardsController extends BaseController {
|
||||||
|
|
||||||
private final AdminBoardsService adminBoardsService;
|
private final AdminBoardsService adminBoardsService;
|
||||||
|
|
||||||
|
/* ---- 게시판관리 ----- */
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "게시판 목록 조회",
|
summary = "게시판 목록 조회",
|
||||||
description = "게시판 목록 조회",
|
description = "게시판 목록 조회",
|
||||||
|
|
@ -42,4 +52,82 @@ public class AdminBoardsController extends BaseController {
|
||||||
resultVO.setResult(resultMap);
|
resultVO.setResult(resultMap);
|
||||||
return resultVO;
|
return resultVO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(
|
||||||
|
summary = "게시판 저장",
|
||||||
|
description = "게시판 저장",
|
||||||
|
tags = {"AdminBoardsController"}
|
||||||
|
)
|
||||||
|
@ApiResponses(value = {
|
||||||
|
@ApiResponse(responseCode = "200", description = "저장 성공"),
|
||||||
|
@ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
|
||||||
|
})
|
||||||
|
@RequestMapping(method = RequestMethod.PUT, value = "/board-mgt")
|
||||||
|
public ResultVO saveBoardMgt(@RequestBody @Valid TnBbs bbs, Errors errors, @AuthenticationPrincipal LoginVO user) {
|
||||||
|
ResultVO resultVO = new ResultVO();
|
||||||
|
if (user == null) {
|
||||||
|
resultVO.setResultCode(ResponseCode.TOKEN_EXPIRED.getCode());
|
||||||
|
} else {
|
||||||
|
if (errors.hasErrors()) {
|
||||||
|
StringBuilder msg = new StringBuilder();
|
||||||
|
for (FieldError error : errors.getFieldErrors()) {
|
||||||
|
msg.append(error.getDefaultMessage());
|
||||||
|
msg.append("\n");
|
||||||
|
}
|
||||||
|
resultVO.setResultCode(ResponseCode.INPUT_CHECK_ERROR.getCode());
|
||||||
|
resultVO.setResultMessage(msg.toString());
|
||||||
|
} else {
|
||||||
|
System.out.println("@@@ bbs.getBbsSeq() : " + bbs.getBbsSeq());
|
||||||
|
adminBoardsService.saveBoard(bbs, user.getId());
|
||||||
|
resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resultVO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(
|
||||||
|
summary = "게시판 삭제",
|
||||||
|
description = "게시판 삭제",
|
||||||
|
tags = {"AdminBoardsController"}
|
||||||
|
)
|
||||||
|
@ApiResponses(value = {
|
||||||
|
@ApiResponse(responseCode = "200", description = "삭제 성공"),
|
||||||
|
@ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
|
||||||
|
})
|
||||||
|
@RequestMapping(method = RequestMethod.DELETE, value = "/board-mgt")
|
||||||
|
public ResultVO removeBoardMgt(@RequestBody TnBbs bbs, @AuthenticationPrincipal LoginVO user) {
|
||||||
|
ResultVO resultVO = new ResultVO();
|
||||||
|
if (user == null) {
|
||||||
|
resultVO.setResultCode(ResponseCode.TOKEN_EXPIRED.getCode());
|
||||||
|
} else {
|
||||||
|
String result = adminBoardsService.deleteBoard(bbs, user.getId());
|
||||||
|
if (result == null) {
|
||||||
|
resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
|
||||||
|
} else if (result.equals("notFind")) {
|
||||||
|
resultVO.setResultCode(ResponseCode.SAVE_ERROR.getCode());
|
||||||
|
resultVO.setResultMessage("대상이 존재하지 않습니다.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resultVO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- 게시물관리 ----- */
|
||||||
|
@Operation(
|
||||||
|
summary = "게시물 목록 조회",
|
||||||
|
description = "게시물 목록 조회",
|
||||||
|
tags = {"AdminBoardsController"}
|
||||||
|
)
|
||||||
|
@ApiResponses(value = {
|
||||||
|
@ApiResponse(responseCode = "200", description = "조회 성공"),
|
||||||
|
@ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
|
||||||
|
})
|
||||||
|
@RequestMapping(method = RequestMethod.GET, value = "/post-list", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
public ResultVO getPostList() throws Exception {
|
||||||
|
ResultVO resultVO = new ResultVO();
|
||||||
|
Map<String, Object> resultMap = new HashMap<>();
|
||||||
|
|
||||||
|
resultMap.put("boardList", adminBoardsService.selectBoardList());
|
||||||
|
resultVO.setResult(resultMap);
|
||||||
|
return resultVO;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ import org.hibernate.annotations.DynamicInsert;
|
||||||
import org.hibernate.annotations.DynamicUpdate;
|
import org.hibernate.annotations.DynamicUpdate;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import java.time.LocalDate;
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
|
|
@ -22,22 +23,25 @@ public class TnBbs {
|
||||||
private Long bbsSeq;
|
private Long bbsSeq;
|
||||||
|
|
||||||
@Column(name = "bbs_id", nullable = false)
|
@Column(name = "bbs_id", nullable = false)
|
||||||
|
@NotBlank(message = "게시판 ID를 입력해주세요.")
|
||||||
private String bbsId;
|
private String bbsId;
|
||||||
|
|
||||||
@Column(name = "bbs_title", nullable = false)
|
@Column(name = "bbs_title", nullable = false)
|
||||||
|
@NotBlank(message = "게시판 이름을 입력해주세요.")
|
||||||
private String bbsTitle;
|
private String bbsTitle;
|
||||||
|
|
||||||
@Column(name = "bbs_desc")
|
@Column(name = "bbs_desc")
|
||||||
|
@NotBlank(message = "게시판 설명을 입력해주세요.")
|
||||||
private String bbsDesc;
|
private String bbsDesc;
|
||||||
|
|
||||||
@Column(name = "bbs_type")
|
@Column(name = "bbs_type")
|
||||||
private String bbsType;
|
private String bbsType;
|
||||||
|
|
||||||
@Column(name = "bbs_ans_yn", nullable = false)
|
@Column(name = "bbs_ans_yn", nullable = false)
|
||||||
private char bbsAnsYn;
|
private String bbsAnsYn;
|
||||||
|
|
||||||
@Column(name = "bbs_repl_yn", nullable = false)
|
@Column(name = "bbs_repl_yn", nullable = false)
|
||||||
private char bbsReplYn;
|
private String bbsReplYn;
|
||||||
|
|
||||||
@Column(name = "read_role_grp_id")
|
@Column(name = "read_role_grp_id")
|
||||||
private String readRoleGrpId;
|
private String readRoleGrpId;
|
||||||
|
|
@ -52,16 +56,16 @@ public class TnBbs {
|
||||||
private String frstCrtId;
|
private String frstCrtId;
|
||||||
|
|
||||||
@Column(name = "frst_crt_dt", nullable = false)
|
@Column(name = "frst_crt_dt", nullable = false)
|
||||||
private LocalDate frstCrtDt;
|
private LocalDateTime frstCrtDt;
|
||||||
|
|
||||||
@Column(name = "last_chg_id")
|
@Column(name = "last_chg_id")
|
||||||
private String lastChgId;
|
private String lastChgId;
|
||||||
|
|
||||||
@Column(name = "last_chg_dt")
|
@Column(name = "last_chg_dt")
|
||||||
private LocalDate lastChgDt;
|
private LocalDateTime lastChgDt;
|
||||||
|
|
||||||
@Column(name = "use_yn", nullable = false)
|
@Column(name = "use_yn", nullable = false)
|
||||||
private char useYn;
|
private String useYn;
|
||||||
|
|
||||||
@Column(name = "oldd_seq")
|
@Column(name = "oldd_seq")
|
||||||
private Long olddSeq;
|
private Long olddSeq;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
package com.dbnt.kcscbackend.admin.boards.entity;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.hibernate.annotations.DynamicInsert;
|
||||||
|
import org.hibernate.annotations.DynamicUpdate;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Entity
|
||||||
|
@NoArgsConstructor
|
||||||
|
@DynamicInsert
|
||||||
|
@DynamicUpdate
|
||||||
|
@Table(name = "tn_bbs_contents")
|
||||||
|
public class TnBbsContents {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
@Column(name = "bbs_cont_seq")
|
||||||
|
private Integer bbsContSeq;
|
||||||
|
|
||||||
|
@Column(name = "bbs_seq", nullable = false)
|
||||||
|
private Integer bbsSeq;
|
||||||
|
|
||||||
|
@Column(name = "bbs_cont_title")
|
||||||
|
private String bbsContTitle;
|
||||||
|
|
||||||
|
@Column(name = "bbs_contents", columnDefinition = "TEXT")
|
||||||
|
private String bbsContents;
|
||||||
|
|
||||||
|
@Column(name = "bbs_cont_seq_group")
|
||||||
|
private Integer bbsContSeqGroup;
|
||||||
|
|
||||||
|
@Column(name = "bbs_cont_seq_parent")
|
||||||
|
private Integer bbsContSeqParent;
|
||||||
|
|
||||||
|
@Column(name = "bbs_cont_level", nullable = false)
|
||||||
|
private Integer bbsContLevel;
|
||||||
|
|
||||||
|
@Column(name = "bbs_cont_sort")
|
||||||
|
private Integer bbsContSort;
|
||||||
|
|
||||||
|
@Column(name = "file_grp_id")
|
||||||
|
private String fileGrpId;
|
||||||
|
|
||||||
|
@Column(name = "bbs_read_cnt", nullable = false)
|
||||||
|
private Integer bbsReadCnt;
|
||||||
|
|
||||||
|
@Column(name = "fixed_yn", nullable = false)
|
||||||
|
private String fixedYn;
|
||||||
|
|
||||||
|
@Column(name = "secret_yn", nullable = false)
|
||||||
|
private String secretYn;
|
||||||
|
|
||||||
|
@Column(name = "secret_pwd")
|
||||||
|
private String secretPwd;
|
||||||
|
|
||||||
|
@Column(name = "doc_info_seq")
|
||||||
|
private Integer docInfoSeq;
|
||||||
|
|
||||||
|
@Column(name = "ip_address", nullable = false)
|
||||||
|
private String ipAddress;
|
||||||
|
|
||||||
|
@Column(name = "frst_crt_id", nullable = false)
|
||||||
|
private String frstCrtId;
|
||||||
|
|
||||||
|
@Column(name = "frst_crt_dt", nullable = false)
|
||||||
|
private LocalDateTime frstCrtDt;
|
||||||
|
|
||||||
|
@Column(name = "last_chg_id")
|
||||||
|
private String lastChgId;
|
||||||
|
|
||||||
|
@Column(name = "last_chg_dt")
|
||||||
|
private LocalDateTime lastChgDt;
|
||||||
|
|
||||||
|
@Column(name = "use_yn", nullable = false)
|
||||||
|
private String useYn;
|
||||||
|
|
||||||
|
@Column(name = "old_seq")
|
||||||
|
private Integer oldSeq;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.dbnt.kcscbackend.admin.boards.repository;
|
||||||
|
|
||||||
|
import com.dbnt.kcscbackend.admin.boards.entity.TnBbsContents;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface TnBbsContentsRepository extends JpaRepository<TnBbsContents, Long> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,13 @@ package com.dbnt.kcscbackend.admin.boards.repository;
|
||||||
|
|
||||||
import com.dbnt.kcscbackend.admin.boards.entity.TnBbs;
|
import com.dbnt.kcscbackend.admin.boards.entity.TnBbs;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface TnBbsRepository extends JpaRepository<TnBbs, Long> {
|
public interface TnBbsRepository extends JpaRepository<TnBbs, Long> {
|
||||||
|
|
||||||
|
@Query(value = "SELECT * FROM tn_bbs WHERE use_yn = 'Y' ORDER BY bbs_seq DESC", nativeQuery = true)
|
||||||
|
List<TnBbs> findAllByOrderByBbsSeqDesc();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,71 @@
|
||||||
package com.dbnt.kcscbackend.admin.boards.service;
|
package com.dbnt.kcscbackend.admin.boards.service;
|
||||||
|
|
||||||
import com.dbnt.kcscbackend.admin.boards.entity.TnBbs;
|
import com.dbnt.kcscbackend.admin.boards.entity.TnBbs;
|
||||||
|
import com.dbnt.kcscbackend.admin.boards.entity.TnBbsContents;
|
||||||
|
import com.dbnt.kcscbackend.admin.boards.repository.TnBbsContentsRepository;
|
||||||
import com.dbnt.kcscbackend.admin.boards.repository.TnBbsRepository;
|
import com.dbnt.kcscbackend.admin.boards.repository.TnBbsRepository;
|
||||||
|
import com.dbnt.kcscbackend.admin.config.entity.TcMenu;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
|
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class AdminBoardsService extends EgovAbstractServiceImpl {
|
public class AdminBoardsService extends EgovAbstractServiceImpl {
|
||||||
|
|
||||||
private final TnBbsRepository tnBbsRepository;
|
private final TnBbsRepository tnBbsRepository;
|
||||||
|
private final TnBbsContentsRepository tnBbsContentsRepository;
|
||||||
|
|
||||||
public List<TnBbs> selectBoardList() { return tnBbsRepository.findAll(); }
|
public List<TnBbs> selectBoardList() {
|
||||||
|
return tnBbsRepository.findAllByOrderByBbsSeqDesc();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<TnBbs> selectBoard(Long bbsSeq) {
|
||||||
|
return tnBbsRepository.findById(bbsSeq);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void saveBoard(TnBbs bbs, String userId) {
|
||||||
|
if (bbs.getBbsSeq() == null) {
|
||||||
|
bbs.setFrstCrtDt(LocalDateTime.now());
|
||||||
|
bbs.setFrstCrtId(userId);
|
||||||
|
bbs.setBbsAnsYn("N");
|
||||||
|
bbs.setBbsReplYn("N");
|
||||||
|
bbs.setUseYn("Y");
|
||||||
|
tnBbsRepository.save(bbs);
|
||||||
|
} else {
|
||||||
|
TnBbs savedBoard = tnBbsRepository.findById(bbs.getBbsSeq()).orElse(null);
|
||||||
|
savedBoard.setBbsId(bbs.getBbsId());
|
||||||
|
savedBoard.setBbsTitle(bbs.getBbsTitle());
|
||||||
|
savedBoard.setBbsDesc(bbs.getBbsDesc());
|
||||||
|
//savedBoard.setUseYn("Y");
|
||||||
|
savedBoard.setLastChgId(userId);
|
||||||
|
savedBoard.setLastChgDt(LocalDateTime.now());
|
||||||
|
tnBbsRepository.save(savedBoard);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public String deleteBoard(TnBbs bbs, String userId) {
|
||||||
|
TnBbs savedBoard = tnBbsRepository.findById(bbs.getBbsSeq()).orElse(null);
|
||||||
|
if (savedBoard == null) {
|
||||||
|
return "notFind";
|
||||||
|
} else {
|
||||||
|
savedBoard.setUseYn("N");
|
||||||
|
savedBoard.setLastChgDt(LocalDateTime.now());
|
||||||
|
savedBoard.setLastChgId(userId);
|
||||||
|
tnBbsRepository.save(savedBoard);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TnBbsContents> selectPostList() {
|
||||||
|
return tnBbsContentsRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package com.dbnt.kcscbackend.admin.config;
|
package com.dbnt.kcscbackend.admin.config;
|
||||||
|
|
||||||
import com.dbnt.kcscbackend.admin.config.entity.TcMenu;
|
import com.dbnt.kcscbackend.admin.config.entity.TcMenu;
|
||||||
|
import com.dbnt.kcscbackend.admin.config.service.AdminCommitteeCodeManagementService;
|
||||||
|
import com.dbnt.kcscbackend.admin.standardResearch.service.AdminStandardResearchService;
|
||||||
import com.dbnt.kcscbackend.commonCode.entity.TcCodeGrp;
|
import com.dbnt.kcscbackend.commonCode.entity.TcCodeGrp;
|
||||||
import com.dbnt.kcscbackend.commonCode.entity.TcCodeItem;
|
import com.dbnt.kcscbackend.commonCode.entity.TcCodeItem;
|
||||||
import com.dbnt.kcscbackend.admin.config.service.AdminConfigService;
|
import com.dbnt.kcscbackend.admin.config.service.AdminConfigService;
|
||||||
|
|
@ -9,20 +11,21 @@ import com.dbnt.kcscbackend.commonCode.service.CommonCodeService;
|
||||||
import com.dbnt.kcscbackend.config.common.BaseController;
|
import com.dbnt.kcscbackend.config.common.BaseController;
|
||||||
import com.dbnt.kcscbackend.config.common.ResponseCode;
|
import com.dbnt.kcscbackend.config.common.ResponseCode;
|
||||||
import com.dbnt.kcscbackend.config.common.ResultVO;
|
import com.dbnt.kcscbackend.config.common.ResultVO;
|
||||||
|
import io.swagger.annotations.ApiParam;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||||
import org.springframework.validation.Errors;
|
import org.springframework.validation.Errors;
|
||||||
import org.springframework.validation.FieldError;
|
import org.springframework.validation.FieldError;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
@ -37,6 +40,9 @@ public class AdminConfigController extends BaseController {
|
||||||
private final AdminConfigService adminConfigService;
|
private final AdminConfigService adminConfigService;
|
||||||
private final CommonCodeService commonCodeService;
|
private final CommonCodeService commonCodeService;
|
||||||
|
|
||||||
|
@Resource(name = "adminCommitteeCodeManagementService")
|
||||||
|
private AdminCommitteeCodeManagementService adminCommitteeCodeManagementService;
|
||||||
|
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "기본코드 그룹 조회",
|
summary = "기본코드 그룹 조회",
|
||||||
description = "기본코드 그룹 조회",
|
description = "기본코드 그룹 조회",
|
||||||
|
|
@ -350,4 +356,50 @@ public class AdminConfigController extends BaseController {
|
||||||
return resultVO;
|
return resultVO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(
|
||||||
|
summary = "'위원회 코드 관리' 페이지에서 목록 불러오는 API",
|
||||||
|
description = "관리자 단에서 '환경설정' > '위원회코드 관리' 페이지에서 목록 불러오는 API",
|
||||||
|
tags = {"AdminConfigController"}
|
||||||
|
)
|
||||||
|
@ApiResponses(value = {
|
||||||
|
@ApiResponse(responseCode = "200", description = "조회 성공"),
|
||||||
|
@ApiResponse(responseCode = "303", description = "만료된 토큰"),
|
||||||
|
@ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
|
||||||
|
})
|
||||||
|
@GetMapping(value = "/committee-code-management")
|
||||||
|
public ResultVO getCommitteeCodeManagement(
|
||||||
|
@AuthenticationPrincipal LoginVO user,
|
||||||
|
HttpServletRequest request,
|
||||||
|
@ApiParam(value="상위 code") @RequestParam(required=true) String paramCodeGroup,
|
||||||
|
@ApiParam(value="code level") @RequestParam(required=true) String paramCodeLevel
|
||||||
|
) throws Exception {
|
||||||
|
|
||||||
|
ResultVO resultVO = new ResultVO();
|
||||||
|
if(user == null) {
|
||||||
|
resultVO.setResultCode(ResponseCode.TOKEN_EXPIRED.getCode());
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
Long upCmtSeq = null;
|
||||||
|
if (!paramCodeGroup.equals("null")) {
|
||||||
|
upCmtSeq = Long.parseLong(paramCodeGroup);
|
||||||
|
}
|
||||||
|
resultVO = adminCommitteeCodeManagementService.getCommitteeCodeManagement(resultVO, request, user, upCmtSeq, paramCodeLevel);
|
||||||
|
} catch (Exception e) {
|
||||||
|
resultVO.setResultCode(ResponseCode.FAILED.getCode());
|
||||||
|
resultVO.setResultMessage(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println(
|
||||||
|
"\n--------------------------------------------------------------\n" +
|
||||||
|
request.getRequestURI() + " OUT:" +
|
||||||
|
"\n--------------------------------------------------------------\n" +
|
||||||
|
"resultVO.toString():" + "\n" +
|
||||||
|
resultVO.toString() + "\n" +
|
||||||
|
"\n--------------------------------------------------------------\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
return resultVO;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.dbnt.kcscbackend.admin.config.service;
|
||||||
|
|
||||||
|
import com.dbnt.kcscbackend.admin.standardResearch.model.CreateStandardResearchVO;
|
||||||
|
import com.dbnt.kcscbackend.admin.standardResearch.model.UpdateStandardResearchVO;
|
||||||
|
import com.dbnt.kcscbackend.auth.entity.LoginVO;
|
||||||
|
import com.dbnt.kcscbackend.config.common.ResultVO;
|
||||||
|
import io.swagger.annotations.ApiParam;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
public interface AdminCommitteeCodeManagementService {
|
||||||
|
public ResultVO createCommitteeCodeManagement(ResultVO resultVO, HttpServletRequest request, LoginVO user, final MultipartHttpServletRequest multiRequest, CreateStandardResearchVO createStandardResearchVO) throws Exception;
|
||||||
|
public ResultVO getCommitteeCodeManagement(ResultVO resultVO, HttpServletRequest request, LoginVO user, Long upCmtSeq, String cmtType) throws Exception;
|
||||||
|
public ResultVO setCommitteeCodeManagement(ResultVO resultVO, HttpServletRequest request, LoginVO user, UpdateStandardResearchVO updateStandardResearchVO, Long popupId) throws Exception;
|
||||||
|
public ResultVO deleteCommitteeCodeManagement(ResultVO resultVO, HttpServletRequest request, LoginVO user, Long popupId) throws Exception;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
package com.dbnt.kcscbackend.admin.config.service.impl;
|
||||||
|
|
||||||
|
import com.dbnt.kcscbackend.admin.config.service.AdminCommitteeCodeManagementService;
|
||||||
|
import com.dbnt.kcscbackend.admin.standardResearch.model.CreateStandardResearchVO;
|
||||||
|
import com.dbnt.kcscbackend.admin.standardResearch.model.UpdateStandardResearchVO;
|
||||||
|
import com.dbnt.kcscbackend.auth.entity.LoginVO;
|
||||||
|
import com.dbnt.kcscbackend.commonCode.repository.TnCmtOrgRepository;
|
||||||
|
import com.dbnt.kcscbackend.config.common.ResponseCode;
|
||||||
|
import com.dbnt.kcscbackend.config.common.ResultVO;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
|
||||||
|
import org.egovframe.rte.ptl.mvc.tags.ui.pagination.PaginationInfo;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Service("adminCommitteeCodeManagementService")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AdminCommitteeCodeManagementServiceImpl extends EgovAbstractServiceImpl implements AdminCommitteeCodeManagementService {
|
||||||
|
|
||||||
|
private final TnCmtOrgRepository tnCmtOrgRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultVO createCommitteeCodeManagement(ResultVO resultVO, HttpServletRequest request, LoginVO user, MultipartHttpServletRequest multiRequest, CreateStandardResearchVO createStandardResearchVO) throws Exception {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultVO getCommitteeCodeManagement(ResultVO resultVO, HttpServletRequest request, LoginVO user, Long upCmtSeq, String cmtType) throws Exception {
|
||||||
|
|
||||||
|
System.out.println(
|
||||||
|
"\n--------------------------------------------------------------\n" +
|
||||||
|
request.getRequestURI() + " IN:" +
|
||||||
|
"\n--------------------------------------------------------------\n" +
|
||||||
|
"user.getEmail():" + "\n" +
|
||||||
|
user.getEmail() + "\n" +
|
||||||
|
"\n--------------------------------------------------------------\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
List<Map<String, Object>> list = tnCmtOrgRepository.findByUseYnAndUpCmtSeqAndCmtTypeOrderByCmtOrder("Y", upCmtSeq, cmtType).stream()
|
||||||
|
.map(item -> {
|
||||||
|
Map<String, Object> returnMap = new HashMap<>();
|
||||||
|
returnMap.put("orgId", item.getCmtSeq());
|
||||||
|
returnMap.put("orgNm", item.getCmtNm());
|
||||||
|
returnMap.put("orgDesc", item.getCmtDesc());
|
||||||
|
return returnMap;
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
Map<String, Object> dto = new HashMap<String, Object>();
|
||||||
|
dto.put("list", list);
|
||||||
|
resultVO.setResult(dto);
|
||||||
|
resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
|
||||||
|
resultVO.setResultMessage(ResponseCode.SUCCESS.getMessage());
|
||||||
|
|
||||||
|
return resultVO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultVO setCommitteeCodeManagement(ResultVO resultVO, HttpServletRequest request, LoginVO user, UpdateStandardResearchVO updateStandardResearchVO, Long popupId) throws Exception {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResultVO deleteCommitteeCodeManagement(ResultVO resultVO, HttpServletRequest request, LoginVO user, Long popupId) throws Exception {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
package com.dbnt.kcscbackend.admin.dashboard;
|
package com.dbnt.kcscbackend.admin.dashboard;
|
||||||
|
|
||||||
import com.dbnt.kcscbackend.admin.dashboard.dto.MonthlyUserLogDTO;
|
//import com.dbnt.kcscbackend.admin.dashboard.dto.MonthlyUserLogDTO;
|
||||||
import com.dbnt.kcscbackend.admin.dashboard.service.AdminDashboardService;
|
import com.dbnt.kcscbackend.admin.dashboard.service.AdminDashboardService;
|
||||||
|
import com.dbnt.kcscbackend.auth.entity.LoginVO;
|
||||||
import com.dbnt.kcscbackend.config.common.BaseController;
|
import com.dbnt.kcscbackend.config.common.BaseController;
|
||||||
|
import com.dbnt.kcscbackend.config.common.ResponseCode;
|
||||||
import com.dbnt.kcscbackend.config.common.ResultVO;
|
import com.dbnt.kcscbackend.config.common.ResultVO;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
|
|
@ -10,6 +12,8 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.http.MediaType;
|
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.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
@ -30,57 +34,116 @@ public class AdminDashboardController extends BaseController {
|
||||||
private final AdminDashboardService adminDashboardService;
|
private final AdminDashboardService adminDashboardService;
|
||||||
|
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "일별 사용자 현황 차트 조회",
|
summary = "해당년도 메뉴/방문자수 월/요일별 조회",
|
||||||
description = "일별 사용자 현황 차트 조회",
|
description = "해당년도 메뉴/방문자수 월/요일별 조회",
|
||||||
tags = {"AdminDashboardController"}
|
tags = {"AdminDashboardController"}
|
||||||
)
|
)
|
||||||
@ApiResponses(value = {
|
@ApiResponses(value = {
|
||||||
@ApiResponse(responseCode = "200", description = "조회 성공"),
|
@ApiResponse(responseCode = "200", description = "조회 성공"),
|
||||||
@ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
|
@ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
|
||||||
})
|
})
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/daily-user-log-list", consumes = MediaType.APPLICATION_JSON_VALUE)
|
@RequestMapping(method = RequestMethod.POST, value = "/menu-login", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||||
public ResultVO getDailyUserLogList() throws Exception {
|
public ResultVO getMenuVisit(@AuthenticationPrincipal LoginVO user)
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
ResultVO resultVO = new ResultVO();
|
ResultVO resultVO = new ResultVO();
|
||||||
Map<String, Object> resultMap = new HashMap<>();
|
Map<String, Object> resultMap = new HashMap<>();
|
||||||
|
|
||||||
// 현재 날짜
|
resultMap.put("menuMonthlyList", adminDashboardService.selectMenuMonthly());
|
||||||
// todo endDate 뒤에 .minus 지워야함
|
resultMap.put("menuDailyList", adminDashboardService.selectMenuDaily());
|
||||||
LocalDate endDate = LocalDate.now().minusMonths(6);
|
resultMap.put("loginMonthlyList", adminDashboardService.selectLoginMonthly());
|
||||||
// 3개월 전 날짜 계산
|
resultMap.put("loginDailyList", adminDashboardService.selectLoginDaily());
|
||||||
LocalDate startDate = endDate.minusMonths(3);
|
|
||||||
|
|
||||||
resultMap.put("dailyUserLogList", adminDashboardService.selectDailyUserLogList(startDate, endDate));
|
resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
|
||||||
|
resultVO.setResultMessage(ResponseCode.SUCCESS.getMessage());
|
||||||
resultVO.setResult(resultMap);
|
resultVO.setResult(resultMap);
|
||||||
return resultVO;
|
return resultVO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "월별 사용자 현황 차트 조회",
|
summary = "이번주 다운로드 조회",
|
||||||
description = "월별 사용자 현황 차트 조회",
|
description = "이번주 다운로드 조회",
|
||||||
tags = {"AdminDashboardController"}
|
tags = {"AdminDashboardController"}
|
||||||
)
|
)
|
||||||
@ApiResponses(value = {
|
@ApiResponses(value = {
|
||||||
@ApiResponse(responseCode = "200", description = "조회 성공"),
|
@ApiResponse(responseCode = "200", description = "조회 성공"),
|
||||||
@ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
|
@ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
|
||||||
})
|
})
|
||||||
@RequestMapping(method = RequestMethod.GET, value = "/monthly-user-log-list", consumes = MediaType.APPLICATION_JSON_VALUE)
|
@RequestMapping(method = RequestMethod.POST, value = "/file", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||||
public ResultVO getMonthlyUserLogList() throws Exception {
|
public ResultVO getfile(@AuthenticationPrincipal LoginVO user)
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
ResultVO resultVO = new ResultVO();
|
ResultVO resultVO = new ResultVO();
|
||||||
Map<String, Object> resultMap = new HashMap<>();
|
Map<String, Object> resultMap = new HashMap<>();
|
||||||
|
|
||||||
// 현재 날짜
|
resultMap.put("fileDailyList", adminDashboardService.selectFileDaily());
|
||||||
// todo endDate 뒤에 .minus 지워야함
|
|
||||||
LocalDate endDate = LocalDate.now().minusMonths(6);
|
|
||||||
// 3개월 전 날짜 계산
|
|
||||||
LocalDate startDate = endDate.minusMonths(3);
|
|
||||||
|
|
||||||
List<Object[]> result = adminDashboardService.selectMonthlyUserLogList(startDate, endDate);
|
resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
|
||||||
List<MonthlyUserLogDTO> monthlyUserLogDTOList = result.stream()
|
resultVO.setResultMessage(ResponseCode.SUCCESS.getMessage());
|
||||||
.map(row -> new MonthlyUserLogDTO((String) row[0], (BigInteger) row[1]))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
resultMap.put("dailyUserLogList", monthlyUserLogDTOList);
|
|
||||||
resultVO.setResult(resultMap);
|
resultVO.setResult(resultMap);
|
||||||
return resultVO;
|
return resultVO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// @Operation(
|
||||||
|
// summary = "일별 사용자 현황 차트 조회",
|
||||||
|
// description = "일별 사용자 현황 차트 조회",
|
||||||
|
// tags = {"AdminDashboardController"}
|
||||||
|
// )
|
||||||
|
// @ApiResponses(value = {
|
||||||
|
// @ApiResponse(responseCode = "200", description = "조회 성공"),
|
||||||
|
// @ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
|
||||||
|
// })
|
||||||
|
// @RequestMapping(method = RequestMethod.GET, value = "/daily-user-log-list", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
// public ResultVO getDailyUserLogList() 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);
|
||||||
|
//
|
||||||
|
// resultMap.put("dailyUserLogList", adminDashboardService.selectDailyUserLogList(startDate, endDate));
|
||||||
|
// 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;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
package com.dbnt.kcscbackend.admin.dashboard.repository;
|
||||||
|
|
||||||
|
import com.dbnt.kcscbackend.admin.logs.entity.TnDailyMenuLog;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface MenuMonthlyRepository extends JpaRepository<TnDailyMenuLog, Long> {
|
||||||
|
|
||||||
|
@Query(value = "WITH all_months AS (" +
|
||||||
|
" SELECT generate_series(DATE_TRUNC('year', CURRENT_DATE), DATE_TRUNC('year', CURRENT_DATE) + INTERVAL '11 month', INTERVAL '1 month') AS month_start" +
|
||||||
|
")" +
|
||||||
|
"SELECT COALESCE(SUM(tn.log_cnt), 0) AS log_cnt " +
|
||||||
|
"FROM all_months " +
|
||||||
|
"LEFT JOIN tn_daily_menu_log tn ON TO_CHAR(all_months.month_start, 'yyyy-mm') = TO_CHAR(tn.log_dt, 'yyyy-mm') " +
|
||||||
|
"GROUP BY TO_CHAR(all_months.month_start, 'yyyy-mm') " +
|
||||||
|
"ORDER BY TO_CHAR(all_months.month_start, 'yyyy-mm') ASC", nativeQuery = true)
|
||||||
|
List<Long> MenuMonthlyList();
|
||||||
|
|
||||||
|
@Query(value = "WITH all_days AS (" +
|
||||||
|
" SELECT generate_series(" +
|
||||||
|
" DATE_TRUNC('year', now())," +
|
||||||
|
" DATE_TRUNC('year', now()) + INTERVAL '1 year' - INTERVAL '1 day'," +
|
||||||
|
" INTERVAL '1 day'" +
|
||||||
|
" ) AS day" +
|
||||||
|
")" +
|
||||||
|
"SELECT COALESCE(SUM(tn.log_cnt), 0) AS log_cnt " +
|
||||||
|
"FROM all_days ad " +
|
||||||
|
"LEFT JOIN tn_daily_menu_log tn ON ad.day = DATE_TRUNC('day', tn.log_dt) " +
|
||||||
|
"GROUP BY TO_CHAR(ad.day, 'Day') " +
|
||||||
|
"ORDER BY MIN(ad.day)", nativeQuery = true)
|
||||||
|
List<Long> MenuDailyList();
|
||||||
|
|
||||||
|
|
||||||
|
@Query(value = "WITH all_months AS (" +
|
||||||
|
" SELECT generate_series(" +
|
||||||
|
" DATE_TRUNC('year', now())," +
|
||||||
|
" DATE_TRUNC('year', now()) + INTERVAL '11 month'," +
|
||||||
|
" INTERVAL '1 month'" +
|
||||||
|
" ) AS month_start" +
|
||||||
|
")" +
|
||||||
|
"SELECT COALESCE(SUM(tn.log_cnt), 0) AS log_cnt " +
|
||||||
|
"FROM all_months " +
|
||||||
|
"LEFT JOIN tn_daily_user_log tn ON TO_CHAR(all_months.month_start, 'yyyy-mm') = TO_CHAR(tn.log_dt, 'yyyy-mm') " +
|
||||||
|
"GROUP BY TO_CHAR(all_months.month_start, 'yyyy-mm') " +
|
||||||
|
"ORDER BY TO_CHAR(all_months.month_start, 'yyyy-mm') ASC", nativeQuery = true)
|
||||||
|
List<Long> LoginMonthlyList();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Query(value = "WITH all_days AS (" +
|
||||||
|
" SELECT generate_series(" +
|
||||||
|
" DATE_TRUNC('year', CURRENT_DATE)," +
|
||||||
|
" DATE_TRUNC('year', CURRENT_DATE) + INTERVAL '1 year' - INTERVAL '1 day'," +
|
||||||
|
" INTERVAL '1 day'" +
|
||||||
|
" ) AS day" +
|
||||||
|
")" +
|
||||||
|
"SELECT COALESCE(SUM(tn.log_cnt), 0) AS log_cnt " +
|
||||||
|
"FROM all_days ad " +
|
||||||
|
"LEFT JOIN tn_daily_user_log tn ON ad.day = tn.log_dt " +
|
||||||
|
"GROUP BY TO_CHAR(ad.day, 'Day') " +
|
||||||
|
"ORDER BY MIN(ad.day)", nativeQuery = true)
|
||||||
|
List<Long> LoginDailyList();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Query(value = "WITH all_days AS (" +
|
||||||
|
" SELECT generate_series(" +
|
||||||
|
" DATE_TRUNC('year', CURRENT_DATE)," +
|
||||||
|
" DATE_TRUNC('year', CURRENT_DATE) + INTERVAL '1 year' - INTERVAL '1 day'," +
|
||||||
|
" INTERVAL '1 day'" +
|
||||||
|
" ) AS day" +
|
||||||
|
")" +
|
||||||
|
"SELECT COALESCE(COUNT(tn.access_dt), 0) AS log_cnt " +
|
||||||
|
"FROM all_days ad " +
|
||||||
|
"LEFT JOIN (SELECT access_dt FROM public.th_attach_file_log WHERE\n" +
|
||||||
|
" access_dt >= CURRENT_DATE - INTERVAL '6 day') tn ON ad.day = DATE_TRUNC('day', tn.access_dt) " +
|
||||||
|
"GROUP BY TO_CHAR(ad.day, 'Day') " +
|
||||||
|
"ORDER BY MIN(ad.day)", nativeQuery = true)
|
||||||
|
List<Long> FileDailyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,24 +1,38 @@
|
||||||
package com.dbnt.kcscbackend.admin.dashboard.service;
|
package com.dbnt.kcscbackend.admin.dashboard.service;
|
||||||
|
|
||||||
import com.dbnt.kcscbackend.admin.dashboard.entity.TnDailyUserLog;
|
//import com.dbnt.kcscbackend.admin.dashboard.entity.TnDailyUserLog;
|
||||||
import com.dbnt.kcscbackend.admin.dashboard.repository.TnDailyUserLogRepository;
|
import com.dbnt.kcscbackend.admin.dashboard.repository.MenuMonthlyRepository;
|
||||||
|
//import com.dbnt.kcscbackend.admin.dashboard.repository.TnDailyUserLogRepository;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
|
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
//import java.time.LocalDate;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class AdminDashboardService extends EgovAbstractServiceImpl {
|
public class AdminDashboardService extends EgovAbstractServiceImpl {
|
||||||
private final TnDailyUserLogRepository tnDailyUserLogRepository;
|
// private final TnDailyUserLogRepository tnDailyUserLogRepository;
|
||||||
|
private final MenuMonthlyRepository menuMonthlyRepository;
|
||||||
|
|
||||||
public List<TnDailyUserLog> selectDailyUserLogList(LocalDate startDate, LocalDate endDate) {
|
public List<Long> selectMenuMonthly() { return menuMonthlyRepository.MenuMonthlyList(); }
|
||||||
return tnDailyUserLogRepository.findByLogDtBetweenOrderByLogDt(startDate, endDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Object[]> selectMonthlyUserLogList(LocalDate startDate, LocalDate endDate) {
|
public List<Long> selectMenuDaily() { return menuMonthlyRepository.MenuDailyList(); }
|
||||||
return tnDailyUserLogRepository.selectMonthlyUserLogStatistics(startDate, endDate);
|
|
||||||
}
|
public List<Long> selectLoginMonthly() { return menuMonthlyRepository.LoginMonthlyList(); }
|
||||||
|
|
||||||
|
public List<Long> selectLoginDaily() { return menuMonthlyRepository.LoginDailyList(); }
|
||||||
|
|
||||||
|
public List<Long> selectFileDaily() { return menuMonthlyRepository.FileDailyList(); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
package com.dbnt.kcscbackend.admin.standardResearch;
|
package com.dbnt.kcscbackend.admin.standardResearch;
|
||||||
|
|
||||||
|
|
||||||
import com.dbnt.kcscbackend.admin.contents.popUp.model.CreatePopupVO;
|
|
||||||
import com.dbnt.kcscbackend.admin.contents.popUp.model.UpdatePopupVO;
|
|
||||||
import com.dbnt.kcscbackend.admin.contents.popUp.utils.EgovFileMngUtil;
|
import com.dbnt.kcscbackend.admin.contents.popUp.utils.EgovFileMngUtil;
|
||||||
import com.dbnt.kcscbackend.admin.standardResearch.model.CreateStandardResearchVO;
|
import com.dbnt.kcscbackend.admin.standardResearch.model.CreateStandardResearchVO;
|
||||||
import com.dbnt.kcscbackend.admin.standardResearch.model.UpdateStandardResearchVO;
|
import com.dbnt.kcscbackend.admin.standardResearch.model.UpdateStandardResearchVO;
|
||||||
|
|
@ -11,7 +9,6 @@ import com.dbnt.kcscbackend.auth.entity.LoginVO;
|
||||||
import com.dbnt.kcscbackend.config.common.ResponseCode;
|
import com.dbnt.kcscbackend.config.common.ResponseCode;
|
||||||
import com.dbnt.kcscbackend.config.common.ResultVO;
|
import com.dbnt.kcscbackend.config.common.ResultVO;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiParam;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||||
|
|
|
||||||
|
|
@ -179,7 +179,7 @@ public class EgovLoginApiController extends BaseController {
|
||||||
if (refreshToken != null){
|
if (refreshToken != null){
|
||||||
String serverToken = refreshToken.getRefreshToken();
|
String serverToken = refreshToken.getRefreshToken();
|
||||||
if(egovJwtTokenUtil.getUserSeFromToken(clientToken).equals(egovJwtTokenUtil.getUserSeFromToken(serverToken))){
|
if(egovJwtTokenUtil.getUserSeFromToken(clientToken).equals(egovJwtTokenUtil.getUserSeFromToken(serverToken))){
|
||||||
return true;
|
return egovJwtTokenUtil.getUserIdFromToken(clientToken).equals("admin");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,9 @@ public class LoginVO implements Serializable{
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = -8274004534207618049L;
|
private static final long serialVersionUID = -8274004534207618049L;
|
||||||
|
|
||||||
|
@Schema(description = "사용자 번호")
|
||||||
|
private Integer userSeq;
|
||||||
|
|
||||||
@Schema(description = "아이디")
|
@Schema(description = "아이디")
|
||||||
@Pattern(regexp = "^[a-zA-Z]{1}[a-zA-Z0-9_]{4,11}$")
|
@Pattern(regexp = "^[a-zA-Z]{1}[a-zA-Z0-9_]{4,11}$")
|
||||||
|
|
|
||||||
|
|
@ -8,5 +8,6 @@ import java.util.List;
|
||||||
public interface TnCmtOrgRepository extends JpaRepository<TnCmtOrg, TnCmtOrg.TnCmtOrgId> {
|
public interface TnCmtOrgRepository extends JpaRepository<TnCmtOrg, TnCmtOrg.TnCmtOrgId> {
|
||||||
List<TnCmtOrg> findByUseYnAndUpCmtSeqOrderByCmtOrder(String useYn, Long upCmtSeq);
|
List<TnCmtOrg> findByUseYnAndUpCmtSeqOrderByCmtOrder(String useYn, Long upCmtSeq);
|
||||||
TnCmtOrg findByUseYnAndCmtSeq(String useYn, Long cmtSeq);
|
TnCmtOrg findByUseYnAndCmtSeq(String useYn, Long cmtSeq);
|
||||||
|
List<TnCmtOrg> findByUseYnAndUpCmtSeqAndCmtTypeOrderByCmtOrder(String useYn, Long upCmtSeq, String cmtType);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||||
LoginVO loginVO = new LoginVO();
|
LoginVO loginVO = new LoginVO();
|
||||||
if( verificationFlag ){
|
if( verificationFlag ){
|
||||||
logger.debug("jwtToken validated");
|
logger.debug("jwtToken validated");
|
||||||
|
loginVO.setUserSeq(Integer.parseInt(jwtTokenUtil.getUserSeqFromToken(jwtToken)));
|
||||||
loginVO.setId(id);
|
loginVO.setId(id);
|
||||||
loginVO.setUserSe( jwtTokenUtil.getUserSeFromToken(jwtToken) );
|
loginVO.setUserSe( jwtTokenUtil.getUserSeFromToken(jwtToken) );
|
||||||
// loginVO.setUniqId( jwtTokenUtil.getInfoFromToken("uniqId",jwtToken) );
|
// loginVO.setUniqId( jwtTokenUtil.getInfoFromToken("uniqId",jwtToken) );
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,8 @@ public class CustomUrlAuthenticationSuccessHandler extends SimpleUrlAuthenticati
|
||||||
MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
|
MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
|
||||||
MediaType jsonMimeType = MediaType.APPLICATION_JSON;
|
MediaType jsonMimeType = MediaType.APPLICATION_JSON;
|
||||||
HashMap<String, Object> resultMap = new HashMap<>();
|
HashMap<String, Object> resultMap = new HashMap<>();
|
||||||
if(securityUser.getUserId().equals("admin") && !adminIpList.contains(ClientUtils.getRemoteIP(request))){
|
|
||||||
|
/*if(securityUser.getUserId().equals("admin") && !adminIpList.contains(ClientUtils.getRemoteIP(request))){
|
||||||
resultMap.put("resultCode", ResponseCode.FAILED.getCode());
|
resultMap.put("resultCode", ResponseCode.FAILED.getCode());
|
||||||
resultMap.put("resultMessage", "관리자 계정은 지정된 아이피에서만 접속할 수 있습니다.\n필요한 경우 관리자에게 요청하십시오.\n접속자 아이피: "+ClientUtils.getRemoteIP(request));
|
resultMap.put("resultMessage", "관리자 계정은 지정된 아이피에서만 접속할 수 있습니다.\n필요한 경우 관리자에게 요청하십시오.\n접속자 아이피: "+ClientUtils.getRemoteIP(request));
|
||||||
}else{
|
}else{
|
||||||
|
|
@ -69,7 +70,13 @@ public class CustomUrlAuthenticationSuccessHandler extends SimpleUrlAuthenticati
|
||||||
// response.addHeader("Authorization", "BEARER "+accessToken);
|
// response.addHeader("Authorization", "BEARER "+accessToken);
|
||||||
// Cookie refreshTokenCookie = new Cookie("refreshToken", refreshToken);
|
// Cookie refreshTokenCookie = new Cookie("refreshToken", refreshToken);
|
||||||
// response.addCookie(refreshTokenCookie);
|
// response.addCookie(refreshTokenCookie);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
String accessToken = jwtTokenUtil.generateAccessToken(securityUser, request.getRemoteAddr());
|
||||||
|
String refreshToken = jwtTokenUtil.generateRefreshTokenToken(securityUser, request.getRemoteAddr());
|
||||||
|
resultMap.put("resultCode", ResponseCode.SUCCESS.getCode());
|
||||||
|
resultMap.put("accessToken", accessToken);
|
||||||
|
resultMap.put("refreshToken", refreshToken);
|
||||||
|
|
||||||
if (jsonConverter.canWrite(resultMap.getClass(), jsonMimeType)) {
|
if (jsonConverter.canWrite(resultMap.getClass(), jsonMimeType)) {
|
||||||
jsonConverter.write(resultMap, jsonMimeType, new ServletServerHttpResponse(response));
|
jsonConverter.write(resultMap, jsonMimeType, new ServletServerHttpResponse(response));
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ public class SecurityConfig {
|
||||||
"/swagger-ui/**",
|
"/swagger-ui/**",
|
||||||
|
|
||||||
/*기준코드 조회*/
|
/*기준코드 조회*/
|
||||||
"/standardCode/**.do"
|
"/standardCode/**"
|
||||||
};
|
};
|
||||||
private static final String[] ORIGINS_WHITELIST = {
|
private static final String[] ORIGINS_WHITELIST = {
|
||||||
"http://localhost:3000",
|
"http://localhost:3000",
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import com.dbnt.kcscbackend.config.common.ResponseCode;
|
||||||
import com.dbnt.kcscbackend.config.common.ResultVO;
|
import com.dbnt.kcscbackend.config.common.ResultVO;
|
||||||
import com.dbnt.kcscbackend.standardCode.entity.TnDocumentCodeList;
|
import com.dbnt.kcscbackend.standardCode.entity.TnDocumentCodeList;
|
||||||
import com.dbnt.kcscbackend.standardCode.entity.TnDocumentContent;
|
import com.dbnt.kcscbackend.standardCode.entity.TnDocumentContent;
|
||||||
|
import com.dbnt.kcscbackend.standardCode.entity.TnDocumentFavorites;
|
||||||
import com.dbnt.kcscbackend.standardCode.entity.TnDocumentInfo;
|
import com.dbnt.kcscbackend.standardCode.entity.TnDocumentInfo;
|
||||||
import com.dbnt.kcscbackend.standardCode.service.StandardCodeService;
|
import com.dbnt.kcscbackend.standardCode.service.StandardCodeService;
|
||||||
import com.dbnt.kcscbackend.standardCode.service.StandardCodeVO;
|
import com.dbnt.kcscbackend.standardCode.service.StandardCodeVO;
|
||||||
|
|
@ -60,7 +61,7 @@ public class StandardCodeController extends BaseController {
|
||||||
@ApiResponse(responseCode = "200", description = "조회 성공"),
|
@ApiResponse(responseCode = "200", description = "조회 성공"),
|
||||||
@ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
|
@ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
|
||||||
})
|
})
|
||||||
@RequestMapping(method = RequestMethod.POST, value = "/getCodeTree.do", consumes = MediaType.APPLICATION_JSON_VALUE)
|
@RequestMapping(method = RequestMethod.GET, value = "/code-tree")
|
||||||
public ResultVO getCodeTree() throws Exception {
|
public ResultVO getCodeTree() throws Exception {
|
||||||
ResultVO resultVO = new ResultVO();
|
ResultVO resultVO = new ResultVO();
|
||||||
Map<String, Object> resultMap = new HashMap<>();
|
Map<String, Object> resultMap = new HashMap<>();
|
||||||
|
|
@ -98,8 +99,8 @@ public class StandardCodeController extends BaseController {
|
||||||
@ApiResponse(responseCode = "200", description = "조회 성공"),
|
@ApiResponse(responseCode = "200", description = "조회 성공"),
|
||||||
@ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
|
@ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
|
||||||
})
|
})
|
||||||
@PostMapping(value = "/getCodeInfo.do", consumes = MediaType.APPLICATION_JSON_VALUE)
|
@GetMapping(value = "/code-info", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||||
public ResultVO getCodeInfo(@RequestBody StandardCodeVO param, @AuthenticationPrincipal LoginVO user)
|
public ResultVO getCodeInfo(StandardCodeVO param, @AuthenticationPrincipal LoginVO user)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
ResultVO resultVO = new ResultVO();
|
ResultVO resultVO = new ResultVO();
|
||||||
Map<String, Object> resultMap = new HashMap<>();
|
Map<String, Object> resultMap = new HashMap<>();
|
||||||
|
|
@ -151,25 +152,10 @@ public class StandardCodeController extends BaseController {
|
||||||
ResultVO resultVO = new ResultVO();
|
ResultVO resultVO = new ResultVO();
|
||||||
Map<String, Object> resultMap = new HashMap<>();
|
Map<String, Object> resultMap = new HashMap<>();
|
||||||
|
|
||||||
String tab = tnDocumentInfo.getTab() != null ? tnDocumentInfo.getTab() : "";
|
tnDocumentInfo.makeListCode();
|
||||||
String category1 = tnDocumentInfo.getCategory1() != null ? tnDocumentInfo.getCategory1() : "";
|
tnDocumentInfo.setUserSeq(user.getUserSeq());
|
||||||
String category2 = tnDocumentInfo.getCategory2() != null ? tnDocumentInfo.getCategory2() : "";
|
resultMap.put("resultList", standardCodeService.selectStandardCodeList(tnDocumentInfo));
|
||||||
String category3 = tnDocumentInfo.getCategory3() != null ? tnDocumentInfo.getCategory3() : "";
|
resultMap.put("resultCnt", standardCodeService.selectStandardCodeListCnt(tnDocumentInfo));
|
||||||
|
|
||||||
Integer categorySeq1 = standardCodeService.selectStandardCodeGroupSeq(tab);
|
|
||||||
Integer categorySeq2 = standardCodeService.selectStandardCodeGroupSeq(tab + category1);
|
|
||||||
Integer categorySeq3 = standardCodeService.selectStandardCodeGroupSeq(tab + category1 + category2);
|
|
||||||
resultMap.put("category1List", standardCodeService.selectStandardCodeCategoryList(categorySeq1));
|
|
||||||
resultMap.put("category2List", standardCodeService.selectStandardCodeCategoryList(categorySeq2));
|
|
||||||
resultMap.put("category3List", standardCodeService.selectStandardCodeCategoryList(categorySeq3));
|
|
||||||
|
|
||||||
tnDocumentInfo.setListCode(tab + category1 + category2 + category3);
|
|
||||||
List<TnDocumentCodeList> tnDocumentCodeList = standardCodeService.selectStandardCodeList(tnDocumentInfo);
|
|
||||||
resultMap.put("resultList", tnDocumentCodeList);
|
|
||||||
Integer totCnt = tnDocumentCodeList.get(0).getContentcount();
|
|
||||||
|
|
||||||
resultMap.put("resultCnt", totCnt);
|
|
||||||
resultMap.put("user", user);
|
|
||||||
|
|
||||||
resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
|
resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
|
||||||
resultVO.setResultMessage(ResponseCode.SUCCESS.getMessage());
|
resultVO.setResultMessage(ResponseCode.SUCCESS.getMessage());
|
||||||
|
|
@ -177,6 +163,84 @@ public class StandardCodeController extends BaseController {
|
||||||
return resultVO;
|
return resultVO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(
|
||||||
|
summary = "건설기준코드 다운로드 리스트 조회",
|
||||||
|
description = "건설기준코드 다운로드 리스트 조회",
|
||||||
|
tags = {"StandardCodeController"}
|
||||||
|
)
|
||||||
|
@ApiResponses(value = {
|
||||||
|
@ApiResponse(responseCode = "200", description = "조회 성공"),
|
||||||
|
@ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
|
||||||
|
})
|
||||||
|
@GetMapping(value = "/standard-code-download-list")
|
||||||
|
public ResultVO selectStandardCodeDownloadList(TnDocumentInfo tnDocumentInfo, @AuthenticationPrincipal LoginVO user)
|
||||||
|
throws Exception {
|
||||||
|
ResultVO resultVO = new ResultVO();
|
||||||
|
Map<String, Object> resultMap = new HashMap<>();
|
||||||
|
String listCode = tnDocumentInfo.getListCode();
|
||||||
|
if(listCode.equals("60")){
|
||||||
|
listCode += "______";
|
||||||
|
}else{
|
||||||
|
listCode += "____";
|
||||||
|
}
|
||||||
|
resultMap.put("resultList", standardCodeService.selectTnDocumentGroupToGroupFullCdLike(listCode));
|
||||||
|
|
||||||
|
resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
|
||||||
|
resultVO.setResultMessage(ResponseCode.SUCCESS.getMessage());
|
||||||
|
resultVO.setResult(resultMap);
|
||||||
|
return resultVO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(
|
||||||
|
summary = "건설기준코드 검색조건 옵션 조회",
|
||||||
|
description = "건설기준코드 검색조건 옵션 조회",
|
||||||
|
tags = {"StandardCodeController"}
|
||||||
|
)
|
||||||
|
@ApiResponses(value = {
|
||||||
|
@ApiResponse(responseCode = "200", description = "조회 성공"),
|
||||||
|
@ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
|
||||||
|
})
|
||||||
|
@GetMapping(value = "/category-option")
|
||||||
|
public ResultVO getCategoryOption(TnDocumentInfo tnDocumentInfo) throws Exception {
|
||||||
|
ResultVO resultVO = new ResultVO();
|
||||||
|
Map<String, Object> resultMap = new HashMap<>();
|
||||||
|
|
||||||
|
resultMap.put("groupList", standardCodeService.selectTnDocumentGroupToGroupFullCdLike(tnDocumentInfo.getListCode()+"__"));
|
||||||
|
|
||||||
|
resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
|
||||||
|
resultVO.setResultMessage(ResponseCode.SUCCESS.getMessage());
|
||||||
|
resultVO.setResult(resultMap);
|
||||||
|
return resultVO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(
|
||||||
|
summary = "건설기준코드 즐겨찾기 추가, 삭제",
|
||||||
|
description = "건설기준코드 즐겨찾기 추가, 삭제",
|
||||||
|
tags = {"StandardCodeController"}
|
||||||
|
)
|
||||||
|
@ApiResponses(value = {
|
||||||
|
@ApiResponse(responseCode = "200", description = "수정 성공"),
|
||||||
|
@ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
|
||||||
|
})
|
||||||
|
@PostMapping(value = "/document-favorite")
|
||||||
|
public ResultVO setDocumentFavorite(@RequestBody TnDocumentFavorites favorites, @AuthenticationPrincipal LoginVO loginUser) throws Exception {
|
||||||
|
ResultVO resultVO = new ResultVO();
|
||||||
|
if(favorites.getActive()==null){
|
||||||
|
resultVO.setResultCode(ResponseCode.SAVE_ERROR.getCode());
|
||||||
|
resultVO.setResultMessage(ResponseCode.SAVE_ERROR.getMessage());
|
||||||
|
return resultVO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(favorites.getActive()){
|
||||||
|
standardCodeService.saveFavorites(loginUser.getUserSeq(), favorites.getGroupSeq());
|
||||||
|
}else{
|
||||||
|
standardCodeService.deleteFavorites(loginUser.getUserSeq(), favorites.getGroupSeq());
|
||||||
|
}
|
||||||
|
resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
|
||||||
|
resultVO.setResultMessage(ResponseCode.SUCCESS.getMessage());
|
||||||
|
return resultVO;
|
||||||
|
}
|
||||||
|
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "건설기준코드 개정이력 조회",
|
summary = "건설기준코드 개정이력 조회",
|
||||||
description = "건설기준코드 개정이력 조회",
|
description = "건설기준코드 개정이력 조회",
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.Transient;
|
import javax.persistence.Transient;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
|
|
@ -28,15 +29,24 @@ public class TnDocumentCodeList {
|
||||||
private String middleCategory;
|
private String middleCategory;
|
||||||
@Column(name = "group_nm")
|
@Column(name = "group_nm")
|
||||||
private String groupNm;
|
private String groupNm;
|
||||||
|
@Column(name = "rvsn_remark")
|
||||||
|
private String rvsnRemark;
|
||||||
@Column(name = "kcsc_cd")
|
@Column(name = "kcsc_cd")
|
||||||
private String kcscCd;
|
private String kcscCd;
|
||||||
@Column(name = "doc_file_grp_id")
|
@Column(name = "doc_file_grp_id")
|
||||||
private String docFileGrpId;
|
private String docFileGrpId;
|
||||||
@Column(name = "contentcount")
|
|
||||||
private Integer contentcount;
|
|
||||||
@Column(name = "parent_group_seq")
|
@Column(name = "parent_group_seq")
|
||||||
private String parentGroupSeq;
|
private String parentGroupSeq;
|
||||||
@Column(name = "group_full_cd")
|
@Column(name = "group_full_cd")
|
||||||
private String groupFullCd;
|
private String groupFullCd;
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
private Integer allCnt;
|
||||||
|
@Transient
|
||||||
|
private Integer remarkCnt;
|
||||||
|
@Transient
|
||||||
|
private Boolean favoriteChk;
|
||||||
|
@Transient
|
||||||
|
private List<TnDocumentInfo> historyList;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.dbnt.kcscbackend.standardCode.entity;
|
||||||
|
|
||||||
|
import lombok.*;
|
||||||
|
import org.hibernate.annotations.DynamicInsert;
|
||||||
|
import org.hibernate.annotations.DynamicUpdate;
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Entity
|
||||||
|
@NoArgsConstructor
|
||||||
|
@DynamicInsert
|
||||||
|
@DynamicUpdate
|
||||||
|
@Table(name = "tn_document_favorites")
|
||||||
|
@IdClass(TnDocumentFavorites.TnDocumentFavoritesId.class)
|
||||||
|
public class TnDocumentFavorites {
|
||||||
|
@Id
|
||||||
|
@Column(name = "user_seq")
|
||||||
|
private Integer userSeq;
|
||||||
|
@Id
|
||||||
|
@Column(name = "group_seq")
|
||||||
|
private Integer groupSeq;
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
private Boolean active;
|
||||||
|
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class TnDocumentFavoritesId implements Serializable {
|
||||||
|
private Integer userSeq;
|
||||||
|
private Integer groupSeq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.dbnt.kcscbackend.standardCode.entity;
|
package com.dbnt.kcscbackend.standardCode.entity;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
@ -92,11 +93,18 @@ public class TnDocumentInfo {
|
||||||
@Transient
|
@Transient
|
||||||
private String searchWrd;
|
private String searchWrd;
|
||||||
@Transient
|
@Transient
|
||||||
private String tab;
|
private String tab = "";
|
||||||
@Transient
|
@Transient
|
||||||
private String category1;
|
private String category1 = "";
|
||||||
@Transient
|
@Transient
|
||||||
private String category2;
|
private String category2 = "";
|
||||||
@Transient
|
@Transient
|
||||||
private String category3;
|
private String category3 = "";
|
||||||
|
@Transient
|
||||||
|
private Integer userSeq;
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
public void makeListCode(){
|
||||||
|
setListCode(getTab()+getCategory1()+getCategory2()+getCategory3());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue