Show warning message when user has been muted several times.

This commit is contained in:
picklesrus 2020-12-17 15:43:07 -05:00
parent 338ac99e6b
commit d8ad0c38ea
5 changed files with 85 additions and 6 deletions

View file

@ -20,6 +20,10 @@ class MuteModal extends React.Component {
'handleNext',
'handlePrevious'
]);
this.numSteps = 2;
if (this.props.showWarning) {
this.numSteps++;
}
this.state = {
step: 0
};
@ -82,6 +86,23 @@ class MuteModal extends React.Component {
/>
</p>
</MuteStep>
{this.props.showWarning ? (
<MuteStep
bottomImg="/svgs/commenting/warning.svg"
bottomImgClass="bottom-img"
header={this.props.intl.formatMessage({id: 'comments.muted.warningBlocked'})}
>
<p>
<FormattedMessage
id="comments.muted.warningCareful"
values={{CommunityGuidelinesLink: (
<a href="/community_guidelines">
<FormattedMessage id="report.CommunityGuidelinesLinkText" />
</a>
)}}
/>
</p>
</MuteStep>) : null}
</Progression>
<FlexRow className={classNames('nav-divider')} />
<FlexRow className={classNames('mute-nav')}>
@ -97,7 +118,7 @@ class MuteModal extends React.Component {
</div>
</Button>
) : null }
{this.state.step >= 1 ? (
{this.state.step >= this.numSteps - 1 ? (
<Button
className={classNames('close-button')}
onClick={this.props.onRequestClose}
@ -131,6 +152,7 @@ MuteModal.propTypes = {
muteStepContent: PropTypes.string
}),
onRequestClose: PropTypes.func,
showWarning: PropTypes.bool,
timeMuted: PropTypes.string
};

View file

@ -354,6 +354,9 @@
"comments.muted.moreInfoGuidelines": "If you would like more information, you can read the {CommunityGuidelinesLink}.",
"comments.muted.moreInfoModal": "For more information, {clickHereLink}.",
"comments.muted.clickHereLinkText": "click here",
"comments.muted.warningBlocked": "If you continue to post comments like this, it will cause you to be blocked from using Scratch",
"comments.muted.warningCareful": "We don't want that to happen, so please be careful and make sure you have read and understand the {CommunityGuidelinesLink} before you try to post again!",
"social.embedLabel": "Embed",
"social.copyEmbedLinkText": "Copy embed",

View file

@ -48,7 +48,8 @@ class ComposeComment extends React.Component {
error: null,
appealId: null,
muteOpen: false,
muteExpiresAtMs: this.props.muteStatus.muteExpiresAt * 1000 // convert to ms
muteExpiresAtMs: this.props.muteStatus.muteExpiresAt * 1000, // convert to ms
showWarning: this.props.muteStatus.showWarning ? this.props.muteStatus.showWarning : false
};
}
handleInput (event) {
@ -80,12 +81,14 @@ class ComposeComment extends React.Component {
let muteOpen = false;
let muteExpiresAtMs = 0;
let rejectedStatus = ComposeStatus.REJECTED;
let showWarning = false;
if (body.status && body.status.mute_status) {
muteExpiresAtMs = body.status.mute_status.muteExpiresAt * 1000; // convert to ms
rejectedStatus = ComposeStatus.REJECTED_MUTE;
if (this.shouldShowMuteModal(body.status.mute_status.offenses)) {
muteOpen = true;
}
showWarning = body.status.mute_status.showWarning;
}
// Note: does not reset the message state
this.setState({
@ -93,7 +96,8 @@ class ComposeComment extends React.Component {
error: body.rejected,
appealId: body.appealId,
muteOpen: muteOpen,
muteExpiresAtMs: muteExpiresAtMs
muteExpiresAtMs: muteExpiresAtMs,
showWarning: showWarning
});
return;
}
@ -287,6 +291,7 @@ class ComposeComment extends React.Component {
className="mod-mute"
muteModalMessages={this.getMuteMessageInfo()}
shouldCloseOnOverlayClick={false}
showWarning={this.state.showWarning}
timeMuted={formatTime.formatRelativeTime(this.state.muteExpiresAtMs, window._locale)}
onRequestClose={this.handleMuteClose}
/>
@ -300,7 +305,8 @@ ComposeComment.propTypes = {
commenteeId: PropTypes.number,
muteStatus: PropTypes.shape({
offenses: PropTypes.array,
muteExpiresAt: PropTypes.number
muteExpiresAt: PropTypes.number,
showWarning: PropTypes.bool
}),
onAddComment: PropTypes.func,
onCancel: PropTypes.func,
@ -317,7 +323,7 @@ ComposeComment.propTypes = {
const mapStateToProps = state => ({
muteStatus: state.session.session.permissions.mute_status ?
state.session.session.permissions.mute_status :
{muteExpiresAt: 0, offenses: []},
{muteExpiresAt: 0, offenses: [], showWarning: false},
user: state.session.session.user
});

View file

@ -104,7 +104,8 @@ describe('Compose Comment test', () => {
permissions: {
mute_status: {
muteExpiresAt: 5,
offenses: []
offenses: [],
showWarning: true
}
}
}
@ -114,6 +115,7 @@ describe('Compose Comment test', () => {
const commentInstance = component.instance();
// Check conversion to ms from seconds is done at init time.
expect(commentInstance.state.muteExpiresAtMs).toEqual(5 * 1000);
expect(commentInstance.state.showWarning).toBe(true);
// Compose box should be hidden if muted unless they got muted due to a comment they just posted.
expect(component.find('FlexRow.compose-comment').exists()).toEqual(false);
expect(component.find('MuteModal').exists()).toEqual(false);
@ -191,9 +193,41 @@ describe('Compose Comment test', () => {
commentInstance.setState({muteOpen: true});
component.update();
expect(component.find('MuteModal').exists()).toEqual(true);
expect(component.find('MuteModal').props().showWarning).toBe(false);
global.Date.now = realDateNow;
});
test('Mute Modal gets showWarning props from state', () => {
const store = mockStore({
session: {
session: {
user: {},
permissions: {
mute_status: {}
}
}
}
});
const component = mountWithIntl(
<ComposeComment
{...defaultProps()}
/>
, {context: {store}}
);
// set state on the ComposeComment component, not the wrapper
const commentInstance = component.find('ComposeComment').instance();
commentInstance.setState({muteOpen: true});
component.update();
expect(component.find('MuteModal').exists()).toEqual(true);
expect(component.find('MuteModal').props().showWarning).toBe(false);
commentInstance.setState({
muteOpen: true,
showWarning: true
});
component.update();
expect(component.find('MuteModal').props().showWarning).toBe(true);
});
test('shouldShowMuteModal is false when list is undefined ', () => {
const commentInstance = getComposeCommentWrapper({}).instance();
expect(commentInstance.shouldShowMuteModal()).toBe(false);

View file

@ -33,6 +33,20 @@ describe('MuteModalTest', () => {
expect(component.find('button.back-button').exists()).toEqual(false);
});
test('Mute Modal shows extra showWarning step', () => {
const component = mountWithIntl(
<MuteModal
showWarning
muteModalMessages={defaultMessages}
/>
);
component.find('MuteModal').instance()
.setState({step: 2});
component.update();
expect(component.find('MuteStep').prop('bottomImg')).toEqual('/svgs/commenting/warning.svg');
expect(component.find('MuteStep').prop('totalSteps')).toEqual(3);
});
test('Mute Modal shows back & close button on last step', () => {
const component = mountWithIntl(
<MuteModal muteModalMessages={defaultMessages} />