mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-24 04:48:03 +00:00
fix admin page checkbox style (#7852)
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import React, { Component, Fragment } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Input } from 'reactstrap';
|
import { Input } from 'reactstrap';
|
||||||
import SettingItemBase from './setting-item-base';
|
import SettingItemBase from './setting-item-base';
|
||||||
@@ -11,7 +11,7 @@ const propTypes = {
|
|||||||
displayName: PropTypes.string.isRequired
|
displayName: PropTypes.string.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
class WebSettingCheckbox extends Component {
|
class CheckboxItem extends Component {
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@@ -35,17 +35,18 @@ class WebSettingCheckbox extends Component {
|
|||||||
return (
|
return (
|
||||||
<SettingItemBase
|
<SettingItemBase
|
||||||
displayName={displayName}
|
displayName={displayName}
|
||||||
|
mainClassName='d-flex'
|
||||||
mainContent={
|
mainContent={
|
||||||
<Fragment>
|
<>
|
||||||
<Input className="ml-0" checked={inputChecked} type='checkbox' onChange={this.onInputChange} />
|
<Input className="ml-0" checked={inputChecked} type='checkbox' onChange={this.onInputChange} />
|
||||||
<p className="ml-4">{helpTip}</p>
|
<p className="ml-2">{helpTip}</p>
|
||||||
</Fragment>
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WebSettingCheckbox.propTypes = propTypes;
|
CheckboxItem.propTypes = propTypes;
|
||||||
|
|
||||||
export default WebSettingCheckbox;
|
export default CheckboxItem;
|
54
frontend/src/pages/common-admin/web-settings/file-item.js
Normal file
54
frontend/src/pages/common-admin/web-settings/file-item.js
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import React, { useRef } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { Button } from 'reactstrap';
|
||||||
|
import { gettext } from '../../../utils/constants';
|
||||||
|
import SettingItemBase from './setting-item-base';
|
||||||
|
|
||||||
|
const propTypes = {
|
||||||
|
postFile: PropTypes.func.isRequired,
|
||||||
|
keyText: PropTypes.string.isRequired,
|
||||||
|
filePath: PropTypes.string.isRequired,
|
||||||
|
helpTip: PropTypes.string.isRequired,
|
||||||
|
fileWidth: PropTypes.number.isRequired,
|
||||||
|
fileHeight: PropTypes.number.isRequired,
|
||||||
|
displayName: PropTypes.string.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
const WebSettingFile = (props) => {
|
||||||
|
|
||||||
|
const fileInput = useRef(null);
|
||||||
|
|
||||||
|
const uploadFile = () => {
|
||||||
|
if (!fileInput.current.files.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const file = fileInput.current.files[0];
|
||||||
|
props.postFile(file, props.keyText);
|
||||||
|
};
|
||||||
|
|
||||||
|
const openFileInput = () => {
|
||||||
|
fileInput.current.click();
|
||||||
|
};
|
||||||
|
|
||||||
|
const { helpTip, filePath, fileWidth, fileHeight, displayName } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SettingItemBase
|
||||||
|
displayName={displayName}
|
||||||
|
helpTip={helpTip}
|
||||||
|
mainContent={
|
||||||
|
<img src={filePath + '?t=' + new Date().getTime()} alt={displayName} width={fileWidth} height={fileHeight} className="mb-1" />
|
||||||
|
}
|
||||||
|
extraContent={
|
||||||
|
<>
|
||||||
|
<Button color="secondary" onClick={openFileInput}>{gettext('Change')}</Button>
|
||||||
|
<input className="d-none" type="file" onChange={uploadFile} ref={fileInput} />
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
WebSettingFile.propTypes = propTypes;
|
||||||
|
|
||||||
|
export default WebSettingFile;
|
21
frontend/src/pages/common-admin/web-settings/section.js
Normal file
21
frontend/src/pages/common-admin/web-settings/section.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
const propTypes = {
|
||||||
|
headingText: PropTypes.string.isRequired,
|
||||||
|
children: PropTypes.object.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
const Section = (props) => {
|
||||||
|
const { headingText, children } = props;
|
||||||
|
return (
|
||||||
|
<div className="mb-4">
|
||||||
|
<h4 className="border-bottom font-weight-normal mb-2 pb-1">{headingText}</h4>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Section.propTypes = propTypes;
|
||||||
|
|
||||||
|
export default Section;
|
@@ -0,0 +1,32 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { Row, Col, Label } from 'reactstrap';
|
||||||
|
|
||||||
|
const propTypes = {
|
||||||
|
displayName: PropTypes.string.isRequired,
|
||||||
|
helpTip: PropTypes.string,
|
||||||
|
mainContent: PropTypes.object.isRequired,
|
||||||
|
extraContent: PropTypes.object
|
||||||
|
};
|
||||||
|
|
||||||
|
function SettingItemBase(props) {
|
||||||
|
const { helpTip, displayName, mainContent, extraContent, mainClassName = '' } = props;
|
||||||
|
return (
|
||||||
|
<Row className="my-4">
|
||||||
|
<Col md="3">
|
||||||
|
<Label className="web-setting-label">{displayName}</Label>
|
||||||
|
</Col>
|
||||||
|
<Col md="5" className={mainClassName}>
|
||||||
|
{mainContent}
|
||||||
|
{helpTip && <p className="small text-secondary mt-1">{helpTip}</p>}
|
||||||
|
</Col>
|
||||||
|
<Col md="4">
|
||||||
|
{extraContent}
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingItemBase.propTypes = propTypes;
|
||||||
|
|
||||||
|
export default SettingItemBase;
|
@@ -1,58 +0,0 @@
|
|||||||
import React, { Component, Fragment } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Button } from 'reactstrap';
|
|
||||||
import { gettext } from '../../../utils/constants';
|
|
||||||
import SettingItemBase from './setting-item-base';
|
|
||||||
|
|
||||||
const propTypes = {
|
|
||||||
postFile: PropTypes.func.isRequired,
|
|
||||||
keyText: PropTypes.string.isRequired,
|
|
||||||
filePath: PropTypes.string.isRequired,
|
|
||||||
helpTip: PropTypes.string.isRequired,
|
|
||||||
fileWidth: PropTypes.number.isRequired,
|
|
||||||
fileHeight: PropTypes.number.isRequired,
|
|
||||||
displayName: PropTypes.string.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
class WebSettingFile extends Component {
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.fileInput = React.createRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
uploadFile = () => {
|
|
||||||
if (!this.fileInput.current.files.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const file = this.fileInput.current.files[0];
|
|
||||||
this.props.postFile(file, this.props.keyText);
|
|
||||||
};
|
|
||||||
|
|
||||||
openFileInput = () => {
|
|
||||||
this.fileInput.current.click();
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { helpTip, filePath, fileWidth, fileHeight, displayName } = this.props;
|
|
||||||
return (
|
|
||||||
<SettingItemBase
|
|
||||||
displayName={displayName}
|
|
||||||
helpTip={helpTip}
|
|
||||||
mainContent={
|
|
||||||
<img src={filePath + '?t=' + new Date().getTime()} alt={displayName} width={fileWidth} height={fileHeight} className="mb-1" />
|
|
||||||
}
|
|
||||||
extraContent={
|
|
||||||
<Fragment>
|
|
||||||
<Button color="secondary" onClick={this.openFileInput}>{gettext('Change')}</Button>
|
|
||||||
<input className="d-none" type="file" onChange={this.uploadFile} ref={this.fileInput} />
|
|
||||||
</Fragment>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WebSettingFile.propTypes = propTypes;
|
|
||||||
|
|
||||||
export default WebSettingFile;
|
|
@@ -2,7 +2,7 @@ import React, { Component, Fragment } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Input, Button, InputGroup } from 'reactstrap';
|
import { Input, Button, InputGroup } from 'reactstrap';
|
||||||
import { gettext } from '../../../utils/constants';
|
import { gettext } from '../../../utils/constants';
|
||||||
import SettingItemBase from './setting-item-base';
|
import SettingItemBase from '../../common-admin/web-settings/setting-item-base';
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
inputType: PropTypes.string,
|
inputType: PropTypes.string,
|
||||||
|
@@ -1,28 +0,0 @@
|
|||||||
import React, { Component } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
const propTypes = {
|
|
||||||
headingText: PropTypes.string.isRequired,
|
|
||||||
children: PropTypes.object.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
class Section extends Component {
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { headingText, children } = this.props;
|
|
||||||
return (
|
|
||||||
<div className="mb-4">
|
|
||||||
<h4 className="border-bottom font-weight-normal mb-2 pb-1">{headingText}</h4>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Section.propTypes = propTypes;
|
|
||||||
|
|
||||||
export default Section;
|
|
@@ -1,41 +0,0 @@
|
|||||||
import React, { Component, Fragment } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Row, Col, Label } from 'reactstrap';
|
|
||||||
|
|
||||||
const propTypes = {
|
|
||||||
displayName: PropTypes.string.isRequired,
|
|
||||||
helpTip: PropTypes.string,
|
|
||||||
mainContent: PropTypes.object.isRequired,
|
|
||||||
extraContent: PropTypes.object
|
|
||||||
};
|
|
||||||
|
|
||||||
class SettingItemBase extends Component {
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { helpTip, displayName, mainContent, extraContent } = this.props;
|
|
||||||
return (
|
|
||||||
<Fragment>
|
|
||||||
<Row className="my-4">
|
|
||||||
<Col md="3">
|
|
||||||
<Label className="web-setting-label">{displayName}</Label>
|
|
||||||
</Col>
|
|
||||||
<Col md="5">
|
|
||||||
{mainContent}
|
|
||||||
{helpTip && <p className="small text-secondary mt-1">{helpTip}</p>}
|
|
||||||
</Col>
|
|
||||||
<Col md="4">
|
|
||||||
{extraContent}
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Fragment>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingItemBase.propTypes = propTypes;
|
|
||||||
|
|
||||||
export default SettingItemBase;
|
|
@@ -6,10 +6,10 @@ import { gettext, mediaUrl, logoPath, orgID, orgEnableAdminCustomLogo, orgEnable
|
|||||||
import Loading from '../../../components/loading';
|
import Loading from '../../../components/loading';
|
||||||
import toaster from '../../../components/toast';
|
import toaster from '../../../components/toast';
|
||||||
import MainPanelTopbar from '../main-panel-topbar';
|
import MainPanelTopbar from '../main-panel-topbar';
|
||||||
import Section from './section';
|
import Section from '../../common-admin/web-settings/section';
|
||||||
|
import CheckboxItem from '../../common-admin/web-settings/checkbox-item';
|
||||||
|
import FileItem from '../../common-admin/web-settings/file-item';
|
||||||
import InputItem from './input-item';
|
import InputItem from './input-item';
|
||||||
import FileItem from './file-item';
|
|
||||||
import CheckboxItem from '../../sys-admin/web-settings/checkbox-item';
|
|
||||||
|
|
||||||
import '../../../css/system-admin-web-settings.css';
|
import '../../../css/system-admin-web-settings.css';
|
||||||
|
|
||||||
@@ -133,7 +133,8 @@ class OrgWebSettings extends Component {
|
|||||||
helpTip={''}
|
helpTip={''}
|
||||||
disabled={!orgEnableAdminCustomName}
|
disabled={!orgEnableAdminCustomName}
|
||||||
/>
|
/>
|
||||||
{ orgEnableAdminCustomLogo && <FileItem
|
{orgEnableAdminCustomLogo &&
|
||||||
|
<FileItem
|
||||||
postFile={this.updateLogo}
|
postFile={this.updateLogo}
|
||||||
displayName='Logo'
|
displayName='Logo'
|
||||||
keyText='Logo'
|
keyText='Logo'
|
||||||
|
@@ -1,51 +0,0 @@
|
|||||||
import React, { Component, Fragment } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Input } from 'reactstrap';
|
|
||||||
import SettingItemBase from './setting-item-base';
|
|
||||||
|
|
||||||
const propTypes = {
|
|
||||||
saveSetting: PropTypes.func.isRequired,
|
|
||||||
keyText: PropTypes.string.isRequired,
|
|
||||||
value: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]),
|
|
||||||
helpTip: PropTypes.string.isRequired,
|
|
||||||
displayName: PropTypes.string.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
class WebSettingCheckbox extends Component {
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
inputChecked: this.props.value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
onInputChange = (e) => {
|
|
||||||
const checked = e.target.checked;
|
|
||||||
const valueToNum = checked ? 1 : 0;
|
|
||||||
this.setState({
|
|
||||||
inputChecked: checked
|
|
||||||
});
|
|
||||||
this.props.saveSetting(this.props.keyText, valueToNum);
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { inputChecked } = this.state;
|
|
||||||
const { helpTip, displayName } = this.props;
|
|
||||||
return (
|
|
||||||
<SettingItemBase
|
|
||||||
displayName={displayName}
|
|
||||||
mainContent={
|
|
||||||
<Fragment>
|
|
||||||
<Input className="ml-0" checked={inputChecked} type='checkbox' onChange={this.onInputChange} />
|
|
||||||
<p className="ml-4">{helpTip}</p>
|
|
||||||
</Fragment>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WebSettingCheckbox.propTypes = propTypes;
|
|
||||||
|
|
||||||
export default WebSettingCheckbox;
|
|
@@ -1,58 +0,0 @@
|
|||||||
import React, { Component, Fragment } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Button } from 'reactstrap';
|
|
||||||
import { gettext } from '../../../utils/constants';
|
|
||||||
import SettingItemBase from './setting-item-base';
|
|
||||||
|
|
||||||
const propTypes = {
|
|
||||||
postFile: PropTypes.func.isRequired,
|
|
||||||
keyText: PropTypes.string.isRequired,
|
|
||||||
filePath: PropTypes.string.isRequired,
|
|
||||||
helpTip: PropTypes.string.isRequired,
|
|
||||||
fileWidth: PropTypes.number.isRequired,
|
|
||||||
fileHeight: PropTypes.number.isRequired,
|
|
||||||
displayName: PropTypes.string.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
class WebSettingFile extends Component {
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.fileInput = React.createRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
uploadFile = () => {
|
|
||||||
if (!this.fileInput.current.files.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const file = this.fileInput.current.files[0];
|
|
||||||
this.props.postFile(file, this.props.keyText);
|
|
||||||
};
|
|
||||||
|
|
||||||
openFileInput = () => {
|
|
||||||
this.fileInput.current.click();
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { helpTip, filePath, fileWidth, fileHeight, displayName } = this.props;
|
|
||||||
return (
|
|
||||||
<SettingItemBase
|
|
||||||
displayName={displayName}
|
|
||||||
helpTip={helpTip}
|
|
||||||
mainContent={
|
|
||||||
<img src={filePath + '?t=' + new Date().getTime()} alt={displayName} width={fileWidth} height={fileHeight} className="mb-1" />
|
|
||||||
}
|
|
||||||
extraContent={
|
|
||||||
<Fragment>
|
|
||||||
<Button color="secondary" onClick={this.openFileInput}>{gettext('Change')}</Button>
|
|
||||||
<input className="d-none" type="file" onChange={this.uploadFile} ref={this.fileInput} />
|
|
||||||
</Fragment>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WebSettingFile.propTypes = propTypes;
|
|
||||||
|
|
||||||
export default WebSettingFile;
|
|
@@ -2,7 +2,7 @@ import React, { Component, Fragment } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Input, Button } from 'reactstrap';
|
import { Input, Button } from 'reactstrap';
|
||||||
import { gettext } from '../../../utils/constants';
|
import { gettext } from '../../../utils/constants';
|
||||||
import SettingItemBase from './setting-item-base';
|
import SettingItemBase from '../../common-admin/web-settings/setting-item-base';
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
inputType: PropTypes.string,
|
inputType: PropTypes.string,
|
||||||
|
@@ -1,28 +0,0 @@
|
|||||||
import React, { Component } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
const propTypes = {
|
|
||||||
headingText: PropTypes.string.isRequired,
|
|
||||||
children: PropTypes.object.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
class Section extends Component {
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { headingText, children } = this.props;
|
|
||||||
return (
|
|
||||||
<div className="mb-4">
|
|
||||||
<h4 className="border-bottom font-weight-normal mb-2 pb-1">{headingText}</h4>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Section.propTypes = propTypes;
|
|
||||||
|
|
||||||
export default Section;
|
|
@@ -1,41 +0,0 @@
|
|||||||
import React, { Component, Fragment } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Row, Col, Label } from 'reactstrap';
|
|
||||||
|
|
||||||
const propTypes = {
|
|
||||||
displayName: PropTypes.string.isRequired,
|
|
||||||
helpTip: PropTypes.string,
|
|
||||||
mainContent: PropTypes.object.isRequired,
|
|
||||||
extraContent: PropTypes.object
|
|
||||||
};
|
|
||||||
|
|
||||||
class SettingItemBase extends Component {
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { helpTip, displayName, mainContent, extraContent } = this.props;
|
|
||||||
return (
|
|
||||||
<Fragment>
|
|
||||||
<Row className="my-4">
|
|
||||||
<Col md="3">
|
|
||||||
<Label className="web-setting-label">{displayName}</Label>
|
|
||||||
</Col>
|
|
||||||
<Col md="5">
|
|
||||||
{mainContent}
|
|
||||||
{helpTip && <p className="small text-secondary mt-1">{helpTip}</p>}
|
|
||||||
</Col>
|
|
||||||
<Col md="4">
|
|
||||||
{extraContent}
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Fragment>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingItemBase.propTypes = propTypes;
|
|
||||||
|
|
||||||
export default SettingItemBase;
|
|
@@ -5,10 +5,10 @@ import { gettext, isPro, mediaUrl, logoPath, faviconPath, loginBGPath } from '..
|
|||||||
import Loading from '../../../components/loading';
|
import Loading from '../../../components/loading';
|
||||||
import toaster from '../../../components/toast';
|
import toaster from '../../../components/toast';
|
||||||
import MainPanelTopbar from '../main-panel-topbar';
|
import MainPanelTopbar from '../main-panel-topbar';
|
||||||
import Section from './section';
|
import Section from '../../common-admin/web-settings/section';
|
||||||
|
import CheckboxItem from '../../common-admin/web-settings/checkbox-item';
|
||||||
|
import FileItem from '../../common-admin/web-settings/file-item';
|
||||||
import InputItem from './input-item';
|
import InputItem from './input-item';
|
||||||
import FileItem from './file-item';
|
|
||||||
import CheckboxItem from './checkbox-item';
|
|
||||||
|
|
||||||
import '../../../css/system-admin-web-settings.css';
|
import '../../../css/system-admin-web-settings.css';
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user