@@ -1,4 +1,5 @@ | |||
import api from '../api'; | |||
import { openModal, closeModal } from './modal'; | |||
export const REPORT_INIT = 'REPORT_INIT'; | |||
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 function initReport(account, status) { | |||
return { | |||
type: REPORT_INIT, | |||
account, | |||
status, | |||
return dispatch => { | |||
dispatch({ | |||
type: REPORT_INIT, | |||
account, | |||
status, | |||
}); | |||
dispatch(openModal('REPORT')); | |||
}; | |||
}; | |||
@@ -40,7 +45,10 @@ export function submitReport() { | |||
account_id: getState().getIn(['reports', 'new', 'account_id']), | |||
status_ids: getState().getIn(['reports', 'new', 'status_ids']), | |||
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 = () => { | |||
this.props.onReport(this.props.status); | |||
this.context.router.history.push('/report'); | |||
} | |||
handleConversationMuteClick = () => { | |||
@@ -38,7 +38,6 @@ export default class Header extends ImmutablePureComponent { | |||
handleReport = () => { | |||
this.props.onReport(this.props.account); | |||
this.context.router.history.push('/report'); | |||
} | |||
handleMute = () => { | |||
@@ -56,7 +56,6 @@ export default class ActionBar extends React.PureComponent { | |||
handleReport = () => { | |||
this.props.onReport(this.props.status); | |||
this.context.router.history.push('/report'); | |||
} | |||
render () { | |||
@@ -5,6 +5,7 @@ import OnboardingModal from './onboarding_modal'; | |||
import VideoModal from './video_modal'; | |||
import BoostModal from './boost_modal'; | |||
import ConfirmationModal from './confirmation_modal'; | |||
import ReportModal from './report_modal'; | |||
import TransitionMotion from 'react-motion/lib/TransitionMotion'; | |||
import spring from 'react-motion/lib/spring'; | |||
@@ -14,6 +15,7 @@ const MODAL_COMPONENTS = { | |||
'VIDEO': VideoModal, | |||
'BOOST': BoostModal, | |||
'CONFIRM': ConfirmationModal, | |||
'REPORT': ReportModal, | |||
}; | |||
export default class ModalRoot extends React.PureComponent { | |||
@@ -1,19 +1,17 @@ | |||
import React from 'react'; | |||
import { connect } from 'react-redux'; | |||
import { changeReportComment, submitReport } from '../../actions/reports'; | |||
import { refreshAccountTimeline } from '../../actions/timelines'; | |||
import { changeReportComment, submitReport } from '../../../actions/reports'; | |||
import { refreshAccountTimeline } from '../../../actions/timelines'; | |||
import PropTypes from 'prop-types'; | |||
import ImmutablePropTypes from 'react-immutable-proptypes'; | |||
import Column from '../ui/components/column'; | |||
import Button from '../../components/button'; | |||
import { makeGetAccount } from '../../selectors'; | |||
import { makeGetAccount } from '../../../selectors'; | |||
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 ColumnBackButtonSlim from '../../components/column_back_button_slim'; | |||
import ImmutablePureComponent from 'react-immutable-pure-component'; | |||
import Button from '../../../components/button'; | |||
const messages = defineMessages({ | |||
heading: { id: 'report.heading', defaultMessage: 'New report' }, | |||
placeholder: { id: 'report.placeholder', defaultMessage: 'Additional comments' }, | |||
submit: { id: 'report.submit', defaultMessage: 'Submit' }, | |||
}); | |||
@@ -37,11 +35,7 @@ const makeMapStateToProps = () => { | |||
@connect(makeMapStateToProps) | |||
@injectIntl | |||
export default class Report extends React.PureComponent { | |||
static contextTypes = { | |||
router: PropTypes.object, | |||
}; | |||
export default class ReportModal extends ImmutablePureComponent { | |||
static propTypes = { | |||
isSubmitting: PropTypes.bool, | |||
@@ -52,17 +46,15 @@ export default class Report extends React.PureComponent { | |||
intl: PropTypes.object.isRequired, | |||
}; | |||
componentWillMount () { | |||
if (!this.props.account) { | |||
this.context.router.history.replace('/'); | |||
} | |||
handleCommentChange = (e) => { | |||
this.props.dispatch(changeReportComment(e.target.value)); | |||
} | |||
componentDidMount () { | |||
if (!this.props.account) { | |||
return; | |||
} | |||
handleSubmit = () => { | |||
this.props.dispatch(submitReport()); | |||
} | |||
componentDidMount () { | |||
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 () { | |||
const { account, comment, intl, statusIds, isSubmitting } = this.props; | |||
@@ -89,36 +72,33 @@ export default class Report extends React.PureComponent { | |||
} | |||
return ( | |||
<Column heading={intl.formatMessage(messages.heading)} icon='flag'> | |||
<ColumnBackButtonSlim /> | |||
<div className='report scrollable'> | |||
<div className='report__target'> | |||
<FormattedMessage id='report.target' defaultMessage='Reporting' /> | |||
<strong>{account.get('acct')}</strong> | |||
</div> | |||
<div className='modal-root__modal report-modal'> | |||
<div className='report-modal__target'> | |||
<FormattedMessage id='report.target' defaultMessage='Report {target}' values={{ target: <strong>{account.get('acct')}</strong> }} /> | |||
</div> | |||
<div className='scrollable report__statuses'> | |||
<div className='report-modal__container'> | |||
<div className='report-modal__statuses'> | |||
<div> | |||
{statusIds.map(statusId => <StatusCheckBox id={statusId} key={statusId} disabled={isSubmitting} />)} | |||
</div> | |||
</div> | |||
<div className='report__textarea-wrapper'> | |||
<div className='report-modal__comment'> | |||
<textarea | |||
className='report__textarea' | |||
className='setting-text light' | |||
placeholder={intl.formatMessage(messages.placeholder)} | |||
value={comment} | |||
onChange={this.handleCommentChange} | |||
disabled={isSubmitting} | |||
/> | |||
<div className='report__submit'> | |||
<div className='report__submit-button'><Button disabled={isSubmitting} text={intl.formatMessage(messages.submit)} onClick={this.handleSubmit} /></div> | |||
</div> | |||
</div> | |||
</div> | |||
</Column> | |||
<div className='report-modal__action-bar'> | |||
<Button disabled={isSubmitting} text={intl.formatMessage(messages.submit)} onClick={this.handleSubmit} /> | |||
</div> | |||
</div> | |||
); | |||
} | |||
@@ -15,7 +15,6 @@ import { refreshHomeTimeline } from '../../actions/timelines'; | |||
import { refreshNotifications } from '../../actions/notifications'; | |||
import UploadArea from './components/upload_area'; | |||
import ColumnsAreaContainer from './containers/columns_area_container'; | |||
import Status from '../../features/status'; | |||
import GettingStarted from '../../features/getting_started'; | |||
import PublicTimeline from '../../features/public_timeline'; | |||
@@ -35,7 +34,6 @@ import GenericNotFound from '../../features/generic_not_found'; | |||
import FavouritedStatuses from '../../features/favourited_statuses'; | |||
import Blocks from '../../features/blocks'; | |||
import Mutes from '../../features/mutes'; | |||
import Report from '../../features/report'; | |||
// Small wrapper to pass multiColumn to the route components | |||
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='/blocks' component={Blocks} content={children} /> | |||
<WrappedRoute path='/mutes' component={Mutes} content={children} /> | |||
<WrappedRoute path='/report' component={Report} content={children} /> | |||
<WrappedRoute component={GenericNotFound} content={children} /> | |||
</WrappedSwitch> | |||
@@ -1130,6 +1130,23 @@ | |||
{ | |||
"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": [ | |||
{ | |||
"defaultMessage": "Compose", | |||
"id": "tabs_bar.compose" | |||
}, | |||
@@ -136,10 +136,10 @@ | |||
"privacy.unlisted.long": "Do not post to public timelines", | |||
"privacy.unlisted.short": "Unlisted", | |||
"reply_indicator.cancel": "Cancel", | |||
"report.heading": "New report", | |||
"report.heading": "Report {target}", | |||
"report.placeholder": "Additional comments", | |||
"report.submit": "Submit", | |||
"report.target": "Reporting", | |||
"report.target": "Reporting {target}", | |||
"search.placeholder": "Search", | |||
"search_results.total": "{count, number} {count, plural, one {result} other {results}}", | |||
"status.cannot_reblog": "This post cannot be boosted", | |||
@@ -600,13 +600,15 @@ | |||
} | |||
.status-check-box { | |||
border-bottom: 1px solid lighten($ui-base-color, 8%); | |||
border-bottom: 1px solid $ui-secondary-color; | |||
display: flex; | |||
.status__content { | |||
background: lighten($ui-base-color, 4%); | |||
flex: 1 1 auto; | |||
padding: 10px; | |||
overflow: hidden; | |||
text-overflow: ellipsis; | |||
white-space: nowrap; | |||
} | |||
} | |||
@@ -1830,6 +1832,17 @@ | |||
@media screen and (max-width: 600px) { | |||
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'; | |||
@@ -2287,67 +2300,6 @@ button.icon-button.active i.fa-retweet { | |||
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 { | |||
color: lighten($ui-base-color, 20%); | |||
background: $ui-base-color; | |||
@@ -3245,7 +3197,8 @@ button.icon-button.active i.fa-retweet { | |||
} | |||
.boost-modal, | |||
.confirmation-modal { | |||
.confirmation-modal, | |||
.report-modal { | |||
background: lighten($ui-secondary-color, 8%); | |||
color: $ui-base-color; | |||
border-radius: 8px; | |||
@@ -3281,7 +3234,8 @@ button.icon-button.active i.fa-retweet { | |||
} | |||
.boost-modal__action-bar, | |||
.confirmation-modal__action-bar { | |||
.confirmation-modal__action-bar, | |||
.report-modal__action-bar { | |||
display: flex; | |||
justify-content: space-between; | |||
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__cancel-button { | |||
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; | |||
font-size: 16px; | |||
text-align: center; | |||