Editable Polygons without proper typings
This commit is contained in:
		
							parent
							
								
									8750b26f1d
								
							
						
					
					
						commit
						423a491e80
					
				@ -58,6 +58,7 @@
 | 
			
		||||
    "jstree-bootstrap-theme": "^1.0.1",
 | 
			
		||||
    "jszip": "^3.4.0",
 | 
			
		||||
    "leaflet": "^1.6.0",
 | 
			
		||||
    "leaflet-editable": "^1.2.0",
 | 
			
		||||
    "leaflet-polylinedecorator": "^1.6.0",
 | 
			
		||||
    "leaflet-providers": "^1.10.1",
 | 
			
		||||
    "leaflet.gridlayer.googlemutant": "0.10.0",
 | 
			
		||||
 | 
			
		||||
@ -43,6 +43,8 @@ import { createTooltip, parseArray, safeExecute } from '@home/components/widget/
 | 
			
		||||
import { WidgetContext } from '@home/models/widget-component.models';
 | 
			
		||||
import { DatasourceData } from '@shared/models/widget.models';
 | 
			
		||||
import { deepClone, isDefinedAndNotNull } from '@core/utils';
 | 
			
		||||
import {newArray} from "@angular/compiler/src/util";
 | 
			
		||||
import {isArray} from "rxjs/internal-compatibility";
 | 
			
		||||
 | 
			
		||||
export default abstract class LeafletMap {
 | 
			
		||||
 | 
			
