-
-
- Failed to sign in! Please check your credentials and try again.
-
-
-
-
+
+
+
+
+ Failed to sign in! Please check your credentials and try again.
+
+
+
+
+
+
diff --git a/ui/src/app/account/login/login.component.spec.ts b/ui/src/app/account/login/login.component.spec.ts
index 5add259bd..cbdf3d8b2 100644
--- a/ui/src/app/account/login/login.component.spec.ts
+++ b/ui/src/app/account/login/login.component.spec.ts
@@ -1,9 +1,4 @@
-import {
- ComponentFixture,
- TestBed,
- tick,
- fakeAsync,
-} from '@angular/core/testing'
+import { ComponentFixture, TestBed, tick, fakeAsync } from '@angular/core/testing'
import { LoginComponent } from './login.component'
import { ReactiveFormsModule } from '@angular/forms'
import { RouterTestingModule } from '@angular/router/testing'
@@ -20,17 +15,9 @@ describe('LoginComponent', () => {
let accountService: jasmine.SpyObj
beforeEach(() => {
- const loginServiceSpy = jasmine.createSpyObj('LoginService', [
- 'login',
- 'logout',
- ])
- const stateStorageServiceSpy = jasmine.createSpyObj('StateStorageService', [
- 'getUrl',
- 'storeUrl',
- ])
- const accountServiceSpy = jasmine.createSpyObj('AccountService', [
- 'getAccountData',
- ])
+ const loginServiceSpy = jasmine.createSpyObj('LoginService', ['login', 'logout'])
+ const stateStorageServiceSpy = jasmine.createSpyObj('StateStorageService', ['getUrl', 'storeUrl'])
+ const accountServiceSpy = jasmine.createSpyObj('AccountService', ['getAccountData'])
TestBed.configureTestingModule({
declarations: [LoginComponent],
@@ -45,12 +32,8 @@ describe('LoginComponent', () => {
fixture = TestBed.createComponent(LoginComponent)
component = fixture.componentInstance
loginService = TestBed.inject(LoginService) as jasmine.SpyObj
- stateStorageService = TestBed.inject(
- StateStorageService
- ) as jasmine.SpyObj
- accountService = TestBed.inject(
- AccountService
- ) as jasmine.SpyObj
+ stateStorageService = TestBed.inject(StateStorageService) as jasmine.SpyObj
+ accountService = TestBed.inject(AccountService) as jasmine.SpyObj
})
it('should create', () => {
diff --git a/ui/src/app/account/login/login.component.ts b/ui/src/app/account/login/login.component.ts
index 54f7e7630..edca1cc51 100644
--- a/ui/src/app/account/login/login.component.ts
+++ b/ui/src/app/account/login/login.component.ts
@@ -1,32 +1,31 @@
-import { AfterViewInit, Component, OnDestroy, Renderer2 } from '@angular/core';
-import { FormBuilder } from '@angular/forms';
-import { Router } from '@angular/router';
-import { AccountService } from '../service/account.service';
-import { LoginService } from '../service/login.service';
-import { StateStorageService } from '../service/state-storage.service';
-import { Subscription, filter, take } from 'rxjs';
-import { EventService } from 'src/app/shared/service/event.service';
-import { EventType } from 'src/app/app.constants';
-import { Event } from 'src/app/shared/model/event.model';
-
+import { AfterViewInit, Component, OnDestroy, Renderer2 } from '@angular/core'
+import { FormBuilder } from '@angular/forms'
+import { Router } from '@angular/router'
+import { AccountService } from '../service/account.service'
+import { LoginService } from '../service/login.service'
+import { StateStorageService } from '../service/state-storage.service'
+import { Subscription, filter, take } from 'rxjs'
+import { EventService } from 'src/app/shared/service/event.service'
+import { EventType } from 'src/app/app.constants'
+import { Event } from 'src/app/shared/model/event.model'
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
- styleUrls: ['./login.component.scss']
+ styleUrls: ['./login.component.scss'],
})
export class LoginComponent implements AfterViewInit, OnDestroy {
- authenticationError = false;
- showMfa = false;
- mfaSent = false;
- mfaError = false;
- sub: Subscription | undefined;
+ authenticationError = false
+ showMfa = false
+ mfaSent = false
+ mfaError = false
+ sub: Subscription | undefined
loginForm = this.fb.group({
username: [''],
password: [''],
- mfaCode: ['']
- });
+ mfaCode: [''],
+ })
constructor(
private loginService: LoginService,
@@ -37,98 +36,95 @@ export class LoginComponent implements AfterViewInit, OnDestroy {
private fb: FormBuilder,
private eventService: EventService
) {
- this.sub = this.eventService.on(EventType.LOG_IN_SUCCESS).subscribe(e => {
- console.log(e.payload);
+ this.sub = this.eventService.on(EventType.LOG_IN_SUCCESS).subscribe((e) => {
+ console.log(e.payload)
})
- }
+ }
- ngOnDestroy(): void {
- this.sub?.unsubscribe();
- console.log('test')
- }
+ ngOnDestroy(): void {
+ this.sub?.unsubscribe()
+ console.log('test')
+ }
ngAfterViewInit() {
- setTimeout(() => this.renderer.selectRootElement('#username').scrollIntoView());
+ setTimeout(() => this.renderer.selectRootElement('#username').scrollIntoView())
}
cancel() {
- this.authenticationError = false;
+ this.authenticationError = false
this.loginForm.patchValue({
username: '',
password: '',
- mfaCode: ''
- });
+ mfaCode: '',
+ })
}
login() {
- this.mfaError = false;
- const mfaCode = this.loginForm.get('mfaCode')?.value;
+ this.mfaError = false
+ const mfaCode = this.loginForm.get('mfaCode')?.value
if (this.showMfa && !mfaCode) {
- this.mfaError = true;
+ this.mfaError = true
} else {
if (mfaCode) {
- this.mfaSent = true;
+ this.mfaSent = true
}
this.loginService
.login({
- username: this.loginForm.get('username')?.value!,
- password: this.loginForm.get('password')?.value!,
- mfaCode: this.loginForm.get('mfaCode')?.value
+ username: this.loginForm.get('username')!.value!,
+ password: this.loginForm.get('password')!.value!,
+ mfaCode: this.loginForm.get('mfaCode')?.value,
})
- .subscribe(
- {
- next: (data) => {
- if (!data.mfaRequired) {
- this.showMfa = false;
- this.accountService.getAccountData().pipe(filter((account) => !!account), take(1)).subscribe((account) => {
+ .subscribe({
+ next: (data) => {
+ if (!data.mfaRequired) {
+ this.showMfa = false
+ this.accountService
+ .getAccountData()
+ .pipe(
+ filter((account) => !!account),
+ take(1)
+ )
+ .subscribe((account) => {
// TODO: remove after sprint review
- console.log("Login successful, account data:", account);
- this.loginSuccess();
- });
- } else {
- this.showMfa = true;
- this.mfaError = this.mfaSent;
- }
- this.mfaSent = false;
- },
- // TODO: review any type
- error: err => {
- this.loginService.logout();
- this.authenticationError = true;
+ console.log('Login successful, account data:', account)
+ this.loginSuccess()
+ })
+ } else {
+ this.showMfa = true
+ this.mfaError = this.mfaSent
}
- }
- );
+ this.mfaSent = false
+ },
+ // TODO: review any type
+ error: (err) => {
+ this.loginService.logout()
+ this.authenticationError = true
+ },
+ })
}
}
loginSuccess(): void {
- this.router.navigate(['']);
+ this.router.navigate([''])
- this.eventService.broadcast(new Event(EventType.LOG_IN_SUCCESS, "logged in"))
- // TODO: Event manager
- /* this.eventManager.broadcast({
- name: 'authenticationSuccess',
- content: 'Sending Authentication Success'
- }); */
+ this.eventService.broadcast(new Event(EventType.LOG_IN_SUCCESS, 'logged in'))
// previousState was set in the authExpiredInterceptor before being redirected to login modal.
// since login is successful, go to stored previousState and clear previousState
- const redirect = this.stateStorageService.getUrl();
+ const redirect = this.stateStorageService.getUrl()
if (redirect) {
- this.stateStorageService.storeUrl(null);
- this.router.navigateByUrl(redirect);
+ this.stateStorageService.storeUrl(null)
+ this.router.navigateByUrl(redirect)
}
}
register() {
- this.router.navigate(['/register']);
+ this.router.navigate(['/register'])
}
requestResetPassword() {
- this.router.navigate(['/reset', 'request']);
+ this.router.navigate(['/reset', 'request'])
}
-
}
-
diff --git a/ui/src/app/account/model/account.model.ts b/ui/src/app/account/model/account.model.ts
index a367bfe03..86497e547 100644
--- a/ui/src/app/account/model/account.model.ts
+++ b/ui/src/app/account/model/account.model.ts
@@ -1,15 +1,14 @@
export interface IAccount {
- activated: boolean,
- authorities: string[],
- email: string,
- firstName: string,
- langKey: string,
- lastName: string,
- imageUrl: string,
- salesforceId: string,
- loggedAs: boolean,
- loginAs: string,
- mainContact: boolean,
- mfaEnabled: boolean
- }
-
\ No newline at end of file
+ activated: boolean
+ authorities: string[]
+ email: string
+ firstName: string
+ langKey: string
+ lastName: string
+ imageUrl: string
+ salesforceId: string
+ loggedAs: boolean
+ loginAs: string
+ mainContact: boolean
+ mfaEnabled: boolean
+}
diff --git a/ui/src/app/account/model/login.model.ts b/ui/src/app/account/model/login.model.ts
index f8bd80aa6..4a6d7b6b7 100644
--- a/ui/src/app/account/model/login.model.ts
+++ b/ui/src/app/account/model/login.model.ts
@@ -1,10 +1,10 @@
export interface ILoginResult {
- mfaRequired: boolean;
- oauth2AccessToken?: any;
+ mfaRequired: boolean
+ oauth2AccessToken?: any
}
export interface ILoginCredentials {
- username?: string;
- password?: string;
- mfaCode?: string | null;
-}
\ No newline at end of file
+ username: string
+ password: string
+ mfaCode?: string | null
+}
diff --git a/ui/src/app/account/service/account.service.ts b/ui/src/app/account/service/account.service.ts
index 9ee2b29f5..fa6f22562 100644
--- a/ui/src/app/account/service/account.service.ts
+++ b/ui/src/app/account/service/account.service.ts
@@ -1,17 +1,7 @@
import { Injectable } from '@angular/core'
import { SessionStorageService } from 'ngx-webstorage'
import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http'
-import {
- BehaviorSubject,
- EMPTY,
- Observable,
- Subject,
- catchError,
- map,
- of,
- takeUntil,
- tap,
-} from 'rxjs'
+import { BehaviorSubject, EMPTY, Observable, Subject, catchError, map, of, takeUntil, tap } from 'rxjs'
import { SERVER_API_URL } from '../../../app/app.constants'
import { IAccount } from '../model/account.model'
@@ -20,12 +10,12 @@ import { IAccount } from '../model/account.model'
@Injectable({ providedIn: 'root' })
export class AccountService {
- private accountData = new BehaviorSubject(undefined);
- private isFetchingAccountData = false;
- private stopFetchingAccountData = new Subject();
- private authenticated = false;
- private authenticationState = new BehaviorSubject(null);
- private logoutAsResourceUrl = SERVER_API_URL + 'services/userservice/api';
+ private accountData = new BehaviorSubject(undefined)
+ private isFetchingAccountData = false
+ private stopFetchingAccountData = new Subject()
+ private authenticated = false
+ private authenticationState = new BehaviorSubject(null)
+ private logoutAsResourceUrl = SERVER_API_URL + 'services/userservice/api'
constructor(
// TODO: uncomment when language service is implemented
@@ -44,10 +34,10 @@ export class AccountService {
.pipe(
takeUntil(this.stopFetchingAccountData),
catchError((err) => {
- this.accountData.next(undefined)
+ this.authenticated = false
+ this.accountData.next(null)
// TODO: uncomment when memberservice is added or change the account service so that this logic is absent from the account service
//this.memberService.memberData.next(undefined);
- this.authenticated = false
this.authenticationState.next(this.accountData)
this.isFetchingAccountData = false
return EMPTY
@@ -56,22 +46,21 @@ export class AccountService {
this.isFetchingAccountData = false
this.authenticationState.next(this.accountData)
if (response && response.body) {
+ this.authenticated = true
const account: IAccount = response.body
this.accountData.next(account)
- this.authenticated = true
+
// After retrieve the account info, the language will be changed to
// the user's preferred language configured in the account setting
if (this.accountData.value?.langKey) {
- const langKey =
- this.sessionStorage.retrieve('locale') ||
- this.accountData.value.langKey
+ const langKey = this.sessionStorage.retrieve('locale') || this.accountData.value.langKey
// TODO: uncomment when language service is implemented
//this.languageService.changeLanguage(langKey);
}
} else {
// TODO: uncomment when memberservice is added or change the account service so that this logic is absent from the account service
//this.memberService.memberData.next(undefined);
- this.accountData.next(undefined)
+ this.accountData.next(null)
this.authenticated = false
console.error('Invalid response:', response)
}
@@ -80,34 +69,19 @@ export class AccountService {
}
getMfaSetup(): Observable> {
- return this.http.get(
- SERVER_API_URL + 'services/userservice/api/account/mfa',
- { observe: 'response' }
- )
+ return this.http.get(SERVER_API_URL + 'services/userservice/api/account/mfa', { observe: 'response' })
}
save(account: any): Observable> {
- return this.http.post(
- SERVER_API_URL + 'services/userservice/api/account',
- account,
- { observe: 'response' }
- )
+ return this.http.post(SERVER_API_URL + 'services/userservice/api/account', account, { observe: 'response' })
}
enableMfa(mfaSetup: any): Observable> {
- return this.http.post(
- SERVER_API_URL + 'services/userservice/api/account/mfa/on',
- mfaSetup,
- { observe: 'response' }
- )
+ return this.http.post(SERVER_API_URL + 'services/userservice/api/account/mfa/on', mfaSetup, { observe: 'response' })
}
disableMfa(): Observable> {
- return this.http.post(
- SERVER_API_URL + 'services/userservice/api/account/mfa/off',
- null,
- { observe: 'response' }
- )
+ return this.http.post(SERVER_API_URL + 'services/userservice/api/account/mfa/off', null, { observe: 'response' })
}
// TODO: any - this seems to only be used for logging out (only ever receives null as arg)
authenticate(identity: any) {
@@ -117,11 +91,7 @@ export class AccountService {
}
hasAnyAuthority(authorities: string[]): boolean {
- if (
- !this.authenticated ||
- !this.accountData ||
- !this.accountData.value?.authorities
- ) {
+ if (!this.authenticated || !this.accountData || !this.accountData.value?.authorities) {
return false
}
@@ -138,19 +108,16 @@ export class AccountService {
if (!this.authenticated) {
return false
} else {
- return (
- this.accountData.value!.authorities &&
- this.accountData.value!.authorities.includes(authority)
- )
+ return this.accountData.value!.authorities && this.accountData.value!.authorities.includes(authority)
}
}
- getAccountData(force?: boolean): Observable {
+ getAccountData(force?: boolean): Observable {
if (force) {
- // TODO: uncomment when memberservice is added or change the account service so that this logic is absent from the account service
+ // TODO: uncomment when memberservice is added or change the account service so that this logic is absent from the account service
//this.memberService.stopFetchingMemberData.next();
//this.memberService.memberData.next(undefined);
- this.stopFetchingAccountData.next(true);
+ this.stopFetchingAccountData.next(true)
}
if ((!this.accountData.value && !this.isFetchingAccountData) || force) {
this.isFetchingAccountData = true
@@ -198,15 +165,11 @@ export class AccountService {
}
getSalesforceId(): string | null {
- return this.isAuthenticated() && this.accountData
- ? this.accountData.value!.salesforceId
- : null
+ return this.isAuthenticated() && this.accountData ? this.accountData.value!.salesforceId : null
}
isOrganizationOwner(): boolean | null {
- return this.isIdentityResolved() && this.accountData
- ? this.accountData.value!.mainContact
- : false
+ return this.isIdentityResolved() && this.accountData ? this.accountData.value!.mainContact : false
}
isLoggedAs(): boolean {
diff --git a/ui/src/app/account/service/auth-jwt.service.ts b/ui/src/app/account/service/auth-jwt.service.ts
index 53339386c..20c97d88d 100644
--- a/ui/src/app/account/service/auth-jwt.service.ts
+++ b/ui/src/app/account/service/auth-jwt.service.ts
@@ -1,24 +1,24 @@
-import { Injectable } from '@angular/core';
-import { HttpClient, HttpResponse } from '@angular/common/http';
-import { Observable } from 'rxjs';
+import { Injectable } from '@angular/core'
+import { HttpClient, HttpResponse } from '@angular/common/http'
+import { Observable } from 'rxjs'
-import { SERVER_API_URL } from '../../../app/app.constants';
-import { ILoginCredentials, ILoginResult } from '../model/login.model';
+import { SERVER_API_URL } from '../../../app/app.constants'
+import { ILoginCredentials, ILoginResult } from '../model/login.model'
@Injectable({ providedIn: 'root' })
export class AuthServerProvider {
constructor(private http: HttpClient) {}
getToken() {
- return null;
+ return null
}
- login(credentials: ILoginCredentials): Observable {
- return this.http.post('/auth/login', credentials);
+ login(credentials: ILoginCredentials): Observable {
+ return this.http.post('/auth/login', credentials)
}
// TODO: not being used?
-/* loginWithToken(jwt, rememberMe) {
+ /* loginWithToken(jwt, rememberMe) {
if (jwt) {
this.storeAuthenticationToken(jwt, rememberMe);
return Promise.resolve(jwt);
@@ -31,6 +31,6 @@ export class AuthServerProvider {
*/
logout(): Observable {
- return this.http.post(SERVER_API_URL + 'auth/logout', null);
+ return this.http.post(SERVER_API_URL + 'auth/logout', null)
}
}
diff --git a/ui/src/app/account/service/login.service.ts b/ui/src/app/account/service/login.service.ts
index c6ed69f1b..b3162785e 100644
--- a/ui/src/app/account/service/login.service.ts
+++ b/ui/src/app/account/service/login.service.ts
@@ -1,30 +1,33 @@
-import { Injectable } from '@angular/core';
-import { AccountService } from './account.service';
-import { AuthServerProvider } from './auth-jwt.service';
-import { Observable } from 'rxjs';
-import { ILoginCredentials, ILoginResult } from '../model/login.model';
+import { Injectable } from '@angular/core'
+import { AccountService } from './account.service'
+import { AuthServerProvider } from './auth-jwt.service'
+import { Observable } from 'rxjs'
+import { ILoginCredentials, ILoginResult } from '../model/login.model'
@Injectable({ providedIn: 'root' })
export class LoginService {
- constructor(private accountService: AccountService, private authServerProvider: AuthServerProvider) {}
+ constructor(
+ private accountService: AccountService,
+ private authServerProvider: AuthServerProvider
+ ) {}
login(credentials: ILoginCredentials): Observable {
- return this.authServerProvider.login(credentials);
+ return this.authServerProvider.login(credentials)
}
isAuthenticated() {
- return this.accountService.isAuthenticated();
+ return this.accountService.isAuthenticated()
}
logoutDirectly() {
- this.accountService.authenticate(null);
+ this.accountService.authenticate(null)
}
logout() {
if (this.accountService.isAuthenticated()) {
- this.authServerProvider.logout().subscribe(() => this.accountService.authenticate(null));
+ this.authServerProvider.logout().subscribe(() => this.accountService.authenticate(null))
} else {
- this.accountService.authenticate(null);
+ this.accountService.authenticate(null)
}
}
}
diff --git a/ui/src/app/account/service/state-storage.service.ts b/ui/src/app/account/service/state-storage.service.ts
index dc12e667b..c0877e46d 100644
--- a/ui/src/app/account/service/state-storage.service.ts
+++ b/ui/src/app/account/service/state-storage.service.ts
@@ -1,38 +1,38 @@
-import { Injectable } from '@angular/core';
-import { SessionStorageService } from 'ngx-webstorage';
+import { Injectable } from '@angular/core'
+import { SessionStorageService } from 'ngx-webstorage'
@Injectable({ providedIn: 'root' })
export class StateStorageService {
constructor(private $sessionStorage: SessionStorageService) {}
getPreviousState() {
- return this.$sessionStorage.retrieve('previousState');
+ return this.$sessionStorage.retrieve('previousState')
}
resetPreviousState() {
- this.$sessionStorage.clear('previousState');
+ this.$sessionStorage.clear('previousState')
}
// TODO: not being used?
- /* storePreviousState(previousStateName, previousStateParams) {
+ /* storePreviousState(previousStateName, previousStateParams) {
const previousState = { name: previousStateName, params: previousStateParams };
this.$sessionStorage.store('previousState', previousState);
} */
getDestinationState() {
- return this.$sessionStorage.retrieve('destinationState');
+ return this.$sessionStorage.retrieve('destinationState')
}
storeUrl(url: string | null) {
- this.$sessionStorage.store('previousUrl', url);
+ this.$sessionStorage.store('previousUrl', url)
}
getUrl() {
- return this.$sessionStorage.retrieve('previousUrl');
+ return this.$sessionStorage.retrieve('previousUrl')
}
// TODO: not being used?
-/* storeDestinationState(destinationState, destinationStateParams, fromState) {
+ /* storeDestinationState(destinationState, destinationStateParams, fromState) {
const destinationInfo = {
destination: {
name: destinationState.name,
diff --git a/ui/src/app/app-routing.module.ts b/ui/src/app/app-routing.module.ts
index c6ffe6c72..07f851645 100644
--- a/ui/src/app/app-routing.module.ts
+++ b/ui/src/app/app-routing.module.ts
@@ -1,17 +1,20 @@
-import { NgModule } from '@angular/core';
-import { RouterModule, Routes } from '@angular/router';
-import { navbarRoute } from './layout/navbar/navbar.route';
+import { NgModule } from '@angular/core'
+import { RouterModule, Routes } from '@angular/router'
+import { navbarRoute } from './layout/navbar/navbar.route'
const routes: Routes = [
{
path: '',
- loadChildren: () =>
- import('./account/account.module').then(m => m.AccountModule)
- }
-]
+ loadChildren: () => import('./account/account.module').then((m) => m.AccountModule),
+ },
+ {
+ path: '',
+ loadChildren: () => import('./home/home.module').then((m) => m.HomeModule),
+ },
+]
@NgModule({
imports: [RouterModule.forRoot([...routes, navbarRoute])],
- exports: [RouterModule]
+ exports: [RouterModule],
})
-export class AppRoutingModule { }
+export class AppRoutingModule {}
diff --git a/ui/src/app/app.component.html b/ui/src/app/app.component.html
index 6c24876e4..79070ce79 100644
--- a/ui/src/app/app.component.html
+++ b/ui/src/app/app.component.html
@@ -1,2 +1 @@
-
-
\ No newline at end of file
+
diff --git a/ui/src/app/app.component.spec.ts b/ui/src/app/app.component.spec.ts
index c27c5baf3..d84f08c36 100644
--- a/ui/src/app/app.component.spec.ts
+++ b/ui/src/app/app.component.spec.ts
@@ -1,26 +1,21 @@
-import { TestBed } from '@angular/core/testing';
-import { RouterTestingModule } from '@angular/router/testing';
-import { HttpClientTestingModule } from '@angular/common/http/testing';
-import { AppComponent } from './app.component';
+import { TestBed } from '@angular/core/testing'
+import { RouterTestingModule } from '@angular/router/testing'
+import { HttpClientTestingModule } from '@angular/common/http/testing'
+import { AppComponent } from './app.component'
describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
- imports: [
- RouterTestingModule,
- HttpClientTestingModule
- ],
- declarations: [
- AppComponent
- ],
- }).compileComponents();
- });
+ imports: [RouterTestingModule, HttpClientTestingModule],
+ declarations: [AppComponent],
+ }).compileComponents()
+ })
it('should create the app', () => {
- const fixture = TestBed.createComponent(AppComponent);
- const app = fixture.componentInstance;
- expect(app).toBeTruthy();
- });
+ const fixture = TestBed.createComponent(AppComponent)
+ const app = fixture.componentInstance
+ expect(app).toBeTruthy()
+ })
it(`should have as title 'ui'`, () => {
const fixture = TestBed.createComponent(AppComponent);
@@ -28,5 +23,4 @@ describe('AppComponent', () => {
expect(app.title).toEqual('ui');
});
-
});
diff --git a/ui/src/app/app.component.ts b/ui/src/app/app.component.ts
index 707777495..d30ceb763 100644
--- a/ui/src/app/app.component.ts
+++ b/ui/src/app/app.component.ts
@@ -1,17 +1,12 @@
-import { Component } from '@angular/core';
-import { HttpClient } from '@angular/common/http';
+import { Component } from '@angular/core'
+import { HttpClient } from '@angular/common/http'
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
- styleUrls: ['./app.component.scss']
+ styleUrls: ['./app.component.scss'],
})
export class AppComponent {
title = 'ui';
-
- constructor(
- private http: HttpClient
- ) {}
-
-
+ constructor(private http: HttpClient) {}
}
diff --git a/ui/src/app/app.constants.ts b/ui/src/app/app.constants.ts
index 4b69d5677..4455bce9b 100644
--- a/ui/src/app/app.constants.ts
+++ b/ui/src/app/app.constants.ts
@@ -1,10 +1,10 @@
-export const SERVER_API_URL = 'http://localhost:4200';
+export const SERVER_API_URL = 'http://localhost:4200'
-export const VERSION = "test-ui";
+export const VERSION = 'test-ui'
export enum EventType {
- LOG_IN_SUCCESS = "LOG_IN_SUCCESS",
- AFFILIATION_CREATED = "AFFILIATION_CREATED",
- AFFILIATION_UPDATED = "AFFILIATION_UPDATED"
- // add as we go
-}
\ No newline at end of file
+ LOG_IN_SUCCESS = 'LOG_IN_SUCCESS',
+ AFFILIATION_CREATED = 'AFFILIATION_CREATED',
+ AFFILIATION_UPDATED = 'AFFILIATION_UPDATED',
+ // add as we go
+}
diff --git a/ui/src/app/app.module.ts b/ui/src/app/app.module.ts
index db97c9597..7ec8d09c2 100644
--- a/ui/src/app/app.module.ts
+++ b/ui/src/app/app.module.ts
@@ -11,12 +11,14 @@ import { NavbarComponent } from './layout/navbar/navbar.component'
import { CommonModule } from '@angular/common'
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
import { HasAnyAuthorityDirective } from './shared/directive/has-any-authority.directive'
+import { HomeModule } from './home/home.module'
@NgModule({
declarations: [AppComponent, NavbarComponent, HasAnyAuthorityDirective],
imports: [
FontAwesomeModule,
AccountModule,
+ HomeModule,
BrowserModule,
HttpClientModule,
AppRoutingModule,
diff --git a/ui/src/app/home/home.component.html b/ui/src/app/home/home.component.html
new file mode 100644
index 000000000..5f2c53ffd
--- /dev/null
+++ b/ui/src/app/home/home.component.html
@@ -0,0 +1 @@
+home works!
diff --git a/ui/src/app/home/home.component.scss b/ui/src/app/home/home.component.scss
new file mode 100644
index 000000000..e69de29bb
diff --git a/ui/src/app/home/home.component.spec.ts b/ui/src/app/home/home.component.spec.ts
new file mode 100644
index 000000000..55d817b9d
--- /dev/null
+++ b/ui/src/app/home/home.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing'
+
+import { HomeComponent } from './home.component'
+
+describe('HomeComponent', () => {
+ let component: HomeComponent
+ let fixture: ComponentFixture
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [HomeComponent],
+ })
+ fixture = TestBed.createComponent(HomeComponent)
+ component = fixture.componentInstance
+ fixture.detectChanges()
+ })
+
+ it('should create', () => {
+ expect(component).toBeTruthy()
+ })
+})
diff --git a/ui/src/app/home/home.component.ts b/ui/src/app/home/home.component.ts
new file mode 100644
index 000000000..68fb47086
--- /dev/null
+++ b/ui/src/app/home/home.component.ts
@@ -0,0 +1,8 @@
+import { Component } from '@angular/core'
+
+@Component({
+ selector: 'app-home',
+ templateUrl: './home.component.html',
+ styleUrls: ['./home.component.scss'],
+})
+export class HomeComponent {}
diff --git a/ui/src/app/home/home.module.ts b/ui/src/app/home/home.module.ts
new file mode 100644
index 000000000..fdf6e1f58
--- /dev/null
+++ b/ui/src/app/home/home.module.ts
@@ -0,0 +1,11 @@
+import { NgModule } from '@angular/core'
+import { CommonModule } from '@angular/common'
+import { RouterModule } from '@angular/router'
+import { routes } from './home.route'
+import { HomeComponent } from './home.component'
+
+@NgModule({
+ declarations: [HomeComponent],
+ imports: [CommonModule, RouterModule.forChild(routes)],
+})
+export class HomeModule {}
diff --git a/ui/src/app/home/home.route.ts b/ui/src/app/home/home.route.ts
new file mode 100644
index 000000000..811895f76
--- /dev/null
+++ b/ui/src/app/home/home.route.ts
@@ -0,0 +1,15 @@
+import { Routes } from '@angular/router'
+import { HomeComponent } from '../home/home.component'
+import { AuthGuard } from '../account/auth.guard'
+
+export const routes: Routes = [
+ {
+ path: '',
+ component: HomeComponent,
+ data: {
+ authorities: ['ROLE_USER'],
+ pageTitle: 'home.title.string',
+ },
+ canActivate: [AuthGuard],
+ },
+]
diff --git a/ui/src/app/layout/navbar/navbar.component.html b/ui/src/app/layout/navbar/navbar.component.html
index 285425d67..17ff32a78 100644
--- a/ui/src/app/layout/navbar/navbar.component.html
+++ b/ui/src/app/layout/navbar/navbar.component.html
@@ -1,157 +1,269 @@
-
-
{{ this.getUserName()}} |
-
- {{ this.getUserName() }}
-
-
+
+
+
+
{{ this.getUserName() }} |
+ {{ this.getUserName() }}
+
+
diff --git a/ui/src/app/layout/navbar/navbar.component.ts b/ui/src/app/layout/navbar/navbar.component.ts
index 873c87991..32dd491b2 100644
--- a/ui/src/app/layout/navbar/navbar.component.ts
+++ b/ui/src/app/layout/navbar/navbar.component.ts
@@ -11,7 +11,7 @@ import {
faUserPlus,
faSignOutAlt,
faWrench,
- faLock
+ faLock,
} from '@fortawesome/free-solid-svg-icons'
import { HttpResponse, HttpErrorResponse } from '@angular/common/http'
import { Observable } from 'rxjs'
@@ -26,11 +26,12 @@ type EntityResponseType = HttpResponse
@Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
- styleUrls: ['navbar.scss'],
+ styleUrls: ['./navbar.scss'],
})
export class NavbarComponent implements OnInit {
isNavbarCollapsed: boolean
version: string
+
organizationName: string | undefined
account: IAccount | undefined
userName: string | undefined
@@ -61,11 +62,7 @@ export class NavbarComponent implements OnInit {
ngOnInit() {
this.accountService.getAuthenticationState().subscribe(() => {
- if (
- !this.memberCallDone &&
- this.isAuthenticated() &&
- this.hasRoleUser()
- ) {
+ if (!this.memberCallDone && this.isAuthenticated() && this.hasRoleUser()) {
this.memberCallDone = true
const salesforceId = this.accountService.getSalesforceId()
diff --git a/ui/src/app/layout/navbar/navbar.route.ts b/ui/src/app/layout/navbar/navbar.route.ts
index 35191434e..c6a25f3ec 100644
--- a/ui/src/app/layout/navbar/navbar.route.ts
+++ b/ui/src/app/layout/navbar/navbar.route.ts
@@ -1,9 +1,9 @@
-import { Route } from '@angular/router';
+import { Route } from '@angular/router'
-import { NavbarComponent } from './navbar.component';
+import { NavbarComponent } from './navbar.component'
export const navbarRoute: Route = {
path: '',
component: NavbarComponent,
- outlet: 'navbar'
-};
+ outlet: 'navbar',
+}
diff --git a/ui/src/app/member/model/member.model.ts b/ui/src/app/member/model/member.model.ts
index a1e03049b..558306881 100644
--- a/ui/src/app/member/model/member.model.ts
+++ b/ui/src/app/member/model/member.model.ts
@@ -1,22 +1,22 @@
-import { Moment } from 'moment';
+import { Moment } from 'moment'
export interface IMember {
- id?: string;
- clientId?: string;
- clientName?: string;
- clientSecret?: string;
- salesforceId?: string;
- parentSalesforceId?: string;
- isConsortiumLead?: boolean;
- superadminEnabled?: boolean;
- assertionServiceEnabled?: boolean;
- createdBy?: string;
- createdDate?: Moment;
- lastModifiedBy?: string;
- lastModifiedDate?: Moment;
- type?: string;
- status?: string;
- defaultLanguage?: string;
+ id?: string
+ clientId?: string
+ clientName?: string
+ clientSecret?: string
+ salesforceId?: string
+ parentSalesforceId?: string
+ isConsortiumLead?: boolean
+ superadminEnabled?: boolean
+ assertionServiceEnabled?: boolean
+ createdBy?: string
+ createdDate?: Moment
+ lastModifiedBy?: string
+ lastModifiedDate?: Moment
+ type?: string
+ status?: string
+ defaultLanguage?: string
}
export class Member implements IMember {
@@ -38,8 +38,8 @@ export class Member implements IMember {
public status?: string,
public defaultLaungage?: string
) {
- this.isConsortiumLead = this.isConsortiumLead || false;
- this.superadminEnabled = this.superadminEnabled || false;
- this.assertionServiceEnabled = this.assertionServiceEnabled || false;
+ this.isConsortiumLead = this.isConsortiumLead || false
+ this.superadminEnabled = this.superadminEnabled || false
+ this.assertionServiceEnabled = this.assertionServiceEnabled || false
}
}
diff --git a/ui/src/app/member/model/salesforce-address.model.ts b/ui/src/app/member/model/salesforce-address.model.ts
index 4ef5c4ffb..82e181f7a 100644
--- a/ui/src/app/member/model/salesforce-address.model.ts
+++ b/ui/src/app/member/model/salesforce-address.model.ts
@@ -1,11 +1,11 @@
export interface ISFAddress {
- city?: string;
- country?: string;
- countryCode?: string;
- postalCode?: string;
- state?: string;
- stateCode?: string;
- street?: string;
+ city?: string
+ country?: string
+ countryCode?: string
+ postalCode?: string
+ state?: string
+ stateCode?: string
+ street?: string
}
export class SFAddress implements ISFAddress {
diff --git a/ui/src/app/member/model/salesforce-country.model copy.ts b/ui/src/app/member/model/salesforce-country.model copy.ts
index 0f0ab25c8..d0d49afd3 100644
--- a/ui/src/app/member/model/salesforce-country.model copy.ts
+++ b/ui/src/app/member/model/salesforce-country.model copy.ts
@@ -1,8 +1,11 @@
export interface ISFState {
- code: string;
- name: string;
+ code: string
+ name: string
}
export class SFState implements ISFState {
- constructor(public code: string, public name: string) {}
+ constructor(
+ public code: string,
+ public name: string
+ ) {}
}
diff --git a/ui/src/app/member/model/salesforce-country.model.ts b/ui/src/app/member/model/salesforce-country.model.ts
index 46ddee0fb..bd4085f45 100644
--- a/ui/src/app/member/model/salesforce-country.model.ts
+++ b/ui/src/app/member/model/salesforce-country.model.ts
@@ -1,11 +1,15 @@
-import { ISFState } from './salesforce-country.model copy';
+import { ISFState } from './salesforce-country.model copy'
export interface ISFCountry {
- code: string;
- name: string;
- states?: ISFState[];
+ code: string
+ name: string
+ states?: ISFState[]
}
export class SFCountry implements ISFCountry {
- constructor(public code: string, public name: string, public states?: ISFState[]) {}
+ constructor(
+ public code: string,
+ public name: string,
+ public states?: ISFState[]
+ ) {}
}
diff --git a/ui/src/app/member/model/salesforce-member-contact.model.ts b/ui/src/app/member/model/salesforce-member-contact.model.ts
index 7b8bde6eb..1bf2a10a6 100644
--- a/ui/src/app/member/model/salesforce-member-contact.model.ts
+++ b/ui/src/app/member/model/salesforce-member-contact.model.ts
@@ -1,26 +1,26 @@
export interface ISFMemberContact {
- memberId?: string;
- votingContant?: boolean;
- memberOrgRole?: string[];
- name?: string;
- contactEmail?: string;
- title?: string;
- phone?: string;
+ memberId?: string
+ votingContant?: boolean
+ memberOrgRole?: string[]
+ name?: string
+ contactEmail?: string
+ title?: string
+ phone?: string
}
export interface ISFRawMemberContact {
- Organization__c?: string;
- Voting_Contact__c?: boolean;
- Contact_Curr_Email__c?: string;
- Member_Org_Role__c?: string;
- Name?: string;
- Title?: string;
- Phone?: string;
+ Organization__c?: string
+ Voting_Contact__c?: boolean
+ Contact_Curr_Email__c?: string
+ Member_Org_Role__c?: string
+ Name?: string
+ Title?: string
+ Phone?: string
}
export interface ISFRawMemberContacts {
- size?: number;
- records?: ISFRawMemberContact[];
+ size?: number
+ records?: ISFRawMemberContact[]
}
export class SFMemberContact implements ISFMemberContact {
@@ -33,19 +33,19 @@ export class SFMemberContact implements ISFMemberContact {
public title?: string,
public phone?: string
) {
- this.memberOrgRole = [];
+ this.memberOrgRole = []
}
}
export class ISFMemberContactUpdate {
- contactName?: string;
- contactEmail?: string;
- contactMember?: string;
- contactNewName?: string;
- contactNewEmail?: string;
- contactNewJobTitle?: string;
- contactNewPhone?: string;
- contactNewRoles?: string[];
+ contactName?: string
+ contactEmail?: string
+ contactMember?: string
+ contactNewName?: string
+ contactNewEmail?: string
+ contactNewJobTitle?: string
+ contactNewPhone?: string
+ contactNewRoles?: string[]
}
export class SFMemberContactUpdate implements ISFMemberContactUpdate {
diff --git a/ui/src/app/member/model/salesforce-member-data.model.ts b/ui/src/app/member/model/salesforce-member-data.model.ts
index 81be087bb..e4ae9ca17 100644
--- a/ui/src/app/member/model/salesforce-member-data.model.ts
+++ b/ui/src/app/member/model/salesforce-member-data.model.ts
@@ -1,68 +1,68 @@
-import { ISFAddress } from './salesforce-address.model';
-import { ISFMemberContact } from './salesforce-member-contact.model';
-import { ISFMemberOrgIds } from './salesforce-member-org-id.model';
+import { ISFAddress } from './salesforce-address.model'
+import { ISFMemberContact } from './salesforce-member-contact.model'
+import { ISFMemberOrgIds } from './salesforce-member-org-id.model'
export interface ISFMemberData {
- id?: string;
- consortiaMember?: boolean;
- consortiaLeadId?: string;
- isConsortiumLead?: boolean;
- name?: string;
- publicDisplayName?: string;
- website?: string;
- billingCountry?: string;
- memberType?: string;
- publicDisplayDescriptionHtml?: string;
- logoUrl?: string;
- publicDisplayEmail?: string;
- membershipStartDateString?: string;
- membershipEndDateString?: string;
- consortiumLeadName?: string;
- consortiumMembers?: ISFConsortiumMemberData[];
- contacts?: ISFMemberContact[];
- orgIds?: ISFMemberOrgIds;
- billingAddress?: ISFAddress;
- trademarkLicense?: string;
+ id?: string
+ consortiaMember?: boolean
+ consortiaLeadId?: string
+ isConsortiumLead?: boolean
+ name?: string
+ publicDisplayName?: string
+ website?: string
+ billingCountry?: string
+ memberType?: string
+ publicDisplayDescriptionHtml?: string
+ logoUrl?: string
+ publicDisplayEmail?: string
+ membershipStartDateString?: string
+ membershipEndDateString?: string
+ consortiumLeadName?: string
+ consortiumMembers?: ISFConsortiumMemberData[]
+ contacts?: ISFMemberContact[]
+ orgIds?: ISFMemberOrgIds
+ billingAddress?: ISFAddress
+ trademarkLicense?: string
}
export interface ISFConsortiumMemberData {
- orgName?: string;
- salesforceId?: string;
- metadata?: ISFConsortiumMemberMetadata;
- terminationMonth?: string;
- terminationYear?: string;
+ orgName?: string
+ salesforceId?: string
+ metadata?: ISFConsortiumMemberMetadata
+ terminationMonth?: string
+ terminationYear?: string
}
export interface ISFConsortiumMemberMetadata {
- name?: string;
+ name?: string
}
export interface ISFRawMemberData {
- Id?: string;
- Consortia_Member__c?: boolean;
- Consortium_Lead__c?: string;
- Name?: string;
- Public_Display_Name__c?: string;
- Website?: string;
- BillingCountry?: string;
- Research_Community__c?: string;
- Public_Display_Description__c?: string;
- Logo_Description__c?: string;
- Public_Display_Email__c?: string;
- Last_membership_start_date__c?: string;
- Last_membership_end_date__c?: string;
- consortiumOpportunities: [ISFRawConsortiumMemberData];
- BillingAddress: ISFAddress;
- Trademark_License__c: string;
+ Id?: string
+ Consortia_Member__c?: boolean
+ Consortium_Lead__c?: string
+ Name?: string
+ Public_Display_Name__c?: string
+ Website?: string
+ BillingCountry?: string
+ Research_Community__c?: string
+ Public_Display_Description__c?: string
+ Logo_Description__c?: string
+ Public_Display_Email__c?: string
+ Last_membership_start_date__c?: string
+ Last_membership_end_date__c?: string
+ consortiumOpportunities: [ISFRawConsortiumMemberData]
+ BillingAddress: ISFAddress
+ Trademark_License__c: string
}
export interface ISFRawConsortiumMemberData {
- AccountId?: string;
- Account?: ISFRawConsortiumMemberMetadata;
+ AccountId?: string
+ Account?: ISFRawConsortiumMemberMetadata
}
export interface ISFRawConsortiumMemberMetadata {
- Public_Display_Name__c?: string;
+ Public_Display_Name__c?: string
}
export class SFMemberData implements ISFMemberData {
@@ -91,5 +91,10 @@ export class SFMemberData implements ISFMemberData {
}
export class SFConsortiumMemberData implements ISFConsortiumMemberData {
- constructor(public salesforceId?: string, public orgName?: string, public terminationMonth?: string, public terminationYear?: string) {}
+ constructor(
+ public salesforceId?: string,
+ public orgName?: string,
+ public terminationMonth?: string,
+ public terminationYear?: string
+ ) {}
}
diff --git a/ui/src/app/member/model/salesforce-member-org-id.model.ts b/ui/src/app/member/model/salesforce-member-org-id.model.ts
index a5febf9fe..71130c134 100644
--- a/ui/src/app/member/model/salesforce-member-org-id.model.ts
+++ b/ui/src/app/member/model/salesforce-member-org-id.model.ts
@@ -1,20 +1,25 @@
export interface ISFMemberOrgIds {
- ROR?: string[];
- GRID?: string[];
- Ringgold?: string[];
- Fundref?: string[];
+ ROR?: string[]
+ GRID?: string[]
+ Ringgold?: string[]
+ Fundref?: string[]
}
export interface ISFRawMemberOrgId {
- Identifier_Type__c: string;
- Name: string;
+ Identifier_Type__c: string
+ Name: string
}
export interface ISFRawMemberOrgIds {
- records?: ISFRawMemberOrgId[];
- size?: number;
- done?: boolean;
+ records?: ISFRawMemberOrgId[]
+ size?: number
+ done?: boolean
}
export class SFMemberOrgIds implements ISFMemberOrgIds {
- constructor(public ROR?: string[], public GRID?: string[], public Ringgold?: string[], public Fundref?: string[]) {}
+ constructor(
+ public ROR?: string[],
+ public GRID?: string[],
+ public Ringgold?: string[],
+ public Fundref?: string[]
+ ) {}
}
diff --git a/ui/src/app/member/model/salesforce-member-update.model.ts b/ui/src/app/member/model/salesforce-member-update.model.ts
index dc35ce3c7..e73c3c5b7 100644
--- a/ui/src/app/member/model/salesforce-member-update.model.ts
+++ b/ui/src/app/member/model/salesforce-member-update.model.ts
@@ -1,13 +1,13 @@
-import { ISFAddress } from './salesforce-address.model';
+import { ISFAddress } from './salesforce-address.model'
export interface ISFMemberUpdate {
- orgName?: string;
- billingAddress?: ISFAddress;
- trademarkLicense?: string;
- publicName?: string;
- description?: string;
- website?: string;
- email?: string;
+ orgName?: string
+ billingAddress?: ISFAddress
+ trademarkLicense?: string
+ publicName?: string
+ description?: string
+ website?: string
+ email?: string
}
export class SFMemberUpdate implements ISFMemberUpdate {
diff --git a/ui/src/app/member/model/salesforce-new-consortium-member.model.ts b/ui/src/app/member/model/salesforce-new-consortium-member.model.ts
index d72f766ca..23e99620f 100644
--- a/ui/src/app/member/model/salesforce-new-consortium-member.model.ts
+++ b/ui/src/app/member/model/salesforce-new-consortium-member.model.ts
@@ -1,19 +1,19 @@
export interface ISFNewConsortiumMember {
- orgName: string;
- trademarkLicense: string;
- startMonth: string;
- startYear: string;
- emailDomain?: string;
- street?: string;
- city?: string;
- state?: string;
- country?: string;
- postcode?: string;
- contactGivenName?: string;
- contactFamilyName?: string;
- contactJobTitle?: string;
- contactEmail?: string;
- contactPhone?: string;
+ orgName: string
+ trademarkLicense: string
+ startMonth: string
+ startYear: string
+ emailDomain?: string
+ street?: string
+ city?: string
+ state?: string
+ country?: string
+ postcode?: string
+ contactGivenName?: string
+ contactFamilyName?: string
+ contactJobTitle?: string
+ contactEmail?: string
+ contactPhone?: string
}
export class SFNewConsortiumMember implements ISFNewConsortiumMember {
diff --git a/ui/src/app/member/service/member.service.ts b/ui/src/app/member/service/member.service.ts
index fdae4e83a..cc56566cb 100644
--- a/ui/src/app/member/service/member.service.ts
+++ b/ui/src/app/member/service/member.service.ts
@@ -37,12 +37,8 @@ export class MemberService {
protected convertDateFromServer(res: EntityResponseType): EntityResponseType {
if (res.body) {
- res.body.createdDate =
- res.body.createdDate != null ? moment(res.body.createdDate) : undefined
- res.body.lastModifiedDate =
- res.body.lastModifiedDate != null
- ? moment(res.body.lastModifiedDate)
- : undefined
+ res.body.createdDate = res.body.createdDate != null ? moment(res.body.createdDate) : undefined
+ res.body.lastModifiedDate = res.body.lastModifiedDate != null ? moment(res.body.lastModifiedDate) : undefined
}
return res
}
diff --git a/ui/src/app/shared/directive/has-any-authority.directive.ts b/ui/src/app/shared/directive/has-any-authority.directive.ts
index 66b2188a0..27e904d84 100644
--- a/ui/src/app/shared/directive/has-any-authority.directive.ts
+++ b/ui/src/app/shared/directive/has-any-authority.directive.ts
@@ -1,5 +1,5 @@
-import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
-import { AccountService } from 'src/app/account/service/account.service';
+import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core'
+import { AccountService } from 'src/app/account/service/account.service'
/**
* @whatItDoes Conditionally includes an HTML element if current user has any
@@ -13,26 +13,30 @@ import { AccountService } from 'src/app/account/service/account.service';
* ```
*/
@Directive({
- selector: '[hasAnyAuthority]'
+ selector: '[appHasAnyAuthority]',
})
export class HasAnyAuthorityDirective {
- private authorities: string[] = [];
+ private authorities: string[] = []
- constructor(private accountService: AccountService, private templateRef: TemplateRef, private viewContainerRef: ViewContainerRef) {}
+ constructor(
+ private accountService: AccountService,
+ private templateRef: TemplateRef,
+ private viewContainerRef: ViewContainerRef
+ ) {}
@Input()
set hasAnyAuthority(value: string | string[]) {
- this.authorities = typeof value === 'string' ? [value] : value;
- this.updateView();
+ this.authorities = typeof value === 'string' ? [value] : value
+ this.updateView()
// Get notified each time authentication state changes.
- this.accountService.getAuthenticationState().subscribe(identity => this.updateView());
+ this.accountService.getAuthenticationState().subscribe((identity) => this.updateView())
}
private updateView(): void {
- const hasAnyAuthority = this.accountService.hasAnyAuthority(this.authorities);
- this.viewContainerRef.clear();
+ const hasAnyAuthority = this.accountService.hasAnyAuthority(this.authorities)
+ this.viewContainerRef.clear()
if (hasAnyAuthority) {
- this.viewContainerRef.createEmbeddedView(this.templateRef);
+ this.viewContainerRef.createEmbeddedView(this.templateRef)
}
}
}
diff --git a/ui/src/app/shared/model/event.model.ts b/ui/src/app/shared/model/event.model.ts
index d4160e609..5643c6f10 100644
--- a/ui/src/app/shared/model/event.model.ts
+++ b/ui/src/app/shared/model/event.model.ts
@@ -1,8 +1,8 @@
-import { EventType } from "src/app/app.constants";
+import { EventType } from 'src/app/app.constants'
export class Event {
- constructor(
- public type: EventType,
- public payload: String,
- ) {}
- }
\ No newline at end of file
+ constructor(
+ public type: EventType,
+ public payload: string
+ ) {}
+}
diff --git a/ui/src/app/shared/service/event.service.spec.ts b/ui/src/app/shared/service/event.service.spec.ts
new file mode 100644
index 000000000..a9e1fdc96
--- /dev/null
+++ b/ui/src/app/shared/service/event.service.spec.ts
@@ -0,0 +1,49 @@
+import { EventType } from 'src/app/app.constants'
+import { EventService } from './event.service'
+import { Event } from '../model/event.model'
+
+describe('EventService', () => {
+ let eventService: EventService
+
+ beforeEach(() => {
+ eventService = new EventService()
+ })
+
+ it('should be created', () => {
+ expect(eventService).toBeTruthy()
+ })
+
+ it('should broadcast events', () => {
+ const event: Event = {
+ type: EventType.LOG_IN_SUCCESS,
+ payload: 'Login successful',
+ }
+ let receivedEvent: Event | undefined
+
+ eventService.on(EventType.LOG_IN_SUCCESS).subscribe((e) => {
+ receivedEvent = e
+ })
+
+ eventService.broadcast(event)
+
+ expect(receivedEvent).toEqual(event)
+ })
+
+ it('should filter events by type', () => {
+ const event1: Event = { type: EventType.LOG_IN_SUCCESS, payload: 'data 1' }
+ const event2: Event = {
+ type: EventType.AFFILIATION_CREATED,
+ payload: 'data 2',
+ }
+ let receivedEvent: Event | undefined
+
+ eventService.on(EventType.LOG_IN_SUCCESS).subscribe((e) => {
+ receivedEvent = e
+ })
+
+ eventService.broadcast(event1)
+ eventService.broadcast(event2)
+
+ expect(receivedEvent).toEqual(event1)
+ })
+})
diff --git a/ui/src/app/shared/service/event.service.ts b/ui/src/app/shared/service/event.service.ts
index 58c419ba5..211e5e248 100644
--- a/ui/src/app/shared/service/event.service.ts
+++ b/ui/src/app/shared/service/event.service.ts
@@ -5,7 +5,6 @@ import { Event } from '../model/event.model'
@Injectable({ providedIn: 'root' })
export class EventService {
-
private events = new Subject()
on(eventType: EventType): Observable {
@@ -15,5 +14,4 @@ export class EventService {
broadcast(event: Event): void {
this.events.next(event)
}
-
}
diff --git a/ui/src/content/scss/global.scss b/ui/src/content/scss/global.scss
new file mode 100644
index 000000000..a36a9ea6c
--- /dev/null
+++ b/ui/src/content/scss/global.scss
@@ -0,0 +1,506 @@
+@import 'bootstrap-variables';
+@import '../../../node_modules/bootstrap/scss/functions';
+@import '../../../node_modules/bootstrap/scss/variables';
+@import '../../../node_modules/@angular/material/prebuilt-themes/indigo-pink.css';
+@import 'spacing';
+
+/* ==============================================================
+Bootstrap tweaks
+===============================================================*/
+html,
+body {
+ height: 100%;
+}
+
+body,
+h1 {
+ font-weight: 400;
+}
+
+h2,
+h3,
+h4 {
+ font-weight: 700;
+}
+
+a {
+ font-weight: $font-weight-bold;
+ cursor: pointer;
+}
+
+pre {
+ white-space: pre-wrap; /* css-3 */
+ white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
+ white-space: -pre-wrap; /* Opera 4-6 */
+ white-space: -o-pre-wrap; /* Opera 7 */
+ word-wrap: break-word;
+}
+
+.container-fluid {
+ flex: 1;
+}
+
+.dropdown-item:hover {
+ color: $dropdown-link-hover-color;
+}
+
+/* ==========================================================================
+Browser Upgrade Prompt
+========================================================================== */
+.browserupgrade {
+ margin: 0.2em 0;
+ color: #000;
+ padding: 0.2em 0;
+}
+
+/* ==========================================================================
+Generic styles
+========================================================================== */
+
+/* Error highlight on input fields */
+.ng-valid[required],
+.ng-valid.required {
+ border-left: 5px solid green;
+}
+
+.ng-invalid:not(form) {
+ border-left: 5px solid red;
+}
+
+/* other generic styles */
+
+.jh-card {
+ padding: 1.5%;
+ margin-top: 20px;
+ border: none;
+}
+
+.error {
+ color: white;
+ background-color: red;
+}
+
+.color-gray {
+ color: $black-transparent;
+}
+
+.pad {
+ padding: 10px;
+}
+
+.w-40 {
+ width: 40% !important;
+}
+
+.w-60 {
+ width: 60% !important;
+}
+
+.break {
+ white-space: normal;
+ word-break: break-all;
+}
+
+.readonly {
+ background-color: #eee;
+ opacity: 1;
+}
+
+.hand,
+[jhisortby] {
+ cursor: pointer;
+}
+
+/* ==========================================================================
+Custom alerts for notification
+========================================================================== */
+.alerts {
+ .alert {
+ text-overflow: ellipsis;
+ pre {
+ background: none;
+ border: none;
+ font: inherit;
+ color: inherit;
+ padding: 0;
+ margin: 0;
+ }
+ .popover pre {
+ font-size: 10px;
+ }
+ }
+ .jhi-toast {
+ position: fixed;
+ width: 100%;
+ &.left {
+ left: 5px;
+ }
+ &.right {
+ right: 5px;
+ }
+ &.top {
+ top: 55px;
+ }
+ &.bottom {
+ bottom: 55px;
+ }
+ }
+}
+
+@media screen and (min-width: 480px) {
+ .alerts .jhi-toast {
+ width: 50%;
+ }
+}
+
+/* ==========================================================================
+entity detail page css
+========================================================================== */
+.row dl.jh-entity-details {
+ width: 100%;
+}
+
+.row .jh-entity-details > {
+ dd {
+ margin-bottom: 15px;
+ float: left;
+ }
+ dd:last-child {
+ margin-bottom: 0;
+ }
+ dt {
+ float: left;
+ clear: both;
+ }
+}
+
+@media screen and (min-width: 768px) {
+ .row-md.jh-entity-details > {
+ dt {
+ border-bottom: 1px solid #eee;
+ margin-bottom: 15px;
+ }
+ dd {
+ border-bottom: 1px solid #eee;
+ margin-left: 0;
+ }
+ }
+}
+
+/* ==========================================================================
+ui bootstrap tweaks
+========================================================================== */
+.nav,
+.pagination,
+.carousel,
+.panel-title a {
+ cursor: pointer;
+}
+
+.thread-dump-modal-lock {
+ max-width: 450px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+/* jhipster-needle-scss-add-main JHipster will add new css style */
+
+.form-control-label {
+ font-weight: bold;
+ margin-top: 0.5rem;
+ margin-bottom: 0.5rem;
+}
+
+input.form-control[type='checkbox'] {
+ width: initial;
+ float: left;
+ margin-right: 0.5rem;
+ margin-bottom: 0.5rem;
+}
+
+input.form-control[type='file'] {
+ border: none;
+}
+
+/* ==========================================================================
+ORCID global styles
+========================================================================== */
+.note {
+ font-size: 0.8em;
+ line-height: normal;
+ font-style: italic;
+}
+
+.article {
+ margin: 2em 4em;
+ border: 1px solid #dee2e6;
+ border-radius: 6px;
+ padding: 2em;
+}
+.id-icon {
+ margin: 0 0.1em 0.2em 0;
+}
+
+.errorMessage {
+ margin-top: 2em;
+ padding: 0.8em 1em;
+ color: #ab2222;
+}
+
+.progress-bar.indeterminate {
+ width: 100%;
+ position: relative;
+ animation: progress-indeterminate 3s linear infinite;
+}
+
+@keyframes progress-indeterminate {
+ from {
+ left: -25%;
+ width: 25%;
+ }
+ to {
+ left: 100%;
+ width: 25%;
+ }
+}
+
+#hideMe {
+ -webkit-animation: cssAnimationHide 60s forwards;
+ animation: cssAnimationHide 60s forwards;
+}
+@keyframes cssAnimationHide {
+ 0% {
+ opacity: 1;
+ }
+ 90% {
+ opacity: 1;
+ }
+ 100% {
+ opacity: 0;
+ }
+}
+@-webkit-keyframes cssAnimationHide {
+ 0% {
+ opacity: 1;
+ }
+ 90% {
+ opacity: 1;
+ }
+ 100% {
+ opacity: 0;
+ }
+}
+
+#showMe {
+ -webkit-animation: cssAnimationShow 60s forwards;
+ animation: cssAnimationShow 60s forwards;
+}
+@keyframes cssAnimationShow {
+ 0% {
+ opacity: 0;
+ }
+ 90% {
+ opacity: 0;
+ }
+ 100% {
+ opacity: 1;
+ }
+}
+@-webkit-keyframes cssAnimationShow {
+ 0% {
+ opacity: 0;
+ }
+ 90% {
+ opacity: 0;
+ }
+ 100% {
+ opacity: 1;
+ }
+}
+
+.progress-line,
+.progress-line:before {
+ height: 3px;
+ width: 100%;
+ margin: 0;
+}
+.progress-line {
+ background-color: #2bbe18;
+ display: -webkit-flex;
+ display: flex;
+}
+.progress-line:before {
+ background-color: #1f7a14;
+ content: '';
+ -webkit-animation: running-progress 2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
+ animation: running-progress 2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
+}
+@-webkit-keyframes running-progress {
+ 0% {
+ margin-left: 0px;
+ margin-right: 100%;
+ }
+ 50% {
+ margin-left: 25%;
+ margin-right: 0%;
+ }
+ 100% {
+ margin-left: 100%;
+ margin-right: 0;
+ }
+}
+@keyframes running-progress {
+ 0% {
+ margin-left: 0px;
+ margin-right: 100%;
+ }
+ 50% {
+ margin-left: 25%;
+ margin-right: 0%;
+ }
+ 100% {
+ margin-left: 100%;
+ margin-right: 0;
+ }
+}
+
+.navbar-brand {
+ overflow: hidden;
+}
+
+.navbar-collapse {
+ width: 500px;
+ flex-shrink: 0;
+}
+
+.truncate-text {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+div.org-name {
+ display: inline-block;
+ max-width: calc(100% - 350px);
+}
+
+ul.validation-errors {
+ list-style: none;
+ padding: 0;
+}
+
+div.filter-group {
+ margin: 10px 0 10px 0;
+}
+
+div.filter-input {
+ position: relative;
+ width: 40%;
+}
+
+div.filter-group > button.search {
+ background-color: white;
+ border: 1px solid #ced4da;
+ position: relative;
+}
+
+div.filter-input > button.reset {
+ background-color: white;
+ border: none;
+ position: absolute;
+ right: 5px;
+ top: 5px;
+ z-index: 100;
+}
+
+input.indented {
+ margin-left: 20px;
+}
+
+p.mfaSecret {
+ margin-left: 35px;
+}
+
+div.success {
+ color: green;
+}
+
+.wide-text {
+ letter-spacing: 0.5px;
+}
+
+.wide-text-25 {
+ letter-spacing: 0.25px;
+}
+
+.font-size-12 {
+ font-size: 0.75rem;
+}
+
+.font-size-14 {
+ font-size: 0.875rem;
+}
+
+.font-size-16 {
+ font-size: 1rem;
+}
+
+.font-size-18 {
+ font-size: 1.125rem;
+}
+
+.font-size-24 {
+ font-size: 1.5rem;
+}
+
+.green-hr {
+ border: 1px solid $secondary;
+ width: 100%;
+ margin-top: 0.5rem;
+}
+
+.w-66 {
+ width: 66% !important;
+}
+
+.w-33 {
+ width: 33% !important;
+}
+
+// innerHtml styling for the public member description
+.main-section-description {
+ p,
+ h1,
+ h2,
+ h3,
+ h4,
+ h5,
+ h6 {
+ margin-bottom: 0;
+ }
+}
+
+.input-field-default-border {
+ border: 1px solid #ced4da !important;
+}
+
+.outline-danger {
+ outline: 2px solid red;
+}
+
+.form-field-text-color-default {
+ color: #495057;
+}
+
+.text-decoration-underline {
+ text-decoration: underline;
+}
+
+.line-height-normal {
+ line-height: normal;
+}
+
+.line-height-150 {
+ line-height: 150%;
+}
diff --git a/ui/src/content/scss/noto-sans.scss b/ui/src/content/scss/noto-sans.scss
index c31dd9175..e45c598ed 100644
--- a/ui/src/content/scss/noto-sans.scss
+++ b/ui/src/content/scss/noto-sans.scss
@@ -5,7 +5,8 @@ $notosans-fontface-path: 'content/fonts/noto-sans' !default;
@mixin notosans-fontface($type, $weight, $style) {
@font-face {
font-family: 'Noto Sans';
- src: url ('#{$notosans-fontface-path}/NotoSans-#{$type}.woff2') format('woff'),
+ src:
+ url ('#{$notosans-fontface-path}/NotoSans-#{$type}.woff2') format('woff'),
url ('#{$notosans-fontface-path}/NotoSans-#{$type}.woff') format('woff');
font-weight: $weight;
font-style: $style;
diff --git a/ui/src/content/scss/spacing.scss b/ui/src/content/scss/spacing.scss
new file mode 100644
index 000000000..51b090925
--- /dev/null
+++ b/ui/src/content/scss/spacing.scss
@@ -0,0 +1,89 @@
+// 8, 16, 24, 32, 40
+@for $i from 1 through 5 {
+ $size: 0.5rem * $i;
+
+ .mt-#{$i * 8} {
+ margin-top: $size;
+ }
+
+ .mr-#{$i * 8} {
+ margin-right: $size;
+ }
+
+ .mb-#{$i * 8} {
+ margin-bottom: $size;
+ }
+
+ .ml-#{$i * 8} {
+ margin-left: $size;
+ }
+
+ .m-#{$i * 8} {
+ margin: $size;
+ }
+
+ .pt-#{$i * 8} {
+ padding-top: $size;
+ }
+
+ .pr-#{$i * 8} {
+ padding-right: $size;
+ }
+
+ .pb-#{$i * 8} {
+ padding-bottom: $size;
+ }
+
+ .pl-#{$i * 8} {
+ padding-left: $size;
+ }
+
+ .p-#{$i * 8} {
+ padding: $size;
+ }
+}
+
+// 10, 20, 30
+@for $i from 1 through 3 {
+ $size: 0.625rem * $i;
+
+ .mt-#{$i * 10} {
+ margin-top: $size;
+ }
+
+ .mr-#{$i * 10} {
+ margin-right: $size;
+ }
+
+ .mb-#{$i * 10} {
+ margin-bottom: $size;
+ }
+
+ .ml-#{$i * 10} {
+ margin-left: $size;
+ }
+
+ .m-#{$i * 10} {
+ margin: $size;
+ }
+
+ .pt-#{$i * 10} {
+ padding-top: $size;
+ }
+
+ .pr-#{$i * 10} {
+ padding-right: $size;
+ }
+
+ .pb-#{$i * 10} {
+ padding-bottom: $size;
+ }
+
+ .pl-#{$i * 10} {
+ padding-left: $size;
+ }
+
+ .p-#{$i * 10} {
+ padding: $size;
+ }
+}
diff --git a/ui/src/environments/environment.prod.ts b/ui/src/environments/environment.prod.ts
index 3612073bc..970e25bd7 100644
--- a/ui/src/environments/environment.prod.ts
+++ b/ui/src/environments/environment.prod.ts
@@ -1,3 +1,3 @@
export const environment = {
- production: true
-};
+ production: true,
+}
diff --git a/ui/src/environments/environment.ts b/ui/src/environments/environment.ts
index f56ff4702..372505677 100644
--- a/ui/src/environments/environment.ts
+++ b/ui/src/environments/environment.ts
@@ -3,8 +3,8 @@
// The list of file replacements can be found in `angular.json`.
export const environment = {
- production: false
-};
+ production: false,
+}
/*
* For easier debugging in development mode, you can import the following file
diff --git a/ui/src/index.html b/ui/src/index.html
index 80ecbe8d6..bee93e114 100644
--- a/ui/src/index.html
+++ b/ui/src/index.html
@@ -1,13 +1,75 @@
-
-
-
- ui
-
-
-
-
-
-
-
+
+
+
+
+
+ ORCID Member Portal
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/src/main.ts b/ui/src/main.ts
index c7b673cf4..274537fe8 100644
--- a/ui/src/main.ts
+++ b/ui/src/main.ts
@@ -1,12 +1,13 @@
-import { enableProdMode } from '@angular/core';
-import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { enableProdMode } from '@angular/core'
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'
-import { AppModule } from './app/app.module';
-import { environment } from './environments/environment';
+import { AppModule } from './app/app.module'
+import { environment } from './environments/environment'
if (environment.production) {
- enableProdMode();
+ enableProdMode()
}
-platformBrowserDynamic().bootstrapModule(AppModule)
- .catch(err => console.error(err));
+platformBrowserDynamic()
+ .bootstrapModule(AppModule)
+ .catch((err) => console.error(err))
diff --git a/ui/src/polyfills.ts b/ui/src/polyfills.ts
index 429bb9ef2..5173f2ff9 100644
--- a/ui/src/polyfills.ts
+++ b/ui/src/polyfills.ts
@@ -45,8 +45,7 @@
/***************************************************************************************************
* Zone JS is required by default for Angular itself.
*/
-import 'zone.js'; // Included with Angular CLI.
-
+import 'zone.js' // Included with Angular CLI.
/***************************************************************************************************
* APPLICATION IMPORTS
diff --git a/ui/src/proxy.conf.json b/ui/src/proxy.conf.json
index 167d1b9ab..99d974100 100644
--- a/ui/src/proxy.conf.json
+++ b/ui/src/proxy.conf.json
@@ -1,16 +1,16 @@
{
- "/auth/login": {
- "target": "http://localhost:8080",
- "secure": false,
- "changeOrigin": true,
- "logLevel": "debug",
- "cookieDomainRewrite": "localhost"
- },
- "/services/*": {
- "target": "http://localhost:8080",
- "secure": false,
- "changeOrigin": true,
- "logLevel": "debug",
- "cookieDomainRewrite": "localhost"
- }
-}
\ No newline at end of file
+ "/auth/login": {
+ "target": "http://localhost:8080",
+ "secure": false,
+ "changeOrigin": true,
+ "logLevel": "debug",
+ "cookieDomainRewrite": "localhost"
+ },
+ "/services/*": {
+ "target": "http://localhost:8080",
+ "secure": false,
+ "changeOrigin": true,
+ "logLevel": "debug",
+ "cookieDomainRewrite": "localhost"
+ }
+}
diff --git a/ui/src/styles.scss b/ui/src/styles.scss
deleted file mode 100644
index 90d4ee007..000000000
--- a/ui/src/styles.scss
+++ /dev/null
@@ -1 +0,0 @@
-/* You can add global styles to this file, and also import other style files */
diff --git a/ui/src/test.ts b/ui/src/test.ts
index 51bb0206a..1055bc735 100644
--- a/ui/src/test.ts
+++ b/ui/src/test.ts
@@ -1,14 +1,8 @@
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
-import 'zone.js/testing';
-import { getTestBed } from '@angular/core/testing';
-import {
- BrowserDynamicTestingModule,
- platformBrowserDynamicTesting
-} from '@angular/platform-browser-dynamic/testing';
+import 'zone.js/testing'
+import { getTestBed } from '@angular/core/testing'
+import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'
// First, initialize the Angular testing environment.
-getTestBed().initTestEnvironment(
- BrowserDynamicTestingModule,
- platformBrowserDynamicTesting(),
-);
+getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting())
diff --git a/ui/tsconfig.app.json b/ui/tsconfig.app.json
index 82d91dc4a..ff396d4ce 100644
--- a/ui/tsconfig.app.json
+++ b/ui/tsconfig.app.json
@@ -5,11 +5,6 @@
"outDir": "./out-tsc/app",
"types": []
},
- "files": [
- "src/main.ts",
- "src/polyfills.ts"
- ],
- "include": [
- "src/**/*.d.ts"
- ]
+ "files": ["src/main.ts", "src/polyfills.ts"],
+ "include": ["src/**/*.d.ts"]
}
diff --git a/ui/tsconfig.json b/ui/tsconfig.json
index 1407cb6e4..c6c687c35 100644
--- a/ui/tsconfig.json
+++ b/ui/tsconfig.json
@@ -18,10 +18,7 @@
"importHelpers": true,
"target": "ES2022",
"module": "es2020",
- "lib": [
- "es2020",
- "dom"
- ],
+ "lib": ["es2020", "dom"],
"useDefineForClassFields": false
},
"angularCompilerOptions": {
diff --git a/ui/tsconfig.spec.json b/ui/tsconfig.spec.json
index 092345b02..669344f8d 100644
--- a/ui/tsconfig.spec.json
+++ b/ui/tsconfig.spec.json
@@ -3,16 +3,8 @@
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
- "types": [
- "jasmine"
- ]
+ "types": ["jasmine"]
},
- "files": [
- "src/test.ts",
- "src/polyfills.ts"
- ],
- "include": [
- "src/**/*.spec.ts",
- "src/**/*.d.ts"
- ]
+ "files": ["src/test.ts", "src/polyfills.ts"],
+ "include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
}