diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts index a1280fef13..91576ec22b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts @@ -20,12 +20,12 @@ import 'leaflet-providers'; import 'leaflet.markercluster/dist/leaflet.markercluster'; import { - FormattedData, - MapSettings, - MarkerSettings, - PolygonSettings, - PolylineSettings, - UnitedMapSettings + FormattedData, + MapSettings, + MarkerSettings, + PolygonSettings, + PolylineSettings, + UnitedMapSettings } from './map-models'; import { Marker } from './markers'; import { BehaviorSubject, Observable } from 'rxjs'; @@ -158,9 +158,9 @@ export default abstract class LeafletMap { this.map = map; if (this.options.useDefaultCenterPosition) { this.map.panTo(this.options.defaultCenterPosition); - this.bounds = map.getBounds(); + this.bounds = map.getBounds(); } - else this.bounds = new L.LatLngBounds(null, null); + else this.bounds = new L.LatLngBounds(null, null); if (this.options.draggableMarker) { this.addMarkerControl(); } @@ -244,7 +244,7 @@ export default abstract class LeafletMap { } // Markers - updateMarkers(markersData) { + updateMarkers(markersData, callback?) { markersData.filter(mdata => !!this.convertPosition(mdata)).forEach(data => { if (data.rotationAngle || data.rotationAngle === 0) { const currentImage = this.options.useMarkerImageFunction ? @@ -265,7 +265,7 @@ export default abstract class LeafletMap { this.updateMarker(data.entityName, data, markersData, this.options) } else { - this.createMarker(data.entityName, data, markersData, this.options as MarkerSettings); + this.createMarker(data.entityName, data, markersData, this.options as MarkerSettings, callback); } }); this.markersData = markersData; @@ -276,9 +276,11 @@ export default abstract class LeafletMap { this.saveMarkerLocation({ ...data, ...this.convertToCustomFormat(e.target._latlng) }); } - private createMarker(key: string, data: FormattedData, dataSources: FormattedData[], settings: MarkerSettings) { + private createMarker(key: string, data: FormattedData, dataSources: FormattedData[], settings: MarkerSettings, callback?) { this.ready$.subscribe(() => { const newMarker = new Marker(this.convertPosition(data), settings, data, dataSources, this.dragMarker); + if (callback) + newMarker.leafletMarker.on('click', () => { callback(data, true) }); if (this.bounds) this.fitBounds(this.bounds.extend(newMarker.leafletMarker.getLatLng())); this.markers.set(key, newMarker); @@ -344,41 +346,58 @@ export default abstract class LeafletMap { // Polyline updatePolylines(polyData: FormattedData[][], data?: FormattedData) { - polyData.forEach((dataSource) => { - if (dataSource.length) { - data = data || dataSource[0]; - if (this.polylines.get(data.$datasource.entityName)) { + polyData.forEach((dataSource: FormattedData[]) => { + data = data || dataSource[0]; + if (dataSource.length && data.entityName === dataSource[0].entityName) { + if (this.polylines.get(data.entityName)) { this.updatePolyline(data, dataSource, this.options); } else { this.createPolyline(data, dataSource, this.options); } } + else { + if (data) + this.removePolyline(dataSource[0]?.entityName) + } }) } createPolyline(data: FormattedData, dataSources: FormattedData[], settings: PolylineSettings) { this.ready$.subscribe(() => { const poly = new Polyline(this.map, - dataSources.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings); + dataSources.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings); const bounds = poly.leafletPoly.getBounds(); this.fitBounds(bounds); - this.polylines.set(data.$datasource.entityName, poly); + this.polylines.set(data.entityName, poly); }); } updatePolyline(data: FormattedData, dataSources: FormattedData[], settings: PolylineSettings) { this.ready$.subscribe(() => { - const poly = this.polylines.get(data.$datasource.entityName); + const poly = this.polylines.get(data.entityName); + const oldBounds = poly.leafletPoly.getBounds(); poly.updatePolyline(dataSources.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings); + const newBounds = poly.leafletPoly.getBounds(); + if (oldBounds.toBBoxString() !== newBounds.toBBoxString()) { + this.fitBounds(newBounds); + } }); } + removePolyline(name: string) { + const poly = this.polylines.get(name); + if (poly) { + this.map.removeLayer(poly.leafletPoly); + this.polylines.delete(name); + } + } + // Polygon updatePolygons(polyData: FormattedData[]) { polyData.forEach((data: FormattedData) => { - if (data.hasOwnProperty(this.options.polygonKeyName)) { + if (data && data.hasOwnProperty(this.options.polygonKeyName)) { if (typeof (data[this.options.polygonKeyName]) === 'string') { data[this.options.polygonKeyName] = JSON.parse(data[this.options.polygonKeyName]) as LatLngTuple[]; } @@ -403,8 +422,13 @@ export default abstract class LeafletMap { updatePolygon(polyData: FormattedData, dataSources: FormattedData[], settings: PolygonSettings) { this.ready$.subscribe(() => { - const poly = this.polygons.get(polyData.$datasource.entityName); + const poly = this.polygons.get(polyData.entityName); + const oldBounds = poly.leafletPoly.getBounds(); poly.updatePolygon(polyData, dataSources, settings); + const newBounds = poly.leafletPoly.getBounds(); + if (oldBounds.toBBoxString() !== newBounds.toBBoxString()) { + this.fitBounds(newBounds); + } }); } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts index 1d28bf9845..1c198825df 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts @@ -26,6 +26,7 @@ import { export type GenericFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string; export type MarkerImageFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string; +export type GetTooltip= (point: FormattedData, setTooltip?: boolean) => string; export type MapSettings = { draggableMarker: boolean; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts index bdd399194b..9e978b39a1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts @@ -69,7 +69,6 @@ export class MapWidgetController implements MapWidgetInterface { this.settings.markerClick = this.getDescriptors('markerClick'); this.settings.polygonClick = this.getDescriptors('polygonClick'); - // this.settings. const MapClass = providerSets[this.provider]?.MapClass; if (!MapClass) { return; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts index 899e608296..48e840dfd7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts @@ -258,7 +258,7 @@ export function parseArray(input: any[]): any[] { time: el[0], deviceType: null }; - entityArray.filter(e => e.data.length).forEach(entity => { + entityArray.filter(e => e.data.length && e.data[i]).forEach(entity => { obj[entity?.dataKey?.label] = entity?.data[i][1]; obj[entity?.dataKey?.label + '|ts'] = entity?.data[0][0]; if (entity?.dataKey?.label === 'type') { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/polyline.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/polyline.ts index 774dbc0b72..543f4a718a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/polyline.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/polyline.ts @@ -65,7 +65,6 @@ export class Polyline { this.dataSources = dataSources; this.leafletPoly.setLatLngs(locations); this.leafletPoly.setStyle(this.getPolyStyle(settings)); - // this.setPolylineLatLngs(data); if (this.polylineDecorator) this.polylineDecorator.setPaths(this.leafletPoly); } @@ -92,8 +91,4 @@ export class Polyline { getPolylineLatLngs() { return this.leafletPoly.getLatLngs(); } - - setPolylineLatLngs(latLngs) { - this.leafletPoly.setLatLngs(latLngs); - } } diff --git a/ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.ts b/ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.ts index 6ec8d377c7..bc22326593 100644 --- a/ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/trip-animation/trip-animation.component.ts @@ -56,6 +56,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { historicalData: FormattedData[][]; normalizationStep: number; interpolatedTimeData = []; + intervals = []; widgetConfig: WidgetConfig; settings; mainTooltip = ''; @@ -68,6 +69,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { maxTimeFormat: string; anchors: number[] = []; useAnchors: boolean; + currentTime: number; static getSettingsSchema(): JsonSettingsSchema { const schema = initSchema(); @@ -99,15 +101,15 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { this.settings.fitMapBounds = true; this.normalizationStep = this.settings.normalizationStep; const subscription = this.ctx.subscriptions[Object.keys(this.ctx.subscriptions)[0]]; - if (subscription) { - subscription.callbacks.onDataUpdated = () => { - this.historicalData = parseArray(this.ctx.data); + if (subscription) subscription.callbacks.onDataUpdated = () => { + this.historicalData = parseArray(this.ctx.data).filter(arr => arr.length); + if (this.historicalData.length) { this.activeTrip = this.historicalData[0][0]; this.calculateIntervals(); this.timeUpdated(this.minTime); - this.mapWidget.map.map?.invalidateSize(); - this.cd.detectChanges(); } + this.mapWidget.map.map?.invalidateSize(); + this.cd.detectChanges(); } } @@ -117,8 +119,16 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { } timeUpdated(time: number) { - const currentPosition = this.interpolatedTimeData.map(dataSource => dataSource[time]); - if(isUndefined(currentPosition[0])){ + this.currentTime = time; + const currentPosition = this.interpolatedTimeData + .map(dataSource => dataSource[time]) + .filter(ds => ds) + .map(ds => { + ds.minTime = this.minTimeFormat; + ds.maxTime = this.maxTimeFormat; + return ds; + }); + if (isUndefined(currentPosition[0])) { const timePoints = Object.keys(this.interpolatedTimeData[0]).map(item => parseInt(item, 10)); for (let i = 1; i < timePoints.length; i++) { if (timePoints[i - 1] < time && timePoints[i] > time) { @@ -134,7 +144,6 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { } } } - this.activeTrip = currentPosition[0]; this.calcLabel(); this.calcTooltip(); if (this.mapWidget) { @@ -145,7 +154,10 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { if (this.settings.showPoints) { this.mapWidget.map.updatePoints(_.values(_.union(this.interpolatedTimeData)[0]), this.calcTooltip); } - this.mapWidget.map.updateMarkers(currentPosition); + this.mapWidget.map.updateMarkers(currentPosition, (trip) => { + this.activeTrip = trip; + this.timeUpdated(this.currentTime) + }); } } @@ -185,6 +197,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { SecurityContext.HTML, tooltipText); this.cd.detectChanges(); } + this.activeTrip = point; return tooltipText; } @@ -212,7 +225,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { }; } const timeStamp = Object.keys(result); - for(let i = 0; i < timeStamp.length - 1; i++){ + for (let i = 0; i < timeStamp.length - 1; i++) { result[timeStamp[i]].rotationAngle += findAngle(result[timeStamp[i]], result[timeStamp[i + 1]], latKeyName, lngKeyName) } return result;