Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
S
scratch-www
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
xpstem
scratch-www
Commits
4e97e7c6
Unverified
Commit
4e97e7c6
authored
Feb 08, 2021
by
picklesrus
Committed by
GitHub
Feb 08, 2021
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #4943 from picklesrus/reply-mute
Open mute modal from reply button if you're muted.
parents
f9ae42d2
7c382a73
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
106 additions
and
4 deletions
+106
-4
src/components/modal/mute/modal.jsx
src/components/modal/mute/modal.jsx
+3
-2
src/views/preview/comment/comment.jsx
src/views/preview/comment/comment.jsx
+1
-0
src/views/preview/comment/compose-comment.jsx
src/views/preview/comment/compose-comment.jsx
+19
-2
test/unit/components/compose-comment.test.jsx
test/unit/components/compose-comment.test.jsx
+83
-0
No files found.
src/components/modal/mute/modal.jsx
View file @
4e97e7c6
...
...
@@ -37,7 +37,7 @@ class MuteModal extends React.Component {
this
.
numSteps
=
this
.
props
.
showWarning
?
steps
.
BAN_WARNING
:
steps
.
MUTE_INFO
;
this
.
state
=
{
step
:
steps
.
COMMENT_ISSUE
step
:
this
.
props
.
startStep
?
this
.
props
.
startStep
:
steps
.
COMMENT_ISSUE
};
}
handleNext
()
{
...
...
@@ -240,7 +240,8 @@ MuteModal.propTypes = {
}),
onRequestClose
:
PropTypes
.
func
,
showWarning
:
PropTypes
.
bool
,
startStep
:
PropTypes
.
oneOf
(
Object
.
keys
(
steps
)),
timeMuted
:
PropTypes
.
string
};
MuteModal
.
steps
=
steps
;
module
.
exports
=
injectIntl
(
MuteModal
);
src/views/preview/comment/comment.jsx
View file @
4e97e7c6
...
...
@@ -231,6 +231,7 @@ class Comment extends React.Component {
{
this
.
state
.
replying
?
(
<
FlexRow
className=
"comment-reply-row"
>
<
ComposeComment
isReply
commenteeId=
{
author
.
id
}
parentId=
{
parentId
||
id
}
projectId=
{
projectId
}
...
...
src/views/preview/comment/compose-comment.jsx
View file @
4e97e7c6
...
...
@@ -50,7 +50,7 @@ class ComposeComment extends React.Component {
status
:
ComposeStatus
.
EDITING
,
error
:
null
,
appealId
:
null
,
muteOpen
:
false
,
muteOpen
:
muteExpiresAtMs
>
Date
.
now
()
&&
this
.
props
.
isReply
,
muteExpiresAtMs
:
muteExpiresAtMs
,
muteType
:
this
.
props
.
muteStatus
.
currentMessageType
,
showWarning
:
this
.
props
.
muteStatus
.
showWarning
?
this
.
props
.
muteStatus
.
showWarning
:
false
...
...
@@ -147,6 +147,13 @@ class ComposeComment extends React.Component {
this
.
setState
({
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
()
{
...
...
@@ -187,6 +194,14 @@ class ComposeComment extends React.Component {
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
()
{
// 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
...
...
@@ -232,7 +247,7 @@ class ComposeComment extends React.Component {
render
()
{
return
(
<
React
.
Fragment
>
{
this
.
isMuted
(
)
?
(
{
(
this
.
isMuted
()
&&
!
(
this
.
props
.
isReply
&&
this
.
state
.
status
!==
ComposeStatus
.
REJECTED_MUTE
)
)
?
(
<
FlexRow
className=
"comment"
>
<
CommentingStatus
>
<
p
><
FormattedMessage
id=
{
this
.
getMuteMessageInfo
().
commentType
}
/></
p
>
...
...
@@ -344,6 +359,7 @@ class ComposeComment extends React.Component {
muteModalMessages=
{
this
.
getMuteMessageInfo
()
}
shouldCloseOnOverlayClick=
{
false
}
showWarning=
{
this
.
state
.
showWarning
}
startStep=
{
this
.
getMuteModalStartStep
()
}
timeMuted=
{
formatTime
.
formatRelativeTime
(
this
.
state
.
muteExpiresAtMs
,
window
.
_locale
)
}
onRequestClose=
{
this
.
handleMuteClose
}
/>
...
...
@@ -355,6 +371,7 @@ class ComposeComment extends React.Component {
ComposeComment
.
propTypes
=
{
commenteeId
:
PropTypes
.
number
,
isReply
:
PropTypes
.
bool
,
muteStatus
:
PropTypes
.
shape
({
offenses
:
PropTypes
.
array
,
muteExpiresAt
:
PropTypes
.
number
,
...
...
test/unit/components/compose-comment.test.jsx
View file @
4e97e7c6
...
...
@@ -101,6 +101,46 @@ describe('Compose Comment test', () => {
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
'
,
()
=>
{
jest
.
useFakeTimers
();
const
realDateNow
=
Date
.
now
.
bind
(
global
.
Date
);
...
...
@@ -133,6 +173,27 @@ describe('Compose Comment test', () => {
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
'
,
()
=>
{
const
realDateNow
=
Date
.
now
.
bind
(
global
.
Date
);
global
.
Date
.
now
=
()
=>
0
;
...
...
@@ -207,6 +268,7 @@ describe('Compose Comment test', () => {
commentInstance
.
setState
({
muteOpen
:
true
});
component
.
update
();
expect
(
component
.
find
(
'
MuteModal
'
).
exists
()).
toEqual
(
true
);
expect
(
component
.
find
(
'
MuteModal
'
).
props
().
startStep
).
toEqual
(
0
);
expect
(
component
.
find
(
'
MuteModal
'
).
props
().
showWarning
).
toBe
(
false
);
global
.
Date
.
now
=
realDateNow
;
});
...
...
@@ -321,6 +383,27 @@ describe('Compose Comment test', () => {
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
'
,
()
=>
{
const
realDateNow
=
Date
.
now
.
bind
(
global
.
Date
);
global
.
Date
.
now
=
()
=>
0
;
// Set "now" to 0 for easier testing.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment