Skip to content

Commit 2313e69

Browse files
committed
hotfix: loading states, error handling
1 parent c03b56f commit 2313e69

File tree

4 files changed

+54
-28
lines changed

4 files changed

+54
-28
lines changed

src/app/interceptors/error.interceptor.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@ export class ErrorInterceptor implements HttpInterceptor {
1919
return next.handle(req).pipe(
2020
catchError((err: HttpErrorResponse) => {
2121
if (err.status === 401) {
22+
// Check if this is a password incorrect error that should be handled locally
23+
const errorMessage = err.error?.message || err.message || '';
24+
const isPasswordIncorrect = errorMessage.toLowerCase().includes('password is incorrect');
25+
26+
if (isPasswordIncorrect) {
27+
// Let the login component handle the password incorrect error locally
28+
return throwError(err);
29+
}
30+
2231
// JWT has expired - log the user out and redirect to login
2332
this.snackbarService.openInfoSnackbar('Your session has expired. Please login again to continue.');
2433

src/app/pages/landing-page/login/login.component.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { SnackbarService } from 'src/app/services/snackbar/snackbar.service';
66
import { UntypedFormBuilder, Validators } from '@angular/forms';
77
import { LoaderService } from 'src/app/services/loader/loader.service';
88
import { Role, SupportedLangs } from 'src/app/models/enums';
9-
import { catchError, mergeMap } from 'rxjs/operators';
9+
import { catchError, finalize, mergeMap } from 'rxjs/operators';
1010
import { ClearanceService } from 'src/app/services/clearance.service';
1111
import { HttpStatusCode } from '@angular/common/http';
1212
import { HttpStatus } from 'src/app/models/Auth';
@@ -62,6 +62,9 @@ export class LoginComponent implements OnDestroy {
6262
mergeMap(() => this.userStateService.getOrUpdateUserState()),
6363
catchError((err) => {
6464
throw err;
65+
}),
66+
finalize(() => {
67+
this.loaderService.hideLoader();
6568
})
6669
)
6770
.subscribe(
@@ -99,10 +102,7 @@ export class LoginComponent implements OnDestroy {
99102
break;
100103
}
101104
}
102-
)
103-
.add(() => {
104-
this.loaderService.hideLoader();
105-
});
105+
);
106106
}
107107

108108
constructor(
@@ -134,6 +134,7 @@ export class LoginComponent implements OnDestroy {
134134
}
135135

136136
ngOnDestroy() {
137+
this.loaderService.hideLoader();
137138
this.subscriptions.forEach((sub) => sub.unsubscribe());
138139
}
139140
}

src/app/pages/participant/participant-dashboard/participant-dashboard.component.ts

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Component, OnDestroy, OnInit } from '@angular/core';
22
import { MatDialog } from '@angular/material/dialog';
33
import { TranslateService } from '@ngx-translate/core';
44
import { Observable, of, Subscription, throwError } from 'rxjs';
5-
import { catchError, map, mergeMap, take, tap } from 'rxjs/operators';
5+
import { catchError, finalize, map, mergeMap, take, tap } from 'rxjs/operators';
66
import { SupportedLangs } from 'src/app/models/enums';
77
import { Study } from 'src/app/models/Study';
88
import { StudyUser } from 'src/app/models/StudyUser';
@@ -61,14 +61,18 @@ export class ParticipantDashboardComponent implements OnInit, OnDestroy {
6161
sub = (studyId ? redirectSub : of(null))
6262
.pipe(
6363
mergeMap(() => this.userStateService.getOrUpdateUserState(true)),
64-
mergeMap((res) =>
65-
res?.lang === SupportedLangs.NONE
64+
mergeMap((res) => {
65+
this.loaderService.hideLoader();
66+
return res?.lang === SupportedLangs.NONE
6667
? this.openLanguageDialog().pipe(
6768
mergeMap((lang) => this.userService.updateUser({ ...res, lang }))
6869
)
69-
: of(res)
70-
),
71-
tap((user) => this.translateService.use(user?.lang)),
70+
: of(res);
71+
}),
72+
tap((user) => {
73+
this.translateService.use(user?.lang ? user.lang : SupportedLangs.EN);
74+
this.loaderService.showLoader();
75+
}),
7276
mergeMap((user) => {
7377
// register the participant for the given study saved in session storage if it exists
7478
return studyId ? this.studyUserService.registerParticipantForStudy(user, studyId) : of(null);
@@ -77,11 +81,18 @@ export class ParticipantDashboardComponent implements OnInit, OnDestroy {
7781
// and does not reflect our recent call to registerParticipantForStudy
7882
mergeMap(() => this.studyUserService.getOrUpdateStudyUsers(true)),
7983
// if 409 (conflict) then we dont want an error
80-
catchError((err) => (err.status === 409 ? of(null) : throwError(err)))
84+
catchError((err) => (err.status === 409 ? of(null) : throwError(err))),
85+
// finalize runs regardless of how the observable completes (success, error, or unsubscription)
86+
finalize(() => {
87+
this.sessionStorageService.removeStudyIdToRegisterInSessionStorage();
88+
this.isLoading = false;
89+
this.loaderService.hideLoader();
90+
})
8191
)
8292
.subscribe(
8393
(_res) => {
8494
// noop
95+
_res;
8596
},
8697
(err) => {
8798
if (err.status === 401) {
@@ -91,12 +102,7 @@ export class ParticipantDashboardComponent implements OnInit, OnDestroy {
91102
console.error(err);
92103
}
93104
}
94-
)
95-
.add(() => {
96-
this.sessionStorageService.removeStudyIdToRegisterInSessionStorage();
97-
this.isLoading = false;
98-
this.loaderService.hideLoader();
99-
});
105+
);
100106

101107
this.subscriptions.push(sub);
102108
}

src/app/pages/participant/participant-dashboard/participant-studies/participant-studies.component.ts

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Component, OnDestroy, OnInit } from '@angular/core';
2-
import { forkJoin, Subscription } from 'rxjs';
3-
import { map, mergeMap } from 'rxjs/operators';
2+
import { forkJoin, of, Subscription } from 'rxjs';
3+
import { finalize, map, mergeMap } from 'rxjs/operators';
44
import { StudyUser } from 'src/app/models/StudyUser';
55
import { LoaderService } from 'src/app/services/loader/loader.service';
66
import { StudyUserService } from 'src/app/services/study-user.service';
@@ -28,10 +28,23 @@ export class ParticipantStudiesComponent implements OnInit, OnDestroy {
2828
this.loaderService.showLoader();
2929
const obs = this.studyUserService.studyUsersObservable
3030
.pipe(
31-
mergeMap((studyUsers: StudyUser[] | null) =>
32-
forkJoin((studyUsers || []).map((studyUser) => this.studyService.getStudyById(studyUser.studyId)))
33-
),
34-
map((studyUserResponses) => studyUserResponses.map((x) => x.body))
31+
mergeMap((studyUsers: StudyUser[] | null) => {
32+
const users = studyUsers || [];
33+
if (users.length === 0) {
34+
return of([]); // Return empty array immediately so finalize gets called
35+
}
36+
return forkJoin(
37+
users.map((studyUser) => {
38+
return this.studyService.getStudyById(studyUser.studyId);
39+
})
40+
);
41+
}),
42+
map((studyUserResponses) => {
43+
return studyUserResponses.map((x) => x.body);
44+
}),
45+
finalize(() => {
46+
this.loaderService.hideLoader();
47+
})
3548
)
3649
.subscribe(
3750
(studies) => {
@@ -62,10 +75,7 @@ export class ParticipantStudiesComponent implements OnInit, OnDestroy {
6275
(err) => {
6376
this.loaderService.hideLoader();
6477
}
65-
)
66-
.add(() => {
67-
this.loaderService.hideLoader();
68-
});
78+
);
6979
this.subscriptions.push(obs);
7080
}
7181

0 commit comments

Comments
 (0)