donmahallem/TrapezeClientNg

View on GitHub
src/app/modules/main-map/main-map-route-display-handler.ts

Summary

Maintainability
A
1 hr
Test Coverage
import { IVehiclePathInfo, TripId } from '@donmahallem/trapeze-api-types';
import * as L from 'leaflet';
import { from, BehaviorSubject, Observable, Subscriber, Subscription } from 'rxjs';
import { catchError, debounceTime, flatMap } from 'rxjs/operators';
import { RouteDisplayHandler } from 'src/app/leaflet';
import { ApiService } from 'src/app/services';
export interface IData {
    hovering: boolean;
    tripId?: TripId;
}
/**
 * Handles polling and displaying of route data on the map
 */
export class MainMapRouteDisplayHandler extends RouteDisplayHandler {
    private updateSubject: BehaviorSubject<IData> = new BehaviorSubject({
        hovering: false,
    });
    private subscription: Subscription;
    /**
     *
     * @param map The map to display the route on
     * @param api the api service to be used
     */
    constructor(map: L.Map, private api: ApiService) {
        super(map);
    }

    /**
     * Does start the updating loop
     */
    public start(): void {
        if (this.subscription && !this.subscription.closed) {
            return;
        }
        this.subscription = this.updateSubject
            .pipe(debounceTime(200))
            .pipe(flatMap((value: IData): Observable<IVehiclePathInfo> => {
                if (value.hovering) {
                    return this.api.getRouteByTripId(value.tripId)
                        .pipe(catchError(() => from([undefined])));
                } else {
                    return from([undefined]);
                }
            }))
            .subscribe(new Subscriber((value: any) => {
                if (value) {
                    if (value.paths && value.paths.length > 0) {
                        this.setRoutePaths(value.paths);
                        return;
                    }
                }
                this.clear();
            }));
    }

    /**
     * Does update the interal state. For display purposese calling start is required but doesn't require
     * to be called before.
     * @param isHovering indicates if the mouse is hovering
     * @param tripId optional TripId
     */
    public setMouseHovering(isHovering: boolean, tripId?: TripId): void {
        this.updateSubject.next({
            hovering: isHovering,
            tripId,
        });
    }

    /**
     * Has to be called to stop the underlying observable
     */
    public stop(): void {
        if (this.subscription) {
            this.subscription.unsubscribe();
        }
    }
}