Commit 5096aa74 by Giang Tran

update code

parent d0825019
[{"D:\\checkin_hrm\\src\\index.js":"1","D:\\checkin_hrm\\src\\reportWebVitals.js":"2","D:\\checkin_hrm\\src\\App.js":"3","D:\\checkin_hrm\\src\\View\\RootView.js":"4","D:\\checkin_hrm\\src\\View\\Home\\HomeContainer.js":"5","D:\\checkin_hrm\\src\\View\\Home\\HomeView.js":"6","D:\\checkin_hrm\\src\\View\\Login\\LoginScreen.js":"7","D:\\checkin_hrm\\src\\View\\Home\\ButtonCheckIn.js":"8"},{"size":500,"mtime":1607323871389,"results":"9","hashOfConfig":"10"},{"size":362,"mtime":1607323871389,"results":"11","hashOfConfig":"10"},{"size":167,"mtime":1610544010654,"results":"12","hashOfConfig":"10"},{"size":615,"mtime":1610551066775,"results":"13","hashOfConfig":"10"},{"size":135,"mtime":1610543552792,"results":"14","hashOfConfig":"10"},{"size":1446,"mtime":1610557883581,"results":"15","hashOfConfig":"10"},{"size":3468,"mtime":1610543552803,"results":"16","hashOfConfig":"10"},{"size":543,"mtime":1610543552786,"results":"17","hashOfConfig":"10"},{"filePath":"18","messages":"19","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"1t40iya",{"filePath":"20","messages":"21","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"22","messages":"23","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"24","messages":"25","errorCount":0,"warningCount":5,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"26","messages":"27","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"28","messages":"29","errorCount":0,"warningCount":10,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"30","messages":"31","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"32","messages":"33","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},"D:\\checkin_hrm\\src\\index.js",[],"D:\\checkin_hrm\\src\\reportWebVitals.js",[],"D:\\checkin_hrm\\src\\App.js",["34"],"D:\\checkin_hrm\\src\\View\\RootView.js",["35","36","37","38","39"],"D:\\checkin_hrm\\src\\View\\Home\\HomeContainer.js",[],"D:\\checkin_hrm\\src\\View\\Home\\HomeView.js",["40","41","42","43","44","45","46","47","48","49"],"D:\\checkin_hrm\\src\\View\\Login\\LoginScreen.js",[],"D:\\checkin_hrm\\src\\View\\Home\\ButtonCheckIn.js",["50","51"],{"ruleId":"52","severity":1,"message":"53","line":2,"column":8,"nodeType":"54","messageId":"55","endLine":2,"endColumn":21},{"ruleId":"52","severity":1,"message":"56","line":1,"column":40,"nodeType":"54","messageId":"55","endLine":1,"endColumn":44},{"ruleId":"52","severity":1,"message":"57","line":2,"column":22,"nodeType":"54","messageId":"55","endLine":2,"endColumn":30},{"ruleId":"52","severity":1,"message":"58","line":3,"column":17,"nodeType":"54","messageId":"55","endLine":3,"endColumn":26},{"ruleId":"52","severity":1,"message":"59","line":3,"column":28,"nodeType":"54","messageId":"55","endLine":3,"endColumn":36},{"ruleId":"52","severity":1,"message":"60","line":8,"column":7,"nodeType":"54","messageId":"55","endLine":8,"endColumn":14},{"ruleId":"52","severity":1,"message":"61","line":2,"column":10,"nodeType":"54","messageId":"55","endLine":2,"endColumn":20},{"ruleId":"52","severity":1,"message":"62","line":6,"column":3,"nodeType":"54","messageId":"55","endLine":6,"endColumn":8},{"ruleId":"52","severity":1,"message":"63","line":7,"column":3,"nodeType":"54","messageId":"55","endLine":7,"endColumn":7},{"ruleId":"52","severity":1,"message":"64","line":8,"column":3,"nodeType":"54","messageId":"55","endLine":8,"endColumn":13},{"ruleId":"52","severity":1,"message":"65","line":12,"column":8,"nodeType":"54","messageId":"55","endLine":12,"endColumn":21},{"ruleId":"52","severity":1,"message":"66","line":15,"column":10,"nodeType":"54","messageId":"55","endLine":15,"endColumn":15},{"ruleId":"52","severity":1,"message":"67","line":15,"column":17,"nodeType":"54","messageId":"55","endLine":15,"endColumn":25},{"ruleId":"68","severity":1,"message":"69","line":25,"column":16,"nodeType":"70","messageId":"71","endLine":25,"endColumn":18},{"ruleId":"72","severity":1,"message":"73","line":33,"column":6,"nodeType":"74","endLine":33,"endColumn":8,"suggestions":"75"},{"ruleId":"68","severity":1,"message":"69","line":49,"column":21,"nodeType":"70","messageId":"71","endLine":49,"endColumn":23},{"ruleId":"52","severity":1,"message":"76","line":2,"column":10,"nodeType":"54","messageId":"55","endLine":2,"endColumn":16},{"ruleId":"52","severity":1,"message":"77","line":2,"column":18,"nodeType":"54","messageId":"55","endLine":2,"endColumn":24},"no-unused-vars","'HomeContainer' is defined but never used.","Identifier","unusedVar","'Link' is defined but never used.","'Redirect' is defined but never used.","'useEffect' is defined but never used.","'useState' is defined but never used.","'history' is assigned a value but never used.","'makeStyles' is defined but never used.","'Paper' is defined but never used.","'Card' is defined but never used.","'Typography' is defined but never used.","'ButtonCheckIn' is defined but never used.","'state' is assigned a value but never used.","'setState' is assigned a value but never used.","eqeqeq","Expected '===' and instead saw '=='.","BinaryExpression","unexpected","react-hooks/exhaustive-deps","React Hook useEffect has a missing dependency: 'getPosition'. Either include it or remove the dependency array.","ArrayExpression",["78"],"'bounce' is defined but never used.","'fadeIn' is defined but never used.",{"desc":"79","fix":"80"},"Update the dependencies array to be: [getPosition]",{"range":"81","text":"82"},[762,764],"[getPosition]"]
\ No newline at end of file
[{"D:\\CheckInWeb\\checkin_hrm\\src\\index.js":"1","D:\\CheckInWeb\\checkin_hrm\\src\\App.js":"2","D:\\CheckInWeb\\checkin_hrm\\src\\reportWebVitals.js":"3","D:\\CheckInWeb\\checkin_hrm\\src\\View\\RootView.js":"4","D:\\CheckInWeb\\checkin_hrm\\src\\View\\Home\\HomeContainer.js":"5","D:\\CheckInWeb\\checkin_hrm\\src\\View\\Home\\HomeView.js":"6","D:\\CheckInWeb\\checkin_hrm\\src\\View\\Login\\LoginScreen.js":"7","D:\\CheckInWeb\\checkin_hrm\\src\\View\\Home\\ButtonCheckIn.js":"8","D:\\CheckInWeb\\checkin_hrm\\src\\api\\user.js":"9","D:\\CheckInWeb\\checkin_hrm\\src\\api\\api.js":"10"},{"size":517,"mtime":1610694367494,"results":"11","hashOfConfig":"12"},{"size":167,"mtime":1610694367492,"results":"13","hashOfConfig":"12"},{"size":375,"mtime":1610694367495,"results":"14","hashOfConfig":"12"},{"size":615,"mtime":1610694367494,"results":"15","hashOfConfig":"12"},{"size":914,"mtime":1610705867222,"results":"16","hashOfConfig":"12"},{"size":1162,"mtime":1610705865694,"results":"17","hashOfConfig":"12"},{"size":4429,"mtime":1610708737159,"results":"18","hashOfConfig":"12"},{"size":543,"mtime":1610694367493,"results":"19","hashOfConfig":"12"},{"size":729,"mtime":1610706103981,"results":"20","hashOfConfig":"12"},{"size":2114,"mtime":1610703712616,"results":"21","hashOfConfig":"12"},{"filePath":"22","messages":"23","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"24"},"l90yup",{"filePath":"25","messages":"26","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"27","usedDeprecatedRules":"24"},{"filePath":"28","messages":"29","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"24"},{"filePath":"30","messages":"31","errorCount":0,"warningCount":5,"fixableErrorCount":0,"fixableWarningCount":0,"source":"32","usedDeprecatedRules":"24"},{"filePath":"33","messages":"34","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"35","messages":"36","errorCount":0,"warningCount":7,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"37","messages":"38","errorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"39","messages":"40","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"41","usedDeprecatedRules":"24"},{"filePath":"42","messages":"43","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"44","messages":"45","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"D:\\CheckInWeb\\checkin_hrm\\src\\index.js",[],["46","47"],"D:\\CheckInWeb\\checkin_hrm\\src\\App.js",["48"],"import RootView from \"./View/RootView\";\r\nimport HomeContainer from \"./View/Home/HomeContainer\";\r\n\r\nfunction App() {\r\n return <RootView />;\r\n}\r\n\r\nexport default App;\r\n","D:\\CheckInWeb\\checkin_hrm\\src\\reportWebVitals.js",[],"D:\\CheckInWeb\\checkin_hrm\\src\\View\\RootView.js",["49","50","51","52","53"],"import { BrowserRouter, Switch, Route, Link } from \"react-router-dom\";\r\nimport { useHistory, Redirect } from \"react-router-dom\";\r\nimport React, { useEffect, useState } from \"react\";\r\nimport LoginScreen from \"./Login/LoginScreen\";\r\nimport HomeScreen from \"./Home/HomeContainer\";\r\n\r\nconst RootView = () => {\r\n let history = useHistory();\r\n return (\r\n <BrowserRouter>\r\n <Switch>\r\n <Route exact path=\"/\">\r\n <LoginScreen />\r\n </Route>\r\n <Route path=\"/home\">\r\n <HomeScreen />\r\n </Route>\r\n </Switch>\r\n </BrowserRouter>\r\n );\r\n};\r\n\r\nexport default RootView;\r\n","D:\\CheckInWeb\\checkin_hrm\\src\\View\\Home\\HomeContainer.js",["54"],"D:\\CheckInWeb\\checkin_hrm\\src\\View\\Home\\HomeView.js",["55","56","57","58","59","60","61"],"D:\\CheckInWeb\\checkin_hrm\\src\\View\\Login\\LoginScreen.js",["62","63","64"],"D:\\CheckInWeb\\checkin_hrm\\src\\View\\Home\\ButtonCheckIn.js",["65","66"],"import React from \"react\";\r\nimport { bounce, fadeIn, bounceIn } from \"react-animations\";\r\nimport Radium, { StyleRoot } from \"radium\";\r\n\r\nconst styles = {\r\n bounce: {\r\n animation: \"x 1s\",\r\n animationName: Radium.keyframes(bounceIn, \"bounceIn\"),\r\n animationDuration: \"10s\",\r\n },\r\n};\r\n\r\nclass ButtonCheckIn extends React.Component {\r\n render() {\r\n return (\r\n <StyleRoot>\r\n <div className=\"test\" style={styles.bounce}>\r\n aaa\r\n </div>\r\n </StyleRoot>\r\n );\r\n }\r\n}\r\n\r\nexport default ButtonCheckIn;\r\n","D:\\CheckInWeb\\checkin_hrm\\src\\api\\user.js",[],"D:\\CheckInWeb\\checkin_hrm\\src\\api\\api.js",[],{"ruleId":"67","replacedBy":"68"},{"ruleId":"69","replacedBy":"70"},{"ruleId":"71","severity":1,"message":"72","line":2,"column":8,"nodeType":"73","messageId":"74","endLine":2,"endColumn":21},{"ruleId":"71","severity":1,"message":"75","line":1,"column":40,"nodeType":"73","messageId":"74","endLine":1,"endColumn":44},{"ruleId":"71","severity":1,"message":"76","line":2,"column":22,"nodeType":"73","messageId":"74","endLine":2,"endColumn":30},{"ruleId":"71","severity":1,"message":"77","line":3,"column":17,"nodeType":"73","messageId":"74","endLine":3,"endColumn":26},{"ruleId":"71","severity":1,"message":"78","line":3,"column":28,"nodeType":"73","messageId":"74","endLine":3,"endColumn":36},{"ruleId":"71","severity":1,"message":"79","line":8,"column":7,"nodeType":"73","messageId":"74","endLine":8,"endColumn":14},{"ruleId":"71","severity":1,"message":"80","line":17,"column":16,"nodeType":"73","messageId":"74","endLine":17,"endColumn":23},{"ruleId":"71","severity":1,"message":"77","line":1,"column":27,"nodeType":"73","messageId":"74","endLine":1,"endColumn":36},{"ruleId":"71","severity":1,"message":"81","line":2,"column":10,"nodeType":"73","messageId":"74","endLine":2,"endColumn":20},{"ruleId":"71","severity":1,"message":"82","line":6,"column":3,"nodeType":"73","messageId":"74","endLine":6,"endColumn":8},{"ruleId":"71","severity":1,"message":"83","line":7,"column":3,"nodeType":"73","messageId":"74","endLine":7,"endColumn":7},{"ruleId":"71","severity":1,"message":"84","line":12,"column":8,"nodeType":"73","messageId":"74","endLine":12,"endColumn":21},{"ruleId":"71","severity":1,"message":"85","line":17,"column":18,"nodeType":"73","messageId":"74","endLine":17,"endColumn":27},{"ruleId":"86","severity":1,"message":"87","line":36,"column":21,"nodeType":"88","messageId":"89","endLine":36,"endColumn":23},{"ruleId":"71","severity":1,"message":"90","line":2,"column":8,"nodeType":"73","messageId":"74","endLine":2,"endColumn":14},{"ruleId":"71","severity":1,"message":"91","line":8,"column":8,"nodeType":"73","messageId":"74","endLine":8,"endColumn":24},{"ruleId":"92","severity":1,"message":"93","line":83,"column":11,"nodeType":"94","endLine":86,"endColumn":13},{"ruleId":"71","severity":1,"message":"95","line":2,"column":10,"nodeType":"73","messageId":"74","endLine":2,"endColumn":16},{"ruleId":"71","severity":1,"message":"96","line":2,"column":18,"nodeType":"73","messageId":"74","endLine":2,"endColumn":24},"no-native-reassign",["97"],"no-negated-in-lhs",["98"],"no-unused-vars","'HomeContainer' is defined but never used.","Identifier","unusedVar","'Link' is defined but never used.","'Redirect' is defined but never used.","'useEffect' is defined but never used.","'useState' is defined but never used.","'history' is assigned a value but never used.","'setUser' is assigned a value but never used.","'makeStyles' is defined but never used.","'Paper' is defined but never used.","'Card' is defined but never used.","'ButtonCheckIn' is defined but never used.","'setStatus' is assigned a value but never used.","eqeqeq","Expected '===' and instead saw '=='.","BinaryExpression","unexpected","'Avatar' is defined but never used.","'LockOutlinedIcon' is defined but never used.","jsx-a11y/alt-text","img elements must have an alt prop, either with meaningful text, or an empty string for decorative images.","JSXOpeningElement","'bounce' is defined but never used.","'fadeIn' is defined but never used.","no-global-assign","no-unsafe-negation"]
\ No newline at end of file
import React, { useState, useEffect } from "react";
import HomeView from "./HomeView";
import { useLocation } from "react-router-dom";
const HomeContainer = (props) => {
return <HomeView />;
const location = useLocation();
const [state, setState] = useState({
latitude: null,
longitude: null,
});
useEffect(() => {
getPosition();
}, []);
const [user, setUser] = useState({
name: location.state.fullName,
code: location.state.code,
});
const getPosition = async () => {
navigator.geolocation.getCurrentPosition((position) => {
if (position.coords.longitude)
setState({
latitude: position.coords.latitude,
longitude: position.coords.longitude,
});
});
};
const onCheckIn = () => {
console.log(state);
};
return <HomeView user={user} onCheckIn={onCheckIn} />;
};
export default HomeContainer;
......@@ -12,38 +12,25 @@ import {
import ButtonCheckIn from "./ButtonCheckIn";
const HomeView = (props) => {
const [state, setState] = useState({
latitude: null,
longitude: null,
});
const { user, onCheckIn } = props;
const [status, setStatus] = useState(0);
const getPosition = () => {
navigator.geolocation.getCurrentPosition((position) => {
console.log(position.coords.longitude);
console.log(position.coords.latitude);
});
if (status == 0) {
setStatus(1);
} else {
setStatus(0);
}
};
useEffect(() => {
getPosition();
}, []);
return (
<Container fixed style={{ height: "100vh" }}>
<div style={{ marginTop: 50 }} />
<div style={{ textAlign: "center", fontSize: "35px" }}>
Tên: Lê Trng Trí
<Typography variant={"h4"} style={{ color: " #3399ff" }}>
Chào mng {user ? user.name : ""}
</Typography>
</div>
<br />
<Grid container style={{ height: "100vh", justifyContent: "center" }}>
<Fab
color="secondary"
aria-label="edit"
style={{ width: "20vw", height: "20vw" }}
onClick={getPosition}
style={{ width: "30vw", height: "30vw" }}
onClick={onCheckIn}
>
<span style={{ fontSize: "3vw" }}>
{status == 0 ? "Checkin" : "Checkout"}
......
import React from "react";
import React, { useState } from "react";
import Avatar from "@material-ui/core/Avatar";
import Button from "@material-ui/core/Button";
import CssBaseline from "@material-ui/core/CssBaseline";
import TextField from "@material-ui/core/TextField";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import Checkbox from "@material-ui/core/Checkbox";
import Link from "@material-ui/core/Link";
import Grid from "@material-ui/core/Grid";
import Box from "@material-ui/core/Box";
import { FormHelperText, Link, Grid, Box, Typography } from "@material-ui/core";
import { useHistory } from "react-router-dom";
import LockOutlinedIcon from "@material-ui/icons/LockOutlined";
import Typography from "@material-ui/core/Typography";
import { makeStyles } from "@material-ui/core/styles";
import Container from "@material-ui/core/Container";
import { loginApi } from "../../api/user";
function Copyright() {
return (
......@@ -46,27 +43,63 @@ const useStyles = makeStyles((theme) => ({
const LoginScreen = () => {
const classes = useStyles();
let history = useHistory();
const [state, setState] = useState({
appcode: "Dcv",
username: "",
password: "",
});
const [helperText, sethelperText] = useState("");
const onLogin = async () => {
console.log("Abc");
if (state.username === "" || state.password === "") {
sethelperText("");
sethelperText("Cần phải điền đầy đủ email và password");
} else {
sethelperText("");
console.log(state);
const res = await loginApi(state);
console.log(res.data);
if (res.data && res.data.errorCode === 0) {
localStorage.setItem("TOKEN_KEY", res.data.data.accessToken);
history.push({
pathname: "/home",
state: { code: res.data.data.code, fullName: res.data.data.fullName },
});
} else if (res.data && res.data.errorCode === 1) {
sethelperText("");
sethelperText("Sai email hoặc mật khẩu");
}
}
};
return (
<div style={{ height: "100vh" }}>
<Container component="main" maxWidth="xs">
<CssBaseline />
<div className={classes.paper}>
<Avatar className={classes.avatar}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Sign in
<img
style={{ width: 200, height: 100, marginTop: 10, marginBottom: 10 }}
src="/logo-DCV.png"
/>
<Typography color={"primary"} component="h1" variant="h5">
ĐĂNG NHP
</Typography>
<form className={classes.form} noValidate>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="email"
label="Email Address"
name="email"
label="email"
autoComplete="email"
onChange={(e) => {
setState({
...state,
username: e.target.value,
});
}}
autoFocus
/>
<TextField
......@@ -74,38 +107,41 @@ const LoginScreen = () => {
margin="normal"
required
fullWidth
name="password"
label="Password"
label="Mật khẩu"
type="password"
id="password"
onChange={(e) => {
setState({
...state,
password: e.target.value,
});
}}
autoComplete="current-password"
/>
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Remember me"
/>
<div style={{ width: "100%" }}>
<FormHelperText
style={{ marginLeft: "16px", color: "red", fontSize: "13px" }}
>
{helperText}
</FormHelperText>
</div>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
className={classes.submit}
onClick={onLogin}
>
Sign In
Đăng nhp
</Button>
<Grid container>
<Grid item xs>
<Link href="#" variant="body2">
Forgot password?
</Link>
</Grid>
<Grid item>
<Link href="#" variant="body2">
{"Don't have an account? Sign Up"}
Quên mt khu?
</Link>
</Grid>
</Grid>
</form>
</div>
<Box mt={8}>
<Copyright />
......
import axios from "axios";
axios.defaults.timeout = 10000;
export async function GetData(url, data) {
const token = localStorage.getItem("TOKEN_KEY");
let myRequest = {
method: "get",
url,
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: "Bearer " + token,
},
params: {
...data,
},
timeout: 60 * 1000,
// withCredentials: true,
};
console.log("My request", myRequest);
return await axios(myRequest)
.then((response) => response)
.then((response) => response)
.catch((error) => {
console.log(error.request);
const err = {
message: "error",
status: error.request.status,
};
return err;
});
}
export async function PostLogin(url, json, isAuth = true) {
let myRequest = {
method: "post",
url,
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
timeout: 60 * 1000,
data: JSON.stringify(json),
};
console.log("post data mobile", myRequest);
return await axios(myRequest)
.then((response) => response)
.then((response) => response)
.catch((error) => {
console.log(error.request);
const err = {
message: "error",
status: error.request.status,
};
return err;
});
}
export async function PostData(url, json, isAuth = true) {
const token = localStorage.getItem("TOKEN_KEY");
let myRequest = {
method: "post",
url,
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: "Bearer " + token,
},
timeout: 60 * 1000,
data: JSON.stringify(json),
};
console.log("post data mobile", myRequest);
return await axios(myRequest)
.then((response) => response)
.then((response) => response)
.catch((error) => {
console.log(error.request);
const err = {
message: "error",
status: error.request.status,
};
return err;
});
}
import { GetData, PostLogin, PostData } from "./api";
export const loginApi = async (body) =>
PostLogin("http://hrm.auth.dcv.vn/api/v1/auth/login", body)
.then((res) => res)
.catch((err) => err);
export const getDataApi = async (body) =>
GetData("http://hrm.auth.dcv.vn/api/v1/auth/login", body)
.then((res) => res)
.catch((err) => err);
export const checkInApi = async (body) =>
PostData("http://hrm.japi.dcv.vn/venus-service/checkinService/checkin", body)
.then((res) => res)
.catch((err) => err);
export const checkOutApi = async (body) =>
PostData("http://hrm.japi.dcv.vn/venus-service/checkinService/checkout", body)
.then((res) => res)
.catch((err) => err);
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