From 6818c9932e4ed641565b5997e82bd15c83be2caa Mon Sep 17 00:00:00 2001 From: Artem Halushko Date: Thu, 5 Mar 2020 11:56:07 +0200 Subject: [PATCH] add some settings support --- .../components/widget/lib/maps/leaflet-map.ts | 63 ++++++++------- .../components/widget/lib/maps/map-models.ts | 8 +- .../components/widget/lib/maps/map-widget2.ts | 79 ++++++++++++++----- .../components/widget/lib/maps/maps-utils.ts | 54 +++++++++++-- .../components/widget/lib/maps/markers.ts | 29 ++++--- .../components/widget/lib/maps/polyline.ts | 27 ++++--- ui/src/app/widget/lib/map-widget2.js | 6 +- 7 files changed, 182 insertions(+), 84 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts index d451474dcf..852ce4b880 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts @@ -98,7 +98,7 @@ export default abstract class LeafletMap { this.map.invalidateSize(true); } - createTool0tip(marker, dsIndex, settings, markerArgs) { + createTooltip(marker, dsIndex, settings, markerArgs) { var popup = L.popup(); popup.setContent(''); marker.bindPopup(popup, { autoClose: settings.autocloseTooltip, closeOnClick: false }); @@ -139,32 +139,29 @@ export default abstract class LeafletMap { updateMarkers(markersData) { markersData.forEach(data => { if (this.markers.get(data.aliasName)) { - this.updateMarker(data.aliasName, this.convertPosition(data), this.options as MarkerSettings) + this.updateMarker(data.aliasName, data, markersData, this.options as MarkerSettings) } else { - this.createMarker(data.aliasName, this.convertPosition(data), this.options as MarkerSettings); + this.createMarker(data.aliasName, data, markersData, this.options as MarkerSettings); } }); } - private createMarker(key, location, settings: MarkerSettings) { + private createMarker(key, data, dataSources, settings: MarkerSettings) { this.ready$.subscribe(() => { - let defaultSettings: MarkerSettings = { - color: '#FD2785' - } - const newMarker = new Marker(this.map, location, { ...defaultSettings, ...settings }); + const newMarker = new Marker(this.map, this.convertPosition(data), settings, data, dataSources); this.map.fitBounds(this.bounds.extend(newMarker.leafletMarker.getLatLng())); this.markers.set(key, newMarker); }); } - private updateMarker(key, location: L.LatLng, settings: MarkerSettings) { + private updateMarker(key, data, dataSources, settings: MarkerSettings) { const marker: Marker = this.markers.get(key); + let location = this.convertPosition(data) if (!location.equals(marker.location)) { marker.updateMarkerPosition(location); } - //other implements later - + marker.updateMarkerIcon(settings, data, dataSources); } private deleteMarker() { @@ -173,28 +170,34 @@ export default abstract class LeafletMap { //polyline - updatePolylines(polyData) { - if (this.poly) { - - } - - else { - this.createPolyline(polyData.map(data => this.convertPosition(data)), this.options); - } - - /* markersData.forEach(data => { - if (this.markers.get(data.aliasName)) { - this.updateMarker(data.aliasName, this.convertPosition(data), this.options as MarkerSettings) - } - else { - this.createMarker(data.aliasName, this.convertPosition(data), this.options as MarkerSettings); - } - });*/ + updatePolylines(polyData: Array>) { + polyData.forEach(data => { + if (data.length) { + let dataSource = polyData.map(arr=>arr[0]); + if (this.poly) { + this.updatePolyline(data, dataSource, this.options); + } + else { + this.createPolyline(data, dataSource, this.options); + } + } + }) } - createPolyline(locations, settings) { + createPolyline(data, dataSources, settings) { this.ready$.subscribe(() => { - this.poly = new Polyline(this.map, locations, settings); + this.poly = new Polyline(this.map, data.map(data => this.convertPosition(data)), data, dataSources, settings); + const bounds = this.bounds.extend(this.poly.leafletPoly.getBounds()); + if (bounds.isValid()) { + this.map.fitBounds(bounds); + this.bounds = bounds; + } + }); + } + + updatePolyline(data, dataSources, settings) { + this.ready$.subscribe(() => { + this.poly.updatePolyline(settings, data, dataSources); const bounds = this.bounds.extend(this.poly.leafletPoly.getBounds()); if (bounds.isValid()) { this.map.fitBounds(bounds); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts index 4731241d0d..08e00ac032 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts @@ -26,9 +26,13 @@ export enum MapProviders { tencent = 'tencent-map' } -export interface MarkerSettings { +export interface MarkerSettings extends MapOptions { showLabel?: boolean, draggable?: boolean, displayTooltip?: boolean, - color?: string + color?: string, + currentImage?: string; + useMarkerImageFunction?: boolean, + markerImages?: string[], + markerImageFunction?: Function; } \ No newline at end of file diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts index ed7691dcd0..1bce0b00be 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts @@ -13,8 +13,7 @@ import { } from './schemes'; import { MapWidgetStaticInterface, MapWidgetInterface } from './map-widget.interface'; import { OpenStreetMap, TencentMap, GoogleMap, HEREMap, ImageMap } from './providers'; -import { WidgetSubscription } from '@app/core/public-api'; -import { parseData, parseArray } from './maps-utils'; +import { parseData, parseArray, parseFunction } from './maps-utils'; export let TbMapWidgetV2: MapWidgetStaticInterface; TbMapWidgetV2 = class TbMapWidgetV2 implements MapWidgetInterface { @@ -24,38 +23,45 @@ TbMapWidgetV2 = class TbMapWidgetV2 implements MapWidgetInterface { data; constructor(mapProvider: MapProviders, private drawRoutes, ctx, $element) { - console.log("TbMapWidgetV2 -> constructor -> ctx", ctx) - // console.log(ctx.subscriptions, ctx.data, ctx.datasources); this.data = ctx.data; - //this.subsciptions. if (!$element) { $element = ctx.$container[0]; } this.provider = mapProvider; - const baseOptions: MapOptions = { - initCallback: () => { }, - defaultZoomLevel: 8, - dontFitMapBounds: false, - disableScrollZooming: false, - minZoomLevel: drawRoutes ? 18 : 15, - mapProvider: mapProvider, - mapUrl: ctx?.settings?.mapImageUrl, - credentials: '', - defaultCenterPosition: [0, 0], - markerClusteringSetting: null - } let MapClass = providerSets[mapProvider]?.MapClass; + let settings = this.initSettings(ctx?.settings); if (!MapClass) { return; } - this.map = new MapClass($element, { ...baseOptions, ...ctx.settings }); + this.map = new MapClass($element, settings); this.schema = providerSets[mapProvider]?.schema; } onInit() { } - update() { + initSettings(settings: any) { + const functionParams = ['data', 'dsData', 'dsIndex']; + const customOptions = { + mapProvider: this.provider, + mapUrl: settings?.mapImageUrl, + labelFunction: parseFunction(settings.labelFunction, functionParams), + tooltipFunction: parseFunction(settings.tooltipFunction, functionParams), + colorFunction: parseFunction(settings.colorFunction, functionParams), + polygonColorFunction: parseFunction(settings.polygonColorFunction, functionParams), + markerImageFunction: parseFunction(settings.markerImageFunction, ['data', 'images', 'dsData', 'dsIndex']), + tooltipPattern: settings.tooltipPattern || + "${entityName}

Latitude: ${" + settings.latKeyName + ":7}
Longitude: ${" + settings.lngKeyName + ":7}", + label: settings.label || "${entityName}", + currentImage: (settings.useMarkerImage && settings.markerImage?.length) ? { + url: settings.markerImage, + size: settings.markerImageSize || 34 + } : null + } + return { ...defaultSettings, ...settings, ...customOptions, } + } + + update() { if (this.drawRoutes) this.map.updatePolylines(parseArray(this.data)); this.map.updateMarkers(parseData(this.data)); @@ -179,4 +185,39 @@ const providerSets = { MapClass: ImageMap, schema: imageMapSettingsSchema } +} + +const defaultSettings = { + xPosKeyName: 'xPos', + yPosKeyName: 'yPos', + markerOffsetX: 0.5, + markerOffsetY: 1, + latKeyName: 'latitude', + lngKeyName: 'longitude', + polygonKeyName: 'coordinates', + showLabel: false, + showTooltip: false, + useDefaultCenterPosition: false, + showTooltipAction: "click", + autocloseTooltip: false, + showPolygon: true, + labelColor: '#000000', + color: "#FE7569", + polygonColor: "#0000ff", + polygonStrokeColor: "#fe0001", + polygonOpacity: 0.5, + polygonStrokeOpacity: 1, + polygonStrokeWeight: 1, + useLabelFunction: true, + markerImages: [], + strokeWeight: 2, + strokeOpacity: 1.0, + initCallback: () => { }, + defaultZoomLevel: 8, + dontFitMapBounds: false, + disableScrollZooming: false, + minZoomLevel: 16, + credentials: '', + defaultCenterPosition: [0, 0], + markerClusteringSetting: null, } \ No newline at end of file diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts index 1400d99558..75b44ac90a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts @@ -24,23 +24,61 @@ export function createTooltip(target, settings, targetArgs?) { export function parseArray(input: any[]): any[] { let alliases: any = _(input).groupBy(el => el?.datasource?.aliasName).values().value(); - return alliases.map(alliasArray => - alliasArray[0].data.map((el, i) => { - const obj = { aliasName: alliasArray[0]?.datasource?.aliasName }; + return alliases.map((alliasArray, dsIndex) => + alliasArray[0].data.map((el, i) => { + const obj = { + aliasName: alliasArray[0]?.datasource?.aliasName, + $datasource: alliasArray[0]?.datasource, + dsIndex: dsIndex + }; alliasArray.forEach(el => { - obj[el?.dataKey?.label] = el?.data[i][1] + obj[el?.dataKey?.label] = el?.data[i][1]; + obj[el?.dataKey?.label + '|ts'] = el?.data[0][0]; }); return obj; }) - ).flat(); + ); } export function parseData(input: any[]): any[] { - return _(input).groupBy(el => el?.datasource?.aliasName).values().value().map(alliasArray => { - const obj = { aliasName: alliasArray[0]?.datasource?.aliasName }; + return _(input).groupBy(el => el?.datasource?.aliasName).values().value().map((alliasArray, i) => { + const obj = { + aliasName: alliasArray[0]?.datasource?.aliasName, + $datasource: alliasArray[0]?.datasource, + dsIndex: i + }; alliasArray.forEach(el => { - obj[el?.dataKey?.label] = el?.data[0][1] + obj[el?.dataKey?.label] = el?.data[0][1]; + obj[el?.dataKey?.label + '|ts'] = el?.data[0][0]; }); return obj; }); +} + +export function safeExecute(func: Function, params = []) { + let res = null; + if (func && typeof (func) == "function") { + try { + res = func(...params); + } + catch (err) { + console.error(err); + res = null; + } + } + return res; +} + +export function parseFunction(source: string, params: string[] = []): Function { + let res = null; + if (source?.length) { + try { + res = new Function(...params, source); + } + catch (err) { + console.error(err); + res = null; + } + } + return res; } \ No newline at end of file diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts index 3a93ccbc92..e116d4cbfb 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts @@ -1,7 +1,6 @@ import L from 'leaflet'; -import { createTooltip } from './maps-utils'; +import { createTooltip, safeExecute } from './maps-utils'; import { MarkerSettings } from './map-models'; -import { Observable } from 'rxjs'; import { aspectCache } from '@app/core/utils'; export class Marker { @@ -11,15 +10,19 @@ export class Marker { tooltipOffset; tooltip; location; + data; + dataSources; - constructor(private map: L.Map, location: L.LatLngExpression, settings: MarkerSettings, onClickListener?, markerArgs?, onDragendListener?) { + constructor(private map: L.Map, location: L.LatLngExpression, public settings: MarkerSettings, data, dataSources, onClickListener?, markerArgs?, onDragendListener?) { //this.map = map; this.location = location; + this.data = data; + this.dataSources = dataSources; this.leafletMarker = L.marker(location, { draggable: settings.draggable }); - this.createMarkerIcon(settings, (iconInfo) => { + this.createMarkerIcon(dataSources, (iconInfo) => { this.leafletMarker.setIcon(iconInfo.icon); if (settings.showLabel) { this.tooltipOffset = [0, -iconInfo.size[1] + 10]; @@ -44,7 +47,7 @@ export class Marker { } - updateMarkerPosition(position: L.LatLngExpression){ + updateMarkerPosition(position: L.LatLngExpression) { this.leafletMarker.setLatLng(position); } @@ -61,8 +64,9 @@ export class Marker { }); } - updateMarkerIcon(settings) { - this.createMarkerIcon(settings, (iconInfo) => { + updateMarkerIcon(settings, data, dataSources) { + this.data = data; + this.createMarkerIcon(dataSources, (iconInfo) => { this.leafletMarker.setIcon(iconInfo.icon); if (settings.showLabel) { this.tooltipOffset = [0, -iconInfo.size[1] + 10]; @@ -71,10 +75,9 @@ export class Marker { }); } - - - createMarkerIcon(settings, onMarkerIconReady) { - var currentImage = settings.currentImage; + createMarkerIcon(dataSources, onMarkerIconReady) { + const currentImage = this.settings.useMarkerImageFunction ? + safeExecute(this.settings.markerImageFunction, [this.data, this.settings.markerImages, dataSources, this.data.dsIndex]) : this.settings.currentImage; // var opMap = this; if (currentImage && currentImage.url) { aspectCache(currentImage.url).subscribe( @@ -101,12 +104,12 @@ export class Marker { }; onMarkerIconReady(iconInfo); } else { - this.createDefaultMarkerIcon(settings.color, onMarkerIconReady); + this.createDefaultMarkerIcon(this.settings.color, onMarkerIconReady); } } ); } else { - this.createDefaultMarkerIcon(settings.color, onMarkerIconReady); + this.createDefaultMarkerIcon(this.settings.color, onMarkerIconReady); } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/polyline.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/polyline.ts index dd7c7d029a..95561f6d64 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/polyline.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/polyline.ts @@ -1,26 +1,31 @@ import L from 'leaflet'; +import { safeExecute } from './maps-utils'; export class Polyline { leafletPoly: L.Polyline; + dataSources; + data; - constructor(private map: L.Map, locations, settings) { + constructor(private map: L.Map, locations, data, dataSources, settings) { + this.dataSources = dataSources; + this.data = data; this.leafletPoly = L.polyline(locations, - { - color: settings.color, - opacity: settings.strokeOpacity, - weight: settings.strokeWeight - } + this.getPolyStyle(settings, data, dataSources) ).addTo(this.map); } - updatePolylineColor(settings, color) { - var style = { - color: color, + updatePolyline(settings, data, dataSources) { + this.leafletPoly.setStyle(this.getPolyStyle(settings, data, dataSources)); + + } + + getPolyStyle(settings, data, dataSources): L.PolylineOptions { + return { + color: settings.useColorFunction ? safeExecute(settings.colorFunction, [data, dataSources, data[0]?.dsIndex]) : settings.color, opacity: settings.strokeOpacity, weight: settings.strokeWeight - }; - this.leafletPoly.setStyle(style); + } } removePolyline() { diff --git a/ui/src/app/widget/lib/map-widget2.js b/ui/src/app/widget/lib/map-widget2.js index bf300630cc..41e5706d31 100644 --- a/ui/src/app/widget/lib/map-widget2.js +++ b/ui/src/app/widget/lib/map-widget2.js @@ -433,7 +433,7 @@ export default class TbMapWidgetV2 { function calculateLocationColor(location, dataMap) { if (location.settings.useColorFunction && location.settings.colorFunction) { var color; - try { + try { color = location.settings.colorFunction(dataMap.dataMap, dataMap.dsDataMap, location.dsIndex); } catch (e) {/**/ } @@ -451,6 +451,8 @@ export default class TbMapWidgetV2 { var color; try { color = location.settings.polygonColorFunction(dataMap.dataMap, dataMap.dsDataMap, location.dsIndex); + // eslint-disable-next-line no-debugger + debugger } catch (e) {/**/ } if (!color) { @@ -485,6 +487,8 @@ export default class TbMapWidgetV2 { if (location.settings.useMarkerImageFunction && location.settings.markerImageFunction) { var image = null; try { + // eslint-disable-next-line no-debugger + debugger; image = location.settings.markerImageFunction(dataMap.dataMap, location.settings.markerImages, dataMap.dsDataMap, location.dsIndex); } catch (e) { image = null;