Commit e8e2f2119352193d06614c7ea554fecca6ae063e

Authored by Igor Kulikov
1 parent 6b53e84c

Map widgets fixes

@@ -38,13 +38,17 @@ import { @@ -38,13 +38,17 @@ import {
38 UnitedMapSettings 38 UnitedMapSettings
39 } from './map-models'; 39 } from './map-models';
40 import { Marker } from './markers'; 40 import { Marker } from './markers';
41 -import { BehaviorSubject, Observable, of } from 'rxjs';  
42 -import { filter } from 'rxjs/operators'; 41 +import { Observable, of } from 'rxjs';
43 import { Polyline } from './polyline'; 42 import { Polyline } from './polyline';
44 import { Polygon } from './polygon'; 43 import { Polygon } from './polygon';
45 -import { createLoadingDiv, createTooltip, parseArray, safeExecute } from '@home/components/widget/lib/maps/maps-utils'; 44 +import {
  45 + createLoadingDiv,
  46 + createTooltip,
  47 + parseArray,
  48 + parseData,
  49 + safeExecute
  50 +} from '@home/components/widget/lib/maps/maps-utils';
46 import { WidgetContext } from '@home/models/widget-component.models'; 51 import { WidgetContext } from '@home/models/widget-component.models';
47 -import { DatasourceData } from '@shared/models/widget.models';  
48 import { deepClone, isDefinedAndNotEmptyStr } from '@core/utils'; 52 import { deepClone, isDefinedAndNotEmptyStr } from '@core/utils';
49 53
50 export default abstract class LeafletMap { 54 export default abstract class LeafletMap {
@@ -53,8 +57,6 @@ export default abstract class LeafletMap { @@ -53,8 +57,6 @@ export default abstract class LeafletMap {
53 polylines: Map<string, Polyline> = new Map(); 57 polylines: Map<string, Polyline> = new Map();
54 polygons: Map<string, Polygon> = new Map(); 58 polygons: Map<string, Polygon> = new Map();
55 map: L.Map; 59 map: L.Map;
56 - map$: BehaviorSubject<L.Map> = new BehaviorSubject(null);  
57 - ready$: Observable<L.Map> = this.map$.pipe(filter(map => !!map));  
58 options: UnitedMapSettings; 60 options: UnitedMapSettings;
59 bounds: L.LatLngBounds; 61 bounds: L.LatLngBounds;
60 datasources: FormattedData[]; 62 datasources: FormattedData[];
@@ -69,6 +71,9 @@ export default abstract class LeafletMap { @@ -69,6 +71,9 @@ export default abstract class LeafletMap {
69 markerLabelText: string; 71 markerLabelText: string;
70 replaceInfoTooltipMarker: Array<ReplaceInfo> = []; 72 replaceInfoTooltipMarker: Array<ReplaceInfo> = [];
71 markerTooltipText: string; 73 markerTooltipText: string;
  74 + drawRoutes: boolean;
  75 + showPolygon: boolean;
  76 + updatePending = false;
72 77
73 protected constructor(public ctx: WidgetContext, 78 protected constructor(public ctx: WidgetContext,
74 public $container: HTMLElement, 79 public $container: HTMLElement,
@@ -78,8 +83,7 @@ export default abstract class LeafletMap { @@ -78,8 +83,7 @@ export default abstract class LeafletMap {
78 83
79 public initSettings(options: MapSettings) { 84 public initSettings(options: MapSettings) {
80 this.options.tinyColor = tinycolor(this.options.color || defaultSettings.color); 85 this.options.tinyColor = tinycolor(this.options.color || defaultSettings.color);
81 - const { initCallback,  
82 - disableScrollZooming, 86 + const { disableScrollZooming,
83 useClusterMarkers, 87 useClusterMarkers,
84 zoomOnClick, 88 zoomOnClick,
85 showCoverageOnHover, 89 showCoverageOnHover,
@@ -91,9 +95,6 @@ export default abstract class LeafletMap { @@ -91,9 +95,6 @@ export default abstract class LeafletMap {
91 if (disableScrollZooming) { 95 if (disableScrollZooming) {
92 this.map.scrollWheelZoom.disable(); 96 this.map.scrollWheelZoom.disable();
93 } 97 }
94 - if (initCallback) {  
95 - setTimeout(options.initCallback, 0);  
96 - }  
97 if (useClusterMarkers) { 98 if (useClusterMarkers) {
98 const clusteringSettings: MarkerClusterGroupOptions = { 99 const clusteringSettings: MarkerClusterGroupOptions = {
99 zoomToBoundsOnClick: zoomOnClick, 100 zoomToBoundsOnClick: zoomOnClick,
@@ -109,7 +110,6 @@ export default abstract class LeafletMap { @@ -109,7 +110,6 @@ export default abstract class LeafletMap {
109 clusteringSettings.disableClusteringAtZoom = Math.floor(maxZoom); 110 clusteringSettings.disableClusteringAtZoom = Math.floor(maxZoom);
110 } 111 }
111 this.markersCluster = markerClusterGroup(clusteringSettings); 112 this.markersCluster = markerClusterGroup(clusteringSettings);
112 - this.ready$.subscribe(map => map.addLayer(this.markersCluster));  
113 } 113 }
114 } 114 }
115 115
@@ -182,18 +182,16 @@ export default abstract class LeafletMap { @@ -182,18 +182,16 @@ export default abstract class LeafletMap {
182 public setLoading(loading: boolean) { 182 public setLoading(loading: boolean) {
183 if (this.loading !== loading) { 183 if (this.loading !== loading) {
184 this.loading = loading; 184 this.loading = loading;
185 - this.ready$.subscribe(() => {  
186 - if (this.loading) {  
187 - if (!this.loadingDiv) {  
188 - this.loadingDiv = createLoadingDiv(this.ctx.translate.instant('common.loading'));  
189 - }  
190 - this.$container.append(this.loadingDiv[0]);  
191 - } else {  
192 - if (this.loadingDiv) {  
193 - this.loadingDiv.remove();  
194 - } 185 + if (this.loading) {
  186 + if (!this.loadingDiv) {
  187 + this.loadingDiv = createLoadingDiv(this.ctx.translate.instant('common.loading'));
195 } 188 }
196 - }); 189 + this.$container.append(this.loadingDiv[0]);
  190 + } else {
  191 + if (this.loadingDiv) {
  192 + this.loadingDiv.remove();
  193 + }
  194 + }
197 } 195 }
198 } 196 }
199 197
@@ -207,11 +205,13 @@ export default abstract class LeafletMap { @@ -207,11 +205,13 @@ export default abstract class LeafletMap {
207 if (this.options.draggableMarker) { 205 if (this.options.draggableMarker) {
208 this.addMarkerControl(); 206 this.addMarkerControl();
209 } 207 }
210 - this.map$.next(this.map);  
211 - }  
212 -  
213 - public setDataSources(dataSources: FormattedData[]) {  
214 - this.datasources = dataSources; 208 + if (this.options.useClusterMarkers) {
  209 + this.map.addLayer(this.markersCluster);
  210 + }
  211 + if (this.updatePending) {
  212 + this.updatePending = false;
  213 + this.updateData(this.drawRoutes, this.showPolygon);
  214 + }
215 } 215 }
216 216
217 public saveMarkerLocation(_e: FormattedData, lat?: number, lng?: number): Observable<any> { 217 public saveMarkerLocation(_e: FormattedData, lat?: number, lng?: number): Observable<any> {
@@ -259,7 +259,7 @@ export default abstract class LeafletMap { @@ -259,7 +259,7 @@ export default abstract class LeafletMap {
259 this.map.once('zoomend', () => { 259 this.map.once('zoomend', () => {
260 let minZoom = this.options.minZoomLevel; 260 let minZoom = this.options.minZoomLevel;
261 if (this.options.defaultZoomLevel) { 261 if (this.options.defaultZoomLevel) {
262 - minZoom = Math.min(minZoom, this.options.defaultZoomLevel); 262 + minZoom = Math.max(minZoom, this.options.defaultZoomLevel);
263 } 263 }
264 if (this.map.getZoom() > minZoom) { 264 if (this.map.getZoom() > minZoom) {
265 this.map.setZoom(minZoom, { animate: false }); 265 this.map.setZoom(minZoom, { animate: false });
@@ -297,8 +297,12 @@ export default abstract class LeafletMap { @@ -297,8 +297,12 @@ export default abstract class LeafletMap {
297 } 297 }
298 } 298 }
299 299
300 - updateData(data: DatasourceData[], formattedData: FormattedData[], drawRoutes: boolean, showPolygon: boolean) {  
301 - this.ready$.subscribe(() => { 300 + updateData(drawRoutes: boolean, showPolygon: boolean) {
  301 + this.drawRoutes = drawRoutes;
  302 + this.showPolygon = showPolygon;
  303 + if (this.map) {
  304 + const data = this.ctx.data;
  305 + const formattedData = parseData(this.ctx.data);
302 if (drawRoutes) { 306 if (drawRoutes) {
303 this.updatePolylines(parseArray(data), false); 307 this.updatePolylines(parseArray(data), false);
304 } 308 }
@@ -306,23 +310,28 @@ export default abstract class LeafletMap { @@ -306,23 +310,28 @@ export default abstract class LeafletMap {
306 this.updatePolygons(formattedData, false); 310 this.updatePolygons(formattedData, false);
307 } 311 }
308 this.updateMarkers(formattedData, false); 312 this.updateMarkers(formattedData, false);
309 - this.updateBoundsInternal(drawRoutes, showPolygon);  
310 - }); 313 + this.updateBoundsInternal();
  314 + if (this.options.draggableMarker) {
  315 + this.datasources = formattedData;
  316 + }
  317 + } else {
  318 + this.updatePending = true;
  319 + }
311 } 320 }
312 321
313 - private updateBoundsInternal(drawRoutes: boolean, showPolygon: boolean) { 322 + private updateBoundsInternal() {
314 const bounds = new L.LatLngBounds(null, null); 323 const bounds = new L.LatLngBounds(null, null);
315 - if (drawRoutes) { 324 + if (this.drawRoutes) {
316 this.polylines.forEach((polyline) => { 325 this.polylines.forEach((polyline) => {
317 bounds.extend(polyline.leafletPoly.getBounds()); 326 bounds.extend(polyline.leafletPoly.getBounds());
318 }); 327 });
319 } 328 }
320 - if (showPolygon) { 329 + if (this.showPolygon) {
321 this.polygons.forEach((polygon) => { 330 this.polygons.forEach((polygon) => {
322 bounds.extend(polygon.leafletPoly.getBounds()); 331 bounds.extend(polygon.leafletPoly.getBounds());
323 }); 332 });
324 } 333 }
325 - if ((this.options as MarkerSettings).useClusterMarkers) { 334 + if ((this.options as MarkerSettings).useClusterMarkers && this.markersCluster.getBounds().isValid()) {
326 bounds.extend(this.markersCluster.getBounds()); 335 bounds.extend(this.markersCluster.getBounds());
327 } else { 336 } else {
328 this.markers.forEach((marker) => { 337 this.markers.forEach((marker) => {
@@ -331,7 +340,7 @@ export default abstract class LeafletMap { @@ -331,7 +340,7 @@ export default abstract class LeafletMap {
331 } 340 }
332 341
333 const mapBounds = this.map.getBounds(); 342 const mapBounds = this.map.getBounds();
334 - if (bounds.isValid() && (!this.bounds || !mapBounds.contains(bounds))) { 343 + if (bounds.isValid() && (!this.bounds || !this.bounds.isValid() || !this.bounds.equals(bounds) && !mapBounds.contains(bounds))) {
335 this.bounds = bounds; 344 this.bounds = bounds;
336 this.fitBounds(bounds); 345 this.fitBounds(bounds);
337 } 346 }
@@ -340,59 +349,57 @@ export default abstract class LeafletMap { @@ -340,59 +349,57 @@ export default abstract class LeafletMap {
340 // Markers 349 // Markers
341 updateMarkers(markersData: FormattedData[], updateBounds = true, callback?) { 350 updateMarkers(markersData: FormattedData[], updateBounds = true, callback?) {
342 const rawMarkers = markersData.filter(mdata => !!this.convertPosition(mdata)); 351 const rawMarkers = markersData.filter(mdata => !!this.convertPosition(mdata));
343 - this.ready$.subscribe(() => {  
344 - const toDelete = new Set(Array.from(this.markers.keys()));  
345 - const createdMarkers: Marker[] = [];  
346 - const updatedMarkers: Marker[] = [];  
347 - const deletedMarkers: Marker[] = [];  
348 - let m: Marker;  
349 - rawMarkers.forEach(data => {  
350 - if (data.rotationAngle || data.rotationAngle === 0) {  
351 - const currentImage = this.options.useMarkerImageFunction ?  
352 - safeExecute(this.options.markerImageFunction,  
353 - [data, this.options.markerImages, markersData, data.dsIndex]) : this.options.currentImage;  
354 - const style = currentImage ? 'background-image: url(' + currentImage.url + ');' : '';  
355 - this.options.icon = L.divIcon({  
356 - html: `<div class="arrow"  
357 - style="transform: translate(-10px, -10px)  
358 - rotate(${data.rotationAngle}deg);  
359 - ${style}"><div>`  
360 - });  
361 - } else {  
362 - this.options.icon = null;  
363 - }  
364 - if (this.markers.get(data.entityName)) {  
365 - m = this.updateMarker(data.entityName, data, markersData, this.options);  
366 - if (m) {  
367 - updatedMarkers.push(m);  
368 - }  
369 - } else {  
370 - m = this.createMarker(data.entityName, data, markersData, this.options as MarkerSettings, updateBounds, callback);  
371 - if (m) {  
372 - createdMarkers.push(m);  
373 - }  
374 - }  
375 - toDelete.delete(data.entityName); 352 + const toDelete = new Set(Array.from(this.markers.keys()));
  353 + const createdMarkers: Marker[] = [];
  354 + const updatedMarkers: Marker[] = [];
  355 + const deletedMarkers: Marker[] = [];
  356 + let m: Marker;
  357 + rawMarkers.forEach(data => {
  358 + if (data.rotationAngle || data.rotationAngle === 0) {
  359 + const currentImage = this.options.useMarkerImageFunction ?
  360 + safeExecute(this.options.markerImageFunction,
  361 + [data, this.options.markerImages, markersData, data.dsIndex]) : this.options.currentImage;
  362 + const style = currentImage ? 'background-image: url(' + currentImage.url + ');' : '';
  363 + this.options.icon = L.divIcon({
  364 + html: `<div class="arrow"
  365 + style="transform: translate(-10px, -10px)
  366 + rotate(${data.rotationAngle}deg);
  367 + ${style}"><div>`
376 }); 368 });
377 - toDelete.forEach((key) => {  
378 - m = this.deleteMarker(key);  
379 - if (m) {  
380 - deletedMarkers.push(m);  
381 - }  
382 - });  
383 - this.markersData = markersData;  
384 - if ((this.options as MarkerSettings).useClusterMarkers) {  
385 - if (createdMarkers.length) {  
386 - this.markersCluster.addLayers(createdMarkers.map(marker => marker.leafletMarker));  
387 - }  
388 - if (updatedMarkers.length) {  
389 - this.markersCluster.refreshClusters(updatedMarkers.map(marker => marker.leafletMarker))  
390 - }  
391 - if (deletedMarkers.length) {  
392 - this.markersCluster.removeLayers(deletedMarkers.map(marker => marker.leafletMarker));  
393 - } 369 + } else {
  370 + this.options.icon = null;
  371 + }
  372 + if (this.markers.get(data.entityName)) {
  373 + m = this.updateMarker(data.entityName, data, markersData, this.options);
  374 + if (m) {
  375 + updatedMarkers.push(m);
394 } 376 }
395 - }); 377 + } else {
  378 + m = this.createMarker(data.entityName, data, markersData, this.options as MarkerSettings, updateBounds, callback);
  379 + if (m) {
  380 + createdMarkers.push(m);
  381 + }
  382 + }
  383 + toDelete.delete(data.entityName);
  384 + });
  385 + toDelete.forEach((key) => {
  386 + m = this.deleteMarker(key);
  387 + if (m) {
  388 + deletedMarkers.push(m);
  389 + }
  390 + });
  391 + this.markersData = markersData;
  392 + if ((this.options as MarkerSettings).useClusterMarkers) {
  393 + if (createdMarkers.length) {
  394 + this.markersCluster.addLayers(createdMarkers.map(marker => marker.leafletMarker));
  395 + }
  396 + if (updatedMarkers.length) {
  397 + this.markersCluster.refreshClusters(updatedMarkers.map(marker => marker.leafletMarker))
  398 + }
  399 + if (deletedMarkers.length) {
  400 + this.markersCluster.removeLayers(deletedMarkers.map(marker => marker.leafletMarker));
  401 + }
  402 + }
396 } 403 }
397 404
398 dragMarker = (e, data = {} as FormattedData) => { 405 dragMarker = (e, data = {} as FormattedData) => {
@@ -420,10 +427,8 @@ export default abstract class LeafletMap { @@ -420,10 +427,8 @@ export default abstract class LeafletMap {
420 427
421 private updateMarker(key: string, data: FormattedData, dataSources: FormattedData[], settings: MarkerSettings): Marker { 428 private updateMarker(key: string, data: FormattedData, dataSources: FormattedData[], settings: MarkerSettings): Marker {
422 const marker: Marker = this.markers.get(key); 429 const marker: Marker = this.markers.get(key);
423 - const location = this.convertPosition(data)  
424 - if (!location.equals(marker.location)) {  
425 - marker.updateMarkerPosition(location);  
426 - } 430 + const location = this.convertPosition(data);
  431 + marker.updateMarkerPosition(location);
427 if (settings.showTooltip) { 432 if (settings.showTooltip) {
428 marker.updateMarkerTooltip(data); 433 marker.updateMarkerTooltip(data);
429 } 434 }
@@ -445,26 +450,24 @@ export default abstract class LeafletMap { @@ -445,26 +450,24 @@ export default abstract class LeafletMap {
445 } 450 }
446 451
447 updatePoints(pointsData: FormattedData[], getTooltip: (point: FormattedData, setTooltip?: boolean) => string) { 452 updatePoints(pointsData: FormattedData[], getTooltip: (point: FormattedData, setTooltip?: boolean) => string) {
448 - this.map$.subscribe(map => {  
449 - if (this.points) {  
450 - map.removeLayer(this.points);  
451 - }  
452 - this.points = new FeatureGroup();  
453 - pointsData.filter(pdata => !!this.convertPosition(pdata)).forEach(data => {  
454 - const point = L.circleMarker(this.convertPosition(data), {  
455 - color: this.options.pointColor,  
456 - radius: this.options.pointSize  
457 - });  
458 - if (!this.options.pointTooltipOnRightPanel) {  
459 - point.on('click', () => getTooltip(data));  
460 - }  
461 - else {  
462 - createTooltip(point, this.options, data.$datasource, getTooltip(data, false));  
463 - }  
464 - this.points.addLayer(point);  
465 - });  
466 - map.addLayer(this.points);  
467 - }); 453 + if (this.points) {
  454 + this.map.removeLayer(this.points);
  455 + }
  456 + this.points = new FeatureGroup();
  457 + pointsData.filter(pdata => !!this.convertPosition(pdata)).forEach(data => {
  458 + const point = L.circleMarker(this.convertPosition(data), {
  459 + color: this.options.pointColor,
  460 + radius: this.options.pointSize
  461 + });
  462 + if (!this.options.pointTooltipOnRightPanel) {
  463 + point.on('click', () => getTooltip(data));
  464 + }
  465 + else {
  466 + createTooltip(point, this.options, data.$datasource, getTooltip(data, false));
  467 + }
  468 + this.points.addLayer(point);
  469 + });
  470 + this.map.addLayer(this.points);
468 } 471 }
469 472
470 // Polyline 473 // Polyline
@@ -494,27 +497,23 @@ export default abstract class LeafletMap { @@ -494,27 +497,23 @@ export default abstract class LeafletMap {
494 } 497 }
495 498
496 createPolyline(data: FormattedData, dataSources: FormattedData[], settings: PolylineSettings, updateBounds = true) { 499 createPolyline(data: FormattedData, dataSources: FormattedData[], settings: PolylineSettings, updateBounds = true) {
497 - this.ready$.subscribe(() => {  
498 - const poly = new Polyline(this.map,  
499 - dataSources.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings);  
500 - if (updateBounds) {  
501 - const bounds = poly.leafletPoly.getBounds();  
502 - this.fitBounds(bounds);  
503 - }  
504 - this.polylines.set(data.entityName, poly);  
505 - }); 500 + const poly = new Polyline(this.map,
  501 + dataSources.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings);
  502 + if (updateBounds) {
  503 + const bounds = poly.leafletPoly.getBounds();
  504 + this.fitBounds(bounds);
  505 + }
  506 + this.polylines.set(data.entityName, poly);
506 } 507 }
507 508
508 updatePolyline(data: FormattedData, dataSources: FormattedData[], settings: PolylineSettings, updateBounds = true) { 509 updatePolyline(data: FormattedData, dataSources: FormattedData[], settings: PolylineSettings, updateBounds = true) {
509 - this.ready$.subscribe(() => {  
510 - const poly = this.polylines.get(data.entityName);  
511 - const oldBounds = poly.leafletPoly.getBounds();  
512 - poly.updatePolyline(dataSources.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings);  
513 - const newBounds = poly.leafletPoly.getBounds();  
514 - if (updateBounds && oldBounds.toBBoxString() !== newBounds.toBBoxString()) {  
515 - this.fitBounds(newBounds);  
516 - }  
517 - }); 510 + const poly = this.polylines.get(data.entityName);
  511 + const oldBounds = poly.leafletPoly.getBounds();
  512 + poly.updatePolyline(dataSources.map(el => this.convertPosition(el)).filter(el => !!el), data, dataSources, settings);
  513 + const newBounds = poly.leafletPoly.getBounds();
  514 + if (updateBounds && oldBounds.toBBoxString() !== newBounds.toBBoxString()) {
  515 + this.fitBounds(newBounds);
  516 + }
518 } 517 }
519 518
520 removePolyline(name: string) { 519 removePolyline(name: string) {
@@ -560,26 +559,22 @@ export default abstract class LeafletMap { @@ -560,26 +559,22 @@ export default abstract class LeafletMap {
560 } 559 }
561 560
562 createPolygon(polyData: FormattedData, dataSources: FormattedData[], settings: PolygonSettings, updateBounds = true) { 561 createPolygon(polyData: FormattedData, dataSources: FormattedData[], settings: PolygonSettings, updateBounds = true) {
563 - this.ready$.subscribe(() => {  
564 - const polygon = new Polygon(this.map, polyData, dataSources, settings);  
565 - if (updateBounds) {  
566 - const bounds = polygon.leafletPoly.getBounds();  
567 - this.fitBounds(bounds);  
568 - }  
569 - this.polygons.set(polyData.entityName, polygon);  
570 - }); 562 + const polygon = new Polygon(this.map, polyData, dataSources, settings);
  563 + if (updateBounds) {
  564 + const bounds = polygon.leafletPoly.getBounds();
  565 + this.fitBounds(bounds);
  566 + }
  567 + this.polygons.set(polyData.entityName, polygon);
571 } 568 }
572 569
573 updatePolygon(polyData: FormattedData, dataSources: FormattedData[], settings: PolygonSettings, updateBounds = true) { 570 updatePolygon(polyData: FormattedData, dataSources: FormattedData[], settings: PolygonSettings, updateBounds = true) {
574 - this.ready$.subscribe(() => {  
575 - const poly = this.polygons.get(polyData.entityName);  
576 - const oldBounds = poly.leafletPoly.getBounds();  
577 - poly.updatePolygon(polyData, dataSources, settings);  
578 - const newBounds = poly.leafletPoly.getBounds();  
579 - if (updateBounds && oldBounds.toBBoxString() !== newBounds.toBBoxString()) {  
580 - this.fitBounds(newBounds);  
581 - }  
582 - }); 571 + const poly = this.polygons.get(polyData.entityName);
  572 + const oldBounds = poly.leafletPoly.getBounds();
  573 + poly.updatePolygon(polyData, dataSources, settings);
  574 + const newBounds = poly.leafletPoly.getBounds();
  575 + if (updateBounds && oldBounds.toBBoxString() !== newBounds.toBBoxString()) {
  576 + this.fitBounds(newBounds);
  577 + }
583 } 578 }
584 579
585 removePolygon(name: string) { 580 removePolygon(name: string) {
@@ -15,14 +15,7 @@ @@ -15,14 +15,7 @@
15 /// 15 ///
16 16
17 import { LatLngTuple } from 'leaflet'; 17 import { LatLngTuple } from 'leaflet';
18 -import { Datasource, JsonSettingsSchema } from '@app/shared/models/widget.models';  
19 -import { Type } from '@angular/core';  
20 -import LeafletMap from './leaflet-map';  
21 -import { OpenStreetMap, TencentMap, GoogleMap, HEREMap, ImageMap } from './providers';  
22 -import {  
23 - openstreetMapSettingsSchema, tencentMapSettingsSchema,  
24 - googleMapSettingsSchema, hereMapSettingsSchema, imageMapSettingsSchema  
25 -} from './schemes'; 18 +import { Datasource } from '@app/shared/models/widget.models';
26 import { EntityType } from '@shared/models/entity-type.models'; 19 import { EntityType } from '@shared/models/entity-type.models';
27 import tinycolor from 'tinycolor2'; 20 import tinycolor from 'tinycolor2';
28 21
@@ -30,12 +23,10 @@ export const DEFAULT_MAP_PAGE_SIZE = 16384; @@ -30,12 +23,10 @@ export const DEFAULT_MAP_PAGE_SIZE = 16384;
30 23
31 export type GenericFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string; 24 export type GenericFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string;
32 export type MarkerImageFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string; 25 export type MarkerImageFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string;
33 -export type GetTooltip = (point: FormattedData, setTooltip?: boolean) => string;  
34 export type PosFuncton = (origXPos, origYPos) => { x, y }; 26 export type PosFuncton = (origXPos, origYPos) => { x, y };
35 27
36 export type MapSettings = { 28 export type MapSettings = {
37 draggableMarker: boolean; 29 draggableMarker: boolean;
38 - initCallback?: () => any;  
39 posFunction: PosFuncton; 30 posFunction: PosFuncton;
40 defaultZoomLevel?: number; 31 defaultZoomLevel?: number;
41 disableScrollZooming?: boolean; 32 disableScrollZooming?: boolean;
@@ -209,40 +200,6 @@ export type actionsHandler = ($event: Event, datasource: Datasource) => void; @@ -209,40 +200,6 @@ export type actionsHandler = ($event: Event, datasource: Datasource) => void;
209 200
210 export type UnitedMapSettings = MapSettings & PolygonSettings & MarkerSettings & PolylineSettings & TripAnimationSettings; 201 export type UnitedMapSettings = MapSettings & PolygonSettings & MarkerSettings & PolylineSettings & TripAnimationSettings;
211 202
212 -interface IProvider {  
213 - MapClass: Type<LeafletMap>,  
214 - schema: JsonSettingsSchema,  
215 - name: string  
216 -}  
217 -  
218 -export const providerSets: { [key: string]: IProvider } = {  
219 - 'openstreet-map': {  
220 - MapClass: OpenStreetMap,  
221 - schema: openstreetMapSettingsSchema,  
222 - name: 'openstreet-map',  
223 - },  
224 - 'tencent-map': {  
225 - MapClass: TencentMap,  
226 - schema: tencentMapSettingsSchema,  
227 - name: 'tencent-map'  
228 - },  
229 - 'google-map': {  
230 - MapClass: GoogleMap,  
231 - schema: googleMapSettingsSchema,  
232 - name: 'google-map'  
233 - },  
234 - here: {  
235 - MapClass: HEREMap,  
236 - schema: hereMapSettingsSchema,  
237 - name: 'here'  
238 - },  
239 - 'image-map': {  
240 - MapClass: ImageMap,  
241 - schema: imageMapSettingsSchema,  
242 - name: 'image-map'  
243 - }  
244 -};  
245 -  
246 export const defaultSettings: any = { 203 export const defaultSettings: any = {
247 xPosKeyName: 'xPos', 204 xPosKeyName: 'xPos',
248 yPosKeyName: 'yPos', 205 yPosKeyName: 'yPos',
@@ -15,12 +15,10 @@ @@ -15,12 +15,10 @@
15 /// 15 ///
16 16
17 import { 17 import {
18 - DEFAULT_MAP_PAGE_SIZE,  
19 defaultSettings, 18 defaultSettings,
20 FormattedData, 19 FormattedData,
21 hereProviders, 20 hereProviders,
22 MapProviders, 21 MapProviders,
23 - providerSets,  
24 UnitedMapSettings 22 UnitedMapSettings
25 } from './map-models'; 23 } from './map-models';
26 import LeafletMap from './leaflet-map'; 24 import LeafletMap from './leaflet-map';
@@ -46,6 +44,7 @@ import _ from 'lodash'; @@ -46,6 +44,7 @@ import _ from 'lodash';
46 import { EntityDataPageLink } from '@shared/models/query/query.models'; 44 import { EntityDataPageLink } from '@shared/models/query/query.models';
47 import { isDefined } from '@core/utils'; 45 import { isDefined } from '@core/utils';
48 import { forkJoin, Observable, of } from 'rxjs'; 46 import { forkJoin, Observable, of } from 'rxjs';
  47 +import { providerSets } from '@home/components/widget/lib/maps/providers';
49 48
50 // @dynamic 49 // @dynamic
51 export class MapWidgetController implements MapWidgetInterface { 50 export class MapWidgetController implements MapWidgetInterface {
@@ -275,11 +274,7 @@ export class MapWidgetController implements MapWidgetInterface { @@ -275,11 +274,7 @@ export class MapWidgetController implements MapWidgetInterface {
275 } 274 }
276 275
277 update() { 276 update() {
278 - const formattedData = parseData(this.data);  
279 - this.map.updateData(this.data, formattedData, this.drawRoutes, this.settings.showPolygon);  
280 - if (this.settings.draggableMarker) {  
281 - this.map.setDataSources(formattedData);  
282 - } 277 + this.map.updateData(this.drawRoutes, this.settings.showPolygon);
283 this.map.setLoading(false); 278 this.map.setLoading(false);
284 } 279 }
285 280
@@ -34,11 +34,10 @@ export class Marker { @@ -34,11 +34,10 @@ export class Marker {
34 tooltipOffset: L.LatLngTuple; 34 tooltipOffset: L.LatLngTuple;
35 markerOffset: L.LatLngTuple; 35 markerOffset: L.LatLngTuple;
36 tooltip: L.Popup; 36 tooltip: L.Popup;
37 - location: L.LatLngExpression;  
38 data: FormattedData; 37 data: FormattedData;
39 dataSources: FormattedData[]; 38 dataSources: FormattedData[];
40 39
41 - constructor(private map: LeafletMap, location: L.LatLngExpression, public settings: MarkerSettings, 40 + constructor(private map: LeafletMap, private location: L.LatLng, public settings: MarkerSettings,
42 data?: FormattedData, dataSources?, onDragendListener?) { 41 data?: FormattedData, dataSources?, onDragendListener?) {
43 this.setDataSources(data, dataSources); 42 this.setDataSources(data, dataSources);
44 this.leafletMarker = L.marker(location, { 43 this.leafletMarker = L.marker(location, {
@@ -94,8 +93,11 @@ export class Marker { @@ -94,8 +93,11 @@ export class Marker {
94 } 93 }
95 } 94 }
96 95
97 - updateMarkerPosition(position: L.LatLngExpression) { 96 + updateMarkerPosition(position: L.LatLng) {
  97 + if (!this.location.equals(position)) {
  98 + this.location = position;
98 this.leafletMarker.setLatLng(position); 99 this.leafletMarker.setLatLng(position);
  100 + }
99 } 101 }
100 102
101 updateMarkerLabel(settings: MarkerSettings) { 103 updateMarkerLabel(settings: MarkerSettings) {
@@ -35,6 +35,7 @@ export class GoogleMap extends LeafletMap { @@ -35,6 +35,7 @@ export class GoogleMap extends LeafletMap {
35 constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) { 35 constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) {
36 super(ctx, $container, options); 36 super(ctx, $container, options);
37 this.resource = ctx.$injector.get(ResourcesService); 37 this.resource = ctx.$injector.get(ResourcesService);
  38 + super.initSettings(options);
38 this.loadGoogle(() => { 39 this.loadGoogle(() => {
39 const map = L.map($container, {attributionControl: false}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel); 40 const map = L.map($container, {attributionControl: false}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
40 (L.gridLayer as any).googleMutant({ 41 (L.gridLayer as any).googleMutant({
@@ -42,7 +43,6 @@ export class GoogleMap extends LeafletMap { @@ -42,7 +43,6 @@ export class GoogleMap extends LeafletMap {
42 }).addTo(map); 43 }).addTo(map);
43 super.setMap(map); 44 super.setMap(map);
44 }, options.gmApiKey); 45 }, options.gmApiKey);
45 - super.initSettings(options);  
46 } 46 }
47 47
48 private loadGoogle(callback, apiKey = 'AIzaSyDoEx2kaGz3PxwbI9T7ccTSg5xjdw8Nw8Q') { 48 private loadGoogle(callback, apiKey = 'AIzaSyDoEx2kaGz3PxwbI9T7ccTSg5xjdw8Nw8Q') {
@@ -25,7 +25,7 @@ export class HEREMap extends LeafletMap { @@ -25,7 +25,7 @@ export class HEREMap extends LeafletMap {
25 const map = L.map($container).setView(options?.defaultCenterPosition, options?.defaultZoomLevel); 25 const map = L.map($container).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
26 const tileLayer = (L.tileLayer as any).provider(options.mapProviderHere || 'HERE.normalDay', options.credentials); 26 const tileLayer = (L.tileLayer as any).provider(options.mapProviderHere || 'HERE.normalDay', options.credentials);
27 tileLayer.addTo(map); 27 tileLayer.addTo(map);
28 - super.setMap(map);  
29 super.initSettings(options); 28 super.initSettings(options);
  29 + super.setMap(map);
30 } 30 }
31 } 31 }
@@ -47,8 +47,8 @@ export class ImageMap extends LeafletMap { @@ -47,8 +47,8 @@ export class ImageMap extends LeafletMap {
47 this.onResize(true); 47 this.onResize(true);
48 } else { 48 } else {
49 this.onResize(); 49 this.onResize();
50 - super.setMap(this.map);  
51 super.initSettings(options); 50 super.initSettings(options);
  51 + super.setMap(this.map);
52 } 52 }
53 }); 53 });
54 } 54 }
@@ -14,8 +14,50 @@ @@ -14,8 +14,50 @@
14 /// limitations under the License. 14 /// limitations under the License.
15 /// 15 ///
16 16
17 -export * from './tencent-map';  
18 -export * from './google-map';  
19 -export * from './here-map';  
20 -export * from './image-map';  
21 -export * from './openstreet-map'; 17 +import {
  18 + googleMapSettingsSchema, hereMapSettingsSchema, imageMapSettingsSchema,
  19 + openstreetMapSettingsSchema,
  20 + tencentMapSettingsSchema
  21 +} from '@home/components/widget/lib/maps/schemes';
  22 +import { OpenStreetMap } from './openstreet-map';
  23 +import { TencentMap } from './tencent-map';
  24 +import { GoogleMap } from './google-map';
  25 +import { HEREMap } from './here-map';
  26 +import { ImageMap } from './image-map';
  27 +import { Type } from '@angular/core';
  28 +import LeafletMap from '@home/components/widget/lib/maps/leaflet-map';
  29 +import { JsonSettingsSchema } from '@shared/models/widget.models';
  30 +
  31 +interface IProvider {
  32 + MapClass: Type<LeafletMap>,
  33 + schema: JsonSettingsSchema,
  34 + name: string
  35 +}
  36 +
  37 +export const providerSets: { [key: string]: IProvider } = {
  38 + 'openstreet-map': {
  39 + MapClass: OpenStreetMap,
  40 + schema: openstreetMapSettingsSchema,
  41 + name: 'openstreet-map',
  42 + },
  43 + 'tencent-map': {
  44 + MapClass: TencentMap,
  45 + schema: tencentMapSettingsSchema,
  46 + name: 'tencent-map'
  47 + },
  48 + 'google-map': {
  49 + MapClass: GoogleMap,
  50 + schema: googleMapSettingsSchema,
  51 + name: 'google-map'
  52 + },
  53 + here: {
  54 + MapClass: HEREMap,
  55 + schema: hereMapSettingsSchema,
  56 + name: 'here'
  57 + },
  58 + 'image-map': {
  59 + MapClass: ImageMap,
  60 + schema: imageMapSettingsSchema,
  61 + name: 'image-map'
  62 + }
  63 +};
@@ -29,7 +29,7 @@ export class OpenStreetMap extends LeafletMap { @@ -29,7 +29,7 @@ export class OpenStreetMap extends LeafletMap {
29 else 29 else
30 tileLayer = (L.tileLayer as any).provider(options.mapProvider || 'OpenStreetMap.Mapnik'); 30 tileLayer = (L.tileLayer as any).provider(options.mapProvider || 'OpenStreetMap.Mapnik');
31 tileLayer.addTo(map); 31 tileLayer.addTo(map);
32 - super.setMap(map);  
33 super.initSettings(options); 32 super.initSettings(options);
  33 + super.setMap(map);
34 } 34 }
35 } 35 }
@@ -31,7 +31,7 @@ export class TencentMap extends LeafletMap { @@ -31,7 +31,7 @@ export class TencentMap extends LeafletMap {
31 attribution: '&copy;2020 Tencent - GS(2018)2236号- Data&copy; NavInfo' 31 attribution: '&copy;2020 Tencent - GS(2018)2236号- Data&copy; NavInfo'
32 }).addTo(map); 32 }).addTo(map);
33 txLayer.addTo(map); 33 txLayer.addTo(map);
34 - super.setMap(map);  
35 super.initSettings(options); 34 super.initSettings(options);
  35 + super.setMap(map);
36 } 36 }
37 } 37 }
@@ -159,7 +159,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy @@ -159,7 +159,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
159 } 159 }
160 this.calcLabel(); 160 this.calcLabel();
161 this.calcTooltip(currentPosition.find(position => position.entityName === this.activeTrip.entityName)); 161 this.calcTooltip(currentPosition.find(position => position.entityName === this.activeTrip.entityName));
162 - if (this.mapWidget) { 162 + if (this.mapWidget && this.mapWidget.map && this.mapWidget.map.map) {
163 this.mapWidget.map.updatePolylines(this.interpolatedTimeData.map(ds => _.values(ds)), true, this.activeTrip); 163 this.mapWidget.map.updatePolylines(this.interpolatedTimeData.map(ds => _.values(ds)), true, this.activeTrip);
164 if (this.settings.showPolygon) { 164 if (this.settings.showPolygon) {
165 this.mapWidget.map.updatePolygons(this.interpolatedTimeData); 165 this.mapWidget.map.updatePolygons(this.interpolatedTimeData);