UI: Add JS modules support to map widgets JS functions.

This commit is contained in:
Igor Kulikov 2024-12-03 17:07:45 +02:00
parent 90ef67bf59
commit a0dcd7cf30
19 changed files with 279 additions and 186 deletions

View File

@ -711,21 +711,6 @@ export function safeExecuteTbFunction<T extends GenericFunction>(func: CompiledT
return res;
}
export function safeExecute(func: (...args: any[]) => any, params = []) {
let res = null;
if (func && typeof (func) === 'function') {
try {
res = func(...params);
}
catch (err) {
console.log('error in external function:', err);
res = null;
}
}
return res;
}
export function padValue(val: any, dec: number): string {
let strVal;
let n;

View File

@ -16,14 +16,11 @@
import L, { LeafletMouseEvent } from 'leaflet';
import { CircleData, WidgetCircleSettings } from '@home/components/widget/lib/maps/map-models';
import {
functionValueCalculator,
parseWithTranslation
} from '@home/components/widget/lib/maps/common-maps-utils';
import { functionValueCalculator, parseWithTranslation } from '@home/components/widget/lib/maps/common-maps-utils';
import LeafletMap from '@home/components/widget/lib/maps/leaflet-map';
import { createTooltip } from '@home/components/widget/lib/maps/maps-utils';
import { FormattedData } from '@shared/models/widget.models';
import { fillDataPattern, processDataPattern, safeExecute } from '@core/utils';
import { fillDataPattern, processDataPattern, safeExecuteTbFunction } from '@core/utils';
export class Circle {
@ -94,7 +91,7 @@ export class Circle {
if (this.settings.showCircleLabel) {
if (!this.map.circleLabelText || this.settings.useCircleLabelFunction) {
const pattern = this.settings.useCircleLabelFunction ?
safeExecute(this.settings.parsedCircleLabelFunction,
safeExecuteTbFunction(this.settings.parsedCircleLabelFunction,
[this.data, this.dataSources, this.data.dsIndex]) : this.settings.circleLabel;
this.map.circleLabelText = parseWithTranslation.prepareProcessPattern(pattern, true);
this.map.replaceInfoTooltipCircle = processDataPattern(this.map.circleLabelText, this.data);
@ -109,7 +106,7 @@ export class Circle {
private updateTooltip() {
const pattern = this.settings.useCircleTooltipFunction ?
safeExecute(this.settings.parsedCircleTooltipFunction, [this.data, this.dataSources, this.data.dsIndex]) :
safeExecuteTbFunction(this.settings.parsedCircleTooltipFunction, [this.data, this.dataSources, this.data.dsIndex]) :
this.settings.circleTooltipPattern;
this.tooltip.setContent(parseWithTranslation.parseTemplate(pattern, this.data, true));
}

View File

@ -29,6 +29,7 @@ import { map } from 'rxjs/operators';
import { FormattedData } from '@shared/models/widget.models';
import L from 'leaflet';
import { ImagePipe } from '@shared/pipe/image.pipe';
import { CompiledTbFunction, GenericFunction } from '@shared/models/js-function.models';
export function getRatio(firsMoment: number, secondMoment: number, intermediateMoment: number): number {
return (intermediateMoment - firsMoment) / (secondMoment - firsMoment);
@ -257,11 +258,11 @@ export const parseWithTranslation = {
}
};
export function functionValueCalculator<T>(useFunction: boolean, func: (...args: any[]) => any, params = [], defaultValue: T): T {
export function functionValueCalculator<T>(useFunction: boolean, func: CompiledTbFunction<GenericFunction>, params = [], defaultValue: T): T {
let res: T;
if (useFunction && isDefined(func) && isFunction(func)) {
try {
res = func(...params);
res = func.execute(...params);
if (!isDefinedAndNotNull(res) || res === '') {
res = defaultValue;
}

View File

@ -54,7 +54,7 @@ import {
isNotEmptyStr,
isString,
mergeFormattedData,
safeExecute
safeExecuteTbFunction
} from '@core/utils';
import { TranslateService } from '@ngx-translate/core';
import {
@ -63,9 +63,9 @@ import {
} from '@home/components/widget/lib/maps/dialogs/select-entity-dialog.component';
import { MatDialog } from '@angular/material/dialog';
import { FormattedData, ReplaceInfo } from '@shared/models/widget.models';
import ITooltipsterInstance = JQueryTooltipster.ITooltipsterInstance;
import { ImagePipe } from '@shared/pipe/image.pipe';
import { take, tap } from 'rxjs/operators';
import ITooltipsterInstance = JQueryTooltipster.ITooltipsterInstance;
export default abstract class LeafletMap {
@ -149,7 +149,7 @@ export default abstract class LeafletMap {
const childCount = cluster.getChildCount();
const formattedData = cluster.getAllChildMarkers().map(clusterMarker => clusterMarker.options.tbMarkerData);
const markerColor = markerClusteringSettings.clusterMarkerFunction
? safeExecute(markerClusteringSettings.parsedClusterMarkerFunction,
? safeExecuteTbFunction(markerClusteringSettings.parsedClusterMarkerFunction,
[formattedData, childCount])
: null;
if (isDefinedAndNotNull(markerColor) && tinycolor(markerColor).isValid()) {
@ -899,7 +899,7 @@ export default abstract class LeafletMap {
rawMarkers.forEach(data => {
if (data.rotationAngle || data.rotationAngle === 0) {
const currentImage: MarkerImageInfo = this.options.useMarkerImageFunction ?
safeExecute(this.options.parsedMarkerImageFunction,
safeExecuteTbFunction(this.options.parsedMarkerImageFunction,
[data, this.options.markerImages, markersData, data.dsIndex]) : this.options.currentImage;
const imageUrl$ =
currentImage
@ -1042,7 +1042,7 @@ export default abstract class LeafletMap {
if (!!this.extractPosition(pdata)) {
const dsData = pointsData.map(ds => ds[tsIndex]);
if (this.options.useColorPointFunction) {
pointColor = safeExecute(this.options.parsedColorPointFunction, [pdata, dsData, pdata.dsIndex]);
pointColor = safeExecuteTbFunction(this.options.parsedColorPointFunction, [pdata, dsData, pdata.dsIndex]);
}
const point = L.circleMarker(this.convertPosition(pdata, dsData), {
color: pointColor,

View File

@ -18,6 +18,7 @@ import { Datasource, FormattedData } from '@app/shared/models/widget.models';
import tinycolor from 'tinycolor2';
import { BaseIconOptions, Icon } from 'leaflet';
import { Observable } from 'rxjs';
import { CompiledTbFunction, TbFunction } from '@shared/models/js-function.models';
export const DEFAULT_MAP_PAGE_SIZE = 16384;
export const DEFAULT_ZOOM_LEVEL = 8;
@ -273,7 +274,7 @@ export interface TripAnimationCommonSettings {
}
export interface WidgetTripAnimationCommonSettings extends TripAnimationCommonSettings {
parsedTooltipFunction: GenericFunction;
parsedTooltipFunction: CompiledTbFunction<GenericFunction>;
}
export const defaultTripAnimationCommonSettings: TripAnimationCommonSettings = {
@ -305,35 +306,35 @@ export const showTooltipActionTranslationMap = new Map<ShowTooltipAction, string
export interface MarkersSettings {
markerOffsetX: number;
markerOffsetY: number;
posFunction?: string;
posFunction?: TbFunction;
draggableMarker: boolean;
showLabel: boolean;
useLabelFunction: boolean;
label?: string;
labelFunction?: string;
labelFunction?: TbFunction;
showTooltip: boolean;
showTooltipAction: ShowTooltipAction;
autocloseTooltip: boolean;
useTooltipFunction: boolean;
tooltipPattern?: string;
tooltipFunction?: string;
tooltipFunction?: TbFunction;
tooltipOffsetX: number;
tooltipOffsetY: number;
color?: string;
useColorFunction: boolean;
colorFunction?: string;
colorFunction?: TbFunction;
useMarkerImageFunction: boolean;
markerImage?: string;
markerImageSize?: number;
markerImageFunction?: string;
markerImageFunction?: TbFunction;
markerImages?: string[];
}
export interface WidgetMarkersSettings extends MarkersSettings, WidgetToolipSettings {
parsedLabelFunction: GenericFunction;
parsedTooltipFunction: GenericFunction;
parsedColorFunction: GenericFunction;
parsedMarkerImageFunction: MarkerImageFunction;
parsedLabelFunction: CompiledTbFunction<GenericFunction>;
parsedTooltipFunction: CompiledTbFunction<GenericFunction>;
parsedColorFunction: CompiledTbFunction<GenericFunction>;
parsedMarkerImageFunction: CompiledTbFunction<MarkerImageFunction>;
markerClick: { [name: string]: actionsHandler };
currentImage: MarkerImageInfo;
tinyColor: tinycolor.Instance;
@ -382,8 +383,7 @@ export interface TripAnimationMarkerSettings {
}
export interface WidgetTripAnimationMarkerSettings extends TripAnimationMarkerSettings {
parsedLabelFunction: GenericFunction;
parsedMarkerImageFunction: MarkerImageFunction;
parsedLabelFunction: CompiledTbFunction<GenericFunction>;
}
export const defaultTripAnimationMarkersSettings: TripAnimationMarkerSettings = {
@ -406,29 +406,29 @@ export interface PolygonSettings {
showPolygonLabel: boolean;
usePolygonLabelFunction: boolean;
polygonLabel?: string;
polygonLabelFunction?: string;
polygonLabelFunction?: TbFunction;
showPolygonTooltip: boolean;
showPolygonTooltipAction: ShowTooltipAction;
autoClosePolygonTooltip: boolean;
usePolygonTooltipFunction: boolean;
polygonTooltipPattern?: string;
polygonTooltipFunction?: string;
polygonTooltipFunction?: TbFunction;
polygonColor?: string;
polygonOpacity?: number;
usePolygonColorFunction: boolean;
polygonColorFunction?: string;
polygonColorFunction?: TbFunction;
polygonStrokeColor?: string;
polygonStrokeOpacity?: number;
polygonStrokeWeight?: number;
usePolygonStrokeColorFunction: boolean;
polygonStrokeColorFunction?: string;
polygonStrokeColorFunction?: TbFunction;
}
export interface WidgetPolygonSettings extends PolygonSettings, WidgetToolipSettings {
parsedPolygonLabelFunction: GenericFunction;
parsedPolygonTooltipFunction: GenericFunction;
parsedPolygonColorFunction: GenericFunction;
parsedPolygonStrokeColorFunction: GenericFunction;
parsedPolygonLabelFunction: CompiledTbFunction<GenericFunction>;
parsedPolygonTooltipFunction: CompiledTbFunction<GenericFunction>;
parsedPolygonColorFunction: CompiledTbFunction<GenericFunction>;
parsedPolygonStrokeColorFunction: CompiledTbFunction<GenericFunction>;
polygonClick: { [name: string]: actionsHandler };
}
@ -464,29 +464,29 @@ export interface CircleSettings {
showCircleLabel: boolean;
useCircleLabelFunction: boolean;
circleLabel?: string;
circleLabelFunction?: string;
circleLabelFunction?: TbFunction;
showCircleTooltip: boolean;
showCircleTooltipAction: ShowTooltipAction;
autoCloseCircleTooltip: boolean;
useCircleTooltipFunction: boolean;
circleTooltipPattern?: string;
circleTooltipFunction?: string;
circleTooltipFunction?: TbFunction;
circleFillColor?: string;
circleFillColorOpacity?: number;
useCircleFillColorFunction: boolean;
circleFillColorFunction?: string;
circleFillColorFunction?: TbFunction;
circleStrokeColor?: string;
circleStrokeOpacity?: number;
circleStrokeWeight?: number;
useCircleStrokeColorFunction: boolean;
circleStrokeColorFunction?: string;
circleStrokeColorFunction?: TbFunction;
}
export interface WidgetCircleSettings extends CircleSettings, WidgetToolipSettings {
parsedCircleLabelFunction: GenericFunction;
parsedCircleTooltipFunction: GenericFunction;
parsedCircleFillColorFunction: GenericFunction;
parsedCircleStrokeColorFunction: GenericFunction;
parsedCircleLabelFunction: CompiledTbFunction<GenericFunction>;
parsedCircleTooltipFunction: CompiledTbFunction<GenericFunction>;
parsedCircleFillColorFunction: CompiledTbFunction<GenericFunction>;
parsedCircleStrokeColorFunction: CompiledTbFunction<GenericFunction>;
circleClick: { [name: string]: actionsHandler };
}
@ -530,13 +530,13 @@ export const polylineDecoratorSymbolTranslationMap = new Map<PolylineDecoratorSy
export interface PolylineSettings {
useStrokeWeightFunction?: boolean;
strokeWeight: number;
strokeWeightFunction?: string;
strokeWeightFunction?: TbFunction;
useStrokeOpacityFunction?: boolean;
strokeOpacity: number;
strokeOpacityFunction?: string;
strokeOpacityFunction?: TbFunction;
useColorFunction?: boolean;
color?: string;
colorFunction?: string;
colorFunction?: TbFunction;
usePolylineDecorator?: boolean;
decoratorSymbol?: PolylineDecoratorSymbol;
decoratorSymbolSize?: number;
@ -548,9 +548,9 @@ export interface PolylineSettings {
}
export interface WidgetPolylineSettings extends PolylineSettings {
parsedColorFunction: GenericFunction;
parsedStrokeOpacityFunction: GenericFunction;
parsedStrokeWeightFunction: GenericFunction;
parsedColorFunction: CompiledTbFunction<GenericFunction>;
parsedStrokeOpacityFunction: CompiledTbFunction<GenericFunction>;
parsedStrokeWeightFunction: CompiledTbFunction<GenericFunction>;
}
export const defaultRouteMapSettings: PolylineSettings = {
@ -578,7 +578,7 @@ export interface PointsSettings {
showPoints?: boolean;
pointColor?: string;
useColorPointFunction?: false;
colorPointFunction?: string;
colorPointFunction?: TbFunction;
pointSize?: number;
usePointAsAnchor?: false;
pointAsAnchorFunction?: string;
@ -586,8 +586,8 @@ export interface PointsSettings {
}
export interface WidgetPointsSettings extends PointsSettings {
parsedColorPointFunction: GenericFunction;
parsedPointAsAnchorFunction: GenericFunction;
parsedColorPointFunction: CompiledTbFunction<GenericFunction>;
parsedPointAsAnchorFunction: CompiledTbFunction<GenericFunction>;
}
export const defaultTripAnimationPointSettings: PointsSettings = {
@ -612,11 +612,11 @@ export interface MarkerClusteringSettings {
chunkedLoading: boolean;
removeOutsideVisibleBounds: boolean;
useIconCreateFunction: boolean;
clusterMarkerFunction?: string;
clusterMarkerFunction?: TbFunction;
}
export interface WidgetMarkerClusteringSettings extends MarkerClusteringSettings {
parsedClusterMarkerFunction?: GenericFunction;
parsedClusterMarkerFunction?: CompiledTbFunction<GenericFunction>;
}
export const defaultMarkerClusteringSettings: MarkerClusteringSettings = {

View File

@ -30,9 +30,9 @@ import { TranslateService } from '@ngx-translate/core';
import { UtilsService } from '@core/services/utils.service';
import { EntityDataPageLink } from '@shared/models/query/query.models';
import { providerClass } from '@home/components/widget/lib/maps/providers/public-api';
import { isDefined, isDefinedAndNotNull, parseFunction } from '@core/utils';
import { isDefined, isDefinedAndNotNull, parseFunction, parseTbFunction } from '@core/utils';
import L from 'leaflet';
import { forkJoin, Observable, of } from 'rxjs';
import { firstValueFrom, forkJoin, from, Observable, of } from 'rxjs';
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';
@ -40,12 +40,18 @@ import { AttributeScope, DataKeyType, LatestTelemetry } from '@shared/models/tel
// @dynamic
export class MapWidgetController implements MapWidgetInterface {
private updatePending = false;
private latestUpdatePending = false;
private resizePending = false;
private destroyed = false;
constructor(
public mapProvider: MapProviders,
private drawRoutes: boolean,
public ctx: WidgetContext,
$element: HTMLElement,
isEdit?: boolean
isEdit = false,
mapLoaded?: (map: LeafletMap) => void
) {
if (this.map) {
this.map.map.remove();
@ -56,37 +62,53 @@ export class MapWidgetController implements MapWidgetInterface {
if (!$element) {
$element = ctx.$container[0];
}
this.settings = this.initSettings(ctx.settings, isEdit);
this.settings.tooltipAction = this.getDescriptors('tooltipAction');
this.settings.markerClick = this.getDescriptors('markerClick');
this.settings.polygonClick = this.getDescriptors('polygonClick');
this.settings.circleClick = this.getDescriptors('circleClick');
from(this.initSettings(ctx.settings, isEdit)).subscribe(settings => {
if (!this.destroyed) {
this.settings = settings;
this.settings.tooltipAction = this.getDescriptors('tooltipAction');
this.settings.markerClick = this.getDescriptors('markerClick');
this.settings.polygonClick = this.getDescriptors('polygonClick');
this.settings.circleClick = this.getDescriptors('circleClick');
const MapClass = providerClass[this.provider];
if (!MapClass) {
return;
}
parseWithTranslation.setTranslate(this.translate);
this.map = new MapClass(this.ctx, $element, this.settings);
(this.ctx as any).mapInstance = this.map;
this.map.saveMarkerLocation = this.setMarkerLocation.bind(this);
this.map.savePolygonLocation = this.savePolygonLocation.bind(this);
this.map.saveLocation = this.saveLocation.bind(this);
let pageSize = this.settings.mapPageSize;
if (isDefinedAndNotNull(this.ctx.widgetConfig.pageSize)) {
pageSize = Math.max(pageSize, this.ctx.widgetConfig.pageSize);
}
this.pageLink = {
page: 0,
pageSize,
textSearch: null,
dynamic: true
};
this.map.setLoading(true);
this.ctx.defaultSubscription.paginatedDataSubscriptionUpdated.subscribe(() => {
this.map.resetState();
const MapClass = providerClass[this.provider];
if (!MapClass) {
return;
}
parseWithTranslation.setTranslate(this.translate);
this.map = new MapClass(this.ctx, $element, this.settings);
(this.ctx as any).mapInstance = this.map;
this.map.saveMarkerLocation = this.setMarkerLocation.bind(this);
this.map.savePolygonLocation = this.savePolygonLocation.bind(this);
this.map.saveLocation = this.saveLocation.bind(this);
let pageSize = this.settings.mapPageSize;
if (isDefinedAndNotNull(this.ctx.widgetConfig.pageSize)) {
pageSize = Math.max(pageSize, this.ctx.widgetConfig.pageSize);
}
this.pageLink = {
page: 0,
pageSize,
textSearch: null,
dynamic: true
};
this.map.setLoading(true);
this.ctx.defaultSubscription.paginatedDataSubscriptionUpdated.subscribe(() => {
this.map.resetState();
});
this.ctx.defaultSubscription.subscribeAllForPaginatedData(this.pageLink, null);
if (this.updatePending) {
this.update();
}
if (this.latestUpdatePending) {
this.latestDataUpdate();
}
if (this.resizePending) {
this.resize();
}
if (mapLoaded) {
mapLoaded(this.map);
}
}
});
this.ctx.defaultSubscription.subscribeAllForPaginatedData(this.pageLink, null);
}
map: LeafletMap;
@ -233,27 +255,27 @@ export class MapWidgetController implements MapWidgetInterface {
}
}
initSettings(settings: UnitedMapSettings, isEditMap?: boolean): WidgetUnitedMapSettings {
async initSettings(settings: UnitedMapSettings, isEditMap?: boolean): Promise<WidgetUnitedMapSettings> {
const functionParams = ['data', 'dsData', 'dsIndex'];
this.provider = settings.provider || this.mapProvider;
const parsedOptions: Partial<WidgetUnitedMapSettings> = {
provider: this.provider,
parsedLabelFunction: parseFunction(settings.labelFunction, functionParams),
parsedTooltipFunction: parseFunction(settings.tooltipFunction, functionParams),
parsedColorFunction: parseFunction(settings.colorFunction, functionParams),
parsedColorPointFunction: parseFunction(settings.colorPointFunction, functionParams),
parsedStrokeOpacityFunction: parseFunction(settings.strokeOpacityFunction, functionParams),
parsedStrokeWeightFunction: parseFunction(settings.strokeWeightFunction, functionParams),
parsedPolygonLabelFunction: parseFunction(settings.polygonLabelFunction, functionParams),
parsedPolygonColorFunction: parseFunction(settings.polygonColorFunction, functionParams),
parsedPolygonStrokeColorFunction: parseFunction(settings.polygonStrokeColorFunction, functionParams),
parsedPolygonTooltipFunction: parseFunction(settings.polygonTooltipFunction, functionParams),
parsedCircleLabelFunction: parseFunction(settings.circleLabelFunction, functionParams),
parsedCircleStrokeColorFunction: parseFunction(settings.circleStrokeColorFunction, functionParams),
parsedCircleFillColorFunction: parseFunction(settings.circleFillColorFunction, functionParams),
parsedCircleTooltipFunction: parseFunction(settings.circleTooltipFunction, functionParams),
parsedMarkerImageFunction: parseFunction(settings.markerImageFunction, ['data', 'images', 'dsData', 'dsIndex']),
parsedClusterMarkerFunction: parseFunction(settings.clusterMarkerFunction, ['data', 'childCount']),
parsedLabelFunction: await firstValueFrom(parseTbFunction(this.ctx.http, settings.labelFunction, functionParams)),
parsedTooltipFunction: await firstValueFrom(parseTbFunction(this.ctx.http, settings.tooltipFunction, functionParams)),
parsedColorFunction: await firstValueFrom(parseTbFunction(this.ctx.http, settings.colorFunction, functionParams)),
parsedColorPointFunction: await firstValueFrom(parseTbFunction(this.ctx.http, settings.colorPointFunction, functionParams)),
parsedStrokeOpacityFunction: await firstValueFrom(parseTbFunction(this.ctx.http, settings.strokeOpacityFunction, functionParams)),
parsedStrokeWeightFunction: await firstValueFrom(parseTbFunction(this.ctx.http, settings.strokeWeightFunction, functionParams)),
parsedPolygonLabelFunction: await firstValueFrom(parseTbFunction(this.ctx.http, settings.polygonLabelFunction, functionParams)),
parsedPolygonColorFunction: await firstValueFrom(parseTbFunction(this.ctx.http, settings.polygonColorFunction, functionParams)),
parsedPolygonStrokeColorFunction: await firstValueFrom(parseTbFunction(this.ctx.http, settings.polygonStrokeColorFunction, functionParams)),
parsedPolygonTooltipFunction: await firstValueFrom(parseTbFunction(this.ctx.http, settings.polygonTooltipFunction, functionParams)),
parsedCircleLabelFunction: await firstValueFrom(parseTbFunction(this.ctx.http, settings.circleLabelFunction, functionParams)),
parsedCircleStrokeColorFunction: await firstValueFrom(parseTbFunction(this.ctx.http, settings.circleStrokeColorFunction, functionParams)),
parsedCircleFillColorFunction: await firstValueFrom(parseTbFunction(this.ctx.http, settings.circleFillColorFunction, functionParams)),
parsedCircleTooltipFunction: await firstValueFrom(parseTbFunction(this.ctx.http, settings.circleTooltipFunction, functionParams)),
parsedMarkerImageFunction: await firstValueFrom(parseTbFunction(this.ctx.http, settings.markerImageFunction, ['data', 'images', 'dsData', 'dsIndex'])),
parsedClusterMarkerFunction: await firstValueFrom(parseTbFunction(this.ctx.http, settings.clusterMarkerFunction, ['data', 'childCount'])),
// labelColor: this.ctx.widgetConfig.color,
// polygonLabelColor: this.ctx.widgetConfig.color,
polygonKeyName: (settings as any).polKeyName ? (settings as any).polKeyName : settings.polygonKeyName,
@ -277,20 +299,36 @@ export class MapWidgetController implements MapWidgetInterface {
}
update() {
if (this.map) {
this.updatePending = false;
this.map.updateData(this.drawRoutes);
this.map.setLoading(false);
} else {
this.updatePending = true;
}
}
latestDataUpdate() {
this.map.updateData(this.drawRoutes);
if (this.map) {
this.latestUpdatePending = false;
this.map.updateData(this.drawRoutes);
} else {
this.latestUpdatePending = true;
}
}
resize() {
this.map.onResize();
this.map?.invalidateSize();
if (this.map) {
this.resizePending = false;
this.map.onResize();
this.map.invalidateSize();
} else {
this.resizePending = true;
}
}
destroy() {
this.destroyed = true;
if (this.map) {
this.map.remove();
}

View File

@ -15,13 +15,11 @@
///
import L from 'leaflet';
import {
GenericFunction,
ShowTooltipAction, WidgetToolipSettings
} from './map-models';
import { GenericFunction, ShowTooltipAction, WidgetToolipSettings } from './map-models';
import { Datasource, FormattedData } from '@app/shared/models/widget.models';
import { fillDataPattern, isDefinedAndNotNull, isString, processDataPattern, safeExecute } from '@core/utils';
import { fillDataPattern, isDefinedAndNotNull, isString, processDataPattern, safeExecuteTbFunction } from '@core/utils';
import { parseWithTranslation } from '@home/components/widget/lib/maps/common-maps-utils';
import { CompiledTbFunction } from '@shared/models/js-function.models';
export function createTooltip(target: L.Layer,
settings: Partial<WidgetToolipSettings>,
@ -90,7 +88,7 @@ export function isJSON(data: string): boolean {
export interface LabelSettings {
showLabel: boolean;
useLabelFunction: boolean;
parsedLabelFunction: GenericFunction;
parsedLabelFunction: CompiledTbFunction<GenericFunction>;
label: string;
}
@ -98,7 +96,7 @@ export function entitiesParseName(entities: FormattedData[], labelSettings: Labe
const div = document.createElement('div');
for (const entity of entities) {
if (labelSettings?.showLabel) {
const pattern = labelSettings.useLabelFunction ? safeExecute(labelSettings.parsedLabelFunction,
const pattern = labelSettings.useLabelFunction ? safeExecuteTbFunction(labelSettings.parsedLabelFunction,
[entity, entities, entity.dsIndex]) : labelSettings.label;
const markerLabelText = parseWithTranslation.prepareProcessPattern(pattern, true);
const replaceInfoLabelMarker = processDataPattern(pattern, entity);

View File

@ -19,7 +19,13 @@ import { MarkerIconInfo, MarkerIconReadyFunction, MarkerImageInfo, WidgetMarkers
import { bindPopupActions, createTooltip } from './maps-utils';
import { loadImageWithAspect, parseWithTranslation } from './common-maps-utils';
import tinycolor from 'tinycolor2';
import { fillDataPattern, isDefined, isDefinedAndNotNull, processDataPattern, safeExecute } from '@core/utils';
import {
fillDataPattern,
isDefined,
isDefinedAndNotNull,
processDataPattern,
safeExecuteTbFunction
} from '@core/utils';
import LeafletMap from './leaflet-map';
import { FormattedData } from '@shared/models/widget.models';
import { ImagePipe } from '@shared/pipe/image.pipe';
@ -101,7 +107,7 @@ export class Marker {
updateMarkerTooltip(data: FormattedData) {
if (!this.map.markerTooltipText || this.settings.useTooltipFunction) {
const pattern = this.settings.useTooltipFunction ?
safeExecute(this.settings.parsedTooltipFunction, [this.data, this.dataSources, this.data.dsIndex]) : this.settings.tooltipPattern;
safeExecuteTbFunction(this.settings.parsedTooltipFunction, [this.data, this.dataSources, this.data.dsIndex]) : this.settings.tooltipPattern;
this.map.markerTooltipText = parseWithTranslation.prepareProcessPattern(pattern, true);
this.map.replaceInfoTooltipMarker = processDataPattern(this.map.markerTooltipText, data);
}
@ -123,7 +129,7 @@ export class Marker {
if (settings.showLabel) {
if (!this.map.markerLabelText || settings.useLabelFunction) {
const pattern = settings.useLabelFunction ?
safeExecute(settings.parsedLabelFunction, [this.data, this.dataSources, this.data.dsIndex]) : settings.label;
safeExecuteTbFunction(settings.parsedLabelFunction, [this.data, this.dataSources, this.data.dsIndex]) : settings.label;
this.map.markerLabelText = parseWithTranslation.prepareProcessPattern(pattern, true);
this.map.replaceInfoLabelMarker = processDataPattern(this.map.markerLabelText, this.data);
}
@ -165,11 +171,11 @@ export class Marker {
return;
}
const currentImage: MarkerImageInfo = this.settings.useMarkerImageFunction ?
safeExecute(this.settings.parsedMarkerImageFunction,
safeExecuteTbFunction(this.settings.parsedMarkerImageFunction,
[this.data, this.settings.markerImages, this.dataSources, this.data.dsIndex]) : this.settings.currentImage;
let currentColor = this.settings.tinyColor;
if (this.settings.useColorFunction) {
const functionColor = safeExecute(this.settings.parsedColorFunction,
const functionColor = safeExecuteTbFunction(this.settings.parsedColorFunction,
[this.data, this.dataSources, this.data.dsIndex]);
if (isDefinedAndNotNull(functionColor)) {
currentColor = tinycolor(functionColor);

View File

@ -16,13 +16,10 @@
import L, { LatLngExpression, LeafletMouseEvent } from 'leaflet';
import { createTooltip, isCutPolygon } from './maps-utils';
import {
functionValueCalculator,
parseWithTranslation
} from './common-maps-utils';
import { functionValueCalculator, parseWithTranslation } from './common-maps-utils';
import { WidgetPolygonSettings } from './map-models';
import { FormattedData } from '@shared/models/widget.models';
import { fillDataPattern, processDataPattern, safeExecute } from '@core/utils';
import { fillDataPattern, processDataPattern, safeExecuteTbFunction } from '@core/utils';
import LeafletMap from '@home/components/widget/lib/maps/leaflet-map';
export class Polygon {
@ -92,7 +89,7 @@ export class Polygon {
updateTooltip(data: FormattedData) {
const pattern = this.settings.usePolygonTooltipFunction ?
safeExecute(this.settings.parsedPolygonTooltipFunction, [this.data, this.dataSources, this.data.dsIndex]) :
safeExecuteTbFunction(this.settings.parsedPolygonTooltipFunction, [this.data, this.dataSources, this.data.dsIndex]) :
this.settings.polygonTooltipPattern;
this.tooltip.setContent(parseWithTranslation.parseTemplate(pattern, data, true));
}
@ -102,7 +99,7 @@ export class Polygon {
if (settings.showPolygonLabel) {
if (!this.map.polygonLabelText || settings.usePolygonLabelFunction) {
const pattern = settings.usePolygonLabelFunction ?
safeExecute(settings.parsedPolygonLabelFunction,
safeExecuteTbFunction(settings.parsedPolygonLabelFunction,
[this.data, this.dataSources, this.data.dsIndex]) : settings.polygonLabel;
this.map.polygonLabelText = parseWithTranslation.prepareProcessPattern(pattern, true);
this.map.replaceInfoLabelPolygon = processDataPattern(this.map.polygonLabelText, this.data);

View File

@ -23,16 +23,17 @@ import {
PosFunction,
WidgetUnitedMapSettings
} from '../map-models';
import { Observable, of, ReplaySubject, switchMap } from 'rxjs';
import { forkJoin, Observable, of, ReplaySubject, switchMap } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { calculateNewPointCoordinate, loadImageWithAspect } from '@home/components/widget/lib/maps/common-maps-utils';
import { WidgetContext } from '@home/models/widget-component.models';
import { DataSet, DatasourceType, FormattedData, widgetType } from '@shared/models/widget.models';
import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
import { WidgetSubscriptionOptions } from '@core/api/widget-api.models';
import { isDefinedAndNotNull, isEmptyStr, isNotEmptyStr, parseFunction } from '@core/utils';
import { isDefinedAndNotNull, isEmptyStr, isNotEmptyStr, parseFunction, parseTbFunction } from '@core/utils';
import { EntityDataPageLink } from '@shared/models/query/query.models';
import { ImagePipe } from '@shared/pipe/image.pipe';
import { CompiledTbFunction } from '@shared/models/js-function.models';
const maxZoom = 4; // ?
@ -43,13 +44,20 @@ export class ImageMap extends LeafletMap {
width = 0;
height = 0;
imageUrl: string;
posFunction: PosFunction;
posFunction: CompiledTbFunction<PosFunction>;
constructor(ctx: WidgetContext, $container: HTMLElement, options: WidgetUnitedMapSettings) {
super(ctx, $container, options);
this.posFunction = parseFunction(options.posFunction,
['origXPos', 'origYPos', 'data', 'dsData', 'dsIndex', 'aspect']) as PosFunction;
this.mapImage(options).subscribe((mapImage) => {
const initData = {
posFunction: parseTbFunction<PosFunction>(this.ctx.http, options.posFunction,
['origXPos', 'origYPos', 'data', 'dsData', 'dsIndex', 'aspect']),
mapImage: this.mapImage(options)
};
forkJoin(initData).subscribe(inited => {
this.posFunction = inited.posFunction;
const mapImage = inited.mapImage;
this.imageUrl = mapImage.imageUrl;
this.aspect = mapImage.aspect;
if (mapImage.update) {
@ -272,7 +280,7 @@ export class ImageMap extends LeafletMap {
convertPosition(data: FormattedData, dsData: FormattedData[]): L.LatLng {
const position = this.extractPosition(data);
if (position) {
const converted = this.posFunction(position.x, position.y, data, dsData, data.dsIndex, this.aspect) || {x: 0, y: 0};
const converted = this.posFunction.execute(position.x, position.y, data, dsData, data.dsIndex, this.aspect) || {x: 0, y: 0};
return this.positionToLatLng(converted);
} else {
return null;

View File

@ -62,6 +62,7 @@
</tb-html>
<tb-js-func [class.!hidden]="!circleSettingsFormGroup.get('useCircleLabelFunction').value"
formControlName="circleLabelFunction"
withModules
[globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.circle-label-function' | translate }}"
@ -105,6 +106,7 @@
</tb-html>
<tb-js-func [class.!hidden]="!circleSettingsFormGroup.get('useCircleTooltipFunction').value"
formControlName="circleTooltipFunction"
withModules
[globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.circle-tooltip-function' | translate }}"
@ -140,6 +142,7 @@
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<tb-js-func formControlName="circleFillColorFunction"
withModules
[globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.circle-fill-color-function' | translate }}"
@ -179,6 +182,7 @@
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<tb-js-func formControlName="circleStrokeColorFunction"
withModules
[globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.circle-stroke-color-function' | translate }}"

View File

@ -78,6 +78,7 @@
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<tb-js-func formControlName="clusterMarkerFunction"
withModules
[globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'childCount']"
functionTitle="{{ 'widgets.maps.marker-color-function' | translate }}"

View File

@ -30,6 +30,7 @@
</section>
<tb-js-func [class.!hidden]="provider !== mapProvider.image"
formControlName="posFunction"
withModules
minHeight="100px"
[globalVariables]="functionScopeVariables"
[functionArgs]="['origXPos', 'origYPos', 'data', 'dsData', 'dsIndex', 'aspect']"
@ -63,6 +64,7 @@
</tb-html>
<tb-js-func [class.!hidden]="!markersSettingsFormGroup.get('useLabelFunction').value"
formControlName="labelFunction"
withModules
[globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.label-function' | translate }}"
@ -106,6 +108,7 @@
</tb-html>
<tb-js-func [class.!hidden]="!markersSettingsFormGroup.get('useTooltipFunction').value"
formControlName="tooltipFunction"
withModules
[globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.tooltip-function' | translate }}"
@ -144,6 +147,7 @@
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<tb-js-func formControlName="colorFunction"
withModules
[globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.color-function' | translate }}"
@ -177,6 +181,7 @@
</mat-form-field>
<tb-js-func [class.!hidden]="!markersSettingsFormGroup.get('useMarkerImageFunction').value"
formControlName="markerImageFunction"
withModules
[globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'images', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.marker-image-function' | translate }}"

View File

@ -62,6 +62,7 @@
</tb-html>
<tb-js-func [class.!hidden]="!polygonSettingsFormGroup.get('usePolygonLabelFunction').value"
formControlName="polygonLabelFunction"
withModules
[globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.polygon-label-function' | translate }}"
@ -105,6 +106,7 @@
</tb-html>
<tb-js-func [class.!hidden]="!polygonSettingsFormGroup.get('usePolygonTooltipFunction').value"
formControlName="polygonTooltipFunction"
withModules
[globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.polygon-tooltip-function' | translate }}"
@ -140,6 +142,7 @@
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<tb-js-func formControlName="polygonColorFunction"
withModules
[globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.polygon-color-function' | translate }}"
@ -179,6 +182,7 @@
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<tb-js-func formControlName="polygonStrokeColorFunction"
withModules
[globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.polygon-stroke-color-function' | translate }}"

View File

@ -81,6 +81,7 @@
</tb-html>
<tb-js-func [class.!hidden]="!tripAnimationCommonSettingsFormGroup.get('useTooltipFunction').value"
formControlName="tooltipFunction"
withModules
[globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.tooltip-function' | translate }}"

View File

@ -46,6 +46,7 @@
</tb-html>
<tb-js-func [class.!hidden]="!tripAnimationMarkerSettingsFormGroup.get('useLabelFunction').value"
formControlName="labelFunction"
withModules
[globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.label-function' | translate }}"
@ -78,6 +79,7 @@
<input matInput type="number" min="1" formControlName="markerImageSize">
</mat-form-field>
<tb-js-func [class.!hidden]="!tripAnimationMarkerSettingsFormGroup.get('useMarkerImageFunction').value"
withModules
formControlName="markerImageFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'images', 'dsData', 'dsIndex']"

View File

@ -47,6 +47,7 @@
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<tb-js-func formControlName="colorFunction"
withModules
[globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.path-color-function' | translate }}"

View File

@ -55,6 +55,7 @@
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<tb-js-func formControlName="colorPointFunction"
withModules
[globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.point-color-function' | translate }}"
@ -75,6 +76,7 @@
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<tb-js-func formControlName="pointAsAnchorFunction"
withModules
[globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.point-as-anchor-function' | translate }}"

View File

@ -48,10 +48,11 @@ import {
isDefined,
isUndefined,
mergeFormattedData,
parseFunction,
safeExecute
parseTbFunction,
safeExecuteTbFunction
} from '@core/utils';
import { MapWidgetInterface } from '@home/components/widget/lib/maps/map-widget.interface';
import { firstValueFrom, from } from 'rxjs';
interface DataMap {
[key: string]: FormattedData;
@ -67,6 +68,10 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
private mapResize$: ResizeObserver;
private initialized = false;
private updatePending = false;
private mapWidgetUpdatePending = false;
constructor(private cd: ChangeDetectorRef, private sanitizer: DomSanitizer) { }
@Input() ctx: WidgetContext;
@ -100,38 +105,33 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
...this.ctx.settings
};
this.useAnchors = this.settings.showPoints && this.settings.usePointAsAnchor;
this.settings.parsedPointAsAnchorFunction = parseFunction(this.settings.pointAsAnchorFunction, ['data', 'dsData', 'dsIndex']);
this.settings.parsedTooltipFunction = parseFunction(this.settings.tooltipFunction, ['data', 'dsData', 'dsIndex']);
this.settings.parsedLabelFunction = parseFunction(this.settings.labelFunction, ['data', 'dsData', 'dsIndex']);
this.settings.parsedColorPointFunction = parseFunction(this.settings.colorPointFunction, ['data', 'dsData', 'dsIndex']);
this.normalizationStep = this.settings.normalizationStep;
const subscription = this.ctx.defaultSubscription;
subscription.callbacks.onDataUpdated = () => {
this.historicalData = formattedDataArrayFromDatasourceData(this.ctx.data).map(
item => this.clearIncorrectFirsLastDatapoint(item)).filter(arr => arr.length);
this.interpolatedTimeData.length = 0;
this.formattedInterpolatedTimeData.length = 0;
const prevMinTime = this.minTime;
const prevMaxTime = this.maxTime;
this.calculateIntervals();
const currentTime = this.calculateCurrentTime(prevMinTime, prevMaxTime);
if (currentTime !== this.currentTime) {
this.timeUpdated(currentTime);
}
this.mapWidget.map.map?.invalidateSize();
this.mapWidget.map.setLoading(false);
this.cd.detectChanges();
this.update();
};
subscription.callbacks.onLatestDataUpdated = () => {
this.formattedLatestData = formattedDataFormDatasourceData(this.ctx.latestData);
this.updateCurrentData();
this.latestDataUpdate();
};
from(this.initializeFunctions()).subscribe(() => {
this.initialized = true;
if (this.updatePending) {
this.updateCurrentData();
}
});
}
ngAfterViewInit() {
import('@home/components/widget/lib/maps/map-widget2').then(
(mod) => {
this.mapWidget = new mod.MapWidgetController(MapProviders.openstreet, false, this.ctx, this.mapContainer.nativeElement);
this.mapWidget = new mod.MapWidgetController(MapProviders.openstreet, false, this.ctx, this.mapContainer.nativeElement, false,
() => {
if (this.mapWidgetUpdatePending) {
this.updateMapWidget();
}
}
);
this.mapResize$ = new ResizeObserver(() => {
this.mapWidget.resize();
});
@ -177,22 +177,65 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
this.updateCurrentData();
}
private updateCurrentData() {
let currentPosition = this.formattedCurrentPosition;
if (this.formattedLatestData.length) {
currentPosition = mergeFormattedData(this.formattedCurrentPosition, this.formattedLatestData);
private async initializeFunctions(): Promise<void> {
this.settings.parsedPointAsAnchorFunction = await firstValueFrom(parseTbFunction(this.ctx.http, this.settings.pointAsAnchorFunction, ['data', 'dsData', 'dsIndex']));
this.settings.parsedTooltipFunction = await firstValueFrom(parseTbFunction(this.ctx.http, this.settings.tooltipFunction, ['data', 'dsData', 'dsIndex']));
this.settings.parsedLabelFunction = await firstValueFrom(parseTbFunction(this.ctx.http, this.settings.labelFunction, ['data', 'dsData', 'dsIndex']));
this.settings.parsedColorPointFunction = await firstValueFrom(parseTbFunction(this.ctx.http, this.settings.colorPointFunction, ['data', 'dsData', 'dsIndex']));
}
private update() {
this.historicalData = formattedDataArrayFromDatasourceData(this.ctx.data).map(
item => this.clearIncorrectFirsLastDatapoint(item)).filter(arr => arr.length);
this.interpolatedTimeData.length = 0;
this.formattedInterpolatedTimeData.length = 0;
const prevMinTime = this.minTime;
const prevMaxTime = this.maxTime;
this.calculateIntervals();
const currentTime = this.calculateCurrentTime(prevMinTime, prevMaxTime);
if (currentTime !== this.currentTime) {
this.timeUpdated(currentTime);
}
this.calcLabel(currentPosition);
this.calcMainTooltip(currentPosition);
if (this.mapWidget && this.mapWidget.map && this.mapWidget.map.map) {
this.mapWidget.map.updateFromData(true, currentPosition, this.formattedInterpolatedTimeData, (trip) => {
this.activeTrip = trip;
this.timeUpdated(this.currentTime);
this.cd.markForCheck();
});
if (this.settings.showPoints) {
this.mapWidget.map.updatePoints(this.formattedInterpolatedTimeData, this.calcTooltip);
this.updateMapWidget();
}
private latestDataUpdate() {
this.formattedLatestData = formattedDataFormDatasourceData(this.ctx.latestData);
this.updateCurrentData();
}
private updateMapWidget() {
if (this.mapWidget?.map) {
this.mapWidgetUpdatePending = false;
this.mapWidget.map.map?.invalidateSize();
this.mapWidget.map.setLoading(false);
this.cd.detectChanges();
} else {
this.mapWidgetUpdatePending = true;
}
}
private updateCurrentData() {
if (this.initialized) {
this.updatePending = false;
let currentPosition = this.formattedCurrentPosition;
if (this.formattedLatestData.length) {
currentPosition = mergeFormattedData(this.formattedCurrentPosition, this.formattedLatestData);
}
this.calcLabel(currentPosition);
this.calcMainTooltip(currentPosition);
if (this.mapWidget?.map?.map) {
this.mapWidget.map.updateFromData(true, currentPosition, this.formattedInterpolatedTimeData, (trip) => {
this.activeTrip = trip;
this.timeUpdated(this.currentTime);
this.cd.markForCheck();
});
if (this.settings.showPoints) {
this.mapWidget.map.updatePoints(this.formattedInterpolatedTimeData, this.calcTooltip);
}
}
} else {
this.updatePending = true;
}
}
@ -235,7 +278,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
if (this.useAnchors) {
const anchorDate = Object.entries(_.union(this.interpolatedTimeData)[0]);
this.anchors = anchorDate
.filter((data: [string, FormattedData], tsIndex) => safeExecute(this.settings.parsedPointAsAnchorFunction, [data[1],
.filter((data: [string, FormattedData], tsIndex) => safeExecuteTbFunction(this.settings.parsedPointAsAnchorFunction, [data[1],
this.formattedInterpolatedTimeData.map(ds => ds[tsIndex]), data[1].dsIndex]))
.map(data => parseInt(data[0], 10));
}
@ -244,7 +287,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
calcTooltip = (point: FormattedData, points: FormattedData[]): string => {
const data = point ? point : this.activeTrip;
const tooltipPattern: string = this.settings.useTooltipFunction ?
safeExecute(this.settings.parsedTooltipFunction,
safeExecuteTbFunction(this.settings.parsedTooltipFunction,
[data, points, point.dsIndex]) : this.settings.tooltipPattern;
return parseWithTranslation.parseTemplate(tooltipPattern, data, true);
}
@ -261,7 +304,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
if (this.activeTrip) {
const data = points[this.activeTrip.dsIndex];
const labelText: string = this.settings.useLabelFunction ?
safeExecute(this.settings.parsedLabelFunction, [data, points, data.dsIndex]) : this.settings.label;
safeExecuteTbFunction(this.settings.parsedLabelFunction, [data, points, data.dsIndex]) : this.settings.label;
this.label = this.sanitizer.bypassSecurityTrustHtml(parseWithTranslation.parseTemplate(labelText, data, true));
}
}