		||||
@ -168,6 +170,75 @@ export default abstract class LeafletMap {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  addPolygonControl() {
 | 
			
		||||
    if (this.options.editablePolygon) {
 | 
			
		||||
      let mousePositionOnMap: L.LatLng[];
 | 
			
		||||
      let addPolygon: L.Control;
 | 
			
		||||
      this.map.on('mousemove', (e: L.LeafletMouseEvent) => {
 | 
			
		||||
        let latlng1 = e.latlng;
 | 
			
		||||
        let latlng2 = L.latLng(e.latlng.lat, e.latlng.lng + 10);
 | 
			
		||||
        let latlng3 = L.latLng(e.latlng.lat-10, e.latlng.lng);
 | 
			
		||||
        mousePositionOnMap = [latlng1,latlng2, latlng3 ];
 | 
			
		||||
      });
 | 
			
		||||
      const dragListener = (e: L.DragEndEvent) => {
 | 
			
		||||
        if (e.type === 'dragend' && mousePositionOnMap) {
 | 
			
		||||
          const icon = new L.Icon.Default();
 | 
			
		||||
          icon.options.shadowSize = [0, 0];
 | 
			
		||||
          const newPolygon = L.polygon(mousePositionOnMap).addTo(this.map);
 | 
			
		||||
          const datasourcesList = document.createElement('div');
 | 
			
		||||
          const customLatLng = {coordinates: this.convertToPolygonFormat(mousePositionOnMap)};
 | 
			
		||||
          this.datasources.forEach(ds => {
 | 
			
		||||
            const dsItem = document.createElement('p');
 | 
			
		||||
            dsItem.appendChild(document.createTextNode(ds.entityName));
 | 
			
		||||
            dsItem.setAttribute('style', 'font-size: 14px');
 | 
			
		||||
            dsItem.onclick = () => {
 | 
			
		||||
              const updatedEnttity = { ...ds, ...customLatLng };
 | 
			
		||||
              this.savePolygonLocation(updatedEnttity).subscribe(() => {
 | 
			
		||||
                this.map.removeLayer(newPolygon);
 | 
			
		||||
                this.deletePolygon(ds.entityName);
 | 
			
		||||
                // this.createPolygon(ds, this.datasources, this.options);
 | 
			
		||||
              });
 | 
			
		||||
            }
 | 
			
		||||
            datasourcesList.append(dsItem);
 | 
			
		||||
          });
 | 
			
		||||
          const deleteBtn = document.createElement('a');
 | 
			
		||||
          deleteBtn.appendChild(document.createTextNode('Delete position'));
 | 
			
		||||
          deleteBtn.setAttribute('color', 'red');
 | 
			
		||||
          deleteBtn.onclick = () => {
 | 
			
		||||
            this.map.removeLayer(newPolygon);
 | 
			
		||||
          }
 | 
			
		||||
          datasourcesList.append(deleteBtn);
 | 
			
		||||
          const popup = L.popup();
 | 
			
		||||
          popup.setContent(datasourcesList);
 | 
			
		||||
          newPolygon.bindPopup(popup).openPopup();
 | 
			
		||||
        }
 | 
			
		||||
        addPolygon.setPosition('topright')
 | 
			
		||||
      }
 | 
			
		||||
      L.Control.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);
 | 
			
		||||
      L.control.addPolygon = (opts) => {
 | 
			
		||||
        return new L.Control.AddPolygon(opts);
 | 
			
		||||
      }
 | 
			
		||||
      addPolygon = L.control.addPolygon({ position: 'topright' }).addTo(this.map);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    public setMap(map: L.Map) {
 | 
			
		||||
        this.map = map;
 | 
			
		||||
        if (this.options.useDefaultCenterPosition) {
 | 
			
		||||
@ -178,6 +249,9 @@ export default abstract class LeafletMap {
 | 
			
		||||
        if (this.options.draggableMarker) {
 | 
			
		||||
            this.addMarkerControl();
 | 
			
		||||
        }
 | 
			
		||||
        if (this.options.editablePolygon) {
 | 
			
		||||
          this.addPolygonControl();
 | 
			
		||||
        }
 | 
			
		||||
        this.map$.next(this.map);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -189,6 +263,10 @@ export default abstract class LeafletMap {
 | 
			
		||||
      return of(null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public savePolygonLocation(_e: FormattedData, coordinates?: Array<[number, number]>): Observable<any> {
 | 
			
		||||
      return of(null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    createLatLng(lat: number, lng: number): L.LatLng {
 | 
			
		||||
        return L.latLng(lat, lng);
 | 
			
		||||
    }
 | 
			
		||||
@ -255,10 +333,16 @@ export default abstract class LeafletMap {
 | 
			
		||||
        return L.latLng(lat, lng) as L.LatLng;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    convertPositionPolygon(expression: Array<[number, number]>): L.LatLngExpression[] {
 | 
			
		||||
      return expression.map((el) => {
 | 
			
		||||
        return el.length === 2 && !el.some(isNaN) ? el : null
 | 
			
		||||
      }).filter(el => !!el)
 | 
			
		||||
    convertPositionPolygon(expression: Array<[number, number]> | Array<Array<[number, number]>>) {
 | 
			
		||||
          return (expression as Array<any>).map((el) => {
 | 
			
		||||
            if (el.length === 2 && !el.some(isNaN)) {
 | 
			
		||||
              return el;
 | 
			
		||||
            } else if (isArray(el) && el.length) {
 | 
			
		||||
              return this.convertPositionPolygon(el);
 | 
			
		||||
            } else {
 | 
			
		||||
              return null;
 | 
			
		||||
            }
 | 
			
		||||
        }).filter(el => !!el)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    convertToCustomFormat(position: L.LatLng): object {
 | 
			
		||||
@ -268,6 +352,26 @@ export default abstract class LeafletMap {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    convertToPolygonFormat(points: Array<any>): Array<any> {
 | 
			
		||||
        if (points.length) {
 | 
			
		||||
            return points.map(point=> {
 | 
			
		||||
                if (point.length) {
 | 
			
		||||
                    return this.convertToPolygonFormat(point);
 | 
			
		||||
                } else {
 | 
			
		||||
                    return [point.lat, point.lng];
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
        } else {
 | 
			
		||||
          return []
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    convertPolygonToCustomFormat(expression: Array<Array<any>>): object {
 | 
			
		||||
        return {
 | 
			
		||||
          [this.options.polygonKeyName] : this.convertToPolygonFormat(expression)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    updateData(data: DatasourceData[], formattedData: FormattedData[], drawRoutes: boolean, showPolygon: boolean) {
 | 
			
		||||
      this.ready$.subscribe(() => {
 | 
			
		||||
        if (drawRoutes) {
 | 
			
		||||
@ -394,6 +498,15 @@ export default abstract class LeafletMap {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    deletePolygon(key: string) {
 | 
			
		||||
      let polygon = this.polygons.get(key)?.leafletPoly;
 | 
			
		||||
      if (polygon) {
 | 
			
		||||
        this.map.removeLayer(polygon);
 | 
			
		||||
        this.polygons.delete(key);
 | 
			
		||||
        polygon = null;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    updatePoints(pointsData: FormattedData[], getTooltip: (point: FormattedData, setTooltip?: boolean) => string) {
 | 
			
		||||
        this.map$.subscribe(map => {
 | 
			
		||||
            if (this.points) {
 | 
			
		||||
@ -509,9 +622,14 @@ export default abstract class LeafletMap {
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    createPolygon(polyData: FormattedData, dataSources: FormattedData[], settings: PolygonSettings, updateBounds = true) {
 | 
			
		||||
  dragPolygonVertex = (e?, data = {} as FormattedData) => {
 | 
			
		||||
    if (e == undefined || (e.type !== 'editable:vertex:dragend' && e.type !== 'editable:vertex:deleted')) return;
 | 
			
		||||
    this.savePolygonLocation({ ...data, ...this.convertPolygonToCustomFormat(e.layer._latlngs) }).subscribe();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  createPolygon(polyData: FormattedData, dataSources: FormattedData[], settings: PolygonSettings, updateBounds = true) {
 | 
			
		||||
        this.ready$.subscribe(() => {
 | 
			
		||||
            const polygon = new Polygon(this.map, polyData, dataSources, settings);
 | 
			
		||||
            const polygon = new Polygon(this.map, polyData, dataSources, settings, this.dragPolygonVertex);
 | 
			
		||||
            if (updateBounds) {
 | 
			
		||||
              const bounds = polygon.leafletPoly.getBounds();
 | 
			
		||||
              this.fitBounds(bounds);
 | 
			
		||||
 | 
			
		||||
@ -34,6 +34,7 @@ export type PosFuncton = (origXPos, origYPos) => { x, y };
 | 
			
		||||
 | 
			
		||||
export type MapSettings = {
 | 
			
		||||
    draggableMarker: boolean;
 | 
			
		||||
    editablePolygon: boolean;
 | 
			
		||||
    initCallback?: () => any;
 | 
			
		||||
    posFunction: PosFuncton;
 | 
			
		||||
    defaultZoomLevel?: number;
 | 
			
		||||
@ -140,6 +141,7 @@ export type PolygonSettings = {
 | 
			
		||||
    usePolygonColorFunction: boolean;
 | 
			
		||||
    polygonTooltipFunction: GenericFunction;
 | 
			
		||||
    polygonColorFunction?: GenericFunction;
 | 
			
		||||
    editablePolygon: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type PolylineSettings = {
 | 
			
		||||
@ -268,6 +270,7 @@ export const defaultSettings: any = {
 | 
			
		||||
    credentials: '',
 | 
			
		||||
    markerClusteringSetting: null,
 | 
			
		||||
    draggableMarker: false,
 | 
			
		||||
    editablePolygon: false,
 | 
			
		||||
    fitMapBounds: true,
 | 
			
		||||
    mapPageSize: DEFAULT_MAP_PAGE_SIZE
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -79,6 +79,7 @@ export class MapWidgetController implements MapWidgetInterface {
 | 
			
		||||
        this.map = new MapClass(this.ctx, $element, this.settings);
 | 
			
		||||
        (this.ctx as any).mapInstance = this.map;
 | 
			
		||||
        this.map.saveMarkerLocation = this.setMarkerLocation;
 | 
			
		||||
        this.map.savePolygonLocation = this.savePolygonLocation;
 | 
			
		||||
        this.pageLink = {
 | 
			
		||||
          page: 0,
 | 
			
		||||
          pageSize: this.settings.mapPageSize,
 | 
			
		||||
@ -239,6 +240,56 @@ export class MapWidgetController implements MapWidgetInterface {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  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;
 | 
			
		||||
@ -270,6 +321,9 @@ export class MapWidgetController implements MapWidgetInterface {
 | 
			
		||||
        if (isEditMap && !settings.hasOwnProperty('draggableMarker')) {
 | 
			
		||||
            settings.draggableMarker = true;
 | 
			
		||||
        }
 | 
			
		||||
        if (isEditMap && !settings.hasOwnProperty('editablePolygon')) {
 | 
			
		||||
            settings.editablePolygon = true;
 | 
			
		||||
        }
 | 
			
		||||
        return { ...defaultSettings, ...settings, ...customOptions, }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -22,13 +22,13 @@
 | 
			
		||||
  background-repeat: no-repeat;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.leaflet-div-icon,
 | 
			
		||||
.tb-marker-label,
 | 
			
		||||
.tb-marker-label:before {
 | 
			
		||||
  border: none;
 | 
			
		||||
  background: none;
 | 
			
		||||
  box-shadow: none;
 | 
			
		||||
}
 | 
			
		||||
//.leaflet-div-icon,
 | 
			
		||||
//.tb-marker-label,
 | 
			
		||||
//.tb-marker-label:before {
 | 
			
		||||
//  border: none;
 | 
			
		||||
//  background: none;
 | 
			
		||||
//  box-shadow: none;
 | 
			
		||||
//}
 | 
			
		||||
 | 
			
		||||
.leaflet-container{
 | 
			
		||||
  background-color: white;
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,8 @@
 | 
			
		||||
/// limitations under the License.
 | 
			
		||||
///
 | 
			
		||||
 | 
			
		||||
import L, { LatLngExpression, LeafletMouseEvent } from 'leaflet';
 | 
			
		||||
import L, { LatLngExpression, LeafletMouseEvent} from 'leaflet';
 | 
			
		||||
import "leaflet-editable/src/Leaflet.Editable";
 | 
			
		||||
import { createTooltip, parseWithTranslation, safeExecute } from './maps-utils';
 | 
			
		||||
import { FormattedData, PolygonSettings } from './map-models';
 | 
			
		||||
 | 
			
		||||
@ -25,11 +26,10 @@ export class Polygon {
 | 
			
		||||
    data: FormattedData;
 | 
			
		||||
    dataSources: FormattedData[];
 | 
			
		||||
 | 
			
		||||
    constructor(public map, polyData: FormattedData, dataSources: FormattedData[], private settings: PolygonSettings) {
 | 
			
		||||
    constructor(public map, polyData: FormattedData, dataSources: FormattedData[], private settings: PolygonSettings, onDragendListener?) {
 | 
			
		||||
        this.dataSources = dataSources;
 | 
			
		||||
        this.data = polyData;
 | 
			
		||||
        const polygonColor = this.getPolygonColor(settings);
 | 
			
		||||
 | 
			
		||||
        this.leafletPoly = L.polygon(polyData[this.settings.polygonKeyName], {
 | 
			
		||||
          fill: true,
 | 
			
		||||
          fillColor: polygonColor,
 | 
			
		||||
@ -38,6 +38,14 @@ export class Polygon {
 | 
			
		||||
          fillOpacity: settings.polygonOpacity,
 | 
			
		||||
          opacity: settings.polygonStrokeOpacity
 | 
			
		||||
        }).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.showPolygonTooltip) {
 | 
			
		||||
            this.tooltip = createTooltip(this.leafletPoly, settings, polyData.$datasource);
 | 
			
		||||
@ -64,7 +72,13 @@ 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);
 | 
			
		||||
        this.updatePolygonColor(settings);
 | 
			
		||||
 | 
			
		||||
@ -36,7 +36,7 @@ export class GoogleMap extends LeafletMap {
 | 
			
		||||
    super(ctx, $container, options);
 | 
			
		||||
    this.resource = ctx.$injector.get(ResourcesService);
 | 
			
		||||
    this.loadGoogle(() => {
 | 
			
		||||
      const map = L.map($container, {attributionControl: false}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
 | 
			
		||||
      const map = L.map($container, {attributionControl: false, editable: !!options.editablePolygon}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
 | 
			
		||||
      (L.gridLayer as any).googleMutant({
 | 
			
		||||
        type: options?.gmDefaultMapType || 'roadmap'
 | 
			
		||||
      }).addTo(map);
 | 
			
		||||
 | 
			
		||||
@ -22,7 +22,7 @@ import { WidgetContext } from '@home/models/widget-component.models';
 | 
			
		||||
export class HEREMap extends LeafletMap {
 | 
			
		||||
    constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) {
 | 
			
		||||
        super(ctx, $container, options);
 | 
			
		||||
        const map = L.map($container).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
 | 
			
		||||
        const map = L.map($container, {editable: !!options.editablePolygon}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
 | 
			
		||||
        const tileLayer = (L.tileLayer as any).provider(options.mapProviderHere || 'HERE.normalDay', options.credentials);
 | 
			
		||||
        tileLayer.addTo(map);
 | 
			
		||||
        super.setMap(map);
 | 
			
		||||
 | 
			
		||||
@ -24,7 +24,9 @@ import { WidgetContext } from '@home/models/widget-component.models';
 | 
			
		||||
import { DataSet, DatasourceType, widgetType } from '@shared/models/widget.models';
 | 
			
		||||
import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
 | 
			
		||||
import { WidgetSubscriptionOptions } from '@core/api/widget-api.models';
 | 
			
		||||
import { isDefinedAndNotNull } from '@core/utils';
 | 
			
		||||
import {isDefinedAndNotNull, isNumber} from '@core/utils';
 | 
			
		||||
import "leaflet-editable/src/Leaflet.Editable";
 | 
			
		||||
import {isArray} from "rxjs/internal-compatibility";
 | 
			
		||||
 | 
			
		||||
const maxZoom = 4;// ?
 | 
			
		||||
 | 
			
		||||
@ -196,14 +198,15 @@ export class ImageMap extends LeafletMap {
 | 
			
		||||
    initMap(updateImage?: boolean) {
 | 
			
		||||
        if (!this.map && this.aspect > 0) {
 | 
			
		||||
            const center = this.pointToLatLng(this.width / 2, this.height / 2);
 | 
			
		||||
            this.map = L.map(this.$container, {
 | 
			
		||||
          this.map = L.map(this.$container, {
 | 
			
		||||
                minZoom: 1,
 | 
			
		||||
                maxZoom,
 | 
			
		||||
                scrollWheelZoom: !this.options.disableScrollZooming,
 | 
			
		||||
                center,
 | 
			
		||||
                zoom: 1,
 | 
			
		||||
                crs: L.CRS.Simple,
 | 
			
		||||
                attributionControl: false
 | 
			
		||||
                attributionControl: false,
 | 
			
		||||
                editable: !!this.options.editablePolygon
 | 
			
		||||
            });
 | 
			
		||||
            this.updateBounds(updateImage);
 | 
			
		||||
        }
 | 
			
		||||
@ -221,14 +224,17 @@ export class ImageMap extends LeafletMap {
 | 
			
		||||
        expression.y * this.height);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    convertPositionPolygon(expression: Array<[number, number]>): L.LatLngExpression[] {
 | 
			
		||||
      return expression.map((el) => {
 | 
			
		||||
    convertPositionPolygon(expression: Array<[number, number]> | Array<Array<[number, number]>>) {
 | 
			
		||||
      return (expression as Array<any>).map((el) => {
 | 
			
		||||
        if (el.length === 2 && !el.some(isNaN)) {
 | 
			
		||||
          return this.pointToLatLng(
 | 
			
		||||
            el[0] * this.width,
 | 
			
		||||
            el[1] * this.height)
 | 
			
		||||
        } else if (isArray(el) && el.length) {
 | 
			
		||||
          return this.convertPositionPolygon(el);
 | 
			
		||||
        } else {
 | 
			
		||||
          return null;
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
      }).filter(el => !!el)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -247,4 +253,25 @@ export class ImageMap extends LeafletMap {
 | 
			
		||||
            [this.options.yPosKeyName]: calculateNewPointCoordinate(point.y, this.height)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    convertToPolygonFormat(points: Array<any>): Array<any> {
 | 
			
		||||
      if (points.length) {
 | 
			
		||||
        return points.map(point=> {
 | 
			
		||||
          if (point.length) {
 | 
			
		||||
            return this.convertToPolygonFormat(point);
 | 
			
		||||
          } else {
 | 
			
		||||
            let pos = this.latLngToPoint(point);
 | 
			
		||||
            return [calculateNewPointCoordinate(pos.x, this.width), calculateNewPointCoordinate(pos.y, this.height)];
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
      } else {
 | 
			
		||||
        return []
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    convertPolygonToCustomFormat(expression: Array<Array<any>>): object {
 | 
			
		||||
      return {
 | 
			
		||||
        [this.options.polygonKeyName] : this.convertToPolygonFormat(expression)
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -22,7 +22,7 @@ import { WidgetContext } from '@home/models/widget-component.models';
 | 
			
		||||
export class OpenStreetMap extends LeafletMap {
 | 
			
		||||
    constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) {
 | 
			
		||||
        super(ctx, $container, options);
 | 
			
		||||
        const map = L.map($container).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
 | 
			
		||||
        const map =  new L.Map($container, {editable: !!options.editablePolygon}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
 | 
			
		||||
        let tileLayer;
 | 
			
		||||
        if (options.useCustomProvider)
 | 
			
		||||
            tileLayer = L.tileLayer(options.customProviderTileUrl);
 | 
			
		||||
 | 
			
		||||
@ -24,7 +24,7 @@ export class TencentMap extends LeafletMap {
 | 
			
		||||
  constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) {
 | 
			
		||||
    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).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
 | 
			
		||||
    const map = L.map($container, {editable: !!options.editablePolygon}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
 | 
			
		||||
    const txLayer = L.tileLayer(txUrl, {
 | 
			
		||||
      subdomains: '0123',
 | 
			
		||||
      tms: true,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										3
									
								
								ui-ngx/src/assets/add_polygon.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								ui-ngx/src/assets/add_polygon.svg
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
<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>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 182 B  | 
							
								
								
									
										5
									
								
								ui-ngx/src/typings/add-marker.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								ui-ngx/src/typings/add-marker.d.ts
									
									
									
									
										vendored
									
									
								
							@ -20,9 +20,12 @@ declare module 'leaflet' {
 | 
			
		||||
 | 
			
		||||
    namespace Control {
 | 
			
		||||
        class AddMarker extends L.Control { }
 | 
			
		||||
        class AddPolygon extends L.Control { }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    namespace control {
 | 
			
		||||
        function addMarker(options): Control.AddMarker;
 | 
			
		||||
        function addPolygon(options): Control.AddPolygon;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										272
									
								
								ui-ngx/src/typings/leadflet-editable.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										272
									
								
								ui-ngx/src/typings/leadflet-editable.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,272 @@
 | 
			
		||||
///
 | 
			
		||||
/// Copyright © 2016-2020 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 * as Leaflet from 'leaflet';
 | 
			
		||||
 | 
			
		||||
declare module 'leaflet' {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Make geometries editable in Leaflet.
 | 
			
		||||
   *
 | 
			
		||||
   * This is not a plug and play UI, and will not. This is a minimal, lightweight, and fully extendable API to
 | 
			
		||||
   * control editing of geometries. So you can easily build your own UI with your own needs and choices.
 | 
			
		||||
   */
 | 
			
		||||
  interface EditableStatic {
 | 
			
		||||
    new (map: Map, options: EditOptions): Editable;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Options to pass to L.Editable when instanciating.
 | 
			
		||||
   */
 | 
			
		||||
  interface EditOptions extends  Leaflet.MapOptions{
 | 
			
		||||
    /**
 | 
			
		||||
     * Class to be used when creating a new Polyline.
 | 
			
		||||
     */
 | 
			
		||||
    polylineClass?: object;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Class to be used when creating a new Polygon.
 | 
			
		||||
     */
 | 
			
		||||
    polygonClass?: object;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Class to be used when creating a new Marker.
 | 
			
		||||
     */
 | 
			
		||||
    markerClass?: object;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * CSS class to be added to the map container while drawing.
 | 
			
		||||
     */
 | 
			
		||||
    drawingCSSClass?: string;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Layer used to store edit tools (vertex, line guide…).
 | 
			
		||||
     */
 | 
			
		||||
    editLayer?: LayerGroup<Leaflet.Layer>;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Default layer used to store drawn features (marker, polyline…).
 | 
			
		||||
     */
 | 
			
		||||
    featuresLayer?: LayerGroup<Polyline|Polygon|Marker>;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Class to be used as vertex, for path editing.
 | 
			
		||||
     */
 | 
			
		||||
    vertexMarkerClass?: object;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Class to be used as middle vertex, pulled by the user to create a new point in the middle of a path.
 | 
			
		||||
     */
 | 
			
		||||
    middleMarkerClass?: object;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Class to be used as Polyline editor.
 | 
			
		||||
     */
 | 
			
		||||
    polylineEditorClass?: object;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Class to be used as Polygon editor.
 | 
			
		||||
     */
 | 
			
		||||
    polygonEditorClass?: object;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Class to be used as Marker editor.
 | 
			
		||||
     */
 | 
			
		||||
    markerEditorClass?: object;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Options to be passed to the line guides.
 | 
			
		||||
     */
 | 
			
		||||
    lineGuideOptions?: object;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set this to true if you don't want middle markers.
 | 
			
		||||
     */
 | 
			
		||||
    skipMiddleMarkers?: boolean;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Make geometries editable in Leaflet.
 | 
			
		||||
   *
 | 
			
		||||
   * This is not a plug and play UI, and will not. This is a minimal, lightweight, and fully extendable API to
 | 
			
		||||
   * control editing of geometries. So you can easily build your own UI with your own needs and choices.
 | 
			
		||||
   */
 | 
			
		||||
  interface Editable extends Leaflet.Evented {
 | 
			
		||||
    /**
 | 
			
		||||
     * Options to pass to L.Editable when instanciating.
 | 
			
		||||
     */
 | 
			
		||||
    options: EditOptions;
 | 
			
		||||
 | 
			
		||||
    currentPolygon: Polyline|Polygon|Marker;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Start drawing a polyline. If latlng is given, a first point will be added. In any case, continuing on user
 | 
			
		||||
     * click. If options is given, it will be passed to the polyline class constructor.
 | 
			
		||||
     */
 | 
			
		||||
    startPolyline(latLng?: LatLng, options?: PolylineOptions): Polyline;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Start drawing a polygon. If latlng is given, a first point will be added. In any case, continuing on user
 | 
			
		||||
     * click. If options is given, it will be passed to the polygon class constructor.
 | 
			
		||||
     */
 | 
			
		||||
    startPolygon(latLng?: LatLng, options?: PolylineOptions): Polygon;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Start adding a marker. If latlng is given, the marker will be shown first at this point. In any case, it
 | 
			
		||||
     * will follow the user mouse, and will have a final latlng on next click (or touch). If options is given,
 | 
			
		||||
     * it will be passed to the marker class constructor.
 | 
			
		||||
     */
 | 
			
		||||
    startMarker(latLng?: LatLng, options?: MarkerOptions): Marker;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * When you need to stop any ongoing drawing, without needing to know which editor is active.
 | 
			
		||||
     */
 | 
			
		||||
    stopDrawing(): void;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * When you need to commit any ongoing drawing, without needing to know which editor is active.
 | 
			
		||||
     */
 | 
			
		||||
    commitDrawing(): void;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  let Editable: EditableStatic;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * EditableMixin is included to L.Polyline, L.Polygon and L.Marker. It adds the following methods to them.
 | 
			
		||||
   *
 | 
			
		||||
   * When editing is enabled, the editor is accessible on the instance with the editor property.
 | 
			
		||||
   */
 | 
			
		||||
  interface EditableMixin {
 | 
			
		||||
    /**
 | 
			
		||||
     * Enable editing, by creating an editor if not existing, and then calling enable on it.
 | 
			
		||||
     */
 | 
			
		||||
    enableEdit(map: L.Map): any;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Disable editing, also remove the editor property reference.
 | 
			
		||||
     */
 | 
			
		||||
    disableEdit(): void;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Enable or disable editing, according to current status.
 | 
			
		||||
     */
 | 
			
		||||
    toggleEdit(): void;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Return true if current instance has an editor attached, and this editor is enabled.
 | 
			
		||||
     */
 | 
			
		||||
    editEnabled(): boolean;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  interface Map {
 | 
			
		||||
    /**
 | 
			
		||||
     * Whether to create a L.Editable instance at map init or not.
 | 
			
		||||
     */
 | 
			
		||||
    editable: boolean;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Options to pass to L.Editable when instanciating.
 | 
			
		||||
     */
 | 
			
		||||
    editOptions: EditOptions;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * L.Editable plugin instance.
 | 
			
		||||
     */
 | 
			
		||||
    editTools: Editable;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // tslint:disable-next-line:no-empty-interface
 | 
			
		||||
  interface Polyline extends EditableMixin {}
 | 
			
		||||
 | 
			
		||||
  namespace Map {
 | 
			
		||||
    interface MapOptions {
 | 
			
		||||
      /**
 | 
			
		||||
       * Whether to create a L.Editable instance at map init or not.
 | 
			
		||||
       */
 | 
			
		||||
      editable?: boolean;
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
       * Options to pass to L.Editable when instanciating.
 | 
			
		||||
       */
 | 
			
		||||
      editOptions?: EditOptions;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * When editing a feature (marker, polyline…), an editor is attached to it. This editor basically knows
 | 
			
		||||
   * how to handle the edition.
 | 
			
		||||
   */
 | 
			
		||||
  interface BaseEditor {
 | 
			
		||||
    /**
 | 
			
		||||
     * Set up the drawing tools for the feature to be editable.
 | 
			
		||||
     */
 | 
			
		||||
    enable(): MarkerEditor|PolylineEditor|PolygonEditor;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Remove editing tools.
 | 
			
		||||
     */
 | 
			
		||||
    disable(): MarkerEditor|PolylineEditor|PolygonEditor;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Inherit from L.Editable.BaseEditor.
 | 
			
		||||
   * Inherited by L.Editable.PolylineEditor and L.Editable.PolygonEditor.
 | 
			
		||||
   */
 | 
			
		||||
  interface PathEditor extends BaseEditor {
 | 
			
		||||
    /**
 | 
			
		||||
     * Rebuild edit elements (vertex, middlemarker, etc.).
 | 
			
		||||
     */
 | 
			
		||||
    reset(): void;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Inherit from L.Editable.PathEditor.
 | 
			
		||||
   */
 | 
			
		||||
  interface PolylineEditor extends PathEditor {
 | 
			
		||||
    /**
 | 
			
		||||
     * Set up drawing tools to continue the line forward.
 | 
			
		||||
     */
 | 
			
		||||
    continueForward(): void;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set up drawing tools to continue the line backward.
 | 
			
		||||
     */
 | 
			
		||||
    continueBackward(): void;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Inherit from L.Editable.PathEditor.
 | 
			
		||||
   */
 | 
			
		||||
  interface PolygonEditor extends PathEditor {
 | 
			
		||||
    /**
 | 
			
		||||
     * Set up drawing tools for creating a new hole on the polygon. If the latlng param is given, a first
 | 
			
		||||
     * point is created.
 | 
			
		||||
     */
 | 
			
		||||
    newHole(latlng: LatLng): void;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Inherit from L.Editable.BaseEditor.
 | 
			
		||||
   */
 | 
			
		||||
    // tslint:disable-next-line:no-empty-interface
 | 
			
		||||
  interface MarkerEditor extends BaseEditor {}
 | 
			
		||||
 | 
			
		||||
  interface Marker extends EditableMixin, MarkerEditor {}
 | 
			
		||||
 | 
			
		||||
  interface Polyline extends EditableMixin, PolylineEditor {}
 | 
			
		||||
 | 
			
		||||
  interface Polygon extends EditableMixin, PolygonEditor {}
 | 
			
		||||
}
 | 
			
		||||
@ -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"
 | 
			
		||||
      "src/typings/add-marker.d.ts",
 | 
			
		||||
      "src/typings/leaflet-editable.d.ts"
 | 
			
		||||
    ],
 | 
			
		||||
    "paths": {
 | 
			
		||||
      "@app/*": ["src/app/*"],
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user