mirror of
https://framagit.org/tykayn/mastodon.git
synced 2023-08-25 08:33:12 +02:00
Adding POST /api/v1/reports API, and a UI for submitting reports
This commit is contained in:
parent
40a4053732
commit
3b81baaaaf
@ -1,4 +1,4 @@
|
||||
import api from '../api'
|
||||
import api from '../api';
|
||||
|
||||
import { updateTimeline } from './timelines';
|
||||
|
||||
|
64
app/assets/javascripts/components/actions/reports.jsx
Normal file
64
app/assets/javascripts/components/actions/reports.jsx
Normal file
@ -0,0 +1,64 @@
|
||||
import api from '../api';
|
||||
|
||||
export const REPORT_INIT = 'REPORT_INIT';
|
||||
export const REPORT_CANCEL = 'REPORT_CANCEL';
|
||||
|
||||
export const REPORT_SUBMIT_REQUEST = 'REPORT_SUBMIT_REQUEST';
|
||||
export const REPORT_SUBMIT_SUCCESS = 'REPORT_SUBMIT_SUCCESS';
|
||||
export const REPORT_SUBMIT_FAIL = 'REPORT_SUBMIT_FAIL';
|
||||
|
||||
export const REPORT_STATUS_TOGGLE = 'REPORT_STATUS_TOGGLE';
|
||||
|
||||
export function initReport(account, status) {
|
||||
return {
|
||||
type: REPORT_INIT,
|
||||
account,
|
||||
status
|
||||
};
|
||||
};
|
||||
|
||||
export function cancelReport() {
|
||||
return {
|
||||
type: REPORT_CANCEL
|
||||
};
|
||||
};
|
||||
|
||||
export function toggleStatusReport(statusId, checked) {
|
||||
return {
|
||||
type: REPORT_STATUS_TOGGLE,
|
||||
statusId,
|
||||
checked,
|
||||
};
|
||||
};
|
||||
|
||||
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'])
|
||||
}).then(response => 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
|
||||
};
|
||||
};
|
@ -11,7 +11,8 @@ const messages = defineMessages({
|
||||
reply: { id: 'status.reply', defaultMessage: 'Reply' },
|
||||
reblog: { id: 'status.reblog', defaultMessage: 'Reblog' },
|
||||
favourite: { id: 'status.favourite', defaultMessage: 'Favourite' },
|
||||
open: { id: 'status.open', defaultMessage: 'Expand' }
|
||||
open: { id: 'status.open', defaultMessage: 'Expand' },
|
||||
report: { id: 'status.report', defaultMessage: 'Report' }
|
||||
});
|
||||
|
||||
const StatusActionBar = React.createClass({
|
||||
@ -27,7 +28,10 @@ const StatusActionBar = React.createClass({
|
||||
onReblog: React.PropTypes.func,
|
||||
onDelete: React.PropTypes.func,
|
||||
onMention: React.PropTypes.func,
|
||||
onBlock: React.PropTypes.func
|
||||
onBlock: React.PropTypes.func,
|
||||
onReport: React.PropTypes.func,
|
||||
me: React.PropTypes.number.isRequired,
|
||||
intl: React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
mixins: [PureRenderMixin],
|
||||
@ -60,6 +64,11 @@ const StatusActionBar = React.createClass({
|
||||
this.context.router.push(`/statuses/${this.props.status.get('id')}`);
|
||||
},
|
||||
|
||||
handleReport () {
|
||||
this.props.onReport(this.props.status);
|
||||
this.context.router.push('/report');
|
||||
},
|
||||
|
||||
render () {
|
||||
const { status, me, intl } = this.props;
|
||||
let menu = [];
|
||||
@ -71,6 +80,7 @@ const StatusActionBar = React.createClass({
|
||||
} else {
|
||||
menu.push({ text: intl.formatMessage(messages.mention), action: this.handleMentionClick });
|
||||
menu.push({ text: intl.formatMessage(messages.block), action: this.handleBlockClick });
|
||||
menu.push({ text: intl.formatMessage(messages.report), action: this.handleReport });
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -34,6 +34,7 @@ import FollowRequests from '../features/follow_requests';
|
||||
import GenericNotFound from '../features/generic_not_found';
|
||||
import FavouritedStatuses from '../features/favourited_statuses';
|
||||
import Blocks from '../features/blocks';
|
||||
import Report from '../features/report';
|
||||
import { IntlProvider, addLocaleData } from 'react-intl';
|
||||
import en from 'react-intl/locale-data/en';
|
||||
import de from 'react-intl/locale-data/de';
|
||||
@ -131,6 +132,7 @@ const Mastodon = React.createClass({
|
||||
|
||||
<Route path='follow_requests' component={FollowRequests} />
|
||||
<Route path='blocks' component={Blocks} />
|
||||
<Route path='report' component={Report} />
|
||||
|
||||
<Route path='*' component={GenericNotFound} />
|
||||
</Route>
|
||||
|
@ -13,6 +13,7 @@ import {
|
||||
} from '../actions/interactions';
|
||||
import { blockAccount } from '../actions/accounts';
|
||||
import { deleteStatus } from '../actions/statuses';
|
||||
import { initReport } from '../actions/reports';
|
||||
import { openMedia } from '../actions/modal';
|
||||
import { createSelector } from 'reselect'
|
||||
import { isMobile } from '../is_mobile'
|
||||
@ -97,6 +98,10 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
|
||||
onBlock (account) {
|
||||
dispatch(blockAccount(account.get('id')));
|
||||
},
|
||||
|
||||
onReport (status) {
|
||||
dispatch(initReport(status.get('account'), status));
|
||||
}
|
||||
|
||||
});
|
||||
|
@ -11,7 +11,8 @@ const messages = defineMessages({
|
||||
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
|
||||
block: { id: 'account.block', defaultMessage: 'Block' },
|
||||
follow: { id: 'account.follow', defaultMessage: 'Follow' },
|
||||
block: { id: 'account.block', defaultMessage: 'Block' }
|
||||
block: { id: 'account.block', defaultMessage: 'Block' },
|
||||
report: { id: 'account.report', defaultMessage: 'Report' }
|
||||
});
|
||||
|
||||
const outerDropdownStyle = {
|
||||
@ -32,7 +33,9 @@ const ActionBar = React.createClass({
|
||||
me: React.PropTypes.number.isRequired,
|
||||
onFollow: React.PropTypes.func,
|
||||
onBlock: React.PropTypes.func.isRequired,
|
||||
onMention: React.PropTypes.func.isRequired
|
||||
onMention: React.PropTypes.func.isRequired,
|
||||
onReport: React.PropTypes.func.isRequired,
|
||||
intl: React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
mixins: [PureRenderMixin],
|
||||
@ -54,6 +57,10 @@ const ActionBar = React.createClass({
|
||||
menu.push({ text: intl.formatMessage(messages.block), action: this.props.onBlock });
|
||||
}
|
||||
|
||||
if (account.get('id') !== me) {
|
||||
menu.push({ text: intl.formatMessage(messages.report), action: this.props.onReport });
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='account__action-bar'>
|
||||
<div style={outerDropdownStyle}>
|
||||
|
@ -13,7 +13,8 @@ const Header = React.createClass({
|
||||
me: React.PropTypes.number.isRequired,
|
||||
onFollow: React.PropTypes.func.isRequired,
|
||||
onBlock: React.PropTypes.func.isRequired,
|
||||
onMention: React.PropTypes.func.isRequired
|
||||
onMention: React.PropTypes.func.isRequired,
|
||||
onReport: React.PropTypes.func.isRequired
|
||||
},
|
||||
|
||||
mixins: [PureRenderMixin],
|
||||
@ -30,6 +31,11 @@ const Header = React.createClass({
|
||||
this.props.onMention(this.props.account, this.context.router);
|
||||
},
|
||||
|
||||
handleReport () {
|
||||
this.props.onReport(this.props.account);
|
||||
this.context.router.push('/report');
|
||||
},
|
||||
|
||||
render () {
|
||||
const { account, me } = this.props;
|
||||
|
||||
@ -50,6 +56,7 @@ const Header = React.createClass({
|
||||
me={me}
|
||||
onBlock={this.handleBlock}
|
||||
onMention={this.handleMention}
|
||||
onReport={this.handleReport}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -8,6 +8,7 @@ import {
|
||||
unblockAccount
|
||||
} from '../../../actions/accounts';
|
||||
import { mentionCompose } from '../../../actions/compose';
|
||||
import { initReport } from '../../../actions/reports';
|
||||
|
||||
const makeMapStateToProps = () => {
|
||||
const getAccount = makeGetAccount();
|
||||
@ -39,6 +40,10 @@ const mapDispatchToProps = dispatch => ({
|
||||
|
||||
onMention (account, router) {
|
||||
dispatch(mentionCompose(account, router));
|
||||
},
|
||||
|
||||
onReport (account) {
|
||||
dispatch(initReport(account));
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -0,0 +1,38 @@
|
||||
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import emojify from '../../../emoji';
|
||||
import Toggle from 'react-toggle';
|
||||
|
||||
const StatusCheckBox = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
status: ImmutablePropTypes.map.isRequired,
|
||||
checked: React.PropTypes.bool,
|
||||
onToggle: React.PropTypes.func.isRequired,
|
||||
disabled: React.PropTypes.bool
|
||||
},
|
||||
|
||||
mixins: [PureRenderMixin],
|
||||
|
||||
render () {
|
||||
const { status, checked, onToggle, disabled } = this.props;
|
||||
const content = { __html: emojify(status.get('content')) };
|
||||
|
||||
return (
|
||||
<div className='status-check-box' style={{ display: 'flex' }}>
|
||||
<div
|
||||
className='status__content'
|
||||
style={{ flex: '1 1 auto', padding: '10px' }}
|
||||
dangerouslySetInnerHTML={content}
|
||||
/>
|
||||
|
||||
<div style={{ flex: '0 0 auto', padding: '10px', display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
|
||||
<Toggle checked={checked} onChange={onToggle} disabled={disabled} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
export default StatusCheckBox;
|
@ -0,0 +1,19 @@
|
||||
import { connect } from 'react-redux';
|
||||
import StatusCheckBox from '../components/status_check_box';
|
||||
import { toggleStatusReport } from '../../../actions/reports';
|
||||
import Immutable from 'immutable';
|
||||
|
||||
const mapStateToProps = (state, { id }) => ({
|
||||
status: state.getIn(['statuses', id]),
|
||||
checked: state.getIn(['reports', 'new', 'status_ids'], Immutable.Set()).includes(id)
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch, { id }) => ({
|
||||
|
||||
onToggle (e) {
|
||||
dispatch(toggleStatusReport(id, e.target.checked));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(StatusCheckBox);
|
130
app/assets/javascripts/components/features/report/index.jsx
Normal file
130
app/assets/javascripts/components/features/report/index.jsx
Normal file
@ -0,0 +1,130 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { cancelReport, changeReportComment, submitReport } from '../../actions/reports';
|
||||
import { fetchAccountTimeline } from '../../actions/accounts';
|
||||
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import Column from '../ui/components/column';
|
||||
import Button from '../../components/button';
|
||||
import { makeGetAccount } from '../../selectors';
|
||||
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
|
||||
import StatusCheckBox from './containers/status_check_box_container';
|
||||
import Immutable from 'immutable';
|
||||
import ColumnBackButtonSlim from '../../components/column_back_button_slim';
|
||||
|
||||
const messages = defineMessages({
|
||||
heading: { id: 'report.heading', defaultMessage: 'New report' },
|
||||
placeholder: { id: 'report.placeholder', defaultMessage: 'Additional comments' },
|
||||
submit: { id: 'report.submit', defaultMessage: 'Submit' }
|
||||
});
|
||||
|
||||
const makeMapStateToProps = () => {
|
||||
const getAccount = makeGetAccount();
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const accountId = state.getIn(['reports', 'new', 'account_id']);
|
||||
|
||||
return {
|
||||
isSubmitting: state.getIn(['reports', 'new', 'isSubmitting']),
|
||||
account: getAccount(state, accountId),
|
||||
comment: state.getIn(['reports', 'new', 'comment']),
|
||||
statusIds: state.getIn(['timelines', 'accounts_timelines', accountId, 'items'], Immutable.List())
|
||||
};
|
||||
};
|
||||
|
||||
return mapStateToProps;
|
||||
};
|
||||
|
||||
const textareaStyle = {
|
||||
marginBottom: '10px'
|
||||
};
|
||||
|
||||
const Report = React.createClass({
|
||||
|
||||
contextTypes: {
|
||||
router: React.PropTypes.object
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
isSubmitting: React.PropTypes.bool,
|
||||
account: ImmutablePropTypes.map,
|
||||
statusIds: ImmutablePropTypes.list.isRequired,
|
||||
comment: React.PropTypes.string.isRequired,
|
||||
dispatch: React.PropTypes.func.isRequired,
|
||||
intl: React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
mixins: [PureRenderMixin],
|
||||
|
||||
componentWillMount () {
|
||||
if (!this.props.account) {
|
||||
this.context.router.replace('/');
|
||||
}
|
||||
},
|
||||
|
||||
componentDidMount () {
|
||||
if (!this.props.account) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.props.dispatch(fetchAccountTimeline(this.props.account.get('id')));
|
||||
},
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
if (this.props.account !== nextProps.account && nextProps.account) {
|
||||
this.props.dispatch(fetchAccountTimeline(nextProps.account.get('id')));
|
||||
}
|
||||
},
|
||||
|
||||
handleCommentChange (e) {
|
||||
this.props.dispatch(changeReportComment(e.target.value));
|
||||
},
|
||||
|
||||
handleSubmit () {
|
||||
this.props.dispatch(submitReport());
|
||||
this.context.router.replace('/');
|
||||
},
|
||||
|
||||
render () {
|
||||
const { account, comment, intl, statusIds, isSubmitting } = this.props;
|
||||
|
||||
if (!account) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Column heading={intl.formatMessage(messages.heading)} icon='flag'>
|
||||
<ColumnBackButtonSlim />
|
||||
<div className='report' style={{ display: 'flex', flexDirection: 'column', maxHeight: '100%', boxSizing: 'border-box' }}>
|
||||
<div className='report__target' style={{ flex: '0 0 auto', padding: '10px' }}>
|
||||
<FormattedMessage id='report.target' defaultMessage='Reporting' />
|
||||
<strong>{account.get('acct')}</strong>
|
||||
</div>
|
||||
|
||||
<div style={{ flex: '1 1 auto' }} className='scrollable'>
|
||||
<div>
|
||||
{statusIds.map(statusId => <StatusCheckBox id={statusId} key={statusId} disabled={isSubmitting} />)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ flex: '0 0 160px', padding: '10px' }}>
|
||||
<textarea
|
||||
className='report__textarea'
|
||||
placeholder={intl.formatMessage(messages.placeholder)}
|
||||
value={comment}
|
||||
onChange={this.handleCommentChange}
|
||||
style={textareaStyle}
|
||||
disabled={isSubmitting}
|
||||
/>
|
||||
|
||||
<div style={{ marginTop: '10px', overflow: 'hidden' }}>
|
||||
<div style={{ float: 'right' }}><Button disabled={isSubmitting} text={intl.formatMessage(messages.submit)} onClick={this.handleSubmit} /></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
export default connect(makeMapStateToProps)(injectIntl(Report));
|
@ -9,7 +9,8 @@ const messages = defineMessages({
|
||||
mention: { id: 'status.mention', defaultMessage: 'Mention' },
|
||||
reply: { id: 'status.reply', defaultMessage: 'Reply' },
|
||||
reblog: { id: 'status.reblog', defaultMessage: 'Reblog' },
|
||||
favourite: { id: 'status.favourite', defaultMessage: 'Favourite' }
|
||||
favourite: { id: 'status.favourite', defaultMessage: 'Favourite' },
|
||||
report: { id: 'status.report', defaultMessage: 'Report' }
|
||||
});
|
||||
|
||||
const ActionBar = React.createClass({
|
||||
@ -25,6 +26,7 @@ const ActionBar = React.createClass({
|
||||
onFavourite: React.PropTypes.func.isRequired,
|
||||
onDelete: React.PropTypes.func.isRequired,
|
||||
onMention: React.PropTypes.func.isRequired,
|
||||
onReport: React.PropTypes.func,
|
||||
me: React.PropTypes.number.isRequired,
|
||||
intl: React.PropTypes.object.isRequired
|
||||
},
|
||||
@ -51,6 +53,11 @@ const ActionBar = React.createClass({
|
||||
this.props.onMention(this.props.status.get('account'), this.context.router);
|
||||
},
|
||||
|
||||
handleReport () {
|
||||
this.props.onReport(this.props.status);
|
||||
this.context.router.push('/report');
|
||||
},
|
||||
|
||||
render () {
|
||||
const { status, me, intl } = this.props;
|
||||
|
||||
@ -60,6 +67,7 @@ const ActionBar = React.createClass({
|
||||
menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick });
|
||||
} else {
|
||||
menu.push({ text: intl.formatMessage(messages.mention), action: this.handleMentionClick });
|
||||
menu.push({ text: intl.formatMessage(messages.report), action: this.handleReport });
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -14,6 +14,7 @@ import {
|
||||
mentionCompose
|
||||
} from '../../actions/compose';
|
||||
import { deleteStatus } from '../../actions/statuses';
|
||||
import { initReport } from '../../actions/reports';
|
||||
import {
|
||||
makeGetStatus,
|
||||
getStatusAncestors,
|
||||
@ -88,6 +89,10 @@ const Status = React.createClass({
|
||||
this.props.dispatch(openMedia(media, index));
|
||||
},
|
||||
|
||||
handleReport (status) {
|
||||
this.props.dispatch(initReport(status.get('account'), status));
|
||||
},
|
||||
|
||||
renderChildren (list) {
|
||||
return list.map(id => <StatusContainer key={id} id={id} />);
|
||||
},
|
||||
@ -123,7 +128,7 @@ const Status = React.createClass({
|
||||
{ancestors}
|
||||
|
||||
<DetailedStatus status={status} me={me} onOpenMedia={this.handleOpenMedia} />
|
||||
<ActionBar status={status} me={me} onReply={this.handleReplyClick} onFavourite={this.handleFavouriteClick} onReblog={this.handleReblogClick} onDelete={this.handleDeleteClick} onMention={this.handleMentionClick} />
|
||||
<ActionBar status={status} me={me} onReply={this.handleReplyClick} onFavourite={this.handleFavouriteClick} onReblog={this.handleReblogClick} onDelete={this.handleDeleteClick} onMention={this.handleMentionClick} onReport={this.handleReport} />
|
||||
|
||||
{descendants}
|
||||
</div>
|
||||
|
@ -14,6 +14,7 @@ import notifications from './notifications';
|
||||
import settings from './settings';
|
||||
import status_lists from './status_lists';
|
||||
import cards from './cards';
|
||||
import reports from './reports';
|
||||
|
||||
export default combineReducers({
|
||||
timelines,
|
||||
@ -30,5 +31,6 @@ export default combineReducers({
|
||||
search,
|
||||
notifications,
|
||||
settings,
|
||||
cards
|
||||
cards,
|
||||
reports
|
||||
});
|
||||
|
57
app/assets/javascripts/components/reducers/reports.jsx
Normal file
57
app/assets/javascripts/components/reducers/reports.jsx
Normal file
@ -0,0 +1,57 @@
|
||||
import {
|
||||
REPORT_INIT,
|
||||
REPORT_SUBMIT_REQUEST,
|
||||
REPORT_SUBMIT_SUCCESS,
|
||||
REPORT_SUBMIT_FAIL,
|
||||
REPORT_CANCEL,
|
||||
REPORT_STATUS_TOGGLE
|
||||
} from '../actions/reports';
|
||||
import Immutable from 'immutable';
|
||||
|
||||
const initialState = Immutable.Map({
|
||||
new: Immutable.Map({
|
||||
isSubmitting: false,
|
||||
account_id: null,
|
||||
status_ids: Immutable.Set(),
|
||||
comment: ''
|
||||
})
|
||||
});
|
||||
|
||||
export default function reports(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case REPORT_INIT:
|
||||
return state.withMutations(map => {
|
||||
map.setIn(['new', 'isSubmitting'], false);
|
||||
map.setIn(['new', 'account_id'], action.account.get('id'));
|
||||
|
||||
if (state.getIn(['new', 'account_id']) !== action.account.get('id')) {
|
||||
map.setIn(['new', 'status_ids'], action.status ? Immutable.Set([action.status.get('id')]) : Immutable.Set());
|
||||
map.setIn(['new', 'comment'], '');
|
||||
} else {
|
||||
map.updateIn(['new', 'status_ids'], Immutable.Set(), set => set.add(action.status.get('id')));
|
||||
}
|
||||
});
|
||||
case REPORT_STATUS_TOGGLE:
|
||||
return state.updateIn(['new', 'status_ids'], Immutable.Set(), set => {
|
||||
if (action.checked) {
|
||||
return set.add(action.statusId);
|
||||
}
|
||||
|
||||
return set.remove(action.statusId);
|
||||
});
|
||||
case REPORT_SUBMIT_REQUEST:
|
||||
return state.setIn(['new', 'isSubmitting'], true);
|
||||
case REPORT_SUBMIT_FAIL:
|
||||
return state.setIn(['new', 'isSubmitting'], false);
|
||||
case REPORT_CANCEL:
|
||||
case REPORT_SUBMIT_SUCCESS:
|
||||
return state.withMutations(map => {
|
||||
map.setIn(['new', 'account_id'], null);
|
||||
map.setIn(['new', 'status_ids'], Immutable.Set());
|
||||
map.setIn(['new', 'comment'], '');
|
||||
map.setIn(['new', 'isSubmitting'], false);
|
||||
});
|
||||
default:
|
||||
return state;
|
||||