2022-01-17 09:41:33 +01:00
|
|
|
import PropTypes from 'prop-types';
|
2023-05-23 17:15:17 +02:00
|
|
|
import { PureComponent } from 'react';
|
|
|
|
|
2022-01-17 09:41:33 +01:00
|
|
|
import { injectIntl, defineMessages } from 'react-intl';
|
2023-05-23 17:15:17 +02:00
|
|
|
|
2022-01-17 09:41:33 +01:00
|
|
|
import classNames from 'classnames';
|
|
|
|
|
2023-05-23 17:15:17 +02:00
|
|
|
import api from 'mastodon/api';
|
|
|
|
|
2022-01-17 09:41:33 +01:00
|
|
|
const messages = defineMessages({
|
2023-08-16 16:38:33 +02:00
|
|
|
legal: { id: 'report.categories.legal', defaultMessage: 'Legal' },
|
2022-01-17 09:41:33 +01:00
|
|
|
other: { id: 'report.categories.other', defaultMessage: 'Other' },
|
|
|
|
spam: { id: 'report.categories.spam', defaultMessage: 'Spam' },
|
|
|
|
violation: { id: 'report.categories.violation', defaultMessage: 'Content violates one or more server rules' },
|
|
|
|
});
|
|
|
|
|
2023-05-23 10:52:27 +02:00
|
|
|
class Category extends PureComponent {
|
2022-01-17 09:41:33 +01:00
|
|
|
|
|
|
|
static propTypes = {
|
|
|
|
id: PropTypes.string.isRequired,
|
|
|
|
text: PropTypes.string.isRequired,
|
|
|
|
selected: PropTypes.bool,
|
|
|
|
disabled: PropTypes.bool,
|
|
|
|
onSelect: PropTypes.func,
|
|
|
|
children: PropTypes.node,
|
|
|
|
};
|
|
|
|
|
|
|
|
handleClick = () => {
|
|
|
|
const { id, disabled, onSelect } = this.props;
|
|
|
|
|
|
|
|
if (!disabled) {
|
|
|
|
onSelect(id);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
render () {
|
|
|
|
const { id, text, disabled, selected, children } = this.props;
|
|
|
|
|
|
|
|
return (
|
2023-04-04 16:33:44 +02:00
|
|
|
<div tabIndex={0} role='button' className={classNames('report-reason-selector__category', { selected, disabled })} onClick={this.handleClick}>
|
2022-01-17 09:41:33 +01:00
|
|
|
{selected && <input type='hidden' name='report[category]' value={id} />}
|
|
|
|
|
|
|
|
<div className='report-reason-selector__category__label'>
|
|
|
|
<span className={classNames('poll__input', { active: selected, disabled })} />
|
|
|
|
{text}
|
|
|
|
</div>
|
|
|
|
|
|
|
|
{(selected && children) && (
|
|
|
|
<div className='report-reason-selector__category__rules'>
|
|
|
|
{children}
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-05-23 10:52:27 +02:00
|
|
|
class Rule extends PureComponent {
|
2022-01-17 09:41:33 +01:00
|
|
|
|
|
|
|
static propTypes = {
|
|
|
|
id: PropTypes.string.isRequired,
|
|
|
|
text: PropTypes.string.isRequired,
|
|
|
|
selected: PropTypes.bool,
|
|
|
|
disabled: PropTypes.bool,
|
|
|
|
onToggle: PropTypes.func,
|
|
|
|
};
|
|
|
|
|
|
|
|
handleClick = () => {
|
|
|
|
const { id, disabled, onToggle } = this.props;
|
|
|
|
|
|
|
|
if (!disabled) {
|
|
|
|
onToggle(id);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
render () {
|
|
|
|
const { id, text, disabled, selected } = this.props;
|
|
|
|
|
|
|
|
return (
|
2023-04-04 16:33:44 +02:00
|
|
|
<div tabIndex={0} role='button' className={classNames('report-reason-selector__rule', { selected, disabled })} onClick={this.handleClick}>
|
2022-01-17 09:41:33 +01:00
|
|
|
<span className={classNames('poll__input', { checkbox: true, active: selected, disabled })} />
|
|
|
|
{selected && <input type='hidden' name='report[rule_ids][]' value={id} />}
|
|
|
|
{text}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-05-23 10:52:27 +02:00
|
|
|
class ReportReasonSelector extends PureComponent {
|
2022-01-17 09:41:33 +01:00
|
|
|
|
|
|
|
static propTypes = {
|
|
|
|
id: PropTypes.string.isRequired,
|
|
|
|
category: PropTypes.string.isRequired,
|
|
|
|
rule_ids: PropTypes.arrayOf(PropTypes.string),
|
|
|
|
disabled: PropTypes.bool,
|
|
|
|
intl: PropTypes.object.isRequired,
|
|
|
|
};
|
|
|
|
|
|
|
|
state = {
|
|
|
|
category: this.props.category,
|
|
|
|
rule_ids: this.props.rule_ids || [],
|
|
|
|
rules: [],
|
|
|
|
};
|
|
|
|
|
|
|
|
componentDidMount() {
|
2024-05-23 09:30:48 +02:00
|
|
|
api(false).get('/api/v1/instance').then(res => {
|
2022-01-17 09:41:33 +01:00
|
|
|
this.setState({
|
|
|
|
rules: res.data.rules,
|
|
|
|
});
|
|
|
|
}).catch(err => {
|
|
|
|
console.error(err);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
_save = () => {
|
|
|
|
const { id, disabled } = this.props;
|
|
|
|
const { category, rule_ids } = this.state;
|
|
|
|
|
|
|
|
if (disabled) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-05-23 09:30:48 +02:00
|
|
|
api(false).put(`/api/v1/admin/reports/${id}`, {
|
2022-01-17 09:41:33 +01:00
|
|
|
category,
|
2024-02-06 10:35:36 +01:00
|
|
|
rule_ids: category === 'violation' ? rule_ids : [],
|
2022-01-17 09:41:33 +01:00
|
|
|
}).catch(err => {
|
|
|
|
console.error(err);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
handleSelect = id => {
|
|
|
|
this.setState({ category: id }, () => this._save());
|
|
|
|
};
|
|
|
|
|
|
|
|
handleToggle = id => {
|
|
|
|
const { rule_ids } = this.state;
|
|
|
|
|
|
|
|
if (rule_ids.includes(id)) {
|
|
|
|
this.setState({ rule_ids: rule_ids.filter(x => x !== id ) }, () => this._save());
|
|
|
|
} else {
|
|
|
|
this.setState({ rule_ids: [...rule_ids, id] }, () => this._save());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
render () {
|
|
|
|
const { disabled, intl } = this.props;
|
|
|
|
const { rules, category, rule_ids } = this.state;
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div className='report-reason-selector'>
|
|
|
|
<Category id='other' text={intl.formatMessage(messages.other)} selected={category === 'other'} onSelect={this.handleSelect} disabled={disabled} />
|
2023-08-16 16:38:33 +02:00
|
|
|
<Category id='legal' text={intl.formatMessage(messages.legal)} selected={category === 'legal'} onSelect={this.handleSelect} disabled={disabled} />
|
2022-01-17 09:41:33 +01:00
|
|
|
<Category id='spam' text={intl.formatMessage(messages.spam)} selected={category === 'spam'} onSelect={this.handleSelect} disabled={disabled} />
|
2024-08-19 14:28:06 +02:00
|
|
|
<Category id='violation' text={intl.formatMessage(messages.violation)} selected={category === 'violation'} onSelect={this.handleSelect} disabled={disabled || rules.length === 0}>
|
2022-01-17 09:41:33 +01:00
|
|
|
{rules.map(rule => <Rule key={rule.id} id={rule.id} text={rule.text} selected={rule_ids.includes(rule.id)} onToggle={this.handleToggle} disabled={disabled} />)}
|
|
|
|
</Category>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2023-03-24 03:17:53 +01:00
|
|
|
|
|
|
|
export default injectIntl(ReportReasonSelector);
|