File

libs/map/src/lib/selector/last-value-map-selector/last-value-map-selector.component.ts

Description

Displays selectable series with their last values on an map.

Extends

MapSelectorComponent

Implements

AfterViewInit DoCheck OnChanges

Metadata

selector n52-last-value-map-selector
styleUrls ../map-selector.component.scss
templateUrl ../map-selector.component.html

Index

Properties
Methods
Inputs
Outputs

Constructor

constructor(mapCache: MapCache, kvDiffers: KeyValueDiffers, iDiffers: IterableDiffers, cd: ChangeDetectorRef, servicesConnector: HelgolandServicesConnector, lastValueLabelGenerator: LastValueLabelGenerator, statusIntervalResolver: StatusIntervalResolverService)
Parameters :
Name Type Optional
mapCache MapCache No
kvDiffers KeyValueDiffers No
iDiffers IterableDiffers No
cd ChangeDetectorRef No
servicesConnector HelgolandServicesConnector No
lastValueLabelGenerator LastValueLabelGenerator No
statusIntervalResolver StatusIntervalResolverService No

Inputs

ignoreStatusIntervalIfBeforeDuration
Default value : Infinity

Ignores all Statusintervals where the timestamp is before a given duration in milliseconds and draws instead the default marker.

lastValuePresentation
Type : LastValuePresentation
Default value : LastValuePresentation.Colorized

Presentation type how to display the series.

lastValueSeriesIDs
Type : string[]
Default value : []

The list of internal series IDs, which should be presented with their last values on the map.

avoidZoomToSelection
Type : boolean
Inherited from MapSelectorComponent
filter
Type : HelgolandParameterFilter
Inherited from MapSelectorComponent
fitBoundsMarkerOptions
Type : L.FitBoundsOptions
Inherited from MapSelectorComponent
markerSelectorGenerator
Type : MarkerSelectorGenerator
Inherited from MapSelectorComponent
serviceUrl
Type : string
Inherited from MapSelectorComponent
baseMaps
Type : LayerMap
Inherited from CachedMapComponent

Map, which holds all base map layer (see: https://leafletjs.com/reference-1.3.4.html#layer)

fitBounds
Type : L.LatLngBoundsExpression
Inherited from CachedMapComponent

Bounds for the map

layerControlOptions
Type : L.Control.LayersOptions
Inherited from CachedMapComponent

Describes the the zoom options (see: https://leafletjs.com/reference-1.3.4.html#control-layers)

mapId
Type : string
Inherited from CachedMapComponent

A map with the given ID is created inside this component. This ID can be used the get the map instance over the map cache service.

mapOptions
Type : L.MapOptions
Inherited from CachedMapComponent

The corresponding leaflet map options (see: https://leafletjs.com/reference-1.3.4.html#map-option)

overlayMaps
Type : LayerMap
Inherited from CachedMapComponent

Map, which holds all overlay map layer (see: https://leafletjs.com/reference-1.3.4.html#layer)

zoomControlOptions
Type : L.Control.ZoomOptions
Inherited from CachedMapComponent

Describes the the zoom control options (see: https://leafletjs.com/reference-1.3.4.html#control-zoom)

Outputs

onContentLoading
Type : EventEmitter<boolean>
Inherited from MapSelectorComponent
onNoResultsFound
Type : EventEmitter<boolean>
Inherited from MapSelectorComponent
onSelected
Type : EventEmitter<T>
Inherited from MapSelectorComponent
mapInitialized
Type : EventEmitter<string>
Inherited from CachedMapComponent

Informs when initialization is done with map id.

Methods

Private createColoredMarker
createColoredMarker(ts: HelgolandTimeseries, color: string)
Parameters :
Name Type Optional
ts HelgolandTimeseries No
color string No
Returns : Layer
Private createColorizedMarker
createColorizedMarker(ts: HelgolandTimeseries)
Parameters :
Name Type Optional
ts HelgolandTimeseries No
Returns : Observable<Layer>
Private createDefaultColoredMarker
createDefaultColoredMarker(ts: HelgolandTimeseries)
Parameters :
Name Type Optional
ts HelgolandTimeseries No
Returns : Layer
Private createFilledMarker
createFilledMarker(ts: HelgolandTimeseries, color: string, radius: number)
Parameters :
Name Type Optional
ts HelgolandTimeseries No
color string No
radius number No
Returns : Layer
Private createLabeledMarker
createLabeledMarker(ts: HelgolandTimeseries)
Parameters :
Name Type Optional
ts HelgolandTimeseries No
Returns : Observable<Layer>
Private createMarker
createMarker(ts: HelgolandTimeseries)
Parameters :
Name Type Optional
ts HelgolandTimeseries No
Returns : any
Private createMarkersBySeriesIDs
createMarkersBySeriesIDs(ids: string[])
Parameters :
Name Type Optional
ids string[] No
Returns : void
Protected drawGeometries
drawGeometries()
Returns : void
Private finalizeMarkerObservables
finalizeMarkerObservables(obsList: Observable[])
Parameters :
Name Type Optional
obsList Observable<any>[] No
Returns : void
Public ngDoCheck
ngDoCheck()
Returns : void
Private removeMarker
removeMarker(markerId: string)
Parameters :
Name Type Optional
markerId string No
Returns : void
Private setId
setId(m: Marker, id: string)
Parameters :
Name Type Optional
m Marker No
id string No
Returns : void
Protected Abstract drawGeometries
drawGeometries()
Inherited from MapSelectorComponent

Draws the geometries

Returns : void
Public ngAfterViewInit
ngAfterViewInit()
Inherited from MapSelectorComponent
Returns : void
Public ngOnChanges
ngOnChanges(changes: SimpleChanges)
Inherited from MapSelectorComponent
Parameters :
Name Type Optional
changes SimpleChanges No
Returns : void
Protected zoomToMarkerBounds
zoomToMarkerBounds(bounds: L.LatLngBoundsExpression)
Inherited from MapSelectorComponent

Zooms to the given bounds

Parameters :
Name Type Optional Description
bounds L.LatLngBoundsExpression No

where to zoom

Returns : void
Private addBaseMap
addBaseMap(layerOptions?: LayerOptions)
Inherited from CachedMapComponent
Parameters :
Name Type Optional
layerOptions LayerOptions Yes
Returns : void
Private addOverlayMap
addOverlayMap(layerOptions: LayerOptions)
Inherited from CachedMapComponent
Parameters :
Name Type Optional
layerOptions LayerOptions No
Returns : void
Protected createMap
createMap()
Inherited from CachedMapComponent
Returns : void
Private generateUUID
generateUUID()
Inherited from CachedMapComponent
Returns : string
Public ngDoCheck
ngDoCheck()
Inherited from CachedMapComponent
Returns : void
Public ngOnChanges
ngOnChanges(changes: SimpleChanges)
Inherited from CachedMapComponent
Parameters :
Name Type Optional
changes SimpleChanges No
Returns : void
Public ngOnDestroy
ngOnDestroy()
Inherited from CachedMapComponent
Returns : void
Public ngOnInit
ngOnInit()
Inherited from CachedMapComponent
Returns : void
Private removeBaseMap
removeBaseMap(layerOptions: LayerOptions)
Inherited from CachedMapComponent
Parameters :
Name Type Optional
layerOptions LayerOptions No
Returns : void
Private removeOverlayMap
removeOverlayMap(layerOptions: LayerOptions)
Inherited from CachedMapComponent
Parameters :
Name Type Optional
layerOptions LayerOptions No
Returns : void
Private updateLayerControl
updateLayerControl()
Inherited from CachedMapComponent
Returns : void
Private updateZoomControl
updateZoomControl()
Inherited from CachedMapComponent
Returns : void

Properties

Private _lastValueSeriesIDsDiff
Type : IterableDiffer<string>
Private markerFeatureGroup
Type : L.FeatureGroup
Default value : featureGroup()
Private _baseMaps
Type : LayerMap
Inherited from CachedMapComponent
Private _differBaseMaps
Type : KeyValueDiffer<string | LayerOptions>
Inherited from CachedMapComponent
Private _differOverlayMaps
Type : KeyValueDiffer<string | LayerOptions>
Inherited from CachedMapComponent
Private _overlayMaps
Type : LayerMap
Inherited from CachedMapComponent
Protected layerControl
Type : L.Control.Layers
Inherited from CachedMapComponent
Protected map
Type : L.Map
Inherited from CachedMapComponent

The map object.

Protected oldBaseLayer
Type : L.Control.LayersObject
Default value : {}
Inherited from CachedMapComponent
Protected oldOverlayLayer
Type : L.Control.LayersObject
Default value : {}
Inherited from CachedMapComponent
Protected zoomControl
Type : L.Control.Zoom
Inherited from CachedMapComponent
import {
  AfterViewInit,
  ChangeDetectorRef,
  Component,
  DoCheck,
  Input,
  IterableDiffer,
  IterableDiffers,
  KeyValueDiffers,
  OnChanges,
} from '@angular/core';
import {
  DatasetType,
  HelgolandServicesConnector,
  HelgolandTimeseries,
  StatusIntervalResolverService,
} from '@helgoland/core';
import { circleMarker, featureGroup, geoJSON, Layer, Marker, marker } from 'leaflet';
import { forkJoin, Observable, Observer } from 'rxjs';
import { switchMap, tap } from 'rxjs/operators';

import { MapCache } from '../../base/map-cache.service';
import { MapSelectorComponent } from '../map-selector.component';
import { LastValueLabelGenerator, LastValuePresentation } from '../services/last-value-label-generator.interface';

/**
 * Displays selectable series with their last values on an map.
 */
@Component({
  selector: 'n52-last-value-map-selector',
  templateUrl: '../map-selector.component.html',
  styleUrls: ['../map-selector.component.scss']
})
export class LastValueMapSelectorComponent extends MapSelectorComponent<HelgolandTimeseries> implements AfterViewInit, DoCheck, OnChanges {

  /**
   * The list of internal series IDs, which should be presented with their last values on the map.
   */
  @Input()
  public lastValueSeriesIDs: string[] = [];

  /**
   * Presentation type how to display the series.
   */
  @Input()
  public lastValuePresentation: LastValuePresentation = LastValuePresentation.Colorized;

  /**
   * Ignores all Statusintervals where the timestamp is before a given duration in milliseconds and draws instead the default marker.
   */
  @Input()
  public ignoreStatusIntervalIfBeforeDuration = Infinity;

  private _lastValueSeriesIDsDiff: IterableDiffer<string>;

  private markerFeatureGroup: L.FeatureGroup = featureGroup();

  constructor(
    protected mapCache: MapCache,
    protected kvDiffers: KeyValueDiffers,
    protected iDiffers: IterableDiffers,
    protected cd: ChangeDetectorRef,
    protected servicesConnector: HelgolandServicesConnector,
    protected lastValueLabelGenerator: LastValueLabelGenerator,
    protected statusIntervalResolver: StatusIntervalResolverService
  ) {
    super(mapCache, kvDiffers, cd);
    this._lastValueSeriesIDsDiff = this.iDiffers.find(this.lastValueSeriesIDs).create();
  }

  public ngDoCheck() {
    super.ngDoCheck();
    const changes = this._lastValueSeriesIDsDiff.diff(this.lastValueSeriesIDs);

    if (changes && this.map) {

      const ids = [];
      changes.forEachAddedItem(record => {
        ids.push(record.item);
      });
      this.createMarkersBySeriesIDs(ids);

      changes.forEachRemovedItem(record => {
        this.removeMarker(record.item);
      });
    }
  }

  protected drawGeometries(): void {
    this.onContentLoading.emit(true);
    if (this.lastValueSeriesIDs && this.lastValueSeriesIDs.length) {
      this.createMarkersBySeriesIDs(this.lastValueSeriesIDs);
    }
  }

  private createMarkersBySeriesIDs(ids: string[]) {
    const obsList: Array<Observable<any>> = [];
    ids.forEach(id => {
      const tsObs = this.servicesConnector.getDataset(id, { type: DatasetType.Timeseries });
      obsList.push(tsObs.pipe(switchMap(val => this.createMarker(val).pipe(tap(res => {
        this.markerFeatureGroup.addLayer(res);
        res.on('click', () => this.onSelected.emit(val));
      })))));
    });
    this.finalizeMarkerObservables(obsList);
  }

  private createMarker(ts: HelgolandTimeseries) {
    switch (this.lastValuePresentation) {
      case LastValuePresentation.Colorized:
        return this.createColorizedMarker(ts);
      case LastValuePresentation.Textual:
        return this.createLabeledMarker(ts);
    }
    return this.createColorizedMarker(ts);
  }

  private finalizeMarkerObservables(obsList: Observable<any>[]) {
    forkJoin(obsList).subscribe(() => {
      if (this.map) {
        const bounds = this.markerFeatureGroup.getBounds();
        this.zoomToMarkerBounds(bounds);
        this.map.invalidateSize();
      }
      this.onContentLoading.emit(false);
    });
    if (this.map) {
      this.markerFeatureGroup.addTo(this.map);
    }
  }

  private createColorizedMarker(ts: HelgolandTimeseries): Observable<Layer> {
    return new Observable<Layer>((observer: Observer<Layer>) => {
      this.servicesConnector.getDatasetExtras(ts).subscribe(extras => {
        let coloredMarker;
        if (extras.statusIntervals) {
          if ((ts.lastValue.timestamp) > new Date().getTime() - this.ignoreStatusIntervalIfBeforeDuration) {
            const interval = this.statusIntervalResolver.getMatchingInterval(ts.lastValue.value, extras.statusIntervals);
            if (interval) {
              coloredMarker = this.createColoredMarker(ts, interval.color);
            }
          }
        }
        if (!coloredMarker) {
          coloredMarker = this.createDefaultColoredMarker(ts);
        }
        this.setId(coloredMarker, ts.internalId);
        observer.next(coloredMarker);
        observer.complete();
      });
    });
  }

  private createColoredMarker(ts: HelgolandTimeseries, color: string): Layer {
    return this.createFilledMarker(ts, color, 10);
  }

  private createDefaultColoredMarker(ts: HelgolandTimeseries): Layer {
    return this.createFilledMarker(ts, '#000', 10);
  }

  private createFilledMarker(ts: HelgolandTimeseries, color: string, radius: number): Layer {
    let geometry: Layer;
    if (ts.platform.geometry.type === 'Point') {
      const point = ts.platform.geometry as GeoJSON.Point;
      geometry = circleMarker([point.coordinates[1], point.coordinates[0]], {
        color: '#000',
        fillColor: color,
        fillOpacity: 0.8,
        radius: 10,
        weight: 2
      });
    } else {
      geometry = geoJSON(ts.platform.geometry, {
        style: () => ({
          color: '#000',
          fillColor: color,
          fillOpacity: 0.8,
          weight: 2
        })
      });
    }
    if (geometry) {
      geometry.on('click', () => this.onSelected.emit(ts));
      return geometry;
    }
  }

  private createLabeledMarker(ts: HelgolandTimeseries): Observable<Layer> {
    return new Observable<Layer>(observer => {
      const icon = this.lastValueLabelGenerator.createIconLabel(ts);
      if (ts.platform.geometry.type === 'Point') {
        const point = ts.platform.geometry as GeoJSON.Point;
        const genMarker = marker([point.coordinates[1], point.coordinates[0]], { icon });
        this.setId(genMarker, ts.internalId);
        observer.next(genMarker);
        observer.complete();
      }
    });
  }

  private setId(m: Marker, id: string) {
    m.feature = {
      id,
      type: 'Feature',
      properties: null,
      geometry: null
    };
  }

  private removeMarker(markerId: string) {
    let searchedLayer;
    this.markerFeatureGroup.eachLayer((layer: Marker) => {
      if (layer.feature.id === markerId) {
        searchedLayer = layer;
      }
    });
    if (searchedLayer) {
      this.markerFeatureGroup.removeLayer(searchedLayer);
    }
  }

}
<div class="map-wrapper" style="height: 100%;">
  <div [attr.id]="mapId" class="map-viewer"></div>
</div>

../map-selector.component.scss

:host {
    position: relative;
    .map-viewer {
        width: 100%;
        height: 100%;
    }
    .map-notifier {
        position: absolute;
        bottom: 10px;
        left: 10px;
        z-index: 1001;
        width: 120px;
        height: 70px;
        padding: 5px;
        opacity: 0.8;
        text-align: center;
    }
}
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""