From 749a0b5c612339afdb501fbadd202fa12482ff23 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Mon, 3 Mar 2025 18:10:23 +0200 Subject: [PATCH] UI: Trip data layer implementation. --- .../lib/maps/data-layer/data-layer-utils.ts | 2 +- .../lib/maps/data-layer/map-data-layer.ts | 2 +- .../lib/maps/data-layer/trips-data-layer.ts | 229 ++++++++++++++---- .../home/components/widget/lib/maps/map.ts | 33 ++- .../widget/lib/maps/models/map.models.ts | 20 +- .../panels/map-timeline-panel.component.ts | 7 +- .../map/map-data-layer-dialog.component.html | 1 + .../map/map-data-layer-dialog.component.ts | 2 +- 8 files changed, 233 insertions(+), 63 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/data-layer-utils.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/data-layer-utils.ts index f5872844c9..6e4ec1e485 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/data-layer-utils.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/data-layer-utils.ts @@ -86,7 +86,7 @@ const bindTooltipActions = (map: TbMap, tooltip: L.Popup, settings: DataLay if (action) { element.onclick = ($event) => { - map.dataItemClick($event, action, data.$datasource); + map.dataItemClick($event, action, data); return false; }; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/map-data-layer.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/map-data-layer.ts index 1c4e58a320..e3f326b729 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/map-data-layer.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/map-data-layer.ts @@ -108,7 +108,7 @@ export abstract class TbDataLayerItem { - this.dataLayer.getMap().dataItemClick(event.originalEvent, clickAction, this.data.$datasource); + this.dataLayer.getMap().dataItemClick(event.originalEvent, clickAction, this.data); }); } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/trips-data-layer.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/trips-data-layer.ts index a7b0d74d4d..45aa31def5 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/trips-data-layer.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/trips-data-layer.ts @@ -17,19 +17,20 @@ import { DataLayerColorProcessor, DataLayerPatternProcessor, - MapDataLayerType, TbDataLayerItem, + MapDataLayerType, + TbDataLayerItem, TbMapDataLayer, UnplacedMapDataItem } from '@home/components/widget/lib/maps/data-layer/map-data-layer'; import { BaseMarkerShapeSettings, - calculateInterpolationRatio, calculateLastPoints, - ClusterMarkerColorFunction, + calculateInterpolationRatio, + calculateLastPoints, DataLayerColorType, - defaultBaseMarkersDataLayerSettings, defaultBaseTripsDataLayerSettings, findRotationAngle, - interpolateLineSegment, isValidLatLng, + interpolateLineSegment, + isValidLatLng, loadImageWithAspect, MapStringFunction, MapType, @@ -40,14 +41,13 @@ import { MarkerImageSettings, MarkerImageType, MarkerPositionFunction, - MarkersDataLayerSettings, MarkerShapeSettings, MarkerType, TbMapDatasource, TripsDataLayerSettings } from '@home/components/widget/lib/maps/models/map.models'; import { forkJoin, Observable, of } from 'rxjs'; -import { FormattedData } from '@shared/models/widget.models'; +import { FormattedData, WidgetActionType } from '@shared/models/widget.models'; import { createColorMarkerIconElement, createColorMarkerShapeURI, @@ -57,7 +57,7 @@ import tinycolor from 'tinycolor2'; import { MatIconRegistry } from '@angular/material/icon'; import { DomSanitizer } from '@angular/platform-browser'; import { catchError, map, switchMap } from 'rxjs/operators'; -import L, { PolylineDecorator } from 'leaflet'; +import L from 'leaflet'; import { CompiledTbFunction } from '@shared/models/js-function.models'; import { deepClone, @@ -74,6 +74,7 @@ import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import moment from 'moment/moment'; import { TbImageMap } from '@home/components/widget/lib/maps/image-map'; import { createTooltip, updateTooltip } from '@home/components/widget/lib/maps/data-layer/data-layer-utils'; +import _ from 'lodash'; type TripRouteData = {[time: number]: FormattedData}; @@ -88,11 +89,12 @@ class TbTripDataItem { private labelOffset: L.PointTuple; private polyline: L.Polyline; - private polylineDecorator: PolylineDecorator; + private polylineDecorator: L.PolylineDecorator; private points: L.FeatureGroup; private currentTime: number; private currentPositionData: FormattedData; + private pointData: FormattedData; constructor(private rawRouteData: FormattedData[], private latestData: FormattedData, @@ -105,11 +107,13 @@ class TbTripDataItem { private create() { this.updateCurrentPosition(); this.layer = L.featureGroup(); - let pointData = this.currentPositionData; + this.pointData = this.currentPositionData; if (this.latestData) { - pointData = {...pointData, ...this.latestData}; + this.pointData = {...this.pointData, ...this.latestData}; } - this.createMarker(pointData); + this.createPath(); + this.updatePoints(); + this.createMarker(); try { this.dataLayer.getDataLayerContainer().addLayer(this.layer); } catch (e) { @@ -121,38 +125,50 @@ class TbTripDataItem { this.rawRouteData = rawRouteData; this.tripRouteData = this.prepareTripRouteData(); this.updateCurrentPosition(true); - let pointData = this.currentPositionData; + this.pointData = this.currentPositionData; if (this.latestData) { - pointData = {...pointData, ...this.latestData}; + this.pointData = {...this.pointData, ...this.latestData}; } - this.updateMarker(pointData); + this.updatePath(); + this.updatePoints(); + this.updateMarker(); } public updateLatestData(latestData: FormattedData) { this.latestData = latestData; + this.pointData = this.currentPositionData; + if (this.latestData) { + this.pointData = {...this.pointData, ...this.latestData}; + } this.updateAppearance(); } public updateAppearance() { - let data = this.currentPositionData; - if (this.latestData) { - data = {...data, ...this.latestData}; - } + this.updatePathAppearance(); const dsData = this.dataLayer.getMap().getData(); if (this.settings.tooltip.show) { updateTooltip(this.dataLayer.getMap(), this.markerTooltip, - this.settings.tooltip, this.dataLayer.dataLayerTooltipProcessor, data, dsData); + this.settings.tooltip, this.dataLayer.dataLayerTooltipProcessor, this.pointData, dsData); } - this.updateMarkerIcon(data, dsData); + this.updatePoints(); + this.updateMarkerIcon(this.pointData, dsData); } public updateCurrentTime() { this.updateCurrentPosition(); - let pointData = this.currentPositionData; + this.pointData = this.currentPositionData; if (this.latestData) { - pointData = {...pointData, ...this.latestData}; + this.pointData = {...this.pointData, ...this.latestData}; } - this.updateMarker(pointData); + this.updatePath(); + this.updateMarker(); + } + + public invalidateCoordinates(): void { + this.tripRouteData = this.prepareTripRouteData(); + this.updatePath(); + this.updatePoints(); + this.updateMarker(); } public remove() { @@ -164,32 +180,117 @@ class TbTripDataItem { return this.layer; } - private createMarker(data: FormattedData) { + public calculateAnchors(): number[] { + const entries = Object.entries(this.tripRouteData); const dsData = this.dataLayer.getMap().getData(); - const location = this.dataLayer.extractLocation(data, dsData); + return entries.filter(data => this.dataLayer.getMap().getLocationSnapFilterFunction().execute(data[1], dsData)) + .map(data => parseInt(data[0], 10)); + } + + private createMarker() { + const dsData = this.dataLayer.getMap().getData(); + const location = this.dataLayer.extractLocation(this.pointData, dsData); this.marker = L.marker(location, { - tbMarkerData: data, + tbMarkerData: this.pointData, snapIgnore: true }); this.marker.addTo(this.layer); - this.updateMarkerIcon(data, dsData); + this.updateMarkerIcon(this.pointData, dsData); if (this.settings.tooltip?.show) { this.markerTooltip = createTooltip(this.dataLayer.getMap(), - this.marker, this.settings.tooltip, data, () => true); + this.marker, this.settings.tooltip, this.pointData, () => true); updateTooltip(this.dataLayer.getMap(), this.markerTooltip, - this.settings.tooltip, this.dataLayer.dataLayerTooltipProcessor, data, dsData); + this.settings.tooltip, this.dataLayer.dataLayerTooltipProcessor, this.pointData, dsData); + } + const clickAction = this.settings.click; + if (clickAction && clickAction.type !== WidgetActionType.doNothing) { + this.marker.on('click', (event) => { + this.dataLayer.getMap().dataItemClick(event.originalEvent, clickAction, this.pointData); + }); } } - private updateMarker(data: FormattedData) { + private updateMarker() { const dsData = this.dataLayer.getMap().getData(); - this.marker.options.tbMarkerData = data; - this.updateMarkerLocation(data, dsData); + this.marker.options.tbMarkerData = this.pointData; + this.updateMarkerLocation(this.pointData, dsData); if (this.settings.tooltip.show) { updateTooltip(this.dataLayer.getMap(), this.markerTooltip, - this.settings.tooltip, this.dataLayer.dataLayerTooltipProcessor, data, dsData); + this.settings.tooltip, this.dataLayer.dataLayerTooltipProcessor, this.pointData, dsData); + } + this.updateMarkerIcon(this.pointData, dsData); + } + + private createPath() { + if (this.settings.showPath) { + const formattedRouteData = _.values(this.tripRouteData); + const dsData = this.dataLayer.getMap().getData(); + const locations = formattedRouteData.map(data => this.dataLayer.extractLocation(data, dsData)); + const pathStyle = this.dataLayer.getPathStyle(this.pointData, dsData); + this.polyline = L.polyline(locations, pathStyle); + this.polyline.addTo(this.layer); + if (this.settings.usePathDecorator) { + this.polylineDecorator = new L.PolylineDecorator(this.polyline, this.dataLayer.getPathDecoratorStyle(pathStyle.color)); + this.polylineDecorator.addTo(this.layer); + } + } + } + + private updatePath() { + if (this.settings.showPath) { + const formattedRouteData = _.values(this.tripRouteData); + const dsData = this.dataLayer.getMap().getData(); + const locations = formattedRouteData.map(data => this.dataLayer.extractLocation(data, dsData)); + this.polyline.setLatLngs(locations); + if (this.settings.usePathDecorator) { + this.polylineDecorator.setPaths(this.polyline); + } + this.updatePathAppearance(); + } + } + + private updatePoints() { + if (this.settings.showPoints) { + if (!this.points) { + this.points = L.featureGroup(); + this.points.addTo(this.layer); + } + this.points.clearLayers(); + const formattedRouteData = _.values(this.tripRouteData); + const dsData = this.dataLayer.getMap().getData(); + const pointsList = formattedRouteData.filter(data => !!this.dataLayer.extractLocationData(data)); + for (const pData of pointsList) { + let pointData = pData; + if (this.latestData) { + pointData = {...pointData, ...this.latestData}; + } + const pointColor = this.dataLayer.pointColorProcessor.processColor(pointData, dsData); + const point = L.circleMarker(this.dataLayer.extractLocation(pointData, dsData), { + stroke: false, + fillOpacity: 1, + fillColor: pointColor, + radius: this.settings.pointSize + }); + if (this.settings.pointTooltip?.show) { + const pointTooltip = createTooltip(this.dataLayer.getMap(), + point, this.settings.pointTooltip, pointData, () => true); + updateTooltip(this.dataLayer.getMap(), pointTooltip, + this.settings.pointTooltip, this.dataLayer.pointTooltipProcessor, pointData, dsData); + } + this.points.addLayer(point); + } + } + } + + private updatePathAppearance() { + if (this.settings.showPath) { + const dsData = this.dataLayer.getMap().getData(); + const pathStyle = this.dataLayer.getPathStyle(this.pointData, dsData); + this.polyline.setStyle(pathStyle); + if (this.settings.usePathDecorator) { + this.polylineDecorator.setPatterns(this.dataLayer.getPathDecoratorStyle(pathStyle.color).patterns) + } } - this.updateMarkerIcon(data, dsData); } private updateMarkerLocation(data: FormattedData, dsData: FormattedData[]) { @@ -231,6 +332,7 @@ class TbTripDataItem { const maxTime = this.dataLayer.getMap().getMaxTime(); const timeStep = this.dataLayer.getMap().getTimeStep(); const timeline = this.dataLayer.getMap().hasTimeline(); + const dsData = this.dataLayer.getMap().getData(); for (const data of this.rawRouteData) { const currentTime = data.time; const normalizeTime = timeline ? (minTime @@ -260,7 +362,9 @@ class TbTripDataItem { } } if (this.settings.rotateMarker) { - result[timeStamp[i]].rotationAngle += findRotationAngle(result[timeStamp[i]], result[timeStamp[i + 1]], xKey, yKey); + const startPoint = this.dataLayer.extractLocation(result[timeStamp[i]], dsData); + const endPoint = this.dataLayer.extractLocation(result[timeStamp[i + 1]], dsData); + result[timeStamp[i]].rotationAngle += findRotationAngle(startPoint, endPoint); } } } @@ -584,10 +688,6 @@ export class TbTripsDataLayer extends TbMapDataLayer { const entityId = rawTripData[0].entityId; @@ -614,9 +714,12 @@ export class TbTripsDataLayer extends TbMapDataLayer item.invalidateCoordinates()); + } + public updateTripsLatestData(tripsLatestData: FormattedData[]) { this.latestTripsData = tripsLatestData.filter(d => d.$datasource.mapDataIds.includes(this.mapDataId)); - console.log(`Update trips latest data`); this.tripItems.forEach((item, entityId) => { const latestData = this.latestTripsData.find(d => d.entityId === entityId); item.updateLatestData(latestData); @@ -624,22 +727,24 @@ export class TbTripsDataLayer extends TbMapDataLayer { item.updateCurrentTime(); }); } public updateAppearance() { - console.log(`Update trips appearance`); this.tripItems.forEach(item => { item.updateAppearance(); }); } public calculateAnchors(): number[] { - return []; + let anchors: number[] = []; + this.tripItems.forEach(item => { + const tripAnchors = item.calculateAnchors(); + anchors = [...new Set([...anchors, ...tripAnchors])]; + }); + return anchors; } private clearIncorrectFirsLastDatapoint(dataSource: FormattedData[]): FormattedData[] { @@ -705,7 +810,7 @@ export class TbTripsDataLayer extends TbMapDataLayer): {x: number; y: number} { + public extractLocationData(data: FormattedData): {x: number; y: number} { if (data) { const xKeyVal = data[this.settings.xKey.label]; const yKeyVal = data[this.settings.yKey.label]; @@ -740,4 +845,36 @@ export class TbTripsDataLayer extends TbMapDataLayer, dsData: FormattedData[]): L.PolylineOptions { + const pathStroke = this.pathStrokeColorProcessor.processColor(data, dsData); + return { + interactive: false, + color: pathStroke, + opacity: 1, + weight: this.settings.pathStrokeWeight, + pmIgnore: true + }; + } + + public getPathDecoratorStyle(pathStroke: string): L.PolylineDecoratorOptions { + const symbolConstructor = L.Symbol[this.settings.pathDecoratorSymbol]; + return { + patterns: [ + { + offset: this.settings.pathDecoratorOffset, + endOffset: this.settings.pathEndDecoratorOffset, + repeat: this.settings.pathDecoratorRepeat, + symbol: symbolConstructor({ + pixelSize: this.settings.pathDecoratorSymbolSize, + polygon: false, + pathOptions: { + color: this.settings.pathDecoratorSymbolColor ? this.settings.pathDecoratorSymbolColor : pathStroke, + stroke: true + } + }) + } + ] + }; + } + } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map.ts index 11af4338e9..6c7d384c81 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map.ts @@ -18,7 +18,7 @@ import { additionalMapDataSourcesToDatasources, BaseMapSettings, CustomActionData, - DataKeyValuePair, + DataKeyValuePair, MapBooleanFunction, MapStringFunction, MapType, mergeMapDatasources, mergeUnplacedDataItemsArrays, @@ -34,12 +34,12 @@ import { formattedDataFormDatasourceData, isDefined, isDefinedAndNotNull, isUndefined, - mergeDeepIgnoreArray + mergeDeepIgnoreArray, parseTbFunction } from '@core/utils'; import { DeepPartial } from '@shared/models/common'; import L from 'leaflet'; import { forkJoin, Observable, of } from 'rxjs'; -import { switchMap, tap } from 'rxjs/operators'; +import { map, switchMap, tap } from 'rxjs/operators'; import '@home/components/widget/lib/maps/leaflet/leaflet-tb'; import { MapDataLayerType, @@ -71,6 +71,7 @@ import TooltipPositioningSide = JQueryTooltipster.TooltipPositioningSide; import { MapTimelinePanelComponent } from '@home/components/widget/lib/maps/panels/map-timeline-panel.component'; import { ComponentRef } from '@angular/core'; import { TbTripsDataLayer } from '@home/components/widget/lib/maps/data-layer/trips-data-layer'; +import { CompiledTbFunction } from '@shared/models/js-function.models'; type TooltipInstancesData = {root: HTMLElement, instances: ITooltipsterInstance[]}; @@ -88,7 +89,7 @@ export abstract class TbMap { protected dataLayers: TbMapDataLayer[]; protected tripDataLayers: TbTripsDataLayer[]; - protected dsData: FormattedData[]; + protected dsData: FormattedData[] = []; protected timeline = false; protected minTime: number; @@ -113,6 +114,7 @@ export abstract class TbMap { protected timeLineComponentRef: ComponentRef; protected timeLineComponent: MapTimelinePanelComponent; + protected locationSnapFilterFunction: CompiledTbFunction; protected addMarkerDataLayers: TbMapDataLayer[]; protected addPolygonDataLayers: TbMapDataLayer[]; @@ -183,7 +185,16 @@ export abstract class TbMap { if (this.map.zoomControl) { this.map.zoomControl.setPosition(this.settings.controlsPosition); } - return this.doSetupControls(); + const setup = [this.doSetupControls()]; + if (this.timeline && this.settings.tripTimeline.snapToRealLocation) { + setup.push(parseTbFunction(this.getCtx().http, this.settings.tripTimeline.locationSnapFilter, ['data', 'dsData']).pipe( + map((parsed) => { + this.locationSnapFilterFunction = parsed; + return null; + }) + )); + } + return forkJoin(setup); } private initMap() { @@ -263,7 +274,6 @@ export abstract class TbMap { this.updateBounds(); }); } - const setup = allDataLayers.map(dl => dl.setup()); forkJoin(setup).subscribe( () => { @@ -919,6 +929,7 @@ export abstract class TbMap { protected invalidateDataLayersCoordinates(): void { this.dataLayers.forEach(dl => dl.invalidateCoordinates()); + this.tripDataLayers.forEach(dl => dl.invalidateCoordinates()); } protected getSidebar(): L.TB.SidebarControl { @@ -953,16 +964,16 @@ export abstract class TbMap { this.updateTripsAnchors(); } - public dataItemClick($event: Event, action: WidgetAction, entityInfo: TbMapDatasource) { + public dataItemClick($event: Event, action: WidgetAction, data: FormattedData) { if ($event) { $event.preventDefault(); $event.stopPropagation(); } - const { entityId, entityName, entityLabel, entityType } = entityInfo; + const { entityId, entityName, entityLabel, entityType } = data.$datasource; this.ctx.actionsApi.handleWidgetAction($event, action, { entityType, id: entityId - }, entityName, null, entityLabel); + }, entityName, data, entityLabel); } public selectItem(item: TbDataLayerItem, cancel = false, force = false): boolean { @@ -1063,6 +1074,10 @@ export abstract class TbMap { return this.currentTime; } + public getLocationSnapFilterFunction(): CompiledTbFunction { + return this.locationSnapFilterFunction; + } + public destroy() { if (this.mapResize$) { this.mapResize$.disconnect(); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/models/map.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/models/map.models.ts index 79fb8a7c04..826b47fc91 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/models/map.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/models/map.models.ts @@ -23,7 +23,16 @@ import { WidgetActionType } from '@shared/models/widget.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; -import { guid, hashCode, isDefinedAndNotNull, isNotEmptyStr, isString, isUndefined, mergeDeep } from '@core/utils'; +import { + guid, + hashCode, + isDefinedAndNotNull, + isNotEmptyStr, + isString, + isUndefined, + isUndefinedOrNull, + mergeDeep +} from '@core/utils'; import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms'; import { materialColors } from '@shared/models/material.models'; import L from 'leaflet'; @@ -1040,6 +1049,9 @@ export interface CustomActionData { export type MapStringFunction = (data: FormattedData, dsData: FormattedData[]) => string; +export type MapBooleanFunction = (data: FormattedData, + dsData: FormattedData[]) => boolean; + export type MarkerImageFunction = (data: FormattedData, markerImages: string[], dsData: FormattedData[]) => MarkerImageInfo; @@ -1322,11 +1334,11 @@ export const interpolateLineSegment = ( }; } -export const findRotationAngle = (startPoint: FormattedData, endPoint: FormattedData, xKey: string, yKey: string): number => { - if (isUndefined(startPoint) || isUndefined(endPoint)) { +export const findRotationAngle = (startPoint: L.LatLng, endPoint: L.LatLng): number => { + if (isUndefinedOrNull(startPoint) || isUndefinedOrNull(endPoint)) { return 0; } - let angle = -Math.atan2(endPoint[xKey] - startPoint[xKey], endPoint[yKey] - startPoint[yKey]); + let angle = -Math.atan2(endPoint.lat - startPoint.lat, endPoint.lng - startPoint.lng); angle = angle * 180 / Math.PI; return parseInt(angle.toFixed(2), 10); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/panels/map-timeline-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/panels/map-timeline-panel.component.ts index 7b2b428c5c..7d165c5a24 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/panels/map-timeline-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/panels/map-timeline-panel.component.ts @@ -27,7 +27,7 @@ import { } from '@angular/core'; import { TripTimelineSettings } from '@home/components/widget/lib/maps/models/map.models'; import { DateFormatProcessor } from '@shared/models/widget-settings.models'; -import { interval, Observable, Subscription } from 'rxjs'; +import { interval, Subscription } from 'rxjs'; import { filter } from 'rxjs/operators'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @@ -75,6 +75,11 @@ export class MapTimelinePanelComponent implements OnInit { set currentTime(time: number) { if (this.currentTimeValue !== time) { this.currentTimeValue = time; + if (this.hasData) { + this.index = Math.ceil((this.currentTimeValue - this.minValue) / this.settings.timeStep); + } else { + this.index = 0; + } this.updateTimestampDisplayValue(); this.cd.markForCheck(); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.html index ffd2166aab..07e0fa43e9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.html @@ -285,6 +285,7 @@ px diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.ts index 7d1d4a4b50..8e57e891c8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.ts @@ -155,7 +155,7 @@ export class MapDataLayerDialogComponent extends DialogComponent