commit
9dd62c95c5
@ -1,89 +1,38 @@
|
|||||||
import api from '../api';
|
import api from '../api';
|
||||||
import { openModal, closeModal } from './modal';
|
import { openModal } from './modal';
|
||||||
|
|
||||||
export const REPORT_INIT = 'REPORT_INIT';
|
|
||||||
export const REPORT_CANCEL = 'REPORT_CANCEL';
|
|
||||||
|
|
||||||
export const REPORT_SUBMIT_REQUEST = 'REPORT_SUBMIT_REQUEST';
|
export const REPORT_SUBMIT_REQUEST = 'REPORT_SUBMIT_REQUEST';
|
||||||
export const REPORT_SUBMIT_SUCCESS = 'REPORT_SUBMIT_SUCCESS';
|
export const REPORT_SUBMIT_SUCCESS = 'REPORT_SUBMIT_SUCCESS';
|
||||||
export const REPORT_SUBMIT_FAIL = 'REPORT_SUBMIT_FAIL';
|
export const REPORT_SUBMIT_FAIL = 'REPORT_SUBMIT_FAIL';
|
||||||
|
|
||||||
export const REPORT_STATUS_TOGGLE = 'REPORT_STATUS_TOGGLE';
|
export const initReport = (account, status) => dispatch =>
|
||||||
export const REPORT_COMMENT_CHANGE = 'REPORT_COMMENT_CHANGE';
|
dispatch(openModal('REPORT', {
|
||||||
export const REPORT_FORWARD_CHANGE = 'REPORT_FORWARD_CHANGE';
|
accountId: account.get('id'),
|
||||||
|
statusId: status.get('id'),
|
||||||
export function initReport(account, status) {
|
}));
|
||||||
return dispatch => {
|
|
||||||
dispatch({
|
export const submitReport = (params, onSuccess, onFail) => (dispatch, getState) => {
|
||||||
type: REPORT_INIT,
|
dispatch(submitReportRequest());
|
||||||
account,
|
|
||||||
status,
|
api(getState).post('/api/v1/reports', params).then(response => {
|
||||||
});
|
dispatch(submitReportSuccess(response.data));
|
||||||
|
if (onSuccess) onSuccess();
|
||||||
dispatch(openModal('REPORT'));
|
}).catch(error => {
|
||||||
};
|
dispatch(submitReportFail(error));
|
||||||
};
|
if (onFail) onFail();
|
||||||
|
});
|
||||||
export function cancelReport() {
|
};
|
||||||
return {
|
|
||||||
type: REPORT_CANCEL,
|
export const submitReportRequest = () => ({
|
||||||
};
|
type: REPORT_SUBMIT_REQUEST,
|
||||||
};
|
});
|
||||||
|
|
||||||
export function toggleStatusReport(statusId, checked) {
|
export const submitReportSuccess = report => ({
|
||||||
return {
|
type: REPORT_SUBMIT_SUCCESS,
|
||||||
type: REPORT_STATUS_TOGGLE,
|
report,
|
||||||
statusId,
|
});
|
||||||
checked,
|
|
||||||
};
|
export const submitReportFail = error => ({
|
||||||
};
|
type: REPORT_SUBMIT_FAIL,
|
||||||
|
error,
|
||||||
export function submitReport() {
|
});
|
||||||
return (dispatch, getState) => {
|
|
||||||
dispatch(submitReportRequest());
|
|
||||||
|
|
||||||
api(getState).post('/api/v1/reports', {
|
|
||||||
account_id: getState().getIn(['reports', 'new', 'account_id']),
|
|
||||||
status_ids: getState().getIn(['reports', 'new', 'status_ids']),
|
|
||||||
comment: getState().getIn(['reports', 'new', 'comment']),
|
|
||||||
forward: getState().getIn(['reports', 'new', 'forward']),
|
|
||||||
}).then(response => {
|
|
||||||
dispatch(closeModal());
|
|
||||||
dispatch(submitReportSuccess(response.data));
|
|
||||||
}).catch(error => dispatch(submitReportFail(error)));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export function submitReportRequest() {
|
|
||||||
return {
|
|
||||||
type: REPORT_SUBMIT_REQUEST,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export function submitReportSuccess(report) {
|
|
||||||
return {
|
|
||||||
type: REPORT_SUBMIT_SUCCESS,
|
|
||||||
report,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export function submitReportFail(error) {
|
|
||||||
return {
|
|
||||||
type: REPORT_SUBMIT_FAIL,
|
|
||||||
error,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export function changeReportComment(comment) {
|
|
||||||
return {
|
|
||||||
type: REPORT_COMMENT_CHANGE,
|
|
||||||
comment,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export function changeReportForward(forward) {
|
|
||||||
return {
|
|
||||||
type: REPORT_FORWARD_CHANGE,
|
|
||||||
forward,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
import api from '../api';
|
||||||
|
|
||||||
|
export const RULES_FETCH_REQUEST = 'RULES_FETCH_REQUEST';
|
||||||
|
export const RULES_FETCH_SUCCESS = 'RULES_FETCH_SUCCESS';
|
||||||
|
export const RULES_FETCH_FAIL = 'RULES_FETCH_FAIL';
|
||||||
|
|
||||||
|
export const fetchRules = () => (dispatch, getState) => {
|
||||||
|
dispatch(fetchRulesRequest());
|
||||||
|
|
||||||
|
api(getState)
|
||||||
|
.get('/api/v1/instance').then(({ data }) => dispatch(fetchRulesSuccess(data.rules)))
|
||||||
|
.catch(err => dispatch(fetchRulesFail(err)));
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchRulesRequest = () => ({
|
||||||
|
type: RULES_FETCH_REQUEST,
|
||||||
|
});
|
||||||
|
|
||||||
|
const fetchRulesSuccess = rules => ({
|
||||||
|
type: RULES_FETCH_SUCCESS,
|
||||||
|
rules,
|
||||||
|
});
|
||||||
|
|
||||||
|
const fetchRulesFail = error => ({
|
||||||
|
type: RULES_FETCH_FAIL,
|
||||||
|
error,
|
||||||
|
});
|
@ -0,0 +1,9 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const Check = () => (
|
||||||
|
<svg width='14' height='11' viewBox='0 0 14 11'>
|
||||||
|
<path d='M11.264 0L5.26 6.004 2.103 2.847 0 4.95l5.26 5.26 8.108-8.107L11.264 0' fill='currentColor' fillRule='evenodd' />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default Check;
|
@ -0,0 +1,93 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
|
import Button from 'mastodon/components/button';
|
||||||
|
import Option from './components/option';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
dislike: { id: 'report.reasons.dislike', defaultMessage: 'I don\'t like it' },
|
||||||
|
dislike_description: { id: 'report.reasons.dislike_description', defaultMessage: 'It is not something you want to see' },
|
||||||
|
spam: { id: 'report.reasons.spam', defaultMessage: 'It\'s spam' },
|
||||||
|
spam_description: { id: 'report.reasons.spam_description', defaultMessage: 'Malicious links, fake engagement, or repetetive replies' },
|
||||||
|
violation: { id: 'report.reasons.violation', defaultMessage: 'It violates server rules' },
|
||||||
|
violation_description: { id: 'report.reasons.violation_description', defaultMessage: 'You are aware that it breaks specific rules' },
|
||||||
|
other: { id: 'report.reasons.other', defaultMessage: 'It\'s something else' },
|
||||||
|
other_description: { id: 'report.reasons.other_description', defaultMessage: 'The issue does not fit into other categories' },
|
||||||
|
status: { id: 'report.category.title_status', defaultMessage: 'post' },
|
||||||
|
account: { id: 'report.category.title_account', defaultMessage: 'profile' },
|
||||||
|
});
|
||||||
|
|
||||||
|
export default @injectIntl
|
||||||
|
class Category extends React.PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
onNextStep: PropTypes.func.isRequired,
|
||||||
|
category: PropTypes.string,
|
||||||
|
onChangeCategory: PropTypes.func.isRequired,
|
||||||
|
startedFrom: PropTypes.oneOf(['status', 'account']),
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
handleNextClick = () => {
|
||||||
|
const { onNextStep, category } = this.props;
|
||||||
|
|
||||||
|
switch(category) {
|
||||||
|
case 'dislike':
|
||||||
|
onNextStep('thanks');
|
||||||
|
break;
|
||||||
|
case 'violation':
|
||||||
|
onNextStep('rules');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
onNextStep('statuses');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handleCategoryToggle = (value, checked) => {
|
||||||
|
const { onChangeCategory } = this.props;
|
||||||
|
|
||||||
|
if (checked) {
|
||||||
|
onChangeCategory(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { category, startedFrom, intl } = this.props;
|
||||||
|
|
||||||
|
const options = [
|
||||||
|
'dislike',
|
||||||
|
'spam',
|
||||||
|
'violation',
|
||||||
|
'other',
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<h3 className='report-dialog-modal__title'><FormattedMessage id='report.category.title' defaultMessage="Tell us what's going on with this {type}" values={{ type: intl.formatMessage(messages[startedFrom]) }} /></h3>
|
||||||
|
<p className='report-dialog-modal__lead'><FormattedMessage id='report.category.subtitle' defaultMessage='Choose the best match' /></p>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{options.map(item => (
|
||||||
|
<Option
|
||||||
|
key={item}
|
||||||
|
name='category'
|
||||||
|
value={item}
|
||||||
|
checked={category === item}
|
||||||
|
onToggle={this.handleCategoryToggle}
|
||||||
|
label={intl.formatMessage(messages[item])}
|
||||||
|
description={intl.formatMessage(messages[`${item}_description`])}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex-spacer' />
|
||||||
|
|
||||||
|
<div className='report-dialog-modal__actions'>
|
||||||
|
<Button onClick={this.handleNextClick} disabled={category === null}><FormattedMessage id='report.next' defaultMessage='Next' /></Button>
|
||||||
|
</div>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { injectIntl, defineMessages, FormattedMessage } from 'react-intl';
|
||||||
|
import Button from 'mastodon/components/button';
|
||||||
|
import Toggle from 'react-toggle';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
placeholder: { id: 'report.placeholder', defaultMessage: 'Type or paste additional comments' },
|
||||||
|
});
|
||||||
|
|
||||||
|
export default @injectIntl
|
||||||
|
class Comment extends React.PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
onSubmit: PropTypes.func.isRequired,
|
||||||
|
comment: PropTypes.string.isRequired,
|
||||||
|
onChangeComment: PropTypes.func.isRequired,
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
isSubmitting: PropTypes.bool,
|
||||||
|
forward: PropTypes.bool,
|
||||||
|
isRemote: PropTypes.bool,
|
||||||
|
domain: PropTypes.string,
|
||||||
|
onChangeForward: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
handleClick = () => {
|
||||||
|
const { onSubmit } = this.props;
|
||||||
|
onSubmit();
|
||||||
|
};
|
||||||
|
|
||||||
|
handleChange = e => {
|
||||||
|
const { onChangeComment } = this.props;
|
||||||
|
onChangeComment(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
handleKeyDown = e => {
|
||||||
|
if (e.keyCode === 13 && (e.ctrlKey || e.metaKey)) {
|
||||||
|
this.handleClick();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handleForwardChange = e => {
|
||||||
|
const { onChangeForward } = this.props;
|
||||||
|
onChangeForward(e.target.checked);
|
||||||
|
};
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { comment, isRemote, forward, domain, isSubmitting, intl } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<h3 className='report-dialog-modal__title'><FormattedMessage id='report.comment.title' defaultMessage='Is there anything else you think we should know?' /></h3>
|
||||||
|
|
||||||
|
<textarea
|
||||||
|
className='report-dialog-modal__textarea'
|
||||||
|
placeholder={intl.formatMessage(messages.placeholder)}
|
||||||
|
value={comment}
|
||||||
|
onChange={this.handleChange}
|
||||||
|
onKeyDown={this.handleKeyDown}
|
||||||
|
disabled={isSubmitting}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{isRemote && (
|
||||||
|
<React.Fragment>
|
||||||
|
<p className='report-dialog-modal__lead'><FormattedMessage id='report.forward_hint' defaultMessage='The account is from another server. Send an anonymized copy of the report there as well?' /></p>
|
||||||
|
|
||||||
|
<label className='report-dialog-modal__toggle'>
|
||||||
|
<Toggle checked={forward} disabled={isSubmitting} onChange={this.handleForwardChange} />
|
||||||
|
<FormattedMessage id='report.forward' defaultMessage='Forward to {target}' values={{ target: domain }} />
|
||||||
|
</label>
|
||||||
|
</React.Fragment>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className='flex-spacer' />
|
||||||
|
|
||||||
|
<div className='report-dialog-modal__actions'>
|
||||||
|
<Button onClick={this.handleClick}><FormattedMessage id='report.submit' defaultMessage='Submit report' /></Button>
|
||||||
|
</div>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import Check from 'mastodon/components/check';
|
||||||
|
|
||||||
|
export default class Option extends React.PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
name: PropTypes.string.isRequired,
|
||||||
|
value: PropTypes.string.isRequired,
|
||||||
|
checked: PropTypes.bool,
|
||||||
|
label: PropTypes.node,
|
||||||
|
description: PropTypes.node,
|
||||||
|
onToggle: PropTypes.func,
|
||||||
|
multiple: PropTypes.bool,
|
||||||
|
labelComponent: PropTypes.node,
|
||||||
|
};
|
||||||
|
|
||||||
|
handleKeyPress = e => {
|
||||||
|
const { value, checked, onToggle } = this.props;
|
||||||
|
|
||||||
|
if (e.key === 'Enter' || e.key === ' ') {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
onToggle(value, !checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChange = e => {
|
||||||
|
const { value, onToggle } = this.props;
|
||||||
|
onToggle(value, e.target.checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { name, value, checked, label, labelComponent, description, multiple } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<label className='dialog-option poll__option selectable'>
|
||||||
|
<input type={multiple ? 'checkbox' : 'radio'} name={name} value={value} checked={checked} onChange={this.handleChange} />
|
||||||
|
|
||||||
|
<span
|
||||||
|
className={classNames('poll__input', { active: checked, checkbox: multiple })}
|
||||||
|
tabIndex='0'
|
||||||
|
role='radio'
|
||||||
|
onKeyPress={this.handleKeyPress}
|
||||||
|
aria-checked={checked}
|
||||||
|
aria-label={label}
|
||||||
|
>{checked && <Check />}</span>
|
||||||
|
|
||||||
|
{labelComponent ? labelComponent : (
|
||||||
|
<span className='poll__option__text'>
|
||||||
|
<strong>{label}</strong>
|
||||||
|
{description}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</label>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,19 +1,15 @@
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import StatusCheckBox from '../components/status_check_box';
|
import StatusCheckBox from '../components/status_check_box';
|
||||||
import { toggleStatusReport } from '../../../actions/reports';
|
import { makeGetStatus } from 'mastodon/selectors';
|
||||||
import { Set as ImmutableSet } from 'immutable';
|
|
||||||
|
|
||||||
const mapStateToProps = (state, { id }) => ({
|
const makeMapStateToProps = () => {
|
||||||
status: state.getIn(['statuses', id]),
|
const getStatus = makeGetStatus();
|
||||||
checked: state.getIn(['reports', 'new', 'status_ids'], ImmutableSet()).includes(id),
|
|
||||||
});
|
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch, { id }) => ({
|
const mapStateToProps = (state, { id }) => ({
|
||||||
|
status: getStatus(state, { id }),
|
||||||
|
});
|
||||||
|
|
||||||
onToggle (e) {
|
return mapStateToProps;
|
||||||
dispatch(toggleStatusReport(id, e.target.checked));
|
};
|
||||||
},
|
|
||||||
|
|
||||||
});
|
export default connect(makeMapStateToProps)(StatusCheckBox);
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(StatusCheckBox);
|
|
||||||
|
@ -0,0 +1,64 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
import Button from 'mastodon/components/button';
|
||||||
|
import Option from './components/option';
|
||||||
|
|
||||||
|
const mapStateToProps = state => ({
|
||||||
|
rules: state.get('rules'),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default @connect(mapStateToProps)
|
||||||
|
class Rules extends React.PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
onNextStep: PropTypes.func.isRequired,
|
||||||
|
rules: ImmutablePropTypes.list,
|
||||||
|
selectedRuleIds: ImmutablePropTypes.set.isRequired,
|
||||||
|
onToggle: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
handleNextClick = () => {
|
||||||
|
const { onNextStep } = this.props;
|
||||||
|
onNextStep('statuses');
|
||||||
|
};
|
||||||
|
|
||||||
|
handleRulesToggle = (value, checked) => {
|
||||||
|
const { onToggle } = this.props;
|
||||||
|
onToggle(value, checked);
|
||||||
|
};
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { rules, selectedRuleIds } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<h3 className='report-dialog-modal__title'><FormattedMessage id='report.rules.title' defaultMessage='Which rules are being violated?' /></h3>
|
||||||
|
<p className='report-dialog-modal__lead'><FormattedMessage id='report.rules.subtitle' defaultMessage='Select all that apply' /></p>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{rules.map(item => (
|
||||||
|
<Option
|
||||||
|
key={item.get('id')}
|
||||||
|
name='rule_ids'
|
||||||
|
value={item.get('id')}
|
||||||
|
checked={selectedRuleIds.includes(item.get('id'))}
|
||||||
|
onToggle={this.handleRulesToggle}
|
||||||
|
label={item.get('text')}
|
||||||
|
multiple
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex-spacer' />
|
||||||
|
|
||||||
|
<div className='report-dialog-modal__actions'>
|
||||||
|
<Button onClick={this.handleNextClick} disabled={selectedRuleIds.size < 1}><FormattedMessage id='report.next' defaultMessage='Next' /></Button>
|
||||||
|
</div>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import StatusCheckBox from 'mastodon/features/report/containers/status_check_box_container';
|
||||||
|
import { OrderedSet } from 'immutable';
|
||||||
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
import Button from 'mastodon/components/button';
|
||||||
|
|
||||||
|
const mapStateToProps = (state, { accountId }) => ({
|
||||||
|
availableStatusIds: OrderedSet(state.getIn(['timelines', `account:${accountId}:with_replies`, 'items'])),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default @connect(mapStateToProps)
|
||||||
|
class Statuses extends React.PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
onNextStep: PropTypes.func.isRequired,
|
||||||
|
accountId: PropTypes.string.isRequired,
|
||||||
|
availableStatusIds: ImmutablePropTypes.set.isRequired,
|
||||||
|
selectedStatusIds: ImmutablePropTypes.set.isRequired,
|
||||||
|
onToggle: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
handleNextClick = () => {
|
||||||
|
const { onNextStep } = this.props;
|
||||||
|
onNextStep('comment');
|
||||||
|
};
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { availableStatusIds, selectedStatusIds, onToggle } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<h3 className='report-dialog-modal__title'><FormattedMessage id='report.statuses.title' defaultMessage='Are there any posts that back up this report?' /></h3>
|
||||||
|
<p className='report-dialog-modal__lead'><FormattedMessage id='report.statuses.subtitle' defaultMessage='Select all that apply' /></p>
|
||||||
|
|
||||||
|
<div className='report-dialog-modal__statuses'>
|
||||||
|
{availableStatusIds.union(selectedStatusIds).map(statusId => (
|
||||||
|
<StatusCheckBox
|
||||||
|
id={statusId}
|
||||||
|
key={statusId}
|
||||||
|
checked={selectedStatusIds.includes(statusId)}
|
||||||
|
onToggle={onToggle}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex-spacer' />
|
||||||
|
|
||||||
|
<div className='report-dialog-modal__actions'>
|
||||||
|
<Button onClick={this.handleNextClick}><FormattedMessage id='report.next' defaultMessage='Next' /></Button>
|
||||||
|
</div>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
import Button from 'mastodon/components/button';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import {
|
||||||
|
unfollowAccount,
|
||||||
|
muteAccount,
|
||||||
|
blockAccount,
|
||||||
|
} from 'mastodon/actions/accounts';
|
||||||
|
|
||||||
|
const mapStateToProps = () => ({});
|
||||||
|
|
||||||
|
export default @connect(mapStateToProps)
|
||||||
|
class Thanks extends React.PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
submitted: PropTypes.bool,
|
||||||
|
onClose: PropTypes.func.isRequired,
|
||||||
|
account: ImmutablePropTypes.map.isRequired,
|
||||||
|
dispatch: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
handleCloseClick = () => {
|
||||||
|
const { onClose } = this.props;
|
||||||
|
onClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
handleUnfollowClick = () => {
|
||||||
|
const { dispatch, account, onClose } = this.props;
|
||||||
|
dispatch(unfollowAccount(account.get('id')));
|
||||||
|
onClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
handleMuteClick = () => {
|
||||||
|
const { dispatch, account, onClose } = this.props;
|
||||||
|
dispatch(muteAccount(account.get('id')));
|
||||||
|
onClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
handleBlockClick = () => {
|
||||||
|
const { dispatch, account, onClose } = this.props;
|
||||||
|
dispatch(blockAccount(account.get('id')));
|
||||||
|
onClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { account, submitted } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<h3 className='report-dialog-modal__title'>{submitted ? <FormattedMessage id='report.thanks.title_actionable' defaultMessage="Thanks for reporting, we'll look into this." /> : <FormattedMessage id='report.thanks.title' defaultMessage="Don't want to see this?" />}</h3>
|
||||||
|
<p className='report-dialog-modal__lead'>{submitted ? <FormattedMessage id='report.thanks.take_action_actionable' defaultMessage='While we review this, you can take action against @{name}:' values={{ name: account.get('username') }} /> : <FormattedMessage id='report.thanks.take_action' defaultMessage='Here are your options for controlling what you see on Mastodon:' />}</p>
|
||||||
|
|
||||||
|
{account.getIn(['relationship', 'following']) && (
|
||||||
|
<React.Fragment>
|
||||||
|
<h4 className='report-dialog-modal__subtitle'><FormattedMessage id='report.unfollow' defaultMessage='Unfollow @{name}' values={{ name: account.get('username') }} /></h4>
|
||||||
|
<p className='report-dialog-modal__lead'><FormattedMessage id='report.unfollow_explanation' defaultMessage='You are following this account. To not see their posts in your home feed anymore, unfollow them.' /></p>
|
||||||
|
<Button secondary onClick={this.handleUnfollowClick}><FormattedMessage id='account.unfollow' defaultMessage='Unfollow' /></Button>
|
||||||
|
<hr />
|
||||||
|
</React.Fragment>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<h4 className='report-dialog-modal__subtitle'><FormattedMessage id='account.mute' defaultMessage='Mute @{name}' values={{ name: account.get('username') }} /></h4>
|
||||||
|
<p className='report-dialog-modal__lead'><FormattedMessage id='report.mute_explanation' defaultMessage='You will not see their posts. They can still follow you and see your posts and will not know that they are muted.' /></p>
|
||||||
|
<Button secondary onClick={this.handleMuteClick}>{!account.getIn(['relationship', 'muting']) ? <FormattedMessage id='report.mute' defaultMessage='Mute' /> : <FormattedMessage id='account.muted' defaultMessage='Muted' />}</Button>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<h4 className='report-dialog-modal__subtitle'><FormattedMessage id='account.block' defaultMessage='Block @{name}' values={{ name: account.get('username') }} /></h4>
|
||||||
|
<p className='report-dialog-modal__lead'><FormattedMessage id='report.block_explanation' defaultMessage='You will not see their posts. They will not be able to see your posts or follow you. They will be able to tell that they are blocked.' /></p>
|
||||||
|
<Button secondary onClick={this.handleBlockClick}>{!account.getIn(['relationship', 'blocking']) ? <FormattedMessage id='report.block' defaultMessage='Block' /> : <FormattedMessage id='account.blocked' defaultMessage='Blocked' />}</Button>
|
||||||
|
|
||||||
|
<div className='flex-spacer' />
|
||||||
|
|
||||||
|
<div className='report-dialog-modal__actions'>
|
||||||
|
<Button onClick={this.handleCloseClick}><FormattedMessage id='report.close' defaultMessage='Done' /></Button>
|
||||||
|
</div>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
import { RULES_FETCH_SUCCESS } from 'mastodon/actions/rules';
|
||||||
|
import { List as ImmutableList, fromJS } from 'immutable';
|
||||||
|
|
||||||
|
const initialState = ImmutableList();
|
||||||
|
|
||||||
|
export default function rules(state = initialState, action) {
|
||||||
|
switch (action.type) {
|
||||||
|
case RULES_FETCH_SUCCESS:
|
||||||
|
return fromJS(action.rules);
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue