Added first app template
This commit is contained in:
		@@ -0,0 +1,16 @@
 | 
			
		||||
import { TestBed } from '@angular/core/testing';
 | 
			
		||||
 | 
			
		||||
import { AuthService } from './auth.service';
 | 
			
		||||
 | 
			
		||||
describe('AuthService', () => {
 | 
			
		||||
  let service: AuthService;
 | 
			
		||||
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    TestBed.configureTestingModule({});
 | 
			
		||||
    service = TestBed.inject(AuthService);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should be created', () => {
 | 
			
		||||
    expect(service).toBeTruthy();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										242
									
								
								frontend/login-counter/src/app/services/auth/auth.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										242
									
								
								frontend/login-counter/src/app/services/auth/auth.service.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,242 @@
 | 
			
		||||
import { HttpClient, HttpHeaders } from '@angular/common/http';
 | 
			
		||||
import { Injectable } from '@angular/core';
 | 
			
		||||
import { Router } from '@angular/router';
 | 
			
		||||
import { JwtHelperService } from '@auth0/angular-jwt';
 | 
			
		||||
import { Observable, Subscription } from 'rxjs';
 | 
			
		||||
import { catchError } from 'rxjs/operators';
 | 
			
		||||
import { AuthUserDTO } from 'src/app/models/auth/auth-user.dto';
 | 
			
		||||
import { UpdateUserDTO } from 'src/app/models/auth/update-user.dto';
 | 
			
		||||
import { EMailStringDTO } from 'src/app/models/auth/email-string.dto';
 | 
			
		||||
import { ResetPasswordDTO } from 'src/app/models/auth/reset-password.dto';
 | 
			
		||||
import { TokenDTO } from 'src/app/models/auth/token.dto';
 | 
			
		||||
import { SettingsService } from '../settings/settings.service';
 | 
			
		||||
import { AuthRoles } from 'src/app/models/auth/auth-roles.enum';
 | 
			
		||||
import { SpinnerService } from '../spinner/spinner.service';
 | 
			
		||||
import { AdminUpdateUserDTO } from 'src/app/models/auth/admin-update-user.dto';
 | 
			
		||||
import { AuthUserSelectCriterion } from 'src/app/models/selection/auth-user/auth-user-select-criterion.dto';
 | 
			
		||||
import { GetFilteredAuthUsersResultDTO } from 'src/app/models/selection/auth-user/get-filtered-auth-users-result.dto';
 | 
			
		||||
 | 
			
		||||
@Injectable({
 | 
			
		||||
  providedIn: 'root'
 | 
			
		||||
})
 | 
			
		||||
export class AuthService {
 | 
			
		||||
 | 
			
		||||
  invalidLogin: boolean;
 | 
			
		||||
  isLoggedIn: boolean;
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private appsettings: SettingsService,
 | 
			
		||||
    private http: HttpClient,
 | 
			
		||||
    private router: Router,
 | 
			
		||||
    private jwtHelper: JwtHelperService,
 | 
			
		||||
    private spinnerService: SpinnerService
 | 
			
		||||
  ) {
 | 
			
		||||
    this.isUserLoggedInAsync();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* data requests */
 | 
			
		||||
  getAllUsers(): Observable<Array<AuthUserDTO>> {
 | 
			
		||||
    return this.http.get<Array<AuthUserDTO>>(`${this.appsettings.getApiURL()}/api/auth/users`, {
 | 
			
		||||
      headers: new HttpHeaders({
 | 
			
		||||
        'Content-Type': 'application/json'
 | 
			
		||||
      })
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getFilteredUsers(selectCriterions: AuthUserSelectCriterion): Observable<GetFilteredAuthUsersResultDTO> {
 | 
			
		||||
    return this.http.post<GetFilteredAuthUsersResultDTO>(`${this.appsettings.getApiURL()}/api/auth/users/get/filtered`, selectCriterions, {
 | 
			
		||||
      headers: new HttpHeaders({
 | 
			
		||||
        'Content-Type': 'application/json'
 | 
			
		||||
      })
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getUserByEMail(email: string): Observable<AuthUserDTO> {
 | 
			
		||||
    return this.http.get<AuthUserDTO>(`${this.appsettings.getApiURL()}/api/auth/users/get/${email}`, {
 | 
			
		||||
      headers: new HttpHeaders({
 | 
			
		||||
        'Content-Type': 'application/json'
 | 
			
		||||
      })
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  findUserByEMail(email: string): Observable<AuthUserDTO> {
 | 
			
		||||
    return this.http.get<AuthUserDTO>(`${this.appsettings.getApiURL()}/api/auth/users/find/${email}`, {
 | 
			
		||||
      headers: new HttpHeaders({
 | 
			
		||||
        'Content-Type': 'application/json'
 | 
			
		||||
      })
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* auth requsts */
 | 
			
		||||
  register(user: AuthUserDTO): Observable<unknown> {
 | 
			
		||||
    return this.http.post<TokenDTO>(`${this.appsettings.getApiURL()}/api/auth/register`, user, {
 | 
			
		||||
      headers: new HttpHeaders({
 | 
			
		||||
        'Content-Type': 'application/json'
 | 
			
		||||
      })
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  confirmEMail(id: string): Observable<boolean> {
 | 
			
		||||
    return this.http.post<boolean>(`${this.appsettings.getApiURL()}/api/auth/register/${id}`, {
 | 
			
		||||
      headers: new HttpHeaders({
 | 
			
		||||
        'Content-Type': 'application/json'
 | 
			
		||||
      })
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  login(user: AuthUserDTO): Observable<TokenDTO> {
 | 
			
		||||
    return this.http.post<TokenDTO>(`${this.appsettings.getApiURL()}/api/auth/login`, user, {
 | 
			
		||||
      headers: new HttpHeaders({
 | 
			
		||||
        'Content-Type': 'application/json'
 | 
			
		||||
      })
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  forgotPassword(email: string): Observable<unknown> {
 | 
			
		||||
    const emailJson = JSON.stringify(email);
 | 
			
		||||
    return this.http.post(`${this.appsettings.getApiURL()}/api/auth/forgot-password`, emailJson, {
 | 
			
		||||
      headers: new HttpHeaders({
 | 
			
		||||
        'Content-Type': 'application/json'
 | 
			
		||||
      })
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getEMailFromforgotPasswordId(id: string): Observable<EMailStringDTO> {
 | 
			
		||||
    const idJson = JSON.stringify(id);
 | 
			
		||||
    return this.http.post<EMailStringDTO>(`${this.appsettings.getApiURL()}/api/auth/confirm-forgot-password`, idJson, {
 | 
			
		||||
      headers: new HttpHeaders({
 | 
			
		||||
        'Content-Type': 'application/json'
 | 
			
		||||
      })
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  resetPassword(resetPasswordDTO: ResetPasswordDTO): Observable<unknown> {
 | 
			
		||||
    return this.http.post(`${this.appsettings.getApiURL()}/api/auth/reset-password`, resetPasswordDTO, {
 | 
			
		||||
      headers: new HttpHeaders({
 | 
			
		||||
        'Content-Type': 'application/json'
 | 
			
		||||
      })
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  updateUser(updateUserDTO: UpdateUserDTO): Observable<unknown> {
 | 
			
		||||
    return this.http.post(`${this.appsettings.getApiURL()}/api/auth/update-user`, updateUserDTO, {
 | 
			
		||||
      headers: new HttpHeaders({
 | 
			
		||||
        'Content-Type': 'application/json'
 | 
			
		||||
      })
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  updateUserAsAdmin(updateUserDTO: AdminUpdateUserDTO): Observable<unknown> {
 | 
			
		||||
    return this.http.post(`${this.appsettings.getApiURL()}/api/auth/update-user-as-admin`, updateUserDTO, {
 | 
			
		||||
      headers: new HttpHeaders({
 | 
			
		||||
        'Content-Type': 'application/json'
 | 
			
		||||
      })
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  refresh(token: TokenDTO): Observable<TokenDTO> {
 | 
			
		||||
    return this.http.post<TokenDTO>(`${this.appsettings.getApiURL()}/api/auth/refresh`, token, {
 | 
			
		||||
      headers: new HttpHeaders({
 | 
			
		||||
        'Content-Type': 'application/json'
 | 
			
		||||
      })
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  logout(): Subscription {
 | 
			
		||||
    const token = this.getToken();
 | 
			
		||||
    this.isLoggedIn = false;
 | 
			
		||||
    localStorage.removeItem('jwt');
 | 
			
		||||
    localStorage.removeItem('rjwt');
 | 
			
		||||
    this.router.navigate(['/auth/login']);
 | 
			
		||||
 | 
			
		||||
    if (token && token.token && token.refreshToken) {
 | 
			
		||||
      return this.http.post<TokenDTO>(`${this.appsettings.getApiURL()}/api/auth/revoke`, token, {
 | 
			
		||||
        headers: new HttpHeaders({
 | 
			
		||||
          'Content-Type': 'application/json'
 | 
			
		||||
        })
 | 
			
		||||
      }).pipe(catchError(error => {
 | 
			
		||||
        error.error = null;
 | 
			
		||||
        throw error;
 | 
			
		||||
      })).subscribe(res => { });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  deleteUserByMail(mail: string) {
 | 
			
		||||
    return this.http.post(`${this.appsettings.getApiURL()}/api/auth/delete-user-by-mail/${mail}`, {
 | 
			
		||||
      headers: new HttpHeaders({
 | 
			
		||||
        'Content-Type': 'application/json'
 | 
			
		||||
      })
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* utils */
 | 
			
		||||
  saveToken(token: TokenDTO): void {
 | 
			
		||||
    localStorage.setItem('jwt', token.token);
 | 
			
		||||
    localStorage.setItem('rjwt', token.refreshToken);
 | 
			
		||||
    if (this.router.url.startsWith('/auth')) {
 | 
			
		||||
      this.router.navigate(['/home']);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getToken(): TokenDTO {
 | 
			
		||||
    return {
 | 
			
		||||
      token: localStorage.getItem('jwt'),
 | 
			
		||||
      refreshToken: localStorage.getItem('rjwt')
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getDecodedToken(): string {
 | 
			
		||||
    return this.jwtHelper.decodeToken(this.getToken().token);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async isUserLoggedInAsync(): Promise<boolean> {
 | 
			
		||||
    this.isLoggedIn = await this._isUserLoggedInAsync();
 | 
			
		||||
    return this.isLoggedIn;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async _isUserLoggedInAsync(): Promise<boolean> {
 | 
			
		||||
    const token = this.getToken();
 | 
			
		||||
    if (!token || !token.refreshToken) {
 | 
			
		||||
      this.isLoggedIn = false;
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (token.token && !this.jwtHelper.isTokenExpired(token.token)) {
 | 
			
		||||
      this.isLoggedIn = true;
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (this.isLoggedIn !== false) {
 | 
			
		||||
      this.spinnerService.showSpinner();
 | 
			
		||||
      const resfreshedToken = await this.refresh(token)
 | 
			
		||||
        .pipe(catchError(err => {
 | 
			
		||||
          this.logout();
 | 
			
		||||
          this.spinnerService.hideSpinner();
 | 
			
		||||
          throw err;
 | 
			
		||||
        }))
 | 
			
		||||
        .toPromise();
 | 
			
		||||
      this.spinnerService.hideSpinner();
 | 
			
		||||
      if (resfreshedToken) {
 | 
			
		||||
        this.saveToken(resfreshedToken);
 | 
			
		||||
        return true;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    this.isLoggedIn = false;
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async hasUserPermission(role: AuthRoles): Promise<boolean> {
 | 
			
		||||
    if (!role || !await this.isUserLoggedInAsync()) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
    const token = this.getDecodedToken();
 | 
			
		||||
    return token['http://schemas.microsoft.com/ws/2008/06/identity/claims/role'] === AuthRoles[role];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getEMailFromDecodedToken(token: string): string {
 | 
			
		||||
    if (!token) {
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
    return token['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name'];
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,16 @@
 | 
			
		||||
import { TestBed } from '@angular/core/testing';
 | 
			
		||||
 | 
			
		||||
import { ConfirmationDialogService } from './confirmation-dialog.service';
 | 
			
		||||
 | 
			
		||||
describe('ConfirmationDialogService', () => {
 | 
			
		||||
  let service: ConfirmationDialogService;
 | 
			
		||||
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    TestBed.configureTestingModule({});
 | 
			
		||||
    service = TestBed.inject(ConfirmationDialogService);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should be created', () => {
 | 
			
		||||
    expect(service).toBeTruthy();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
@@ -0,0 +1,53 @@
 | 
			
		||||
import { Injectable } from '@angular/core';
 | 
			
		||||
import { ConfirmationService } from 'primeng/api';
 | 
			
		||||
import { ConfirmationDialog } from 'src/app/models/utils/confirmation-dialog';
 | 
			
		||||
 | 
			
		||||
@Injectable({
 | 
			
		||||
  providedIn: 'root'
 | 
			
		||||
})
 | 
			
		||||
export class ConfirmationDialogService {
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private confirmationService: ConfirmationService
 | 
			
		||||
  ) { }
 | 
			
		||||
 | 
			
		||||
  errorDialog(header: string, message: string) {
 | 
			
		||||
    this.confirmationService.confirm({
 | 
			
		||||
      key: 'errorConfirmationDialog',
 | 
			
		||||
      header: header,
 | 
			
		||||
      message: message
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  confirmDialog(header: string, message: string, accept?: () => void, reject?: () => void) {
 | 
			
		||||
    let options: ConfirmationDialog = {
 | 
			
		||||
      key: 'confirmConfirmationDialog',
 | 
			
		||||
      header: header,
 | 
			
		||||
      message: message
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (accept) {
 | 
			
		||||
      options.accept = accept;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (reject) {
 | 
			
		||||
      options.reject = reject;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.confirmationService.confirm(options);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  warningDialog(header: string, message: string, accept?: () => void) {
 | 
			
		||||
    let options: ConfirmationDialog = {
 | 
			
		||||
      key: 'warningConfirmationDialog',
 | 
			
		||||
      header: header,
 | 
			
		||||
      message: message
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (accept) {
 | 
			
		||||
      options.accept = accept;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.confirmationService.confirm(options);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,16 @@
 | 
			
		||||
import { TestBed } from '@angular/core/testing';
 | 
			
		||||
 | 
			
		||||
import { DataService } from './data.service';
 | 
			
		||||
 | 
			
		||||
describe('DataService', () => {
 | 
			
		||||
  let service: DataService;
 | 
			
		||||
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    TestBed.configureTestingModule({});
 | 
			
		||||
    service = TestBed.inject(DataService);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should be created', () => {
 | 
			
		||||
    expect(service).toBeTruthy();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										15
									
								
								frontend/login-counter/src/app/services/data/data.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								frontend/login-counter/src/app/services/data/data.service.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
import { HttpClient, HttpHeaders } from '@angular/common/http';
 | 
			
		||||
import { Injectable } from '@angular/core';
 | 
			
		||||
import { Observable } from 'rxjs';
 | 
			
		||||
import { SettingsService } from '../settings/settings.service';
 | 
			
		||||
 | 
			
		||||
@Injectable({
 | 
			
		||||
  providedIn: 'root'
 | 
			
		||||
})
 | 
			
		||||
export class DataService {
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private appsettings: SettingsService,
 | 
			
		||||
    private http: HttpClient,
 | 
			
		||||
  ) { }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,16 @@
 | 
			
		||||
import { TestBed } from '@angular/core/testing';
 | 
			
		||||
 | 
			
		||||
import { ErrorHandlerService } from './error-handler.service';
 | 
			
		||||
 | 
			
		||||
describe('ErrorHandlerService', () => {
 | 
			
		||||
  let service: ErrorHandlerService;
 | 
			
		||||
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    TestBed.configureTestingModule({});
 | 
			
		||||
    service = TestBed.inject(ErrorHandlerService);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should be created', () => {
 | 
			
		||||
    expect(service).toBeTruthy();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
@@ -0,0 +1,34 @@
 | 
			
		||||
import { HttpErrorResponse } from '@angular/common/http';
 | 
			
		||||
import { ErrorHandler, Injectable, Injector } from '@angular/core';
 | 
			
		||||
import { Observable, throwError } from 'rxjs';
 | 
			
		||||
import { ErrorDTO } from 'src/app/models/error/error-dto';
 | 
			
		||||
import { ToastService } from '../toast/toast.service';
 | 
			
		||||
 | 
			
		||||
@Injectable()
 | 
			
		||||
export class ErrorHandlerService implements ErrorHandler {
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private injector: Injector
 | 
			
		||||
  ) { }
 | 
			
		||||
 | 
			
		||||
  handleError(error: HttpErrorResponse): Observable<never> {
 | 
			
		||||
    if (error && error.error) {
 | 
			
		||||
      let message = 'Unbekannter Fehler';
 | 
			
		||||
      let header = 'Fehler';
 | 
			
		||||
      const errorDto: ErrorDTO = error.error;
 | 
			
		||||
 | 
			
		||||
      if (errorDto.errorCode !== undefined) {
 | 
			
		||||
        header = 'Fehlercode: ' + errorDto.errorCode;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (errorDto.message) {
 | 
			
		||||
        message = errorDto.message;
 | 
			
		||||
      } else if (error.message) {
 | 
			
		||||
        message = error.message;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this.injector.get(ToastService).error(header, message);
 | 
			
		||||
    }
 | 
			
		||||
    return throwError(error);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,16 @@
 | 
			
		||||
import { TestBed } from '@angular/core/testing';
 | 
			
		||||
 | 
			
		||||
import { GuiService } from './gui.service';
 | 
			
		||||
 | 
			
		||||
describe('GuiService', () => {
 | 
			
		||||
  let service: GuiService;
 | 
			
		||||
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    TestBed.configureTestingModule({});
 | 
			
		||||
    service = TestBed.inject(GuiService);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should be created', () => {
 | 
			
		||||
    expect(service).toBeTruthy();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										41
									
								
								frontend/login-counter/src/app/services/gui/gui.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								frontend/login-counter/src/app/services/gui/gui.service.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
import { HttpClient, HttpHeaders } from '@angular/common/http';
 | 
			
		||||
import { Injectable } from '@angular/core';
 | 
			
		||||
import { Observable, Subscribable } from 'rxjs';
 | 
			
		||||
import { SettingsDTO } from 'src/app/models/config/settings.dto';
 | 
			
		||||
import { SoftwareVersionDTO } from 'src/app/models/config/software-version.dto';
 | 
			
		||||
import { SettingsService } from '../settings/settings.service';
 | 
			
		||||
 | 
			
		||||
@Injectable({
 | 
			
		||||
  providedIn: 'root'
 | 
			
		||||
})
 | 
			
		||||
export class GuiService {
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private appsettings: SettingsService,
 | 
			
		||||
    private http: HttpClient,
 | 
			
		||||
  ) { }
 | 
			
		||||
 | 
			
		||||
  getApiVersion(): Observable<SoftwareVersionDTO> {
 | 
			
		||||
    return this.http.get<SoftwareVersionDTO>(`${this.appsettings.getApiURL()}/api/gui/api-version`, {
 | 
			
		||||
      headers: new HttpHeaders({
 | 
			
		||||
        'Content-Type': 'application/json'
 | 
			
		||||
      })
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getSettings(): Observable<SettingsDTO> {
 | 
			
		||||
    return this.http.get<SettingsDTO>(`${this.appsettings.getApiURL()}/api/gui/settings`, {
 | 
			
		||||
      headers: new HttpHeaders({
 | 
			
		||||
        'Content-Type': 'application/json'
 | 
			
		||||
      })
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  sendTestMail(mail: string): Observable<unknown> {
 | 
			
		||||
    return this.http.post(`${this.appsettings.getApiURL()}/api/gui/send-test-mail/${mail}`, {
 | 
			
		||||
      headers: new HttpHeaders({
 | 
			
		||||
        'Content-Type': 'application/json'
 | 
			
		||||
      })
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,16 @@
 | 
			
		||||
import { TestBed } from '@angular/core/testing';
 | 
			
		||||
 | 
			
		||||
import { SettingsService } from './settings.service';
 | 
			
		||||
 | 
			
		||||
describe('SettingsService', () => {
 | 
			
		||||
  let service: SettingsService;
 | 
			
		||||
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    TestBed.configureTestingModule({});
 | 
			
		||||
    service = TestBed.inject(SettingsService);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should be created', () => {
 | 
			
		||||
    expect(service).toBeTruthy();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
@@ -0,0 +1,62 @@
 | 
			
		||||
import { HttpClient } from '@angular/common/http';
 | 
			
		||||
import { Injectable } from '@angular/core';
 | 
			
		||||
import { throwError } from 'rxjs';
 | 
			
		||||
import { catchError } from 'rxjs/operators';
 | 
			
		||||
import { Appsettings } from 'src/app/models/config/appsettings';
 | 
			
		||||
import { SoftwareVersion } from 'src/app/models/config/software-version';
 | 
			
		||||
import { Theme } from 'src/app/models/view/theme';
 | 
			
		||||
import { Themes } from 'src/app/models/view/themes.enum';
 | 
			
		||||
 | 
			
		||||
@Injectable({
 | 
			
		||||
  providedIn: 'root'
 | 
			
		||||
})
 | 
			
		||||
export class SettingsService {
 | 
			
		||||
  appsettings: Appsettings;
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private http: HttpClient
 | 
			
		||||
  ) { }
 | 
			
		||||
 | 
			
		||||
  loadSettings(): Promise<Appsettings> {
 | 
			
		||||
    return new Promise((resolve, reject) => {
 | 
			
		||||
      this.http.get<Appsettings>('../../assets/config.json')
 | 
			
		||||
        .pipe(catchError(error => {
 | 
			
		||||
          reject(error);
 | 
			
		||||
          return throwError(error);
 | 
			
		||||
        })).subscribe(settings => {
 | 
			
		||||
          this.appsettings = settings;
 | 
			
		||||
          resolve(settings);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public getApiURL(): string {
 | 
			
		||||
    if (!this.appsettings || !this.appsettings.ApiURL) {
 | 
			
		||||
      console.error('ApiURL is not set!');
 | 
			
		||||
      return '';
 | 
			
		||||
    }
 | 
			
		||||
    return this.appsettings.ApiURL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public getWebVersion(): SoftwareVersion {
 | 
			
		||||
    if (!this.appsettings || !this.appsettings.WebVersion) {
 | 
			
		||||
      console.error('WebVersion is not set!');
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
    const webVersion = new SoftwareVersion(
 | 
			
		||||
      this.appsettings.WebVersion.Major,
 | 
			
		||||
      this.appsettings.WebVersion.Minor,
 | 
			
		||||
      this.appsettings.WebVersion.Micro
 | 
			
		||||
    );
 | 
			
		||||
    return webVersion;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public getThemes(): Theme[] {
 | 
			
		||||
    if (!this.appsettings || !this.appsettings.Themes) {
 | 
			
		||||
      console.error('Themes is not set!');
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
    return this.appsettings.Themes;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -0,0 +1,16 @@
 | 
			
		||||
import { TestBed } from '@angular/core/testing';
 | 
			
		||||
 | 
			
		||||
import { SignalRService } from './signalr.service';
 | 
			
		||||
 | 
			
		||||
describe('SignalrService', () => {
 | 
			
		||||
  let service: SignalRService;
 | 
			
		||||
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    TestBed.configureTestingModule({});
 | 
			
		||||
    service = TestBed.inject(SignalRService);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should be created', () => {
 | 
			
		||||
    expect(service).toBeTruthy();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
@@ -0,0 +1,59 @@
 | 
			
		||||
import { Injectable } from '@angular/core';
 | 
			
		||||
import * as signalR from "@aspnet/signalr";
 | 
			
		||||
import { ToastOptions } from 'src/app/models/utils/toast-options';
 | 
			
		||||
import { SettingsService } from '../settings/settings.service';
 | 
			
		||||
import { SpinnerService } from '../spinner/spinner.service';
 | 
			
		||||
import { ToastService } from '../toast/toast.service';
 | 
			
		||||
 | 
			
		||||
@Injectable({
 | 
			
		||||
  providedIn: 'root'
 | 
			
		||||
})
 | 
			
		||||
export class SignalRService {
 | 
			
		||||
 | 
			
		||||
  hubConnection: signalR.HubConnection;
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private settingsService: SettingsService,
 | 
			
		||||
    private toastService: ToastService,
 | 
			
		||||
    private spinnerService: SpinnerService
 | 
			
		||||
  ) { }
 | 
			
		||||
 | 
			
		||||
  startSignalR() {
 | 
			
		||||
    this.hubConnection = new signalR.HubConnectionBuilder()
 | 
			
		||||
      .configureLogging(signalR.LogLevel.Information)
 | 
			
		||||
      .withUrl(this.settingsService.getApiURL() + '/notify')
 | 
			
		||||
      .build();
 | 
			
		||||
 | 
			
		||||
    this.hubConnection.start().then(() => {
 | 
			
		||||
      console.log('Connected!');
 | 
			
		||||
    }).catch((err) => {
 | 
			
		||||
      const options: ToastOptions = {
 | 
			
		||||
        sticky: true,
 | 
			
		||||
        closable: false
 | 
			
		||||
      };
 | 
			
		||||
      this.spinnerService.showSpinner();
 | 
			
		||||
      this.toastService.error("Server nicht erreichbar", "Die Verbindung zum Server konnte nicht hergestellt werden!\nLaden Sie die Seite neu.", options);
 | 
			
		||||
      return console.error(err.toString());
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    this.hubConnection.onreconnected(() => {
 | 
			
		||||
      if (this.spinnerService.showSpinnerState) {
 | 
			
		||||
        this.spinnerService.hideSpinner();
 | 
			
		||||
        const options: ToastOptions = {
 | 
			
		||||
          closable: false
 | 
			
		||||
        };
 | 
			
		||||
        this.toastService.info("Server verbunden", "Die Verbindung zum Server konnte hergestellt werden.", options);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    this.hubConnection.onclose(() => {
 | 
			
		||||
      console.log('Disconnected');
 | 
			
		||||
      const options: ToastOptions = {
 | 
			
		||||
        sticky: true,
 | 
			
		||||
        closable: false
 | 
			
		||||
      };
 | 
			
		||||
      this.spinnerService.showSpinner();
 | 
			
		||||
      this.toastService.error("Server nicht erreichbar", "Die Verbindung zum Server konnte nicht hergestellt werden!\nLaden Sie die Seite neu.", options);
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,16 @@
 | 
			
		||||
import { TestBed } from '@angular/core/testing';
 | 
			
		||||
 | 
			
		||||
import { SpinnerService } from './spinner.service';
 | 
			
		||||
 | 
			
		||||
describe('SpinnerService', () => {
 | 
			
		||||
  let service: SpinnerService;
 | 
			
		||||
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    TestBed.configureTestingModule({});
 | 
			
		||||
    service = TestBed.inject(SpinnerService);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should be created', () => {
 | 
			
		||||
    expect(service).toBeTruthy();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
@@ -0,0 +1,22 @@
 | 
			
		||||
import { Injectable } from '@angular/core';
 | 
			
		||||
 | 
			
		||||
@Injectable({
 | 
			
		||||
  providedIn: 'root'
 | 
			
		||||
})
 | 
			
		||||
export class SpinnerService {
 | 
			
		||||
 | 
			
		||||
  showSpinnerState = false;
 | 
			
		||||
  constructor() { }
 | 
			
		||||
 | 
			
		||||
  showSpinner() {
 | 
			
		||||
    this.showSpinnerState = true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  hideSpinner() {
 | 
			
		||||
    this.showSpinnerState = false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  toggleSpinner() {
 | 
			
		||||
    this.showSpinnerState = !this.showSpinnerState;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,16 @@
 | 
			
		||||
import { TestBed } from '@angular/core/testing';
 | 
			
		||||
 | 
			
		||||
import { ThemeService } from './theme.service';
 | 
			
		||||
 | 
			
		||||
describe('ThemeService', () => {
 | 
			
		||||
  let service: ThemeService;
 | 
			
		||||
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    TestBed.configureTestingModule({});
 | 
			
		||||
    service = TestBed.inject(ThemeService);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should be created', () => {
 | 
			
		||||
    expect(service).toBeTruthy();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
@@ -0,0 +1,92 @@
 | 
			
		||||
import { Injectable } from '@angular/core';
 | 
			
		||||
import { Themes } from 'src/app/models/view/themes.enum';
 | 
			
		||||
import { AuthService } from '../auth/auth.service';
 | 
			
		||||
 | 
			
		||||
@Injectable({
 | 
			
		||||
  providedIn: 'root'
 | 
			
		||||
})
 | 
			
		||||
export class ThemeService {
 | 
			
		||||
 | 
			
		||||
  themeName: string;
 | 
			
		||||
 | 
			
		||||
  sidebarWidth = '150px';
 | 
			
		||||
  isSidebarOpen = false;
 | 
			
		||||
  hasLangChanged = false;
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private authService: AuthService
 | 
			
		||||
  ) {
 | 
			
		||||
    this.loadTheme();
 | 
			
		||||
    this.loadMenu();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  loadTheme(): void {
 | 
			
		||||
    const token = this.authService.getDecodedToken();
 | 
			
		||||
    const mail = this.authService.getEMailFromDecodedToken(token);
 | 
			
		||||
 | 
			
		||||
    if (!mail) {
 | 
			
		||||
      this.themeName = localStorage.getItem(`default_themeName`);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let themeName = localStorage.getItem(`${mail}_themeName`);
 | 
			
		||||
    if (!themeName) {
 | 
			
		||||
      themeName = Themes.DefaultLight;
 | 
			
		||||
      this.setTheme(themeName);
 | 
			
		||||
    }
 | 
			
		||||
    this.themeName = themeName;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  setTheme(name: string): void {
 | 
			
		||||
    this.authService.isUserLoggedInAsync().then(result => {
 | 
			
		||||
      if (!result) {
 | 
			
		||||
        localStorage.setItem(`default_themeName`, Themes.DefaultLight);
 | 
			
		||||
        this.themeName = Themes.DefaultLight;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const token = this.authService.getDecodedToken();
 | 
			
		||||
      const mail = this.authService.getEMailFromDecodedToken(token);
 | 
			
		||||
      localStorage.setItem(`${mail}_themeName`, name);
 | 
			
		||||
      localStorage.setItem(`default_themeName`, name);
 | 
			
		||||
      this.themeName = name;
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  loadMenu() {
 | 
			
		||||
    const token = this.authService.getDecodedToken();
 | 
			
		||||
    const mail = this.authService.getEMailFromDecodedToken(token);
 | 
			
		||||
 | 
			
		||||
    if (!mail) {
 | 
			
		||||
      this.setSideWidth(true);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let isMenuOpen = true;
 | 
			
		||||
    let isMenuOpenStr = localStorage.getItem(`${mail}_isMenuOpen`);
 | 
			
		||||
 | 
			
		||||
    if (isMenuOpenStr != null || isMenuOpenStr != "") {
 | 
			
		||||
      isMenuOpen = Boolean(JSON.parse(isMenuOpenStr));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.setIsMenuOpen(isMenuOpen);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  setIsMenuOpen(isMenuOpen: boolean) {
 | 
			
		||||
    this.authService.isUserLoggedInAsync().then(result => {
 | 
			
		||||
      if (!result) {
 | 
			
		||||
        this.setSideWidth(true);
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const token = this.authService.getDecodedToken();
 | 
			
		||||
      const mail = this.authService.getEMailFromDecodedToken(token);
 | 
			
		||||
      localStorage.setItem(`${mail}_isMenuOpen`, isMenuOpen + "");
 | 
			
		||||
      this.setSideWidth(isMenuOpen);
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  setSideWidth($event): void {
 | 
			
		||||
    this.sidebarWidth = $event ? '150px' : '50px';
 | 
			
		||||
    this.isSidebarOpen = $event;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,16 @@
 | 
			
		||||
import { TestBed } from '@angular/core/testing';
 | 
			
		||||
 | 
			
		||||
import { ToastService } from './toast.service';
 | 
			
		||||
 | 
			
		||||
describe('ToastService', () => {
 | 
			
		||||
  let service: ToastService;
 | 
			
		||||
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    TestBed.configureTestingModule({});
 | 
			
		||||
    service = TestBed.inject(ToastService);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should be created', () => {
 | 
			
		||||
    expect(service).toBeTruthy();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
@@ -0,0 +1,40 @@
 | 
			
		||||
import { Injectable } from '@angular/core';
 | 
			
		||||
import { MessageService } from 'primeng/api';
 | 
			
		||||
import { ToastOptions } from 'src/app/models/utils/toast-options';
 | 
			
		||||
 | 
			
		||||
@Injectable({
 | 
			
		||||
  providedIn: 'root'
 | 
			
		||||
})
 | 
			
		||||
export class ToastService {
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private messageService: MessageService
 | 
			
		||||
  ) { }
 | 
			
		||||
 | 
			
		||||
  private toast(type: string, summary: string, detail: string, options: ToastOptions = null) {
 | 
			
		||||
    this.messageService.add({
 | 
			
		||||
      severity: type,
 | 
			
		||||
      summary: summary,
 | 
			
		||||
      detail: detail,
 | 
			
		||||
      life: options ? options.life: null,
 | 
			
		||||
      sticky: options ? options.sticky: null,
 | 
			
		||||
      closable: options ? options.closable: null
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  success(summary: string, detail: string, options: ToastOptions = null) {
 | 
			
		||||
    this.toast('success', summary, detail, options);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  info(summary: string, detail: string, options: ToastOptions = null) {
 | 
			
		||||
    this.toast('info', summary, detail, options);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  warn(summary: string, detail: string, options: ToastOptions = null) {
 | 
			
		||||
    this.toast('warn', summary, detail, options);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  error(summary: string, detail: string, options: ToastOptions = null) {
 | 
			
		||||
    this.toast('error', summary, detail, options);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user