adding HttpInterceptors...

This commit is contained in:
Maria Teresa Paratore 2023-11-21 18:50:56 +01:00
parent 31a74a259a
commit 5988c79723
12 changed files with 168 additions and 87 deletions

View File

@ -1,6 +1,6 @@
import { NgModule, LOCALE_ID, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { NgModule, LOCALE_ID, CUSTOM_ELEMENTS_SCHEMA, importProvidersFrom } from '@angular/core';
import { registerLocaleData } from '@angular/common'; import { registerLocaleData } from '@angular/common';
import { HttpClientModule } from '@angular/common/http'; import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
import locale from '@angular/common/locales/en'; import locale from '@angular/common/locales/en';
import { BrowserModule, Title } from '@angular/platform-browser'; import { BrowserModule, Title } from '@angular/platform-browser';
import { ServiceWorkerModule } from '@angular/service-worker'; import { ServiceWorkerModule } from '@angular/service-worker';
@ -18,7 +18,6 @@ import { HomeModule} from './home/home.module';
// jhipster-needle-angular-add-module-import JHipster will add new module here // jhipster-needle-angular-add-module-import JHipster will add new module here
import { NgbDateDayjsAdapter } from './config/datepicker-adapter'; import { NgbDateDayjsAdapter } from './config/datepicker-adapter';
import { fontAwesomeIcons } from './config/font-awesome-icons'; import { fontAwesomeIcons } from './config/font-awesome-icons';
import { httpInterceptorProviders } from 'app/core/interceptor/index';
import { MainComponent } from './layouts/main/main.component'; import { MainComponent } from './layouts/main/main.component';
import { NavbarComponent } from './layouts/navbar/navbar.component'; import { NavbarComponent } from './layouts/navbar/navbar.component';
import { FooterComponent } from './layouts/footer/footer.component'; import { FooterComponent } from './layouts/footer/footer.component';
@ -29,6 +28,7 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { RawjsonPaneComponent } from './rawjson-pane/rawjson-pane.component'; import { RawjsonPaneComponent } from './rawjson-pane/rawjson-pane.component';
import { ClipboardModule } from '@angular/cdk/clipboard'; import { ClipboardModule } from '@angular/cdk/clipboard';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { SpinnercontrolInterceptor } from './shared/spinnercontrol.interceptor';
@NgModule({ @NgModule({
imports: [ imports: [
@ -51,6 +51,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
Title, Title,
{ provide: LOCALE_ID, useValue: 'en' }, { provide: LOCALE_ID, useValue: 'en' },
{ provide: NgbDateAdapter, useClass: NgbDateDayjsAdapter }, { provide: NgbDateAdapter, useClass: NgbDateDayjsAdapter },
{provide:HTTP_INTERCEPTORS,useClass:SpinnercontrolInterceptor, multi: true}
], ],
declarations: [MainComponent, NavbarComponent, ErrorComponent, PageRibbonComponent, ActiveMenuDirective, FooterComponent], declarations: [MainComponent, NavbarComponent, ErrorComponent, PageRibbonComponent, ActiveMenuDirective, FooterComponent],
bootstrap: [MainComponent], bootstrap: [MainComponent],

View File

@ -8,9 +8,7 @@ export function instanceOfContext(context: any): boolean{
const res = !!context // truthy const res = !!context // truthy
&& typeof context !== 'string' // Not just string input in the autocomplete && typeof context !== 'string' // Not just string input in the autocomplete
&& 'name' in context; // Has some qualifying property of context type && 'name' in context; // Has some qualifying property of context type
console.debug("--- In instanceOfContext: ");
console.debug(res); console.debug(res);
console.debug("---");
return res; return res;
} }

View File

@ -1,10 +1,7 @@
<div class="row" > <div class="row" >
<div *ngIf="ctxLoaderService.isLoading|async" class="loader-container"> <div *ngIf="loading" class="loader-container">
<mat-progress-bar mode="indeterminate" ></mat-progress-bar> <mat-spinner mode="indeterminate" style="top: 50%; left: 50%;"></mat-spinner>
</div> </div>
<div class="d-flex flex-row py-4"> <div class="d-flex flex-row py-4">
<div id="btn-group" class="col-md-3 mt-3"> <div id="btn-group" class="col-md-3 mt-3">
<button mat-raised-button color="primary"><mat-icon>source</mat-icon> <span>File</span></button> <button mat-raised-button color="primary"><mat-icon>source</mat-icon> <span>File</span></button>
@ -18,6 +15,8 @@
<jhi-rsc-tree (resourceTypeEm)="buildTableData($event)"></jhi-rsc-tree> <jhi-rsc-tree (resourceTypeEm)="buildTableData($event)"></jhi-rsc-tree>
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-9"> <div class="col-md-9">

View File

@ -23,20 +23,11 @@ Main page styles
} }
.loader-container{ .loader-container{
position: fixed; position: absolute;
height: 100%;
width: 100%; width: 100%;
background: black;
opacity: 0.3;
z-index: 99; z-index: 99;
} }
/*
.loading-container {
display: flex;
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0,0,0,0.7);
z-index: 5;
}
*/

View File

@ -12,17 +12,18 @@ import { AccountService } from 'app/core/auth/account.service';
import { Account } from 'app/core/auth/account.model'; import { Account } from 'app/core/auth/account.model';
import { AbstractControl, FormBuilder, FormControl, FormGroup, ValidationErrors, ValidatorFn, Validators } from '@angular/forms'; import { AbstractControl, FormBuilder, FormControl, FormGroup, ValidationErrors, ValidatorFn, Validators } from '@angular/forms';
import { Clipboard } from '@angular/cdk/clipboard' import { Clipboard } from '@angular/cdk/clipboard'
import { Observable, delay, map, startWith } from 'rxjs'; import { BehaviorSubject, Observable, delay, map, startWith } from 'rxjs';
import { ContextsLoaderService } from 'app/services/contexts-loader.service'; import { ContextsLoaderService } from 'app/services/contexts-loader.service';
import { IContextNode } from 'app/services/i-context-node'; import { IContextNode } from 'app/services/i-context-node';
import { AutofillValidator, instanceOfContext } from './autofill-validator'; import { AutofillValidator, instanceOfContext } from './autofill-validator';
import { SpinnerLoadingService } from 'app/services/spinner-loading.service';
@Component({ @Component({
selector: 'jhi-home', selector: 'jhi-home',
templateUrl: './home.component.html', templateUrl: './home.component.html',
styleUrls: ['./home.component.scss'], styleUrls: ['./home.component.scss'],
providers: [ContextsLoaderService], providers: [ContextsLoaderService, SpinnerLoadingService],
}) })
export class HomeComponent implements OnInit { export class HomeComponent implements OnInit {
@ -34,13 +35,14 @@ export class HomeComponent implements OnInit {
//public filteredContextsStr: Observable<string[]>| undefined; //public filteredContextsStr: Observable<string[]>| undefined;
chooseContextForm: FormGroup | any; chooseContextForm: FormGroup | any;
resType: string; resType: string;
loading: boolean = false; loading: boolean = false;
constructor( constructor(
private accountService: AccountService, private accountService: AccountService,
private loginService: LoginService, private loginService: LoginService,
public ctxLoaderService : ContextsLoaderService, private ctxLoaderService : ContextsLoaderService,
private progressService : SpinnerLoadingService,
private fb: FormBuilder, private fb: FormBuilder,
private clipboard: Clipboard) { private clipboard: Clipboard) {
//initialise on HostingNodes //initialise on HostingNodes
@ -59,7 +61,6 @@ export class HomeComponent implements OnInit {
} }
ngOnInit(): void { ngOnInit(): void {
//this.listenToLoading();
//to identify users and their account //to identify users and their account
this.accountService.identity().subscribe(account => (this.account = account)); this.accountService.identity().subscribe(account => (this.account = account));
this.chooseContextForm = this.fb.group({ this.chooseContextForm = this.fb.group({
@ -67,11 +68,15 @@ export class HomeComponent implements OnInit {
uidfield: [''], uidfield: [''],
}); });
//TODO: DEBUG HERE
//vedi: https://medium.com/swlh/angular-loading-spinner-using-http-interceptor-63c1bb76517b
//per ora ascolto solo il caricamento dei contesti
this.listenToLoading();
// per la form dei contesti // per la form dei contesti
this.ctxLoaderService.fetchAll().subscribe(res => { this.ctxLoaderService.fetchAll().subscribe(res => {
this.allCtxs = res; this.allCtxs = res;
}); });
console.debug("----->val:"+this.chooseContextForm.get('namefield').value);
this.filteredContexts = this.chooseContextForm.get('namefield').valueChanges.pipe( this.filteredContexts = this.chooseContextForm.get('namefield').valueChanges.pipe(
startWith(''), startWith(''),
map(ctx => (ctx ? this.filterContexts(ctx/*,contextInput*/) : this.allCtxs.slice())) map(ctx => (ctx ? this.filterContexts(ctx/*,contextInput*/) : this.allCtxs.slice()))
@ -79,6 +84,18 @@ export class HomeComponent implements OnInit {
} }
/**
* Listen to the loadingSub property in the LoadingService class. This drives the
* display of the loading spinner.
*/
listenToLoading(): void {
this.progressService.getState()
.subscribe((loading) => {
this.loading = loading;
console.debug("**********this.loading..."+this.loading);
});
}
//mettere ANY come tipo dell'argomento per evitare errore TypeScript nella map!! //mettere ANY come tipo dell'argomento per evitare errore TypeScript nella map!!

View File

@ -15,8 +15,6 @@ import { TableScreenModule } from 'app/table-screen/table-screen.module';
import { TableScreenEsModule } from 'app/table-screen-es/table-screen-es.module'; import { TableScreenEsModule } from 'app/table-screen-es/table-screen-es.module';
import { AsyncPipe, NgSwitchCase, NgSwitchDefault } from '@angular/common'; import { AsyncPipe, NgSwitchCase, NgSwitchDefault } from '@angular/common';
import { MatProgressBarModule } from '@angular/material/progress-bar'; import { MatProgressBarModule } from '@angular/material/progress-bar';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { InterceptorService } from 'app/services/interceptor.service';
@NgModule({ @NgModule({
imports: [SharedModule, imports: [SharedModule,
@ -36,8 +34,5 @@ import { InterceptorService } from 'app/services/interceptor.service';
NgSwitchDefault], NgSwitchDefault],
declarations: [HomeComponent], declarations: [HomeComponent],
schemas:[CUSTOM_ELEMENTS_SCHEMA], schemas:[CUSTOM_ELEMENTS_SCHEMA],
providers:[
{provide:HTTP_INTERCEPTORS,useClass:InterceptorService, multi: true}
]
}) })
export class HomeModule {} export class HomeModule {}

View File

@ -1,7 +1,8 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable no-console */ /* eslint-disable no-console */
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http'; import { HttpClient, HttpHeaders } from '@angular/common/http';
import { BehaviorSubject, Observable, map, tap } from 'rxjs'; import { Observable } from 'rxjs';
import { appProperties } from 'app/config/app-properties'; import { appProperties } from 'app/config/app-properties';
import { IContextNode } from './i-context-node'; import { IContextNode } from './i-context-node';
@ -10,16 +11,16 @@ import { IContextNode } from './i-context-node';
}) })
export class ContextsLoaderService { export class ContextsLoaderService {
public isLoading: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
httpOptions = { httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' }), headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
}; };
constructor(private http: HttpClient) {} constructor(private http: HttpClient) {}
fetchAll(): Observable<IContextNode[]> { fetchAll(): Observable<IContextNode[]> {
return this.http.get<IContextNode[]>(appProperties.BASEURL_API + 'is/allcontexts'); return this.http.get<IContextNode[]>(appProperties.BASEURL_API + 'is/allcontexts');
} }
} }

View File

@ -1,22 +0,0 @@
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { ContextsLoaderService } from './contexts-loader.service';
import { Observable, finalize } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class InterceptorService implements HttpInterceptor{
constructor(public ctxLoaderServ : ContextsLoaderService) { }
intercept(req: HttpRequest<any>, next:HttpHandler): Observable<HttpEvent<any>>{
this.ctxLoaderServ.isLoading.next(true);
return next.handle(req).pipe(
finalize(
()=>{
this.ctxLoaderServ.isLoading.next(false);
})
);
}
}

View File

@ -1,20 +0,0 @@
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { IContextNode } from './i-context-node';
@Injectable({
providedIn: 'root',
})
export class MockCtxloaderService {
httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
};
constructor(private http: HttpClient) {}
getData(): Observable<IContextNode[]> {
//TODO: pipe per gestione errori
return this.http.get<IContextNode[]>('http://localhost:3002/is/allcontexttree');
}
}

View File

@ -1,6 +1,6 @@
/* eslint-disable no-console */ /* eslint-disable no-console */
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs'; import { BehaviorSubject, Observable, Subject } from 'rxjs';
import { appProperties } from 'app/config/app-properties'; import { appProperties } from 'app/config/app-properties';
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { IHostingNode } from './i-hosting-node'; import { IHostingNode } from './i-hosting-node';
@ -11,13 +11,20 @@ import { IEService } from './i-e-service';
}) })
export class ResourcesImplService { export class ResourcesImplService {
public isLoading: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false); //public isLoading: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
httpOptions = { httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' }), headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
}; };
private loading: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
constructor(private http: HttpClient) { } constructor(private http: HttpClient) { }
public isLoading():Observable<any>{
return this.loading;
}
//TODO: qui va messo parametro per paginazione //TODO: qui va messo parametro per paginazione
fetchResourceImpls(ctx:string, type:string): Observable<any[]> { fetchResourceImpls(ctx:string, type:string): Observable<any[]> {
const SERVICE_URL = appProperties.BASEURL_API+'is/resourceinstances'; const SERVICE_URL = appProperties.BASEURL_API+'is/resourceinstances';

View File

@ -0,0 +1,35 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
/* eslint-disable @typescript-eslint/no-empty-function */
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class SpinnerLoadingService {
private state: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);
constructor() { }
getState():Observable<boolean>{
return this.state.asObservable();
};
setState(newState : boolean) : void{
this.state.next(newState);
};
}
/*
*/

View File

@ -0,0 +1,79 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */
/* eslint-disable no-console */
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor,
HttpResponse
} from '@angular/common/http';
import { Observable, finalize, tap } from 'rxjs';
//import { SpinnerLoadingService } from 'app/services/spinner-loading.service';
import { ContextsLoaderService } from 'app/services/contexts-loader.service';
import { SpinnerLoadingService } from 'app/services/spinner-loading.service';
@Injectable()
export class SpinnercontrolInterceptor implements HttpInterceptor {
/*
Like intercept(), the handle() method transforms an HTTP request into an Observable
of HttpEvents which ultimately include the server's response.
The intercept() method could inspect that observable and alter it before returning
it to the caller.
*/
private myService : SpinnerLoadingService;
constructor(private spinnerLoaderServ: SpinnerLoadingService) {
this.myService = spinnerLoaderServ;
}
intercept(req: HttpRequest<any>, next: HttpHandler) {
const started = Date.now();
let ok: string;
// extend server response observable with logging
return next.handle(req)
.pipe(
tap({
// Succeeds when there is a response; ignore other events
next: (event) => (ok = event instanceof HttpResponse ? 'succeeded' : ''),
// Operation failed; error is an HttpErrorResponse
error: (_error) => (ok = 'failed')
}),
// Log when response observable either completes or errors
finalize(() => {
const elapsed = Date.now() - started;
const msg = `${req.method} "${req.urlWithParams}"
${ok} in ${elapsed} ms.`;
console.debug("***** MSG INIZIO ******");
console.debug(msg);
console.debug("***** MSG FINE ******");
this.spinnerLoaderServ.setState(false);
})
);
}
/*
intercept(
request: HttpRequest<any>,next: HttpHandler): Observable<HttpEvent<Response>> {
console.log('********Outgoing HTTP request', request);
if(request.url.includes('resourcetypes')){
return next.handle(request).pipe(
tap((event: HttpEvent<any>) => {
console.log('*******Incoming HTTP response', event);
this.spinnerLoaderServ.setState(false);
})
);
}else{
return new Observable<HttpEvent<any>>();
}
}
*/
}