Merge pull request #5616 from vvlladd28/improvement/map-widgets/marker-placement
[3.3.3] UI: Improvement add/edit location marker/polygon in maps widgets
This commit is contained in:
		
						commit
						715eefa6d0
					
				
							
								
								
									
										1
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								pom.xml
									
									
									
									
									
								
							@ -830,6 +830,7 @@
 | 
			
		||||
                            <exclude>src/.browserslistrc</exclude>
 | 
			
		||||
                            <exclude>**/yarn.lock</exclude>
 | 
			
		||||
                            <exclude>**/*.raw</exclude>
 | 
			
		||||
                            <exclude>**/*.patch</exclude>
 | 
			
		||||
                            <exclude>**/apache/cassandra/io/**</exclude>
 | 
			
		||||
                            <exclude>.run/**</exclude>
 | 
			
		||||
                        </excludes>
 | 
			
		||||
 | 
			
		||||
@ -79,6 +79,7 @@
 | 
			
		||||
              "src/app/modules/home/components/widget/lib/maps/markers.scss",
 | 
			
		||||
              "node_modules/leaflet.markercluster/dist/MarkerCluster.css",
 | 
			
		||||
              "node_modules/leaflet.markercluster/dist/MarkerCluster.Default.css",
 | 
			
		||||
              "node_modules/@geoman-io/leaflet-geoman-free/dist/leaflet-geoman.css",
 | 
			
		||||
              "node_modules/prismjs/themes/prism.css",
 | 
			
		||||
              "node_modules/prismjs/plugins/line-numbers/prism-line-numbers.css"
 | 
			
		||||
            ],
 | 
			
		||||
 | 
			
		||||
@ -28,6 +28,7 @@
 | 
			
		||||
    "@date-io/date-fns": "^2.10.11",
 | 
			
		||||
    "@flowjs/flow.js": "^2.14.1",
 | 
			
		||||
    "@flowjs/ngx-flow": "~0.4.6",
 | 
			
		||||
    "@geoman-io/leaflet-geoman-free": "^2.11.3",
 | 
			
		||||
    "@juggle/resize-observer": "^3.3.1",
 | 
			
		||||
    "@mat-datetimepicker/core": "~6.0.2",
 | 
			
		||||
    "@material-ui/core": "^4.11.4",
 | 
			
		||||
@ -57,11 +58,10 @@
 | 
			
		||||
    "jstree-bootstrap-theme": "^1.0.1",
 | 
			
		||||
    "jszip": "^3.6.0",
 | 
			
		||||
    "leaflet": "^1.7.1",
 | 
			
		||||
    "leaflet-editable": "^1.2.0",
 | 
			
		||||
    "leaflet-polylinedecorator": "^1.6.0",
 | 
			
		||||
    "leaflet-providers": "^1.12.0",
 | 
			
		||||
    "leaflet.gridlayer.googlemutant": "0.10.2",
 | 
			
		||||
    "leaflet.markercluster": "^1.5.0",
 | 
			
		||||
    "leaflet-providers": "^1.13.0",
 | 
			
		||||
    "leaflet.gridlayer.googlemutant": "^0.13.4",
 | 
			
		||||
    "leaflet.markercluster": "^1.5.3",
 | 
			
		||||
    "material-design-icons": "^3.0.1",
 | 
			
		||||
    "messageformat": "^2.3.0",
 | 
			
		||||
    "moment": "^2.29.1",
 | 
			
		||||
@ -113,10 +113,11 @@
 | 
			
		||||
    "@types/jquery": "^3.5.2",
 | 
			
		||||
    "@types/js-beautify": "^1.13.1",
 | 
			
		||||
    "@types/jstree": "^3.3.40",
 | 
			
		||||
    "@types/leaflet": "1.5.17",
 | 
			
		||||
    "@types/leaflet-editable": "^1.2.1",
 | 
			
		||||
    "@types/leaflet-polylinedecorator": "^1.6.0",
 | 
			
		||||
    "@types/leaflet.markercluster": "^1.4.4",
 | 
			
		||||
    "@types/leaflet": "^1.7.6",
 | 
			
		||||
    "@types/leaflet-polylinedecorator": "^1.6.1",
 | 
			
		||||
    "@types/leaflet-providers": "^1.2.1",
 | 
			
		||||
    "@types/leaflet.gridlayer.googlemutant": "^0.4.6",
 | 
			
		||||
    "@types/leaflet.markercluster": "^1.4.6",
 | 
			
		||||
    "@types/lodash": "^4.14.170",
 | 
			
		||||
    "@types/moment-timezone": "^0.5.30",
 | 
			
		||||
    "@types/mousetrap": "1.6.3",
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,54 @@
 | 
			
		||||
<!--
 | 
			
		||||
 | 
			
		||||
    Copyright © 2016-2021 The Thingsboard Authors
 | 
			
		||||
 | 
			
		||||
    Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
    you may not use this file except in compliance with the License.
 | 
			
		||||
    You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
        http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
    Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
    distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
    See the License for the specific language governing permissions and
 | 
			
		||||
    limitations under the License.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<form #addEntityForm="ngForm" [formGroup]="selectEntityFormGroup" (ngSubmit)="save()">
 | 
			
		||||
  <mat-toolbar fxLayout="row" color="primary">
 | 
			
		||||
    <h2 translate>widgets.maps.select-entity</h2>
 | 
			
		||||
    <span fxFlex></span>
 | 
			
		||||
    <button mat-icon-button [matDialogClose]="null" type="button">
 | 
			
		||||
      <mat-icon class="material-icons">close</mat-icon>
 | 
			
		||||
    </button>
 | 
			
		||||
  </mat-toolbar>
 | 
			
		||||
  <mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async">
 | 
			
		||||
  </mat-progress-bar>
 | 
			
		||||
  <div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
 | 
			
		||||
  <div mat-dialog-content>
 | 
			
		||||
    <mat-form-field class="mat-block" style="min-width: 280px">
 | 
			
		||||
      <mat-label translate>entity.entity</mat-label>
 | 
			
		||||
      <mat-select formControlName="entity">
 | 
			
		||||
        <mat-option *ngFor="let entity of data.entities" [value]="entity">
 | 
			
		||||
          {{ entity.entityName }}
 | 
			
		||||
        </mat-option>
 | 
			
		||||
      </mat-select>
 | 
			
		||||
    </mat-form-field>
 | 
			
		||||
    <div class="tb-hint" translate>widgets.maps.select-entity-hint</div>
 | 
			
		||||
  </div>
 | 
			
		||||
  <div mat-dialog-actions fxLayout="row" fxLayoutAlign="end center">
 | 
			
		||||
    <button mat-button color="primary"
 | 
			
		||||
            type="button"
 | 
			
		||||
            [disabled]="(isLoading$ | async)"
 | 
			
		||||
            [matDialogClose]="null"
 | 
			
		||||
            cdkFocusInitial>
 | 
			
		||||
      {{ 'action.cancel' | translate }}
 | 
			
		||||
    </button>
 | 
			
		||||
    <button mat-raised-button color="primary"
 | 
			
		||||
            type="submit"
 | 
			
		||||
            [disabled]="(isLoading$ | async) || addEntityForm.invalid || !addEntityForm.dirty">
 | 
			
		||||
      {{ 'action.add' | translate }}
 | 
			
		||||
    </button>
 | 
			
		||||
  </div>
 | 
			
		||||
</form>
 | 
			
		||||
@ -0,0 +1,21 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright © 2016-2021 The Thingsboard Authors
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
:host {
 | 
			
		||||
  .tb-hint {
 | 
			
		||||
    margin-top: -1.25em;
 | 
			
		||||
    max-width: fit-content;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,56 @@
 | 
			
		||||
///
 | 
			
		||||
/// Copyright © 2016-2021 The Thingsboard Authors
 | 
			
		||||
///
 | 
			
		||||
/// Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
/// you may not use this file except in compliance with the License.
 | 
			
		||||
/// You may obtain a copy of the License at
 | 
			
		||||
///
 | 
			
		||||
///     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
///
 | 
			
		||||
/// Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
/// distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
/// See the License for the specific language governing permissions and
 | 
			
		||||
/// limitations under the License.
 | 
			
		||||
///
 | 
			
		||||
 | 
			
		||||
import { Component, Inject } from '@angular/core';
 | 
			
		||||
import { DialogComponent } from '@shared/components/dialog.component';
 | 
			
		||||
import { Store } from '@ngrx/store';
 | 
			
		||||
import { AppState } from '@core/core.state';
 | 
			
		||||
import { Router } from '@angular/router';
 | 
			
		||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
 | 
			
		||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
 | 
			
		||||
import { FormattedData } from '@home/components/widget/lib/maps/map-models';
 | 
			
		||||
 | 
			
		||||
export interface SelectEntityDialogData {
 | 
			
		||||
  entities: FormattedData[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'tb-select-entity-dialog',
 | 
			
		||||
  templateUrl: './select-entity-dialog.component.html',
 | 
			
		||||
  styleUrls: ['./select-entity-dialog.component.scss']
 | 
			
		||||
})
 | 
			
		||||
export class SelectEntityDialogComponent extends DialogComponent<SelectEntityDialogComponent, FormattedData> {
 | 
			
		||||
 | 
			
		||||
  selectEntityFormGroup: FormGroup;
 | 
			
		||||
 | 
			
		||||
  constructor(protected store: Store<AppState>,
 | 
			
		||||
              protected router: Router,
 | 
			
		||||
              @Inject(MAT_DIALOG_DATA) public data: SelectEntityDialogData,
 | 
			
		||||
              public dialogRef: MatDialogRef<SelectEntityDialogComponent, FormattedData>,
 | 
			
		||||
              public fb: FormBuilder) {
 | 
			
		||||
    super(store, router, dialogRef);
 | 
			
		||||
 | 
			
		||||
    this.selectEntityFormGroup = this.fb.group(
 | 
			
		||||
      {
 | 
			
		||||
        entity: ['', Validators.required]
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  save(): void {
 | 
			
		||||
    this.dialogRef.close(this.selectEntityFormGroup.value.entity);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -14,23 +14,15 @@
 | 
			
		||||
/// limitations under the License.
 | 
			
		||||
///
 | 
			
		||||
 | 
			
		||||
import L, {
 | 
			
		||||
  FeatureGroup,
 | 
			
		||||
  Icon,
 | 
			
		||||
  LatLngBounds,
 | 
			
		||||
  LatLngTuple,
 | 
			
		||||
  markerClusterGroup,
 | 
			
		||||
  MarkerClusterGroup,
 | 
			
		||||
  MarkerClusterGroupOptions, Projection
 | 
			
		||||
} from 'leaflet';
 | 
			
		||||
import L, { FeatureGroup, Icon, LatLngBounds, LatLngTuple, Projection } from 'leaflet';
 | 
			
		||||
import tinycolor from 'tinycolor2';
 | 
			
		||||
import 'leaflet-providers';
 | 
			
		||||
import 'leaflet.markercluster/dist/leaflet.markercluster';
 | 
			
		||||
import { MarkerClusterGroup, MarkerClusterGroupOptions } from 'leaflet.markercluster/dist/leaflet.markercluster';
 | 
			
		||||
import '@geoman-io/leaflet-geoman-free';
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
  defaultSettings,
 | 
			
		||||
  FormattedData,
 | 
			
		||||
  MapProviders,
 | 
			
		||||
  MapSettings,
 | 
			
		||||
  MarkerSettings,
 | 
			
		||||
  PolygonSettings,
 | 
			
		||||
@ -39,12 +31,10 @@ import {
 | 
			
		||||
  UnitedMapSettings
 | 
			
		||||
} from './map-models';
 | 
			
		||||
import { Marker } from './markers';
 | 
			
		||||
import { Observable, of } from 'rxjs';
 | 
			
		||||
import { forkJoin, Observable, of } from 'rxjs';
 | 
			
		||||
import { Polyline } from './polyline';
 | 
			
		||||
import { Polygon } from './polygon';
 | 
			
		||||
import {
 | 
			
		||||
  createTooltip,
 | 
			
		||||
} from '@home/components/widget/lib/maps/maps-utils';
 | 
			
		||||
import { createTooltip } from '@home/components/widget/lib/maps/maps-utils';
 | 
			
		||||
import {
 | 
			
		||||
  checkLngLat,
 | 
			
		||||
  createLoadingDiv,
 | 
			
		||||
@ -54,6 +44,15 @@ import {
 | 
			
		||||
} from '@home/components/widget/lib/maps/common-maps-utils';
 | 
			
		||||
import { WidgetContext } from '@home/models/widget-component.models';
 | 
			
		||||
import { deepClone, isDefinedAndNotNull, isEmptyStr, isString } from '@core/utils';
 | 
			
		||||
import { TranslateService } from '@ngx-translate/core';
 | 
			
		||||
import {
 | 
			
		||||
  SelectEntityDialogComponent,
 | 
			
		||||
  SelectEntityDialogData
 | 
			
		||||
} from '@home/components/widget/lib/maps/dialogs/select-entity-dialog.component';
 | 
			
		||||
import { MatDialog } from '@angular/material/dialog';
 | 
			
		||||
import { AttributeService } from '@core/http/attribute.service';
 | 
			
		||||
import { EntityId } from '@shared/models/id/entity-id';
 | 
			
		||||
import { AttributeScope, DataKeyType, LatestTelemetry } from '@shared/models/telemetry/telemetry.models';
 | 
			
		||||
 | 
			
		||||
export default abstract class LeafletMap {
 | 
			
		||||
 | 
			
		||||
@ -78,20 +77,20 @@ export default abstract class LeafletMap {
 | 
			
		||||
    drawRoutes: boolean;
 | 
			
		||||
    showPolygon: boolean;
 | 
			
		||||
    updatePending = false;
 | 
			
		||||
    editPolygons = false;
 | 
			
		||||
    selectedEntity: FormattedData;
 | 
			
		||||
    addMarkers: L.Marker[] = [];
 | 
			
		||||
    addPolygons: L.Polygon[] = [];
 | 
			
		||||
  // tslint:disable-next-line:no-string-literal
 | 
			
		||||
    southWest = new L.LatLng(-Projection.SphericalMercator['MAX_LATITUDE'], -180);
 | 
			
		||||
  // tslint:disable-next-line:no-string-literal
 | 
			
		||||
    northEast = new L.LatLng(Projection.SphericalMercator['MAX_LATITUDE'], 180);
 | 
			
		||||
    mousePositionOnMap: L.LatLng;
 | 
			
		||||
    addMarker: L.Control;
 | 
			
		||||
    addPolygon: L.Control;
 | 
			
		||||
 | 
			
		||||
    protected constructor(public ctx: WidgetContext,
 | 
			
		||||
                          public $container: HTMLElement,
 | 
			
		||||
                          options: UnitedMapSettings) {
 | 
			
		||||
        this.options = options;
 | 
			
		||||
        this.editPolygons = options.showPolygon && options.editablePolygon;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public initSettings(options: MapSettings) {
 | 
			
		||||
@ -102,16 +101,28 @@ export default abstract class LeafletMap {
 | 
			
		||||
            removeOutsideVisibleBounds,
 | 
			
		||||
            animate,
 | 
			
		||||
            chunkedLoading,
 | 
			
		||||
            spiderfyOnMaxZoom,
 | 
			
		||||
            maxClusterRadius,
 | 
			
		||||
            maxZoom }: MapSettings = options;
 | 
			
		||||
        if (useClusterMarkers) {
 | 
			
		||||
            // disabled marker cluster icon
 | 
			
		||||
            (L as any).MarkerCluster = (L as any).MarkerCluster.extend({
 | 
			
		||||
              options: { pmIgnore: true, ...L.Icon.prototype.options }
 | 
			
		||||
            });
 | 
			
		||||
            const clusteringSettings: MarkerClusterGroupOptions = {
 | 
			
		||||
                spiderfyOnMaxZoom: false,
 | 
			
		||||
                spiderfyOnMaxZoom,
 | 
			
		||||
                zoomToBoundsOnClick: zoomOnClick,
 | 
			
		||||
                showCoverageOnHover,
 | 
			
		||||
                removeOutsideVisibleBounds,
 | 
			
		||||
                animate,
 | 
			
		||||
                chunkedLoading
 | 
			
		||||
                chunkedLoading,
 | 
			
		||||
                pmIgnore: true,
 | 
			
		||||
                spiderLegPolylineOptions: {
 | 
			
		||||
                  pmIgnore: true
 | 
			
		||||
                },
 | 
			
		||||
                polygonOptions: {
 | 
			
		||||
                  pmIgnore: true
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
            if (maxClusterRadius && maxClusterRadius > 0) {
 | 
			
		||||
                clusteringSettings.maxClusterRadius = Math.floor(maxClusterRadius);
 | 
			
		||||
@ -119,183 +130,165 @@ export default abstract class LeafletMap {
 | 
			
		||||
            if (maxZoom && maxZoom >= 0 && maxZoom < 19) {
 | 
			
		||||
                clusteringSettings.disableClusteringAtZoom = Math.floor(maxZoom);
 | 
			
		||||
            }
 | 
			
		||||
            this.markersCluster = markerClusterGroup(clusteringSettings);
 | 
			
		||||
            this.markersCluster = new MarkerClusterGroup(clusteringSettings);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    addMarkerControl() {
 | 
			
		||||
        if (this.options.draggableMarker) {
 | 
			
		||||
            this.map.on('mousemove', (e: L.LeafletMouseEvent) => {
 | 
			
		||||
                this.mousePositionOnMap = e.latlng;
 | 
			
		||||
            });
 | 
			
		||||
            const dragListener = (e: L.DragEndEvent) => {
 | 
			
		||||
                if (e.type === 'dragend' && this.mousePositionOnMap) {
 | 
			
		||||
                    const icon = L.icon({
 | 
			
		||||
                      iconRetinaUrl: 'marker-icon-2x.png',
 | 
			
		||||
                      iconUrl: 'marker-icon.png',
 | 
			
		||||
                      shadowUrl: 'marker-shadow.png',
 | 
			
		||||
                      iconSize: [25, 41],
 | 
			
		||||
                      iconAnchor: [12, 41],
 | 
			
		||||
                      popupAnchor: [1, -34],
 | 
			
		||||
                      tooltipAnchor: [16, -28],
 | 
			
		||||
                      shadowSize: [41, 41]
 | 
			
		||||
                    });
 | 
			
		||||
                    const customLatLng = this.convertToCustomFormat(this.mousePositionOnMap);
 | 
			
		||||
                    this.mousePositionOnMap.lat = customLatLng[this.options.latKeyName];
 | 
			
		||||
                    this.mousePositionOnMap.lng = customLatLng[this.options.lngKeyName];
 | 
			
		||||
 | 
			
		||||
                    const newMarker = L.marker(this.mousePositionOnMap, { icon }).addTo(this.map);
 | 
			
		||||
                    this.addMarkers.push(newMarker);
 | 
			
		||||
                    const datasourcesList = document.createElement('div');
 | 
			
		||||
                    const header = document.createElement('p');
 | 
			
		||||
                    header.appendChild(document.createTextNode('Select entity:'));
 | 
			
		||||
                    header.setAttribute('style', 'font-size: 14px; margin: 8px 0');
 | 
			
		||||
                    datasourcesList.appendChild(header);
 | 
			
		||||
                    this.datasources.forEach(ds => {
 | 
			
		||||
                        const dsItem = document.createElement('p');
 | 
			
		||||
                        dsItem.appendChild(document.createTextNode(ds.entityName));
 | 
			
		||||
                        dsItem.setAttribute('style', 'font-size: 14px; margin: 8px 0; cursor: pointer');
 | 
			
		||||
                        dsItem.onclick = () => {
 | 
			
		||||
                            const updatedEnttity = { ...ds, ...customLatLng };
 | 
			
		||||
                            this.saveMarkerLocation(updatedEnttity).subscribe(() => {
 | 
			
		||||
                              this.map.removeLayer(newMarker);
 | 
			
		||||
                              const markerIndex = this.addMarkers.indexOf(newMarker);
 | 
			
		||||
                              if (markerIndex > -1) {
 | 
			
		||||
                                this.addMarkers.splice(markerIndex, 1);
 | 
			
		||||
                              }
 | 
			
		||||
                              this.deleteMarker(ds.entityName);
 | 
			
		||||
                              this.createMarker(ds.entityName, updatedEnttity, this.datasources, this.options);
 | 
			
		||||
                            });
 | 
			
		||||
                        };
 | 
			
		||||
                        datasourcesList.appendChild(dsItem);
 | 
			
		||||
                    });
 | 
			
		||||
                    datasourcesList.appendChild(document.createElement('br'));
 | 
			
		||||
                    const deleteBtn = document.createElement('a');
 | 
			
		||||
                    deleteBtn.appendChild(document.createTextNode('Discard changes'));
 | 
			
		||||
                    deleteBtn.onclick = () => {
 | 
			
		||||
                        this.map.removeLayer(newMarker);
 | 
			
		||||
                        const markerIndex = this.addMarkers.indexOf(newMarker);
 | 
			
		||||
                        if (markerIndex > -1) {
 | 
			
		||||
                          this.addMarkers.splice(markerIndex, 1);
 | 
			
		||||
                        }
 | 
			
		||||
                    };
 | 
			
		||||
                    datasourcesList.appendChild(deleteBtn);
 | 
			
		||||
                    const popup = L.popup();
 | 
			
		||||
                    popup.setContent(datasourcesList);
 | 
			
		||||
                    newMarker.bindPopup(popup).openPopup();
 | 
			
		||||
                }
 | 
			
		||||
                this.addMarker.setPosition('topright');
 | 
			
		||||
            };
 | 
			
		||||
            const addMarker = L.Control.extend({
 | 
			
		||||
                onAdd() {
 | 
			
		||||
                    const img = L.DomUtil.create('img') as any;
 | 
			
		||||
                    img.src = `assets/add_location.svg`;
 | 
			
		||||
                    img.style.width = '32px';
 | 
			
		||||
                    img.style.height = '32px';
 | 
			
		||||
                    img.title = 'Drag and drop to add marker';
 | 
			
		||||
                    img.onclick = this.dragMarker;
 | 
			
		||||
                    img.draggable = true;
 | 
			
		||||
                    const draggableImg = new L.Draggable(img);
 | 
			
		||||
                    draggableImg.enable();
 | 
			
		||||
                    draggableImg.on('dragend', dragListener);
 | 
			
		||||
                    return img;
 | 
			
		||||
                },
 | 
			
		||||
                onRemove() {
 | 
			
		||||
                },
 | 
			
		||||
                dragMarker: this.dragMarker
 | 
			
		||||
            } as any);
 | 
			
		||||
            const addMarkerControl = (opts) => {
 | 
			
		||||
                return new addMarker(opts);
 | 
			
		||||
            };
 | 
			
		||||
            this.addMarker = addMarkerControl({ position: 'topright' }).addTo(this.map);
 | 
			
		||||
        }
 | 
			
		||||
    private selectEntityWithoutLocationDialog(shapes: L.PM.SUPPORTED_SHAPES): Observable<FormattedData> {
 | 
			
		||||
      let entities;
 | 
			
		||||
      switch (shapes) {
 | 
			
		||||
        case 'Polygon':
 | 
			
		||||
        case 'Rectangle':
 | 
			
		||||
          entities = this.datasources.filter(pData => !this.isValidPolygonPosition(pData));
 | 
			
		||||
          break;
 | 
			
		||||
        case 'Marker':
 | 
			
		||||
          entities = this.datasources.filter(mData => !this.convertPosition(mData));
 | 
			
		||||
          break;
 | 
			
		||||
        default:
 | 
			
		||||
          return of(null);
 | 
			
		||||
      }
 | 
			
		||||
      if (entities.length === 1) {
 | 
			
		||||
        return of(entities[0]);
 | 
			
		||||
      }
 | 
			
		||||
      const dialog = this.ctx.$injector.get(MatDialog);
 | 
			
		||||
      return dialog.open<SelectEntityDialogComponent, SelectEntityDialogData, FormattedData>(SelectEntityDialogComponent,
 | 
			
		||||
        {
 | 
			
		||||
          disableClose: true,
 | 
			
		||||
          panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
 | 
			
		||||
          data: {
 | 
			
		||||
            entities
 | 
			
		||||
          }
 | 
			
		||||
        }).afterClosed();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  addPolygonControl() {
 | 
			
		||||
    if (this.options.showPolygon && this.options.editablePolygon) {
 | 
			
		||||
      this.map.on('mousemove', (e: L.LeafletMouseEvent) => {
 | 
			
		||||
        this.mousePositionOnMap = e.latlng;
 | 
			
		||||
    private selectEntityWithoutLocation(type: string) {
 | 
			
		||||
      this.selectEntityWithoutLocationDialog(type.substring(2)).subscribe((data) => {
 | 
			
		||||
        if (data !== null) {
 | 
			
		||||
          this.selectedEntity = data;
 | 
			
		||||
          this.toggleDrawMode(type);
 | 
			
		||||
        } else {
 | 
			
		||||
          this.map.pm.Toolbar.toggleButton(type, false);
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private toggleDrawMode(type: string) {
 | 
			
		||||
      this.map.pm.Draw[type].toggle();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    addEditControl() {
 | 
			
		||||
      // Customize edit marker
 | 
			
		||||
      if (this.options.draggableMarker) {
 | 
			
		||||
        const actions = [{
 | 
			
		||||
          text: L.PM.Utils.getTranslation('actions.cancel'),
 | 
			
		||||
          onClick: () => this.toggleDrawMode('tbMarker')
 | 
			
		||||
        }];
 | 
			
		||||
 | 
			
		||||
        this.map.pm.Toolbar.copyDrawControl('Marker', {
 | 
			
		||||
          name: 'tbMarker',
 | 
			
		||||
          afterClick: () => this.selectEntityWithoutLocation('tbMarker'),
 | 
			
		||||
          disabled: true,
 | 
			
		||||
          actions
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Customize edit polygon
 | 
			
		||||
      if (this.editPolygons) {
 | 
			
		||||
        const rectangleActions = [
 | 
			
		||||
          {
 | 
			
		||||
            text: L.PM.Utils.getTranslation('actions.cancel'),
 | 
			
		||||
            onClick: () => this.toggleDrawMode('tbRectangle')
 | 
			
		||||
          }
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        const polygonActions = [
 | 
			
		||||
          'finish' as const,
 | 
			
		||||
          'removeLastVertex' as const,
 | 
			
		||||
          {
 | 
			
		||||
            text: L.PM.Utils.getTranslation('actions.cancel'),
 | 
			
		||||
            onClick: () => this.toggleDrawMode('tbPolygon')
 | 
			
		||||
          }
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        this.map.pm.Toolbar.copyDrawControl('Rectangle', {
 | 
			
		||||
          name: 'tbRectangle',
 | 
			
		||||
          afterClick: () => this.selectEntityWithoutLocation('tbRectangle'),
 | 
			
		||||
          disabled: true,
 | 
			
		||||
          actions: rectangleActions
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.map.pm.Toolbar.copyDrawControl('Polygon', {
 | 
			
		||||
          name: 'tbPolygon',
 | 
			
		||||
          afterClick: () => this.selectEntityWithoutLocation('tbPolygon'),
 | 
			
		||||
          disabled: true,
 | 
			
		||||
          actions: polygonActions
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const translateService = this.ctx.$injector.get(TranslateService);
 | 
			
		||||
      this.map.pm.setLang('en', translateService.instant('widgets.maps'), 'en');
 | 
			
		||||
      this.map.pm.addControls({
 | 
			
		||||
        position: 'topleft',
 | 
			
		||||
        drawMarker: false,
 | 
			
		||||
        drawCircle: false,
 | 
			
		||||
        drawCircleMarker: false,
 | 
			
		||||
        drawRectangle: false,
 | 
			
		||||
        drawPolyline: false,
 | 
			
		||||
        drawPolygon: false,
 | 
			
		||||
        editMode: this.editPolygons,
 | 
			
		||||
        cutPolygon: this.editPolygons,
 | 
			
		||||
        rotateMode: this.editPolygons
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      const dragListener = (e: L.DragEndEvent) => {
 | 
			
		||||
        if (e.type === 'dragend') {
 | 
			
		||||
          const polygonOffset = this.options.provider === MapProviders.image ? 10 : 0.01;
 | 
			
		||||
 | 
			
		||||
          const convert = this.convertToCustomFormat(this.mousePositionOnMap, polygonOffset);
 | 
			
		||||
          this.mousePositionOnMap.lat = convert[this.options.latKeyName];
 | 
			
		||||
          this.mousePositionOnMap.lng = convert[this.options.lngKeyName];
 | 
			
		||||
 | 
			
		||||
          const latlng1 = this.mousePositionOnMap;
 | 
			
		||||
          const latlng2 = L.latLng(this.mousePositionOnMap.lat, this.mousePositionOnMap.lng + polygonOffset);
 | 
			
		||||
          const latlng3 = L.latLng(this.mousePositionOnMap.lat - polygonOffset, this.mousePositionOnMap.lng);
 | 
			
		||||
          const polygonPoints = [latlng1, latlng2, latlng3];
 | 
			
		||||
 | 
			
		||||
          const newPolygon = L.polygon(polygonPoints).addTo(this.map);
 | 
			
		||||
          this.addPolygons.push(newPolygon);
 | 
			
		||||
          const datasourcesList = document.createElement('div');
 | 
			
		||||
          const customLatLng = {[this.options.polygonKeyName]: this.convertToPolygonFormat(polygonPoints)};
 | 
			
		||||
          const header = document.createElement('p');
 | 
			
		||||
          header.appendChild(document.createTextNode('Select entity:'));
 | 
			
		||||
          header.setAttribute('style', 'font-size: 14px; margin: 8px 0');
 | 
			
		||||
          datasourcesList.appendChild(header);
 | 
			
		||||
          this.datasources.forEach(ds => {
 | 
			
		||||
            const dsItem = document.createElement('p');
 | 
			
		||||
            dsItem.appendChild(document.createTextNode(ds.entityName));
 | 
			
		||||
            dsItem.setAttribute('style', 'font-size: 14px; margin: 8px 0; cursor: pointer');
 | 
			
		||||
            dsItem.onclick = () => {
 | 
			
		||||
              const updatedEnttity = { ...ds, ...customLatLng };
 | 
			
		||||
              this.savePolygonLocation(updatedEnttity).subscribe(() => {
 | 
			
		||||
                this.map.removeLayer(newPolygon);
 | 
			
		||||
                const polygonIndex = this.addPolygons.indexOf(newPolygon);
 | 
			
		||||
                if (polygonIndex > -1) {
 | 
			
		||||
                  this.addPolygons.splice(polygonIndex, 1);
 | 
			
		||||
                }
 | 
			
		||||
                this.deletePolygon(ds.entityName);
 | 
			
		||||
              });
 | 
			
		||||
            };
 | 
			
		||||
            datasourcesList.appendChild(dsItem);
 | 
			
		||||
      this.map.on('pm:create', (e) => {
 | 
			
		||||
        if (e.shape === 'tbMarker') {
 | 
			
		||||
          // @ts-ignore
 | 
			
		||||
          this.saveLocation(this.selectedEntity, this.convertToCustomFormat(e.layer.getLatLng())).subscribe(() => {
 | 
			
		||||
          });
 | 
			
		||||
        } else if (e.shape === 'tbRectangle' || e.shape === 'tbPolygon') {
 | 
			
		||||
          // @ts-ignore
 | 
			
		||||
          this.saveLocation(this.selectedEntity, this.convertPolygonToCustomFormat(e.layer.getLatLngs()[0])).subscribe(() => {
 | 
			
		||||
          });
 | 
			
		||||
          datasourcesList.appendChild(document.createElement('br'));
 | 
			
		||||
          const deleteBtn = document.createElement('a');
 | 
			
		||||
          deleteBtn.appendChild(document.createTextNode('Discard changes'));
 | 
			
		||||
          deleteBtn.onclick = () => {
 | 
			
		||||
            this.map.removeLayer(newPolygon);
 | 
			
		||||
            const polygonIndex = this.addPolygons.indexOf(newPolygon);
 | 
			
		||||
            if (polygonIndex > -1) {
 | 
			
		||||
              this.addPolygons.splice(polygonIndex, 1);
 | 
			
		||||
            }
 | 
			
		||||
          };
 | 
			
		||||
          datasourcesList.appendChild(deleteBtn);
 | 
			
		||||
          const popup = L.popup();
 | 
			
		||||
          popup.setContent(datasourcesList);
 | 
			
		||||
          newPolygon.bindPopup(popup).openPopup();
 | 
			
		||||
        }
 | 
			
		||||
        this.addPolygon.setPosition('topright');
 | 
			
		||||
      };
 | 
			
		||||
      const addPolygon = L.Control.extend({
 | 
			
		||||
        onAdd() {
 | 
			
		||||
          const img = L.DomUtil.create('img') as any;
 | 
			
		||||
          img.src = `assets/add_polygon.svg`;
 | 
			
		||||
          img.style.width = '32px';
 | 
			
		||||
          img.style.height = '32px';
 | 
			
		||||
          img.title = 'Drag and drop to add Polygon';
 | 
			
		||||
          img.onclick = this.dragPolygonVertex;
 | 
			
		||||
          img.draggable = true;
 | 
			
		||||
          const draggableImg = new L.Draggable(img);
 | 
			
		||||
          draggableImg.enable();
 | 
			
		||||
          draggableImg.on('dragend', dragListener);
 | 
			
		||||
          return img;
 | 
			
		||||
        },
 | 
			
		||||
        onRemove() {
 | 
			
		||||
        },
 | 
			
		||||
        dragPolygonVertex: this.dragPolygonVertex
 | 
			
		||||
      } as any);
 | 
			
		||||
      const addPolygonControl = (opts) => {
 | 
			
		||||
        return new addPolygon(opts);
 | 
			
		||||
      };
 | 
			
		||||
      this.addPolygon = addPolygonControl({ position: 'topright' }).addTo(this.map);
 | 
			
		||||
        // @ts-ignore
 | 
			
		||||
        e.layer._pmTempLayer = true;
 | 
			
		||||
        e.layer.remove();
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      this.map.on('pm:cut', (e) => {
 | 
			
		||||
        // @ts-ignore
 | 
			
		||||
        e.originalLayer.setLatLngs(e.layer.getLatLngs());
 | 
			
		||||
        e.originalLayer.addTo(this.map);
 | 
			
		||||
        // @ts-ignore
 | 
			
		||||
        e.originalLayer._pmTempLayer = false;
 | 
			
		||||
        const iterator = this.polygons.values();
 | 
			
		||||
        let result = iterator.next();
 | 
			
		||||
        while (!result.done && e.originalLayer !== result.value.leafletPoly) {
 | 
			
		||||
          result = iterator.next();
 | 
			
		||||
        }
 | 
			
		||||
        // @ts-ignore
 | 
			
		||||
        e.layer._pmTempLayer = true;
 | 
			
		||||
        e.layer.remove();
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      this.map.on('pm:remove', (e) => {
 | 
			
		||||
        if (e.shape === 'Marker') {
 | 
			
		||||
          const iterator = this.markers.values();
 | 
			
		||||
          let result = iterator.next();
 | 
			
		||||
          while (!result.done && e.layer !== result.value.leafletMarker) {
 | 
			
		||||
            result = iterator.next();
 | 
			
		||||
          }
 | 
			
		||||
          this.saveLocation(result.value.data, this.convertToCustomFormat(null)).subscribe(() => {});
 | 
			
		||||
        } else if (e.shape === 'Polygon') {
 | 
			
		||||
          const iterator = this.polygons.values();
 | 
			
		||||
          let result = iterator.next();
 | 
			
		||||
          while (!result.done && e.layer !== result.value.leafletPoly) {
 | 
			
		||||
            result = iterator.next();
 | 
			
		||||
          }
 | 
			
		||||
          this.saveLocation(result.value.data, this.convertPolygonToCustomFormat(null)).subscribe(() => {});
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    public setLoading(loading: boolean) {
 | 
			
		||||
      if (this.loading !== loading) {
 | 
			
		||||
@ -337,11 +330,10 @@ export default abstract class LeafletMap {
 | 
			
		||||
        if (this.options.disableScrollZooming) {
 | 
			
		||||
          this.map.scrollWheelZoom.disable();
 | 
			
		||||
        }
 | 
			
		||||
        if (this.options.draggableMarker) {
 | 
			
		||||
          this.addMarkerControl();
 | 
			
		||||
        }
 | 
			
		||||
        if (this.options.editablePolygon) {
 | 
			
		||||
          this.addPolygonControl();
 | 
			
		||||
        if (this.options.draggableMarker || this.editPolygons) {
 | 
			
		||||
          this.addEditControl();
 | 
			
		||||
        } else {
 | 
			
		||||
          this.map.pm.disableDraw();
 | 
			
		||||
        }
 | 
			
		||||
        if (this.options.useClusterMarkers) {
 | 
			
		||||
          this.map.addLayer(this.markersCluster);
 | 
			
		||||
@ -352,12 +344,53 @@ export default abstract class LeafletMap {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public saveMarkerLocation(datasource: FormattedData, lat?: number, lng?: number): Observable<any> {
 | 
			
		||||
      return of(null);
 | 
			
		||||
    }
 | 
			
		||||
    private saveLocation(e: FormattedData, values: {[key: string]: any}): Observable<any> {
 | 
			
		||||
      const attributeService = this.ctx.$injector.get(AttributeService);
 | 
			
		||||
      const attributes = [];
 | 
			
		||||
      const timeseries = [];
 | 
			
		||||
 | 
			
		||||
    public savePolygonLocation(datasource: FormattedData, coordinates?: Array<[number, number]>): Observable<any> {
 | 
			
		||||
      return of(null);
 | 
			
		||||
      const entityId: EntityId = {
 | 
			
		||||
        entityType: e.$datasource.entityType,
 | 
			
		||||
        id: e.$datasource.entityId
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      for (const dataKeyName of Object.keys(values)) {
 | 
			
		||||
        for (const key of e.$datasource.dataKeys) {
 | 
			
		||||
          if (dataKeyName === key.name) {
 | 
			
		||||
            const value = {
 | 
			
		||||
              key: key.name,
 | 
			
		||||
              value: values[dataKeyName]
 | 
			
		||||
            };
 | 
			
		||||
            if (key.type === DataKeyType.attribute) {
 | 
			
		||||
              attributes.push(value);
 | 
			
		||||
            } else if (key.type === DataKeyType.timeseries) {
 | 
			
		||||
              timeseries.push(value);
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const observables: Observable<any>[] = [];
 | 
			
		||||
      if (timeseries.length) {
 | 
			
		||||
        observables.push(attributeService.saveEntityTimeseries(
 | 
			
		||||
          entityId,
 | 
			
		||||
          LatestTelemetry.LATEST_TELEMETRY,
 | 
			
		||||
          timeseries
 | 
			
		||||
        ));
 | 
			
		||||
      }
 | 
			
		||||
      if (attributes.length) {
 | 
			
		||||
        observables.push(attributeService.saveEntityAttributes(
 | 
			
		||||
          entityId,
 | 
			
		||||
          AttributeScope.SERVER_SCOPE,
 | 
			
		||||
          attributes
 | 
			
		||||
        ));
 | 
			
		||||
      }
 | 
			
		||||
      if (observables.length) {
 | 
			
		||||
        return forkJoin(observables);
 | 
			
		||||
      } else {
 | 
			
		||||
        return of(null);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    createLatLng(lat: number, lng: number): L.LatLng {
 | 
			
		||||
@ -441,7 +474,7 @@ export default abstract class LeafletMap {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    convertToCustomFormat(position: L.LatLng, offset = 0): object {
 | 
			
		||||
      position = checkLngLat(position, this.southWest, this.northEast, offset);
 | 
			
		||||
      position = position ? checkLngLat(position, this.southWest, this.northEast, offset) : {lat: null, lng: null} as L.LatLng;
 | 
			
		||||
 | 
			
		||||
      return {
 | 
			
		||||
        [this.options.latKeyName]: position.lat,
 | 
			
		||||
@ -455,17 +488,18 @@ export default abstract class LeafletMap {
 | 
			
		||||
          if (point.length) {
 | 
			
		||||
            return this.convertToPolygonFormat(point);
 | 
			
		||||
          } else {
 | 
			
		||||
            return [point.lat, point.lng];
 | 
			
		||||
            const convertPoint = checkLngLat(point, this.southWest, this.northEast);
 | 
			
		||||
            return [convertPoint.lat, convertPoint.lng];
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
      } else {
 | 
			
		||||
        return [];
 | 
			
		||||
      }
 | 
			
		||||
      return [];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    convertPolygonToCustomFormat(expression: any[][]): object {
 | 
			
		||||
    convertPolygonToCustomFormat(expression: any[][]): {[key: string]: any} {
 | 
			
		||||
      const coordinate = expression ? this.convertToPolygonFormat(expression) : null;
 | 
			
		||||
      return {
 | 
			
		||||
        [this.options.polygonKeyName] : this.convertToPolygonFormat(expression)
 | 
			
		||||
        [this.options.polygonKeyName]: coordinate
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -484,7 +518,15 @@ export default abstract class LeafletMap {
 | 
			
		||||
        }
 | 
			
		||||
        this.updateMarkers(formattedData, false);
 | 
			
		||||
        this.updateBoundsInternal();
 | 
			
		||||
        if (this.options.draggableMarker || this.options.editablePolygon) {
 | 
			
		||||
        if (this.options.draggableMarker) {
 | 
			
		||||
          const foundEntityWithoutLocation = formattedData.some(mData => !this.convertPosition(mData));
 | 
			
		||||
          this.map.pm.Toolbar.setButtonDisabled('tbMarker', !foundEntityWithoutLocation);
 | 
			
		||||
          this.datasources = formattedData;
 | 
			
		||||
        }
 | 
			
		||||
        if (this.editPolygons) {
 | 
			
		||||
          const foundEntityWithoutPolygon = formattedData.some(pData => !this.isValidPolygonPosition(pData));
 | 
			
		||||
          this.map.pm.Toolbar.setButtonDisabled('tbPolygon', !foundEntityWithoutPolygon);
 | 
			
		||||
          this.map.pm.Toolbar.setButtonDisabled('tbRectangle', !foundEntityWithoutPolygon);
 | 
			
		||||
          this.datasources = formattedData;
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
@ -577,10 +619,10 @@ export default abstract class LeafletMap {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    dragMarker = (e, data = {} as FormattedData) => {
 | 
			
		||||
        if (e.type !== 'dragend') {
 | 
			
		||||
        if (e === undefined) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        this.saveMarkerLocation({ ...data, ...this.convertToCustomFormat(e.target._latlng) }).subscribe();
 | 
			
		||||
        this.saveLocation(data, this.convertToCustomFormat(e.target._latlng)).subscribe();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private createMarker(key: string, data: FormattedData, dataSources: FormattedData[], settings: MarkerSettings,
 | 
			
		||||
@ -728,11 +770,15 @@ export default abstract class LeafletMap {
 | 
			
		||||
 | 
			
		||||
    // Polygon
 | 
			
		||||
 | 
			
		||||
  isValidPolygonPosition(data: FormattedData): boolean {
 | 
			
		||||
    return data && isDefinedAndNotNull(data[this.options.polygonKeyName]) && !isEmptyStr(data[this.options.polygonKeyName]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  updatePolygons(polyData: FormattedData[], updateBounds = true) {
 | 
			
		||||
    const keys: string[] = [];
 | 
			
		||||
    this.polygonsData = deepClone(polyData);
 | 
			
		||||
    polyData.forEach((data: FormattedData) => {
 | 
			
		||||
      if (data && isDefinedAndNotNull(data[this.options.polygonKeyName]) && !isEmptyStr(data[this.options.polygonKeyName])) {
 | 
			
		||||
      if (this.isValidPolygonPosition(data)) {
 | 
			
		||||
        if (isString((data[this.options.polygonKeyName]))) {
 | 
			
		||||
          data[this.options.polygonKeyName] = JSON.parse(data[this.options.polygonKeyName]);
 | 
			
		||||
        }
 | 
			
		||||
@ -758,15 +804,14 @@ export default abstract class LeafletMap {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  dragPolygonVertex = (e?, data = {} as FormattedData) => {
 | 
			
		||||
    if (e === undefined || (e.type !== 'editable:vertex:dragend' && e.type !== 'editable:vertex:deleted')) {
 | 
			
		||||
    if (e === undefined) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    if (this.options.provider !== MapProviders.image) {
 | 
			
		||||
      for (const key of Object.keys(e.layer._latlngs[0])) {
 | 
			
		||||
        e.layer._latlngs[0][key] = checkLngLat(e.layer._latlngs[0][key], this.southWest, this.northEast);
 | 
			
		||||
      }
 | 
			
		||||
    let coordinates = e.layer.getLatLngs();
 | 
			
		||||
    if (coordinates.length === 1) {
 | 
			
		||||
      coordinates = coordinates[0];
 | 
			
		||||
    }
 | 
			
		||||
    this.savePolygonLocation({ ...data, ...this.convertPolygonToCustomFormat(e.layer._latlngs) }).subscribe();
 | 
			
		||||
    this.saveLocation(data, this.convertPolygonToCustomFormat(coordinates)).subscribe(() => {});
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    createPolygon(polyData: FormattedData, dataSources: FormattedData[], settings: PolygonSettings, updateBounds = true) {
 | 
			
		||||
 | 
			
		||||
@ -57,6 +57,7 @@ export type MapSettings = {
 | 
			
		||||
    showCoverageOnHover: boolean,
 | 
			
		||||
    animate: boolean,
 | 
			
		||||
    maxClusterRadius: number,
 | 
			
		||||
    spiderfyOnMaxZoom: boolean,
 | 
			
		||||
    chunkedLoading: boolean,
 | 
			
		||||
    removeOutsideVisibleBounds: boolean,
 | 
			
		||||
    useCustomProvider: boolean,
 | 
			
		||||
 | 
			
		||||
@ -14,41 +14,23 @@
 | 
			
		||||
/// limitations under the License.
 | 
			
		||||
///
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
  defaultSettings,
 | 
			
		||||
  FormattedData,
 | 
			
		||||
  hereProviders,
 | 
			
		||||
  MapProviders,
 | 
			
		||||
  UnitedMapSettings
 | 
			
		||||
} from './map-models';
 | 
			
		||||
import { defaultSettings, hereProviders, MapProviders, UnitedMapSettings } from './map-models';
 | 
			
		||||
import LeafletMap from './leaflet-map';
 | 
			
		||||
import {
 | 
			
		||||
  commonMapSettingsSchema,
 | 
			
		||||
  mapPolygonSchema,
 | 
			
		||||
  mapProviderSchema,
 | 
			
		||||
  markerClusteringSettingsSchema,
 | 
			
		||||
  markerClusteringSettingsSchemaLeaflet,
 | 
			
		||||
  routeMapSettingsSchema
 | 
			
		||||
} from './schemes';
 | 
			
		||||
import { MapWidgetInterface, MapWidgetStaticInterface } from './map-widget.interface';
 | 
			
		||||
import {
 | 
			
		||||
  addCondition,
 | 
			
		||||
  addGroupInfo,
 | 
			
		||||
  addToSchema,
 | 
			
		||||
  initSchema,
 | 
			
		||||
  mergeSchemes
 | 
			
		||||
} from '@core/schema-utils';
 | 
			
		||||
import { addCondition, addGroupInfo, addToSchema, initSchema, mergeSchemes } from '@core/schema-utils';
 | 
			
		||||
import { WidgetContext } from '@app/modules/home/models/widget-component.models';
 | 
			
		||||
import { getDefCenterPosition, getProviderSchema, parseFunction, parseWithTranslation } from './common-maps-utils';
 | 
			
		||||
import { Datasource, DatasourceData, JsonSettingsSchema, WidgetActionDescriptor } from '@shared/models/widget.models';
 | 
			
		||||
import { EntityId } from '@shared/models/id/entity-id';
 | 
			
		||||
import { AttributeScope, DataKeyType, LatestTelemetry } from '@shared/models/telemetry/telemetry.models';
 | 
			
		||||
import { AttributeService } from '@core/http/attribute.service';
 | 
			
		||||
import { TranslateService } from '@ngx-translate/core';
 | 
			
		||||
import { UtilsService } from '@core/services/utils.service';
 | 
			
		||||
import { EntityDataPageLink } from '@shared/models/query/query.models';
 | 
			
		||||
import { isDefined } from '@core/utils';
 | 
			
		||||
import { forkJoin, Observable, of } from 'rxjs';
 | 
			
		||||
import { providerClass } from '@home/components/widget/lib/maps/providers';
 | 
			
		||||
 | 
			
		||||
// @dynamic
 | 
			
		||||
@ -81,8 +63,6 @@ export class MapWidgetController implements MapWidgetInterface {
 | 
			
		||||
        }
 | 
			
		||||
        parseWithTranslation.setTranslate(this.translate);
 | 
			
		||||
        this.map = new MapClass(this.ctx, $element, this.settings);
 | 
			
		||||
        this.map.saveMarkerLocation = this.setMarkerLocation;
 | 
			
		||||
        this.map.savePolygonLocation = this.savePolygonLocation;
 | 
			
		||||
        this.pageLink = {
 | 
			
		||||
          page: 0,
 | 
			
		||||
          pageSize: this.settings.mapPageSize,
 | 
			
		||||
@ -178,112 +158,6 @@ export class MapWidgetController implements MapWidgetInterface {
 | 
			
		||||
        }, entityName, null, entityLabel);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setMarkerLocation = (e: FormattedData, lat?: number, lng?: number) => {
 | 
			
		||||
        const attributeService = this.ctx.$injector.get(AttributeService);
 | 
			
		||||
 | 
			
		||||
        const entityId: EntityId = {
 | 
			
		||||
            entityType: e.$datasource.entityType,
 | 
			
		||||
            id: e.$datasource.entityId
 | 
			
		||||
        };
 | 
			
		||||
        const attributes = [];
 | 
			
		||||
        const timeseries = [];
 | 
			
		||||
 | 
			
		||||
        const latProperties = [this.settings.latKeyName, this.settings.xPosKeyName];
 | 
			
		||||
        const lngProperties = [this.settings.lngKeyName, this.settings.yPosKeyName];
 | 
			
		||||
        e.$datasource.dataKeys.forEach(key => {
 | 
			
		||||
            let value;
 | 
			
		||||
            if (latProperties.includes(key.name)) {
 | 
			
		||||
                value = {
 | 
			
		||||
                    key: key.name,
 | 
			
		||||
                    value: isDefined(lat) ? lat : e[key.name]
 | 
			
		||||
                };
 | 
			
		||||
            } else if (lngProperties.includes(key.name)) {
 | 
			
		||||
              value = {
 | 
			
		||||
                key: key.name,
 | 
			
		||||
                value: isDefined(lng) ? lng : e[key.name]
 | 
			
		||||
              };
 | 
			
		||||
            }
 | 
			
		||||
            if (value) {
 | 
			
		||||
              if (key.type === DataKeyType.attribute) {
 | 
			
		||||
                attributes.push(value);
 | 
			
		||||
              }
 | 
			
		||||
              if (key.type === DataKeyType.timeseries) {
 | 
			
		||||
                timeseries.push(value);
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        const observables: Observable<any>[] = [];
 | 
			
		||||
        if (timeseries.length) {
 | 
			
		||||
            observables.push(attributeService.saveEntityTimeseries(
 | 
			
		||||
              entityId,
 | 
			
		||||
              LatestTelemetry.LATEST_TELEMETRY,
 | 
			
		||||
              timeseries
 | 
			
		||||
            ));
 | 
			
		||||
        }
 | 
			
		||||
        if (attributes.length) {
 | 
			
		||||
            observables.push(attributeService.saveEntityAttributes(
 | 
			
		||||
              entityId,
 | 
			
		||||
              AttributeScope.SERVER_SCOPE,
 | 
			
		||||
              attributes
 | 
			
		||||
            ));
 | 
			
		||||
        }
 | 
			
		||||
        if (observables.length) {
 | 
			
		||||
          return forkJoin(observables);
 | 
			
		||||
        } else {
 | 
			
		||||
          return of(null);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  savePolygonLocation = (e: FormattedData, coordinates?: Array<any>) => {
 | 
			
		||||
    const attributeService = this.ctx.$injector.get(AttributeService);
 | 
			
		||||
 | 
			
		||||
    const entityId: EntityId = {
 | 
			
		||||
      entityType: e.$datasource.entityType,
 | 
			
		||||
      id: e.$datasource.entityId
 | 
			
		||||
    };
 | 
			
		||||
    const attributes = [];
 | 
			
		||||
    const timeseries = [];
 | 
			
		||||
 | 
			
		||||
    const coordinatesProperties =  this.settings.polygonKeyName;
 | 
			
		||||
    e.$datasource.dataKeys.forEach(key => {
 | 
			
		||||
      let value;
 | 
			
		||||
      if (coordinatesProperties === key.name) {
 | 
			
		||||
        value = {
 | 
			
		||||
          key: key.name,
 | 
			
		||||
          value: isDefined(coordinates) ? coordinates : e[key.name]
 | 
			
		||||
        };
 | 
			
		||||
      }
 | 
			
		||||
      if (value) {
 | 
			
		||||
        if (key.type === DataKeyType.attribute) {
 | 
			
		||||
          attributes.push(value);
 | 
			
		||||
        }
 | 
			
		||||
        if (key.type === DataKeyType.timeseries) {
 | 
			
		||||
          timeseries.push(value);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    const observables: Observable<any>[] = [];
 | 
			
		||||
    if (timeseries.length) {
 | 
			
		||||
      observables.push(attributeService.saveEntityTimeseries(
 | 
			
		||||
        entityId,
 | 
			
		||||
        LatestTelemetry.LATEST_TELEMETRY,
 | 
			
		||||
        timeseries
 | 
			
		||||
      ));
 | 
			
		||||
    }
 | 
			
		||||
    if (attributes.length) {
 | 
			
		||||
      observables.push(attributeService.saveEntityAttributes(
 | 
			
		||||
        entityId,
 | 
			
		||||
        AttributeScope.SERVER_SCOPE,
 | 
			
		||||
        attributes
 | 
			
		||||
      ));
 | 
			
		||||
    }
 | 
			
		||||
    if (observables.length) {
 | 
			
		||||
      return forkJoin(observables);
 | 
			
		||||
    } else {
 | 
			
		||||
      return of(null);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    initSettings(settings: UnitedMapSettings, isEditMap?: boolean): UnitedMapSettings {
 | 
			
		||||
        const functionParams = ['data', 'dsData', 'dsIndex'];
 | 
			
		||||
        this.provider = settings.provider || this.mapProvider;
 | 
			
		||||
 | 
			
		||||
@ -29,6 +29,10 @@
 | 
			
		||||
  box-shadow: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.leaflet-container{
 | 
			
		||||
.leaflet-container {
 | 
			
		||||
  background-color: white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.leaflet-buttons-control-button.pm-disabled {
 | 
			
		||||
  pointer-events: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -42,9 +42,7 @@ export class Marker {
 | 
			
		||||
  constructor(private map: LeafletMap, private location: L.LatLng, public settings: MarkerSettings,
 | 
			
		||||
              data?: FormattedData, dataSources?, onDragendListener?) {
 | 
			
		||||
        this.setDataSources(data, dataSources);
 | 
			
		||||
        this.leafletMarker = L.marker(location, {
 | 
			
		||||
            draggable: settings.draggableMarker
 | 
			
		||||
        });
 | 
			
		||||
        this.leafletMarker = L.marker(location, {pmIgnore: !settings.draggableMarker});
 | 
			
		||||
 | 
			
		||||
        this.markerOffset = [
 | 
			
		||||
          isDefined(settings.markerOffsetX) ? settings.markerOffsetX : 0.5,
 | 
			
		||||
@ -72,8 +70,8 @@ export class Marker {
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (onDragendListener) {
 | 
			
		||||
            this.leafletMarker.on('dragend', (e) => onDragendListener(e, this.data));
 | 
			
		||||
        if (settings.draggableMarker && onDragendListener) {
 | 
			
		||||
          this.leafletMarker.on('pm:dragend', (e) => onDragendListener(e, this.data));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -199,19 +197,24 @@ export class Marker {
 | 
			
		||||
 | 
			
		||||
    createColoredMarkerIcon(color: tinycolor.Instance): { size: number[], icon: Icon } {
 | 
			
		||||
      return {
 | 
			
		||||
            size: [21, 34],
 | 
			
		||||
            icon: L.icon({
 | 
			
		||||
              iconUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|' + color.toHex(),
 | 
			
		||||
              iconSize: [21, 34],
 | 
			
		||||
              iconAnchor: [21 * this.markerOffset[0], 34 * this.markerOffset[1]],
 | 
			
		||||
              popupAnchor: [0, -34],
 | 
			
		||||
              shadowUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_shadow',
 | 
			
		||||
              shadowSize: [40, 37],
 | 
			
		||||
              shadowAnchor: [12, 35]
 | 
			
		||||
        size: [21, 34],
 | 
			
		||||
        icon: L.icon({
 | 
			
		||||
          iconUrl: this.createColorIconURI(color),
 | 
			
		||||
          iconSize: [21, 34],
 | 
			
		||||
          iconAnchor: [21 * this.markerOffset[0], 34 * this.markerOffset[1]],
 | 
			
		||||
          popupAnchor: [0, -34],
 | 
			
		||||
          shadowUrl: 'assets/shadow.png',
 | 
			
		||||
          shadowSize: [40, 37],
 | 
			
		||||
          shadowAnchor: [12, 35]
 | 
			
		||||
        })
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    createColorIconURI(color: tinycolor.Instance): string {
 | 
			
		||||
      const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="-191.35 -351.18 1083.58 1730.46"><path fill-rule="evenodd" clip-rule="evenodd" fill="#${color.toHex()}" stroke="#000" stroke-width="37" stroke-miterlimit="10" d="M351.833 1360.78c-38.766-190.3-107.116-348.665-189.903-495.44C100.523 756.469 29.386 655.978-36.434 550.404c-21.972-35.244-40.934-72.477-62.047-109.054-42.216-73.137-76.444-157.935-74.269-267.932 2.125-107.473 33.208-193.685 78.03-264.173C-21-206.69 102.481-301.745 268.164-326.724c135.466-20.425 262.475 14.082 352.543 66.747 73.6 43.038 130.596 100.528 173.92 168.28 45.22 70.716 76.36 154.26 78.971 263.233 1.337 55.83-7.805 107.532-20.684 150.417-13.034 43.41-33.996 79.695-52.646 118.455-36.406 75.659-82.049 144.981-127.855 214.345-136.437 206.606-264.496 417.31-320.58 706.028z"/><circle fill-rule="evenodd" clip-rule="evenodd" cx="352.891" cy="225.779" r="183.332"/></svg>`;
 | 
			
		||||
      return 'data:image/svg+xml;base64,' + btoa(svg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    removeMarker() {
 | 
			
		||||
        /*     this.map$.subscribe(map =>
 | 
			
		||||
                 this.leafletMarker.addTo(map))*/
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,6 @@
 | 
			
		||||
