Turn report screen into a modal (#3965)
parent
39b7512782
commit
0d316bcfd2
|
@ -1,4 +1,5 @@
|
||||||
import api from '../api';
|
import api from '../api';
|
||||||
|
import { openModal, closeModal } from './modal';
|
||||||
|
|
||||||
export const REPORT_INIT = 'REPORT_INIT';
|
export const REPORT_INIT = 'REPORT_INIT';
|
||||||
export const REPORT_CANCEL = 'REPORT_CANCEL';
|
export const REPORT_CANCEL = 'REPORT_CANCEL';
|
||||||
|
@ -11,10 +12,14 @@ export const REPORT_STATUS_TOGGLE = 'REPORT_STATUS_TOGGLE';
|
||||||
export const REPORT_COMMENT_CHANGE = 'REPORT_COMMENT_CHANGE';
|
export const REPORT_COMMENT_CHANGE = 'REPORT_COMMENT_CHANGE';
|
||||||
|
|
||||||
export function initReport(account, status) {
|
export function initReport(account, status) {
|
||||||
return {
|
return dispatch => {
|
||||||
|
dispatch({
|
||||||
type: REPORT_INIT,
|
type: REPORT_INIT,
|
||||||
account,
|
account,
|
||||||
status,
|
status,
|
||||||
|
});
|
||||||
|
|
||||||
|
dispatch(openModal('REPORT'));
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -40,7 +45,10 @@ export function submitReport() {
|
||||||
account_id: getState().getIn(['reports', 'new', 'account_id']),
|
account_id: getState().getIn(['reports', 'new', 'account_id']),
|
||||||
status_ids: getState().getIn(['reports', 'new', 'status_ids']),
|
status_ids: getState().getIn(['reports', 'new', 'status_ids']),
|
||||||
comment: getState().getIn(['reports', 'new', 'comment']),
|
comment: getState().getIn(['reports', 'new', 'comment']),
|
||||||
}).then(response => dispatch(submitReportSuccess(response.data))).catch(error => dispatch(submitReportFail(error)));
|
}).then(response => {
|
||||||
|
dispatch(closeModal());
|
||||||
|
dispatch(submitReportSuccess(response.data));
|
||||||
|
}).catch(error => dispatch(submitReportFail(error)));
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,6 @@ export default class StatusActionBar extends ImmutablePureComponent {
|
||||||
|
|
||||||
handleReport = () => {
|
handleReport = () => {
|
||||||
this.props.onReport(this.props.status);
|
this.props.onReport(this.props.status);
|
||||||
this.context.router.history.push('/report');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleConversationMuteClick = () => {
|
handleConversationMuteClick = () => {
|
||||||
|
|
|
@ -38,7 +38,6 @@ export default class Header extends ImmutablePureComponent {
|
||||||
|
|
||||||
handleReport = () => {
|
handleReport = () => {
|
||||||
this.props.onReport(this.props.account);
|
this.props.onReport(this.props.account);
|
||||||
this.context.router.history.push('/report');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMute = () => {
|
handleMute = () => {
|
||||||
|
|
|
@ -56,7 +56,6 @@ export default class ActionBar extends React.PureComponent {
|
||||||
|
|
||||||
handleReport = () => {
|
handleReport = () => {
|
||||||
this.props.onReport(this.props.status);
|
this.props.onReport(this.props.status);
|
||||||
this.context.router.history.push('/report');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import OnboardingModal from './onboarding_modal';
|
||||||
import VideoModal from './video_modal';
|
import VideoModal from './video_modal';
|
||||||
import BoostModal from './boost_modal';
|
import BoostModal from './boost_modal';
|
||||||
import ConfirmationModal from './confirmation_modal';
|
import ConfirmationModal from './confirmation_modal';
|
||||||
|
import ReportModal from './report_modal';
|
||||||
import TransitionMotion from 'react-motion/lib/TransitionMotion';
|
import TransitionMotion from 'react-motion/lib/TransitionMotion';
|
||||||
import spring from 'react-motion/lib/spring';
|
import spring from 'react-motion/lib/spring';
|
||||||
|
|
||||||
|
@ -14,6 +15,7 @@ const MODAL_COMPONENTS = {
|
||||||
'VIDEO': VideoModal,
|
'VIDEO': VideoModal,
|
||||||
'BOOST': BoostModal,
|
'BOOST': BoostModal,
|
||||||
'CONFIRM': ConfirmationModal,
|
'CONFIRM': ConfirmationModal,
|
||||||
|
'REPORT': ReportModal,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class ModalRoot extends React.PureComponent {
|
export default class ModalRoot extends React.PureComponent {
|
||||||
|
|
|
@ -1,19 +1,17 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { changeReportComment, submitReport } from '../../actions/reports';
|
import { changeReportComment, submitReport } from '../../../actions/reports';
|
||||||
import { refreshAccountTimeline } from '../../actions/timelines';
|
import { refreshAccountTimeline } from '../../../actions/timelines';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import Column from '../ui/components/column';
|
import { makeGetAccount } from '../../../selectors';
|
||||||
import Button from '../../components/button';
|
|
||||||
import { makeGetAccount } from '../../selectors';
|
|
||||||
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
|
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
|
||||||
import StatusCheckBox from './containers/status_check_box_container';
|
import StatusCheckBox from '../../report/containers/status_check_box_container';
|
||||||
import Immutable from 'immutable';
|
import Immutable from 'immutable';
|
||||||
import ColumnBackButtonSlim from '../../components/column_back_button_slim';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
import Button from '../../../components/button';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'report.heading', defaultMessage: 'New report' },
|
|
||||||
placeholder: { id: 'report.placeholder', defaultMessage: 'Additional comments' },
|
placeholder: { id: 'report.placeholder', defaultMessage: 'Additional comments' },
|
||||||
submit: { id: 'report.submit', defaultMessage: 'Submit' },
|
submit: { id: 'report.submit', defaultMessage: 'Submit' },
|
||||||
});
|
});
|
||||||
|
@ -37,11 +35,7 @@ const makeMapStateToProps = () => {
|
||||||
|
|
||||||
@connect(makeMapStateToProps)
|
@connect(makeMapStateToProps)
|
||||||
@injectIntl
|
@injectIntl
|
||||||
export default class Report extends React.PureComponent {
|
export default class ReportModal extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
isSubmitting: PropTypes.bool,
|
isSubmitting: PropTypes.bool,
|
||||||
|
@ -52,17 +46,15 @@ export default class Report extends React.PureComponent {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillMount () {
|
handleCommentChange = (e) => {
|
||||||
if (!this.props.account) {
|
this.props.dispatch(changeReportComment(e.target.value));
|
||||||
this.context.router.history.replace('/');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleSubmit = () => {
|
||||||
|
this.props.dispatch(submitReport());
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
if (!this.props.account) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.props.dispatch(refreshAccountTimeline(this.props.account.get('id')));
|
this.props.dispatch(refreshAccountTimeline(this.props.account.get('id')));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,15 +64,6 @@ export default class Report extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCommentChange = (e) => {
|
|
||||||
this.props.dispatch(changeReportComment(e.target.value));
|
|
||||||
}
|
|
||||||
|
|
||||||
handleSubmit = () => {
|
|
||||||
this.props.dispatch(submitReport());
|
|
||||||
this.context.router.history.replace('/');
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { account, comment, intl, statusIds, isSubmitting } = this.props;
|
const { account, comment, intl, statusIds, isSubmitting } = this.props;
|
||||||
|
|
||||||
|
@ -89,36 +72,33 @@ export default class Report extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column heading={intl.formatMessage(messages.heading)} icon='flag'>
|
<div className='modal-root__modal report-modal'>
|
||||||
<ColumnBackButtonSlim />
|
<div className='report-modal__target'>
|
||||||
|
<FormattedMessage id='report.target' defaultMessage='Report {target}' values={{ target: <strong>{account.get('acct')}</strong> }} />
|
||||||
<div className='report scrollable'>
|
|
||||||
<div className='report__target'>
|
|
||||||
<FormattedMessage id='report.target' defaultMessage='Reporting' />
|
|
||||||
<strong>{account.get('acct')}</strong>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='scrollable report__statuses'>
|
<div className='report-modal__container'>
|
||||||
|
<div className='report-modal__statuses'>
|
||||||
<div>
|
<div>
|
||||||
{statusIds.map(statusId => <StatusCheckBox id={statusId} key={statusId} disabled={isSubmitting} />)}
|
{statusIds.map(statusId => <StatusCheckBox id={statusId} key={statusId} disabled={isSubmitting} />)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='report__textarea-wrapper'>
|
<div className='report-modal__comment'>
|
||||||
<textarea
|
<textarea
|
||||||
className='report__textarea'
|
className='setting-text light'
|
||||||
placeholder={intl.formatMessage(messages.placeholder)}
|
placeholder={intl.formatMessage(messages.placeholder)}
|
||||||
value={comment}
|
value={comment}
|
||||||
onChange={this.handleCommentChange}
|
onChange={this.handleCommentChange}
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className='report__submit'>
|
<div className='report-modal__action-bar'>
|
||||||
<div className='report__submit-button'><Button disabled={isSubmitting} text={intl.formatMessage(messages.submit)} onClick={this.handleSubmit} /></div>
|
<Button disabled={isSubmitting} text={intl.formatMessage(messages.submit)} onClick={this.handleSubmit} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</Column>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@ import { refreshHomeTimeline } from '../../actions/timelines';
|
||||||
import { refreshNotifications } from '../../actions/notifications';
|
import { refreshNotifications } from '../../actions/notifications';
|
||||||
import UploadArea from './components/upload_area';
|
import UploadArea from './components/upload_area';
|
||||||
import ColumnsAreaContainer from './containers/columns_area_container';
|
import ColumnsAreaContainer from './containers/columns_area_container';
|
||||||
|
|
||||||
import Status from '../../features/status';
|
import Status from '../../features/status';
|
||||||
import GettingStarted from '../../features/getting_started';
|
import GettingStarted from '../../features/getting_started';
|
||||||
import PublicTimeline from '../../features/public_timeline';
|
import PublicTimeline from '../../features/public_timeline';
|
||||||
|
@ -35,7 +34,6 @@ import GenericNotFound from '../../features/generic_not_found';
|
||||||
import FavouritedStatuses from '../../features/favourited_statuses';
|
import FavouritedStatuses from '../../features/favourited_statuses';
|
||||||
import Blocks from '../../features/blocks';
|
import Blocks from '../../features/blocks';
|
||||||
import Mutes from '../../features/mutes';
|
import Mutes from '../../features/mutes';
|
||||||
import Report from '../../features/report';
|
|
||||||
|
|
||||||
// Small wrapper to pass multiColumn to the route components
|
// Small wrapper to pass multiColumn to the route components
|
||||||
const WrappedSwitch = ({ multiColumn, children }) => (
|
const WrappedSwitch = ({ multiColumn, children }) => (
|
||||||
|
@ -206,7 +204,6 @@ export default class UI extends React.PureComponent {
|
||||||
<WrappedRoute path='/follow_requests' component={FollowRequests} content={children} />
|
<WrappedRoute path='/follow_requests' component={FollowRequests} content={children} />
|
||||||
<WrappedRoute path='/blocks' component={Blocks} content={children} />
|
<WrappedRoute path='/blocks' component={Blocks} content={children} />
|
||||||
<WrappedRoute path='/mutes' component={Mutes} content={children} />
|
<WrappedRoute path='/mutes' component={Mutes} content={children} />
|
||||||
<WrappedRoute path='/report' component={Report} content={children} />
|
|
||||||
|
|
||||||
<WrappedRoute component={GenericNotFound} content={children} />
|
<WrappedRoute component={GenericNotFound} content={children} />
|
||||||
</WrappedSwitch>
|
</WrappedSwitch>
|
||||||
|
|
|
@ -1127,6 +1127,23 @@
|
||||||
],
|
],
|
||||||
"path": "app/javascript/mastodon/features/ui/components/onboarding_modal.json"
|
"path": "app/javascript/mastodon/features/ui/components/onboarding_modal.json"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"descriptors": [
|
||||||
|
{
|
||||||
|
"defaultMessage": "Additional comments",
|
||||||
|
"id": "report.placeholder"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"defaultMessage": "Submit",
|
||||||
|
"id": "report.submit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"defaultMessage": "Report {target}",
|
||||||
|
"id": "report.target"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"path": "app/javascript/mastodon/features/ui/components/report_modal.json"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"descriptors": [
|
"descriptors": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -136,10 +136,10 @@
|
||||||
"privacy.unlisted.long": "Do not post to public timelines",
|
"privacy.unlisted.long": "Do not post to public timelines",
|
||||||
"privacy.unlisted.short": "Unlisted",
|
"privacy.unlisted.short": "Unlisted",
|
||||||
"reply_indicator.cancel": "Cancel",
|
"reply_indicator.cancel": "Cancel",
|
||||||
"report.heading": "New report",
|
"report.heading": "Report {target}",
|
||||||
"report.placeholder": "Additional comments",
|
"report.placeholder": "Additional comments",
|
||||||
"report.submit": "Submit",
|
"report.submit": "Submit",
|
||||||
"report.target": "Reporting",
|
"report.target": "Reporting {target}",
|
||||||
"search.placeholder": "Search",
|
"search.placeholder": "Search",
|
||||||
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
|
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
|
||||||
"status.cannot_reblog": "This post cannot be boosted",
|
"status.cannot_reblog": "This post cannot be boosted",
|
||||||
|
|
|
@ -600,13 +600,15 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-check-box {
|
.status-check-box {
|
||||||
border-bottom: 1px solid lighten($ui-base-color, 8%);
|
border-bottom: 1px solid $ui-secondary-color;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
.status__content {
|
.status__content {
|
||||||
background: lighten($ui-base-color, 4%);
|
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1830,6 +1832,17 @@
|
||||||
@media screen and (max-width: 600px) {
|
@media screen and (max-width: 600px) {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.light {
|
||||||
|
color: $ui-base-color;
|
||||||
|
border-bottom: 2px solid lighten($ui-base-color, 27%);
|
||||||
|
|
||||||
|
&:focus,
|
||||||
|
&:active {
|
||||||
|
color: $ui-base-color;
|
||||||
|
border-bottom-color: $ui-highlight-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@import 'boost';
|
@import 'boost';
|
||||||
|
@ -2287,67 +2300,6 @@ button.icon-button.active i.fa-retweet {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.report.scrollable {
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
max-height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.report__target {
|
|
||||||
border-bottom: 1px solid lighten($ui-base-color, 4%);
|
|
||||||
color: $ui-secondary-color;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
padding: 10px;
|
|
||||||
|
|
||||||
strong {
|
|
||||||
display: block;
|
|
||||||
color: $primary-text-color;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.report__statuses {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.report__textarea-wrapper {
|
|
||||||
flex: 0 0 100px;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.report__textarea {
|
|
||||||
background: transparent;
|
|
||||||
box-sizing: border-box;
|
|
||||||
border: 0;
|
|
||||||
border-bottom: 2px solid $ui-primary-color;
|
|
||||||
border-radius: 2px 2px 0 0;
|
|
||||||
color: $primary-text-color;
|
|
||||||
display: block;
|
|
||||||
font-family: inherit;
|
|
||||||
font-size: 14px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
outline: 0;
|
|
||||||
padding: 7px 4px;
|
|
||||||
resize: vertical;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
&:active,
|
|
||||||
&:focus {
|
|
||||||
border-bottom-color: $ui-highlight-color;
|
|
||||||
background: rgba($base-overlay-background, 0.1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.report__submit {
|
|
||||||
margin-top: 10px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.report__submit-button {
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.empty-column-indicator {
|
.empty-column-indicator {
|
||||||
color: lighten($ui-base-color, 20%);
|
color: lighten($ui-base-color, 20%);
|
||||||
background: $ui-base-color;
|
background: $ui-base-color;
|
||||||
|
@ -3245,7 +3197,8 @@ button.icon-button.active i.fa-retweet {
|
||||||
}
|
}
|
||||||
|
|
||||||
.boost-modal,
|
.boost-modal,
|
||||||
.confirmation-modal {
|
.confirmation-modal,
|
||||||
|
.report-modal {
|
||||||
background: lighten($ui-secondary-color, 8%);
|
background: lighten($ui-secondary-color, 8%);
|
||||||
color: $ui-base-color;
|
color: $ui-base-color;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
@ -3281,7 +3234,8 @@ button.icon-button.active i.fa-retweet {
|
||||||
}
|
}
|
||||||
|
|
||||||
.boost-modal__action-bar,
|
.boost-modal__action-bar,
|
||||||
.confirmation-modal__action-bar {
|
.confirmation-modal__action-bar,
|
||||||
|
.report-modal__action-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
background: $ui-secondary-color;
|
background: $ui-secondary-color;
|
||||||
|
@ -3317,6 +3271,23 @@ button.icon-button.active i.fa-retweet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.report-modal__statuses,
|
||||||
|
.report-modal__comment {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-modal__statuses {
|
||||||
|
min-height: 20vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-modal__comment {
|
||||||
|
.setting-text {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.confirmation-modal__action-bar {
|
.confirmation-modal__action-bar {
|
||||||
.confirmation-modal__cancel-button {
|
.confirmation-modal__cancel-button {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
@ -3332,7 +3303,8 @@ button.icon-button.active i.fa-retweet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.confirmation-modal__container {
|
.confirmation-modal__container,
|
||||||
|
.report-modal__target {
|
||||||
padding: 30px;
|
padding: 30px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
Loading…
Reference in New Issue