MinsoftK

front-end 삭제할 파일 잔류

This diff is collapsed. Click to expand it.
.App {
text-align: center;
.trigger {
font-size: 18px;
line-height: 64px;
padding: 0 24px;
cursor: pointer;
transition: color 0.3s;
}
.App-logo {
height: 40vmin;
pointer-events: none;
.trigger:hover {
color: #1890ff;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
.logo {
height: 32px;
background: rgba(255, 255, 255, 0.2);
margin: 16px;
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
.site-layout .site-layout-background {
background: #fff;
}
\ No newline at end of file
......
.site-layout .site-layout-background {
background: #fff;
}
[data-theme="dark"] .site-layout .site-layout-background {
background: #141414;
}
/*
.ant-menu-item.ant-menu-item-only-child.ant-menu-item:link {
background-color: red;
}
.ant-menu-item.ant-menu-item-only-child.ant-menu-item:visited {
background-color: red;
}
*/
.logout {
position: absolute;
right:15px;
top:15px;
text-align: center;
justify-content: center;
}
\ No newline at end of file
This diff is collapsed. Click to expand it.
import React,{useState} from 'react';
import LoginForm from '../component/LoginForm';
import { getLoginInfo } from '../lib/api/login';
import {Redirect, withRouter} from "react-router-dom";
const fetchLogInfo= async(data) =>{
try{
const result = await getLoginInfo(data);
if(result.status ===200){
console.log("서버 데이터와 일치: "+ result.data ); // result의 반환값 확인
return true;
}
} catch(e){
console.log(e);
alert("id와 비밀번호를 확인해주세요!");
return false;
}
}
const Login = () => {
const [authenticated,setAuthenticated] = useState(false);
const onFinish = async (values)=> {
console.log('Received values of form: ', values);
const isAuth = await fetchLogInfo(values);
sessionStorage.setItem("isAuth", isAuth); //세션 스토리지 저장
sessionStorage.setItem("id",values.userid);
setAuthenticated(isAuth);
}
if(authenticated){
// history.push('/Home');
return <Redirect to="/Home"/>
}else{
return <LoginForm onFinish={onFinish} >
</LoginForm>
}
};
export default withRouter(Login);
.trigger {
font-size: 18px;
line-height: 64px;
padding: 0 24px;
cursor: pointer;
transition: color 0.3s;
}
.trigger:hover {
color: #1890ff;
}
.logo {
height: 32px;
background: rgba(255, 255, 255, 0.2);
margin: 16px;
}
.site-layout .site-layout-background {
background: #fff;
}
div.demo-editor.rdw-editor-main {
border: 1px solid #f1f1f1;
height: 65vh;
}
\ No newline at end of file
import React, { useState, useEffect, useCallback } from 'react';
import { Drawer, message } from 'antd';
import { UploadOutlined, RetweetOutlined } from '@ant-design/icons';
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';
import { getTexToSvg, checkQno, saveFileAndQno } from '../lib/api/tikz'; // Request api
import TikzForm from '../component/tikzForm';
const fetchTexToSvg = async (data) => {
// getTexToSvg api를 이용하기 위한 const
try {
const result = await getTexToSvg({ tex: data });
if (result.status === 200) {
console.log(result.status);
console.log(result.data);
return result.data;
}
} catch (e) {
console.log(e);
//Notification. 추가해서 변환상태 알려주기
return null;
}
};
const fetchSaveData = async (data) => {
try{
const result = await saveFileAndQno(data);
console.log(result);
if(result.status===200){
return result.data;
}
}catch(e){
console.log(e);
message.warning(e.message);
}
}
/* 문항번호 체크 */
const fetchCheckQno = async(qno) => {
try{
const result = await checkQno(qno);
if(result.status===200){
console.log(result);
message.info("사용 가능한 문항 번호 입니다.");
return true;
}else{
message.info("존재 하지 않는 문항 번호 입니다.");
return false;
}
}catch(e){
console.log(e);
message.info("존재 하지 않는 문항 번호 입니다.");
return false;
}
}
const _tikzcode= "% 예시 (x축, y축, 반지름이 1cm인 원의 그림) %\n\
% 오른쪽의 변환 버튼을 눌러보세요! %\n\n\
\\documentclass{article}\n\
\\usepackage{tikz}\n\
\\begin{document}\n\n\n\
\\begin{tikzpicture}\n\
\\draw (-1.5,0) -- (1.5,0);\n\
\\draw (0,-1.5) -- (0,1.5);\n\
\\draw (0,0) circle (1cm);\n\
\\end{tikzpicture}\n\n\n\
\\end{document}";
const Tikz = ({ onLeave, visible, callback, selectItem, mode }) => {
const [fields,setFields] =useState([]);
const [qno, setQno] = useState(null);
const [number, setNumber] = useState(null); //문항번호를 저장하는 state
const [inputText, setinputText] = useState(_tikzcode); //tikz code를 저장하는 state
const [svg, setSvg] = useState(null); //변환된 svg 데이터를 저장하는 state
const [qnoCheck,setQnoCheck] = useState(false);
const [tikzcode,setTikzCode] = useState(_tikzcode);
//svg
//onclickevent : Tikz 변환하기 Button의 onClick Event
//onChangeTikz : TextArea 컴포넌트의 onChange event
//onFinish : Form data를 제출하기 위한 event
useEffect(()=> {
if(mode==='preview'&&selectItem){
console.log(selectItem);
let initFields = [
{name:['qno'],value:selectItem.qno},
{name:['typeSol'],value:selectItem.typeSol},
{name:['typeQue'],value:selectItem.typeQue},
{name:['creator'],value:selectItem.creator},
];
setQno(selectItem.qno);
setTikzCode(selectItem.tex);
setFields(initFields);
setSvg(null);
}
},[mode, selectItem]);
useEffect(()=>{
if(mode === 'new'){
let initFields = [
{name:['qno'],value:null},
{name:['typeSol'],value:null},
{name:['typeQue'],value:null},
{name:['creator'],value:null},
];
setQno(null);
setTikzCode(_tikzcode);
setFields(initFields);
setSvg(null);
}
},[mode]);
const onClickEvent = (e) => {
if(inputText){
callbackSVG(inputText);
}
if (inputText === null) {
console.log(inputText);
alert(
//data에 null이 입력된 경우
'Code 값을 입력해주세요!'
);
} else {
console.log(inputText);
callbackSVG(inputText);
}
};
const onChangeQno = (value) => {
console.log(value);
setQno(value);
setFields([...fields, {name:['qno'],value:value}]);
};
/*
useEffect(()=>{
if(!visible ){
let initFields = [
{name:['qno'],value:null},
{name:['typeSol'],value:null},
{name:['typeQue'],value:null},
{name:['creator'],value:null},
];
setQno(null);
setTikzCode(tikzcode);
setFields(initFields);
}
},[visible,mode]);
*/
const callbackSVG = useCallback(async () => {
const result = await fetchTexToSvg(inputText);
setSvg(result); //api로 받아온 result를 svg state에 저장
}, [inputText]);
const onChangeTikz = (e) => {
if (e) {
setinputText(e.target.value);
} else setinputText(null);
};
const onSaveEvent = () => {
try {
//서버에 저장이 확인 됐을때 200, 500(오류) http status
const result = alert('전송이 성공적으로 완료됐습니다.');
} catch (e) {
//서버에 저장 오류가 났을때
console.log(e);
alert(e);
}
};
const onClickQno = async(e)=>{
e.preventDefault();
//번호가 호출 성공시 setQnoCheck(true);
if(qno){
const _checkQno= await fetchCheckQno(qno);
setQnoCheck(_checkQno);
}
};
const onFinish = async(values) => {
console.log(values);
console.log(qnoCheck);
if(!qnoCheck){
message.warning("문제 번호를 확인해 주세요.")
return;
}else{
const creator = sessionStorage.getItem('id');
console.log('Received values of form: ', values);
const result = await fetchSaveData({...values, creator});
console.log(result);
if(result){
message.info(result.message);
let initFields = [
{name:['qno'],value:null},
{name:['typeSol'],value:null},
{name:['typeQue'],value:null},
{name:['creator'],value:null},
];
setFields(initFields);
onLeave();
callback({status:'SAVE_OK'});
setQno(null);
}else{
callback({status:'SAVE_FAIL'})
}
}
};
const onChangeTypeSol = (value) => {
console.log(value);
setFields([...fields, {name:['typeSol'],value:value}]);
}
const onChangeTypeQue = (value) => {
console.log(value);
setFields([...fields, {name:['typeQue'],value:value}])
}
return (
<Drawer
title={'Tikz Editor'}
placement={'bottom'}
closable={true}
height={'90vh'}
onClose={onLeave}
visible={visible}>
<TikzForm
svg={svg}
onClickEvent={onClickEvent}
onChangeTikz={onChangeTikz}
onSaveEvent={onSaveEvent}
onFinish={onFinish}
tikzcode={tikzcode}
fields={fields}
onClickQno={onClickQno}
onChangeQno={onChangeQno}
onChangeTypeSol={onChangeTypeSol}
onChangeTypeQue={onChangeTypeQue}
qno={qno}>
</TikzForm>
</Drawer>
);
};
export default Tikz;
//<Transform value={tikzHtml}></Transform>
import React from 'react';
import { Menu, Dropdown, Button } from 'antd';
//import Scroll from '../component/Slider';
// 화살표 함수에서 {} 가 들어가는 경우에는 처리해야 되는 루틴이 있을때 return 값만 있을때는 () or 생략도 가능하다.
//
//기본적인 도형들을 그리는 도형상수
const draw = () => (
<Menu>
<Menu.Item>
<button onclick="">Triangle</button>
</Menu.Item>
<Menu.Item>
<a
target="_blank"
rel="noopener noreferrer"
href="http://www.taobao.com/">
Rectangle
</a>
</Menu.Item>
<Menu.Item>
<a target="_blank" rel="noopener noreferrer" href="http://www.tmall.com/">
pentagon
</a>
</Menu.Item>
<Menu.Item danger>도형 디자인</Menu.Item>
</Menu>
);
//기본적인 그래프를 그리는 그래프 상수
const graph = () => (
<Menu>
<Menu.Item>
<a
target="_blank"
rel="noopener noreferrer"
href="http://www.alipay.com/">
2차함수
</a>
</Menu.Item>
<Menu.Item>
<a
target="_blank"
rel="noopener noreferrer"
href="http://www.taobao.com/">
3차함수
</a>
</Menu.Item>
<Menu.Item danger>함수 디자인</Menu.Item>
</Menu>
);
// x축 y축을 그리게 만드는 상수
const grid = () => (
<Menu>
<Menu.Item>
<a
target="_blank"
rel="noopener noreferrer"
href="http://www.alipay.com/">
2차원
</a>
</Menu.Item>
<Menu.Item>
<a
target="_blank"
rel="noopener noreferrer"
href="http://www.taobao.com/">
3차원
</a>
</Menu.Item>
<Menu.Item>
<a target="_blank" rel="noopener noreferrer" href="http://www.tmall.com/">
3rd menu item
</a>
</Menu.Item>
<Menu.Item danger>좌표축 디자인</Menu.Item>
</Menu>
);
// 수학 공식들을 선택하는 상수
const MathFunction = () => (
<Menu>
<Menu.Item>
<a
target="_blank"
rel="noopener noreferrer"
href="http://www.alipay.com/"></a>
</Menu.Item>
<Menu.Item>
<a
target="_blank"
rel="noopener noreferrer"
href="http://www.taobao.com/">
2nd menu item
</a>
</Menu.Item>
<Menu.Item>
<a target="_blank" rel="noopener noreferrer" href="http://www.tmall.com/">
3rd menu item
</a>
</Menu.Item>
<Menu.Item danger>a danger item</Menu.Item>
</Menu>
);
//위의 상수 값들을 집어넣어 Dropdowm 메뉴 바들을 구성해준다.
const DropMenu = () => (
//위의 상수 값들을 집어넣어 Dropdowm 메뉴 바들을 구성해준다. const DropMenu
<div style={{ display: 'inline-block' }}>
<Dropdown overlay={draw} placement="bottomLeft" arrow>
<Button>Draw</Button>
</Dropdown>
<Button>Graph</Button>
<Dropdown overlay={grid} placement="bottomRight" arrow>
<Button>Grid</Button>
</Dropdown>
<Dropdown overlay={MathFunction} arrow>
<Button>Function</Button>
</Dropdown>
</div>
);
export default DropMenu;
//<Scroll> </Scroll>
\ No newline at end of file
import React from 'react';
import { Form, Input, Button, Checkbox, Row, Col } from 'antd';
import { UserOutlined, LockOutlined } from '@ant-design/icons';
import {HeartOutlined} from '@ant-design/icons';
const LoginForm = ({onFinish},) => {
return (
<Form name="normal_login" className="login-form" initialValues={{remember: true, }} onFinish={onFinish}>
<Row justify="center" style={{marginTop:'80px'}}>
<HeartOutlined />
</Row>
<Row justify="center" style={{marginTop:'20px'}}>
<Col>
<Form.Item name="userid" rules={[{required: true, message: 'id를 입력해주세요.', },]}>
<Input prefix={<UserOutlined className="site-form-item-icon" />} placeholder="User id" />
</Form.Item>
</Col>
</Row>
<Row justify="center" style={{marginTop:'10px'}}>
<Col>
<Form.Item name="userpwd" rules={[{required: true, message: '비밀번호를 입력해주세요.'},]}>
<Input prefix={<LockOutlined className="site-form-item-icon" />} type="password" placeholder="Password"/>
</Form.Item>
</Col>
</Row>
<Row justify="center" style={{marginTop:'10px'}}>
<Col>
<Form.Item name="remember" valuePropName="checked" noStyle>
<Checkbox>Remember me</Checkbox>
</Form.Item>
</Col>
</Row>
<Row justify="center" style={{marginTop:'10px'}}>
<Col>
<Form.Item>
<Button type="primary" htmlType="submit" className="login-form-button">
로그인하기
</Button>
</Form.Item>
</Col>
</Row>
</Form>
);
}
export default LoginForm;
\ No newline at end of file
import React,{Flagment} from 'react';
import { Drawer, Input, Button, Menu, Form, Col, Row, AutoComplete, Tooltip, Select } from 'antd';
import { UploadOutlined, RetweetOutlined } from '@ant-design/icons';
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';
import { PanZoom } from 'react-easy-panzoom';
import { InputNumber } from 'antd';
import { IFrame } from './iframe';
import './tikzForm.css';
const { TextArea } = Input;
const {Option} = Select;
const TikzForm = ({ svg, onClickEvent, onChangeTikz, onFinish, onChangeQno, onClickQno, tikzcode, fields, qno, onChangeTypeSol,onChangeTypeQue}) => {
//svg
//onclickevent : Tikz 변환하기 Button의 onClick Event
//onChangeTikz : TextArea 컴포넌트의 onChange event
//onFinish : Form data를 제출하기 위한 event
//onSaveEvent : Tikz 등록하기의 버튼 event
console.log(fields);
return (
<Form onFinish={onFinish} fields={[...fields]}>
<Form.Item
name="qno"
label="문제 번호"
rules={[
{
required: true,
message: '문항번호를 입력해 주세요.',
},
]}><Row>
<Col>
<InputNumber
min={0}
max={10000}
value={qno}
onChange={onChangeQno}>
</InputNumber>
</Col>
<Col>
<Button onClick={onClickQno}>번호 확인</Button>
</Col>
</Row>
</Form.Item>
<Form.Item
name="typeSol"
label="문제 타입"
wrapperCol={{span: 2 }}
rules={[
{
required: true,
message: '문제 타입을 선택해 주세요.',
},
]}>
<Select onChange={onChangeTypeSol}>
<Option value="오지선다형">오지선다형</Option>
<Option value="단답형">단답형</Option>
<Option value="계산식">계산식</Option>
</Select>
</Form.Item>
<Form.Item
name="typeQue"
label="문제/풀이 구분"
rules={[
{
required: true,
message: '문제/풀이 구분을 선택해 주세요.',
},
]}
wrapperCol={{span: 2 }}
>
<Select onChange={onChangeTypeQue}>
<Option value="문제">문제</Option>
<Option value="풀이">풀이</Option>
</Select>
</Form.Item>
<Row justify="space-between" align="middle">
<Col span={11}>
<Form.Item name="tikzCode" rules={[{ required: true, message: 'tikz 코드를 입력해 주세요.' }]} initialValue={tikzcode}>
<TextArea
style={{ width: '44vw', height: '70vh' }}
onChange={onChangeTikz}
/>
</Form.Item>
</Col>
<Col span={2} style={{textAlign:'center'}} >
<Tooltip title={'tikz 미리보기'}>
<Button type="ghost" icon={<RetweetOutlined />} onClick={onClickEvent}></Button>
</Tooltip>
</Col>
<Col span={11} >
<IFrame
style={{
width: '44vw',
height: '70vh',
marginTop: '-15px',
border: '1px solid #d9d9d9',
}}>
<PanZoom
style={{
display: 'block',
outline: 'none',
width: '44vw',
height: '70vh',
margin: '0px',
}}>
<div dangerouslySetInnerHTML={{ __html: svg }} />
</PanZoom>
</IFrame>
</Col>
</Row>
<Form.Item>
<Button type="primary" htmlType="submit">
저장하기
</Button>
</Form.Item>
</Form>
);
};
export default TikzForm;
import { Upload, Button, message } from 'antd';
import { UploadOutlined } from '@ant-design/icons';
import reqwest from 'reqwest';
class Demo extends React.Component {
state = {
fileList: [],
uploading: false,
};
handleUpload = () => {
const { fileList } = this.state;
const formData = new FormData();
fileList.forEach((file) => {
formData.append('files[]', file);
});
this.setState({
uploading: true,
});
// You can use any AJAX library you like
reqwest({
url: 'https://localhost:5000/user',
method: 'post',
processData: false,
data: formData,
success: () => {
this.setState({
fileList: [],
uploading: false,
});
message.success('upload successfully.');
},
error: () => {
this.setState({
uploading: false,
});
message.error('upload failed.');
},
});
};
render() {
const { uploading, fileList } = this.state;
const props = {
onRemove: (file) => {
this.setState((state) => {
const index = state.fileList.indexOf(file);
const newFileList = state.fileList.slice();
newFileList.splice(index, 1);
return {
fileList: newFileList,
};
});
},
beforeUpload: (file) => {
this.setState((state) => ({
fileList: [...state.fileList, file],
}));
return false;
},
fileList,
};
return (
<>
<Upload {...props}>
<Button>
<UploadOutlined /> Select File
</Button>
</Upload>
<Button
type="primary"
onClick={this.handleUpload}
disabled={fileList.length === 0}
loading={uploading}
style={{ marginTop: 16 }}>
{uploading ? 'Uploading' : 'Start Upload'}
</Button>
</>
);
}
}
......@@ -2,16 +2,21 @@ import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import * as serviceWorker from './serviceWorker';
import { createBrowserHistory } from 'history';
import { BrowserRouter,Router } from 'react-router-dom';
const history = createBrowserHistory();
//<BrowserRouter history={history}></BrowserRouter>
ReactDOM.render(
<React.StrictMode>
<BrowserRouter history={history}>
<App />
</React.StrictMode>,
</BrowserRouter>
,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
......
import axios from 'axios';
import qs from 'qs';
export const checkFiles = (data, whatUpload) => {
const options = {
method: 'POST',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
data: qs.stringify(data),
url: 'http://localhost:5000/{whatUpload}',
};
return axios(options);
};
//export const tikz = (id) => tikz.post(`/users?id=${id != null ? id : ''}`);
//export const testAdd = (name, tel) => client.post('/users/add', { name, tel });
import axios from 'axios';
const client = axios.create();
client.defaults.baseURL = '';
client.defaults.withCredentials = true;
export default client;
import client from './client';
export const feedbackFind = () => client.get('/commenter');
export const feedbackAdd = (nickname, comment) =>
client.post('/commenter/add', { nickname, comment });
import axios from 'axios';
const hostMath = "http://ai.natmal.com:7070";
export const checkQno = (qno) => axios.get(`${hostMath}/checkQno?qno=${qno}`);
export const saveFileAndQno = (formData) =>
{
return axios({
method: 'post',
url: '/upload/html',
data: formData,
headers: {
'Content-Type': 'multipart/form-data',
},
});
}
export const getData = (user, pageSize, currentPage,orderWhat,orderKind) => axios.post('/tikzs',{user, pageSize, currentPage,orderWhat,orderKind});
import axios from 'axios';
import qs from 'qs';
export const getLoginInfo = (data) =>
{
const options = {
method: 'POST',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
data: qs.stringify(data),
url:'http://ai.natmal.com:7070/checkUser',
};
return axios(options);
}
//export const tikz = (id) => tikz.post(`/users?id=${id != null ? id : ''}`);
//export const testAdd = (name, tel) => client.post('/users/add', { name, tel });
import axios from 'axios';
import qs from 'qs';
export const matchInfo = (data) =>
{
const options = {
method: 'GET',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
data: qs.stringify(data),
url:'http://localhost:5000/users',
};
return axios(options);
}
//export const tikz = (id) => tikz.post(`/users?id=${id != null ? id : ''}`);
//export const testAdd = (name, tel) => client.post('/users/add', { name, tel });
import axios from 'axios';
const hostMath = 'http://ai.natmal.com:7070';
export const checkQno = (qno) => axios.get(`${hostMath}/checkQno?qno=${qno}`);
export const saveFileAndQno = (formData) =>
{
console.log(formData);
return axios({
method: 'post',
url: '/upload/math',
data: formData,
headers: {
'Content-Type': 'multipart/form-data',
},
});
}
//export const getMathData = (user, pageSize, currentPage,orderWhat) => axios.post('/tikzs',{user, pageSize, currentPage,ordeWhat});
import client from './client';
export const testFind = (id) => client.get(`/users?id=${id != null ? id : ''}`);
export const testAdd = (name, tel) => client.post('/users/add', { name, tel });
export const testEdit = (id, name, tel) =>
client.post('/users/edit', { id, name, tel });
export const testDelete = (id) => client.get('/users/delete?id=' + id);
import axios from 'axios';
import qs from 'qs';
export const getTexToSvg = (data) =>
{
const options = {
method: 'POST',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
data: qs.stringify(data),
url:'http://ai.natmal.com:9292',
};
return axios(options);
}
const hostMath = "http://ai.natmal.com:7070";
export const checkQno = (qno) => axios.get(`${hostMath}/checkQno?qno=${qno}`);
export const saveFileAndQno = (data) => axios.post('/upload/tikz',{...data});
export const removeItem = (id) => axios.get(`/tikzs/removeItem?id=${id}`);
export const removeItems = (ids) => axios.post("/tikzs/removeItems",{ids});
//export const getData = (user, pageSize, currentPage,orderWhat) => axios.post('/tikzs',{user, pageSize, currentPage,ordeWhat});
//export const tikz = (id) => tikz.post(`/users?id=${id != null ? id : ''}`);
//export const testAdd = (name, tel) => client.post('/users/add', { name, tel });