import L, { LatLngExpression, LeafletMouseEvent } from 'leaflet';
 | 
			
		||||
import { createTooltip } from './maps-utils';
 | 
			
		||||
import { functionValueCalculator, parseWithTranslation, safeExecute } from './common-maps-utils';
 | 
			
		||||
import 'leaflet-editable/src/Leaflet.Editable';
 | 
			
		||||
import { FormattedData, PolygonSettings } from './map-models';
 | 
			
		||||
 | 
			
		||||
export class Polygon {
 | 
			
		||||
@ -37,14 +36,12 @@ export class Polygon {
 | 
			
		||||
          color: settings.polygonStrokeColor,
 | 
			
		||||
          weight: settings.polygonStrokeWeight,
 | 
			
		||||
          fillOpacity: settings.polygonOpacity,
 | 
			
		||||
          opacity: settings.polygonStrokeOpacity
 | 
			
		||||
          opacity: settings.polygonStrokeOpacity,
 | 
			
		||||
          pmIgnore: !settings.editablePolygon
 | 
			
		||||
        }).addTo(this.map);
 | 
			
		||||
        if (settings.editablePolygon) {
 | 
			
		||||
            this.leafletPoly.enableEdit(this.map);
 | 
			
		||||
            if (onDragendListener) {
 | 
			
		||||
                this.leafletPoly.on('editable:vertex:dragend', e => onDragendListener(e, this.data));
 | 
			
		||||
                this.leafletPoly.on('editable:vertex:deleted', e => onDragendListener(e, this.data));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        if (settings.editablePolygon && onDragendListener) {
 | 
			
		||||
          this.leafletPoly.on('pm:edit', (e) => onDragendListener(e, this.data));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -73,13 +70,7 @@ export class Polygon {
 | 
			
		||||
    updatePolygon(data: FormattedData, dataSources: FormattedData[], settings: PolygonSettings) {
 | 
			
		||||
      this.data = data;
 | 
			
		||||
      this.dataSources = dataSources;
 | 
			
		||||
      if (settings.editablePolygon) {
 | 
			
		||||
        this.leafletPoly.disableEdit();
 | 
			
		||||
      }
 | 
			
		||||
      this.leafletPoly.setLatLngs(data[this.settings.polygonKeyName]);
 | 
			
		||||
      if (settings.editablePolygon) {
 | 
			
		||||
        this.leafletPoly.enableEdit(this.map);
 | 
			
		||||
      }
 | 
			
		||||
      if (settings.showPolygonTooltip) {
 | 
			
		||||
        this.updateTooltip(this.data);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,8 @@
 | 
			
		||||
/// limitations under the License.
 | 
			
		||||
///
 | 
			
		||||
 | 
			
		||||
import L, { PolylineDecoratorOptions } from 'leaflet';
 | 
			
		||||
// @ts-ignore
 | 
			
		||||
import L, { PolylineDecorator, PolylineDecoratorOptions, Symbol } from 'leaflet';
 | 
			
		||||
import 'leaflet-polylinedecorator';
 | 
			
		||||
 | 
			
		||||
import { FormattedData, PolylineSettings } from './map-models';
 | 
			
		||||
@ -23,7 +24,7 @@ import { functionValueCalculator } from '@home/components/widget/lib/maps/common
 | 
			
		||||
export class Polyline {
 | 
			
		||||
 | 
			
		||||
  leafletPoly: L.Polyline;
 | 
			
		||||
  polylineDecorator: L.PolylineDecorator;
 | 
			
		||||
  polylineDecorator: PolylineDecorator;
 | 
			
		||||
  dataSources: FormattedData[];
 | 
			
		||||
  data: FormattedData;
 | 
			
		||||
 | 
			
		||||
@ -36,7 +37,7 @@ export class Polyline {
 | 
			
		||||
    ).addTo(this.map);
 | 
			
		||||
 | 
			
		||||
    if (settings.usePolylineDecorator) {
 | 
			
		||||
      this.polylineDecorator = L.polylineDecorator(this.leafletPoly, this.getDecoratorSettings(settings)).addTo(this.map);
 | 
			
		||||
      this.polylineDecorator = new PolylineDecorator(this.leafletPoly, this.getDecoratorSettings(settings)).addTo(this.map);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -47,7 +48,7 @@ export class Polyline {
 | 
			
		||||
          offset: settings.decoratorOffset,
 | 
			
		||||
          endOffset: settings.endDecoratorOffset,
 | 
			
		||||
          repeat: settings.decoratorRepeat,
 | 
			
		||||
          symbol: L.Symbol[settings.decoratorSymbol]({
 | 
			
		||||
          symbol: Symbol[settings.decoratorSymbol]({
 | 
			
		||||
            pixelSize: settings.decoratorSymbolSize,
 | 
			
		||||
            polygon: false,
 | 
			
		||||
            pathOptions: {
 | 
			
		||||
@ -78,7 +79,8 @@ export class Polyline {
 | 
			
		||||
      opacity: functionValueCalculator(settings.useStrokeOpacityFunction, settings.strokeOpacityFunction,
 | 
			
		||||
        [this.data, this.dataSources, this.data.dsIndex], settings.strokeOpacity),
 | 
			
		||||
      weight: functionValueCalculator(settings.useStrokeWeightFunction, settings.strokeWeightFunction,
 | 
			
		||||
        [this.data, this.dataSources, this.data.dsIndex], settings.strokeWeight)
 | 
			
		||||
        [this.data, this.dataSources, this.data.dsIndex], settings.strokeWeight),
 | 
			
		||||
      pmIgnore: true
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -38,7 +38,6 @@ export class GoogleMap extends LeafletMap {
 | 
			
		||||
    this.loadGoogle(() => {
 | 
			
		||||
      const map = L.map($container, {
 | 
			
		||||
        attributionControl: false,
 | 
			
		||||
        editable: !!options.editablePolygon,
 | 
			
		||||
        tap: L.Browser.safari && L.Browser.mobile
 | 
			
		||||
      }).setView(options?.defaultCenterPosition, options?.defaultZoomLevel || DEFAULT_ZOOM_LEVEL);
 | 
			
		||||
      (L.gridLayer as any).googleMutant({
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,6 @@ export class HEREMap extends LeafletMap {
 | 
			
		||||
    constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) {
 | 
			
		||||
        super(ctx, $container, options);
 | 
			
		||||
        const map = L.map($container, {
 | 
			
		||||
          editable: !!options.editablePolygon,
 | 
			
		||||
          tap: L.Browser.safari && L.Browser.mobile
 | 
			
		||||
        }).setView(options?.defaultCenterPosition, options?.defaultZoomLevel || DEFAULT_ZOOM_LEVEL);
 | 
			
		||||
        const tileLayer = (L.tileLayer as any).provider(options.mapProviderHere || 'HERE.normalDay', options.credentials);
 | 
			
		||||
 | 
			
		||||
@ -22,7 +22,6 @@ import { filter, map, mergeMap } from 'rxjs/operators';
 | 
			
		||||
import {
 | 
			
		||||
  aspectCache,
 | 
			
		||||
  calculateNewPointCoordinate,
 | 
			
		||||
  checkLngLat,
 | 
			
		||||
  parseFunction
 | 
			
		||||
} from '@home/components/widget/lib/maps/common-maps-utils';
 | 
			
		||||
import { WidgetContext } from '@home/models/widget-component.models';
 | 
			
		||||
@ -221,7 +220,6 @@ export class ImageMap extends LeafletMap {
 | 
			
		||||
          zoom: 1,
 | 
			
		||||
          crs: L.CRS.Simple,
 | 
			
		||||
          attributionControl: false,
 | 
			
		||||
          editable: !!this.options.editablePolygon,
 | 
			
		||||
          tap: L.Browser.safari && L.Browser.mobile
 | 
			
		||||
        });
 | 
			
		||||
        this.updateBounds(updateImage);
 | 
			
		||||
@ -263,7 +261,13 @@ export class ImageMap extends LeafletMap {
 | 
			
		||||
        return L.CRS.Simple.latLngToPoint(latLng, maxZoom - 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    convertToCustomFormat(position: L.LatLng, offset = 0, width = this.width, height = this.height): object {
 | 
			
		||||
    convertToCustomFormat(position: L.LatLng, offset = 0, width = this.width, height = this.height): {[key: string]: any} {
 | 
			
		||||
      if (!position) {
 | 
			
		||||
        return {
 | 
			
		||||
          [this.options.xPosKeyName]: null,
 | 
			
		||||
          [this.options.yPosKeyName]: null
 | 
			
		||||
        };
 | 
			
		||||
      }
 | 
			
		||||
      const point = this.latLngToPoint(position);
 | 
			
		||||
      const customX = calculateNewPointCoordinate(point.x, width);
 | 
			
		||||
      const customY = calculateNewPointCoordinate(point.y, height);
 | 
			
		||||
@ -279,13 +283,9 @@ export class ImageMap extends LeafletMap {
 | 
			
		||||
        point.y = height;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const customLatLng = checkLngLat(this.pointToLatLng(point.x, point.y), this.southWest, this.northEast, offset);
 | 
			
		||||
 | 
			
		||||
      return {
 | 
			
		||||
        [this.options.xPosKeyName]: customX,
 | 
			
		||||
        [this.options.yPosKeyName]: customY,
 | 
			
		||||
        [this.options.latKeyName]: customLatLng.lat,
 | 
			
		||||
        [this.options.lngKeyName]: customLatLng.lng
 | 
			
		||||
        [this.options.yPosKeyName]: customY
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -304,9 +304,10 @@ export class ImageMap extends LeafletMap {
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    convertPolygonToCustomFormat(expression: any[][]): object {
 | 
			
		||||
    convertPolygonToCustomFormat(expression: any[][]): {[key: string]: any} {
 | 
			
		||||
      const coordinate = expression ? this.convertToPolygonFormat(expression) : null;
 | 
			
		||||
      return {
 | 
			
		||||
        [this.options.polygonKeyName] : this.convertToPolygonFormat(expression)
 | 
			
		||||
        [this.options.polygonKeyName]: coordinate
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,6 @@ export class OpenStreetMap extends LeafletMap {
 | 
			
		||||
    constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) {
 | 
			
		||||
        super(ctx, $container, options);
 | 
			
		||||
        const map =  L.map($container, {
 | 
			
		||||
          editable: !!options.editablePolygon,
 | 
			
		||||
          tap: L.Browser.safari && L.Browser.mobile
 | 
			
		||||
        }).setView(options?.defaultCenterPosition, options?.defaultZoomLevel || DEFAULT_ZOOM_LEVEL);
 | 
			
		||||
        let tileLayer;
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,6 @@ export class TencentMap extends LeafletMap {
 | 
			
		||||
    super(ctx, $container, options);
 | 
			
		||||
    const txUrl = 'http://rt{s}.map.gtimg.com/realtimerender?z={z}&x={x}&y={y}&type=vector&style=0';
 | 
			
		||||
    const map = L.map($container, {
 | 
			
		||||
      editable: !!options.editablePolygon,
 | 
			
		||||
      tap: L.Browser.safari && L.Browser.mobile
 | 
			
		||||
    }).setView(options?.defaultCenterPosition, options?.defaultZoomLevel || DEFAULT_ZOOM_LEVEL);
 | 
			
		||||
    const txLayer = L.tileLayer(txUrl, {
 | 
			
		||||
 | 
			
		||||
@ -728,6 +728,11 @@ export const markerClusteringSettingsSchemaLeaflet =
 | 
			
		||||
                type: 'number',
 | 
			
		||||
                default: 80
 | 
			
		||||
            },
 | 
			
		||||
            spiderfyOnMaxZoom: {
 | 
			
		||||
              title: 'Spiderfy at the max zoom level (to see all cluster markers)',
 | 
			
		||||
              type: 'boolean',
 | 
			
		||||
              default: false
 | 
			
		||||
            },
 | 
			
		||||
            chunkedLoading: {
 | 
			
		||||
                title: 'Use chunks for adding markers so that the page does not freeze',
 | 
			
		||||
                type: 'boolean',
 | 
			
		||||
@ -747,6 +752,7 @@ export const markerClusteringSettingsSchemaLeaflet =
 | 
			
		||||
        'showCoverageOnHover',
 | 
			
		||||
        'animate',
 | 
			
		||||
        'maxClusterRadius',
 | 
			
		||||
        'spiderfyOnMaxZoom',
 | 
			
		||||
        'chunkedLoading',
 | 
			
		||||
        'removeOutsideVisibleBounds'
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
@ -100,7 +100,10 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
 | 
			
		||||
    addGroupInfo(schema, 'Path Settings');
 | 
			
		||||
    addToSchema(schema, addCondition(pointSchema, 'model.showPoints === true', ['showPoints']));
 | 
			
		||||
    addGroupInfo(schema, 'Path Points Settings');
 | 
			
		||||
    addToSchema(schema, addCondition(mapPolygonSchema, 'model.showPolygon === true', ['showPolygon']));
 | 
			
		||||
    const mapPolygonSchemaWithoutEdit = mapPolygonSchema;
 | 
			
		||||
    delete mapPolygonSchemaWithoutEdit.schema.properties.editablePolygon;
 | 
			
		||||
    mapPolygonSchemaWithoutEdit.form.splice(mapPolygonSchemaWithoutEdit.form.indexOf('editablePolygon'), 1);
 | 
			
		||||
    addToSchema(schema, addCondition(mapPolygonSchemaWithoutEdit, 'model.showPolygon === true', ['showPolygon']));
 | 
			
		||||
    addGroupInfo(schema, 'Polygon Settings');
 | 
			
		||||
    return schema;
 | 
			
		||||
  }
 | 
			
		||||
@ -115,6 +118,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
 | 
			
		||||
      rotationAngle: 0
 | 
			
		||||
    };
 | 
			
		||||
    this.settings = { ...settings, ...this.ctx.settings };
 | 
			
		||||
    this.settings.editablePolygon = false;
 | 
			
		||||
    this.useAnchors = this.settings.showPoints && this.settings.usePointAsAnchor;
 | 
			
		||||
    this.settings.pointAsAnchorFunction = parseFunction(this.settings.pointAsAnchorFunction, ['data', 'dsData', 'dsIndex']);
 | 
			
		||||
    this.settings.tooltipFunction = parseFunction(this.settings.tooltipFunction, ['data', 'dsData', 'dsIndex']);
 | 
			
		||||
 | 
			
		||||
@ -41,6 +41,7 @@ import { EdgesOverviewWidgetComponent } from '@home/components/widget/lib/edges-
 | 
			
		||||
import { JsonInputWidgetComponent } from '@home/components/widget/lib/json-input-widget.component';
 | 
			
		||||
import { QrCodeWidgetComponent } from '@home/components/widget/lib/qrcode-widget.component';
 | 
			
		||||
import { MarkdownWidgetComponent } from '@home/components/widget/lib/markdown-widget.component';
 | 
			
		||||
import { SelectEntityDialogComponent } from './lib/maps/dialogs/select-entity-dialog.component';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations:
 | 
			
		||||
@ -62,7 +63,8 @@ import { MarkdownWidgetComponent } from '@home/components/widget/lib/markdown-wi
 | 
			
		||||
      NavigationCardsWidgetComponent,
 | 
			
		||||
      NavigationCardWidgetComponent,
 | 
			
		||||
      QrCodeWidgetComponent,
 | 
			
		||||
      MarkdownWidgetComponent
 | 
			
		||||
      MarkdownWidgetComponent,
 | 
			
		||||
      SelectEntityDialogComponent
 | 
			
		||||
    ],
 | 
			
		||||
  imports: [
 | 
			
		||||
    CommonModule,
 | 
			
		||||
 | 
			
		||||
@ -1 +0,0 @@
 | 
			
		||||
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48"><path d="M24 4c-7.72 0-14 6.28-14 14 0 10.5 14 26 14 26s14-15.5 14-26c0-7.72-6.28-14-14-14zm8 16h-6v6h-4v-6h-6v-4h6v-6h4v6h6v4z"/></svg>
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 219 B  | 
@ -1,3 +0,0 @@
 | 
			
		||||
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48">
 | 
			
		||||
  <polygon points="2,46 46,46 24,2" style="fill:transparent;stroke:black;stroke-width:2"/>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 182 B  | 
@ -3238,7 +3238,40 @@
 | 
			
		||||
            "update-timeseries": "Update timeseries",
 | 
			
		||||
            "value": "Value"
 | 
			
		||||
        },
 | 
			
		||||
        "invalid-qr-code-text": "Invalid input text for QR code. Input should have a string type"
 | 
			
		||||
        "invalid-qr-code-text": "Invalid input text for QR code. Input should have a string type",
 | 
			
		||||
        "maps": {
 | 
			
		||||
            "select-entity": "Select entity",
 | 
			
		||||
            "select-entity-hint": "Hint: after selection click at the map to set position",
 | 
			
		||||
            "tooltips": {
 | 
			
		||||
                "placeMarker": "Click to place marker",
 | 
			
		||||
                "firstVertex": "Click to place first point",
 | 
			
		||||
                "continueLine": "Click to continue drawing",
 | 
			
		||||
                "finishLine": "Click any existing marker to finish",
 | 
			
		||||
                "finishPoly": "Click first marker to finish and save",
 | 
			
		||||
                "finishRect": "Click to finish and save",
 | 
			
		||||
                "startCircle": "Click to place circle center",
 | 
			
		||||
                "finishCircle": "Click to finish circle",
 | 
			
		||||
                "placeCircleMarker": "Click to place circle marker"
 | 
			
		||||
            },
 | 
			
		||||
            "actions": {
 | 
			
		||||
                "finish": "Finish",
 | 
			
		||||
                "cancel": "Cancel",
 | 
			
		||||
                "removeLastVertex": "Remove last point"
 | 
			
		||||
            },
 | 
			
		||||
            "buttonTitles": {
 | 
			
		||||
                "drawMarkerButton": "Create marker",
 | 
			
		||||
                "drawPolyButton": "Create polygon",
 | 
			
		||||
                "drawLineButton": "Create Polyline",
 | 
			
		||||
                "drawCircleButton": "Create Circle",
 | 
			
		||||
                "drawRectButton": "Create rectangle",
 | 
			
		||||
                "editButton": "Edit mode",
 | 
			
		||||
                "dragButton": "Drag-drop mode",
 | 
			
		||||
                "cutButton": "Cut polygon area",
 | 
			
		||||
                "deleteButton": "Remove",
 | 
			
		||||
                "drawCircleMarkerButton": "Create circle marker",
 | 
			
		||||
                "rotateButton": "Rotate polygon"
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "icon": {
 | 
			
		||||
        "icon": "Icon",
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								ui-ngx/src/assets/shadow.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								ui-ngx/src/assets/shadow.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 712 B  | 
@ -3,7 +3,7 @@
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "outDir": "../out-tsc/app",
 | 
			
		||||
    "types": ["node", "jquery", "flot", "tooltipster", "tinycolor2", "js-beautify",
 | 
			
		||||
       "react", "react-dom", "jstree", "raphael", "canvas-gauges", "leaflet", "leaflet.markercluster", "leaflet-editable"]
 | 
			
		||||
       "react", "react-dom", "jstree", "raphael", "canvas-gauges"]
 | 
			
		||||
  },
 | 
			
		||||
  "angularCompilerOptions": {
 | 
			
		||||
    "fullTemplateTypeCheck": true
 | 
			
		||||
 | 
			
		||||
@ -17,15 +17,13 @@
 | 
			
		||||
import * as L from 'leaflet';
 | 
			
		||||
 | 
			
		||||
declare module 'leaflet' {
 | 
			
		||||
 | 
			
		||||
    namespace Control {
 | 
			
		||||
        class AddMarker extends L.Control { }
 | 
			
		||||
        class AddPolygon extends L.Control { }
 | 
			
		||||
  namespace PM {
 | 
			
		||||
    interface PMMapToolbar {
 | 
			
		||||
      toggleButton(
 | 
			
		||||
        name: string,
 | 
			
		||||
        status: boolean,
 | 
			
		||||
        disableOthers?: boolean
 | 
			
		||||
      ): void;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    namespace control {
 | 
			
		||||
        function addMarker(options): Control.AddMarker;
 | 
			
		||||
        function addPolygon(options): Control.AddPolygon;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -20,7 +20,8 @@
 | 
			
		||||
      "src/typings/jquery.flot.typings.d.ts",
 | 
			
		||||
      "src/typings/jquery.jstree.typings.d.ts",
 | 
			
		||||
      "src/typings/split.js.typings.d.ts",
 | 
			
		||||
      "src/typings/add-marker.d.ts"
 | 
			
		||||
      "node_modules/@geoman-io/leaflet-geoman-free/dist/leaflet-geoman.d.ts",
 | 
			
		||||
      "src/typings/leaflet-geoman-extend.d.ts"
 | 
			
		||||
    ],
 | 
			
		||||
    "paths": {
 | 
			
		||||
      "@app/*": ["src/app/*"],
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										282
									
								
								ui-ngx/yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										282
									
								
								ui-ngx/yarn.lock
									
									
									
									
									
								
							@ -1422,6 +1422,18 @@
 | 
			
		||||
    "@types/flowjs" "2.13.3"
 | 
			
		||||
    tslib "^1.9.0"
 | 
			
		||||
 | 
			
		||||
"@geoman-io/leaflet-geoman-free@^2.11.3":
 | 
			
		||||
  version "2.11.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@geoman-io/leaflet-geoman-free/-/leaflet-geoman-free-2.11.3.tgz#480164ab76c2b2a885003e0c111284f3c3160a36"
 | 
			
		||||
  integrity sha512-LsiurEgKEHBcTnAVl8h7EfS5V/doCuxePzPE9SnfrhtJBN7IzP6UwkEo35Agwko+BnIuw/o2bE4F7irvKwQzjw==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@turf/boolean-contains" "6.3.0"
 | 
			
		||||
    "@turf/kinks" "6.3.0"
 | 
			
		||||
    "@turf/line-intersect" "6.3.0"
 | 
			
		||||
    "@turf/line-split" "6.3.0"
 | 
			
		||||
    lodash "4.17.21"
 | 
			
		||||
    polygon-clipping "0.15.3"
 | 
			
		||||
 | 
			
		||||
"@istanbuljs/schema@^0.1.2":
 | 
			
		||||
  version "0.1.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd"
 | 
			
		||||
@ -1688,6 +1700,167 @@
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.1.1.tgz#3348564048e7a2d7398c935d466c0414ebb6a669"
 | 
			
		||||
  integrity sha512-Z6DoceYb/1xSg5+e+ZlPZ9v0N16ZvZ+wYMraFue4HYrE4ttONKtsvruIRf6t9TBR0YvSOfi1hUU0fJfBLCDYow==
 | 
			
		||||
 | 
			
		||||
"@turf/bbox@*", "@turf/bbox@^6.3.0":
 | 
			
		||||
  version "6.5.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@turf/bbox/-/bbox-6.5.0.tgz#bec30a744019eae420dac9ea46fb75caa44d8dc5"
 | 
			
		||||
  integrity sha512-RBbLaao5hXTYyyg577iuMtDB8ehxMlUqHEJiMs8jT1GHkFhr6sYre3lmLsPeYEi/ZKj5TP5tt7fkzNdJ4GIVyw==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@turf/helpers" "^6.5.0"
 | 
			
		||||
    "@turf/meta" "^6.5.0"
 | 
			
		||||
 | 
			
		||||
"@turf/bearing@^6.5.0":
 | 
			
		||||
  version "6.5.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@turf/bearing/-/bearing-6.5.0.tgz#462a053c6c644434bdb636b39f8f43fb0cd857b0"
 | 
			
		||||
  integrity sha512-dxINYhIEMzgDOztyMZc20I7ssYVNEpSv04VbMo5YPQsqa80KO3TFvbuCahMsCAW5z8Tncc8dwBlEFrmRjJG33A==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@turf/helpers" "^6.5.0"
 | 
			
		||||
    "@turf/invariant" "^6.5.0"
 | 
			
		||||
 | 
			
		||||
"@turf/boolean-contains@6.3.0":
 | 
			
		||||
  version "6.3.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@turf/boolean-contains/-/boolean-contains-6.3.0.tgz#fe4fc359e408c8c3c89e7fb159c9d31fde48779a"
 | 
			
		||||
  integrity sha512-1MW7B5G5tIu1lnAv3pXyFzl75wfBYnbA2GhwHDb4okIXMhloy/r5uIqAZHo0fOXykKVJS/gIfA/MioKIftoTug==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@turf/bbox" "^6.3.0"
 | 
			
		||||
    "@turf/boolean-point-in-polygon" "^6.3.0"
 | 
			
		||||
    "@turf/boolean-point-on-line" "^6.3.0"
 | 
			
		||||
    "@turf/helpers" "^6.3.0"
 | 
			
		||||
    "@turf/invariant" "^6.3.0"
 | 
			
		||||
 | 
			
		||||
"@turf/boolean-point-in-polygon@^6.3.0":
 | 
			
		||||
  version "6.5.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@turf/boolean-point-in-polygon/-/boolean-point-in-polygon-6.5.0.tgz#6d2e9c89de4cd2e4365004c1e51490b7795a63cf"
 | 
			
		||||
  integrity sha512-DtSuVFB26SI+hj0SjrvXowGTUCHlgevPAIsukssW6BG5MlNSBQAo70wpICBNJL6RjukXg8d2eXaAWuD/CqL00A==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@turf/helpers" "^6.5.0"
 | 
			
		||||
    "@turf/invariant" "^6.5.0"
 | 
			
		||||
 | 
			
		||||
"@turf/boolean-point-on-line@^6.3.0":
 | 
			
		||||
  version "6.5.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@turf/boolean-point-on-line/-/boolean-point-on-line-6.5.0.tgz#a8efa7bad88760676f395afb9980746bc5b376e9"
 | 
			
		||||
  integrity sha512-A1BbuQ0LceLHvq7F/P7w3QvfpmZqbmViIUPHdNLvZimFNLo4e6IQunmzbe+8aSStH9QRZm3VOflyvNeXvvpZEQ==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@turf/helpers" "^6.5.0"
 | 
			
		||||
    "@turf/invariant" "^6.5.0"
 | 
			
		||||
 | 
			
		||||
"@turf/destination@^6.5.0":
 | 
			
		||||
  version "6.5.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@turf/destination/-/destination-6.5.0.tgz#30a84702f9677d076130e0440d3223ae503fdae1"
 | 
			
		||||
  integrity sha512-4cnWQlNC8d1tItOz9B4pmJdWpXqS0vEvv65bI/Pj/genJnsL7evI0/Xw42RvEGROS481MPiU80xzvwxEvhQiMQ==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@turf/helpers" "^6.5.0"
 | 
			
		||||
    "@turf/invariant" "^6.5.0"
 | 
			
		||||
 | 
			
		||||
"@turf/distance@^6.5.0":
 | 
			
		||||
  version "6.5.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@turf/distance/-/distance-6.5.0.tgz#21f04d5f86e864d54e2abde16f35c15b4f36149a"
 | 
			
		||||
  integrity sha512-xzykSLfoURec5qvQJcfifw/1mJa+5UwByZZ5TZ8iaqjGYN0vomhV9aiSLeYdUGtYRESZ+DYC/OzY+4RclZYgMg==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@turf/helpers" "^6.5.0"
 | 
			
		||||
    "@turf/invariant" "^6.5.0"
 | 
			
		||||
 | 
			
		||||
"@turf/helpers@6.x", "@turf/helpers@^6.3.0", "@turf/helpers@^6.5.0":
 | 
			
		||||
  version "6.5.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@turf/helpers/-/helpers-6.5.0.tgz#f79af094bd6b8ce7ed2bd3e089a8493ee6cae82e"
 | 
			
		||||
  integrity sha512-VbI1dV5bLFzohYYdgqwikdMVpe7pJ9X3E+dlr425wa2/sMJqYDhTO++ec38/pcPvPE6oD9WEEeU3Xu3gza+VPw==
 | 
			
		||||
 | 
			
		||||
"@turf/invariant@^6.3.0", "@turf/invariant@^6.5.0":
 | 
			
		||||
  version "6.5.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@turf/invariant/-/invariant-6.5.0.tgz#970afc988023e39c7ccab2341bd06979ddc7463f"
 | 
			
		||||
  integrity sha512-Wv8PRNCtPD31UVbdJE/KVAWKe7l6US+lJItRR/HOEW3eh+U/JwRCSUl/KZ7bmjM/C+zLNoreM2TU6OoLACs4eg==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@turf/helpers" "^6.5.0"
 | 
			
		||||
 | 
			
		||||
"@turf/kinks@6.3.0":
 | 
			
		||||
  version "6.3.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@turf/kinks/-/kinks-6.3.0.tgz#a16b4ccc5a5aae139d43e36271e0a0494fdb4bf7"
 | 
			
		||||
  integrity sha512-BLWvbl2/fa4SeJzVMbleT6Vo1cmzwmzRfxL2xxMei2jmf6JSvqDoMJFwIHGXrLZXvhOCb1b2C+MhBfhtc7kYkQ==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@turf/helpers" "^6.3.0"
 | 
			
		||||
 | 
			
		||||
"@turf/line-intersect@6.3.0":
 | 
			
		||||
  version "6.3.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@turf/line-intersect/-/line-intersect-6.3.0.tgz#726a50edc66bb7b5e798b052b103fb0da4d1c4f4"
 | 
			
		||||
  integrity sha512-3naxR7XpkPd2vst3Mw6DFry4C9m3o0/f2n/xu5UAyxb88Ie4m2k+1eqkhzMMx/0L+E6iThWpLx7DASM6q6o9ow==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@turf/helpers" "^6.3.0"
 | 
			
		||||
    "@turf/invariant" "^6.3.0"
 | 
			
		||||
    "@turf/line-segment" "^6.3.0"
 | 
			
		||||
    "@turf/meta" "^6.3.0"
 | 
			
		||||
    geojson-rbush "3.x"
 | 
			
		||||
 | 
			
		||||
"@turf/line-intersect@^6.3.0", "@turf/line-intersect@^6.5.0":
 | 
			
		||||
  version "6.5.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@turf/line-intersect/-/line-intersect-6.5.0.tgz#dea48348b30c093715d2195d2dd7524aee4cf020"
 | 
			
		||||
  integrity sha512-CS6R1tZvVQD390G9Ea4pmpM6mJGPWoL82jD46y0q1KSor9s6HupMIo1kY4Ny+AEYQl9jd21V3Scz20eldpbTVA==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@turf/helpers" "^6.5.0"
 | 
			
		||||
    "@turf/invariant" "^6.5.0"
 | 
			
		||||
    "@turf/line-segment" "^6.5.0"
 | 
			
		||||
    "@turf/meta" "^6.5.0"
 | 
			
		||||
    geojson-rbush "3.x"
 | 
			
		||||
 | 
			
		||||
"@turf/line-segment@^6.3.0", "@turf/line-segment@^6.5.0":
 | 
			
		||||
  version "6.5.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@turf/line-segment/-/line-segment-6.5.0.tgz#ee73f3ffcb7c956203b64ed966d96af380a4dd65"
 | 
			
		||||
  integrity sha512-jI625Ho4jSuJESNq66Mmi290ZJ5pPZiQZruPVpmHkUw257Pew0alMmb6YrqYNnLUuiVVONxAAKXUVeeUGtycfw==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@turf/helpers" "^6.5.0"
 | 
			
		||||
    "@turf/invariant" "^6.5.0"
 | 
			
		||||
    "@turf/meta" "^6.5.0"
 | 
			
		||||
 | 
			
		||||
"@turf/line-split@6.3.0":
 | 
			
		||||
  version "6.3.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@turf/line-split/-/line-split-6.3.0.tgz#ee218f66cd65ce84eafc4956c24083663f6082ea"
 | 
			
		||||
  integrity sha512-Q0nUJ0vczy11piyEz0FaKScFwSQtb1HJ2RPEMCw1coUJhTCB02KBWQLImhYqwsD3uLg+H/fxaJ1Gva6EPWoDNQ==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@turf/bbox" "^6.3.0"
 | 
			
		||||
    "@turf/helpers" "^6.3.0"
 | 
			
		||||
    "@turf/invariant" "^6.3.0"
 | 
			
		||||
    "@turf/line-intersect" "^6.3.0"
 | 
			
		||||
    "@turf/line-segment" "^6.3.0"
 | 
			
		||||
    "@turf/meta" "^6.3.0"
 | 
			
		||||
    "@turf/nearest-point-on-line" "^6.3.0"
 | 
			
		||||
    "@turf/square" "^6.3.0"
 | 
			
		||||
    "@turf/truncate" "^6.3.0"
 | 
			
		||||
    geojson-rbush "3.x"
 | 
			
		||||
 | 
			
		||||
"@turf/meta@6.x", "@turf/meta@^6.3.0", "@turf/meta@^6.5.0":
 | 
			
		||||
  version "6.5.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@turf/meta/-/meta-6.5.0.tgz#b725c3653c9f432133eaa04d3421f7e51e0418ca"
 | 
			
		||||
  integrity sha512-RrArvtsV0vdsCBegoBtOalgdSOfkBrTJ07VkpiCnq/491W67hnMWmDu7e6Ztw0C3WldRYTXkg3SumfdzZxLBHA==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@turf/helpers" "^6.5.0"
 | 
			
		||||
 | 
			
		||||
"@turf/nearest-point-on-line@^6.3.0":
 | 
			
		||||
  version "6.5.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@turf/nearest-point-on-line/-/nearest-point-on-line-6.5.0.tgz#8e1cd2cdc0b5acaf4c8d8b3b33bb008d3cb99e7b"
 | 
			
		||||
  integrity sha512-WthrvddddvmymnC+Vf7BrkHGbDOUu6Z3/6bFYUGv1kxw8tiZ6n83/VG6kHz4poHOfS0RaNflzXSkmCi64fLBlg==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@turf/bearing" "^6.5.0"
 | 
			
		||||
    "@turf/destination" "^6.5.0"
 | 
			
		||||
    "@turf/distance" "^6.5.0"
 | 
			
		||||
    "@turf/helpers" "^6.5.0"
 | 
			
		||||
    "@turf/invariant" "^6.5.0"
 | 
			
		||||
    "@turf/line-intersect" "^6.5.0"
 | 
			
		||||
    "@turf/meta" "^6.5.0"
 | 
			
		||||
 | 
			
		||||
"@turf/square@^6.3.0":
 | 
			
		||||
  version "6.5.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@turf/square/-/square-6.5.0.tgz#ab43eef99d39c36157ab5b80416bbeba1f6b2122"
 | 
			
		||||
  integrity sha512-BM2UyWDmiuHCadVhHXKIx5CQQbNCpOxB6S/aCNOCLbhCeypKX5Q0Aosc5YcmCJgkwO5BERCC6Ee7NMbNB2vHmQ==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@turf/distance" "^6.5.0"
 | 
			
		||||
    "@turf/helpers" "^6.5.0"
 | 
			
		||||
 | 
			
		||||
"@turf/truncate@^6.3.0":
 | 
			
		||||
  version "6.5.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@turf/truncate/-/truncate-6.5.0.tgz#c3a16cad959f1be1c5156157d5555c64b19185d8"
 | 
			
		||||
  integrity sha512-pFxg71pLk+eJj134Z9yUoRhIi8vqnnKvCYwdT4x/DQl/19RVdq1tV3yqOT3gcTQNfniteylL5qV1uTBDV5sgrg==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@turf/helpers" "^6.5.0"
 | 
			
		||||
    "@turf/meta" "^6.5.0"
 | 
			
		||||
 | 
			
		||||
"@types/canvas-gauges@^2.1.2":
 | 
			
		||||
  version "2.1.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@types/canvas-gauges/-/canvas-gauges-2.1.2.tgz#fb9ece324cb15ae137791ad21eb2db70e11a7210"
 | 
			
		||||
@ -1725,6 +1898,11 @@
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.7.tgz#c8fa532b60a0042219cdf173ca21a975ef0666ad"
 | 
			
		||||
  integrity sha512-wE2v81i4C4Ol09RtsWFAqg3BUitWbHSpSlIo+bNdsCJijO9sjme+zm+73ZMCa/qMC8UEERxzGbvmr1cffo2SiQ==
 | 
			
		||||
 | 
			
		||||
"@types/geojson@7946.0.8":
 | 
			
		||||
  version "7946.0.8"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.8.tgz#30744afdb385e2945e22f3b033f897f76b1f12ca"
 | 
			
		||||
  integrity sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==
 | 
			
		||||
 | 
			
		||||
"@types/glob@^7.1.1":
 | 
			
		||||
  version "7.1.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183"
 | 
			
		||||
@ -1791,34 +1969,48 @@
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@types/jquery" "*"
 | 
			
		||||
 | 
			
		||||
"@types/leaflet-editable@^1.2.1":
 | 
			
		||||
"@types/leaflet-polylinedecorator@^1.6.1":
 | 
			
		||||
  version "1.6.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@types/leaflet-polylinedecorator/-/leaflet-polylinedecorator-1.6.1.tgz#b6522f9dae52146bf73da249e4bedfbab200c6e4"
 | 
			
		||||
  integrity sha512-9etweJ2U4SWqcV/AR3i0NdWJByeMn6+zMUNlO6jVbpL8UI6qrMKybu8v9/s6UR4oXvsV4lZT6vzAsNAAMq5Ssg==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@types/leaflet" "*"
 | 
			
		||||
 | 
			
		||||
"@types/leaflet-providers@^1.2.1":
 | 
			
		||||
  version "1.2.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@types/leaflet-editable/-/leaflet-editable-1.2.1.tgz#12f1bd1d9af7beafbac256216062e97fe2ee4d55"
 | 
			
		||||
  integrity sha512-7Oms1HgulWiclkI0s1XLmr1yRylNoJX8sVUfAv9+28JzwWbKbLcQ6//vhFEOmoMlBQyL5veogKpUUb5qeF+Qyg==
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@types/leaflet-providers/-/leaflet-providers-1.2.1.tgz#620669b828959740a2d8572e0c0288a2382d3564"
 | 
			
		||||
  integrity sha512-uNyuXiNV2q3fmgNjQji2P6RjQISmL40bbOL91/3OAwiE3XhkLKPmSAtAcfe11MAIz45iEjdFZJWppq9QyfnPIw==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@types/leaflet" "*"
 | 
			
		||||
 | 
			
		||||
"@types/leaflet-polylinedecorator@^1.6.0":
 | 
			
		||||
  version "1.6.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@types/leaflet-polylinedecorator/-/leaflet-polylinedecorator-1.6.0.tgz#1572131ffedb3154c6e18e682d2fb700e203af19"
 | 
			
		||||
  integrity sha512-Z2BXZDjKEqHclwrAmhYdF1RwyFfa/NFxsoF79sitzaj5D/4YWHp/zDRcUZar5cQFKRgK66AYEIF7nKVuMzUGdw==
 | 
			
		||||
"@types/leaflet.gridlayer.googlemutant@^0.4.6":
 | 
			
		||||
  version "0.4.6"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@types/leaflet.gridlayer.googlemutant/-/leaflet.gridlayer.googlemutant-0.4.6.tgz#86d3ba9d432dec29b4796e37d815c233680e7fcb"
 | 
			
		||||
  integrity sha512-L0J7NadcZp5bcKQrv4DVlsEbQ90xLsOKScckAMnxoghh/wogk0GVkauYOYHBKeKDkx9qkMRzTf8oO+fKeYD7oQ==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@types/leaflet" "*"
 | 
			
		||||
 | 
			
		||||
"@types/leaflet.markercluster@^1.4.4":
 | 
			
		||||
  version "1.4.4"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@types/leaflet.markercluster/-/leaflet.markercluster-1.4.4.tgz#4b4772c86182923e920061a0c25cb3e53543ad35"
 | 
			
		||||
  integrity sha512-BQAilNWlBpYl4+PrsJXLOh4vyv7KfWi5kh3Fclg5y4gEeNeXKqhS6y1zzBB4+wcTuVUnMWfm2G0MfqA4yA5A5A==
 | 
			
		||||
"@types/leaflet.markercluster@^1.4.6":
 | 
			
		||||
  version "1.4.6"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@types/leaflet.markercluster/-/leaflet.markercluster-1.4.6.tgz#1159460b374ba5e329cb678d0e427f99dca75be5"
 | 
			
		||||
  integrity sha512-MD+bUDzxHznY0zOlSBUAMNQUGB2+xpJPKrR2MNEoBAAKa3QTKJJySBtCqWyGLvYNNO+Cdyc2c64aF2IFwe4fcQ==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@types/leaflet" "*"
 | 
			
		||||
 | 
			
		||||
"@types/leaflet@*", "@types/leaflet@1.5.17":
 | 
			
		||||
"@types/leaflet@*":
 | 
			
		||||
  version "1.5.17"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@types/leaflet/-/leaflet-1.5.17.tgz#b2153dc12c344e6896a93ffc6b61ac79da251e5b"
 | 
			
		||||
  integrity sha512-2XYq9k6kNjhNI7PaTz8Rdxcc8Vzwu97OaS9CtcrTxnTSxFUGwjlGjTDvhTLJU+JRSfZ4lBwGcl0SjZHALdVr6g==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@types/geojson" "*"
 | 
			
		||||
 | 
			
		||||
"@types/leaflet@^1.7.6":
 | 
			
		||||
  version "1.7.6"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@types/leaflet/-/leaflet-1.7.6.tgz#6580f4babb648972c5af3abc3d66866753fa9311"
 | 
			
		||||
  integrity sha512-Emkz3V08QnlelSbpT46OEAx+TBZYTOX2r1yM7W+hWg5+djHtQ1GbEXBDRLaqQDOYcDI51Ss0ayoqoKD4CtLUDA==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@types/geojson" "*"
 | 
			
		||||
 | 
			
		||||
"@types/lodash@^4.14.170":
 | 
			
		||||
  version "4.14.170"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.170.tgz#0d67711d4bf7f4ca5147e9091b847479b87925d6"
 | 
			
		||||
@ -4858,6 +5050,17 @@ gensync@^1.0.0-beta.2:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
 | 
			
		||||
  integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
 | 
			
		||||
 | 
			
		||||
geojson-rbush@3.x:
 | 
			
		||||
  version "3.2.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/geojson-rbush/-/geojson-rbush-3.2.0.tgz#8b543cf0d56f99b78faf1da52bb66acad6dfc290"
 | 
			
		||||
  integrity sha512-oVltQTXolxvsz1sZnutlSuLDEcQAKYC/uXt9zDzJJ6bu0W+baTI8LZBaTup5afzibEH4N3jlq2p+a152wlBJ7w==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@turf/bbox" "*"
 | 
			
		||||
    "@turf/helpers" "6.x"
 | 
			
		||||
    "@turf/meta" "6.x"
 | 
			
		||||
    "@types/geojson" "7946.0.8"
 | 
			
		||||
    rbush "^3.0.1"
 | 
			
		||||
 | 
			
		||||
get-caller-file@^2.0.1, get-caller-file@^2.0.5:
 | 
			
		||||
  version "2.0.5"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
 | 
			
		||||
@ -6224,11 +6427,6 @@ klona@^2.0.4:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.4.tgz#7bb1e3affb0cb8624547ef7e8f6708ea2e39dfc0"
 | 
			
		||||
  integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==
 | 
			
		||||
 | 
			
		||||
leaflet-editable@^1.2.0:
 | 
			
		||||
  version "1.2.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/leaflet-editable/-/leaflet-editable-1.2.0.tgz#a3a01001764ba58ea923381ee6a1c814708a0b84"
 | 
			
		||||
  integrity sha512-wG11JwpL8zqIbypTop6xCRGagMuWw68ihYu4uqrqc5Ep0wnEJeyob7NB2Rt5t74Oih4rwJ3OfwaGbzdowOGfYQ==
 | 
			
		||||
 | 
			
		||||
leaflet-polylinedecorator@^1.6.0:
 | 
			
		||||
  version "1.6.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/leaflet-polylinedecorator/-/leaflet-polylinedecorator-1.6.0.tgz#9ef79fd1b5302d67b72efe959a8ecd2553f27266"
 | 
			
		||||
@ -6236,25 +6434,25 @@ leaflet-polylinedecorator@^1.6.0:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    leaflet-rotatedmarker "^0.2.0"
 | 
			
		||||
 | 
			
		||||
leaflet-providers@^1.12.0:
 | 
			
		||||
  version "1.12.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/leaflet-providers/-/leaflet-providers-1.12.0.tgz#bf407f580d9564480e2346bc1e6412ef696624cf"
 | 
			
		||||
  integrity sha512-pU/mR4B+NbayBGCg5/88dmRq7t1EGiNPhsVGV3yqHuDn594vIwus4CiPVW0RtiKJNKg8Vf1pILAbFl0i+yk+lQ==
 | 
			
		||||
leaflet-providers@^1.13.0:
 | 
			
		||||
  version "1.13.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/leaflet-providers/-/leaflet-providers-1.13.0.tgz#10c843a23d5823a65096d40ad53f27029e13434b"
 | 
			
		||||
  integrity sha512-f/sN5wdgBbVA2jcCYzScIfYNxKdn2wBJP9bu+5cRX9Xj6g8Bt1G9Sr8WgJAt/ckIFIc3LVVxCBNFpSCfTuUElg==
 | 
			
		||||
 | 
			
		||||
leaflet-rotatedmarker@^0.2.0:
 | 
			
		||||
  version "0.2.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/leaflet-rotatedmarker/-/leaflet-rotatedmarker-0.2.0.tgz#4467f49f98d1bfd56959bd9c6705203dd2601277"
 | 
			
		||||
  integrity sha1-RGf0n5jRv9VpWb2cZwUgPdJgEnc=
 | 
			
		||||
 | 
			
		||||
leaflet.gridlayer.googlemutant@0.10.2:
 | 
			
		||||
  version "0.10.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/leaflet.gridlayer.googlemutant/-/leaflet.gridlayer.googlemutant-0.10.2.tgz#3c5351db4230beac1b1ea1f774d9288cfb0b6283"
 | 
			
		||||
  integrity sha512-r3le0W8izKmF2aeCCYp6P+dLQvPadV/vpJkres0ltDHiWac6qt3fQPNWjQl+8WCsCmcGTb1y5bmHOx0Yj6HA7g==
 | 
			
		||||
leaflet.gridlayer.googlemutant@0.13.4:
 | 
			
		||||
  version "0.13.4"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/leaflet.gridlayer.googlemutant/-/leaflet.gridlayer.googlemutant-0.13.4.tgz#0add37d240c70c999e1f1d341208e6fea2372c40"
 | 
			
		||||
  integrity sha512-oC6xUSFJ9HP4WIupXakgiYckdBHuHQeSaxTXsVlcvcpfsuYoJ/HFIrz1bmK4Qr/qKO4fY1MDM6AoewU7Bph8ZQ==
 | 
			
		||||
 | 
			
		||||
leaflet.markercluster@^1.5.0:
 | 
			
		||||
  version "1.5.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/leaflet.markercluster/-/leaflet.markercluster-1.5.0.tgz#54db42485da32fc3d92c7ae22d0d7982879e0b67"
 | 
			
		||||
  integrity sha512-Fvf/cq4o806mJL50n+fZW9+QALDDLPvt7vuAjlD2vfnxx3srMDs2vWINJze4nKYJYRY45OC6tM/669C3pLwMCA==
 | 
			
		||||
leaflet.markercluster@^1.5.3:
 | 
			
		||||
  version "1.5.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/leaflet.markercluster/-/leaflet.markercluster-1.5.3.tgz#9cdb52a4eab92671832e1ef9899669e80efc4056"
 | 
			
		||||
  integrity sha512-vPTw/Bndq7eQHjLBVlWpnGeLa3t+3zGiuM7fJwCkiMFq+nmRuG3RI3f7f4N4TDX7T4NpbAXpR2+NTRSEGfCSeA==
 | 
			
		||||
 | 
			
		||||
leaflet@^1.7.1:
 | 
			
		||||
  version "1.7.1"
 | 
			
		||||
@ -6365,7 +6563,7 @@ lodash.uniq@^4.5.0:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
 | 
			
		||||
  integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
 | 
			
		||||
 | 
			
		||||
lodash@^4.0.1, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@~4.17.21:
 | 
			
		||||
lodash@4.17.21, lodash@^4.0.1, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@~4.17.21:
 | 
			
		||||
  version "4.17.21"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
 | 
			
		||||
  integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
 | 
			
		||||
@ -7651,6 +7849,13 @@ pnp-webpack-plugin@1.6.4:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    ts-pnp "^1.1.6"
 | 
			
		||||
 | 
			
		||||
polygon-clipping@0.15.3:
 | 
			
		||||
  version "0.15.3"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/polygon-clipping/-/polygon-clipping-0.15.3.tgz#0215840438470ba2e9e6593625e4ea5c1087b4b7"
 | 
			
		||||
  integrity sha512-ho0Xx5DLkgxRx/+n4O74XyJ67DcyN3Tu9bGYKsnTukGAW6ssnuak6Mwcyb1wHy9MZc9xsUWqIoiazkZB5weECg==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    splaytree "^3.1.0"
 | 
			
		||||
 | 
			
		||||
popper.js@1.16.1-lts:
 | 
			
		||||
  version "1.16.1-lts"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1-lts.tgz#cf6847b807da3799d80ee3d6d2f90df8a3f50b05"
 | 
			
		||||
@ -8191,6 +8396,11 @@ querystringify@^2.1.1:
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6"
 | 
			
		||||
  integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==
 | 
			
		||||
 | 
			
		||||
quickselect@^2.0.0:
 | 
			
		||||
  version "2.0.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/quickselect/-/quickselect-2.0.0.tgz#f19680a486a5eefb581303e023e98faaf25dd018"
 | 
			
		||||
  integrity sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==
 | 
			
		||||
 | 
			
		||||
raf@^3.4.0, raf@^3.4.1:
 | 
			
		||||
  version "3.4.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
 | 
			
		||||
@ -8243,6 +8453,13 @@ raw-loader@4.0.2:
 | 
			
		||||
    loader-utils "^2.0.0"
 | 
			
		||||
    schema-utils "^3.0.0"
 | 
			
		||||
 | 
			
		||||
rbush@^3.0.1:
 | 
			
		||||
  version "3.0.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/rbush/-/rbush-3.0.1.tgz#5fafa8a79b3b9afdfe5008403a720cc1de882ecf"
 | 
			
		||||
  integrity sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    quickselect "^2.0.0"
 | 
			
		||||
 | 
			
		||||
rc-align@^4.0.0:
 | 
			
		||||
  version "4.0.8"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/rc-align/-/rc-align-4.0.8.tgz#276c3f5dfadf0de4bb95392cb81568c9e947a668"
 | 
			
		||||
@ -9298,6 +9515,11 @@ speed-measure-webpack-plugin@1.4.2:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    chalk "^4.1.0"
 | 
			
		||||
 | 
			
		||||
splaytree@^3.1.0:
 | 
			
		||||
  version "3.1.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/splaytree/-/splaytree-3.1.0.tgz#17d4a0108a6da3627579690b7b847241e18ddec8"
 | 
			
		||||
  integrity sha512-gvUGR7xnOy0fLKTCxDeUZYgU/I1Tdf8M/lM1Qrf8L2TIOR5ipZjGk02uYcdv0o2x7WjVRgpm3iS2clLyuVAt0Q==
 | 
			
		||||
 | 
			
		||||
split-string@^3.0.1, split-string@^3.0.2:
 | 
			
		||||
  version "3.1.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user