Unverified Commit 394039b0 authored by Eric Rosenbaum's avatar Eric Rosenbaum Committed by GitHub

Merge pull request #4974 from LLK/develop

merge from develop to release branch
parents c42334a4 a9412af9
This diff is collapsed.
...@@ -37,7 +37,7 @@ class MuteModal extends React.Component { ...@@ -37,7 +37,7 @@ class MuteModal extends React.Component {
this.numSteps = this.props.showWarning ? steps.BAN_WARNING : steps.MUTE_INFO; this.numSteps = this.props.showWarning ? steps.BAN_WARNING : steps.MUTE_INFO;
this.state = { this.state = {
step: steps.COMMENT_ISSUE step: this.props.startStep ? this.props.startStep : steps.COMMENT_ISSUE
}; };
} }
handleNext () { handleNext () {
...@@ -240,7 +240,8 @@ MuteModal.propTypes = { ...@@ -240,7 +240,8 @@ MuteModal.propTypes = {
}), }),
onRequestClose: PropTypes.func, onRequestClose: PropTypes.func,
showWarning: PropTypes.bool, showWarning: PropTypes.bool,
startStep: PropTypes.oneOf(Object.keys(steps)),
timeMuted: PropTypes.string timeMuted: PropTypes.string
}; };
MuteModal.steps = steps;
module.exports = injectIntl(MuteModal); module.exports = injectIntl(MuteModal);
...@@ -231,6 +231,7 @@ class Comment extends React.Component { ...@@ -231,6 +231,7 @@ class Comment extends React.Component {
{this.state.replying ? ( {this.state.replying ? (
<FlexRow className="comment-reply-row"> <FlexRow className="comment-reply-row">
<ComposeComment <ComposeComment
isReply
commenteeId={author.id} commenteeId={author.id}
parentId={parentId || id} parentId={parentId || id}
projectId={projectId} projectId={projectId}
......
...@@ -50,7 +50,7 @@ class ComposeComment extends React.Component { ...@@ -50,7 +50,7 @@ class ComposeComment extends React.Component {
status: ComposeStatus.EDITING, status: ComposeStatus.EDITING,
error: null, error: null,
appealId: null, appealId: null,
muteOpen: false, muteOpen: muteExpiresAtMs > Date.now() && this.props.isReply,
muteExpiresAtMs: muteExpiresAtMs, muteExpiresAtMs: muteExpiresAtMs,
muteType: this.props.muteStatus.currentMessageType, muteType: this.props.muteStatus.currentMessageType,
showWarning: this.props.muteStatus.showWarning ? this.props.muteStatus.showWarning : false showWarning: this.props.muteStatus.showWarning ? this.props.muteStatus.showWarning : false
...@@ -147,6 +147,13 @@ class ComposeComment extends React.Component { ...@@ -147,6 +147,13 @@ class ComposeComment extends React.Component {
this.setState({ this.setState({
muteOpen: false muteOpen: false
}); });
// Cancel (i.e. complete) the reply action if the user clicked on the reply button while
// alreay muted. This "closes" the reply. If they just got muted, we want to leave it open
// so the blue CommentingStatus box shows.
if (this.props.isReply && this.state.status !== ComposeStatus.REJECTED_MUTE) {
this.handleCancel();
}
} }
handleMuteOpen () { handleMuteOpen () {
...@@ -187,6 +194,14 @@ class ComposeComment extends React.Component { ...@@ -187,6 +194,14 @@ class ComposeComment extends React.Component {
return creationTimeMinutesAgo < 2 && numOffenses === 1; return creationTimeMinutesAgo < 2 && numOffenses === 1;
} }
getMuteModalStartStep () {
// Decides which step of the mute modal to start on. If this was a reply button click,
// we show them the step that tells them how much time is left on their mute, otherwise
// they start at the beginning of the progression.
return this.props.isReply && this.state.status !== ComposeStatus.REJECTED_MUTE ?
MuteModal.steps.MUTE_INFO : MuteModal.steps.COMMENT_ISSUE;
}
getMuteMessageInfo () { getMuteMessageInfo () {
// return the ids for the messages that are shown for this mute type // return the ids for the messages that are shown for this mute type
// If mute modals have more than one unique "step" we could pass an array of steps // If mute modals have more than one unique "step" we could pass an array of steps
...@@ -232,7 +247,7 @@ class ComposeComment extends React.Component { ...@@ -232,7 +247,7 @@ class ComposeComment extends React.Component {
render () { render () {
return ( return (
<React.Fragment> <React.Fragment>
{this.isMuted() ? ( {(this.isMuted() && !(this.props.isReply && this.state.status !== ComposeStatus.REJECTED_MUTE)) ? (
<FlexRow className="comment"> <FlexRow className="comment">
<CommentingStatus> <CommentingStatus>
<p><FormattedMessage id={this.getMuteMessageInfo().commentType} /></p> <p><FormattedMessage id={this.getMuteMessageInfo().commentType} /></p>
...@@ -344,6 +359,7 @@ class ComposeComment extends React.Component { ...@@ -344,6 +359,7 @@ class ComposeComment extends React.Component {
muteModalMessages={this.getMuteMessageInfo()} muteModalMessages={this.getMuteMessageInfo()}
shouldCloseOnOverlayClick={false} shouldCloseOnOverlayClick={false}
showWarning={this.state.showWarning} showWarning={this.state.showWarning}
startStep={this.getMuteModalStartStep()}
timeMuted={formatTime.formatRelativeTime(this.state.muteExpiresAtMs, window._locale)} timeMuted={formatTime.formatRelativeTime(this.state.muteExpiresAtMs, window._locale)}
onRequestClose={this.handleMuteClose} onRequestClose={this.handleMuteClose}
/> />
...@@ -355,6 +371,7 @@ class ComposeComment extends React.Component { ...@@ -355,6 +371,7 @@ class ComposeComment extends React.Component {
ComposeComment.propTypes = { ComposeComment.propTypes = {
commenteeId: PropTypes.number, commenteeId: PropTypes.number,
isReply: PropTypes.bool,
muteStatus: PropTypes.shape({ muteStatus: PropTypes.shape({
offenses: PropTypes.array, offenses: PropTypes.array,
muteExpiresAt: PropTypes.number, muteExpiresAt: PropTypes.number,
......
...@@ -101,6 +101,46 @@ describe('Compose Comment test', () => { ...@@ -101,6 +101,46 @@ describe('Compose Comment test', () => {
global.Date.now = realDateNow; global.Date.now = realDateNow;
}); });
test('Comment Status and compose box do not show on replies when muted, but mute modal does', () => {
const realDateNow = Date.now.bind(global.Date);
global.Date.now = () => 0;
const store = mockStore({
session: {
session: {
user: {},
permissions: {
mute_status: {
muteExpiresAt: 5,
offenses: [],
showWarning: true
}
}
}
}
});
const component = mountWithIntl(
<ComposeComment
{...defaultProps()}
isReply
/>
, {context: {store}}
);
expect(component.find('FlexRow.compose-comment').exists()).toEqual(false);
expect(component.find('MuteModal').exists()).toBe(true);
expect(component.find('MuteModal').props().startStep).toBe(1);
expect(component.find('CommentingStatus').exists()).toEqual(false);
global.Date.now = realDateNow;
});
test('Comment Status and compose box show on replies when not muted', () => {
const realDateNow = Date.now.bind(global.Date);
global.Date.now = () => 0;
const component = getComposeCommentWrapper({isReply: true});
expect(component.find('FlexRow.compose-comment').exists()).toEqual(true);
expect(component.find('CommentingStatus').exists()).toEqual(false);
global.Date.now = realDateNow;
});
test('Comment Status initialized properly when muted', () => { test('Comment Status initialized properly when muted', () => {
jest.useFakeTimers(); jest.useFakeTimers();
const realDateNow = Date.now.bind(global.Date); const realDateNow = Date.now.bind(global.Date);
...@@ -133,6 +173,27 @@ describe('Compose Comment test', () => { ...@@ -133,6 +173,27 @@ describe('Compose Comment test', () => {
global.Date.now = realDateNow; global.Date.now = realDateNow;
}); });
test('Comment Status shows when user just submitted a reply comment that got them muted', () => {
const realDateNow = Date.now.bind(global.Date);
global.Date.now = () => 0;
const component = getComposeCommentWrapper({isReply: true});
const commentInstance = component.instance();
commentInstance.setState({
status: 'REJECTED_MUTE',
muteExpiresAtMs: 100
});
component.update();
expect(component.find('FlexRow.compose-comment').exists()).toEqual(true);
expect(component.find('MuteModal').exists()).toEqual(false);
expect(component.find('CommentingStatus').exists()).toEqual(true);
// Compose box exists but is disabled
expect(component.find('InplaceInput.compose-input').exists()).toEqual(true);
expect(component.find('InplaceInput.compose-input').props().disabled).toBe(true);
expect(component.find('Button.compose-post').props().disabled).toBe(true);
expect(component.find('Button.compose-cancel').props().disabled).toBe(true);
global.Date.now = realDateNow;
});
test('Comment Status shows when user just submitted a comment that got them muted', () => { test('Comment Status shows when user just submitted a comment that got them muted', () => {
const realDateNow = Date.now.bind(global.Date); const realDateNow = Date.now.bind(global.Date);
global.Date.now = () => 0; global.Date.now = () => 0;
...@@ -207,6 +268,7 @@ describe('Compose Comment test', () => { ...@@ -207,6 +268,7 @@ describe('Compose Comment test', () => {
commentInstance.setState({muteOpen: true}); commentInstance.setState({muteOpen: true});
component.update(); component.update();
expect(component.find('MuteModal').exists()).toEqual(true); expect(component.find('MuteModal').exists()).toEqual(true);
expect(component.find('MuteModal').props().startStep).toEqual(0);
expect(component.find('MuteModal').props().showWarning).toBe(false); expect(component.find('MuteModal').props().showWarning).toBe(false);
global.Date.now = realDateNow; global.Date.now = realDateNow;
}); });
...@@ -321,6 +383,27 @@ describe('Compose Comment test', () => { ...@@ -321,6 +383,27 @@ describe('Compose Comment test', () => {
global.Date.now = realDateNow; global.Date.now = realDateNow;
}); });
test('getMuteModalStartStep: not a reply ', () => {
const commentInstance = getComposeCommentWrapper({}).instance();
expect(commentInstance.getMuteModalStartStep()).toBe(0);
});
test('getMuteModalStartStep: A reply that got them muted ', () => {
const commentInstance = getComposeCommentWrapper({isReply: true}).instance();
commentInstance.setState({
status: 'REJECTED_MUTE'
});
expect(commentInstance.getMuteModalStartStep()).toBe(0);
});
test('getMuteModalStartStep: A reply click when already muted ', () => {
const commentInstance = getComposeCommentWrapper({isReply: true}).instance();
commentInstance.setState({
status: 'EDITING'
});
expect(commentInstance.getMuteModalStartStep()).toBe(1);
});
test('isMuted: expiration is in the future ', () => { test('isMuted: expiration is in the future ', () => {
const realDateNow = Date.now.bind(global.Date); const realDateNow = Date.now.bind(global.Date);
global.Date.now = () => 0; // Set "now" to 0 for easier testing. global.Date.now = () => 0; // Set "now" to 0 for easier testing.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment