Skip to content

Commit 111327b

Browse files
committed
Fixed retweet logic on user profile page. Minor fixes
1 parent bc9b720 commit 111327b

File tree

20 files changed

+109
-79
lines changed

20 files changed

+109
-79
lines changed

frontend/src/components/TweetComponent/TweetActions/TweetActions.tsx

+7-10
Original file line numberDiff line numberDiff line change
@@ -8,36 +8,33 @@ import {
88
selectUserProfilePinnedTweetId
99
} from "../../../store/ducks/userProfile/selectors";
1010
import { selectUserDataId } from "../../../store/ducks/user/selectors";
11+
import { TweetType } from "../../../types/common";
1112

1213
interface TweetActionsProps {
13-
retweetsUserIds?: number[];
1414
tweetId?: number;
15+
tweetType?: TweetType;
1516
activeTab?: number;
1617
}
1718

18-
const TweetActions: FC<TweetActionsProps> = memo(({ retweetsUserIds = [], tweetId, activeTab }): ReactElement | null => {
19+
const TweetActions: FC<TweetActionsProps> = memo(({ tweetId, tweetType, activeTab }): ReactElement | null => {
1920
const userProfileId = useSelector(selectUserProfileId);
20-
const userProfilePinnedTweetId = useSelector(selectUserProfilePinnedTweetId);
21+
const pinnedTweetId = useSelector(selectUserProfilePinnedTweetId);
2122
const fullName = useSelector(selectUserProfileFullName);
2223
const myProfileId = useSelector(selectUserDataId);
2324

24-
const isTweetRetweetedByUser = retweetsUserIds.includes(userProfileId!);
25-
const isOwnProfile = myProfileId === userProfileId;
26-
const isPinnedTweet = userProfilePinnedTweetId === tweetId;
27-
2825
if (activeTab !== 0) {
2926
return null;
3027
}
3128

3229
return (
3330
<>
34-
{(isTweetRetweetedByUser && userProfileId) && (
31+
{(tweetType === TweetType.RETWEET) && (
3532
<TweetActionResult
3633
action={TweetActionResults.RETWEET}
37-
text={`${isOwnProfile ? "You" : fullName} Retweeted`}
34+
text={`${(myProfileId === userProfileId) ? "You" : fullName} Retweeted`}
3835
/>
3936
)}
40-
{isPinnedTweet && <TweetActionResult action={TweetActionResults.PIN} text="Pinned Tweet" />}
37+
{(pinnedTweetId === tweetId) && <TweetActionResult action={TweetActionResults.PIN} text="Pinned Tweet" />}
4138
</>
4239
);
4340
});

frontend/src/components/TweetComponent/TweetActions/__tests__/TweetActions.test.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from "react";
22

33
import { createMockRootState, mountWithStore } from "../../../../util/test-utils/test-helper";
4-
import { LoadingStatus } from "../../../../types/common";
4+
import { LoadingStatus, TweetType } from "../../../../types/common";
55
import { mockUser, mockUserProfile } from "../../../../util/test-utils/mock-test-data";
66
import TweetActionResult from "../../../TweetActionResult/TweetActionResult";
77
import TweetActions from "../TweetActions";
@@ -13,8 +13,8 @@ describe("TweetActions", () => {
1313
it("should render user profile retweeted", () => {
1414
const wrapper = mountWithStore(
1515
<TweetActions
16-
retweetsUserIds={[1]}
1716
tweetId={mockUser.pinnedTweetId!}
17+
tweetType={TweetType.RETWEET}
1818
activeTab={0}
1919
/>, mockState);
2020
expect(wrapper.find(TweetActionResult).at(0).prop("text")).toBe("Random Retweeted");
@@ -23,8 +23,8 @@ describe("TweetActions", () => {
2323
it("should render my profile retweeted", () => {
2424
const wrapper = mountWithStore(
2525
<TweetActions
26-
retweetsUserIds={[2]}
2726
tweetId={mockUser.pinnedTweetId!}
27+
tweetType={TweetType.RETWEET}
2828
activeTab={0}
2929
/>, mockRootState);
3030
expect(wrapper.find(TweetActionResult).at(0).prop("text")).toBe("You Retweeted");

frontend/src/components/TweetComponent/TweetComponent.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ const TweetComponent: FC<TweetComponentProps> = memo(({ tweet, activeTab, isTwee
4040

4141
return (
4242
<Paper className={classes.container} variant="outlined">
43-
<TweetActions tweetId={tweet?.id} retweetsUserIds={tweet?.retweetsUserIds} activeTab={activeTab} />
43+
<TweetActions tweetId={tweet?.id} tweetType={tweet?.tweetType} activeTab={activeTab} />
4444
<div className={classes.tweetWrapper}>
4545
<TweetAvatar userId={tweet?.author.id} src={tweet?.author.avatar ?? DEFAULT_PROFILE_IMG} />
4646
<div className={classes.tweetContainer}>

frontend/src/components/Users/Users.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const Users: FC = (): ReactElement => {
4646
<Typography variant={"body1"} component={"div"}>
4747
{t("SHOW_MORE", { defaultValue: "Show more" })}
4848
</Typography>
49-
</ListItem>`
49+
</ListItem>
5050
</List>
5151
)}
5252
</Paper>

frontend/src/store/ducks/userTweets/reducer.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ export const userTweetsReducer = produce((draft: Draft<UserTweetsState>, action:
1616

1717
switch (action.type) {
1818
case UserTweetsActionType.SET_TWEETS:
19-
const replaceTweets = action.payload.items.map(tweet => tweet.retweet ? tweet.retweet : tweet);
20-
draft.items = [...draft.items, ...replaceTweets];
19+
draft.items = [...draft.items, ...action.payload.items];
2120
draft.pagesCount = action.payload.pagesCount;
2221
draft.loadingState = LoadingStatus.LOADED;
2322
break;

frontend/src/types/common.ts

+6
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ export enum ReplyType {
3737
MENTION = "MENTION"
3838
}
3939

40+
export enum TweetType {
41+
TWEET = "TWEET",
42+
RETWEET = "RETWEET",
43+
REPLY = "REPLY"
44+
}
45+
4046
export enum LinkCoverSize {
4147
SMALL = "SMALL",
4248
MEDIUM = "MEDIUM",

frontend/src/types/tweet.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import { Image, LinkCoverSize, ReplyType } from "./common";
1+
import { Image, LinkCoverSize, ReplyType, TweetType } from "./common";
22
import { TaggedUserResponse } from "./user";
33
import { TweetListResponse } from "./lists";
44

55
export interface TweetResponse {
66
id: number;
77
text: string;
8+
tweetType: TweetType;
89
createdAt: string;
910
scheduledDate: string;
1011
addressedUsername: string;
@@ -22,7 +23,6 @@ export interface TweetResponse {
2223
imageDescription: string;
2324
taggedImageUsers: TaggedUserResponse[];
2425
quoteTweet: QuoteTweetResponse;
25-
retweet: TweetResponse;
2626
tweetList: TweetListResponse;
2727
poll: PollResponse;
2828
retweetsCount: number;
@@ -35,7 +35,6 @@ export interface TweetResponse {
3535
isUserFollowByOtherUser: boolean;
3636
isTweetDeleted: boolean;
3737
isTweetBookmarked: boolean;
38-
retweetsUserIds?: number[];
3938
}
4039

4140
export interface TweetAdditionalInfoResponse {

frontend/src/util/test-utils/mock-test-data.ts

-1
Original file line numberDiff line numberDiff line change
@@ -836,7 +836,6 @@ export const mockFullTweet = {
836836
{ "id": 101, "choice": "test choice 2", "votedUser": [] },
837837
{ "id": 102, "choice": "test choice 3", "votedUser": [] }]
838838
},
839-
"retweetsUserIds": [1, 2],
840839
"retweetsCount": 2,
841840
"likesCount": 2,
842841
"quotesCount": 2,

tweet-service/src/main/java/com/gmail/merikbest2015/controller/rest/RetweetController.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import com.gmail.merikbest2015.commons.constants.PathConstants;
44
import com.gmail.merikbest2015.commons.dto.HeaderResponse;
5-
import com.gmail.merikbest2015.dto.response.TweetUserResponse;
5+
import com.gmail.merikbest2015.commons.dto.response.tweet.TweetResponse;
66
import com.gmail.merikbest2015.commons.dto.response.notification.NotificationTweetResponse;
77
import com.gmail.merikbest2015.commons.dto.response.user.UserResponse;
88
import com.gmail.merikbest2015.mapper.RetweetMapper;
@@ -25,9 +25,9 @@ public class RetweetController {
2525
private final RetweetMapper retweetMapper;
2626

2727
@GetMapping(PathConstants.REPLIES_USER_ID)
28-
public ResponseEntity<List<TweetUserResponse>> getUserRetweetsAndReplies(@PathVariable("userId") Long userId,
29-
@PageableDefault(size = 10) Pageable pageable) {
30-
HeaderResponse<TweetUserResponse> response = retweetMapper.getUserRetweetsAndReplies(userId, pageable);
28+
public ResponseEntity<List<TweetResponse>> getUserRetweetsAndReplies(@PathVariable("userId") Long userId,
29+
@PageableDefault(size = 10) Pageable pageable) {
30+
HeaderResponse<TweetResponse> response = retweetMapper.getUserRetweetsAndReplies(userId, pageable);
3131
return ResponseEntity.ok().headers(response.getHeaders()).body(response.getItems());
3232
}
3333

tweet-service/src/main/java/com/gmail/merikbest2015/controller/rest/TweetController.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ public ResponseEntity<TweetResponse> getPinnedTweetByUserId(@PathVariable("userI
4444
}
4545

4646
@GetMapping(PathConstants.USER_USER_ID)
47-
public ResponseEntity<List<TweetUserResponse>> getUserTweets(@PathVariable("userId") Long userId,
48-
@PageableDefault(size = 10) Pageable pageable) {
49-
HeaderResponse<TweetUserResponse> response = tweetMapper.getUserTweets(userId, pageable);
47+
public ResponseEntity<List<TweetResponse>> getUserTweets(@PathVariable("userId") Long userId,
48+
@PageableDefault(size = 10) Pageable pageable) {
49+
HeaderResponse<TweetResponse> response = tweetMapper.getUserTweets(userId, pageable);
5050
return ResponseEntity.ok().headers(response.getHeaders()).body(response.getItems());
5151
}
5252

tweet-service/src/main/java/com/gmail/merikbest2015/mapper/RetweetMapper.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
import com.gmail.merikbest2015.commons.dto.HeaderResponse;
44
import com.gmail.merikbest2015.commons.dto.response.notification.NotificationTweetResponse;
5+
import com.gmail.merikbest2015.commons.dto.response.tweet.TweetResponse;
56
import com.gmail.merikbest2015.commons.dto.response.user.UserResponse;
67
import com.gmail.merikbest2015.commons.mapper.BasicMapper;
7-
import com.gmail.merikbest2015.dto.response.TweetUserResponse;
88
import com.gmail.merikbest2015.model.Tweet;
99
import com.gmail.merikbest2015.repository.projection.TweetUserProjection;
1010
import com.gmail.merikbest2015.repository.projection.UserProjection;
@@ -21,9 +21,9 @@ public class RetweetMapper {
2121
private final BasicMapper basicMapper;
2222
private final RetweetService retweetService;
2323

24-
public HeaderResponse<TweetUserResponse> getUserRetweetsAndReplies(Long userId, Pageable pageable) {
24+
public HeaderResponse<TweetResponse> getUserRetweetsAndReplies(Long userId, Pageable pageable) {
2525
Page<TweetUserProjection> tweets = retweetService.getUserRetweetsAndReplies(userId, pageable);
26-
return basicMapper.getHeaderResponse(tweets, TweetUserResponse.class);
26+
return basicMapper.getHeaderResponse(tweets, TweetResponse.class);
2727
}
2828

2929
public HeaderResponse<UserResponse> getRetweetedUsersByTweetId(Long tweetId, Pageable pageable) {

tweet-service/src/main/java/com/gmail/merikbest2015/mapper/TweetMapper.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,13 @@ public TweetResponse getTweetById(Long tweetId) {
3939

4040
public TweetResponse getPinnedTweetByUserId(Long userId) {
4141
return tweetService.getPinnedTweetByUserId(userId)
42-
.map(tweet -> basicMapper.convertToResponse(tweet, TweetUserResponse.class))
42+
.map(tweet -> basicMapper.convertToResponse(tweet, TweetResponse.class))
4343
.orElse(null);
4444
}
4545

46-
public HeaderResponse<TweetUserResponse> getUserTweets(Long userId, Pageable pageable) {
46+
public HeaderResponse<TweetResponse> getUserTweets(Long userId, Pageable pageable) {
4747
Page<TweetUserProjection> tweets = tweetService.getUserTweets(userId, pageable);
48-
return basicMapper.getHeaderResponse(tweets, TweetUserResponse.class);
48+
return basicMapper.getHeaderResponse(tweets, TweetResponse.class);
4949
}
5050

5151
public HeaderResponse<TweetResponse> getUserMediaTweets(Long userId, Pageable pageable) {

tweet-service/src/main/java/com/gmail/merikbest2015/repository/RetweetRepository.java

-5
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
import org.springframework.data.repository.query.Param;
77
import org.springframework.stereotype.Repository;
88

9-
import java.util.List;
10-
119
@Repository
1210
public interface RetweetRepository extends JpaRepository<Tweet, Long> {
1311

@@ -18,7 +16,4 @@ SELECT CASE WHEN count(tweet) > 0 THEN true ELSE false END
1816
AND tweet.retweet.id = :tweetId
1917
""")
2018
boolean isUserRetweetedTweet(@Param("userId") Long userId, @Param("tweetId") Long tweetId);
21-
22-
@Query("SELECT tweet.author.id FROM Tweet tweet WHERE tweet.retweet.id = :tweetId")
23-
List<Long> getRetweetsUserIds(@Param("tweetId") Long tweetId);
2419
}

tweet-service/src/main/java/com/gmail/merikbest2015/repository/projection/TweetProjection.java

+9-5
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,29 @@ public interface TweetProjection {
2121
List<TweetImageProjection> getImages();
2222
String getImageDescription();
2323
QuoteTweetProjection getQuoteTweet();
24-
TweetProjection getRetweet();
2524
PollProjection getPoll();
25+
String getLink();
26+
String getLinkTitle();
27+
String getLinkDescription();
28+
String getLinkCover();
29+
LinkCoverSize getLinkCoverSize();
2630
boolean isDeleted();
2731
TweetAuthorProjection getAuthor();
2832
Long getRetweetsCount();
2933
Long getLikesCount();
3034
Long getRepliesCount();
3135
Long getQuotesCount();
3236

33-
@Value("#{target.addressedUser == null ? null : target.addressedUser.id}")
37+
@Value("#{target.addressedUser?.id}")
3438
Long getAddressedId();
3539

36-
@Value("#{target.addressedUser == null ? null : target.addressedUser.username}")
40+
@Value("#{target.addressedUser?.username}")
3741
String getAddressedUsername();
3842

39-
@Value("#{target.addressedTweet == null ? null : target.addressedTweet.id}")
43+
@Value("#{target.addressedTweet?.id}")
4044
Long getAddressedTweetId();
4145

42-
@Value("#{target.listId == null ? null : @tweetProjectionHelper.getTweetList(target.listId)}")
46+
@Value("#{@tweetProjectionHelper.getTweetList(target.listId)}")
4347
TweetListResponse getTweetList();
4448

4549
List<TaggedUserProjection> getTaggedImageUsers();

tweet-service/src/main/java/com/gmail/merikbest2015/repository/projection/TweetUserProjection.java

+53-13
Original file line numberDiff line numberDiff line change
@@ -10,57 +10,97 @@
1010
import java.util.List;
1111

1212
public interface TweetUserProjection {
13+
14+
@Value("#{target.retweet != null ? target.retweet.id : target.id}")
1315
Long getId();
16+
17+
@Value("#{target.retweet != null ? target.retweet.text : target.text}")
1418
String getText();
19+
1520
TweetType getTweetType();
21+
22+
@Value("#{target.retweet != null ? target.retweet.createdAt : target.createdAt}")
1623
LocalDateTime getCreatedAt();
24+
25+
@Value("#{target.retweet != null ? target.retweet.scheduledDate : target.scheduledDate}")
1726
LocalDateTime getScheduledDate();
27+
28+
@Value("#{target.retweet != null ? target.retweet.replyType : target.replyType}")
1829
ReplyType getReplyType();
30+
31+
@Value("#{target.retweet != null ? target.retweet.link : target.link}")
1932
String getLink();
33+
34+
@Value("#{target.retweet != null ? target.retweet.linkTitle : target.linkTitle}")
2035
String getLinkTitle();
36+
37+
@Value("#{target.retweet != null ? target.retweet.linkDescription : target.linkDescription}")
2138
String getLinkDescription();
39+
40+
@Value("#{target.retweet != null ? target.retweet.linkCover : target.linkCover}")
2241
String getLinkCover();
23-
GifImageProjection getGifImage();
42+
43+
@Value("#{target.retweet != null ? target.retweet.linkCoverSize : target.linkCoverSize}")
2444
LinkCoverSize getLinkCoverSize();
45+
46+
@Value("#{target.retweet != null ? target.retweet.gifImage : target.gifImage}")
47+
GifImageProjection getGifImage();
48+
49+
@Value("#{target.retweet != null ? target.retweet.listId : target.listId}")
2550
Long getListId();
51+
52+
@Value("#{target.retweet != null ? target.retweet.images : target.images}")
2653
List<TweetImageProjection> getImages();
54+
55+
@Value("#{target.retweet != null ? target.retweet.imageDescription : target.imageDescription}")
2756
String getImageDescription();
57+
58+
@Value("#{target.retweet != null ? target.retweet.quoteTweet : target.quoteTweet}")
2859
QuoteTweetProjection getQuoteTweet();
29-
TweetProjection getRetweet();
60+
61+
@Value("#{target.retweet != null ? target.retweet.poll : target.poll}")
3062
PollProjection getPoll();
63+
64+
@Value("#{target.retweet != null ? target.retweet.deleted : target.deleted}")
3165
boolean isDeleted();
66+
67+
@Value("#{target.retweet != null ? target.retweet.author : target.author}")
3268
TweetAuthorProjection getAuthor();
69+
70+
@Value("#{target.retweet != null ? target.retweet.retweetsCount : target.retweetsCount}")
3371
Long getRetweetsCount();
72+
73+
@Value("#{target.retweet != null ? target.retweet.likesCount : target.likesCount}")
3474
Long getLikesCount();
75+
76+
@Value("#{target.retweet != null ? target.retweet.repliesCount : target.repliesCount}")
3577
Long getRepliesCount();
3678

37-
@Value("#{target.addressedUser == null ? null : target.addressedUser.id}")
79+
@Value("#{target.retweet != null ? target.retweet.addressedUser?.id : target.addressedUser?.id}")
3880
Long getAddressedId();
3981

40-
@Value("#{target.addressedUser == null ? null : target.addressedUser.username}")
82+
@Value("#{target.retweet != null ? target.retweet.addressedUser?.username : target.addressedUser?.username}")
4183
String getAddressedUsername();
4284

43-
@Value("#{target.addressedTweet == null ? null : target.addressedTweet.id}")
85+
@Value("#{target.retweet != null ? target.retweet.addressedTweet?.id : target.addressedTweet?.id}")
4486
Long getAddressedTweetId();
4587

46-
@Value("#{target.listId == null ? null : @tweetProjectionHelper.getTweetList(target.listId)}")
88+
@Value("#{@tweetProjectionHelper.getTweetList(target.retweet != null ? target.retweet.listId : target.listId)}")
4789
TweetListResponse getTweetList();
4890

91+
@Value("#{target.retweet != null ? target.retweet.taggedImageUsers : target.taggedImageUsers}")
4992
List<TaggedUserProjection> getTaggedImageUsers();
5093

51-
@Value("#{@retweetRepository.getRetweetsUserIds(target.id)}")
52-
List<Long> getRetweetsUserIds();
53-
54-
@Value("#{@tweetProjectionHelper.isUserLikedTweet(target.id)}")
94+
@Value("#{@tweetProjectionHelper.isUserLikedTweet(target.retweet != null ? target.retweet.id : target.id)}")
5595
boolean getIsTweetLiked();
5696

57-
@Value("#{@tweetProjectionHelper.isUserRetweetedTweet(target.id)}")
97+
@Value("#{@tweetProjectionHelper.isUserRetweetedTweet(target.retweet != null ? target.retweet.id : target.id)}")
5898
boolean getIsTweetRetweeted();
5999

60-
@Value("#{@tweetProjectionHelper.isUserBookmarkedTweet(target.id)}")
100+
@Value("#{@tweetProjectionHelper.isUserBookmarkedTweet(target.retweet != null ? target.retweet.id : target.id)}")
61101
boolean getIsTweetBookmarked();
62102

63-
@Value("#{@userServiceImpl.isUserFollowByOtherUser(target.author.id)}")
103+
@Value("#{@userServiceImpl.isUserFollowByOtherUser(target.retweet != null ? target.retweet.author.id : target.author.id)}")
64104
boolean getIsUserFollowByOtherUser();
65105

66106
interface QuoteTweetProjection {

tweet-service/src/main/java/com/gmail/merikbest2015/service/util/TweetProjectionHelper.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,6 @@ public boolean isUserBookmarkedTweet(Long tweetId) {
3434
}
3535

3636
public TweetListResponse getTweetList(Long listId) {
37-
return listsClient.getTweetList(listId);
37+
return listId != null ? listsClient.getTweetList(listId) : null;
3838
}
3939
}

0 commit comments

Comments
 (0)