Commit 2eb32b90 authored by Choi Ga Young's avatar Choi Ga Young
Browse files

plan관련

parent 617ce4d0
...@@ -14744,6 +14744,26 @@ ...@@ -14744,6 +14744,26 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/normalize-url/node_modules/query-string": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
"integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=",
"dependencies": {
"object-assign": "^4.1.0",
"strict-uri-encode": "^1.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/normalize-url/node_modules/strict-uri-encode": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/npm-run-path": { "node_modules/npm-run-path": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
...@@ -17073,18 +17093,6 @@ ...@@ -17073,18 +17093,6 @@
"node": ">=0.6" "node": ">=0.6"
} }
}, },
"node_modules/query-string": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
"integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=",
"dependencies": {
"object-assign": "^4.1.0",
"strict-uri-encode": "^1.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/querystring": { "node_modules/querystring": {
"version": "0.2.1", "version": "0.2.1",
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz",
...@@ -19845,14 +19853,6 @@ ...@@ -19845,14 +19853,6 @@
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz",
"integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ=="
}, },
"node_modules/strict-uri-encode": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/string_decoder": { "node_modules/string_decoder": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
...@@ -34256,6 +34256,22 @@ ...@@ -34256,6 +34256,22 @@
"prepend-http": "^1.0.0", "prepend-http": "^1.0.0",
"query-string": "^4.1.0", "query-string": "^4.1.0",
"sort-keys": "^1.0.0" "sort-keys": "^1.0.0"
},
"dependencies": {
"query-string": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
"integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=",
"requires": {
"object-assign": "^4.1.0",
"strict-uri-encode": "^1.0.0"
}
},
"strict-uri-encode": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM="
}
} }
}, },
"npm-run-path": { "npm-run-path": {
...@@ -36108,15 +36124,6 @@ ...@@ -36108,15 +36124,6 @@
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
}, },
"query-string": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
"integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=",
"requires": {
"object-assign": "^4.1.0",
"strict-uri-encode": "^1.0.0"
}
},
"querystring": { "querystring": {
"version": "0.2.1", "version": "0.2.1",
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz",
...@@ -38335,11 +38342,6 @@ ...@@ -38335,11 +38342,6 @@
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz",
"integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ=="
}, },
"strict-uri-encode": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM="
},
"string_decoder": { "string_decoder": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
...@@ -27,8 +27,9 @@ function App() { ...@@ -27,8 +27,9 @@ function App() {
<Route path="/schedule/edit" component={ScheduleEditPage} /> <Route path="/schedule/edit" component={ScheduleEditPage} />
<Route path="/schedule/:date" component={SchedulePage} /> <Route path="/schedule/:date" component={SchedulePage} />
<Route path="/todo/:date" component={ToDoPage} /> <Route path="/todo/:date" component={ToDoPage} />
<Route path="/studyplan/edit" component={StudyPlanEditPage} /> <Route path="/studyplan/edit/add/:subjectId" component={StudyPlanEditPage} />
<Route path="/studyplan/:" component={StudyPlanPage} /> <Route path="/studyplan/edit/:planId" component={StudyPlanEditPage} />
<Route path="/studyplan/:subjectId" component={StudyPlanPage} />
<Route path="/studyplan" component={StudyPlanListPage} /> <Route path="/studyplan" component={StudyPlanListPage} />
<Route path="/subject/edit/:subjectId" component={SubjectEditPage} /> <Route path="/subject/edit/:subjectId" component={SubjectEditPage} />
<Route path="/subject/edit" component={SubjectEditPage} /> <Route path="/subject/edit" component={SubjectEditPage} />
......
import axios from "axios";
import baseUrl from "../utils/baseUrl";
const addPlan = async (info, id) => {
console.log('addPlan 확인', id)
const url = `${baseUrl}/api/plan/addplan/${id}`
const { data } = await axios.post(url, { info, id });
return data
}
const editPlan = async (info, id) => {
console.log('editPlan확인', id)
const url = `${baseUrl}/api/plan/edit/${id}`
const { data } = await axios.put(url, info);
return data
}
const getDetail = async (id) => {
const url = `${baseUrl}/api/plan/getDetail/${id}`
const { data } = await axios.get(url)
return data
}
const planApi = {
addPlan,
editPlan,
getDetail
};
export default planApi
\ No newline at end of file
...@@ -8,7 +8,7 @@ const StudyPlanCard = () => { ...@@ -8,7 +8,7 @@ const StudyPlanCard = () => {
<> <>
<div className="d-flex justify-content-center mt-3"> <div className="d-flex justify-content-center mt-3">
<div className="card" style={{ width: "20rem" }}> <div className="card" style={{ width: "20rem" }}>
<Link className="text-decoration-none link-dark" to="/studyplan/:"> <Link className="text-decoration-none link-dark" to="/studyplan/1be7e4db-796d-4d9b-bfab-fdc440d25171">
<div className="card-body"> <div className="card-body">
<div className="d-flex justify-content-between"> <div className="d-flex justify-content-between">
<h5 className="card-title col-10">운영체제</h5> <h5 className="card-title col-10">운영체제</h5>
......
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import { useAuth } from "../../utils/context.js";
import BtnGroup from "../Buttons/BtnGroup"; import BtnGroup from "../Buttons/BtnGroup";
import subjectApi from '../../apis/subject.api.js';
import planApi from '../../apis/plan.api.js';
import styles from "./form.module.scss"; import styles from "./form.module.scss";
import catchErrors from '../../utils/catchErrors.js';
const StudyPlanEditForm = () => { const StudyPlanEditForm = () => {
const { user } = useAuth();
const params = useParams();
const [disabled, setDisabled] = useState(true)
const [selected, setSelected] = useState("");
const [error, setError] = useState("");
const [studyplan, setStudyplan] = useState({ const [studyplan, setStudyplan] = useState({
studyplanTitle: "", studyplanTitle: "",
endDate: "", endDate: "",
deadline: "", deadline: "",
memo: "" memo: "",
deadline: "",
selected: ""
}) })
const [disabled, setDisabled] = useState(true) const [list, setList] = useState([])
useEffect(() => { useEffect(() => {
let isMounted = true; let isMounted = true;
const checkInfo = { studyplanTitle: studyplan.studyplanTitle, endDate: studyplan.endDate } const checkInfo = { studyplanTitle: studyplan.studyplanTitle, endDate: studyplan.endDate, selected: selected }
if (studyplan.deadline !== "on") { if (studyplan.deadline === "on") {
checkInfo.endTime = studyplan.endTime checkInfo.endTime = studyplan.endTime
} else { } else {
delete checkInfo.endTime delete checkInfo.endTime
...@@ -28,6 +40,25 @@ const StudyPlanEditForm = () => { ...@@ -28,6 +40,25 @@ const StudyPlanEditForm = () => {
} }
}, [studyplan]) }, [studyplan])
useEffect(() => {
subjectTitle(user.id)
if (params.hasOwnProperty('planId')) {
console.log('planId params확인');
getInfo(params.planId);
}
}, [])
async function getInfo(id) {
const result = await planApi.getDetail(id)
console.log('수정 getInfo result', result)
}
async function subjectTitle(id) {
const result = await subjectApi.subjectTitle(id)
console.log('result확인--select', result)
setList(result)
}
function handleChange(e) { function handleChange(e) {
const { name, value } = e.target const { name, value } = e.target
if (name === "deadline") { if (name === "deadline") {
...@@ -37,24 +68,66 @@ const StudyPlanEditForm = () => { ...@@ -37,24 +68,66 @@ const StudyPlanEditForm = () => {
} }
} }
async function handleSubmit(e) {
e.preventDefault();
try {
setError("")
studyplan.selected = selected
if (params.hasOwnProperty('subjectId')) {
//등록함수 실행
console.log('등록함수')
const result = await planApi.addPlan(studyplan, params.subjectId)
if (result) {
alert("등록되었습니다")
setList([])
setStudyplan({
studyplanTitle: "",
endDate: "",
deadline: "",
memo: "",
selected: ""
})
} else {
alert("등록에 실패하였습니다.")
}
} else {
//수정함수 실행
console.log('수정함수')
const result = await planApi.editPlan(studyplan, params.subjectId)
console.log('수정 후 result확인', result)
}
} catch (error) {
catchErrors(error, setError)
setStudyplan({
studyplanTitle: "",
endDate: "",
deadline: "",
memo: ""
})
}
}
function handleSelect(e) {
setSelected(e.target.value);
}
return ( return (
<div className="pt-5"> <div className="pt-5">
<select className={`form-select mb-4 ${styles.selectInput}`} aria-label="Choose subject"> <select className={`form-select mb-4 ${styles.selectInput}`} aria-label="Choose subject" onChange={handleSelect}>
<option selected>관련 과목을 선택해주세요.</option> <option selected>관련 과목을 선택해주세요.</option>
<option value="1">운영체제</option> {list.length !== 0 ? list.map((i) => <option value={i.id}>{i.name}</option>) : null}
<option value="2">네트워크 프로그래밍 실습</option>
<option value="3">수학적 모델링</option>
</select> </select>
<input type="text" name="studyplanTitle" <input type="text" name="studyplanTitle"
className={`form-control shadow-none rounded-0 mb-5 ${styles.textInput}`} className={`form-control shadow-none rounded-0 mb-5 ${styles.textInput}`}
placeholder="제목" onChange={handleChange} /> placeholder="제목" value={studyplan.studyplanTitle} onChange={handleChange} />
<div className="d-flex mb-3"> <div className="d-flex mb-3">
<label className="col col-form-label align-self-center py-0">마감일</label> <label className="col col-form-label align-self-center py-0">마감일</label>
<div className={studyplan.deadline === "on" ? "col-7" : "col-5"}> <div className={studyplan.deadline === "on" ? "col-5" : "col-7"}>
<input className={`form-control shadow-none ${styles.dateInput}`} type="date" name="endDate" aria-label="endDate" onChange={handleChange} /> <input className={`form-control shadow-none ${styles.dateInput}`} type="date" name="endDate" aria-label="endDate" value={studyplan.endDate} onChange={handleChange} />
</div> </div>
<div className={"col-4 " + (studyplan.deadline === "on" ? "d-none" : "d-block")}> <div className={"col-4 " + (studyplan.deadline === "on" ? "d-block" : "d-none")}>
<input className={`form-control shadow-none ${styles.dateInput}`} type="time" name="endTime" aria-label="endTime" onChange={handleChange} /> <input className={`form-control shadow-none ${styles.dateInput}`} type="time" name="endTime" aria-label="endTime" value={studyplan.endTime} onChange={handleChange} />
</div> </div>
</div> </div>
<div className="d-flex justify-content-end form-check mb-4"> <div className="d-flex justify-content-end form-check mb-4">
...@@ -64,10 +137,10 @@ const StudyPlanEditForm = () => { ...@@ -64,10 +137,10 @@ const StudyPlanEditForm = () => {
<div className="d-flex justify-content-between mb-5"> <div className="d-flex justify-content-between mb-5">
<i className="col bi bi-journal-text fs-3"></i> <i className="col bi bi-journal-text fs-3"></i>
<div className="col-10"> <div className="col-10">
<textarea className={`form-control shadow-none ${styles.textArea}`} name="memo" rows="5" onChange={handleChange}></textarea> <textarea className={`form-control shadow-none ${styles.textArea}`} name="memo" rows="5" value={studyplan.memo} onChange={handleChange}></textarea>
</div> </div>
</div> </div>
<BtnGroup disabled={disabled} /> <BtnGroup disabled={disabled} handleSubmit={handleSubmit} />
</div> </div>
) )
} }
......
...@@ -30,14 +30,14 @@ const PlanItem = () => { ...@@ -30,14 +30,14 @@ const PlanItem = () => {
<div id="flush-collapseOne" className="accordion-collapse collapse" aria-labelledby="flush-headingOne" data-bs-parent="S#addplanlist"> <div id="flush-collapseOne" className="accordion-collapse collapse" aria-labelledby="flush-headingOne" data-bs-parent="S#addplanlist">
<div className={`accordion-body px-0 pt-2 pb-0 mb-3 ${styles.textBox}`}> <div className={`accordion-body px-0 pt-2 pb-0 mb-3 ${styles.textBox}`}>
<div className="d-flex align-items-start fw-bold"> <div className="d-flex align-items-start fw-bold">
<i class="bi bi-clock-history fs-5"></i> <i className="bi bi-clock-history fs-5"></i>
<div className="col-11 ms-2 align-self-center"> <div className="col-11 ms-2 align-self-center">
21.09.30 16:00 21.09.30 16:00
</div> </div>
</div> </div>
컴퓨터의 프로세스 체크하는 프로그램 만들기 과제<br />결과화면 캡쳐해서 exe파일이랑 함께 압축하여 제출하기 컴퓨터의 프로세스 체크하는 프로그램 만들기 과제<br />결과화면 캡쳐해서 exe파일이랑 함께 압축하여 제출하기
<div className="d-flex justify-content-end mt-3"> <div className="d-flex justify-content-end mt-3">
<Link className="btn btn-light btn-sm border-dark" to="/studyplan/edit">수정</Link> <Link className="btn btn-light btn-sm border-dark" to="/studyplan/edit/bd67541e-504d-402f-8190-18808c229fcf">수정</Link>
<button type="button" className="btn btn-crimson btn-sm ms-2" onClick={delPlan}>삭제</button> <button type="button" className="btn btn-crimson btn-sm ms-2" onClick={delPlan}>삭제</button>
</div> </div>
</div> </div>
......
import { useState, useEffect } from 'react';
import { useAuth } from "../utils/context.js"
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import StudyPlanCard from "./Card/StudyPlanCard.js"; import StudyPlanCard from "./Card/StudyPlanCard.js";
import subjectApi from '../apis/subject.api.js';
const StudyPlanList = () => { const StudyPlanList = () => {
const { user } = useAuth();
useEffect(() => {
getList(user.id);
}, [])
async function getList(id) {
const result = await subjectApi.allSubject(id)
}
return ( return (
<> <>
<StudyPlanCard /> <StudyPlanCard />
......
import { useParams } from "react-router-dom";
import Menu from "../components/Menu/Menu.js"; import Menu from "../components/Menu/Menu.js";
import BackBtn from "../components/Buttons/BackBtn.js"; import BackBtn from "../components/Buttons/BackBtn.js";
import Footer from "../components/Footer.js"; import Footer from "../components/Footer.js";
import AddplanList from "../components/StudyPlan/AddplanList.js"; import AddplanList from "../components/StudyPlan/AddplanList.js";
const StudyPlanPage = () => { const StudyPlanPage = () => {
const { subjectId } = useParams();
return ( return (
<> <>
<Menu /> <Menu />
<BackBtn /> <BackBtn />
<h2 className="text-center">운영체제</h2> <h2 className="text-center">운영체제</h2>
<AddplanList /> <AddplanList />
<Footer pathname="studyplan/edit" /> <Footer pathname={`studyplan/edit/add/${subjectId}`} />
</> </>
) )
} }
......
import { Plan } from "../db/index.js";
const addPlan = async (req, res) => {
console.log('server/addPlan req.body', req.body)
try {
let end = null;
let tf = false;
const { info } = req.body
const { studyplanTitle, endDate, endTime, deadline, memo, selected } = info
console.log('제목확인', studyplanTitle)
if (deadline === "on") {
end = new Date(endDate + " " + endTime)
tf = true
} else {
end = new Date(endDate)
}
const result = await Plan.create({
subjectId: selected,
title: studyplanTitle,
deadline: end,
memo: memo,
timeChecked: tf,
checked: false
})
return res.json(result)
} catch (error) {
console.log(error)
return res.status(500).send(error.message || "계획저장 에러발생")
}
}
const editPlan = async (req, res) => {
console.log('server/editPlan req.body', req.body)
try {
} catch (error) {
console.log(error)
return res.status(500).send(error.message || "계획수정 에러발생")
}
}
const getInfo = async (req, res) => {
console.log('server/getInfo req.params', req.params)
try {
const { planId } = req.params;
const findInfo = await Plan.findOne({ where: { id: planId } })
console.log('findInfo확인', findInfo.dataValues)
} catch (error) {
console.log(error)
return res.status(500).send(error.message || "계획 가져오기 에러발생")
}
}
export default {
addPlan,
editPlan,
getInfo
}
\ No newline at end of file
...@@ -5,6 +5,7 @@ import KUModel from "../models/ku.model.js"; ...@@ -5,6 +5,7 @@ import KUModel from "../models/ku.model.js";
import ScheduleModel from "../models/schedule.model.js"; import ScheduleModel from "../models/schedule.model.js";
import TodoModel from "../models/todo.model.js"; import TodoModel from "../models/todo.model.js";
import SubjectModel from "../models/subject.model.js"; import SubjectModel from "../models/subject.model.js";
import PlanModel from "../models/plan.model.js";
const sequelize = new Sequelize( const sequelize = new Sequelize(
String(dbConfig.database), String(dbConfig.database),
...@@ -27,9 +28,11 @@ const KU = KUModel(sequelize) ...@@ -27,9 +28,11 @@ const KU = KUModel(sequelize)
const Schedule = ScheduleModel(sequelize) const Schedule = ScheduleModel(sequelize)
const Todo = TodoModel(sequelize) const Todo = TodoModel(sequelize)
const Subject = SubjectModel(sequelize) const Subject = SubjectModel(sequelize)
const Plan = PlanModel(sequelize)
Schedule.belongsTo(User) Schedule.belongsTo(User)
Subject.belongsTo(User) Subject.belongsTo(User)
Plan.belongsTo(Subject)
export { export {
sequelize, sequelize,
...@@ -37,5 +40,6 @@ export { ...@@ -37,5 +40,6 @@ export {
KU, KU,
Schedule, Schedule,
Todo, Todo,
Subject Subject,
Plan
} }
\ No newline at end of file
import Sequelize from "sequelize";
const { DataTypes } = Sequelize;
const PlanModel = (sequelize) => {
const Plan = sequelize.define(
"plan",
{
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true
},
title: {
type: DataTypes.STRING
},
deadline: {
type: DataTypes.DATE
},
memo: {
type: DataTypes.STRING
},
timeChecked: {
type: DataTypes.BOOLEAN
},
checked: {
type: DataTypes.BOOLEAN
}
},
{
timestamps: true,
freezeTableName: true,
tableName: "plans",
}
);
return Plan
};
export default PlanModel;
\ No newline at end of file
...@@ -2,11 +2,13 @@ import express from "express"; ...@@ -2,11 +2,13 @@ import express from "express";
import userRouter from './user.route.js'; import userRouter from './user.route.js';
import scheduleRouter from "./schedule.route.js"; import scheduleRouter from "./schedule.route.js";
import subjectRouter from './subject.route.js'; import subjectRouter from './subject.route.js';
import planRouter from './plan.route.js'
const router = express.Router(); const router = express.Router();
router.use('/auth', userRouter) router.use('/auth', userRouter)
router.use('/schedule', scheduleRouter) router.use('/schedule', scheduleRouter)
router.use('/subject', subjectRouter) router.use('/subject', subjectRouter)
router.use('/plan', planRouter)
export default router; export default router;
\ No newline at end of file
import express from 'express';
import planCtrl from '../controllers/plan.controller.js'
const router = express.Router();
router
.route("/addplan/:subjectId")
.post(planCtrl.addPlan)
router
.route("/edit/:subjectId")
.put(planCtrl.editPlan)
router
.route("/getDetail/:planId")
.get(planCtrl.getInfo)
export default router;
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment