diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 96710356..7dd8801e 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -75,7 +75,9 @@ import { SharedModule } from './shared/shared.module';
PhaseService,
GithubEventService,
Title,
- LoggingService]
+ ErrorHandlingService,
+ LoggingService
+ ]
},
{
provide: IssueService,
diff --git a/src/app/auth/auth.component.html b/src/app/auth/auth.component.html
index ee113cc7..605b674f 100644
--- a/src/app/auth/auth.component.html
+++ b/src/app/auth/auth.component.html
@@ -1,13 +1,16 @@
Confirm Login Account
- Session on {{ currentSessionOrg }}
@@ -24,3 +27,8 @@
+
+
diff --git a/src/app/auth/auth.component.ts b/src/app/auth/auth.component.ts
index a30274e5..9bb41d18 100644
--- a/src/app/auth/auth.component.ts
+++ b/src/app/auth/auth.component.ts
@@ -134,6 +134,14 @@ export class AuthComponent implements OnInit, OnDestroy {
return this.authState === AuthState.ConfirmOAuthUser;
}
+ isUserAuthenticated(): boolean {
+ return this.authState === AuthState.Authenticated;
+ }
+
+ isRepoSet(): boolean {
+ return this.phaseService.isRepoSet();
+ }
+
get currentSessionOrg(): string {
if (!this.sessionInformation) {
// Retrieve org details of session information from local storage
diff --git a/src/app/auth/auth.module.ts b/src/app/auth/auth.module.ts
index 901bc391..46d81bbf 100644
--- a/src/app/auth/auth.module.ts
+++ b/src/app/auth/auth.module.ts
@@ -4,12 +4,20 @@ import { SharedModule } from '../shared/shared.module';
import { AuthRoutingModule } from './auth-routing.module';
import { AuthComponent } from './auth.component';
import { ConfirmLoginComponent } from './confirm-login/confirm-login.component';
+import { LoginComponent } from './login/login.component';
import { JsonParseErrorDialogComponent } from './profiles/json-parse-error-dialog/json-parse-error-dialog.component';
import { ProfilesComponent } from './profiles/profiles.component';
import { SessionSelectionComponent } from './session-selection/session-selection.component';
@NgModule({
imports: [AuthRoutingModule, SharedModule, CommonModule],
- declarations: [AuthComponent, ProfilesComponent, JsonParseErrorDialogComponent, ConfirmLoginComponent, SessionSelectionComponent]
+ declarations: [
+ AuthComponent,
+ ProfilesComponent,
+ JsonParseErrorDialogComponent,
+ LoginComponent,
+ ConfirmLoginComponent,
+ SessionSelectionComponent
+ ]
})
export class AuthModule {}
diff --git a/src/app/auth/confirm-login/confirm-login.component.ts b/src/app/auth/confirm-login/confirm-login.component.ts
index 95df775e..94c414d3 100644
--- a/src/app/auth/confirm-login/confirm-login.component.ts
+++ b/src/app/auth/confirm-login/confirm-login.component.ts
@@ -1,15 +1,7 @@
import { Component, Input, OnInit } from '@angular/core';
-import { Router } from '@angular/router';
-import { Observable, of } from 'rxjs';
-import { mergeMap } from 'rxjs/operators';
-import { Phase } from '../../core/models/phase.model';
-import { Repo } from '../../core/models/repo.model';
import { AuthService, AuthState } from '../../core/services/auth.service';
import { ErrorHandlingService } from '../../core/services/error-handling.service';
-import { GithubService } from '../../core/services/github.service';
-import { GithubEventService } from '../../core/services/githubevent.service';
import { LoggingService } from '../../core/services/logging.service';
-import { PhaseService } from '../../core/services/phase.service';
import { UserService } from '../../core/services/user.service';
@Component({
@@ -23,13 +15,9 @@ export class ConfirmLoginComponent implements OnInit {
constructor(
private authService: AuthService,
- private phaseService: PhaseService,
private userService: UserService,
private errorHandlingService: ErrorHandlingService,
- private githubEventService: GithubEventService,
private logger: LoggingService,
- private router: Router,
- public githubService: GithubService
) {}
ngOnInit() {}
@@ -44,42 +32,17 @@ export class ConfirmLoginComponent implements OnInit {
this.authService.startOAuthProcess();
}
- /**
- * Handles the clean up required after authentication and setting up of user data is completed.
- */
- handleAuthSuccess() {
- this.authService.setTitleWithPhaseDetail();
- this.router.navigateByUrl(Phase.issuesViewer);
- this.authService.changeAuthState(AuthState.Authenticated);
- }
-
/**
* Will complete the process of logging in the given user.
*/
completeLoginProcess(): void {
this.authService.changeAuthState(AuthState.AwaitingAuthentication);
- this.phaseService.initializeCurrentRepository();
- this.logger.info(`ConfirmLoginComponent: Current repo is ${this.phaseService.currentRepo}`);
+ this.logger.info(`ConfirmLoginComponent: Completing login process`);
this.userService
.createUserModel(this.username)
- .pipe(
- mergeMap(() => {
- const currentRepo = this.phaseService.currentRepo;
- if (Repo.isInvalidRepoName(currentRepo)) {
- return of(false);
- }
- return this.githubService.isRepositoryPresent(currentRepo.owner, currentRepo.name);
- }),
- mergeMap((isValidRepository) => {
- if (!isValidRepository) {
- return new Observable();
- }
- return this.githubEventService.setLatestChangeEvent();
- })
- )
.subscribe(
() => {
- this.handleAuthSuccess();
+ this.authService.changeAuthState(AuthState.Authenticated);
},
(error) => {
this.authService.changeAuthState(AuthState.NotAuthenticated);
@@ -87,6 +50,5 @@ export class ConfirmLoginComponent implements OnInit {
this.logger.info(`ConfirmLoginComponent: Completion of login process failed with an error: ${error}`);
}
);
- this.handleAuthSuccess();
}
}
diff --git a/src/app/auth/login/login.component.css b/src/app/auth/login/login.component.css
new file mode 100644
index 00000000..dec75881
--- /dev/null
+++ b/src/app/auth/login/login.component.css
@@ -0,0 +1,18 @@
+.login-button {
+ background: #f7fcfe;
+ line-height: 45px;
+ border: 1px solid currentColor;
+ width: 100%;
+}
+
+.logo {
+ align-items: center;
+ display: inline-flex;
+ margin: 0 3px 3px 3px;
+}
+
+.github-logo {
+ font-size: 20px;
+ width: 20px;
+ height: 20px;
+}
diff --git a/src/app/auth/login/login.component.html b/src/app/auth/login/login.component.html
new file mode 100644
index 00000000..afcde449
--- /dev/null
+++ b/src/app/auth/login/login.component.html
@@ -0,0 +1,4 @@
+
diff --git a/src/app/auth/login/login.component.ts b/src/app/auth/login/login.component.ts
new file mode 100644
index 00000000..b08195d5
--- /dev/null
+++ b/src/app/auth/login/login.component.ts
@@ -0,0 +1,29 @@
+import { Component } from '@angular/core';
+import { AuthService, AuthState } from '../../core/services/auth.service';
+import { ErrorHandlingService } from '../../core/services/error-handling.service';
+import { LoggingService } from '../../core/services/logging.service';
+
+@Component({
+ selector: 'app-auth-login',
+ templateUrl: './login.component.html',
+ styleUrls: ['./login.component.css']
+})
+
+export class LoginComponent {
+ constructor(
+ private authService: AuthService,
+ private errorHandlingService: ErrorHandlingService,
+ private logger: LoggingService
+ ) {}
+
+ startLoginProcess() {
+ this.logger.info('LoginComponent: Beginning login process');
+ try {
+ this.authService.startOAuthProcess();
+ } catch (error) {
+ this.authService.changeAuthState(AuthState.NotAuthenticated);
+ this.errorHandlingService.handleError(error);
+ this.logger.info(`LoginComponent: Login process failed with an error: ${error}`);
+ }
+ }
+}
diff --git a/src/app/auth/session-selection/session-selection.component.ts b/src/app/auth/session-selection/session-selection.component.ts
index 3a71b533..8ba5421a 100644
--- a/src/app/auth/session-selection/session-selection.component.ts
+++ b/src/app/auth/session-selection/session-selection.component.ts
@@ -2,7 +2,7 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Observable } from 'rxjs';
import { Profile } from '../../core/models/profile.model';
-import { AuthService, AuthState } from '../../core/services/auth.service';
+import { AuthService } from '../../core/services/auth.service';
import { ErrorHandlingService } from '../../core/services/error-handling.service';
import { LoggingService } from '../../core/services/logging.service';
import { RepoUrlCacheService } from '../../core/services/repo-url-cache.service';
@@ -78,13 +78,12 @@ export class SessionSelectionComponent implements OnInit {
this.logger.info(`SessionSelectionComponent: Selected Repository: ${repoInformation}`);
- try {
- this.authService.startOAuthProcess();
- } catch (error) {
- this.errorHandlingService.handleError(error);
- this.authService.changeAuthState(AuthState.NotAuthenticated);
- this.isSettingUpSession = false;
- }
+ this.authService.setRepo()
+ .subscribe(
+ (res) => {
+ this.isSettingUpSession = false;
+ }
+ );
}
/**
diff --git a/src/app/core/services/auth.service.ts b/src/app/core/services/auth.service.ts
index b300d9b3..3ab0ec02 100644
--- a/src/app/core/services/auth.service.ts
+++ b/src/app/core/services/auth.service.ts
@@ -2,10 +2,13 @@ import { Injectable } from '@angular/core';
import { NgZone } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { Router } from '@angular/router';
-import { BehaviorSubject } from 'rxjs';
+import { BehaviorSubject, from, Observable, of } from 'rxjs';
+import { catchError, map } from 'rxjs/operators';
import { AppConfig } from '../../../environments/environment';
import { generateSessionId } from '../../shared/lib/session';
import { uuid } from '../../shared/lib/uuid';
+import { Phase } from '../models/phase.model';
+import { ErrorHandlingService } from './error-handling.service';
import { GithubService } from './github.service';
import { GithubEventService } from './githubevent.service';
import { IssueService } from './issue.service';
@@ -47,8 +50,9 @@ export class AuthService {
private phaseService: PhaseService,
private githubEventService: GithubEventService,
private titleService: Title,
+ private errorHandlingService: ErrorHandlingService,
private logger: LoggingService
- ) {}
+ ) {}
/**
* Will store the OAuth token.
@@ -136,6 +140,35 @@ export class AuthService {
this.logger.info(`AuthService: Redirecting for Github authentication`);
}
+ /**
+ * Handles the clean up required after authentication and setting up of repository is completed.
+ */
+ handleSetRepoSuccess() {
+ this.setTitleWithPhaseDetail();
+ this.router.navigateByUrl(Phase.issuesViewer);
+ }
+
+ /**
+ * Setup repository after authentication.
+ */
+ setRepo(): Observable {
+ return from(this.phaseService.initializeCurrentRepository())
+ .pipe(
+ map(() => {
+ if (!this.phaseService.currentRepo) {
+ return false;
+ }
+ this.githubEventService.setLatestChangeEvent();
+ this.handleSetRepoSuccess();
+ return true;
+ }),
+ catchError((error) => {
+ this.errorHandlingService.handleError(error);
+ return of(false);
+ })
+ );
+ }
+
/**
* Will redirect to GitHub OAuth page
*/
diff --git a/src/app/core/services/factories/factory.auth.service.ts b/src/app/core/services/factories/factory.auth.service.ts
index e3cf520d..21476b48 100644
--- a/src/app/core/services/factories/factory.auth.service.ts
+++ b/src/app/core/services/factories/factory.auth.service.ts
@@ -3,6 +3,7 @@ import { Title } from '@angular/platform-browser';
import { Router } from '@angular/router';
// import { AppConfig } from '../../../../environments/environment';
import { AuthService } from '../auth.service';
+import { ErrorHandlingService } from '../error-handling.service';
import { GithubService } from '../github.service';
import { GithubEventService } from '../githubevent.service';
import { IssueService } from '../issue.service';
@@ -22,6 +23,7 @@ export function AuthServiceFactory(
phaseService: PhaseService,
githubEventService: GithubEventService,
titleService: Title,
+ errorHandlingService: ErrorHandlingService,
logger: LoggingService
) {
// TODO: Write Mocks
@@ -50,5 +52,7 @@ export function AuthServiceFactory(
phaseService,
githubEventService,
titleService,
- logger);
+ errorHandlingService,
+ logger
+ );
}
diff --git a/src/app/core/services/github.service.ts b/src/app/core/services/github.service.ts
index 30cf078b..1480ac21 100644
--- a/src/app/core/services/github.service.ts
+++ b/src/app/core/services/github.service.ts
@@ -148,6 +148,8 @@ export class GithubService {
* @returns Observable that returns true if there are pages that do not exist in the cache model.
*/
private toFetchIssues(filter: RestGithubIssueFilter): Observable {
+ const pageFetchLimit = 100;
+
let responseInFirstPage: GithubResponse;
return this.getIssuesAPICall(filter, 1).pipe(
map((response: GithubResponse) => {
@@ -156,6 +158,9 @@ export class GithubService {
}),
flatMap((numOfPages: number) => {
const apiCalls: Observable>[] = [];
+ if (numOfPages > pageFetchLimit) {
+ throw new Error(`Repository has too many pages (${numOfPages}), not supported.`);
+ }
for (let i = 2; i <= numOfPages; i++) {
apiCalls.push(this.getIssuesAPICall(filter, i));
}
diff --git a/src/app/core/services/issue.service.ts b/src/app/core/services/issue.service.ts
index ec9721cf..e1a52022 100644
--- a/src/app/core/services/issue.service.ts
+++ b/src/app/core/services/issue.service.ts
@@ -1,5 +1,5 @@
import { Injectable } from '@angular/core';
-import { BehaviorSubject, EMPTY, Observable, of, Subscription, timer } from 'rxjs';
+import { BehaviorSubject, Observable, of, Subscription, throwError, timer } from 'rxjs';
import { catchError, exhaustMap, finalize, map } from 'rxjs/operators';
import RestGithubIssueFilter from '../models/github/github-issue-filter.model';
import { GithubIssue } from '../models/github/github-issue.model';
@@ -43,9 +43,7 @@ export class IssueService {
.pipe(
exhaustMap(() => {
return this.reloadAllIssues().pipe(
- catchError(() => {
- return EMPTY;
- }),
+ catchError((err) => throwError(err)),
finalize(() => this.isLoading.next(false))
);
})
diff --git a/src/app/core/services/phase.service.ts b/src/app/core/services/phase.service.ts
index 9147593f..4d168f0a 100644
--- a/src/app/core/services/phase.service.ts
+++ b/src/app/core/services/phase.service.ts
@@ -45,6 +45,9 @@ export class PhaseService {
public currentRepo: Repo; // current or main repository of current phase
public otherRepos: Repo[]; // more repositories relevant to this phase
+ repoSetSource = new BehaviorSubject(false);
+ repoSetState = this.repoSetSource.asObservable();
+
/**
* Expose an observable to track changes to currentRepo
*
@@ -58,7 +61,10 @@ export class PhaseService {
public sessionData = STARTING_SESSION_DATA; // stores session data for the session
- constructor(private githubService: GithubService, private repoUrlCacheService: RepoUrlCacheService, public logger: LoggingService) {}
+ constructor(
+ private githubService: GithubService,
+ private repoUrlCacheService: RepoUrlCacheService,
+ public logger: LoggingService) {}
/**
* Sets the current main repository and additional repos if any.
@@ -120,7 +126,7 @@ export class PhaseService {
/**
* Retrieves the repository url from local storage and sets to current repository.
*/
- initializeCurrentRepository() {
+ async initializeCurrentRepository() {
const org = window.localStorage.getItem('org');
const repoName = window.localStorage.getItem('dataRepo');
this.logger.info(`Phase Service: received initial org (${org}) and initial name (${repoName})`);
@@ -130,15 +136,17 @@ export class PhaseService {
} else {
repo = new Repo(org, repoName);
}
+ const isValidRepository = await this.githubService.isRepositoryPresent(repo.owner, repo.name).toPromise();
+ if (!isValidRepository) {
+ throw new Error('Invalid repository name. Please check your organisation and repository name.');
+ }
this.logger.info(`PhaseService: Repo is ${repo}`);
this.setRepository(repo);
+ this.repoSetSource.next(true);
}
- /**
- * Checks if the necessary repository is available. TODO: Future to use to verify setRepository.
- */
- verifySessionAvailability(): Observable {
- return this.githubService.isRepositoryPresent(this.currentRepo.owner, this.currentRepo.name);
+ isRepoSet(): boolean {
+ return this.repoSetSource.getValue();
}
/**
diff --git a/src/app/shared/layout/header.component.html b/src/app/shared/layout/header.component.html
index dc16a9d9..0632a9aa 100644
--- a/src/app/shared/layout/header.component.html
+++ b/src/app/shared/layout/header.component.html
@@ -37,7 +37,7 @@
-
+
{{ this.currentRepo }}
@@ -56,7 +56,7 @@