fix(frontend): annule le chargement en cours lors d'un changement rapide de site
Sans switchMap sur le flux externe, une réponse HTTP en retard pouvait écraser l'affichage du site actuellement sélectionné après une navigation rapide entre deux sites.
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import { Component, computed, effect, inject, signal } from '@angular/core';
|
import { Component, DestroyRef, computed, inject, signal } from '@angular/core';
|
||||||
import { toSignal } from '@angular/core/rxjs-interop';
|
import { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop';
|
||||||
import { ActivatedRoute, RouterLink } from '@angular/router';
|
import { ActivatedRoute, RouterLink } from '@angular/router';
|
||||||
import { catchError, EMPTY, map, Observable, switchMap } from 'rxjs';
|
import { catchError, EMPTY, filter, map, Observable, switchMap } from 'rxjs';
|
||||||
import { SitesService } from '../../../core/services/sites.service';
|
import { SitesService } from '../../../core/services/sites.service';
|
||||||
import { ReadingsService } from '../../../core/services/readings.service';
|
import { ReadingsService } from '../../../core/services/readings.service';
|
||||||
import { Site } from '../../../shared/models/site.model';
|
import { Site } from '../../../shared/models/site.model';
|
||||||
@@ -83,6 +83,7 @@ export class SiteDetail {
|
|||||||
private route = inject(ActivatedRoute);
|
private route = inject(ActivatedRoute);
|
||||||
private sitesService = inject(SitesService);
|
private sitesService = inject(SitesService);
|
||||||
private readingsService = inject(ReadingsService);
|
private readingsService = inject(ReadingsService);
|
||||||
|
private destroyRef = inject(DestroyRef);
|
||||||
|
|
||||||
siteId = toSignal(this.route.paramMap.pipe(map((params) => params.get('siteId') ?? '')));
|
siteId = toSignal(this.route.paramMap.pipe(map((params) => params.get('siteId') ?? '')));
|
||||||
|
|
||||||
@@ -105,11 +106,19 @@ export class SiteDetail {
|
|||||||
});
|
});
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
effect(() => {
|
toObservable(this.siteId)
|
||||||
const siteId = this.siteId();
|
.pipe(
|
||||||
if (siteId) {
|
filter((siteId): siteId is string => !!siteId),
|
||||||
this.load(siteId);
|
// Piège : switchMap sur le flux externe annule le chargement en cours dès qu'un
|
||||||
}
|
// nouveau siteId arrive, sinon une réponse en retard peut écraser le site affiché.
|
||||||
|
switchMap((siteId) => this.load(siteId)),
|
||||||
|
takeUntilDestroyed(this.destroyRef),
|
||||||
|
)
|
||||||
|
.subscribe((result) => {
|
||||||
|
this.error.set(null);
|
||||||
|
this.site.set(result.site);
|
||||||
|
this.latestReading.set(result.latest);
|
||||||
|
this.history.set(result.history);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,10 +126,8 @@ export class SiteDetail {
|
|||||||
return status ? (TON_PAR_STATUT[status] ?? 'neutral') : 'neutral';
|
return status ? (TON_PAR_STATUT[status] ?? 'neutral') : 'neutral';
|
||||||
}
|
}
|
||||||
|
|
||||||
private load(siteId: string): void {
|
private load(siteId: string) {
|
||||||
this.sitesService
|
return this.sitesService.getSite(siteId).pipe(
|
||||||
.getSite(siteId)
|
|
||||||
.pipe(
|
|
||||||
switchMap((site) =>
|
switchMap((site) =>
|
||||||
this.readingsService.getLatest(siteId).pipe(map((latest) => ({ site, latest }))),
|
this.readingsService.getLatest(siteId).pipe(map((latest) => ({ site, latest }))),
|
||||||
),
|
),
|
||||||
@@ -137,13 +144,7 @@ export class SiteDetail {
|
|||||||
.pipe(map((history) => ({ site, latest, history })));
|
.pipe(map((history) => ({ site, latest, history })));
|
||||||
}),
|
}),
|
||||||
catchError(() => this.reportUnavailable()),
|
catchError(() => this.reportUnavailable()),
|
||||||
)
|
);
|
||||||
.subscribe((result) => {
|
|
||||||
this.error.set(null);
|
|
||||||
this.site.set(result.site);
|
|
||||||
this.latestReading.set(result.latest);
|
|
||||||
this.history.set(result.history);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private reasonFor(field: MetricKey, reading: Reading | null): string {
|
private reasonFor(field: MetricKey, reading: Reading | null): string {
|
||||||
|
|||||||
Reference in New Issue
Block a user