Showing
3 changed files
with
296 additions
and
20 deletions
1 | -import logo from './logo.svg'; | 1 | +import React,{useState, useEffect} from 'react'; |
2 | -import './App.css'; | 2 | +import { Route, Redirect, withRouter, Switch} from 'react-router-dom'; |
3 | +import { Home, Html, Mathcha, Tikz, Login} from './Container'; | ||
4 | +import {isauth} from './Container/Login'; | ||
5 | +//import {ConnectedRouter} from 'connected-react-router'; | ||
3 | 6 | ||
4 | -function App() { | 7 | + |
8 | +const authentication = () => {} | ||
9 | + | ||
10 | + | ||
11 | +function App() { | ||
5 | return ( | 12 | return ( |
6 | - <div className="App"> | 13 | + <div> |
7 | - <header className="App-header"> | 14 | + <Switch> |
8 | - <img src={logo} className="App-logo" alt="logo" /> | 15 | + <Route exact path="/" component={Login}/> |
9 | - <p> | 16 | + <Route path="/Home" component={Home}/> |
10 | - Edit <code>src/App.js</code> and save to reload. | 17 | + </Switch> |
11 | - </p> | ||
12 | - <a | ||
13 | - className="App-link" | ||
14 | - href="https://reactjs.org" | ||
15 | - target="_blank" | ||
16 | - rel="noopener noreferrer" | ||
17 | - > | ||
18 | - Learn React | ||
19 | - </a> | ||
20 | - </header> | ||
21 | </div> | 18 | </div> |
22 | ); | 19 | ); |
23 | } | 20 | } |
24 | - | 21 | +//history를 쓰는 경우는 Link |
25 | -export default App; | 22 | +export default withRouter(App); | ... | ... |
minsung/src/Container/Html.js
0 → 100644
1 | +import React, { useState, useEffect } from 'react'; | ||
2 | +import { Modal, Upload, message, Form, InputNumber, Button , Select ,Row, Col} from 'antd'; | ||
3 | +import { InboxOutlined, LockOutlined, SaveTwoTone } from '@ant-design/icons'; | ||
4 | +import { saveFileAndQno } from 'lib/api/html'; | ||
5 | +import { checkQno } from '../lib/api/html'; | ||
6 | + | ||
7 | +const { Option} = Select; | ||
8 | +//파일 업로드 | ||
9 | +//업로드 폼에서의 로직 | ||
10 | + | ||
11 | +const fetchSaveData = async (data) => { | ||
12 | + try{ | ||
13 | + console.log(data); | ||
14 | + const result = await saveFileAndQno(data); | ||
15 | + if(result.status===200){ | ||
16 | + return result.data; | ||
17 | + } | ||
18 | + }catch(e){ | ||
19 | + console.log(e); | ||
20 | + message.warn(e.message); | ||
21 | + } | ||
22 | +} | ||
23 | + | ||
24 | +const fetchCheckQno = async(qno) => { | ||
25 | + try{ | ||
26 | + const result = await checkQno(qno); | ||
27 | + if(result.status===200){ | ||
28 | + console.log(result); | ||
29 | + message.info("사용 가능한 문항 번호 입니다."); | ||
30 | + return true; | ||
31 | + }else{ | ||
32 | + message.info("존재 하지 않는 문항 번호 입니다."); | ||
33 | + return false; | ||
34 | + } | ||
35 | + }catch(e){ | ||
36 | + console.log(e); | ||
37 | + message.info("존재 하지 않는 문항 번호 입니다."); | ||
38 | + return false; | ||
39 | + } | ||
40 | +} | ||
41 | + | ||
42 | +const Html = ({ visible, onCancel, callback }) => { | ||
43 | + const [fields,setFields] =useState([]); | ||
44 | + const [qno, setQno] = useState(null); | ||
45 | + const [upload,setUpload]=useState(false); | ||
46 | + const [fileList, setFileList]=useState([]); | ||
47 | + const [qnoCheck,setQnoCheck] =useState(false); | ||
48 | + | ||
49 | + | ||
50 | + const changeNumber = (value) => { | ||
51 | + setQno(value); | ||
52 | + setFields([...fields, {name:['qno'],value:value}]); | ||
53 | + }; | ||
54 | + | ||
55 | + | ||
56 | + useEffect(()=>{ | ||
57 | + if(!visible){ | ||
58 | + let initFields = [ | ||
59 | + {name:['qno'],value:null}, | ||
60 | + {name:['typeSol'],value:null}, | ||
61 | + {name:['typeQue'],value:null}, | ||
62 | + {name:['creator'],value:null}, | ||
63 | + ]; | ||
64 | + setQno(null); | ||
65 | + setFields(initFields); | ||
66 | + setFileList([]); | ||
67 | + } | ||
68 | + },[visible]); | ||
69 | + | ||
70 | + const props = { | ||
71 | + multiple:false, | ||
72 | + //data: { qno: qno }, | ||
73 | + accept:'.html', | ||
74 | + onRemove: file => { | ||
75 | + const index = fileList.indexOf(file); | ||
76 | + const newFileList = fileList.slice(); | ||
77 | + newFileList.splice(index, 1); | ||
78 | + return { | ||
79 | + fileList: newFileList, | ||
80 | + }; | ||
81 | + }, | ||
82 | + | ||
83 | + beforeUpload: file => { | ||
84 | + console.log(file); | ||
85 | + if(file.name.indexOf('.html')>0) | ||
86 | + { | ||
87 | + setFileList([file]); | ||
88 | + }else { | ||
89 | + setFileList([]); | ||
90 | + message.info("Html 형식의 파일이 아닙니다."); | ||
91 | + } | ||
92 | + return false; | ||
93 | + | ||
94 | + }, | ||
95 | + }; | ||
96 | + | ||
97 | + const onOk = () => { | ||
98 | + setUpload(true) | ||
99 | + }; | ||
100 | + | ||
101 | + | ||
102 | + const normFile = e => { | ||
103 | + console.log('Upload event:', e); | ||
104 | + if (Array.isArray(e)) { | ||
105 | + return e; | ||
106 | + } | ||
107 | + return e && e.fileList; | ||
108 | + }; | ||
109 | + | ||
110 | + const onClickQno = async(e)=>{ | ||
111 | + e.preventDefault(); | ||
112 | + //번호가 호출 성공시 setQnoCheck(true); | ||
113 | + if(qno){ | ||
114 | + const _checkQno= await fetchCheckQno(qno); | ||
115 | + setQnoCheck(_checkQno); | ||
116 | + } | ||
117 | + }; | ||
118 | + | ||
119 | + const onFinish = async values => { | ||
120 | + console.log(qnoCheck); | ||
121 | + if(!qnoCheck){ | ||
122 | + message.warning("문제 번호를 확인해 주세요.") | ||
123 | + return; | ||
124 | + }else{ | ||
125 | + const creator = sessionStorage.getItem('id'); | ||
126 | + console.log('Received values of form: ', values); | ||
127 | + const formData = new FormData(); | ||
128 | + formData.append('qno', values.qno); | ||
129 | + formData.append('typeSol', values.typeSol); | ||
130 | + formData.append('typeQue', values.typeQue); | ||
131 | + formData.append('html', values.html[0]); | ||
132 | + formData.append('creator', creator); | ||
133 | + | ||
134 | + const result = await fetchSaveData(formData); | ||
135 | + console.log(result); | ||
136 | + if(result){ | ||
137 | + message.info(result.message); | ||
138 | + let initFields = [ | ||
139 | + {name:['qno'],value:null}, | ||
140 | + {name:['typeSol'],value:null}, | ||
141 | + {name:['typeQue'],value:null}, | ||
142 | + {name:['creator'],value:null}, | ||
143 | + ]; | ||
144 | + setQno(null); | ||
145 | + setFields(initFields); | ||
146 | + setFileList([]); | ||
147 | + onCancel(); | ||
148 | + callback({status:'SAVE_OK'}); | ||
149 | + }else{ | ||
150 | + callback({status:'SAVE_FAIL'}) | ||
151 | + } | ||
152 | + } | ||
153 | + }; | ||
154 | + | ||
155 | + const onChangeTypeSol = (value) => { | ||
156 | + console.log(value); | ||
157 | + setFields([...fields, {name:['typeSol'],value:value}]); | ||
158 | + } | ||
159 | + | ||
160 | + const onChangeTypeQue = (value) => { | ||
161 | + console.log(value); | ||
162 | + setFields([...fields, {name:['typeQue'],value:value}]) | ||
163 | + } | ||
164 | + | ||
165 | + | ||
166 | + | ||
167 | + const formItemLayout = { | ||
168 | + labelCol: { span: 6 }, | ||
169 | + wrapperCol: { span: 14 }, | ||
170 | + }; | ||
171 | + | ||
172 | + return ( | ||
173 | + <Modal | ||
174 | + placement={'bottom'} | ||
175 | + closable={true} | ||
176 | + height={'75%'} | ||
177 | + visible={visible} | ||
178 | + okText={'저장'} | ||
179 | + cancelText={'이전'} | ||
180 | + onCancel={onCancel} | ||
181 | + footer={null} | ||
182 | + > | ||
183 | + <Form name="validate_other" | ||
184 | + {...formItemLayout} | ||
185 | + onFinish={onFinish} | ||
186 | + fields={[{name:['html'],value:fileList},...fields]} | ||
187 | + > | ||
188 | + <Form.Item | ||
189 | + name="qno" | ||
190 | + label="문제 번호" | ||
191 | + rules={[ | ||
192 | + { | ||
193 | + required: true, | ||
194 | + message: '저장할 html의 문항번호를 입력해 주세요.', | ||
195 | + }, | ||
196 | + ]}> | ||
197 | + <Row> | ||
198 | + <Col> | ||
199 | + <InputNumber | ||
200 | + min={0} | ||
201 | + max={10000} | ||
202 | + value={qno} | ||
203 | + onChange={changeNumber}> | ||
204 | + </InputNumber> | ||
205 | + </Col> | ||
206 | + <Col> | ||
207 | + <Button onClick={onClickQno}>번호 확인</Button> | ||
208 | + </Col> | ||
209 | + </Row> | ||
210 | + </Form.Item> | ||
211 | + <Form.Item | ||
212 | + name="typeSol" | ||
213 | + label="문제 타입" | ||
214 | + rules={[ | ||
215 | + { | ||
216 | + required: true, | ||
217 | + message: '저장할 html의 문제 타입을 선택해 주세요.', | ||
218 | + }, | ||
219 | + ]}> | ||
220 | + <Select onChange={onChangeTypeSol}> | ||
221 | + <Option value="오지선다형">오지선다형</Option> | ||
222 | + <Option value="단답형">단답형</Option> | ||
223 | + <Option value="계산식">계산식</Option> | ||
224 | + </Select> | ||
225 | + </Form.Item> | ||
226 | + <Form.Item | ||
227 | + name="typeQue" | ||
228 | + label="문제/풀이 구분" | ||
229 | + rules={[ | ||
230 | + { | ||
231 | + required: true, | ||
232 | + message: '저장할 html의 문제/풀이 구분을 선택해 주세요.', | ||
233 | + }, | ||
234 | + ]}> | ||
235 | + <Select onChange={onChangeTypeQue}> | ||
236 | + <Option value="문제">문제</Option> | ||
237 | + <Option value="풀이">풀이</Option> | ||
238 | + </Select> | ||
239 | + </Form.Item> | ||
240 | + <Form.Item label="파일 업로드"> | ||
241 | + <Form.Item | ||
242 | + name="html" | ||
243 | + valuePropName="fileList" | ||
244 | + getValueFromEvent={normFile} | ||
245 | + | ||
246 | + noStyle | ||
247 | + rules={[ | ||
248 | + { | ||
249 | + required: true, | ||
250 | + message: '파일을 드래그하거나 선택해 주세요.', | ||
251 | + }, | ||
252 | + ]}> | ||
253 | + <Upload.Dragger name="files" {...props} > | ||
254 | + <p className="ant-upload-drag-icon"> | ||
255 | + <InboxOutlined /> | ||
256 | + </p> | ||
257 | + <p className="ant-upload-text">Click or drag file to this area to upload</p> | ||
258 | + <p className="ant-upload-hint">Support for a single or bulk upload.</p> | ||
259 | + </Upload.Dragger> | ||
260 | + </Form.Item> | ||
261 | + </Form.Item> | ||
262 | + | ||
263 | + <Form.Item style={{alignContent:'middle'}} wrapperCol={{ span: 12, offset: 6 }}> | ||
264 | + <Button type="primary" htmlType="submit"> | ||
265 | + 저장 | ||
266 | + </Button> | ||
267 | + </Form.Item> | ||
268 | + </Form> | ||
269 | + | ||
270 | + </Modal> | ||
271 | + ); | ||
272 | +}; | ||
273 | + | ||
274 | +export default Html; |
-
Please register or login to post a comment