Compare commits
No commits in common. "432cad27ab1e31df6dde53701aa88cb30ec85f96" and "98d2da2e2117a528ec1fe89254b4a2f9fdeeca98" have entirely different histories.
432cad27ab
...
98d2da2e21
File diff suppressed because it is too large
Load Diff
|
|
@ -3,8 +3,6 @@
|
||||||
"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",
|
||||||
|
|
@ -12,25 +10,19 @@
|
||||||
"@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,6 +1,4 @@
|
||||||
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';
|
||||||
|
|
@ -14,11 +12,9 @@ import './css/Custom/customMain.css'
|
||||||
function App() {
|
function App() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeCustomization>
|
<div className="wrap">
|
||||||
<ScrollTop>
|
|
||||||
<RootRoutes />
|
<RootRoutes />
|
||||||
</ScrollTop>
|
</div>
|
||||||
</ThemeCustomization>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,11 +29,7 @@ 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(accessToken && new Date(sessionUser.exp*1000) < new Date()){
|
|
||||||
//만료된 토큰 재발급 절차 진행.
|
|
||||||
accessTokenRefresh(url, requestOptions, handler, errorHandler);
|
|
||||||
}else{
|
|
||||||
if(sessionUserId != null){
|
if(sessionUserId != null){
|
||||||
if( !requestOptions['headers'] ) requestOptions['headers']={}
|
if( !requestOptions['headers'] ) requestOptions['headers']={}
|
||||||
if( !requestOptions['headers']['Authorization'] ) requestOptions['headers']['Authorization']=null;
|
if( !requestOptions['headers']['Authorization'] ) requestOptions['headers']['Authorization']=null;
|
||||||
|
|
@ -52,12 +48,14 @@ export function requestFetch(url, requestOptions, handler, errorHandler) {
|
||||||
|
|
||||||
fetch(SERVER_URL + url, requestOptions)
|
fetch(SERVER_URL + url, requestOptions)
|
||||||
.then(response => {// response Stream. Not completion object
|
.then(response => {// response Stream. Not completion object
|
||||||
|
//console.log("requestFetch [Response Stream] ", response);
|
||||||
return response.json();
|
return response.json();
|
||||||
})
|
})
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
if (Number(resp.resultCode) === Number(CODE.RCV_ERROR_AUTH)) {
|
if (Number(resp.resultCode) === Number(CODE.RCV_ERROR_AUTH)) {
|
||||||
alert("로그인이 해제되었습니다.")
|
//accessToken 갱신 요청
|
||||||
window.location.href = "/login"
|
accessTokenRefresh(url, requestOptions, handler, errorHandler);
|
||||||
|
return resp;
|
||||||
} else {
|
} else {
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
@ -89,7 +87,7 @@ export function requestFetch(url, requestOptions, handler, errorHandler) {
|
||||||
console.log("requestFetch finally end");
|
console.log("requestFetch finally end");
|
||||||
console.groupEnd("requestFetch");
|
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 row">
|
<div className="inner">
|
||||||
<div className="col">
|
<div className="col">
|
||||||
<h3>건설기준코드</h3>
|
<h3>건설기준코드</h3>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,10 @@
|
||||||
import React, {useEffect, useState} from 'react';
|
import React 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 ({loadingState}) {
|
function Loading () {
|
||||||
const [visible, setVisible] = useState(loadingState);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setVisible(loadingState)
|
|
||||||
}, [loadingState]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LoadingDiv $visible={visible}>
|
<LoadingDiv>
|
||||||
<Blocks
|
<Blocks
|
||||||
height="150"
|
height="150"
|
||||||
width="150"
|
width="150"
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,4 @@ 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"};
|
|
||||||
`
|
`
|
||||||
|
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
@ -1,103 +0,0 @@
|
||||||
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,16 +18,15 @@ import FormDialog from '../../components/alert/FormDialog';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function generate(items, element, onClickListner,nameKey,
|
function generate(items, element, onClickListner) {
|
||||||
idKey) {
|
|
||||||
return items.map((value, index) =>
|
return items.map((value, index) =>
|
||||||
React.cloneElement(element, {
|
React.cloneElement(element, {
|
||||||
key: value[nameKey],
|
key: value,
|
||||||
},
|
},
|
||||||
<Card fullWidth sx={{ '&': { boxShadow: 'none' } }}>
|
<Card fullWidth sx={{ '&': { boxShadow: 'none' } }}>
|
||||||
<CardActionArea fullWidth sx={{ px: 1 }}>
|
<CardActionArea fullWidth sx={{ px: 1 }}>
|
||||||
<ListItemText
|
<ListItemText
|
||||||
primary={value[nameKey]}
|
primary={value}
|
||||||
key={index}
|
key={index}
|
||||||
data-index={index}
|
data-index={index}
|
||||||
onClick={(e) => {onClickListner(e, index);}}
|
onClick={(e) => {onClickListner(e, index);}}
|
||||||
|
|
@ -100,9 +99,7 @@ function ListCreateUpdateDelete(props) {
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
</ListItem>,
|
</ListItem>,
|
||||||
onClickItem,
|
onClickItem
|
||||||
props.nameKey,
|
|
||||||
props.idKey
|
|
||||||
)}
|
)}
|
||||||
</List>
|
</List>
|
||||||
</Demo>
|
</Demo>
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,12 @@ 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]);
|
||||||
|
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
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,27 +46,14 @@
|
||||||
.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{
|
||||||
.standard_code_modal .head >span:nth-child(1),.standard_code_modal .result .list_item >div:nth-child(1){width: 12%;}
|
padding: 0 0;
|
||||||
.standard_code_modal .head >span:nth-child(2),.standard_code_modal .result .list_item >div:nth-child(2){width: 15%;}
|
width: 80%;
|
||||||
.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:not(.tabs) {display: table-cell; width: 220px; vertical-align: top;} /* changed by lim width: 260px; */
|
.c_wrap .layout .nav {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;}
|
||||||
|
|
|
||||||
|
|
@ -1,199 +0,0 @@
|
||||||
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,6 +1,5 @@
|
||||||
import React, { useState, useEffect, useRef } from 'react';
|
import React, { useState, useEffect, useRef } from 'react';
|
||||||
import {Link, useNavigate, useLocation, useParams} from 'react-router-dom';
|
import { Link, useNavigate, useLocation } 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';
|
||||||
|
|
@ -8,10 +7,9 @@ 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, reloadFunction}) {
|
function EgovAdminBoardEdit(props) {
|
||||||
console.group("EgovAdminBoardEdit");
|
console.group("EgovAdminBoardEdit");
|
||||||
console.log("[Start] EgovAdminBoardEdit ------------------------------");
|
console.log("[Start] EgovAdminBoardEdit ------------------------------");
|
||||||
console.log("EgovAdminBoardEdit [props] : ", props);
|
console.log("EgovAdminBoardEdit [props] : ", props);
|
||||||
|
|
@ -22,141 +20,411 @@ function EgovAdminBoardEdit({props, reloadFunction}) {
|
||||||
|
|
||||||
console.log("EgovAdminBoardEdit [location] : ", location);
|
console.log("EgovAdminBoardEdit [location] : ", location);
|
||||||
|
|
||||||
let item = null;
|
const replyPosblAtRadioGroup = [{ value: "Y", label: "가능" }, { value: "N", label: "불가능" }];
|
||||||
item = props;
|
const fileAtchPosblAtRadioGroup = [{ value: "Y", label: "가능" }, { value: "N", label: "불가능" }];
|
||||||
console.log("@@@ item : " + JSON.stringify(item));
|
const bbsTyCodeOptions = [{ value: "", label: "선택" }, { value: "BBST01", label: "일반게시판" }, { value: "BBST03", label: "공지게시판" }];
|
||||||
|
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(item != null ? {mode: props.mode} : {mode: CODE.MODE_CREATE});
|
const [modeInfo, setModeInfo] = useState({ mode: props.mode });
|
||||||
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">
|
||||||
<Modal.Header closeButton>
|
{/* <!-- Location --> */}
|
||||||
<Modal.Title>
|
<div className="location">
|
||||||
{modeInfo.mode === CODE.MODE_CREATE && '게시판 생성'}
|
<ul>
|
||||||
{modeInfo.mode === CODE.MODE_MODIFY && '게시판 수정'}
|
<li><Link to={URL.MAIN} className="home">Home</Link></li>
|
||||||
</Modal.Title>
|
<li><Link to={URL.ADMIN}>사이트관리</Link></li>
|
||||||
</Modal.Header>
|
<li>게시판생성 관리</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{/* <!--// Location --> */}
|
||||||
|
|
||||||
|
<div className="layout">
|
||||||
|
{/* <!-- Navigation --> */}
|
||||||
|
<EgovLeftNav></EgovLeftNav>
|
||||||
|
{/* <!--// Navigation --> */}
|
||||||
|
|
||||||
|
<div className="contents BOARD_CREATE_REG" id="contents">
|
||||||
|
{/* <!-- 본문 --> */}
|
||||||
|
|
||||||
|
<div className="top_tit">
|
||||||
|
<h1 className="tit_1">사이트관리</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{modeInfo.mode === CODE.MODE_CREATE &&
|
||||||
|
<h2 className="tit_2">게시판 생성</h2>
|
||||||
|
}
|
||||||
|
|
||||||
|
{modeInfo.mode === CODE.MODE_MODIFY &&
|
||||||
|
<h2 className="tit_2">게시판 수정</h2>
|
||||||
|
}
|
||||||
|
|
||||||
<Modal.Body>
|
|
||||||
<div className="board_view2">
|
<div className="board_view2">
|
||||||
<Form onSubmit={(e) => {editBoard(e)}} noValidate>
|
|
||||||
<dl>
|
<dl>
|
||||||
<dt><label htmlFor="bbsId">게시판 ID</label><span className="req">필수</span></dt>
|
<dt><label htmlFor="bbsNm">게시판명</label><span className="req">필수</span></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<Form.Control className="f_input2 w_full" type="text" name="bbsId" placeholder="게시판 ID" required
|
<input className="f_input2 w_full" type="text" name="bbsNm" title="" id="bbsNm" placeholder=""
|
||||||
defaultValue={props?.bbsId} readOnly={props!==undefined}/>
|
defaultValue={boardDetail.bbsNm}
|
||||||
|
onChange={e => setBoardDetail({ ...boardDetail, bbsNm: e.target.value })}
|
||||||
|
ref={el => (checkRef.current[0] = el)}
|
||||||
|
/>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<dl>
|
<dl>
|
||||||
<dt><label htmlFor="bbsTitle">게시판명</label><span className="req">필수</span></dt>
|
<dt><label htmlFor="bbsIntrcn">게시판 소개</label><span className="req">필수</span></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<Form.Control className="f_input2 w_full" type="text" name="bbsTitle" placeholder="게시판명" required
|
<textarea className="f_txtar w_full h_100" name="bbsIntrcn" id="bbsIntrcn" cols="30" rows="10" placeholder=""
|
||||||
defaultValue={props?.bbsTitle}/>
|
defaultValue={boardDetail.bbsIntrcn}
|
||||||
|
onChange={e => setBoardDetail({ ...boardDetail, bbsIntrcn: e.target.value })}
|
||||||
|
ref={el => (checkRef.current[1] = el)}
|
||||||
|
></textarea>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<dl>
|
<dl>
|
||||||
<dt><label htmlFor="bbsDesc">게시판 소개</label><span className="req">필수</span></dt>
|
<dt>게시판 유형<span className="req">필수</span></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<Form.Control className="f_txtar w_full h_100" as="textarea" name="bbsDesc" placeholder="게시판 소개" required
|
{/* 수정/조회 일때 변경 불가 */}
|
||||||
defaultValue={props?.bbsDesc}/>
|
{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>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
{/* <!-- 버튼영역 --> */}
|
{/* <!-- 버튼영역 --> */}
|
||||||
<div className="board_btn_area">
|
<div className="board_btn_area">
|
||||||
<div className="left_col btn1">
|
<div className="left_col btn1">
|
||||||
<button type="submit" className="btn btn_skyblue_h46 w_100">저장
|
<button className="btn btn_skyblue_h46 w_100"
|
||||||
</button>
|
onClick={() => updateBoard()}>저장</button>
|
||||||
{modeInfo.mode === CODE.MODE_MODIFY &&
|
{modeInfo.mode === CODE.MODE_MODIFY &&
|
||||||
<button type={"button"} className="btn btn_skyblue_h46 w_100" onClick={()=>{deleteBoard(props)}}>삭제</button>
|
<button className="btn btn_skyblue_h46 w_100" onClick={() => {
|
||||||
|
deleteBoardArticle(boardDetail.bbsId);
|
||||||
|
}}>삭제</button>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="right_col btn1">
|
<div className="right_col btn1">
|
||||||
<button type={"button"} className="btn btn_blue_h46 w_100" onClick={()=>{reloadFunction()}}>목록</button>
|
<Link to={URL.ADMIN_BOARD} className="btn btn_blue_h46 w_100">목록</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/* <!--// 버튼영역 --> */}
|
{/* <!--// 버튼영역 --> */}
|
||||||
</Form>
|
|
||||||
</div>
|
</div>
|
||||||
</Modal.Body>
|
|
||||||
</>
|
{/* <!--// 본문 --> */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,41 +1,13 @@
|
||||||
import React, { useState, useEffect, useCallback } from 'react';
|
import React 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 Keywords(props) {
|
||||||
|
|
||||||
function StandardCodeMgt(props) {
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<div className="c_wrap">
|
Keywords
|
||||||
{/* <!-- 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 StandardCodeMgt;
|
export default Keywords;
|
||||||
|
|
@ -3,12 +3,11 @@ 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 Modal from "react-bootstrap/Modal";
|
import EgovPaging from 'components/EgovPaging';
|
||||||
import EgovAdminBoardEdit from "../board/EgovAdminBoardEdit";
|
|
||||||
import {format} from "date-fns";
|
import { itemIdxByPage } from 'utils/calc';
|
||||||
|
|
||||||
function EgovAdminBoardList(props) {
|
function EgovAdminBoardList(props) {
|
||||||
console.group("EgovAdminBoardList");
|
console.group("EgovAdminBoardList");
|
||||||
|
|
@ -21,15 +20,10 @@ 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';
|
||||||
|
|
@ -55,15 +49,14 @@ function EgovAdminBoardList(props) {
|
||||||
if (index === 0) mutListTag = []; // 목록 초기화
|
if (index === 0) mutListTag = []; // 목록 초기화
|
||||||
|
|
||||||
mutListTag.push(
|
mutListTag.push(
|
||||||
<div className="list_item">
|
<Link 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 ? format(item.frstCrtDt, "yyyy-MM-dd HH:mm") : ""}</div>
|
<div>{item.frstCrtDt}</div>
|
||||||
<div>{item.lastChgDt ? format(item.lastChgDt, "yyyy-MM-dd HH:mm") : ""}</div>
|
<div>{item.lastChgDt}</div>
|
||||||
<div><button className={"btn btn_blue_h31 px-1"} onClick={()=>{editBoard(item)}}>수정</button></div>
|
</Link>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -82,14 +75,6 @@ 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 (
|
||||||
|
|
@ -165,7 +150,6 @@ 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}
|
||||||
|
|
@ -185,9 +169,6 @@ function EgovAdminBoardList(props) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Modal show={show} onHide={handleClose} keyboard={false}>
|
|
||||||
{modalBody}
|
|
||||||
</Modal>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,41 +1,13 @@
|
||||||
import React, { useState, useEffect, useCallback } from 'react';
|
import React 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 Posts(props) {
|
||||||
|
|
||||||
function StandardCodeMgt(props) {
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<div className="c_wrap">
|
Posts
|
||||||
{/* <!-- 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 StandardCodeMgt;
|
export default Posts;
|
||||||
|
|
@ -1,41 +1,13 @@
|
||||||
import React, { useState, useEffect, useCallback } from 'react';
|
import React 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 AboutSiteMgt(props) {
|
||||||
|
|
||||||
function StandardCodeMgt(props) {
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<div className="c_wrap">
|
AboutSiteMgt
|
||||||
{/* <!-- 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 StandardCodeMgt;
|
export default AboutSiteMgt;
|
||||||
|
|
@ -1,8 +1,25 @@
|
||||||
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 * as EgovNet from 'api/egovFetch';
|
import List from '@mui/material/List';
|
||||||
|
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';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -18,12 +35,13 @@ import { default as EgovLeftNav } from 'components/leftmenu/EgovLeftNavAdmin';
|
||||||
|
|
||||||
function CommitteeCodeMgt(props) {
|
function CommitteeCodeMgt(props) {
|
||||||
|
|
||||||
const [searchCondition, setSearchCondition] = useState({ paramCodeGroup: null, paramCodeLevel: 'LV_01' });
|
const [dense, setDense] = useState(false);
|
||||||
|
const [secondary, setSecondary] = useState(false);
|
||||||
|
|
||||||
const [depth01List, setDepth01List] = useState([]);
|
const [depth01List, setDepth01List] = useState(["중앙건설기술심의", "테스트2"]);
|
||||||
const [depth02List, setDepth02List] = useState([]);
|
const [depth02List, setDepth02List] = useState(["123", "테스트2"]);
|
||||||
const [depth03List, setDepth03List] = useState([]);
|
const [depth03List, setDepth03List] = useState(["다람쥐", "쳇바퀴"]);
|
||||||
const [depth04List, setDepth04List] = useState([]);
|
const [depth04List, setDepth04List] = useState(["임시 텍스트", "text"]);
|
||||||
const [summaryArray, setSummaryArray] = useState({});
|
const [summaryArray, setSummaryArray] = useState({});
|
||||||
|
|
||||||
const [depth01SelectedIndex, setDepth01SelectedIndex] = React.useState();
|
const [depth01SelectedIndex, setDepth01SelectedIndex] = React.useState();
|
||||||
|
|
@ -31,70 +49,13 @@ 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].orgNm ? depth01List[depth01SelectedIndex].orgNm : "",
|
"중앙건설기술심의" : depth01List[depth01SelectedIndex],
|
||||||
"총괄위원회" : depth02List[depth02SelectedIndex] && depth02List[depth02SelectedIndex].orgNm ? depth02List[depth02SelectedIndex].orgNm : "",
|
"총괄위원회" : depth02List[depth02SelectedIndex],
|
||||||
"건설기준위원회" : depth03List[depth03SelectedIndex] && depth03List[depth03SelectedIndex].orgNm ? depth03List[depth03SelectedIndex].orgNm : "",
|
"건설기준위원회" : depth03List[depth03SelectedIndex],
|
||||||
"실무위원회" : depth04List[depth04SelectedIndex] && depth04List[depth04SelectedIndex].orgNm ? depth04List[depth04SelectedIndex].orgNm : "",
|
"실무위원회" : depth04List[depth04SelectedIndex],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
console.log(`${depth01List[depth01SelectedIndex]}[${depth01SelectedIndex}]`);
|
console.log(`${depth01List[depth01SelectedIndex]}[${depth01SelectedIndex}]`);
|
||||||
|
|
@ -109,6 +70,12 @@ function CommitteeCodeMgt(props) {
|
||||||
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() {
|
||||||
return (
|
return (
|
||||||
|
|
@ -123,8 +90,6 @@ function CommitteeCodeMgt(props) {
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<div className="c_wrap">
|
<div className="c_wrap">
|
||||||
|
|
@ -142,6 +107,7 @@ 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',
|
||||||
|
|
@ -153,13 +119,11 @@ function CommitteeCodeMgt(props) {
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ListCreateUpdateDelete title="중앙건설기술심의" items={depth01List} setItemIndex={setDepth01SelectedIndex} nameKey="orgNm" idKey="orgId" />
|
<ListCreateUpdateDelete title="중앙건설기술심의" items={depth01List} setItemIndex={setDepth01SelectedIndex}/>
|
||||||
<ListCreateUpdateDelete title="총괄위원회" items={depth02List} setItemIndex={setDepth02SelectedIndex} nameKey="orgNm" idKey="orgId" />
|
<ListCreateUpdateDelete title="총괄위원회" items={depth02List} setItemIndex={setDepth02SelectedIndex}/>
|
||||||
<ListCreateUpdateDelete title="건설기준위원회" items={depth03List} setItemIndex={setDepth03SelectedIndex} nameKey="orgNm" idKey="orgId" />
|
<ListCreateUpdateDelete title="건설기준위원회" items={depth03List} setItemIndex={setDepth03SelectedIndex}/>
|
||||||
<ListCreateUpdateDelete title="실무위원회" items={depth04List} setItemIndex={setDepth04SelectedIndex} nameKey="orgNm" idKey="orgId" />
|
<ListCreateUpdateDelete title="실무위원회" items={depth04List} setItemIndex={setDepth04SelectedIndex}/>
|
||||||
|
|
||||||
</Box>
|
</Box>
|
||||||
{ true &&
|
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
|
@ -172,8 +136,6 @@ function CommitteeCodeMgt(props) {
|
||||||
>
|
>
|
||||||
<ListLabelInputs title="위원회 코드정보" items={summaryArray} />
|
<ListLabelInputs title="위원회 코드정보" items={summaryArray} />
|
||||||
</Box>
|
</Box>
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
{/* <!--// 본문 --> */}
|
{/* <!--// 본문 --> */}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,11 @@
|
||||||
import React, { useState, useEffect, useCallback } from 'react';
|
import React 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">
|
||||||
<div className="c_wrap">
|
StandardCodeMgt
|
||||||
{/* <!-- 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} from 'react';
|
import React, {useState, useEffect, useCallback, useRef, PureComponent} 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,7 +145,6 @@ 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} from 'react';
|
import React, {useState, useEffect, useCallback, useRef, PureComponent} 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,7 +85,6 @@ 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 } from 'react';
|
import React, { useState, useEffect, useCallback, useRef } 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,7 +77,6 @@ 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} from 'react';
|
import React, {useState, useEffect, useCallback, useRef, PureComponent} 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,7 +84,6 @@ 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 }) => {
|
||||||
|
|
|
||||||
|
|
@ -1,166 +0,0 @@
|
||||||
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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,202 @@
|
||||||
|
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;
|
||||||
|
|
@ -0,0 +1,364 @@
|
||||||
|
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,221 +1,328 @@
|
||||||
import React, {useState, useEffect, useCallback} from 'react'; // PureComponent
|
import React, {useState, useEffect, useCallback, PureComponent} from 'react';
|
||||||
import {Link} from 'react-router-dom'; //useLocation
|
import {Link, useLocation} from 'react-router-dom';
|
||||||
|
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 EgovAdminDashboard(props) {
|
function EgovAdminScheduleList(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 innerConsole = (...args) => {
|
const [searchCondition, setSearchCondition] = useState(location.state?.searchCondition || {schdulSe: '', year: TODAY.getFullYear(), month: TODAY.getMonth(), date: TODAY.getDate()});
|
||||||
// console.log(...args);
|
const [calendarTag, setCalendarTag] = useState([]);
|
||||||
// }
|
|
||||||
|
|
||||||
// const changeDate = (target, amount) => {
|
const [scheduleList, setScheduleList] = useState([]);
|
||||||
// let changedDate;
|
const [dailyUserLogList, setDailyUserLogList] = useState([]);
|
||||||
//
|
|
||||||
// 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 retrieveList = useCallback((srchcnd) => {
|
const innerConsole = (...args) => {
|
||||||
// console.groupCollapsed("EgovAdminScheduleList.retrieveList()");
|
console.log(...args);
|
||||||
//
|
}
|
||||||
// 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 Location = React.memo(function Location() {
|
const changeDate = (target, amount) => {
|
||||||
// return (
|
let changedDate;
|
||||||
// <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>
|
|
||||||
// )
|
|
||||||
// });
|
|
||||||
|
|
||||||
// useEffect(() => {
|
if (target === CODE.DATE_YEAR) {
|
||||||
// //retrieveList(searchCondition); disabled by thkim
|
changedDate = new Date(searchCondition.year + amount, searchCondition.month, searchCondition.date);
|
||||||
// // eslint-disable-next-line react-hooks/exhaustive-deps
|
}
|
||||||
// }, [searchCondition]);
|
|
||||||
|
|
||||||
// const [dailyUserLogList, setDailyUserLogList] = useState([]);
|
if (target === CODE.DATE_MONTH) {
|
||||||
// const [isDailyChart, setIsDailyChart] = useState(true);
|
changedDate = new Date(searchCondition.year, searchCondition.month + amount, searchCondition.date);
|
||||||
//
|
}
|
||||||
// const getDailyUserLogList = useCallback(() => {
|
setSearchCondition({...searchCondition, year: changedDate.getFullYear(), month: changedDate.getMonth(), date: changedDate.getDate()});
|
||||||
// // 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;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// class UserLogChart extends PureComponent {
|
const retrieveList = useCallback((srchcnd) => {
|
||||||
// render() {
|
console.groupCollapsed("EgovAdminScheduleList.retrieveList()");
|
||||||
// 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]");
|
const retrieveListURL = '/schedule/month' + EgovNet.getQueryString(srchcnd);
|
||||||
// console.groupEnd("EgovAdminScheduleList");
|
|
||||||
|
|
||||||
// const [value, setValue] = useState('today');
|
const requestOptions = {
|
||||||
const [slot, setSlot] = useState('week');
|
method: "GET",
|
||||||
const [totalDownloads, setTotalDownloads] = useState(0);
|
headers: {
|
||||||
|
'Content-type': 'application/json',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 총 다운로드 수를 받아온 후 state 업데이트
|
EgovNet.requestFetch(retrieveListURL,
|
||||||
const handleTotalDownloads = (sum) => {
|
requestOptions,
|
||||||
setTotalDownloads(sum);
|
(resp) => {
|
||||||
};
|
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 (
|
return (
|
||||||
<div className="container">
|
|
||||||
<div className="c_wrap">
|
|
||||||
{/* <!-- Location --> */}
|
|
||||||
<div className="location">
|
<div className="location">
|
||||||
<ul>
|
<ul>
|
||||||
<li><Link to={URL.MAIN} className="home">Home</Link></li>
|
<li><Link to={URL.MAIN} className="home">Home</Link></li>
|
||||||
<li><Link to={URL.ADMIN}>사이트관리</Link></li>
|
<li><Link to={URL.ADMIN}>사이트관리</Link></li>
|
||||||
<li>Dashboard</li>
|
<li>일정관리</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</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 (
|
||||||
|
<div className="container">
|
||||||
|
<div className="c_wrap">
|
||||||
|
{/* <!-- Location --> */}
|
||||||
|
<Location/>
|
||||||
{/* <!--// Location --> */}
|
{/* <!--// Location --> */}
|
||||||
|
|
||||||
<div className="layout">
|
<div className="layout">
|
||||||
|
|
@ -227,132 +334,16 @@ function EgovAdminDashboard(props) {
|
||||||
{/* <!-- 본문 --> */}
|
{/* <!-- 본문 --> */}
|
||||||
|
|
||||||
<div className="top_tit">
|
<div className="top_tit">
|
||||||
<h1 className="tit_1">Dashboard</h1>
|
<h1 className="tit_1">사이트관리</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Grid container rowSpacing={4.5} columnSpacing={2.75}>
|
<h2 className="tit_2"></h2>
|
||||||
{/* 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>
|
|
||||||
|
|
||||||
<Grid item md={8} sx={{ display: { sm: 'none', md: 'block', lg: 'none' } }} />
|
<ChartToggle isDailyChart={isDailyChart} onToggle={handleChartToggle}/>
|
||||||
|
|
||||||
{/* row 2 */}
|
<div style={{width: 1000, height: 300}}>
|
||||||
<Grid item xs={12} md={7} lg={8}>
|
<UserLogChart/>
|
||||||
<Grid container alignItems="center" justifyContent="space-between">
|
</div>
|
||||||
<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>
|
||||||
|
|
@ -360,4 +351,4 @@ function EgovAdminDashboard(props) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default EgovAdminDashboard;
|
export default EgovAdminScheduleList;
|
||||||
|
|
@ -1,156 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
@ -1,125 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
@ -1,83 +0,0 @@
|
||||||
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,9 +35,11 @@ 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,9 +35,11 @@ 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,9 +35,10 @@ 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 } from 'react';
|
import React, { useState, useEffect, useRef } 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 { setLocalItem } from 'utils/storage';
|
import { getLocalItem, setLocalItem, setSessionItem } from 'utils/storage';
|
||||||
import InfoShareChk from "./InfoShareChk";
|
import InfoShareChk from "./InfoShareChk";
|
||||||
|
|
||||||
function Join(props) {
|
function Join(props) {
|
||||||
|
|
@ -21,6 +21,7 @@ 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
|
|
@ -1,88 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
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,17 +1,119 @@
|
||||||
import React from 'react';
|
import React, {useState, useEffect, useCallback, useRef} from 'react';
|
||||||
import Col from "react-bootstrap/Col";
|
import {Link, useLocation, useParams} from 'react-router-dom';
|
||||||
import Row from "react-bootstrap/Row";
|
|
||||||
import FavoriteIcon from "./FavoriteIcon";
|
|
||||||
import Button from "react-bootstrap/Button";
|
|
||||||
|
|
||||||
function StandardCodeList({listData, filterData, getHistoryModal}) {
|
import * as EgovNet from 'api/egovFetch';
|
||||||
|
import URL from 'constants/url';
|
||||||
|
import {StandardCodeListModal, StandardCodeListModalTable} from './StandardCodeListModal'
|
||||||
|
import {AiFillFileMarkdown, AiFillStar} from "react-icons/ai";
|
||||||
|
import StandardCodeSearchForm from "./StandardCodeSearchForm";
|
||||||
|
|
||||||
function historyBtn(item){
|
function StandardCodeList({}) {
|
||||||
getHistoryModal(item);
|
const {listCode} = useParams();
|
||||||
|
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={"result standard_code_result"}>
|
<div className="StandardCodeList container">
|
||||||
|
<div className="c_wrap codelistcontent">
|
||||||
|
<div className="location">
|
||||||
|
<ul>
|
||||||
|
<li><Link to={URL.MAIN} className="home">Home</Link></li>
|
||||||
|
<li><Link to='#'>건설기준코드</Link></li>
|
||||||
|
<li><Link to={URL.STANDARD_CODE_LIST}>건설기준코드 검색</Link></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="layout">
|
||||||
|
<div className="contents NOTICE_LIST listtablediv">
|
||||||
|
<div className="top_tit">
|
||||||
|
<h2 className="tit_1">건설기준코드 검색</h2>
|
||||||
|
</div>
|
||||||
|
<StandardCodeSearchForm param={listCode} reloadFunction={retrieveList}/>
|
||||||
|
<div><span>전체 {resultCnt} 건</span></div>
|
||||||
|
{/* <!-- 게시판목록 --> */}
|
||||||
|
<div className="board_list code_list">
|
||||||
|
<div className="head">
|
||||||
|
<span>대분류</span>
|
||||||
|
<span>중분류</span>
|
||||||
|
<span>코드번호</span>
|
||||||
|
<span>코드명</span>
|
||||||
|
<span>개정이력</span>
|
||||||
|
<span>보기</span>
|
||||||
|
<span>즐겨찾기</span>
|
||||||
|
</div>
|
||||||
|
<div className="result">
|
||||||
{listData.filter(item => {
|
{listData.filter(item => {
|
||||||
if (item.groupNm.includes(filterData)) {
|
if (item.groupNm.includes(filterData)) {
|
||||||
return item
|
return item
|
||||||
|
|
@ -23,45 +125,20 @@ function StandardCodeList({listData, filterData, getHistoryModal}) {
|
||||||
<div className="mainCategory">{item.mainCategory}</div>
|
<div className="mainCategory">{item.mainCategory}</div>
|
||||||
<div className="middleCategory">{item.middleCategory}</div>
|
<div className="middleCategory">{item.middleCategory}</div>
|
||||||
<div className="kcscCd">{item.kcscCd}</div>
|
<div className="kcscCd">{item.kcscCd}</div>
|
||||||
<div className="groupNm">{item.groupNm}<br/><span className={"text-danger"}>{item.rvsnRemark}</span></div>
|
<div className="groupNm">{item.groupNm}</div>
|
||||||
<div className="Revisionhistory">
|
<div className="Revisionhistory"><a className="vieweratag" onClick={showHandling} data-groupSeq={item.groupSeq}>개정이력</a></div>
|
||||||
<Button size={"sm"} variant={"outline-secondary"} onClick={()=>{historyBtn(item)}}>개정 이력</Button>
|
<div className="fille">{item.contentcount > 0 ? <a className="vieweratag" href={"/standardCode/viewer/" + item.kcscCd}>내용보기</a> : null}</div>
|
||||||
</div>
|
<div className="star"><AiFillStar/></div>
|
||||||
<div className="fille">
|
|
||||||
<Row className={"justify-content-start"}>
|
|
||||||
{item.historyList.filter(history => {
|
|
||||||
return history;
|
|
||||||
}).map(history => {
|
|
||||||
let buttonClass = "btn btn-sm docInfoBtn docInfoActive "
|
|
||||||
let pClass = "yearInfo yearInfoActive";
|
|
||||||
if(history.docEr === 'E'){
|
|
||||||
buttonClass += "btn-success "
|
|
||||||
}else{
|
|
||||||
buttonClass += "btn-primary "
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Col xs={"auto"} className={"px-1"}>
|
|
||||||
<input type="button"
|
|
||||||
className={buttonClass}
|
|
||||||
value={history.docEr==='E'?'제':'개'}
|
|
||||||
onClick={()=>{
|
|
||||||
const rvsnYmd = new Date(history.rvsnYmd)
|
|
||||||
rvsnYmd.setHours(rvsnYmd.getHours()+9)
|
|
||||||
window.open("/standardCode/viewer/"+history.kcscCd+":"+rvsnYmd.toISOString().split('T')[0]);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<br/>
|
|
||||||
<p className={pClass}>{history.docYr}</p>
|
|
||||||
</Col>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</Row>
|
|
||||||
</div>
|
|
||||||
<FavoriteIcon item={item}/>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<StandardCodeListModal size={"lg"} show={show} content={groupSeq} onClose={close} title={"개정이력"}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
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};
|
||||||
|
|
@ -1,111 +0,0 @@
|
||||||
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,41 +1,16 @@
|
||||||
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, resultCnt, remarkCnt, downloadModal}){
|
function StandardCodeSearchForm({param, reloadFunction}){
|
||||||
|
|
||||||
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),
|
||||||
category3: param?.substring(6, 8),
|
searchWrd: ''
|
||||||
});
|
});
|
||||||
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){
|
||||||
|
|
@ -47,43 +22,6 @@ function StandardCodeSearchForm({param, reloadFunction, resultCnt, remarkCnt, do
|
||||||
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">
|
||||||
|
|
@ -102,61 +40,45 @@ function StandardCodeSearchForm({param, reloadFunction, resultCnt, remarkCnt, do
|
||||||
</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">
|
||||||
<div className={`tab`} onClick={downloadModal}>통합 다운로드</div>
|
<label className="f_select w_306" htmlFor="sel1">
|
||||||
|
<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>
|
||||||
<Row className={"justify-content-between"}>
|
|
||||||
<Col>
|
|
||||||
{subTabsVisible && (
|
{subTabsVisible && (
|
||||||
<Nav className={"tabs"} variant={"tabs"} >
|
<div className="right_col">
|
||||||
<Nav.Item><Nav.Link className={`${searchCondition.tab === 40 ? 'active' : ''}`} onClick={() => {setSearchCondition({...searchCondition, tab: 40})}}>서울특별시</Nav.Link></Nav.Item>
|
<div className="mini_board">
|
||||||
<Nav.Item><Nav.Link className={`${searchCondition.tab === 50 ? 'active' : ''}`} onClick={() => {setSearchCondition({...searchCondition, tab: 50})}}>고속도로공사</Nav.Link></Nav.Item>
|
<ul>
|
||||||
<Nav.Item><Nav.Link className={`${searchCondition.tab === 60 ? 'active' : ''}`} onClick={() => {setSearchCondition({...searchCondition, tab: 60})}}>한국농어촌공사</Nav.Link></Nav.Item>
|
<div className={`tab ${searchCondition.tab === 40 ? 'active' : ''}`} onClick={() => {setSearchCondition({...searchCondition, tab: 40})}}>서울특별시</div>
|
||||||
<Nav.Item><Nav.Link className={`${searchCondition.tab === 70 ? 'active' : ''}`} onClick={() => {setSearchCondition({...searchCondition, tab: 70})}}>철도건설공사</Nav.Link></Nav.Item>
|
<div className={`tab ${searchCondition.tab === 50 ? 'active' : ''}`} onClick={() => {setSearchCondition({...searchCondition, tab: 50})}}>고속도로공사</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 === 60 ? 'active' : ''}`} onClick={() => {setSearchCondition({...searchCondition, tab: 60})}}>한국농어촌공사</div>
|
||||||
<Nav.Item><Nav.Link className={`${searchCondition.tab === 90 ? 'active' : ''}`} onClick={() => {setSearchCondition({...searchCondition, tab: 90})}}>K-Water</Nav.Link></Nav.Item>
|
<div className={`tab ${searchCondition.tab === 70 ? 'active' : ''}`} onClick={() => {setSearchCondition({...searchCondition, tab: 70})}}>철도건설공사</div>
|
||||||
</Nav>
|
<div className={`tab ${searchCondition.tab === 80 ? 'active' : ''}`} onClick={() => {setSearchCondition({...searchCondition, tab: 80})}}>LH한국토지주택공사</div>
|
||||||
|
<div className={`tab ${searchCondition.tab === 90 ? 'active' : ''}`} onClick={() => {setSearchCondition({...searchCondition, tab: 90})}}>K-Water</div>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</Col>
|
|
||||||
<Col xs={"auto"}>
|
|
||||||
<Button href={"/standardCode/info"} size={"sm"} variant={"secondary"}>건설기준코드 안내</Button>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,13 +49,17 @@ const BookmarkModal = ({docCode, docPart, ymd}) => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const getCodeInfo = useCallback(() => {
|
const getCodeInfo = useCallback(() => {
|
||||||
|
console.groupCollapsed("EgovMain.getCodeInfo()");
|
||||||
EgovNet.requestFetch(
|
EgovNet.requestFetch(
|
||||||
'/standardCode/code-info?docCode='+docCode,
|
'/standardCode/getCodeInfo.do',
|
||||||
{
|
{
|
||||||
method: "GET",
|
method: "POST",
|
||||||
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,47 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
@ -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,21 +10,18 @@ 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();
|
||||||
|
|
@ -32,8 +29,6 @@ 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;
|
||||||
|
|
@ -49,21 +44,65 @@ function CodeViewer(props) {
|
||||||
console.log("viewer [docCode] : ", docCode);
|
console.log("viewer [docCode] : ", docCode);
|
||||||
|
|
||||||
const updateDocCode = (docCode)=>{
|
const updateDocCode = (docCode)=>{
|
||||||
setDocLoading(true);
|
setDocSummary([<div></div>])
|
||||||
|
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/code-info?docCode='+docCode,
|
'/standardCode/getCodeInfo.do',
|
||||||
{
|
{
|
||||||
method: "GET",
|
method: "POST",
|
||||||
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;
|
||||||
|
|
@ -268,7 +307,6 @@ 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){
|
||||||
|
|
@ -382,15 +420,9 @@ 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);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
@ -399,9 +431,8 @@ function CodeViewer(props) {
|
||||||
console.groupEnd("viewer");
|
console.groupEnd("viewer");
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/*{treeLoading || docLoading? ():()}*/}
|
{treeLoading || docLoading? (<Loading/>):(
|
||||||
<Loading loadingState={treeLoading || docLoading}/>
|
<Row className="mx-0">
|
||||||
<Row className={`mx-0 ${treeLoading || docLoading?'d-none':''}`}>
|
|
||||||
<Col xs={12} className="border-bottom">
|
<Col xs={12} className="border-bottom">
|
||||||
<Row>
|
<Row>
|
||||||
<Col xs={3}></Col>
|
<Col xs={3}></Col>
|
||||||
|
|
@ -412,36 +443,26 @@ function CodeViewer(props) {
|
||||||
<Col xs={"auto"}>{docInfo}</Col>
|
<Col xs={"auto"}>{docInfo}</Col>
|
||||||
<Col>
|
<Col>
|
||||||
<input type="button" className="btn btn-sm btn-primary optionBtn" value="연혁"/>
|
<input type="button" className="btn btn-sm btn-primary optionBtn" value="연혁"/>
|
||||||
<input type="button" className="btn btn-sm btn-primary optionBtn" value="2단비교"/>
|
<input type="button" className="btn btn-sm btn-primary optionBtn" value="비교"/>
|
||||||
<input type="button" className="btn btn-sm btn-primary optionBtn" value="신구조문"/>
|
|
||||||
<input type="button" className="btn btn-sm btn-primary optionBtn" value="첨부파일"/>
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs={"auto"}>
|
<Col xs={"auto"}>{errorSelector}</Col>
|
||||||
<InputGroup>
|
|
||||||
<Form.Control type="text" size={"sm"} placeholder={"문서 내 검색"}/>
|
|
||||||
{errorSelector}
|
|
||||||
</InputGroup>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
</Row>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs={colList[0]} className={`border-end viewerDiv ${colList[0]===3?'':'d-none'}`}>
|
<Col xs={3} className="border-end viewerDiv">
|
||||||
{/*{codeTree}*/}
|
{codeTree}
|
||||||
<ViewerTree docCode={docCode} updateDocCode={updateDocCode} setTreeLoading={setTreeLoading}/>
|
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs={colList[1]} className="border-end viewerDiv">
|
<Col xs={2} className="border-end viewerDiv">
|
||||||
<div>
|
|
||||||
<Button size={"sm"} variant={"outline-secondary"} onClick={treeControl}>{colList[0]===3?'트리 접기':'트리 펼치기'}</Button>
|
|
||||||
</div>
|
|
||||||
{docSummary}
|
{docSummary}
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs={colList[2]} className="viewerDiv detailInfoDiv" ref={actionAppend}>
|
<Col xs={7} className="viewerDiv detailInfoDiv" ref={actionAppend}>
|
||||||
{docDetail}
|
{docDetail}
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</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>
|
||||||
|
|
@ -450,8 +471,8 @@ function CodeViewer(props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeViewer.defaultProps = {
|
CodeViewer.defaultProps = {
|
||||||
docCode: 'KDS 11 10 15',
|
docCode: 'KCS 24 31 10',
|
||||||
docName: '지반계측'
|
docName: '용접(한계상태설계법)'
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CodeViewer;
|
export default CodeViewer;
|
||||||
|
|
@ -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,13 +110,11 @@ import AdminLogsFileDownloadStatus from 'pages/admin/logs/FileDownloadStatus';
|
||||||
|
|
||||||
|
|
||||||
//건설기준코드
|
//건설기준코드
|
||||||
import CodeViewer from 'pages/standardCode/viewer/CodeViewer';
|
import CodeViewer from 'pages/standardCode/viewer/viewer';
|
||||||
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줄) */}
|
||||||
|
|
@ -138,8 +136,6 @@ 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 일 때만 페이지를 렌더링이 되는 변수 사용.
|
||||||
}
|
}
|
||||||
|
|
@ -252,9 +248,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} />} />
|
||||||
|
|
@ -308,7 +304,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 />} />
|
||||||
|
|
@ -331,10 +327,9 @@ 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={<StandardCodePage />} />
|
<Route path={URL.STANDARD_CODE_LIST} element={<StandardCodeList />} />
|
||||||
<Route path={URL.STANDARD_CODE_LIST_LINK} element={<StandardCodePage />} />
|
<Route path={URL.STANDARD_CODE_LIST_LINK} element={<StandardCodeList />} />
|
||||||
|
|
||||||
</Routes>
|
</Routes>
|
||||||
<EgovFooter />
|
<EgovFooter />
|
||||||
|
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
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
|
|
||||||
};
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
// ==============================|| OVERRIDES - BADGE ||============================== //
|
|
||||||
|
|
||||||
export default function Badge(theme) {
|
|
||||||
return {
|
|
||||||
MuiBadge: {
|
|
||||||
styleOverrides: {
|
|
||||||
standard: {
|
|
||||||
minWidth: theme.spacing(2),
|
|
||||||
height: theme.spacing(2),
|
|
||||||
padding: theme.spacing(0.5)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
// ==============================|| 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
// ==============================|| OVERRIDES - CARD CONTENT ||============================== //
|
|
||||||
|
|
||||||
export default function CardContent() {
|
|
||||||
return {
|
|
||||||
MuiCardContent: {
|
|
||||||
styleOverrides: {
|
|
||||||
root: {
|
|
||||||
padding: 20,
|
|
||||||
'&:last-child': {
|
|
||||||
paddingBottom: 20
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
// ==============================|| OVERRIDES - CHECKBOX ||============================== //
|
|
||||||
|
|
||||||
export default function Checkbox(theme) {
|
|
||||||
return {
|
|
||||||
MuiCheckbox: {
|
|
||||||
styleOverrides: {
|
|
||||||
root: {
|
|
||||||
color: theme.palette.secondary[300]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
// ==============================|| 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
// ==============================|| 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'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
// ==============================|| 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'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
// ==============================|| OVERRIDES - LINER PROGRESS ||============================== //
|
|
||||||
|
|
||||||
export default function LinearProgress() {
|
|
||||||
return {
|
|
||||||
MuiLinearProgress: {
|
|
||||||
styleOverrides: {
|
|
||||||
root: {
|
|
||||||
height: 6,
|
|
||||||
borderRadius: 100
|
|
||||||
},
|
|
||||||
bar: {
|
|
||||||
borderRadius: 100
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
// ==============================|| OVERRIDES - LINK ||============================== //
|
|
||||||
|
|
||||||
export default function Link() {
|
|
||||||
return {
|
|
||||||
MuiLink: {
|
|
||||||
defaultProps: {
|
|
||||||
underline: 'hover'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
// ==============================|| OVERRIDES - LIST ITEM ICON ||============================== //
|
|
||||||
|
|
||||||
export default function ListItemIcon() {
|
|
||||||
return {
|
|
||||||
MuiListItemIcon: {
|
|
||||||
styleOverrides: {
|
|
||||||
root: {
|
|
||||||
minWidth: 24
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
// 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
// ==============================|| OVERRIDES - TAB ||============================== //
|
|
||||||
|
|
||||||
export default function Tab(theme) {
|
|
||||||
return {
|
|
||||||
MuiTab: {
|
|
||||||
styleOverrides: {
|
|
||||||
root: {
|
|
||||||
minHeight: 46,
|
|
||||||
color: theme.palette.text.primary
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
// ==============================|| 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
// ==============================|| OVERRIDES - TABS ||============================== //
|
|
||||||
|
|
||||||
export default function Tabs() {
|
|
||||||
return {
|
|
||||||
MuiTabs: {
|
|
||||||
styleOverrides: {
|
|
||||||
vertical: {
|
|
||||||
overflow: 'visible'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
// ==============================|| OVERRIDES - TYPOGRAPHY ||============================== //
|
|
||||||
|
|
||||||
export default function Typography() {
|
|
||||||
return {
|
|
||||||
MuiTypography: {
|
|
||||||
styleOverrides: {
|
|
||||||
gutterBottom: {
|
|
||||||
marginBottom: 12
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
// 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()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
// 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;
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
// 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;
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
||||||
// ==============================|| 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;
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
// ==============================|| 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;
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
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,11 +1,7 @@
|
||||||
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;
|
||||||
|
|
@ -13,15 +9,10 @@ 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;
|
||||||
|
|
||||||
|
|
@ -33,7 +24,6 @@ public class AdminBoardsController extends BaseController {
|
||||||
|
|
||||||
private final AdminBoardsService adminBoardsService;
|
private final AdminBoardsService adminBoardsService;
|
||||||
|
|
||||||
/* ---- 게시판관리 ----- */
|
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "게시판 목록 조회",
|
summary = "게시판 목록 조회",
|
||||||
description = "게시판 목록 조회",
|
description = "게시판 목록 조회",
|
||||||
|
|
@ -52,82 +42,4 @@ 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,8 +6,7 @@ import org.hibernate.annotations.DynamicInsert;
|
||||||
import org.hibernate.annotations.DynamicUpdate;
|
import org.hibernate.annotations.DynamicUpdate;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import javax.validation.constraints.NotBlank;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
|
|
@ -23,25 +22,22 @@ 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 String bbsAnsYn;
|
private char bbsAnsYn;
|
||||||
|
|
||||||
@Column(name = "bbs_repl_yn", nullable = false)
|
@Column(name = "bbs_repl_yn", nullable = false)
|
||||||
private String bbsReplYn;
|
private char bbsReplYn;
|
||||||
|
|
||||||
@Column(name = "read_role_grp_id")
|
@Column(name = "read_role_grp_id")
|
||||||
private String readRoleGrpId;
|
private String readRoleGrpId;
|
||||||
|
|
@ -56,16 +52,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 LocalDateTime frstCrtDt;
|
private LocalDate 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 LocalDateTime lastChgDt;
|
private LocalDate lastChgDt;
|
||||||
|
|
||||||
@Column(name = "use_yn", nullable = false)
|
@Column(name = "use_yn", nullable = false)
|
||||||
private String useYn;
|
private char useYn;
|
||||||
|
|
||||||
@Column(name = "oldd_seq")
|
@Column(name = "oldd_seq")
|
||||||
private Long olddSeq;
|
private Long olddSeq;
|
||||||
|
|
|
||||||
|
|
@ -1,83 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
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,13 +2,7 @@ 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,71 +1,19 @@
|
||||||
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() {
|
public List<TnBbs> selectBoardList() { return tnBbsRepository.findAll(); }
|
||||||
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,8 +1,6 @@
|
||||||
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;
|
||||||
|
|
@ -11,21 +9,20 @@ 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.*;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import 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;
|
||||||
|
|
@ -40,9 +37,6 @@ 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 = "기본코드 그룹 조회",
|
||||||
|
|
@ -356,50 +350,4 @@ 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,75 +0,0 @@
|
||||||
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,10 +1,8 @@
|
||||||
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;
|
||||||
|
|
@ -12,8 +10,6 @@ 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;
|
||||||
|
|
@ -34,116 +30,57 @@ 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.POST, value = "/menu-login", consumes = MediaType.APPLICATION_JSON_VALUE)
|
@RequestMapping(method = RequestMethod.GET, value = "/daily-user-log-list", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||||
public ResultVO getMenuVisit(@AuthenticationPrincipal LoginVO user)
|
public ResultVO getDailyUserLogList() throws Exception {
|
||||||
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());
|
// 현재 날짜
|
||||||
resultMap.put("menuDailyList", adminDashboardService.selectMenuDaily());
|
// todo endDate 뒤에 .minus 지워야함
|
||||||
resultMap.put("loginMonthlyList", adminDashboardService.selectLoginMonthly());
|
LocalDate endDate = LocalDate.now().minusMonths(6);
|
||||||
resultMap.put("loginDailyList", adminDashboardService.selectLoginDaily());
|
// 3개월 전 날짜 계산
|
||||||
|
LocalDate startDate = endDate.minusMonths(3);
|
||||||
|
|
||||||
resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
|
resultMap.put("dailyUserLogList", adminDashboardService.selectDailyUserLogList(startDate, endDate));
|
||||||
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.POST, value = "/file", consumes = MediaType.APPLICATION_JSON_VALUE)
|
@RequestMapping(method = RequestMethod.GET, value = "/monthly-user-log-list", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||||
public ResultVO getfile(@AuthenticationPrincipal LoginVO user)
|
public ResultVO getMonthlyUserLogList() throws Exception {
|
||||||
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);
|
||||||
|
|
||||||
resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
|
List<Object[]> result = adminDashboardService.selectMonthlyUserLogList(startDate, endDate);
|
||||||
resultVO.setResultMessage(ResponseCode.SUCCESS.getMessage());
|
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);
|
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;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,83 +0,0 @@
|
||||||
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,38 +1,24 @@
|
||||||
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.MenuMonthlyRepository;
|
import com.dbnt.kcscbackend.admin.dashboard.repository.TnDailyUserLogRepository;
|
||||||
//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<Long> selectMenuMonthly() { return menuMonthlyRepository.MenuMonthlyList(); }
|
public List<TnDailyUserLog> selectDailyUserLogList(LocalDate startDate, LocalDate endDate) {
|
||||||
|
return tnDailyUserLogRepository.findByLogDtBetweenOrderByLogDt(startDate, endDate);
|
||||||
public List<Long> selectMenuDaily() { return menuMonthlyRepository.MenuDailyList(); }
|
}
|
||||||
|
|
||||||
public List<Long> selectLoginMonthly() { return menuMonthlyRepository.LoginMonthlyList(); }
|
public List<Object[]> selectMonthlyUserLogList(LocalDate startDate, LocalDate endDate) {
|
||||||
|
return tnDailyUserLogRepository.selectMonthlyUserLogStatistics(startDate, endDate);
|
||||||
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,6 +1,8 @@
|
||||||
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;
|
||||||
|
|
@ -9,6 +11,7 @@ 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 egovJwtTokenUtil.getUserIdFromToken(clientToken).equals("admin");
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,6 @@ 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}$")
|
||||||
@NotBlank(message = "아이디를 입력해주세요.")
|
@NotBlank(message = "아이디를 입력해주세요.")
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,5 @@ 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,7 +67,6 @@ 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,8 +57,7 @@ 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{
|
||||||
|
|
@ -70,13 +69,7 @@ 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/**"
|
"/standardCode/**.do"
|
||||||
};
|
};
|
||||||
private static final String[] ORIGINS_WHITELIST = {
|
private static final String[] ORIGINS_WHITELIST = {
|
||||||
"http://localhost:3000",
|
"http://localhost:3000",
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ 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;
|
||||||
|
|
@ -61,7 +60,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.GET, value = "/code-tree")
|
@RequestMapping(method = RequestMethod.POST, value = "/getCodeTree.do", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||||
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<>();
|
||||||
|
|
@ -99,8 +98,8 @@ public class StandardCodeController extends BaseController {
|
||||||
@ApiResponse(responseCode = "200", description = "조회 성공"),
|
@ApiResponse(responseCode = "200", description = "조회 성공"),
|
||||||
@ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
|
@ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
|
||||||
})
|
})
|
||||||
@GetMapping(value = "/code-info", consumes = MediaType.APPLICATION_JSON_VALUE)
|
@PostMapping(value = "/getCodeInfo.do", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||||
public ResultVO getCodeInfo(StandardCodeVO param, @AuthenticationPrincipal LoginVO user)
|
public ResultVO getCodeInfo(@RequestBody 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<>();
|
||||||
|
|
@ -152,10 +151,25 @@ 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<>();
|
||||||
|
|
||||||
tnDocumentInfo.makeListCode();
|
String tab = tnDocumentInfo.getTab() != null ? tnDocumentInfo.getTab() : "";
|
||||||
tnDocumentInfo.setUserSeq(user.getUserSeq());
|
String category1 = tnDocumentInfo.getCategory1() != null ? tnDocumentInfo.getCategory1() : "";
|
||||||
resultMap.put("resultList", standardCodeService.selectStandardCodeList(tnDocumentInfo));
|
String category2 = tnDocumentInfo.getCategory2() != null ? tnDocumentInfo.getCategory2() : "";
|
||||||
resultMap.put("resultCnt", standardCodeService.selectStandardCodeListCnt(tnDocumentInfo));
|
String category3 = tnDocumentInfo.getCategory3() != null ? tnDocumentInfo.getCategory3() : "";
|
||||||
|
|
||||||
|
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());
|
||||||
|
|
@ -163,84 +177,6 @@ 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,7 +10,6 @@ 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
|
||||||
|
|
@ -29,24 +28,15 @@ 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;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
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,6 +1,5 @@
|
||||||
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;
|
||||||
|
|
@ -93,18 +92,11 @@ 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