Skip to content

Commit 37b3858

Browse files
committed
feat(welcome-ack): present "welcome" header to new users
1 parent 35ed5a3 commit 37b3858

23 files changed

+142
-28
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
db.users.update(
2+
{ "welcomeAck": { "$exists": false } },
3+
{ "$set": { "welcomeAck": true } },
4+
{ "multi": true }
5+
);
6+
7+
//or the equivalent
8+
db.users.updateMany(
9+
{ "welcomeAck": { "$exists": false } },
10+
{ "$set": { "welcomeAck": true } }
11+
);

backend/src/model/user.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ const userSchema = new Schema({
4545
followers: {type: [String], select: false},
4646
showAllPublicInFeed: Boolean,
4747
enableLocalStorage: Boolean,
48+
welcomeAck: Boolean,
4849
__v: {type: Number, select: false}
4950
},
5051
{

backend/src/routes/users/user-data.service.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,17 @@ let updateUserDataFeedToggle = async function (showAllPublicInFeed, userId) {
6767
return updatedUserData;
6868
}
6969

70+
let updateUserDataWelcomeAck = async function ( userId) {
71+
const updatedUserData = await User.findOneAndUpdate(
72+
{userId: userId},
73+
{
74+
$set: {welcomeAck: true}
75+
}
76+
);
77+
78+
return updatedUserData;
79+
}
80+
7081
let updateLocalStorageOption = async function (enableLocalStorage, userId) {
7182
const updatedUserData = await User.findOneAndUpdate(
7283
{userId: userId},
@@ -627,6 +638,7 @@ module.exports = {
627638
updateUserDataHistoryReadLaterPinned: updateUserDataHistoryReadLaterPinned,
628639
updateUserDataFeedToggle: updateUserDataFeedToggle,
629640
updateLocalStorageOption: updateLocalStorageOption,
641+
updateUserDataWelcomeAck: updateUserDataWelcomeAck,
630642
createUserData: createUserData,
631643
getUserData: getUserData,
632644
deleteUserData: deleteUserData,

backend/src/routes/users/user.router.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
const express = require('express');
22
const usersRouter = express.Router();
33

4-
const cheerio = require('cheerio');
5-
64
const personalBookmarksRouter = require('./bookmarks/personal-bookmarks.router');
75
const personalCodeletsRouter = require('./snippets/personal-snippets.router');
86

@@ -255,6 +253,16 @@ usersRouter.patch('/:userId/local-storage', keycloak.protect(), async (request,
255253
return response.status(HttpStatus.OK).send({localStorageOptionUpdated: true});
256254
});
257255

256+
/*
257+
* Update welcomeAck flag
258+
*/
259+
usersRouter.patch('/:userId/welcome-acknowledge', keycloak.protect(), async (request, response) => {
260+
userIdTokenValidator.validateUserId(request);
261+
await UserDataService.updateUserDataWelcomeAck(request.params.userId);
262+
263+
return response.status(HttpStatus.OK).send({welcomeAck: true});
264+
});
265+
258266
/*
259267
* DELETE user
260268
*/

frontend/src/app/app.component.html

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,20 +80,19 @@
8080
<div class="container">
8181

8282
<div class="main-body">
83-
<div *ngIf="showAcknowledgeMigrationHeader" class="alert alert-warning header-notification-wrapper shadow-sm">
83+
<div *ngIf="(userData$ | async) && !(userData$ | async).welcomeAck" class="alert alert-warning shadow-sm">
8484
<div>
85-
<i class="fas fa-exclamation-circle fa-lg mr-1"></i> <b>Bookmarks.dev</b> has rebranded to <b>Codever</b>
86-
</div>
87-
<div>
88-
<button type="button" class="ml-2 btn btn-primary btn-sm mr-2"
89-
(click)="acknowledgeCodeverRebranding('cool')">
90-
Cool <i class="fas fa-thumbs-up"></i>
91-
</button>
92-
<button type="button" class="ml-2 btn btn-primary btn-sm mr-2"
93-
(click)="acknowledgeCodeverRebranding('ook')">
94-
Ok <i class="fas fa-check-circle"></i>
95-
</button>
85+
<h4>Welcome to Codever 🙏 !!!</h4>
86+
<ul style="list-style-type: none; margin-left: -1.5rem">
87+
<li>👉 &nbsp;Go to <a [routerLink]="['/dashboard']"><i class="fas fa-tachometer-alt"></i> My Dashboard</a>
88+
where you can <strong>import</strong> your browser bookmarks, view your latest activity and your used
89+
tags or searches</li>
90+
<li class="mt-1">👉 &nbsp;See our <a [routerLink]="['/howto']"><i class="fas fa-info-circle"></i> HowTo Guides</a> and use <a [routerLink]="['/extensions']">one of our many extensions <i class="fas fa-wrench"></i></a> to help you easily manage your bookmarks and snippets
91+
from your favorite browser or IDE </li>
92+
</ul>
9693
</div>
94+
95+
<button class="ml-2 btn btn-primary btn-sm" (click)="acknowledgeWelcomeMessage()">Got it <i class="fas fa-check-circle"></i></button>
9796
</div>
9897
<app-loader></app-loader>
9998
<router-outlet></router-outlet>

frontend/src/app/app.component.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export class AppComponent implements OnInit {
3030
userIsLoggedIn = false;
3131
userId: string;
3232

33+
userData$: Observable<UserData>;
3334
showAcknowledgeMigrationHeader = false;
3435
latestSearches$: Observable<Search[]>;
3536

@@ -59,7 +60,8 @@ export class AppComponent implements OnInit {
5960
this.userInfoStore.getUserInfo$().subscribe(userInfo => {
6061
this.userId = userInfo.sub;
6162
});
62-
this.latestSearches$ = this.userDataStore.getUserData$().pipe(
63+
this.userData$ = this.userDataStore.getUserData$();
64+
this.latestSearches$ = this.userData$.pipe(
6365
map(userData => {
6466
for (let i = 0; i < 10; i++) {
6567
this.hoveringLastSearches.push(false);
@@ -175,11 +177,15 @@ export class AppComponent implements OnInit {
175177
userAgent: navigator.userAgent
176178
}
177179

178-
this.feedbackService.createBookmark(feedback).subscribe();
180+
this.feedbackService.createFeedback(feedback).subscribe();
179181
}
180182

181183
hovering(i: number): boolean {
182184
return this.hoveringLastSearches[i];
183185
}
184186

187+
acknowledgeWelcomeMessage() {
188+
this.userDataStore.updateWelcomeAcknowledge$();
189+
}
190+
185191
}

frontend/src/app/core/model/user-data.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export interface UserData {
1515
followers?: string[];
1616
showAllPublicInFeed?: boolean;
1717
enableLocalStorage?: boolean;
18+
welcomeAck?: boolean; // acknowledges the welcome dialog
1819
}
1920

2021
export interface Profile {

frontend/src/app/core/user-data.service.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,4 +204,11 @@ export class UserDataService {
204204
.get<UserDataProfile[]>(`${this.usersApiBaseUrl}/${userId}/followers`)
205205
.pipe(shareReplay(1));
206206
}
207+
208+
updateAcknowledgeWelcome(userId: string): Observable<UserData> {
209+
return this.httpClient
210+
.patch(`${this.usersApiBaseUrl}/${userId}/welcome-acknowledge`, {headers: this.headers})
211+
.pipe(shareReplay(1));
212+
}
213+
207214
}

frontend/src/app/core/user/userdata.store.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ export class UserDataStore {
9292
favorites: [],
9393
history: [],
9494
followers: [],
95-
following: following
95+
following: following,
96+
welcomeAck: false
9697
}
9798

9899
this.userService.createInitialUserData(initialUserData).subscribe((data) => {
@@ -425,4 +426,18 @@ export class UserDataStore {
425426
}
426427
}
427428
}
429+
430+
431+
updateWelcomeAcknowledge$(): Observable<UserData> {
432+
const obs: Observable<any> = this.userService.updateAcknowledgeWelcome(this.userId);
433+
obs.subscribe(
434+
() => {
435+
this.userData.welcomeAck = true;
436+
this._userData.next(this.userData);
437+
}
438+
);
439+
440+
return obs;
441+
}
442+
428443
}

0 commit comments

Comments
 (0)