Skip to content

Commit c5d43dd

Browse files
fehmerMiodec
andauthored
feat(profile): optionally include test activity on users public profile (@fehmer) (monkeytypegame#6824)
Co-authored-by: Miodec <[email protected]>
1 parent 91f64d2 commit c5d43dd

File tree

19 files changed

+209
-46
lines changed

19 files changed

+209
-46
lines changed

backend/__tests__/api/controllers/user.spec.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2948,6 +2948,9 @@ describe("user controller test", () => {
29482948
streak: { length: 2, lastResultTimestamp: 2000, maxLength: 5 },
29492949
lbOptOut: false,
29502950
bananas: 47, //should get removed
2951+
testActivity: {
2952+
"2024": fillYearWithDay(94),
2953+
},
29512954
};
29522955

29532956
beforeEach(async () => {
@@ -2961,6 +2964,7 @@ describe("user controller test", () => {
29612964

29622965
it("should get by name without authentication", async () => {
29632966
//GIVEN
2967+
29642968
getUserByNameMock.mockResolvedValue(foundUser as any);
29652969

29662970
const rank = { rank: 24 } as LeaderboardEntry;
@@ -3018,6 +3022,46 @@ describe("user controller test", () => {
30183022
expect(getUserByNameMock).toHaveBeenCalledWith("bob", "get user profile");
30193023
expect(getUserMock).not.toHaveBeenCalled();
30203024
});
3025+
it("should get testActivity if enabled", async () => {
3026+
//GIVEN
3027+
vi.useFakeTimers().setSystemTime(1712102400000);
3028+
getUserByNameMock.mockResolvedValue({
3029+
...foundUser,
3030+
profileDetails: { showActivityOnPublicProfile: true },
3031+
} as any);
3032+
const rank = { rank: 24 } as LeaderboardEntry;
3033+
leaderboardGetRankMock.mockResolvedValue(rank);
3034+
leaderboardGetCountMock.mockResolvedValue(100);
3035+
3036+
//WHEN
3037+
const { body } = await mockApp.get("/users/bob/profile").expect(200);
3038+
3039+
//THEN
3040+
expect(body.data.testActivity).toEqual(
3041+
expect.objectContaining({
3042+
lastDay: 1712102400000,
3043+
testsByDays: expect.arrayContaining([]),
3044+
})
3045+
);
3046+
});
3047+
it("should not get testActivity if disabled", async () => {
3048+
//GIVEN
3049+
vi.useFakeTimers().setSystemTime(1712102400000);
3050+
getUserByNameMock.mockResolvedValue({
3051+
...foundUser,
3052+
profileDetails: { showActivityOnPublicProfile: false },
3053+
} as any);
3054+
const rank = { rank: 24 } as LeaderboardEntry;
3055+
leaderboardGetRankMock.mockResolvedValue(rank);
3056+
leaderboardGetCountMock.mockResolvedValue(100);
3057+
3058+
//WHEN
3059+
const { body } = await mockApp.get("/users/bob/profile").expect(200);
3060+
3061+
//THEN
3062+
expect(body.data.testActivity).toBeUndefined();
3063+
});
3064+
30213065
it("should get base profile for banned user", async () => {
30223066
//GIVEN
30233067
getUserByNameMock.mockResolvedValue({
@@ -3132,6 +3176,7 @@ describe("user controller test", () => {
31323176
twitter: "twitter",
31333177
website: "https://monkeytype.com",
31343178
},
3179+
showActivityOnPublicProfile: false,
31353180
};
31363181

31373182
//WHEN
@@ -3159,6 +3204,7 @@ describe("user controller test", () => {
31593204
twitter: "twitter",
31603205
website: "https://monkeytype.com",
31613206
},
3207+
showActivityOnPublicProfile: false,
31623208
},
31633209
{
31643210
badges: [{ id: 4 }, { id: 2, selected: true }, { id: 3 }],

backend/src/api/controllers/user.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -972,14 +972,25 @@ export async function getProfile(
972972
uid: user.uid,
973973
} as UserProfile;
974974

975+
if (user.profileDetails?.showActivityOnPublicProfile) {
976+
profileData.testActivity = generateCurrentTestActivity(user.testActivity);
977+
} else {
978+
delete profileData.testActivity;
979+
}
975980
return new MonkeyResponse("Profile retrieved", profileData);
976981
}
977982

978983
export async function updateProfile(
979984
req: MonkeyRequest<undefined, UpdateUserProfileRequest>
980985
): Promise<UpdateUserProfileResponse> {
981986
const { uid } = req.ctx.decodedToken;
982-
const { bio, keyboard, socialProfiles, selectedBadgeId } = req.body;
987+
const {
988+
bio,
989+
keyboard,
990+
socialProfiles,
991+
selectedBadgeId,
992+
showActivityOnPublicProfile,
993+
} = req.body;
983994

984995
const user = await UserDAL.getPartialUser(uid, "update user profile", [
985996
"banned",
@@ -1005,6 +1016,7 @@ export async function updateProfile(
10051016
socialProfiles,
10061017
sanitizeString
10071018
) as UserProfileDetails["socialProfiles"],
1019+
showActivityOnPublicProfile,
10081020
};
10091021

10101022
await UserDAL.updateProfile(uid, profileDetailsUpdates, user.inventory);

frontend/src/html/pages/account.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@
287287

288288
<!-- <div class="group createdDate">Account created on -</div> -->
289289

290-
<div id="testActivity" class="hidden">
290+
<div class="testActivity hidden">
291291
<div class="wrapper">
292292
<div class="top">
293293
<div class="year"><select class="yearSelect"></select></div>

frontend/src/html/pages/profile.html

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,5 +162,27 @@
162162
</div>
163163
<div class="lbOptOutReminder hidden"></div>
164164
</div>
165+
<div class="testActivity hidden">
166+
<div class="wrapper">
167+
<div class="top">
168+
<div class="title"></div>
169+
<div class="legend">
170+
<span>less</span>
171+
<div data-level="0"></div>
172+
<div data-level="1"></div>
173+
<div data-level="2"></div>
174+
<div data-level="3"></div>
175+
<div data-level="4"></div>
176+
<span>more</span>
177+
</div>
178+
</div>
179+
<div class="activity"></div>
180+
<div class="months"></div>
181+
<div class="daysFull"></div>
182+
<div class="days"></div>
183+
<div class="nodata hidden">No data found.</div>
184+
<div class="note">Note: All activity data is using UTC time.</div>
185+
</div>
186+
</div>
165187
</div>
166188
</div>

frontend/src/html/popups.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,6 +1377,17 @@
13771377
<label>badge</label>
13781378
<div class="badgeSelectionContainer"></div>
13791379
</div>
1380+
<div>
1381+
<label>public activity</label>
1382+
<label class="checkbox">
1383+
<input
1384+
class="editProfileShowActivityOnPublicProfile"
1385+
type="checkbox"
1386+
checked
1387+
/>
1388+
<span>Include test activity graph on your public profile.</span>
1389+
</label>
1390+
</div>
13801391
<button class="edit-profile-submit" type="submit">save</button>
13811392
</form>
13821393
</dialog>

frontend/src/styles/account.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@
459459
background-color: var(--sub-alt-color);
460460
}
461461

462-
#testActivity {
462+
.testActivity {
463463
// width: max-content;
464464
// justify-self: center;
465465
background: var(--sub-alt-color);

frontend/src/styles/media-queries-blue.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@
231231
}
232232
}
233233
}
234-
#testActivity {
234+
.testActivity {
235235
--box-size: 0.58em;
236236
// .activity div,
237237
// .legend div {

frontend/src/styles/media-queries-brown.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
border-radius: 0.3rem;
5555
font-size: 0.5rem;
5656
}
57-
#testActivity {
57+
.testActivity {
5858
display: none;
5959
}
6060

frontend/src/styles/media-queries-green.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@
272272
}
273273
}
274274
}
275-
#testActivity {
275+
.testActivity {
276276
--box-size: 0.7em;
277277
.wrapper {
278278
grid-template-areas:

frontend/src/styles/media-queries-orange.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
.content-grid {
99
--content-max-width: 1280px;
1010
}
11-
#testActivity {
11+
.testActivity {
1212
--box-size: 1.05em;
1313
.daysFull {
1414
margin-right: 1rem;

0 commit comments

Comments
 (0)