Skip to content

Commit 006e33c

Browse files
authored
feat(threaded-replies): Create Replies component (#3288)
* feat(threaded-replies): Create Replies component * feat(threaded-replies): Add refactor styling * feat(threaded-replies): Add RepliesToggle component * feat(threaded-replies): Use correct import * feat(threaded-replies): Fix linting errors * feat(threaded-replies): split RepliesToggle out * feat(threaded-replies): Add tests and fix styling * feat(threaded-replies): Update snapshot and isHoverable * feat(threaded-replies): Move Replies to BaseComment * feat(threaded-replies): Fix lint errors
1 parent f73b9f9 commit 006e33c

File tree

13 files changed

+399
-84
lines changed

13 files changed

+399
-84
lines changed

src/elements/content-sidebar/activity-feed/activity-feed/ActiveState.js

Lines changed: 51 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ import ActivityItem from './ActivityItem';
1010
import AppActivity from '../app-activity';
1111
import AnnotationActivity from '../annotations';
1212
import Comment from '../comment';
13-
import BaseComment from '../comment/BaseComment';
1413
import TaskNew from '../task-new';
1514
import Version, { CollapsedVersion } from '../version';
1615
import withErrorHandling from '../../withErrorHandling';
16+
import { BaseComment } from '../comment/BaseComment';
1717
import {
1818
FEED_ITEM_TYPE_ANNOTATION,
1919
FEED_ITEM_TYPE_APP_ACTIVITY,
@@ -156,6 +156,10 @@ const ActiveState = ({
156156
const isFocused = item === activeFeedItem;
157157
const refValue = isFocused ? activeFeedItemRef : undefined;
158158
const itemFileVersionId = getProp(item, 'file_version.id');
159+
const replyProps = {
160+
hasReplies,
161+
onReplySelect: onCommentSelectHandler(item.id),
162+
};
159163

160164
switch (item.type) {
161165
case FEED_ITEM_TYPE_COMMENT:
@@ -164,49 +168,52 @@ const ActiveState = ({
164168
key={item.type + item.id}
165169
data-testid="comment"
166170
isFocused={isFocused}
171+
isHoverable
172+
hasNewThreadedReplies={hasNewThreadedReplies}
167173
ref={refValue}
168174
>
169-
<ActivityThread
170-
data-testid="activity-thread"
171-
currentUser={currentUser}
172-
getAvatarUrl={getAvatarUrl}
173-
getMentionWithQuery={getMentionWithQuery}
174-
getUserProfileUrl={getUserProfileUrl}
175-
hasNewThreadedReplies={hasNewThreadedReplies}
176-
hasReplies={hasReplies}
177-
isPending={item.isPending}
178-
isRepliesLoading={item.isRepliesLoading}
179-
mentionSelectorContacts={mentionSelectorContacts}
180-
onHideReplies={onHideRepliesHandler(item.id)}
181-
onReplyCreate={onReplyCreateHandler(item.id, item.type)}
182-
onReplyDelete={onReplyDeleteHandler(item.id)}
183-
onReplyEdit={onReplyUpdateHandler(item.id)}
184-
onReplySelect={onCommentSelectHandler(item.id)}
185-
onShowReplies={onShowRepliesHandler(item.id, item.type)}
186-
repliesTotalCount={item.total_reply_count}
187-
replies={item.replies}
188-
translations={translations}
189-
>
190-
{hasNewThreadedReplies ? (
191-
<BaseComment
192-
{...item}
193-
currentUser={currentUser}
194-
getAvatarUrl={getAvatarUrl}
195-
getMentionWithQuery={getMentionWithQuery}
196-
getUserProfileUrl={getUserProfileUrl}
197-
mentionSelectorContacts={mentionSelectorContacts}
198-
onDelete={onCommentDelete}
199-
onEdit={onCommentEdit}
200-
onSelect={onCommentSelectHandler(item.id)}
201-
permissions={{
202-
can_delete: getProp(item.permissions, 'can_delete', false),
203-
can_edit: getProp(item.permissions, 'can_edit', false),
204-
can_reply: getProp(item.permissions, 'can_reply', false),
205-
can_resolve: getProp(item.permissions, 'can_resolve', false),
206-
}}
207-
translations={translations}
208-
/>
209-
) : (
175+
{hasNewThreadedReplies ? (
176+
<BaseComment
177+
{...item}
178+
{...replyProps}
179+
currentUser={currentUser}
180+
getAvatarUrl={getAvatarUrl}
181+
getMentionWithQuery={getMentionWithQuery}
182+
getUserProfileUrl={getUserProfileUrl}
183+
mentionSelectorContacts={mentionSelectorContacts}
184+
onDelete={onCommentDelete}
185+
onEdit={onCommentEdit}
186+
onSelect={onCommentSelectHandler(item.id)}
187+
permissions={{
188+
can_delete: getProp(item.permissions, 'can_delete', false),
189+
can_edit: getProp(item.permissions, 'can_edit', false),
190+
can_reply: getProp(item.permissions, 'can_reply', false),
191+
can_resolve: getProp(item.permissions, 'can_resolve', false),
192+
}}
193+
translations={translations}
194+
/>
195+
) : (
196+
<ActivityThread
197+
data-testid="activity-thread"
198+
currentUser={currentUser}
199+
getAvatarUrl={getAvatarUrl}
200+
getMentionWithQuery={getMentionWithQuery}
201+
getUserProfileUrl={getUserProfileUrl}
202+
hasNewThreadedReplies={hasNewThreadedReplies}
203+
hasReplies={hasReplies}
204+
isPending={item.isPending}
205+
isRepliesLoading={item.isRepliesLoading}
206+
mentionSelectorContacts={mentionSelectorContacts}
207+
onHideReplies={onHideRepliesHandler(item.id)}
208+
onReplyCreate={onReplyCreateHandler(item.id, item.type)}
209+
onReplyDelete={onReplyDeleteHandler(item.id)}
210+
onReplyEdit={onReplyUpdateHandler(item.id)}
211+
onReplySelect={onCommentSelectHandler(item.id)}
212+
onShowReplies={onShowRepliesHandler(item.id, item.type)}
213+
repliesTotalCount={item.total_reply_count}
214+
replies={item.replies}
215+
translations={translations}
216+
>
210217
<Comment
211218
{...item}
212219
currentUser={currentUser}
@@ -225,8 +232,8 @@ const ActiveState = ({
225232
}}
226233
translations={translations}
227234
/>
228-
)}
229-
</ActivityThread>
235+
</ActivityThread>
236+
)}
230237
</ActivityItem>
231238
);
232239
case FEED_ITEM_TYPE_TASK:
Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,28 @@
11
@import '../../../common/variables';
22

33
.bcs-ActivityItem {
4-
.bcs-BaseComment {
5-
padding: $sidebarActivityFeedSpacingVertical $sidebarActivityFeedSpacingHorizontal;
4+
&.hasNewThreadedReplies {
5+
padding: 2px $bdl-grid-unit * 2;
6+
7+
& > div {
8+
padding: $bdl-grid-unit * 2;
9+
padding-right: $bdl-grid-unit * 4;
10+
}
11+
12+
&.bcs-is-hoverable:hover {
13+
background-color: $bdl-light-blue-05;
14+
}
15+
}
16+
}
17+
18+
.bcs-ActivityItem.bcs-is-focused {
19+
&.hasNewThreadedReplies {
20+
background-color: $white;
21+
22+
& > div {
23+
background-color: $bdl-light-blue-05;
24+
border-radius: $bdl-border-radius-size-med;
25+
box-shadow: 0 0 0 2px $bdl-box-blue;
26+
}
627
}
728
}

src/elements/content-sidebar/activity-feed/activity-feed/ActivityItem.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,24 @@ type Props = {
66
children: React.ReactNode;
77
className?: string;
88
isFocused?: boolean;
9+
isHoverable?: boolean;
10+
hasNewThreadedReplies?: boolean;
911
};
1012

11-
function ActivityItem({ children, className, isFocused, ...rest }: Props, ref: React.Ref<HTMLLIElement>) {
13+
function ActivityItem(
14+
{ children, className, isFocused, isHoverable = false, hasNewThreadedReplies = false, ...rest }: Props,
15+
ref: React.Ref<HTMLLIElement>,
16+
) {
1217
return (
13-
<li className={classNames('bcs-ActivityItem', className, { 'bcs-is-focused': isFocused })} ref={ref} {...rest}>
18+
<li
19+
className={classNames('bcs-ActivityItem', className, {
20+
'bcs-is-focused': isFocused,
21+
'bcs-is-hoverable': isHoverable && hasNewThreadedReplies,
22+
hasNewThreadedReplies,
23+
})}
24+
ref={ref}
25+
{...rest}
26+
>
1427
{children}
1528
</li>
1629
);

src/elements/content-sidebar/activity-feed/activity-feed/ActivityThread.scss

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,6 @@ $sidebarActivityFeedSelectedItemBorderWidth: 2px;
2424
padding-top: $sidebarThreadedActivityCardSpacingTop - $sidebarActivityFeedSelectedItemBorderWidth;
2525
}
2626

27-
// Styling duplicated for Comment refactor
28-
.bcs-BaseComment {
29-
padding: $sidebarThreadedActivityCardSpacingTop $sidebarThreadedActivityCardSpacingHorizontal $sidebarActivityFeedSpacingVertical;
30-
}
31-
32-
.bcs-ActivityThread-content > .bcs-BaseComment {
33-
padding-top: $sidebarThreadedActivityCardSpacingTop - $sidebarActivityFeedSelectedItemBorderWidth;
34-
}
35-
3627
.bcs-ActivityThread-toggle {
3728
color: $bdl-box-blue;
3829

@@ -98,14 +89,3 @@ $sidebarActivityFeedSelectedItemBorderWidth: 2px;
9889
.be .bcs-activity-feed-annotation-activity.bcs-ActivityItem.bcs-is-focused .bcs-ActivityThread .bcs-ActivityCard::before {
9990
content: none;
10091
}
101-
102-
// Styling duplicated for Comment refactor
103-
.be .bcs-activity-feed .bcs-activity-feed-items-container .bcs-ActivityItem.bcs-is-focused .bcs-ActivityThread .bcs-BaseComment {
104-
box-shadow: none;
105-
animation: none;
106-
}
107-
108-
// Disable legacy annotation select indicator (orange bar)
109-
.be .bcs-activity-feed-annotation-activity.bcs-ActivityItem.bcs-is-focused .bcs-ActivityThread .bcs-BaseComment::before {
110-
content: none;
111-
}

src/elements/content-sidebar/activity-feed/activity-feed/ActivityThreadReplies.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// @flow
22
import React from 'react';
3-
import BaseComment from '../comment/BaseComment';
43
import Comment from '../comment';
54
import LoadingIndicator from '../../../../components/loading-indicator';
5+
import { BaseComment } from '../comment/BaseComment';
66

77
import type { GetAvatarUrlCallback, GetProfileUrlCallback } from '../../../common/flowTypes';
88
import type { Translations } from '../../flowTypes';

src/elements/content-sidebar/activity-feed/activity-feed/ActivityThreadReplies.scss

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,6 @@
2525
padding-bottom: 0;
2626
}
2727
}
28-
29-
.bcs-BaseComment {
30-
&:first-child {
31-
padding-top: 0;
32-
}
33-
34-
&:last-child {
35-
padding-bottom: 0;
36-
}
37-
}
3828
}
3929

4030
.bcs-ActivityThreadReplies-loading {

src/elements/content-sidebar/activity-feed/activity-feed/__tests__/ActivityItem.test.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,24 @@ describe('src/elements/content-sidebar/activity-feed/activity-feed/ActivityItem'
1616
test.each([true, false])('should compile its className with isFocused equal to %s', isFocused => {
1717
expect(getWrapper({ isFocused }).hasClass('bcs-is-focused')).toBe(isFocused);
1818
});
19+
20+
test('should compile its className with isHoverable if isHoverable is true and hasNewThreadedReplies is true', () => {
21+
const wrapper = getWrapper({ isHoverable: true, hasNewThreadedReplies: true });
22+
23+
expect(wrapper.hasClass('bcs-is-hoverable')).toBe(true);
24+
});
25+
26+
test.each`
27+
hasNewThreadedReplies | isHoverable
28+
${false} | ${false}
29+
${true} | ${false}
30+
${false} | ${true}
31+
`(
32+
`should not compile its className with isHoverable if isHoverable is $isHoverable and hasNewThreadedReplies is $hasNewThreadedReplies`,
33+
({ hasNewThreadedReplies, isHoverable }) => {
34+
const wrapper = getWrapper({ isHoverable, hasNewThreadedReplies });
35+
36+
expect(wrapper.hasClass('bcs-is-hoverable')).toBe(false);
37+
},
38+
);
1939
});

src/elements/content-sidebar/activity-feed/activity-feed/__tests__/__snapshots__/ActiveState.test.js.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,9 @@ exports[`elements/content-sidebar/ActiveState/activity-feed/ActiveState should r
103103
</ForwardRef(ActivityItem)>
104104
<ForwardRef(ActivityItem)
105105
data-testid="comment"
106+
hasNewThreadedReplies={false}
106107
isFocused={false}
108+
isHoverable={true}
107109
key="commentc_123"
108110
>
109111
<ActivityThread

0 commit comments

Comments
 (0)