sexy boy
This commit is contained in:
parent
e67759372a
commit
436fd597b2
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -59,5 +59,5 @@ typings/
|
||||||
|
|
||||||
dist/
|
dist/
|
||||||
node_modules/
|
node_modules/
|
||||||
public/
|
|
||||||
.vscode/
|
|
||||||
|
|
29
.vscode/tasks.json
vendored
Normal file
29
.vscode/tasks.json
vendored
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||||
|
// for the documentation about the tasks.json format
|
||||||
|
"version": "0.1.0",
|
||||||
|
"isShellCommand": true,
|
||||||
|
"showOutput": "always",
|
||||||
|
"suppressTaskName": false,
|
||||||
|
"args": [
|
||||||
|
"--color"
|
||||||
|
],
|
||||||
|
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"taskName": "npm:webpack-dev-server",
|
||||||
|
"command": "npm",
|
||||||
|
"args": ["run", "webpack-dev-server"],
|
||||||
|
"isBuildCommand": true,
|
||||||
|
"isTestCommand": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"taskName": "gulp:webpack",
|
||||||
|
"command": "gulp",
|
||||||
|
"args": ["webpack"],
|
||||||
|
"isBuildCommand": true,
|
||||||
|
"isTestCommand": false
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
19
public/index.html
Normal file
19
public/index.html
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Hello React!</title>
|
||||||
|
<!--[if lte IE 9]>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-promise/4.1.0/es6-promise.auto.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
<!-- Dependencies -->
|
||||||
|
|
||||||
|
<!-- Main -->
|
||||||
|
<script src="./vendor.bundle.js"></script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="example"></div>
|
||||||
|
<script src="./bundle.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
34
src/ts/components/rest.tsx
Normal file
34
src/ts/components/rest.tsx
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
|
||||||
|
|
||||||
|
const url = "http://192.168.1.203:8080/v1/overflow/services";
|
||||||
|
|
||||||
|
export class OFRest {
|
||||||
|
|
||||||
|
obj: any;
|
||||||
|
|
||||||
|
|
||||||
|
constructor(serviceName: string, methodName: string, data: any) {
|
||||||
|
|
||||||
|
this.obj = {
|
||||||
|
"serviceName": serviceName,
|
||||||
|
"methodName": methodName,
|
||||||
|
"param": data
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Call() {
|
||||||
|
return fetch(url, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
// mode: 'no-cors'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(this.obj)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
177
src/ts/containers/member/login.tsx
Normal file
177
src/ts/containers/member/login.tsx
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
/**
|
||||||
|
* In this file, we create a React component
|
||||||
|
* which incorporates components provided by Material-UI.
|
||||||
|
*/
|
||||||
|
import * as React from 'react';
|
||||||
|
import RaisedButton from 'material-ui/RaisedButton';
|
||||||
|
import Dialog from 'material-ui/Dialog';
|
||||||
|
import { deepOrange500 } from 'material-ui/styles/colors';
|
||||||
|
import FlatButton from 'material-ui/FlatButton';
|
||||||
|
import getMuiTheme from 'material-ui/styles/getMuiTheme';
|
||||||
|
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
|
||||||
|
|
||||||
|
import * as ReactDOM from 'react-dom';
|
||||||
|
|
||||||
|
import Divider from 'material-ui/Divider';
|
||||||
|
import Paper from 'material-ui/Paper';
|
||||||
|
import TextField from 'material-ui/TextField';
|
||||||
|
|
||||||
|
import SelectField from 'material-ui/SelectField';
|
||||||
|
import MenuItem from 'material-ui/MenuItem';
|
||||||
|
|
||||||
|
import Slider from 'material-ui/Slider';
|
||||||
|
|
||||||
|
import * as http from "http"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
body: {
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
container: {
|
||||||
|
textAlign: 'center',
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
textfield: {
|
||||||
|
width: 300,
|
||||||
|
marginLeft: 3
|
||||||
|
},
|
||||||
|
|
||||||
|
customWidth: {
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
margin: 12,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const muiTheme = getMuiTheme({
|
||||||
|
palette: {
|
||||||
|
accent1Color: deepOrange500,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export class MemberLogin extends React.Component<any, any> {
|
||||||
|
constructor(props: any, context: any) {
|
||||||
|
super(props, context);
|
||||||
|
|
||||||
|
this.handleSignUp = this.handleSignUp.bind(this);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
open: false,
|
||||||
|
value: 1,
|
||||||
|
|
||||||
|
email: "",
|
||||||
|
pw: "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChange = () => this.setState({});
|
||||||
|
|
||||||
|
private emailInput: any;
|
||||||
|
|
||||||
|
handleRequestClose = () => {
|
||||||
|
this.setState({
|
||||||
|
open: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTouchTap = () => {
|
||||||
|
this.setState({
|
||||||
|
open: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSignUp = () => {
|
||||||
|
|
||||||
|
let output: string;
|
||||||
|
let obj: any; //new object declaration
|
||||||
|
obj = {
|
||||||
|
"email": this.state.email,
|
||||||
|
"pwSalt": this.state.pw,
|
||||||
|
};
|
||||||
|
|
||||||
|
let exeObj: any;
|
||||||
|
exeObj = {
|
||||||
|
"serviceName": "Member",
|
||||||
|
"methodName": "Login",
|
||||||
|
"param": obj
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
output = JSON.stringify(exeObj);
|
||||||
|
|
||||||
|
// obj = { "value": output };
|
||||||
|
|
||||||
|
fetch('http://192.168.1.203:8080/v1/overflow/services', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
// mode: 'no-cors'
|
||||||
|
},
|
||||||
|
body: output
|
||||||
|
}).then(function (response) {
|
||||||
|
return response.json();
|
||||||
|
}).then(function (json) {
|
||||||
|
console.log(json);
|
||||||
|
|
||||||
|
}).catch((err) => {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
btnTouchTap = () => {
|
||||||
|
alert(event)
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MuiThemeProvider muiTheme={muiTheme}>
|
||||||
|
|
||||||
|
<div style={styles.container}>
|
||||||
|
<h1>Log in with a overflow Account:</h1>
|
||||||
|
<br />
|
||||||
|
<TextField
|
||||||
|
ref="email"
|
||||||
|
hintText="smith@gmail.com"
|
||||||
|
floatingLabelText="Email address*"
|
||||||
|
errorText=""
|
||||||
|
style={styles.textfield}
|
||||||
|
underlineShow={true}
|
||||||
|
value={this.state.email}
|
||||||
|
onChange={(e, newValue) => this.setState({ email: newValue })}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
hintText="Password"
|
||||||
|
floatingLabelText="Password"
|
||||||
|
type="password"
|
||||||
|
style={styles.textfield}
|
||||||
|
value={this.state.pw}
|
||||||
|
onChange={(e, newValue) => this.setState({ pw: newValue })}
|
||||||
|
/>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
|
||||||
|
<RaisedButton label="Sign In" primary={true} style={styles.button} onClick={this.handleSignUp.bind(this)} />
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</MuiThemeProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@ import * as http from "http"
|
||||||
|
|
||||||
import { MemberRegistResult } from './registResult';
|
import { MemberRegistResult } from './registResult';
|
||||||
|
|
||||||
|
import { OFRest } from '../../components/rest';
|
||||||
|
|
||||||
|
|
||||||
const styles = {
|
const styles = {
|
||||||
body: {
|
body: {
|
||||||
|
@ -60,10 +62,13 @@ export class MemberRegist extends React.Component<any, any> {
|
||||||
|
|
||||||
this.handleSignUp = this.handleSignUp.bind(this);
|
this.handleSignUp = this.handleSignUp.bind(this);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
open: false,
|
open: false,
|
||||||
value: 1,
|
value: 1,
|
||||||
|
|
||||||
|
id:0,
|
||||||
email: "",
|
email: "",
|
||||||
name: "",
|
name: "",
|
||||||
company: "",
|
company: "",
|
||||||
|
@ -76,17 +81,7 @@ export class MemberRegist extends React.Component<any, any> {
|
||||||
|
|
||||||
private emailInput: any;
|
private emailInput: any;
|
||||||
|
|
||||||
handleRequestClose = () => {
|
|
||||||
this.setState({
|
|
||||||
open: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleTouchTap = () => {
|
|
||||||
this.setState({
|
|
||||||
open: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleSignUp = () => {
|
handleSignUp = () => {
|
||||||
|
|
||||||
|
@ -100,17 +95,74 @@ export class MemberRegist extends React.Component<any, any> {
|
||||||
"phone": this.state.phone
|
"phone": this.state.phone
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let os: OFRest = new OFRest("Member", "Regist", obj);
|
||||||
|
|
||||||
|
os.Call().then(function (res) {
|
||||||
|
return res.json();
|
||||||
|
}).then(function(json) {
|
||||||
|
console.log(json);
|
||||||
|
ReactDOM.render(<MemberRegistResult />, document.getElementById('example'));
|
||||||
|
}).catch(function(err) {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
// let exeObj: any;
|
||||||
|
// exeObj = {
|
||||||
|
// "serviceName": "Member",
|
||||||
|
// "methodName": "Regist",
|
||||||
|
// "param": obj
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// output = JSON.stringify(exeObj);
|
||||||
|
|
||||||
|
// // obj = { "value": output };
|
||||||
|
|
||||||
|
// fetch('http://192.168.1.203:8080/v1/overflow/services', {
|
||||||
|
// method: 'POST',
|
||||||
|
// headers: {
|
||||||
|
// 'Accept': 'application/json',
|
||||||
|
// // mode: 'no-cors'
|
||||||
|
// },
|
||||||
|
// body: output
|
||||||
|
// }).then(function (response) {
|
||||||
|
// return response.json();
|
||||||
|
// }).then(function (json) {
|
||||||
|
// console.log(json);
|
||||||
|
// ReactDOM.render(<MemberRegistResult />, document.getElementById('example')
|
||||||
|
// );
|
||||||
|
// }).catch((err) => {
|
||||||
|
// console.log(err);
|
||||||
|
// });
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTestRead = () => {
|
||||||
|
let output: string;
|
||||||
|
let obj: any; //new object declaration
|
||||||
|
obj = {
|
||||||
|
"id":this.state.id,
|
||||||
|
"email": this.state.email,
|
||||||
|
"pwSalt": this.state.pw,
|
||||||
|
"name": this.state.name,
|
||||||
|
"company": this.state.company,
|
||||||
|
"phone": this.state.phone
|
||||||
|
};
|
||||||
|
|
||||||
let exeObj: any;
|
let exeObj: any;
|
||||||
exeObj = {
|
exeObj = {
|
||||||
"serviceName": "Member",
|
"serviceName": "Member",
|
||||||
"methodName":"Regist",
|
"methodName": "Read",
|
||||||
"param": obj
|
"param": obj
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
output = JSON.stringify(exeObj);
|
output = JSON.stringify(exeObj);
|
||||||
|
|
||||||
// obj = { "value": output };
|
|
||||||
|
|
||||||
fetch('http://192.168.1.203:8080/v1/overflow/services', {
|
fetch('http://192.168.1.203:8080/v1/overflow/services', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
@ -123,16 +175,87 @@ export class MemberRegist extends React.Component<any, any> {
|
||||||
return response.json();
|
return response.json();
|
||||||
}).then(function (json) {
|
}).then(function (json) {
|
||||||
console.log(json);
|
console.log(json);
|
||||||
ReactDOM.render(<MemberRegistResult />, document.getElementById('example')
|
|
||||||
);
|
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTestUpdate = () => {
|
||||||
|
let output: string;
|
||||||
|
let obj: any; //new object declaration
|
||||||
|
obj = {
|
||||||
|
"id":this.state.id,
|
||||||
|
"email": this.state.email,
|
||||||
|
"pwSalt": this.state.pw,
|
||||||
|
"name": this.state.name,
|
||||||
|
"company": this.state.company,
|
||||||
|
"phone": this.state.phone
|
||||||
|
};
|
||||||
|
|
||||||
|
let exeObj: any;
|
||||||
|
exeObj = {
|
||||||
|
"serviceName": "Member",
|
||||||
|
"methodName": "Modify",
|
||||||
|
"param": obj
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
output = JSON.stringify(exeObj);
|
||||||
|
|
||||||
|
|
||||||
|
fetch('http://192.168.1.203:8080/v1/overflow/services', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
// mode: 'no-cors'
|
||||||
|
},
|
||||||
|
body: output
|
||||||
|
}).then(function (response) {
|
||||||
|
return response.json();
|
||||||
|
}).then(function (json) {
|
||||||
|
console.log(json);
|
||||||
|
}).catch((err) => {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTestDelete = () => {
|
||||||
|
let output: string;
|
||||||
|
let obj: any; //new object declaration
|
||||||
|
obj = {
|
||||||
|
"id":this.state.id,
|
||||||
|
"email": this.state.email,
|
||||||
|
"pwSalt": this.state.pw,
|
||||||
|
"name": this.state.name,
|
||||||
|
"company": this.state.company,
|
||||||
|
"phone": this.state.phone
|
||||||
|
};
|
||||||
|
|
||||||
|
let exeObj: any;
|
||||||
|
exeObj = {
|
||||||
|
"serviceName": "Member",
|
||||||
|
"methodName": "Remove",
|
||||||
|
"param": obj
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
output = JSON.stringify(exeObj);
|
||||||
|
|
||||||
|
|
||||||
|
fetch('http://192.168.1.203:8080/v1/overflow/services', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
// mode: 'no-cors'
|
||||||
|
},
|
||||||
|
body: output
|
||||||
|
}).then(function (response) {
|
||||||
|
return response.json();
|
||||||
|
}).then(function (json) {
|
||||||
|
console.log(json);
|
||||||
|
}).catch((err) => {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -213,7 +336,18 @@ export class MemberRegist extends React.Component<any, any> {
|
||||||
|
|
||||||
|
|
||||||
<RaisedButton label="Sign Up" primary={true} style={styles.button} onClick={this.handleSignUp.bind(this)} />
|
<RaisedButton label="Sign Up" primary={true} style={styles.button} onClick={this.handleSignUp.bind(this)} />
|
||||||
|
<RaisedButton label="Read" primary={true} style={styles.button} onClick={this.handleTestRead.bind(this)} />
|
||||||
|
<RaisedButton label="Update" primary={true} style={styles.button} onClick={this.handleTestUpdate.bind(this)} />
|
||||||
|
<RaisedButton label="Delete" primary={true} style={styles.button} onClick={this.handleTestDelete.bind(this)} />
|
||||||
|
<br/>
|
||||||
|
<TextField
|
||||||
|
hintText="id"
|
||||||
|
floatingLabelText="id"
|
||||||
|
|
||||||
|
style={styles.textfield}
|
||||||
|
value={this.state.id}
|
||||||
|
onChange={(e, newValue) => this.setState({ id: newValue })}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</MuiThemeProvider>
|
</MuiThemeProvider>
|
||||||
|
|
58
src/ts/containers/prove/download.tsx
Normal file
58
src/ts/containers/prove/download.tsx
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { List, ListItem } from 'material-ui/List';
|
||||||
|
import ContentInbox from 'material-ui/svg-icons/content/inbox';
|
||||||
|
import ActionGrade from 'material-ui/svg-icons/action/grade';
|
||||||
|
import ContentSend from 'material-ui/svg-icons/content/send';
|
||||||
|
import ContentDrafts from 'material-ui/svg-icons/content/drafts';
|
||||||
|
import Divider from 'material-ui/Divider';
|
||||||
|
import ActionInfo from 'material-ui/svg-icons/action/info';
|
||||||
|
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
|
||||||
|
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
container: {
|
||||||
|
textAlign: "center",
|
||||||
|
width: 250,
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ProveDownload extends React.Component<any, any> {
|
||||||
|
constructor(props: any, context: any) {
|
||||||
|
super(props, context)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
render() {
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MuiThemeProvider >
|
||||||
|
<div style={styles.container}>
|
||||||
|
<List>
|
||||||
|
<ListItem primaryText="Mac OS X" leftIcon={<ContentInbox />} />
|
||||||
|
<ListItem primaryText="Windows" leftIcon={<ContentInbox />} />
|
||||||
|
<ListItem primaryText="Debian" leftIcon={<ContentInbox />} />
|
||||||
|
<ListItem primaryText="Ubuntu" leftIcon={<ContentInbox />} />
|
||||||
|
<ListItem primaryText="Amazon Linux" leftIcon={<ContentInbox />} />
|
||||||
|
<ListItem primaryText="CentOS/RedJat" leftIcon={<ContentInbox />} />
|
||||||
|
<ListItem primaryText="Fedora" leftIcon={<ContentInbox />} />
|
||||||
|
<ListItem primaryText="SUSE" leftIcon={<ContentInbox />} />
|
||||||
|
<ListItem primaryText="CoreOS" leftIcon={<ContentInbox />} />
|
||||||
|
<ListItem primaryText="Docker" leftIcon={<ContentInbox />} />
|
||||||
|
<ListItem primaryText="Kubernetes" leftIcon={<ContentInbox />} />
|
||||||
|
<ListItem primaryText="Openshift" leftIcon={<ContentInbox />} />
|
||||||
|
<ListItem primaryText="Chef" leftIcon={<ContentInbox />} />
|
||||||
|
<ListItem primaryText="Puppet" leftIcon={<ContentInbox />} />
|
||||||
|
<ListItem primaryText="Ansible" leftIcon={<ContentInbox />} />
|
||||||
|
<ListItem primaryText="From Source" leftIcon={<ContentInbox />} />
|
||||||
|
</List>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</MuiThemeProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
0
src/ts/containers/prove/installguide.tsx
Normal file
0
src/ts/containers/prove/installguide.tsx
Normal file
|
@ -4,6 +4,9 @@ import * as injectTapEventPlugin from 'react-tap-event-plugin';
|
||||||
import { MemberRegist } from './containers/member/regist';
|
import { MemberRegist } from './containers/member/regist';
|
||||||
import { MemberRegistResult } from './containers/member/registResult';
|
import { MemberRegistResult } from './containers/member/registResult';
|
||||||
import { MemberEmailConfirm } from './containers/member/emailConfirm';
|
import { MemberEmailConfirm } from './containers/member/emailConfirm';
|
||||||
|
import { MemberLogin } from './containers/member/login';
|
||||||
|
import { Main } from './containers/Main';
|
||||||
|
import { ProveDownload } from './containers/prove/download';
|
||||||
|
|
||||||
|
|
||||||
import '../scss/index.scss';
|
import '../scss/index.scss';
|
||||||
|
|
Loading…
Reference in New Issue
Block a user