Skip to content

Commit 678cf17

Browse files
authored
feat(tasks): show completion timestamp for task assignees (#1158)
* feat(tasks): show completion timestamp for task assignees * refactor(tasks): date/tooltips
1 parent 169f7bf commit 678cf17

File tree

7 files changed

+71
-41
lines changed

7 files changed

+71
-41
lines changed

flow-typed/box-ui-elements.js

+1
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,7 @@ type TaskMini = {|
654654
type TaskCollabRole = 'CREATOR' | 'ASSIGNEE';
655655

656656
type TaskCollab<R> = {|
657+
completed_at?: ?ISODate,
657658
id: ID,
658659
role: R,
659660
status: TaskCollabStatus,

i18n/en-US.properties

+6-6
Original file line numberDiff line numberDiff line change
@@ -432,16 +432,16 @@ be.tasks.feed.moreAssigneesLabel = See all assignees
432432
be.tasks.feed.rejectAction = Reject
433433
# Label for a rejected task
434434
be.tasks.feed.rejectedLabel = Task Rejected
435-
# accepted task status
436-
be.tasks.status.accepted = Accepted
437-
# Completed task status
438-
be.tasks.status.completed = Completed
435+
# Accepted task status, where dateTime is a readable time like "Today at 2pm"
436+
be.tasks.status.accepted = Accepted {dateTime}
437+
# Completed task status, where dateTime is a readable time like "Today at 2pm"
438+
be.tasks.status.completed = Completed {dateTime}
439439
# Task status when in progress
440440
be.tasks.status.inProgress = Awaiting
441441
# Task status when not started
442442
be.tasks.status.notStarted = Awaiting
443-
# Rejected task status
444-
be.tasks.status.rejected = Rejected
443+
# Rejected task status, where dateTime is a readable time like "Today at 2pm"
444+
be.tasks.status.rejected = Rejected {dateTime}
445445
# Label and date for task due date
446446
be.tasks.taskDueDate = Due: {date}
447447
# Tasks for approval

src/elements/common/messages.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -1015,18 +1015,18 @@ const messages = defineMessages({
10151015
},
10161016
tasksFeedStatusRejected: {
10171017
id: 'be.tasks.status.rejected',
1018-
defaultMessage: 'Rejected',
1019-
description: 'Rejected task status',
1018+
defaultMessage: 'Rejected {dateTime}',
1019+
description: 'Rejected task status, where dateTime is a readable time like "Today at 2pm"',
10201020
},
10211021
tasksFeedStatusAccepted: {
10221022
id: 'be.tasks.status.accepted',
1023-
defaultMessage: 'Accepted',
1024-
description: 'accepted task status',
1023+
defaultMessage: 'Accepted {dateTime}',
1024+
description: 'Accepted task status, where dateTime is a readable time like "Today at 2pm"',
10251025
},
10261026
tasksFeedStatusCompleted: {
10271027
id: 'be.tasks.status.completed',
1028-
defaultMessage: 'Completed',
1029-
description: 'Completed task status',
1028+
defaultMessage: 'Completed {dateTime}',
1029+
description: 'Completed task status, where dateTime is a readable time like "Today at 2pm"',
10301030
},
10311031
tasksFeedStatusNotStarted: {
10321032
id: 'be.tasks.status.notStarted',

src/elements/content-sidebar/activity-feed/comment/Comment.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ class Comment extends React.Component<Props, State> {
166166
}
167167
>
168168
<small className="bcs-comment-created-at">
169-
<ReadableTime alwaysShowTime timestamp={createdAtTimestamp} />
169+
<ReadableTime relativeThreshold={0} alwaysShowTime timestamp={createdAtTimestamp} />
170170
</small>
171171
</Tooltip>
172172
</div>

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

+4
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ exports[`elements/content-sidebar/ActivityFeed/comment/Comment should correctly
5555
>
5656
<ReadableTime
5757
alwaysShowTime={true}
58+
relativeThreshold={0}
5859
timestamp={1506534041000}
5960
/>
6061
</small>
@@ -126,6 +127,7 @@ exports[`elements/content-sidebar/ActivityFeed/comment/Comment should correctly
126127
>
127128
<ReadableTime
128129
alwaysShowTime={true}
130+
relativeThreshold={0}
129131
timestamp={1506534041000}
130132
/>
131133
</small>
@@ -198,6 +200,7 @@ exports[`elements/content-sidebar/ActivityFeed/comment/Comment should render an
198200
>
199201
<ReadableTime
200202
alwaysShowTime={true}
203+
relativeThreshold={0}
201204
timestamp={1506534041000}
202205
/>
203206
</small>
@@ -273,6 +276,7 @@ exports[`elements/content-sidebar/ActivityFeed/comment/Comment should render com
273276
>
274277
<ReadableTime
275278
alwaysShowTime={true}
279+
relativeThreshold={0}
276280
timestamp={1506534041000}
277281
/>
278282
</small>

src/elements/content-sidebar/activity-feed/task-new/Assignees.js

+39-22
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import uniqueId from 'lodash/uniqueId';
66
import { Flyout, Overlay } from '../../../../components/flyout';
77
import Tooltip from '../../../../components/tooltip';
88
import PlainButton from '../../../../components/plain-button';
9+
import ReadableTime from '../../../../components/time/ReadableTime';
910
import messages from '../../../common/messages';
1011
import AssigneeStatus from './AssigneeStatus';
1112
import { TASK_NEW_APPROVED, TASK_NEW_REJECTED, TASK_NEW_COMPLETED, TASK_NEW_NOT_STARTED } from '../../../../constants';
@@ -19,20 +20,26 @@ type Props = {|
1920
|} & InjectIntlProvidedProps;
2021

2122
const statusMessages = {
22-
[TASK_NEW_APPROVED]: <FormattedMessage {...messages.tasksFeedStatusAccepted} />,
23-
[TASK_NEW_REJECTED]: <FormattedMessage {...messages.tasksFeedStatusRejected} />,
24-
[TASK_NEW_COMPLETED]: <FormattedMessage {...messages.tasksFeedStatusCompleted} />,
25-
[TASK_NEW_NOT_STARTED]: <FormattedMessage {...messages.tasksFeedStatusNotStarted} />,
23+
[TASK_NEW_APPROVED]: messages.tasksFeedStatusAccepted,
24+
[TASK_NEW_REJECTED]: messages.tasksFeedStatusRejected,
25+
[TASK_NEW_COMPLETED]: messages.tasksFeedStatusCompleted,
26+
[TASK_NEW_NOT_STARTED]: null,
2627
};
2728

28-
const AssigneeTooltipLabel = React.memo(({ user, status }) => {
29+
const Datestamp = ({ date }: { date: ISODate | Date }) => {
30+
return <ReadableTime timestamp={new Date(date).getTime()} alwaysShowTime relativeThreshold={0} />;
31+
};
32+
33+
const AssignmentDetails = React.memo(({ user, status, completedAt, className }) => {
2934
const statusMessage = statusMessages[status] || null;
3035
return (
31-
<div className="bcs-task-assignment-tooltip-text">
32-
<div>
33-
<strong>{user.name}</strong>
34-
</div>
35-
{statusMessage && <div>{statusMessage}</div>}
36+
<div className={className}>
37+
<div className="bcs-task-assignment-details-name">{user.name}</div>
38+
{statusMessage && completedAt && (
39+
<div className="bcs-task-assignment-details-status">
40+
<FormattedMessage {...statusMessage} values={{ dateTime: <Datestamp date={completedAt} /> }} />
41+
</div>
42+
)}
3643
</div>
3744
);
3845
});
@@ -53,34 +60,44 @@ class Assignees extends React.Component<Props> {
5360
const areThereMoreEntries = !!next_marker; // there are more assignees in another page of results
5461
const visibleAssignees = entries
5562
.slice(0, maxAvatars)
56-
.map(({ id: assignmentId, target, status: assigneeStatus }) => {
63+
.map(({ id, target, status, completed_at: completedAt }) => {
5764
return (
58-
<Tooltip key={assignmentId} text={<AssigneeTooltipLabel user={target} status={assigneeStatus} />}>
65+
<Tooltip
66+
key={id}
67+
text={
68+
<AssignmentDetails
69+
className="bcs-task-assignment-tooltip"
70+
user={target}
71+
status={status}
72+
completedAt={completedAt}
73+
/>
74+
}
75+
>
5976
<AssigneeStatus
60-
key={assignmentId}
61-
status={assigneeStatus}
77+
status={status}
6278
user={target}
6379
getAvatarUrl={getAvatarUrl}
6480
data-testid="task-assignment-status"
6581
/>
6682
</Tooltip>
6783
);
6884
});
69-
const allAssignees = entries.map(({ id: assignmentId, target, status: assigneeStatus }) => {
70-
const statusMessage = statusMessages[assigneeStatus] || null;
85+
const allAssignees = entries.map(({ id, target, status, completed_at: completedAt }) => {
7186
return (
72-
<li key={assignmentId} className="bcs-task-assignment-list-item">
87+
<li key={id} className="bcs-task-assignment-list-item">
7388
<AssigneeStatus
74-
status={assigneeStatus}
89+
status={status}
7590
className="bcs-task-assignment-list-item-avatar"
7691
user={target}
7792
getAvatarUrl={getAvatarUrl}
7893
data-testid="task-assignment-status"
7994
/>
80-
<div className="bcs-task-assignment-list-item-details">
81-
<div>{target.name}</div>
82-
<div className="bcs-task-assignment-list-item-status">{statusMessage}</div>
83-
</div>
95+
<AssignmentDetails
96+
className="bcs-task-assignment-list-item-details"
97+
user={target}
98+
status={status}
99+
completedAt={completedAt}
100+
/>
84101
</li>
85102
);
86103
});

src/elements/content-sidebar/activity-feed/task-new/Task.scss

+14-6
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ $card-left-offset: 40px;
114114

115115
.bcs-comment {
116116
.bcs-comment-user-name {
117-
margin-right: 0;
117+
margin-right: 3px;
118118

119119
&.link {
120120
white-space: normal;
@@ -127,10 +127,6 @@ $card-left-offset: 40px;
127127
}
128128
}
129129

130-
.bcs-task-assignment-tooltip-text {
131-
text-align: center;
132-
}
133-
134130
.bcs-task-assignment-status {
135131
display: inline-block;
136132
height: 32px;
@@ -170,10 +166,14 @@ $card-left-offset: 40px;
170166
}
171167

172168
.bcs-task-assignment-list-item {
173-
align-items: flex-start;
169+
align-items: center;
174170
display: flex;
175171
margin: 6px 0 0 0;
176172
padding: 3px 0;
173+
174+
.bcs-task-assignment-details-status {
175+
color: $bdl-neutral-02;
176+
}
177177
}
178178

179179
.bcs-task-assignment-list-item-avatar {
@@ -187,3 +187,11 @@ $card-left-offset: 40px;
187187
.bcs-task-assignment-list-item-status {
188188
color: $bdl-neutral-02;
189189
}
190+
191+
.bcs-task-assignment-tooltip {
192+
text-align: center;
193+
194+
.bcs-task-assignment-details-name {
195+
font-weight: bold;
196+
}
197+
}

0 commit comments

Comments
 (0)